From 1d9ce79f9e396599b2503f385c74bd132bf88fed Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Wed, 27 Jun 2012 05:24:56 +0200 Subject: Misc cleanup: Add @Override, remove trailing whitespace --- .../macosx/cgl/MacOSXExternalCGLContext.java | 27 ++++++++++++++-------- 1 file changed, 18 insertions(+), 9 deletions(-) (limited to 'src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java') diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java index 58cea4ade..ad4c06af2 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java @@ -1,22 +1,22 @@ /* * Copyright (c) 2005 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. */ @@ -112,17 +112,19 @@ public class MacOSXExternalCGLContext extends MacOSXCGLContext { if(0 == currentDrawable) { // set a fake marker stating a valid drawable - currentDrawable = 1; + currentDrawable = 1; } WrappedSurface ns = new WrappedSurface(cfg); ns.setSurfaceHandle(currentDrawable); return new MacOSXExternalCGLContext(new Drawable(factory, ns), isNSContext, contextHandle); } + @Override protected boolean createImpl(GLContextImpl shareWith) throws GLException { return true; } + @Override public int makeCurrent() throws GLException { // Save last context if necessary to allow external GLContexts to // talk to other GLContexts created by this library @@ -132,20 +134,24 @@ public class MacOSXExternalCGLContext extends MacOSXCGLContext { setCurrent(null); } return super.makeCurrent(); - } + } + @Override public void release() throws GLException { super.release(); setCurrent(lastContext); lastContext = null; } + @Override protected void makeCurrentImpl() throws GLException { } + @Override protected void releaseImpl() throws GLException { } + @Override protected void destroyImpl() throws GLException { } @@ -155,14 +161,17 @@ public class MacOSXExternalCGLContext extends MacOSXCGLContext { super(factory, comp, true); } + @Override public GLContext createContext(GLContext shareWith) { throw new GLException("Should not call this"); } + @Override public int getWidth() { throw new GLException("Should not call this"); } + @Override public int getHeight() { throw new GLException("Should not call this"); } -- cgit v1.2.3 From 20bf031db719f7baa4c6e74734fc999061e08fe2 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Thu, 19 Jul 2012 21:15:10 +0200 Subject: Bug 599 - FBObject / Offscreen Support - Part 1 - New FBObject implementation handling FBO and it's attachments *** API CHANGE: Util -> Core *** while it's size and sample-count can be reconfigured on the fly. - com.jogamp.opengl.util.FBObject -> com.jogamp.opengl.FBObject - agnostic to texture unit - separate attachments using OO hierarchy reflecting FBO - handling MSAA and blitting - no FBO destruction for reconfig (attach/detach) - New GLFBODrawableImpl impl. an FBObject based GLDrawable - Instantiated by a dummy native surface (onscreen and invisible) hooked up to a dummy GLDrawable, which is the delegation for context creation. - Utilizies ProxySurface.UpstreamSurfaceHook for dummy surface avoiding specialization for native platforms. - TODO: Allow to utilize common surface interface as a dummy-surface to supporting API seperation of windowing/GL. The latter allows impl. of createGLDrawable(NativeSurface) with FBO. - New OffscreenAutoDrawable (extends GLAutoDrawableDelegate) for all offscreen drawables. Shall replace GLPbuffer. - New GLCapabilities*.isFBO() / setFBO(boolean) to request FBO offscreen, similar to isPBuffer(). Rule: if both are requested, FBO shall be favored. - GLContext adds raw FBO availability query (min. FBO avail), FBObject contains fine grained queries (TODO: Move parts to GLContext for efficiency). - Add framebuffer tracking, allowing fast querying: - GLBase/GLContext: public int getBoundFramebuffer(int target); public int getDefaultDrawFramebuffer(); public int getDefaultReadFramebuffer(); - GLContextImpl public final void setBoundFramebuffer(int target, int framebufferName) .. called by GL impl bind framebuffer - GL: getDefaultDrawFramebuffer(), getDefaultReadFramebuffer() Adding default framebuffer queries being issued by GL.glBindFramebuffer(target, 0) w/ a default framebuffer, o.e. zero. This allows a transparent use of a custom FBO even in case the applications attempts to reset FBO to zero. Value flow: GL <- GLContext <- GLDrawable, - GLCapabilities handle fbo/pbuffer seperate, don't disable the other - GLContext/GL track read/write framebuffer to be queried by FBObject to determine whether to bind/unbind a framebuffer - Test cases for multiple FBO w/ and w/o MSAA Other Features: - New interface ProxySurface.UpstreamSurfaceHook, allowing to hook an upstream surface of unknown type providing lifecycle and information (size, ..) callbacks. Used for all new dummy NativeSurface impl and SWT GLCanvas. - GLContext -> GLDrawable propagation context/drawable lifecycle via ProxySurface.UpstreamSurfaceHook allowing dynamic resources to react (create, init, ..) - contextRealized() - contextMadeCurrent() - SurfaceChangeable -> MutableSurface currently only contains setting the surface handle. TODO: May need to move ProxySurface.UpstreamSurfaceHook -> MutableSurface.UpstreamSurfaceHook, allowing other impl. classes (NEWT OffscreenWindow) to utilize the new upstream hookup mechanism - will allow FBO/Dummy window to work. - SWT GLCanvas using ProxySurface.UpstreamSurfaceHook for proper size propagation. - New GLAutoDrawable::getUpstreamWidget(), allowing GLEventListener to fetch the owning Java side UI element (NEWT, SWT, AWT, ..). - GLDrawableFactory: Removed createOffscreenSurface() - unused and not GL related - EGLDrawableFactory handles device/profile avail. mapping while actually creating context/drawable. This allows us to learn whether the ES context is software/hardware as well as FBO avail. - EGLDrawable: Removed secret buckets of EGL configs :) Employ native surface (X11, WGL, ..) to EGL 'mapping' in EGLDrawableFactory utilizing new EGLUpstreamSurfaceHook (implements ProxySurface.UpstreamSurfaceHook). Other Bugs: - Add CTX_OPTION_DEBUG to ctx/extension cache key since only a debug ctx may expose the ARB debug capability. This bug caused lack of ARB/AMD debug functionality. - Fix GLProfile deadlock (debug mode, w/ EGL/ES, no X11), dump availability information _after_ lock. - ImmModeSink draw(): Use GL's glDrawElements(..), don't cast for GL2ES1. Fixes use for GL2ES2. - Fix KeyEvent.getKeyChar() comment (-> only stable for keyTyped(..)) Misc: - Refined alot of API doc - New GLExtensions holds commonly used GL extension strings, allows better referencing and usage lookup. - Move GL (interface) decl. to GLBase - GLBuffers: Cleanup API doc (format, types) - TextureIO: Add PAM and PPM static suffix identifier - GLCapabilities getNumSamples() returns 0 if sampleBuffers is disabled, this seems to be more natural. - finalized a lot --- .gitignore | 5 +- doc/Platform.GLES.txt | 4 +- doc/TODO.txt | 11 +- etc/test.bat | 2 +- etc/test_dbg.bat | 2 +- make/config/jogl/gl-common.cfg | 13 + make/config/jogl/gl-if-CustomJavaCode-gl.java | 26 - .../config/jogl/gl-impl-CustomJavaCode-common.java | 53 +- .../jogl/gl-impl-CustomJavaCode-desktop.java | 25 +- .../jogl/gl-impl-CustomJavaCode-gl2_es2.java | 6 +- make/config/jogl/gl-impl-CustomJavaCode-gl4bc.java | 56 +- make/config/jogl/gl-impl-CustomJavaCode-gles1.java | 66 +- make/config/jogl/gl-impl-CustomJavaCode-gles2.java | 63 +- make/scripts/java-win32-dbg.bat | 13 +- make/scripts/java-win32.bat | 4 +- make/scripts/java-win64-dbg.bat | 12 +- make/scripts/java-win64.bat | 3 +- make/scripts/tests-x32.bat | 3 +- make/scripts/tests-x64.bat | 5 +- make/scripts/tests.sh | 41 +- make/stub_includes/opengl/macosx-window-system.h | 2 +- .../jogamp/gluegen/opengl/BuildStaticGLInfo.java | 4 +- .../com/jogamp/gluegen/opengl/GLConfiguration.java | 10 +- .../com/jogamp/gluegen/opengl/GLEmitter.java | 18 +- .../gluegen/runtime/opengl/GLExtensionNames.java | 190 -- .../gluegen/runtime/opengl/GLNameResolver.java | 191 ++ .../runtime/opengl/GLProcAddressResolver.java | 4 +- src/jogl/classes/com/jogamp/opengl/FBObject.java | 1943 ++++++++++++++++++++ .../classes/com/jogamp/opengl/GLExtensions.java | 81 + .../classes/com/jogamp/opengl/JoglVersion.java | 18 +- .../com/jogamp/opengl/OffscreenAutoDrawable.java | 89 + .../classes/com/jogamp/opengl/swt/GLCanvas.java | 72 +- .../classes/com/jogamp/opengl/util/FBObject.java | 483 ----- .../classes/com/jogamp/opengl/util/GLBuffers.java | 179 +- .../com/jogamp/opengl/util/GLReadBufferUtil.java | 12 +- .../com/jogamp/opengl/util/ImmModeSink.java | 25 +- .../com/jogamp/opengl/util/awt/Screenshot.java | 3 +- .../com/jogamp/opengl/util/awt/TextRenderer.java | 3 +- .../com/jogamp/opengl/util/texture/Texture.java | 25 +- .../com/jogamp/opengl/util/texture/TextureIO.java | 8 + .../opengl/util/texture/TextureSequence.java | 1 - .../util/texture/spi/NetPbmTextureWriter.java | 6 +- .../media/opengl/DefaultGLCapabilitiesChooser.java | 5 +- .../classes/javax/media/opengl/GLAutoDrawable.java | 48 +- .../javax/media/opengl/GLAutoDrawableDelegate.java | 18 +- src/jogl/classes/javax/media/opengl/GLBase.java | 55 + .../classes/javax/media/opengl/GLCapabilities.java | 31 +- .../media/opengl/GLCapabilitiesImmutable.java | 6 +- src/jogl/classes/javax/media/opengl/GLContext.java | 94 +- .../javax/media/opengl/GLDrawableFactory.java | 84 +- src/jogl/classes/javax/media/opengl/GLProfile.java | 52 +- .../classes/javax/media/opengl/awt/GLCanvas.java | 7 +- .../classes/javax/media/opengl/awt/GLJPanel.java | 7 +- .../jogamp/graph/curve/opengl/VBORegion2PES2.java | 32 +- src/jogl/classes/jogamp/opengl/GLContextImpl.java | 190 +- .../jogamp/opengl/GLDebugMessageHandler.java | 22 +- .../jogamp/opengl/GLDrawableFactoryImpl.java | 234 ++- src/jogl/classes/jogamp/opengl/GLDrawableImpl.java | 47 +- .../classes/jogamp/opengl/GLFBODrawableImpl.java | 138 ++ .../jogamp/opengl/GLGraphicsConfigurationUtil.java | 66 +- src/jogl/classes/jogamp/opengl/GLPbufferImpl.java | 8 +- src/jogl/classes/jogamp/opengl/egl/EGLContext.java | 76 +- .../classes/jogamp/opengl/egl/EGLDisplayUtil.java | 27 +- .../classes/jogamp/opengl/egl/EGLDrawable.java | 214 +-- .../jogamp/opengl/egl/EGLDrawableFactory.java | 307 +++- .../opengl/egl/EGLGraphicsConfiguration.java | 2 +- .../egl/EGLGraphicsConfigurationFactory.java | 65 +- .../jogamp/opengl/egl/EGLOnscreenDrawable.java | 4 +- .../jogamp/opengl/egl/EGLPbufferDrawable.java | 34 +- .../jogamp/opengl/egl/EGLUpstreamSurfaceHook.java | 56 + .../jogamp/opengl/macosx/cgl/MacOSXCGLContext.java | 24 +- .../opengl/macosx/cgl/MacOSXCGLDrawable.java | 4 - .../macosx/cgl/MacOSXCGLDrawableFactory.java | 153 +- .../macosx/cgl/MacOSXCGLGraphicsConfiguration.java | 4 +- .../macosx/cgl/MacOSXExternalCGLContext.java | 3 +- .../macosx/cgl/MacOSXPbufferCGLDrawable.java | 12 +- .../jogamp/opengl/util/av/EGLMediaPlayerImpl.java | 8 +- .../windows/wgl/WindowsBitmapWGLDrawable.java | 6 +- .../windows/wgl/WindowsDummyWGLDrawable.java | 109 -- .../windows/wgl/WindowsExternalWGLContext.java | 3 +- .../windows/wgl/WindowsExternalWGLDrawable.java | 7 +- .../windows/wgl/WindowsPbufferWGLContext.java | 4 +- .../windows/wgl/WindowsPbufferWGLDrawable.java | 19 +- .../opengl/windows/wgl/WindowsWGLContext.java | 6 +- .../windows/wgl/WindowsWGLDrawableFactory.java | 130 +- .../wgl/WindowsWGLGraphicsConfiguration.java | 22 +- .../WindowsWGLGraphicsConfigurationFactory.java | 19 +- .../jogamp/opengl/x11/glx/X11DummyGLXDrawable.java | 102 - .../opengl/x11/glx/X11ExternalGLXContext.java | 12 +- .../opengl/x11/glx/X11ExternalGLXDrawable.java | 5 +- .../jogamp/opengl/x11/glx/X11GLXContext.java | 9 +- .../opengl/x11/glx/X11GLXDrawableFactory.java | 145 +- .../x11/glx/X11GLXGraphicsConfiguration.java | 29 +- .../glx/X11GLXGraphicsConfigurationFactory.java | 17 +- .../opengl/x11/glx/X11OnscreenGLXDrawable.java | 7 +- .../opengl/x11/glx/X11PbufferGLXDrawable.java | 18 +- .../opengl/x11/glx/X11PixmapGLXDrawable.java | 6 +- .../macosx/MacOSXWindowSystemInterface-pbuffer.m | 2 +- .../native/macosx/MacOSXWindowSystemInterface.m | 12 +- .../com/jogamp/nativewindow/WrappedSurface.java | 34 +- .../jogamp/nativewindow/egl/EGLGraphicsDevice.java | 42 +- .../com/jogamp/nativewindow/swt/SWTAccessor.java | 3 - .../jogamp/nativewindow/x11/X11GraphicsDevice.java | 36 +- .../jogamp/nativewindow/x11/X11GraphicsScreen.java | 8 +- .../media/nativewindow/AbstractGraphicsDevice.java | 27 +- .../media/nativewindow/DefaultGraphicsDevice.java | 13 + .../javax/media/nativewindow/MutableSurface.java | 44 + .../javax/media/nativewindow/ProxySurface.java | 127 +- .../media/nativewindow/SurfaceChangeable.java | 54 - .../jogamp/nativewindow/SurfaceUpdatedHelper.java | 4 +- .../nativewindow/jawt/macosx/MacOSXJAWTWindow.java | 21 +- .../jogamp/nativewindow/macosx/OSXUtil.java | 13 +- .../jogamp/nativewindow/windows/GDISurface.java | 51 +- src/nativewindow/native/macosx/OSXmisc.m | 52 +- src/newt/classes/com/jogamp/newt/Window.java | 16 +- .../classes/com/jogamp/newt/event/KeyEvent.java | 2 +- .../classes/com/jogamp/newt/opengl/GLWindow.java | 7 +- src/newt/classes/jogamp/newt/OffscreenWindow.java | 41 +- .../classes/jogamp/newt/driver/android/MD.java | 2 +- .../jogamp/newt/driver/macosx/MacWindow.java | 8 +- src/newt/native/NewtMacWindow.m | 6 +- .../test/junit/graph/TestTextRendererNEWT00.java | 2 +- .../graph/demos/GPURendererListenerBase01.java | 2 +- .../junit/graph/demos/ui/UIListenerBase01.java | 2 +- .../test/junit/jogl/acore/TestFBODrawableNEWT.java | 272 +++ .../test/junit/jogl/acore/TestFBOMRTNEWT01.java | 266 +++ .../junit/jogl/acore/TestFBOMix2DemosES2NEWT.java | 258 +++ .../jogl/acore/TestGLAutoDrawableDelegateNEWT.java | 2 +- .../acore/TestGLContextDrawableSwitchNEWT.java | 2 +- .../test/junit/jogl/acore/TestGLProfile01NEWT.java | 2 +- .../junit/jogl/acore/TestShutdownCompleteNEWT.java | 2 +- .../test/junit/jogl/caps/MultisampleDemoES1.java | 154 -- .../junit/jogl/caps/TestMultisampleES1AWT.java | 19 +- .../junit/jogl/caps/TestMultisampleES1NEWT.java | 20 +- .../junit/jogl/caps/TestMultisampleES2NEWT.java | 143 ++ .../opengl/test/junit/jogl/demos/es1/GearsES1.java | 19 +- .../junit/jogl/demos/es1/MultisampleDemoES1.java | 123 ++ .../test/junit/jogl/demos/es2/FBOMix2DemosES2.java | 309 ++++ .../opengl/test/junit/jogl/demos/es2/GearsES2.java | 39 +- .../junit/jogl/demos/es2/MultisampleDemoES2.java | 178 ++ .../test/junit/jogl/demos/es2/RedSquareES2.java | 48 +- .../jogl/demos/es2/TextureSequenceCubeES2.java | 9 +- .../test/junit/jogl/demos/es2/av/MovieCube.java | 5 +- .../test/junit/jogl/demos/es2/av/MovieSimple.java | 5 +- .../jogl/demos/es2/newt/TestGearsES2NEWT.java | 3 - .../jogl/demos/es2/newt/TestRedSquareES2NEWT.java | 7 +- .../junit/jogl/demos/es2/shader/mgl_default_xxx.fp | 10 + .../junit/jogl/demos/es2/shader/mgl_default_xxx.vp | 14 + .../junit/jogl/demos/es2/shader/texture02_xxx.fp | 20 + .../opengl/test/junit/jogl/demos/gl2/Gears.java | 18 +- .../jogl/demos/gl2/awt/TestGLJPanelAWTBug450.java | 188 ++ .../demos/gl2/awt/TestGearsGLJPanelAWTBug450.java | 194 -- .../test/junit/jogl/glsl/TestFBOMRTNEWT01.java | 229 --- .../junit/jogl/glsl/TestGLSLShaderState01NEWT.java | 1 - .../junit/jogl/glsl/TestGLSLShaderState02NEWT.java | 1 - .../test/junit/jogl/offscreen/ReadBufferBase.java | 4 +- .../test/junit/jogl/offscreen/Surface2File.java | 2 +- .../test/junit/jogl/swt/TestSWTAccessor02GLn.java | 41 +- .../TestGLReadBufferUtilTextureIOWrite01AWT.java | 19 +- .../TestGLReadBufferUtilTextureIOWrite01NEWT.java | 36 +- .../TestGLReadBufferUtilTextureIOWrite02AWT.java | 20 +- .../TestGLReadBufferUtilTextureIOWrite02NEWT.java | 20 +- .../util/texture/TestPNGTextureFromFileAWT.java | 13 +- .../util/texture/TestPNGTextureFromFileNEWT.java | 11 +- .../jogamp/opengl/test/junit/util/UITestCase.java | 55 +- 165 files changed, 6996 insertions(+), 3008 deletions(-) delete mode 100644 src/jogl/classes/com/jogamp/gluegen/runtime/opengl/GLExtensionNames.java create mode 100644 src/jogl/classes/com/jogamp/gluegen/runtime/opengl/GLNameResolver.java create mode 100644 src/jogl/classes/com/jogamp/opengl/FBObject.java create mode 100644 src/jogl/classes/com/jogamp/opengl/GLExtensions.java create mode 100644 src/jogl/classes/com/jogamp/opengl/OffscreenAutoDrawable.java delete mode 100644 src/jogl/classes/com/jogamp/opengl/util/FBObject.java create mode 100644 src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java create mode 100644 src/jogl/classes/jogamp/opengl/egl/EGLUpstreamSurfaceHook.java delete mode 100644 src/jogl/classes/jogamp/opengl/windows/wgl/WindowsDummyWGLDrawable.java delete mode 100644 src/jogl/classes/jogamp/opengl/x11/glx/X11DummyGLXDrawable.java create mode 100644 src/nativewindow/classes/javax/media/nativewindow/MutableSurface.java delete mode 100644 src/nativewindow/classes/javax/media/nativewindow/SurfaceChangeable.java create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBODrawableNEWT.java create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMRTNEWT01.java create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMix2DemosES2NEWT.java delete mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/caps/MultisampleDemoES1.java create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/caps/TestMultisampleES2NEWT.java create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/MultisampleDemoES1.java create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/FBOMix2DemosES2.java create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/MultisampleDemoES2.java create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/mgl_default_xxx.fp create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/mgl_default_xxx.vp create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/shader/texture02_xxx.fp create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGLJPanelAWTBug450.java delete mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/awt/TestGearsGLJPanelAWTBug450.java delete mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/glsl/TestFBOMRTNEWT01.java (limited to 'src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java') diff --git a/.gitignore b/.gitignore index 6e3af642b..1cd3375b4 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,7 @@ javadoc_public build-temp make/temp* .idea/workspace.xml -**~ \ No newline at end of file +.settings/* +**~ +build* +make/lib/external/* diff --git a/doc/Platform.GLES.txt b/doc/Platform.GLES.txt index 0bcd3bc8b..901e040c4 100644 --- a/doc/Platform.GLES.txt +++ b/doc/Platform.GLES.txt @@ -33,7 +33,7 @@ a request for e.g. GL2ES2 will utilize the highest common desktop profile. ...> Linux: - PVRVFrame 2.09.29.0649 + PVRVFrame 2.09.29.0649, Version_REL_2.10 Debian Wheezy/testing x64, NV 290.10, 32bit libraries: OK GL_VENDOR Imagination Technologies (Host GL: `NVIDIA Corporation`) GL_RENDERER PowerVR PVRVFrame 8.1 SGX (Host GL: `GeForce GTX 460/PCI/SSE2`) @@ -75,7 +75,7 @@ Linux: Ubuntu 11.10 x64, AMD Catalyst 12.1, 64bit libraries, libgles2-mesa 7.11-0ubuntu3: Error (swrast error, null values) Windows: - PVRVFrame 2.09.29.0649 + PVRVFrame 2.09.29.0649, Version_REL_2.10 Windows7 64bit, NV 290.10, 32bit libraries: OK GL_VENDOR Imagination Technologies (Host GL: `NVIDIA Corporation`) GL_RENDERER PowerVR PVRVFrame 8.1 SGX (Host GL: `GeForce GTX 460/PCIe/SSE2`) diff --git a/doc/TODO.txt b/doc/TODO.txt index f86d31e4c..82f013265 100644 --- a/doc/TODO.txt +++ b/doc/TODO.txt @@ -1,16 +1,15 @@ WIP: +- GLPbuffer -> GLOffscreenAutoDrawable + - GLPbuffer GLDrawableFactory.createPbuffer() -> + GLOffscreenAutoDrawable GLDrawableFactory.createOffsceenAutoDrawable() + - Mark both deprecated! + Random, somewhat old to-do list: - Non-const array types must be properly released with JNI_COMMIT in order to see side effects if the array was copied. -- figure out how to deal with WGL entry points: - WINGDIAPI HGLRC WINAPI wglCreateLayerContext(HDC, int); - WINGDIAPI BOOL WINAPI wglUseFontBitmapsA(HDC, DWORD, DWORD, DWORD); - WINGDIAPI BOOL WINAPI wglUseFontBitmapsW(HDC, DWORD, DWORD, DWORD); - see commented-out section in make/stub_includes/win32/wingdi.h - - Need a disciplined mechanism for converting char* argument types. For example, many C functions accept a "char*" argument with the semantic that output data will be written into the buffer pointed to by the diff --git a/etc/test.bat b/etc/test.bat index 0c82233ca..d635c7e8f 100755 --- a/etc/test.bat +++ b/etc/test.bat @@ -1,7 +1,7 @@ set BLD_DIR=jar -set CP_ALL=.;%BLD_DIR%\gluegen-rt.jar;%BLD_DIR%\jogl.all.jar +set CP_ALL=.;%BLD_DIR%\gluegen-rt.jar;%BLD_DIR%\jogl-all.jar echo CP_ALL %CP_ALL% set X_ARGS="-Dsun.java2d.noddraw=true" "-Dsun.awt.noerasebackground=true" diff --git a/etc/test_dbg.bat b/etc/test_dbg.bat index 33bbb912b..209690758 100755 --- a/etc/test_dbg.bat +++ b/etc/test_dbg.bat @@ -1,7 +1,7 @@ set BLD_DIR=jar -set CP_ALL=.;%BLD_DIR%\gluegen-rt.jar;%BLD_DIR%\jogl.all.jar +set CP_ALL=.;%BLD_DIR%\gluegen-rt.jar;%BLD_DIR%\jogl-all.jar echo CP_ALL %CP_ALL% set D_ARGS="-Djogamp.debug=all" "-Dnativewindow.debug=all" "-Djogl.debug=all" "-Dnewt.debug=all" diff --git a/make/config/jogl/gl-common.cfg b/make/config/jogl/gl-common.cfg index 8af080ec8..9c5467583 100644 --- a/make/config/jogl/gl-common.cfg +++ b/make/config/jogl/gl-common.cfg @@ -481,6 +481,19 @@ JavaPrologue glGetString return _context.getGLVersion(); JavaPrologue glGetString } */ JavaPrologue glGetString } +# +# Allow special FBO GLContext/GLDrawable to reset to it's +# default FBO framebuffer. +# +JavaPrologue glBindFramebuffer if( 0 == framebuffer ) { +JavaPrologue glBindFramebuffer if( GL_FRAMEBUFFER == target || 0x8CA9 /* GL_DRAW_FRAMEBUFFER */ == target ) { +JavaPrologue glBindFramebuffer framebuffer = _context.getDefaultDrawFramebuffer(); +JavaPrologue glBindFramebuffer } else if( 0x8CA8 /* GL_READ_FRAMEBUFFER */ == target ) { +JavaPrologue glBindFramebuffer framebuffer = _context.getDefaultReadFramebuffer(); +JavaPrologue glBindFramebuffer } +JavaPrologue glBindFramebuffer } +JavaEpilogue glBindFramebuffer _context.setBoundFramebuffer(target, framebuffer); + # # Directives for Vertex Buffer Object and Pixel Buffer Object checking # diff --git a/make/config/jogl/gl-if-CustomJavaCode-gl.java b/make/config/jogl/gl-if-CustomJavaCode-gl.java index 77378aa45..9ea4f98b4 100644 --- a/make/config/jogl/gl-if-CustomJavaCode-gl.java +++ b/make/config/jogl/gl-if-CustomJavaCode-gl.java @@ -57,29 +57,3 @@ earmarked for ES 3.0 (hence kept in GL while fixing Bug 590) */ public static final int GL_HALF_FLOAT = 0x140B; - public void glClearDepth( double depth ); - - 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(); - diff --git a/make/config/jogl/gl-impl-CustomJavaCode-common.java b/make/config/jogl/gl-impl-CustomJavaCode-common.java index d552bc6e4..b05ba2643 100644 --- a/make/config/jogl/gl-impl-CustomJavaCode-common.java +++ b/make/config/jogl/gl-impl-CustomJavaCode-common.java @@ -1,48 +1,57 @@ + @Override public GLProfile getGLProfile() { return this.glProfile; } private final GLProfile glProfile; - public int glGetBoundBuffer(int target) { + @Override + public final int glGetBoundBuffer(int target) { return bufferStateTracker.getBoundBufferObject(target, this); } - public long glGetBufferSize(int buffer) { + @Override + public final long glGetBufferSize(int buffer) { return bufferSizeTracker.getDirectStateBufferSize(buffer, this); } - public boolean glIsVBOArrayEnabled() { + @Override + public final boolean glIsVBOArrayEnabled() { return checkArrayVBOEnabled(false); } - public boolean glIsVBOElementArrayEnabled() { + @Override + public final boolean glIsVBOElementArrayEnabled() { return checkElementVBOEnabled(false); } + @Override public final boolean isGL() { return true; } + @Override public final GL getGL() throws GLException { return this; } - public boolean isFunctionAvailable(String glFunctionName) { + @Override + public final boolean isFunctionAvailable(String glFunctionName) { return _context.isFunctionAvailable(glFunctionName); } - public boolean isExtensionAvailable(String glExtensionName) { + @Override + public final boolean isExtensionAvailable(String glExtensionName) { return _context.isExtensionAvailable(glExtensionName); } - public Object getExtension(String extensionName) { + @Override + public final Object getExtension(String extensionName) { // At this point we don't expose any extensions using this mechanism return null; } - /** Returns the context this GL object is associated with for better - error checking by DebugGL. */ - public GLContext getContext() { + @Override + public final GLContext getContext() { return _context; } @@ -51,18 +60,36 @@ /** * @see javax.media.opengl.GLContext#setSwapInterval(int) */ - public void setSwapInterval(int interval) { + @Override + public final void setSwapInterval(int interval) { _context.setSwapInterval(interval); } /** * @see javax.media.opengl.GLContext#getSwapInterval() */ - public int getSwapInterval() { + @Override + public final int getSwapInterval() { return _context.getSwapInterval(); } - public Object getPlatformGLExtensions() { + @Override + public final Object getPlatformGLExtensions() { return _context.getPlatformGLExtensions(); } + @Override + public final int getBoundFramebuffer(int target) { + return _context.getBoundFramebuffer(target); + } + + @Override + public final int getDefaultDrawFramebuffer() { + return _context.getDefaultDrawFramebuffer(); + } + + @Override + public final int getDefaultReadFramebuffer() { + return _context.getDefaultReadFramebuffer(); + } + diff --git a/make/config/jogl/gl-impl-CustomJavaCode-desktop.java b/make/config/jogl/gl-impl-CustomJavaCode-desktop.java index 33b0f1326..6a74b80a6 100644 --- a/make/config/jogl/gl-impl-CustomJavaCode-desktop.java +++ b/make/config/jogl/gl-impl-CustomJavaCode-desktop.java @@ -4,34 +4,42 @@ return GLBuffers.sizeof(this, imageSizeTemp, format, type, width, height, depth, pack) ; } + @Override public final boolean isGL4bc() { return _context.isGL4bc(); } + @Override public final boolean isGL4() { return _context.isGL4(); } + @Override public final boolean isGL3bc() { return _context.isGL3bc(); } + @Override public final boolean isGL3() { return _context.isGL3(); } + @Override public final boolean isGL2() { return _context.isGL2(); } + @Override public final boolean isGL2ES1() { return _context.isGL2ES1(); } + @Override public final boolean isGL2ES2() { return _context.isGL2ES2(); } + @Override public final boolean isGLES2Compatible() { return _context.isGLES2Compatible(); } @@ -40,10 +48,12 @@ return _context.isGL2GL3(); } + @Override public final boolean hasGLSL() { return _context.hasGLSL(); } + @Override public final GL4bc getGL4bc() throws GLException { if(!isGL4bc()) { throw new GLException("Not a GL4bc implementation"); @@ -51,6 +61,7 @@ return this; } + @Override public final GL4 getGL4() throws GLException { if(!isGL4()) { throw new GLException("Not a GL4 implementation"); @@ -58,6 +69,7 @@ return this; } + @Override public final GL3bc getGL3bc() throws GLException { if(!isGL3bc()) { throw new GLException("Not a GL3bc implementation"); @@ -65,6 +77,7 @@ return this; } + @Override public final GL3 getGL3() throws GLException { if(!isGL3()) { throw new GLException("Not a GL3 implementation"); @@ -72,6 +85,7 @@ return this; } + @Override public final GL2 getGL2() throws GLException { if(!isGL2()) { throw new GLException("Not a GL2 implementation"); @@ -79,6 +93,7 @@ return this; } + @Override public final GL2ES1 getGL2ES1() throws GLException { if(!isGL2ES1()) { throw new GLException("Not a GL2ES1 implementation"); @@ -86,6 +101,7 @@ return this; } + @Override public final GL2ES2 getGL2ES2() throws GLException { if(!isGL2ES2()) { throw new GLException("Not a GL2ES2 implementation"); @@ -93,6 +109,7 @@ return this; } + @Override public final GL2GL3 getGL2GL3() throws GLException { if(!isGL2GL3()) { throw new GLException("Not a GL2GL3 implementation"); @@ -100,26 +117,32 @@ return this; } + @Override public final boolean isGLES1() { return false; } + @Override public final boolean isGLES2() { return false; } + @Override public final boolean isGLES() { return false; } + @Override public final GLES1 getGLES1() throws GLException { throw new GLException("Not a GLES1 implementation"); } + @Override public final GLES2 getGLES2() throws GLException { throw new GLException("Not a GLES2 implementation"); } - public boolean isNPOTTextureAvailable() { + @Override + public final boolean isNPOTTextureAvailable() { return _context.isNPOTTextureAvailable(); } diff --git a/make/config/jogl/gl-impl-CustomJavaCode-gl2_es2.java b/make/config/jogl/gl-impl-CustomJavaCode-gl2_es2.java index b31a087e7..82b791208 100644 --- a/make/config/jogl/gl-impl-CustomJavaCode-gl2_es2.java +++ b/make/config/jogl/gl-impl-CustomJavaCode-gl2_es2.java @@ -1,4 +1,5 @@ - public void glVertexAttribPointer(GLArrayData array) { + @Override + public final void glVertexAttribPointer(GLArrayData array) { if(array.getComponentCount()==0) return; if(array.isVBO()) { glVertexAttribPointer(array.getLocation(), array.getComponentCount(), array.getComponentType(), @@ -9,7 +10,8 @@ } } - public void glUniform(GLUniformData data) { + @Override + public final void glUniform(GLUniformData data) { boolean done=false; if(data.isBuffer()) { Buffer buffer = data.getBuffer(); diff --git a/make/config/jogl/gl-impl-CustomJavaCode-gl4bc.java b/make/config/jogl/gl-impl-CustomJavaCode-gl4bc.java index 95aa7cc2c..e079a1a24 100644 --- a/make/config/jogl/gl-impl-CustomJavaCode-gl4bc.java +++ b/make/config/jogl/gl-impl-CustomJavaCode-gl4bc.java @@ -33,7 +33,7 @@ public GL4bcImpl(GLProfile glp, GLContextImpl context) { * Provides platform-independent access to the wglAllocateMemoryNV / * glXAllocateMemoryNV extension. */ -public java.nio.ByteBuffer glAllocateMemoryNV(int arg0, float arg1, float arg2, float arg3) { +public final java.nio.ByteBuffer glAllocateMemoryNV(int arg0, float arg1, float arg2, float arg3) { return _context.glAllocateMemoryNV(arg0, arg1, arg2, arg3); } @@ -52,7 +52,7 @@ private boolean haveGL15; private boolean haveGL21; private boolean haveARBVertexBufferObject; -private void initBufferObjectExtensionChecks() { +private final void initBufferObjectExtensionChecks() { if (bufferObjectExtensionsInitialized) return; bufferObjectExtensionsInitialized = true; @@ -63,12 +63,12 @@ private void initBufferObjectExtensionChecks() { haveARBVertexBufferObject = isExtensionAvailable("GL_ARB_vertex_buffer_object"); } -private boolean checkBufferObject(boolean extension1, - boolean extension2, - boolean extension3, - boolean enabled, - int state, - String kind, boolean throwException) { +private final boolean checkBufferObject(boolean extension1, + boolean extension2, + boolean extension3, + boolean enabled, + int state, + String kind, boolean throwException) { if (inBeginEndPair) { throw new GLException("May not call this between glBegin and glEnd"); } @@ -100,7 +100,7 @@ private boolean checkBufferObject(boolean extension1, return true; } -private boolean checkArrayVBODisabled(boolean throwException) { +private final boolean checkArrayVBODisabled(boolean throwException) { initBufferObjectExtensionChecks(); return checkBufferObject(haveGL15, haveARBVertexBufferObject, @@ -110,7 +110,7 @@ private boolean checkArrayVBODisabled(boolean throwException) { "array vertex_buffer_object", throwException); } -private boolean checkArrayVBOEnabled(boolean throwException) { +private final boolean checkArrayVBOEnabled(boolean throwException) { initBufferObjectExtensionChecks(); return checkBufferObject(haveGL15, haveARBVertexBufferObject, @@ -120,7 +120,7 @@ private boolean checkArrayVBOEnabled(boolean throwException) { "array vertex_buffer_object", throwException); } -private boolean checkElementVBODisabled(boolean throwException) { +private final boolean checkElementVBODisabled(boolean throwException) { initBufferObjectExtensionChecks(); return checkBufferObject(haveGL15, haveARBVertexBufferObject, @@ -130,7 +130,7 @@ private boolean checkElementVBODisabled(boolean throwException) { "element vertex_buffer_object", throwException); } -private boolean checkElementVBOEnabled(boolean throwException) { +private final boolean checkElementVBOEnabled(boolean throwException) { initBufferObjectExtensionChecks(); return checkBufferObject(haveGL15, haveARBVertexBufferObject, @@ -140,7 +140,7 @@ private boolean checkElementVBOEnabled(boolean throwException) { "element vertex_buffer_object", throwException); } -private boolean checkUnpackPBODisabled(boolean throwException) { +private final boolean checkUnpackPBODisabled(boolean throwException) { initBufferObjectExtensionChecks(); return checkBufferObject(haveARBPixelBufferObject, haveEXTPixelBufferObject, @@ -150,7 +150,7 @@ private boolean checkUnpackPBODisabled(boolean throwException) { "unpack pixel_buffer_object", throwException); } -private boolean checkUnpackPBOEnabled(boolean throwException) { +private final boolean checkUnpackPBOEnabled(boolean throwException) { initBufferObjectExtensionChecks(); return checkBufferObject(haveARBPixelBufferObject, haveEXTPixelBufferObject, @@ -160,7 +160,7 @@ private boolean checkUnpackPBOEnabled(boolean throwException) { "unpack pixel_buffer_object", throwException); } -private boolean checkPackPBODisabled(boolean throwException) { +private final boolean checkPackPBODisabled(boolean throwException) { initBufferObjectExtensionChecks(); return checkBufferObject(haveARBPixelBufferObject, haveEXTPixelBufferObject, @@ -170,7 +170,7 @@ private boolean checkPackPBODisabled(boolean throwException) { "pack pixel_buffer_object", throwException); } -private boolean checkPackPBOEnabled(boolean throwException) { +private final boolean checkPackPBOEnabled(boolean throwException) { initBufferObjectExtensionChecks(); return checkBufferObject(haveARBPixelBufferObject, haveEXTPixelBufferObject, @@ -180,18 +180,20 @@ private boolean checkPackPBOEnabled(boolean throwException) { "pack pixel_buffer_object", throwException); } -public boolean glIsPBOPackEnabled() { +@Override +public final boolean glIsPBOPackEnabled() { return checkPackPBOEnabled(false); } -public boolean glIsPBOUnpackEnabled() { +@Override +public final boolean glIsPBOUnpackEnabled() { return checkUnpackPBOEnabled(false); } -private HashMap arbMemCache = new HashMap(); +private final HashMap arbMemCache = new HashMap(); /** Entry point to C language function:
LPVOID glMapBuffer(GLenum target, GLenum access); */ -public java.nio.ByteBuffer glMapBuffer(int target, int access) { +public final java.nio.ByteBuffer glMapBuffer(int target, int access) { final long __addr_ = ((GL4bcProcAddressTable)_context.getGLProcAddressTable())._addressof_glMapBuffer; if (__addr_ == 0) { throw new GLException("Method \"glMapBuffer\" not available"); @@ -230,7 +232,7 @@ public java.nio.ByteBuffer glMapBuffer(int target, int access) { native private long dispatch_glMapBuffer(int target, int access, long glProcAddress); /** Entry point to C language function: GLvoid * {@native glMapNamedBufferEXT}(GLuint buffer, GLenum access);
Part of GL_EXT_direct_state_access */ -public java.nio.ByteBuffer glMapNamedBufferEXT(int bufferName, int access) { +public final java.nio.ByteBuffer glMapNamedBufferEXT(int bufferName, int access) { final long __addr_ = ((GL4bcProcAddressTable)_context.getGLProcAddressTable())._addressof_glMapNamedBufferEXT; if (__addr_ == 0) { throw new GLException("Method \"glMapNamedBufferEXT\" not available"); @@ -269,7 +271,8 @@ private native long dispatch_glMapNamedBufferEXT(int buffer, int access, long pr native private ByteBuffer newDirectByteBuffer(long addr, long capacity); - public void glVertexPointer(GLArrayData array) { + @Override + public final void glVertexPointer(GLArrayData array) { if(array.getComponentCount()==0) return; if(array.isVBO()) { glVertexPointer(array.getComponentCount(), array.getComponentType(), array.getStride(), array.getVBOOffset()); @@ -277,7 +280,8 @@ native private ByteBuffer newDirectByteBuffer(long addr, long capacity); glVertexPointer(array.getComponentCount(), array.getComponentType(), array.getStride(), array.getBuffer()); } } - public void glColorPointer(GLArrayData array) { + @Override + public final void glColorPointer(GLArrayData array) { if(array.getComponentCount()==0) return; if(array.isVBO()) { glColorPointer(array.getComponentCount(), array.getComponentType(), array.getStride(), array.getVBOOffset()); @@ -286,7 +290,8 @@ native private ByteBuffer newDirectByteBuffer(long addr, long capacity); } } - public void glNormalPointer(GLArrayData array) { + @Override + public final void glNormalPointer(GLArrayData array) { if(array.getComponentCount()==0) return; if(array.getComponentCount()!=3) { throw new GLException("Only 3 components per normal allowed"); @@ -297,7 +302,8 @@ native private ByteBuffer newDirectByteBuffer(long addr, long capacity); glNormalPointer(array.getComponentType(), array.getStride(), array.getBuffer()); } } - public void glTexCoordPointer(GLArrayData array) { + @Override + public final void glTexCoordPointer(GLArrayData array) { if(array.getComponentCount()==0) return; if(array.isVBO()) { glTexCoordPointer(array.getComponentCount(), array.getComponentType(), array.getStride(), array.getVBOOffset()); diff --git a/make/config/jogl/gl-impl-CustomJavaCode-gles1.java b/make/config/jogl/gl-impl-CustomJavaCode-gles1.java index dff33cf81..68eadc683 100644 --- a/make/config/jogl/gl-impl-CustomJavaCode-gles1.java +++ b/make/config/jogl/gl-impl-CustomJavaCode-gles1.java @@ -12,98 +12,122 @@ public GLES1Impl(GLProfile glp, GLContextImpl context) { this.glProfile = glp; } +@Override public final boolean isGL4bc() { return false; } +@Override public final boolean isGL4() { return false; } +@Override public final boolean isGL3bc() { return false; } +@Override public final boolean isGL3() { return false; } +@Override public final boolean isGL2() { return false; } +@Override public final boolean isGLES1() { return true; } +@Override public final boolean isGLES2() { return false; } +@Override public final boolean isGLES() { return true; } +@Override public final boolean isGL2ES1() { return true; } +@Override public final boolean isGL2ES2() { return false; } +@Override public final boolean isGLES2Compatible() { return false; } +@Override public final boolean isGL2GL3() { return false; } +@Override public final boolean hasGLSL() { return false; } +@Override public boolean isNPOTTextureAvailable() { return false; } +@Override public final GL4bc getGL4bc() throws GLException { throw new GLException("Not a GL4bc implementation"); } +@Override public final GL4 getGL4() throws GLException { throw new GLException("Not a GL4 implementation"); } +@Override public final GL3bc getGL3bc() throws GLException { throw new GLException("Not a GL3bc implementation"); } +@Override public final GL3 getGL3() throws GLException { throw new GLException("Not a GL3 implementation"); } +@Override public final GL2 getGL2() throws GLException { throw new GLException("Not a GL2 implementation"); } +@Override public final GLES1 getGLES1() throws GLException { return this; } +@Override public final GLES2 getGLES2() throws GLException { throw new GLException("Not a GLES2 implementation"); } +@Override public final GL2ES1 getGL2ES1() throws GLException { return this; } +@Override public final GL2ES2 getGL2ES2() throws GLException { throw new GLException("Not a GL2ES2 implementation"); } +@Override public final GL2GL3 getGL2GL3() throws GLException { throw new GLException("Not a GL2GL3 implementation"); } @@ -119,17 +143,17 @@ private final GLStateTracker glStateTracker; private boolean bufferObjectExtensionsInitialized = false; private boolean haveOESFramebufferObject; -private void initBufferObjectExtensionChecks() { +private final void initBufferObjectExtensionChecks() { if (bufferObjectExtensionsInitialized) return; bufferObjectExtensionsInitialized = true; haveOESFramebufferObject = isExtensionAvailable("GL_OES_framebuffer_object"); } -private boolean checkBufferObject(boolean avail, - boolean enabled, - int state, - String kind, boolean throwException) { +private final boolean checkBufferObject(boolean avail, + boolean enabled, + int state, + String kind, boolean throwException) { if (!avail) { if (!enabled) return true; @@ -157,7 +181,7 @@ private boolean checkBufferObject(boolean avail, return true; } -private boolean checkArrayVBODisabled(boolean throwException) { +private final boolean checkArrayVBODisabled(boolean throwException) { initBufferObjectExtensionChecks(); return checkBufferObject(true, false, @@ -165,7 +189,7 @@ private boolean checkArrayVBODisabled(boolean throwException) { "array vertex_buffer_object", throwException); } -private boolean checkArrayVBOEnabled(boolean throwException) { +private final boolean checkArrayVBOEnabled(boolean throwException) { initBufferObjectExtensionChecks(); return checkBufferObject(true, true, @@ -173,7 +197,7 @@ private boolean checkArrayVBOEnabled(boolean throwException) { "array vertex_buffer_object", throwException); } -private boolean checkElementVBODisabled(boolean throwException) { +private final boolean checkElementVBODisabled(boolean throwException) { initBufferObjectExtensionChecks(); return checkBufferObject(true, false, @@ -181,7 +205,7 @@ private boolean checkElementVBODisabled(boolean throwException) { "element vertex_buffer_object", throwException); } -private boolean checkElementVBOEnabled(boolean throwException) { +private final boolean checkElementVBOEnabled(boolean throwException) { initBufferObjectExtensionChecks(); return checkBufferObject(true, true, @@ -189,30 +213,30 @@ private boolean checkElementVBOEnabled(boolean throwException) { "element vertex_buffer_object", throwException); } -private boolean checkUnpackPBODisabled(boolean throwException) { +private final boolean checkUnpackPBODisabled(boolean throwException) { // PBO n/a for ES 1.1 or ES 2.0 return true; } -private boolean checkUnpackPBOEnabled(boolean throwException) { +private final boolean checkUnpackPBOEnabled(boolean throwException) { // PBO n/a for ES 1.1 or ES 2.0 return false; } -private boolean checkPackPBODisabled(boolean throwException) { +private final boolean checkPackPBODisabled(boolean throwException) { // PBO n/a for ES 1.1 or ES 2.0 return true; } -private boolean checkPackPBOEnabled(boolean throwException) { +private final boolean checkPackPBOEnabled(boolean throwException) { // PBO n/a for ES 1.1 or ES 2.0 return false; } -private HashMap arbMemCache = new HashMap(); +private final HashMap arbMemCache = new HashMap(); /** Entry point to C language function:
LPVOID glMapBuffer(GLenum target, GLenum access); */ -public java.nio.ByteBuffer glMapBuffer(int target, int access) { +public final java.nio.ByteBuffer glMapBuffer(int target, int access) { final long __addr_ = ((GLES1ProcAddressTable)_context.getGLProcAddressTable())._addressof_glMapBuffer; if (__addr_ == 0) { throw new GLException("Method \"glMapBuffer\" not available"); @@ -252,7 +276,8 @@ native private long dispatch_glMapBuffer(int target, int access, long glProcAddr native private ByteBuffer newDirectByteBuffer(long addr, long capacity); -public void glVertexPointer(GLArrayData array) { +@Override +public final void glVertexPointer(GLArrayData array) { if(array.getComponentCount()==0) return; if(array.isVBO()) { glVertexPointer(array.getComponentCount(), array.getComponentType(), array.getStride(), array.getVBOOffset()); @@ -260,7 +285,8 @@ public void glVertexPointer(GLArrayData array) { glVertexPointer(array.getComponentCount(), array.getComponentType(), array.getStride(), array.getBuffer()); } } -public void glColorPointer(GLArrayData array) { +@Override +public final void glColorPointer(GLArrayData array) { if(array.getComponentCount()==0) return; if(array.isVBO()) { glColorPointer(array.getComponentCount(), array.getComponentType(), array.getStride(), array.getVBOOffset()); @@ -269,7 +295,8 @@ public void glColorPointer(GLArrayData array) { } } -public void glNormalPointer(GLArrayData array) { +@Override +public final void glNormalPointer(GLArrayData array) { if(array.getComponentCount()==0) return; if(array.getComponentCount()!=3) { throw new GLException("Only 3 components per normal allowed"); @@ -280,7 +307,8 @@ public void glNormalPointer(GLArrayData array) { glNormalPointer(array.getComponentType(), array.getStride(), array.getBuffer()); } } -public void glTexCoordPointer(GLArrayData array) { +@Override +public final void glTexCoordPointer(GLArrayData array) { if(array.getComponentCount()==0) return; if(array.isVBO()) { glTexCoordPointer(array.getComponentCount(), array.getComponentType(), array.getStride(), array.getVBOOffset()); diff --git a/make/config/jogl/gl-impl-CustomJavaCode-gles2.java b/make/config/jogl/gl-impl-CustomJavaCode-gles2.java index a4976f5ea..760287364 100644 --- a/make/config/jogl/gl-impl-CustomJavaCode-gles2.java +++ b/make/config/jogl/gl-impl-CustomJavaCode-gles2.java @@ -1,6 +1,3 @@ -// Tracks glBegin/glEnd calls to determine whether it is legal to -// query Vertex Buffer Object state -private boolean inBeginEndPair; public GLES2Impl(GLProfile glp, GLContextImpl context) { this._context = context; @@ -16,18 +13,22 @@ public GLES2Impl(GLProfile glp, GLContextImpl context) { this.glProfile = glp; } +@Override public final boolean isGL4bc() { return false; } +@Override public final boolean isGL4() { return false; } +@Override public final boolean isGL3bc() { return false; } +@Override public final boolean isGL3() { return false; } @@ -36,78 +37,97 @@ public final boolean isGL2() { return false; } +@Override public final boolean isGLES1() { return false; } +@Override public final boolean isGLES2() { return true; } +@Override public final boolean isGLES() { return true; } +@Override public final boolean isGL2ES1() { return false; } +@Override public final boolean isGL2ES2() { return true; } +@Override public final boolean isGLES2Compatible() { return true; } +@Override public final boolean isGL2GL3() { return false; } +@Override public final boolean hasGLSL() { return true; } +@Override public boolean isNPOTTextureAvailable() { return true; } +@Override public final GL4bc getGL4bc() throws GLException { throw new GLException("Not a GL4bc implementation"); } +@Override public final GL4 getGL4() throws GLException { throw new GLException("Not a GL4 implementation"); } +@Override public final GL3bc getGL3bc() throws GLException { throw new GLException("Not a GL3bc implementation"); } +@Override public final GL3 getGL3() throws GLException { throw new GLException("Not a GL3 implementation"); } +@Override public final GL2 getGL2() throws GLException { throw new GLException("Not a GL2 implementation"); } +@Override public final GLES1 getGLES1() throws GLException { throw new GLException("Not a GLES1 implementation"); } +@Override public final GLES2 getGLES2() throws GLException { return this; } +@Override public final GL2ES1 getGL2ES1() throws GLException { throw new GLException("Not a GL2ES1 implementation"); } +@Override public final GL2ES2 getGL2ES2() throws GLException { return this; } +@Override public final GL2GL3 getGL2GL3() throws GLException { throw new GLException("Not a GL2GL3 implementation"); } @@ -123,17 +143,17 @@ private final GLStateTracker glStateTracker; private boolean bufferObjectExtensionsInitialized = false; private boolean haveOESFramebufferObject; -private void initBufferObjectExtensionChecks() { +private final void initBufferObjectExtensionChecks() { if (bufferObjectExtensionsInitialized) return; bufferObjectExtensionsInitialized = true; haveOESFramebufferObject = isExtensionAvailable("GL_OES_framebuffer_object"); } -private boolean checkBufferObject(boolean avail, - boolean enabled, - int state, - String kind, boolean throwException) { +private final boolean checkBufferObject(boolean avail, + boolean enabled, + int state, + String kind, boolean throwException) { if (!avail) { if (!enabled) return true; @@ -161,7 +181,7 @@ private boolean checkBufferObject(boolean avail, return true; } -private boolean checkArrayVBODisabled(boolean throwException) { +private final boolean checkArrayVBODisabled(boolean throwException) { initBufferObjectExtensionChecks(); return checkBufferObject(true, false, @@ -169,7 +189,7 @@ private boolean checkArrayVBODisabled(boolean throwException) { "array vertex_buffer_object", throwException); } -private boolean checkArrayVBOEnabled(boolean throwException) { +private final boolean checkArrayVBOEnabled(boolean throwException) { initBufferObjectExtensionChecks(); return checkBufferObject(true, true, @@ -177,7 +197,7 @@ private boolean checkArrayVBOEnabled(boolean throwException) { "array vertex_buffer_object", throwException); } -private boolean checkElementVBODisabled(boolean throwException) { +private final boolean checkElementVBODisabled(boolean throwException) { initBufferObjectExtensionChecks(); return checkBufferObject(true, false, @@ -185,7 +205,7 @@ private boolean checkElementVBODisabled(boolean throwException) { "element vertex_buffer_object", throwException); } -private boolean checkElementVBOEnabled(boolean throwException) { +private final boolean checkElementVBOEnabled(boolean throwException) { initBufferObjectExtensionChecks(); return checkBufferObject(true, true, @@ -193,30 +213,31 @@ private boolean checkElementVBOEnabled(boolean throwException) { "element vertex_buffer_object", throwException); } -private boolean checkUnpackPBODisabled(boolean throwException) { +private final boolean checkUnpackPBODisabled(boolean throwException) { // PBO n/a for ES 1.1 or ES 2.0 return true; } -private boolean checkUnpackPBOEnabled(boolean throwException) { +private final boolean checkUnpackPBOEnabled(boolean throwException) { // PBO n/a for ES 1.1 or ES 2.0 return false; } -private boolean checkPackPBODisabled(boolean throwException) { +private final boolean checkPackPBODisabled(boolean throwException) { // PBO n/a for ES 1.1 or ES 2.0 return true; } -private boolean checkPackPBOEnabled(boolean throwException) { +private final boolean checkPackPBOEnabled(boolean throwException) { // PBO n/a for ES 1.1 or ES 2.0 return false; } -private HashMap arbMemCache = new HashMap(); +private final HashMap arbMemCache = new HashMap(); /** Entry point to C language function:
LPVOID glMapBuffer(GLenum target, GLenum access); */ -public java.nio.ByteBuffer glMapBuffer(int target, int access) { +@Override +public final java.nio.ByteBuffer glMapBuffer(int target, int access) { final long __addr_ = ((GLES2ProcAddressTable)_context.getGLProcAddressTable())._addressof_glMapBuffer; if (__addr_ == 0) { throw new GLException("Method \"glMapBuffer\" not available"); @@ -256,11 +277,13 @@ native private long dispatch_glMapBuffer(int target, int access, long glProcAddr native private ByteBuffer newDirectByteBuffer(long addr, long capacity); -public void glClearDepth(double depth) { +@Override +public final void glClearDepth(double depth) { glClearDepthf((float)depth); } -public void glDepthRange(double zNear, double zFar) { +@Override +public final void glDepthRange(double zNear, double zFar) { glDepthRangef((float)zNear, (float)zFar); } diff --git a/make/scripts/java-win32-dbg.bat b/make/scripts/java-win32-dbg.bat index d1797bdbb..6f8206721 100755 --- a/make/scripts/java-win32-dbg.bat +++ b/make/scripts/java-win32-dbg.bat @@ -9,9 +9,9 @@ set BLD_DIR=..\%BLD_SUB% set FFMPEG_LIB=%PROJECT_ROOT%\make\lib\ffmpeg\x32 -set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;%FFMPEG_LIB%;%PATH% -REM set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;%PROJECT_ROOT%\make\lib\angle\win32;%PATH% -REM set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;%PROJECT_ROOT%\make\lib\PVRVFrame\OGLES-2.0\Windows_x86_32;%PATH% +REM set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;%FFMPEG_LIB%;%PATH% +REM set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;%PROJECT_ROOT%\make\lib\external\angle\win32;%PATH% +set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;%PROJECT_ROOT%\make\lib\external\PVRVFrame\OGLES-2.0\Windows_x86_32;%PATH% REM set LIB_DIR=%BLD_DIR%\lib;..\..\gluegen\%BLD_SUB%\obj set LIB_DIR=%FFMPEG_LIB% @@ -20,11 +20,14 @@ set CP_ALL=.;%BLD_DIR%\jar\jogl-all.jar;%BLD_DIR%\jar\jogl-test.jar;..\..\gluege echo CP_ALL %CP_ALL% -set D_ARGS="-Djogamp.debug.IOUtil" "-Djogl.debug.GLSLCode" "-Djogl.debug.GLMediaPlayer" +set D_ARGS="-Djogl.debug.GLContext" "-Djogl.debug.FBObject" +REM set D_ARGS="-Djogl.debug.GLDrawable" "-Djogl.debug.EGLDrawableFactory.DontQuery" +REM set D_ARGS="-Djogl.debug.GLDrawable" "-Djogl.debug.EGLDrawableFactory.QueryNativeTK" +REM set D_ARGS="-Djogl.debug=all" "-Dnewt.debug=all" "-Dnativewindow.debug=all" +REM set D_ARGS="-Djogamp.debug.IOUtil" "-Djogl.debug.GLSLCode" "-Djogl.debug.GLMediaPlayer" REM set D_ARGS="-Djogl.debug.ExtensionAvailabilityCache" "-Djogl.debug=all" "-Dnewt.debug=all" "-Dnativewindow.debug=all" "-Djogamp.debug.ProcAddressHelper=true" "-Djogamp.debug.NativeLibrary=true" "-Djogamp.debug.NativeLibrary.Lookup=true" REM set D_ARGS="-Djogl.debug=all" "-Dnewt.debug=all" "-Dnativewindow.debug=all" "-Djogamp.debug.NativeLibrary=true" REM set D_ARGS="-Djogamp.debug.JNILibLoader=true" "-Djogamp.debug.NativeLibrary=true" "-Djogamp.debug.NativeLibrary.Lookup=true" "-Djogl.debug.GLProfile=true" -REM set D_ARGS="-Djogl.debug=all" "-Dnewt.debug=all" "-Dnativewindow.debug=all" REM set D_ARGS="-Dnewt.debug.Window" "-Dnativewindow.debug.TraceLock" REM set D_ARGS="-Dnativewindow.debug.TraceLock" REM set D_ARGS="-Dnewt.debug.Window" "-Dnewt.debug.Display" diff --git a/make/scripts/java-win32.bat b/make/scripts/java-win32.bat index 9d59c045e..1d8430280 100755 --- a/make/scripts/java-win32.bat +++ b/make/scripts/java-win32.bat @@ -8,8 +8,8 @@ set PROJECT_ROOT=D:\projects\jogamp\jogl set BLD_DIR=..\%BLD_SUB% REM set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;c:\mingw\bin;%PATH% -set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;%PROJECT_ROOT%\make\lib\angle\win32;%PATH% -REM set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;%PROJECT_ROOT%\make\lib\PVRVFrame\OGLES-2.0\Windows_x86_32;%PATH% +REM set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;%PROJECT_ROOT%\make\lib\angle\win32;%PATH% +set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;%PROJECT_ROOT%\make\lib\PVRVFrame\OGLES-2.0\Windows_x86_32;%PATH% set BLD_DIR=..\%BLD_SUB% REM set LIB_DIR=..\..\gluegen\%BLD_SUB%\obj;%BLD_DIR%\lib diff --git a/make/scripts/java-win64-dbg.bat b/make/scripts/java-win64-dbg.bat index d6b0435ea..109755d2e 100755 --- a/make/scripts/java-win64-dbg.bat +++ b/make/scripts/java-win64-dbg.bat @@ -9,7 +9,8 @@ set BLD_DIR=..\%BLD_SUB% set FFMPEG_LIB=%PROJECT_ROOT%\make\lib\ffmpeg\x64 -set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;%FFMPEG_LIB%;%PATH% +set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;c:\mingw\bin;%PATH% +REM set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;%PROJECT_ROOT%\make\lib\external\PVRVFrame\OGLES-2.0\Windows_x86_64;%PATH% REM set LIB_DIR=%BLD_DIR%\lib;..\..\gluegen\%BLD_SUB%\obj set LIB_DIR=%FFMPEG_LIB% @@ -17,7 +18,13 @@ set CP_ALL=.;%BLD_DIR%\jar\jogl-all.jar;%BLD_DIR%\jar\jogl-test.jar;..\..\gluege echo CP_ALL %CP_ALL% -set D_ARGS="-Djogamp.debug.IOUtil" "-Djogl.debug.GLSLCode" "-Djogl.debug.GLMediaPlayer" +set D_ARGS="-Djogl.debug.GLContext" "-Djogl.debug.FBObject" +REM set D_ARGS="-Djogl.debug.GLDrawable" "-Djogl.debug.EGLDrawableFactory.DontQuery" +REM set D_ARGS="-Djogl.debug.GLDrawable" "-Djogl.debug.EGLDrawableFactory.QueryNativeTK" +REM set D_ARGS="-Djogl.debug=all" "-Dnewt.debug=all" "-Dnativewindow.debug=all" +REM set D_ARGS="-Djogl.debug=all" "-Dnewt.debug=all" "-Dnativewindow.debug=all" "-Djogamp.debug=all" "-Djogl.debug.EGLDrawableFactory.DontQuery" +REM set D_ARGS="-Dnativewindow.debug.GraphicsConfiguration -Djogl.debug.CapabilitiesChooser -Djogl.debug.GLProfile" +REM set D_ARGS="-Djogamp.debug.IOUtil" "-Djogl.debug.GLSLCode" "-Djogl.debug.GLMediaPlayer" REM set D_ARGS="-Djogamp.debug.NativeLibrary=true" "-Djogamp.debug.NativeLibrary.Lookup=true" "-Djogl.debug.GLSLCode" REM set D_ARGS="-Djogl.debug.ExtensionAvailabilityCache" "-Djogl.debug=all" "-Dnewt.debug=all" "-Dnativewindow.debug=all" "-Djogamp.debug.ProcAddressHelper=true" "-Djogamp.debug.NativeLibrary=true" "-Djogamp.debug.NativeLibrary.Lookup=true" REM set D_ARGS="-Djogl.debug=all" "-Dnewt.debug=all" "-Dnativewindow.debug=all" "-Djogamp.debug.NativeLibrary=true" @@ -33,7 +40,6 @@ REM set D_ARGS="-Djogl.debug.GLCanvas" "-Djogl.debug.Animator" "-Djogl.debug.GLC REM set D_ARGS="-Dnewt.debug.Window" REM set D_ARGS="-Djogl.debug.GLDebugMessageHandler" "-Djogl.debug.DebugGL" "-Djogl.debug.TraceGL" REM set D_ARGS="-Djogl.debug.DebugGL" "-Djogl.debug.GLDebugMessageHandler" "-Djogl.debug.GLSLCode" -REM set D_ARGS="-Djogl.debug.GraphicsConfiguration" "-Djogl.debug.CapabilitiesChooser" REM set D_ARGS="-Djogl.debug.GLContext" "-Dnewt.debug=all" REM set D_ARGS="-Dnewt.debug.Window" "-Dnativewindow.debug.TraceLock" REM set D_ARGS="-Dnativewindow.debug.TraceLock" diff --git a/make/scripts/java-win64.bat b/make/scripts/java-win64.bat index b8f438aab..2c09feedc 100755 --- a/make/scripts/java-win64.bat +++ b/make/scripts/java-win64.bat @@ -4,7 +4,8 @@ set J2RE_HOME=c:\jre1.6.0_30_x64 set JAVA_HOME=c:\jdk1.6.0_30_x64 set ANT_PATH=C:\apache-ant-1.8.2 -set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;c:\mingw\bin;%PATH% +REM set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;c:\mingw\bin;%PATH% +set PATH=%JAVA_HOME%\bin;%ANT_PATH%\bin;%PROJECT_ROOT%\make\lib\external\PVRVFrame\OGLES-2.0\Windows_x86_64;%PATH% set BLD_DIR=..\%BLD_SUB% REM set LIB_DIR=%BLD_DIR%\lib;..\..\gluegen\%BLD_SUB%\obj diff --git a/make/scripts/tests-x32.bat b/make/scripts/tests-x32.bat index c29dcef39..7947759a4 100755 --- a/make/scripts/tests-x32.bat +++ b/make/scripts/tests-x32.bat @@ -51,7 +51,7 @@ REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.newt.TestScreenMode0 REM scripts\java-win32.bat com.jogamp.opengl.test.junit.newt.ManualScreenMode03NEWT REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.es2.av.MovieSimple %* -scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.es2.av.MovieCube %* +REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.es2.av.MovieCube %* REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.es2.TexCubeES2 %* REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.newt.TestDisplayLifecycle01NEWT @@ -94,6 +94,7 @@ REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.jogl.acore.TestGPUMe REM scripts\java-win32.bat com.jogamp.opengl.test.junit.jogl.acore.TestMapBuffer01NEWT REM scripts\java-win32.bat com.jogamp.opengl.test.junit.jogl.glsl.TestRulerNEWT01 +scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.jogl.acore.TestFBODrawableNEWT %* REM scripts\java-win32.bat com.jogamp.opengl.test.junit.jogl.glsl.TestFBOMRTNEWT01 REM scripts\java-win32-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestElektronenMultipliziererNEWT %* diff --git a/make/scripts/tests-x64.bat b/make/scripts/tests-x64.bat index 32729d235..0b3711784 100755 --- a/make/scripts/tests-x64.bat +++ b/make/scripts/tests-x64.bat @@ -72,7 +72,7 @@ REM scripts\java-win64.bat com.jogamp.opengl.test.junit.newt.TestWindowClosingPr REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.swt.TestSWT01GLn %* REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.swt.TestSWT02GLn %* REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.swt.TestSWTAWT01GLn %* -scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.swt.TestSWTJOGLGLCanvas01GLn %* +REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.swt.TestSWTJOGLGLCanvas01GLn %* REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.offscreen.TestOffscreen02BitmapNEWT -time 5000 @@ -96,7 +96,8 @@ REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.acore.TestGPUMe REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestMapBuffer01NEWT REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.glsl.TestRulerNEWT01 -REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.glsl.TestFBOMRTNEWT01 +scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.acore.TestFBODrawableNEWT %* +REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.glsl.TestFBOMRTNEWT01 %* REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestElektronenMultipliziererNEWT %* diff --git a/make/scripts/tests.sh b/make/scripts/tests.sh index 0258187fd..591f5f9d2 100755 --- a/make/scripts/tests.sh +++ b/make/scripts/tests.sh @@ -53,10 +53,17 @@ function jrun() { swton=$1 shift + #D_ARGS="-Djogl.debug.FBObject -Djogl.debug.DebugGL" + #D_ARGS="-Djogl.debug.FBObject" + #D_ARGS="-Dnativewindow.debug.GraphicsConfiguration -Djogl.debug.GLDrawable -Djogl.debug.GLContext -Djogl.debug.FBObject" #D_ARGS="-Djogl.debug.GLContext.NoProfileAliasing" #D_ARGS="-Djogamp.debug=all -Dnativewindow.debug=all -Djogl.debug=all -Dnewt.debug=all" #D_ARGS="-Djogl.debug=all -Dnativewindow.debug=all -Dnewt.debug=all" + #D_ARGS="-Djogl.debug=all -Dnativewindow.debug=all -Dnewt.debug=all -Djogamp.debug.Lock" #D_ARGS="-Djogl.debug=all -Dnativewindow.debug=all" + #D_ARGS="-Djogl.debug.EGLDrawableFactory.DontQuery -Djogl.debug.GLDrawable" + #D_ARGS="-Djogl.debug.EGLDrawableFactory.QueryNativeTK -Djogl.debug.GLDrawable" + #D_ARGS="-Djogl.debug.GLDrawable" #D_ARGS="-Djogl.debug=all -Dnewt.debug=all" #D_ARGS="-Djogl.debug.DebugGL -Djogl.debug.TraceGL" #D_ARGS="-Djogl.debug.GLDebugMessageHandler" @@ -71,6 +78,7 @@ function jrun() { #D_ARGS="-Djogamp.debug.IOUtil -Djogl.debug.GLSLCode -Djogl.debug.GLMediaPlayer" #D_ARGS="-Djogl.debug.GLArrayData" #D_ARGS="-Djogl.debug.EGL -Dnativewindow.debug.GraphicsConfiguration -Djogl.debug.GLDrawable" + #D_ARGS="-Djogl.debug.GLDrawable" #D_ARGS="-Dnewt.test.Screen.disableScreenMode -Dnewt.debug.Screen" #D_ARGS="-Djogl.debug.ExtensionAvailabilityCache -Djogl.debug=all -Dnativewindow.debug=all -Djogamp.debug.ProcAddressHelper=true -Djogamp.debug.NativeLibrary=true -Djogamp.debug.NativeLibrary.Lookup=true" #D_ARGS="-Dnewt.debug.MainThread" @@ -85,7 +93,7 @@ function jrun() { #D_ARGS="-Dnativewindow.debug.NativeWindow" #D_ARGS="-Dnewt.debug.Window -Dnewt.debug.Display -Dnewt.debug.EDT" #D_ARGS="-Dnewt.debug.EDT -Dnewt.debug.Window -Djogl.debug.GLContext" - #D_ARGS="-Dnativewindow.debug.ToolkitLock.TraceLock -Dnativewindow.debug.X11Util.XErrorStackDump -Dnativewindow.debug.X11Util.TraceDisplayLifecycle -Dnativewindow.debug.X11Util" + #D_ARGS="-Dnativewindow.debug.X11Util.XErrorStackDump -Dnativewindow.debug.X11Util.TraceDisplayLifecycle -Dnativewindow.debug.X11Util" #D_ARGS="-Dnativewindow.debug.X11Util -Djogl.debug.GLContext -Djogl.debug.GLDrawable -Dnewt.debug=all" #D_ARGS="-Dnativewindow.debug.X11Util -Dnativewindow.debug.X11Util.XSync" #D_ARGS="-Dnativewindow.debug.X11Util.XSync -Dnewt.debug.Window" @@ -100,9 +108,9 @@ function jrun() { #D_ARGS="-Djogl.debug.Animator -Dnewt.debug=all" #D_ARGS="-Dnewt.debug.EDT -Dnewt.debug.Display -Dnativewindow.debug.X11Util -Djogl.debug.GLDrawable -Djogl.debug.GLCanvas" #D_ARGS="-Djogl.debug.GLContext" - #D_ARGS="-Djogl.debug.GraphicsConfiguration -Djogl.debug.CapabilitiesChooser" + #D_ARGS="-Dnativewindow.debug.GraphicsConfiguration -Djogl.debug.CapabilitiesChooser" #D_ARGS="-Dnewt.debug.Screen -Dnewt.debug.EDT -Djogamp.debug.Lock" - #D_ARGS="-Djogl.debug.GLContext -Djogl.debug.GraphicsConfiguration" + #D_ARGS="-Djogl.debug.GLContext -Dnativewindow.debug.GraphicsConfiguration" #D_ARGS="-Dnewt.debug.EDT" #D_ARGS="-Dnewt.debug.Window -Dnewt.debug.Display -Dnewt.debug.EDT -Djogl.debug.GLContext" #D_ARGS="-Dnewt.debug.Window -Djogl.debug.Animator -Dnewt.debug.Screen" @@ -115,8 +123,6 @@ function jrun() { #D_ARGS="-Xprof" #D_ARGS="-Djogl.debug.Animator" #D_ARGS="-Dnativewindow.debug=all" - #D_ARGS="-Djogl.debug.GraphicsConfiguration" - #D_ARGS="-Djogl.debug.GLCanvas -Djogl.debug.GraphicsConfiguration" #D_ARGS="-Djogl.debug.GLCanvas" #D_ARGS="-Dnativewindow.debug.ToolkitLock.TraceLock" #D_ARGS="-Djogl.debug.graph.curve -Djogl.debug.GLSLCode -Djogl.debug.TraceGL" @@ -162,20 +168,20 @@ function jrun() { C_ARG="com.jogamp.newt.util.MainThread" fi fi + #export LD_LIBRARY_PATH=$spath/../lib/external/PVRVFrame/OGLES-2.0/Linux_x86_64:$LD_LIBRARY_PATH + #export LD_LIBRARY_PATH=$spath/../lib/external/PVRVFrame/OGLES-2.0/Linux_x86_32:$LD_LIBRARY_PATH + #export LD_LIBRARY_PATH=/usr/local/projects/Xorg.modular/build-x86_64/lib:$LD_LIBRARY_PATH + #export LD_LIBRARY_PATH=/opt-linux-x86_64/x11lib-1.3:$LD_LIBRARY_PATH + #export LD_LIBRARY_PATH=/opt-linux-x86_64/mesa-7.8.1/lib64:$LD_LIBRARY_PATH + #export LD_LIBRARY_PATH=/usr/lib/mesa:/usr/lib32/mesa:$LD_LIBRARY_PATH + #export LD_LIBRARY_PATH=/usr/lib/x86_64-linux-gnu/mesa:/usr/lib/i386-linux-gnu/mesa:$LD_LIBRARY_PATH echo echo "Test Start: $*" echo echo LD_LIBRARY_PATH $LD_LIBRARY_PATH echo echo $javaexe $javaxargs $X_ARGS $D_ARGS $C_ARG $* - #LD_LIBRARY_PATH=/usr/local/projects/Xorg.modular/build-x86_64/lib:$LD_LIBRARY_PATH \ - #LD_LIBRARY_PATH=/opt-linux-x86_64/x11lib-1.3:$LD_LIBRARY_PATH \ - #LD_LIBRARY_PATH=/opt-linux-x86_64/mesa-7.8.1/lib64:$LD_LIBRARY_PATH \ #LIBGL_DRIVERS_PATH=/usr/lib/mesa:/usr/lib32/mesa \ - #LD_LIBRARY_PATH=/usr/lib/mesa:/usr/lib32/mesa:$LD_LIBRARY_PATH \ - #LD_LIBRARY_PATH=/usr/lib/x86_64-linux-gnu/mesa:/usr/lib/i386-linux-gnu/mesa:$LD_LIBRARY_PATH \ - #LD_LIBRARY_PATH=$spath/../lib/PVRVFrame/OGLES-2.0/Linux_x86_64:$LD_LIBRARY_PATH \ - #LD_LIBRARY_PATH=$spath/../lib/PVRVFrame/OGLES-2.0/Linux_x86_32:$LD_LIBRARY_PATH \ #gdb --args $javaexe $javaxargs $X_ARGS $D_ARGS $C_ARG $* $javaexe $javaxargs $X_ARGS $D_ARGS $C_ARG $* echo @@ -228,6 +234,7 @@ function testawtswt() { #testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextVBOES2NEWT2 $* #testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableDelegateNEWT $* #testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLContextDrawableSwitchNEWT $* +#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestFBODrawableNEWT $* #testnoawt com.jogamp.opengl.test.junit.newt.parenting.TestParenting01NEWT $* #testnoawt com.jogamp.opengl.test.junit.newt.parenting.TestParenting02NEWT $* @@ -292,7 +299,7 @@ function testawtswt() { # swt (testswt) # #testswt com.jogamp.opengl.test.junit.jogl.swt.TestSWTEclipseGLCanvas01GLn $* -testswt com.jogamp.opengl.test.junit.jogl.swt.TestSWTJOGLGLCanvas01GLn $* +#testswt com.jogamp.opengl.test.junit.jogl.swt.TestSWTJOGLGLCanvas01GLn $* #testawtswt com.jogamp.opengl.test.junit.jogl.swt.TestSWTJOGLGLCanvas01GLn $* #testswt com.jogamp.opengl.test.junit.jogl.swt.TestSWTAccessor02GLn $* @@ -322,7 +329,8 @@ testswt com.jogamp.opengl.test.junit.jogl.swt.TestSWTJOGLGLCanvas01GLn $* #testawt com.jogamp.opengl.test.junit.newt.parenting.TestTranslucentParentingAWT $* #testawt com.jogamp.opengl.test.junit.newt.TestCloseNewtAWT #testawt com.jogamp.opengl.test.junit.jogl.caps.TestMultisampleES1AWT $* -#testawt com.jogamp.opengl.test.junit.jogl.caps.TestMultisampleES1NEWT $* +#testnoawt com.jogamp.opengl.test.junit.jogl.caps.TestMultisampleES1NEWT $* +#testnoawt com.jogamp.opengl.test.junit.jogl.caps.TestMultisampleES2NEWT $* #testawt com.jogamp.opengl.test.junit.jogl.caps.TestTranslucencyAWT $* #testawt com.jogamp.opengl.test.junit.jogl.caps.TestTranslucencyNEWT $* #testawt com.jogamp.opengl.test.junit.jogl.glsl.TestShaderCompilationBug459AWT @@ -358,7 +366,9 @@ testswt com.jogamp.opengl.test.junit.jogl.swt.TestSWTJOGLGLCanvas01GLn $* #testnoawt com.jogamp.opengl.test.junit.jogl.glsl.TestGLSLShaderState01NEWT $* #testnoawt com.jogamp.opengl.test.junit.jogl.glsl.TestGLSLShaderState02NEWT $* #testnoawt com.jogamp.opengl.test.junit.jogl.glsl.TestRulerNEWT01 $* -#testnoawt com.jogamp.opengl.test.junit.jogl.glsl.TestFBOMRTNEWT01 $* +#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestFBOMRTNEWT01 $* +testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestFBOMix2DemosES2NEWT $* +#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestFBODrawableNEWT $* # # Graph @@ -394,6 +404,7 @@ testswt com.jogamp.opengl.test.junit.jogl.swt.TestSWTJOGLGLCanvas01GLn $* #testawt com.jogamp.opengl.test.junit.newt.TestFocus02SwingAWTRobot $* #linux: +#testnoawt com.jogamp.opengl.test.junit.jogl.caps.TestMultisampleES2NEWT $* # linux NV: cannot make ctx current .. # osx: #testawt com.jogamp.opengl.test.junit.newt.parenting.TestParentingFocusTraversal01AWT $* diff --git a/make/stub_includes/opengl/macosx-window-system.h b/make/stub_includes/opengl/macosx-window-system.h index e7fe13553..47b51a509 100644 --- a/make/stub_includes/opengl/macosx-window-system.h +++ b/make/stub_includes/opengl/macosx-window-system.h @@ -31,7 +31,7 @@ NSView* getNSView(NSOpenGLContext* ctx); NSOpenGLContext* createContext(NSOpenGLContext* shareContext, NSView* nsView, - Bool isBackingLayerView, + Bool allowIncompleteView, NSOpenGLPixelFormat* pixelFormat, Bool opaque, int* viewNotReady); diff --git a/src/jogl/classes/com/jogamp/gluegen/opengl/BuildStaticGLInfo.java b/src/jogl/classes/com/jogamp/gluegen/opengl/BuildStaticGLInfo.java index 87a734e1f..482d35cae 100644 --- a/src/jogl/classes/com/jogamp/gluegen/opengl/BuildStaticGLInfo.java +++ b/src/jogl/classes/com/jogamp/gluegen/opengl/BuildStaticGLInfo.java @@ -293,9 +293,9 @@ public class BuildStaticGLInfo { output.println(" public static String getFunctionAssociation(String glFunctionName)"); output.println(" {"); output.println(" String mappedName = null;"); - output.println(" int funcNamePermNum = com.jogamp.gluegen.runtime.opengl.GLExtensionNames.getFuncNamePermutationNumber(glFunctionName);"); + output.println(" int funcNamePermNum = com.jogamp.gluegen.runtime.opengl.GLNameResolver.getFuncNamePermutationNumber(glFunctionName);"); output.println(" for(int i = 0; null==mappedName && i < funcNamePermNum; i++) {"); - output.println(" String tmp = com.jogamp.gluegen.runtime.opengl.GLExtensionNames.getFuncNamePermutation(glFunctionName, i);"); + output.println(" String tmp = com.jogamp.gluegen.runtime.opengl.GLNameResolver.getFuncNamePermutation(glFunctionName, i);"); output.println(" try {"); output.println(" mappedName = (String)funcToAssocMap.get(tmp);"); output.println(" } catch (Exception e) { }"); diff --git a/src/jogl/classes/com/jogamp/gluegen/opengl/GLConfiguration.java b/src/jogl/classes/com/jogamp/gluegen/opengl/GLConfiguration.java index c1a4facd2..ba025e18c 100755 --- a/src/jogl/classes/com/jogamp/gluegen/opengl/GLConfiguration.java +++ b/src/jogl/classes/com/jogamp/gluegen/opengl/GLConfiguration.java @@ -43,7 +43,7 @@ import com.jogamp.gluegen.GlueEmitterControls; import com.jogamp.gluegen.GlueGen; import com.jogamp.gluegen.MethodBinding; import com.jogamp.gluegen.procaddress.ProcAddressConfiguration; -import com.jogamp.gluegen.runtime.opengl.GLExtensionNames; +import com.jogamp.gluegen.runtime.opengl.GLNameResolver; import java.io.File; import java.io.IOException; import java.util.ArrayList; @@ -224,11 +224,11 @@ public class GLConfiguration extends ProcAddressConfiguration { } } } - boolean isGLEnum = GLExtensionNames.isGLEnumeration(symbol); - boolean isGLFunc = GLExtensionNames.isGLFunction(symbol); + boolean isGLEnum = GLNameResolver.isGLEnumeration(symbol); + boolean isGLFunc = GLNameResolver.isGLFunction(symbol); if (isGLFunc || isGLEnum) { - if (GLExtensionNames.isExtensionVEN(symbol, isGLFunc)) { - String extSuffix = GLExtensionNames.getExtensionSuffix(symbol, isGLFunc); + if (GLNameResolver.isExtensionVEN(symbol, isGLFunc)) { + String extSuffix = GLNameResolver.getExtensionSuffix(symbol, isGLFunc); if (getDropUniqVendorExtensions(extSuffix)) { if (DEBUG_IGNORES) { System.err.println("Ignore UniqVendorEXT: " + symbol + ", vendor " + extSuffix); diff --git a/src/jogl/classes/com/jogamp/gluegen/opengl/GLEmitter.java b/src/jogl/classes/com/jogamp/gluegen/opengl/GLEmitter.java index f4658ad7b..809c6783d 100644 --- a/src/jogl/classes/com/jogamp/gluegen/opengl/GLEmitter.java +++ b/src/jogl/classes/com/jogamp/gluegen/opengl/GLEmitter.java @@ -51,7 +51,7 @@ import com.jogamp.gluegen.SymbolFilter; import com.jogamp.gluegen.cgram.types.FunctionSymbol; import com.jogamp.gluegen.procaddress.ProcAddressEmitter; import com.jogamp.gluegen.procaddress.ProcAddressJavaMethodBindingEmitter; -import com.jogamp.gluegen.runtime.opengl.GLExtensionNames; +import com.jogamp.gluegen.runtime.opengl.GLNameResolver; import java.io.IOException; import java.io.PrintWriter; @@ -110,13 +110,13 @@ public class GLEmitter extends ProcAddressEmitter { if (declarations != null) { for (Iterator 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/GLExtensionNames.java deleted file mode 100644 index 426333034..000000000 --- a/src/jogl/classes/com/jogamp/gluegen/runtime/opengl/GLExtensionNames.java +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Copyright (c) 2003-2005 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. - * - */ -package com.jogamp.gluegen.runtime.opengl; - -public class GLExtensionNames { - //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 - // - // Pass-1 Unify ARB extensions with the same value - // Pass-2 Unify vendor extensions, - // if exist as an ARB extension with the same value. - // Pass-3 Emit - - public static final String[] extensionsARB = { "ARB", "GL2", "OES", "KHR", "OML" }; - public static final String[] extensionsVEN = { "3DFX", - "AMD", - "ANGLE", - "ARM", - "APPLE", - "ATI", - "EXT", - "HI", - "HP", - "IBM", - "IMG", - "MESA", - "MESAX", - "NV", - "QCOM", - "SGI", - "SGIS", - "SGIX", - "SUN", - "VIV", - "WIN" - }; - - - public static final boolean isGLFunction(String str) { - return str.startsWith("gl") || /* str.startsWith("glu") || str.startsWith("glX") || */ - str.startsWith("egl") || str.startsWith("wgl") || str.startsWith("agl") || - str.startsWith("cgl") ; - } - - public static final boolean isGLEnumeration(String str) { - return str.startsWith("GL_") || str.startsWith("GLU_") || str.startsWith("GLX_") || - str.startsWith("EGL_") || str.startsWith("WGL_") || str.startsWith("AGL_") || - str.startsWith("CGL_") ; - } - - public static final int getExtensionIdx(String[] extensions, String str, boolean isGLFunc) { - if(isGLFunc) { - for(int i = extensions.length - 1 ; i>=0 ; i--) { - if( str.endsWith(extensions[i]) ) { - return i; - } - } - } else { - for(int i = extensions.length - 1 ; i>=0 ; i--) { - if( str.endsWith("_"+extensions[i]) ) { - return i; - } - } - } - return -1; - } - - public static final boolean isExtension(String[] extensions, String str, boolean isGLFunc) { - return getExtensionIdx(extensions, str, isGLFunc)>=0; - } - - public static final String getExtensionSuffix(String str, boolean isGLFunc) { - int idx = getExtensionIdx(extensionsARB, str, isGLFunc); - if(idx>=0) { - return extensionsARB[idx]; - } - idx = getExtensionIdx(extensionsVEN, str, isGLFunc); - if(idx>=0) { - return extensionsVEN[idx]; - } - return null; - } - - public static final String normalize(String[] extensions, String str, boolean isGLFunc) { - boolean touched = false; - for(int i = extensions.length - 1 ; !touched && i>=0 ; i--) { - if(isGLFunc) { - if(str.endsWith(extensions[i])) { - // functions - str = str.substring(0, str.length()-extensions[i].length()); - touched=true; - } - } else { - if(str.endsWith("_"+extensions[i])) { - // enums - str = str.substring(0, str.length()-1-extensions[i].length()); - touched=true; - } - } - } - return str; - } - public static final String normalizeARB(String str, boolean isGLFunc) { - return normalize(extensionsARB, str, isGLFunc); - } - public static final boolean isExtensionARB(String str, boolean isGLFunc) { - return isExtension(extensionsARB, str, isGLFunc); - } - public static final String normalizeVEN(String str, boolean isGLFunc) { - return normalize(extensionsVEN, str, isGLFunc); - } - public static final boolean isExtensionVEN(String str, boolean isGLFunc) { - return isExtension(extensionsVEN, str, isGLFunc); - } - public static final String normalize(String str, boolean isGLFunc) { - if (isExtensionARB(str, isGLFunc)) { - return normalizeARB(str, isGLFunc); - } - if (isExtensionVEN(str, isGLFunc)) { - return normalizeVEN(str, isGLFunc); - } - return str; - } - public static final boolean isExtension(String str, boolean isGLFunc) { - return isExtension(extensionsARB, str, isGLFunc) || - isExtension(extensionsVEN, str, isGLFunc); - } - - public static final int getFuncNamePermutationNumber(String name) { - if(isExtensionARB(name, true) || isExtensionVEN(name, true)) { - // no name permutation, if it's already a known extension - return 1; - } - return 1 + extensionsARB.length + extensionsVEN.length; - } - - public static final String getFuncNamePermutation(String name, int i) { - // identity - if(i==0) { - return name; - } - if(0>i || i>=(1+extensionsARB.length + extensionsVEN.length)) { - throw new RuntimeException("Index out of range [0.."+(1+extensionsARB.length+extensionsVEN.length-1)+"]: "+i); - } - // ARB - i-=1; - if(i=0 ; i--) { + if( str.endsWith(extensions[i]) ) { + return i; + } + } + } else { + for(int i = extensions.length - 1 ; i>=0 ; i--) { + if( str.endsWith("_"+extensions[i]) ) { + return i; + } + } + } + return -1; + } + + public static final boolean isExtension(String[] extensions, String str, boolean isGLFunc) { + return getExtensionIdx(extensions, str, isGLFunc)>=0; + } + + public static final String getExtensionSuffix(String str, boolean isGLFunc) { + int idx = getExtensionIdx(extensionsARB, str, isGLFunc); + if(idx>=0) { + return extensionsARB[idx]; + } + idx = getExtensionIdx(extensionsVEN, str, isGLFunc); + if(idx>=0) { + return extensionsVEN[idx]; + } + return null; + } + + public static final String normalize(String[] extensions, String str, boolean isGLFunc) { + boolean touched = false; + for(int i = extensions.length - 1 ; !touched && i>=0 ; i--) { + if(isGLFunc) { + if(str.endsWith(extensions[i])) { + // functions + str = str.substring(0, str.length()-extensions[i].length()); + touched=true; + } + } else { + if(str.endsWith("_"+extensions[i])) { + // enums + str = str.substring(0, str.length()-1-extensions[i].length()); + touched=true; + } + } + } + return str; + } + public static final String normalizeARB(String str, boolean isGLFunc) { + return normalize(extensionsARB, str, isGLFunc); + } + public static final boolean isExtensionARB(String str, boolean isGLFunc) { + return isExtension(extensionsARB, str, isGLFunc); + } + public static final String normalizeVEN(String str, boolean isGLFunc) { + return normalize(extensionsVEN, str, isGLFunc); + } + public static final boolean isExtensionVEN(String str, boolean isGLFunc) { + return isExtension(extensionsVEN, str, isGLFunc); + } + public static final String normalize(String str, boolean isGLFunc) { + if (isExtensionARB(str, isGLFunc)) { + return normalizeARB(str, isGLFunc); + } + if (isExtensionVEN(str, isGLFunc)) { + return normalizeVEN(str, isGLFunc); + } + return str; + } + public static final boolean isExtension(String str, boolean isGLFunc) { + return isExtension(extensionsARB, str, isGLFunc) || + isExtension(extensionsVEN, str, isGLFunc); + } + + public static final int getFuncNamePermutationNumber(String name) { + if(isExtensionARB(name, true) || isExtensionVEN(name, true)) { + // no name permutation, if it's already a known extension + return 1; + } + return 1 + extensionsARB.length + extensionsVEN.length; + } + + public static final String getFuncNamePermutation(String name, int i) { + // identity + if(i==0) { + return name; + } + if(0>i || i>=(1+extensionsARB.length + extensionsVEN.length)) { + throw new RuntimeException("Index out of range [0.."+(1+extensionsARB.length+extensionsVEN.length-1)+"]: "+i); + } + // ARB + i-=1; + if(i + * Supports on-the-fly reconfiguration of dimension and multisample buffers via {@link #reset(GL, int, int, int)} + * while preserving the {@link Attachment} references. + *

+ *

+ * Integrates default read/write framebuffers via {@link GLContext#getDefaultReadFramebuffer()} and {@link GLContext#getDefaultReadFramebuffer()}, + * which is being hooked at {@link GL#glBindFramebuffer(int, int)} when the default (zero) framebuffer is selected. + *

+ * + *

FIXME: Implement support for {@link Type#DEPTH_TEXTURE}, {@link Type#STENCIL_TEXTURE} .

+ */ +public class FBObject { + protected static final boolean DEBUG = Debug.debug("FBObject"); + + /** + * Returns true if basic FBO support is available, otherwise false. + *

+ * Basic FBO is supported if the context is either GL-ES >= 2.0, GL >= core 3.0 or implements the extensions + * ARB_ES2_compatibility, ARB_framebuffer_object, EXT_framebuffer_object or OES_framebuffer_object. + *

+ *

+ * Basic FBO support may only include one color attachment and no multisampling, + * as well as limited internal formats for renderbuffer. + *

+ * @see GLContext#hasFBO() + */ + public static final boolean supportsBasicFBO(GL gl) { + return gl.getContext().hasFBO(); + } + + /** + * Returns true if full FBO support is available, otherwise false. + *

+ * Full FBO is supported if the context is either GL >= core 3.0 or implements the extensions + * ARB_framebuffer_object, or all of + * EXT_framebuffer_object, EXT_framebuffer_multisample, + * EXT_framebuffer_blit, GL_EXT_packed_depth_stencil. + *

+ *

+ * Full FBO support includes multiple color attachments and multisampling. + *

+ */ + public static final boolean supportsFullFBO(GL gl) { + return gl.isGL3() || // GL >= 3.0 + + gl.isExtensionAvailable(GLExtensions.ARB_framebuffer_object) || // ARB_framebuffer_object + + ( gl.isExtensionAvailable(GLExtensions.EXT_framebuffer_object) && // All EXT_framebuffer_object* + gl.isExtensionAvailable(GLExtensions.EXT_framebuffer_multisample) && + gl.isExtensionAvailable(GLExtensions.EXT_framebuffer_blit) && + gl.isExtensionAvailable(GLExtensions.EXT_packed_depth_stencil) ) ; + } + + public static final int getMaxSamples(GL gl) { + if( supportsFullFBO(gl) ) { + int[] val = new int[] { 0 } ; + gl.glGetIntegerv(GL2GL3.GL_MAX_SAMPLES, val, 0); + return val[0]; + } else { + return 0; + } + } + + /** Common super class of all attachments */ + public static abstract class Attachment { + public enum Type { + NONE, DEPTH, STENCIL, DEPTH_STENCIL, COLOR, COLOR_TEXTURE, DEPTH_TEXTURE, STENCIL_TEXTURE; + + /** + * Returns {@link #COLOR}, {@link #DEPTH}, {@link #STENCIL} or {@link #DEPTH_STENCIL} + * @throws IllegalArgumentException if format cannot be handled. + */ + public static Type determine(int format) throws IllegalArgumentException { + switch(format) { + case GL.GL_RGBA4: + case GL.GL_RGB5_A1: + case GL.GL_RGB565: + case GL.GL_RGB8: + case GL.GL_RGBA8: + return Type.COLOR; + case GL.GL_DEPTH_COMPONENT16: + case GL.GL_DEPTH_COMPONENT24: + case GL.GL_DEPTH_COMPONENT32: + return Type.DEPTH; + case GL.GL_STENCIL_INDEX1: + case GL.GL_STENCIL_INDEX4: + case GL.GL_STENCIL_INDEX8: + return Type.STENCIL; + case GL.GL_DEPTH24_STENCIL8: + return Type.DEPTH_STENCIL; + default: + throw new IllegalArgumentException("format invalid: 0x"+Integer.toHexString(format)); + } + } + }; + + /** immutable type [{@link #COLOR}, {@link #DEPTH}, {@link #STENCIL}, {@link #COLOR_TEXTURE}, {@link #DEPTH_TEXTURE}, {@link #STENCIL_TEXTURE} ] */ + public final Type type; + + /** immutable the internal format */ + public final int format; + + private int width, height; + + private int name; + + /** true if resource is initialized by {@link #initialize(GL)}, hence {@link #free(GL)} is allowed to free the GL resources. */ + protected boolean resourceOwner; + + private int initCounter; + + protected Attachment(Type type, int iFormat, int width, int height, int name) { + this.type = type; + this.format = iFormat; + this.width = width; + this.height = height; + this.name = name; + this.resourceOwner = false; + this.initCounter = 0; + } + + /** width of attachment */ + public final int getWidth() { return width; } + /** height of attachment */ + public final int getHeight() { return height; } + /* pp */ final void setSize(int w, int h) { width = w; height = h; } + + /** buffer name [1..max], maybe a texture or renderbuffer name, depending on type. */ + public final int getName() { return name; } + /* pp */ final void setName(int n) { name = n; } + + public final int getInitCounter() { return initCounter; } + + /** + * Initializes the attachment buffer and set it's parameter, if uninitialized, i.e. name is zero. + *

Implementation employs an initialization counter, hence it can be paired recursively with {@link #free(GL)}.

+ * @throws GLException if buffer generation or setup fails. The just created buffer name will be deleted in this case. + */ + public void initialize(GL gl) throws GLException { + initCounter++; + /* + super.initialize(gl); + if(1 == getInitCounter() && 0 == getName() ) { + do init .. + freeResources = true; // if all OK + } + */ + } + + /** + * Releases the attachment buffer if initialized, i.e. name is zero. + *

Implementation employs an initialization counter, hence it can be paired recursively with {@link #initialize(GL)}.

+ * @throws GLException if buffer release fails. + */ + public void free(GL gl) throws GLException { + /* + if(1 == getInitCounter() && freeResources && .. ) { + do free .. + } + super.free(gl); + */ + initCounter--; + if(0 == initCounter) { + resourceOwner = false; + name = 0; + } + if(DEBUG) { + System.err.println("Attachment.free: "+this); + } + } + + /** + *

+ * Comparison by {@link #type}, {@link #format}, {@link #width}, {@link #height} and {@link #name}. + *

+ * {@inheritDoc} + */ + @Override + public boolean equals(Object o) { + if( this == o ) return true; + if( ! ( o instanceof Attachment ) ) return false; + final Attachment a = (Attachment)o; + return type == a.type && + format == a.format || + width == a.width || + height== a.height || + name == a.name ; + } + + /** + *

+ * Hashed by {@link #type}, {@link #format}, {@link #width}, {@link #height} and {@link #name}. + *

+ * {@inheritDoc} + */ + @Override + public int hashCode() { + // 31 * x == (x << 5) - x + int hash = 31 + type.ordinal(); + hash = ((hash << 5) - hash) + format; + hash = ((hash << 5) - hash) + width; + hash = ((hash << 5) - hash) + height; + hash = ((hash << 5) - hash) + name; + return hash; + } + + int objectHashCode() { return super.hashCode(); } + + public String toString() { + return getClass().getSimpleName()+"[type "+type+", format 0x"+Integer.toHexString(format)+", "+width+"x"+height+ + ", name 0x"+Integer.toHexString(name)+", obj 0x"+Integer.toHexString(objectHashCode())+ + ", resOwner "+resourceOwner+", initCount "+initCounter+"]"; + } + + public static Type getType(int attachmentPoint, int maxColorAttachments) { + if( GL.GL_COLOR_ATTACHMENT0 <= attachmentPoint && attachmentPoint < GL.GL_COLOR_ATTACHMENT0+maxColorAttachments ) { + return Type.COLOR; + } + switch(attachmentPoint) { + case GL.GL_DEPTH_ATTACHMENT: + return Type.DEPTH; + case GL.GL_STENCIL_ATTACHMENT: + return Type.STENCIL; + default: + throw new IllegalArgumentException("Invalid attachment point 0x"+Integer.toHexString(attachmentPoint)); + } + } + } + + /** Other renderbuffer attachment which maybe a colorbuffer, depth or stencil. */ + public static class RenderAttachment extends Attachment { + private int samples; + + /** + * @param type allowed types are {@link Type#DEPTH}, {@link Type#STENCIL} or {@link Type#COLOR} + * @param iFormat + * @param samples + * @param width + * @param height + * @param name + */ + public RenderAttachment(Type type, int iFormat, int samples, int width, int height, int name) { + super(validateType(type), iFormat, width, height, name); + this.samples = samples; + } + + /** number of samples, or zero for no multisampling */ + public final int getSamples() { return samples; } + /* pp */ final void setSamples(int s) { samples = s; } + + private static Type validateType(Type type) { + switch(type) { + case DEPTH: + case STENCIL: + case COLOR: + return type; + default: + throw new IllegalArgumentException("Invalid type: "+type); + } + } + + /** + *

+ * Comparison by {@link #type}, {@link #format}, {@link #samples}, {@link #width}, {@link #height} and {@link #name}. + *

+ * {@inheritDoc} + */ + @Override + public boolean equals(Object o) { + if( this == o ) return true; + if( ! ( o instanceof RenderAttachment ) ) return false; + return super.equals(o) && + samples == ((RenderAttachment)o).samples; + } + + /** + *

+ * Hashed by {@link #type}, {@link #format}, {@link #samples}, {@link #width}, {@link #height} and {@link #name}. + *

+ * {@inheritDoc} + */ + @Override + public int hashCode() { + // 31 * x == (x << 5) - x + int hash = super.hashCode(); + hash = ((hash << 5) - hash) + samples; + return hash; + } + + @Override + public void initialize(GL gl) throws GLException { + super.initialize(gl); + if( 1 == getInitCounter() && 0 == getName() ) { + final int[] name = new int[] { -1 }; + gl.glGenRenderbuffers(1, name, 0); + if( 0 == name[0] ) { + throw new GLException("null renderbuffer, "+this); + } + setName(name[0]); + + gl.glBindRenderbuffer(GL.GL_RENDERBUFFER, getName()); + if( samples > 0 ) { + ((GL2GL3)gl).glRenderbufferStorageMultisample(GL.GL_RENDERBUFFER, samples, format, getWidth(), getHeight()); + } else { + gl.glRenderbufferStorage(GL.GL_RENDERBUFFER, format, getWidth(), getHeight()); + } + int glerr = gl.glGetError(); + if(GL.GL_NO_ERROR != glerr) { + gl.glDeleteRenderbuffers(1, name, 0); + setName(0); + throw new GLException("GL Error 0x"+Integer.toHexString(glerr)+" while creating "+this); + } + resourceOwner = true; + if(DEBUG) { + System.err.println("Attachment.init: "+this); + } + } + } + + @Override + public void free(GL gl) { + if(1 == getInitCounter() && resourceOwner && 0 != getName() ) { + final int[] name = new int[] { getName() }; + gl.glDeleteRenderbuffers(1, name, 0); + } + super.free(gl); + } + + public String toString() { + return getClass().getSimpleName()+"[type "+type+", format 0x"+Integer.toHexString(format)+", samples "+samples+", "+getWidth()+"x"+getHeight()+ + ", name 0x"+Integer.toHexString(getName())+", obj 0x"+Integer.toHexString(objectHashCode())+ + ", resOwner "+resourceOwner+", initCount "+getInitCounter()+"]"; + } + } + + /** + * Marker interface, denotes a color buffer attachment. + *

Always an instance of {@link Attachment}.

+ *

Either an instance of {@link ColorAttachment} or {@link TextureAttachment}. + */ + public static interface Colorbuffer { + } + + /** Color render buffer attachment */ + public static class ColorAttachment extends RenderAttachment implements Colorbuffer { + public ColorAttachment(int iFormat, int samples, int width, int height, int name) { + super(Type.COLOR, iFormat, samples, width, height, name); + } + } + + /** Texture attachment */ + public static class TextureAttachment extends Attachment implements Colorbuffer { + /** details of the texture setup */ + public final int dataFormat, dataType, magFilter, minFilter, wrapS, wrapT; + + /** + * @param type allowed types are [ {@link Type#COLOR_TEXTURE}, {@link Type#DEPTH_TEXTURE}, {@link Type#STENCIL_TEXTURE} ] + * @param iFormat + * @param width + * @param height + * @param dataFormat + * @param dataType + * @param magFilter + * @param minFilter + * @param wrapS + * @param wrapT + * @param name + */ + public TextureAttachment(Type type, int iFormat, int width, int height, int dataFormat, int dataType, + int magFilter, int minFilter, int wrapS, int wrapT, int name) { + super(validateType(type), iFormat, width, height, name); + this.dataFormat = dataFormat; + this.dataType = dataType; + this.magFilter = magFilter; + this.minFilter = minFilter; + this.wrapS = wrapS; + this.wrapT = wrapT; + } + + private static Type validateType(Type type) { + switch(type) { + case COLOR_TEXTURE: + case DEPTH_TEXTURE: + case STENCIL_TEXTURE: + return type; + default: + throw new IllegalArgumentException("Invalid type: "+type); + } + } + + /** + * Initializes the texture and set it's parameter, if uninitialized, i.e. name is zero. + * @throws GLException if texture generation and setup fails. The just created texture name will be deleted in this case. + */ + @Override + public void initialize(GL gl) throws GLException { + super.initialize(gl); + if( 1 == getInitCounter() && 0 == getName() ) { + final int[] name = new int[] { -1 }; + gl.glGenTextures(1, name, 0); + if(0 == name[0]) { + throw new GLException("null texture, "+this); + } + setName(name[0]); + + gl.glBindTexture(GL.GL_TEXTURE_2D, name[0]); + gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, format, getWidth(), getHeight(), 0, dataFormat, dataType, null); + if( 0 < magFilter ) { + gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, magFilter); + } + if( 0 < minFilter ) { + gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, minFilter); + } + if( 0 < wrapS ) { + gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, wrapS); + } + if( 0 < wrapT ) { + gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, wrapT); + } + int glerr = gl.glGetError(); + if(GL.GL_NO_ERROR != glerr) { + gl.glDeleteTextures(1, name, 0); + setName(0); + throw new GLException("GL Error 0x"+Integer.toHexString(glerr)+" while creating "+this); + } + resourceOwner = true; + } + if(DEBUG) { + System.err.println("Attachment.init: "+this); + } + } + + @Override + public void free(GL gl) { + if(1 == getInitCounter() && resourceOwner && 0 != getName() ) { + final int[] name = new int[] { getName() }; + gl.glDeleteTextures(1, name, 0); + } + super.free(gl); + } + } + + private boolean initialized; + private boolean basicFBOSupport; + private boolean fullFBOSupport; + private boolean rgba8Avail; + private boolean depth24Avail; + private boolean depth32Avail; + private boolean stencil01Avail; + private boolean stencil04Avail; + private boolean stencil08Avail; + private boolean stencil16Avail; + private boolean packedDepthStencilAvail; + private int maxColorAttachments, maxSamples, maxTextureSize, maxRenderbufferSize; + + private int width, height, samples; + private int vStatus; + private int fbName; + private boolean bound; + + private int colorAttachmentCount; + private Colorbuffer[] colorAttachmentPoints; // colorbuffer attachment points + private RenderAttachment depth, stencil; // depth and stencil maybe equal in case of packed-depth-stencil + + private final FBObject samplesSink; // MSAA sink + private TextureAttachment samplesSinkTexture; + private boolean samplesSinkDirty; + + // + // ColorAttachment helper .. + // + + private final void validateColorAttachmentPointRange(int point) { + if(maxColorAttachments != colorAttachmentPoints.length) { + throw new InternalError("maxColorAttachments "+maxColorAttachments+", array.lenght "+colorAttachmentPoints); + } + if(0 > point || point >= maxColorAttachments) { + throw new IllegalArgumentException("attachment point out of range: "+point+", should be within [0.."+(maxColorAttachments-1)+"]"); + } + } + + private final void validateAddColorAttachment(int point, Colorbuffer ca) { + validateColorAttachmentPointRange(point); + if( null != colorAttachmentPoints[point] ) { + throw new IllegalArgumentException("Cannot attach "+ca+", attachment point already in use by "+colorAttachmentPoints[point]); + } + } + + private final void addColorAttachment(int point, Colorbuffer ca) { + validateColorAttachmentPointRange(point); + final Colorbuffer c = colorAttachmentPoints[point]; + if( null != c && c != ca ) { + throw new IllegalArgumentException("Add failed: requested to add "+ca+" at "+point+", but slot is holding "+c+"; "+this); + } + colorAttachmentPoints[point] = ca; + colorAttachmentCount++; + } + + private final void removeColorAttachment(int point, Colorbuffer ca) { + validateColorAttachmentPointRange(point); + final Colorbuffer c = colorAttachmentPoints[point]; + if( null != c && c != ca ) { + throw new IllegalArgumentException("Remove failed: requested to removed "+ca+" at "+point+", but slot is holding "+c+"; "+this); + } + colorAttachmentPoints[point] = null; + colorAttachmentCount--; + } + + /** + * Return the {@link Colorbuffer} attachment at attachmentPoint if it is attached to this FBO, otherwise null. + * + * @see #attachColorbuffer(GL, boolean) + * @see #attachColorbuffer(GL, boolean) + * @see #attachTexture2D(GL, int, boolean, int, int, int, int) + * @see #attachTexture2D(GL, int, int, int, int, int, int, int, int) + */ + public final Colorbuffer getColorbuffer(int attachmentPoint) { + validateColorAttachmentPointRange(attachmentPoint); + return colorAttachmentPoints[attachmentPoint]; + } + + /** + * Finds the passed {@link Colorbuffer} within the valid range of attachment points + * using reference comparison only. + *

+ * Note: Slow. Implementation uses a logN array search to save resources, i.e. not using a HashMap. + *

+ * @param ca the {@link Colorbuffer} to look for. + * @return -1 if the {@link Colorbuffer} could not be found, otherwise [0..{@link #getMaxColorAttachments()}-1] + */ + public final int getColorbufferAttachmentPoint(Colorbuffer ca) { + for(int i=0; ireference only. + * + *

+ * Note: Slow. Uses {@link #getColorbufferAttachmentPoint(Colorbuffer)} to determine it's attachment point + * to be used for {@link #getColorbuffer(int)} + *

+ * + * @see #attachColorbuffer(GL, boolean) + * @see #attachColorbuffer(GL, boolean) + * @see #attachTexture2D(GL, int, boolean, int, int, int, int) + * @see #attachTexture2D(GL, int, int, int, int, int, int, int, int) + */ + public final Colorbuffer getColorbuffer(Colorbuffer ca) { + final int p = getColorbufferAttachmentPoint(ca); + return p>=0 ? getColorbuffer(p) : null; + } + + /** + * Creates an uninitialized FBObject instance. + *

+ * Call {@link #init(GL, int, int, int)} .. etc to use it. + *

+ */ + public FBObject() { + this(false); + } + /* pp */ FBObject(boolean isSampleSink) { + this.initialized = false; + + // TBD @ init + this.basicFBOSupport = false; + this.fullFBOSupport = false; + this.rgba8Avail = false; + this.depth24Avail = false; + this.depth32Avail = false; + this.stencil01Avail = false; + this.stencil04Avail = false; + this.stencil08Avail = false; + this.stencil16Avail = false; + this.packedDepthStencilAvail = false; + this.maxColorAttachments=-1; + this.maxSamples=-1; + this.maxTextureSize = 0; + this.maxRenderbufferSize = 0; + + this.width = 0; + this.height = 0; + this.samples = 0; + this.vStatus = -1; + this.fbName = 0; + this.bound = false; + + this.colorAttachmentPoints = null; // at init .. + this.colorAttachmentCount = 0; + this.depth = null; + this.stencil = null; + + this.samplesSink = isSampleSink ? null : new FBObject(true); + this.samplesSinkTexture = null; + this.samplesSinkDirty = true; + } + + private void init(GL gl, int width, int height, int samples) throws GLException { + if(initialized) { + throw new GLException("FBO already initialized"); + } + fullFBOSupport = supportsFullFBO(gl); + + if( !fullFBOSupport && !supportsBasicFBO(gl) ) { + throw new GLException("FBO not supported w/ context: "+gl.getContext()+", "+this); + } + + basicFBOSupport = true; + + rgba8Avail = gl.isGL2GL3() || gl.isExtensionAvailable(GLExtensions.OES_rgb8_rgba8); + depth24Avail = fullFBOSupport || gl.isExtensionAvailable(GLExtensions.OES_depth24); + depth32Avail = fullFBOSupport || gl.isExtensionAvailable(GLExtensions.OES_depth32); + stencil01Avail = fullFBOSupport || gl.isExtensionAvailable(GLExtensions.OES_stencil1); + stencil04Avail = fullFBOSupport || gl.isExtensionAvailable(GLExtensions.OES_stencil4); + stencil08Avail = fullFBOSupport || gl.isExtensionAvailable(GLExtensions.OES_stencil8); + stencil16Avail = fullFBOSupport; + + packedDepthStencilAvail = fullFBOSupport || gl.isExtensionAvailable(GLExtensions.OES_packed_depth_stencil); + + final boolean NV_fbo_color_attachments = gl.isExtensionAvailable(GLExtensions.NV_fbo_color_attachments); + + int val[] = new int[1]; + + int glerr = gl.glGetError(); + if(DEBUG && GL.GL_NO_ERROR != glerr) { + System.err.println("FBObject.init-preexisting.0 GL Error 0x"+Integer.toHexString(glerr)); + } + + int realMaxColorAttachments = 1; + maxColorAttachments = 1; + if( null != samplesSink && fullFBOSupport || NV_fbo_color_attachments ) { + try { + gl.glGetIntegerv(GL2GL3.GL_MAX_COLOR_ATTACHMENTS, val, 0); + glerr = gl.glGetError(); + if(GL.GL_NO_ERROR == glerr) { + realMaxColorAttachments = 1 <= val[0] ? val[0] : 1; // cap minimum to 1 + } else if(DEBUG) { + System.err.println("FBObject.init-GL_MAX_COLOR_ATTACHMENTS query GL Error 0x"+Integer.toHexString(glerr)); + } + } catch (GLException gle) {} + } + maxColorAttachments = realMaxColorAttachments <= 8 ? realMaxColorAttachments : 8; // cap to limit array size + + colorAttachmentPoints = new Colorbuffer[maxColorAttachments]; + colorAttachmentCount = 0; + + maxSamples = 0; + if(fullFBOSupport) { + gl.glGetIntegerv(GL2GL3.GL_MAX_SAMPLES, val, 0); + glerr = gl.glGetError(); + if(GL.GL_NO_ERROR == glerr) { + maxSamples = val[0]; + } else if(DEBUG) { + System.err.println("FBObject.init-GL_MAX_SAMPLES query GL Error 0x"+Integer.toHexString(glerr)); + } + } + gl.glGetIntegerv(GL.GL_MAX_TEXTURE_SIZE, val, 0); + maxTextureSize = val[0]; + gl.glGetIntegerv(GL.GL_MAX_RENDERBUFFER_SIZE, val, 0); + this.maxRenderbufferSize = val[0]; + + glerr = gl.glGetError(); + if(DEBUG && GL.GL_NO_ERROR != glerr) { + System.err.println("FBObject.init-preexisting.1 GL Error 0x"+Integer.toHexString(glerr)); + } + + this.width = width; + this.height = height; + this.samples = samples <= maxSamples ? samples : maxSamples; + + if(DEBUG) { + System.err.println("FBObject "+width+"x"+height+", "+samples+" -> "+samples+" samples"); + System.err.println("basicFBOSupport: "+basicFBOSupport); + System.err.println("fullFBOSupport: "+fullFBOSupport); + System.err.println("maxColorAttachments: "+maxColorAttachments+"/"+realMaxColorAttachments); + System.err.println("maxSamples: "+maxSamples); + System.err.println("maxTextureSize: "+maxTextureSize); + System.err.println("maxRenderbufferSize: "+maxRenderbufferSize); + System.err.println("rgba8: "+rgba8Avail); + System.err.println("depth24: "+depth24Avail); + System.err.println("depth32: "+depth32Avail); + System.err.println("stencil01: "+stencil01Avail); + System.err.println("stencil04: "+stencil04Avail); + System.err.println("stencil08: "+stencil08Avail); + System.err.println("stencil16: "+stencil16Avail); + System.err.println("packedDepthStencil: "+packedDepthStencilAvail); + System.err.println("NV_fbo_color_attachments: "+NV_fbo_color_attachments); + System.err.println(gl.getContext().getGLVersion()); + System.err.println(JoglVersion.getGLStrings(gl, null).toString()); + System.err.println(gl.getContext()); + } + + checkNoError(null, gl.glGetError(), "FBObject Init.pre"); // throws GLException if error + + if(width > 2 + maxTextureSize || height> 2 + maxTextureSize || + width > maxRenderbufferSize || height> maxRenderbufferSize ) { + throw new GLException("size "+width+"x"+height+" exceeds on of the maxima [texture "+maxTextureSize+", renderbuffer "+maxRenderbufferSize+"]"); + } + + if(null != samplesSink) { + // init sampling sink + samplesSink.reset(gl, width, height); + resetMSAATexture2DSink(gl); + } + + // generate fbo .. + gl.glGenFramebuffers(1, val, 0); + fbName = val[0]; + if(0 == fbName) { + throw new GLException("null framebuffer"); + } + + // bind fbo .. + gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, fbName); + checkNoError(gl, gl.glGetError(), "FBObject Init.bindFB"); // throws GLException if error + if(!gl.glIsFramebuffer(fbName)) { + checkNoError(gl, GL.GL_INVALID_VALUE, "FBObject Init.isFB"); // throws GLException + } + bound = true; + initialized = true; + + updateStatus(gl); + if(DEBUG) { + System.err.println("FBObject.init(): "+this); + } + } + + /** + * Initializes or resets this FBO's instance. + *

+ * In case the new parameters are compatible with the current ones + * no action will be performed. Otherwise all attachments will be recreated + * to match the new given parameters. + *

+ *

+ * Currently incompatibility and hence recreation is given if + * the size or sample count doesn't match for subsequent calls. + *

+ * + *

Leaves the FBO bound state untouched

+ * + * @param gl the current GL context + * @param newWidth + * @param newHeight + * @throws GLException in case of an error + */ + public final void reset(GL gl, int newWidth, int newHeight) { + reset(gl, newWidth, newHeight, 0); + } + + /** + * Initializes or resets this FBO's instance. + *

+ * In case the new parameters are compatible with the current ones + * no action will be performed. Otherwise all attachments will be recreated + * to match the new given parameters. + *

+ *

+ * Currently incompatibility and hence recreation is given if + * the size or sample count doesn't match for subsequent calls. + *

+ * + *

Leaves the FBO bound state untouched

+ * + * @param gl the current GL context + * @param newWidth + * @param newHeight + * @param newSamples if > 0, MSAA will be used, otherwise no multisampling. Will be capped to {@link #getMaxSamples()}. + * @throws GLException in case of an error + */ + public final void reset(GL gl, int newWidth, int newHeight, int newSamples) { + if(!initialized) { + init(gl, newWidth, newHeight, newSamples); + return; + } + newSamples = newSamples <= maxSamples ? newSamples : maxSamples; // clamp + + if( newWidth != width || newHeight != height || newSamples != samples ) { + if(DEBUG) { + System.err.println("FBObject.reset - START - "+this); + } + + final boolean wasBound = isBound(); + + width = newWidth; + height = newHeight; + samples = newSamples; + detachAllImpl(gl, true , true); + resetMSAATexture2DSink(gl); + + if(wasBound) { + bind(gl); + } else { + unbind(gl); + } + + if(DEBUG) { + System.err.println("FBObject.reset - END - "+this); + } + } + } + + /** + * Note that the status may reflect an incomplete state during transition of attachments. + * @return The FB status. {@link GL.GL_FRAMEBUFFER_COMPLETE} if ok, otherwise return GL FBO error state or -1 + * @see #validateStatus() + */ + public final int getStatus() { + return vStatus; + } + + /** return the {@link #getStatus()} as a string. */ + public final String getStatusString() { + return getStatusString(vStatus); + } + + public static final String getStatusString(int fbStatus) { + switch(fbStatus) { + case -1: + return "NOT A FBO"; + + case GL.GL_FRAMEBUFFER_COMPLETE: + return "OK"; + + case GL.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: + return("GL FBO: incomplete, incomplete attachment\n"); + case GL.GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: + return("GL FBO: incomplete, missing attachment"); + case GL.GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS: + return("GL FBO: incomplete, attached images must have same dimensions"); + case GL.GL_FRAMEBUFFER_INCOMPLETE_FORMATS: + return("GL FBO: incomplete, attached images must have same format"); + case GL2GL3.GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER: + return("GL FBO: incomplete, missing draw buffer"); + case GL2GL3.GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER: + return("GL FBO: incomplete, missing read buffer"); + case GL2GL3.GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: + return("GL FBO: incomplete, missing multisample buffer"); + case GL3.GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS: + return("GL FBO: incomplete, layer targets"); + + case GL.GL_FRAMEBUFFER_UNSUPPORTED: + return("GL FBO: Unsupported framebuffer format"); + case GL2GL3.GL_FRAMEBUFFER_UNDEFINED: + return("GL FBO: framebuffer undefined"); + + case 0: + return("GL FBO: incomplete, implementation fault"); + default: + return("GL FBO: incomplete, implementation ERROR 0x"+Integer.toHexString(fbStatus)); + } + } + + /** + * The status may even be valid if incomplete during transition of attachments. + * @see #getStatus() + */ + public final boolean isStatusValid() { + switch(vStatus) { + case GL.GL_FRAMEBUFFER_COMPLETE: + return true; + + case GL.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: + case GL.GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: + case GL.GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS: + case GL.GL_FRAMEBUFFER_INCOMPLETE_FORMATS: + case GL2GL3.GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER: + case GL2GL3.GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER: + case GL2GL3.GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: + case GL3.GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS: + if(0 == colorAttachmentCount || null == depth) { + // we are in transition + return true; + } + + case GL.GL_FRAMEBUFFER_UNSUPPORTED: + case GL2GL3.GL_FRAMEBUFFER_UNDEFINED: + + case 0: + default: + System.out.println("Framebuffer " + fbName + " is incomplete: status = 0x" + Integer.toHexString(vStatus) + + " : " + getStatusString(vStatus)); + return false; + } + } + + private final boolean checkNoError(GL gl, int err, String exceptionMessage) throws GLException { + if(GL.GL_NO_ERROR != err) { + if(null != gl) { + destroy(gl); + } + if(null != exceptionMessage) { + throw new GLException(exceptionMessage+" GL Error 0x"+Integer.toHexString(err)); + } + return false; + } + return true; + } + + private final void checkInitialized() throws GLException { + if(!initialized) { + throw new GLException("FBO not initialized, call init(GL) first."); + } + } + + /** + * Attaches a Texture2D Color Buffer to this FBO's instance at the given attachment point, + * selecting the texture data type and format automatically. + * + *

Using default min/mag filter {@link GL#GL_NEAREST} and default wrapS/wrapT {@link GL#GL_CLAMP_TO_EDGE}.

+ * + *

Leaves the FBO bound.

+ * + * @param gl the current GL context + * @param attachmentPoint the color attachment point ranging from [0..{@link #getMaxColorAttachments()}-1] + * @param alpha set to true if you request alpha channel, otherwise false; + * @return TextureAttachment instance describing the new attached texture colorbuffer if bound and configured successfully, otherwise GLException is thrown + * @throws GLException in case the texture colorbuffer couldn't be allocated or MSAA has been chosen + */ + public final TextureAttachment attachTexture2D(GL gl, int attachmentPoint, boolean alpha) throws GLException { + return attachTexture2D(gl, attachmentPoint, alpha, GL.GL_NEAREST, GL.GL_NEAREST, GL.GL_CLAMP_TO_EDGE, GL.GL_CLAMP_TO_EDGE); + } + + /** + * Attaches a Texture2D Color Buffer to this FBO's instance at the given attachment point, + * selecting the texture data type and format automatically. + * + *

Leaves the FBO bound.

+ * + * @param gl the current GL context + * @param attachmentPoint the color attachment point ranging from [0..{@link #getMaxColorAttachments()}-1] + * @param alpha set to true if you request alpha channel, otherwise false; + * @param magFilter if > 0 value for {@link GL#GL_TEXTURE_MAG_FILTER} + * @param minFilter if > 0 value for {@link GL#GL_TEXTURE_MIN_FILTER} + * @param wrapS if > 0 value for {@link GL#GL_TEXTURE_WRAP_S} + * @param wrapT if > 0 value for {@link GL#GL_TEXTURE_WRAP_T} + * @return TextureAttachment instance describing the new attached texture colorbuffer if bound and configured successfully, otherwise GLException is thrown + * @throws GLException in case the texture colorbuffer couldn't be allocated or MSAA has been chosen + */ + public final TextureAttachment attachTexture2D(GL gl, int attachmentPoint, boolean alpha, int magFilter, int minFilter, int wrapS, int wrapT) throws GLException { + final int textureInternalFormat, textureDataFormat, textureDataType; + if(gl.isGLES()) { + textureInternalFormat = alpha ? GL.GL_RGBA : GL.GL_RGB; + textureDataFormat = alpha ? GL.GL_RGBA : GL.GL_RGB; + textureDataType = GL.GL_UNSIGNED_BYTE; + } else { + textureInternalFormat = alpha ? GL.GL_RGBA8 : GL.GL_RGB8; + textureDataFormat = alpha ? GL.GL_BGRA : GL.GL_RGB; + textureDataType = alpha ? GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV : GL.GL_UNSIGNED_BYTE; + } + return attachTexture2D(gl, attachmentPoint, textureInternalFormat, textureDataFormat, textureDataType, magFilter, minFilter, wrapS, wrapT); + } + + /** + * Attaches a Texture2D Color Buffer to this FBO's instance at the given attachment point. + * + *

Leaves the FBO bound.

+ * + * @param gl the current GL context + * @param attachmentPoint the color attachment point ranging from [0..{@link #getMaxColorAttachments()}-1] + * @param internalFormat internalFormat parameter to {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, long)} + * @param dataFormat format parameter to {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, long)} + * @param dataType type parameter to {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, long)} + * @param magFilter if > 0 value for {@link GL#GL_TEXTURE_MAG_FILTER} + * @param minFilter if > 0 value for {@link GL#GL_TEXTURE_MIN_FILTER} + * @param wrapS if > 0 value for {@link GL#GL_TEXTURE_WRAP_S} + * @param wrapT if > 0 value for {@link GL#GL_TEXTURE_WRAP_T} + * @return TextureAttachment instance describing the new attached texture colorbuffer if bound and configured successfully, otherwise GLException is thrown + * @throws GLException in case the texture colorbuffer couldn't be allocated or MSAA has been chosen + */ + public final TextureAttachment attachTexture2D(GL gl, int attachmentPoint, + int internalFormat, int dataFormat, int dataType, + int magFilter, int minFilter, int wrapS, int wrapT) throws GLException { + return attachTexture2D(gl, attachmentPoint, + new TextureAttachment(Type.COLOR_TEXTURE, internalFormat, width, height, dataFormat, dataType, + magFilter, minFilter, wrapS, wrapT, 0 /* name */)); + } + + /** + * Attaches a Texture2D Color Buffer to this FBO's instance at the given attachment point. + * + *

+ * In case the passed TextureAttachment texA is uninitialized, i.e. it's texture name is zero, + * a new texture name is generated and setup w/ the texture parameter.
+ * Otherwise, i.e. texture name is not zero, the passed TextureAttachment texA is + * considered complete and assumed matching this FBO requirement. A GL error may occur is the latter is untrue. + *

+ * + *

Leaves the FBO bound.

+ * + * @param gl the current GL context + * @param attachmentPoint the color attachment point ranging from [0..{@link #getMaxColorAttachments()}-1] + * @param texA the to be attached {@link TextureAttachment}. Maybe complete or uninitialized, see above. + * @return the passed TextureAttachment texA instance describing the new attached texture colorbuffer if bound and configured successfully, otherwise GLException is thrown + * @throws GLException in case the texture colorbuffer couldn't be allocated or MSAA has been chosen + */ + public final TextureAttachment attachTexture2D(GL gl, int attachmentPoint, TextureAttachment texA) throws GLException { + validateAddColorAttachment(attachmentPoint, texA); + + if(samples>0) { + removeColorAttachment(attachmentPoint, texA); + throw new GLException("Texture2D not supported w/ MSAA. If you have enabled MSAA with exisiting texture attachments, you may want to detach them via detachAllTexturebuffer(gl)."); + } + + texA.initialize(gl); + addColorAttachment(attachmentPoint, texA); + + bind(gl); + + // Set up the color buffer for use as a renderable texture: + gl.glFramebufferTexture2D(GL.GL_FRAMEBUFFER, + GL.GL_COLOR_ATTACHMENT0 + attachmentPoint, + GL.GL_TEXTURE_2D, texA.getName(), 0); + updateStatus(gl); + + if(!isStatusValid()) { + detachColorbuffer(gl, attachmentPoint); + throw new GLException("attachTexture2D "+texA+" at "+attachmentPoint+" failed "+getStatusString()+", "+this); + } + if(DEBUG) { + System.err.println("FBObject.attachTexture2D: "+this); + } + return texA; + } + + /** + * Attaches a Color Buffer to this FBO's instance at the given attachment point, + * selecting the format automatically. + * + *

Leaves the FBO bound.

+ * + * @param gl the current GL context + * @param attachmentPoint the color attachment point ranging from [0..{@link #getMaxColorAttachments()}-1] + * @param alpha set to true if you request alpha channel, otherwise false; + * @return ColorAttachment instance describing the new attached colorbuffer if bound and configured successfully, otherwise GLException is thrown + * @throws GLException in case the colorbuffer couldn't be allocated + */ + public final ColorAttachment attachColorbuffer(GL gl, int attachmentPoint, boolean alpha) throws GLException { + final int internalFormat; + if( rgba8Avail ) { + internalFormat = alpha ? GL.GL_RGBA8 : GL.GL_RGB8 ; + } else { + internalFormat = alpha ? GL.GL_RGBA4 : GL.GL_RGB565; + } + return attachColorbuffer(gl, attachmentPoint, internalFormat); + } + + /** + * Attaches a Color Buffer to this FBO's instance at the given attachment point. + * + *

Leaves the FBO bound.

+ * + * @param gl the current GL context + * @param attachmentPoint the color attachment point ranging from [0..{@link #getMaxColorAttachments()}-1] + * @param internalFormat usually {@link GL#GL_RGBA4}, {@link GL#GL_RGB5_A1}, {@link GL#GL_RGB565}, {@link GL#GL_RGB8} or {@link GL#GL_RGBA8} + * @return ColorAttachment instance describing the new attached colorbuffer if bound and configured successfully, otherwise GLException is thrown + * @throws GLException in case the colorbuffer couldn't be allocated + * @throws IllegalArgumentException if internalFormat doesn't reflect a colorbuffer + */ + public final ColorAttachment attachColorbuffer(GL gl, int attachmentPoint, int internalFormat) throws GLException, IllegalArgumentException { + final Attachment.Type atype = Attachment.Type.determine(internalFormat); + if( Attachment.Type.COLOR != atype ) { + throw new IllegalArgumentException("colorformat invalid: 0x"+Integer.toHexString(internalFormat)+", "+this); + } + + return attachColorbuffer(gl, attachmentPoint, new ColorAttachment(internalFormat, samples, width, height, 0)); + } + + /** + * Attaches a Color Buffer to this FBO's instance at the given attachment point. + * + *

Leaves the FBO bound.

+ * + * @param gl + * @param attachmentPoint the color attachment point ranging from [0..{@link #getMaxColorAttachments()}-1] + * @param colA the template for the new {@link ColorAttachment} + * @return ColorAttachment instance describing the new attached colorbuffer if bound and configured successfully, otherwise GLException is thrown + * @throws GLException in case the colorbuffer couldn't be allocated + */ + public final ColorAttachment attachColorbuffer(GL gl, int attachmentPoint, ColorAttachment colA) throws GLException { + validateAddColorAttachment(attachmentPoint, colA); + + colA.initialize(gl); + addColorAttachment(attachmentPoint, colA); + + bind(gl); + + // Attach the color buffer + gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, + GL.GL_COLOR_ATTACHMENT0 + attachmentPoint, + GL.GL_RENDERBUFFER, colA.getName()); + + updateStatus(gl); + if(!isStatusValid()) { + detachColorbuffer(gl, attachmentPoint); + throw new GLException("attachColorbuffer "+colA+" at "+attachmentPoint+" failed "+getStatusString()+", "+this); + } + if(DEBUG) { + System.err.println("FBObject.attachColorbuffer: "+this); + } + return colA; + } + + + /** + * Attaches one depth, stencil or packed-depth-stencil buffer to this FBO's instance, + * selecting the internalFormat automatically. + *

+ * Stencil and depth buffer can be attached only once. + *

+ *

+ * In case the desired type or bit-number is not supported, the next available one is chosen. + *

+ *

+ * Use {@link #getDepthAttachment()} and/or {@link #getStencilAttachment()} to retrieve details + * about the attached buffer. The details cannot be returned, since it's possible 2 buffers + * are being created, depth and stencil. + *

+ * + *

Leaves the FBO bound.

+ * + * @param gl + * @param atype either {@link Type#DEPTH}, {@link Type#STENCIL} or {@link Type#DEPTH_STENCIL} + * @param reqBits desired bits for depth or -1 for default (24 bits) + * @throws GLException in case the renderbuffer couldn't be allocated or one is already attached. + * @throws IllegalArgumentException + * @see #getDepthAttachment() + * @see #getStencilAttachment() + */ + public final void attachRenderbuffer(GL gl, Attachment.Type atype, int reqBits) throws GLException, IllegalArgumentException { + if( 0 > reqBits ) { + reqBits = 24; + } + final int internalFormat; + int internalStencilFormat = -1; + + switch ( atype ) { + case DEPTH: + if( 32 <= reqBits && depth32Avail ) { + internalFormat = GL.GL_DEPTH_COMPONENT32; + } else if( 24 <= reqBits && depth24Avail ) { + internalFormat = GL.GL_DEPTH_COMPONENT24; + } else { + internalFormat = GL.GL_DEPTH_COMPONENT16; + } + break; + + case STENCIL: + if( 16 <= reqBits && stencil16Avail ) { + internalFormat = GL2GL3.GL_STENCIL_INDEX16; + } else if( 8 <= reqBits && stencil08Avail ) { + internalFormat = GL.GL_STENCIL_INDEX8; + } else if( 4 <= reqBits && stencil04Avail ) { + internalFormat = GL.GL_STENCIL_INDEX4; + } else if( 1 <= reqBits && stencil01Avail ) { + internalFormat = GL.GL_STENCIL_INDEX1; + } else { + throw new GLException("stencil buffer n/a"); + } + break; + + case DEPTH_STENCIL: + if( packedDepthStencilAvail ) { + internalFormat = GL.GL_DEPTH24_STENCIL8; + } else { + if( 24 <= reqBits && depth24Avail ) { + internalFormat = GL.GL_DEPTH_COMPONENT24; + } else { + internalFormat = GL.GL_DEPTH_COMPONENT16; + } + if( stencil08Avail ) { + internalStencilFormat = GL.GL_STENCIL_INDEX8; + } else if( stencil04Avail ) { + internalStencilFormat = GL.GL_STENCIL_INDEX4; + } else if( stencil01Avail ) { + internalStencilFormat = GL.GL_STENCIL_INDEX1; + } else { + throw new GLException("stencil buffer n/a"); + } + } + break; + default: + throw new IllegalArgumentException("only depth/stencil types allowed, was "+atype+", "+this); + } + + attachRenderbufferImpl(gl, atype, internalFormat); + + if(0<=internalStencilFormat) { + attachRenderbufferImpl(gl, Attachment.Type.STENCIL, internalStencilFormat); + } + } + + /** + * Attaches one depth, stencil or packed-depth-stencil buffer to this FBO's instance, + * depending on the internalFormat. + *

+ * Stencil and depth buffer can be attached only once. + *

+ *

+ * Use {@link #getDepthAttachment()} and/or {@link #getStencilAttachment()} to retrieve details + * about the attached buffer. The details cannot be returned, since it's possible 2 buffers + * are being created, depth and stencil. + *

+ * + *

Leaves the FBO bound.

+ * + * @param gl the current GL context + * @param internalFormat {@link GL#GL_DEPTH_COMPONENT16}, {@link GL#GL_DEPTH_COMPONENT24}, {@link GL#GL_DEPTH_COMPONENT32}, + * {@link GL#GL_STENCIL_INDEX1}, {@link GL#GL_STENCIL_INDEX4}, {@link GL#GL_STENCIL_INDEX8} + * or {@link GL#GL_DEPTH24_STENCIL8} + * @throws GLException in case the renderbuffer couldn't be allocated or one is already attached. + * @throws IllegalArgumentException + * @see #getDepthAttachment() + * @see #getStencilAttachment() + */ + public final void attachRenderbuffer(GL gl, int internalFormat) throws GLException, IllegalArgumentException { + final Attachment.Type atype = Attachment.Type.determine(internalFormat); + if( Attachment.Type.DEPTH != atype && Attachment.Type.STENCIL != atype && Attachment.Type.DEPTH_STENCIL != atype ) { + throw new IllegalArgumentException("renderformat invalid: 0x"+Integer.toHexString(internalFormat)+", "+this); + } + attachRenderbufferImpl(gl, atype, internalFormat); + } + + protected final void attachRenderbufferImpl(GL gl, Attachment.Type atype, int internalFormat) throws GLException { + if( null != depth && ( Attachment.Type.DEPTH == atype || Attachment.Type.DEPTH_STENCIL == atype ) ) { + throw new GLException("FBO depth buffer already attached (rb "+depth+"), type is "+atype+", 0x"+Integer.toHexString(internalFormat)+", "+this); + } + if( null != stencil && ( Attachment.Type.STENCIL== atype || Attachment.Type.DEPTH_STENCIL == atype ) ) { + throw new GLException("FBO stencil buffer already attached (rb "+stencil+"), type is "+atype+", 0x"+Integer.toHexString(internalFormat)+", "+this); + } + attachRenderbufferImpl2(gl, atype, internalFormat); + } + + private final void attachRenderbufferImpl2(GL gl, Attachment.Type atype, int internalFormat) throws GLException { + if( Attachment.Type.DEPTH == atype ) { + if(null == depth) { + depth = new RenderAttachment(Type.DEPTH, internalFormat, samples, width, height, 0); + } else { + depth.setSize(width, height); + depth.setSamples(samples); + } + depth.initialize(gl); + } else if( Attachment.Type.STENCIL == atype ) { + if(null == stencil) { + stencil = new RenderAttachment(Type.STENCIL, internalFormat, samples, width, height, 0); + } else { + stencil.setSize(width, height); + stencil.setSamples(samples); + } + stencil.initialize(gl); + } else if( Attachment.Type.DEPTH_STENCIL == atype ) { + if(null == depth) { + depth = new RenderAttachment(Type.DEPTH, internalFormat, samples, width, height, 0); + } else { + depth.setSize(width, height); + depth.setSamples(samples); + } + depth.initialize(gl); + if(null == stencil) { + stencil = new RenderAttachment(Type.STENCIL, internalFormat, samples, width, height, depth.getName()); + } else { + stencil.setName(depth.getName()); + stencil.setSize(width, height); + stencil.setSamples(samples); + } + stencil.initialize(gl); + } + + bind(gl); + + // Attach the buffer + if( Attachment.Type.DEPTH == atype ) { + gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_DEPTH_ATTACHMENT, GL.GL_RENDERBUFFER, depth.getName()); + } else if( Attachment.Type.STENCIL == atype ) { + gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_STENCIL_ATTACHMENT, GL.GL_RENDERBUFFER, stencil.getName()); + } else if( Attachment.Type.DEPTH_STENCIL == atype ) { + gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_DEPTH_ATTACHMENT, GL.GL_RENDERBUFFER, depth.getName()); + gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_STENCIL_ATTACHMENT, GL.GL_RENDERBUFFER, stencil.getName()); + } + + updateStatus(gl); + if( !isStatusValid() ) { + detachRenderbuffer(gl, atype); + throw new GLException("renderbuffer attachment failed: "+this.getStatusString()); + } + + if(DEBUG) { + System.err.println("FBObject.attachRenderbuffer: "+this); + } + } + + /** + *

Leaves the FBO bound!

+ * @param gl + * @param ca + * @throws IllegalArgumentException + */ + public final void detachColorbuffer(GL gl, int attachmentPoint) throws IllegalArgumentException { + if(null == detachColorbufferImpl(gl, attachmentPoint, false)) { + throw new IllegalArgumentException("ColorAttachment at "+attachmentPoint+", not attached, "+this); + } + if(DEBUG) { + System.err.println("FBObject.detachAll: "+this); + } + } + + private final Colorbuffer detachColorbufferImpl(GL gl, int attachmentPoint, boolean recreate) { + final Colorbuffer colbuf = colorAttachmentPoints[attachmentPoint]; // shortcut, don't validate here + + if(null == colbuf) { + return null; + } + + bind(gl); + + if(colbuf instanceof TextureAttachment) { + final TextureAttachment texA = (TextureAttachment) colbuf; + if( 0 != texA.getName() ) { + gl.glFramebufferTexture2D(GL.GL_FRAMEBUFFER, + GL.GL_COLOR_ATTACHMENT0 + attachmentPoint, + GL.GL_TEXTURE_2D, 0, 0); + gl.glBindTexture(GL.GL_TEXTURE_2D, 0); + } + texA.free(gl); + removeColorAttachment(attachmentPoint, texA); + if(recreate) { + texA.setSize(width, height); + attachTexture2D(gl, attachmentPoint, texA); + } + } else if(colbuf instanceof ColorAttachment) { + final ColorAttachment colA = (ColorAttachment) colbuf; + if( 0 != colA.getName() ) { + gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, + GL.GL_COLOR_ATTACHMENT0+attachmentPoint, + GL.GL_RENDERBUFFER, 0); + } + colA.free(gl); + removeColorAttachment(attachmentPoint, colbuf); + if(recreate) { + colA.setSize(width, height); + colA.setSamples(samples); + attachColorbuffer(gl, attachmentPoint, colA); + } + } + return colbuf; + } + + /** + * + * @param gl + * @param reqAType {@link Type#DEPTH}, {@link Type#DEPTH} or {@link Type#DEPTH_STENCIL} + */ + public final void detachRenderbuffer(GL gl, Attachment.Type atype) throws IllegalArgumentException { + detachRenderbufferImpl(gl, atype, false); + } + + public final boolean isDepthStencilPackedFormat() { + final boolean res = null != depth && null != stencil && + depth.format == stencil.format ; + if(res && depth.getName() != stencil.getName() ) { + throw new InternalError("depth/stencil packed format not sharing: depth "+depth+", stencil "+stencil); + } + return res; + } + + private final void detachRenderbufferImpl(GL gl, Attachment.Type atype, boolean recreate) throws IllegalArgumentException { + switch ( atype ) { + case DEPTH: + case STENCIL: + case DEPTH_STENCIL: + break; + default: + throw new IllegalArgumentException("only depth/stencil types allowed, was "+atype+", "+this); + } + if( null == depth && null == stencil ) { + return ; // nop + } + // reduction of possible combinations, create unique atype command(s) + final ArrayList actions = new ArrayList(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. + *

Leaves the FBO bound!

+ *

+ * An attached sampling sink texture will be detached as well, see {@link #getSamplingSink()}. + *

+ * @param gl the current GL context + */ + public final void detachAll(GL gl) { + if(null != samplesSink) { + samplesSink.detachAll(gl); + } + detachAllImpl(gl, true/* detachNonColorbuffer */, false /* recreate */); + } + + /** + * Detaches all {@link ColorAttachment}s and {@link TextureAttachment}s. + *

Leaves the FBO bound!

+ *

+ * An attached sampling sink texture will be detached as well, see {@link #getSamplingSink()}. + *

+ * @param gl the current GL context + */ + public final void detachAllColorbuffer(GL gl) { + if(null != samplesSink) { + samplesSink.detachAllColorbuffer(gl); + } + detachAllImpl(gl, false/* detachNonColorbuffer */, false /* recreate */); + } + + /** + * Detaches all {@link TextureAttachment}s + *

Leaves the FBO bound!

+ *

+ * An attached sampling sink texture will be detached as well, see {@link #getSamplingSink()}. + *

+ * @param gl the current GL context + */ + public final void detachAllTexturebuffer(GL gl) { + if(null != samplesSink) { + samplesSink.detachAllTexturebuffer(gl); + } + for(int i=0; i0 ) { + 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()}. + * + *

If multisampling is used, it sets the read framebuffer to the sampling sink {@link #getWriteFramebuffer()}, + * if full FBO is supported.

+ * + *

+ * In case you have attached more than one color buffer, + * you may want to setup {@link GL2GL3#glDrawBuffers(int, int[], int)}. + *

+ * @param gl the current GL context + * @throws GLException + */ + public final void bind(GL gl) throws GLException { + if(!bound || fbName != gl.getBoundFramebuffer(GL.GL_FRAMEBUFFER)) { + checkInitialized(); + if(samples > 0 && fullFBOSupport) { + // draw to multisampling - read from samplesSink + gl.glBindFramebuffer(GL2GL3.GL_DRAW_FRAMEBUFFER, getWriteFramebuffer()); + gl.glBindFramebuffer(GL2GL3.GL_READ_FRAMEBUFFER, getReadFramebuffer()); + } else { + // one for all + gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, getWriteFramebuffer()); + } + + checkNoError(null, gl.glGetError(), "FBObject post-bind"); // throws GLException if error + bound = true; + samplesSinkDirty = true; + } + } + + /** + * Unbind this FBO, i.e. bind read and write framebuffer to default, see {@link GLBase#getDefaultDrawFramebuffer()}. + * + *

If full FBO is supported, sets the read and write framebuffer individually to default, hence not disturbing + * an optional operating MSAA FBO, see {@link GLBase#getDefaultReadFramebuffer()} and {@link GLBase#getDefaultDrawFramebuffer()}

+ * + * @param gl the current GL context + * @throws GLException + */ + public final void unbind(GL gl) throws GLException { + if(bound) { + if(fullFBOSupport) { + // default read/draw buffers, may utilize GLContext/GLDrawable override of + // GLContext.getDefaultDrawFramebuffer() and GLContext.getDefaultReadFramebuffer() + gl.glBindFramebuffer(GL2GL3.GL_DRAW_FRAMEBUFFER, 0); + gl.glBindFramebuffer(GL2GL3.GL_READ_FRAMEBUFFER, 0); + } else { + gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0); // default draw buffer + } + checkNoError(null, gl.glGetError(), "FBObject post-unbind"); // throws GLException if error + bound = false; + } + } + + /** + * Returns true if framebuffer object is bound via {@link #bind(GL)}, otherwise false. + *

+ * Method verifies the bound state via {@link GL#getBoundFramebuffer(int)}. + *

+ * @param gl the current GL context + */ + public final boolean isBound(GL gl) { + bound = bound && fbName != gl.getBoundFramebuffer(GL.GL_FRAMEBUFFER) ; + return bound; + } + + /** Returns true if framebuffer object is bound via {@link #bind(GL)}, otherwise false. */ + public final boolean isBound() { return bound; } + + /** + * Samples the multisampling colorbuffer (msaa-buffer) to it's sink {@link #getSamplingSink()}. + * + *

The operation is skipped, if no multisampling is used or + * the msaa-buffer has not been flagged dirty by a previous call of {@link #bind(GL)}, + * see {@link #isSamplingBufferDirty()}

+ * + *

If full FBO is supported, sets the read and write framebuffer individually to default after sampling, hence not disturbing + * an optional operating MSAA FBO, see {@link GLBase#getDefaultReadFramebuffer()} and {@link GLBase#getDefaultDrawFramebuffer()}

+ * + *

In case you intend to employ {@link GL#glReadPixels(int, int, int, int, int, int, java.nio.Buffer) glReadPixels(..)} + * you may want to call {@link GL#glBindFramebuffer(int, int) glBindFramebuffer}({@link GL2GL3#GL_READ_FRAMEBUFFER}, {@link #getReadFramebuffer()}); + *

+ * + *

Leaves the FBO unbound.

+ * + * @param gl the current GL context + * @param ta {@link TextureAttachment} to use, prev. attached w/ {@link #attachTexture2D(GL, int, boolean, int, int, int, int) attachTexture2D(..)} + * @throws IllegalArgumentException + */ + public final void syncSamplingBuffer(GL gl) { + unbind(gl); + if(samples>0 && samplesSinkDirty) { + samplesSinkDirty = false; + resetMSAATexture2DSink(gl); + gl.glBindFramebuffer(GL2GL3.GL_READ_FRAMEBUFFER, fbName); + gl.glBindFramebuffer(GL2GL3.GL_DRAW_FRAMEBUFFER, samplesSink.getWriteFramebuffer()); + ((GL2GL3)gl).glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, // since MSAA is supported, ugly cast is OK + GL.GL_COLOR_BUFFER_BIT, GL.GL_NEAREST); + if(fullFBOSupport) { + // default read/draw buffers, may utilize GLContext/GLDrawable override of + // GLContext.getDefaultDrawFramebuffer() and GLContext.getDefaultReadFramebuffer() + gl.glBindFramebuffer(GL2GL3.GL_DRAW_FRAMEBUFFER, 0); + gl.glBindFramebuffer(GL2GL3.GL_READ_FRAMEBUFFER, 0); + } else { + gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0); // default draw buffer + } + } + } + + /** + * Bind the given texture colorbuffer. + * + *

If multisampling is being used, {@link #syncSamplingBuffer(GL)} is being called.

+ * + *

Leaves the FBO unbound!

+ * + * @param gl the current GL context + * @param ta {@link TextureAttachment} to use, prev. attached w/ {@link #attachTexture2D(GL, int, boolean, int, int, int, int) attachTexture2D(..)} + * @throws IllegalArgumentException + */ + public final void use(GL gl, TextureAttachment ta) throws IllegalArgumentException { + if(null == ta) { throw new IllegalArgumentException("null TextureAttachment"); } + if(samples > 0 && samplesSinkTexture == ta) { + syncSamplingBuffer(gl); + } else { + unbind(gl); + } + gl.glBindTexture(GL.GL_TEXTURE_2D, ta.getName()); // use it .. + } + + /** + * Unbind texture, ie bind 'non' texture 0 + * + *

Leaves the FBO unbound.

+ */ + public final void unuse(GL gl) { + unbind(gl); + gl.glBindTexture(GL.GL_TEXTURE_2D, 0); // don't use it + } + + /** + * Returns true if basic or full FBO is supported, otherwise false. + * @param full true for full FBO supported query, otherwise false for basic FBO support query. + * @see #supportsFullFBO(GL) + * @see #supportsBasicFBO(GL) + * @throws GLException if {@link #init(GL)} hasn't been called. + */ + public final boolean supportsFBO(boolean full) throws GLException { checkInitialized(); return full ? fullFBOSupport : basicFBOSupport; } + + /** + * Returns true if renderbuffer accepts internal format {@link GL#GL_RGB8} and {@link GL#GL_RGBA8}, otherwise false. + * @throws GLException if {@link #init(GL)} hasn't been called. + */ + public final boolean supportsRGBA8() throws GLException { checkInitialized(); return rgba8Avail; } + + /** + * Returns true if {@link GL#GL_DEPTH_COMPONENT16}, {@link GL#GL_DEPTH_COMPONENT24} or {@link GL#GL_DEPTH_COMPONENT32} is supported, otherwise false. + * @param bits 16, 24 or 32 bits + * @throws GLException if {@link #init(GL)} hasn't been called. + */ + public final boolean supportsDepth(int bits) throws GLException { + checkInitialized(); + switch(bits) { + case 16: return basicFBOSupport; + case 24: return depth24Avail; + case 32: return depth32Avail; + default: return false; + } + } + + /** + * Returns true if {@link GL#GL_STENCIL_INDEX1}, {@link GL#GL_STENCIL_INDEX4}, {@link GL#GL_STENCIL_INDEX8} or {@link GL2GL3#GL_STENCIL_INDEX16} is supported, otherwise false. + * @param bits 1, 4, 8 or 16 bits + * @throws GLException if {@link #init(GL)} hasn't been called. + */ + public final boolean supportsStencil(int bits) throws GLException { + checkInitialized(); + switch(bits) { + case 1: return stencil01Avail; + case 4: return stencil04Avail; + case 8: return stencil08Avail; + case 16: return stencil16Avail; + default: return false; + } + } + + /** + * Returns true if {@link GL#GL_DEPTH24_STENCIL8} is supported, otherwise false. + * @throws GLException if {@link #init(GL)} hasn't been called. + */ + public final boolean supportsPackedDepthStencil() throws GLException { checkInitialized(); return packedDepthStencilAvail; } + + /** + * Returns the maximum number of colorbuffer attachments. + * @throws GLException if {@link #init(GL)} hasn't been called. + */ + public final int getMaxColorAttachments() throws GLException { checkInitialized(); return maxColorAttachments; } + + /** + * Returns the maximum number of samples for multisampling. Maybe zero if multisampling is not supported. + * @throws GLException if {@link #init(GL)} hasn't been called. + */ + public final int getMaxSamples() throws GLException { checkInitialized(); return maxSamples; } + + /** + * Returns true if this instance has been initialized with {@link #reset(GL, int, int)} + * or {@link #reset(GL, int, int, int)}, otherwise false + */ + public final boolean isInitialized() { return initialized; } + /** Returns the width */ + public final int getWidth() { return width; } + /** Returns the height */ + public final int getHeight() { return height; } + /** Returns the number of samples for multisampling (MSAA). zero if no multisampling is used. */ + public final int getNumSamples() { return samples; } + /** Returns the framebuffer name to render to. */ + public final int getWriteFramebuffer() { return fbName; } + /** Returns the framebuffer name to read from. Depending on multisampling, this may be a different framebuffer. */ + public final int getReadFramebuffer() { return ( samples > 0 ) ? samplesSink.getReadFramebuffer() : fbName; } + /** Return the number of color/texture attachments */ + public final int getColorAttachmentCount() { return colorAttachmentCount; } + /** Return the stencil {@link RenderAttachment} attachment, if exist. Maybe share the same {@link Attachment#getName()} as {@link #getDepthAttachment()}, if packed depth-stencil is being used. */ + public final RenderAttachment getStencilAttachment() { return stencil; } + /** Return the depth {@link RenderAttachment} attachment. Maybe share the same {@link Attachment#getName()} as {@link #getStencilAttachment()}, if packed depth-stencil is being used. */ + public final RenderAttachment getDepthAttachment() { return depth; } + + /** Return the complete multisampling {@link FBObject} sink, if using multisampling. */ + public final FBObject getSamplingSinkFBO() { return samplesSink; } + + /** Return the multisampling {@link TextureAttachment} sink, if using multisampling. */ + public final TextureAttachment getSamplingSink() { return samplesSinkTexture; } + /** + * Returns true if the multisampling colorbuffer (msaa-buffer) + * has been flagged dirty by a previous call of {@link #bind(GL)}, + * otherwise false. + */ + public final boolean isSamplingBufferDirty() { return samplesSinkDirty; } + + int objectHashCode() { return super.hashCode(); } + + public final String toString() { + final String caps = null != colorAttachmentPoints ? Arrays.asList(colorAttachmentPoints).toString() : null ; + return "FBO[name r/w "+fbName+"/"+getReadFramebuffer()+", init "+initialized+", bound "+bound+", size "+width+"x"+height+", samples "+samples+"/"+maxSamples+ + ", depth "+depth+", stencil "+stencil+", color attachments: "+colorAttachmentCount+"/"+maxColorAttachments+ + ": "+caps+", msaa-sink "+samplesSinkTexture+", isSamplesSink "+(null == samplesSink)+ + ", obj 0x"+Integer.toHexString(objectHashCode())+"]"; + } + + private final void updateStatus(GL gl) { + if( 0 == fbName ) { + vStatus = -1; + } else { + vStatus = gl.glCheckFramebufferStatus(GL.GL_FRAMEBUFFER); + } + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/GLExtensions.java b/src/jogl/classes/com/jogamp/opengl/GLExtensions.java new file mode 100644 index 000000000..f7e25fa01 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/GLExtensions.java @@ -0,0 +1,81 @@ +/** + * Copyright 2012 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.opengl; + +/** + * Class holding OpenGL extension strings, commonly used by JOGL's implementation. + */ +public class GLExtensions { + public static final String VERSION_1_2 = "GL_VERSION_1_2"; + public static final String VERSION_1_4 = "GL_VERSION_1_4"; + public static final String VERSION_1_5 = "GL_VERSION_1_5"; + public static final String VERSION_2_0 = "GL_VERSION_2_0"; + + public static final String ARB_debug_output = "GL_ARB_debug_output"; + public static final String AMD_debug_output = "GL_AMD_debug_output"; + + public static final String ARB_framebuffer_object = "GL_ARB_framebuffer_object"; + public static final String OES_framebuffer_object = "GL_OES_framebuffer_object"; + public static final String EXT_framebuffer_object = "GL_EXT_framebuffer_object"; + public static final String EXT_framebuffer_blit = "GL_EXT_framebuffer_blit"; + public static final String EXT_framebuffer_multisample = "GL_EXT_framebuffer_multisample"; + public static final String EXT_packed_depth_stencil = "GL_EXT_packed_depth_stencil"; + public static final String OES_depth24 = "GL_OES_depth24"; + public static final String OES_depth32 = "GL_OES_depth32"; + public static final String OES_packed_depth_stencil = "GL_OES_packed_depth_stencil"; + public static final String NV_fbo_color_attachments = "GL_NV_fbo_color_attachments"; + + public static final String ARB_ES2_compatibility = "GL_ARB_ES2_compatibility"; + + public static final String EXT_abgr = "GL_EXT_abgr"; + public static final String OES_rgb8_rgba8 = "GL_OES_rgb8_rgba8"; + public static final String OES_stencil1 = "GL_OES_stencil1"; + public static final String OES_stencil4 = "GL_OES_stencil4"; + public static final String OES_stencil8 = "GL_OES_stencil8"; + public static final String APPLE_float_pixels = "GL_APPLE_float_pixels"; + + public static final String ARB_texture_non_power_of_two = "GL_ARB_texture_non_power_of_two"; + public static final String ARB_texture_rectangle = "GL_ARB_texture_rectangle"; + public static final String EXT_texture_rectangle = "GL_EXT_texture_rectangle"; + public static final String NV_texture_rectangle = "GL_NV_texture_rectangle"; + public static final String EXT_texture_format_BGRA8888 = "GL_EXT_texture_format_BGRA8888"; + public static final String IMG_texture_format_BGRA8888 = "GL_IMG_texture_format_BGRA8888"; + public static final String EXT_texture_compression_s3tc = "GL_EXT_texture_compression_s3tc"; + public static final String NV_texture_compression_vtc = "GL_NV_texture_compression_vtc"; + public static final String SGIS_generate_mipmap = "GL_SGIS_generate_mipmap"; + public static final String OES_read_format = "GL_OES_read_format"; + + public static final String OES_EGL_image_external = "GL_OES_EGL_image_external"; + + // + // Aliased GLX/WGL/.. extensions + // + + public static final String ARB_pixel_format = "GL_ARB_pixel_format"; + public static final String ARB_pbuffer = "GL_ARB_pbuffer"; +} diff --git a/src/jogl/classes/com/jogamp/opengl/JoglVersion.java b/src/jogl/classes/com/jogamp/opengl/JoglVersion.java index 75785fd86..cdb4b82bb 100644 --- a/src/jogl/classes/com/jogamp/opengl/JoglVersion.java +++ b/src/jogl/classes/com/jogamp/opengl/JoglVersion.java @@ -93,11 +93,13 @@ public class JoglVersion extends JogampVersion { return sb; } - public static StringBuilder getDefaultOpenGLInfo(StringBuilder sb, boolean withCapabilitiesInfo) { + public static StringBuilder getDefaultOpenGLInfo(AbstractGraphicsDevice device, StringBuilder sb, boolean withCapabilitiesInfo) { if(null==sb) { sb = new StringBuilder(); } - final AbstractGraphicsDevice device = GLProfile.getDefaultDevice(); + if(null == device) { + device = GLProfile.getDefaultDevice(); + } sb.append("Default Profiles on device ").append(device).append(Platform.getNewline()); if(null!=device) { GLProfile.glAvailabilityToString(device, sb, "\t", 1); @@ -120,13 +122,21 @@ public class JoglVersion extends JogampVersion { if(null==sb) { sb = new StringBuilder(); } - GLContext ctx = gl.getContext(); - + sb.append(VersionUtil.SEPERATOR).append(Platform.getNewline()); sb.append(device.getClass().getSimpleName()).append("[type ") .append(device.getType()).append(", connection ").append(device.getConnection()).append("]: ").append(Platform.getNewline()); GLProfile.glAvailabilityToString(device, sb, "\t", 1); sb.append(Platform.getNewline()); + + return getGLStrings(gl, sb); + } + + public static StringBuilder getGLStrings(GL gl, StringBuilder sb) { + if(null==sb) { + sb = new StringBuilder(); + } + final GLContext ctx = gl.getContext(); sb.append("Swap Interval ").append(gl.getSwapInterval()); sb.append(Platform.getNewline()); sb.append("GL Profile ").append(gl.getGLProfile()); diff --git a/src/jogl/classes/com/jogamp/opengl/OffscreenAutoDrawable.java b/src/jogl/classes/com/jogamp/opengl/OffscreenAutoDrawable.java new file mode 100644 index 000000000..1ea8595c6 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/OffscreenAutoDrawable.java @@ -0,0 +1,89 @@ +/** + * Copyright 2012 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package com.jogamp.opengl; + +import javax.media.opengl.GLAutoDrawableDelegate; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawable; +import javax.media.opengl.GLException; + +import jogamp.opengl.GLFBODrawableImpl; + +/** + * Platform-independent class exposing FBO offscreen functionality to + * applications. + *

+ * This class distinguishes itself from {@link GLAutoDrawableDelegate} + * with it's {@link #setSize(int, int)} functionality. + *

+ */ +public class OffscreenAutoDrawable extends GLAutoDrawableDelegate { + + public OffscreenAutoDrawable(GLDrawable drawable, GLContext context, Object upstreamWidget) { + super(drawable, context, upstreamWidget); + } + + /** + * Attempts to resize this offscreen auto drawable, if supported + * by the underlying {@link GLDrawable). + * @param newWidth + * @param newHeight + * @return true if resize was executed, otherwise false. + * @throws GLException in case of an error during the resize operation + */ + public boolean setSize(int newWidth, int newHeight) throws GLException { + boolean done = false; + if(drawable instanceof GLFBODrawableImpl) { + context.makeCurrent(); + try { + ((GLFBODrawableImpl)drawable).setSize(context.getGL(), newWidth, newHeight); + done = true; + } finally { + context.release(); + } + } + if(done) { + this.defaultWindowResizedOp(); + return true; + } + return false; + } + + /** + * If the underlying {@link GLDrawable} is an FBO implementation + * and contains an {#link FBObject}, the same is returned. + * Otherwise returns null. + */ + public FBObject getFBObject() { + if(drawable instanceof GLFBODrawableImpl) { + return ((GLFBODrawableImpl)drawable).getFBObject(); + } + return null; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java b/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java index 5ee58b78d..0d9d3ddf5 100644 --- a/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java +++ b/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java @@ -231,6 +231,8 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { /* Get the nativewindow-Graphics Device associated with this control (which is determined by the parent Composite) */ device = SWTAccessor.getDevice(this); + /* Since we have no means of querying the screen index yet, assume 0. Good choice due to Xinerama alike settings anyways. */ + final int screenIdx = 0; /* Native handle for the control, used to associate with GLContext */ nativeWindowHandle = SWTAccessor.getWindowHandle(this); @@ -243,7 +245,7 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { final GLDrawableFactory glFactory = GLDrawableFactory.getFactory(caps.getGLProfile()); /* Create a NativeWindow proxy for the SWT canvas */ - proxySurface = glFactory.createProxySurface(device, nativeWindowHandle, caps, chooser); + proxySurface = glFactory.createProxySurface(device, screenIdx, nativeWindowHandle, caps, chooser, swtCanvasUpStreamHook); /* Associate a GL surface with the proxy */ drawable = glFactory.createGLDrawable(proxySurface); @@ -265,12 +267,58 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { addControlListener(new ControlAdapter() { @Override public void controlResized(final ControlEvent arg0) { - clientArea = GLCanvas.this.getClientArea(); - /* Mark for OpenGL reshape next time the control is painted */ - sendReshape = true; + updateSizeCheck(); } }); } + private final ProxySurface.UpstreamSurfaceHook swtCanvasUpStreamHook = new ProxySurface.UpstreamSurfaceHook() { + @Override + public final void create(ProxySurface s) { /* nop */ } + + @Override + public final void destroy(ProxySurface s) { /* nop */ } + + @Override + public final int getWidth(ProxySurface s) { + return clientArea.width; + } + + @Override + public final int getHeight(ProxySurface s) { + return clientArea.height; + } + + @Override + public String toString() { + return "SETUpstreamSurfaceHook[upstream: "+GLCanvas.this.toString()+"]"; + } + + }; + + protected final void updateSizeCheck() { + clientArea = GLCanvas.this.getClientArea(); + if (clientArea != null && + proxySurface.getWidth() != clientArea.width && + proxySurface.getHeight() != clientArea.height) { + sendReshape = true; // Mark for OpenGL reshape next time the control is painted + } + sendReshape = false; + } + + @Override + public final Object getUpstreamWidget() { + return this; + } + + @Override + public int getWidth() { + return clientArea.width; + } + + @Override + public int getHeight() { + return clientArea.height; + } @Override public void addGLEventListener(final GLEventListener arg0) { @@ -417,25 +465,11 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { return (drawable != null) ? drawable.getHandle() : 0; } - @Override - public int getHeight() { - final Rectangle clientArea = this.clientArea; - if (clientArea == null) return 0; - return clientArea.height; - } - @Override public NativeSurface getNativeSurface() { return (drawable != null) ? drawable.getNativeSurface() : null; } - @Override - public int getWidth() { - final Rectangle clientArea = this.clientArea; - if (clientArea == null) return 0; - return clientArea.width; - } - @Override public boolean isRealized() { return (drawable != null) ? drawable.isRealized() : false; @@ -515,7 +549,7 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { // System.err.println(NativeWindowVersion.getInstance()); System.err.println(JoglVersion.getInstance()); - System.err.println(JoglVersion.getDefaultOpenGLInfo(null, true).toString()); + System.err.println(JoglVersion.getDefaultOpenGLInfo(null, null, true).toString()); final GLCapabilitiesImmutable caps = new GLCapabilities( GLProfile.getDefault(GLProfile.getDefaultDevice()) ); final Display display = new Display(); diff --git a/src/jogl/classes/com/jogamp/opengl/util/FBObject.java b/src/jogl/classes/com/jogamp/opengl/util/FBObject.java deleted file mode 100644 index 3e049a334..000000000 --- a/src/jogl/classes/com/jogamp/opengl/util/FBObject.java +++ /dev/null @@ -1,483 +0,0 @@ -/* - * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. - * Copyright (c) 2011 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * - Redistribution of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistribution in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * Neither the name of Sun Microsystems, Inc. or the names of - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * This software is provided "AS IS," without a warranty of any kind. ALL - * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, - * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN - * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR - * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR - * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR - * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR - * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE - * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, - * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF - * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - * - */ - -package com.jogamp.opengl.util; - -import javax.media.opengl.*; - -public class FBObject { - static final int MAX_FBO_TEXTURES = 32; // just for our impl .. not the real 'max' FBO color attachments - private int[] fbo_tex_names; - private int[] fbo_tex_units; - private int fbo_tex_num; - private int colorattachment_num; - - private boolean initialized; - private int width, height; - private int fb, depth_rb, stencil_rb, vStatus; - private boolean bound; - - public FBObject(int width, int height) { - this.fbo_tex_names = new int[MAX_FBO_TEXTURES]; - this.fbo_tex_units = new int[MAX_FBO_TEXTURES]; - this.fbo_tex_num = 0; - this.colorattachment_num = 0; - this.initialized = false; - this.width = width; - this.height = height; - this.fb = 0; - this.depth_rb = 0; - this.stencil_rb = 0; - this.bound = false; - } - - /** - * @return true if the FB status is valid, otherwise false - * @see #getStatus() - */ - public boolean isStatusValid() { - switch(vStatus) { - case GL.GL_FRAMEBUFFER_COMPLETE: - return true; - case GL.GL_FRAMEBUFFER_UNSUPPORTED: - case GL.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: - case GL.GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: - case GL.GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS: - case GL.GL_FRAMEBUFFER_INCOMPLETE_FORMATS: - //case GL2.GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER: - //case GL2.GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER: - //case GL2.GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT: - case 0: - default: - System.out.println("Framebuffer " + fb + " is incomplete: status = 0x" + Integer.toHexString(vStatus) + - " : " + getStatusString(vStatus)); - return false; - } - } - - /** - * @return The FB status. {@link GL.GL_FRAMEBUFFER_COMPLETE} if ok, otherwise return GL FBO error state or -1 - * @see #validateStatus() - */ - public int getStatus() { - return vStatus; - } - - public String getStatusString() { - return getStatusString(vStatus); - } - - public static final String getStatusString(int fbStatus) { - switch(fbStatus) { - case -1: - return "NOT A FBO"; - case GL.GL_FRAMEBUFFER_COMPLETE: - return "OK"; - case GL.GL_FRAMEBUFFER_UNSUPPORTED: - return("GL FBO: Unsupported framebuffer format"); - case GL.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: - return("GL FBO: incomplete, incomplete attachment\n"); - case GL.GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: - return("GL FBO: incomplete, missing attachment"); - case GL.GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS: - return("GL FBO: incomplete, attached images must have same dimensions"); - case GL.GL_FRAMEBUFFER_INCOMPLETE_FORMATS: - return("GL FBO: incomplete, attached images must have same format"); - case GL2.GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER: - return("GL FBO: incomplete, missing draw buffer"); - case GL2.GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER: - return("GL FBO: incomplete, missing read buffer"); - case GL2.GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: - return("GL FBO: incomplete, missing multisample buffer"); - case 0: - return("GL FBO: incomplete, implementation fault"); - default: - return("GL FBO: incomplete, implementation ERROR"); - } - } - - private boolean checkNoError(GL gl, int err, String exceptionMessage) { - if(GL.GL_NO_ERROR != err) { - if(null != gl) { - destroy(gl); - } - if(null != exceptionMessage) { - throw new GLException(exceptionMessage+" GL Error 0x"+Integer.toHexString(err)); - } - return false; - } - return true; - } - - private final void checkInitialized() { - if(!initialized) { - throw new GLException("FBO not initialized, call init(GL) first."); - } - } - - private final void checkBound(GL gl, boolean shallBeBound) { - checkInitialized(); - if(bound != shallBeBound) { - final String s0 = shallBeBound ? "not" : "already" ; - throw new GLException("FBO "+s0+" bound "+toString()); - } - checkNoError(null, gl.glGetError(), "FBObject pre"); // throws GLException if error - } - - /** - * Initializes this FBO's instance with it's texture. - * - *

Leaves the FBO bound!

- * - * @param gl the current GL context - * @throws GLException in case of an error - */ - public void init(GL gl) throws GLException { - if(initialized) { - throw new GLException("FBO already initialized"); - } - checkNoError(null, gl.glGetError(), "FBObject Init.pre"); // throws GLException if error - - // generate fbo .. - int name[] = new int[1]; - - gl.glGenFramebuffers(1, name, 0); - fb = name[0]; - if(fb==0) { - throw new GLException("null generated framebuffer"); - } - - // bind fbo .. - gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, fb); - checkNoError(gl, gl.glGetError(), "FBObject Init.bindFB"); // throws GLException if error - if(!gl.glIsFramebuffer(fb)) { - checkNoError(gl, GL.GL_INVALID_VALUE, "FBObject Init.isFB"); // throws GLException - } - bound = true; - initialized = true; - - updateStatus(gl); - } - - /** - * Attaches a[nother] Texture2D Color Buffer to this FBO's instance, - * selecting the texture data type and format automatically. - *

This may be done as many times as many color attachments are supported, - * see {@link GL2GL3#GL_MAX_COLOR_ATTACHMENTS}.

- * - *

Assumes a bound FBO

- *

Leaves the FBO bound!

- * - * @param gl the current GL context - * @param texUnit the desired texture unit ranging from [0..{@link GL2#GL_MAX_TEXTURE_UNITS}-1], or -1 if no unit shall be activate at {@link #use(GL, int)} - * @param magFilter if > 0 value for {@link GL#GL_TEXTURE_MAG_FILTER} - * @param minFilter if > 0 value for {@link GL#GL_TEXTURE_MIN_FILTER} - * @param wrapS if > 0 value for {@link GL#GL_TEXTURE_WRAP_S} - * @param wrapT if > 0 value for {@link GL#GL_TEXTURE_WRAP_T} - * @return idx of the new attached texture, otherwise -1 - * @throws GLException in case of an error - */ - public int attachTexture2D(GL gl, int texUnit, int magFilter, int minFilter, int wrapS, int wrapT) throws GLException { - final int textureInternalFormat, textureDataFormat, textureDataType; - if(gl.isGLES()) { - textureInternalFormat=GL.GL_RGBA; - textureDataFormat=GL.GL_RGBA; - textureDataType=GL.GL_UNSIGNED_BYTE; - } else { - textureInternalFormat=GL.GL_RGBA8; - textureDataFormat=GL.GL_BGRA; - textureDataType=GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV; - } - return attachTexture2D(gl, texUnit, textureInternalFormat, textureDataFormat, textureDataType, magFilter, minFilter, wrapS, wrapT); - } - - /** - * Attaches a[nother] Texture2D Color Buffer to this FBO's instance, - * selecting the texture data type and format automatically. - *

This may be done as many times as many color attachments are supported, - * see {@link GL2GL3#GL_MAX_COLOR_ATTACHMENTS}.

- * - *

Assumes a bound FBO

- *

Leaves the FBO bound!

- * - * @param gl the current GL context - * @param texUnit the desired texture unit ranging from [0..{@link GL2#GL_MAX_TEXTURE_UNITS}-1], or -1 if no unit shall be activate at {@link #use(GL, int)} - * @param textureInternalFormat internalFormat parameter to {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, long)} - * @param textureDataFormat format parameter to {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, long)} - * @param textureDataType type parameter to {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, long)} - * @param magFilter if > 0 value for {@link GL#GL_TEXTURE_MAG_FILTER} - * @param minFilter if > 0 value for {@link GL#GL_TEXTURE_MIN_FILTER} - * @param wrapS if > 0 value for {@link GL#GL_TEXTURE_WRAP_S} - * @param wrapT if > 0 value for {@link GL#GL_TEXTURE_WRAP_T} - * @return index of the texture colorbuffer if bound and configured successfully, otherwise -1 - * @throws GLException in case the texture colorbuffer couldn't be allocated - */ - public int attachTexture2D(GL gl, int texUnit, - int textureInternalFormat, int textureDataFormat, int textureDataType, - int magFilter, int minFilter, int wrapS, int wrapT) throws GLException { - checkBound(gl, true); - final int fbo_tex_idx = fbo_tex_num; - gl.glGenTextures(1, fbo_tex_names, fbo_tex_num); - if(fbo_tex_names[fbo_tex_idx]==0) { - throw new GLException("null generated texture"); - } - fbo_tex_units[fbo_tex_idx] = texUnit; - fbo_tex_num++; - if(0<=texUnit) { - gl.glActiveTexture(GL.GL_TEXTURE0 + texUnit); - } - gl.glBindTexture(GL.GL_TEXTURE_2D, fbo_tex_names[fbo_tex_idx]); - checkNoError(gl, gl.glGetError(), "FBObject Init.bindTex"); // throws GLException if error - gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, textureInternalFormat, width, height, 0, - textureDataFormat, textureDataType, null); - int glerr = gl.glGetError(); - if(GL.GL_NO_ERROR != glerr) { - int[] sz = new int[1]; - gl.glGetIntegerv(GL.GL_MAX_TEXTURE_SIZE, sz, 0); - // throws GLException if error - checkNoError(gl, glerr, "FBObject Init.texImage2D: "+ - " int-fmt 0x"+Integer.toHexString(textureInternalFormat)+ - ", "+width+"x"+height+ - ", data-fmt 0x"+Integer.toHexString(textureDataFormat)+ - ", data-type 0x"+Integer.toHexString(textureDataType)+ - ", max tex-sz "+sz[0]); - } - if( 0 < magFilter ) { - gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, magFilter); - } - if( 0 < minFilter ) { - gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, minFilter); - } - if( 0 < wrapS ) { - gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, wrapS); - } - if( 0 < wrapT ) { - gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, wrapT); - } - - // Set up the color buffer for use as a renderable texture: - gl.glFramebufferTexture2D(GL.GL_FRAMEBUFFER, - GL.GL_COLOR_ATTACHMENT0 + colorattachment_num++, - GL.GL_TEXTURE_2D, fbo_tex_names[fbo_tex_idx], 0); - - updateStatus(gl); - return isStatusValid() ? fbo_tex_idx : -1; - } - - /** - * Attaches one Depth Buffer to this FBO's instance. - *

This may be done only one time.

- * - *

Assumes a bound FBO

- *

Leaves the FBO bound!

- * @param gl the current GL context - * @param depthComponentType {@link GL#GL_DEPTH_COMPONENT16}, {@link GL#GL_DEPTH_COMPONENT24} or {@link GL#GL_DEPTH_COMPONENT32} - * @return true if the depth renderbuffer could be bound and configured, otherwise false - * @throws GLException in case the depth renderbuffer couldn't be allocated or one is already attached. - */ - public boolean attachDepthBuffer(GL gl, int depthComponentType) throws GLException { - checkBound(gl, true); - if(depth_rb != 0) { - throw new GLException("FBO depth buffer already attached (rb "+depth_rb+")"); - } - int name[] = new int[1]; - gl.glGenRenderbuffers(1, name, 0); - depth_rb = name[0]; - if(depth_rb==0) { - throw new GLException("null generated renderbuffer"); - } - // Initialize the depth buffer: - gl.glBindRenderbuffer(GL.GL_RENDERBUFFER, depth_rb); - if(!gl.glIsRenderbuffer(depth_rb)) { - System.err.println("not a depthbuffer: "+ depth_rb); - name[0] = depth_rb; - gl.glDeleteRenderbuffers(1, name, 0); - depth_rb=0; - return false; - } - - gl.glRenderbufferStorage(GL.GL_RENDERBUFFER, depthComponentType, width, height); - // Set up the depth buffer attachment: - gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, - GL.GL_DEPTH_ATTACHMENT, - GL.GL_RENDERBUFFER, depth_rb); - updateStatus(gl); - return isStatusValid(); - } - - /** - * Attaches one Stencil Buffer to this FBO's instance. - *

This may be done only one time.

- * - *

Assumes a bound FBO

- *

Leaves the FBO bound!

- * @param gl the current GL context - * @param stencilComponentType {@link GL#GL_STENCIL_INDEX1}, {@link GL#GL_STENCIL_INDEX4} or {@link GL#GL_STENCIL_INDEX8} - * @return true if the stencil renderbuffer could be bound and configured, otherwise false - * @throws GLException in case the stencil renderbuffer couldn't be allocated or one is already attached. - */ - public boolean attachStencilBuffer(GL gl, int stencilComponentType) throws GLException { - checkBound(gl, true); - if(stencil_rb != 0) { - throw new GLException("FBO stencil buffer already attached (rb "+stencil_rb+")"); - } - int name[] = new int[1]; - gl.glGenRenderbuffers(1, name, 0); - stencil_rb = name[0]; - if(stencil_rb==0) { - throw new GLException("null generated stencilbuffer"); - } - // Initialize the stencil buffer: - gl.glBindRenderbuffer(GL.GL_RENDERBUFFER, stencil_rb); - if(!gl.glIsRenderbuffer(stencil_rb)) { - System.err.println("not a stencilbuffer: "+ stencil_rb); - name[0] = stencil_rb; - gl.glDeleteRenderbuffers(1, name, 0); - stencil_rb=0; - return false; - } - gl.glRenderbufferStorage(GL.GL_RENDERBUFFER, stencilComponentType, width, height); - gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, - GL.GL_STENCIL_ATTACHMENT, - GL.GL_RENDERBUFFER, stencil_rb); - updateStatus(gl); - return isStatusValid(); - } - - /** - * @param gl the current GL context - */ - public void destroy(GL gl) { - if(bound) { - unbind(gl); - } - - int name[] = new int[1]; - - if(0!=stencil_rb) { - name[0] = stencil_rb; - gl.glDeleteRenderbuffers(1, name, 0); - stencil_rb = 0; - } - if(0!=depth_rb) { - name[0] = depth_rb; - gl.glDeleteRenderbuffers(1, name, 0); - depth_rb=0; - } - if(null!=fbo_tex_names && fbo_tex_num>0) { - gl.glDeleteTextures(1, fbo_tex_names, fbo_tex_num); - fbo_tex_names = new int[MAX_FBO_TEXTURES]; - fbo_tex_units = new int[MAX_FBO_TEXTURES]; - fbo_tex_num = 0; - } - colorattachment_num = 0; - if(0!=fb) { - name[0] = fb; - gl.glDeleteFramebuffers(1, name, 0); - fb = 0; - } - initialized = false; - } - - /** - * Bind this FBO - *

In case you have attached more than one color buffer, - * you may want to setup {@link GL2GL3#glDrawBuffers(int, int[], int)}.

- * @param gl the current GL context - */ - public void bind(GL gl) { - checkBound(gl, false); - gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, fb); - bound = true; - } - - /** - * Unbind FBO, ie bind 'non' FBO 0 - * @param gl the current GL context - */ - public void unbind(GL gl) { - checkBound(gl, true); - gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0); - bound = false; - } - - /** - * Bind the texture with given index. - * - *

If a valid texture unit was named via {@link #attachTexture2D(GL, int, int, int, int, int) attachTexture2D(..)}, - * the unit is activated via {@link GL#glActiveTexture(int) glActiveTexture(GL.GL_TEXTURE0 + unit)}.

- * @param gl the current GL context - * @param texIdx index of the texture to use, prev. attached w/ {@link #attachTexture2D(GL, int, int, int, int, int) attachTexture2D(..)} - */ - public void use(GL gl, int texIdx) { - checkBound(gl, false); - if(texIdx >= fbo_tex_num) { - throw new GLException("Invalid texId, only "+fbo_tex_num+" textures are attached"); - } - if(0<=fbo_tex_units[texIdx]) { - gl.glActiveTexture(GL.GL_TEXTURE0 + fbo_tex_units[texIdx]); - } - gl.glBindTexture(GL.GL_TEXTURE_2D, fbo_tex_names[texIdx]); // use it .. - } - - /** Unbind texture, ie bind 'non' texture 0 */ - public void unuse(GL gl) { - checkBound(gl, false); - gl.glBindTexture(GL.GL_TEXTURE_2D, 0); // don't use it - } - - public final boolean isBound() { return bound; } - public final int getWidth() { return width; } - public final int getHeight() { return height; } - public final int getFBName() { return fb; } - public final int getTextureNumber() { return fbo_tex_num; } - public final int getTextureName(int idx) { return fbo_tex_names[idx]; } - - /** @return the named texture unit ranging from [0..{@link GL2#GL_MAX_TEXTURE_UNITS}-1], or -1 if no unit was desired. */ - public final int getTextureUnit(int idx) { return fbo_tex_units[idx]; } - public final int getColorAttachmentNumber() { return colorattachment_num; } - public final int getStencilBuffer() { return stencil_rb; } - public final int getDepthBuffer() { return depth_rb; } - public final String toString() { - return "FBO[name "+fb+", size "+width+"x"+height+", color num "+colorattachment_num+", tex num "+fbo_tex_num+", depth "+depth_rb+", stencil "+stencil_rb+"]"; - } - - private void updateStatus(GL gl) { - if(!gl.glIsFramebuffer(fb)) { - vStatus = -1; - } else { - vStatus = gl.glCheckFramebufferStatus(GL.GL_FRAMEBUFFER); - } - } -} diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLBuffers.java b/src/jogl/classes/com/jogamp/opengl/util/GLBuffers.java index 8401b9cd2..331d6fa4e 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/GLBuffers.java +++ b/src/jogl/classes/com/jogamp/opengl/util/GLBuffers.java @@ -39,6 +39,7 @@ package com.jogamp.opengl.util; import com.jogamp.common.nio.Buffers; + import javax.media.opengl.GL; import javax.media.opengl.GL2; import javax.media.opengl.GL2ES2; @@ -56,22 +57,32 @@ import java.nio.*; public class GLBuffers extends Buffers { /** - * @param glType shall be one of - * GL_UNSIGNED_BYTE, GL_BYTE, GL_UNSIGNED_SHORT, GL_SHORT, - * GL_UNSIGNED_INT, GL_INT, GL_HALF_FLOAT, GL_FLOAT, GL_DOUBLE, - * GL_UNSIGNED_BYTE_3_3_2, GL_UNSIGNED_BYTE_2_3_3_REV, - * GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_SHORT_5_6_5_REV, - * GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_4_4_4_4_REV, - * GL_UNSIGNED_SHORT_5_5_5_1, GL_UNSIGNED_SHORT_1_5_5_5_REV, - * GL_UNSIGNED_INT_8_8_8_8, GL_UNSIGNED_INT_8_8_8_8_REV, - * GL_UNSIGNED_INT_10_10_10_2, GL_UNSIGNED_INT_2_10_10_10_REV - * GL_UNSIGNED_INT_24_8, GL_UNSIGNED_INT_10F_11F_11F_REV, - * GL_UNSIGNED_INT_5_9_9_9_REV, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, - * GL_HILO16_NV, GL_SIGNED_HILO16_NV (27) + * @param glType shall be one of (29)
+ * GL_BYTE, GL_UNSIGNED_BYTE,
+ * GL_UNSIGNED_BYTE_3_3_2, GL_UNSIGNED_BYTE_2_3_3_REV,
+ *
+ * GL_SHORT, GL_UNSIGNED_SHORT,
+ * 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.GL_HALF_FLOAT, GLES2.GL_HALF_FLOAT_OES:
+ *
+ * GL_FIXED, GL_INT
+ * GL_UNSIGNED_INT, 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_HILO16_NV, GL_SIGNED_HILO16_NV
+ *
+ * GL2GL3.GL_FLOAT_32_UNSIGNED_INT_24_8_REV
+ *
+ * GL_FLOAT, GL_DOUBLE
+ * * @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)
+ * GL_BYTE, GL_UNSIGNED_BYTE,
+ * GL_UNSIGNED_BYTE_3_3_2, GL_UNSIGNED_BYTE_2_3_3_REV,
+ *
+ * GL_SHORT, GL_UNSIGNED_SHORT,
+ * 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_HALF_FLOAT, GL_HALF_FLOAT_OES
+ *
+ * GL_FIXED, GL_INT
+ * GL_UNSIGNED_INT, 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_HILO16_NV, GL_SIGNED_HILO16_NV
+ *
+ * GL_FLOAT_32_UNSIGNED_INT_24_8_REV
+ *
+ * GL_FLOAT, GL_DOUBLE
+ * * @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)
+ * GL_BYTE, GL_UNSIGNED_BYTE,
+ * GL_UNSIGNED_BYTE_3_3_2, GL_UNSIGNED_BYTE_2_3_3_REV,
+ *
+ * GL_SHORT, GL_UNSIGNED_SHORT,
+ * 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_HALF_FLOAT, GL_HALF_FLOAT_OES
+ *
+ * GL_FIXED, GL_INT
+ * GL_UNSIGNED_INT, 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_HILO16_NV, GL_SIGNED_HILO16_NV
+ *
+ * GL_FLOAT_32_UNSIGNED_INT_24_8_REV
+ *
+ * GL_FLOAT, GL_DOUBLE
* @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)
+ * GL_COLOR_INDEX GL_STENCIL_INDEX
+ * GL_DEPTH_COMPONENT GL_DEPTH_STENCIL
+ * GL_RED GL_RED_INTEGER
+ * GL_GREEN GL_GREEN_INTEGER
+ * GL_BLUE GL_BLUE_INTEGER
+ * GL_ALPHA GL_LUMINANCE (12)
+ *
+ * GL_LUMINANCE_ALPHA GL_RG
+ * GL_RG_INTEGER GL_HILO_NV
+ * GL_SIGNED_HILO_NV (5)
+ *
+ * GL_RGB GL_RGB_INTEGER
+ * GL_BGR GL_BGR_INTEGER (4)
+ *
+ * GL_RGBA GL_RGBA_INTEGER
+ * GL_BGRA GL_BGRA_INTEGER
+ * GL_ABGR_EXT (5)
* - * @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)
+ * GL_BITMAP,
+ * GL_BYTE, GL_UNSIGNED_BYTE,
+ * GL_UNSIGNED_BYTE_3_3_2, GL_UNSIGNED_BYTE_2_3_3_REV,
+ *
+ * GL_SHORT, GL_UNSIGNED_SHORT,
+ * 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_HALF_FLOAT, GL_HALF_FLOAT_OES
+ *
+ * GL_FIXED, GL_INT
+ * GL_UNSIGNED_INT, 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_HILO16_NV, GL_SIGNED_HILO16_NV
+ *
+ * GL_FLOAT_32_UNSIGNED_INT_24_8_REV
+ *
+ * GL_FLOAT, GL_DOUBLE
* * @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 performance tips 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..1b84bd9bd 100644 --- a/src/jogl/classes/javax/media/opengl/DefaultGLCapabilitiesChooser.java +++ b/src/jogl/classes/javax/media/opengl/DefaultGLCapabilitiesChooser.java @@ -141,7 +141,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 +158,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 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.

- + based rendering mechanism as well by end users directly. +

The implementation shall initialize itself as soon as possible, ie if the attached {@link javax.media.nativewindow.NativeSurface NativeSurface} becomes visible/realized. The following protocol shall be satisfied: @@ -64,18 +64,18 @@ import jogamp.opengl.Debug; registered {@link GLEventListener}s. This can be done immediatly, or with the followup {@link #display display(..)} call.

  • 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.
  • -

    - +

    +

    Another implementation detail is the drawable reconfiguration. One use case is where a window is being dragged to another screen with a different pixel configuration, ie {@link GLCapabilities}. The implementation - shall be able to detect such cases in conjunction with the associated {@link javax.media.nativewindow.NativeSurface NativeSurface}.
    + shall be able to detect such cases in conjunction with the associated {@link javax.media.nativewindow.NativeSurface NativeSurface}.
    For example, AWT's {@link java.awt.Canvas} 's {@link java.awt.Canvas#getGraphicsConfiguration getGraphicsConfiguration()} is capable to determine a display device change. This is demonstrated within {@link javax.media.opengl.awt.GLCanvas}'s and NEWT's AWTCanvas {@link javax.media.opengl.awt.GLCanvas#getGraphicsConfiguration getGraphicsConfiguration()} specialization. Another demonstration is NEWT's {@link javax.media.nativewindow.NativeWindow NativeWindow} - implementation on the Windows platform, which utilizes the native platform's MonitorFromWindow(HWND) function.
    + implementation on the Windows platform, which utilizes the native platform's MonitorFromWindow(HWND) function.
    All OpenGL resources shall be regenerated, while the drawable's {@link GLCapabilities} has - to be choosen again. The following protocol shall be satisfied. + to be chosen again. The following protocol shall be satisfied.

    • Controlled disposal:
      • @@ -97,16 +97,16 @@ import jogamp.opengl.Debug;
      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.

      - - However, to not introduce to much breakage with older applications and because of the situation + and make your application comply with the above protocol. +

      + Avoiding breakage with older applications and because of the situation mentioned above, the boolean system property jogl.screenchange.action will control the - screen change action as follows:
      - + screen change action as follows:

           -Djogl.screenchange.action=false Disable the drawable reconfiguration (the default)
           -Djogl.screenchange.action=true  Enable  the drawable reconfiguration
           
      +

      */ public interface GLAutoDrawable extends GLDrawable { /** Flag reflecting wheather the drawable reconfiguration will be issued in @@ -362,5 +362,29 @@ public interface GLAutoDrawable extends GLDrawable { demos for examples. @return the set GL pipeline or null if not successful */ public GL setGL(GL gl); + + /** + * Method may return the upstream UI toolkit object + * holding this {@link GLAutoDrawable} instance, if exist. + *

      + * Currently known Java UI toolkits and it's known return types are: + * + * + *
      Toolkit GLAutoDrawable Implementation ~ Return Type of getUpstreamWidget() + *
      NEWT {@link com.jogamp.newt.opengl.GLWindow} has a {@link com.jogamp.newt.Window} + *
      SWT {@link com.jogamp.opengl.swt.GLCanvas} is a {@link org.eclipse.swt.widgets.Canvas} + *
      AWT {@link javax.media.opengl.awt.GLCanvas} is a {@link java.awt.Canvas} + *
      AWT {@link javax.media.opengl.awt.GLJPanel} is a {@link javax.swing.JPanel} + *
      + * However, the result may be other object types than the listed above + * due to new supported toolkits. + *

      + *

      + * This method may also return null if no UI toolkit is being used, + * as common for offscreen rendering. + *

      + * @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..1f6166719 100644 --- a/src/jogl/classes/javax/media/opengl/GLAutoDrawableDelegate.java +++ b/src/jogl/classes/javax/media/opengl/GLAutoDrawableDelegate.java @@ -56,8 +56,14 @@ import jogamp.opengl.GLDrawableImpl; public class GLAutoDrawableDelegate extends GLAutoDrawableBase { public static final boolean DEBUG = Debug.debug("GLAutoDrawableDelegate"); - public GLAutoDrawableDelegate(GLDrawable drawable, GLContext context) { + /** + * @param drawable + * @param context + * @param upstreamWidget optional UI element holding this instance, see {@link #getUpstreamWidget()}. + */ + public GLAutoDrawableDelegate(GLDrawable drawable, GLContext context, Object upstreamWidget) { super((GLDrawableImpl)drawable, (GLContextImpl)context); + this.upstreamWidget = null; } // @@ -80,8 +86,14 @@ 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 + public final Object getUpstreamWidget() { + return upstreamWidget; + } + /** * {@inheritDoc} *

      diff --git a/src/jogl/classes/javax/media/opengl/GLBase.java b/src/jogl/classes/javax/media/opengl/GLBase.java index bd24b15bc..f5831a72d 100644 --- a/src/jogl/classes/javax/media/opengl/GLBase.java +++ b/src/jogl/classes/javax/media/opengl/GLBase.java @@ -340,5 +340,60 @@ public interface GLBase { * completeness. */ public Object getExtension(String extensionName); + + /** Aliased entrypoint of void {@native glClearDepth}(GLclampd depth); and void {@native glClearDepthf}(GLclampf depth); . */ + public void glClearDepth( double depth ); + + /** Aliased entrypoint of void {@native glDepthRange}(GLclampd depth); and void {@native glDepthRangef}(GLclampf depth); . */ + public void glDepthRange(double zNear, double zFar); + + /** + * @param target a GL buffer (VBO) target as used in {@link GL#glBindBuffer(int, int)}, ie {@link GL#GL_ELEMENT_ARRAY_BUFFER}, {@link GL#GL_ARRAY_BUFFER}, .. + * @return the GL buffer (VBO) name bound to a target via {@link GL#glBindBuffer(int, int)} or 0 if unbound. + */ + public int glGetBoundBuffer(int target); + + /** + * @param buffer a GL buffer name, generated with {@link GL#glGenBuffers(int, int[], int)} and used in {@link GL#glBindBuffer(int, int)}, {@link GL#glBufferData(int, long, java.nio.Buffer, int)} or {@link GL2#glNamedBufferDataEXT(int, long, java.nio.Buffer, int)} for example. + * @return the size of the given GL buffer + */ + public long glGetBufferSize(int buffer); + + /** + * @return true if a VBO is bound to {@link GL.GL_ARRAY_BUFFER} via {@link GL#glBindBuffer(int, int)}, otherwise false + */ + public boolean glIsVBOArrayEnabled(); + + /** + * @return true if a VBO is bound to {@link GL.GL_ELEMENT_ARRAY_BUFFER} via {@link GL#glBindBuffer(int, int)}, otherwise false + */ + public boolean glIsVBOElementArrayEnabled(); + + /** + * Return the framebuffer name bound to this context, + * see {@link GL#glBindFramebuffer(int, int)}. + */ + public int getBoundFramebuffer(int target); + + /** + * Return the default draw framebuffer name. + *

      + * May differ from it's default zero + * in case an framebuffer object ({@link FBObject}) based drawable + * is being used. + *

      + */ + public int getDefaultDrawFramebuffer(); + + /** + * Return the default read framebuffer name. + *

      + * May differ from it's default zero + * in case an framebuffer object ({@link FBObject}) based drawable + * is being used. + *

      + */ + public int getDefaultReadFramebuffer(); + } diff --git a/src/jogl/classes/javax/media/opengl/GLCapabilities.java b/src/jogl/classes/javax/media/opengl/GLCapabilities.java index e5258bcfd..8845ec665 100644 --- a/src/jogl/classes/javax/media/opengl/GLCapabilities.java +++ b/src/jogl/classes/javax/media/opengl/GLCapabilities.java @@ -183,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; @@ -231,15 +231,13 @@ public class GLCapabilities extends Capabilities implements Cloneable, GLCapabil /** * Enables or disables pbuffer usage. *

      - * If enabled this method also invokes {@link #setOnscreen(int) setOnscreen(false)} - * and {@link #setFBO(int) setFBO(false)}
      + * If enabled this method also invokes {@link #setOnscreen(int) setOnscreen(false)}. *

      * Defaults to false. */ public void setPBuffer(boolean enable) { if(enable) { setOnscreen(false); - setFBO(false); } isPBuffer = enable; } @@ -252,28 +250,28 @@ public class GLCapabilities extends Capabilities implements Cloneable, GLCapabil /** * Enables or disables FBO usage. *

      - * If enabled this method also invokes {@link #setOnscreen(int) setOnscreen(false)} - * and {@link #setPBuffer(int) setPBuffer(false)}
      + * If enabled this method also invokes {@link #setOnscreen(int) setOnscreen(false)}. *

      * Defaults to false. */ public void setFBO(boolean enable) { if(enable) { setOnscreen(false); - setPBuffer(false); } isFBO = enable; } /** * Sets whether the drawable surface supports onscreen.
      - * If enabled this method also invokes {@link #setPBuffer(int) setPBuffer(false)}
      + * If enabled this method also invokes {@link #setPBuffer(int) setPBuffer(false)} + * and {@link #setFBO(int) setFBO(false)}
      * Defaults to true. */ @Override public void setOnscreen(boolean onscreen) { if(onscreen) { setPBuffer(false); + setFBO(false); } super.setOnscreen(onscreen); } @@ -413,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 @@ -492,12 +493,14 @@ public class GLCapabilities extends Capabilities implements Cloneable, GLCapabil if(!isOnscreen()) { if(isFBO) { sink.append(", fbo"); - } else if(isPBuffer) { + } + 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 883f3912e..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,12 +144,12 @@ 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 is used/requested. + * Indicates whether FBO offscreen is used/requested. */ boolean isFBO(); 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 true (default), bootstrapping the available GL profiles * will use the highest compatible GL context for each profile, @@ -120,13 +122,13 @@ public abstract class GLContext { protected static final int CTX_PROFILE_ES = 1 << 3; /** ARB_create_context related: flag forward compatible. Cache key value. See {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */ protected static final int CTX_OPTION_FORWARD = 1 << 4; - /** ARB_create_context related: flag debug. Not a cache key. See {@link #setContextCreationFlags(int)}, {@link GLAutoDrawable#setContextCreationFlags(int)}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */ + /** ARB_create_context related: flag debug. Cache key value. See {@link #setContextCreationFlags(int)}, {@link GLAutoDrawable#setContextCreationFlags(int)}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */ public static final int CTX_OPTION_DEBUG = 1 << 5; /** GL_ARB_ES2_compatibility implementation related: Context is compatible w/ ES2. Not a cache key. See {@link #isGLES2Compatible()}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */ protected static final int CTX_IMPL_ES2_COMPAT = 1 << 8; - /** Context supports FBO, details see {@link #hasFBO()}. + /** Context supports basic FBO, details see {@link #hasFBO()}. * Not a cache key. * @see #hasFBO() * @see #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile) @@ -136,16 +138,6 @@ public abstract class GLContext { /** Context uses software rasterizer, otherwise hardware rasterizer. Cache key value. See {@link #isHardwareRasterizer()}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */ protected static final int CTX_IMPL_ACCEL_SOFT = 1 << 15; - protected static final String GL_ARB_ES2_compatibility = "GL_ARB_ES2_compatibility"; - protected static final String GL_ARB_framebuffer_object = "GL_ARB_framebuffer_object"; - protected static final String GL_EXT_framebuffer_object = "GL_EXT_framebuffer_object"; - protected static final String GL_EXT_framebuffer_blit = "GL_EXT_framebuffer_blit"; - protected static final String GL_EXT_framebuffer_multisample = "GL_EXT_framebuffer_multisample"; - protected static final String GL_EXT_packed_depth_stencil = "GL_EXT_packed_depth_stencil"; - protected static final String GL_ARB_texture_non_power_of_two = "GL_ARB_texture_non_power_of_two"; - protected static final String GL_EXT_texture_format_BGRA8888 = "GL_EXT_texture_format_BGRA8888"; - protected static final String GL_IMG_texture_format_BGRA8888 = "GL_IMG_texture_format_BGRA8888"; - private static final ThreadLocal currentContext = new ThreadLocal(); private final HashMap attachedObjectsByString = new HashMap(); @@ -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 - * GL_ARB_ES2_compatibility, ARB_framebuffer_object or all of - * EXT_framebuffer_object, EXT_framebuffer_multisample, - * EXT_framebuffer_blit, GL_EXT_packed_depth_stencil. + /** + * Returns true if basic FBO support is available, otherwise false. + *

      + * Basic FBO is supported if the context is either GL-ES >= 2.0, GL >= core 3.0 or implements the extensions + * GL_ARB_ES2_compatibility, GL_ARB_framebuffer_object, GL_EXT_framebuffer_object or GL_OES_framebuffer_object. + *

      + *

      + * Basic FBO support may only include one color attachment and no multisampling, + * as well as limited internal formats for renderbuffer. + *

      * @see #CTX_IMPL_FBO + * @see com.jogamp.opengl.FBObject#supportsBasicFBO(GL) + * @see com.jogamp.opengl.FBObject#supportsFullFBO(GL) */ public final boolean hasFBO() { return 0 != ( ctxOptions & CTX_IMPL_FBO ) ; @@ -659,13 +659,13 @@ public abstract class GLContext { /** Note: The GL impl. may return a const value, ie {@link GLES2#isNPOTTextureAvailable()} always returns true. */ public boolean isNPOTTextureAvailable() { - return isGL3() || isGLES2Compatible() || isExtensionAvailable(GL_ARB_texture_non_power_of_two); + return isGL3() || isGLES2Compatible() || isExtensionAvailable(GLExtensions.ARB_texture_non_power_of_two); } public boolean isTextureFormatBGRA8888Available() { return isGL2GL3() || - isExtensionAvailable(GL_EXT_texture_format_BGRA8888) || - isExtensionAvailable(GL_IMG_texture_format_BGRA8888) ; + isExtensionAvailable(GLExtensions.EXT_texture_format_BGRA8888) || + isExtensionAvailable(GLExtensions.IMG_texture_format_BGRA8888) ; } /** @see GLProfile#isGL4bc() */ @@ -798,7 +798,32 @@ public abstract class GLContext { } protected boolean bindSwapBarrierImpl(int group, int barrier) { /** nop per default .. **/ return false; } - + /** + * Return the framebuffer name bound to this context, + * see {@link GL#glBindFramebuffer(int, int)}. + */ + public abstract int getBoundFramebuffer(int target); + + /** + * Return the default draw framebuffer name. + *

      + * May differ from it's default zero + * in case an framebuffer object ({@link FBObject}) based drawable + * is being used. + *

      + */ + public abstract int getDefaultDrawFramebuffer(); + + /** + * Return the default read framebuffer name. + *

      + * May differ from it's default zero + * in case an framebuffer object ({@link FBObject}) based drawable + * is being used. + *

      + */ + public abstract int getDefaultReadFramebuffer(); + /** * @return The extension implementing the GLDebugOutput feature, * either GL_ARB_debug_output or GL_AMD_debug_output. @@ -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 @@ -1180,6 +1211,23 @@ public abstract class GLContext { return null; } + /** + * Returns true if it is possible to create an framebuffer object (FBO). + *

      + * FBO feature is implemented in OpenGL, hence it is {@link GLProfile} dependent. + *

      + *

      + * FBO support is queried as described in {@link #hasFBO()}. + *

      + * + * @param device the device to request whether FBO is available for + * @param glp {@link GLProfile} to check for FBO capabilities + * @see GLContext#hasFBO() + */ + public static final boolean isFBOAvailable(AbstractGraphicsDevice device, GLProfile glp) { + return 0 != ( CTX_IMPL_FBO & getAvailableContextProperties(device, glp) ); + } + /** * @param device the device to request whether the profile is available for * @param reqMajor Key Value either 1, 2, 3 or 4 diff --git a/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java b/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java index d6480e7aa..612a02f14 100644 --- a/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java +++ b/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java @@ -50,9 +50,11 @@ import com.jogamp.common.JogampRuntimeException; import com.jogamp.common.util.ReflectionUtil; import javax.media.nativewindow.AbstractGraphicsDevice; +import javax.media.nativewindow.AbstractGraphicsScreen; import javax.media.nativewindow.NativeSurface; import javax.media.nativewindow.NativeWindowFactory; import javax.media.nativewindow.ProxySurface; +import javax.media.nativewindow.ProxySurface.UpstreamSurfaceHook; import javax.media.opengl.GLProfile.ShutdownType; import jogamp.opengl.Debug; @@ -398,9 +400,18 @@ public abstract class GLDrawableFactory { /** * Creates a Offscreen GLDrawable incl it's offscreen {@link javax.media.nativewindow.NativeSurface} with the given capabilites and dimensions. *

      - * A Pbuffer drawable/surface is created if both {@link javax.media.opengl.GLCapabilities#isPBuffer() caps.isPBuffer()} - * and {@link #canCreateGLPbuffer(javax.media.nativewindow.AbstractGraphicsDevice) canCreateGLPbuffer(device)} is true.
      - * Otherwise a simple pixmap/bitmap drawable/surface is created, which is unlikely to be hardware accelerated.
      + * It's {@link AbstractGraphicsConfiguration} is properly set according to the given {@link GLCapabilitiesImmutable}, see below. + *

      + *

      + * A FBO drawable is created if both {@link javax.media.opengl.GLCapabilities#isFBO() caps.isFBO()} + * and {@link GLContext#isFBOAvailable(AbstractGraphicsDevice, GLProfile) canCreateFBO(device, caps.getGLProfile())} is true. + *

      + *

      + * A Pbuffer drawable is created if both {@link javax.media.opengl.GLCapabilities#isPBuffer() caps.isPBuffer()} + * and {@link #canCreateGLPbuffer(javax.media.nativewindow.AbstractGraphicsDevice) canCreateGLPbuffer(device)} is true. + *

      + *

      + * If neither FBO nor Pbuffer is available, a simple pixmap/bitmap drawable/surface is created, which is unlikely to be hardware accelerated. *

      * * @param device which {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection() connection} denotes the shared device to be used, may be null for the platform's default device. @@ -421,42 +432,31 @@ public abstract class GLDrawableFactory { throws GLException; /** - * Creates an offscreen NativeSurface.
      - * 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.
      - * Otherwise a simple pixmap/bitmap surface is created. The latter is unlikely to be hardware accelerated.
      - * - * @param device which {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection() connection} denotes the shared the target device, may be null for the platform's default device. - * @param 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.
      - * 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. + *

      + * It's {@link AbstractGraphicsConfiguration} is properly set according to the given {@link GLCapabilitiesImmutable}. + *

      + *

      + * Lifecycle (destruction) of the given surface handle shall be handled by the caller. + *

      + *

      + * Such surface can be used to instantiate a GLDrawable. With the help of {@link GLAutoDrawableDelegate} + * you will be able to implement a new native windowing system binding almost on-the-fly, see {@link com.jogamp.opengl.swt.GLCanvas}. + *

      * - * @param device the platform's target device, shall not be null + * @param device which {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection() connection} denotes the shared the target device, may be null for the platform's default device. + * Caller has to ensure it is compatible w/ the given windowHandle + * @param screenIdx matching screen index of given windowHandle * @param windowHandle the native window handle * @param caps the requested GLCapabilties * @param chooser the custom chooser, may be null for default - * @return The proxy surface wrapping the windowHandle on the device + * @param upstream optional {@link ProxySurface.UpstreamSurfaceHook} allowing control of the {@link ProxySurface}'s lifecycle and data it presents. + * @return the created {@link ProxySurface} instance w/ defined surface handle. */ - public abstract ProxySurface createProxySurface(AbstractGraphicsDevice device, + public abstract ProxySurface createProxySurface(AbstractGraphicsDevice device, + int screenIdx, long windowHandle, - GLCapabilitiesImmutable caps, - GLCapabilitiesChooser chooser); + GLCapabilitiesImmutable caps, GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstream); /** * Returns true if it is possible to create a GLPbuffer. Some older @@ -492,23 +492,7 @@ public abstract class GLDrawableFactory { GLContext shareWith) throws GLException; - /** - * Returns true if it is possible to create an framebuffer object (FBO). - *

      - * FBO feature is implemented in OpenGL, hence it is {@link GLProfile} dependent. - *

      - *

      - * FBO support is queried as described in {@link GLContext#hasFBO()}. - *

      - * - * @param device which {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection() connection} denotes the shared the target device, may be null for the platform's default device. - * @param glp {@link GLProfile} to check for FBO capabilities - * @see GLContext#hasFBO() - */ - public final boolean canCreateFBO(AbstractGraphicsDevice device, GLProfile glp) { - return 0 != ( GLContext.CTX_IMPL_FBO & GLContext.getAvailableContextProperties(device, glp) ); - } - + //---------------------------------------------------------------------- // Methods for interacting with third-party OpenGL libraries diff --git a/src/jogl/classes/javax/media/opengl/GLProfile.java b/src/jogl/classes/javax/media/opengl/GLProfile.java index a7200b560..73d13a387 100644 --- a/src/jogl/classes/javax/media/opengl/GLProfile.java +++ b/src/jogl/classes/javax/media/opengl/GLProfile.java @@ -117,10 +117,12 @@ public class GLProfile { * @deprecated Use {@link #initSingleton()}. This method is subject to be removed in future versions of JOGL. */ public static void initSingleton(final boolean firstUIActionOnProcess) { + final boolean justInitialized; initLock.lock(); try { if(!initialized) { // volatile: ok initialized = true; + justInitialized = true; if(DEBUG) { System.err.println("GLProfile.initSingleton(firstUIActionOnProcess: "+firstUIActionOnProcess+") - thread "+Thread.currentThread().getName()); Thread.dumpStack(); @@ -166,10 +168,17 @@ public class GLProfile { return null; } }); + } else { + justInitialized = false; } } finally { initLock.unlock(); } + if(DEBUG) { + if( justInitialized && ( hasGL234Impl || hasGLES1Impl || hasGLES2Impl ) ) { + System.err.println(JoglVersion.getDefaultOpenGLInfo(defaultDevice, null, true)); + } + } } /** @@ -1532,18 +1541,17 @@ public class GLProfile { if(DEBUG) { // System.err.println("GLProfile.init addedAnyProfile "+addedAnyProfile+" (desktop: "+addedDesktopProfile+", egl "+addedEGLProfile+")"); - System.err.println("GLProfile.init addedAnyProfile "+addedAnyProfile); - System.err.println("GLProfile.init isAWTAvailable "+isAWTAvailable); - System.err.println("GLProfile.init hasDesktopGLFactory "+hasDesktopGLFactory); - System.err.println("GLProfile.init hasGL234Impl "+hasGL234Impl); - System.err.println("GLProfile.init hasEGLFactory "+hasEGLFactory); - System.err.println("GLProfile.init hasGLES1Impl "+hasGLES1Impl); - System.err.println("GLProfile.init hasGLES2Impl "+hasGLES2Impl); - System.err.println("GLProfile.init defaultDevice "+defaultDevice); - System.err.println("GLProfile.init profile order "+array2String(GL_PROFILE_LIST_ALL)); - if(hasGL234Impl || hasGLES1Impl || hasGLES2Impl) { // avoid deadlock - System.err.println(JoglVersion.getDefaultOpenGLInfo(null, true)); - } + System.err.println("GLProfile.init addedAnyProfile "+addedAnyProfile); + System.err.println("GLProfile.init isAWTAvailable "+isAWTAvailable); + System.err.println("GLProfile.init hasDesktopGLFactory "+hasDesktopGLFactory); + System.err.println("GLProfile.init hasGL234Impl "+hasGL234Impl); + System.err.println("GLProfile.init hasEGLFactory "+hasEGLFactory); + System.err.println("GLProfile.init hasGLES1Impl "+hasGLES1Impl); + System.err.println("GLProfile.init hasGLES2Impl "+hasGLES2Impl); + System.err.println("GLProfile.init defaultDevice "+defaultDevice); + System.err.println("GLProfile.init defaultDevice Desktop "+defaultDesktopDevice); + System.err.println("GLProfile.init defaultDevice EGL "+defaultEGLDevice); + System.err.println("GLProfile.init profile order "+array2String(GL_PROFILE_LIST_ALL)); } } @@ -1642,24 +1650,6 @@ public class GLProfile { if (DEBUG) { System.err.println("GLProfile.initProfilesForDevice: "+device+": egl Shared Ctx "+eglSharedCtxAvail); } - if( hasGLES2Impl ) { - // The native ES2 impl. overwrites a previous mapping using 'ES2 compatibility' by a desktop profile - GLContext.mapAvailableGLVersion(device, - 2, GLContext.CTX_PROFILE_ES, - 2, 0, GLContext.CTX_PROFILE_ES|GLContext.CTX_IMPL_ES2_COMPAT); - if (DEBUG) { - System.err.println(GLContext.getThreadName() + ": initProfilesForDeviceCritical-MapVersionsAvailable HAVE: ES2 -> ES 2.0"); - } - } - if( hasGLES1Impl ) { - // Always favor the native ES1 impl. - GLContext.mapAvailableGLVersion(device, - 1, GLContext.CTX_PROFILE_ES, - 1, 0, GLContext.CTX_PROFILE_ES); - if (DEBUG) { - System.err.println(GLContext.getThreadName() + ": initProfilesForDeviceCritical-MapVersionsAvailable HAVE: ES1 -> ES 1.0"); - } - } addedEGLProfile = computeProfileMap(device, false /* desktopCtxUndef*/, false /* esCtxUndef */); } @@ -1767,7 +1757,7 @@ public class GLProfile { } _mappedProfiles.put(profile, glProfile); if (DEBUG) { - System.err.println("GLProfile.init map "+glProfile+" on devide "+device.getConnection()); + System.err.println("GLProfile.init map "+glProfile+" on device "+device.getConnection()); } if(null==defaultGLProfileHW && isHardwareRasterizer[0]) { defaultGLProfileHW=glProfile; diff --git a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java index 48f7ea24a..c2e36ef9b 100644 --- a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java +++ b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java @@ -261,6 +261,11 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing this.device = device; } + @Override + public final Object getUpstreamWidget() { + return this; + } + @Override public void setShallUseOffscreenLayer(boolean v) { shallUseOffscreenLayer = v; @@ -1070,7 +1075,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing // System.err.println(NativeWindowVersion.getInstance()); System.err.println(JoglVersion.getInstance()); - System.err.println(JoglVersion.getDefaultOpenGLInfo(null, true).toString()); + System.err.println(JoglVersion.getDefaultOpenGLInfo(null, null, true).toString()); final GLCapabilitiesImmutable caps = new GLCapabilities( GLProfile.getDefault(GLProfile.getDefaultDevice()) ); final Frame frame = new Frame("JOGL AWT Test"); diff --git a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java index cd18c5098..acb8f2183 100644 --- a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java +++ b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java @@ -87,7 +87,7 @@ import jogamp.opengl.awt.Java2D; import jogamp.opengl.awt.Java2DGLContext; import com.jogamp.nativewindow.awt.AWTWindowClosingProtocol; -import com.jogamp.opengl.util.FBObject; +import com.jogamp.opengl.FBObject; import com.jogamp.opengl.util.GLBuffers; // FIXME: Subclasses need to call resetGLFunctionAvailability() on their @@ -250,6 +250,11 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing this.shareWith = shareWith; } + @Override + public final Object getUpstreamWidget() { + return this; + } + @Override public void display() { if (EventQueue.isDispatchThread()) { diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PES2.java b/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PES2.java index 804e9ee14..aabef29b0 100644 --- a/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PES2.java +++ b/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PES2.java @@ -32,7 +32,6 @@ import java.nio.FloatBuffer; import javax.media.opengl.GL2ES2; // FIXME: Subsume GL2GL3.GL_DRAW_FRAMEBUFFER -> GL2ES2.GL_DRAW_FRAMEBUFFER ! import javax.media.opengl.GL; -import javax.media.opengl.GLException; import javax.media.opengl.GLUniformData; import javax.media.opengl.fixedfunc.GLMatrixFunc; @@ -45,7 +44,9 @@ import com.jogamp.graph.geom.Vertex; import com.jogamp.graph.curve.opengl.GLRegion; import com.jogamp.graph.curve.opengl.RenderState; -import com.jogamp.opengl.util.FBObject; +import com.jogamp.opengl.FBObject; +import com.jogamp.opengl.FBObject.Attachment; +import com.jogamp.opengl.FBObject.TextureAttachment; import com.jogamp.opengl.util.GLArrayDataServer; import com.jogamp.opengl.util.PMVMatrix; import com.jogamp.opengl.util.glsl.ShaderState; @@ -60,6 +61,7 @@ public class VBORegion2PES2 extends GLRegion { private FBObject fbo; + private TextureAttachment texA; private PMVMatrix fboPMVMatrix; GLUniformData mgl_fboPMVMatrix; @@ -72,7 +74,7 @@ public class VBORegion2PES2 extends GLRegion { super(renderModes); fboPMVMatrix = new PMVMatrix(); mgl_fboPMVMatrix = new GLUniformData(UniformNames.gcu_PMVMatrix, 4, 4, fboPMVMatrix.glGetPMvMatrixf()); - mgl_ActiveTexture = new GLUniformData(UniformNames.gcu_TextureUnit, textureEngine); + mgl_ActiveTexture = new GLUniformData(UniformNames.gcu_TextureUnit, textureEngine); } public void update(GL2ES2 gl, RenderState rs) { @@ -214,8 +216,9 @@ public class VBORegion2PES2 extends GLRegion { final ShaderState st = rs.getShaderState(); gl.glViewport(0, 0, width, hight); - st.uniform(gl, mgl_ActiveTexture); - fbo.use(gl, 0); + st.uniform(gl, mgl_ActiveTexture); + gl.glActiveTexture(GL.GL_TEXTURE0 + mgl_ActiveTexture.intValue()); + fbo.use(gl, texA); verticeFboAttr.enableBuffer(gl, true); texCoordFboAttr.enableBuffer(gl, true); indicesFbo.enableBuffer(gl, true); @@ -244,20 +247,16 @@ public class VBORegion2PES2 extends GLRegion { // System.out.println("FBO Scale: " + m.glGetMatrixf().get(0) +" " + m.glGetMatrixf().get(5)); if(null != fbo && fbo.getWidth() != tex_width_c && fbo.getHeight() != tex_height_c ) { - fbo.destroy(gl); - fbo = null; + fbo.reset(gl, tex_width_c, tex_height_c); } - if(null == fbo) { - fbo = new FBObject(tex_width_c, tex_height_c); - fbo.init(gl); + if(null == fbo) { + fbo = new FBObject(); + fbo.reset(gl, tex_width_c, tex_height_c); // FIXME: shall not use bilinear, due to own AA ? However, w/o bilinear result is not smooth - fbo.attachTexture2D(gl, mgl_ActiveTexture.intValue(), GL2ES2.GL_LINEAR, GL2ES2.GL_LINEAR, GL2ES2.GL_CLAMP_TO_EDGE, GL2ES2.GL_CLAMP_TO_EDGE); - // fbo.attachTexture2D(gl, mgl_ActiveTexture.intValue(), GL2ES2.GL_NEAREST, GL2ES2.GL_NEAREST, GL2ES2.GL_CLAMP_TO_EDGE, GL2ES2.GL_CLAMP_TO_EDGE); - fbo.attachDepthBuffer(gl, GL.GL_DEPTH_COMPONENT16); // FIXME: or shall we use 24 or 32 bit depth ? - if(!fbo.isStatusValid()) { - throw new GLException("FBO invalid: "+fbo); - } + texA = fbo.attachTexture2D(gl, 0, true, GL2ES2.GL_LINEAR, GL2ES2.GL_LINEAR, GL2ES2.GL_CLAMP_TO_EDGE, GL2ES2.GL_CLAMP_TO_EDGE); + // texA = fbo.attachTexture2D(gl, 0, GL2ES2.GL_NEAREST, GL2ES2.GL_NEAREST, GL2ES2.GL_CLAMP_TO_EDGE, GL2ES2.GL_CLAMP_TO_EDGE); + fbo.attachRenderbuffer(gl, Attachment.Type.DEPTH, 24); } else { fbo.bind(gl); } @@ -305,6 +304,7 @@ public class VBORegion2PES2 extends GLRegion { if(null != fbo) { fbo.destroy(gl); fbo = null; + texA = null; } if(null != verticeTxtAttr) { st.ownAttribute(verticeTxtAttr, false); diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java index 4dd8806fa..e730bc62e 100644 --- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java +++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java @@ -49,8 +49,9 @@ import com.jogamp.common.os.DynamicLookupHelper; import com.jogamp.common.util.ReflectionUtil; import com.jogamp.gluegen.runtime.FunctionAddressResolver; import com.jogamp.gluegen.runtime.ProcAddressTable; -import com.jogamp.gluegen.runtime.opengl.GLExtensionNames; +import com.jogamp.gluegen.runtime.opengl.GLNameResolver; import com.jogamp.gluegen.runtime.opengl.GLProcAddressResolver; +import com.jogamp.opengl.GLExtensions; import javax.media.nativewindow.AbstractGraphicsConfiguration; import javax.media.nativewindow.AbstractGraphicsDevice; @@ -88,13 +89,14 @@ public abstract class GLContextImpl extends GLContext { // Tracks creation and initialization of buffer objects to avoid // repeated glGet calls upon glMapBuffer operations private GLBufferSizeTracker bufferSizeTracker; // Singleton - Set by GLContextShareSet - private GLBufferStateTracker bufferStateTracker = new GLBufferStateTracker(); - private GLStateTracker glStateTracker = new GLStateTracker(); + private final GLBufferStateTracker bufferStateTracker = new GLBufferStateTracker(); + private final GLStateTracker glStateTracker = new GLStateTracker(); private GLDebugMessageHandler glDebugHandler = null; + private final int[] boundFBOTarget = new int[] { 0, 0 }; // { draw, read } protected GLDrawableImpl drawable; protected GLDrawableImpl drawableRead; - + protected GL gl; protected static final Object mappedContextTypeObjectLock; @@ -140,11 +142,11 @@ public abstract class GLContextImpl extends GLContext { bufferSizeTracker.clearCachedBufferSizes(); } - if (bufferStateTracker != null) { + if (bufferStateTracker != null) { // bufferStateTracker.clearBufferObjectState(); } - if (glStateTracker != null) { + if (glStateTracker != null) { // glStateTracker.clearStates(false); } @@ -156,6 +158,11 @@ public abstract class GLContextImpl extends GLContext { glRenderer = ""; glRendererLowerCase = glRenderer; + + if (boundFBOTarget != null) { // + 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); @@ -488,11 +497,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 +559,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 +574,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 +790,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 +1048,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 +1109,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 +1178,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 +1191,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 +1285,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 +1343,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)); } @@ -1371,6 +1397,56 @@ public abstract class GLContextImpl extends GLContext { return lock.getQueueLength()>0; } + //--------------------------------------------------------------------------- + // 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)}. + * + *

      Invoked by {@link GL#glBindFramebuffer(int, int)}.

      + * + *

      Assumes valid framebufferName range of [0..{@link Integer#MAX_VALUE}]

      + * + *

      Does not throw an exception if target is unknown or framebufferName invalid.

      + */ + 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 ARB {@link GLDebugMessage}, using {@link GLDebugMessage#translateAMDEvent(javax.media.opengl.GLContext, long, int, int, int, String)}.

      */ public class GLDebugMessageHandler { - /** Extension GL_ARB_debug_output implementing GLDebugMessage */ - public static final String GL_ARB_debug_output = "GL_ARB_debug_output".intern(); - - /** Extension GL_AMD_debug_output 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..897d3fcaf 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 device {@link AbstractGraphicsDevice#getConnection()}, * either a preexisting or newly created, or null if creation failed or not supported.
      @@ -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 1 refers to ES1 and 2 to ES2, * otherwise the profile is ignored. @@ -125,6 +126,7 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { //--------------------------------------------------------------------------- // Dispatching GLDrawable construction in respect to the NativeSurface Capabilities // + @Override public GLDrawable createGLDrawable(NativeSurface target) { if (target == null) { throw new IllegalArgumentException("Null target"); @@ -132,23 +134,37 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { final MutableGraphicsConfiguration config = (MutableGraphicsConfiguration) target.getGraphicsConfiguration(); final GLCapabilitiesImmutable chosenCaps = (GLCapabilitiesImmutable) config.getChosenCapabilities(); final AbstractGraphicsDevice adevice = config.getScreen().getDevice(); + final boolean isFBOAvailable = GLContext.isFBOAvailable(adevice, chosenCaps.getGLProfile()); GLDrawable result = null; adevice.lock(); try { final OffscreenLayerSurface ols = NativeWindowFactory.getOffscreenLayerSurface(target, true); if(null != ols) { - // layered surface -> Offscreen/PBuffer + // layered surface -> Offscreen/[FBO|PBuffer] final GLCapabilities chosenCapsMod = (GLCapabilities) chosenCaps.cloneMutable(); chosenCapsMod.setOnscreen(false); - chosenCapsMod.setPBuffer(canCreateGLPbuffer(adevice)); + if( isFBOAvailable ) { + chosenCapsMod.setFBO(true); + } else if(canCreateGLPbuffer(adevice)) { + chosenCapsMod.setPBuffer(true); + } else { + chosenCapsMod.setFBO(false); + chosenCapsMod.setPBuffer(false); + } config.setChosenCapabilities(chosenCapsMod); if(DEBUG) { System.err.println("GLDrawableFactoryImpl.createGLDrawable -> OnscreenDrawable -> Offscreen-Layer: "+target); } - if( ! ( target instanceof SurfaceChangeable ) ) { + if( ! ( target instanceof MutableSurface ) ) { throw new IllegalArgumentException("Passed NativeSurface must implement SurfaceChangeable for offscreen layered surface: "+target); + } + if( ((GLCapabilitiesImmutable)config.getRequestedCapabilities()).isFBO() && isFBOAvailable ) { + // FIXME JAU: Need to revise passed MutableSurface to work w/ FBO .. + final GLDrawableImpl dummyDrawable = createOnscreenDrawableImpl(target); + result = new GLFBODrawableImpl(this, dummyDrawable, target, target.getWidth(), target.getHeight(), 0 /* textureUnit */); + } else { + result = createOffscreenDrawableImpl(target); } - result = createOffscreenDrawableImpl(target); } else if(chosenCaps.isOnscreen()) { // onscreen if(DEBUG) { @@ -158,12 +174,18 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { } else { // offscreen if(DEBUG) { - System.err.println("GLDrawableFactoryImpl.createGLDrawable -> OffScreenDrawable (PBuffer: "+chosenCaps.isPBuffer()+"): "+target); + System.err.println("GLDrawableFactoryImpl.createGLDrawable -> OffScreenDrawable, FBO-chosen(-avail)/PBuffer: "+chosenCaps.isFBO()+"("+isFBOAvailable+")/"+chosenCaps.isPBuffer()+": "+target); } - if( ! ( target instanceof SurfaceChangeable ) ) { + if( ! ( target instanceof MutableSurface ) ) { throw new IllegalArgumentException("Passed NativeSurface must implement SurfaceChangeable for offscreen: "+target); } - result = createOffscreenDrawableImpl(target); + if( ((GLCapabilitiesImmutable)config.getRequestedCapabilities()).isFBO() && isFBOAvailable ) { + // FIXME JAU: Need to revise passed MutableSurface to work w/ FBO .. + final GLDrawableImpl dummyDrawable = createOnscreenDrawableImpl(target); + result = new GLFBODrawableImpl(this, dummyDrawable, target, target.getWidth(), target.getHeight(), 0 /* textureUnit */); + } else { + result = createOffscreenDrawableImpl(target); + } } } finally { adevice.unlock(); @@ -176,43 +198,42 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { //--------------------------------------------------------------------------- // - // Onscreen GLDrawable construction + // Onscreen GLDrawable construction // protected abstract GLDrawableImpl createOnscreenDrawableImpl(NativeSurface target); //--------------------------------------------------------------------------- // - // PBuffer Offscreen GLDrawable construction + // PBuffer Offscreen GLDrawable construction // - + + @Override public abstract boolean canCreateGLPbuffer(AbstractGraphicsDevice device); + @Override public GLPbuffer createGLPbuffer(AbstractGraphicsDevice deviceReq, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser, int width, int height, GLContext shareWith) { - if(height<=0 || height<=0) { - throw new GLException("Width and height of pbuffer must be positive (were (" + - width + ", " + height + "))"); + if(width<=0 || height<=0) { + throw new GLException("initial size must be positive (were (" + width + " x " + height + "))"); } - AbstractGraphicsDevice device = getOrCreateSharedDevice(deviceReq); if(null == device) { throw new GLException("No shared device for requested: "+deviceReq); } - - if (!canCreateGLPbuffer(device)) { - throw new GLException("Pbuffer support not available with device: "+device); + if ( !canCreateGLPbuffer(device) ) { + throw new GLException("Pbuffer not available with device: "+device); } - - GLCapabilitiesImmutable capsChosen = GLGraphicsConfigurationUtil.fixGLPBufferGLCapabilities(capsRequested); + + final GLCapabilitiesImmutable capsChosen = GLGraphicsConfigurationUtil.fixGLPBufferGLCapabilities(capsRequested); GLDrawableImpl drawable = null; device.lock(); try { - drawable = (GLDrawableImpl) createGLDrawable( createOffscreenSurfaceImpl(device, capsChosen, capsRequested, chooser, width, height) ); + drawable = (GLDrawableImpl) createGLDrawable( createMutableSurfaceImpl(device, true, capsChosen, capsRequested, chooser, width, height, null) ); if(null != drawable) { drawable.setRealized(true); } @@ -228,75 +249,155 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { //--------------------------------------------------------------------------- // - // Offscreen GLDrawable construction + // Offscreen GLDrawable construction // - protected abstract GLDrawableImpl createOffscreenDrawableImpl(NativeSurface target) ; - + @Override public GLDrawable createOffscreenDrawable(AbstractGraphicsDevice deviceReq, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser, - int width, - int height) { + int width, int height) { if(width<=0 || height<=0) { - throw new GLException("Width and height of pbuffer must be positive (were (" + - width + ", " + height + "))"); + throw new GLException("initial size must be positive (were (" + width + " x " + height + "))"); } - AbstractGraphicsDevice device = getOrCreateSharedDevice(deviceReq); + final AbstractGraphicsDevice device = getOrCreateSharedDevice(deviceReq); if(null == device) { throw new GLException("No shared device for requested: "+deviceReq); } - GLCapabilitiesImmutable capsChosen = GLGraphicsConfigurationUtil.fixOffScreenGLCapabilities(capsRequested, canCreateGLPbuffer(deviceReq)); - + + if( capsRequested.isFBO() && GLContext.isFBOAvailable(device, capsRequested.getGLProfile()) ) { + device.lock(); + try { + return createFBODrawableImpl(device, capsRequested, chooser, width, height); + } finally { + device.unlock(); + } + } + + final GLCapabilitiesImmutable capsChosen = GLGraphicsConfigurationUtil.fixOffscreenGLCapabilities(capsRequested, false, canCreateGLPbuffer(device)); device.lock(); try { - return createGLDrawable( createOffscreenSurfaceImpl(device, capsChosen, capsRequested, chooser, width, height) ); + return createOffscreenDrawableImpl( createMutableSurfaceImpl(device, true, capsChosen, capsRequested, chooser, width, height, null) ); } finally { device.unlock(); } } - public NativeSurface createOffscreenSurface(AbstractGraphicsDevice deviceReq, - GLCapabilitiesImmutable capsRequested, - GLCapabilitiesChooser chooser, - int width, int height) { - AbstractGraphicsDevice device = getOrCreateSharedDevice(deviceReq); + /** Creates a platform independent offscreen FBO GLDrawable implementation */ + protected GLDrawable createFBODrawableImpl(AbstractGraphicsDevice device, GLCapabilitiesImmutable requestedCaps, GLCapabilitiesChooser chooser, + int initialWidth, int initialHeight) { + final GLCapabilitiesImmutable dummyCaps = GLGraphicsConfigurationUtil.fixOnscreenGLCapabilities(requestedCaps); + final NativeSurface dummySurface = createDummySurfaceImpl(device, true, dummyCaps, null, 64, 64); + final GLDrawableImpl dummyDrawable = createOnscreenDrawableImpl(dummySurface); + + return new GLFBODrawableImpl(this, dummyDrawable, dummySurface, initialWidth, initialHeight, 0 /* textureUnit */); + } + + /** Creates a platform dependent offscreen pbuffer/pixmap GLDrawable implementation */ + protected abstract GLDrawableImpl createOffscreenDrawableImpl(NativeSurface target) ; + + /** + * Creates a mutable {@link ProxySurface} w/o defined surface handle. + *

      + * It's {@link AbstractGraphicsConfiguration} is properly set according to the given {@link GLCapabilitiesImmutable}. + *

      + *

      + * Lifecycle (destruction) of the TBD surface handle shall be handled by the caller. + *

      + * @param device a valid platform dependent target device. + * @param createNewDevice if true a new device instance is created using device details, + * otherwise device instance is used as-is. + * @param capsChosen + * @param capsRequested + * @param chooser the custom chooser, may be null for default + * @param width the initial width + * @param height the initial height + * @param lifecycleHook optional control of the surface's lifecycle + * @return the created {@link MutableSurface} instance w/o defined surface handle + */ + protected abstract ProxySurface createMutableSurfaceImpl(AbstractGraphicsDevice device, boolean createNewDevice, + GLCapabilitiesImmutable capsChosen, + GLCapabilitiesImmutable capsRequested, + GLCapabilitiesChooser chooser, int width, int height, UpstreamSurfaceHook lifecycleHook); + + /** + * A dummy surface is not visible on screen and will not be used to render directly to, + * it maybe on- or offscreen. + *

      + * It is used to allow the creation of a {@link GLDrawable} and {@link GLContext} to query information. + * It also allows creation of framebuffer objects which are used for rendering. + *

      + * @param deviceReq which {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection() connection} denotes the shared device to be used, may be null for the platform's default device. + * @param requestedCaps + * @param chooser the custom chooser, may be null for default + * @param width the initial width + * @param height the initial height + * + * @return the created {@link MutableSurface} instance w/o defined surface handle + */ + public NativeSurface createDummySurface(AbstractGraphicsDevice deviceReq, GLCapabilitiesImmutable requestedCaps, GLCapabilitiesChooser chooser, + int width, int height) { + final AbstractGraphicsDevice device = getOrCreateSharedDevice(deviceReq); if(null == device) { throw new GLException("No shared device for requested: "+deviceReq); } - GLCapabilitiesImmutable capsChosen = GLGraphicsConfigurationUtil.fixOffScreenGLCapabilities(capsRequested, canCreateGLPbuffer(deviceReq)); - device.lock(); try { - return createOffscreenSurfaceImpl(device, capsChosen, capsRequested, chooser, width, height); + return createDummySurfaceImpl(device, true, requestedCaps, chooser, width, height); } finally { device.unlock(); } } - + /** - * creates an offscreen NativeSurface, which must implement SurfaceChangeable as well, - * so the windowing system related implementation is able to set the surface handle. + * A dummy surface is not visible on screen and will not be used to render directly to, + * it maybe on- or offscreen. + *

      + * It is used to allow the creation of a {@link GLDrawable} and {@link GLContext} to query information. + * It also allows creation of framebuffer objects which are used for rendering. + *

      + * @param device a valid platform dependent target device. + * @param createNewDevice if true a new device instance is created using device details, + * otherwise device instance is used as-is. + * @param requestedCaps + * @param chooser the custom chooser, may be null for default + * @param width the initial width + * @param height the initial height + * @return the created {@link MutableSurface} instance w/o defined surface handle */ - protected abstract NativeSurface createOffscreenSurfaceImpl(AbstractGraphicsDevice device, - GLCapabilitiesImmutable capabilities, GLCapabilitiesImmutable capsRequested, - GLCapabilitiesChooser chooser, - int width, int height); + public abstract ProxySurface createDummySurfaceImpl(AbstractGraphicsDevice device, boolean createNewDevice, + GLCapabilitiesImmutable requestedCaps, GLCapabilitiesChooser chooser, int width, int height); - public ProxySurface createProxySurface(AbstractGraphicsDevice device, long windowHandle, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser) { + //--------------------------------------------------------------------------- + // + // ProxySurface (Wrapped pre-existing native surface) construction + // + + @Override + public ProxySurface createProxySurface(AbstractGraphicsDevice deviceReq, int screenIdx, long windowHandle, + GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstream) { + final AbstractGraphicsDevice device = getOrCreateSharedDevice(deviceReq); if(null == device) { - throw new GLException("No shared device for requested: "+device); + throw new GLException("No shared device for requested: "+deviceReq); } device.lock(); try { - return createProxySurfaceImpl(device, windowHandle, capsRequested, chooser); + return createProxySurfaceImpl(device, screenIdx, windowHandle, capsRequested, chooser, upstream); } finally { device.unlock(); } - } - - protected abstract ProxySurface createProxySurfaceImpl(AbstractGraphicsDevice device, long windowHandle, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser); + } + + /** + * Creates a {@link ProxySurface} with a set surface handle. + *

      + * Implementation is also required to allocate it's own {@link AbstractGraphicsDevice} instance. + *

      + * @param upstream TODO + */ + protected abstract ProxySurface createProxySurfaceImpl(AbstractGraphicsDevice deviceReq, int screenIdx, long windowHandle, + GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstream); //--------------------------------------------------------------------------- // @@ -304,7 +405,8 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { // protected abstract GLContext createExternalGLContextImpl(); - + + @Override public GLContext createExternalGLContext() { NativeWindowFactory.getDefaultToolkitLock().lock(); try { @@ -316,6 +418,7 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { protected abstract GLDrawable createExternalGLDrawableImpl(); + @Override public GLDrawable createExternalGLDrawable() { NativeWindowFactory.getDefaultToolkitLock().lock(); try { @@ -398,7 +501,7 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { * normal ahead of time, use resetDisplayGamma(). Throws * IllegalArgumentException if any of the parameters were * out-of-bounds. - * + * * @param gamma The gamma value, typically > 1.0 (default value is * 1.0) * @param brightness The brightness value between -1.0 and 1.0, @@ -484,7 +587,8 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { return; if (gammaShutdownHook == null) { gammaShutdownHook = new Thread(new Runnable() { - public void run() { + @Override + public void run() { synchronized (GLDrawableFactoryImpl.this) { resetGammaRamp(originalGammaRamp); } diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java b/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java index 58a4ac6b4..abf2bf557 100644 --- a/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java +++ b/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java @@ -42,6 +42,7 @@ package jogamp.opengl; import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.nativewindow.NativeSurface; +import javax.media.nativewindow.ProxySurface; import javax.media.opengl.GLCapabilitiesImmutable; import javax.media.opengl.GLContext; import javax.media.opengl.GLDrawable; @@ -75,7 +76,7 @@ public abstract class GLDrawableImpl implements GLDrawable { if( !realized ) { return; // destroyed already } - GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable)surface.getGraphicsConfiguration().getChosenCapabilities(); + final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable)surface.getGraphicsConfiguration().getChosenCapabilities(); if ( caps.getDoubleBuffered() ) { if(!surface.surfaceSwap()) { int lockRes = lockSurface(); // it's recursive, so it's ok within [makeCurrent .. release] @@ -149,6 +150,9 @@ public abstract class GLDrawableImpl implements GLDrawable { realized = realizedArg; AbstractGraphicsDevice aDevice = surface.getGraphicsConfiguration().getScreen().getDevice(); if(realizedArg) { + if(surface instanceof ProxySurface) { + ((ProxySurface)surface).createNotify(); + } if(NativeSurface.LOCK_SURFACE_NOT_READY >= lockSurface()) { throw new GLException("GLDrawableImpl.setRealized(true): Surface not ready (lockSurface)"); } @@ -156,17 +160,21 @@ public abstract class GLDrawableImpl implements GLDrawable { aDevice.lock(); } try { - setRealizedImpl(); if(realizedArg) { + setRealizedImpl(); updateHandle(); } else { destroyHandle(); + setRealizedImpl(); } } finally { if(realizedArg) { unlockSurface(); } else { aDevice.unlock(); + if(surface instanceof ProxySurface) { + ((ProxySurface)surface).destroyNotify(); + } } } } else if(DEBUG) { @@ -175,6 +183,39 @@ public abstract class GLDrawableImpl implements GLDrawable { } protected abstract void setRealizedImpl(); + /** + * Callback for special implementations, allowing GLContext to trigger GL related lifecycle: construct, destroy. + *

      + * If realized is true, the context has just been created and made current. + *

      + *

      + * If realized is false, the context is still current and will be release and destroyed after this method returns. + *

      + *

      + * @see #contextMadeCurrent(GLContext, boolean) + */ + protected void contextRealized(GLContext glc, boolean realized) {} + + /** + * Callback for special implementations, allowing GLContext to trigger GL related lifecycle: makeCurrent, release. + *

      + * Will not be called if {@link #contextRealized(GLContext, boolean)} has been triggered. + *

      + *

      + * If current is true, the context has just been made current. + *

      + *

      + * If current is false, the context is still current and will be release after this method returns. + *

      + * @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..900d6a2a0 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 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,12 +165,13 @@ 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; diff --git a/src/jogl/classes/jogamp/opengl/GLPbufferImpl.java b/src/jogl/classes/jogamp/opengl/GLPbufferImpl.java index a8277fd71..bbc28e283 100644 --- a/src/jogl/classes/jogamp/opengl/GLPbufferImpl.java +++ b/src/jogl/classes/jogamp/opengl/GLPbufferImpl.java @@ -54,8 +54,7 @@ import javax.media.opengl.GLPbuffer; public class GLPbufferImpl extends GLAutoDrawableBase implements GLPbuffer { private int floatMode; - public GLPbufferImpl(GLDrawableImpl pbufferDrawable, - GLContext sharedContext) { + public GLPbufferImpl(GLDrawableImpl pbufferDrawable, GLContext sharedContext) { super(pbufferDrawable, null); // drawable := pbufferDrawable GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) @@ -111,6 +110,11 @@ public class GLPbufferImpl extends GLAutoDrawableBase implements GLPbuffer { // GLAutoDrawable completion // + @Override + public final Object getUpstreamWidget() { + return null; + } + @Override public void destroy() { defaultDestroyOp(); 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)}. + *

      + * We intentionally override a non native EGL device ES profile mapping, + * i.e. this will override/modify an already 'set' X11/WGL/.. mapping. + *

      + * + * @param device + */ + protected void mapCurrentAvailableGLVersion(AbstractGraphicsDevice device) { + mapCurrentAvailableGLVersionImpl(device, ctxMajorVersion, ctxMinorVersion, ctxOptions); + } + + protected static void mapStaticGLESVersion(AbstractGraphicsDevice device, int major) { + int ctp = ( 2 == major ) ? ( GLContext.CTX_PROFILE_ES | GLContext.CTX_IMPL_ES2_COMPAT | GLContext.CTX_IMPL_FBO ) : ( GLContext.CTX_PROFILE_ES ); + mapCurrentAvailableGLVersionImpl(device, major, 0, ctp); + } + private static void mapCurrentAvailableGLVersionImpl(AbstractGraphicsDevice device, int major, int minor, int ctp) { + if( 0 != ( ctp & GLContext.CTX_PROFILE_ES) ) { + // ES1 or ES2 + final int reqMajor = major; + final int reqProfile = GLContext.CTX_PROFILE_ES; + GLContext.mapAvailableGLVersion(device, reqMajor, reqProfile, + major, minor, ctp); + } + } + + protected static boolean getAvailableGLVersionsSet(AbstractGraphicsDevice device) { + return GLContext.getAvailableGLVersionsSet(device); + } + protected static void setAvailableGLVersionsSet(AbstractGraphicsDevice device) { + GLContext.setAvailableGLVersionsSet(device); + } + protected static String toHexString(int hex) { return GLContext.toHexString(hex); } diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDisplayUtil.java b/src/jogl/classes/jogamp/opengl/egl/EGLDisplayUtil.java index 7f10d3bd9..432010f49 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLDisplayUtil.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLDisplayUtil.java @@ -136,7 +136,17 @@ public class EGLDisplayUtil { return res; } - public static final EGLGraphicsDevice.EGLTerminateCallback eglTerminateCallback = new EGLGraphicsDevice.EGLTerminateCallback() { + public static final EGLGraphicsDevice.EGLDisplayLifecycleCallback eglLifecycleCallback = new EGLGraphicsDevice.EGLDisplayLifecycleCallback() { + public long eglGetAndInitDisplay(long nativeDisplayID) { + long eglDisplay = EGLDisplayUtil.eglGetDisplay(nativeDisplayID); + if (eglDisplay == EGL.EGL_NO_DISPLAY) { + throw new GLException("Failed to created EGL display: 0x"+Long.toHexString(nativeDisplayID)+", error 0x"+Integer.toHexString(EGL.eglGetError())); + } + if (!EGLDisplayUtil.eglInitialize(eglDisplay, null, null)) { + throw new GLException("eglInitialize failed"+", error 0x"+Integer.toHexString(EGL.eglGetError())); + } + return eglDisplay; + } public void eglTerminate(long eglDisplayHandle) { EGLDisplayUtil.eglTerminate(eglDisplayHandle); } @@ -148,17 +158,12 @@ public class EGLDisplayUtil { * @param unitID * @return an initialized EGLGraphicsDevice * @throws GLException if {@link EGL#eglGetDisplay(long)} or {@link EGL#eglInitialize(long, int[], int, int[], int)} fails - * @see EGLGraphicsDevice#EGLGraphicsDevice(long, long, String, int, com.jogamp.nativewindow.egl.EGLGraphicsDevice.EGLTerminateCallback) + * @see EGLGraphicsDevice#EGLGraphicsDevice(long, long, String, int, com.jogamp.nativewindow.egl.EGLGraphicsDevice.EGLDisplayLifecycleCallback) */ public static EGLGraphicsDevice eglCreateEGLGraphicsDevice(long nativeDisplayID, String connection, int unitID) { - long eglDisplay = EGLDisplayUtil.eglGetDisplay(nativeDisplayID); - if (eglDisplay == EGL.EGL_NO_DISPLAY) { - throw new GLException("Failed to created EGL display: 0x"+Long.toHexString(nativeDisplayID)+", error 0x"+Integer.toHexString(EGL.eglGetError())); - } - if (!EGLDisplayUtil.eglInitialize(eglDisplay, null, null)) { - throw new GLException("eglInitialize failed"+", error 0x"+Integer.toHexString(EGL.eglGetError())); - } - return new EGLGraphicsDevice(nativeDisplayID, eglDisplay, connection, unitID, eglTerminateCallback); + final EGLGraphicsDevice eglDisplay = new EGLGraphicsDevice(nativeDisplayID, 0, connection, unitID, eglLifecycleCallback); + eglDisplay.open(); + return eglDisplay; } /** @@ -189,6 +194,6 @@ public class EGLDisplayUtil { throw new GLException("eglInitialize failed"+", error 0x"+Integer.toHexString(EGL.eglGetError())); } final AbstractGraphicsDevice adevice = surface.getGraphicsConfiguration().getScreen().getDevice(); - return new EGLGraphicsDevice(nativeDisplayID, eglDisplay, adevice.getConnection(), adevice.getUnitID(), eglTerminateCallback); + return new EGLGraphicsDevice(nativeDisplayID, eglDisplay, adevice.getConnection(), adevice.getUnitID(), eglLifecycleCallback); } } diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java b/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java index d777c4f04..383b61f88 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java @@ -36,82 +36,65 @@ package jogamp.opengl.egl; -import jogamp.opengl.GLDynamicLookupHelper; -import jogamp.opengl.GLDrawableImpl; +import javax.media.nativewindow.MutableSurface; +import javax.media.nativewindow.NativeSurface; +import javax.media.nativewindow.NativeWindow; +import javax.media.nativewindow.ProxySurface; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLException; -import javax.media.nativewindow.*; -import javax.media.nativewindow.VisualIDHolder.VIDType; -import javax.media.opengl.*; +import jogamp.opengl.GLDrawableImpl; +import jogamp.opengl.GLDynamicLookupHelper; -import com.jogamp.nativewindow.egl.*; +import com.jogamp.nativewindow.egl.EGLGraphicsDevice; public abstract class EGLDrawable extends GLDrawableImpl { - private boolean ownEGLDisplay = false; // for destruction private boolean ownEGLSurface = false; // for destruction - private EGLGraphicsConfiguration eglConfig; - private EGLGraphicsDevice eglDevice; - private long eglSurface; - protected EGLDrawable(EGLDrawableFactory factory, - NativeSurface component) throws GLException { + protected EGLDrawable(EGLDrawableFactory factory, NativeSurface component) throws GLException { super(factory, component, false); - eglSurface=EGL.EGL_NO_SURFACE; - eglDevice=null; - } - - public final long getDisplay() { - return null != eglDevice ? eglDevice.getHandle() : 0; - } - - @Override - public final long getHandle() { - return eglSurface; - } - - public final EGLGraphicsConfiguration getGraphicsConfiguration() { - return eglConfig; - } - - @Override - public final GLCapabilitiesImmutable getChosenGLCapabilities() { - return (null==eglConfig)?super.getChosenGLCapabilities():(GLCapabilitiesImmutable)eglConfig.getChosenCapabilities(); } @Override public abstract GLContext createContext(GLContext shareWith); - protected abstract long createSurface(long eglDpy, long eglNativeCfg, long surfaceHandle); + protected abstract long createSurface(EGLGraphicsConfiguration config, long nativeSurfaceHandle); private final void recreateSurface() { - // create a new EGLSurface .. - if(EGL.EGL_NO_SURFACE!=eglSurface) { - EGL.eglDestroySurface(eglDevice.getHandle(), eglSurface); - } - + final EGLGraphicsConfiguration eglConfig = (EGLGraphicsConfiguration) surface.getGraphicsConfiguration(); + final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) eglConfig.getScreen().getDevice(); if(DEBUG) { - System.err.println(getThreadName() + ": createSurface using "+eglDevice+", "+eglConfig); + System.err.println(getThreadName() + ": createSurface using "+eglConfig); + } + if( EGL.EGL_NO_SURFACE != surface.getSurfaceHandle() ) { + EGL.eglDestroySurface(eglDevice.getHandle(), surface.getSurfaceHandle()); } - - eglSurface = createSurface(eglDevice.getHandle(), eglConfig.getNativeConfig(), surface.getSurfaceHandle()); - int eglError0 = EGL.EGL_SUCCESS; + + final EGLUpstreamSurfaceHook upstreamHook = (EGLUpstreamSurfaceHook) ((ProxySurface)surface).getUpstreamSurfaceHook(); + final NativeSurface upstreamSurface = upstreamHook.getUpstreamSurface(); + long eglSurface = createSurface(eglConfig, upstreamSurface.getSurfaceHandle()); + + int eglError0; if (EGL.EGL_NO_SURFACE == eglSurface) { eglError0 = EGL.eglGetError(); if(EGL.EGL_BAD_NATIVE_WINDOW == eglError0) { // Try window handle if available and differs (Windows HDC / HWND). // ANGLE impl. required HWND on Windows. - if(surface instanceof NativeWindow) { - final NativeWindow nw = (NativeWindow) surface; + if(upstreamSurface instanceof NativeWindow) { + final NativeWindow nw = (NativeWindow) upstreamSurface; if(nw.getWindowHandle() != nw.getSurfaceHandle()) { if(DEBUG) { System.err.println(getThreadName() + ": Info: Creation of window surface w/ surface handle failed: "+eglConfig+", error "+toHexString(eglError0)+", retry w/ windowHandle"); } - eglSurface = createSurface(eglDevice.getHandle(), eglConfig.getNativeConfig(), nw.getWindowHandle()); + eglSurface = createSurface(eglConfig, nw.getWindowHandle()); if (EGL.EGL_NO_SURFACE == eglSurface) { eglError0 = EGL.eglGetError(); } } } } + } else { + eglError0 = EGL.EGL_SUCCESS; } if (EGL.EGL_NO_SURFACE == eglSurface) { throw new GLException("Creation of window surface failed: "+eglConfig+", "+surface+", error "+toHexString(eglError0)); @@ -120,6 +103,8 @@ public abstract class EGLDrawable extends GLDrawableImpl { if(DEBUG) { System.err.println(getThreadName() + ": setSurface using component: handle "+toHexString(surface.getSurfaceHandle())+" -> "+toHexString(eglSurface)); } + + ((MutableSurface)surface).setSurfaceHandle(eglSurface); } @Override @@ -131,123 +116,71 @@ public abstract class EGLDrawable extends GLDrawableImpl { @Override protected final void setRealizedImpl() { + final EGLGraphicsConfiguration eglConfig = (EGLGraphicsConfiguration) surface.getGraphicsConfiguration(); + final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) eglConfig.getScreen().getDevice(); if (realized) { - AbstractGraphicsConfiguration aConfig = surface.getGraphicsConfiguration(); - AbstractGraphicsDevice aDevice = aConfig.getScreen().getDevice(); - if(aDevice instanceof EGLGraphicsDevice) { + final long eglDisplayHandle = eglDevice.getHandle(); + if (EGL.EGL_NO_DISPLAY == eglDisplayHandle) { + throw new GLException("Invalid EGL display in EGLGraphicsDevice "+eglDevice); + } + int[] tmp = new int[1]; + boolean eglSurfaceValid = 0 != surface.getSurfaceHandle(); + if(eglSurfaceValid) { + eglSurfaceValid = EGL.eglQuerySurface(eglDisplayHandle, surface.getSurfaceHandle(), EGL.EGL_CONFIG_ID, tmp, 0); + if(!eglSurfaceValid) { + if(DEBUG) { + System.err.println(getThreadName() + ": EGLDrawable.setRealizedImpl eglQuerySuface failed: "+toHexString(EGL.eglGetError())+", "+surface); + } + } + } + if(eglSurfaceValid) { + // surface holds valid EGLSurface if(DEBUG) { - System.err.println(getThreadName() + ": EGLDrawable.setRealized(true): using existing EGL config - START"); + System.err.println(getThreadName() + ": EGLDrawable.setRealizedImpl re-using component's EGLSurface: handle "+toHexString(surface.getSurfaceHandle())); + } + ownEGLSurface=false; + } else { + // EGLSurface is ours - subsequent updateHandle() will issue recreateSurface(); + // However .. let's validate the surface object first + if( ! (surface instanceof ProxySurface) ) { + throw new InternalError("surface not ProxySurface: "+surface.getClass().getName()+", "+surface); } - // just fetch the data .. trust but verify .. - ownEGLDisplay = false; - eglDevice = (EGLGraphicsDevice) aDevice; - if (eglDevice.getHandle() == EGL.EGL_NO_DISPLAY) { - throw new GLException("Invalid EGL display in EGLGraphicsDevice "+eglDevice); + final ProxySurface.UpstreamSurfaceHook upstreamHook = ((ProxySurface)surface).getUpstreamSurfaceHook(); + if( null == upstreamHook ) { + throw new InternalError("null upstreamHook of: "+surface); } - if(aConfig instanceof EGLGraphicsConfiguration) { - eglConfig = (EGLGraphicsConfiguration) aConfig; // done .. - if (null == eglConfig) { - throw new GLException("Null EGLGraphicsConfiguration from "+aConfig); - } - - int[] tmp = new int[1]; - if ( 0 != surface.getSurfaceHandle() && - EGL.eglQuerySurface(eglDevice.getHandle(), surface.getSurfaceHandle(), EGL.EGL_CONFIG_ID, tmp, 0) ) { - // surface holds static EGLSurface - eglSurface = surface.getSurfaceHandle(); - if(DEBUG) { - System.err.println(getThreadName() + ": setSurface re-using component's EGLSurface: handle "+toHexString(eglSurface)); - } - ownEGLSurface=false; - } else { - // EGLSurface is ours - subsequent updateHandle() will issue recreateSurface(); - ownEGLSurface=true; - } - } else { - throw new GLException("EGLGraphicsDevice hold by non EGLGraphicsConfiguration: "+aConfig); + if( ! (upstreamHook instanceof EGLUpstreamSurfaceHook) ) { + throw new InternalError("upstreamHook not EGLUpstreamSurfaceHook: Surface: "+surface.getClass().getName()+", "+surface+"; UpstreamHook: "+upstreamHook.getClass().getName()+", "+upstreamHook); } - } else { - if(DEBUG) { - System.err.println(getThreadName() + ": EGLDrawable.setRealized(true): creating new EGL config - START"); + if( null == ((EGLUpstreamSurfaceHook)upstreamHook).getUpstreamSurface() ) { + throw new InternalError("null upstream surface"); } - // create a new EGL config .. - ownEGLDisplay=true; - // EGLSurface is ours .. ownEGLSurface=true; - - eglDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(surface, true); - AbstractGraphicsScreen eglScreen = new DefaultGraphicsScreen(eglDevice, aConfig.getScreen().getIndex()); - final GLCapabilitiesImmutable capsRequested = (GLCapabilitiesImmutable) aConfig.getRequestedCapabilities(); - if(aConfig instanceof EGLGraphicsConfiguration) { - final EGLGLCapabilities capsChosen = (EGLGLCapabilities) aConfig.getChosenCapabilities(); - if(0 == capsChosen.getEGLConfig()) { - // 'refresh' the native EGLConfig handle - capsChosen.setEGLConfig(EGLGraphicsConfiguration.EGLConfigId2EGLConfig(eglDevice.getHandle(), capsChosen.getEGLConfigID())); - if(0 == capsChosen.getEGLConfig()) { - throw new GLException("Refreshing native EGLConfig handle failed: "+capsChosen+" of "+aConfig); - } - } - eglConfig = new EGLGraphicsConfiguration(eglScreen, capsChosen, capsRequested, null); - if(DEBUG) { - System.err.println(getThreadName() + ": Reusing chosenCaps: "+eglConfig); - } - } else { - eglConfig = EGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic( - capsRequested, capsRequested, null, eglScreen, aConfig.getVisualID(VIDType.NATIVE), false); - - if (null == eglConfig) { - throw new GLException("Couldn't create EGLGraphicsConfiguration from "+eglScreen); - } else if(DEBUG) { - System.err.println(getThreadName() + ": Chosen eglConfig: "+eglConfig); - } + if(DEBUG) { + System.err.println(getThreadName() + ": EGLDrawable.setRealizedImpl owning EGLSurface"); } - // subsequent updateHandle() will issue recreateSurface(); - } - if(DEBUG) { - System.err.println(getThreadName() + ": EGLDrawable.setRealized(true): END: ownDisplay "+ownEGLDisplay+", ownSurface "+ownEGLSurface); } - } else if (ownEGLSurface && eglSurface != EGL.EGL_NO_SURFACE) { + } else if (ownEGLSurface && surface.getSurfaceHandle() != EGL.EGL_NO_SURFACE) { if(DEBUG) { - System.err.println(getThreadName() + ": EGLDrawable.setRealized(false): ownDisplay "+ownEGLDisplay+", ownSurface "+ownEGLSurface+", "+eglDevice+", eglSurface: "+toHexString(eglSurface)); + System.err.println(getThreadName() + ": EGLDrawable.setRealized(false): ownSurface "+ownEGLSurface+", "+eglDevice+", eglSurface: "+toHexString(surface.getSurfaceHandle())); } // Destroy the window surface - if (!EGL.eglDestroySurface(eglDevice.getHandle(), eglSurface)) { + if (!EGL.eglDestroySurface(eglDevice.getHandle(), surface.getSurfaceHandle())) { throw new GLException("Error destroying window surface (eglDestroySurface)"); } - eglSurface = EGL.EGL_NO_SURFACE; - eglConfig=null; - eglDevice.close(); - eglDevice=null; + ((MutableSurface)surface).setSurfaceHandle(EGL.EGL_NO_SURFACE); } } @Override protected final void swapBuffersImpl() { + final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) surface.getGraphicsConfiguration().getScreen().getDevice(); // single-buffer is already filtered out @ GLDrawableImpl#swapBuffers() - if(!EGL.eglSwapBuffers(eglDevice.getHandle(), eglSurface)) { + if(!EGL.eglSwapBuffers(eglDevice.getHandle(), surface.getSurfaceHandle())) { throw new GLException("Error swapping buffers, eglError "+toHexString(EGL.eglGetError())+", "+this); } } - /** - * Surface not realizes yet (onscreen) .. Quering EGL surface size only makes sense for external drawable. - * Leave it here for later impl. of an EGLExternalDrawable. - public int getWidth() { - int[] tmp = new int[1]; - if (!EGL.eglQuerySurface(eglDisplay, eglSurface, EGL.EGL_WIDTH, tmp, 0)) { - throw new GLException("Error querying surface width, eglError "+toHexString(EGL.eglGetError())); - } - return tmp[0]; - } - - public int getHeight() { - int[] tmp = new int[1]; - if (!EGL.eglQuerySurface(eglDisplay, eglSurface, EGL.EGL_HEIGHT, tmp, 0)) { - throw new GLException("Error querying surface height, eglError "+toHexString(EGL.eglGetError())); - } - return tmp[0]; - } */ - @Override public GLDynamicLookupHelper getGLDynamicLookupHelper() { if (getGLProfile().usesNativeGLES2()) { @@ -263,10 +196,9 @@ public abstract class EGLDrawable extends GLDrawableImpl { public String toString() { return getClass().getName()+"[realized "+isRealized()+ ",\n\tfactory "+getFactory()+ - ",\n\tdevice "+eglDevice+ ",\n\tsurface "+getNativeSurface()+ - ",\n\teglSurface "+toHexString(eglSurface)+ - ",\n\teglConfig "+eglConfig+ + ",\n\teglSurface "+toHexString(surface.getSurfaceHandle())+ + ",\n\teglConfig "+surface.getGraphicsConfiguration()+ ",\n\trequested "+getRequestedGLCapabilities()+ ",\n\tchosen "+getChosenGLCapabilities()+"]"; } diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java index f4fa1f13f..c848e3e5c 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java @@ -46,21 +46,29 @@ import javax.media.nativewindow.AbstractGraphicsConfiguration; import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.nativewindow.AbstractGraphicsScreen; import javax.media.nativewindow.DefaultGraphicsScreen; +import javax.media.nativewindow.MutableSurface; import javax.media.nativewindow.NativeSurface; import javax.media.nativewindow.NativeWindowFactory; import javax.media.nativewindow.ProxySurface; +import javax.media.nativewindow.ProxySurface.UpstreamSurfaceHook; +import javax.media.nativewindow.VisualIDHolder.VIDType; import javax.media.nativewindow.VisualIDHolder; +import javax.media.opengl.GL; +import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLCapabilitiesChooser; import javax.media.opengl.GLCapabilitiesImmutable; import javax.media.opengl.GLContext; import javax.media.opengl.GLDrawable; +import javax.media.opengl.GLDrawableFactory; import javax.media.opengl.GLException; import javax.media.opengl.GLProfile; import javax.media.opengl.GLProfile.ShutdownType; +import jogamp.opengl.Debug; import jogamp.opengl.GLDrawableFactoryImpl; import jogamp.opengl.GLDrawableImpl; import jogamp.opengl.GLDynamicLookupHelper; +import jogamp.opengl.GLGraphicsConfigurationUtil; import com.jogamp.common.JogampRuntimeException; import com.jogamp.common.os.Platform; @@ -69,6 +77,9 @@ import com.jogamp.nativewindow.WrappedSurface; import com.jogamp.nativewindow.egl.EGLGraphicsDevice; public class EGLDrawableFactory extends GLDrawableFactoryImpl { + /* package */ static final boolean QUERY_EGL_ES = !Debug.isPropertyDefined("jogl.debug.EGLDrawableFactory.DontQuery", true); + /* package */ static final boolean QUERY_EGL_ES_NATIVE_TK = Debug.isPropertyDefined("jogl.debug.EGLDrawableFactory.QueryNativeTK", true); + private static GLDynamicLookupHelper eglES1DynamicLookupHelper = null; private static GLDynamicLookupHelper eglES2DynamicLookupHelper = null; private static boolean isANGLE = false; @@ -231,7 +242,7 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { // final EGLContext getContextES1() { return contextES1; } // final EGLContext getContextES2() { return contextES2; } final boolean wasES1ContextAvailable() { return wasES1ContextCreated; } - final boolean wasES2ContextAvailable() { return wasES2ContextCreated; } + final boolean wasES2ContextAvailable() { return wasES2ContextCreated; } } @Override @@ -245,35 +256,98 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { return null!=eglES2DynamicLookupHelper || null!=eglES1DynamicLookupHelper; } - /** - private boolean isEGLContextAvailable(EGLGraphicsDevice sharedDevice, String profile) { - boolean madeCurrent = false; - final GLCapabilities caps = new GLCapabilities(GLProfile.get(profile)); - caps.setRedBits(5); caps.setGreenBits(5); caps.setBlueBits(5); caps.setAlphaBits(0); - caps.setDoubleBuffered(false); - caps.setOnscreen(false); - caps.setPBuffer(true); - final EGLDrawable drawable = (EGLDrawable) createGLDrawable( createOffscreenSurfaceImpl(sharedDevice, caps, caps, null, 64, 64) ); - if(null!=drawable) { + private boolean isEGLContextAvailable(AbstractGraphicsDevice adevice, EGLGraphicsDevice sharedEGLDevice, String profileString) { + if( !GLProfile.isAvailable(adevice, profileString) ) { + return false; + } + final GLProfile glp = GLProfile.get(adevice, profileString) ; + final GLDrawableFactoryImpl desktopFactory = (GLDrawableFactoryImpl) GLDrawableFactory.getDesktopFactory(); + EGLGraphicsDevice eglDevice = null; + NativeSurface surface = null; + ProxySurface upstreamSurface = null; // X11, GLX, .. + boolean success = false; + boolean deviceFromUpstreamSurface = false; + try { + final GLCapabilities caps = new GLCapabilities(glp); + caps.setRedBits(5); caps.setGreenBits(5); caps.setBlueBits(5); caps.setAlphaBits(0); + if(adevice instanceof EGLGraphicsDevice || null == desktopFactory || !QUERY_EGL_ES_NATIVE_TK) { + eglDevice = sharedEGLDevice; // reuse + surface = createDummySurfaceImpl(eglDevice, false, caps, null, 64, 64); // egl pbuffer offscreen + upstreamSurface = (ProxySurface)surface; + upstreamSurface.createNotify(); + deviceFromUpstreamSurface = false; + } else { + surface = desktopFactory.createDummySurface(adevice, caps, null, 64, 64); // X11, WGL, .. dummy window + upstreamSurface = ( surface instanceof ProxySurface ) ? (ProxySurface)surface : null ; + if(null != upstreamSurface) { + upstreamSurface.createNotify(); + } + eglDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(surface, true); + deviceFromUpstreamSurface = true; + } + + final EGLDrawable drawable = (EGLDrawable) createOnscreenDrawableImpl ( surface ); + drawable.setRealized(true); final EGLContext context = (EGLContext) drawable.createContext(null); if (null != context) { - context.setSynchronized(true); try { context.makeCurrent(); // could cause exception - madeCurrent = context.isCurrent(); + success = context.isCurrent(); + if(success) { + final String glVersion = context.getGL().glGetString(GL.GL_VERSION); + if(null == glVersion) { + // Oops .. something is wrong + if(DEBUG) { + System.err.println("EGLDrawableFactory.isEGLContextAvailable: "+eglDevice+", "+context.getGLVersion()+" - VERSION is null, dropping availability!"); + } + success = false; + } + } + if(success) { + context.mapCurrentAvailableGLVersion(eglDevice); + if(eglDevice != adevice) { + context.mapCurrentAvailableGLVersion(adevice); + } + } } catch (GLException gle) { if (DEBUG) { - System.err.println("EGLDrawableFactory.createShared: INFO: makeCurrent failed"); + System.err.println("EGLDrawableFactory.createShared: INFO: context create/makeCurrent failed"); gle.printStackTrace(); } } finally { context.destroy(); } } - drawable.destroy(); + drawable.setRealized(false); + } catch (Throwable t) { + if(DEBUG) { + System.err.println("Catched Exception:"); + t.printStackTrace(); + } + success = false; + } finally { + if(eglDevice == sharedEGLDevice) { + if(null != upstreamSurface) { + upstreamSurface.destroyNotify(); + } + } else if( deviceFromUpstreamSurface ) { + if(null != eglDevice) { + eglDevice.close(); + } + if(null != upstreamSurface) { + upstreamSurface.destroyNotify(); + } + } else { + if(null != upstreamSurface) { + upstreamSurface.destroyNotify(); + } + if(null != eglDevice) { + eglDevice.close(); + } + } } - return madeCurrent; - } */ + return success; + } /* package */ SharedResource getOrCreateEGLSharedResource(AbstractGraphicsDevice adevice) { if(null == eglES1DynamicLookupHelper && null == eglES2DynamicLookupHelper) { @@ -285,18 +359,41 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { sr = sharedMap.get(connection); } if(null==sr) { - final EGLGraphicsDevice sharedDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(EGL.EGL_DEFAULT_DISPLAY, connection, adevice.getUnitID()); + final boolean madeCurrentES1; + final boolean madeCurrentES2; + final EGLGraphicsDevice sharedDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(EGL.EGL_DEFAULT_DISPLAY, AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT); - // final boolean madeCurrentES1 = isEGLContextAvailable(sharedDevice, GLProfile.GLES1); - // final boolean madeCurrentES2 = isEGLContextAvailable(sharedDevice, GLProfile.GLES2); - final boolean madeCurrentES1 = true; // FIXME - final boolean madeCurrentES2 = true; // FIXME + if(QUERY_EGL_ES) { + madeCurrentES1 = isEGLContextAvailable(adevice, sharedDevice, GLProfile.GLES1); + madeCurrentES2 = isEGLContextAvailable(adevice, sharedDevice, GLProfile.GLES2); + } else { + madeCurrentES1 = true; + madeCurrentES2 = true; + EGLContext.mapStaticGLESVersion(sharedDevice, 1); + if(sharedDevice != adevice) { + EGLContext.mapStaticGLESVersion(adevice, 1); + } + EGLContext.mapStaticGLESVersion(sharedDevice, 2); + if(sharedDevice != adevice) { + EGLContext.mapStaticGLESVersion(adevice, 2); + } + } + + if( !EGLContext.getAvailableGLVersionsSet(adevice) ) { + // Even though we override the non EGL native mapping intentionally, + // avoid exception due to double 'set' - carefull exception of the rule. + EGLContext.setAvailableGLVersionsSet(adevice); + } sr = new SharedResource(sharedDevice, madeCurrentES1, madeCurrentES2); + synchronized(sharedMap) { sharedMap.put(connection, sr); + if(adevice != sharedDevice) { + sharedMap.put(sharedDevice.getConnection(), sr); + } } if (DEBUG) { - System.err.println("EGLDrawableFactory.createShared: device: " + sharedDevice); + System.err.println("EGLDrawableFactory.createShared: devices: queried " + QUERY_EGL_ES + "[nativeTK "+QUERY_EGL_ES_NATIVE_TK+"], " + adevice + ", " + sharedDevice); System.err.println("EGLDrawableFactory.createShared: context ES1: " + madeCurrentES1); System.err.println("EGLDrawableFactory.createShared: context ES2: " + madeCurrentES2); } @@ -367,8 +464,51 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { if (target == null) { throw new IllegalArgumentException("Null target"); } - return new EGLOnscreenDrawable(this, target); + return new EGLOnscreenDrawable(this, getEGLSurface(target)); + } + + protected static NativeSurface getEGLSurface(NativeSurface surface) { + AbstractGraphicsConfiguration aConfig = surface.getGraphicsConfiguration(); + AbstractGraphicsDevice aDevice = aConfig.getScreen().getDevice(); + if( aDevice instanceof EGLGraphicsDevice && aConfig instanceof EGLGraphicsConfiguration ) { + // already in native EGL format + if(DEBUG) { + System.err.println(getThreadName() + ": getEGLSurface - already in EGL format - use as-is: "+aConfig); + } + return surface; + } + // create EGL instance out of platform native types + final EGLGraphicsDevice eglDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(surface, true); + final AbstractGraphicsScreen eglScreen = new DefaultGraphicsScreen(eglDevice, aConfig.getScreen().getIndex()); + final GLCapabilitiesImmutable capsRequested = (GLCapabilitiesImmutable) aConfig.getRequestedCapabilities(); + final EGLGraphicsConfiguration eglConfig; + if( aConfig instanceof EGLGraphicsConfiguration ) { + // Config is already in EGL type - reuse .. + final EGLGLCapabilities capsChosen = (EGLGLCapabilities) aConfig.getChosenCapabilities(); + if( 0 == capsChosen.getEGLConfig() ) { + // 'refresh' the native EGLConfig handle + capsChosen.setEGLConfig(EGLGraphicsConfiguration.EGLConfigId2EGLConfig(eglDevice.getHandle(), capsChosen.getEGLConfigID())); + if( 0 == capsChosen.getEGLConfig() ) { + throw new GLException("Refreshing native EGLConfig handle failed: "+capsChosen+" of "+aConfig); + } + } + eglConfig = new EGLGraphicsConfiguration(eglScreen, capsChosen, capsRequested, null); + if(DEBUG) { + System.err.println(getThreadName() + ": getEGLSurface - Reusing chosenCaps: "+eglConfig); + } + } else { + eglConfig = EGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic( + capsRequested, capsRequested, null, eglScreen, aConfig.getVisualID(VIDType.NATIVE), false); + + if (null == eglConfig) { + throw new GLException("Couldn't create EGLGraphicsConfiguration from "+eglScreen); + } else if(DEBUG) { + System.err.println(getThreadName() + ": getEGLSurface - Chosen eglConfig: "+eglConfig); + } + } + return new WrappedSurface(eglConfig, EGL.EGL_NO_SURFACE, surface.getWidth(), surface.getHeight(), new EGLUpstreamSurfaceHook(surface)); } + static String getThreadName() { return Thread.currentThread().getName(); } @Override protected GLDrawableImpl createOffscreenDrawableImpl(NativeSurface target) { @@ -390,22 +530,115 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { } @Override - protected NativeSurface createOffscreenSurfaceImpl(AbstractGraphicsDevice deviceReq, GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser, int width, int height) { - final EGLGraphicsDevice eglDeviceReq = (EGLGraphicsDevice) deviceReq; - final EGLGraphicsDevice device = EGLDisplayUtil.eglCreateEGLGraphicsDevice(eglDeviceReq.getNativeDisplayID(), deviceReq.getConnection(), deviceReq.getUnitID()); - WrappedSurface ns = new WrappedSurface(EGLGraphicsConfigurationFactory.createOffscreenGraphicsConfiguration(device, capsChosen, capsRequested, chooser)); - ns.surfaceSizeChanged(width, height); - return ns; + protected ProxySurface createMutableSurfaceImpl(AbstractGraphicsDevice deviceReq, boolean createNewDevice, + GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsRequested, + GLCapabilitiesChooser chooser, int width, int height, UpstreamSurfaceHook lifecycleHook) { + final EGLGraphicsDevice device; + if(createNewDevice) { + final EGLGraphicsDevice eglDeviceReq = (EGLGraphicsDevice) deviceReq; + device = EGLDisplayUtil.eglCreateEGLGraphicsDevice(eglDeviceReq.getNativeDisplayID(), deviceReq.getConnection(), deviceReq.getUnitID()); + } else { + device = (EGLGraphicsDevice) deviceReq; + } + final DefaultGraphicsScreen screen = new DefaultGraphicsScreen(device, 0); + final EGLGraphicsConfiguration config = EGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsChosen, capsRequested, chooser, screen, VisualIDHolder.VID_UNDEFINED, false); + if(null == config) { + throw new GLException("Choosing GraphicsConfiguration failed w/ "+capsChosen+" on "+screen); + } + return new WrappedSurface(config, 0, width, height, lifecycleHook); + } + + @Override + public final ProxySurface createDummySurfaceImpl(AbstractGraphicsDevice deviceReq, boolean createNewDevice, + GLCapabilitiesImmutable requestedCaps, GLCapabilitiesChooser chooser, int width, int height) { + final GLCapabilitiesImmutable chosenCaps = GLGraphicsConfigurationUtil.fixOffscreenGLCapabilities(requestedCaps, false, canCreateGLPbuffer(deviceReq)); + return createMutableSurfaceImpl(deviceReq, createNewDevice, chosenCaps, requestedCaps, chooser, width, height, dummySurfaceLifecycleHook); + } + private static final ProxySurface.UpstreamSurfaceHook dummySurfaceLifecycleHook = new ProxySurface.UpstreamSurfaceHook() { + @Override + public final void create(ProxySurface s) { + if( EGL.EGL_NO_SURFACE == s.getSurfaceHandle() ) { + final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) s.getGraphicsConfiguration().getScreen().getDevice(); + if(0 == eglDevice.getHandle()) { + eglDevice.open(); + s.setImplBitfield(ProxySurface.OWN_DEVICE); + } + createPBufferSurfaceImpl(s, false); + if(DEBUG) { + System.err.println("EGLDrawableFactory.dummySurfaceLifecycleHook.create: "+s); + } + } + } + @Override + public final void destroy(ProxySurface s) { + if( EGL.EGL_NO_SURFACE != s.getSurfaceHandle() ) { + final EGLGraphicsConfiguration config = (EGLGraphicsConfiguration) s.getGraphicsConfiguration(); + final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) config.getScreen().getDevice(); + EGL.eglDestroySurface(eglDevice.getHandle(), s.getSurfaceHandle()); + s.setSurfaceHandle(EGL.EGL_NO_SURFACE); + if( 0 != ( ProxySurface.OWN_DEVICE & s.getImplBitfield() ) ) { + eglDevice.close(); + } + if(DEBUG) { + System.err.println("EGLDrawableFactory.dummySurfaceLifecycleHook.create: "+s); + } + } + } + @Override + public final int getWidth(ProxySurface s) { + return s.initialWidth; + } + @Override + public final int getHeight(ProxySurface s) { + return s.initialHeight; + } + @Override + public String toString() { + return "EGLSurfaceLifecycleHook[]"; + } + + }; + + /** + * @param ms {@link MutableSurface} which dimensions and config are being used to create the pbuffer surface. + * It will also hold the resulting pbuffer surface handle. + * @param useTexture + * @return the passed {@link MutableSurface} which now has the EGL pbuffer surface set as it's handle + */ + protected static MutableSurface createPBufferSurfaceImpl(MutableSurface ms, boolean useTexture) { + final EGLGraphicsConfiguration config = (EGLGraphicsConfiguration) ms.getGraphicsConfiguration(); + final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) config.getScreen().getDevice(); + final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) config.getChosenCapabilities(); + final int texFormat; + + if(useTexture) { + texFormat = caps.getAlphaBits() > 0 ? EGL.EGL_TEXTURE_RGBA : EGL.EGL_TEXTURE_RGB ; + } else { + texFormat = EGL.EGL_NO_TEXTURE; + } + + if (DEBUG) { + System.out.println("Pbuffer config: " + config); + } + + final int[] attrs = EGLGraphicsConfiguration.CreatePBufferSurfaceAttribList(ms.getWidth(), ms.getHeight(), texFormat); + final long surf = EGL.eglCreatePbufferSurface(eglDevice.getHandle(), config.getNativeConfig(), attrs, 0); + if (EGL.EGL_NO_SURFACE==surf) { + throw new GLException("Creation of window surface (eglCreatePbufferSurface) failed, dim "+ms.getWidth()+"x"+ms.getHeight()+", error 0x"+Integer.toHexString(EGL.eglGetError())); + } else if(DEBUG) { + System.err.println("PBuffer setSurface result: eglSurface 0x"+Long.toHexString(surf)); + } + ms.setSurfaceHandle(surf); + return ms; } @Override - protected ProxySurface createProxySurfaceImpl(AbstractGraphicsDevice adevice, long windowHandle, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser) { - // FIXME device/windowHandle -> screen ?! - EGLGraphicsDevice device = (EGLGraphicsDevice) adevice; - DefaultGraphicsScreen screen = new DefaultGraphicsScreen(device, 0); - EGLGraphicsConfiguration cfg = EGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsRequested, capsRequested, chooser, screen, VisualIDHolder.VID_UNDEFINED, false); - WrappedSurface ns = new WrappedSurface(cfg, windowHandle); - return ns; + protected ProxySurface createProxySurfaceImpl(AbstractGraphicsDevice deviceReq, int screenIdx, long windowHandle, GLCapabilitiesImmutable capsRequested, GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstream) { + final EGLGraphicsDevice eglDeviceReq = (EGLGraphicsDevice) deviceReq; + final EGLGraphicsDevice device = EGLDisplayUtil.eglCreateEGLGraphicsDevice(eglDeviceReq.getNativeDisplayID(), deviceReq.getConnection(), deviceReq.getUnitID()); + final DefaultGraphicsScreen screen = new DefaultGraphicsScreen(device, screenIdx); + final EGLGraphicsConfiguration cfg = EGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsRequested, capsRequested, chooser, screen, VisualIDHolder.VID_UNDEFINED, false); + return new WrappedSurface(cfg, windowHandle, 0, 0, upstream); } @Override diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java b/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java index 56e7a4d22..214b36493 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java @@ -151,7 +151,7 @@ public class EGLGraphicsConfiguration extends MutableGraphicsConfiguration imple public static EGLGLCapabilities EGLConfig2Capabilities(GLProfile glp, long display, long config, boolean relaxed, boolean onscreen, boolean usePBuffer, boolean forceTransparentFlag) { List bucket = new ArrayList(); - 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) ) { diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfigurationFactory.java b/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfigurationFactory.java index 809e2b688..6be9cb547 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; @@ -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 availableCaps = null; IntBuffer numConfigs = Buffers.newDirectIntBuffer(1); @@ -236,11 +239,9 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact 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(eglDevice.getHandle(), capsChosen, capsReq, chooser, absScreen, nativeVisualID, forceTransparentFlag); if(null==res) { @@ -251,13 +252,18 @@ 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.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); } @@ -266,11 +272,16 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact 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); } @@ -279,13 +290,18 @@ public class EGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFact if(null==res) { // // rgb565 - d16, s4 - fixedCaps = new GLCapabilities(glp); + final GLCapabilities fixedCaps = new GLCapabilities(glp); 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); } @@ -309,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 availableCaps = null; int recommendedIndex = -1; long recommendedEGLConfig = -1; @@ -322,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)); @@ -362,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); } } @@ -370,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; } @@ -428,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..4bf2a3c9d 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java @@ -48,6 +48,7 @@ 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; @@ -63,6 +64,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 +254,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 +342,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 +430,13 @@ 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 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 +450,12 @@ 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 screen refresh-rate: "+sRefreshRate+" hz, "+screenVSyncTimeout+" micros"); // Thread.dumpStack(); } @@ -457,7 +463,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, + drawable.getHandle(), allowIncompleteView, pixelFormat, chosenCaps.isBackgroundOpaque(), viewNotReady, 0); @@ -473,10 +479,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); diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawable.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawable.java index 257635b8c..841edb2b0 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawable.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawable.java @@ -106,10 +106,6 @@ public abstract class MacOSXCGLDrawable extends GLDrawableImpl { protected void setRealizedImpl() { } - protected long getNSViewHandle() { - return GLBackendType.NSOPENGL == openGLMode ? getHandle() : 0; - } - protected void registerContext(MacOSXCGLContext ctx) { // NOTE: we need to keep track of the created contexts in order to // implement swapBuffers() because of how Mac OS X implements its 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..421e1ef96 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); } 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..b144c020d 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; @@ -95,12 +95,6 @@ public class MacOSXPbufferCGLDrawable extends MacOSXCGLDrawable { return ctx; } - @Override - protected long getNSViewHandle() { - // pbuffer handle is NSOpenGLPixelBuffer - return 0; - } - @Override public long getHandle() { return pBuffer; @@ -115,7 +109,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 +168,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/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/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(); - 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 bucket = new ArrayList(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 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= 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 capsBucket = new ArrayList(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..943c7fec4 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; @@ -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 availableCaps = null; if ( sharedResource.needsCurrentContext4ARBPFDQueries() ) { @@ -150,7 +151,7 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat } static List 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/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..b847363e0 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXContext.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXContext.java @@ -76,8 +76,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); @@ -97,8 +104,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..e6b74a769 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 functionNameMap; @@ -83,8 +84,8 @@ public abstract class X11GLXContext extends GLContextImpl { functionNameMap.put("glFreeMemoryNV", "glXFreeMemoryNV"); extensionNameMap = new HashMap(); - extensionNameMap.put("GL_ARB_pbuffer", "GLX_SGIX_pbuffer"); - extensionNameMap.put("GL_ARB_pixel_format", "GLX_SGIX_pbuffer"); // good enough + extensionNameMap.put(GLExtensions.ARB_pbuffer, X11GLXDrawableFactory.GLX_SGIX_pbuffer); + extensionNameMap.put(GLExtensions.ARB_pixel_format, X11GLXDrawableFactory.GLX_SGIX_pbuffer); // good enough } X11GLXContext(GLDrawableImpl drawable, @@ -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..8ffbf3951 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java @@ -49,6 +49,8 @@ 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.GLCapabilities; import javax.media.opengl.GLCapabilitiesChooser; import javax.media.opengl.GLCapabilitiesImmutable; import javax.media.opengl.GLContext; @@ -64,6 +66,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 +82,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 +158,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 +169,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 +229,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 +249,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 +305,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 +401,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 +502,88 @@ 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); + 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 X11GLXGraphicsConfiguration cfg = X11GLXGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsRequested, capsRequested, chooser, screen); + 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..b5b80e0b3 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfiguration.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfiguration.java @@ -36,12 +36,14 @@ package jogamp.opengl.x11.glx; import java.util.ArrayList; import java.util.List; +import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.nativewindow.GraphicsConfigurationFactory; 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 +69,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 +83,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)); } @@ -233,11 +236,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 +251,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 bucket = new ArrayList(); - 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 +279,12 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem } static boolean GLXFBConfig2GLCapabilities(List 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) { diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfigurationFactory.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfigurationFactory.java index 8377d2453..331401c06 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfigurationFactory.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfigurationFactory.java @@ -44,6 +44,7 @@ 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; @@ -161,7 +162,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))); } @@ -209,7 +210,7 @@ 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; @@ -245,7 +246,7 @@ 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()); } @@ -258,6 +259,7 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF GLProfile glProfile = capsChosen.getGLProfile(); boolean onscreen = capsChosen.isOnscreen(); boolean usePBuffer = capsChosen.isPBuffer(); + boolean useFBO = capsChosen.isFBO(); // Utilizing FBConfig // @@ -270,13 +272,12 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF int[] attribs = X11GLXGraphicsConfiguration.GLCapabilities2AttribList(capsChosen, true, isMultisampleAvailable, display, screen); int[] count = { -1 }; List availableCaps = new ArrayList(); - final int winattrmask = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, usePBuffer); - + final int winattrmask = GLGraphicsConfigurationUtil.getWinAttributeBits(onscreen, usePBuffer, useFBO); // 1st choice: get GLCapabilities based on users GLCapabilities setting recommendedIndex as preferred choice 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,7 +310,7 @@ 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))); } @@ -338,7 +339,7 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF } GLProfile glProfile = capsChosen.getGLProfile(); - final int winattrmask = GLGraphicsConfigurationUtil.getWinAttributeBits(capsChosen.isOnscreen(), false /* pbuffer */); + final int winattrmask = GLGraphicsConfigurationUtil.getWinAttributeBits(capsChosen.isOnscreen(), false /* pbuffer */, false); List availableCaps = new ArrayList(); int recommendedIndex = -1; 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..d3f703142 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) { 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/egl/EGLGraphicsDevice.java b/src/nativewindow/classes/com/jogamp/nativewindow/egl/EGLGraphicsDevice.java index d161f2f34..389949e90 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/egl/EGLGraphicsDevice.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/egl/EGLGraphicsDevice.java @@ -38,7 +38,7 @@ import javax.media.nativewindow.*; */ public class EGLGraphicsDevice extends DefaultGraphicsDevice implements Cloneable { final long nativeDisplayID; - final EGLTerminateCallback eglTerminateCallback; + final EGLDisplayLifecycleCallback eglLifecycleCallback; /** * Hack to allow inject a EGL termination call. @@ -47,7 +47,14 @@ public class EGLGraphicsDevice extends DefaultGraphicsDevice implements Cloneabl * since then it can be utilized directly. *

      */ - public interface EGLTerminateCallback { + public interface EGLDisplayLifecycleCallback { + /** + * Implementation should issue an EGL.eglGetDisplay(nativeDisplayID) + * inclusive EGL.eglInitialize(eglDisplayHandle, ..) call. + * @param eglDisplayHandle + */ + public long eglGetAndInitDisplay(long nativeDisplayID); + /** * Implementation should issue an EGL.eglTerminate(eglDisplayHandle) call. * @param eglDisplayHandle @@ -61,28 +68,45 @@ public class EGLGraphicsDevice extends DefaultGraphicsDevice implements Cloneabl */ public EGLGraphicsDevice(String connection, int unitID) { super(NativeWindowFactory.TYPE_EGL, connection, unitID); - this.nativeDisplayID = 0; - this.eglTerminateCallback = null; + this.nativeDisplayID = 0 ; // EGL.EGL_DEFAULT_DISPLAY + this.eglLifecycleCallback = null; } - public EGLGraphicsDevice(long nativeDisplayID, long eglDisplay, String connection, int unitID, EGLTerminateCallback eglTerminateCallback) { + public EGLGraphicsDevice(long nativeDisplayID, long eglDisplay, String connection, int unitID, EGLDisplayLifecycleCallback eglLifecycleCallback) { super(NativeWindowFactory.TYPE_EGL, connection, unitID, eglDisplay); this.nativeDisplayID = nativeDisplayID; - this.eglTerminateCallback = eglTerminateCallback; + this.eglLifecycleCallback = eglLifecycleCallback; } public long getNativeDisplayID() { return nativeDisplayID; } + @Override public Object clone() { return super.clone(); } + + @Override + public boolean open() { + if(null != eglLifecycleCallback && 0 == handle) { + if(DEBUG) { + System.err.println(Thread.currentThread().getName() + " - EGLGraphicsDevice.open(): "+this); + } + handle = eglLifecycleCallback.eglGetAndInitDisplay(nativeDisplayID); + if(0 == handle) { + throw new NativeWindowException("EGLGraphicsDevice.open() failed: "+this); + } + return true; + } + return false; + } + @Override public boolean close() { - if(null != eglTerminateCallback) { + if(null != eglLifecycleCallback && 0 != handle) { if(DEBUG) { - System.err.println(Thread.currentThread().getName() + " - eglTerminate: "+this); + System.err.println(Thread.currentThread().getName() + " - EGLGraphicsDevice.close(): "+this); } - eglTerminateCallback.eglTerminate(handle); + eglLifecycleCallback.eglTerminate(handle); } return super.close(); } diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java b/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java index 735d85fb1..0494bb408 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/swt/SWTAccessor.java @@ -43,7 +43,6 @@ import com.jogamp.nativewindow.macosx.MacOSXGraphicsDevice; import com.jogamp.nativewindow.windows.WindowsGraphicsDevice; import com.jogamp.nativewindow.x11.X11GraphicsDevice; -import jogamp.common.awt.AWTEDTExecutor; import jogamp.nativewindow.macosx.OSXUtil; public class SWTAccessor { @@ -204,8 +203,6 @@ public class SWTAccessor { if( null != OS_gtk_class ) { long widgedHandle = callStaticMethodL2L(OS_GTK_WIDGET_WINDOW, handle); long displayHandle = callStaticMethodL2L(OS_gdk_x11_drawable_get_xdisplay, widgedHandle); - // FIXME: May think about creating a private non-shared X11 Display handle, like we use to for AWT - // to avoid locking problems ! return new X11GraphicsDevice(displayHandle, AbstractGraphicsDevice.DEFAULT_UNIT, false); } if( NativeWindowFactory.TYPE_WINDOWS == NativeWindowFactory.getNativeWindowType(false) ) { diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsDevice.java b/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsDevice.java index a02332413..7a98e3c25 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsDevice.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/x11/X11GraphicsDevice.java @@ -33,7 +33,6 @@ package com.jogamp.nativewindow.x11; -import jogamp.nativewindow.Debug; import jogamp.nativewindow.x11.X11Lib; import jogamp.nativewindow.x11.X11Util; @@ -46,7 +45,7 @@ import javax.media.nativewindow.ToolkitLock; */ public class X11GraphicsDevice extends DefaultGraphicsDevice implements Cloneable { - final boolean closeDisplay; + final boolean handleOwner; /** Constructs a new X11GraphicsDevice corresponding to the given connection and default * {@link javax.media.nativewindow.ToolkitLock} via {@link NativeWindowFactory#getDefaultToolkitLock(String)}.
      @@ -56,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 @@ -69,7 +68,7 @@ public class X11GraphicsDevice extends DefaultGraphicsDevice implements Cloneabl if(0==display) { throw new NativeWindowException("null display"); } - closeDisplay = owner; + handleOwner = owner; } /** @@ -82,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 (int) 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..014f4f688 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 (int) 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 4979f1949..756e4451b 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsDevice.java +++ b/src/nativewindow/classes/javax/media/nativewindow/AbstractGraphicsDevice.java @@ -113,16 +113,33 @@ public interface AbstractGraphicsDevice extends Cloneable { */ public void unlock(); + /** + * Optionally [re]opening the device if handle is null. + *

      + * The default implementation is a NOP. + *

      + *

      + * Example implementations like {@link com.jogamp.nativewindow.x11.X11GraphicsDevice} + * or {@link com.jogamp.nativewindow.egl.EGLGraphicsDevice} + * issue the native open operation in case handle is null. + *

      + * + * @return true if the handle was null and opening was successful, otherwise false. + */ + public boolean open(); + /** - * Optionally closing the device. + * Optionally closing the device if handle is not null. *

      * The default implementation is a NOP, just setting the handle to null. *

      - * 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)},
      - * which shall be invoked at creation time to determine ownership/role of freeing the resource.
      + *

      + * Example implementations like {@link com.jogamp.nativewindow.x11.X11GraphicsDevice} + * or {@link com.jogamp.nativewindow.egl.EGLGraphicsDevice} + * issue the native close operation or skip it depending on the handles's ownership. + *

      * - * @return true if the handle was not null, otherwise false. + * @return true if the handle was not null and closing was successful, otherwise false. */ public boolean close(); } diff --git a/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java b/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java index 187959a67..583fde07f 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java +++ b/src/nativewindow/classes/javax/media/nativewindow/DefaultGraphicsDevice.java @@ -97,22 +97,27 @@ public class DefaultGraphicsDevice implements Cloneable, AbstractGraphicsDevice } } + @Override public final String getType() { return type; } + @Override public final String getConnection() { return connection; } + @Override public final int getUnitID() { return unitID; } + @Override public final String getUniqueID() { return uniqueID; } + @Override public final long getHandle() { return handle; } @@ -124,6 +129,7 @@ public class DefaultGraphicsDevice implements Cloneable, AbstractGraphicsDevice * @see DefaultGraphicsDevice#DefaultGraphicsDevice(java.lang.String, long) * @see DefaultGraphicsDevice#DefaultGraphicsDevice(java.lang.String, long, javax.media.nativewindow.ToolkitLock) */ + @Override public final void lock() { toolkitLock.lock(); } @@ -135,10 +141,17 @@ public class DefaultGraphicsDevice implements Cloneable, AbstractGraphicsDevice * @see DefaultGraphicsDevice#DefaultGraphicsDevice(java.lang.String, long) * @see DefaultGraphicsDevice#DefaultGraphicsDevice(java.lang.String, long, javax.media.nativewindow.ToolkitLock) */ + @Override public final void unlock() { toolkitLock.unlock(); } + + @Override + public boolean open() { + return false; + } + @Override public boolean close() { if(0 != handle) { handle = 0; diff --git a/src/nativewindow/classes/javax/media/nativewindow/MutableSurface.java b/src/nativewindow/classes/javax/media/nativewindow/MutableSurface.java new file mode 100644 index 000000000..ff53c8109 --- /dev/null +++ b/src/nativewindow/classes/javax/media/nativewindow/MutableSurface.java @@ -0,0 +1,44 @@ +/** + * Copyright 2012 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package javax.media.nativewindow; + +/** + * Provides a {@link NativeSurface} with a mutable surfaceHandle + * via {@link #setSurfaceHandle(long)}. + * + * @see NativeSurface + */ +public interface MutableSurface extends NativeSurface { + + /** + * Sets the surface handle which is created outside of this implementation. + */ + public void setSurfaceHandle(long surfaceHandle); +} + diff --git a/src/nativewindow/classes/javax/media/nativewindow/ProxySurface.java b/src/nativewindow/classes/javax/media/nativewindow/ProxySurface.java index 1dabc3dcd..7fc9789c2 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/ProxySurface.java +++ b/src/nativewindow/classes/javax/media/nativewindow/ProxySurface.java @@ -28,38 +28,108 @@ package javax.media.nativewindow; - import jogamp.nativewindow.Debug; import jogamp.nativewindow.SurfaceUpdatedHelper; import com.jogamp.common.util.locks.LockFactory; import com.jogamp.common.util.locks.RecursiveLock; -public abstract class ProxySurface implements NativeSurface { +public abstract class ProxySurface implements NativeSurface, MutableSurface { public static final boolean DEBUG = Debug.debug("ProxySurface"); + + /** + * Implementation specific bitvalue stating the upstream's {@link AbstractGraphicsDevice} is owned by this {@link ProxySurface}. + * @see #setImplBitfield(int) + * @see #getImplBitfield() + */ + public static final int OWN_DEVICE = 1 << 7; + + /** + * Implementation specific bitvalue stating the upstream's {@link NativeSurface} is an invisible window, i.e. maybe incomplete. + * @see #setImplBitfield(int) + * @see #getImplBitfield() + */ + public static final int INVISIBLE_WINDOW = 1 << 8; - private SurfaceUpdatedHelper surfaceUpdatedHelper = new SurfaceUpdatedHelper(); - private AbstractGraphicsConfiguration config; // control access due to delegation - protected RecursiveLock surfaceLock = LockFactory.createRecursiveLock(); + /** Interface allowing upstream caller to pass lifecycle actions and size info to a {@link ProxySurface} instance. */ + public interface UpstreamSurfaceHook { + /** called within {@link ProxySurface#createNotify()} within lock, before using surface. */ + public void create(ProxySurface s); + /** called within {@link ProxySurface#destroyNotify()} within lock, before clearing fields. */ + public void destroy(ProxySurface s); + + /** Returns the width of the upstream surface */ + public int getWidth(ProxySurface s); + /** Returns the height of the upstream surface */ + public int getHeight(ProxySurface s); + } + + private final SurfaceUpdatedHelper surfaceUpdatedHelper = new SurfaceUpdatedHelper(); + private final AbstractGraphicsConfiguration config; // control access due to delegation + private final UpstreamSurfaceHook upstream; + public final int initialWidth; + public final int initialHeight; private long surfaceHandle_old; + protected RecursiveLock surfaceLock = LockFactory.createRecursiveLock(); protected long displayHandle; - protected int height; protected int scrnIndex; - protected int width; + protected int implBitfield; - public ProxySurface(AbstractGraphicsConfiguration cfg) { - invalidate(); - config = cfg; - displayHandle=cfg.getNativeGraphicsConfiguration().getScreen().getDevice().getHandle(); - surfaceHandle_old = 0; + /** + * @param cfg the {@link AbstractGraphicsConfiguration} to be used + * @param initialWidth the initial width + * @param initialHeight the initial height + */ + protected ProxySurface(AbstractGraphicsConfiguration cfg, int initialWidth, int initialHeight, UpstreamSurfaceHook upstream) { + if(null == cfg) { + throw new IllegalArgumentException("null config"); + } + this.config = cfg; + this.upstream = upstream; + this.initialWidth = initialWidth; + this.initialHeight = initialHeight; + this.displayHandle=config.getNativeGraphicsConfiguration().getScreen().getDevice().getHandle(); + this.surfaceHandle_old = 0; + this.implBitfield = 0; } - void invalidate() { - displayHandle = 0; - invalidateImpl(); + public final UpstreamSurfaceHook getUpstreamSurfaceHook() { return upstream; } + + /** + * If a valid {@link UpstreamSurfaceHook} instance is passed in the + * {@link ProxySurface#ProxySurface(AbstractGraphicsConfiguration, int, int, UpstreamSurfaceHook) constructor}, + * {@link UpstreamSurfaceHook#create(ProxySurface)} is being issued and the proxy surface/window handles shall be set. + */ + public void createNotify() { + if(null != upstream) { + upstream.create(this); + } + this.displayHandle=config.getNativeGraphicsConfiguration().getScreen().getDevice().getHandle(); + this.surfaceHandle_old = 0; } - protected abstract void invalidateImpl(); - + + /** + * If a valid {@link UpstreamSurfaceHook} instance is passed in the + * {@link ProxySurface#ProxySurface(AbstractGraphicsConfiguration, int, int, UpstreamSurfaceHook) constructor}, + * {@link UpstreamSurfaceHook#destroy(ProxySurface)} is being issued and all fields are cleared. + */ + public void destroyNotify() { + if(null != upstream) { + upstream.destroy(this); + invalidateImpl(); + } + this.displayHandle = 0; + this.surfaceHandle_old = 0; + } + + /** + * Must be overridden by implementations allowing having a {@link UpstreamSurfaceHook} being passed. + * @see #destroyNotify() + */ + protected void invalidateImpl() { + throw new InternalError("UpstreamSurfaceHook given, but required method not implemented."); + } + @Override public final long getDisplayHandle() { return displayHandle; @@ -82,19 +152,23 @@ public abstract class ProxySurface implements NativeSurface { @Override public abstract long getSurfaceHandle(); + @Override + public abstract void setSurfaceHandle(long surfaceHandle); + @Override public final int getWidth() { - return width; + if(null != upstream) { + return upstream.getWidth(this); + } + return initialWidth; } @Override public final int getHeight() { - return height; - } - - public void surfaceSizeChanged(int width, int height) { - this.width = width; - this.height = height; + if(null != upstream) { + return upstream.getHeight(this); + } + return initialHeight; } @Override @@ -187,7 +261,10 @@ public abstract class ProxySurface implements NativeSurface { public final Thread getSurfaceLockOwner() { return surfaceLock.getOwner(); } - + @Override public abstract String toString(); + + public int getImplBitfield() { return implBitfield; } + public void setImplBitfield(int v) { implBitfield=v; } } diff --git a/src/nativewindow/classes/javax/media/nativewindow/SurfaceChangeable.java b/src/nativewindow/classes/javax/media/nativewindow/SurfaceChangeable.java deleted file mode 100644 index 956e68e61..000000000 --- a/src/nativewindow/classes/javax/media/nativewindow/SurfaceChangeable.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * - Redistribution of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * - Redistribution in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * Neither the name of Sun Microsystems, Inc. or the names of - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * This software is provided "AS IS," without a warranty of any kind. ALL - * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, - * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN - * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR - * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR - * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR - * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR - * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE - * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, - * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF - * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - * - * You acknowledge that this software is not designed or intended for use - * in the design, construction, operation or maintenance of any nuclear - * facility. - * - * Sun gratefully acknowledges that this software was originally authored - * and developed by Kenneth Bradley Russell and Christopher John Kline. - */ - -package javax.media.nativewindow; - -public interface SurfaceChangeable { - - /** Sets the surface handle which is created outside of this implementation */ - public void setSurfaceHandle(long surfaceHandle); - - /** - * The surface's size has been determined or changed. - * Implementation shall update the stored surface size with the given ones. - */ - public void surfaceSizeChanged(int width, int height); - -} - diff --git a/src/nativewindow/classes/jogamp/nativewindow/SurfaceUpdatedHelper.java b/src/nativewindow/classes/jogamp/nativewindow/SurfaceUpdatedHelper.java index 4877d5c4f..4f68c6945 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/SurfaceUpdatedHelper.java +++ b/src/nativewindow/classes/jogamp/nativewindow/SurfaceUpdatedHelper.java @@ -34,8 +34,8 @@ import javax.media.nativewindow.NativeSurface; import javax.media.nativewindow.SurfaceUpdatedListener; public class SurfaceUpdatedHelper implements SurfaceUpdatedListener { - private Object surfaceUpdatedListenersLock = new Object(); - private ArrayList surfaceUpdatedListeners = new ArrayList(); + private final Object surfaceUpdatedListenersLock = new Object(); + private final ArrayList surfaceUpdatedListeners = new ArrayList(); // // 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..99fc9244e 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java +++ b/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java @@ -63,19 +63,15 @@ public class OSXUtil { return (Point) GetLocationOnScreen0(windowOrView, src_x, src_y); } - public static long CreateNSView(int x, int y, int width, int height) { - return CreateNSView0(x, y, width, height); - } - public static void DestroyNSView(long nsView) { - DestroyNSView0(nsView); - } - 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); @@ -134,10 +130,9 @@ public class OSXUtil { private static native boolean initIDs0(); private static native Object GetLocationOnScreen0(long windowOrView, int src_x, int src_y); - private static native long CreateNSView0(int x, int y, int width, int height); - private static native void DestroyNSView0(long nsView); 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} + *

      + * Actually the window handle (HWND), since the surfaceHandle (HDC) is derived + * from it at {@link #lockSurface()}. + *

      + */ + @Override + public final void setSurfaceHandle(long surfaceHandle) { + this.windowHandle = surfaceHandle; + } + + /** + * Sets the window handle (HWND). + */ + public final void setWindowHandle(long windowHandle) { + this.windowHandle = windowHandle; + } + + public final long getWindowHandle() { + return windowHandle; } @Override final protected int lockSurfaceImpl() { + if (0 == windowHandle) { + throw new NativeWindowException("null window handle: "+this); + } if (0 != surfaceHandle) { throw new InternalError("surface not released"); } @@ -89,12 +117,15 @@ public class GDISurface extends ProxySurface { @Override final public String toString() { - return "GDISurface[config "+getPrivateGraphicsConfiguration()+ + final UpstreamSurfaceHook ush = getUpstreamSurfaceHook(); + final String ush_s = null != ush ? ( ush.getClass().getName() + ": " + ush ) : "nil"; + return getClass().getSimpleName()+"[config "+getPrivateGraphicsConfiguration()+ ", displayHandle 0x"+Long.toHexString(getDisplayHandle())+ ", windowHandle 0x"+Long.toHexString(windowHandle)+ ", surfaceHandle 0x"+Long.toHexString(getSurfaceHandle())+ ", size "+getWidth()+"x"+getHeight()+ - ", surfaceLock "+surfaceLock+"]"; + ", surfaceLock "+surfaceLock+ + ", upstreamSurfaceHook "+ush_s+"]"; } } diff --git a/src/nativewindow/native/macosx/OSXmisc.m b/src/nativewindow/native/macosx/OSXmisc.m index e010fc440..ebfefe345 100644 --- a/src/nativewindow/native/macosx/OSXmisc.m +++ b/src/nativewindow/native/macosx/OSXmisc.m @@ -148,37 +148,6 @@ JNIEXPORT jobject JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_GetLocationOnS return res; } -/* - * Class: Java_jogamp_nativewindow_macosx_OSXUtil - * Method: CreateNSView0 - * Signature: (IIIIZ)J - */ -JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_CreateNSView0 - (JNIEnv *env, jclass unused, jint x, jint y, jint width, jint height) -{ - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - NSRect rect = NSMakeRect(x, y, width, height); - NSView * view = [[NSView alloc] initWithFrame: rect] ; - [view setCanDrawConcurrently: YES]; - [pool release]; - - return (jlong) (intptr_t) view; -} - -/* - * Class: Java_jogamp_nativewindow_macosx_OSXUtil - * Method: DestroyNSView0 - * Signature: (J)V - */ -JNIEXPORT void JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_DestroyNSView0 - (JNIEnv *env, jclass unused, jlong nsView) -{ - NSView* view = (NSView*) (intptr_t) nsView; - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - [view release]; - [pool release]; -} - /* * Class: Java_jogamp_nativewindow_macosx_OSXUtil * Method: CreateNSWindow0 @@ -222,6 +191,27 @@ JNIEXPORT void JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_DestroyNSWindow0 [pool release]; } +/* + * Class: Java_jogamp_nativewindow_macosx_OSXUtil + * Method: GetNSView0 + * Signature: (J)J + */ +JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_GetNSView0 + (JNIEnv *env, jclass unused, jlong window) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + NSWindow* win = (NSWindow*) ((intptr_t) window); + + DBG_PRINT( "contentView0 - window: %p (START)\n", win); + + jlong res = (jlong) ((intptr_t) [win contentView]); + + DBG_PRINT( "contentView0 - window: %p (END)\n", win); + + [pool release]; + return res; +} + /* * Class: Java_jogamp_nativewindow_macosx_OSXUtil * Method: CreateCALayer0 diff --git a/src/newt/classes/com/jogamp/newt/Window.java b/src/newt/classes/com/jogamp/newt/Window.java index 71e86d520..e8537fec5 100644 --- a/src/newt/classes/com/jogamp/newt/Window.java +++ b/src/newt/classes/com/jogamp/newt/Window.java @@ -40,8 +40,20 @@ import javax.media.nativewindow.NativeWindow; import javax.media.nativewindow.WindowClosingProtocol; /** - * Specifying the public Window functionality for the - * using a Window and for shadowing one like {@link com.jogamp.newt.opengl.GLWindow}. + * Specifying NEWT's Window functionality: + *
        + *
      • On- and offscreen windows
      • + *
      • Keyboard and multi-pointer input
      • + *
      • Native reparenting
      • + *
      • Toggable fullscreen and decoration mode
      • + *
      • Transparency
      • + *
      • ... and more
      • + *
      + *

      + * One use case is {@link com.jogamp.newt.opengl.GLWindow}, which delegates + * window operation to an instance of this interface while providing OpenGL + * functionality. + *

      */ public interface Window extends NativeWindow, WindowClosingProtocol { public static final boolean DEBUG_MOUSE_EVENT = Debug.debug("Window.MouseEvent"); diff --git a/src/newt/classes/com/jogamp/newt/event/KeyEvent.java b/src/newt/classes/com/jogamp/newt/event/KeyEvent.java index 44fcea49c..4db661eeb 100644 --- a/src/newt/classes/com/jogamp/newt/event/KeyEvent.java +++ b/src/newt/classes/com/jogamp/newt/event/KeyEvent.java @@ -43,7 +43,7 @@ public class KeyEvent extends InputEvent this.keyChar=keyChar; } - /** Only valid if delivered via {@link KeyListener#keyPressed(KeyEvent)} */ + /** Only valid on all platforms at {@link KeyListener#keyTyped(KeyEvent)} */ public char getKeyChar() { return keyChar; } diff --git a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java index f08fbc8fa..c50ab77c4 100644 --- a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java +++ b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java @@ -124,6 +124,11 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind this.window.setLifecycleHook(new GLLifecycleHook()); } + @Override + public final Object getUpstreamWidget() { + return window; + } + /** * Creates a new GLWindow attaching a new Window referencing a * new default Screen and default Display with the given GLCapabilities. @@ -762,7 +767,7 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind System.err.println(GlueGenVersion.getInstance()); System.err.println(JoglVersion.getInstance()); - System.err.println(JoglVersion.getDefaultOpenGLInfo(null, true).toString()); + System.err.println(JoglVersion.getDefaultOpenGLInfo(null, null, true).toString()); final GLProfile glp = GLProfile.getDefault(); final GLCapabilitiesImmutable caps = new GLCapabilities( glp ); diff --git a/src/newt/classes/jogamp/newt/OffscreenWindow.java b/src/newt/classes/jogamp/newt/OffscreenWindow.java index 050e24b6c..be543aba9 100644 --- a/src/newt/classes/jogamp/newt/OffscreenWindow.java +++ b/src/newt/classes/jogamp/newt/OffscreenWindow.java @@ -34,15 +34,24 @@ package jogamp.newt; -import javax.media.nativewindow.*; +import javax.media.nativewindow.AbstractGraphicsConfiguration; +import javax.media.nativewindow.AbstractGraphicsScreen; +import javax.media.nativewindow.GraphicsConfigurationFactory; +import javax.media.nativewindow.MutableSurface; +import javax.media.nativewindow.NativeWindowException; +import javax.media.nativewindow.ProxySurface; import javax.media.nativewindow.util.Insets; import javax.media.nativewindow.util.Point; -public class OffscreenWindow extends WindowImpl implements SurfaceChangeable { +public class OffscreenWindow extends WindowImpl implements MutableSurface { long surfaceHandle = 0; - + ProxySurface.UpstreamSurfaceHook upstreamHook; + ProxySurface dummySurface; + public OffscreenWindow() { + upstreamHook = null; + dummySurface = null; } static long nextWindowHandle = 0x100; // start here - a marker @@ -52,6 +61,17 @@ public class OffscreenWindow extends WindowImpl implements SurfaceChangeable { throw new NativeWindowException("Capabilities is onscreen"); } final AbstractGraphicsScreen aScreen = getScreen().getGraphicsScreen(); + /** Cannot use OpenGL here .. + if(capsRequested instanceof GLCapabilitiesImmutable) { + final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) capsRequested; + if(caps.isFBO() && GLContext.isFBOAvailable(aScreen.getDevice(), caps.getGLProfile()) ) { + final GLDrawableFactoryImpl factory = (GLDrawableFactoryImpl) GLDrawableFactory.getFactory(caps.getGLProfile()); + final GLCapabilitiesImmutable dummyCaps = GLGraphicsConfigurationUtil.fixOnscreenGLCapabilities(caps); + final ProxySurface dummySurface = factory.createDummySurfaceImpl(aScreen.getDevice(), false, dummyCaps, null, 64, 64); + upstreamHook = dummySurface.getUpstreamSurfaceHook(); + dummySurface.createNotify(); + } + } */ final AbstractGraphicsConfiguration cfg = GraphicsConfigurationFactory.getFactory(aScreen.getDevice()).chooseGraphicsConfiguration( capsRequested, capsRequested, capabilitiesChooser, aScreen); if (null == cfg) { @@ -68,13 +88,14 @@ public class OffscreenWindow extends WindowImpl implements SurfaceChangeable { // nop } - public void surfaceSizeChanged(int width, int height) { - sizeChanged(false, width, height, false); - } - @Override public synchronized void destroy() { super.destroy(); + if(null != dummySurface) { + dummySurface.destroyNotify(); + dummySurface = null; + upstreamHook = null; + } surfaceHandle = 0; } @@ -84,8 +105,12 @@ public class OffscreenWindow extends WindowImpl implements SurfaceChangeable { @Override public long getSurfaceHandle() { + if(null != dummySurface) { + return dummySurface.getSurfaceHandle(); + // return upstreamHook.getWidth(); + } return surfaceHandle; - } + } protected void requestFocusImpl(boolean reparented) { } diff --git a/src/newt/classes/jogamp/newt/driver/android/MD.java b/src/newt/classes/jogamp/newt/driver/android/MD.java index 403eae383..f2f30937b 100644 --- a/src/newt/classes/jogamp/newt/driver/android/MD.java +++ b/src/newt/classes/jogamp/newt/driver/android/MD.java @@ -43,7 +43,7 @@ public class MD { .append(JoglVersion.getInstance()).append(Platform.NEWLINE) .append(Platform.NEWLINE); - JoglVersion.getDefaultOpenGLInfo(sb, true); + JoglVersion.getDefaultOpenGLInfo(null, sb, true); return sb.toString(); } diff --git a/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java b/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java index 942994c13..fcca5c843 100644 --- a/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java +++ b/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java @@ -38,7 +38,7 @@ import javax.media.nativewindow.AbstractGraphicsConfiguration; import javax.media.nativewindow.GraphicsConfigurationFactory; import javax.media.nativewindow.NativeWindow; import javax.media.nativewindow.NativeWindowException; -import javax.media.nativewindow.SurfaceChangeable; +import javax.media.nativewindow.MutableSurface; import javax.media.nativewindow.util.Insets; import javax.media.nativewindow.util.InsetsImmutable; import javax.media.nativewindow.util.Point; @@ -50,7 +50,7 @@ import jogamp.newt.driver.DriverUpdatePosition; import com.jogamp.newt.event.KeyEvent; -public class MacWindow extends WindowImpl implements SurfaceChangeable, DriverClearFocus, DriverUpdatePosition { +public class MacWindow extends WindowImpl implements MutableSurface, DriverClearFocus, DriverUpdatePosition { static { MacDisplay.initSingleton(); @@ -131,10 +131,6 @@ public class MacWindow extends WindowImpl implements SurfaceChangeable, DriverCl } } - public void surfaceSizeChanged(int width, int height) { - sizeChanged(false, width, height, false); - } - @Override protected void setTitleImpl(final String title) { setTitle0(getWindowHandle(), title); diff --git a/src/newt/native/NewtMacWindow.m b/src/newt/native/NewtMacWindow.m index f914467af..b58b99e38 100644 --- a/src/newt/native/NewtMacWindow.m +++ b/src/newt/native/NewtMacWindow.m @@ -972,7 +972,7 @@ static jint mods2JavaMods(NSUInteger mods) NSView* nsview = [self contentView]; if( ! [nsview isMemberOfClass:[NewtView class]] ) { - return; + return NO; } NewtView* view = (NewtView *) nsview; @@ -981,14 +981,14 @@ static jint mods2JavaMods(NSUInteger mods) DBG_PRINT( "*************** windowWillClose.0: %p\n", (void *)(intptr_t)javaWindowObject); if (javaWindowObject == NULL) { DBG_PRINT("windowWillClose: null javaWindowObject\n"); - return; + return NO; } int shallBeDetached = 0; JavaVM *jvmHandle = [view getJVMHandle]; JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, [view getJVMVersion], &shallBeDetached); if(NULL==env) { DBG_PRINT("windowWillClose: null JNIEnv\n"); - return; + return NO; } [view setDestroyNotifySent: true]; // earmark assumption of being closed diff --git a/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT00.java b/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT00.java index a09cc76ac..b22be0a93 100644 --- a/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT00.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/TestTextRendererNEWT00.java @@ -194,7 +194,7 @@ public class TestTextRendererNEWT00 extends UITestCase { pw.printf("%s-%03dx%03d-T%04d", objName, drawable.getWidth(), drawable.getHeight(), texSize[0]); final String filename = dir + sw +".png"; - if(screenshot.readPixels(drawable.getGL(), drawable, false)) { + if(screenshot.readPixels(drawable.getGL(), false)) { screenshot.write(new File(filename)); } } diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURendererListenerBase01.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURendererListenerBase01.java index a3182a30f..6378c1ee3 100644 --- a/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURendererListenerBase01.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/GPURendererListenerBase01.java @@ -194,7 +194,7 @@ public abstract class GPURendererListenerBase01 implements GLEventListener { pw.printf("-%03dx%03d-Z%04d-T%04d-%s", drawable.getWidth(), drawable.getHeight(), (int)Math.abs(zoom), texSize[0], objName); final String filename = dir + tech + sw +".png"; - if(screenshot.readPixels(drawable.getGL(), drawable, false)) { + if(screenshot.readPixels(drawable.getGL(), false)) { screenshot.write(new File(filename)); } } diff --git a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UIListenerBase01.java b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UIListenerBase01.java index d0093ad0c..15daf70cd 100644 --- a/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UIListenerBase01.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/demos/ui/UIListenerBase01.java @@ -180,7 +180,7 @@ public abstract class UIListenerBase01 implements GLEventListener { pw.printf("-%03dx%03d-Z%04d-T%04d-%s", drawable.getWidth(), drawable.getHeight(), (int)Math.abs(zoom), 0, objName); final String filename = dir + tech + sw +".png"; - if(screenshot.readPixels(drawable.getGL(), drawable, false)) { + if(screenshot.readPixels(drawable.getGL(), false)) { screenshot.write(new File(filename)); } } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBODrawableNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBODrawableNEWT.java new file mode 100644 index 000000000..1a33845b3 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBODrawableNEWT.java @@ -0,0 +1,272 @@ +/** + * Copyright 2012 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package com.jogamp.opengl.test.junit.jogl.acore; + +import java.io.IOException; + +import javax.media.opengl.GL; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawable; +import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; + +import jogamp.opengl.GLFBODrawableImpl; + +import org.junit.Assert; +import org.junit.Test; + +import com.jogamp.opengl.FBObject; +import com.jogamp.opengl.OffscreenAutoDrawable; +import com.jogamp.opengl.test.junit.jogl.demos.es2.FBOMix2DemosES2; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.jogl.demos.es2.MultisampleDemoES2; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.util.GLReadBufferUtil; +import com.jogamp.opengl.util.texture.TextureIO; + +public class TestFBODrawableNEWT extends UITestCase { + + static final int widthStep = 800/4; + static final int heightStep = 600/4; + volatile int szStep = 2; + + @Test + public void testGL2ES2_Demo1Normal() throws InterruptedException { + final GLProfile glp = GLProfile.getGL2ES2(); + final GLCapabilities caps = new GLCapabilities(glp); + testGLFBODrawableImpl(caps, new GearsES2(0)); + } + + @Test + public void testGL2ES2_Demo1MSAA4() throws InterruptedException { + final GLProfile glp = GLProfile.getGL2ES2(); + final GLCapabilities caps = new GLCapabilities(glp); + caps.setSampleBuffers(true); + caps.setNumSamples(4); + testGLFBODrawableImpl(caps, new GearsES2(0)); + } + + @Test + public void testGL2ES2_Demo2Normal() throws InterruptedException { + final GLProfile glp = GLProfile.getGL2ES2(); + final GLCapabilities caps = new GLCapabilities(glp); + testGLFBODrawableImpl(caps, new MultisampleDemoES2(false)); + } + + @Test + public void testGL2ES2_Demo2MSAA4() throws InterruptedException { + final GLProfile glp = GLProfile.getGL2ES2(); + final GLCapabilities caps = new GLCapabilities(glp); + caps.setSampleBuffers(true); + caps.setNumSamples(4); + testGLFBODrawableImpl(caps, new MultisampleDemoES2(true)); + } + + @Test + public void testGL2ES2_FBODemoNormal() throws InterruptedException { + final GLProfile glp = GLProfile.getGL2ES2(); + final FBOMix2DemosES2 demo = new FBOMix2DemosES2(0); + demo.setDoRotation(false); + final GLCapabilities caps = new GLCapabilities(glp); + testGLFBODrawableImpl(caps, demo); + } + + @Test + public void testGL2ES2_FBODemoMSAA4() throws InterruptedException { + final GLProfile glp = GLProfile.getGL2ES2(); + final FBOMix2DemosES2 demo = new FBOMix2DemosES2(0); + demo.setDoRotation(false); + final GLCapabilities caps = new GLCapabilities(glp); + caps.setSampleBuffers(true); + caps.setNumSamples(4); + testGLFBODrawableImpl(caps, demo); + } + + @Test + public void testEGLES2_Demo0Normal() throws InterruptedException { + if( GLProfile.isAvailable(GLProfile.GLES2) ) { + final GLProfile glp = GLProfile.get(GLProfile.GLES2); + final GLCapabilities caps = new GLCapabilities(glp); + testGLFBODrawableImpl(caps, new GearsES2(0)); + } else { + System.err.println("EGL ES2 n/a"); + } + } + + @Test + public void testEGLES2_Demo0MSAA4() throws InterruptedException { + if( GLProfile.isAvailable(GLProfile.GLES2) ) { + final GLProfile glp = GLProfile.get(GLProfile.GLES2); + final GLCapabilities caps = new GLCapabilities(glp); + caps.setSampleBuffers(true); + caps.setNumSamples(4); + testGLFBODrawableImpl(caps, new GearsES2(0)); + } else { + System.err.println("EGL ES2 n/a"); + } + } + + boolean skipShot = false; + + void testGLFBODrawableImpl(GLCapabilities caps, GLEventListener demo) throws InterruptedException { + final GLReadBufferUtil screenshot = new GLReadBufferUtil(false, false); + caps.setFBO(true); + final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile()); + final GLDrawable fboDrawable = factory.createOffscreenDrawable(null, caps, null, widthStep*szStep, heightStep*szStep); + Assert.assertNotNull(fboDrawable); + Assert.assertTrue("Not an FBO Drawable", fboDrawable instanceof GLFBODrawableImpl); + + fboDrawable.setRealized(true); + Assert.assertTrue(fboDrawable.isRealized()); + + final FBObject fbo = ((GLFBODrawableImpl)fboDrawable).getFBObject(); + + System.out.println("Realized: "+fboDrawable); + System.out.println("Realized: "+fboDrawable.getChosenGLCapabilities()); + System.out.println("Realized: "+fbo); + + final GLContext context = fboDrawable.createContext(null); + Assert.assertNotNull(context); + + int res = context.makeCurrent(); + Assert.assertTrue(GLContext.CONTEXT_CURRENT_NEW==res || GLContext.CONTEXT_CURRENT==res); + context.release(); + + System.out.println("Post Create-Ctx: "+fbo); + final FBObject.Colorbuffer colorA = fbo.getColorbuffer(0); + Assert.assertNotNull(colorA); + final FBObject.RenderAttachment depthA = fbo.getDepthAttachment(); + Assert.assertNotNull(depthA); + + final OffscreenAutoDrawable glad = new OffscreenAutoDrawable(fboDrawable, context, null); + + glad.addGLEventListener(demo); + glad.addGLEventListener(new GLEventListener() { + volatile int displayCount=0; + volatile int reshapeCount=0; + public void init(GLAutoDrawable drawable) {} + public void dispose(GLAutoDrawable drawable) {} + public void display(GLAutoDrawable drawable) { + final GL gl = drawable.getGL(); + // System.err.println(Thread.currentThread().getName()+": ** display: "+displayCount+": step "+szStep+" "+drawable.getWidth()+"x"+drawable.getHeight()); + // System.err.println(Thread.currentThread().getName()+": ** FBO-THIS: "+fbo); + // System.err.println(Thread.currentThread().getName()+": ** FBO-SINK: "+fbo.getSamplingSinkFBO()); + // System.err.println(Thread.currentThread().getName()+": ** drawable-read: "+gl.getDefaultReadFramebuffer()); + if(skipShot) { + skipShot=false; + } else { + snapshot(getSimpleTestName("."), displayCount, "msaa"+fbo.getNumSamples(), gl, screenshot, TextureIO.PNG, null); + } + Assert.assertEquals(drawable.getWidth(), widthStep*szStep); + Assert.assertEquals(drawable.getHeight(), heightStep*szStep); + displayCount++; + } + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { + System.err.println(Thread.currentThread().getName()+": ** reshape: "+reshapeCount+": step "+szStep+" "+width+"x"+height+" - "+drawable.getWidth()+"x"+drawable.getHeight()); + Assert.assertEquals(drawable.getWidth(), widthStep*szStep); + Assert.assertEquals(drawable.getHeight(), heightStep*szStep); + reshapeCount++; + } + }); + + // 0 - szStep = 2 + glad.display(); + + // 1, 2 (resize + display) + szStep = 1; + skipShot=true; + glad.setSize(widthStep*szStep, heightStep*szStep); + glad.display(); + Assert.assertEquals(glad.getWidth(), widthStep*szStep); + Assert.assertEquals(glad.getHeight(), heightStep*szStep); + { + // Check whether the attachment reference are still valid! + FBObject.Colorbuffer _colorA = fbo.getColorbuffer(0); + Assert.assertNotNull(_colorA); + Assert.assertTrue(colorA == _colorA); + Assert.assertTrue(colorA.equals(_colorA)); + FBObject.RenderAttachment _depthA = fbo.getDepthAttachment(); + Assert.assertNotNull(_depthA); + Assert.assertTrue(depthA == _depthA); + Assert.assertTrue(depthA.equals(_depthA)); + + _colorA = fbo.getColorbuffer(colorA); + Assert.assertNotNull(_colorA); + Assert.assertTrue(colorA == _colorA); + Assert.assertTrue(colorA.equals(_colorA)); + } + + // 3, 4 (resize + display) + szStep = 4; + skipShot=true; + glad.setSize(widthStep*szStep, heightStep*szStep); + glad.display(); + Assert.assertEquals(glad.getWidth(), widthStep*szStep); + Assert.assertEquals(glad.getHeight(), heightStep*szStep); + { + // Check whether the attachment reference are still valid! + FBObject.Colorbuffer _colorA = fbo.getColorbuffer(0); + Assert.assertNotNull(_colorA); + Assert.assertTrue(colorA == _colorA); + final FBObject.RenderAttachment _depthA = fbo.getDepthAttachment(); + Assert.assertNotNull(_depthA); + Assert.assertTrue(depthA == _depthA); + + _colorA = fbo.getColorbuffer(colorA); + Assert.assertNotNull(_colorA); + Assert.assertTrue(colorA == _colorA); + } + + // 5 + glad.display(); + Assert.assertEquals(glad.getWidth(), widthStep*szStep); + Assert.assertEquals(glad.getHeight(), heightStep*szStep); + + // 6, 7 (resize + display) + szStep = 3; + skipShot=true; + glad.setSize(widthStep*szStep, heightStep*szStep); + glad.display(); + Assert.assertEquals(glad.getWidth(), widthStep*szStep); + Assert.assertEquals(glad.getHeight(), heightStep*szStep); + + glad.destroy(); + System.out.println("Fin: "+fboDrawable); + + // final GLAutoDrawableDelegate glad = new GLAutoDrawableDelegate(fboDrawable, context); + } + + public static void main(String args[]) throws IOException { + org.junit.runner.JUnitCore.main(TestFBODrawableNEWT.class.getName()); + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMRTNEWT01.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMRTNEWT01.java new file mode 100644 index 000000000..f7c83a03b --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMRTNEWT01.java @@ -0,0 +1,266 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.opengl.test.junit.jogl.acore; + +import com.jogamp.opengl.FBObject; +import com.jogamp.opengl.FBObject.TextureAttachment; +import com.jogamp.opengl.util.GLArrayDataServer; +import com.jogamp.opengl.util.GLReadBufferUtil; +import com.jogamp.opengl.util.PMVMatrix; +import com.jogamp.opengl.util.glsl.ShaderCode; +import com.jogamp.opengl.util.glsl.ShaderProgram; +import com.jogamp.opengl.util.glsl.ShaderState; +import com.jogamp.opengl.util.texture.TextureIO; +import com.jogamp.opengl.FBObject.Attachment.Type; +import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.NEWTGLContext; +import com.jogamp.opengl.test.junit.util.UITestCase; + +import java.io.IOException; + +import javax.media.nativewindow.NativeSurface; +import javax.media.opengl.GL; +import javax.media.opengl.GL2ES2; +import javax.media.opengl.GL2GL3; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLDrawable; +import javax.media.opengl.GLPipelineFactory; +import javax.media.opengl.GLProfile; +import javax.media.opengl.GLUniformData; + +import org.junit.Assert; +import org.junit.Test; + +public class TestFBOMRTNEWT01 extends UITestCase { + static long durationPerTest = 10*40*2; // ms + + @Test + public void test01() throws InterruptedException { + final int step = 4; + final int width = 800; + final int height = 600; + // preset .. + if(!GLProfile.isAvailable(GLProfile.GL2GL3)) { + System.err.println("Test requires GL2/GL3 profile."); + return; + } + final NEWTGLContext.WindowContext winctx = NEWTGLContext.createOnscreenWindow( + new GLCapabilities(GLProfile.getGL2GL3()), width/step, height/step, true); + final GLDrawable drawable = winctx.context.getGLDrawable(); + GL2GL3 gl = winctx.context.getGL().getGL2GL3(); + gl = gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Debug", null, gl, null) ).getGL2GL3(); + System.err.println(winctx.context); + + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + // test code .. + final ShaderState st = new ShaderState(); + // st.setVerbose(true); + + final ShaderCode vp0 = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, RedSquareES2.class, "shader", + "shader/bin", "fbo-mrt-1", false); + final ShaderCode fp0 = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, RedSquareES2.class, "shader", + "shader/bin", "fbo-mrt-1", false); + final ShaderProgram sp0 = new ShaderProgram(); + sp0.add(gl, vp0, System.err); + sp0.add(gl, fp0, System.err); + Assert.assertTrue(0<=sp0.program()); + Assert.assertTrue(!sp0.inUse()); + Assert.assertTrue(!sp0.linked()); + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + st.attachShaderProgram(gl, sp0, false); + + final ShaderCode vp1 = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, RedSquareES2.class, "shader", + "shader/bin", "fbo-mrt-2", false); + final ShaderCode fp1 = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, RedSquareES2.class, "shader", + "shader/bin", "fbo-mrt-2", false); + final ShaderProgram sp1 = new ShaderProgram(); + sp1.add(gl, vp1, System.err); + sp1.add(gl, fp1, System.err); + Assert.assertTrue(0<=sp1.program()); + Assert.assertTrue(!sp1.inUse()); + Assert.assertTrue(!sp1.linked()); + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + st.attachShaderProgram(gl, sp1, true); + + final PMVMatrix pmvMatrix = new PMVMatrix(); + final GLUniformData pmvMatrixUniform = new GLUniformData("gcu_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf()); + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + st.ownUniform(pmvMatrixUniform); + st.uniform(gl, pmvMatrixUniform); + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + + final GLArrayDataServer vertices0 = GLArrayDataServer.createGLSL("gca_Vertices", 3, GL.GL_FLOAT, false, 4, GL.GL_STATIC_DRAW); + // st.bindAttribLocation(gl, 0, vertices0); + vertices0.putf(0); vertices0.putf(1); vertices0.putf(0); + vertices0.putf(1); vertices0.putf(1); vertices0.putf(0); + vertices0.putf(0); vertices0.putf(0); vertices0.putf(0); + vertices0.putf(1); vertices0.putf(0); vertices0.putf(0); + vertices0.seal(gl, true); + st.ownAttribute(vertices0, true); + vertices0.enableBuffer(gl, false); + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + + final GLArrayDataServer colors0 = GLArrayDataServer.createGLSL("gca_Colors", 4, GL.GL_FLOAT, false, 4, GL.GL_STATIC_DRAW); + // st.bindAttribLocation(gl, 1, colors0); + colors0.putf(1); colors0.putf(0); colors0.putf(1); colors0.putf(1); + colors0.putf(0); colors0.putf(0); colors0.putf(1); colors0.putf(1); + colors0.putf(0); colors0.putf(0); colors0.putf(0); colors0.putf(1); + colors0.putf(0); colors0.putf(1); colors0.putf(1); colors0.putf(1); + colors0.seal(gl, true); + st.ownAttribute(colors0, true); + colors0.enableBuffer(gl, false); + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + + final GLUniformData texUnit0 = new GLUniformData("gcs_TexUnit0", 0); + st.ownUniform(texUnit0); + st.uniform(gl, texUnit0); + final GLUniformData texUnit1 = new GLUniformData("gcs_TexUnit1", 1); + st.ownUniform(texUnit1); + st.uniform(gl, texUnit1); + + final GLArrayDataServer texCoords0 = GLArrayDataServer.createGLSL("gca_TexCoords", 2, GL.GL_FLOAT, false, 4, GL.GL_STATIC_DRAW); + // st.bindAttribLocation(gl, 2, texCoords0); + texCoords0.putf(0f); texCoords0.putf(1f); + texCoords0.putf(1f); texCoords0.putf(1f); + texCoords0.putf(0f); texCoords0.putf(0f); + texCoords0.putf(1f); texCoords0.putf(0f); + texCoords0.seal(gl, true); + st.ownAttribute(texCoords0, true); + texCoords0.enableBuffer(gl, false); + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + + final int texA0Point = 0; // attachment point for texA0 + final int texA1Point = 1; // attachment point for texA1 + + // FBO w/ 2 texture2D color buffers + final FBObject fbo_mrt = new FBObject(); + fbo_mrt.reset(gl, drawable.getWidth(), drawable.getHeight()); + final TextureAttachment texA0 = fbo_mrt.attachTexture2D(gl, texA0Point, true, GL.GL_NEAREST, GL.GL_NEAREST, GL.GL_CLAMP_TO_EDGE, GL.GL_CLAMP_TO_EDGE); + final TextureAttachment texA1 = fbo_mrt.attachTexture2D(gl, texA1Point, true, GL.GL_NEAREST, GL.GL_NEAREST, GL.GL_CLAMP_TO_EDGE, GL.GL_CLAMP_TO_EDGE); + fbo_mrt.attachRenderbuffer(gl, Type.DEPTH, 24); + Assert.assertTrue( fbo_mrt.isStatusValid() ) ; + fbo_mrt.unbind(gl); + + // misc GL setup + gl.glClearColor(1, 1, 1, 1); + gl.glEnable(GL2ES2.GL_DEPTH_TEST); + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + + // reshape + pmvMatrix.glMatrixMode(PMVMatrix.GL_PROJECTION); + pmvMatrix.glLoadIdentity(); + pmvMatrix.glOrthof(0f, 1f, 0f, 1f, -10f, 10f); + pmvMatrix.glMatrixMode(PMVMatrix.GL_MODELVIEW); + pmvMatrix.glLoadIdentity(); + st.uniform(gl, pmvMatrixUniform); + Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); + + final int[] two_buffers = new int[] { GL.GL_COLOR_ATTACHMENT0+texA0Point, GL.GL_COLOR_ATTACHMENT0+texA1Point }; + final int[] bck_buffers = new int[] { GL2GL3.GL_BACK_LEFT }; + + final GLReadBufferUtil screenshot = new GLReadBufferUtil(true, false); + int step_i = 0; + int[] last_snap_size = new int[] { 0, 0 }; + + for(int i=0; i buffer0, Green -> buffer1 + st.attachShaderProgram(gl, sp0, true); + vertices0.enableBuffer(gl, true); + colors0.enableBuffer(gl, true); + + fbo_mrt.bind(gl); + gl.glDrawBuffers(2, two_buffers, 0); + gl.glViewport(0, 0, fbo_mrt.getWidth(), fbo_mrt.getHeight()); + + gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); + gl.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 4); + fbo_mrt.unbind(gl); + vertices0.enableBuffer(gl, false); + colors0.enableBuffer(gl, false); + + // pass 2 - mix buffer0, buffer1 and blue + // rg = buffer0.rg + buffer1.rg, b = Blue - length(rg); + st.attachShaderProgram(gl, sp1, true); + vertices0.enableBuffer(gl, true); + colors0.enableBuffer(gl, true); + texCoords0.enableBuffer(gl, true); + gl.glDrawBuffers(1, bck_buffers, 0); + + gl.glViewport(0, 0, drawable.getWidth(), drawable.getHeight()); + + 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); + vertices0.enableBuffer(gl, false); + 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); + } + + public static void main(String args[]) throws IOException { + System.err.println("main - start"); + for(int i=0; i "+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()= 0; i--) { - immModeSink.glVertex3f((float) (radius * Math.cos(i * increment)), - (float) (radius * Math.sin(i * increment)), - 0f); - immModeSink.glVertex3f((float) (-1.0 * radius * Math.cos(i * increment)), - (float) (-1.0 * radius * Math.sin(i * increment)), - 0f); - } - immModeSink.glEnd(gl, false); - } - - public void dispose(GLAutoDrawable drawable) { - immModeSink.destroy(drawable.getGL()); - immModeSink = null; - } - - public void display(GLAutoDrawable drawable) { - GL2ES1 gl = drawable.getGL().getGL2ES1(); - if (multisample) { - gl.glEnable(GL.GL_MULTISAMPLE); - } - gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); - immModeSink.draw(gl, true); - if (multisample) { - gl.glDisable(GL.GL_MULTISAMPLE); - } - } - - // Unused routines - public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { - } - - public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) { - } -} 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..b2dad1f39 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/caps/TestMultisampleES2NEWT.java @@ -0,0 +1,143 @@ +/* + * 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 + private GLWindow window; + + public static void main(String[] args) { + for(int i=0; i0) { + caps.setSampleBuffers(true); + caps.setNumSamples(reqSamples); + } + + 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/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/demos/es1/MultisampleDemoES1.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/MultisampleDemoES1.java new file mode 100644 index 000000000..aad56581b --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es1/MultisampleDemoES1.java @@ -0,0 +1,123 @@ +/* + * 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.es1; + +import javax.media.opengl.GL; +import javax.media.opengl.GL2ES1; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLEventListener; + +import com.jogamp.opengl.util.ImmModeSink; + +public class MultisampleDemoES1 implements GLEventListener { + + boolean multisample; + ImmModeSink immModeSink; + + public MultisampleDemoES1(boolean multisample) { + this.multisample = multisample; + } + + public void init(GLAutoDrawable drawable) { + System.err.println(); + System.err.println("Requested: " + drawable.getNativeSurface().getGraphicsConfiguration().getRequestedCapabilities()); + System.err.println(); + System.err.println("Chosen : " + drawable.getChosenGLCapabilities()); + System.err.println(); + GL2ES1 gl = drawable.getGL().getGL2ES1(); + 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.glMatrixMode(GL2ES1.GL_MODELVIEW); + gl.glLoadIdentity(); + gl.glMatrixMode(GL2ES1.GL_PROJECTION); + gl.glLoadIdentity(); + gl.glOrtho(-1, 1, -1, 1, -1, 1); + if (multisample) { + gl.glDisable(GL.GL_MULTISAMPLE); + } + immModeSink = ImmModeSink.createFixed(gl, GL.GL_STATIC_DRAW, 40, + 3, GL.GL_FLOAT, // vertex + 0, 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.glVertex3f((float) (-1.0 * radius * Math.cos(i * increment)), + (float) (-1.0 * radius * Math.sin(i * increment)), + 0f); + } + immModeSink.glEnd(gl, false); + } + + public void dispose(GLAutoDrawable drawable) { + immModeSink.destroy(drawable.getGL()); + immModeSink = null; + } + + public void display(GLAutoDrawable drawable) { + GL2ES1 gl = drawable.getGL().getGL2ES1(); + if (multisample) { + gl.glEnable(GL.GL_MULTISAMPLE); + } + gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); + immModeSink.draw(gl, true); + if (multisample) { + gl.glDisable(GL.GL_MULTISAMPLE); + } + } + + // Unused routines + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { + } + + public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) { + } +} 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..436c44759 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,9 @@ */ package com.jogamp.opengl.test.junit.jogl.demos.es2; +import com.jogamp.newt.Window; import com.jogamp.newt.event.MouseAdapter; import com.jogamp.newt.event.MouseEvent; -import com.jogamp.newt.opengl.GLWindow; import com.jogamp.opengl.util.GLArrayDataServer; import com.jogamp.opengl.util.PMVMatrix; import com.jogamp.opengl.util.glsl.ShaderCode; @@ -37,10 +37,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 { @@ -52,10 +50,11 @@ public class RedSquareES2 implements GLEventListener { 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 +64,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,13 +129,13 @@ 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); + final Object upstreamWidget = glad.getUpstreamWidget(); + if (!isFBOSlave && upstreamWidget instanceof Window) { + window = (Window) upstreamWidget; + window.addMouseListener(myMouse); } t0 = System.currentTimeMillis(); System.err.println(Thread.currentThread()+" RedSquareES2.init FIN"); @@ -145,6 +145,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 +172,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,9 +195,9 @@ public class RedSquareES2 implements GLEventListener { } isInitialized = false; System.err.println(Thread.currentThread()+" RedSquareES2.dispose ... "); - if (null != glWindow) { - glWindow.removeMouseListener(myMouse); - glWindow = null; + if (null != window) { + window.removeMouseListener(myMouse); + window = null; } GL2ES2 gl = glad.getGL().getGL2ES2(); st.destroy(gl); @@ -207,24 +210,9 @@ public class RedSquareES2 implements GLEventListener { 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; - } - }); - } + if(null != window && e.getSource() == window) { + window.setFullscreen(!window.isFullscreen()); + System.err.println("setFullscreen: "+window.isFullscreen()); } } } 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..797a16485 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 @@ -258,7 +258,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= height. + * + * Draws the Gears demo in a window that's twice as wide than it is tall, + * and checks to see if a particular pixel in the right half of the frame + * is colored. + * + * @author Wade Walker (adapted from TestGearsGLJPanelAWT) + */ +public class TestGLJPanelAWTBug450 extends UITestCase { + static GLProfile glp; + static int width, height; + static int r_x, r_y; + /** Set this if test fails. Needed because we can't throw an exception + * all the way up the stack from where we test the pixel. */ + static boolean failed; + + @BeforeClass + public static void initClass() { + glp = GLProfile.getGL2ES2(); + Assert.assertNotNull(glp); + height = 256; + width = 2*height; + r_x = 5*height/4; // 5/8 * width + r_y = height/2; + } + + @AfterClass + public static void releaseClass() { + } + + 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); + + GLJPanel glJPanel = new GLJPanel(caps); + Assert.assertNotNull(glJPanel); + RedSquareES2 demo = new RedSquareES2(); + demo.setAspect((float)width/(float)height); + demo.setDoRotation(false); + glJPanel.addGLEventListener(demo); + glJPanel.addGLEventListener(new GLEventListener() { + int f = 0; + @Override + public void init(GLAutoDrawable drawable) { + // drawable.getGL().glClearColor(0, 0, 1, 1); + } + @Override + public void display(GLAutoDrawable drawable) { + // look at one pixel at the bottom of the frame, just right of + // the center line, and make sure it's not black + GL2 gl = GLUgl2.getCurrentGL2(); + ByteBuffer bytebuffer = ByteBuffer.allocateDirect( 3 ); + gl.glReadPixels( r_x, r_y, 1, 1, GL2.GL_BGR, GL2.GL_UNSIGNED_BYTE, bytebuffer ); + byte byte0 = bytebuffer.get( 0 ); + byte byte1 = bytebuffer.get( 1 ); + byte byte2 = bytebuffer.get( 2 ); + if( (byte0 == 0) && (byte1 == 0) && (byte2 == 0) ) { + failed = true; + } + if(0 == f) { + System.err.println("BGR ("+r_x+"/"+r_y+"): "+byte0+", "+byte1+", "+byte2+" - OK "+(!failed)); + snapshot(getSimpleTestName("."), f, null, gl, screenshot, TextureIO.PNG, null); + } + f++; + } + @Override + public void dispose(GLAutoDrawable drawable) {} + @Override + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { } + }); + + FPSAnimator animator = new FPSAnimator(glJPanel, 60); + + final JFrame _frame = frame; + final GLJPanel _glJPanel = glJPanel; + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + _frame.getContentPane().add(_glJPanel, BorderLayout.CENTER); + _frame.setSize(width, height); + _frame.setVisible(true); + } } ) ; + + animator.setUpdateFPSFrames(1, null); + animator.start(); + Assert.assertEquals(true, animator.isAnimating()); + + while(animator.isAnimating() && animator.getTotalFPSDuration()= height. - * - * Draws the Gears demo in a window that's twice as wide than it is tall, - * and checks to see if a particular pixel in the right half of the frame - * is colored. - * - * @author Wade Walker (adapted from TestGearsGLJPanelAWT) - */ -public class TestGearsGLJPanelAWTBug450 extends UITestCase { - static GLProfile glp; - static int width, height; - static int r_x, r_y; - /** Set this if test fails. Needed because we can't throw an exception - * all the way up the stack from where we test the pixel. */ - static boolean failed; - - @BeforeClass - public static void initClass() { - glp = GLProfile.getGL2ES2(); - Assert.assertNotNull(glp); - height = 256; - width = 2*height; - r_x = 5*height/4; // 5/8 * width - r_y = height/2; - } - - @AfterClass - 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 - { - JFrame frame = new JFrame("Swing GLJPanel"); - Assert.assertNotNull(frame); - - GLJPanel glJPanel = new GLJPanel(caps); - Assert.assertNotNull(glJPanel); - RedSquareES2 demo = new RedSquareES2(); - demo.setAspect((float)width/(float)height); - demo.setDoRotation(false); - glJPanel.addGLEventListener(demo); - glJPanel.addGLEventListener(new GLEventListener() { - int f = 0; - @Override - public void init(GLAutoDrawable drawable) { - // drawable.getGL().glClearColor(0, 0, 1, 1); - } - @Override - public void display(GLAutoDrawable drawable) { - // look at one pixel at the bottom of the frame, just right of - // the center line, and make sure it's not black - GL2 gl = GLUgl2.getCurrentGL2(); - ByteBuffer bytebuffer = ByteBuffer.allocateDirect( 3 ); - gl.glReadPixels( r_x, r_y, 1, 1, GL2.GL_BGR, GL2.GL_UNSIGNED_BYTE, bytebuffer ); - byte byte0 = bytebuffer.get( 0 ); - byte byte1 = bytebuffer.get( 1 ); - byte byte2 = bytebuffer.get( 2 ); - if( (byte0 == 0) && (byte1 == 0) && (byte2 == 0) ) { - failed = true; - } - if(0 == f) { - System.err.println("BGR ("+r_x+"/"+r_y+"): "+byte0+", "+byte1+", "+byte2+" - OK "+(!failed)); - snapshot(drawable, true, false, getSimpleTestName(".")+".png"); - } - f++; - } - @Override - public void dispose(GLAutoDrawable drawable) {} - @Override - public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { } - }); - - FPSAnimator animator = new FPSAnimator(glJPanel, 60); - - final JFrame _frame = frame; - final GLJPanel _glJPanel = glJPanel; - SwingUtilities.invokeAndWait(new Runnable() { - public void run() { - _frame.getContentPane().add(_glJPanel, BorderLayout.CENTER); - _frame.setSize(width, height); - _frame.setVisible(true); - } } ) ; - - animator.setUpdateFPSFrames(1, null); - animator.start(); - Assert.assertEquals(true, animator.isAnimating()); - - while(animator.isAnimating() && animator.getTotalFPSDuration() buffer0, Green -> buffer1 - st.attachShaderProgram(gl, sp0, true); - vertices0.enableBuffer(gl, true); - colors0.enableBuffer(gl, true); - - fbo_mrt.bind(gl); - gl.glDrawBuffers(2, two_buffers, 0); - gl.glViewport(0, 0, fbo_mrt.getWidth(), fbo_mrt.getHeight()); - - gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); - gl.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 4); - fbo_mrt.unbind(gl); - vertices0.enableBuffer(gl, false); - colors0.enableBuffer(gl, false); - - // pass 2 - mix buffer0, buffer1 and blue - // rg = buffer0.rg + buffer1.rg, b = Blue - length(rg); - st.attachShaderProgram(gl, sp1, true); - vertices0.enableBuffer(gl, true); - colors0.enableBuffer(gl, true); - texCoords0.enableBuffer(gl, true); - 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.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); - gl.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 4); - fbo_mrt.unuse(gl); - vertices0.enableBuffer(gl, false); - colors0.enableBuffer(gl, false); - texCoords0.enableBuffer(gl, false); - - drawable.swapBuffers(); - Thread.sleep(50); - } - - NEWTGLContext.destroyWindow(winctx); - } - - public static void main(String args[]) throws IOException { - System.err.println("main - start"); - for(int i=0; i 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/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: + *
      +     * TestFBODrawableNEWT.test01-F_rgba-I_rgba-S0_default-GL2-n0004-0800x0600.png
      +     * TestFBODrawableNEWT.test01-F_rgba-I_rgba-S0_default-GL2-n0005-0800x0600.png
      +     * 
      + * + * @param simpleTestName will be used as the filename prefix + * @param sn sequential number + * @param postSNDetail optional detail to be added to the filename after sn + * @param gl the current GL context object. It's read drawable is being used as the pixel source and to gather some details which will end up in the filename. + * @param readBufferUtil the {@link GLReadBufferUtil} to be used to read the pixels for the screenshot. + * @param fileSuffix Optional file suffix without a dot defining the file type, i.e. "png". + * If null the "png" as defined in {@link TextureIO#PNG} is being used. + * @param destPath Optional platform dependent file path. It shall use {@link File#separatorChar} as is directory separator. + * It shall not end with a directory separator, {@link File#separatorChar}. + * If null the current working directory is being used. + */ + public static void snapshot(String simpleTestName, int sn, String postSNDetail, GL gl, GLReadBufferUtil readBufferUtil, String fileSuffix, String destPath) { + if(null == fileSuffix) { + fileSuffix = TextureIO.PNG; + } + final StringWriter filenameSW = new StringWriter(); + { + final GLDrawable drawable = gl.getContext().getGLReadDrawable(); + final GLCapabilitiesImmutable caps = drawable.getChosenGLCapabilities(); + final String F_pfmt = readBufferUtil.hasAlpha() ? "rgba" : "rgb_"; + final String pfmt = caps.getAlphaBits() > 0 ? "rgba" : "rgb_"; + final String aaext = caps.getSampleExtension(); + final int samples = caps.getNumSamples() ; + postSNDetail = null != postSNDetail ? "-"+postSNDetail : ""; + final PrintWriter pw = new PrintWriter(filenameSW); + pw.printf("%s-n%04d%s-F_%s-I_%s-S%d_%s-%s-%04dx%04d.%s", + simpleTestName, sn, postSNDetail, F_pfmt, pfmt, samples, aaext, drawable.getGLProfile().getName(), + drawable.getWidth(), drawable.getHeight(), fileSuffix); + } + final String filename = null != destPath ? destPath + File.separator + filenameSW.toString() : filenameSW.toString(); + System.err.println(Thread.currentThread().getName()+": ** screenshot: "+filename); + gl.glFinish(); // just make sure rendering finished .. + if(readBufferUtil.readPixels(gl, false)) { + readBufferUtil.write(new File(filename)); + } + } } -- cgit v1.2.3 From 4dd44b985fe0541be3a3bcd9045d201ed3ca2cc5 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Sat, 15 Sep 2012 16:54:52 +0200 Subject: Seamless Integration of an FBObject based GLFBODrawable as GLOffscreenAutoDrawable.FBO and as an OffscreenLayerSurface's drawable (OSX) - Fix Bugs 569 and 599 Summary: ========= The new FBObject based GLFBODrawable implementation allows the seamless utilization of FBO offscreen rendering in single buffer, double buffer and MSAA mode. The GLFBODrawable uses a parent drawable based on a dummy surface to allow a GLOffscreenAutoDrawable.FBO creation or a mutable surface supporting an existing offscreen layer surface (OSX CALayer). Offscreen GLDrawable's and GLOffscreenAutoDrawable's can be selected via the GLCapabilities. If simply !onscreen is selected in the caps instance w/o enabling FBO, PBuffer or Bitmap, the factory will automatically choose regarding availability: FBO > PBuffer > Bitmap Double buffering is supported in MSAA more (intrinsic) and explicit in non MSAA. It is preferred when delivering resources (texture id's or framebuffer names) to a shared GLContext. This is demonstrated in (emulates our OSX CALayer implementation): TestFBOOffThreadSharedContextMix2DemosES2NEWT, TestFBOOnThreadSharedContext1DemoES2NEWT and with the OSX JAWT OffscreenLayerSurface itself. FBO is the preferred choice. +++ Offscreen drawables can be resized while maintaining a bound GLContext (e.g. w/ GLAutoDrawable). Previously both, drawable and context, needed to be destroyed and recreated at offscreen resize. Common implementation in GLDrawableHelper is used in the implementations (NEWT's GLWindow, AWT GLCanvas, SWT GLCanvas). +++ Tested: ======= Manually run all unit tests on: - Linux x86_64 NVidia/AMD/Mesa3d(ES) - OSX x86_64 NVidia - Windows x86_64 NVidia - Android arm Mali-400/Tegra-2 No regressions. Disclaimer: =========== This feature is committed almost in one patch. Both previous commits were introducing / fixing the capabilities behavior: 90d45928186f2be99999461cfe45f76a783cc961 9036376b7806a5fc61590bf49404eb71830de92f I have to appologize for the huge size and impact (files and platforms) of this commit however, I could not find a better way to inject this feature in one sane piece. NativeWindow Details: ===================== Complete decoupling of platform impl. detail of surfaces implementing ProxySurface. Used to generalize dummy surfaces and EGL surfaces on top of a native platform surface. - ProxySurface.UpstreamSurfaceHook -> UpstreamSurfaceHook - abstract class ProxySurface -> interface ProxySurface + ProxySurfaceImpl - Misc. implementations JOGL Details: ===================== FBOObject: API Change / Simplification & Usability - Removed reference counter to remove complexity, allow user to choose. - Add 'dispose' flag for detachColorbuffer(..), allowing to keep attachment alive - Fix equals operation of Attachment - Check pre-exising GL errors - Interface Colobuffer gets lifecycle methods - Add static factory methods to create Attachments w/o FBObject instance - Reset: - Clip min size to 1 - Keep alive samplingSink, i.e. don't issue resetMSAATexture2DSink(..). It gets called at syncFramebuffer()/use(..) later on before actual usage. This allows the consumer to utilize the GL_FRONT buffer until (e.g.) swap. - misc bugfixes GLOffscreenAutoDrawable: API Change - Reloc and interfacing - class com.jogamp.opengl.OffscreenAutoDrawable -> javax.media.opengl.* interfaces GLOffscreenAutoDrawable extends GLAutoDrawable GLOffscreenAutoDrawable.FBO extends GLOffscreenAutoDrawable, GLFBODrawable - Added general implementation and FBO specialization - Replacing GLPBuffer (deprecated) .. usable for any offscreen GLDrawable via factory GLAutoDrawable: - Add 'GLDrawable getDelegatedDrawable()' - Refine documentation of setContext(..), remove disclaimer and fixme tags GLDrawableFactory: - Refine API doc and it's selection mechanism for offscreen. - Add createOffscreenDrawable(..) - Add createOffscreenAutoDrawable(..) - Add canCreateFBO(..) - Mark createGLPbuffer(..) deprectated Mark GLPBuffer deprecated New: GLFBODrawable extends GLDrawable GLCanvas (AWT and SWT): Add offscreen resize support w/o GLContext recreation GLAutoDrawableBase .. GLWindow: - Add offscreen resize support w/o GLContext recreation - Remove double swapBuffer call - GLBase/GLContext: - Add: - boolean hasBasicFBOSupport() - boolean hasFullFBOSupport() - int getMaxRenderbufferSamples() - boolean isTextureFormatBGRA8888Available() GLContext: Fix version detection and hasGLSL() - Version detection in setGLFunctionAvailability(..) - Query GL_VERSION ASAP and parse it and compare w/ given major/minor - Use parsed version if valid and lower than given _or_ given is invalid. - Use validated version for caching (procaddr, ..), version number, etc. - Fix hasGLSL() Since 'isGL2ES2()' is true if 'isGL2()' and the latter simply alows GL 1.*, we confine the result to a GL >= 2.0 on desktops. FIXME: May consider GL 1.5 w/ extensions. - return isGL2ES2(); + return isGLES2() || + isGL3() || + isGL2() && ctxMajorVersion>1 ; GLDrawableImpl: - Add 'associateContext(GLContext, boolean)' allowing impl. to have a (weak) reference list of bound context. This is was pulled up from the OSX specific drawable impl. - swapBuffersImpl() -> swapBuffersImpl(boolean doubleBuffered) and call it regardless of single buffering. This is required to propagate this event to impl. properly, i.e. FBODrawable requires a swap notification. - Clarify 'contextMadeCurrent(..)' protocol GLDrawableHelper: - Add resize and recreate offscreen drawable util method - Simplify required init/reshape calls for GLEventListener - GLGraphicsConfigurationUtil: - fixWinAttribBitsAndHwAccel: Reflect sharede context hw-accel bits - OSX has no offscreen bitmap, use pbuffer - use proper offscreen auto selection if offscreen and no modes are set EGL Context/Drawable/DrawableFactory: Abstract native platform code out of base classes - Use EGLWrappedSurface w/ UpstreamSurfaceHook to handle upstream (X11, WGL, ..) lifecycle - in case the EGL resource is hooked up on it. Invisible dummy surfaces: All platforms - size is now reduced to 64x64 and decoupled of actual generic mutable size - fix device lifecycle, no more leaks +++ OSX ==== Enable support for GLFBODrawableImpl in offscreen CALayer mode - NSOpenGLImpl: hooks to calayer native code - calayer code: - allows pbuffer and texures (FBO) - decouple size and draw calls avoiding flickering - enable auto resize of calayer tree MacOSXCGLContext: - NSOpenGLImpl: - Fix false pbuffer 'usage', validate the pointer - If !pbuffer, copy other window mode bits of caps - MacOSXCGLGraphicsConfiguration: - Only assume pbuffer if !onscreen - Remove reference of native pixelformat pointer Native code: - use 'respondsToSelector:' query before calling 'new' methods avoiding an error message where unsuported (prev. OSX versions) - if monitor refresh-rate is queried 0, set to default 60hz - add missing NSAutoreleasePool decoration +++ Android / NEWT: =============== Issue setVisible(..) w/o wait, i.e. queue on EDT, @Android surfaceChanged() callback. Otherwise we could deadlock: setVisible(..) -> EDT -> setVisibleImpl(..) -> 'GL-display'. the latter may may cause havoc while Android-EDT is blocked [until it's return]. --- doc/TODO.txt | 12 - make/build-jogl.xml | 2 +- .../config/jogl/gl-impl-CustomJavaCode-common.java | 20 + make/scripts/java-win64-dbg.bat | 4 +- make/scripts/tests-x64.bat | 45 +- make/scripts/tests.sh | 50 +- make/stub_includes/opengl/macosx-window-system.h | 11 +- src/jogl/classes/com/jogamp/opengl/FBObject.java | 882 +++++++++++++-------- .../com/jogamp/opengl/GLAutoDrawableDelegate.java | 189 +++++ .../classes/com/jogamp/opengl/GLExtensions.java | 3 + .../com/jogamp/opengl/OffscreenAutoDrawable.java | 112 --- .../classes/com/jogamp/opengl/swt/GLCanvas.java | 41 +- .../classes/javax/media/opengl/GLAutoDrawable.java | 38 +- .../javax/media/opengl/GLAutoDrawableDelegate.java | 144 ---- src/jogl/classes/javax/media/opengl/GLBase.java | 38 + src/jogl/classes/javax/media/opengl/GLContext.java | 97 ++- .../javax/media/opengl/GLDrawableFactory.java | 128 ++- .../classes/javax/media/opengl/GLFBODrawable.java | 173 ++++ .../media/opengl/GLOffscreenAutoDrawable.java | 63 ++ src/jogl/classes/javax/media/opengl/GLPbuffer.java | 6 +- .../classes/javax/media/opengl/awt/GLCanvas.java | 119 +-- .../classes/javax/media/opengl/awt/GLJPanel.java | 13 +- .../classes/jogamp/opengl/GLAutoDrawableBase.java | 76 +- src/jogl/classes/jogamp/opengl/GLContextImpl.java | 175 ++-- .../jogamp/opengl/GLDrawableFactoryImpl.java | 127 +-- .../classes/jogamp/opengl/GLDrawableHelper.java | 185 ++++- src/jogl/classes/jogamp/opengl/GLDrawableImpl.java | 80 +- .../classes/jogamp/opengl/GLFBODrawableImpl.java | 496 ++++++++++-- .../jogamp/opengl/GLGraphicsConfigurationUtil.java | 28 +- .../jogamp/opengl/GLOffscreenAutoDrawableImpl.java | 123 +++ src/jogl/classes/jogamp/opengl/GLPbufferImpl.java | 31 +- src/jogl/classes/jogamp/opengl/egl/EGLContext.java | 6 - .../classes/jogamp/opengl/egl/EGLDrawable.java | 135 ++-- .../jogamp/opengl/egl/EGLDrawableFactory.java | 163 +--- .../opengl/egl/EGLDummyUpstreamSurfaceHook.java | 49 ++ .../jogamp/opengl/egl/EGLExternalContext.java | 11 - .../jogamp/opengl/egl/EGLGLCapabilities.java | 5 +- .../opengl/egl/EGLGraphicsConfiguration.java | 9 +- .../jogamp/opengl/egl/EGLOnscreenContext.java | 11 - .../jogamp/opengl/egl/EGLOnscreenDrawable.java | 4 +- .../jogamp/opengl/egl/EGLPbufferContext.java | 10 - .../jogamp/opengl/egl/EGLPbufferDrawable.java | 8 +- .../jogamp/opengl/egl/EGLUpstreamSurfaceHook.java | 145 +++- .../jogamp/opengl/egl/EGLWrappedSurface.java | 26 + .../jogamp/opengl/macosx/cgl/MacOSXCGLContext.java | 716 ++++++++++------- .../opengl/macosx/cgl/MacOSXCGLDrawable.java | 48 +- .../macosx/cgl/MacOSXCGLDrawableFactory.java | 71 +- .../macosx/cgl/MacOSXCGLGraphicsConfiguration.java | 21 +- .../cgl/MacOSXCGLGraphicsConfigurationFactory.java | 2 +- .../macosx/cgl/MacOSXExternalCGLContext.java | 7 +- .../macosx/cgl/MacOSXOnscreenCGLDrawable.java | 4 +- .../opengl/macosx/cgl/MacOSXPbufferCGLContext.java | 1 + .../macosx/cgl/MacOSXPbufferCGLDrawable.java | 42 +- .../windows/wgl/WindowsExternalWGLContext.java | 4 +- .../windows/wgl/WindowsExternalWGLDrawable.java | 4 +- .../opengl/windows/wgl/WindowsWGLDrawable.java | 43 +- .../windows/wgl/WindowsWGLDrawableFactory.java | 58 +- .../wgl/WindowsWGLGraphicsConfiguration.java | 29 +- .../WindowsWGLGraphicsConfigurationFactory.java | 28 +- .../opengl/x11/glx/X11ExternalGLXContext.java | 4 +- .../opengl/x11/glx/X11ExternalGLXDrawable.java | 5 +- .../jogamp/opengl/x11/glx/X11GLXDrawable.java | 7 +- .../opengl/x11/glx/X11GLXDrawableFactory.java | 63 +- .../x11/glx/X11GLXGraphicsConfiguration.java | 6 +- .../glx/X11GLXGraphicsConfigurationFactory.java | 6 +- .../opengl/x11/glx/X11PbufferGLXDrawable.java | 17 +- .../macosx/MacOSXWindowSystemInterface-calayer.m | 665 ++++++++++++++++ .../macosx/MacOSXWindowSystemInterface-pbuffer.m | 494 ------------ .../native/macosx/MacOSXWindowSystemInterface.m | 40 +- .../DelegatedUpstreamSurfaceHookMutableSize.java | 39 + ...elegatedUpstreamSurfaceHookWithSurfaceSize.java | 54 ++ .../UpstreamSurfaceHookMutableSize.java | 45 ++ .../com/jogamp/nativewindow/WrappedSurface.java | 78 -- .../com/jogamp/nativewindow/awt/JAWTWindow.java | 99 ++- .../jogamp/nativewindow/egl/EGLGraphicsDevice.java | 4 +- .../javax/media/nativewindow/NativeSurface.java | 5 +- .../media/nativewindow/OffscreenLayerSurface.java | 3 + .../javax/media/nativewindow/ProxySurface.java | 266 ++----- .../media/nativewindow/UpstreamSurfaceHook.java | 52 ++ .../jogamp/nativewindow/ProxySurfaceImpl.java | 326 ++++++++ .../jogamp/nativewindow/WrappedSurface.java | 95 +++ .../nativewindow/jawt/macosx/MacOSXJAWTWindow.java | 84 +- .../macosx/OSXDummyUpstreamSurfaceHook.java | 56 ++ .../jogamp/nativewindow/macosx/OSXUtil.java | 15 + .../windows/GDIDummyUpstreamSurfaceHook.java | 50 ++ .../jogamp/nativewindow/windows/GDISurface.java | 34 +- .../x11/X11DummyUpstreamSurfaceHook.java | 60 ++ src/nativewindow/native/macosx/OSXmisc.m | 189 +++-- .../classes/com/jogamp/newt/awt/NewtCanvasAWT.java | 9 + .../classes/com/jogamp/newt/opengl/GLWindow.java | 25 +- .../classes/com/jogamp/newt/swt/NewtCanvasSWT.java | 3 + src/newt/classes/jogamp/newt/OffscreenWindow.java | 31 +- src/newt/classes/jogamp/newt/WindowImpl.java | 34 +- .../jogamp/newt/driver/android/WindowDriver.java | 2 +- .../jogamp/newt/driver/macosx/WindowDriver.java | 24 +- src/newt/native/MacWindow.m | 49 +- .../test/android/MovieCubeActivityLauncher0.java | 2 + .../android/NEWTGraphUI1pActivityLauncher.java | 22 +- .../jogl/acore/TestFBOAutoDrawableDeadlockAWT.java | 128 +++ .../jogl/acore/TestFBOAutoDrawableFactoryNEWT.java | 375 +++++++++ .../test/junit/jogl/acore/TestFBODrawableNEWT.java | 272 ------- .../test/junit/jogl/acore/TestFBOMRTNEWT01.java | 2 +- .../junit/jogl/acore/TestFBOMix2DemosES2NEWT.java | 2 +- ...tFBOOffThreadSharedContextMix2DemosES2NEWT.java | 298 +++++++ .../TestFBOOnThreadSharedContext1DemoES2NEWT.java | 273 +++++++ .../jogl/acore/TestGLAutoDrawableDelegateNEWT.java | 152 ---- ...estGLAutoDrawableDelegateOnOffscrnCapsNEWT.java | 384 +++++++++ .../TestGLAutoDrawableFactoryOffscrnCapsNEWT.java | 317 ++++++++ ...TestGLAutoDrawableGLCanvasOnOffscrnCapsAWT.java | 328 ++++++++ ...estGLAutoDrawableGLWindowOnOffscrnCapsNEWT.java | 351 ++++++++ ...LAutoDrawableNewtCanvasAWTOnOffscrnCapsAWT.java | 300 +++++++ .../junit/jogl/acore/TestGLCapabilities01NEWT.java | 266 ------- .../acore/TestGLContextDrawableSwitchNEWT.java | 22 +- .../junit/jogl/acore/TestGLDrawable01NEWT.java | 171 ---- .../jogl/acore/TestGLExtensionQueryOffscreen.java | 19 +- .../jogl/acore/TestNEWTCloseX11DisplayBug565.java | 46 +- .../acore/TestOffscreenLayer01GLCanvasAWT.java | 236 ++++++ .../acore/TestOffscreenLayer02NewtCanvasAWT.java | 233 ++++++ .../junit/jogl/acore/TestPBufferDeadlockAWT.java | 2 + .../junit/jogl/acore/TestSharedContextListAWT.java | 20 +- .../jogl/acore/TestSharedContextListNEWT.java | 20 +- .../jogl/acore/TestSharedContextListNEWT2.java | 14 +- .../jogl/acore/TestSharedContextNewtAWTBug523.java | 17 +- .../jogl/acore/TestSharedContextVBOES1NEWT.java | 20 +- .../jogl/acore/TestSharedContextVBOES2NEWT.java | 20 +- .../jogl/acore/TestSharedContextVBOES2NEWT2.java | 14 +- .../awt/TestBug461FBOSupersamplingSwingAWT.java | 159 ++++ .../TestBug461OffscreenSupersamplingSwingAWT.java | 157 ---- .../TestBug461PBufferSupersamplingSwingAWT.java | 159 ++++ .../junit/jogl/caps/TestMultisampleES1AWT.java | 2 +- .../junit/jogl/caps/TestMultisampleES1NEWT.java | 2 +- .../junit/jogl/caps/TestMultisampleES2NEWT.java | 2 +- .../opengl/test/junit/jogl/demos/es1/GearsES1.java | 6 + .../test/junit/jogl/demos/es1/RedSquareES1.java | 19 +- .../test/junit/jogl/demos/es2/FBOMix2DemosES2.java | 5 +- .../opengl/test/junit/jogl/demos/es2/GearsES2.java | 17 +- .../test/junit/jogl/demos/es2/Mix2TexturesES2.java | 216 +++++ .../test/junit/jogl/demos/es2/RedSquareES2.java | 21 +- .../junit/jogl/demos/es2/awt/TestGearsES2AWT.java | 27 +- .../opengl/test/junit/jogl/demos/gl2/Gears.java | 13 +- .../jogl/demos/gl2/awt/TestGLJPanelAWTBug450.java | 2 +- .../test/junit/jogl/offscreen/ReadBufferBase.java | 2 +- .../test/junit/jogl/swt/TestNewtCanvasSWTGLn.java | 2 +- .../junit/jogl/swt/TestSWTJOGLGLCanvas01GLn.java | 2 +- .../TestGLReadBufferUtilTextureIOWrite01AWT.java | 4 +- .../TestGLReadBufferUtilTextureIOWrite01NEWT.java | 16 +- .../TestGLReadBufferUtilTextureIOWrite02AWT.java | 2 +- .../TestGLReadBufferUtilTextureIOWrite02NEWT.java | 2 +- .../util/texture/TestPNGTextureFromFileAWT.java | 2 +- .../util/texture/TestPNGTextureFromFileNEWT.java | 2 +- .../test/junit/newt/TestFocus01SwingAWTRobot.java | 21 +- .../test/junit/newt/TestFocus02SwingAWTRobot.java | 16 +- .../opengl/test/junit/newt/TestWindows01NEWT.java | 1 - .../parenting/NewtAWTReparentingKeyAdapter.java | 2 +- .../TestParentingOffscreenLayer01GLCanvasAWT.java | 211 ----- ...TestParentingOffscreenLayer02NewtCanvasAWT.java | 221 ------ .../opengl/test/junit/util/AWTRobotUtil.java | 39 +- .../opengl/test/junit/util/NEWTGLContext.java | 4 +- .../jogamp/opengl/test/junit/util/UITestCase.java | 109 ++- 159 files changed, 9357 insertions(+), 4643 deletions(-) create mode 100644 src/jogl/classes/com/jogamp/opengl/GLAutoDrawableDelegate.java delete mode 100644 src/jogl/classes/com/jogamp/opengl/OffscreenAutoDrawable.java delete mode 100644 src/jogl/classes/javax/media/opengl/GLAutoDrawableDelegate.java create mode 100644 src/jogl/classes/javax/media/opengl/GLFBODrawable.java create mode 100644 src/jogl/classes/javax/media/opengl/GLOffscreenAutoDrawable.java create mode 100644 src/jogl/classes/jogamp/opengl/GLOffscreenAutoDrawableImpl.java create mode 100644 src/jogl/classes/jogamp/opengl/egl/EGLDummyUpstreamSurfaceHook.java create mode 100644 src/jogl/classes/jogamp/opengl/egl/EGLWrappedSurface.java create mode 100644 src/jogl/native/macosx/MacOSXWindowSystemInterface-calayer.m delete mode 100644 src/jogl/native/macosx/MacOSXWindowSystemInterface-pbuffer.m create mode 100644 src/nativewindow/classes/com/jogamp/nativewindow/DelegatedUpstreamSurfaceHookMutableSize.java create mode 100644 src/nativewindow/classes/com/jogamp/nativewindow/DelegatedUpstreamSurfaceHookWithSurfaceSize.java create mode 100644 src/nativewindow/classes/com/jogamp/nativewindow/UpstreamSurfaceHookMutableSize.java delete mode 100644 src/nativewindow/classes/com/jogamp/nativewindow/WrappedSurface.java create mode 100644 src/nativewindow/classes/javax/media/nativewindow/UpstreamSurfaceHook.java create mode 100644 src/nativewindow/classes/jogamp/nativewindow/ProxySurfaceImpl.java create mode 100644 src/nativewindow/classes/jogamp/nativewindow/WrappedSurface.java create mode 100644 src/nativewindow/classes/jogamp/nativewindow/macosx/OSXDummyUpstreamSurfaceHook.java create mode 100644 src/nativewindow/classes/jogamp/nativewindow/windows/GDIDummyUpstreamSurfaceHook.java create mode 100644 src/nativewindow/classes/jogamp/nativewindow/x11/X11DummyUpstreamSurfaceHook.java create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOAutoDrawableDeadlockAWT.java create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOAutoDrawableFactoryNEWT.java delete mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBODrawableNEWT.java create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOOffThreadSharedContextMix2DemosES2NEWT.java create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOOnThreadSharedContext1DemoES2NEWT.java delete mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableDelegateNEWT.java create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableDelegateOnOffscrnCapsNEWT.java create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryOffscrnCapsNEWT.java create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableGLCanvasOnOffscrnCapsAWT.java create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT.java create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableNewtCanvasAWTOnOffscrnCapsAWT.java delete mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLCapabilities01NEWT.java delete mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLDrawable01NEWT.java create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/acore/TestOffscreenLayer01GLCanvasAWT.java create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/acore/TestOffscreenLayer02NewtCanvasAWT.java create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug461FBOSupersamplingSwingAWT.java delete mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug461OffscreenSupersamplingSwingAWT.java create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/awt/TestBug461PBufferSupersamplingSwingAWT.java create mode 100644 src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/Mix2TexturesES2.java delete mode 100644 src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParentingOffscreenLayer01GLCanvasAWT.java delete mode 100644 src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParentingOffscreenLayer02NewtCanvasAWT.java (limited to 'src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java') diff --git a/doc/TODO.txt b/doc/TODO.txt index 20a7a9071..0ce1fd3ac 100644 --- a/doc/TODO.txt +++ b/doc/TODO.txt @@ -1,13 +1,6 @@ Version 2.0: -- Fix ES2 detection if it fails (no egl pbuffer on nokia es2) ? - SIGG slides / video -- FBO Drawable w/ given NativeSurface - and OSX w/ JAWT - - Bug 569 - - Bug 599 - -- cleanup jocl build/jar/demos -- clean up . in jar names in all docs and tutorials - ES3 / GL 4.3 @@ -15,11 +8,6 @@ Version 2.0: WIP: -- GLPbuffer -> GLOffscreenAutoDrawable - - GLPbuffer GLDrawableFactory.createPbuffer() -> - GLOffscreenAutoDrawable GLDrawableFactory.createOffsceenAutoDrawable() - - Mark both deprecated! - - Optimize/Fix NIO caching of glMapBuffer/glUnmapBuffer - optimize the NIO caching, i.e. memory range, incr. reference count - _remove_ the cached object w/ decr. ref count, remove object diff --git a/make/build-jogl.xml b/make/build-jogl.xml index 40859845c..a72d6c77c 100644 --- a/make/build-jogl.xml +++ b/make/build-jogl.xml @@ -1375,7 +1375,7 @@ - + diff --git a/make/config/jogl/gl-impl-CustomJavaCode-common.java b/make/config/jogl/gl-impl-CustomJavaCode-common.java index b05ba2643..283a4e623 100644 --- a/make/config/jogl/gl-impl-CustomJavaCode-common.java +++ b/make/config/jogl/gl-impl-CustomJavaCode-common.java @@ -50,6 +50,26 @@ return null; } + @Override + public final boolean hasBasicFBOSupport() { + return _context.hasBasicFBOSupport(); + } + + @Override + public final boolean hasFullFBOSupport() { + return _context.hasFullFBOSupport(); + } + + @Override + public final int getMaxRenderbufferSamples() { + return _context.getMaxRenderbufferSamples(); + } + + @Override + public final boolean isTextureFormatBGRA8888Available() { + return _context.isTextureFormatBGRA8888Available(); + } + @Override public final GLContext getContext() { return _context; diff --git a/make/scripts/java-win64-dbg.bat b/make/scripts/java-win64-dbg.bat index 510ebf4dc..b63438534 100755 --- a/make/scripts/java-win64-dbg.bat +++ b/make/scripts/java-win64-dbg.bat @@ -30,13 +30,15 @@ REM set D_ARGS="-Djogl.debug.ExtensionAvailabilityCache" "-Djogl.debug=all" "-Dn REM set D_ARGS="-Djogl.debug=all" "-Dnewt.debug=all" "-Dnativewindow.debug=all" "-Djogamp.debug.NativeLibrary=true" REM set D_ARGS="-Djogl.debug.GLContext" "-Djogl.debug.ExtensionAvailabilityCache" "-Djogamp.debug.ProcAddressHelper=true" REM set D_ARGS="-Djogl.debug.GraphicsConfiguration" +REM set D_ARGS="-Djogl.debug.GLContext" "-Djogl.debug.GLDrawable" "-Dnativewindow.debug.GraphicsConfiguration" REM set D_ARGS="-Djogamp.debug.JNILibLoader=true" "-Djogamp.debug.NativeLibrary=true" "-Djogamp.debug.NativeLibrary.Lookup=true" "-Djogl.debug.GLProfile=true" REM set D_ARGS="-Djogl.debug=all" "-Dnewt.debug=all" "-Dnativewindow.debug=all" "-Djogamp.debug.Lock" "-Djogamp.debug.Lock.TraceLock" -set D_ARGS="-Djogl.debug=all" "-Dnativewindow.debug=all" +REM set D_ARGS="-Djogl.debug=all" "-Dnativewindow.debug=all" REM set D_ARGS="-Djogl.debug=all" REM set D_ARGS="-Djogl.debug.GLCanvas" "-Djogl.debug.Animator" "-Djogl.debug.GLContext" "-Djogl.debug.GLContext.TraceSwitch" "-Djogl.debug.DebugGL" "-Djogl.debug.TraceGL" REM set D_ARGS="-Djogl.debug.GLCanvas" "-Djogl.debug.Animator" "-Djogl.debug.GLContext" "-Djogl.debug.GLContext.TraceSwitch" "-Djogl.windows.useWGLVersionOf5WGLGDIFuncSet" REM set D_ARGS="-Djogl.debug.GLCanvas" "-Djogl.debug.Animator" "-Djogl.debug.GLContext" "-Djogl.debug.GLContext.TraceSwitch" +set D_ARGS="-Dnewt.debug.Window" REM set D_ARGS="-Dnewt.debug.Window" "-Dnewt.debug.Display" REM set D_ARGS="-Djogl.debug.GLDebugMessageHandler" "-Djogl.debug.DebugGL" "-Djogl.debug.TraceGL" REM set D_ARGS="-Djogl.debug.DebugGL" "-Djogl.debug.GLDebugMessageHandler" "-Djogl.debug.GLSLCode" diff --git a/make/scripts/tests-x64.bat b/make/scripts/tests-x64.bat index 22cce49aa..a4207b696 100755 --- a/make/scripts/tests-x64.bat +++ b/make/scripts/tests-x64.bat @@ -1,9 +1,9 @@ REM scripts\java-win64-dbg.bat jogamp.newt.awt.opengl.VersionApplet REM scripts\java-win64-dbg.bat com.jogamp.newt.opengl.GLWindow REM scripts\java-win64-dbg.bat javax.media.opengl.awt.GLCanvas -REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestGLCapabilities01NEWT $* -scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestShutdownCompleteNEWT $* -REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestShutdownCompleteAWT $* +REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.acore.TestGLCapabilities01NEWT %* +REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestShutdownCompleteNEWT %* +REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestShutdownCompleteAWT %* REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.acore.TestMainVersionGLWindowNEWT %* REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.offscreen.TestOffscreen01GLPBufferNEWT -time 5000 REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.awt.TestAWT01GLn @@ -40,13 +40,13 @@ REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.parenting.TestP REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.parenting.TestParenting03bAWT -time 100000 REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.parenting.TestParentingFocusTraversal01AWT %* REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.parenting.TestParentingOffscreenLayer01AWT %* -REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.parenting.TestParenting01aSWT $* -REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.parenting.TestParenting04AWT $* -REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.parenting.TestParenting04SWT $* +REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.parenting.TestParenting01aSWT %* +REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.parenting.TestParenting04AWT %* +REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.parenting.TestParenting04SWT %* -REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.swt.TestSWTAccessor03AWTGLn $* -REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.swt.TestSWTJOGLGLCanvas01GLn $* -REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.swt.TestNewtCanvasSWTGLn $* +REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.swt.TestSWTAccessor03AWTGLn %* +REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.swt.TestSWTJOGLGLCanvas01GLn %* +REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.swt.TestNewtCanvasSWTGLn %* REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.TestWindows01NEWT REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.newt.TestGLWindows01NEWT @@ -73,9 +73,9 @@ REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.caps.TestMultis REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.awt.TestBug461OffscreenSupersamplingSwingAWT REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.glsl.TestShaderCompilationBug459AWT -REM scripts\java-win64.bat com.jogamp.opengl.test.junit.newt.TestWindowClosingProtocol01AWT $* -REM scripts\java-win64.bat com.jogamp.opengl.test.junit.newt.TestWindowClosingProtocol02NEWT $* -REM scripts\java-win64.bat com.jogamp.opengl.test.junit.newt.TestWindowClosingProtocol03NewtAWT $* +REM scripts\java-win64.bat com.jogamp.opengl.test.junit.newt.TestWindowClosingProtocol01AWT %* +REM scripts\java-win64.bat com.jogamp.opengl.test.junit.newt.TestWindowClosingProtocol02NEWT %* +REM scripts\java-win64.bat com.jogamp.opengl.test.junit.newt.TestWindowClosingProtocol03NewtAWT %* REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.swt.TestSWT01GLn %* REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.swt.TestSWT02GLn %* @@ -96,16 +96,25 @@ REM scripts\java-win64.bat com.jogamp.opengl.test.junit.graph.demos.GPUTextNewtD REM scripts\java-win64.bat com.jogamp.opengl.test.junit.graph.demos.GPURegionNewtDemo01 REM scripts\java-win64.bat com.jogamp.opengl.test.junit.graph.demos.GPURegionNewtDemo02 -REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestGLDebug00NEWT $* -REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.acore.TestGLDebug01NEWT $* +REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestGLDebug00NEWT %* +REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.acore.TestGLDebug01NEWT %* -REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestGPUMemSec01NEWT $* -REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.acore.TestGPUMemSec01NEWT $* +REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestGPUMemSec01NEWT %* +REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.acore.TestGPUMemSec01NEWT %* REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestMapBuffer01NEWT +scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableDelegateOnOffscrnCapsNEWT $* +REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT $* +REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableGLCanvasOnOffscrnCapsAWT $* +REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableFactoryOffscrnCapsNEWT $* + +REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestFBOAutoDrawableFactoryNEWT $* +REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestFBOAutoDrawableOffThreadSharedContextES2NEWT $* +REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestFBOMix2DemosES2NEWT $* +REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestFBOMRTNEWT01 $* +REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestFBOAutoDrawableDeadlockAWT $* +REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.awt.TestBug461FBOSupersamplingSwingAWT REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.glsl.TestRulerNEWT01 -REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.acore.TestFBODrawableNEWT %* -REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.glsl.TestFBOMRTNEWT01 %* REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestElektronenMultipliziererNEWT %* diff --git a/make/scripts/tests.sh b/make/scripts/tests.sh index ce04ae4dc..d2e2db375 100755 --- a/make/scripts/tests.sh +++ b/make/scripts/tests.sh @@ -32,7 +32,7 @@ MOSX=0 MOSX_MT=0 uname -a | grep -i Darwin && MOSX=1 if [ $MOSX -eq 1 ] ; then - #export NSZombieEnabled=YES + export NSZombieEnabled=YES MOSX_MT=1 fi @@ -56,11 +56,13 @@ function jrun() { #D_ARGS="-Djogl.disable.opengles" #D_ARGS="-Djogl.debug.DebugGL -Djogl.debug.GLSLCode -Dnewt.debug.Window.MouseEvent" #D_ARGS="-Djogl.debug.TraceGL -Djogl.debug.DebugGL -Djogl.debug.GLSLCode" + #D_ARGS="-Djogl.debug.FBObject -Djogl.debug.GLContext -Djogl.debug.GLDrawable -Djogl.debug.GLCanvas -Dnewt.debug.Window" #D_ARGS="-Djogl.debug.FBObject" #D_ARGS="-Dnativewindow.debug.GraphicsConfiguration -Djogl.debug.GLDrawable -Djogl.debug.GLContext -Djogl.debug.FBObject" #D_ARGS="-Djogl.debug.GLContext.NoProfileAliasing" #D_ARGS="-Djogamp.debug=all -Dnativewindow.debug=all -Djogl.debug=all -Dnewt.debug=all" - #D_ARGS="-Djogl.debug=all -Dnativewindow.debug=all -Dnewt.debug=all" + #D_ARGS="-Dnativewindow.debug=all -Djogl.debug=all -Dnewt.debug=all" + #D_ARGS="-Djogl.debug.GLContext -Djogl.debug.GLDrawable -Dnativewindow.debug.GraphicsConfiguration" #D_ARGS="-Djogl.fbo.force.none" #D_ARGS="-Djogl.debug=all -Dnativewindow.debug=all -Dnewt.debug=all -Djogamp.debug.Lock" #D_ARGS="-Djogl.debug=all" @@ -208,7 +210,7 @@ function testawtswt() { } # -# newt (testnoawt and testawt) +# core/newt (testnoawt and testawt) # #testnoawt com.jogamp.nativewindow.NativeWindowVersion $* #testnoawt com.jogamp.opengl.JoglVersion $* @@ -237,6 +239,26 @@ function testawtswt() { #testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLContextDrawableSwitchNEWT $* #testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestFBODrawableNEWT $* +testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableDelegateOnOffscrnCapsNEWT $* +#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT $* +#testawt com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableGLCanvasOnOffscrnCapsAWT $* +#testawt com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableNewtCanvasAWTOnOffscrnCapsAWT $* +#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableFactoryOffscrnCapsNEWT $* + +#testawt com.jogamp.opengl.test.junit.jogl.acore.TestOffscreenLayer01GLCanvasAWT $* +#testawt com.jogamp.opengl.test.junit.jogl.acore.TestOffscreenLayer02NewtCanvasAWT $* + +#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestFBOAutoDrawableFactoryNEWT $* +#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestFBOOffThreadSharedContextMix2DemosES2NEWT $* +#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestFBOOnThreadSharedContext1DemoES2NEWT $* +#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestFBOMix2DemosES2NEWT $* +#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestFBOMRTNEWT01 $* +#testawt com.jogamp.opengl.test.junit.jogl.acore.TestFBOAutoDrawableDeadlockAWT $* +#testawt com.jogamp.opengl.test.junit.jogl.awt.TestBug461FBOSupersamplingSwingAWT + +#testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT $* +#testawt com.jogamp.opengl.test.junit.jogl.demos.es2.awt.TestGearsES2AWT $* + #testnoawt com.jogamp.opengl.test.junit.newt.parenting.TestParenting01NEWT $* #testnoawt com.jogamp.opengl.test.junit.newt.parenting.TestParenting02NEWT $* #testawt com.jogamp.opengl.test.junit.newt.parenting.TestParenting01cSwingAWT $* @@ -331,10 +353,8 @@ function testawtswt() { #testawt com.jogamp.opengl.test.junit.newt.parenting.TestParenting03AWT $* #testawt com.jogamp.opengl.test.junit.newt.parenting.TestParenting04AWT $* #testawtswt com.jogamp.opengl.test.junit.newt.parenting.TestParenting01aSWT $* -testawtswt com.jogamp.opengl.test.junit.newt.parenting.TestParenting04SWT $* +#testawtswt com.jogamp.opengl.test.junit.newt.parenting.TestParenting04SWT $* #testawt com.jogamp.opengl.test.junit.newt.parenting.TestParentingFocusTraversal01AWT $* -#testawt com.jogamp.opengl.test.junit.newt.parenting.TestParentingOffscreenLayer01GLCanvasAWT $* -#testawt com.jogamp.opengl.test.junit.newt.parenting.TestParentingOffscreenLayer02NewtCanvasAWT $* #testawt com.jogamp.opengl.test.junit.newt.parenting.TestTranslucentParentingAWT $* #testawt com.jogamp.opengl.test.junit.newt.TestCloseNewtAWT #testawt com.jogamp.opengl.test.junit.jogl.caps.TestMultisampleES1AWT $* @@ -376,24 +396,6 @@ testawtswt com.jogamp.opengl.test.junit.newt.parenting.TestParenting04SWT $* #testnoawt com.jogamp.opengl.test.junit.jogl.glsl.TestGLSLShaderState02NEWT $* #testnoawt com.jogamp.opengl.test.junit.jogl.glsl.TestRulerNEWT01 $* -# -# FBO / .. -# - -#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestFBODrawableNEWT $* -#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLDrawable00NEWT $* -#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLDrawable01NEWT $* -#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLDrawable01bNEWT $* -#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLDrawable02NEWT $* -#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestFBOMix2DemosES2NEWT $* -#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestFBODrawableMix2DemosES2NEWT $* -#testawt com.jogamp.opengl.test.junit.jogl.acore.TestFBOAutoDrawableDeadlockAWT $* -#testawt com.jogamp.opengl.test.junit.jogl.awt.TestBug461FBOSupersamplingSwingAWT -#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestFBOMRTNEWT01 $* -#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableDelegateNEWT $* -#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLContextDrawableSwitchNEWT $* -#testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT $* - # # Graph # diff --git a/make/stub_includes/opengl/macosx-window-system.h b/make/stub_includes/opengl/macosx-window-system.h index 47b51a509..c627f67de 100644 --- a/make/stub_includes/opengl/macosx-window-system.h +++ b/make/stub_includes/opengl/macosx-window-system.h @@ -13,6 +13,7 @@ #include #include #include +#include typedef int Bool; @@ -51,12 +52,13 @@ NSOpenGLPixelBuffer* createPBuffer(int renderTarget, int internalFormat, int wid Bool destroyPBuffer(NSOpenGLPixelBuffer* pBuffer); void setContextPBuffer(NSOpenGLContext* ctx, NSOpenGLPixelBuffer* pBuffer); void setContextTextureImageToPBuffer(NSOpenGLContext* ctx, NSOpenGLPixelBuffer* pBuffer, GLenum colorBuffer); +Bool isNSOpenGLPixelBuffer(uint64_t object); -// NSOpenGLLayer* createNSOpenGLLayer(NSOpenGLContext* ctx, NSOpenGLPixelFormat* fmt, NSView* view, Bool opaque); -NSOpenGLLayer* createNSOpenGLLayer(NSOpenGLContext* ctx, NSOpenGLPixelFormat* fmt, NSOpenGLPixelBuffer* pbuffer, Bool opaque, int texWidth, int texHeight); +NSOpenGLLayer* createNSOpenGLLayer(NSOpenGLContext* ctx, NSOpenGLPixelFormat* fmt, NSOpenGLPixelBuffer* p, uint32_t texID, Bool opaque, int texWidth, int texHeight); void setNSOpenGLLayerSwapInterval(NSOpenGLLayer* layer, int interval); void waitUntilNSOpenGLLayerIsReady(NSOpenGLLayer* layer, long to_micros); -void setNSOpenGLLayerNeedsDisplay(NSOpenGLLayer* glLayer); +void flushNSOpenGLLayerPBuffer(NSOpenGLLayer* layer); +void setNSOpenGLLayerNeedsDisplay(NSOpenGLLayer* layer, NSOpenGLPixelBuffer* p, uint32_t texID, int texWidth, int texHeight); void releaseNSOpenGLLayer(NSOpenGLLayer *glLayer); void* getProcAddress(const char *procName); @@ -67,6 +69,3 @@ void setSwapInterval(NSOpenGLContext* ctx, int interval); Bool setGammaRamp(int tableSize, float* redRamp, float* greenRamp, float* blueRamp); void resetGammaRamp(); -/* returns the screen refresh rate in Hz */ -int getScreenRefreshRate(int scrn_idx); - diff --git a/src/jogl/classes/com/jogamp/opengl/FBObject.java b/src/jogl/classes/com/jogamp/opengl/FBObject.java index 8a6495e6b..cc0af29a9 100644 --- a/src/jogl/classes/com/jogamp/opengl/FBObject.java +++ b/src/jogl/classes/com/jogamp/opengl/FBObject.java @@ -35,6 +35,7 @@ import javax.media.opengl.GL; import javax.media.opengl.GL2GL3; import javax.media.opengl.GL3; import javax.media.opengl.GLBase; +import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLContext; import javax.media.opengl.GLException; import javax.media.opengl.GLProfile; @@ -61,55 +62,33 @@ public class FBObject { protected static final boolean DEBUG = Debug.debug("FBObject"); private static final boolean forceMinimumFBOSupport = Debug.isPropertyDefined("jogl.fbo.force.min", true); + private static enum DetachAction { NONE, DISPOSE, RECREATE }; + /** - * Returns true if basic FBO support is available, otherwise false. - *

      - * Basic FBO is supported if the context is either GL-ES >= 2.0, GL >= core 3.0 or implements the extensions - * ARB_ES2_compatibility, ARB_framebuffer_object, EXT_framebuffer_object or OES_framebuffer_object. - *

      - *

      - * Basic FBO support may only include one color attachment and no multisampling, - * as well as limited internal formats for renderbuffer. - *

      - * @see GLContext#hasFBO() - */ - public static final boolean supportsBasicFBO(GL gl) { - return gl.getContext().hasFBO(); - } - - /** - * Returns true if full FBO support is available, otherwise false. - *

      - * Full FBO is supported if the context is either GL >= core 3.0 or implements the extensions - * ARB_framebuffer_object, or all of - * EXT_framebuffer_object, EXT_framebuffer_multisample, - * EXT_framebuffer_blit, GL_EXT_packed_depth_stencil. - *

      - *

      - * Full FBO support includes multiple color attachments and multisampling. - *

      + * Marker interface, denotes a color buffer attachment. + *

      Always an instance of {@link Attachment}.

      + *

      Either an instance of {@link ColorAttachment} or {@link TextureAttachment}. */ - public static final boolean supportsFullFBO(GL gl) { - return !forceMinimumFBOSupport && - ( gl.isGL3() || // GL >= 3.0 - gl.isExtensionAvailable(GLExtensions.ARB_framebuffer_object) || // ARB_framebuffer_object - - ( gl.isExtensionAvailable(GLExtensions.EXT_framebuffer_object) && // All EXT_framebuffer_object* - gl.isExtensionAvailable(GLExtensions.EXT_framebuffer_multisample) && - gl.isExtensionAvailable(GLExtensions.EXT_framebuffer_blit) && - gl.isExtensionAvailable(GLExtensions.EXT_packed_depth_stencil) - ) - ) ; - } - - public static final int getMaxSamples(GL gl) { - if( supportsFullFBO(gl) ) { - int[] val = new int[] { 0 } ; - gl.glGetIntegerv(GL2GL3.GL_MAX_SAMPLES, val, 0); - return val[0]; - } else { - return 0; - } + public static interface Colorbuffer { + /** + * Initializes the color buffer and set it's parameter, if uninitialized, i.e. name is zero. + * @return true if newly initialized, otherwise false. + * @throws GLException if buffer generation or setup fails. The just created buffer name will be deleted in this case. + */ + public boolean initialize(GL gl) throws GLException; + + /** + * Releases the color buffer if initialized, i.e. name is not zero. + * @throws GLException if buffer release fails. + */ + public void free(GL gl) throws GLException; + + /** + * Writes the internal format to the given GLCapabilities object. + * @param caps the destination for format bits + * @param rgba8Avail whether rgba8 is available + */ + public void formatToGLCapabilities(GLCapabilities caps, boolean rgba8Avail); } /** Common super class of all attachments */ @@ -155,21 +134,89 @@ public class FBObject { private int name; - /** true if resource is initialized by {@link #initialize(GL)}, hence {@link #free(GL)} is allowed to free the GL resources. */ - protected boolean resourceOwner; - - private int initCounter; - protected Attachment(Type type, int iFormat, int width, int height, int name) { this.type = type; this.format = iFormat; this.width = width; this.height = height; this.name = name; - this.resourceOwner = false; - this.initCounter = 0; } + /** + * Writes the internal format to the given GLCapabilities object. + * @param caps the destination for format bits + * @param rgba8Avail whether rgba8 is available + */ + public final void formatToGLCapabilities(GLCapabilities caps, boolean rgba8Avail) { + final int _format; + switch(format) { + case GL.GL_RGBA: + _format = rgba8Avail ? GL.GL_RGBA8 : GL.GL_RGBA4; + break; + case GL.GL_RGB: + _format = rgba8Avail ? GL.GL_RGB8 : GL.GL_RGB565; + break; + default: + _format = format; + } + switch(_format) { + case GL.GL_RGBA4: + caps.setRedBits(4); + caps.setGreenBits(4); + caps.setBlueBits(4); + caps.setAlphaBits(4); + break; + case GL.GL_RGB5_A1: + caps.setRedBits(5); + caps.setGreenBits(5); + caps.setBlueBits(5); + caps.setAlphaBits(1); + break; + case GL.GL_RGB565: + caps.setRedBits(5); + caps.setGreenBits(6); + caps.setBlueBits(5); + caps.setAlphaBits(0); + break; + case GL.GL_RGB8: + caps.setRedBits(8); + caps.setGreenBits(8); + caps.setBlueBits(8); + caps.setAlphaBits(0); + break; + case GL.GL_RGBA8: + caps.setRedBits(8); + caps.setGreenBits(8); + caps.setBlueBits(8); + caps.setAlphaBits(8); + break; + case GL.GL_DEPTH_COMPONENT16: + caps.setDepthBits(16); + break; + case GL.GL_DEPTH_COMPONENT24: + caps.setDepthBits(24); + break; + case GL.GL_DEPTH_COMPONENT32: + caps.setDepthBits(32); + break; + case GL.GL_STENCIL_INDEX1: + caps.setStencilBits(1); + break; + case GL.GL_STENCIL_INDEX4: + caps.setStencilBits(4); + break; + case GL.GL_STENCIL_INDEX8: + caps.setStencilBits(8); + break; + case GL.GL_DEPTH24_STENCIL8: + caps.setDepthBits(24); + caps.setStencilBits(8); + break; + default: + throw new IllegalArgumentException("format invalid: 0x"+Integer.toHexString(format)); + } + } + /** width of attachment */ public final int getWidth() { return width; } /** height of attachment */ @@ -180,45 +227,31 @@ public class FBObject { public final int getName() { return name; } /* pp */ final void setName(int n) { name = n; } - public final int getInitCounter() { return initCounter; } - /** - * Initializes the attachment buffer and set it's parameter, if uninitialized, i.e. name is zero. - *

      Implementation employs an initialization counter, hence it can be paired recursively with {@link #free(GL)}.

      - * @throws GLException if buffer generation or setup fails. The just created buffer name will be deleted in this case. - */ - public void initialize(GL gl) throws GLException { - initCounter++; - /* - super.initialize(gl); - if(1 == getInitCounter() && 0 == getName() ) { + * Initializes the attachment and set it's parameter, if uninitialized, i.e. name is zero. + *
      +            final boolean init = 0 == name;
      +            if( init ) {
                       do init ..
      -                freeResources = true; // if all OK
                   }
      -            */
      -        }
      +            return init;
      +         * 
      + * @return true if newly initialized, otherwise false. + * @throws GLException if buffer generation or setup fails. The just created buffer name will be deleted in this case. + */ + public abstract boolean initialize(GL gl) throws GLException; /** - * Releases the attachment buffer if initialized, i.e. name is zero. - *

      Implementation employs an initialization counter, hence it can be paired recursively with {@link #initialize(GL)}.

      - * @throws GLException if buffer release fails. - */ - public void free(GL gl) throws GLException { - /* - if(1 == getInitCounter() && freeResources && .. ) { + * Releases the attachment if initialized, i.e. name is not zero. + *
      +            if(0 != name) {
                       do free ..
      -            }
      -            super.free(gl);
      -            */
      -            initCounter--;
      -            if(0 == initCounter) {
      -                resourceOwner = false;
                       name = 0;
                   }
      -            if(DEBUG) {
      -                System.err.println("Attachment.free: "+this);
      -            }
      -        }
      +         * 
      + * @throws GLException if buffer release fails. + */ + public abstract void free(GL gl) throws GLException; /** *

      @@ -232,9 +265,9 @@ public class FBObject { if( ! ( o instanceof Attachment ) ) return false; final Attachment a = (Attachment)o; return type == a.type && - format == a.format || - width == a.width || - height== a.height || + format == a.format && + width == a.width && + height== a.height && name == a.name ; } @@ -259,8 +292,7 @@ public class FBObject { public String toString() { return getClass().getSimpleName()+"[type "+type+", format 0x"+Integer.toHexString(format)+", "+width+"x"+height+ - ", name 0x"+Integer.toHexString(name)+", obj 0x"+Integer.toHexString(objectHashCode())+ - ", resOwner "+resourceOwner+", initCount "+initCounter+"]"; + ", name 0x"+Integer.toHexString(name)+", obj 0x"+Integer.toHexString(objectHashCode())+"]"; } public static Type getType(int attachmentPoint, int maxColorAttachments) { @@ -277,7 +309,7 @@ public class FBObject { } } } - + /** Other renderbuffer attachment which maybe a colorbuffer, depth or stencil. */ public static class RenderAttachment extends Attachment { private int samples; @@ -339,14 +371,13 @@ public class FBObject { } @Override - public void initialize(GL gl) throws GLException { - super.initialize(gl); - if( 1 == getInitCounter() && 0 == getName() ) { + public boolean initialize(GL gl) throws GLException { + final boolean init = 0 == getName(); + if( init ) { + int glerr = checkPreGLError(gl); + final int[] name = new int[] { -1 }; gl.glGenRenderbuffers(1, name, 0); - if( 0 == name[0] ) { - throw new GLException("null renderbuffer, "+this); - } setName(name[0]); gl.glBindRenderbuffer(GL.GL_RENDERBUFFER, getName()); @@ -355,43 +386,37 @@ public class FBObject { } else { gl.glRenderbufferStorage(GL.GL_RENDERBUFFER, format, getWidth(), getHeight()); } - int glerr = gl.glGetError(); + glerr = gl.glGetError(); if(GL.GL_NO_ERROR != glerr) { gl.glDeleteRenderbuffers(1, name, 0); setName(0); throw new GLException("GL Error 0x"+Integer.toHexString(glerr)+" while creating "+this); } - resourceOwner = true; if(DEBUG) { System.err.println("Attachment.init: "+this); } } + return init; } @Override public void free(GL gl) { - if(1 == getInitCounter() && resourceOwner && 0 != getName() ) { - final int[] name = new int[] { getName() }; + final int[] name = new int[] { getName() }; + if( 0 != name[0] ) { gl.glDeleteRenderbuffers(1, name, 0); + setName(0); + if(DEBUG) { + System.err.println("Attachment.free: "+this); + } } - super.free(gl); } public String toString() { return getClass().getSimpleName()+"[type "+type+", format 0x"+Integer.toHexString(format)+", samples "+samples+", "+getWidth()+"x"+getHeight()+ - ", name 0x"+Integer.toHexString(getName())+", obj 0x"+Integer.toHexString(objectHashCode())+ - ", resOwner "+resourceOwner+", initCount "+getInitCounter()+"]"; + ", name 0x"+Integer.toHexString(getName())+", obj 0x"+Integer.toHexString(objectHashCode())+"]"; } } - /** - * Marker interface, denotes a color buffer attachment. - *

      Always an instance of {@link Attachment}.

      - *

      Either an instance of {@link ColorAttachment} or {@link TextureAttachment}. - */ - public static interface Colorbuffer { - } - /** Color render buffer attachment */ public static class ColorAttachment extends RenderAttachment implements Colorbuffer { public ColorAttachment(int iFormat, int samples, int width, int height, int name) { @@ -444,9 +469,11 @@ public class FBObject { * @throws GLException if texture generation and setup fails. The just created texture name will be deleted in this case. */ @Override - public void initialize(GL gl) throws GLException { - super.initialize(gl); - if( 1 == getInitCounter() && 0 == getName() ) { + public boolean initialize(GL gl) throws GLException { + final boolean init = 0 == getName(); + if( init ) { + int glerr = checkPreGLError(gl); + final int[] name = new int[] { -1 }; gl.glGenTextures(1, name, 0); if(0 == name[0]) { @@ -468,31 +495,111 @@ public class FBObject { if( 0 < wrapT ) { gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, wrapT); } - int glerr = gl.glGetError(); + glerr = gl.glGetError(); if(GL.GL_NO_ERROR != glerr) { gl.glDeleteTextures(1, name, 0); setName(0); throw new GLException("GL Error 0x"+Integer.toHexString(glerr)+" while creating "+this); } - resourceOwner = true; - } - if(DEBUG) { - System.err.println("Attachment.init: "+this); + if(DEBUG) { + System.err.println("Attachment.init: "+this); + } } + return init; } @Override public void free(GL gl) { - if(1 == getInitCounter() && resourceOwner && 0 != getName() ) { - final int[] name = new int[] { getName() }; + final int[] name = new int[] { getName() }; + if( 0 != name[0] ) { gl.glDeleteTextures(1, name, 0); + setName(0); + if(DEBUG) { + System.err.println("Attachment.free: "+this); + } } - super.free(gl); + } + } + + /** + * Creates a color {@link TextureAttachment}, i.e. type {@link Type#COLOR_TEXTURE}, + * selecting the texture data type and format automatically. + * + *

      Using default min/mag filter {@link GL#GL_NEAREST} and default wrapS/wrapT {@link GL#GL_CLAMP_TO_EDGE}.

      + * + * @param glp the chosen {@link GLProfile} + * @param alpha set to true if you request alpha channel, otherwise false; + * @param width texture width + * @param height texture height + * @return the created and uninitialized color {@link TextureAttachment} + */ + public static final TextureAttachment createColorTextureAttachment(GLProfile glp, boolean alpha, int width, int height) { + return createColorTextureAttachment(glp, alpha, width, height, GL.GL_NEAREST, GL.GL_NEAREST, GL.GL_CLAMP_TO_EDGE, GL.GL_CLAMP_TO_EDGE); + } + + /** + * Creates a color {@link TextureAttachment}, i.e. type {@link Type#COLOR_TEXTURE}, + * selecting the texture data type and format automatically. + * + * @param glp the chosen {@link GLProfile} + * @param alpha set to true if you request alpha channel, otherwise false; + * @param width texture width + * @param height texture height + * @param magFilter if > 0 value for {@link GL#GL_TEXTURE_MAG_FILTER} + * @param minFilter if > 0 value for {@link GL#GL_TEXTURE_MIN_FILTER} + * @param wrapS if > 0 value for {@link GL#GL_TEXTURE_WRAP_S} + * @param wrapT if > 0 value for {@link GL#GL_TEXTURE_WRAP_T} + * @return the created and uninitialized color {@link TextureAttachment} + */ + public static final TextureAttachment createColorTextureAttachment(GLProfile glp, boolean alpha, int width, int height, + int magFilter, int minFilter, int wrapS, int wrapT) { + final int textureInternalFormat, textureDataFormat, textureDataType; + if(glp.isGLES()) { + textureInternalFormat = alpha ? GL.GL_RGBA : GL.GL_RGB; + textureDataFormat = alpha ? GL.GL_RGBA : GL.GL_RGB; + textureDataType = GL.GL_UNSIGNED_BYTE; + } else { + textureInternalFormat = alpha ? GL.GL_RGBA8 : GL.GL_RGB8; + textureDataFormat = alpha ? GL.GL_BGRA : GL.GL_RGB; + textureDataType = alpha ? GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV : GL.GL_UNSIGNED_BYTE; + } + return createColorTextureAttachment(textureInternalFormat, width, height, textureDataFormat, textureDataType, magFilter, minFilter, wrapS, wrapT); + } + + /** + * Creates a color {@link TextureAttachment}, i.e. type {@link Type#COLOR_TEXTURE}. + * + * @param internalFormat internalFormat parameter to {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, long)} + * @param width texture width + * @param height texture height + * @param dataFormat format parameter to {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, long)} + * @param dataType type parameter to {@link GL#glTexImage2D(int, int, int, int, int, int, int, int, long)} + * @param magFilter if > 0 value for {@link GL#GL_TEXTURE_MAG_FILTER} + * @param minFilter if > 0 value for {@link GL#GL_TEXTURE_MIN_FILTER} + * @param wrapS if > 0 value for {@link GL#GL_TEXTURE_WRAP_S} + * @param wrapT if > 0 value for {@link GL#GL_TEXTURE_WRAP_T} + * @return the created and uninitialized color {@link TextureAttachment} + */ + public static final TextureAttachment createColorTextureAttachment(int internalFormat, int width, int height, int dataFormat, int dataType, + int magFilter, int minFilter, int wrapS, int wrapT) { + return new TextureAttachment(Type.COLOR_TEXTURE, internalFormat, width, height, dataFormat, dataType, + magFilter, minFilter, wrapS, wrapT, 0 /* name */); + } + + private static boolean hasAlpha(int format) { + switch(format) { + case GL.GL_RGBA8: + case GL.GL_RGBA4: + case GL.GL_RGBA: + case GL.GL_BGRA: + case 4: + return true; + default: + return false; } } private boolean initialized; - private boolean basicFBOSupport; private boolean fullFBOSupport; private boolean rgba8Avail; private boolean depth24Avail; @@ -523,6 +630,9 @@ public class FBObject { // private final void validateColorAttachmentPointRange(int point) { + if(!initialized) { + throw new GLException("FBO not initialized"); + } if(maxColorAttachments != colorAttachmentPoints.length) { throw new InternalError("maxColorAttachments "+maxColorAttachments+", array.lenght "+colorAttachmentPoints); } @@ -621,7 +731,6 @@ public class FBObject { this.initialized = false; // TBD @ init - this.basicFBOSupport = false; this.fullFBOSupport = false; this.rgba8Avail = false; this.depth24Avail = false; @@ -657,14 +766,11 @@ public class FBObject { private void init(GL gl, int width, int height, int samples) throws GLException { if(initialized) { throw new GLException("FBO already initialized"); - } - fullFBOSupport = supportsFullFBO(gl); - - if( !fullFBOSupport && !supportsBasicFBO(gl) ) { + } + if( !gl.hasBasicFBOSupport() ) { throw new GLException("FBO not supported w/ context: "+gl.getContext()+", "+this); } - - basicFBOSupport = true; + fullFBOSupport = gl.hasFullFBOSupport(); rgba8Avail = gl.isGL2GL3() || gl.isExtensionAvailable(GLExtensions.OES_rgb8_rgba8); depth24Avail = fullFBOSupport || gl.isExtensionAvailable(GLExtensions.OES_depth24); @@ -680,10 +786,7 @@ public class FBObject { int val[] = new int[1]; - int glerr = gl.glGetError(); - if(DEBUG && GL.GL_NO_ERROR != glerr) { - System.err.println("FBObject.init-preexisting.0 GL Error 0x"+Integer.toHexString(glerr)); - } + int glerr = checkPreGLError(gl); int realMaxColorAttachments = 1; maxColorAttachments = 1; @@ -703,16 +806,7 @@ public class FBObject { colorAttachmentPoints = new Colorbuffer[maxColorAttachments]; colorAttachmentCount = 0; - maxSamples = 0; - if(fullFBOSupport) { - gl.glGetIntegerv(GL2GL3.GL_MAX_SAMPLES, val, 0); - glerr = gl.glGetError(); - if(GL.GL_NO_ERROR == glerr) { - maxSamples = val[0]; - } else if(DEBUG) { - System.err.println("FBObject.init-GL_MAX_SAMPLES query GL Error 0x"+Integer.toHexString(glerr)); - } - } + maxSamples = gl.getMaxRenderbufferSamples(); if(!forceMinimumFBOSupport) { gl.glGetIntegerv(GL.GL_MAX_TEXTURE_SIZE, val, 0); maxTextureSize = val[0]; @@ -733,10 +827,9 @@ public class FBObject { this.samples = samples <= maxSamples ? samples : maxSamples; if(DEBUG) { - System.err.println("FBObject "+width+"x"+height+", "+samples+" -> "+samples+" samples"); - System.err.println("basicFBOSupport: "+basicFBOSupport); + System.err.println("FBObject "+width+"x"+height+", "+samples+" -> "+this.samples+" samples"); System.err.println("fullFBOSupport: "+fullFBOSupport); - System.err.println("maxColorAttachments: "+maxColorAttachments+"/"+realMaxColorAttachments); + System.err.println("maxColorAttachments: "+maxColorAttachments+"/"+realMaxColorAttachments+" [capped/real]"); System.err.println("maxSamples: "+maxSamples); System.err.println("maxTextureSize: "+maxTextureSize); System.err.println("maxRenderbufferSize: "+maxRenderbufferSize); @@ -761,12 +854,8 @@ public class FBObject { throw new GLException("size "+width+"x"+height+" exceeds on of the maxima [texture "+maxTextureSize+", renderbuffer "+maxRenderbufferSize+"]"); } - if(null != samplesSink) { - // init sampling sink - samplesSink.reset(gl, width, height); - resetMSAATexture2DSink(gl); - } - + resetMSAATexture2DSink(gl); + // generate fbo .. gl.glGenFramebuffers(1, val, 0); fbName = val[0]; @@ -780,7 +869,8 @@ public class FBObject { if(!gl.glIsFramebuffer(fbName)) { checkNoError(gl, GL.GL_INVALID_VALUE, "FBObject Init.isFB"); // throws GLException } - bound = true; + bound = true; + samplesSinkDirty = true; initialized = true; updateStatus(gl); @@ -797,7 +887,7 @@ public class FBObject { * to match the new given parameters. *

      *

      - * Currently incompatibility and hence recreation is given if + * Incompatibility and hence recreation is forced if * the size or sample count doesn't match for subsequent calls. *

      * @@ -820,17 +910,17 @@ public class FBObject { * to match the new given parameters. *

      *

      - * Currently incompatibility and hence recreation is given if - * the size or sample count doesn't match for subsequent calls. + * Currently incompatibility and hence recreation of the attachments will be performed + * if the size or sample count doesn't match for subsequent calls. *

      * *

      Leaves the FBO bound state untouched

      * * @param gl the current GL context - * @param newWidth - * @param newHeight + * @param newWidth the new width, it's minimum is capped to 1 + * @param newHeight the new height, it's minimum is capped to 1 * @param newSamples if > 0, MSAA will be used, otherwise no multisampling. Will be capped to {@link #getMaxSamples()}. - * @throws GLException in case of an error + * @throws GLException in case of an error, i.e. size too big, etc .. */ public final void reset(GL gl, int newWidth, int newHeight, int newSamples) { if(!initialized) { @@ -841,13 +931,15 @@ public class FBObject { newSamples = newSamples <= maxSamples ? newSamples : maxSamples; // clamp if( newWidth != width || newHeight != height || newSamples != samples ) { + if(0>=newWidth) { newWidth = 1; } + if(0>=newHeight) { newHeight = 1; } if(newWidth > 2 + maxTextureSize || newHeight> 2 + maxTextureSize || newWidth > maxRenderbufferSize || newHeight> maxRenderbufferSize ) { throw new GLException("size "+width+"x"+height+" exceeds on of the maxima [texture "+maxTextureSize+", renderbuffer "+maxRenderbufferSize+"]"); } if(DEBUG) { - System.err.println("FBObject.reset - START - "+this); + System.err.println("FBObject.reset - START - "+width+"x"+height+", "+samples+" -> "+newWidth+"x"+newHeight+", "+newSamples+"; "+this); } final boolean wasBound = isBound(); @@ -856,11 +948,18 @@ public class FBObject { height = newHeight; samples = newSamples; detachAllImpl(gl, true , true); - resetMSAATexture2DSink(gl); - if(wasBound) { - bind(gl); - } else { + /** + * Postpone reset of samplesSink until syncFramebuffer, + * issued at use(..) method (swapBuffer usually initiates it). + * This allows another thread to still use the 'samplesSinkTexture' + * until swapBuffer happens and does not invalidate the GL_FRONT + * FBO (framebuffer & texture). + resetMSAATexture2DSink(gl); + */ + samplesSinkDirty = true; + + if(!wasBound) { unbind(gl); } @@ -870,6 +969,28 @@ public class FBObject { } } + /** + * Writes the internal format of the attachments to the given GLCapabilities object. + * @param caps the destination for format bits + */ + public final void formatToGLCapabilities(GLCapabilities caps) { + caps.setSampleBuffers(samples > 0); + caps.setNumSamples(samples); + caps.setDepthBits(0); + caps.setStencilBits(0); + + final Colorbuffer cb = samples > 0 ? getSamplingSink() : getColorbuffer(0); + if(null != cb) { + cb.formatToGLCapabilities(caps, rgba8Avail); + } + if(null != depth) { + depth.formatToGLCapabilities(caps, rgba8Avail); + } + if(null != stencil && stencil != depth) { + stencil.formatToGLCapabilities(caps, rgba8Avail); + } + } + /** * Note that the status may reflect an incomplete state during transition of attachments. * @return The FB status. {@link GL.GL_FRAMEBUFFER_COMPLETE} if ok, otherwise return GL FBO error state or -1 @@ -954,6 +1075,15 @@ public class FBObject { } } + private static int checkPreGLError(GL gl) { + int glerr = gl.glGetError(); + if(DEBUG && GL.GL_NO_ERROR != glerr) { + System.err.println("Pre-existing GL error: 0x"+Integer.toHexString(glerr)); + Thread.dumpStack(); + } + return glerr; + } + private final boolean checkNoError(GL gl, int err, String exceptionMessage) throws GLException { if(GL.GL_NO_ERROR != err) { if(null != gl) { @@ -974,7 +1104,7 @@ public class FBObject { } /** - * Attaches a Texture2D Color Buffer to this FBO's instance at the given attachment point, + * Attaches a {@link Colorbuffer}, i.e. {@link TextureAttachment}, to this FBO's instance at the given attachment point, * selecting the texture data type and format automatically. * *

      Using default min/mag filter {@link GL#GL_NEAREST} and default wrapS/wrapT {@link GL#GL_CLAMP_TO_EDGE}.

      @@ -986,13 +1116,15 @@ public class FBObject { * @param alpha set to true if you request alpha channel, otherwise false; * @return TextureAttachment instance describing the new attached texture colorbuffer if bound and configured successfully, otherwise GLException is thrown * @throws GLException in case the texture colorbuffer couldn't be allocated or MSAA has been chosen + * @see #createColorTextureAttachment(GLProfile, boolean, int, int) */ public final TextureAttachment attachTexture2D(GL gl, int attachmentPoint, boolean alpha) throws GLException { - return attachTexture2D(gl, attachmentPoint, alpha, GL.GL_NEAREST, GL.GL_NEAREST, GL.GL_CLAMP_TO_EDGE, GL.GL_CLAMP_TO_EDGE); + return (TextureAttachment)attachColorbuffer(gl, attachmentPoint, + createColorTextureAttachment(gl.getGLProfile(), alpha, width, height)); } /** - * Attaches a Texture2D Color Buffer to this FBO's instance at the given attachment point, + * Attaches a {@link Colorbuffer}, i.e. {@link TextureAttachment}, to this FBO's instance at the given attachment point, * selecting the texture data type and format automatically. * *

      Leaves the FBO bound.

      @@ -1006,23 +1138,15 @@ public class FBObject { * @param wrapT if > 0 value for {@link GL#GL_TEXTURE_WRAP_T} * @return TextureAttachment instance describing the new attached texture colorbuffer if bound and configured successfully, otherwise GLException is thrown * @throws GLException in case the texture colorbuffer couldn't be allocated or MSAA has been chosen + * @see #createColorTextureAttachment(GLProfile, boolean, int, int, int, int, int, int) */ public final TextureAttachment attachTexture2D(GL gl, int attachmentPoint, boolean alpha, int magFilter, int minFilter, int wrapS, int wrapT) throws GLException { - final int textureInternalFormat, textureDataFormat, textureDataType; - if(gl.isGLES()) { - textureInternalFormat = alpha ? GL.GL_RGBA : GL.GL_RGB; - textureDataFormat = alpha ? GL.GL_RGBA : GL.GL_RGB; - textureDataType = GL.GL_UNSIGNED_BYTE; - } else { - textureInternalFormat = alpha ? GL.GL_RGBA8 : GL.GL_RGB8; - textureDataFormat = alpha ? GL.GL_BGRA : GL.GL_RGB; - textureDataType = alpha ? GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV : GL.GL_UNSIGNED_BYTE; - } - return attachTexture2D(gl, attachmentPoint, textureInternalFormat, textureDataFormat, textureDataType, magFilter, minFilter, wrapS, wrapT); + return (TextureAttachment)attachColorbuffer(gl, attachmentPoint, + createColorTextureAttachment(gl.getGLProfile(), alpha, width, height, magFilter, minFilter, wrapS, wrapT)); } /** - * Attaches a Texture2D Color Buffer to this FBO's instance at the given attachment point. + * Attaches a {@link Colorbuffer}, i.e. {@link TextureAttachment}, to this FBO's instance at the given attachment point. * *

      Leaves the FBO bound.

      * @@ -1037,66 +1161,33 @@ public class FBObject { * @param wrapT if > 0 value for {@link GL#GL_TEXTURE_WRAP_T} * @return TextureAttachment instance describing the new attached texture colorbuffer if bound and configured successfully, otherwise GLException is thrown * @throws GLException in case the texture colorbuffer couldn't be allocated or MSAA has been chosen + * @see #createColorTextureAttachment(int, int, int, int, int, int, int, int, int) */ public final TextureAttachment attachTexture2D(GL gl, int attachmentPoint, int internalFormat, int dataFormat, int dataType, int magFilter, int minFilter, int wrapS, int wrapT) throws GLException { - return attachTexture2D(gl, attachmentPoint, - new TextureAttachment(Type.COLOR_TEXTURE, internalFormat, width, height, dataFormat, dataType, - magFilter, minFilter, wrapS, wrapT, 0 /* name */)); + return (TextureAttachment)attachColorbuffer(gl, attachmentPoint, + createColorTextureAttachment(internalFormat, width, height, dataFormat, dataType, magFilter, minFilter, wrapS, wrapT)); } /** - * Attaches a Texture2D Color Buffer to this FBO's instance at the given attachment point. + * Creates a {@link ColorAttachment}, selecting the format automatically. * - *

      - * In case the passed TextureAttachment texA is uninitialized, i.e. it's texture name is zero, - * a new texture name is generated and setup w/ the texture parameter.
      - * Otherwise, i.e. texture name is not zero, the passed TextureAttachment texA is - * considered complete and assumed matching this FBO requirement. A GL error may occur is the latter is untrue. - *

      - * - *

      Leaves the FBO bound.

      - * - * @param gl the current GL context - * @param attachmentPoint the color attachment point ranging from [0..{@link #getMaxColorAttachments()}-1] - * @param texA the to be attached {@link TextureAttachment}. Maybe complete or uninitialized, see above. - * @return the passed TextureAttachment texA instance describing the new attached texture colorbuffer if bound and configured successfully, otherwise GLException is thrown - * @throws GLException in case the texture colorbuffer couldn't be allocated or MSAA has been chosen + * @param alpha set to true if you request alpha channel, otherwise false; + * @return uninitialized ColorAttachment instance describing the new attached colorbuffer */ - public final TextureAttachment attachTexture2D(GL gl, int attachmentPoint, TextureAttachment texA) throws GLException { - validateAddColorAttachment(attachmentPoint, texA); - - if(samples>0) { - removeColorAttachment(attachmentPoint, texA); - throw new GLException("Texture2D not supported w/ MSAA. If you have enabled MSAA with exisiting texture attachments, you may want to detach them via detachAllTexturebuffer(gl)."); - } - - texA.initialize(gl); - addColorAttachment(attachmentPoint, texA); - - bind(gl); - - // Set up the color buffer for use as a renderable texture: - gl.glFramebufferTexture2D(GL.GL_FRAMEBUFFER, - GL.GL_COLOR_ATTACHMENT0 + attachmentPoint, - GL.GL_TEXTURE_2D, texA.getName(), 0); - - if(!ignoreStatus) { - updateStatus(gl); - if(!isStatusValid()) { - detachColorbuffer(gl, attachmentPoint); - throw new GLException("attachTexture2D "+texA+" at "+attachmentPoint+" failed "+getStatusString()+", "+this); - } - } - if(DEBUG) { - System.err.println("FBObject.attachTexture2D: "+this); + public final ColorAttachment createColorAttachment(boolean alpha) { + final int internalFormat; + if( rgba8Avail ) { + internalFormat = alpha ? GL.GL_RGBA8 : GL.GL_RGB8 ; + } else { + internalFormat = alpha ? GL.GL_RGBA4 : GL.GL_RGB565; } - return texA; + return new ColorAttachment(internalFormat, samples, width, height, 0); } - + /** - * Attaches a Color Buffer to this FBO's instance at the given attachment point, + * Attaches a {@link Colorbuffer}, i.e. {@link ColorAttachment}, to this FBO's instance at the given attachment point, * selecting the format automatically. * *

      Leaves the FBO bound.

      @@ -1106,19 +1197,14 @@ public class FBObject { * @param alpha set to true if you request alpha channel, otherwise false; * @return ColorAttachment instance describing the new attached colorbuffer if bound and configured successfully, otherwise GLException is thrown * @throws GLException in case the colorbuffer couldn't be allocated + * @see #createColorAttachment(boolean) */ public final ColorAttachment attachColorbuffer(GL gl, int attachmentPoint, boolean alpha) throws GLException { - final int internalFormat; - if( rgba8Avail ) { - internalFormat = alpha ? GL.GL_RGBA8 : GL.GL_RGB8 ; - } else { - internalFormat = alpha ? GL.GL_RGBA4 : GL.GL_RGB565; - } - return attachColorbuffer(gl, attachmentPoint, internalFormat); + return (ColorAttachment) attachColorbuffer(gl, attachmentPoint, createColorAttachment(alpha)); } /** - * Attaches a Color Buffer to this FBO's instance at the given attachment point. + * Attaches a {@link Colorbuffer}, i.e. {@link ColorAttachment}, to this FBO's instance at the given attachment point. * *

      Leaves the FBO bound.

      * @@ -1135,46 +1221,80 @@ public class FBObject { throw new IllegalArgumentException("colorformat invalid: 0x"+Integer.toHexString(internalFormat)+", "+this); } - return attachColorbuffer(gl, attachmentPoint, new ColorAttachment(internalFormat, samples, width, height, 0)); + return (ColorAttachment) attachColorbuffer(gl, attachmentPoint, new ColorAttachment(internalFormat, samples, width, height, 0)); } /** - * Attaches a Color Buffer to this FBO's instance at the given attachment point. + * Attaches a {@link Colorbuffer}, i.e. {@link ColorAttachment} or {@link TextureAttachment}, + * to this FBO's instance at the given attachment point. * + *

      + * If {@link Colorbuffer} is a {@link TextureAttachment} and is uninitialized, i.e. it's texture name is zero, + * a new texture name is generated and setup w/ the texture parameter.
      + * Otherwise, i.e. texture name is not zero, the passed TextureAttachment texA is + * considered complete and assumed matching this FBO requirement. A GL error may occur is the latter is untrue. + *

      + * *

      Leaves the FBO bound.

      * * @param gl * @param attachmentPoint the color attachment point ranging from [0..{@link #getMaxColorAttachments()}-1] - * @param colA the template for the new {@link ColorAttachment} - * @return ColorAttachment instance describing the new attached colorbuffer if bound and configured successfully, otherwise GLException is thrown - * @throws GLException in case the colorbuffer couldn't be allocated + * @param colbuf the to be attached {@link Colorbuffer} + * @return newly attached {@link Colorbuffer} instance if bound and configured successfully, otherwise GLException is thrown + * @throws GLException in case the colorbuffer couldn't be allocated or MSAA has been chosen in case of a {@link TextureAttachment} */ - public final ColorAttachment attachColorbuffer(GL gl, int attachmentPoint, ColorAttachment colA) throws GLException { - validateAddColorAttachment(attachmentPoint, colA); - - colA.initialize(gl); - addColorAttachment(attachmentPoint, colA); + public final Colorbuffer attachColorbuffer(GL gl, int attachmentPoint, Colorbuffer colbuf) throws GLException { + validateAddColorAttachment(attachmentPoint, colbuf); - bind(gl); + final boolean initializedColorbuf = colbuf.initialize(gl); + addColorAttachment(attachmentPoint, colbuf); - // Attach the color buffer - gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, - GL.GL_COLOR_ATTACHMENT0 + attachmentPoint, - GL.GL_RENDERBUFFER, colA.getName()); + bind(gl); - if(!ignoreStatus) { - updateStatus(gl); - if(!isStatusValid()) { - detachColorbuffer(gl, attachmentPoint); - throw new GLException("attachColorbuffer "+colA+" at "+attachmentPoint+" failed "+getStatusString()+", "+this); + if(colbuf instanceof TextureAttachment) { + final TextureAttachment texA = (TextureAttachment) colbuf; + + if(samples>0) { + removeColorAttachment(attachmentPoint, texA); + if(initializedColorbuf) { + texA.free(gl); + } + throw new GLException("Texture2D not supported w/ MSAA. If you have enabled MSAA with exisiting texture attachments, you may want to detach them via detachAllTexturebuffer(gl)."); + } + + // Set up the color buffer for use as a renderable texture: + gl.glFramebufferTexture2D(GL.GL_FRAMEBUFFER, + GL.GL_COLOR_ATTACHMENT0 + attachmentPoint, + GL.GL_TEXTURE_2D, texA.getName(), 0); + + if(!ignoreStatus) { + updateStatus(gl); + if(!isStatusValid()) { + detachColorbuffer(gl, attachmentPoint, true); + throw new GLException("attachTexture2D "+texA+" at "+attachmentPoint+" failed "+getStatusString()+", "+this); + } + } + } else if(colbuf instanceof ColorAttachment) { + final ColorAttachment colA = (ColorAttachment) colbuf; + + // Attach the color buffer + gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, + GL.GL_COLOR_ATTACHMENT0 + attachmentPoint, + GL.GL_RENDERBUFFER, colA.getName()); + + if(!ignoreStatus) { + updateStatus(gl); + if(!isStatusValid()) { + detachColorbuffer(gl, attachmentPoint, true); + throw new GLException("attachColorbuffer "+colA+" at "+attachmentPoint+" failed "+getStatusString()+", "+this); + } } } if(DEBUG) { - System.err.println("FBObject.attachColorbuffer: "+this); + System.err.println("FBObject.attachColorbuffer: [attachmentPoint "+attachmentPoint+", colbuf "+colbuf+"]: "+this); } - return colA; + return colbuf; } - /** * Attaches one depth, stencil or packed-depth-stencil buffer to this FBO's instance, @@ -1355,33 +1475,39 @@ public class FBObject { if(!ignoreStatus) { updateStatus(gl); if( !isStatusValid() ) { - detachRenderbuffer(gl, atype); + detachRenderbuffer(gl, atype, true); throw new GLException("renderbuffer attachment failed: "+this.getStatusString()); } } if(DEBUG) { - System.err.println("FBObject.attachRenderbuffer: "+this); - } + System.err.println("FBObject.attachRenderbuffer: [attachmentType "+atype+"]: "+this); + } } /** + * Detaches a {@link Colorbuffer}, i.e. {@link ColorAttachment} or {@link TextureAttachment}. *

      Leaves the FBO bound!

      + * * @param gl - * @param ca + * @param attachmentPoint + * @param dispose true if the Colorbuffer shall be disposed + * @return the detached Colorbuffer * @throws IllegalArgumentException */ - public final void detachColorbuffer(GL gl, int attachmentPoint) throws IllegalArgumentException { - if(null == detachColorbufferImpl(gl, attachmentPoint, false)) { + public final Colorbuffer detachColorbuffer(GL gl, int attachmentPoint, boolean dispose) throws IllegalArgumentException { + final Colorbuffer res = detachColorbufferImpl(gl, attachmentPoint, dispose ? DetachAction.DISPOSE : DetachAction.NONE); + if(null == res) { throw new IllegalArgumentException("ColorAttachment at "+attachmentPoint+", not attached, "+this); } if(DEBUG) { - System.err.println("FBObject.detachColorbuffer: [attachmentPoint "+attachmentPoint+"]: "+this); + System.err.println("FBObject.detachColorbuffer: [attachmentPoint "+attachmentPoint+", dispose "+dispose+"]: "+res+", "+this); } + return res; } - private final Colorbuffer detachColorbufferImpl(GL gl, int attachmentPoint, boolean recreate) { - final Colorbuffer colbuf = colorAttachmentPoints[attachmentPoint]; // shortcut, don't validate here + private final Colorbuffer detachColorbufferImpl(GL gl, int attachmentPoint, DetachAction detachAction) { + Colorbuffer colbuf = colorAttachmentPoints[attachmentPoint]; // shortcut, don't validate here if(null == colbuf) { return null; @@ -1389,6 +1515,8 @@ public class FBObject { bind(gl); + removeColorAttachment(attachmentPoint, colbuf); + if(colbuf instanceof TextureAttachment) { final TextureAttachment texA = (TextureAttachment) colbuf; if( 0 != texA.getName() ) { @@ -1397,11 +1525,22 @@ public class FBObject { GL.GL_TEXTURE_2D, 0, 0); gl.glBindTexture(GL.GL_TEXTURE_2D, 0); } - texA.free(gl); - removeColorAttachment(attachmentPoint, texA); - if(recreate) { - texA.setSize(width, height); - attachTexture2D(gl, attachmentPoint, texA); + switch(detachAction) { + case DISPOSE: + texA.free(gl); + break; + case RECREATE: + texA.free(gl); + if(samples == 0) { + // stay non MSAA + texA.setSize(width, height); + } else { + // switch to MSAA + colbuf = createColorAttachment(hasAlpha(texA.format)); + } + attachColorbuffer(gl, attachmentPoint, colbuf); + break; + default: } } else if(colbuf instanceof ColorAttachment) { final ColorAttachment colA = (ColorAttachment) colbuf; @@ -1410,12 +1549,30 @@ public class FBObject { GL.GL_COLOR_ATTACHMENT0+attachmentPoint, GL.GL_RENDERBUFFER, 0); } - colA.free(gl); - removeColorAttachment(attachmentPoint, colbuf); - if(recreate) { - colA.setSize(width, height); - colA.setSamples(samples); - attachColorbuffer(gl, attachmentPoint, colA); + switch(detachAction) { + case DISPOSE: + colA.free(gl); + break; + case RECREATE: + colA.free(gl); + if(samples > 0) { + // stay MSAA + colA.setSize(width, height); + colA.setSamples(samples); + } else { + // switch to non MSAA + if(null != samplesSinkTexture) { + colbuf = createColorTextureAttachment(samplesSinkTexture.format, width, height, + samplesSinkTexture.dataFormat, samplesSinkTexture.dataType, + samplesSinkTexture.magFilter, samplesSinkTexture.minFilter, + samplesSinkTexture.wrapS, samplesSinkTexture.wrapT); + } else { + colbuf = createColorTextureAttachment(gl.getGLProfile(), true, width, height); + } + } + attachColorbuffer(gl, attachmentPoint, colbuf); + break; + default: } } return colbuf; @@ -1424,10 +1581,14 @@ public class FBObject { /** * * @param gl + * @param dispose true if the Colorbuffer shall be disposed * @param reqAType {@link Type#DEPTH}, {@link Type#DEPTH} or {@link Type#DEPTH_STENCIL} */ - public final void detachRenderbuffer(GL gl, Attachment.Type atype) throws IllegalArgumentException { - detachRenderbufferImpl(gl, atype, false); + public final void detachRenderbuffer(GL gl, Attachment.Type atype, boolean dispose) throws IllegalArgumentException { + detachRenderbufferImpl(gl, atype, dispose ? DetachAction.DISPOSE : DetachAction.NONE); + if(DEBUG) { + System.err.println("FBObject.detachRenderbuffer: [attachmentType "+atype+", dispose "+dispose+"]: "+this); + } } public final boolean isDepthStencilPackedFormat() { @@ -1439,7 +1600,7 @@ public class FBObject { return res; } - private final void detachRenderbufferImpl(GL gl, Attachment.Type atype, boolean recreate) throws IllegalArgumentException { + private final void detachRenderbufferImpl(GL gl, Attachment.Type atype, DetachAction detachAction) throws IllegalArgumentException { switch ( atype ) { case DEPTH: case STENCIL: @@ -1485,8 +1646,14 @@ public class FBObject { if( 0 != depth.getName() ) { gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_DEPTH_ATTACHMENT, GL.GL_RENDERBUFFER, 0); } - depth.free(gl); - if(!recreate) { + switch(detachAction) { + case DISPOSE: + case RECREATE: + depth.free(gl); + break; + default: + } + if(DetachAction.RECREATE != detachAction) { depth = null; } break; @@ -1495,8 +1662,14 @@ public class FBObject { if(0 != stencil.getName()) { gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_STENCIL_ATTACHMENT, GL.GL_RENDERBUFFER, 0); } - stencil.free(gl); - if(!recreate) { + switch(detachAction) { + case DISPOSE: + case RECREATE: + stencil.free(gl); + break; + default: + } + if(DetachAction.RECREATE != detachAction) { stencil = null; } break; @@ -1506,9 +1679,15 @@ public class FBObject { gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_DEPTH_ATTACHMENT, GL.GL_RENDERBUFFER, 0); gl.glFramebufferRenderbuffer(GL.GL_FRAMEBUFFER, GL.GL_STENCIL_ATTACHMENT, GL.GL_RENDERBUFFER, 0); } - depth.free(gl); - stencil.free(gl); - if(!recreate) { + switch(detachAction) { + case DISPOSE: + case RECREATE: + depth.free(gl); + stencil.free(gl); + break; + default: + } + if(DetachAction.RECREATE != detachAction) { depth = null; stencil = null; } @@ -1516,14 +1695,15 @@ public class FBObject { default: throw new InternalError("XXX"); } - if(recreate) { + if(DetachAction.RECREATE == detachAction) { attachRenderbufferImpl2(gl, action, format); } } } /** - * Detaches all {@link ColorAttachment}s, {@link TextureAttachment}s and {@link RenderAttachment}s. + * Detaches all {@link ColorAttachment}s, {@link TextureAttachment}s and {@link RenderAttachment}s + * and disposes them. *

      Leaves the FBO bound!

      *

      * An attached sampling sink texture will be detached as well, see {@link #getSamplingSink()}. @@ -1538,7 +1718,8 @@ public class FBObject { } /** - * Detaches all {@link ColorAttachment}s and {@link TextureAttachment}s. + * Detaches all {@link ColorAttachment}s and {@link TextureAttachment}s + * and disposes them. *

      Leaves the FBO bound!

      *

      * An attached sampling sink texture will be detached as well, see {@link #getSamplingSink()}. @@ -1553,7 +1734,7 @@ public class FBObject { } /** - * Detaches all {@link TextureAttachment}s + * Detaches all {@link TextureAttachment}s and disposes them. *

      Leaves the FBO bound!

      *

      * An attached sampling sink texture will be detached as well, see {@link #getSamplingSink()}. @@ -1566,30 +1747,33 @@ public class FBObject { } for(int i=0; i reset try { for(int i=0; i0 ) { throw new InternalError("Non zero ColorAttachments "+this); } if(detachNonColorbuffer) { - detachRenderbufferImpl(gl, Attachment.Type.DEPTH_STENCIL, recreate); + detachRenderbufferImpl(gl, Attachment.Type.DEPTH_STENCIL, recreate ? DetachAction.RECREATE : DetachAction.DISPOSE); } if(ignoreStatus) { // post validate updateStatus(gl); @@ -1651,14 +1835,22 @@ public class FBObject { } private final void resetMSAATexture2DSink(GL gl) throws GLException { + if(null == samplesSink ) { + return; // this is the sample sink! + } if(0 == samples) { // MSAA off - if(null != samplesSink) { + if(samplesSink.initialized) { + // cleanup samplesSink.detachAll(gl); } return; } + if(!samplesSink.initialized) { + samplesSink.init(gl, width, height, 0); + } + boolean sampleSinkSizeMismatch = sampleSinkSizeMismatch(); boolean sampleSinkTexMismatch = sampleSinkTexMismatch(); boolean sampleSinkDepthStencilMismatch = sampleSinkDepthStencilMismatch(); @@ -1692,7 +1884,7 @@ public class FBObject { samplesSinkTexture = samplesSink.attachTexture2D(gl, 0, true); } else if( 0 == samplesSinkTexture.getName() ) { samplesSinkTexture.setSize(width, height); - samplesSink.attachTexture2D(gl, 0, samplesSinkTexture); + samplesSink.attachColorbuffer(gl, 0, samplesSinkTexture); } if( sampleSinkDepthStencilMismatch ) { @@ -1768,6 +1960,17 @@ public class FBObject { bound = false; } } + + /** + * Method simply marks this FBO unbound w/o interfering w/ the bound framebuffer as perfomed by {@link #unbind(GL)}. + *

      + * Only use this method if a subsequent {@link #unbind(GL)}, {@link #use(GL, TextureAttachment)} or {@link #bind(GL)} + * follows on any FBO. + *

      + */ + public final void markUnbound() { + bound = false; + } /** * Returns true if framebuffer object is bound via {@link #bind(GL)}, otherwise false. @@ -1785,49 +1988,54 @@ public class FBObject { public final boolean isBound() { return bound; } /** - * Samples the multisampling colorbuffer (msaa-buffer) to it's sink {@link #getSamplingSink()}. - * - *

      The operation is skipped, if no multisampling is used or - * the msaa-buffer has not been flagged dirty by a previous call of {@link #bind(GL)}, - * see {@link #isSamplingBufferDirty()}

      - * - *

      If full FBO is supported, sets the read and write framebuffer individually to default after sampling, hence not disturbing - * an optional operating MSAA FBO, see {@link GLBase#getDefaultReadFramebuffer()} and {@link GLBase#getDefaultDrawFramebuffer()}

      - * - *

      In case you intend to employ {@link GL#glReadPixels(int, int, int, int, int, int, java.nio.Buffer) glReadPixels(..)} + * If multisampling is being used and flagged dirty by a previous call of {@link #bind(GL)} or after initialization, + * the msaa-buffers are sampled to it's sink {@link #getSamplingSink()}. + *

      + * Method also updates the sampling sink configuration (if used). Hence it is recommended to call this + * method after your have initialized the FBO and attached renderbuffer etc for the 1st time. + * Method is called automatically by {@link #use(GL, TextureAttachment)}. + *

      + *

      + * Methos always resets the framebuffer binding to default in the end. + * If full FBO is supported, sets the read and write framebuffer individually to default after sampling, hence not disturbing + * an optional operating MSAA FBO, see {@link GLBase#getDefaultReadFramebuffer()} and {@link GLBase#getDefaultDrawFramebuffer()} + *

      + *

      + * In case you use this FBO w/o the {@link GLFBODrawable} and intend to employ {@link GL#glReadPixels(int, int, int, int, int, int, java.nio.Buffer) glReadPixels(..)} * you may want to call {@link GL#glBindFramebuffer(int, int) glBindFramebuffer}({@link GL2GL3#GL_READ_FRAMEBUFFER}, {@link #getReadFramebuffer()}); *

      - * *

      Leaves the FBO unbound.

      * * @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); + public final void syncFramebuffer(GL gl) { + markUnbound(); 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 + ((GL2GL3)gl).glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, // since MSAA is supported, casting to GL2GL3 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 - } + } + if(fullFBOSupport) { + // default read/draw buffers, may utilize GLContext/GLDrawable override of + // GLContext.getDefaultDrawFramebuffer() and GLContext.getDefaultReadFramebuffer() + gl.glBindFramebuffer(GL2GL3.GL_DRAW_FRAMEBUFFER, 0); + gl.glBindFramebuffer(GL2GL3.GL_READ_FRAMEBUFFER, 0); + } else { + gl.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0); // default draw buffer } } /** * Bind the given texture colorbuffer. * - *

      If multisampling is being used, {@link #syncSamplingBuffer(GL)} is being called.

      + *

      If using multiple texture units, ensure you call {@link GL#glActiveTexture(int)} first!

      + * + *

      {@link #syncFramebuffer(GL)} is being called

      * *

      Leaves the FBO unbound!

      * @@ -1837,11 +2045,7 @@ public class FBObject { */ public final void use(GL gl, TextureAttachment ta) throws IllegalArgumentException { if(null == ta) { throw new IllegalArgumentException("null TextureAttachment, this: "+toString()); } - if(samples > 0 && samplesSinkTexture == ta) { - syncSamplingBuffer(gl); - } else { - unbind(gl); - } + syncFramebuffer(gl); gl.glBindTexture(GL.GL_TEXTURE_2D, ta.getName()); // use it .. } @@ -1855,14 +2059,8 @@ public class FBObject { gl.glBindTexture(GL.GL_TEXTURE_2D, 0); // don't use it } - /** - * Returns true if basic or full FBO is supported, otherwise false. - * @param full true for full FBO supported query, otherwise false for basic FBO support query. - * @see #supportsFullFBO(GL) - * @see #supportsBasicFBO(GL) - * @throws GLException if {@link #init(GL)} hasn't been called. - */ - public final boolean supportsFBO(boolean full) throws GLException { checkInitialized(); return full ? fullFBOSupport : basicFBOSupport; } + /** @see GL#hasFullFBOSupport() */ + public final boolean hasFullFBOSupport() throws GLException { checkInitialized(); return this.fullFBOSupport; } /** * Returns true if renderbuffer accepts internal format {@link GL#GL_RGB8} and {@link GL#GL_RGBA8}, otherwise false. @@ -1878,7 +2076,7 @@ public class FBObject { public final boolean supportsDepth(int bits) throws GLException { checkInitialized(); switch(bits) { - case 16: return basicFBOSupport; + case 16: return true; case 24: return depth24Avail; case 32: return depth32Avail; default: return false; @@ -1913,11 +2111,11 @@ public class FBObject { */ public final int getMaxColorAttachments() throws GLException { checkInitialized(); return maxColorAttachments; } - /** - * Returns the maximum number of samples for multisampling. Maybe zero if multisampling is not supported. - * @throws GLException if {@link #init(GL)} hasn't been called. - */ - public final int getMaxSamples() throws GLException { checkInitialized(); return maxSamples; } + public final int getMaxTextureSize() throws GLException { checkInitialized(); return this.maxTextureSize; } + public final int getMaxRenderbufferSize() throws GLException { checkInitialized(); return this.maxRenderbufferSize; } + + /** @see GL#getMaxRenderbufferSamples() */ + public final int getMaxSamples() throws GLException { checkInitialized(); return this.maxSamples; } /** * Returns true if this instance has been initialized with {@link #reset(GL, int, int)} diff --git a/src/jogl/classes/com/jogamp/opengl/GLAutoDrawableDelegate.java b/src/jogl/classes/com/jogamp/opengl/GLAutoDrawableDelegate.java new file mode 100644 index 000000000..38a8deef8 --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/GLAutoDrawableDelegate.java @@ -0,0 +1,189 @@ +/** + * Copyright 2012 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package com.jogamp.opengl; + +import javax.media.nativewindow.AbstractGraphicsDevice; +import javax.media.nativewindow.NativeSurface; +import javax.media.nativewindow.WindowClosingProtocol; +import javax.media.nativewindow.WindowClosingProtocol.WindowClosingMode; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawable; +import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLException; + +import com.jogamp.common.util.locks.LockFactory; +import com.jogamp.common.util.locks.RecursiveLock; + +import jogamp.opengl.GLAutoDrawableBase; +import jogamp.opengl.GLContextImpl; +import jogamp.opengl.GLDrawableImpl; + + +/** + * Fully functional {@link GLAutoDrawable} implementation + * utilizing already created created {@link GLDrawable} and {@link GLContext} instances. + *

      + * Since no native windowing system events are being processed, it is recommended + * to handle at least: + *

        + *
      • {@link com.jogamp.newt.event.WindowListener#windowRepaint(com.jogamp.newt.event.WindowUpdateEvent) repaint} using {@link #windowRepaintOp()}
      • + *
      • {@link com.jogamp.newt.event.WindowListener#windowResized(com.jogamp.newt.event.WindowEvent) resize} using {@link #windowResizedOp()}
      • + *
      • {@link com.jogamp.newt.event.WindowListener#windowDestroyNotify(com.jogamp.newt.event.WindowEvent) destroy-notify} using {@link #windowDestroyNotifyOp()}
      • + *
      + *

      + *

      + * See example {@link com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableDelegateNEWT TestGLAutoDrawableDelegateNEWT}. + *

      + */ +public class GLAutoDrawableDelegate extends GLAutoDrawableBase implements GLAutoDrawable { + /** + * @param drawable a valid and already realized {@link GLDrawable} + * @param context a valid {@link GLContext}, may not be made current (created) yet. + * @param upstreamWidget optional UI element holding this instance, see {@link #getUpstreamWidget()}. + * @param ownDevice pass true if {@link AbstractGraphicsDevice#close()} shall be issued, + * otherwise pass false. Closing the device is required in case + * the drawable is created w/ it's own new instance, e.g. offscreen drawables, + * and no further lifecycle handling is applied. + * @param lock optional custom {@link RecursiveLock}. + */ + public GLAutoDrawableDelegate(GLDrawable drawable, GLContext context, Object upstreamWidget, boolean ownDevice, RecursiveLock lock) { + super((GLDrawableImpl)drawable, (GLContextImpl)context, ownDevice); + if(null == drawable) { + throw new IllegalArgumentException("null drawable"); + } + if(null == context) { + throw new IllegalArgumentException("null context"); + } + if(!drawable.isRealized()) { + throw new IllegalArgumentException("drawable not realized"); + } + this.upstreamWidget = upstreamWidget; + this.lock = ( null != lock ) ? lock : LockFactory.createRecursiveLock() ; + } + + // + // expose default methods + // + + /** Default implementation to handle repaint events from the windowing system */ + public final void windowRepaintOp() { + super.defaultWindowRepaintOp(); + } + + /** Implementation to handle resize events from the windowing system. All required locks are being claimed. */ + public final void windowResizedOp(int newWidth, int newHeight) { + super.defaultWindowResizedOp(newWidth, newHeight); + } + + /** + * Implementation to handle destroy notifications from the windowing system. + * + *

      + * If the {@link NativeSurface} does not implement {@link WindowClosingProtocol} + * or {@link WindowClosingMode#DISPOSE_ON_CLOSE} is enabled (default), + * a thread safe destruction is being induced. + *

      + */ + public final void windowDestroyNotifyOp() { + super.defaultWindowDestroyNotifyOp(); + } + + // + // Complete GLAutoDrawable + // + + private Object upstreamWidget; + private final RecursiveLock lock; + + @Override + protected final RecursiveLock getLock() { return lock; } + + @Override + public final Object getUpstreamWidget() { + return upstreamWidget; + } + + /** + * Set the upstream UI toolkit object. + * @see #getUpstreamWidget() + */ + public final void setUpstreamWidget(Object newUpstreamWidget) { + upstreamWidget = newUpstreamWidget; + } + + /** + * {@inheritDoc} + *

      + * This implementation calls {@link #defaultDestroy()}. + *

      + *

      + * User still needs to destroy the upstream window, which details are hidden from this aspect. + * This can be performed by overriding {@link #destroyImplInLock()}. + *

      + */ + @Override + public final void destroy() { + defaultDestroy(); + } + + @Override + protected void destroyImplInLock() { + super.destroyImplInLock(); + } + + @Override + public void display() { + defaultDisplay(); + } + + // + // GLDrawable delegation + // + + @Override + public final GLDrawableFactory getFactory() { + return drawable.getFactory(); + } + + @Override + public final void setRealized(boolean realized) { + } + + @Override + public final void swapBuffers() throws GLException { + defaultSwapBuffers(); + } + + @Override + public String toString() { + return getClass().getSimpleName()+"[ \n\tHelper: " + helper + ", \n\tDrawable: " + drawable + + ", \n\tContext: " + context + ", \n\tUpstreamWidget: "+upstreamWidget+ /** ", \n\tFactory: "+factory+ */ "]"; + } +} diff --git a/src/jogl/classes/com/jogamp/opengl/GLExtensions.java b/src/jogl/classes/com/jogamp/opengl/GLExtensions.java index f7e25fa01..cf81b85ee 100644 --- a/src/jogl/classes/com/jogamp/opengl/GLExtensions.java +++ b/src/jogl/classes/com/jogamp/opengl/GLExtensions.java @@ -72,6 +72,9 @@ public class GLExtensions { public static final String OES_EGL_image_external = "GL_OES_EGL_image_external"; + public static final String ARB_gpu_shader_fp64 = "GL_ARB_gpu_shader_fp64"; + public static final String ARB_shader_objects = "GL_ARB_shader_objects"; + // // Aliased GLX/WGL/.. extensions // diff --git a/src/jogl/classes/com/jogamp/opengl/OffscreenAutoDrawable.java b/src/jogl/classes/com/jogamp/opengl/OffscreenAutoDrawable.java deleted file mode 100644 index 4caea03b2..000000000 --- a/src/jogl/classes/com/jogamp/opengl/OffscreenAutoDrawable.java +++ /dev/null @@ -1,112 +0,0 @@ -/** - * Copyright 2012 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ - -package com.jogamp.opengl; - -import javax.media.nativewindow.AbstractGraphicsDevice; -import javax.media.opengl.GLAutoDrawableDelegate; -import javax.media.opengl.GLContext; -import javax.media.opengl.GLDrawable; -import javax.media.opengl.GLException; - -import jogamp.opengl.GLFBODrawableImpl; - -/** - * Platform-independent class exposing FBO offscreen functionality to - * applications. - *

      - * This class distinguishes itself from {@link GLAutoDrawableDelegate} - * with it's {@link #setSize(int, int)} functionality. - *

      - */ -public class OffscreenAutoDrawable extends GLAutoDrawableDelegate { - - /** - * @param drawable a valid {@link GLDrawable}, may not be realized yet. - * @param context a valid {@link GLContext}, may not be made current (created) yet. - * @param ownDevice pass true if {@link AbstractGraphicsDevice#close()} shall be issued, - * otherwise pass false. Closing the device is required in case - * the drawable is created w/ it's own new instance, e.g. offscreen drawables, - * and no further lifecycle handling is applied. - */ - public OffscreenAutoDrawable(GLDrawable drawable, GLContext context, boolean ownDevice) { - super(drawable, context, null, ownDevice); - } - - /** - * Attempts to resize this offscreen auto drawable, if supported - * by the underlying {@link GLDrawable). - * @param newWidth - * @param newHeight - * @return true if resize was executed, otherwise false. - * @throws GLException in case of an error during the resize operation - */ - public boolean setSize(int newWidth, int newHeight) throws GLException { - boolean done = false; - if(drawable instanceof GLFBODrawableImpl) { - Throwable tFBO = null; - Throwable tGL = null; - context.makeCurrent(); - try { - ((GLFBODrawableImpl)drawable).setSize(context.getGL(), newWidth, newHeight); - done = true; - } catch (Throwable t) { - tFBO = t; - } finally { - try { - context.release(); - } catch (Throwable t) { - tGL = t; - } - } - if(null != tFBO) { - throw new GLException("OffscreenAutoDrawable.setSize(..) GLFBODrawableImpl.setSize(..) exception", tFBO); - } - if(null != tGL) { - throw new GLException("OffscreenAutoDrawable.setSize(..) GLContext.release() exception", tGL); - } - } - if(done) { - this.defaultWindowResizedOp(); - return true; - } - return false; - } - - /** - * If the underlying {@link GLDrawable} is an FBO implementation - * and contains an {#link FBObject}, the same is returned. - * Otherwise returns null. - */ - public FBObject getFBObject() { - if(drawable instanceof GLFBODrawableImpl) { - return ((GLFBODrawableImpl)drawable).getFBObject(); - } - return null; - } -} diff --git a/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java b/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java index 8d237162c..02f62daec 100644 --- a/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java +++ b/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java @@ -30,6 +30,7 @@ package com.jogamp.opengl.swt; import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.nativewindow.NativeSurface; import javax.media.nativewindow.ProxySurface; +import javax.media.nativewindow.UpstreamSurfaceHook; import javax.media.opengl.GL; import javax.media.opengl.GLAnimatorControl; import javax.media.opengl.GLAutoDrawable; @@ -48,6 +49,7 @@ import javax.media.opengl.Threading; import jogamp.opengl.Debug; import jogamp.opengl.GLContextImpl; import jogamp.opengl.GLDrawableHelper; +import jogamp.opengl.GLDrawableImpl; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ControlAdapter; @@ -97,8 +99,8 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { private final GLCapabilitiesImmutable capsRequested; private final GLCapabilitiesChooser capsChooser; - private volatile GLDrawable drawable; // volatile: avoid locking for read-only access - private GLContext context; + private volatile GLDrawableImpl drawable; // volatile: avoid locking for read-only access + private GLContextImpl context; /* Native window surface */ private AbstractGraphicsDevice device; @@ -319,7 +321,7 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { } }); } - private final ProxySurface.UpstreamSurfaceHook swtCanvasUpStreamHook = new ProxySurface.UpstreamSurfaceHook() { + private final UpstreamSurfaceHook swtCanvasUpStreamHook = new UpstreamSurfaceHook() { @Override public final void create(ProxySurface s) { /* nop */ } @@ -349,7 +351,27 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { ( nClientArea.width != oClientArea.width || nClientArea.height != oClientArea.height ) ) { clientArea = nClientArea; // write back new value - sendReshape = true; // Mark for OpenGL reshape next time the control is painted + + GLDrawableImpl _drawable = drawable; + if( null != _drawable ) { + if(DEBUG) { + System.err.println("GLCanvas.sizeChanged: ("+Thread.currentThread().getName()+"): "+nClientArea.width+"x"+nClientArea.height+" - surfaceHandle 0x"+Long.toHexString(getNativeSurface().getSurfaceHandle())); + } + if( ! _drawable.getChosenGLCapabilities().isOnscreen() ) { + final RecursiveLock _lock = lock; + _lock.lock(); + try { + final GLDrawableImpl _drawableNew = GLDrawableHelper.resizeOffscreenDrawable(_drawable, context, nClientArea.width, nClientArea.height); + if(_drawable != _drawableNew) { + // write back + drawable = _drawableNew; + } + } finally { + _lock.unlock(); + } + sendReshape = true; // async if display() doesn't get called below, but avoiding deadlock + } + } } } @@ -391,10 +413,10 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { if(null != proxySurface) { /* Associate a GL surface with the proxy */ - drawable = glFactory.createGLDrawable(proxySurface); + drawable = (GLDrawableImpl) glFactory.createGLDrawable(proxySurface); drawable.setRealized(true); - context = drawable.createContext(shareWith); + context = (GLContextImpl) drawable.createContext(shareWith); } } finally { _lock.unlock(); @@ -455,6 +477,11 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { return helper.getAutoSwapBufferMode(); } + @Override + public final GLDrawable getDelegatedDrawable() { + return drawable; + } + @Override public GLContext getContext() { return null != drawable ? context : null; @@ -502,7 +529,7 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { _lock.lock(); try { final GLContext oldCtx = context; - final boolean newCtxCurrent = helper.switchContext(drawable, oldCtx, newCtx, additionalCtxCreationFlags); + final boolean newCtxCurrent = GLDrawableHelper.switchContext(drawable, oldCtx, newCtx, additionalCtxCreationFlags); context=(GLContextImpl)newCtx; if(newCtxCurrent) { context.makeCurrent(); diff --git a/src/jogl/classes/javax/media/opengl/GLAutoDrawable.java b/src/jogl/classes/javax/media/opengl/GLAutoDrawable.java index 0b2c664fe..38f1746f9 100644 --- a/src/jogl/classes/javax/media/opengl/GLAutoDrawable.java +++ b/src/jogl/classes/javax/media/opengl/GLAutoDrawable.java @@ -114,6 +114,12 @@ public interface GLAutoDrawable extends GLDrawable { * where you drag the window to another monitor. */ public static final boolean SCREEN_CHANGE_ACTION_ENABLED = Debug.getBooleanProperty("jogl.screenchange.action", true); + /** + * If the implementation uses delegation, return the delegated {@link GLDrawable} instance, + * otherwise return this instance. + */ + public GLDrawable getDelegatedDrawable(); + /** * Returns the context associated with this drawable. The returned * context will be synchronized. @@ -124,23 +130,31 @@ public interface GLAutoDrawable extends GLDrawable { /** * Associate a new context to this drawable and also propagates the context/drawable switch by * calling {@link GLContext#setGLDrawable(GLDrawable, boolean) newCtx.setGLDrawable(drawable, true);}. - * drawable might be an inner GLDrawable instance if using such a delegation pattern, - * or this GLAutoDrawable itself. - *

      - * If the old context's drawable was an {@link GLAutoDrawable}, it's reference to the given drawable - * is being cleared by calling - * {@link GLAutoDrawable#setContext(GLContext) ((GLAutoDrawable)oldCtx.getGLDrawable()).setContext(null)}. - *

      + * drawable might be an inner GLDrawable instance if using a delegation pattern, + * or this GLAutoDrawable instance. *

      * If the old or new context was current on this thread, it is being released before switching the drawable. * The new context will be made current afterwards, if it was current before. - * However the user shall take extra care that not other thread - * attempts to make this context current. Otherwise a race condition may happen. + * However the user shall take extra care that no other thread + * attempts to make this context current. + *

      + *

      + * Be aware that the old context is still bound to the drawable, + * and that one context can only be bound to one drawable at one time! *

      *

      - * Disclaimer: Even though the API may allows this functionality in theory, your mileage may vary - * switching the drawable of an already established GLContext, i.e. which is already made current once. - * FIXME: Validate functionality! + * In case you do not intend to use the old context anymore, i.e. + * not assigning it to another drawable, it shall be + * destroyed before setting the new context, i.e.: + *

      +            GLContext oldCtx = glad.getContext();
      +            if(null != oldCtx) {
      +                oldCtx.destroy();
      +            }
      +            glad.setContext(newCtx);            
      +   * 
      + * This is required, since a context must have a valid drawable at all times + * and this API shall not restrict the user in any way. *

      * * @param newCtx the new context diff --git a/src/jogl/classes/javax/media/opengl/GLAutoDrawableDelegate.java b/src/jogl/classes/javax/media/opengl/GLAutoDrawableDelegate.java deleted file mode 100644 index 67e81270d..000000000 --- a/src/jogl/classes/javax/media/opengl/GLAutoDrawableDelegate.java +++ /dev/null @@ -1,144 +0,0 @@ -/** - * Copyright 2012 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ - -package javax.media.opengl; - -import javax.media.nativewindow.AbstractGraphicsDevice; - -import com.jogamp.common.util.locks.LockFactory; -import com.jogamp.common.util.locks.RecursiveLock; - -import jogamp.opengl.Debug; -import jogamp.opengl.GLAutoDrawableBase; -import jogamp.opengl.GLContextImpl; -import jogamp.opengl.GLDrawableImpl; - - -/** - * Fully functional {@link GLAutoDrawable} implementation - * utilizing already created created {@link GLDrawable} and {@link GLContext} instances. - *

      - * Since no native windowing system events are being processed, it is recommended - * to handle at least: - *

        - *
      • {@link com.jogamp.newt.event.WindowListener#windowRepaint(com.jogamp.newt.event.WindowUpdateEvent) repaint} using {@link #defaultWindowRepaintOp()}
      • - *
      • {@link com.jogamp.newt.event.WindowListener#windowResized(com.jogamp.newt.event.WindowEvent) resize} using {@link #defaultWindowResizedOp()}
      • - *
      • {@link com.jogamp.newt.event.WindowListener#windowDestroyNotify(com.jogamp.newt.event.WindowEvent) destroy-notify} using {@link #defaultWindowDestroyNotifyOp()}
      • - *
      - *

      - *

      - * See example {@link com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableDelegateNEWT TestGLAutoDrawableDelegateNEWT}. - *

      - */ -public class GLAutoDrawableDelegate extends GLAutoDrawableBase { - public static final boolean DEBUG = Debug.debug("GLAutoDrawableDelegate"); - - /** - * @param drawable a valid {@link GLDrawable}, may not be realized yet. - * @param context a valid {@link GLContext}, may not be made current (created) yet. - * @param upstreamWidget optional UI element holding this instance, see {@link #getUpstreamWidget()}. - * @param ownDevice pass true if {@link AbstractGraphicsDevice#close()} shall be issued, - * otherwise pass false. Closing the device is required in case - * the drawable is created w/ it's own new instance, e.g. offscreen drawables, - * and no further lifecycle handling is applied. - */ - public GLAutoDrawableDelegate(GLDrawable drawable, GLContext context, Object upstreamWidget, boolean ownDevice) { - super((GLDrawableImpl)drawable, (GLContextImpl)context, ownDevice); - this.upstreamWidget = null; - } - - // - // expose default methods - // - - public final void windowRepaintOp() { - super.defaultWindowRepaintOp(); - } - - public final void windowResizedOp() { - super.defaultWindowResizedOp(); - } - - public final void windowDestroyNotifyOp() { - super.defaultWindowDestroyNotifyOp(); - } - - // - // Complete GLAutoDrawable - // - - private final RecursiveLock lock = LockFactory.createRecursiveLock(); // instance wide lock - private final Object upstreamWidget; - - @Override - protected final RecursiveLock getLock() { return lock; } - - @Override - public final Object getUpstreamWidget() { - return upstreamWidget; - } - - /** - * {@inheritDoc} - *

      - * This implementation calls {@link #defaultDestroy()}. - *

      - *

      - * User still needs to destroy the upstream window, which details are hidden from this aspect. - * This can be performed by overriding {@link #destroyImplInLock()}. - *

      - */ - @Override - public final void destroy() { - defaultDestroy(); - } - - @Override - public void display() { - defaultDisplay(); - } - - // - // GLDrawable delegation - // - - @Override - public final GLDrawableFactory getFactory() { - return drawable.getFactory(); - } - - @Override - public final void setRealized(boolean realized) { - } - - @Override - public final void swapBuffers() throws GLException { - defaultSwapBuffers(); - } - -} diff --git a/src/jogl/classes/javax/media/opengl/GLBase.java b/src/jogl/classes/javax/media/opengl/GLBase.java index f5831a72d..9bcee819a 100644 --- a/src/jogl/classes/javax/media/opengl/GLBase.java +++ b/src/jogl/classes/javax/media/opengl/GLBase.java @@ -273,6 +273,42 @@ public interface GLBase { */ public boolean isExtensionAvailable(String glExtensionName); + /** + * Returns true if basic FBO support is available, otherwise false. + *

      + * Basic FBO is supported if the context is either GL-ES >= 2.0, GL >= core 3.0 or implements the extensions + * GL_ARB_ES2_compatibility, GL_ARB_framebuffer_object, GL_EXT_framebuffer_object or GL_OES_framebuffer_object. + *

      + *

      + * Basic FBO support may only include one color attachment and no multisampling, + * as well as limited internal formats for renderbuffer. + *

      + * @see GLContext#hasBasicFBOSupport() + */ + public boolean hasBasicFBOSupport(); + + /** + * Returns true if full FBO support is available, otherwise false. + *

      + * Full FBO is supported if the context is either GL >= core 3.0 or implements the extensions + * ARB_framebuffer_object, or all of + * EXT_framebuffer_object, EXT_framebuffer_multisample, + * EXT_framebuffer_blit, GL_EXT_packed_depth_stencil. + *

      + *

      + * Full FBO support includes multiple color attachments and multisampling. + *

      + * @see GLContext#hasFullFBOSupport() + */ + public boolean hasFullFBOSupport(); + + /** + * Returns the maximum number of FBO RENDERBUFFER samples + * if {@link #hasFullFBOSupport() full FBO is supported}, otherwise false. + * @see GLContext#getMaxRenderbufferSamples() + */ + public int getMaxRenderbufferSamples(); + /** * Returns true if the GL context supports non power of two (NPOT) textures, * otherwise false. @@ -284,6 +320,8 @@ public interface GLBase { */ public boolean isNPOTTextureAvailable(); + public boolean isTextureFormatBGRA8888Available(); + /** Provides a platform-independent way to specify the minimum swap interval for buffer swaps. An argument of 0 disables sync-to-vertical-refresh completely, while an argument of 1 diff --git a/src/jogl/classes/javax/media/opengl/GLContext.java b/src/jogl/classes/javax/media/opengl/GLContext.java index c2f94b9af..a5e639c74 100644 --- a/src/jogl/classes/javax/media/opengl/GLContext.java +++ b/src/jogl/classes/javax/media/opengl/GLContext.java @@ -96,6 +96,9 @@ public abstract class GLContext { */ public static final boolean PROFILE_ALIASING = !Debug.isPropertyDefined("jogl.debug.GLContext.NoProfileAliasing", true); + protected static final boolean FORCE_NO_FBO_SUPPORT = Debug.isPropertyDefined("jogl.fbo.force.none", true); + protected static final boolean FORCE_MIN_FBO_SUPPORT = Debug.isPropertyDefined("jogl.fbo.force.min", true); + public static final boolean DEBUG = Debug.debug("GLContext"); public static final boolean TRACE_SWITCH = Debug.isPropertyDefined("jogl.debug.GLContext.TraceSwitch", true); @@ -127,9 +130,9 @@ public abstract class GLContext { /** GL_ARB_ES2_compatibility implementation related: Context is compatible w/ ES2. Not a cache key. See {@link #isGLES2Compatible()}, {@link #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile)}. */ protected static final int CTX_IMPL_ES2_COMPAT = 1 << 8; - /** Context supports basic FBO, details see {@link #hasFBO()}. + /** Context supports basic FBO, details see {@link #hasBasicFBOSupport()}. * Not a cache key. - * @see #hasFBO() + * @see #hasBasicFBOSupport() * @see #getAvailableContextProperties(AbstractGraphicsDevice, GLProfile) */ protected static final int CTX_IMPL_FBO = 1 << 9; @@ -178,11 +181,6 @@ public abstract class GLContext { * and made current afterwards. However the user shall take extra care that not other thread * attempts to make this context current. Otherwise a race condition may happen. *

      - *

      - * Disclaimer: Even though the API may allows this functionality in theory, your mileage may vary - * switching the drawable of an already established GLContext, i.e. which is already made current once. - * FIXME: Validate functionality! - *

      * @param readWrite the read/write drawable for framebuffer operations. * @param setWriteOnly if true and if the current read-drawable differs * from the write-drawable ({@link #setGLReadDrawable(GLDrawable)}), @@ -603,12 +601,23 @@ public abstract class GLContext { /** * @return true if impl. is a hardware rasterizer, otherwise false. + * @see #isHardwareRasterizer(AbstractGraphicsDevice, GLProfile) * @see GLProfile#isHardwareRasterizer() */ public final boolean isHardwareRasterizer() { return 0 == ( ctxOptions & CTX_IMPL_ACCEL_SOFT ) ; } + /** + * @return true if context supports GLSL, i.e. is either {@link #isGLES2()}, {@link #isGL3()} or {@link #isGL2()} and major-version > 1. + * @see GLProfile#hasGLSL() + */ + public final boolean hasGLSL() { + return isGLES2() || + isGL3() || + isGL2() && ctxMajorVersion>1 ; + } + /** * Returns true if basic FBO support is available, otherwise false. *

      @@ -620,21 +629,54 @@ public abstract class GLContext { * as well as limited internal formats for renderbuffer. *

      * @see #CTX_IMPL_FBO - * @see com.jogamp.opengl.FBObject#supportsBasicFBO(GL) - * @see com.jogamp.opengl.FBObject#supportsFullFBO(GL) */ - public final boolean hasFBO() { + public final boolean hasBasicFBOSupport() { return 0 != ( ctxOptions & CTX_IMPL_FBO ) ; } + /** + * Returns true if full FBO support is available, otherwise false. + *

      + * Full FBO is supported if the context is either GL >= core 3.0 or implements the extensions + * ARB_framebuffer_object, or all of + * EXT_framebuffer_object, EXT_framebuffer_multisample, + * EXT_framebuffer_blit, GL_EXT_packed_depth_stencil. + *

      + *

      + * Full FBO support includes multiple color attachments and multisampling. + *

      + */ + public final boolean hasFullFBOSupport() { + return !FORCE_MIN_FBO_SUPPORT && hasBasicFBOSupport() && + ( isGL3() || // GL >= 3.0 + isExtensionAvailable(GLExtensions.ARB_framebuffer_object) || // ARB_framebuffer_object + ( isExtensionAvailable(GLExtensions.EXT_framebuffer_object) && // All EXT_framebuffer_object* + isExtensionAvailable(GLExtensions.EXT_framebuffer_multisample) && + isExtensionAvailable(GLExtensions.EXT_framebuffer_blit) && + isExtensionAvailable(GLExtensions.EXT_packed_depth_stencil) + ) + ) ; + } + /** - * @return true if context supports GLSL - * @see GLProfile#hasGLSL() + * Returns the maximum number of FBO RENDERBUFFER samples + * if {@link #hasFullFBOSupport() full FBO is supported}, otherwise false. */ - public final boolean hasGLSL() { - return isGL2ES2() ; + public final int getMaxRenderbufferSamples() { + if( hasFullFBOSupport() ) { + final GL gl = getGL(); + final int[] val = new int[] { 0 } ; + gl.glGetIntegerv(GL2GL3.GL_MAX_SAMPLES, val, 0); + final int glerr = gl.glGetError(); + if(GL.GL_NO_ERROR == glerr) { + return val[0]; + } else if(DEBUG) { + System.err.println("GLContext.getMaxRenderbufferSamples: GL_MAX_SAMPLES query GL Error 0x"+Integer.toHexString(glerr)); + } + } + return 0; } - + /** Note: The GL impl. may return a const value, ie {@link GLES2#isNPOTTextureAvailable()} always returns true. */ public boolean isNPOTTextureAvailable() { return isGL3() || isGLES2Compatible() || isExtensionAvailable(GLExtensions.ARB_texture_non_power_of_two); @@ -1014,6 +1056,9 @@ public abstract class GLContext { validateProfileBits(profile, "profile"); validateProfileBits(resCtp, "resCtp"); + if(FORCE_NO_FBO_SUPPORT) { + resCtp &= ~CTX_IMPL_FBO ; + } if(DEBUG) { System.err.println("GLContext.mapAvailableGLVersion: "+device+": "+getGLVersion(reqMajor, 0, profile, null)+" -> "+getGLVersion(resMajor, resMinor, resCtp, null)); // Thread.dumpStack(); @@ -1197,17 +1242,35 @@ public abstract class GLContext { * FBO feature is implemented in OpenGL, hence it is {@link GLProfile} dependent. *

      *

      - * FBO support is queried as described in {@link #hasFBO()}. + * FBO support is queried as described in {@link #hasBasicFBOSupport()}. *

      * * @param device the device to request whether FBO is available for * @param glp {@link GLProfile} to check for FBO capabilities - * @see GLContext#hasFBO() + * @see GLContext#hasBasicFBOSupport() */ public static final boolean isFBOAvailable(AbstractGraphicsDevice device, GLProfile glp) { return 0 != ( CTX_IMPL_FBO & getAvailableContextProperties(device, glp) ); } + /** + * @return 1 if using a hardware rasterizer, 0 if using a software rasterizer and -1 if not determined yet. + * @see GLContext#isHardwareRasterizer() + * @see GLProfile#isHardwareRasterizer() + */ + public static final int isHardwareRasterizer(AbstractGraphicsDevice device, GLProfile glp) { + final int r; + final int ctp = getAvailableContextProperties(device, glp); + if(0 == ctp) { + r = -1; + } else if( 0 == ( CTX_IMPL_ACCEL_SOFT & ctp ) ) { + r = 1; + } else { + r = 0; + } + return r; + } + /** * @param device the device to request whether the profile is available for * @param reqMajor Key Value either 1, 2, 3 or 4 diff --git a/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java b/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java index 9fd895c1f..b6e7b0576 100644 --- a/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java +++ b/src/jogl/classes/javax/media/opengl/GLDrawableFactory.java @@ -48,13 +48,16 @@ import java.util.List; import com.jogamp.common.JogampRuntimeException; import com.jogamp.common.util.ReflectionUtil; +import com.jogamp.opengl.GLAutoDrawableDelegate; import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.nativewindow.AbstractGraphicsScreen; +import javax.media.nativewindow.AbstractGraphicsConfiguration; +import javax.media.nativewindow.CapabilitiesImmutable; import javax.media.nativewindow.NativeSurface; import javax.media.nativewindow.NativeWindowFactory; import javax.media.nativewindow.ProxySurface; -import javax.media.nativewindow.ProxySurface.UpstreamSurfaceHook; +import javax.media.nativewindow.UpstreamSurfaceHook; import jogamp.opengl.Debug; @@ -373,44 +376,63 @@ public abstract class GLDrawableFactory { // Methods to create high-level objects /** - * Returns a GLDrawable according to it's chosen Capabilities,
      + * Returns a GLDrawable according to it's chosen {@link GLCapabilitiesImmutable},
      * which determines pixel format, on- and offscreen incl. PBuffer type. *

      - * The native platform's chosen Capabilties are referenced within the target - * NativeSurface's AbstractGraphicsConfiguration.

      - * - * In case target's {@link javax.media.nativewindow.Capabilities#isOnscreen()} is true,
      - * an onscreen GLDrawable will be realized. + * The chosen {@link GLCapabilitiesImmutable} are referenced within the target + * {@link NativeSurface}'s {@link AbstractGraphicsConfiguration}.

      + *

      *

      - * In case target's {@link javax.media.nativewindow.Capabilities#isOnscreen()} is false,
      - * either a Pbuffer drawable is created if target's {@link javax.media.opengl.GLCapabilities#isPBuffer()} is true,
      - * or a simple pixmap/bitmap drawable is created. The latter is unlikely to be hardware accelerated.
      + * An onscreen GLDrawable is created if {@link CapabilitiesImmutable#isOnscreen() caps.isOnscreen()} is true. + *

      *

      - * + * A FBO drawable is created if both {@link GLCapabilitiesImmutable#isFBO() caps.isFBO()} + * and {@link GLContext#isFBOAvailable(AbstractGraphicsDevice, GLProfile) canCreateFBO(device, caps.getGLProfile())} is true. + *

      + *

      + * A Pbuffer drawable is created if both {@link GLCapabilitiesImmutable#isPBuffer() caps.isPBuffer()} + * and {@link #canCreateGLPbuffer(AbstractGraphicsDevice) canCreateGLPbuffer(device)} is true. + *

      + *

      + * If not onscreen and neither FBO nor Pbuffer is available, + * a simple pixmap/bitmap drawable/surface is created, which is unlikely to be hardware accelerated. + *

      + * * @throws IllegalArgumentException if the passed target is null * @throws GLException if any window system-specific errors caused * the creation of the GLDrawable to fail. * + * @see #canCreateGLPbuffer(AbstractGraphicsDevice) + * @see GLContext#isFBOAvailable(AbstractGraphicsDevice, GLProfile) + * @see javax.media.opengl.GLCapabilities#isOnscreen() + * @see javax.media.opengl.GLCapabilities#isFBO() + * @see javax.media.opengl.GLCapabilities#isPBuffer() * @see javax.media.nativewindow.GraphicsConfigurationFactory#chooseGraphicsConfiguration(Capabilities, CapabilitiesChooser, AbstractGraphicsScreen) */ public abstract GLDrawable createGLDrawable(NativeSurface target) throws IllegalArgumentException, GLException; - + /** - * Creates a Offscreen GLDrawable incl it's offscreen {@link javax.media.nativewindow.NativeSurface} with the given capabilites and dimensions. + * Creates an {@link GLOffscreenAutoDrawable} incl it's offscreen {@link javax.media.nativewindow.NativeSurface} with the given capabilites and dimensions. *

      - * It's {@link AbstractGraphicsConfiguration} is properly set according to the given {@link GLCapabilitiesImmutable}, see below. + * The {@link GLOffscreenAutoDrawable}'s {@link GLDrawable} is realized and it's {@link GLContext} assigned but not yet made current. *

      *

      - * A FBO drawable is created if both {@link javax.media.opengl.GLCapabilities#isFBO() caps.isFBO()} + * In case the passed {@link GLCapabilitiesImmutable} contains default values, i.e. + * {@link GLCapabilitiesImmutable#isOnscreen() caps.isOnscreen()} == true, + * it is auto-configured. The latter will set offscreen and also FBO or Pbuffer, whichever is available in that order. + *

      + *

      + * A FBO based auto drawable, {@link GLOffscreenAutoDrawable.FBO}, is created if both {@link GLCapabilitiesImmutable#isFBO() caps.isFBO()} * and {@link GLContext#isFBOAvailable(AbstractGraphicsDevice, GLProfile) canCreateFBO(device, caps.getGLProfile())} is true. *

      *

      - * A Pbuffer drawable is created if both {@link javax.media.opengl.GLCapabilities#isPBuffer() caps.isPBuffer()} - * and {@link #canCreateGLPbuffer(javax.media.nativewindow.AbstractGraphicsDevice) canCreateGLPbuffer(device)} is true. + * A Pbuffer based auto drawable is created if both {@link GLCapabilitiesImmutable#isPBuffer() caps.isPBuffer()} + * and {@link #canCreateGLPbuffer(AbstractGraphicsDevice) canCreateGLPbuffer(device)} is true. *

      *

      - * If neither FBO nor Pbuffer is available, a simple pixmap/bitmap drawable/surface is created, which is unlikely to be hardware accelerated. + * If neither FBO nor Pbuffer is available, + * a simple pixmap/bitmap auto drawable is created, which is unlikely to be hardware accelerated. *

      * * @param device which {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection() connection} denotes the shared device to be used, may be null for the platform's default device. @@ -418,17 +440,55 @@ public abstract class GLDrawableFactory { * @param chooser the custom chooser, may be null for default * @param width the requested offscreen width * @param height the requested offscreen height + * @return the created and initialized offscreen {@link GLOffscreenAutoDrawable} instance * - * @return the created offscreen GLDrawable + * @throws GLException if any window system-specific errors caused + * the creation of the Offscreen to fail. + * + * @see #createOffscreenDrawable(AbstractGraphicsDevice, GLCapabilitiesImmutable, GLCapabilitiesChooser, int, int) + */ + public abstract GLOffscreenAutoDrawable createOffscreenAutoDrawable(AbstractGraphicsDevice device, + GLCapabilitiesImmutable caps, + GLCapabilitiesChooser chooser, + int width, int height, + GLContext shareWith) throws GLException; + /** + * Creates a offscreen {@link GLDrawable} incl it's offscreen {@link javax.media.nativewindow.NativeSurface} with the given capabilites and dimensions. + *

      + * In case the passed {@link GLCapabilitiesImmutable} contains default values, i.e. + * {@link GLCapabilitiesImmutable#isOnscreen() caps.isOnscreen()} == true, + * it is auto-configured. The latter will set offscreen and also FBO or Pbuffer, whichever is available in that order. + *

      + *

      + * A resizeable FBO drawable, {@link GLFBODrawable.Resizeable}, is created if both {@link GLCapabilitiesImmutable#isFBO() caps.isFBO()} + * and {@link GLContext#isFBOAvailable(AbstractGraphicsDevice, GLProfile) canCreateFBO(device, caps.getGLProfile())} is true. + *

      + *

      + * A Pbuffer drawable is created if both {@link GLCapabilitiesImmutable#isPBuffer() caps.isPBuffer()} + * and {@link #canCreateGLPbuffer(AbstractGraphicsDevice) canCreateGLPbuffer(device)} is true. + *

      + *

      + * If neither FBO nor Pbuffer is available, + * a simple pixmap/bitmap drawable is created, which is unlikely to be hardware accelerated. + *

      + * + * @param device which {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection() connection} denotes the shared device to be used, may be null for the platform's default device. + * @param caps the requested GLCapabilties + * @param chooser the custom chooser, may be null for default + * @param width the requested offscreen width + * @param height the requested offscreen height + * + * @return the created offscreen {@link GLDrawable} * * @throws GLException if any window system-specific errors caused * the creation of the Offscreen to fail. + * + * @see #createOffscreenAutoDrawable(AbstractGraphicsDevice, GLCapabilitiesImmutable, GLCapabilitiesChooser, int, int, GLContext) */ public abstract GLDrawable createOffscreenDrawable(AbstractGraphicsDevice device, - GLCapabilitiesImmutable capabilities, + GLCapabilitiesImmutable caps, GLCapabilitiesChooser chooser, - int width, int height) - throws GLException; + int width, int height) throws GLException; /** * Creates a proxy {@link NativeSurface} w/ defined surface handle, i.e. a {@link WrappedSurface} or {@link GDISurface} instance. @@ -458,6 +518,21 @@ public abstract class GLDrawableFactory { long windowHandle, GLCapabilitiesImmutable caps, GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstream); + /** + * Returns true if it is possible to create an framebuffer object (FBO). + *

      + * FBO feature is implemented in OpenGL, hence it is {@link GLProfile} dependent. + *

      + *

      + * FBO support is queried as described in {@link GLContext#hasBasicFBOSupport()}. + *

      + * + * @param device which {@link javax.media.nativewindow.AbstractGraphicsDevice#getConnection() connection} denotes the shared the target device, may be null for the platform's default device. + * @param glp {@link GLProfile} to check for FBO capabilities + * @see GLContext#hasBasicFBOSupport() + */ + public abstract boolean canCreateFBO(AbstractGraphicsDevice device, GLProfile glp); + /** * Returns true if it is possible to create a GLPbuffer. Some older * graphics cards do not have this capability. @@ -467,7 +542,10 @@ public abstract class GLDrawableFactory { public abstract boolean canCreateGLPbuffer(AbstractGraphicsDevice device); /** - * Creates a GLPbuffer with the given capabilites and dimensions.

      + * Creates a GLPbuffer {@link GLAutoDrawable} with the given capabilites and dimensions. + *

      + * The GLPbuffer drawable is realized and initialized eagerly. + *

      * * See the note in the overview documentation on * context sharing. @@ -479,10 +557,12 @@ public abstract class GLDrawableFactory { * @param initialHeight initial height of pbuffer * @param shareWith a shared GLContext this GLPbuffer shall use * - * @return the new {@link GLPbuffer} specific {@link GLAutoDrawable} + * @return the created and initialized {@link GLPbuffer} instance * * @throws GLException if any window system-specific errors caused * the creation of the GLPbuffer to fail. + * + * @deprecated {@link GLPbuffer} is deprecated, use {@link #createOffscreenAutoDrawable(AbstractGraphicsDevice, GLCapabilitiesImmutable, GLCapabilitiesChooser, int, int, GLContext)} */ public abstract GLPbuffer createGLPbuffer(AbstractGraphicsDevice device, GLCapabilitiesImmutable capabilities, diff --git a/src/jogl/classes/javax/media/opengl/GLFBODrawable.java b/src/jogl/classes/javax/media/opengl/GLFBODrawable.java new file mode 100644 index 000000000..45fd3b686 --- /dev/null +++ b/src/jogl/classes/javax/media/opengl/GLFBODrawable.java @@ -0,0 +1,173 @@ +/** + * Copyright 2012 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package javax.media.opengl; + +import javax.media.nativewindow.NativeWindowException; + +import com.jogamp.opengl.FBObject; +import com.jogamp.opengl.FBObject.TextureAttachment; + +/** + * Platform-independent {@link GLDrawable} specialization, + * exposing {@link FBObject} functionality. + * + *

      + * A {@link GLFBODrawable} is uninitialized until a {@link GLContext} is bound + * and made current the first time. + *

      + * + *

      + * MSAA is used if {@link GLCapabilitiesImmutable#getNumSamples() requested}. + *

      + *

      + * Double buffering is used if {@link GLCapabilitiesImmutable#getDoubleBuffered() requested}. + *

      + *

      + * In MSAA mode, it always uses the implicit 2nd {@link FBObject framebuffer} {@link FBObject#getSamplingSinkFBO() sink}. + * Hence double buffering is always the case w/ MSAA. + *

      + *

      + * In non MSAA a second explicit {@link FBObject framebuffer} is being used. + * This method allows compliance w/ the spec, i.e. read and draw framebuffer selection + * and double buffer usage for e.g. {@link GL#glReadPixels(int, int, int, int, int, int, java.nio.Buffer) glReadPixels(..)}. + * This method also allows usage of both textures seperately. + *

      + *

      + * It would be possible to implement double buffering simply using + * {@link FBObject.TextureAttachment texture attachment}s with one {@link FBObject framebuffer}. + * This would require mode selection and hence complicate the API. Besides, it would + * not support differentiation of read and write framebuffer and hence not be spec compliant. + *

      + *

      + * Actual swapping of the {@link FBObject.TextureAttachment texture}s or {@link FBObject framebuffer} + * is performed either in the {@link #contextMadeCurrent(boolean) context current hook} + * or when {@link #swapBuffersImpl(boolean) swapping buffers}, whatever comes first.
      + *

      + */ +public interface GLFBODrawable extends GLDrawable { + // public enum DoubleBufferMode { NONE, TEXTURE, FBO }; // TODO: Add or remove TEXTURE (only) DoubleBufferMode support + + /** + * @return true if initialized, i.e. a {@link GLContext} is bound and made current once, otherwise false. + */ + public boolean isInitialized(); + + /** + * Notify this instance about upstream size change + * to reconfigure the {@link FBObject}. + * @param gl GL context object bound to this drawable, will be made current during operation. + * A prev. current context will be make current after operation. + * @throws GLException if resize operation failed + */ + void resetSize(GL gl) throws GLException; + + /** + * @return the used texture unit + */ + int getTextureUnit(); + + /** + * + * @param unit the texture unit to be used + */ + void setTextureUnit(int unit); + + /** + * Set a new sample size + * @param gl GL context object bound to this drawable, will be made current during operation. + * A prev. current context will be make current after operation. + * @param newSamples new sample size + * @throws GLException if resetting the FBO failed + */ + void setNumSamples(GL gl, int newSamples) throws GLException; + + /** + * @return the number of sample buffers if using MSAA, otherwise 0 + */ + int getNumSamples(); + + /** + * @return the used {@link DoubleBufferMode} + */ + // DoubleBufferMode getDoubleBufferMode(); // TODO: Add or remove TEXTURE (only) DoubleBufferMode support + + /** + * Sets the {@link DoubleBufferMode}. Must be called before {@link #isInitialized() initialization}, + * otherwise an exception is thrown. + *

      + * This call has no effect is MSAA is selected, since MSAA always forces the mode to {@link DoubleBufferMode#FBO FBO}. + * Also setting the mode to {@link DoubleBufferMode#NONE NONE} where double buffering is {@link GLCapabilitiesImmutable#getDoubleBuffered() requested} + * or setting a double buffering mode w/o {@link GLCapabilitiesImmutable#getDoubleBuffered() request} will be ignored. + *

      + *

      + * Since {@link DoubleBufferMode#TEXTURE TEXTURE} mode is currently not implemented, this method has no effect. + *

      + * @throws GLException if already initialized, see {@link #isInitialized()}. + */ + // void setDoubleBufferMode(DoubleBufferMode mode) throws GLException; // TODO: Add or remove TEXTURE (only) DoubleBufferMode support + + /** + * If MSAA is being used and {@link GL#GL_FRONT} is requested, + * the internal {@link FBObject} {@link FBObject#getSamplingSinkFBO() sample sink} is being returned. + * + * @param bufferName {@link GL#GL_FRONT} and {@link GL#GL_BACK} are valid buffer names + * @return the named {@link FBObject} + * @throws IllegalArgumentException if an illegal buffer name is being used + */ + FBObject getFBObject(int bufferName) throws IllegalArgumentException; + + /** + * Returns the named texture buffer. + *

      + * If MSAA is being used, only the {@link GL#GL_FRONT} buffer is accessible + * and an exception is being thrown if {@link GL#GL_BACK} is being requested. + *

      + * @param bufferName {@link GL#GL_FRONT} and {@link GL#GL_BACK} are valid buffer names + * @return the named {@link TextureAttachment} + * @throws IllegalArgumentException if using MSAA and {@link GL#GL_BACK} is requested or an illegal buffer name is being used + */ + FBObject.TextureAttachment getTextureBuffer(int bufferName) throws IllegalArgumentException; + + /** Resizeable {@link GLFBODrawable} specialization */ + public interface Resizeable extends GLFBODrawable { + /** + * Resize this drawable. + *

      + * This drawable is being locked during operation. + *

      + * @param context the {@link GLContext} bound to this drawable, will be made current during operation + * A prev. current context will be make current after operation. + * @param newWidth + * @param newHeight + * @throws NativeWindowException in case the surface could no be locked + * @throws GLException in case an error during the resize operation occurred + */ + void setSize(GLContext context, int newWidth, int newHeight) throws NativeWindowException, GLException; + } +} diff --git a/src/jogl/classes/javax/media/opengl/GLOffscreenAutoDrawable.java b/src/jogl/classes/javax/media/opengl/GLOffscreenAutoDrawable.java new file mode 100644 index 000000000..6fe76a3f4 --- /dev/null +++ b/src/jogl/classes/javax/media/opengl/GLOffscreenAutoDrawable.java @@ -0,0 +1,63 @@ +/** + * Copyright 2012 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package javax.media.opengl; + +import javax.media.nativewindow.NativeWindowException; + +import com.jogamp.opengl.FBObject; + +/** + * Platform-independent {@link GLAutoDrawable} specialization, + * exposing offscreen functionality. + *

      + * This class distinguishes itself from {@link GLAutoDrawable} + * with it's {@link #setSize(int, int)} functionality. + *

      + */ +public interface GLOffscreenAutoDrawable extends GLAutoDrawable { + + /** + * Resize this auto drawable. + * @param newWidth + * @param newHeight + * @throws NativeWindowException in case the surface could no be locked + * @throws GLException in case of an error during the resize operation + */ + void setSize(int newWidth, int newHeight) throws NativeWindowException, GLException; + + /** + * Set the upstream UI toolkit object. + * @see #getUpstreamWidget() + */ + void setUpstreamWidget(Object newUpstreamWidget); + + /** {@link FBObject} based {@link GLOffscreenAutoDrawable} specialization */ + public interface FBO extends GLOffscreenAutoDrawable, GLFBODrawable { + } +} diff --git a/src/jogl/classes/javax/media/opengl/GLPbuffer.java b/src/jogl/classes/javax/media/opengl/GLPbuffer.java index 273a992cf..de7731a3b 100644 --- a/src/jogl/classes/javax/media/opengl/GLPbuffer.java +++ b/src/jogl/classes/javax/media/opengl/GLPbuffer.java @@ -45,7 +45,11 @@ package javax.media.opengl; contains experimental methods for accessing the pbuffer's contents as a texture map and enabling rendering to floating-point frame buffers. These methods are not guaranteed to be supported on all - platforms and may be deprecated in a future release. */ + platforms and may be deprecated in a future release. + + @deprecated Use {@link GLOffscreenAutoDrawable} w/ {@link GLCapabilities#setFBO(boolean)} + via {@link GLDrawableFactory#createOffscreenAutoDrawable(javax.media.nativewindow.AbstractGraphicsDevice, GLCapabilitiesImmutable, GLCapabilitiesChooser, int, int, GLContext) GLDrawableFactory.createOffscreenAutoDrawable(..)}. + */ public interface GLPbuffer extends GLAutoDrawable { /** Indicates the GL_APPLE_float_pixels extension is being used for this pbuffer. */ diff --git a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java index 033591fe3..329cf9e3f 100644 --- a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java +++ b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java @@ -98,6 +98,7 @@ import jogamp.common.awt.AWTEDTExecutor; import jogamp.opengl.Debug; import jogamp.opengl.GLContextImpl; import jogamp.opengl.GLDrawableHelper; +import jogamp.opengl.GLDrawableImpl; // FIXME: Subclasses need to call resetGLFunctionAvailability() on their // context whenever the displayChanged() function is called on our @@ -109,6 +110,16 @@ import jogamp.opengl.GLDrawableHelper; interfaces when adding a heavyweight doesn't work either because of Z-ordering or LayoutManager problems. * + *
      Offscreen Layer Remarks
      + * + * {@link OffscreenLayerOption#setShallUseOffscreenLayer(boolean) setShallUseOffscreenLayer(true)} + * maybe called to use an offscreen drawable (FBO or PBuffer) allowing + * the underlying JAWT mechanism to composite the image, if supported. + *

      + * {@link OffscreenLayerOption#setShallUseOffscreenLayer(boolean) setShallUseOffscreenLayer(true)} + * is being called if {@link GLCapabilitiesImmutable#isOnscreen()} is false. + *

      + * *
      Java2D OpenGL Remarks
      * * To avoid any conflicts with a potential Java2D OpenGL context,
      @@ -145,7 +156,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing private final RecursiveLock lock = LockFactory.createRecursiveLock(); private final GLDrawableHelper helper = new GLDrawableHelper(); private AWTGraphicsConfiguration awtConfig; - private volatile GLDrawable drawable; // volatile: avoid locking for read-only access + private volatile GLDrawableImpl drawable; // volatile: avoid locking for read-only access private volatile JAWTWindow jawtWindow; // the JAWTWindow presentation of this AWT Canvas, bound to the 'drawable' lifecycle private GLContextImpl context; private volatile boolean sendReshape = false; // volatile: maybe written by EDT w/o locking @@ -237,6 +248,9 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing // don't allow the user to change data capsReqUser = (GLCapabilitiesImmutable) capsReqUser.cloneMutable(); } + if(!capsReqUser.isOnscreen()) { + setShallUseOffscreenLayer(true); // trigger offscreen layer - if supported + } if(null==device) { GraphicsConfiguration gc = super.getGraphicsConfiguration(); @@ -451,11 +465,9 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing /** Overridden to cause OpenGL rendering to be performed during repaint cycles. Subclasses which override this method must call super.paint() in their paint() method in order to function - properly.

      - - Overrides: -

      paint in class java.awt.Component
      */ - @Override + properly. + */ + @Override public void paint(Graphics g) { if (Beans.isDesignTime()) { // Make GLCanvas behave better in NetBeans GUI builder @@ -544,7 +556,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing jawtWindow.setShallUseOffscreenLayer(shallUseOffscreenLayer); jawtWindow.lockSurface(); try { - drawable = GLDrawableFactory.getFactory(capsReqUser.getGLProfile()).createGLDrawable(jawtWindow); + drawable = (GLDrawableImpl) GLDrawableFactory.getFactory(capsReqUser.getGLProfile()).createGLDrawable(jawtWindow); context = (GLContextImpl) drawable.createContext(shareWith); context.setContextCreationFlags(additionalCtxCreationFlags); } finally { @@ -561,13 +573,15 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing 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(); + AWTEDTExecutor.singleton.invoke(getTreeLock(), true, setRealizedOnEDTAction); + if( _drawable.isRealized() ) { + sendReshape=true; // ensure a reshape is being send .. + if(DEBUG) { + System.err.println(getThreadName()+": Realized Drawable: "+_drawable.toString()); + Thread.dumpStack(); + } + return true; } - return true; } } return false; @@ -575,7 +589,10 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing private Runnable setRealizedOnEDTAction = new Runnable() { @Override public void run() { - drawable.setRealized(true); + final GLDrawable _drawable = drawable; + if ( null != _drawable && 0 < _drawable.getWidth() * _drawable.getHeight() ) { + _drawable.setRealized(true); + } } }; /**

      Overridden to track when this component is removed from a @@ -620,22 +637,37 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing @SuppressWarnings("deprecation") @Override public void reshape(int x, int y, int width, int height) { - super.reshape(x, y, width, height); - final GLDrawable _drawable = drawable; - if(null != _drawable && _drawable.isRealized() && !_drawable.getChosenGLCapabilities().isOnscreen()) { - dispose(true); - } else { - sendReshape = true; + synchronized (getTreeLock()) { // super.reshape(..) claims tree lock, so we do extend it's lock over reshape + super.reshape(x, y, width, height); + + GLDrawableImpl _drawable = drawable; + if( null != _drawable ) { + if(DEBUG) { + System.err.println("GLCanvas.sizeChanged: ("+Thread.currentThread().getName()+"): "+width+"x"+height+" - surfaceHandle 0x"+Long.toHexString(getNativeSurface().getSurfaceHandle())); + } + if( ! _drawable.getChosenGLCapabilities().isOnscreen() ) { + final RecursiveLock _lock = lock; + _lock.lock(); + try { + final GLDrawableImpl _drawableNew = GLDrawableHelper.resizeOffscreenDrawable(_drawable, context, width, height); + if(_drawable != _drawableNew) { + // write back + drawable = _drawableNew; + } + } finally { + _lock.unlock(); + } + } + sendReshape = true; // async if display() doesn't get called below, but avoiding deadlock + } } } - /** Overrides: -

      update in class java.awt.Component
      */ /** * Overridden from Canvas to prevent the AWT's clearing of the * canvas from interfering with the OpenGL rendering. */ - @Override + @Override public void update(Graphics g) { paint(g); } @@ -681,7 +713,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing _lock.lock(); try { final GLContext oldCtx = context; - final boolean newCtxCurrent = helper.switchContext(drawable, oldCtx, newCtx, additionalCtxCreationFlags); + final boolean newCtxCurrent = GLDrawableHelper.switchContext(drawable, oldCtx, newCtx, additionalCtxCreationFlags); context=(GLContextImpl)newCtx; if(newCtxCurrent) { context.makeCurrent(); @@ -692,6 +724,11 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing } } + @Override + public final GLDrawable getDelegatedDrawable() { + return drawable; + } + @Override public GLContext getContext() { return context; @@ -866,7 +903,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing if(!disposeRegenerate) { if(null != awtConfig) { - disposeAbstractGraphicsDevice(); + AWTEDTExecutor.singleton.invoke(getTreeLock(), true, disposeAbstractGraphicsDeviceActionOnEDT); } awtConfig=null; } @@ -881,7 +918,13 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing } }; - private final Runnable disposeAbstractGraphicsDeviceAction = new Runnable() { + /** + * Disposes the AbstractGraphicsDevice within EDT, + * since resources created (X11: Display), must be destroyed in the same thread, where they have been created. + * + * @see #chooseGraphicsConfiguration(javax.media.opengl.GLCapabilitiesImmutable, javax.media.opengl.GLCapabilitiesImmutable, javax.media.opengl.GLCapabilitiesChooser, java.awt.GraphicsDevice) + */ + private final Runnable disposeAbstractGraphicsDeviceActionOnEDT = new Runnable() { @Override public void run() { if(null != awtConfig) { @@ -900,27 +943,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing } } }; - - /** - * Disposes the AbstractGraphicsDevice within EDT, - * since resources created (X11: Display), must be destroyed in the same thread, where they have been created. - * - * @see #chooseGraphicsConfiguration(javax.media.opengl.GLCapabilitiesImmutable, javax.media.opengl.GLCapabilitiesImmutable, javax.media.opengl.GLCapabilitiesChooser, java.awt.GraphicsDevice) - */ - private void disposeAbstractGraphicsDevice() { - if( EventQueue.isDispatchThread() || Thread.holdsLock(getTreeLock()) ) { - disposeAbstractGraphicsDeviceAction.run(); - } else { - try { - EventQueue.invokeAndWait(disposeAbstractGraphicsDeviceAction); - } catch (InvocationTargetException e) { - throw new GLException(e.getTargetException()); - } catch (InterruptedException e) { - throw new GLException(e); - } - } - } - + private final Runnable initAction = new Runnable() { @Override public void run() { @@ -1046,7 +1069,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing * @param device * @return the chosen AWTGraphicsConfiguration * - * @see #disposeAbstractGraphicsDevice() + * @see #disposeAbstractGraphicsDeviceActionOnEDT */ private AWTGraphicsConfiguration chooseGraphicsConfiguration(final GLCapabilitiesImmutable capsChosen, final GLCapabilitiesImmutable capsRequested, diff --git a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java index acb8f2183..6d4a5861f 100644 --- a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java +++ b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java @@ -121,7 +121,7 @@ import com.jogamp.opengl.util.GLBuffers; *

      */ -@SuppressWarnings("serial") +@SuppressWarnings({ "serial", "deprecation" }) public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosingProtocol { private static final boolean DEBUG = Debug.debug("GLJPanel"); @@ -396,7 +396,6 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing their reshape() method in order to function properly.

      reshape in class java.awt.Component
      */ - @SuppressWarnings("deprecation") @Override public void reshape(int x, int y, int width, int height) { super.reshape(x, y, width, height); @@ -471,7 +470,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing return null; } final GLContext oldCtx = backend.getContext(); - final boolean newCtxCurrent = helper.switchContext(backend.getDrawable(), oldCtx, newCtx, additionalCtxCreationFlags); + final boolean newCtxCurrent = GLDrawableHelper.switchContext(backend.getDrawable(), oldCtx, newCtx, additionalCtxCreationFlags); backend.setContext(newCtx); if(newCtxCurrent) { newCtx.makeCurrent(); @@ -480,6 +479,14 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing } + @Override + public final GLDrawable getDelegatedDrawable() { + if (backend == null) { + return null; + } + return backend.getDrawable(); + } + @Override public GLContext getContext() { if (backend == null) { diff --git a/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java b/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java index cc4e1b434..07029f143 100644 --- a/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java +++ b/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java @@ -30,16 +30,15 @@ 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.NativeWindowException; import javax.media.nativewindow.WindowClosingProtocol; import javax.media.nativewindow.WindowClosingProtocol.WindowClosingMode; import javax.media.opengl.FPSCounter; import javax.media.opengl.GL; import javax.media.opengl.GLAnimatorControl; import javax.media.opengl.GLAutoDrawable; -import javax.media.opengl.GLAutoDrawableDelegate; import javax.media.opengl.GLCapabilitiesImmutable; import javax.media.opengl.GLContext; import javax.media.opengl.GLDrawable; @@ -49,6 +48,7 @@ import javax.media.opengl.GLProfile; import javax.media.opengl.GLRunnable; import com.jogamp.common.util.locks.RecursiveLock; +import com.jogamp.opengl.GLAutoDrawableDelegate; import com.jogamp.opengl.util.Animator; @@ -61,38 +61,36 @@ import com.jogamp.opengl.util.Animator; * @see GLWindow */ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter { - public static final boolean DEBUG = Debug.debug("GLAutoDrawable"); + public static final boolean DEBUG = GLDrawableImpl.DEBUG; protected final GLDrawableHelper helper = new GLDrawableHelper(); protected final FPSCounterImpl fpsCounter = new FPSCounterImpl(); protected volatile GLDrawableImpl drawable; // volatile: avoid locking for read-only access protected GLContextImpl context; - protected final boolean ownDevice; + protected final boolean ownsDevice; protected int additionalCtxCreationFlags = 0; protected volatile boolean sendReshape = false; // volatile: maybe written by WindowManager thread w/o locking protected volatile boolean sendDestroy = false; // volatile: maybe written by WindowManager thread w/o locking /** - * @param drawable a valid {@link GLDrawableImpl}, may not be realized yet. - * @param context a valid {@link GLContextImpl}, may not be made current (created) yet. - * @param ownDevice pass true if {@link AbstractGraphicsDevice#close()} shall be issued, - * otherwise pass false. Closing the device is required in case - * the drawable is created w/ it's own new instance, e.g. offscreen drawables, - * and no further lifecycle handling is applied. + * @param drawable upstream {@link GLDrawableImpl} instance, may be null for lazy initialization + * @param context upstream {@link GLContextImpl} instance, may be null for lazy initialization + * @param ownsDevice pass true if {@link AbstractGraphicsDevice#close()} shall be issued, + * otherwise pass false. Closing the device is required in case + * the drawable is created w/ it's own new instance, e.g. offscreen drawables, + * and no further lifecycle handling is applied. */ - public GLAutoDrawableBase(GLDrawableImpl drawable, GLContextImpl context, boolean ownDevice) { + public GLAutoDrawableBase(GLDrawableImpl drawable, GLContextImpl context, boolean ownsDevice) { this.drawable = drawable; this.context = context; - this.ownDevice = ownDevice; + this.ownsDevice = ownsDevice; resetFPSCounter(); } + /** Returns the recursive lock object of the upstream implementation, which synchronizes multithreaded access. */ protected abstract RecursiveLock getLock(); - /** Returns the delegated GLDrawable */ - public final GLDrawable getDelegatedDrawable() { return drawable; } - /** Default implementation to handle repaint events from the windowing system */ protected final void defaultWindowRepaintOp() { final GLDrawable _drawable = drawable; @@ -103,29 +101,43 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter { } } - /** Default implementation to handle resize events from the windowing system */ - protected final void defaultWindowResizedOp() { - final GLDrawable _drawable = drawable; + /** Default implementation to handle resize events from the windowing system. All required locks are being claimed. */ + protected final void defaultWindowResizedOp(int newWidth, int newHeight) throws NativeWindowException, GLException { + GLDrawableImpl _drawable = drawable; if( null!=_drawable ) { if(DEBUG) { - System.err.println("GLAutoDrawableBase.sizeChanged: ("+Thread.currentThread().getName()+"): "+getWidth()+"x"+getHeight()+" - surfaceHandle 0x"+Long.toHexString(getNativeSurface().getSurfaceHandle())); + System.err.println("GLAutoDrawableBase.sizeChanged: ("+Thread.currentThread().getName()+"): "+newWidth+"x"+newHeight+" - surfaceHandle 0x"+Long.toHexString(getNativeSurface().getSurfaceHandle())); + } + if( ! _drawable.getChosenGLCapabilities().isOnscreen() ) { + final RecursiveLock _lock = getLock(); + _lock.lock(); + try { + final GLDrawableImpl _drawableNew = GLDrawableHelper.resizeOffscreenDrawable(_drawable, context, newWidth, newHeight); + if(_drawable != _drawableNew) { + // write back + _drawable = _drawableNew; + drawable = _drawableNew; + } + } finally { + _lock.unlock(); + } } sendReshape = true; // async if display() doesn't get called below, but avoiding deadlock if( _drawable.isRealized() ) { if( !_drawable.getNativeSurface().isSurfaceLockedByOtherThread() && !helper.isAnimatorAnimating() ) { display(); } - } + } } } - + /** * Default implementation to handle destroy notifications from the windowing system. * *

      * If the {@link NativeSurface} does not implement {@link WindowClosingProtocol} * or {@link WindowClosingMode#DISPOSE_ON_CLOSE} is enabled (default), - * {@link #defaultDestroy()} is being called. + * a thread safe destruction is being induced. *

      */ protected final void defaultWindowDestroyNotifyOp() { @@ -174,7 +186,7 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter { ctrl.resume(); } } else if (null != ns && ns.isSurfaceLockedByOtherThread()) { - // surface is locked by another thread + // Surface is locked by another thread. // Flag that destroy should be performed on the next // attempt to display. sendDestroy = true; // async, but avoiding deadlock @@ -225,7 +237,7 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter { } _drawable.setRealized(false); } - if( ownDevice ) { + if( ownsDevice ) { _drawable.getNativeSurface().getGraphicsConfiguration().getScreen().getDevice().close(); } } @@ -238,7 +250,6 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter { _lock.lock(); try { if(drawable!=null && context != null) { - drawable.swapBuffers(); helper.invokeGL(drawable, context, defaultSwapAction, defaultInitAction); } } finally { @@ -276,7 +287,7 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter { destroy(); return; } - final RecursiveLock _lock = getLock(); + final RecursiveLock _lock = getLock(); _lock.lock(); try { if( null != context ) { @@ -294,6 +305,11 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter { drawable.swapBuffers(); } } ; + @Override + public final GLDrawable getDelegatedDrawable() { + return drawable; + } + @Override public final GLContext getContext() { return context; @@ -305,7 +321,7 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter { lock.lock(); try { final GLContext oldCtx = context; - final boolean newCtxCurrent = helper.switchContext(drawable, oldCtx, newCtx, additionalCtxCreationFlags); + final boolean newCtxCurrent = GLDrawableHelper.switchContext(drawable, oldCtx, newCtx, additionalCtxCreationFlags); context=(GLContextImpl)newCtx; if(newCtxCurrent) { context.makeCurrent(); @@ -529,4 +545,10 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter { final GLDrawable _drawable = drawable; return null != _drawable ? _drawable.getHandle() : 0; } + + @Override + public String toString() { + return getClass().getSimpleName()+"[ \n\tHelper: " + helper + ", \n\tDrawable: " + drawable + + ", \n\tContext: " + context + /** ", \n\tWindow: "+window+ ", \n\tFactory: "+factory+ */ "]"; + } } diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java index e82756022..050c619fd 100644 --- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java +++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java @@ -47,6 +47,7 @@ import java.util.Map; import com.jogamp.common.os.DynamicLookupHelper; import com.jogamp.common.util.ReflectionUtil; +import com.jogamp.common.util.VersionNumber; import com.jogamp.gluegen.runtime.FunctionAddressResolver; import com.jogamp.gluegen.runtime.ProcAddressTable; import com.jogamp.gluegen.runtime.opengl.GLNameResolver; @@ -85,6 +86,7 @@ public abstract class GLContextImpl extends GLContext { private String glRenderer; private String glRendererLowerCase; + private String glVersion; // Tracks creation and initialization of buffer objects to avoid // repeated glGet calls upon glMapBuffer operations @@ -126,6 +128,9 @@ public abstract class GLContextImpl extends GLContext { GLContextShareSet.synchronizeBufferObjectSharing(shareWith, this); this.drawable = drawable; + if(null != drawable) { + drawable.associateContext(this, true); + } this.drawableRead = drawable; this.glDebugHandler = new GLDebugMessageHandler(this); @@ -205,8 +210,10 @@ public abstract class GLContextImpl extends GLContext { if(!setWriteOnly || drawableRead==drawable) { // if !setWriteOnly || !explicitReadDrawable drawableRead = (GLDrawableImpl) readWrite; } - final GLDrawable old = drawable; + final GLDrawableImpl old = drawable; + old.associateContext(this, false); drawable = (GLDrawableImpl) readWrite ; + drawable.associateContext(this, true); if(lockHeld) { makeCurrent(); } @@ -272,7 +279,7 @@ public abstract class GLContextImpl extends GLContext { if( actualRelease ) { if( !inDestruction ) { try { - drawable.contextMadeCurrent(this, false); + contextMadeCurrent(false); } catch (Throwable t) { drawableContextMadeCurrentException = t; } @@ -331,7 +338,8 @@ public abstract class GLContextImpl extends GLContext { makeCurrent(); } try { - drawable.contextRealized(this, false); + contextRealized(false); + drawable.associateContext(this, false); } catch (Throwable t) { drawableContextRealizedException = t; } @@ -514,19 +522,17 @@ public abstract class GLContextImpl extends GLContext { gl = gl.getContext().setGL( GLPipelineFactory.create("javax.media.opengl.Trace", null, gl, new Object[] { System.err } ) ); } - drawable.contextRealized(this, true); + contextRealized(true); if(DEBUG || TRACE_SWITCH) { System.err.println(getThreadName() +": GLContext.ContextSwitch: obj " + toHexString(hashCode()) + ", ctx "+toHexString(contextHandle)+" - switch - CONTEXT_CURRENT_NEW - "+lock); } - } else { - drawable.contextMadeCurrent(this, true); - - if(TRACE_SWITCH) { - System.err.println(getThreadName() +": GLContext.ContextSwitch: obj " + toHexString(hashCode()) + ", ctx "+toHexString(contextHandle)+" - switch - CONTEXT_CURRENT - "+lock); - } + } else if(TRACE_SWITCH) { + System.err.println(getThreadName() +": GLContext.ContextSwitch: obj " + toHexString(hashCode()) + ", ctx "+toHexString(contextHandle)+" - switch - CONTEXT_CURRENT - "+lock); } + contextMadeCurrent(true); + /* FIXME: refactor dependence on Java 2D / JOGL bridge // Try cleaning up any stale server-side OpenGL objects @@ -608,6 +614,20 @@ public abstract class GLContextImpl extends GLContext { } protected abstract void makeCurrentImpl() throws GLException; + /** + * @see GLDrawableImpl#contextRealized(GLContext, boolean) + */ + protected void contextRealized(boolean realized) { + drawable.contextRealized(this, realized); + } + + /** + * @see GLDrawableImpl#contextMadeCurrent(GLContext, boolean) + */ + protected void contextMadeCurrent(boolean current) { + drawable.contextMadeCurrent(this, current); + } + /** * Platform dependent entry point for context creation.
      * @@ -934,52 +954,43 @@ public abstract class GLContextImpl extends GLContext { /** * If major > 0 || minor > 0 : Use passed values, determined at creation time - * If major==0 && minor == 0 : Use GL_VERSION * Otherwise .. don't touch .. */ private final void setContextVersion(int major, int minor, int ctp, boolean setVersionString) { - if (0==ctp) { + if ( 0 == ctp ) { throw new GLException("Invalid GL Version "+major+"."+minor+", ctp "+toHexString(ctp)); } - if(major>0 || minor>0) { - if (!GLContext.isValidGLVersion(major, minor)) { - GLException e = new GLException("Invalid GL Version "+major+"."+minor+", ctp "+toHexString(ctp)); - throw e; - } - ctxMajorVersion = major; - ctxMinorVersion = minor; - ctxOptions = ctp; - if(setVersionString) { - ctxVersionString = getGLVersion(ctxMajorVersion, ctxMinorVersion, ctxOptions, getGL().glGetString(GL.GL_VERSION)); - } - return; + + if (!GLContext.isValidGLVersion(major, minor)) { + throw new GLException("Invalid GL Version "+major+"."+minor+", ctp "+toHexString(ctp)); } - - if(major==0 && minor==0) { - String versionStr = getGL().glGetString(GL.GL_VERSION); - if(null==versionStr) { - throw new GLException("GL_VERSION is NULL: "+this); - } - ctxOptions = ctp; - - // Set version - GLVersionNumber version = new GLVersionNumber(versionStr); + ctxMajorVersion = major; + ctxMinorVersion = minor; + ctxOptions = ctp; + if(setVersionString) { + ctxVersionString = getGLVersion(ctxMajorVersion, ctxMinorVersion, ctxOptions, getGL().glGetString(GL.GL_VERSION)); + } + } + + private static final VersionNumber getGLVersionNumber(int ctp, String glVersionStr) { + if( null != glVersionStr ) { + final GLVersionNumber version = new GLVersionNumber(glVersionStr); if (version.isValid()) { - ctxMajorVersion = version.getMajor(); - ctxMinorVersion = version.getMinor(); - // We cannot promote a non ARB context to >= 3.1, - // reduce it to 3.0 then. - if ( ( ctxMajorVersion>3 || ctxMajorVersion==3 && ctxMinorVersion>=1 ) - && 0 == (ctxOptions & CTX_IS_ARB_CREATED) ) { - ctxMajorVersion = 3; - ctxMinorVersion = 0; - } - if(setVersionString) { - ctxVersionString = getGLVersion(ctxMajorVersion, ctxMinorVersion, ctxOptions, versionStr); - } - return; + int major = version.getMajor(); + int minor = version.getMinor(); + // We cannot promote a non ARB context to >= 3.1, + // reduce it to 3.0 then. + if ( 0 == (ctp & CTX_IS_ARB_CREATED) && + ( major > 3 || major == 3 && minor >= 1 ) ) { + major = 3; + minor = 0; + } + if ( GLContext.isValidGLVersion(major, minor) ) { + return new VersionNumber(major, minor, 0); + } } } + return null; } //---------------------------------------------------------------------- @@ -1019,14 +1030,18 @@ public abstract class GLContextImpl extends GLContext { /** * Pbuffer support; given that this is a GLContext associated with a * pbuffer, binds this pbuffer to its texture target. + * @throws GLException if not implemented (default) + * @deprecated use FBO/GLOffscreenAutoDrawable instead of pbuffer */ - public abstract void bindPbufferToTexture(); + public void bindPbufferToTexture() { throw new GLException("not implemented"); } /** * Pbuffer support; given that this is a GLContext associated with a * pbuffer, releases this pbuffer from its texture target. + * @throws GLException if not implemented (default) + * @deprecated use FBO/GLOffscreenAutoDrawable instead of pbuffer */ - public abstract void releasePbufferFromTexture(); + public void releasePbufferFromTexture() { throw new GLException("not implemented"); } public abstract ByteBuffer glAllocateMemoryNV(int arg0, float arg1, float arg2, float arg3); @@ -1064,7 +1079,7 @@ public abstract class GLContextImpl extends GLContext { table.reset(getDrawableImpl().getGLDynamicLookupHelper() ); } - private final boolean initGLRendererStrings() { + private final boolean initGLRendererAndGLVersionStrings() { final GLDynamicLookupHelper glDynLookupHelper = getDrawableImpl().getGLDynamicLookupHelper(); final long _glGetString = glDynLookupHelper.dynamicLookupFunction("glGetString"); if(0 == _glGetString) { @@ -1083,14 +1098,27 @@ public abstract class GLContextImpl extends GLContext { Thread.dumpStack(); } return false; - } else { - glRenderer = _glRenderer; - glRendererLowerCase = glRenderer.toLowerCase(); - return true; } + glRenderer = _glRenderer; + glRendererLowerCase = glRenderer.toLowerCase(); + + final String _glVersion = glGetStringInt(GL.GL_VERSION, _glGetString); + if(null == _glVersion) { + // FIXME + if(DEBUG) { + System.err.println("Warning: GL_VERSION is NULL."); + Thread.dumpStack(); + } + return false; + } + glVersion = _glVersion; + return true; } } + protected final String getGLVersionString() { + return glVersion; + } protected final String getGLRendererString(boolean lowerCase) { return lowerCase ? glRendererLowerCase : glRenderer; } @@ -1128,17 +1156,44 @@ public abstract class GLContextImpl extends GLContext { 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)); + { + final boolean initGLRendererAndGLVersionStringsOK = initGLRendererAndGLVersionStrings(); + if(DEBUG) { + if( !initGLRendererAndGLVersionStringsOK ) { + System.err.println("Warning: setGLFunctionAvailability: intialization of GL renderer strings failed. "+adevice+" - "+GLContext.getGLVersion(major, minor, ctxProfileBits, null)); + } else { + System.err.println(getThreadName() + ": GLContext.setGLFuncAvail: Given "+adevice+" - "+GLContext.getGLVersion(major, minor, ctxProfileBits, glVersion)); + } + } } if(!isCurrentContextHardwareRasterizer()) { ctxProfileBits |= GLContext.CTX_IMPL_ACCEL_SOFT; } - + + // Pick the version from the GL-version string, + // if smaller _or_ given major == 0. + final VersionNumber glVersionNumber; + { + final VersionNumber setGLVersionNumber = new VersionNumber(major, minor, 0); + final VersionNumber strGLVersionNumber = getGLVersionNumber(ctxProfileBits, glVersion); + if( null != strGLVersionNumber && ( strGLVersionNumber.compareTo(setGLVersionNumber) <= 0 || 0 == major ) ) { + glVersionNumber = strGLVersionNumber; + major = glVersionNumber.getMajor(); + minor = glVersionNumber.getMinor(); + } else { + glVersionNumber = setGLVersionNumber; + } + } + if ( !GLContext.isValidGLVersion(major, minor) ) { + throw new GLException("Invalid GL Version "+major+"."+minor+", ctp "+toHexString(ctxProfileBits)+", "+glVersion+", "+glVersionNumber); + } + if( 2 > major ) { // there is no ES2-compat for a profile w/ major < 2 + ctxProfileBits &= ~GLContext.CTX_IMPL_ES2_COMPAT; + } contextFQN = getContextFQN(adevice, major, minor, ctxProfileBits); if (DEBUG) { - System.err.println(getThreadName() + ": GLContext.setGLFuncAvail.0 FQN: "+contextFQN+" - "+GLContext.getGLVersion(major, minor, ctxProfileBits, null)); + System.err.println(getThreadName() + ": GLContext.setGLFuncAvail.0 validated FQN: "+contextFQN+" - "+GLContext.getGLVersion(major, minor, ctxProfileBits, glVersion) + ", "+glVersionNumber); } // @@ -1201,6 +1256,10 @@ public abstract class GLContextImpl extends GLContext { ctxProfileBits |= CTX_IMPL_FBO; } + if(FORCE_NO_FBO_SUPPORT) { + ctxProfileBits &= ~CTX_IMPL_FBO ; + } + // // Set GL Version (complete w/ version string) // diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java b/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java index e1e253d35..4f965f620 100644 --- a/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java +++ b/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java @@ -48,18 +48,21 @@ import javax.media.nativewindow.NativeWindowFactory; import javax.media.nativewindow.OffscreenLayerSurface; import javax.media.nativewindow.ProxySurface; import javax.media.nativewindow.MutableSurface; -import javax.media.nativewindow.ProxySurface.UpstreamSurfaceHook; -import javax.media.opengl.GLCapabilities; +import javax.media.nativewindow.UpstreamSurfaceHook; 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.GLFBODrawable; +import javax.media.opengl.GLOffscreenAutoDrawable; import javax.media.opengl.GLPbuffer; import javax.media.opengl.GLProfile; import com.jogamp.nativewindow.MutableGraphicsConfiguration; +import com.jogamp.nativewindow.DelegatedUpstreamSurfaceHookWithSurfaceSize; +import com.jogamp.nativewindow.UpstreamSurfaceHookMutableSize; /** Extends GLDrawableFactory with a few methods for handling @@ -67,6 +70,7 @@ import com.jogamp.nativewindow.MutableGraphicsConfiguration; Independent Bitmaps on Windows, pixmaps on X11). Direct access to these GLDrawables is not supplied directly to end users, though they may be instantiated by the GLJPanel implementation. */ +@SuppressWarnings("deprecation") public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { protected static final boolean DEBUG = GLDrawableImpl.DEBUG; @@ -141,55 +145,53 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { final OffscreenLayerSurface ols = NativeWindowFactory.getOffscreenLayerSurface(target, true); if(null != ols) { // layered surface -> Offscreen/[FBO|PBuffer] - final GLCapabilities chosenCapsMod = (GLCapabilities) chosenCaps.cloneMutable(); - chosenCapsMod.setOnscreen(false); - chosenCapsMod.setDoubleBuffered(false); - /* 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); + final boolean isPbufferAvailable = canCreateGLPbuffer(adevice) ; + if(!isPbufferAvailable && !isFBOAvailable) { + throw new GLException("Neither FBO nor Pbuffer is available for "+target); } + final GLCapabilitiesImmutable chosenCapsMod = GLGraphicsConfigurationUtil.fixOffscreenGLCapabilities(chosenCaps, isFBOAvailable, isPbufferAvailable); config.setChosenCapabilities(chosenCapsMod); + ols.setChosenCapabilities(chosenCapsMod); if(DEBUG) { - System.err.println("GLDrawableFactoryImpl.createGLDrawable -> OnscreenDrawable -> Offscreen-Layer: "+target); + System.err.println("GLDrawableFactoryImpl.createGLDrawable -> OnscreenDrawable -> Offscreen-Layer"); + System.err.println("chosenCaps: "+chosenCaps); + System.err.println("chosenCapsMod: "+chosenCapsMod); + System.err.println("OffscreenLayerSurface: **** "+ols); + System.err.println("Target: **** "+target); + Thread.dumpStack(); } 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 */); + if( chosenCapsMod.isFBO() && isFBOAvailable ) { + // target surface is already a native one + result = createFBODrawableImpl(target, chosenCapsMod, 0); } else { result = createOffscreenDrawableImpl(target); } } else if(chosenCaps.isOnscreen()) { // onscreen + final GLCapabilitiesImmutable chosenCapsMod = GLGraphicsConfigurationUtil.fixOnscreenGLCapabilities(chosenCaps); + config.setChosenCapabilities(chosenCapsMod); if(DEBUG) { System.err.println("GLDrawableFactoryImpl.createGLDrawable -> OnscreenDrawable: "+target); } result = createOnscreenDrawableImpl(target); } else { // offscreen - final GLCapabilitiesImmutable reqCaps = (GLCapabilitiesImmutable)config.getRequestedCapabilities(); if(DEBUG) { - System.err.println("GLDrawableFactoryImpl.createGLDrawable -> OffScreenDrawable, FBO req / chosen - avail, PBuffer: "+reqCaps.isFBO()+" / "+chosenCaps.isFBO()+" - "+isFBOAvailable+", "+chosenCaps.isPBuffer()+": "+target); + System.err.println("GLDrawableFactoryImpl.createGLDrawable -> OffScreenDrawable, FBO chosen / avail, PBuffer: "+ + chosenCaps.isFBO()+" / "+isFBOAvailable+", "+chosenCaps.isPBuffer()+": "+target); } if( ! ( target instanceof MutableSurface ) ) { - throw new IllegalArgumentException("Passed NativeSurface must implement SurfaceChangeable for offscreen: "+target); + throw new IllegalArgumentException("Passed NativeSurface must implement MutableSurface for offscreen: "+target); } - if( reqCaps.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 */); + if( chosenCaps.isFBO() && isFBOAvailable ) { + // need to hook-up a native dummy surface since source may not have + final ProxySurface dummySurface = createDummySurfaceImpl(adevice, true, chosenCaps, null, 64, 64); + dummySurface.setUpstreamSurfaceHook(new DelegatedUpstreamSurfaceHookWithSurfaceSize(dummySurface.getUpstreamSurfaceHook(), target)); + result = createFBODrawableImpl(dummySurface, chosenCaps, 0); } else { - final GLCapabilities chosenCapsMod = (GLCapabilities) chosenCaps.cloneMutable(); - chosenCapsMod.setDoubleBuffered(false); - config.setChosenCapabilities(chosenCapsMod); result = createOffscreenDrawableImpl(target); } } @@ -211,7 +213,7 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { //--------------------------------------------------------------------------- // - // PBuffer Offscreen GLDrawable construction + // PBuffer Offscreen GLAutoDrawable construction // @Override @@ -239,7 +241,8 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { GLDrawableImpl drawable = null; device.lock(); try { - drawable = (GLDrawableImpl) createGLDrawable( createMutableSurfaceImpl(device, true, capsChosen, capsRequested, chooser, width, height, null) ); + drawable = createOffscreenDrawableImpl( createMutableSurfaceImpl(device, true, capsChosen, capsRequested, chooser, + new UpstreamSurfaceHookMutableSize(width, height) ) ); if(null != drawable) { drawable.setRealized(true); } @@ -247,10 +250,7 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { device.unlock(); } - if(null==drawable) { - throw new GLException("Could not create Pbuffer drawable for: "+device+", "+capsChosen+", "+width+"x"+height); - } - return new GLPbufferImpl( drawable, shareWith, true); + return new GLPbufferImpl( drawable, (GLContextImpl) drawable.createContext(shareWith) ); } //--------------------------------------------------------------------------- @@ -258,6 +258,29 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { // Offscreen GLDrawable construction // + public final boolean canCreateFBO(AbstractGraphicsDevice deviceReq, GLProfile glp) { + AbstractGraphicsDevice device = getOrCreateSharedDevice(deviceReq); + if(null == device) { + throw new GLException("No shared device for requested: "+deviceReq); + } + return GLContext.isFBOAvailable(device, glp); + } + + @Override + public GLOffscreenAutoDrawable createOffscreenAutoDrawable(AbstractGraphicsDevice deviceReq, + GLCapabilitiesImmutable capsRequested, + GLCapabilitiesChooser chooser, + int width, int height, + GLContext shareWith) { + final GLDrawable drawable = createOffscreenDrawable( deviceReq, capsRequested, chooser, width, height ); + drawable.setRealized(true); + final GLContext context = drawable.createContext(shareWith); + if(drawable instanceof GLFBODrawableImpl) { + return new GLOffscreenAutoDrawableImpl.FBOImpl( (GLFBODrawableImpl)drawable, context, null, null ); + } + return new GLOffscreenAutoDrawableImpl( drawable, context, null, null); + } + @Override public GLDrawable createOffscreenDrawable(AbstractGraphicsDevice deviceReq, GLCapabilitiesImmutable capsRequested, @@ -274,10 +297,13 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { final GLCapabilitiesImmutable capsChosen = GLGraphicsConfigurationUtil.fixOffscreenGLCapabilities(capsRequested, GLContext.isFBOAvailable(device, capsRequested.getGLProfile()), canCreateGLPbuffer(device)); + if( capsChosen.isFBO() ) { device.lock(); try { - return createFBODrawableImpl(device, capsRequested, chooser, width, height); + final ProxySurface dummySurface = createDummySurfaceImpl(device, true, capsRequested, null, width, height); + final GLDrawableImpl dummyDrawable = createOnscreenDrawableImpl(dummySurface); + return new GLFBODrawableImpl.ResizeableImpl(this, dummyDrawable, dummySurface, capsChosen, 0); } finally { device.unlock(); } @@ -285,20 +311,17 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { device.lock(); try { - return createOffscreenDrawableImpl( createMutableSurfaceImpl(device, true, capsChosen, capsRequested, chooser, width, height, null) ); + return createOffscreenDrawableImpl( createMutableSurfaceImpl(device, true, capsChosen, capsRequested, chooser, + new UpstreamSurfaceHookMutableSize(width, height) ) ); } finally { device.unlock(); } } - /** 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); + /** Creates a platform independent FBO offscreen GLDrawable */ + protected GLFBODrawable createFBODrawableImpl(NativeSurface dummySurface, GLCapabilitiesImmutable fboCaps, int textureUnit) { final GLDrawableImpl dummyDrawable = createOnscreenDrawableImpl(dummySurface); - - return new GLFBODrawableImpl(this, dummyDrawable, dummySurface, initialWidth, initialHeight, 0 /* textureUnit */); + return new GLFBODrawableImpl(this, dummyDrawable, dummySurface, fboCaps, textureUnit); } /** Creates a platform dependent offscreen pbuffer/pixmap GLDrawable implementation */ @@ -318,15 +341,13 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { * @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 + * @param upstreamHook surface size information and 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); + GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstreamHook); /** * A dummy surface is not visible on screen and will not be used to render directly to, @@ -341,9 +362,9 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { * @param width the initial width * @param height the initial height * - * @return the created {@link MutableSurface} instance w/o defined surface handle + * @return the created {@link ProxySurface} instance w/o defined surface handle but platform specific {@link UpstreamSurfaceHook}. */ - public NativeSurface createDummySurface(AbstractGraphicsDevice deviceReq, GLCapabilitiesImmutable requestedCaps, GLCapabilitiesChooser chooser, + public ProxySurface createDummySurface(AbstractGraphicsDevice deviceReq, GLCapabilitiesImmutable requestedCaps, GLCapabilitiesChooser chooser, int width, int height) { final AbstractGraphicsDevice device = getOrCreateSharedDevice(deviceReq); if(null == device) { @@ -369,9 +390,11 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { * otherwise device instance is used as-is. * @param requestedCaps * @param chooser the custom chooser, may be null for default - * @param width the initial width - * @param height the initial height - * @return the created {@link MutableSurface} instance w/o defined surface handle + * @param width the initial width as returned by {@link NativeSurface#getWidth()}, not the actual dummy surface width. + * The latter is platform specific and small + * @param height the initial height as returned by {@link NativeSurface#getHeight()}, not the actual dummy surface height, + * The latter is platform specific and small + * @return the created {@link ProxySurface} instance w/o defined surface handle but platform specific {@link UpstreamSurfaceHook}. */ public abstract ProxySurface createDummySurfaceImpl(AbstractGraphicsDevice device, boolean createNewDevice, GLCapabilitiesImmutable requestedCaps, GLCapabilitiesChooser chooser, int width, int height); diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java b/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java index 090c5fe69..bdf0b6d74 100644 --- a/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java +++ b/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java @@ -43,12 +43,19 @@ package jogamp.opengl; import java.util.ArrayList; import java.util.HashSet; +import javax.media.nativewindow.NativeSurface; +import javax.media.nativewindow.NativeWindowException; +import javax.media.nativewindow.ProxySurface; +import javax.media.nativewindow.UpstreamSurfaceHook; import javax.media.opengl.GLAnimatorControl; import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLContext; import javax.media.opengl.GLDrawable; +import javax.media.opengl.GLDrawableFactory; import javax.media.opengl.GLEventListener; import javax.media.opengl.GLException; +import javax.media.opengl.GLFBODrawable; import javax.media.opengl.GLRunnable; import com.jogamp.opengl.util.Animator; @@ -108,24 +115,27 @@ public class GLDrawableHelper { /** * Associate a new context to the drawable and also propagates the context/drawable switch by * calling {@link GLContext#setGLDrawable(GLDrawable, boolean) newCtx.setGLDrawable(drawable, true);}. - *

      - * If the old context's drawable was an {@link GLAutoDrawable}, it's reference to the given drawable - * is being cleared by calling - * {@link GLAutoDrawable#setContext(GLContext) ((GLAutoDrawable)oldCtx.getGLDrawable()).setContext(null)}. - *

      *

      * If the old or new context was current on this thread, it is being released before switching the drawable. *

      + *

      + * Be aware that the old context is still bound to the drawable, + * and that one context can only bound to one drawable at one time! + *

      + *

      + * No locking is being performed on the drawable, caller is required to take care of it. + *

      * * @param drawable the drawable which context is changed - * @param newCtx the new context * @param oldCtx the old context - * @return true if the newt context was current, otherwise false + * @param newCtx the new context + * @param newCtxCreationFlags additional creation flags if newCtx is not null and not been created yet, see {@link GLContext#setContextCreationFlags(int)} + * @return true if the new context was current, otherwise false * * @see GLAutoDrawable#setContext(GLContext) */ - public final boolean switchContext(GLDrawable drawable, GLContext oldCtx, GLContext newCtx, int additionalCtxCreationFlags) { - if(null != oldCtx && oldCtx.isCurrent()) { + public static final boolean switchContext(GLDrawable drawable, GLContext oldCtx, GLContext newCtx, int newCtxCreationFlags) { + if( null != oldCtx && oldCtx.isCurrent() ) { oldCtx.release(); } final boolean newCtxCurrent; @@ -134,17 +144,135 @@ public class GLDrawableHelper { if(newCtxCurrent) { newCtx.release(); } - newCtx.setContextCreationFlags(additionalCtxCreationFlags); + newCtx.setContextCreationFlags(newCtxCreationFlags); newCtx.setGLDrawable(drawable, true); // propagate context/drawable switch } else { newCtxCurrent = false; } - if(null!=oldCtx && oldCtx.getGLDrawable() instanceof GLAutoDrawable) { - ((GLAutoDrawable)oldCtx.getGLDrawable()).setContext(null); - } return newCtxCurrent; } + /** + * If the drawable is not realized, OP is a NOP. + *
        + *
      • release context if current
      • + *
      • destroy old drawable
      • + *
      • create new drawable
      • + *
      • attach new drawable to context
      • + *
      • make context current, if it was current
      • + *
      + *

      + * No locking is being performed, caller is required to take care of it. + *

      + * + * @param drawable + * @param context maybe null + * @return the new drawable + */ + public static final GLDrawableImpl recreateGLDrawable(GLDrawableImpl drawable, GLContext context) { + if( ! drawable.isRealized() ) { + return drawable; + } + final boolean contextCurrent = null != context && context.isCurrent(); + final GLDrawableFactory factory = drawable.getFactory(); + final NativeSurface surface = drawable.getNativeSurface(); + final ProxySurface proxySurface = (surface instanceof ProxySurface) ? (ProxySurface)surface : null; + + if(contextCurrent) { + context.release(); + } + + if(null != proxySurface) { + proxySurface.enableUpstreamSurfaceHookLifecycle(false); + } + try { + drawable.setRealized(false); + drawable = (GLDrawableImpl) factory.createGLDrawable(surface); // [2] + drawable.setRealized(true); + } finally { + if(null != proxySurface) { + proxySurface.enableUpstreamSurfaceHookLifecycle(true); + } + } + + if(null != context) { + context.setGLDrawable(drawable, true); // re-association + } + + if(contextCurrent) { + context.makeCurrent(); + } + return drawable; + } + + /** + * Performs resize operation on the given drawable, assuming it is offscreen. + *

      + * The {@link GLDrawableImpl}'s {@link NativeSurface} is being locked during operation. + * In case the holder is an auto drawable or similar, it's lock shall be claimed by the caller. + *

      + *

      + * May recreate the drawable via {@link #recreateGLDrawable(GLDrawableImpl, GLContext)} + * in case of a a pbuffer- or pixmap-drawable. + *

      + *

      + * FBO drawables are resized w/o drawable destruction. + *

      + *

      + * Offscreen resize operation is validated w/ drawable size in the end. + * An exception is thrown if not successful. + *

      + * + * @param drawable + * @param context + * @param newWidth the new width, it's minimum is capped to 1 + * @param newHeight the new height, it's minimum is capped to 1 + * @return the new drawable in case of an pbuffer/pixmap drawable, otherwise the passed drawable is being returned. + * @throws NativeWindowException is drawable is not offscreen or it's surface lock couldn't be claimed + * @throws GLException may be thrown a resize operation + */ + public static final GLDrawableImpl resizeOffscreenDrawable(GLDrawableImpl drawable, GLContext context, int newWidth, int newHeight) + throws NativeWindowException, GLException + { + if(drawable.getChosenGLCapabilities().isOnscreen()) { + throw new NativeWindowException("Drawable is not offscreen: "+drawable); + } + final NativeSurface ns = drawable.getNativeSurface(); + final int lockRes = ns.lockSurface(); + if (NativeSurface.LOCK_SURFACE_NOT_READY >= lockRes) { + throw new NativeWindowException("Could not lock surface of drawable: "+drawable); + } + try { + if(0>=newWidth) { newWidth = 1; } + if(0>=newHeight) { newHeight = 1; } + // propagate new size + if(ns instanceof ProxySurface) { + final ProxySurface ps = (ProxySurface) ns; + final UpstreamSurfaceHook ush = ps.getUpstreamSurfaceHook(); + if(ush instanceof UpstreamSurfaceHook.MutableSize) { + ((UpstreamSurfaceHook.MutableSize)ush).setSize(newWidth, newHeight); + } else if(DEBUG) { // we have to assume UpstreamSurfaceHook contains the new size already, hence size check @ bottom + System.err.println("GLDrawableHelper.resizeOffscreenDrawable: Drawable's offscreen ProxySurface n.a. UpstreamSurfaceHook.MutableSize, but "+ush.getClass().getName()+": "+ush); + } + } else if(DEBUG) { // we have to assume surface contains the new size already, hence size check @ bottom + System.err.println("GLDrawableHelper.resizeOffscreenDrawable: Drawable's offscreen surface n.a. ProxySurface, but "+ns.getClass().getName()+": "+ns); + } + if(drawable instanceof GLFBODrawable) { + if( null != context && context.isCreated() ) { + ((GLFBODrawable) drawable).resetSize(context.getGL()); + } + } else { + drawable = GLDrawableHelper.recreateGLDrawable(drawable, context); + } + } finally { + ns.unlockSurface(); + } + if(drawable.getWidth() != newWidth || drawable.getHeight() != newHeight) { + throw new InternalError("Incomplete resize operation: expected "+newWidth+"x"+newHeight+", has: "+drawable); + } + return drawable; + } + public final void addGLEventListener(GLEventListener listener) { addGLEventListener(-1, listener); } @@ -196,15 +324,11 @@ public class GLDrawableHelper { } } - private final boolean init(GLEventListener l, GLAutoDrawable drawable, boolean sendReshape) { - if(listenersToBeInit.remove(l)) { - l.init(drawable); - if(sendReshape) { - reshape(l, drawable, 0, 0, drawable.getWidth(), drawable.getHeight(), true /* setViewport */, false /* checkInit */); - } - return true; + private final void init(GLEventListener l, GLAutoDrawable drawable, boolean sendReshape) { + l.init(drawable); + if(sendReshape) { + reshape(l, drawable, 0, 0, drawable.getWidth(), drawable.getHeight(), true /* setViewport */, false /* checkInit */); } - return false; } /** The default init action to be called once after ctx is being created @ 1st makeCurrent(). */ @@ -214,14 +338,11 @@ public class GLDrawableHelper { for (int i=0; i < _listeners.size(); i++) { final GLEventListener listener = _listeners.get(i) ; - // If make current ctx, invoked by invokGL(..), results in a new ctx, init gets called. + // If make ctx current, invoked by invokGL(..), results in a new ctx, init gets called. // This may happen not just for initial setup, but for ctx recreation due to resource change (drawable/window), - // hence the must always be initialized unconditional. - listenersToBeInit.add(listener); - - if ( ! init( listener, drawable, true /* sendReshape */) ) { - throw new GLException("GLEventListener "+listener+" already initialized: "+drawable); - } + // hence it must be called unconditional, always. + listenersToBeInit.remove(listener); // remove if exist, avoiding dbl init + init( listener, drawable, true /* sendReshape */); } } } @@ -239,7 +360,9 @@ public class GLDrawableHelper { final GLEventListener listener = _listeners.get(i) ; // GLEventListener may need to be init, // in case this one is added after the realization of the GLAutoDrawable - init( listener, drawable, true /* sendReshape */) ; + if( listenersToBeInit.remove(listener) ) { + init( listener, drawable, true /* sendReshape */) ; + } listener.display(drawable); } } @@ -251,7 +374,9 @@ public class GLDrawableHelper { // GLEventListener may need to be init, // in case this one is added after the realization of the GLAutoDrawable synchronized(listenersLock) { - init( listener, drawable, false /* sendReshape */) ; + if( listenersToBeInit.remove(listener) ) { + init( listener, drawable, false /* sendReshape */) ; + } } } if(setViewport) { diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java b/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java index abf2bf557..311690f1d 100644 --- a/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java +++ b/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java @@ -43,6 +43,7 @@ package jogamp.opengl; import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.nativewindow.NativeSurface; import javax.media.nativewindow.ProxySurface; +import javax.media.opengl.GL; import javax.media.opengl.GLCapabilitiesImmutable; import javax.media.opengl.GLContext; import javax.media.opengl.GLDrawable; @@ -76,31 +77,46 @@ public abstract class GLDrawableImpl implements GLDrawable { if( !realized ) { return; // destroyed already } - final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable)surface.getGraphicsConfiguration().getChosenCapabilities(); - if ( caps.getDoubleBuffered() ) { - if(!surface.surfaceSwap()) { - int lockRes = lockSurface(); // it's recursive, so it's ok within [makeCurrent .. release] - if (NativeSurface.LOCK_SURFACE_NOT_READY == lockRes) { - return; + int lockRes = lockSurface(); // it's recursive, so it's ok within [makeCurrent .. release] + if (NativeSurface.LOCK_SURFACE_NOT_READY == lockRes) { + return; + } + try { + if (NativeSurface.LOCK_SURFACE_CHANGED == lockRes) { + updateHandle(); + } + final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable)surface.getGraphicsConfiguration().getChosenCapabilities(); + if ( caps.getDoubleBuffered() ) { + if(!surface.surfaceSwap()) { + swapBuffersImpl(true); } - try { - if (NativeSurface.LOCK_SURFACE_CHANGED == lockRes) { - updateHandle(); - } - swapBuffersImpl(); - } finally { - unlockSurface(); + } else { + final GLContext ctx = GLContext.getCurrent(); + if(null!=ctx && ctx.getGLDrawable()==this) { + ctx.getGL().glFlush(); } + swapBuffersImpl(false); } - } else { - GLContext ctx = GLContext.getCurrent(); - if(null!=ctx && ctx.getGLDrawable()==this) { - ctx.getGL().glFinish(); - } - } + } finally { + unlockSurface(); + } surface.surfaceUpdated(this, surface, System.currentTimeMillis()); } - protected abstract void swapBuffersImpl(); + + /** + * Platform and implementation depending surface swap. + *

      The surface is locked.

      + *

      + * If doubleBuffered is true, + * an actual platform dependent surface swap shall be executed. + *

      + *

      + * If doubleBuffered is false, + * {@link GL#glFlush()} has been called already and + * the implementation may execute implementation specific code. + *

      + */ + protected abstract void swapBuffersImpl(boolean doubleBuffered); public final static String toHexString(long hex) { return "0x" + Long.toHexString(hex); @@ -181,6 +197,9 @@ public abstract class GLDrawableImpl implements GLDrawable { System.err.println(getThreadName() + ": setRealized: "+getClass().getName()+" "+this.realized+" == "+realizedArg); } } + /** + * Platform specific realization of drawable + */ protected abstract void setRealizedImpl(); /** @@ -189,7 +208,7 @@ public abstract class GLDrawableImpl implements GLDrawable { * If realized is true, the context has just been created and made current. *

      *

      - * If realized is false, the context is still current and will be release and destroyed after this method returns. + * If realized is false, the context is still current and will be released and destroyed after this method returns. *

      *

      * @see #contextMadeCurrent(GLContext, boolean) @@ -199,18 +218,27 @@ public abstract class GLDrawableImpl implements GLDrawable { /** * Callback for special implementations, allowing GLContext to trigger GL related lifecycle: makeCurrent, release. *

      - * Will not be called if {@link #contextRealized(GLContext, boolean)} has been triggered. - *

      - *

      * If current is true, the context has just been made current. *

      *

      * If current is false, the context is still current and will be release after this method returns. *

      + *

      + * Note: Will also be called after {@link #contextRealized(GLContext, boolean) contextRealized(ctx, true)} + * but not at context destruction, i.e. {@link #contextRealized(GLContext, boolean) contextRealized(ctx, false)}. + *

      * @see #contextRealized(GLContext, boolean) */ protected void contextMadeCurrent(GLContext glc, boolean current) { } + /** + * Callback for special implementations, allowing to associate bound context to this drawable (bound == true) + * or to remove such association (bound == false). + * @param ctx the just bounded or unbounded context + * @param bound if true create an association, otherwise remove it + */ + protected void associateContext(GLContext ctx, boolean bound) { } + /** Callback for special implementations, allowing GLContext to fetch a custom default render framebuffer. Defaults to zero.*/ protected int getDefaultDrawFramebuffer() { return 0; } /** Callback for special implementations, allowing GLContext to fetch a custom default read framebuffer. Defaults to zero. */ @@ -245,8 +273,8 @@ public abstract class GLDrawableImpl implements GLDrawable { public String toString() { return getClass().getSimpleName()+"[Realized "+isRealized()+ ",\n\tFactory "+getFactory()+ - ",\n\thandle "+toHexString(getHandle())+ - ",\n\tWindow "+getNativeSurface()+"]"; + ",\n\tHandle "+toHexString(getHandle())+ + ",\n\tSurface "+getNativeSurface()+"]"; } protected static String getThreadName() { diff --git a/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java b/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java index 03bc26cbc..de45466f3 100644 --- a/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java +++ b/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java @@ -1,142 +1,476 @@ package jogamp.opengl; import javax.media.nativewindow.NativeSurface; +import javax.media.nativewindow.NativeWindowException; +import javax.media.nativewindow.ProxySurface; +import javax.media.nativewindow.UpstreamSurfaceHook; import javax.media.opengl.GL; -import javax.media.opengl.GL2GL3; +import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLCapabilitiesImmutable; import javax.media.opengl.GLContext; import javax.media.opengl.GLException; +import javax.media.opengl.GLFBODrawable; import com.jogamp.nativewindow.MutableGraphicsConfiguration; import com.jogamp.opengl.FBObject; import com.jogamp.opengl.FBObject.Attachment; +import com.jogamp.opengl.FBObject.Colorbuffer; import com.jogamp.opengl.FBObject.TextureAttachment; /** - * Offscreen GLDrawable implementation using framebuffer object (FBO) - * as it's offscreen rendering mechanism. + * {@link FBObject} offscreen GLDrawable implementation, i.e. {@link GLFBODrawable}. + *

      + * It utilizes the context lifecycle hook {@link #contextRealized(GLContext, boolean)} + * to initialize the {@link FBObject} instance. + *

      + *

      + * It utilizes the context current hook {@link #contextMadeCurrent(GLContext, boolean) contextMadeCurrent(context, true)} + * to {@link FBObject#bind(GL) bind} the FBO. + *

      + * See {@link GLFBODrawable} for double buffering details. * * @see GLDrawableImpl#contextRealized(GLContext, boolean) * @see GLDrawableImpl#contextMadeCurrent(GLContext, boolean) * @see GLDrawableImpl#getDefaultDrawFramebuffer() * @see GLDrawableImpl#getDefaultReadFramebuffer() */ -public class GLFBODrawableImpl extends GLDrawableImpl { - final GLDrawableImpl parent; - final FBObject fbo; - int texUnit; - int samplesTexUnit = 0; - int width=0, height=0, samples=0; - - protected GLFBODrawableImpl(GLDrawableFactoryImpl factory, GLDrawableImpl parent, - NativeSurface surface, int initialWidth, int initialHeight, int textureUnit) { +public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable { + protected static final boolean DEBUG = GLDrawableImpl.DEBUG || Debug.debug("FBObject"); + + private final GLDrawableImpl parent; + + private boolean initialized; + private int texUnit; + private int samples; + + private FBObject[] fbos; + private int fboIBack; // points to GL_BACK buffer + private int fboIFront; // points to GL_FRONT buffer + private FBObject pendingFBOReset = null; + private boolean fboBound; + private static final int bufferCount = 2; // number of FBOs for double buffering. TODO: Possible to configure! + + // private DoubleBufferMode doubleBufferMode; // TODO: Add or remove TEXTURE (only) DoubleBufferMode support + + private SwapBufferContext swapBufferContext; + + public static interface SwapBufferContext { + public void swapBuffers(boolean doubleBuffered); + } + + protected GLFBODrawableImpl(GLDrawableFactoryImpl factory, GLDrawableImpl parent, NativeSurface surface, + GLCapabilitiesImmutable fboCaps, int textureUnit) { super(factory, surface, false); + this.initialized = false; + + // Replace the chosen caps of dummy-surface w/ it's clone and copied values of orig FBO caps request. + // The dummy-surface has already been configured, hence value replace is OK + // and due to cloning, the native GLCapability portion is being preserved. + final MutableGraphicsConfiguration msConfig = (MutableGraphicsConfiguration) surface.getGraphicsConfiguration(); + final GLCapabilities fboCapsNative = (GLCapabilities) msConfig.getChosenCapabilities().cloneMutable(); + fboCapsNative.copyFrom(fboCaps); + msConfig.setChosenCapabilities(fboCapsNative); + this.parent = parent; this.texUnit = textureUnit; - final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) surface.getGraphicsConfiguration().getChosenCapabilities(); - this.width = initialWidth; - this.height = initialHeight; - this.samples = caps.getNumSamples(); - this.fbo = new FBObject(); + this.samples = fboCaps.getNumSamples(); + + // default .. // TODO: Add or remove TEXTURE (only) DoubleBufferMode support + // this.doubleBufferMode = ( samples > 0 || fboCaps.getDoubleBuffered() ) ? DoubleBufferMode.FBO : DoubleBufferMode.NONE ; + + this.swapBufferContext = null; } - @Override - protected void contextRealized(GLContext glc, boolean realized) { - final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) surface.getGraphicsConfiguration().getChosenCapabilities(); - final GL gl = glc.getGL(); - if(realized) { - fbo.reset(gl, width, height, samples); - samples = fbo.getNumSamples(); // update, maybe capped + private final void initialize(boolean realize, GL gl) { + if(realize) { + final int maxSamples = gl.getMaxRenderbufferSamples(); + samples = samples <= maxSamples ? samples : maxSamples; + + final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) surface.getGraphicsConfiguration().getChosenCapabilities(); + final int fbosN; if(samples > 0) { - fbo.attachColorbuffer(gl, 0, caps.getAlphaBits()>0); + fbosN = 1; + } else if( caps.getDoubleBuffered() ) { + fbosN = bufferCount; } else { - fbo.attachTexture2D(gl, 0, caps.getAlphaBits()>0); + fbosN = 1; } - if( caps.getStencilBits() > 0 ) { - fbo.attachRenderbuffer(gl, Attachment.Type.DEPTH_STENCIL, 24); - } else { - fbo.attachRenderbuffer(gl, Attachment.Type.DEPTH, 24); + + fbos = new FBObject[fbosN]; + fboIBack = 0; // head + fboIFront = fbos.length - 1; // tail + + for(int i=0; i 0) { + fbos[i].attachColorbuffer(gl, 0, caps.getAlphaBits()>0); + } else { + fbos[i].attachTexture2D(gl, 0, caps.getAlphaBits()>0); + } + if( caps.getStencilBits() > 0 ) { + fbos[i].attachRenderbuffer(gl, Attachment.Type.DEPTH_STENCIL, 24); + } else { + fbos[i].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); + fbos[fboIFront].syncFramebuffer(gl); + fboBound = false; + final GLCapabilities fboCapsNative = (GLCapabilities) surface.getGraphicsConfiguration().getChosenCapabilities(); + fbos[0].formatToGLCapabilities(fboCapsNative); + fboCapsNative.setDoubleBuffered( fboCapsNative.getDoubleBuffered() || samples > 0 ); + + initialized = true; } else { - fbo.unbind(gl); - final TextureAttachment attachment = samples > 0 ? fbo.getSamplingSink() : (TextureAttachment) fbo.getColorbuffer(0) ; - if(null == attachment) { - throw new GLException("Null texture colorbuffer, samples "+samples+", "+fbo.toString()); - } - gl.glActiveTexture(GL.GL_TEXTURE0 + texUnit); - fbo.use(gl, attachment ); - if( samples > 0) { - gl.glBindFramebuffer(GL2GL3.GL_READ_FRAMEBUFFER, fbo.getReadFramebuffer()); + initialized = false; + + for(int i=0; i "+newSamples); + } + initialize(false, gl); + samples = newSamples; + initialize(true, gl); + } else { + if(DEBUG) { + System.err.println("GLFBODrawableImpl.reset(): simple reconfig: "+samples+" -> "+newSamples); + } + final int nWidth = getWidth(); + final int nHeight = getHeight(); + samples = newSamples; + pendingFBOReset = ( 1 < fbos.length ) ? fbos[fboIFront] : null; // pending-front reset only w/ double buffering (or zero samples) + for(int i=0; i 0 ) { + res = fbos[0].getSamplingSinkFBO(); + } else { + res = fbos[fboIFront]; + } + break; + case GL.GL_BACK: + res = fbos[fboIBack]; + break; + default: + throw new IllegalArgumentException(illegalBufferName+toHexString(bufferName)); + } + return res; + } + + @Override + public final TextureAttachment getTextureBuffer(int bufferName) throws IllegalArgumentException { + if(!initialized) { + return null; + } + final TextureAttachment res; + switch(bufferName) { + case GL.GL_FRONT: + if( samples > 0 ) { + res = fbos[0].getSamplingSink(); + } else { + res = (TextureAttachment) fbos[fboIFront].getColorbuffer(0); + } + break; + case GL.GL_BACK: + if( samples > 0 ) { + throw new IllegalArgumentException("Cannot access GL_BACK buffer of MSAA FBO: "+this); + } else { + res = (TextureAttachment) fbos[fboIBack].getColorbuffer(0); + } + break; + default: + throw new IllegalArgumentException(illegalBufferName+toHexString(bufferName)); + } + return res; + } + private static final String illegalBufferName = "Only GL_FRONT and GL_BACK buffer are allowed, passed "; + + @Override + public String toString() { + return getClass().getSimpleName()+"[Initialized "+initialized+", realized "+isRealized()+", texUnit "+texUnit+", samples "+samples+ + ",\n\tFactory "+getFactory()+ + ",\n\tHandle "+toHexString(getHandle())+ + ",\n\tCaps "+surface.getGraphicsConfiguration().getChosenCapabilities()+ + ",\n\tfboI back "+fboIBack+", front "+fboIFront+", num "+(initialized ? fbos.length : 0)+ + ",\n\tFBO front read "+getDefaultReadFramebuffer()+", "+getFBObject(GL.GL_FRONT)+ + ",\n\tFBO back write "+getDefaultDrawFramebuffer()+", "+getFBObject(GL.GL_BACK)+ + ",\n\tSurface "+getNativeSurface()+ + "]"; + } + + public static class ResizeableImpl extends GLFBODrawableImpl implements GLFBODrawable.Resizeable { + protected ResizeableImpl(GLDrawableFactoryImpl factory, GLDrawableImpl parent, ProxySurface surface, + GLCapabilitiesImmutable fboCaps, int textureUnit) { + super(factory, parent, surface, fboCaps, textureUnit); + } + + @Override + public final void setSize(GLContext context, int newWidth, int newHeight) throws NativeWindowException, GLException { + if(DEBUG) { + System.err.println("GLFBODrawableImpl.ResizeableImpl setSize: ("+Thread.currentThread().getName()+"): "+newWidth+"x"+newHeight+" - surfaceHandle 0x"+Long.toHexString(getNativeSurface().getSurfaceHandle())); + } + int lockRes = lockSurface(); + if (NativeSurface.LOCK_SURFACE_NOT_READY >= lockRes) { + throw new NativeWindowException("Could not lock surface: "+this); + } + try { + // propagate new size + final ProxySurface ps = (ProxySurface) getNativeSurface(); + final UpstreamSurfaceHook ush = ps.getUpstreamSurfaceHook(); + if(ush instanceof UpstreamSurfaceHook.MutableSize) { + ((UpstreamSurfaceHook.MutableSize)ush).setSize(newWidth, newHeight); + } else { + throw new InternalError("GLFBODrawableImpl.ResizableImpl's ProxySurface doesn't hold a UpstreamSurfaceHookMutableSize but "+ush.getClass().getName()+", "+ps+", ush"); + } + if( null != context && context.isCreated() ) { + resetSize(context.getGL()); + } + } finally { + unlockSurface(); + } + } + } } diff --git a/src/jogl/classes/jogamp/opengl/GLGraphicsConfigurationUtil.java b/src/jogl/classes/jogamp/opengl/GLGraphicsConfigurationUtil.java index 768fc6892..79f96b64a 100644 --- a/src/jogl/classes/jogamp/opengl/GLGraphicsConfigurationUtil.java +++ b/src/jogl/classes/jogamp/opengl/GLGraphicsConfigurationUtil.java @@ -28,8 +28,12 @@ package jogamp.opengl; +import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLContext; + +import com.jogamp.common.os.Platform; public class GLGraphicsConfigurationUtil { public static final String NV_coverage_sample = "NV_coverage_sample"; @@ -119,26 +123,34 @@ public class GLGraphicsConfigurationUtil { return getExclusiveWinAttributeBits(caps.isOnscreen(), caps.isFBO(), caps.isPBuffer(), caps.isBitmap()); } - public static final GLCapabilities setWinAttributeBits(GLCapabilities caps, int winattrbits) { + public static final GLCapabilities fixWinAttribBitsAndHwAccel(AbstractGraphicsDevice device, int winattrbits, GLCapabilities caps) { caps.setBitmap ( 0 != ( BITMAP_BIT & winattrbits ) ); caps.setPBuffer ( 0 != ( PBUFFER_BIT & winattrbits ) ); caps.setFBO ( 0 != ( FBO_BIT & winattrbits ) ); // we reflect availability semantics, hence setting onscreen at last (maybe overwritten above)! - caps.setOnscreen( 0 != ( WINDOW_BIT & winattrbits ) ); - return caps; - } + caps.setOnscreen( 0 != ( WINDOW_BIT & winattrbits ) ); + final int accel = GLContext.isHardwareRasterizer( device, caps.getGLProfile() ); + if(0 == accel && caps.getHardwareAccelerated() ) { + caps.setHardwareAccelerated(false); + } + + return caps; + } + public static GLCapabilitiesImmutable fixGLCapabilities(GLCapabilitiesImmutable capsRequested, boolean fboAvailable, boolean pbufferAvailable) { if( !capsRequested.isOnscreen() ) { return fixOffscreenGLCapabilities(capsRequested, fboAvailable, pbufferAvailable); - } + } /* we maintain the offscreen mode flags in onscreen mode - else { + return fixOnscreenGLCapabilities(capsRequested); + } */ return capsRequested; } public static GLCapabilitiesImmutable fixOnscreenGLCapabilities(GLCapabilitiesImmutable capsRequested) { - if( !capsRequested.isOnscreen() ) { + if( !capsRequested.isOnscreen() || capsRequested.isFBO() || capsRequested.isPBuffer() || capsRequested.isBitmap() ) { // fix caps .. final GLCapabilities caps2 = (GLCapabilities) capsRequested.cloneMutable(); caps2.setBitmap (false); @@ -157,9 +169,11 @@ public class GLGraphicsConfigurationUtil { public static GLCapabilitiesImmutable fixOffscreenGLCapabilities(GLCapabilitiesImmutable capsRequested, boolean fboAvailable, boolean pbufferAvailable) { final boolean auto = !capsRequested.isFBO() && !capsRequested.isPBuffer() && !capsRequested.isBitmap() ; + + final boolean requestedPBuffer = capsRequested.isPBuffer() || Platform.getOSType() == Platform.OSType.MACOS ; // no native bitmap for OSX final boolean useFBO = fboAvailable && ( auto || capsRequested.isFBO() ) ; - final boolean usePbuffer = !useFBO && pbufferAvailable && ( auto || capsRequested.isPBuffer() ) ; + final boolean usePbuffer = !useFBO && pbufferAvailable && ( auto || requestedPBuffer ) ; final boolean useBitmap = !useFBO && !usePbuffer && ( auto || capsRequested.isBitmap() ) ; if( capsRequested.isOnscreen() || diff --git a/src/jogl/classes/jogamp/opengl/GLOffscreenAutoDrawableImpl.java b/src/jogl/classes/jogamp/opengl/GLOffscreenAutoDrawableImpl.java new file mode 100644 index 000000000..7701f209f --- /dev/null +++ b/src/jogl/classes/jogamp/opengl/GLOffscreenAutoDrawableImpl.java @@ -0,0 +1,123 @@ +/** + * 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 jogamp.opengl; + +import javax.media.nativewindow.NativeWindowException; +import javax.media.opengl.GL; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawable; +import javax.media.opengl.GLException; +import javax.media.opengl.GLOffscreenAutoDrawable; + +import com.jogamp.common.util.locks.RecursiveLock; +import com.jogamp.opengl.FBObject; +import com.jogamp.opengl.GLAutoDrawableDelegate; + +import jogamp.opengl.GLFBODrawableImpl; + +public class GLOffscreenAutoDrawableImpl extends GLAutoDrawableDelegate implements GLOffscreenAutoDrawable { + + /** + * @param drawable a valid and already realized {@link GLDrawable} + * @param context a valid {@link GLContext}, may not be made current (created) yet. + * @param upstreamWidget optional UI element holding this instance, see {@link #getUpstreamWidget()}. + * @param lock optional upstream lock, may be null + */ + public GLOffscreenAutoDrawableImpl(GLDrawable drawable, GLContext context, Object upstreamWidget, RecursiveLock lock) { + super(drawable, context, upstreamWidget, true, lock); + } + + @Override + public void setSize(int newWidth, int newHeight) throws NativeWindowException, GLException { + this.defaultWindowResizedOp(newWidth, newHeight); + } + + public static class FBOImpl extends GLOffscreenAutoDrawableImpl implements GLOffscreenAutoDrawable.FBO { + /** + * @param drawable a valid and already realized {@link GLDrawable} + * @param context a valid {@link GLContext}, may not be made current (created) yet. + * @param upstreamWidget optional UI element holding this instance, see {@link #getUpstreamWidget()}. + * @param lock optional upstream lock, may be null + */ + public FBOImpl(GLFBODrawableImpl drawable, GLContext context, Object upstreamWidget, RecursiveLock lock) { + super(drawable, context, upstreamWidget, lock); + } + + @Override + public boolean isInitialized() { + return ((GLFBODrawableImpl)drawable).isInitialized(); + } + + @Override + public final int getTextureUnit() { + return ((GLFBODrawableImpl)drawable).getTextureUnit(); + } + + @Override + public final void setTextureUnit(int unit) { + ((GLFBODrawableImpl)drawable).setTextureUnit(unit); + } + + @Override + public final int getNumSamples() { + return ((GLFBODrawableImpl)drawable).getNumSamples(); + } + + @Override + public final void setNumSamples(GL gl, int newSamples) throws GLException { + ((GLFBODrawableImpl)drawable).setNumSamples(gl, newSamples); + windowRepaintOp(); + } + + /** // TODO: Add or remove TEXTURE (only) DoubleBufferMode support + @Override + public DoubleBufferMode getDoubleBufferMode() { + return ((GLFBODrawableImpl)drawable).getDoubleBufferMode(); + } + + @Override + public void setDoubleBufferMode(DoubleBufferMode mode) throws GLException { + ((GLFBODrawableImpl)drawable).setDoubleBufferMode(mode); + } */ + + @Override + public final FBObject getFBObject(int bufferName) { + return ((GLFBODrawableImpl)drawable).getFBObject(bufferName); + } + + public final FBObject.TextureAttachment getTextureBuffer(int bufferName) { + return ((GLFBODrawableImpl)drawable).getTextureBuffer(bufferName); + } + + @Override + public void resetSize(GL gl) throws GLException { + ((GLFBODrawableImpl)drawable).resetSize(gl); + } + } +} diff --git a/src/jogl/classes/jogamp/opengl/GLPbufferImpl.java b/src/jogl/classes/jogamp/opengl/GLPbufferImpl.java index 32f4cb696..b438131bc 100644 --- a/src/jogl/classes/jogamp/opengl/GLPbufferImpl.java +++ b/src/jogl/classes/jogamp/opengl/GLPbufferImpl.java @@ -40,9 +40,6 @@ 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; @@ -50,36 +47,18 @@ 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 - interface so can be interacted with via its display() method. */ - +@SuppressWarnings("deprecation") public class GLPbufferImpl extends GLAutoDrawableBase implements GLPbuffer { private int floatMode; - public GLPbufferImpl(GLDrawableImpl pbufferDrawable, GLContext sharedContext, boolean ownDevice) { - super(pbufferDrawable, null, ownDevice); // drawable := pbufferDrawable - - GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) - drawable.getNativeSurface().getGraphicsConfiguration().getChosenCapabilities(); - if(caps.isOnscreen()) { - if(caps.isPBuffer()) { - throw new IllegalArgumentException("Error: Given drawable is Onscreen and Pbuffer: "+pbufferDrawable); - } - throw new IllegalArgumentException("Error: Given drawable is Onscreen: "+pbufferDrawable); - } else { - if(!caps.isPBuffer()) { - throw new IllegalArgumentException("Error: Given drawable is not Pbuffer: "+pbufferDrawable); - } - } - context = (GLContextImpl) drawable.createContext(sharedContext); + public GLPbufferImpl(GLDrawableImpl pbufferDrawable, GLContextImpl pbufferContext) { + super(pbufferDrawable, pbufferContext, true); // drawable := pbufferDrawable, context := pbufferContext } // // pbuffer specifics - // - + // + @Override public void bindTexture() { // Doesn't make much sense to try to do this on the event dispatch diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLContext.java b/src/jogl/classes/jogamp/opengl/egl/EGLContext.java index 03d0d650f..06953a8e1 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLContext.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLContext.java @@ -282,12 +282,6 @@ public abstract class EGLContext extends GLContextImpl { return EGL.eglSwapInterval(drawable.getNativeSurface().getDisplayHandle(), interval); } - @Override - public abstract void bindPbufferToTexture(); - - @Override - public abstract void releasePbufferFromTexture(); - // // Accessible .. // diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java b/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java index 0dba4bb09..167eebf3a 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLDrawable.java @@ -36,7 +36,8 @@ package jogamp.opengl.egl; -import javax.media.nativewindow.MutableSurface; +import java.nio.IntBuffer; + import javax.media.nativewindow.NativeSurface; import javax.media.nativewindow.NativeWindow; import javax.media.nativewindow.ProxySurface; @@ -46,10 +47,10 @@ import javax.media.opengl.GLException; import jogamp.opengl.GLDrawableImpl; import jogamp.opengl.GLDynamicLookupHelper; +import com.jogamp.common.nio.Buffers; import com.jogamp.nativewindow.egl.EGLGraphicsDevice; public abstract class EGLDrawable extends GLDrawableImpl { - private boolean ownEGLSurface = false; // for destruction protected EGLDrawable(EGLDrawableFactory factory, NativeSurface component) throws GLException { super(factory, component, false); @@ -58,21 +59,14 @@ public abstract class EGLDrawable extends GLDrawableImpl { @Override public abstract GLContext createContext(GLContext shareWith); - protected abstract long createSurface(EGLGraphicsConfiguration config, long nativeSurfaceHandle); + protected abstract long createSurface(EGLGraphicsConfiguration config, int width, int height, 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 "+eglConfig); - } - if( EGL.EGL_NO_SURFACE != surface.getSurfaceHandle() ) { - EGL.eglDestroySurface(eglDevice.getHandle(), surface.getSurfaceHandle()); - } + private final long createEGLSurface() { + final EGLWrappedSurface eglws = (EGLWrappedSurface) surface; + final EGLGraphicsConfiguration eglConfig = (EGLGraphicsConfiguration) eglws.getGraphicsConfiguration(); + final NativeSurface upstreamSurface = eglws.getUpstreamSurface(); - final EGLUpstreamSurfaceHook upstreamHook = (EGLUpstreamSurfaceHook) ((ProxySurface)surface).getUpstreamSurfaceHook(); - final NativeSurface upstreamSurface = upstreamHook.getUpstreamSurface(); - long eglSurface = createSurface(eglConfig, upstreamSurface.getSurfaceHandle()); + long eglSurface = createSurface(eglConfig, eglws.getWidth(), eglws.getHeight(), upstreamSurface.getSurfaceHandle()); int eglError0; if (EGL.EGL_NO_SURFACE == eglSurface) { @@ -86,7 +80,7 @@ public abstract class EGLDrawable extends GLDrawableImpl { if(DEBUG) { System.err.println(getThreadName() + ": Info: Creation of window surface w/ surface handle failed: "+eglConfig+", error "+toHexString(eglError0)+", retry w/ windowHandle"); } - eglSurface = createSurface(eglConfig, nw.getWindowHandle()); + eglSurface = createSurface(eglConfig, eglws.getWidth(), eglws.getHeight(), nw.getWindowHandle()); if (EGL.EGL_NO_SURFACE == eglSurface) { eglError0 = EGL.eglGetError(); } @@ -99,34 +93,53 @@ public abstract class EGLDrawable extends GLDrawableImpl { if (EGL.EGL_NO_SURFACE == eglSurface) { throw new GLException("Creation of window surface failed: "+eglConfig+", "+surface+", error "+toHexString(eglError0)); } - if(DEBUG) { - System.err.println(getThreadName() + ": setSurface using component: handle "+toHexString(surface.getSurfaceHandle())+" -> "+toHexString(eglSurface)); + System.err.println(getThreadName() + ": createEGLSurface handle "+toHexString(eglSurface)); } - - ((MutableSurface)surface).setSurfaceHandle(eglSurface); + return eglSurface; } @Override protected final void updateHandle() { - if(ownEGLSurface) { - recreateSurface(); + final EGLWrappedSurface eglws = (EGLWrappedSurface) surface; + if(DEBUG) { + System.err.println(getThreadName() + ": updateHandle of "+eglws); + } + if( eglws.containsUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ) ) { + if( EGL.EGL_NO_SURFACE != eglws.getSurfaceHandle() ) { + throw new InternalError("Set surface but claimed to be invalid: "+eglws); + } + eglws.setSurfaceHandle( createEGLSurface() ); + } else if( EGL.EGL_NO_SURFACE == eglws.getSurfaceHandle() ) { + throw new InternalError("Nil surface but claimed to be valid: "+eglws); + } + } + + protected void destroyHandle() { + final EGLWrappedSurface eglws = (EGLWrappedSurface) surface; + if(DEBUG) { + System.err.println(getThreadName() + ": destroyHandle of "+eglws); + } + if( EGL.EGL_NO_SURFACE == eglws.getSurfaceHandle() ) { + throw new InternalError("Nil surface but claimed to be valid: "+eglws); + } + final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) eglws.getGraphicsConfiguration().getScreen().getDevice(); + if( eglws.containsUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ) ) { + EGL.eglDestroySurface(eglDevice.getHandle(), eglws.getSurfaceHandle()); + eglws.setSurfaceHandle(EGL.EGL_NO_SURFACE); } } - protected static boolean isValidEGLSurface(EGLGraphicsDevice eglDevice, NativeSurface surface) { - final long eglDisplayHandle = eglDevice.getHandle(); - if (EGL.EGL_NO_DISPLAY == eglDisplayHandle) { - throw new GLException("Invalid EGL display in EGLGraphicsDevice "+eglDevice); + protected static boolean isValidEGLSurface(long eglDisplayHandle, long surfaceHandle) { + if( 0 == surfaceHandle ) { + return false; } - boolean eglSurfaceValid = 0 != surface.getSurfaceHandle(); - if(eglSurfaceValid) { - int[] tmp = new int[1]; - eglSurfaceValid = EGL.eglQuerySurface(eglDisplayHandle, surface.getSurfaceHandle(), EGL.EGL_CONFIG_ID, tmp, 0); - if(!eglSurfaceValid) { - if(DEBUG) { - System.err.println(getThreadName() + ": EGLDrawable.isValidEGLSurface eglQuerySuface failed: "+toHexString(EGL.eglGetError())+", "+surface); - } + final IntBuffer val = Buffers.newDirectIntBuffer(1); + final boolean eglSurfaceValid = EGL.eglQuerySurface(eglDisplayHandle, surfaceHandle, EGL.EGL_CONFIG_ID, val); + if( !eglSurfaceValid ) { + final int eglErr = EGL.eglGetError(); + if(DEBUG) { + System.err.println(getThreadName() + ": EGLDrawable.isValidEGLSurface eglQuerySuface failed: error "+toHexString(eglErr)+", "+toHexString(surfaceHandle)); } } return eglSurfaceValid; @@ -134,55 +147,19 @@ public abstract class EGLDrawable extends GLDrawableImpl { @Override protected final void setRealizedImpl() { - final EGLGraphicsConfiguration eglConfig = (EGLGraphicsConfiguration) surface.getGraphicsConfiguration(); - final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) eglConfig.getScreen().getDevice(); - if (realized) { - final boolean eglSurfaceValid = isValidEGLSurface(eglDevice, surface); - 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 { - // 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); - } - final ProxySurface.UpstreamSurfaceHook upstreamHook = ((ProxySurface)surface).getUpstreamSurfaceHook(); - if( null == upstreamHook ) { - throw new InternalError("null upstreamHook of: "+surface); - } - if( ! (upstreamHook instanceof EGLUpstreamSurfaceHook) ) { - throw new InternalError("upstreamHook not EGLUpstreamSurfaceHook: Surface: "+surface.getClass().getName()+", "+surface+"; UpstreamHook: "+upstreamHook.getClass().getName()+", "+upstreamHook); - } - if( null == ((EGLUpstreamSurfaceHook)upstreamHook).getUpstreamSurface() ) { - throw new InternalError("null upstream surface"); - } - ownEGLSurface=true; - if(DEBUG) { - System.err.println(getThreadName() + ": EGLDrawable.setRealizedImpl owning EGLSurface"); - } - } - } else if (ownEGLSurface && surface.getSurfaceHandle() != EGL.EGL_NO_SURFACE) { - if(DEBUG) { - System.err.println(getThreadName() + ": EGLDrawable.setRealized(false): ownSurface "+ownEGLSurface+", "+eglDevice+", eglSurface: "+toHexString(surface.getSurfaceHandle())); - } - // Destroy the window surface - if (!EGL.eglDestroySurface(eglDevice.getHandle(), surface.getSurfaceHandle())) { - throw new GLException("Error destroying window surface (eglDestroySurface)"); - } - ((MutableSurface)surface).setSurfaceHandle(EGL.EGL_NO_SURFACE); + if(DEBUG) { + System.err.println(getThreadName() + ": EGLDrawable.setRealized("+realized+"): NOP - "+surface); } } @Override - protected final void swapBuffersImpl() { - final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) surface.getGraphicsConfiguration().getScreen().getDevice(); - // single-buffer is already filtered out @ GLDrawableImpl#swapBuffers() - if(!EGL.eglSwapBuffers(eglDevice.getHandle(), surface.getSurfaceHandle())) { - throw new GLException("Error swapping buffers, eglError "+toHexString(EGL.eglGetError())+", "+this); + protected final void swapBuffersImpl(boolean doubleBuffered) { + if(doubleBuffered) { + final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) surface.getGraphicsConfiguration().getScreen().getDevice(); + // single-buffer is already filtered out @ GLDrawableImpl#swapBuffers() + if(!EGL.eglSwapBuffers(eglDevice.getHandle(), surface.getSurfaceHandle())) { + throw new GLException("Error swapping buffers, eglError "+toHexString(EGL.eglGetError())+", "+this); + } } } diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java index 292eb17c8..e98d69140 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLDrawableFactory.java @@ -52,8 +52,7 @@ 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.UpstreamSurfaceHook; import javax.media.nativewindow.VisualIDHolder; import javax.media.opengl.GL; import javax.media.opengl.GLCapabilities; @@ -65,6 +64,7 @@ import javax.media.opengl.GLDrawableFactory; import javax.media.opengl.GLException; import javax.media.opengl.GLProfile; +import jogamp.nativewindow.WrappedSurface; import jogamp.opengl.Debug; import jogamp.opengl.GLDrawableFactoryImpl; import jogamp.opengl.GLDrawableImpl; @@ -76,10 +76,11 @@ import com.jogamp.common.nio.Buffers; import com.jogamp.common.nio.PointerBuffer; import com.jogamp.common.os.Platform; import com.jogamp.common.util.ReflectionUtil; -import com.jogamp.nativewindow.WrappedSurface; import com.jogamp.nativewindow.egl.EGLGraphicsDevice; public class EGLDrawableFactory extends GLDrawableFactoryImpl { + protected static final boolean DEBUG = GLDrawableFactoryImpl.DEBUG; + /* package */ static final boolean QUERY_EGL_ES = !Debug.isPropertyDefined("jogl.debug.EGLDrawableFactory.DontQuery", true); /* package */ static final boolean QUERY_EGL_ES_NATIVE_TK = Debug.isPropertyDefined("jogl.debug.EGLDrawableFactory.QueryNativeTK", true); @@ -112,7 +113,7 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { } catch (JogampRuntimeException jre) { /* n/a .. */ } } - defaultDevice = new EGLGraphicsDevice(AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT); + defaultDevice = new EGLGraphicsDevice(); // FIXME: Probably need to move EGL from a static model // to a dynamic one, where there can be 2 instances @@ -310,6 +311,7 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { try { final GLCapabilities reqCapsAny = new GLCapabilities(glp); reqCapsAny.setRedBits(5); reqCapsAny.setGreenBits(5); reqCapsAny.setBlueBits(5); reqCapsAny.setAlphaBits(0); + reqCapsAny.setDoubleBuffered(false); final GLCapabilitiesImmutable reqCapsPBuffer = GLGraphicsConfigurationUtil.fixGLPBufferGLCapabilities(reqCapsAny); final List availablePBufferCapsL = getAvailableEGLConfigs(sharedEGLDevice, reqCapsPBuffer); hasPBuffer[0] = availablePBufferCapsL.size() > 0; @@ -324,18 +326,20 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { } else { final List capsAnyL = getAvailableEGLConfigs(eglDevice, reqCapsAny); if(capsAnyL.size() > 0) { - final GLCapabilitiesImmutable caps = capsAnyL.get(0); - EGLContext.mapStaticGLESVersion(eglDevice, caps); + final GLCapabilitiesImmutable chosenCaps = capsAnyL.get(0); + EGLContext.mapStaticGLESVersion(eglDevice, chosenCaps); if(eglDevice != adevice) { - EGLContext.mapStaticGLESVersion(adevice, caps); + EGLContext.mapStaticGLESVersion(adevice, chosenCaps); } + final EGLGraphicsDevice adeviceEGLDevice = new EGLGraphicsDevice(adevice.getHandle(), EGL.EGL_NO_DISPLAY, adevice.getConnection(), adevice.getUnitID(), null); + EGLContext.mapStaticGLESVersion(adeviceEGLDevice, chosenCaps); success = true; } if(DEBUG) { System.err.println("EGLDrawableFactory.isEGLContextAvailable() no pbuffer config available, detected !pbuffer config: "+success); EGLGraphicsConfigurationFactory.printCaps("!PBufferCaps", capsAnyL, System.err); } - } + } } else { surface = desktopFactory.createDummySurface(adevice, reqCapsAny, null, 64, 64); // X11, WGL, .. dummy window upstreamSurface = ( surface instanceof ProxySurface ) ? (ProxySurface)surface : null ; @@ -361,6 +365,8 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { if(eglDevice != adevice) { context.mapCurrentAvailableGLVersion(adevice); } + final EGLGraphicsDevice adeviceEGLDevice = new EGLGraphicsDevice(adevice.getHandle(), EGL.EGL_NO_DISPLAY, adevice.getConnection(), adevice.getUnitID(), null); + context.mapCurrentAvailableGLVersion(adeviceEGLDevice); success = true; } else { // Oops .. something is wrong @@ -538,70 +544,9 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { if (target == null) { throw new IllegalArgumentException("Null target"); } - return new EGLOnscreenDrawable(this, getEGLSurface(target)); + return new EGLOnscreenDrawable(this, EGLWrappedSurface.get(target)); } - protected static NativeSurface getEGLSurface(NativeSurface surface) { - AbstractGraphicsConfiguration aConfig = surface.getGraphicsConfiguration(); - AbstractGraphicsDevice aDevice = aConfig.getScreen().getDevice(); - if( aDevice instanceof EGLGraphicsDevice && aConfig instanceof EGLGraphicsConfiguration ) { - if(surface instanceof WrappedSurface) { - // already wrapped surface - no wrapped recursion - if(DEBUG) { - System.err.println(getThreadName() + ": getEGLSurface - already wrapped surface - use as-is: "+surface); - } - return surface; - } - if(EGLDrawable.isValidEGLSurface((EGLGraphicsDevice)aDevice, surface)) { - // already in native EGL format - if(DEBUG) { - System.err.println(getThreadName() + ": getEGLSurface - already valid EGL surface - use as-is: "+surface); - } - return surface; - } - } - // create EGL instance out of platform native types - final EGLGraphicsDevice eglDevice; - if( aDevice instanceof EGLGraphicsDevice ) { - eglDevice = (EGLGraphicsDevice) aDevice; - if(DEBUG) { - System.err.println(getThreadName() + ": getEGLSurface - Reusing eglDevice: "+eglDevice); - } - if(0 == eglDevice.getHandle()) { - eglDevice.open(); - } - } else { - eglDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(surface); - } - 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 with error "+EGLContext.toHexString(EGL.eglGetError())+": "+eglDevice+", "+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 @@ -615,7 +560,7 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { throw new GLException("Non pbuffer not yet implemented"); } // PBuffer GLDrawable Creation - return new EGLPbufferDrawable(this, getEGLSurface(target)); + return new EGLPbufferDrawable(this, EGLWrappedSurface.get(target)); } @Override @@ -628,20 +573,24 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { @Override protected ProxySurface createMutableSurfaceImpl(AbstractGraphicsDevice deviceReq, boolean createNewDevice, GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsRequested, - GLCapabilitiesChooser chooser, int width, int height, UpstreamSurfaceHook lifecycleHook) { + GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstreamHook) { + final boolean ownDevice; final EGLGraphicsDevice device; - if(createNewDevice) { - final EGLGraphicsDevice eglDeviceReq = (EGLGraphicsDevice) deviceReq; - device = EGLDisplayUtil.eglCreateEGLGraphicsDevice(eglDeviceReq.getNativeDisplayID(), deviceReq.getConnection(), deviceReq.getUnitID()); + if(createNewDevice || ! ( deviceReq instanceof EGLGraphicsDevice ) ) { + final long nativeDisplayID = ( deviceReq instanceof EGLGraphicsDevice) ? + ( (EGLGraphicsDevice) deviceReq ).getNativeDisplayID() : deviceReq.getHandle() ; + device = EGLDisplayUtil.eglCreateEGLGraphicsDevice(nativeDisplayID, deviceReq.getConnection(), deviceReq.getUnitID()); + ownDevice = true; } else { device = (EGLGraphicsDevice) deviceReq; + ownDevice = false; } 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); + return new WrappedSurface(config, 0, upstreamHook, ownDevice); } @Override @@ -649,54 +598,9 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { GLCapabilitiesImmutable requestedCaps, GLCapabilitiesChooser chooser, int width, int height) { final GLCapabilitiesImmutable chosenCaps = GLGraphicsConfigurationUtil.fixDoubleBufferedGLCapabilities( - GLGraphicsConfigurationUtil.fixOffscreenGLCapabilities(requestedCaps, false, canCreateGLPbuffer(deviceReq)), - false); - return createMutableSurfaceImpl(deviceReq, createNewDevice, chosenCaps, requestedCaps, chooser, width, height, dummySurfaceLifecycleHook); + GLGraphicsConfigurationUtil.fixOffscreenGLCapabilities(requestedCaps, false, canCreateGLPbuffer(deviceReq)), false); + return createMutableSurfaceImpl(deviceReq, createNewDevice, chosenCaps, requestedCaps, chooser, new EGLDummyUpstreamSurfaceHook(width, height)); } - 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. @@ -705,7 +609,9 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { * @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(); + return null; + } + protected static long createPBufferSurfaceImpl(EGLGraphicsConfiguration config, int width, int height, boolean useTexture) { final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) config.getScreen().getDevice(); final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) config.getChosenCapabilities(); final int texFormat; @@ -720,15 +626,14 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { System.out.println("Pbuffer config: " + config); } - final int[] attrs = EGLGraphicsConfiguration.CreatePBufferSurfaceAttribList(ms.getWidth(), ms.getHeight(), texFormat); + final int[] attrs = EGLGraphicsConfiguration.CreatePBufferSurfaceAttribList(width, height, 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())); + throw new GLException("Creation of window surface (eglCreatePbufferSurface) failed, dim "+width+"x"+height+", "+eglDevice+", "+config+", 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; + return surf; } @Override @@ -737,7 +642,7 @@ public class EGLDrawableFactory extends GLDrawableFactoryImpl { 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); + return new WrappedSurface(cfg, windowHandle, upstream, true); } @Override diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLDummyUpstreamSurfaceHook.java b/src/jogl/classes/jogamp/opengl/egl/EGLDummyUpstreamSurfaceHook.java new file mode 100644 index 000000000..b172d4f35 --- /dev/null +++ b/src/jogl/classes/jogamp/opengl/egl/EGLDummyUpstreamSurfaceHook.java @@ -0,0 +1,49 @@ +package jogamp.opengl.egl; + +import javax.media.nativewindow.NativeSurface; +import javax.media.nativewindow.ProxySurface; +import javax.media.nativewindow.UpstreamSurfaceHook; + +import com.jogamp.nativewindow.UpstreamSurfaceHookMutableSize; +import com.jogamp.nativewindow.egl.EGLGraphicsDevice; + +public class EGLDummyUpstreamSurfaceHook extends UpstreamSurfaceHookMutableSize { + /** + * @param width the initial width as returned by {@link NativeSurface#getWidth()} via {@link UpstreamSurfaceHook#getWidth(ProxySurface)}, + * not the actual dummy surface width. + * The latter is platform specific and small + * @param height the initial height as returned by {@link NativeSurface#getHeight()} via {@link UpstreamSurfaceHook#getHeight(ProxySurface)}, + * not the actual dummy surface height, + * The latter is platform specific and small + */ + public EGLDummyUpstreamSurfaceHook(int width, int height) { + super(width, height); + } + + @Override + public final void create(ProxySurface s) { + final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) s.getGraphicsConfiguration().getScreen().getDevice(); + if(0 == eglDevice.getHandle()) { + eglDevice.open(); + s.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_DEVICE ); + } + if( EGL.EGL_NO_SURFACE == s.getSurfaceHandle() ) { + s.setSurfaceHandle( EGLDrawableFactory.createPBufferSurfaceImpl((EGLGraphicsConfiguration)s.getGraphicsConfiguration(), 64, 64, false) ); + s.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ); + } + s.addUpstreamOptionBits(ProxySurface.OPT_UPSTREAM_WINDOW_INVISIBLE); + } + + @Override + public final void destroy(ProxySurface s) { + if( s.containsUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ) ) { + final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) s.getGraphicsConfiguration().getScreen().getDevice(); + if( EGL.EGL_NO_SURFACE == s.getSurfaceHandle() ) { + throw new InternalError("Owns upstream surface, but no EGL surface: "+s); + } + EGL.eglDestroySurface(eglDevice.getHandle(), s.getSurfaceHandle()); + s.setSurfaceHandle(EGL.EGL_NO_SURFACE); + s.clearUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ); + } + } +} diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLExternalContext.java b/src/jogl/classes/jogamp/opengl/egl/EGLExternalContext.java index 585638d21..84bd705db 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLExternalContext.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLExternalContext.java @@ -79,15 +79,4 @@ public class EGLExternalContext extends EGLContext { @Override protected void destroyImpl() throws GLException { } - - @Override - public void bindPbufferToTexture() { - throw new GLException("Should not call this"); - } - - @Override - public void releasePbufferFromTexture() { - throw new GLException("Should not call this"); - } - } diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLGLCapabilities.java b/src/jogl/classes/jogamp/opengl/egl/EGLGLCapabilities.java index e513a86cf..f857c6b5c 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLGLCapabilities.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLGLCapabilities.java @@ -57,8 +57,8 @@ public class EGLGLCapabilities extends GLCapabilities { this.eglcfg = eglcfg; this.eglcfgid = eglcfgid; if(!isCompatible(glp, renderableType)) { - throw new GLException("Incompatible "+glp+ - " with EGL-RenderableType["+renderableTypeToString(null, renderableType)+"]"); + throw new GLException("Requested GLProfile "+glp+ + " not compatible with EGL-RenderableType["+renderableTypeToString(null, renderableType)+"]"); } this.renderableType = renderableType; this.nativeVisualID = visualID; @@ -131,6 +131,7 @@ public class EGLGLCapabilities extends GLCapabilities { sink = new StringBuilder(); } boolean first=true; + sink.append("0x").append(Integer.toHexString(renderableType)).append(": "); if(0 != (renderableType & EGL.EGL_OPENGL_BIT)) { sink.append("GL"); first=false; } diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java b/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java index 8ee98072f..7bf201238 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLGraphicsConfiguration.java @@ -211,6 +211,13 @@ public class EGLGraphicsConfiguration extends MutableGraphicsConfiguration imple if(null == glp) { glp = EGLGLCapabilities.getCompatible(device, rType); } + if(!EGLGLCapabilities.isCompatible(glp, rType)) { + if(DEBUG) { + System.err.println("config "+toHexString(config)+": Requested GLProfile "+glp+ + " not compatible with EGL-RenderableType["+EGLGLCapabilities.renderableTypeToString(null, rType)+"]"); + } + return null; + } caps = new EGLGLCapabilities(config, cfgID, visualID, glp, rType); } catch (GLException gle) { if(DEBUG) { @@ -288,7 +295,7 @@ public class EGLGraphicsConfiguration extends MutableGraphicsConfiguration imple return null; } - return (EGLGLCapabilities) GLGraphicsConfigurationUtil.setWinAttributeBits(caps, drawableTypeBits); + return (EGLGLCapabilities) GLGraphicsConfigurationUtil.fixWinAttribBitsAndHwAccel(device, drawableTypeBits, caps); } public static int[] GLCapabilities2AttribList(GLCapabilitiesImmutable caps) { diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLOnscreenContext.java b/src/jogl/classes/jogamp/opengl/egl/EGLOnscreenContext.java index eae47fa92..325ad6142 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLOnscreenContext.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLOnscreenContext.java @@ -41,16 +41,5 @@ public class EGLOnscreenContext extends EGLContext { public EGLOnscreenContext(EGLOnscreenDrawable drawable, GLContext shareWith) { super(drawable, shareWith); } - - @Override - public void bindPbufferToTexture() { - throw new GLException("Should not call this"); - } - - @Override - public void releasePbufferFromTexture() { - throw new GLException("Should not call this"); - } - } diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLOnscreenDrawable.java b/src/jogl/classes/jogamp/opengl/egl/EGLOnscreenDrawable.java index d54057775..6440cf1e5 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(EGLGraphicsConfiguration config, long nativeSurfaceHandle) { + protected long createSurface(EGLGraphicsConfiguration config, int width, int height, long nativeSurfaceHandle) { return EGL.eglCreateWindowSurface(config.getScreen().getDevice().getHandle(), config.getNativeConfig(), nativeSurfaceHandle, null); - } + } } diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLPbufferContext.java b/src/jogl/classes/jogamp/opengl/egl/EGLPbufferContext.java index 7175d516f..bb9eeb892 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLPbufferContext.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLPbufferContext.java @@ -46,15 +46,5 @@ public class EGLPbufferContext extends EGLContext { public int getFloatingPointMode() { return 0; // FIXME ?? } - - @Override - public void bindPbufferToTexture() { - throw new GLException("Not yet implemented"); - } - - @Override - public void releasePbufferFromTexture() { - throw new GLException("Not yet implemented"); - } } diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLPbufferDrawable.java b/src/jogl/classes/jogamp/opengl/egl/EGLPbufferDrawable.java index 4a36625bd..eb7e320c8 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLPbufferDrawable.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLPbufferDrawable.java @@ -52,12 +52,8 @@ public class EGLPbufferDrawable extends EGLDrawable { } @Override - 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()); - } - return EGLDrawableFactory.createPBufferSurfaceImpl(ms, useTexture).getSurfaceHandle(); + protected long createSurface(EGLGraphicsConfiguration config, int width, int height, long nativeSurfaceHandle) { + return EGLDrawableFactory.createPBufferSurfaceImpl(config, width, height, false); } @Override diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLUpstreamSurfaceHook.java b/src/jogl/classes/jogamp/opengl/egl/EGLUpstreamSurfaceHook.java index 42c6e100e..342c4c417 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLUpstreamSurfaceHook.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLUpstreamSurfaceHook.java @@ -1,38 +1,163 @@ package jogamp.opengl.egl; +import javax.media.nativewindow.AbstractGraphicsConfiguration; +import javax.media.nativewindow.AbstractGraphicsDevice; +import javax.media.nativewindow.AbstractGraphicsScreen; +import javax.media.nativewindow.DefaultGraphicsScreen; import javax.media.nativewindow.NativeSurface; import javax.media.nativewindow.ProxySurface; +import javax.media.nativewindow.UpstreamSurfaceHook; +import javax.media.nativewindow.VisualIDHolder.VIDType; +import javax.media.opengl.GLCapabilitiesImmutable; import javax.media.opengl.GLException; import com.jogamp.nativewindow.egl.EGLGraphicsDevice; -public class EGLUpstreamSurfaceHook implements ProxySurface.UpstreamSurfaceHook { +public class EGLUpstreamSurfaceHook implements UpstreamSurfaceHook.MutableSize { + protected static final boolean DEBUG = EGLDrawableFactory.DEBUG; private final NativeSurface upstreamSurface; + private final UpstreamSurfaceHook.MutableSize upstreamSurfaceHookMutableSize; public EGLUpstreamSurfaceHook(NativeSurface upstream) { upstreamSurface = upstream; + if(upstreamSurface instanceof ProxySurface) { + final UpstreamSurfaceHook ush = ((ProxySurface)upstreamSurface).getUpstreamSurfaceHook(); + if(ush instanceof UpstreamSurfaceHook.MutableSize) { + // offscreen NativeSurface w/ MutableSize (default) + upstreamSurfaceHookMutableSize = (UpstreamSurfaceHook.MutableSize) ush; + } else { + upstreamSurfaceHookMutableSize = null; + } + } else { + upstreamSurfaceHookMutableSize = null; + } } public final NativeSurface getUpstreamSurface() { return upstreamSurface; } + static String getThreadName() { return Thread.currentThread().getName(); } + + public final void setSize(int width, int height) { + if(null != upstreamSurfaceHookMutableSize) { + upstreamSurfaceHookMutableSize.setSize(width, height); + } + } + @Override public final void create(ProxySurface surface) { + final String dbgPrefix; + if(DEBUG) { + dbgPrefix = getThreadName() + ": EGLUpstreamSurfaceHook.create("+surface.getClass().getSimpleName()+"): "; + System.err.println(dbgPrefix+this); + } else { + dbgPrefix = null; + } + if(upstreamSurface instanceof ProxySurface) { + // propagate createNotify(..) so upstreamSurface will be created ((ProxySurface)upstreamSurface).createNotify(); - if(NativeSurface.LOCK_SURFACE_NOT_READY >= upstreamSurface.lockSurface()) { - throw new GLException("Could not lock: "+upstreamSurface); + } + + // lock upstreamSurface, so it can be used in case EGLDisplay is derived from it! + if(NativeSurface.LOCK_SURFACE_NOT_READY >= upstreamSurface.lockSurface()) { + throw new GLException("Could not lock: "+upstreamSurface); + } + try { + evalUpstreamSurface(dbgPrefix, surface); + } finally { + upstreamSurface.unlockSurface(); + } + } + + private final void evalUpstreamSurface(String dbgPrefix, ProxySurface surface) { + // + // evaluate nature of upstreamSurface, may create EGL instances if required + // + + boolean isEGLSurfaceValid = true; // assume yes + + final AbstractGraphicsConfiguration aConfig = upstreamSurface.getGraphicsConfiguration(); + final AbstractGraphicsDevice aDevice = aConfig.getScreen().getDevice(); + + final EGLGraphicsDevice eglDevice; + if( aDevice instanceof EGLGraphicsDevice ) { + eglDevice = (EGLGraphicsDevice) aDevice; + if(DEBUG) { + System.err.println(dbgPrefix+"Reusing eglDevice: "+eglDevice); + } + if(EGL.EGL_NO_DISPLAY == eglDevice.getHandle()) { + eglDevice.open(); + isEGLSurfaceValid = false; + surface.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_DEVICE ); + } + } else { + eglDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(upstreamSurface); + isEGLSurfaceValid = false; + surface.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_DEVICE ); + } + + 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( !isEGLSurfaceValid || !EGLGraphicsConfiguration.isEGLConfigValid(eglDevice.getHandle(), 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 with error "+EGLContext.toHexString(EGL.eglGetError())+": "+eglDevice+", "+capsChosen+" of "+aConfig); + } + final AbstractGraphicsScreen eglScreen = new DefaultGraphicsScreen(eglDevice, aConfig.getScreen().getIndex()); + eglConfig = new EGLGraphicsConfiguration(eglScreen, capsChosen, capsRequested, null); + if(DEBUG) { + System.err.println(dbgPrefix+"Refreshing eglConfig: "+eglConfig); + } + isEGLSurfaceValid = false; + } else { + eglConfig = (EGLGraphicsConfiguration) aConfig; + if(DEBUG) { + System.err.println(dbgPrefix+"Reusing eglConfig: "+eglConfig); + } + } + } else { + final AbstractGraphicsScreen eglScreen = new DefaultGraphicsScreen(eglDevice, aConfig.getScreen().getIndex()); + 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(dbgPrefix+"Chosen eglConfig: "+eglConfig); } + isEGLSurfaceValid = false; } - final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) surface.getGraphicsConfiguration().getScreen().getDevice(); - eglDevice.open(); + surface.setGraphicsConfiguration(eglConfig); + + if(isEGLSurfaceValid) { + isEGLSurfaceValid = EGLDrawable.isValidEGLSurface(eglDevice.getHandle(), upstreamSurface.getSurfaceHandle()); + } + if(isEGLSurfaceValid) { + surface.setSurfaceHandle(upstreamSurface.getSurfaceHandle()); + surface.clearUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ); + if(DEBUG) { + System.err.println(dbgPrefix+"Fin: Already valid EGL surface - use as-is: "+upstreamSurface); + } + } else { + surface.setSurfaceHandle(EGL.EGL_NO_SURFACE); + surface.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ); // create/destroy in EGLDrawable + if(DEBUG) { + System.err.println(dbgPrefix+"Fin: EGL surface n/a - TBD: "+upstreamSurface); + } + } } @Override public final void destroy(ProxySurface surface) { - final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) surface.getGraphicsConfiguration().getScreen().getDevice(); - eglDevice.close(); + if(EGLDrawableFactory.DEBUG) { + System.err.println("EGLUpstreamSurfaceHook.destroy("+surface.getClass().getSimpleName()+"): "+this); + } + surface.clearUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ); if(upstreamSurface instanceof ProxySurface) { - upstreamSurface.unlockSurface(); ((ProxySurface)upstreamSurface).destroyNotify(); } } @@ -49,8 +174,8 @@ public class EGLUpstreamSurfaceHook implements ProxySurface.UpstreamSurfaceHook @Override public String toString() { - final String us_s = null != upstreamSurface ? ( upstreamSurface.getClass().getName() + ": " + upstreamSurface ) : "nil"; - return "EGLUpstreamSurfaceHook[upstream: "+us_s+"]"; + final String us_s = null != upstreamSurface ? ( upstreamSurface.getClass().getName() + ": 0x" + Long.toHexString(upstreamSurface.getSurfaceHandle()) ) : "nil"; + return "EGLUpstreamSurfaceHook[ "+ upstreamSurface.getWidth() + "x" + upstreamSurface.getHeight() + ", " + us_s+ "]"; } } diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLWrappedSurface.java b/src/jogl/classes/jogamp/opengl/egl/EGLWrappedSurface.java new file mode 100644 index 000000000..b36303392 --- /dev/null +++ b/src/jogl/classes/jogamp/opengl/egl/EGLWrappedSurface.java @@ -0,0 +1,26 @@ +package jogamp.opengl.egl; + +import javax.media.nativewindow.NativeSurface; + +import jogamp.nativewindow.WrappedSurface; + +public class EGLWrappedSurface extends WrappedSurface { + + public static EGLWrappedSurface get(NativeSurface surface) { + if(surface instanceof EGLWrappedSurface) { + return (EGLWrappedSurface)surface; + } + return new EGLWrappedSurface(surface); + } + + public EGLWrappedSurface(NativeSurface surface) { + super(surface.getGraphicsConfiguration(), EGL.EGL_NO_SURFACE, new EGLUpstreamSurfaceHook(surface), false /* tbd in UpstreamSurfaceHook */); + if(EGLDrawableFactory.DEBUG) { + System.err.println("EGLWrappedSurface.ctor(): "+this); + } + } + + public final NativeSurface getUpstreamSurface() { + return ((EGLUpstreamSurfaceHook)super.getUpstreamSurfaceHook()).getUpstreamSurface(); + } +} diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java index 55aea3a98..ec29558d1 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java @@ -49,6 +49,7 @@ import javax.media.nativewindow.NativeSurface; import javax.media.nativewindow.NativeWindowFactory; import javax.media.nativewindow.OffscreenLayerSurface; import javax.media.nativewindow.ProxySurface; +import javax.media.opengl.GL; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLCapabilitiesImmutable; import javax.media.opengl.GLContext; @@ -58,6 +59,7 @@ import javax.media.opengl.GLProfile; import jogamp.nativewindow.macosx.OSXUtil; import jogamp.opengl.GLContextImpl; import jogamp.opengl.GLDrawableImpl; +import jogamp.opengl.GLFBODrawableImpl; import jogamp.opengl.GLGraphicsConfigurationUtil; import jogamp.opengl.macosx.cgl.MacOSXCGLDrawable.GLBackendType; @@ -76,9 +78,11 @@ public abstract class MacOSXCGLContext extends GLContextImpl boolean isNSContext(); long create(long share, int ctp, int major, int minor); boolean destroy(long ctx); + boolean contextRealized(boolean realized); boolean copyImpl(long src, int mask); boolean makeCurrent(long ctx); boolean release(long ctx); + boolean detachPBuffer(); boolean setSwapInterval(int interval); boolean swapBuffers(); } @@ -279,7 +283,24 @@ public abstract class MacOSXCGLContext extends GLContextImpl throw new GLException("Error destroying OpenGL Context: "+this); } } + + @Override + protected void contextRealized(boolean realized) { + // context stuff depends on drawable stuff + if(realized) { + super.contextRealized(true); // 1) init drawable stuff + impl.contextRealized(true); // 2) init context stuff + } else { + impl.contextRealized(false); // 1) free context stuff + super.contextRealized(false); // 2) free drawable stuff + } + } + + /* pp */ void detachPBuffer() { + impl.detachPBuffer(); + } + @Override protected void copyImpl(GLContext source, int mask) throws GLException { if( isNSContext() != ((MacOSXCGLContext)source).isNSContext() ) { @@ -365,16 +386,6 @@ public abstract class MacOSXCGLContext extends GLContextImpl throw new GLException("Should not call this"); } - @Override - public void bindPbufferToTexture() { - throw new GLException("Should not call this"); - } - - @Override - public void releasePbufferFromTexture() { - throw new GLException("Should not call this"); - } - // Support for "mode switching" as described in MacOSXCGLDrawable public void setOpenGLMode(GLBackendType mode) { if (mode == openGLMode) { @@ -421,323 +432,486 @@ public abstract class MacOSXCGLContext extends GLContextImpl // NSOpenGLContext-based implementation class NSOpenGLImpl implements GLBackendImpl { - long nsOpenGLLayer = 0; - long nsOpenGLLayerPFmt = 0; - float screenVSyncTimeout; // microSec - int vsyncTimeout; // microSec - for nsOpenGLLayer mode - - @Override - public boolean isNSContext() { return true; } - - @Override - public long create(long share, int ctp, int major, int minor) { - long ctx = 0; - 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) { - if(DEBUG) { - System.err.println("Unable to allocate pixel format with requested GLCapabilities: "+chosenCaps); - } - return 0; - } - config.setChosenPixelFormat(pixelFormat); - int sRefreshRate = CGL.getScreenRefreshRate(drawable.getNativeSurface().getGraphicsConfiguration().getScreen().getIndex()); - screenVSyncTimeout = 1000000f / sRefreshRate; - if(DEBUG) { - System.err.println("NS create OSX>=lion "+isLionOrLater); - 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(nsViewHandle)); - System.err.println("NS create screen refresh-rate: "+sRefreshRate+" hz, "+screenVSyncTimeout+" micros"); - // Thread.dumpStack(); - } - try { - int[] viewNotReady = new int[1]; - // Try to allocate a context with this - ctx = CGL.createContext(share, - nsViewHandle, allowIncompleteView, - pixelFormat, - chosenCaps.isBackgroundOpaque(), - viewNotReady, 0); - if (0 == ctx) { - if(DEBUG) { - System.err.println("NS create failed: viewNotReady: "+ (1 == viewNotReady[0])); - } - return 0; - } + private OffscreenLayerSurface backingLayerHost = null; + private long nsOpenGLLayer = 0; + private long nsOpenGLLayerPFmt = 0; + private float screenVSyncTimeout; // microSec + private int vsyncTimeout; // microSec - for nsOpenGLLayer mode + private int lastWidth=0, lastHeight=0; // allowing to detect size change + private long lastPBufferHandle = 0; // allowing to detect pbuffer recreation + + @Override + public boolean isNSContext() { return true; } + + @Override + public long create(long share, int ctp, int major, int minor) { + long ctx = 0; + final NativeSurface surface = drawable.getNativeSurface(); + final MacOSXCGLGraphicsConfiguration config = (MacOSXCGLGraphicsConfiguration) surface.getGraphicsConfiguration(); + final GLCapabilitiesImmutable chosenCaps = (GLCapabilitiesImmutable) config.getChosenCapabilities(); + final long nsViewHandle; + final boolean isPBuffer; + final boolean isFBO; + if(drawable instanceof GLFBODrawableImpl) { + nsViewHandle = 0; + isPBuffer = false; + isFBO = true; + if(DEBUG) { + System.err.println("NS create GLFBODrawableImpl drawable: isFBO "+isFBO+", isPBuffer "+isPBuffer+", "+drawable.getClass().getName()+",\n\t"+drawable); + } + } else if(drawable instanceof MacOSXCGLDrawable) { + // we allow null here! (special pbuffer case) + nsViewHandle = ((MacOSXCGLDrawable)MacOSXCGLContext.this.drawable).getNSViewHandle(); + isPBuffer = CGL.isNSOpenGLPixelBuffer(drawable.getHandle()); + isFBO = false; + if(DEBUG) { + System.err.println("NS create MacOSXCGLDrawable drawable handle isFBO "+isFBO+", isPBuffer "+isPBuffer+", "+drawable.getClass().getName()+",\n\t"+drawable); + } + } else { + // we only allow a valid NSView here + final long drawableHandle = drawable.getHandle(); + final boolean isNSView = OSXUtil.isNSView(drawableHandle); + final boolean isNSWindow = OSXUtil.isNSWindow(drawableHandle); + isPBuffer = CGL.isNSOpenGLPixelBuffer(drawableHandle); + isFBO = false; - if (!chosenCaps.isPBuffer() && !chosenCaps.isBackgroundOpaque()) { - // Set the context opacity - CGL.setContextOpacity(ctx, 0); + if(DEBUG) { + System.err.println("NS create Anonymous drawable handle "+toHexString(drawableHandle)+": isNSView "+isNSView+", isNSWindow "+isNSWindow+", isFBO "+isFBO+", isPBuffer "+isPBuffer+", "+drawable.getClass().getName()+",\n\t"+drawable); + } + if( isNSView ) { + nsViewHandle = drawableHandle; + } else if( isNSWindow ) { + nsViewHandle = OSXUtil.GetNSView(drawableHandle); + } else if( isPBuffer ) { + nsViewHandle = 0; + } else { + throw new RuntimeException("Anonymous drawable instance's handle neither NSView, NSWindow nor PBuffer: "+toHexString(drawableHandle)+", "+drawable.getClass().getName()+",\n\t"+drawable); + } } + backingLayerHost = NativeWindowFactory.getOffscreenLayerSurface(surface, true); + boolean allowIncompleteView = null != backingLayerHost; + if( !allowIncompleteView && surface instanceof ProxySurface ) { + allowIncompleteView = ((ProxySurface)surface).containsUpstreamOptionBits( ProxySurface.OPT_UPSTREAM_WINDOW_INVISIBLE ); + } + long pixelFormat = MacOSXCGLGraphicsConfiguration.GLCapabilities2NSPixelFormat(chosenCaps, ctp, major, minor); + if (pixelFormat == 0) { + if(DEBUG) { + System.err.println("Unable to allocate pixel format with requested GLCapabilities: "+chosenCaps); + } + return 0; + } GLCapabilities fixedCaps = MacOSXCGLGraphicsConfiguration.NSPixelFormat2GLCapabilities(chosenCaps.getGLProfile(), pixelFormat); - fixedCaps = GLGraphicsConfigurationUtil.fixOpaqueGLCapabilities(fixedCaps, chosenCaps.isBackgroundOpaque()); - if(!fixedCaps.isPBuffer()) { + if(chosenCaps.isOnscreen() || !fixedCaps.isPBuffer()) { // not handled, so copy them fixedCaps.setFBO(chosenCaps.isFBO()); + fixedCaps.setPBuffer(chosenCaps.isPBuffer()); fixedCaps.setBitmap(chosenCaps.isBitmap()); fixedCaps.setOnscreen(chosenCaps.isOnscreen()); } - config.setChosenCapabilities(fixedCaps); + fixedCaps = GLGraphicsConfigurationUtil.fixOpaqueGLCapabilities(fixedCaps, chosenCaps.isBackgroundOpaque()); + int sRefreshRate = OSXUtil.GetScreenRefreshRate(drawable.getNativeSurface().getGraphicsConfiguration().getScreen().getIndex()); + screenVSyncTimeout = 1000000f / sRefreshRate; if(DEBUG) { + System.err.println("NS create OSX>=lion "+isLionOrLater); + 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 drawable type: "+drawable.getClass().getName()); + System.err.println("NS create drawable handle: isPBuffer "+isPBuffer+", isFBO "+isFBO); + System.err.println("NS create pixelFormat: "+toHexString(pixelFormat)); + System.err.println("NS create chosenCaps: "+chosenCaps); System.err.println("NS create fixedCaps: "+fixedCaps); + System.err.println("NS create drawable native-handle: "+toHexString(drawable.getHandle())); + System.err.println("NS create drawable NSView-handle: "+toHexString(nsViewHandle)); + System.err.println("NS create screen refresh-rate: "+sRefreshRate+" hz, "+screenVSyncTimeout+" micros"); + // Thread.dumpStack(); } if(fixedCaps.isPBuffer()) { - // Must now associate the pbuffer with our newly-created context - CGL.setContextPBuffer(ctx, drawable.getHandle()); + if(!isPBuffer) { + throw new InternalError("fixedCaps is PBuffer, handle not: "+drawable); + } + } else { + if(isPBuffer) { + throw new InternalError("handle is PBuffer, fixedCaps not: "+drawable); + } } - // - // handled layered surface - // + config.setChosenCapabilities(fixedCaps); + /** if(null != backingLayerHost) { - nsOpenGLLayerPFmt = pixelFormat; - pixelFormat = 0; - final int texWidth, texHeight; - if(drawable instanceof MacOSXPbufferCGLDrawable) { - final MacOSXPbufferCGLDrawable osxPDrawable = (MacOSXPbufferCGLDrawable)drawable; - texWidth = osxPDrawable.getTextureWidth(); - texHeight = osxPDrawable.getTextureHeight(); - } else { - texWidth = drawable.getWidth(); - texHeight = drawable.getHeight(); + backingLayerHost.setChosenCapabilities(fixedCaps); + } */ + + try { + int[] viewNotReady = new int[1]; + // Try to allocate a context with this + ctx = CGL.createContext(share, + nsViewHandle, allowIncompleteView, + pixelFormat, + chosenCaps.isBackgroundOpaque(), + viewNotReady, 0); + if (0 == ctx) { + if(DEBUG) { + System.err.println("NS create failed: viewNotReady: "+ (1 == viewNotReady[0])); + } + return 0; } - if(0>=texWidth || 0>=texHeight || !drawable.isRealized()) { - throw new GLException("Drawable not realized yet or invalid texture size, texSize "+texWidth+"x"+texHeight+", "+drawable); + + if(null != backingLayerHost) { + nsOpenGLLayerPFmt = pixelFormat; + pixelFormat = 0; } - 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); + + if (chosenCaps.isOnscreen() && !chosenCaps.isBackgroundOpaque()) { + // Set the context opacity + CGL.setContextOpacity(ctx, 0); + } + } finally { + if(0!=pixelFormat) { + CGL.deletePixelFormat(pixelFormat); + pixelFormat = 0; } - backingLayerHost.attachSurfaceLayer(nsOpenGLLayer); - setSwapInterval(1); // enabled per default in layered surface - } - } finally { - if(0!=pixelFormat) { - CGL.deletePixelFormat(pixelFormat); - } - } - return ctx; - } - - @Override - public boolean destroy(long ctx) { - if(0 != nsOpenGLLayer) { - final NativeSurface surface = drawable.getNativeSurface(); - if (DEBUG) { - System.err.println("NS destroy nsOpenGLLayer "+toHexString(nsOpenGLLayer)); - } - final OffscreenLayerSurface ols = NativeWindowFactory.getOffscreenLayerSurface(surface, true); - if(null != ols && ols.isSurfaceLayerAttached()) { - // still having a valid OLS attached to surface (parent OLS could have been removed) - ols.detachSurfaceLayer(); } - CGL.releaseNSOpenGLLayer(nsOpenGLLayer); - CGL.deletePixelFormat(nsOpenGLLayerPFmt); - nsOpenGLLayerPFmt = 0; - nsOpenGLLayer = 0; + return ctx; } - return CGL.deleteContext(ctx, true); - } - - @Override - public boolean copyImpl(long src, int mask) { - CGL.copyContext(contextHandle, src, mask); - return true; - } - @Override - public boolean makeCurrent(long ctx) { - final long cglCtx = CGL.getCGLContext(ctx); - if(0 == cglCtx) { - throw new InternalError("Null CGLContext for: "+this); + @Override + public boolean destroy(long ctx) { + lastPBufferHandle = 0; + return CGL.deleteContext(ctx, true); } - int err = CGL.CGLLockContext(cglCtx); - if(CGL.kCGLNoError == err) { - return CGL.makeCurrentContext(ctx); - } else if(DEBUG) { - System.err.println("NSGL: Could not lock context: err 0x"+Integer.toHexString(err)+": "+this); + + @Override + public boolean contextRealized(boolean realized) { + if( realized ) { + if( null != backingLayerHost ) { + // + // handled layered surface + // + final GLCapabilitiesImmutable chosenCaps = drawable.getChosenGLCapabilities(); + final long ctx = MacOSXCGLContext.this.getHandle(); + final int texID; + final long drawableHandle = drawable.getHandle(); + if(drawable instanceof GLFBODrawableImpl) { + final GLFBODrawableImpl fbod = (GLFBODrawableImpl)drawable; + texID = fbod.getTextureBuffer(GL.GL_FRONT).getName(); + fbod.setSwapBufferContext(new GLFBODrawableImpl.SwapBufferContext() { + public void swapBuffers(boolean doubleBuffered) { + MacOSXCGLContext.NSOpenGLImpl.this.swapBuffers(); + } } ) ; + lastPBufferHandle = 0; + } else if( chosenCaps.isPBuffer() && CGL.isNSOpenGLPixelBuffer(drawableHandle) ) { + texID = 0; + lastPBufferHandle = drawableHandle; + } else { + throw new GLException("BackingLayerHost w/ unknown handle (!FBO, !PBuffer): "+drawable); + } + lastWidth = drawable.getWidth(); + lastHeight = drawable.getHeight(); + if(0>=lastWidth || 0>=lastHeight || !drawable.isRealized()) { + throw new GLException("Drawable not realized yet or invalid texture size, texSize "+lastWidth+"x"+lastHeight+", "+drawable); + } + nsOpenGLLayer = CGL.createNSOpenGLLayer(ctx, nsOpenGLLayerPFmt, lastPBufferHandle, texID, chosenCaps.isBackgroundOpaque(), lastWidth, lastHeight); + if (DEBUG) { + System.err.println("NS create nsOpenGLLayer "+toHexString(nsOpenGLLayer)+" w/ pbuffer "+toHexString(lastPBufferHandle)+", texID "+texID+", texSize "+lastWidth+"x"+lastHeight+", "+drawable); + } + backingLayerHost.attachSurfaceLayer(nsOpenGLLayer); + setSwapInterval(1); // enabled per default in layered surface + } else { + lastWidth = drawable.getWidth(); + lastHeight = drawable.getHeight(); + } + } else { + if( 0 != nsOpenGLLayer ) { + final NativeSurface surface = drawable.getNativeSurface(); + if (DEBUG) { + System.err.println("NS destroy nsOpenGLLayer "+toHexString(nsOpenGLLayer)+", "+drawable); + } + final OffscreenLayerSurface ols = NativeWindowFactory.getOffscreenLayerSurface(surface, true); + if(null != ols && ols.isSurfaceLayerAttached()) { + // still having a valid OLS attached to surface (parent OLS could have been removed) + ols.detachSurfaceLayer(); + } + CGL.releaseNSOpenGLLayer(nsOpenGLLayer); + nsOpenGLLayer = 0; + } + if(0 != nsOpenGLLayerPFmt) { + CGL.deletePixelFormat(nsOpenGLLayerPFmt); + nsOpenGLLayerPFmt = 0; + } + lastPBufferHandle = 0; + } + backingLayerHost = null; + return true; } - return false; - } - @Override - public boolean release(long ctx) { - try { - gl.glFlush(); // w/o glFlush()/glFinish() OSX < 10.7 (NVidia driver) may freeze - } catch (GLException gle) { - if(DEBUG) { - System.err.println("MacOSXCGLContext.NSOpenGLImpl.release: INFO: glFlush() catched exception:"); - gle.printStackTrace(); + private final void validatePBufferConfig(long ctx) { + final GLCapabilitiesImmutable chosenCaps = drawable.getChosenGLCapabilities(); + final long drawableHandle = drawable.getHandle(); + if(chosenCaps.isPBuffer() && CGL.isNSOpenGLPixelBuffer(drawableHandle) && lastPBufferHandle != drawableHandle) { + // Must associate the pbuffer with our newly-created context + lastPBufferHandle = drawableHandle; + if(0 != drawableHandle) { + CGL.setContextPBuffer(ctx, drawableHandle); + } + if(DEBUG) { + System.err.println("NS.validateDrawableConfig bind pbuffer "+toHexString(drawableHandle)+" -> ctx "+toHexString(ctx)); + } } } - final boolean res = CGL.clearCurrentContext(ctx); - final long cglCtx = CGL.getCGLContext(ctx); - if(0 == cglCtx) { - throw new InternalError("Null CGLContext for: "+this); + + /** Returns true if size has been updated, otherwise false (same size). */ + private final boolean validateDrawableSizeConfig(long ctx) { + final int width = drawable.getWidth(); + final int height = drawable.getHeight(); + if( lastWidth != width || lastHeight != height ) { + lastWidth = drawable.getWidth(); + lastHeight = drawable.getHeight(); + if(DEBUG) { + System.err.println("NS.validateDrawableConfig size changed"); + } + return true; + } + return false; } - final int err = CGL.CGLUnlockContext(cglCtx); - if(DEBUG && CGL.kCGLNoError != err) { - System.err.println("CGL: Could not unlock context: err 0x"+Integer.toHexString(err)+": "+this); + + @Override + public boolean copyImpl(long src, int mask) { + CGL.copyContext(contextHandle, src, mask); + return true; } - return res && CGL.kCGLNoError == err; - } - @Override - public boolean setSwapInterval(int interval) { - if(0 != nsOpenGLLayer) { - CGL.setNSOpenGLLayerSwapInterval(nsOpenGLLayer, interval); - vsyncTimeout = interval * (int)screenVSyncTimeout; - if(DEBUG) { System.err.println("NS setSwapInterval: "+vsyncTimeout+" micros"); } + @Override + public boolean makeCurrent(long ctx) { + final long cglCtx = CGL.getCGLContext(ctx); + if(0 == cglCtx) { + throw new InternalError("Null CGLContext for: "+this); + } + int err = CGL.CGLLockContext(cglCtx); + if(CGL.kCGLNoError == err) { + validatePBufferConfig(ctx); // required to handle pbuffer change ASAP + return CGL.makeCurrentContext(ctx); + } else if(DEBUG) { + System.err.println("NSGL: Could not lock context: err 0x"+Integer.toHexString(err)+": "+this); + } + return false; + } + + @Override + public boolean release(long ctx) { + try { + gl.glFlush(); // w/o glFlush()/glFinish() OSX < 10.7 (NVidia driver) may freeze + } catch (GLException gle) { + if(DEBUG) { + System.err.println("MacOSXCGLContext.NSOpenGLImpl.release: INFO: glFlush() catched exception:"); + gle.printStackTrace(); + } + } + final boolean res = CGL.clearCurrentContext(ctx); + final long cglCtx = CGL.getCGLContext(ctx); + if(0 == cglCtx) { + throw new InternalError("Null CGLContext for: "+this); + } + final int err = CGL.CGLUnlockContext(cglCtx); + if(DEBUG && CGL.kCGLNoError != err) { + System.err.println("CGL: Could not unlock context: err 0x"+Integer.toHexString(err)+": "+this); + } + return res && CGL.kCGLNoError == err; } - CGL.setSwapInterval(contextHandle, interval); - return true; - } - @Override - public boolean swapBuffers() { - if( 0 != nsOpenGLLayer ) { - // If v-sync is disabled, frames will be drawn as quickly as possible - // w/o delay but in sync w/ CALayer. Otherwise wait until next swap interval (v-sync). - CGL.waitUntilNSOpenGLLayerIsReady(nsOpenGLLayer, vsyncTimeout); + @Override + public boolean detachPBuffer() { + if(0 != lastPBufferHandle) { + lastPBufferHandle = 0; + if(0 != nsOpenGLLayer) { + CGL.flushNSOpenGLLayerPBuffer(nsOpenGLLayer); // notify invalid pbuffer + } + // CGL.setContextPBuffer(contextHandle, 0); // doesn't work, i.e. not taking nil + } + return true; } - if(CGL.flushBuffer(contextHandle)) { + + @Override + public boolean setSwapInterval(int interval) { if(0 != nsOpenGLLayer) { - // trigger CALayer to update - CGL.setNSOpenGLLayerNeedsDisplay(nsOpenGLLayer); + CGL.setNSOpenGLLayerSwapInterval(nsOpenGLLayer, interval); + vsyncTimeout = interval * (int)screenVSyncTimeout + 1000; // +1ms + if(DEBUG) { System.err.println("NS setSwapInterval: "+vsyncTimeout+" micros"); } } + CGL.setSwapInterval(contextHandle, interval); return true; } - return false; - } + + private int skipSync=0; + + @Override + public boolean swapBuffers() { + final boolean res; + if( 0 != nsOpenGLLayer ) { + if( validateDrawableSizeConfig(contextHandle) ) { + // skip wait-for-vsync for a few frames if size has changed, + // allowing to update the texture IDs ASAP. + skipSync = 10; + } + + final int texID; + final boolean valid; + if(drawable instanceof GLFBODrawableImpl) { + texID = ((GLFBODrawableImpl)drawable).getTextureBuffer(GL.GL_FRONT).getName(); + valid = 0 != texID; + } else { + texID = 0; + valid = 0 != lastPBufferHandle; + } + if(valid) { + if(0 == skipSync) { + // If v-sync is disabled, frames will be drawn as quickly as possible + // w/o delay but in sync w/ CALayer. Otherwise wait until next swap interval (v-sync). + CGL.waitUntilNSOpenGLLayerIsReady(nsOpenGLLayer, vsyncTimeout); + } else { + skipSync--; + } + res = CGL.flushBuffer(contextHandle); + if(res) { + // trigger CALayer to update incl. possible surface change + CGL.setNSOpenGLLayerNeedsDisplay(nsOpenGLLayer, lastPBufferHandle, texID, lastWidth, lastHeight); + } + } else { + res = true; + } + } else { + res = CGL.flushBuffer(contextHandle); + } + return res; + } + } class CGLImpl implements GLBackendImpl { - @Override - public boolean isNSContext() { return false; } - - @Override - public long create(long share, int ctp, int major, int minor) { - long ctx = 0; - MacOSXCGLGraphicsConfiguration config = (MacOSXCGLGraphicsConfiguration) drawable.getNativeSurface().getGraphicsConfiguration(); - GLCapabilitiesImmutable chosenCaps = (GLCapabilitiesImmutable)config.getChosenCapabilities(); - long pixelFormat = MacOSXCGLGraphicsConfiguration.GLCapabilities2CGLPixelFormat(chosenCaps, ctp, major, minor); - if (pixelFormat == 0) { - throw new GLException("Unable to allocate pixel format with requested GLCapabilities"); - } - config.setChosenPixelFormat(pixelFormat); - try { - // Create new context - PointerBuffer ctxPB = PointerBuffer.allocateDirect(1); - if (DEBUG) { - System.err.println("Share context for CGL-based pbuffer context is " + toHexString(share)); + @Override + public boolean isNSContext() { return false; } + + @Override + public long create(long share, int ctp, int major, int minor) { + long ctx = 0; + MacOSXCGLGraphicsConfiguration config = (MacOSXCGLGraphicsConfiguration) drawable.getNativeSurface().getGraphicsConfiguration(); + GLCapabilitiesImmutable chosenCaps = (GLCapabilitiesImmutable)config.getChosenCapabilities(); + long pixelFormat = MacOSXCGLGraphicsConfiguration.GLCapabilities2CGLPixelFormat(chosenCaps, ctp, major, minor); + if (pixelFormat == 0) { + throw new GLException("Unable to allocate pixel format with requested GLCapabilities"); } - int res = CGL.CGLCreateContext(pixelFormat, share, ctxPB); - if (res != CGL.kCGLNoError) { - throw new GLException("Error code " + res + " while creating context"); - } - if(chosenCaps.isPBuffer()) { - // Attach newly-created context to the pbuffer - res = CGL.CGLSetPBuffer(ctxPB.get(0), drawable.getHandle(), 0, 0, 0); + try { + // Create new context + PointerBuffer ctxPB = PointerBuffer.allocateDirect(1); + if (DEBUG) { + System.err.println("Share context for CGL-based pbuffer context is " + toHexString(share)); + } + int res = CGL.CGLCreateContext(pixelFormat, share, ctxPB); if (res != CGL.kCGLNoError) { - throw new GLException("Error code " + res + " while attaching context to pbuffer"); + throw new GLException("Error code " + res + " while creating context"); } - } - ctx = ctxPB.get(0); - if(0!=ctx) { - if(DEBUG) { - GLCapabilitiesImmutable caps0 = MacOSXCGLGraphicsConfiguration.CGLPixelFormat2GLCapabilities(pixelFormat); - System.err.println("NS created: "+caps0); + ctx = ctxPB.get(0); + + if (0 != ctx) { + GLCapabilities fixedCaps = MacOSXCGLGraphicsConfiguration.CGLPixelFormat2GLCapabilities(pixelFormat); + fixedCaps = GLGraphicsConfigurationUtil.fixOpaqueGLCapabilities(fixedCaps, chosenCaps.isBackgroundOpaque()); + if(chosenCaps.isOnscreen() || !fixedCaps.isPBuffer()) { + // not handled, so copy them + fixedCaps.setFBO(chosenCaps.isFBO()); + fixedCaps.setPBuffer(chosenCaps.isPBuffer()); + fixedCaps.setBitmap(chosenCaps.isBitmap()); + fixedCaps.setOnscreen(chosenCaps.isOnscreen()); + } + config.setChosenCapabilities(fixedCaps); + if(DEBUG) { + System.err.println("CGL create fixedCaps: "+fixedCaps); + } + if(fixedCaps.isPBuffer()) { + // Must now associate the pbuffer with our newly-created context + res = CGL.CGLSetPBuffer(ctx, drawable.getHandle(), 0, 0, 0); + if (res != CGL.kCGLNoError) { + throw new GLException("Error code " + res + " while attaching context to pbuffer"); + } + } } + } finally { + CGL.CGLDestroyPixelFormat(pixelFormat); } - } finally { - CGL.CGLDestroyPixelFormat(pixelFormat); + return ctx; } - return ctx; - } - @Override - public boolean destroy(long ctx) { - return CGL.CGLDestroyContext(ctx) == CGL.kCGLNoError; - } + @Override + public boolean destroy(long ctx) { + return CGL.CGLDestroyContext(ctx) == CGL.kCGLNoError; + } - @Override - public boolean copyImpl(long src, int mask) { - CGL.CGLCopyContext(src, contextHandle, mask); - return true; - } + @Override + public boolean contextRealized(boolean realized) { + return true; + } + + @Override + public boolean copyImpl(long src, int mask) { + CGL.CGLCopyContext(src, contextHandle, mask); + return true; + } - @Override - public boolean makeCurrent(long ctx) { - int err = CGL.CGLLockContext(ctx); - if(CGL.kCGLNoError == err) { - err = CGL.CGLSetCurrentContext(ctx); + @Override + public boolean makeCurrent(long ctx) { + int err = CGL.CGLLockContext(ctx); if(CGL.kCGLNoError == err) { - return true; + err = CGL.CGLSetCurrentContext(ctx); + if(CGL.kCGLNoError == err) { + return true; + } else if(DEBUG) { + System.err.println("CGL: Could not make context current: err 0x"+Integer.toHexString(err)+": "+this); + } } else if(DEBUG) { - System.err.println("CGL: Could not make context current: err 0x"+Integer.toHexString(err)+": "+this); + System.err.println("CGL: Could not lock context: err 0x"+Integer.toHexString(err)+": "+this); } - } else if(DEBUG) { - System.err.println("CGL: Could not lock context: err 0x"+Integer.toHexString(err)+": "+this); + return false; } - return false; - } - @Override - public boolean release(long ctx) { - try { - gl.glFlush(); // w/o glFlush()/glFinish() OSX < 10.7 (NVidia driver) may freeze - } catch (GLException gle) { - if(DEBUG) { - System.err.println("MacOSXCGLContext.CGLImpl.release: INFO: glFlush() catched exception:"); - gle.printStackTrace(); + @Override + public boolean release(long ctx) { + try { + gl.glFlush(); // w/o glFlush()/glFinish() OSX < 10.7 (NVidia driver) may freeze + } catch (GLException gle) { + if(DEBUG) { + System.err.println("MacOSXCGLContext.CGLImpl.release: INFO: glFlush() catched exception:"); + gle.printStackTrace(); + } } + int err = CGL.CGLSetCurrentContext(0); + if(DEBUG && CGL.kCGLNoError != err) { + System.err.println("CGL: Could not release current context: err 0x"+Integer.toHexString(err)+": "+this); + } + int err2 = CGL.CGLUnlockContext(ctx); + if(DEBUG && CGL.kCGLNoError != err2) { + System.err.println("CGL: Could not unlock context: err 0x"+Integer.toHexString(err2)+": "+this); + } + return CGL.kCGLNoError == err && CGL.kCGLNoError == err2; + } + + @Override + public boolean detachPBuffer() { + /* Doesn't work, i.e. not taking NULL + final int res = CGL.CGLSetPBuffer(contextHandle, 0, 0, 0, 0); + if (res != CGL.kCGLNoError) { + throw new GLException("Error code " + res + " while detaching context from pbuffer"); + } */ + return true; } - int err = CGL.CGLSetCurrentContext(0); - if(DEBUG && CGL.kCGLNoError != err) { - System.err.println("CGL: Could not release current context: err 0x"+Integer.toHexString(err)+": "+this); + + @Override + public boolean setSwapInterval(int interval) { + int[] lval = new int[] { interval } ; + CGL.CGLSetParameter(contextHandle, CGL.kCGLCPSwapInterval, lval, 0); + return true; } - int err2 = CGL.CGLUnlockContext(ctx); - if(DEBUG && CGL.kCGLNoError != err2) { - System.err.println("CGL: Could not unlock context: err 0x"+Integer.toHexString(err2)+": "+this); + @Override + public boolean swapBuffers() { + return CGL.kCGLNoError == CGL.CGLFlushDrawable(contextHandle); } - return CGL.kCGLNoError == err && CGL.kCGLNoError == err2; - } - - @Override - public boolean setSwapInterval(int interval) { - int[] lval = new int[] { interval } ; - CGL.CGLSetParameter(contextHandle, CGL.kCGLCPSwapInterval, lval, 0); - return true; - } - @Override - public boolean swapBuffers() { - return CGL.kCGLNoError == CGL.CGLFlushDrawable(contextHandle); - } } } diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawable.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawable.java index af767f0c3..cc727c8e1 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawable.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawable.java @@ -42,10 +42,10 @@ package jogamp.opengl.macosx.cgl; import java.lang.ref.WeakReference; import java.util.ArrayList; -import java.util.Iterator; import java.util.List; import javax.media.nativewindow.NativeSurface; +import javax.media.opengl.GLContext; import javax.media.opengl.GLDrawableFactory; import javax.media.opengl.GLException; @@ -92,7 +92,7 @@ public abstract class MacOSXCGLDrawable extends GLDrawableImpl { this.id = id; } } - private List> createdContexts = new ArrayList>(); + /* pp */ List> createdContexts = new ArrayList>(); private boolean haveSetOpenGLMode = false; private GLBackendType openGLMode = GLBackendType.NSOPENGL; @@ -110,26 +110,42 @@ public abstract class MacOSXCGLDrawable extends GLDrawableImpl { return GLBackendType.NSOPENGL == openGLMode ? getHandle() : 0; } - protected void registerContext(MacOSXCGLContext ctx) { + @Override + protected void associateContext(GLContext ctx, boolean bound) { // NOTE: we need to keep track of the created contexts in order to // implement swapBuffers() because of how Mac OS X implements its // OpenGL window interface synchronized (createdContexts) { - createdContexts.add(new WeakReference(ctx)); - } + if(bound) { + createdContexts.add(new WeakReference((MacOSXCGLContext)ctx)); + } else { + for(int i=0; i ref = createdContexts.get(i); + final MacOSXCGLContext _ctx = ref.get(); + if( _ctx == null || _ctx == ctx) { + createdContexts.remove(i); + } else { + i++; + } + } + } + } } + @Override - protected final void swapBuffersImpl() { - // single-buffer is already filtered out @ GLDrawableImpl#swapBuffers() - synchronized (createdContexts) { - for (Iterator> iter = createdContexts.iterator(); iter.hasNext(); ) { - WeakReference ref = iter.next(); - MacOSXCGLContext ctx = ref.get(); - if (ctx != null) { - ctx.swapBuffers(); - } else { - iter.remove(); - } + protected final void swapBuffersImpl(boolean doubleBuffered) { + if(doubleBuffered) { + synchronized (createdContexts) { + for(int i=0; i ref = createdContexts.get(i); + final MacOSXCGLContext ctx = ref.get(); + if (ctx != null) { + ctx.swapBuffers(); + i++; + } else { + createdContexts.remove(i); + } + } } } } diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java index 591fafc68..e174d38f4 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawableFactory.java @@ -51,7 +51,7 @@ import javax.media.nativewindow.AbstractGraphicsScreen; import javax.media.nativewindow.DefaultGraphicsScreen; import javax.media.nativewindow.NativeSurface; import javax.media.nativewindow.ProxySurface; -import javax.media.nativewindow.ProxySurface.UpstreamSurfaceHook; +import javax.media.nativewindow.UpstreamSurfaceHook; import javax.media.opengl.GL; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLCapabilitiesChooser; @@ -61,7 +61,8 @@ import javax.media.opengl.GLDrawable; import javax.media.opengl.GLException; import javax.media.opengl.GLProfile; -import jogamp.nativewindow.macosx.OSXUtil; +import jogamp.nativewindow.WrappedSurface; +import jogamp.nativewindow.macosx.OSXDummyUpstreamSurfaceHook; import jogamp.opengl.DesktopGLDynamicLookupHelper; import jogamp.opengl.GLContextImpl; import jogamp.opengl.GLDrawableFactoryImpl; @@ -71,7 +72,7 @@ import jogamp.opengl.GLGraphicsConfigurationUtil; import com.jogamp.common.JogampRuntimeException; import com.jogamp.common.util.ReflectionUtil; -import com.jogamp.nativewindow.WrappedSurface; +import com.jogamp.nativewindow.MutableGraphicsConfiguration; import com.jogamp.nativewindow.macosx.MacOSXGraphicsDevice; import com.jogamp.opengl.GLExtensions; @@ -320,9 +321,14 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl { @Override protected GLDrawableImpl createOffscreenDrawableImpl(NativeSurface target) { - AbstractGraphicsConfiguration config = target.getGraphicsConfiguration(); - GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) config.getChosenCapabilities(); + final MutableGraphicsConfiguration config = (MutableGraphicsConfiguration) target.getGraphicsConfiguration(); + final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) config.getChosenCapabilities(); if(!caps.isPBuffer()) { + // Actual implementation is using PBuffer ... + final GLCapabilities modCaps = (GLCapabilities) caps.cloneMutable(); + modCaps.setPBuffer(true); + modCaps.setBitmap(false); + config.setChosenCapabilities(modCaps); return new MacOSXOffscreenCGLDrawable(this, target); } return new MacOSXPbufferCGLDrawable(this, target); @@ -336,7 +342,7 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl { @Override protected ProxySurface createMutableSurfaceImpl(AbstractGraphicsDevice deviceReq, boolean createNewDevice, GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsRequested, - GLCapabilitiesChooser chooser, int width, int height, UpstreamSurfaceHook lifecycleHook) { + GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstreamHook) { final MacOSXGraphicsDevice device; if(createNewDevice) { device = new MacOSXGraphicsDevice(deviceReq.getUnitID()); @@ -348,68 +354,23 @@ public class MacOSXCGLDrawableFactory extends GLDrawableFactoryImpl { if(null == config) { throw new GLException("Choosing GraphicsConfiguration failed w/ "+capsChosen+" on "+screen); } - return new WrappedSurface(config, 0, width, height, lifecycleHook); + return new WrappedSurface(config, 0, upstreamHook, createNewDevice); } @Override 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); + return createMutableSurfaceImpl(deviceReq, createNewDevice, chosenCaps, requestedCaps, chooser, + new OSXDummyUpstreamSurfaceHook(width, height)); } - 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); + return new WrappedSurface(config, windowHandle, upstream, true); } @Override diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfiguration.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfiguration.java index 149927160..8866c7ce6 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfiguration.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfiguration.java @@ -51,23 +51,16 @@ import com.jogamp.common.nio.PointerBuffer; import com.jogamp.nativewindow.MutableGraphicsConfiguration; public class MacOSXCGLGraphicsConfiguration extends MutableGraphicsConfiguration implements Cloneable { - long pixelformat; MacOSXCGLGraphicsConfiguration(AbstractGraphicsScreen screen, - GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsRequested, - long pixelformat) { + GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsRequested) { super(screen, capsChosen, capsRequested); - this.pixelformat=pixelformat; } public Object clone() { return super.clone(); } - void setChosenPixelFormat(long pixelformat) { - this.pixelformat=pixelformat; - } - protected static List getAvailableCapabilities(MacOSXCGLDrawableFactory factory, AbstractGraphicsDevice device) { MacOSXCGLDrawableFactory.SharedResource sharedResource = factory.getOrCreateOSXSharedResource(device); if(null == sharedResource) { @@ -114,11 +107,11 @@ public class MacOSXCGLGraphicsConfiguration extends MutableGraphicsConfiguration break; case CGL.kCGLPFAColorFloat: - ivalues[idx] = caps.getPbufferFloatingPointBuffers() ? 1 : 0; + ivalues[idx] = ( !caps.isOnscreen() && caps.isPBuffer() && caps.getPbufferFloatingPointBuffers() ) ? 1 : 0; break; case CGL.NSOpenGLPFAPixelBuffer: - ivalues[idx] = caps.isPBuffer() ? 1 : 0; + ivalues[idx] = ( !caps.isOnscreen() && caps.isPBuffer() ) ? 1 : 0; break; case CGL.NSOpenGLPFADoubleBuffer: @@ -188,11 +181,11 @@ public class MacOSXCGLGraphicsConfiguration extends MutableGraphicsConfiguration attrs[i++] = CGL.kCGLPFAOpenGLProfile; attrs[i++] = MacOSXCGLContext.GLProfile2CGLOGLProfileValue(ctp, major, minor); } - if(caps.isPBuffer()) { + if(!caps.isOnscreen() && caps.isPBuffer()) { attrs[i++] = CGL.kCGLPFAPBuffer; - } - if (caps.getPbufferFloatingPointBuffers()) { - attrs[i++] = CGL.kCGLPFAColorFloat; + if (caps.getPbufferFloatingPointBuffers()) { + attrs[i++] = CGL.kCGLPFAColorFloat; + } } if (caps.getDoubleBuffered()) { attrs[i++] = CGL.kCGLPFADoubleBuffer; diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfigurationFactory.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfigurationFactory.java index 13faf7090..43a9d0d1a 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfigurationFactory.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLGraphicsConfigurationFactory.java @@ -96,6 +96,6 @@ public class MacOSXCGLGraphicsConfigurationFactory extends GLGraphicsConfigurati capsChosen = GLGraphicsConfigurationUtil.fixGLCapabilities( capsChosen, GLContext.isFBOAvailable(device, capsChosen.getGLProfile()), factory.canCreateGLPbuffer(device) ); - return new MacOSXCGLGraphicsConfiguration(absScreen, (GLCapabilitiesImmutable)capsChosen, (GLCapabilitiesImmutable)capsRequested, 0); + return new MacOSXCGLGraphicsConfiguration(absScreen, (GLCapabilitiesImmutable)capsChosen, (GLCapabilitiesImmutable)capsRequested); } } diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java index 6be9e386d..65ed5fc15 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java @@ -49,8 +49,8 @@ import javax.media.opengl.GLContext; import javax.media.opengl.GLDrawableFactory; import javax.media.opengl.GLException; -import com.jogamp.nativewindow.WrappedSurface; +import jogamp.nativewindow.WrappedSurface; import jogamp.opengl.GLContextImpl; import jogamp.opengl.GLContextShareSet; import jogamp.opengl.macosx.cgl.MacOSXCGLDrawable.GLBackendType; @@ -62,7 +62,6 @@ public class MacOSXExternalCGLContext extends MacOSXCGLContext { private MacOSXExternalCGLContext(Drawable drawable, boolean isNSContext, long handle) { super(drawable, null); setOpenGLMode(isNSContext ? GLBackendType.NSOPENGL : GLBackendType.CGL ); - drawable.registerContext(this); this.contextHandle = handle; GLContextShareSet.contextCreated(this); setGLFunctionAvailability(false, 0, 0, CTX_PROFILE_COMPAT); @@ -108,13 +107,13 @@ public class MacOSXExternalCGLContext extends MacOSXCGLContext { } AbstractGraphicsScreen aScreen = DefaultGraphicsScreen.createDefault(NativeWindowFactory.TYPE_MACOSX); - MacOSXCGLGraphicsConfiguration cfg = new MacOSXCGLGraphicsConfiguration(aScreen, caps, caps, pixelFormat); + MacOSXCGLGraphicsConfiguration cfg = new MacOSXCGLGraphicsConfiguration(aScreen, caps, caps); if(0 == currentDrawable) { // set a fake marker stating a valid drawable currentDrawable = 1; } - WrappedSurface ns = new WrappedSurface(cfg, currentDrawable, 64, 64, null); + WrappedSurface ns = new WrappedSurface(cfg, currentDrawable, 64, 64, true); return new MacOSXExternalCGLContext(new Drawable(factory, ns), isNSContext, contextHandle); } diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOnscreenCGLDrawable.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOnscreenCGLDrawable.java index b1e283ebc..ec9628004 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOnscreenCGLDrawable.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOnscreenCGLDrawable.java @@ -52,9 +52,7 @@ public class MacOSXOnscreenCGLDrawable extends MacOSXCGLDrawable { @Override public GLContext createContext(GLContext shareWith) { - final MacOSXOnscreenCGLContext ctx= new MacOSXOnscreenCGLContext(this, shareWith); - registerContext(ctx); - return ctx; + return new MacOSXOnscreenCGLContext(this, shareWith); } } diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLContext.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLContext.java index 88886ddd2..7e2d8cf10 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLContext.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLContext.java @@ -39,6 +39,7 @@ import javax.media.opengl.GLPbuffer; import jogamp.opengl.GLContextImpl; +@SuppressWarnings("deprecation") public class MacOSXPbufferCGLContext extends MacOSXCGLContext { // State for render-to-texture and render-to-texture-rectangle support diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLDrawable.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLDrawable.java index 8f2f386af..668e463a2 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLDrawable.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLDrawable.java @@ -40,6 +40,8 @@ package jogamp.opengl.macosx.cgl; +import java.lang.ref.WeakReference; + import javax.media.nativewindow.DefaultGraphicsConfiguration; import javax.media.nativewindow.NativeSurface; import javax.media.nativewindow.MutableSurface; @@ -70,9 +72,6 @@ public class MacOSXPbufferCGLDrawable extends MacOSXCGLDrawable { // private int textureTarget; // e.g. GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE_NV // private int texture; // actual texture object - // Note that we can not store this in the NativeSurface because the - // semantic is that contains an NSView - protected long pBuffer; protected int pBufferTexTarget, pBufferTexWidth, pBufferTexHeight; public MacOSXPbufferCGLDrawable(GLDrawableFactory factory, NativeSurface target) { @@ -90,9 +89,7 @@ public class MacOSXPbufferCGLDrawable extends MacOSXCGLDrawable { @Override public GLContext createContext(GLContext shareWith) { - final MacOSXPbufferCGLContext ctx = new MacOSXPbufferCGLContext(this, shareWith); - registerContext(ctx); - return ctx; + return new MacOSXPbufferCGLContext(this, shareWith); } @Override @@ -101,27 +98,34 @@ public class MacOSXPbufferCGLDrawable extends MacOSXCGLDrawable { return 0; } - @Override - public long getHandle() { - return pBuffer; - } - protected int getTextureTarget() { return pBufferTexTarget; } protected int getTextureWidth() { return pBufferTexWidth; } protected int getTextureHeight() { return pBufferTexHeight; } protected void destroyPbuffer() { - if (this.pBuffer != 0) { - NativeSurface ns = getNativeSurface(); + final MutableSurface ms = (MutableSurface) getNativeSurface(); + final long pBuffer = ms.getSurfaceHandle(); + if (0 != pBuffer) { + synchronized (createdContexts) { + for(int i=0; i ref = createdContexts.get(i); + final MacOSXCGLContext ctx = ref.get(); + if (ctx != null) { + ctx.detachPBuffer(); + i++; + } else { + createdContexts.remove(i); + } + } + } impl.destroy(pBuffer); - this.pBuffer = 0; - ((MutableSurface)ns).setSurfaceHandle(0); + ms.setSurfaceHandle(0); } } private void createPbuffer() { - final NativeSurface ns = getNativeSurface(); - final DefaultGraphicsConfiguration config = (DefaultGraphicsConfiguration) ns.getGraphicsConfiguration(); + final MutableSurface ms = (MutableSurface) getNativeSurface(); + final DefaultGraphicsConfiguration config = (DefaultGraphicsConfiguration) ms.getGraphicsConfiguration(); final GLCapabilitiesImmutable capabilities = (GLCapabilitiesImmutable)config.getChosenCapabilities(); final GLProfile glProfile = capabilities.getGLProfile(); MacOSXCGLDrawableFactory.SharedResource sr = ((MacOSXCGLDrawableFactory)factory).getOrCreateOSXSharedResource(config.getScreen().getDevice()); @@ -161,7 +165,7 @@ public class MacOSXPbufferCGLDrawable extends MacOSXCGLDrawable { } } - pBuffer = impl.create(pBufferTexTarget, internalFormat, getWidth(), getHeight()); + final long pBuffer = impl.create(pBufferTexTarget, internalFormat, getWidth(), getHeight()); if(DEBUG) { System.err.println("MacOSXPbufferCGLDrawable tex: target "+toHexString(pBufferTexTarget)+ ", pbufferSize "+getWidth()+"x"+getHeight()+ @@ -174,7 +178,7 @@ public class MacOSXPbufferCGLDrawable extends MacOSXCGLDrawable { throw new GLException("pbuffer creation error: CGL.createPBuffer() failed"); } - ((MutableSurface)ns).setSurfaceHandle(pBuffer); + ms.setSurfaceHandle(pBuffer); } @Override diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLContext.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLContext.java index 96c1187d3..f6cc2956d 100644 --- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLContext.java +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLContext.java @@ -50,8 +50,8 @@ import javax.media.opengl.GLDrawableFactory; import javax.media.opengl.GLException; import javax.media.opengl.GLProfile; -import com.jogamp.nativewindow.WrappedSurface; +import jogamp.nativewindow.WrappedSurface; import jogamp.nativewindow.windows.GDI; import jogamp.opengl.GLContextShareSet; @@ -102,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, 64, 64, null)), ctx, cfg); + return new WindowsExternalWGLContext(new Drawable(factory, new WrappedSurface(cfg, hdc, 64, 64, true)), 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 15bd005dc..f8c237c9e 100644 --- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLDrawable.java +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLDrawable.java @@ -49,10 +49,10 @@ import javax.media.opengl.GLDrawableFactory; import javax.media.opengl.GLException; import javax.media.opengl.GLProfile; +import jogamp.nativewindow.WrappedSurface; import jogamp.nativewindow.windows.GDI; import jogamp.nativewindow.windows.GDIUtil; -import com.jogamp.nativewindow.WrappedSurface; public class WindowsExternalWGLDrawable extends WindowsWGLDrawable { @@ -72,7 +72,7 @@ public class WindowsExternalWGLDrawable extends WindowsWGLDrawable { 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)); + return new WindowsExternalWGLDrawable(factory, new WrappedSurface(cfg, hdc, 64, 64, true)); } diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawable.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawable.java index ca7886e7f..3b3f0c123 100644 --- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawable.java +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawable.java @@ -73,27 +73,28 @@ public abstract class WindowsWGLDrawable extends GLDrawableImpl { } @Override - protected final void swapBuffersImpl() { - // single-buffer is already filtered out @ GLDrawableImpl#swapBuffers() - final long t0; - if (PROFILING) { - t0 = System.currentTimeMillis(); - } else { - t0 = 0; - } - - if (!WGLUtil.SwapBuffers(getHandle()) && (GDI.GetLastError() != GDI.ERROR_SUCCESS)) { - throw new GLException("Error swapping buffers"); - } - - if (PROFILING) { - profilingSwapBuffersTime += System.currentTimeMillis() - t0; - if (++profilingSwapBuffersTicks == PROFILING_TICKS) { - System.err.println("SwapBuffers calls: " + profilingSwapBuffersTime + " ms / " + PROFILING_TICKS + " calls (" + - ((float) profilingSwapBuffersTime / (float) PROFILING_TICKS) + " ms/call)"); - profilingSwapBuffersTime = 0; - profilingSwapBuffersTicks = 0; - } + protected final void swapBuffersImpl(boolean doubleBuffered) { + if(doubleBuffered) { + final long t0; + if (PROFILING) { + t0 = System.currentTimeMillis(); + } else { + t0 = 0; + } + + if (!WGLUtil.SwapBuffers(getHandle()) && (GDI.GetLastError() != GDI.ERROR_SUCCESS)) { + throw new GLException("Error swapping buffers"); + } + + if (PROFILING) { + profilingSwapBuffersTime += System.currentTimeMillis() - t0; + if (++profilingSwapBuffersTicks == PROFILING_TICKS) { + System.err.println("SwapBuffers calls: " + profilingSwapBuffersTime + " ms / " + PROFILING_TICKS + " calls (" + + ((float) profilingSwapBuffersTime / (float) PROFILING_TICKS) + " ms/call)"); + profilingSwapBuffersTime = 0; + profilingSwapBuffersTicks = 0; + } + } } } diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java index 7ea487523..91d5c225a 100644 --- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java @@ -52,7 +52,7 @@ import javax.media.nativewindow.AbstractGraphicsScreen; import javax.media.nativewindow.DefaultGraphicsScreen; import javax.media.nativewindow.NativeSurface; import javax.media.nativewindow.ProxySurface; -import javax.media.nativewindow.ProxySurface.UpstreamSurfaceHook; +import javax.media.nativewindow.UpstreamSurfaceHook; import javax.media.opengl.GL; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLCapabilitiesChooser; @@ -62,9 +62,10 @@ import javax.media.opengl.GLDrawable; import javax.media.opengl.GLException; import javax.media.opengl.GLProfile; +import jogamp.nativewindow.WrappedSurface; import jogamp.nativewindow.windows.GDI; +import jogamp.nativewindow.windows.GDIDummyUpstreamSurfaceHook; import jogamp.nativewindow.windows.GDISurface; -import jogamp.nativewindow.windows.GDIUtil; import jogamp.nativewindow.windows.RegisteredClassFactory; import jogamp.opengl.DesktopGLDynamicLookupHelper; import jogamp.opengl.GLContextImpl; @@ -79,7 +80,6 @@ import com.jogamp.common.nio.PointerBuffer; import com.jogamp.common.os.Platform; 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; @@ -541,7 +541,7 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl { @Override protected final ProxySurface createMutableSurfaceImpl(AbstractGraphicsDevice deviceReq, boolean createNewDevice, GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsRequested, - GLCapabilitiesChooser chooser, int width, int height, UpstreamSurfaceHook lifecycleHook) { + GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstreamHook) { final WindowsGraphicsDevice device; if(createNewDevice) { device = new WindowsGraphicsDevice(deviceReq.getConnection(), deviceReq.getUnitID()); @@ -553,7 +553,7 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl { if(null == config) { throw new GLException("Choosing GraphicsConfiguration failed w/ "+capsChosen+" on "+screen); } - return new WrappedSurface(config, 0, width, height, lifecycleHook); + return new WrappedSurface(config, 0, upstreamHook, createNewDevice); } @Override @@ -571,57 +571,15 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl { 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[]"; - } - }; - + return new GDISurface(config, 0, new GDIDummyUpstreamSurfaceHook(width, height), createNewDevice); + } @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); + return new GDISurface(cfg, windowHandle, upstream, true); } @Override diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfiguration.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfiguration.java index 4d1069e6b..058f4e336 100644 --- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfiguration.java +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfiguration.java @@ -107,7 +107,7 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio if(hasARB) { caps = wglARBPFID2GLCapabilities(sharedResource, device, glp, hdc, pfdID, GLGraphicsConfigurationUtil.ALL_BITS); } else { - caps = PFD2GLCapabilities(glp, hdc, pfdID, GLGraphicsConfigurationUtil.ALL_BITS); + caps = PFD2GLCapabilities(device, glp, hdc, pfdID, GLGraphicsConfigurationUtil.ALL_BITS); } if(null==caps) { throw new GLException("Couldn't choose Capabilities by: HDC 0x"+Long.toHexString(hdc)+ @@ -325,7 +325,7 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio throw new GLException("wglARBPFID2GLCapabilities: Error getting pixel format attributes for pixel format " + pfdID + " of device context " + toHexString(hdc) + ", werr " + GDI.GetLastError()); } - return AttribList2GLCapabilities(glp, hdc, pfdID, iattributes, niattribs, iresults, winattrbits); + return AttribList2GLCapabilities(device, glp, hdc, pfdID, iattributes, niattribs, iresults, winattrbits); } static int[] wglChoosePixelFormatARB(WindowsWGLDrawableFactory.SharedResource sharedResource, AbstractGraphicsDevice device, @@ -390,7 +390,7 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio for(int i = 0; i= 1 && ((WindowsWGLContext)sharedResource.getContext()).getWGLExt().wglGetPixelFormatAttribivARB(hdc, pfdIDs[i], 0, niattribs, iattributes, 0, iresults, 0) ) { - final GLCapabilitiesImmutable caps = AttribList2GLCapabilities(glp, hdc, pfdIDs[i], iattributes, niattribs, iresults, winattrbits); + final GLCapabilitiesImmutable caps = AttribList2GLCapabilities(device, glp, hdc, pfdIDs[i], iattributes, niattribs, iresults, winattrbits); if(null != caps) { bucket.add(caps); if(DEBUG) { @@ -398,7 +398,7 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio System.err.println("wglARBPFIDs2GLCapabilities: bucket["+i+" -> "+j+"]: "+caps); } } else if(DEBUG) { - GLCapabilitiesImmutable skipped = AttribList2GLCapabilities(glp, hdc, pfdIDs[i], iattributes, niattribs, iresults, GLGraphicsConfigurationUtil.ALL_BITS); + GLCapabilitiesImmutable skipped = AttribList2GLCapabilities(device, glp, hdc, pfdIDs[i], iattributes, niattribs, iresults, GLGraphicsConfigurationUtil.ALL_BITS); System.err.println("wglARBPFIDs2GLCapabilities: bucket["+i+" -> skip]: pfdID "+pfdIDs[i]+", "+skipped+", winattr "+GLGraphicsConfigurationUtil.winAttributeBits2String(null, winattrbits).toString()); } } else if (DEBUG) { @@ -616,9 +616,9 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio return val; } - static WGLGLCapabilities AttribList2GLCapabilities(final GLProfile glp, - final long hdc, final int pfdID, final int[] iattribs, - final int niattribs, final int[] iresults, final int winattrmask) { + static WGLGLCapabilities AttribList2GLCapabilities(final AbstractGraphicsDevice device, + final GLProfile glp, final long hdc, final int pfdID, + final int[] iattribs, final int niattribs, final int[] iresults, final int winattrmask) { final int allDrawableTypeBits = AttribList2DrawableTypeBits(iattribs, niattribs, iresults); int drawableTypeBits = winattrmask & allDrawableTypeBits; @@ -637,7 +637,7 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio } final WGLGLCapabilities res = new WGLGLCapabilities(pfd, pfdID, glp); res.setValuesByARB(iattribs, niattribs, iresults); - return (WGLGLCapabilities) GLGraphicsConfigurationUtil.setWinAttributeBits(res, drawableTypeBits); + return (WGLGLCapabilities) GLGraphicsConfigurationUtil.fixWinAttribBitsAndHwAccel(device, drawableTypeBits, res); } // @@ -672,7 +672,7 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio return val; } - static WGLGLCapabilities PFD2GLCapabilities(final GLProfile glp, final long hdc, final int pfdID, final int winattrmask) { + static WGLGLCapabilities PFD2GLCapabilities(AbstractGraphicsDevice device, final GLProfile glp, final long hdc, final int pfdID, final int winattrmask) { PIXELFORMATDESCRIPTOR pfd = createPixelFormatDescriptor(hdc, pfdID); if(null == pfd) { return null; @@ -689,21 +689,22 @@ public class WindowsWGLGraphicsConfiguration extends MutableGraphicsConfiguratio final WGLGLCapabilities res = new WGLGLCapabilities(pfd, pfdID, glp); res.setValuesByGDI(); - return (WGLGLCapabilities) GLGraphicsConfigurationUtil.setWinAttributeBits(res, drawableTypeBits ); + return (WGLGLCapabilities) GLGraphicsConfigurationUtil.fixWinAttribBitsAndHwAccel(device, drawableTypeBits, res); } - static WGLGLCapabilities PFD2GLCapabilitiesNoCheck(final GLProfile glp, final long hdc, final int pfdID) { + static WGLGLCapabilities PFD2GLCapabilitiesNoCheck(AbstractGraphicsDevice device, final GLProfile glp, final long hdc, final int pfdID) { PIXELFORMATDESCRIPTOR pfd = createPixelFormatDescriptor(hdc, pfdID); - return PFD2GLCapabilitiesNoCheck(glp, pfd, pfdID); + return PFD2GLCapabilitiesNoCheck(device, glp, pfd, pfdID); } - static WGLGLCapabilities PFD2GLCapabilitiesNoCheck(GLProfile glp, PIXELFORMATDESCRIPTOR pfd, int pfdID) { + static WGLGLCapabilities PFD2GLCapabilitiesNoCheck(AbstractGraphicsDevice device, GLProfile glp, PIXELFORMATDESCRIPTOR pfd, int pfdID) { if(null == pfd) { return null; } final WGLGLCapabilities res = new WGLGLCapabilities(pfd, pfdID, glp); res.setValuesByGDI(); - return (WGLGLCapabilities) GLGraphicsConfigurationUtil.setWinAttributeBits(res, PFD2DrawableTypeBits(pfd)); + + return (WGLGLCapabilities) GLGraphicsConfigurationUtil.fixWinAttribBitsAndHwAccel(device, PFD2DrawableTypeBits(pfd), res); } static PIXELFORMATDESCRIPTOR GLCapabilities2PFD(GLCapabilitiesImmutable caps, PIXELFORMATDESCRIPTOR pfd) { diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java index 41c9bba02..d2d1dafc8 100644 --- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLGraphicsConfigurationFactory.java @@ -113,13 +113,14 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat } protected static List getAvailableCapabilities(WindowsWGLDrawableFactory factory, AbstractGraphicsDevice device) { - WindowsWGLDrawableFactory.SharedResource sharedResource = factory.getOrCreateSharedResource(device); + final WindowsWGLDrawableFactory.SharedResource sharedResource = factory.getOrCreateSharedResource(device); if(null == sharedResource) { throw new GLException("Shared resource for device n/a: "+device); } - GLDrawableImpl sharedDrawable = sharedResource.getDrawable(); - GLCapabilitiesImmutable capsChosen = sharedDrawable.getChosenGLCapabilities(); - GLContext sharedContext = sharedResource.getContext(); + final GLDrawableImpl sharedDrawable = sharedResource.getDrawable(); + final GLContext sharedContext = sharedResource.getContext(); + final GLProfile glp = GLProfile.getDefault(device); + List availableCaps = null; if ( sharedResource.needsCurrentContext4ARBPFDQueries() ) { @@ -135,10 +136,10 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat throw new GLException("Error: HDC is null"); } if (sharedResource.hasARBPixelFormat()) { - availableCaps = WindowsWGLGraphicsConfigurationFactory.getAvailableGLCapabilitiesARB(sharedResource, sharedResource.getDevice(), capsChosen.getGLProfile(), hdc); + availableCaps = WindowsWGLGraphicsConfigurationFactory.getAvailableGLCapabilitiesARB(sharedResource, sharedResource.getDevice(), glp, hdc); } if( null == availableCaps || availableCaps.isEmpty() ) { - availableCaps = getAvailableGLCapabilitiesGDI(device, capsChosen.getGLProfile(), hdc); + availableCaps = getAvailableGLCapabilitiesGDI(device, glp, hdc); } } finally { if ( sharedResource.needsCurrentContext4ARBPFDQueries() ) { @@ -165,7 +166,7 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat int numFormats = pformats.length; List bucket = new ArrayList(numFormats); for (int i = 0; i < numFormats; i++) { - final GLCapabilitiesImmutable caps = WindowsWGLGraphicsConfiguration.PFD2GLCapabilities(glProfile, hdc, pformats[i], GLGraphicsConfigurationUtil.ALL_BITS); + final GLCapabilitiesImmutable caps = WindowsWGLGraphicsConfiguration.PFD2GLCapabilities(device, glProfile, hdc, pformats[i], GLGraphicsConfigurationUtil.ALL_BITS); if(null != caps) { bucket.add(caps); } @@ -439,7 +440,7 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat private static boolean updateGraphicsConfigurationGDI(WindowsWGLGraphicsConfiguration config, CapabilitiesChooser chooser, long hdc, boolean extHDC, int[] pformats) { GLCapabilitiesImmutable capsChosen = (GLCapabilitiesImmutable) config.getChosenCapabilities(); - if(capsChosen.isPBuffer()) { + if( !capsChosen.isOnscreen() && capsChosen.isPBuffer() ) { if (DEBUG) { System.err.println("updateGraphicsConfigurationGDI: no pbuffer supported on GDI: " + capsChosen); } @@ -454,6 +455,7 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat System.err.println("updateGraphicsConfigurationGDI: capsChosen "+capsChosen+", "+GLGraphicsConfigurationUtil.winAttributeBits2String(null, winattrmask).toString()); } + AbstractGraphicsDevice device = config.getScreen().getDevice(); int pfdID; // chosen or preset PFD ID WGLGLCapabilities pixelFormatCaps = null; // chosen or preset PFD ID's caps boolean pixelFormatSet = false; // indicates a preset PFD ID [caps] @@ -468,7 +470,7 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat + ", pixelformat " + pfdID); } pixelFormatSet = true; - pixelFormatCaps = WindowsWGLGraphicsConfiguration.PFD2GLCapabilities(glProfile, hdc, pfdID, winattrmask); + pixelFormatCaps = WindowsWGLGraphicsConfiguration.PFD2GLCapabilities(device, glProfile, hdc, pfdID, winattrmask); if(null == pixelFormatCaps) { throw new GLException("Could not map PFD2GLCaps w/ already chosen pfdID "+pfdID); } @@ -480,7 +482,7 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat List availableCaps = new ArrayList(); for (int i = 0; i < pformats.length; i++) { - final GLCapabilitiesImmutable caps = WindowsWGLGraphicsConfiguration.PFD2GLCapabilities(glProfile, hdc, pformats[i], winattrmask); + final GLCapabilitiesImmutable caps = WindowsWGLGraphicsConfiguration.PFD2GLCapabilities(device, glProfile, hdc, pformats[i], winattrmask); if(null != caps) { availableCaps.add(caps); if(DEBUG) { @@ -488,7 +490,7 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat System.err.println("updateGraphicsConfigurationGDI: availableCaps["+i+" -> "+j+"]: "+caps); } } else if(DEBUG) { - GLCapabilitiesImmutable skipped = WindowsWGLGraphicsConfiguration.PFD2GLCapabilitiesNoCheck(glProfile, hdc, pformats[i]); + GLCapabilitiesImmutable skipped = WindowsWGLGraphicsConfiguration.PFD2GLCapabilitiesNoCheck(device, glProfile, hdc, pformats[i]); System.err.println("updateGraphicsConfigurationGDI: availableCaps["+i+" -> skip]: pfdID "+pformats[i]+", "+skipped); } } @@ -505,8 +507,8 @@ public class WindowsWGLGraphicsConfigurationFactory extends GLGraphicsConfigurat recommendedIndex--) { /* nop */ } if(DEBUG && 0 > recommendedIndex) { - final GLCapabilitiesImmutable reqPFDCaps = WindowsWGLGraphicsConfiguration.PFD2GLCapabilitiesNoCheck(glProfile, pfd, pfdID); - final GLCapabilitiesImmutable chosenCaps = WindowsWGLGraphicsConfiguration.PFD2GLCapabilities(glProfile, hdc, pfdID, winattrmask); + final GLCapabilitiesImmutable reqPFDCaps = WindowsWGLGraphicsConfiguration.PFD2GLCapabilitiesNoCheck(device, glProfile, pfd, pfdID); + final GLCapabilitiesImmutable chosenCaps = WindowsWGLGraphicsConfiguration.PFD2GLCapabilities(device, glProfile, hdc, pfdID, winattrmask); System.err.println("Chosen PFDID "+pfdID+", but not found in available caps (use given pfdIDs "+givenPFormats+", reqPFDCaps "+reqPFDCaps+", chosenCaps: "+chosenCaps); } } diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXContext.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXContext.java index 1f3edbd8a..03a0eefbf 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXContext.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXContext.java @@ -48,10 +48,10 @@ import javax.media.opengl.GLDrawableFactory; import javax.media.opengl.GLException; import javax.media.opengl.GLProfile; +import jogamp.nativewindow.WrappedSurface; import jogamp.opengl.GLContextImpl; import jogamp.opengl.GLContextShareSet; -import com.jogamp.nativewindow.WrappedSurface; import com.jogamp.nativewindow.x11.X11GraphicsScreen; public class X11ExternalGLXContext extends X11GLXContext { @@ -105,7 +105,7 @@ public class X11ExternalGLXContext extends X11GLXContext { cfg = X11GLXGraphicsConfiguration.create(glp, x11Screen, val[0]); } - final WrappedSurface ns = new WrappedSurface(cfg, drawable, w, h, null); + final WrappedSurface ns = new WrappedSurface(cfg, drawable, w, h, true); 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 8652e2d4a..ac78c6f4a 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXDrawable.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXDrawable.java @@ -45,7 +45,8 @@ import javax.media.opengl.GLDrawableFactory; import javax.media.opengl.GLException; import javax.media.opengl.GLProfile; -import com.jogamp.nativewindow.WrappedSurface; +import jogamp.nativewindow.WrappedSurface; + import com.jogamp.nativewindow.x11.X11GraphicsScreen; @@ -87,7 +88,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])+")"); } } - return new X11ExternalGLXDrawable(factory, new WrappedSurface(cfg, drawable, w, h, null)); + return new X11ExternalGLXDrawable(factory, new WrappedSurface(cfg, drawable, w, h, true)); } @Override diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawable.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawable.java index e9912ce9d..8c642777d 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawable.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawable.java @@ -69,9 +69,10 @@ public abstract class X11GLXDrawable extends GLDrawableImpl { } @Override - protected final void swapBuffersImpl() { - // single-buffer is already filtered out @ GLDrawableImpl#swapBuffers() - GLX.glXSwapBuffers(getNativeSurface().getDisplayHandle(), getHandle()); + protected final void swapBuffersImpl(boolean doubleBuffered) { + if(doubleBuffered) { + GLX.glXSwapBuffers(getNativeSurface().getDisplayHandle(), getHandle()); + } } //--------------------------------------------------------------------------- diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java index bc3e5b793..fb11f8bba 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawableFactory.java @@ -49,7 +49,7 @@ 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.UpstreamSurfaceHook; import javax.media.nativewindow.VisualIDHolder; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLCapabilitiesChooser; @@ -59,6 +59,8 @@ import javax.media.opengl.GLDrawable; import javax.media.opengl.GLException; import javax.media.opengl.GLProfile; +import jogamp.nativewindow.WrappedSurface; +import jogamp.nativewindow.x11.X11DummyUpstreamSurfaceHook; import jogamp.nativewindow.x11.X11Lib; import jogamp.nativewindow.x11.X11Util; import jogamp.opengl.DesktopGLDynamicLookupHelper; @@ -70,7 +72,6 @@ import jogamp.opengl.GLGraphicsConfigurationUtil; import jogamp.opengl.SharedResourceRunner; import com.jogamp.common.util.VersionNumber; -import com.jogamp.nativewindow.WrappedSurface; import com.jogamp.nativewindow.x11.X11GraphicsDevice; import com.jogamp.nativewindow.x11.X11GraphicsScreen; @@ -505,7 +506,7 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { protected final ProxySurface createMutableSurfaceImpl(AbstractGraphicsDevice deviceReq, boolean createNewDevice, GLCapabilitiesImmutable capsChosen, GLCapabilitiesImmutable capsRequested, - GLCapabilitiesChooser chooser, int width, int height, UpstreamSurfaceHook lifecycleHook) { + GLCapabilitiesChooser chooser, UpstreamSurfaceHook upstreamHook) { final X11GraphicsDevice device; if(createNewDevice) { // Null X11 locking, due to private non-shared Display handle @@ -518,65 +519,15 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { if(null == config) { throw new GLException("Choosing GraphicsConfiguration failed w/ "+capsChosen+" on "+screen); } - return new WrappedSurface( config, 0, width, height, lifecycleHook); + return new WrappedSurface(config, 0, upstreamHook, createNewDevice); } @Override 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); + return createMutableSurfaceImpl(deviceReq, createNewDevice, chosenCaps, requestedCaps, chooser, new X11DummyUpstreamSurfaceHook(width, height)); } - 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) { @@ -593,7 +544,7 @@ public class X11GLXDrawableFactory extends GLDrawableFactoryImpl { if(DEBUG) { System.err.println("X11GLXDrawableFactory.createProxySurfaceImpl 0x"+Long.toHexString(windowHandle)+": "+cfg); } - return new WrappedSurface(cfg, windowHandle, 0, 0, upstream); + return new WrappedSurface(cfg, windowHandle, upstream, true); } @Override diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfiguration.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfiguration.java index 866fcbbe4..96c3c4123 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfiguration.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfiguration.java @@ -307,7 +307,7 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem return null; // no RGBA -> color index not supported } - X11GLCapabilities res = new X11GLCapabilities(visualInfo, fbcfg, fbcfgid, glp); + final X11GLCapabilities res = new X11GLCapabilities(visualInfo, fbcfg, fbcfgid, glp); if (isMultisampleAvailable) { res.setSampleBuffers(glXGetFBConfig(display, fbcfg, GLX.GLX_SAMPLE_BUFFERS, tmp, 0) != 0); res.setNumSamples (glXGetFBConfig(display, fbcfg, GLX.GLX_SAMPLES, tmp, 0)); @@ -342,7 +342,7 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem res.setPbufferFloatingPointBuffers(glXGetFBConfig(display, fbcfg, GLXExt.GLX_FLOAT_COMPONENTS_NV, tmp, 0) != GL.GL_FALSE); } catch (Exception e) {} - return (X11GLCapabilities) GLGraphicsConfigurationUtil.setWinAttributeBits(res, drawableTypeBits); + return (X11GLCapabilities) GLGraphicsConfigurationUtil.fixWinAttribBitsAndHwAccel(device, drawableTypeBits, res); } private static String glXGetFBConfigErrorCode(int err) { @@ -462,7 +462,7 @@ public class X11GLXGraphicsConfiguration extends X11GraphicsConfiguration implem 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 (X11GLCapabilities) GLGraphicsConfigurationUtil.setWinAttributeBits(res, drawableTypeBits); + return (X11GLCapabilities) GLGraphicsConfigurationUtil.fixWinAttribBitsAndHwAccel(device, drawableTypeBits, res); } private static String glXGetConfigErrorCode(int err) { diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfigurationFactory.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfigurationFactory.java index 8086cd26a..431706e24 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfigurationFactory.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXGraphicsConfigurationFactory.java @@ -129,9 +129,7 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF } final X11GraphicsScreen sharedScreen = (X11GraphicsScreen) sharedResource.getScreen(); final boolean isMultisampleAvailable = factory.isGLXMultisampleAvailable(sharedScreen.getDevice()); - final X11GLXDrawable sharedDrawable = (X11GLXDrawable) sharedResource.getDrawable(); - final GLCapabilitiesImmutable capsChosen = sharedDrawable.getChosenGLCapabilities(); - final GLProfile glp = capsChosen.getGLProfile(); + final GLProfile glp = GLProfile.getDefault(device); List availableCaps = null; @@ -217,7 +215,7 @@ public class X11GLXGraphicsConfigurationFactory extends GLGraphicsConfigurationF X11GLXDrawableFactory factory = (X11GLXDrawableFactory) GLDrawableFactory.getDesktopFactory(); capsChosen = GLGraphicsConfigurationUtil.fixGLCapabilities( capsChosen, GLContext.isFBOAvailable(x11Device, capsChosen.getGLProfile()), factory.canCreateGLPbuffer(x11Device) ); - boolean usePBuffer = capsChosen.isPBuffer(); + boolean usePBuffer = !capsChosen.isOnscreen() && capsChosen.isPBuffer(); X11GLXGraphicsConfiguration res = null; if( factory.isGLXVersionGreaterEqualOneThree(x11Device) ) { diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11PbufferGLXDrawable.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11PbufferGLXDrawable.java index e1fe2f27e..bba2b3513 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11PbufferGLXDrawable.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11PbufferGLXDrawable.java @@ -81,10 +81,11 @@ public class X11PbufferGLXDrawable extends X11GLXDrawable { } private void createPbuffer() { - X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration) getNativeSurface().getGraphicsConfiguration(); - AbstractGraphicsScreen aScreen = config.getScreen(); - AbstractGraphicsDevice aDevice = aScreen.getDevice(); - long display = aDevice.getHandle(); + final MutableSurface ms = (MutableSurface) getNativeSurface(); + final X11GLXGraphicsConfiguration config = (X11GLXGraphicsConfiguration) ms.getGraphicsConfiguration(); + final AbstractGraphicsScreen aScreen = config.getScreen(); + final AbstractGraphicsDevice aDevice = aScreen.getDevice(); + final long display = aDevice.getHandle(); if (DEBUG) { System.out.println("Pbuffer config: " + config); @@ -94,8 +95,6 @@ public class X11PbufferGLXDrawable extends X11GLXDrawable { throw new GLException("Null display"); } - NativeSurface ns = getNativeSurface(); - GLCapabilitiesImmutable chosenCaps = (GLCapabilitiesImmutable)config.getChosenCapabilities(); if (chosenCaps.getPbufferRenderToTexture()) { @@ -111,9 +110,9 @@ public class X11PbufferGLXDrawable extends X11GLXDrawable { int[] iattributes = new int[7]; iattributes[niattribs++] = GLX.GLX_PBUFFER_WIDTH; - iattributes[niattribs++] = ns.getWidth(); + iattributes[niattribs++] = ms.getWidth(); iattributes[niattribs++] = GLX.GLX_PBUFFER_HEIGHT; - iattributes[niattribs++] = ns.getHeight(); + iattributes[niattribs++] = ms.getHeight(); iattributes[niattribs++] = GLX.GLX_LARGEST_PBUFFER; // exact iattributes[niattribs++] = 0; iattributes[niattribs++] = 0; @@ -125,7 +124,7 @@ public class X11PbufferGLXDrawable extends X11GLXDrawable { } // Set up instance variables - ((MutableSurface)ns).setSurfaceHandle(pbuffer); + ms.setSurfaceHandle(pbuffer); if (DEBUG) { System.err.println("Created pbuffer " + this); diff --git a/src/jogl/native/macosx/MacOSXWindowSystemInterface-calayer.m b/src/jogl/native/macosx/MacOSXWindowSystemInterface-calayer.m new file mode 100644 index 000000000..63323b76d --- /dev/null +++ b/src/jogl/native/macosx/MacOSXWindowSystemInterface-calayer.m @@ -0,0 +1,665 @@ +#import "MacOSXWindowSystemInterface.h" +#import +#import +#include "timespec.h" + +// +// CADisplayLink only available on iOS >= 3.1, sad, since it's convenient. +// Use CVDisplayLink otherwise. +// +// #define HAS_CADisplayLink 1 +// + +// lock/sync debug output +// +// #define DBG_SYNC 1 +// +#ifdef DBG_SYNC + // #define SYNC_PRINT(...) NSLog(@ ## __VA_ARGS__) + #define SYNC_PRINT(...) fprintf(stderr, __VA_ARGS__); fflush(stderr) +#else + #define SYNC_PRINT(...) +#endif + +// fps debug output +// +// #define DBG_PERF 1 + +@interface MyNSOpenGLLayer: NSOpenGLLayer +{ +@private + GLfloat gl_texCoords[8]; + +@protected + NSOpenGLContext* parentCtx; + NSOpenGLPixelFormat* parentPixelFmt; + volatile NSOpenGLPixelBuffer* pbuffer; + volatile GLuint textureID; + volatile int texWidth; + volatile int texHeight; +#ifdef HAS_CADisplayLink + CADisplayLink* displayLink; +#else + CVDisplayLinkRef displayLink; +#endif + int tc; + struct timespec tStart; +@public + struct timespec lastWaitTime; + GLint swapInterval; + GLint swapIntervalCounter; + pthread_mutex_t renderLock; + pthread_cond_t renderSignal; + volatile Bool shallDraw; + volatile int newTexWidth; + volatile int newTexHeight; +} + +- (id) setupWithContext: (NSOpenGLContext*) parentCtx + pixelFormat: (NSOpenGLPixelFormat*) pfmt + pbuffer: (NSOpenGLPixelBuffer*) p + texIDArg: (GLuint) texID + opaque: (Bool) opaque + texWidth: (int) texWidth + texHeight: (int) texHeight; + +- (Bool) validateTexSizeWithNewSize; +- (Bool) validateTexSize: (int) _texWidth texHeight: (int) _texHeight; +- (void) setTextureID: (int) _texID; + +- (void) validatePBuffer: (NSOpenGLPixelBuffer*) p; + +- (NSOpenGLContext *)openGLContextForPixelFormat:(NSOpenGLPixelFormat *)pixelFormat; +- (void)disableAnimation; +- (void)pauseAnimation:(Bool)pause; +- (void)deallocPBuffer; +- (void)releaseLayer; +- (void)dealloc; +- (void)setSwapInterval:(int)interval; +- (void)tick; +- (void)waitUntilRenderSignal: (long) to_micros; +- (Bool)isGLSourceValid; + +@end + +#ifndef HAS_CADisplayLink + +static CVReturn renderMyNSOpenGLLayer(CVDisplayLinkRef displayLink, + const CVTimeStamp *inNow, + const CVTimeStamp *inOutputTime, + CVOptionFlags flagsIn, + CVOptionFlags *flagsOut, + void *displayLinkContext) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + MyNSOpenGLLayer* l = (MyNSOpenGLLayer*)displayLinkContext; + pthread_mutex_lock(&l->renderLock); + if( 0 < l->swapInterval ) { + l->swapIntervalCounter++; + if( l->swapIntervalCounter >= l->swapInterval ) { + SYNC_PRINT("", (int)l->swapIntervalCounter, l->swapInterval); + l->swapIntervalCounter = 0; + pthread_cond_signal(&l->renderSignal); // wake up vsync + } + } + pthread_mutex_unlock(&l->renderLock); + [pool release]; + return kCVReturnSuccess; +} + +#endif + +static const GLfloat gl_verts[] = { + -1.0, -1.0, + -1.0, 1.0, + 1.0, 1.0, + 1.0, -1.0 +}; + +@implementation MyNSOpenGLLayer + +- (id) setupWithContext: (NSOpenGLContext*) _parentCtx + pixelFormat: (NSOpenGLPixelFormat*) _parentPixelFmt + pbuffer: (NSOpenGLPixelBuffer*) p + texIDArg: (GLuint) texID + opaque: (Bool) opaque + texWidth: (int) _texWidth + texHeight: (int) _texHeight; +{ + pthread_mutexattr_t renderLockAttr; + pthread_mutexattr_init(&renderLockAttr); + pthread_mutexattr_settype(&renderLockAttr, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(&renderLock, &renderLockAttr); // recursive + pthread_cond_init(&renderSignal, NULL); // no attribute + + { + int i; + for(i=0; i<8; i++) { + gl_texCoords[i] = 0.0f; + } + } + parentCtx = _parentCtx; + parentPixelFmt = _parentPixelFmt; + swapInterval = 1; // defaults to on (as w/ new GL profiles) + swapIntervalCounter = 0; + timespec_now(&lastWaitTime); + shallDraw = NO; + newTexWidth = _texWidth; + newTexHeight = _texHeight; + [self validateTexSizeWithNewSize]; + [self setTextureID: texID]; + + pbuffer = p; + if(NULL != pbuffer) { + [pbuffer retain]; + } + + { + // no animations for add/remove/swap sublayers etc + // doesn't work: [self removeAnimationForKey: kCAOnOrderIn, kCAOnOrderOut, kCATransition] + [self removeAllAnimations]; + } + + // instantiate a deactivated displayLink +#ifdef HAS_CADisplayLink + displayLink = [[CVDisplayLink displayLinkWithTarget:self selector:@selector(setNeedsDisplay)] retain]; +#else + CVReturn cvres; + { + int allDisplaysMask = 0; + int virtualScreen, accelerated, displayMask; + for (virtualScreen = 0; virtualScreen < [parentPixelFmt numberOfVirtualScreens]; virtualScreen++) { + [parentPixelFmt getValues:&displayMask forAttribute:NSOpenGLPFAScreenMask forVirtualScreen:virtualScreen]; + [parentPixelFmt getValues:&accelerated forAttribute:NSOpenGLPFAAccelerated forVirtualScreen:virtualScreen]; + if (accelerated) { + allDisplaysMask |= displayMask; + } + } + cvres = CVDisplayLinkCreateWithOpenGLDisplayMask(allDisplaysMask, &displayLink); + if(kCVReturnSuccess != cvres) { + DBG_PRINT("MyNSOpenGLLayer::init %p, CVDisplayLinkCreateWithOpenGLDisplayMask %X failed: %d\n", self, allDisplaysMask, cvres); + displayLink = NULL; + } + } + if(NULL != displayLink) { + cvres = CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext(displayLink, [parentCtx CGLContextObj], [parentPixelFmt CGLPixelFormatObj]); + if(kCVReturnSuccess != cvres) { + DBG_PRINT("MyNSOpenGLLayer::init %p, CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext failed: %d\n", self, cvres); + displayLink = NULL; + } + } + if(NULL != displayLink) { + cvres = CVDisplayLinkSetOutputCallback(displayLink, renderMyNSOpenGLLayer, self); + if(kCVReturnSuccess != cvres) { + DBG_PRINT("MyNSOpenGLLayer::init %p, CVDisplayLinkSetOutputCallback failed: %d\n", self, cvres); + displayLink = NULL; + } + } +#endif + [self pauseAnimation: YES]; + + [self removeAllAnimations]; + [self setAutoresizingMask: (kCALayerWidthSizable|kCALayerHeightSizable)]; + [self setNeedsDisplayOnBoundsChange: YES]; + + [self setOpaque: opaque ? YES : NO]; + + if(NULL != pbuffer) { + DBG_PRINT("MyNSOpenGLLayer::init (pbuffer) %p, ctx %p, pfmt %p, pbuffer %p, opaque %d, pbuffer %dx%d -> tex %dx%d, bounds: %lf/%lf %lfx%lf (refcnt %d)\n", + self, parentCtx, parentPixelFmt, pbuffer, opaque, [pbuffer pixelsWide], [pbuffer pixelsHigh], texWidth, texHeight, + lRect.origin.x, lRect.origin.y, lRect.size.width, lRect.size.height, (int)[self retainCount]); + } else { + DBG_PRINT("MyNSOpenGLLayer::init (texture) %p, ctx %p, pfmt %p, opaque %d, tex[id %d, %dx%d], bounds: %lf/%lf %lfx%lf (refcnt %d)\n", + self, parentCtx, parentPixelFmt, opaque, (int)textureID, texWidth, texHeight, + lRect.origin.x, lRect.origin.y, lRect.size.width, lRect.size.height, (int)[self retainCount]); + } + return self; +} + +- (Bool) validateTexSizeWithNewSize +{ + return [self validateTexSize: newTexWidth texHeight: newTexHeight]; +} + +- (Bool) validateTexSize: (int) _texWidth texHeight: (int) _texHeight +{ + if(_texHeight != texHeight || _texWidth != texWidth) { + texWidth = _texWidth; + texHeight = _texHeight; + CGRect lRect = [self bounds]; + lRect.origin.x = 0; + lRect.origin.y = 0; + lRect.size.width = texWidth; + lRect.size.height = texHeight; + [self setFrame: lRect]; + + GLfloat texCoordWidth, texCoordHeight; + if(NULL != pbuffer) { + GLenum textureTarget = [pbuffer textureTarget] ; + GLsizei pwidth = [pbuffer pixelsWide]; + GLsizei pheight = [pbuffer pixelsHigh]; + if( GL_TEXTURE_2D == textureTarget ) { + texCoordWidth = (GLfloat)pwidth /(GLfloat)texWidth ; + texCoordHeight = (GLfloat)pheight/(GLfloat)texHeight ; + } else { + texCoordWidth = pwidth; + texCoordHeight = pheight; + } + } else { + texCoordWidth = (GLfloat)1.0f; + texCoordHeight = (GLfloat)1.0f; + } + gl_texCoords[3] = texCoordHeight; + gl_texCoords[5] = texCoordHeight; + gl_texCoords[4] = texCoordWidth; + gl_texCoords[6] = texCoordWidth; + return YES; + } else { + return NO; + } +} + +- (void) setTextureID: (int) _texID +{ + textureID = _texID; +} + +- (void) validatePBuffer: (NSOpenGLPixelBuffer*) p +{ + if( pbuffer != p ) { + DBG_PRINT("MyNSOpenGLLayer::validatePBuffer.0 %p, pbuffer %p, (refcnt %d)\n", self, p, (int)[self retainCount]); + + SYNC_PRINT("{PB-nil}"); + + [self deallocPBuffer]; + + pbuffer = p; + if(NULL != pbuffer) { + [pbuffer retain]; + } + [self setTextureID: 0]; + + shallDraw = NO; + } +} + +/** +- (NSOpenGLPixelFormat *)openGLPixelFormatForDisplayMask:(uint32_t)mask +{ + DBG_PRINT("MyNSOpenGLLayer::openGLPixelFormatForDisplayMask: %p (refcnt %d) - parent-pfmt %p -> new-pfmt %p\n", + self, (int)[self retainCount], parentPixelFmt, parentPixelFmt); + return parentPixelFmt; +} */ + +- (NSOpenGLContext *)openGLContextForPixelFormat:(NSOpenGLPixelFormat *)pixelFormat +{ + NSOpenGLContext * nctx = [[NSOpenGLContext alloc] initWithFormat:pixelFormat shareContext:parentCtx]; + DBG_PRINT("MyNSOpenGLLayer::openGLContextForPixelFormat: %p (refcnt %d) - pfmt %p, parent %p -> new-ctx %p\n", + self, (int)[self retainCount], pixelFormat, parentCtx, nctx); + return nctx; +} + +- (void)disableAnimation +{ + DBG_PRINT("MyNSOpenGLLayer::disableAnimation: %p (refcnt %d) - displayLink %p\n", self, (int)[self retainCount], displayLink); + pthread_mutex_lock(&renderLock); + [self setAsynchronous: NO]; + if(NULL != displayLink) { +#ifdef HAS_CADisplayLink + [displayLink setPaused: YES]; + [displayLink release]; +#else + CVDisplayLinkStop(displayLink); + CVDisplayLinkRelease(displayLink); +#endif + displayLink = NULL; + } + pthread_mutex_unlock(&renderLock); +} + +- (void)deallocPBuffer +{ + if(NULL != pbuffer) { + NSOpenGLContext* context = [self openGLContext]; + if(NULL!=context) { + [context makeCurrentContext]; + + DBG_PRINT("MyNSOpenGLLayer::deallocPBuffer (with ctx) %p (refcnt %d) - context %p, pbuffer %p, texID %d\n", self, (int)[self retainCount], context, pbuffer, (int)texureID); + + if( 0 != textureID ) { + glDeleteTextures(1, &textureID); + } + [pbuffer release]; + + [context clearDrawable]; + } else { + DBG_PRINT("MyNSOpenGLLayer::deallocPBuffer (w/o ctx) %p (refcnt %d) - context %p, pbuffer %p, texID %d\n", self, (int)[self retainCount], context, pbuffer, (int)texureID); + } + pbuffer = NULL; + [self setTextureID: 0]; + } +} + +- (void)releaseLayer +{ + DBG_PRINT("MyNSOpenGLLayer::releaseLayer.0: %p (refcnt %d)\n", self, (int)[self retainCount]); + pthread_mutex_lock(&renderLock); + [self disableAnimation]; + [self deallocPBuffer]; + [self release]; + DBG_PRINT("MyNSOpenGLLayer::releaseLayer.X: %p (refcnt %d)\n", self, (int)[self retainCount]); + pthread_mutex_unlock(&renderLock); +} + +- (void)dealloc +{ + DBG_PRINT("MyNSOpenGLLayer::dealloc.0 %p (refcnt %d)\n", self, (int)[self retainCount]); + // NSLog(@"MyNSOpenGLLayer::dealloc: %@",[NSThread callStackSymbols]); + + pthread_mutex_lock(&renderLock); + [self disableAnimation]; + [self deallocPBuffer]; + pthread_mutex_unlock(&renderLock); + pthread_cond_destroy(&renderSignal); + pthread_mutex_destroy(&renderLock); + [super dealloc]; + DBG_PRINT("MyNSOpenGLLayer::dealloc.X %p\n", self); +} + +- (Bool)isGLSourceValid +{ + return NULL != pbuffer || 0 != textureID ; +} + +- (void)resizeWithOldSuperlayerSize:(CGSize)size + { + CGRect lRectS = [[self superlayer] bounds]; + + DBG_PRINT("MyNSOpenGLLayer::resizeWithOldSuperlayerSize: %p, texSize %dx%d, bounds: %lfx%lf -> %lfx%lf (refcnt %d)\n", + self, texWidth, texHeight, size.width, size.height, lRectS.size.width, lRectS.size.height, (int)[self retainCount]); + + newTexWidth = lRectS.size.width; + newTexHeight = lRectS.size.height; + shallDraw = YES; + SYNC_PRINT("", newTexWidth, newTexHeight); + + [super resizeWithOldSuperlayerSize: size]; +} + +- (BOOL)canDrawInOpenGLContext:(NSOpenGLContext *)context pixelFormat:(NSOpenGLPixelFormat *)pixelFormat + forLayerTime:(CFTimeInterval)timeInterval displayTime:(const CVTimeStamp *)timeStamp +{ + SYNC_PRINT("", (int)shallDraw); + return shallDraw; +} + +- (void)drawInOpenGLContext:(NSOpenGLContext *)context pixelFormat:(NSOpenGLPixelFormat *)pixelFormat + forLayerTime:(CFTimeInterval)timeInterval displayTime:(const CVTimeStamp *)timeStamp +{ + pthread_mutex_unlock(&renderLock); + SYNC_PRINT("<* "); + // NSLog(@"MyNSOpenGLLayer::DRAW: %@",[NSThread callStackSymbols]); + + if( shallDraw && ( NULL != pbuffer || 0 != textureID ) ) { + [context makeCurrentContext]; + + GLenum textureTarget; + + Bool texSizeChanged = [self validateTexSizeWithNewSize]; + + if( NULL != pbuffer ) { + if( texSizeChanged && 0 != textureID ) { + glDeleteTextures(1, &textureID); + [self setTextureID: 0]; + } + textureTarget = [pbuffer textureTarget]; + if( 0 == textureID ) { + glGenTextures(1, &textureID); + glBindTexture(textureTarget, textureID); + glTexParameteri(textureTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(textureTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + } else { + glBindTexture(textureTarget, textureID); + } + [context setTextureImageToPixelBuffer: pbuffer colorBuffer: GL_FRONT]; + } else { + textureTarget = GL_TEXTURE_2D; + glBindTexture(textureTarget, textureID); + } + SYNC_PRINT(" %d*>", (int)textureID); + + glEnable(textureTarget); + + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glVertexPointer(2, GL_FLOAT, 0, gl_verts); + glTexCoordPointer(2, GL_FLOAT, 0, gl_texCoords); + + glDrawArrays(GL_QUADS, 0, 4); + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + + glDisable(textureTarget); + glBindTexture(textureTarget, 0); + + [context clearDrawable]; + + [super drawInOpenGLContext: context pixelFormat: pixelFormat forLayerTime: timeInterval displayTime: timeStamp]; + + } else { + // glClear(GL_COLOR_BUFFER_BIT); + // glBlitFramebuffer(0, 0, texWidth, texHeight, + // 0, 0, texWidth, texHeight, + // GL_COLOR_BUFFER_BIT, GL_NEAREST); + SYNC_PRINT(" 0*>"); + } + + #ifdef DBG_PERF + [self tick]; + #endif + shallDraw = NO; + + if( 0 >= swapInterval ) { + pthread_cond_signal(&renderSignal); // wake up !vsync + SYNC_PRINT(""); + } + SYNC_PRINT("<$>\n"); + pthread_mutex_unlock(&renderLock); +} + +- (void)pauseAnimation:(Bool)pause +{ + DBG_PRINT("MyNSOpenGLLayer::pauseAnimation: %d\n", (int)pause); + [self setAsynchronous: NO]; + if(pause) { + if(NULL != displayLink) { + #ifdef HAS_CADisplayLink + [displayLink setPaused: YES]; + #else + CVDisplayLinkStop(displayLink); + #endif + } + } else { + if(NULL != displayLink) { + #ifdef HAS_CADisplayLink + [displayLink setPaused: NO]; + [displayLink setFrameInterval: swapInterval]; + #else + CVDisplayLinkStart(displayLink); + #endif + } + } + tc = 0; + timespec_now(&tStart); +} + +- (void)setSwapInterval:(int)interval +{ + /** + * v-sync doesn't works w/ NSOpenGLLayer's context .. well :( + * Using CVDisplayLink .. see setSwapInterval() below. + * + GLint si; + [context getValues: &si forParameter: NSOpenGLCPSwapInterval]; + if(si != swapInterval) { + DBG_PRINT("MyNSOpenGLLayer::drawInOpenGLContext %p setSwapInterval: %d -> %d\n", self, si, swapInterval); + [context setValues: &swapInterval forParameter: NSOpenGLCPSwapInterval]; + } + */ + + pthread_mutex_lock(&renderLock); + DBG_PRINT("MyNSOpenGLLayer::setSwapInterval.0: %d - displayLink %p\n", interval, displayLink); + swapInterval = interval; + swapIntervalCounter = 0; + pthread_mutex_unlock(&renderLock); + + if(0 < swapInterval) { + [self pauseAnimation: NO]; + } else { + [self pauseAnimation: YES]; + } + DBG_PRINT("MyNSOpenGLLayer::setSwapInterval.X: %d\n", interval); +} + +-(void)tick +{ + tc++; + if(tc%60==0) { + struct timespec t1, td; + timespec_now(&t1); + timespec_subtract(&td, &t1, &tStart); + long td_ms = timespec_milliseconds(&td); + fprintf(stderr, "NSOpenGLLayer: %ld ms / %d frames, %ld ms / frame, %f fps\n", + td_ms, tc, td_ms/tc, (tc * 1000.0) / (float)td_ms ); + fflush(NULL); + } +} + +- (void)waitUntilRenderSignal: (long) to_micros +{ + BOOL ready = NO; + int wr = 0; + pthread_mutex_lock(&renderLock); + SYNC_PRINT("{W %ld us", to_micros); + do { + if(0 >= swapInterval) { + ready = YES; + } + if(NO == ready) { + #ifdef DBG_SYNC + struct timespec t0, t1, td, td2; + timespec_now(&t0); + #endif + if(0 < to_micros) { + struct timespec to_abs = lastWaitTime; + timespec_addmicros(&to_abs, to_micros); + #ifdef DBG_SYNC + timespec_subtract(&td, &to_abs, &t0); + fprintf(stderr, ", (%ld) / ", timespec_milliseconds(&td)); + #endif + wr = pthread_cond_timedwait(&renderSignal, &renderLock, &to_abs); + #ifdef DBG_SYNC + timespec_now(&t1); + timespec_subtract(&td, &t1, &t0); + timespec_subtract(&td2, &t1, &lastWaitTime); + fprintf(stderr, "(%ld) / (%ld) ms", timespec_milliseconds(&td), timespec_milliseconds(&td2)); + #endif + } else { + pthread_cond_wait (&renderSignal, &renderLock); + #ifdef DBG_SYNC + timespec_now(&t1); + timespec_subtract(&td, &t1, &t0); + timespec_subtract(&td2, &t1, &lastWaitTime); + fprintf(stderr, "(%ld) / (%ld) ms", timespec_milliseconds(&td), timespec_milliseconds(&td2)); + #endif + } + ready = YES; + } + } while (NO == ready && 0 == wr) ; + SYNC_PRINT("-%d-%d-%d}", shallDraw, wr, ready); + timespec_now(&lastWaitTime); + pthread_mutex_unlock(&renderLock); +} + +@end + +NSOpenGLLayer* createNSOpenGLLayer(NSOpenGLContext* ctx, NSOpenGLPixelFormat* fmt, NSOpenGLPixelBuffer* p, uint32_t texID, Bool opaque, int texWidth, int texHeight) { + // This simply crashes after dealloc() has been called .. ie. ref-count -> 0 too early ? + // However using alloc/init, actual dealloc happens at JAWT destruction, hence too later IMHO. + // return [[MyNSOpenGLLayer layer] setupWithContext:ctx pixelFormat: fmt pbuffer: p texIDArg: (GLuint)texID + // opaque: opaque texWidth: texWidth texHeight: texHeight]; + + return [[[MyNSOpenGLLayer alloc] init] setupWithContext:ctx pixelFormat: fmt pbuffer: p texIDArg: (GLuint)texID + opaque: opaque texWidth: texWidth texHeight: texHeight]; +} + +void setNSOpenGLLayerSwapInterval(NSOpenGLLayer* layer, int interval) { + MyNSOpenGLLayer* l = (MyNSOpenGLLayer*) layer; + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + [l setSwapInterval: interval]; + [pool release]; +} + +void waitUntilNSOpenGLLayerIsReady(NSOpenGLLayer* layer, long to_micros) { + MyNSOpenGLLayer* l = (MyNSOpenGLLayer*) layer; + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + [l waitUntilRenderSignal: to_micros]; + [pool release]; +} + +void flushNSOpenGLLayerPBuffer(NSOpenGLLayer* layer) { + MyNSOpenGLLayer* l = (MyNSOpenGLLayer*) layer; + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + + pthread_mutex_lock(&l->renderLock); + [l validatePBuffer:0]; + pthread_mutex_unlock(&l->renderLock); + + [pool release]; +} + +void setNSOpenGLLayerNeedsDisplay(NSOpenGLLayer* layer, NSOpenGLPixelBuffer* p, uint32_t texID, int texWidth, int texHeight) { + MyNSOpenGLLayer* l = (MyNSOpenGLLayer*) layer; + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + Bool shallDraw; + + pthread_mutex_lock(&l->renderLock); + [l validatePBuffer:p]; + // l->newTexWidth = texWidth; + // l->newTexHeight = texHeight; + [l setTextureID: texID]; + shallDraw = [l isGLSourceValid]; + l->shallDraw = shallDraw; + pthread_mutex_unlock(&l->renderLock); + + SYNC_PRINT("", texWidth, texHeight, l->newTexWidth, l->newTexHeight, (int)shallDraw); + if(shallDraw) { + if ( [NSThread isMainThread] == YES ) { + [l setNeedsDisplay]; + } else { + // don't wait - using doublebuffering + [l performSelectorOnMainThread:@selector(setNeedsDisplay) withObject:nil waitUntilDone:NO]; + } + } + // DBG_PRINT("MyNSOpenGLLayer::setNSOpenGLLayerNeedsDisplay %p\n", l); + [pool release]; +} + +void releaseNSOpenGLLayer(NSOpenGLLayer* layer) { + MyNSOpenGLLayer* l = (MyNSOpenGLLayer*) layer; + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + DBG_PRINT("MyNSOpenGLLayer::releaseNSOpenGLLayer.0: %p\n", l); + + if ( [NSThread isMainThread] == YES ) { + [l releaseLayer]; + } else { + [l performSelectorOnMainThread:@selector(releaseLayer) withObject:nil waitUntilDone:NO]; + } + + DBG_PRINT("MyNSOpenGLLayer::releaseNSOpenGLLayer.X: %p\n", l); + [pool release]; +} + diff --git a/src/jogl/native/macosx/MacOSXWindowSystemInterface-pbuffer.m b/src/jogl/native/macosx/MacOSXWindowSystemInterface-pbuffer.m deleted file mode 100644 index b81b43e54..000000000 --- a/src/jogl/native/macosx/MacOSXWindowSystemInterface-pbuffer.m +++ /dev/null @@ -1,494 +0,0 @@ -#import "MacOSXWindowSystemInterface.h" -#import -#import -#include "timespec.h" - -// -// CADisplayLink only available on iOS >= 3.1, sad, since it's convenient. -// Use CVDisplayLink otherwise. -// -// #define HAS_CADisplayLink 1 -// - -// lock/sync debug output -// -// #define DBG_SYNC 1 -// -#ifdef DBG_SYNC - // #define SYNC_PRINT(...) NSLog(@ ## __VA_ARGS__) - #define SYNC_PRINT(...) fprintf(stderr, __VA_ARGS__); fflush(stderr) -#else - #define SYNC_PRINT(...) -#endif - -// fps debug output -// -// #define DBG_PERF 1 - -@interface MyNSOpenGLLayer: NSOpenGLLayer -{ -@protected - NSOpenGLPixelBuffer* pbuffer; - int texWidth; - int texHeight; - GLuint textureID; -#ifdef HAS_CADisplayLink - CADisplayLink* displayLink; -#else - CVDisplayLinkRef displayLink; -#endif - int tc; - struct timespec t0; -@public - struct timespec lastWaitTime; - GLint swapInterval; - GLint swapIntervalCounter; - pthread_mutex_t renderLock; - pthread_cond_t renderSignal; - BOOL shallDraw; -} - -- (id) setupWithContext: (NSOpenGLContext*) ctx - pixelFormat: (NSOpenGLPixelFormat*) pfmt - pbuffer: (NSOpenGLPixelBuffer*) p - opaque: (Bool) opaque - texWidth: (int) texWidth - texHeight: (int) texHeight; - -- (void)deallocTex; -- (void)disableAnimation; -- (void)releaseLayer; -- (void)dealloc; -- (int)getSwapInterval; -- (void)setSwapInterval:(int)interval; -- (void)tick; - -@end - -#ifndef HAS_CADisplayLink - -static CVReturn renderMyNSOpenGLLayer(CVDisplayLinkRef displayLink, - const CVTimeStamp *inNow, - const CVTimeStamp *inOutputTime, - CVOptionFlags flagsIn, - CVOptionFlags *flagsOut, - void *displayLinkContext) -{ - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - MyNSOpenGLLayer* l = (MyNSOpenGLLayer*)displayLinkContext; - pthread_mutex_lock(&l->renderLock); - #ifdef DBG_PERF - [l tick]; - #endif - if(0 < l->swapInterval) { - l->swapIntervalCounter++; - if(l->swapIntervalCounter>=l->swapInterval) { - l->swapIntervalCounter = 0; - pthread_cond_signal(&l->renderSignal); - SYNC_PRINT("S"); - } - } - pthread_mutex_unlock(&l->renderLock); - [pool release]; - return kCVReturnSuccess; -} - -#endif - -@implementation MyNSOpenGLLayer - -- (id) setupWithContext: (NSOpenGLContext*) _ctx - pixelFormat: (NSOpenGLPixelFormat*) _fmt - pbuffer: (NSOpenGLPixelBuffer*) p - opaque: (Bool) opaque - texWidth: (int) _texWidth - texHeight: (int) _texHeight; -{ - pthread_mutexattr_t renderLockAttr; - pthread_mutexattr_init(&renderLockAttr); - pthread_mutexattr_settype(&renderLockAttr, PTHREAD_MUTEX_RECURSIVE); - pthread_mutex_init(&renderLock, &renderLockAttr); // recursive - pthread_cond_init(&renderSignal, NULL); // no attribute - - textureID = 0; - swapInterval = 1; // defaults to on (as w/ new GL profiles) - swapIntervalCounter = 0; - timespec_now(&lastWaitTime); - shallDraw = NO; - texWidth = _texWidth; - texHeight = _texHeight; - pbuffer = p; - [pbuffer retain]; - - { - CGRect lRect = CGRectMake(0, 0, texWidth, texHeight); - [self setFrame:lRect]; - - // no animations for add/remove/swap sublayers etc - // doesn't work: [self removeAnimationForKey: kCAOnOrderIn, kCAOnOrderOut, kCATransition] - [self removeAllAnimations]; - } - - // instantiate a deactivated displayLink -#ifdef HAS_CADisplayLink - displayLink = [[CVDisplayLink displayLinkWithTarget:self selector:@selector(setNeedsDisplay)] retain]; - [displayLink setPaused: YES]; -#else - CVReturn cvres; - { - int allDisplaysMask = 0; - int virtualScreen, accelerated, displayMask; - for (virtualScreen = 0; virtualScreen < [_fmt numberOfVirtualScreens]; virtualScreen++) { - [_fmt getValues:&displayMask forAttribute:NSOpenGLPFAScreenMask forVirtualScreen:virtualScreen]; - [_fmt getValues:&accelerated forAttribute:NSOpenGLPFAAccelerated forVirtualScreen:virtualScreen]; - if (accelerated) { - allDisplaysMask |= displayMask; - } - } - cvres = CVDisplayLinkCreateWithOpenGLDisplayMask(allDisplaysMask, &displayLink); - if(kCVReturnSuccess != cvres) { - DBG_PRINT("MyNSOpenGLLayer::init %p, CVDisplayLinkCreateWithOpenGLDisplayMask %X failed: %d\n", self, allDisplaysMask, cvres); - displayLink = NULL; - } - } - if(NULL != displayLink) { - cvres = CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext(displayLink, [_ctx CGLContextObj], [_fmt CGLPixelFormatObj]); - if(kCVReturnSuccess != cvres) { - DBG_PRINT("MyNSOpenGLLayer::init %p, CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext failed: %d\n", self, cvres); - displayLink = NULL; - } - } - if(NULL != displayLink) { - cvres = CVDisplayLinkSetOutputCallback(displayLink, renderMyNSOpenGLLayer, self); - if(kCVReturnSuccess != cvres) { - DBG_PRINT("MyNSOpenGLLayer::init %p, CVDisplayLinkSetOutputCallback failed: %d\n", self, cvres); - displayLink = NULL; - } - } - if(NULL != displayLink) { - CVDisplayLinkStop(displayLink); - } -#endif - [self setAsynchronous: YES]; - - [self setNeedsDisplayOnBoundsChange: YES]; - - [self setOpaque: opaque ? YES : NO]; - - CGRect lRect = [self frame]; - DBG_PRINT("MyNSOpenGLLayer::init %p, ctx %p, pfmt %p, pbuffer %p, opaque %d, pbuffer %dx%d -> tex %dx%d, frame: %lf/%lf %lfx%lf (refcnt %d)\n", - self, _ctx, _fmt, pbuffer, opaque, [pbuffer pixelsWide], [pbuffer pixelsHigh], texWidth, texHeight, - lRect.origin.x, lRect.origin.y, lRect.size.width, lRect.size.height, (int)[self retainCount]); - return self; -} - -- (void)disableAnimation -{ - DBG_PRINT("MyNSOpenGLLayer::disableAnimation: %p (refcnt %d) - displayLink %p\n", self, (int)[self retainCount], displayLink); - pthread_mutex_lock(&renderLock); - [self setAsynchronous: NO]; - if(NULL != displayLink) { -#ifdef HAS_CADisplayLink - [displayLink setPaused: YES]; - [displayLink release]; -#else - CVDisplayLinkStop(displayLink); - CVDisplayLinkRelease(displayLink); -#endif - displayLink = NULL; - } - pthread_mutex_unlock(&renderLock); -} - -- (void)deallocTex -{ - pthread_mutex_lock(&renderLock); - NSOpenGLContext* context = [self openGLContext]; - DBG_PRINT("MyNSOpenGLLayer::deallocTex %p (refcnt %d) - context %p, pbuffer %p\n", self, (int)[self retainCount], context, pbuffer); - if(NULL != pbuffer) { - if(NULL!=context) { - [context makeCurrentContext]; - if(0 != textureID) { - glDeleteTextures(1, &textureID); - textureID = 0; - } - [context clearDrawable]; - } - [pbuffer release]; - pbuffer = NULL; - } - pthread_mutex_unlock(&renderLock); -} - -- (void)releaseLayer -{ - DBG_PRINT("MyNSOpenGLLayer::releaseLayer.0: %p (refcnt %d)\n", self, (int)[self retainCount]); - pthread_mutex_lock(&renderLock); - [self disableAnimation]; - [self deallocTex]; - [self release]; - DBG_PRINT("MyNSOpenGLLayer::releaseLayer.X: %p (refcnt %d)\n", self, (int)[self retainCount]); - pthread_mutex_unlock(&renderLock); -} - -- (void)dealloc -{ - DBG_PRINT("MyNSOpenGLLayer::dealloc.0 %p (refcnt %d)\n", self, (int)[self retainCount]); - // NSLog(@"MyNSOpenGLLayer::dealloc: %@",[NSThread callStackSymbols]); - - [self disableAnimation]; - [self deallocTex]; - pthread_cond_destroy(&renderSignal); - pthread_mutex_destroy(&renderLock); - [super dealloc]; - DBG_PRINT("MyNSOpenGLLayer::dealloc.X %p\n", self); -} - -- (BOOL)canDrawInOpenGLContext:(NSOpenGLContext *)context pixelFormat:(NSOpenGLPixelFormat *)pixelFormat - forLayerTime:(CFTimeInterval)timeInterval displayTime:(const CVTimeStamp *)timeStamp -{ - // assume both methods 'canDrawInOpenGLContext' and 'drawInOpenGLContext' - // are called from the same thread subsequently - pthread_mutex_lock(&renderLock); - Bool res = NULL != pbuffer && YES == shallDraw; - if(!res) { - SYNC_PRINT("0"); - pthread_mutex_unlock(&renderLock); - } else { - SYNC_PRINT("1"); - } - return res; -} - -- (void)drawInOpenGLContext:(NSOpenGLContext *)context pixelFormat:(NSOpenGLPixelFormat *)pixelFormat - forLayerTime:(CFTimeInterval)timeInterval displayTime:(const CVTimeStamp *)timeStamp -{ - [context makeCurrentContext]; - - GLenum textureTarget = [pbuffer textureTarget]; - GLfloat texCoordWidth, texCoordHeight; - { - GLsizei pwidth = [pbuffer pixelsWide]; - GLsizei pheight = [pbuffer pixelsHigh]; - texCoordWidth = textureTarget == GL_TEXTURE_2D ? (GLfloat)pwidth /(GLfloat)texWidth : pwidth; - texCoordHeight = textureTarget == GL_TEXTURE_2D ? (GLfloat)pheight/(GLfloat)texHeight : pheight; - } - Bool texCreated = 0 == textureID; - - if(texCreated) { - glGenTextures(1, &textureID); - - CGRect lRect = [self frame]; - DBG_PRINT("MyNSOpenGLLayer::drawInOpenGLContext %p, pbuffer %p %dx%d -> tex %dx%d [%fx%f] id 0x%X target 0x%X, frame: %lf/%lf %lfx%lf (refcnt %d)\n", - self, pbuffer, [pbuffer pixelsWide], [pbuffer pixelsHigh], texWidth, texHeight, texCoordWidth, texCoordHeight, textureID, textureTarget, - lRect.origin.x, lRect.origin.y, lRect.size.width, lRect.size.height, (int)[self retainCount]); - } - - glBindTexture(textureTarget, textureID); - - /** - if(texCreated) { - // proper tex size setup - glTexImage2D(textureTarget, 0, GL_RGB, texWidth, texHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); - } */ - - [context setTextureImageToPixelBuffer: pbuffer colorBuffer: GL_FRONT]; - - glTexParameteri(textureTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(textureTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - glEnable(textureTarget); - - static GLfloat verts[] = { - -1.0, -1.0, - -1.0, 1.0, - 1.0, 1.0, - 1.0, -1.0 - }; - - GLfloat tex[] = { - 0.0, 0.0, - 0.0, texCoordHeight, - texCoordWidth, texCoordHeight, - texCoordWidth, 0.0 - }; - - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glVertexPointer(2, GL_FLOAT, 0, verts); - glTexCoordPointer(2, GL_FLOAT, 0, tex); - - glDrawArrays(GL_QUADS, 0, 4); - - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - - glDisable(textureTarget); - glBindTexture(textureTarget, 0); - - [super drawInOpenGLContext: context pixelFormat: pixelFormat forLayerTime: timeInterval displayTime: timeStamp]; - shallDraw = NO; - if(0 >= swapInterval) { - pthread_cond_signal(&renderSignal); // just to wake up - SYNC_PRINT("s"); - } - SYNC_PRINT("$"); - pthread_mutex_unlock(&renderLock); -} - -- (int)getSwapInterval -{ - return swapInterval; -} - -- (void)setSwapInterval:(int)interval -{ - /** - * v-sync doesn't works w/ NSOpenGLLayer's context .. well :( - * Using CVDisplayLink .. see setSwapInterval() below. - * - GLint si; - [context getValues: &si forParameter: NSOpenGLCPSwapInterval]; - if(si != swapInterval) { - DBG_PRINT("MyNSOpenGLLayer::drawInOpenGLContext %p setSwapInterval: %d -> %d\n", self, si, swapInterval); - [context setValues: &swapInterval forParameter: NSOpenGLCPSwapInterval]; - } - } */ - - pthread_mutex_lock(&renderLock); - DBG_PRINT("MyNSOpenGLLayer::setSwapInterval.0: %d - displayLink %p\n", interval, displayLink); - swapInterval = interval; - swapIntervalCounter = 0; - pthread_mutex_unlock(&renderLock); - - if(NULL!=displayLink) { - if(0 < swapInterval) { - tc = 0; - timespec_now(&t0); - - [self setAsynchronous: NO]; - #ifdef HAS_CADisplayLink - [displayLink setPaused: NO]; - [displayLink setFrameInterval: interval]; - #else - DBG_PRINT("MyNSOpenGLLayer::setSwapInterval.1.b.1\n"); - CVDisplayLinkStart(displayLink); - DBG_PRINT("MyNSOpenGLLayer::setSwapInterval.1.b.X\n"); - #endif - } else { - #ifdef HAS_CADisplayLink - [displayLink setPaused: YES]; - #else - DBG_PRINT("MyNSOpenGLLayer::setSwapInterval.0.b.1\n"); - CVDisplayLinkStop(displayLink); - DBG_PRINT("MyNSOpenGLLayer::setSwapInterval.0.b.X\n"); - #endif - [self setAsynchronous: YES]; - } - } - DBG_PRINT("MyNSOpenGLLayer::setSwapInterval.X: %d\n", interval); -} - --(void)tick -{ - tc++; - if(tc%60==0) { - struct timespec t1, td; - timespec_now(&t1); - timespec_subtract(&td, &t1, &t0); - long td_ms = timespec_milliseconds(&td); - fprintf(stderr, "NSOpenGLLayer: %ld ms / %d frames, %ld ms / frame, %f fps\n", - td_ms, tc, td_ms/tc, (tc * 1000.0) / (float)td_ms ); - fflush(NULL); - } -} - -@end - -NSOpenGLLayer* createNSOpenGLLayer(NSOpenGLContext* ctx, NSOpenGLPixelFormat* fmt, NSOpenGLPixelBuffer* p, Bool opaque, int texWidth, int texHeight) { - // This simply crashes after dealloc() has been called .. ie. ref-count -> 0 too early ? - // However using alloc/init, actual dealloc happens at JAWT destruction, hence too later IMHO. - // return [[MyNSOpenGLLayer layer] setupWithContext:ctx pixelFormat: fmt pbuffer: p opaque: opaque texWidth: texWidth texHeight: texHeight]; - - return [[[MyNSOpenGLLayer alloc] init] setupWithContext:ctx pixelFormat: fmt pbuffer: p opaque: opaque texWidth: texWidth texHeight: texHeight]; -} - -void setNSOpenGLLayerSwapInterval(NSOpenGLLayer* layer, int interval) { - MyNSOpenGLLayer* l = (MyNSOpenGLLayer*) layer; - [l setSwapInterval: interval]; -} - -void waitUntilNSOpenGLLayerIsReady(NSOpenGLLayer* layer, long to_micros) { - MyNSOpenGLLayer* l = (MyNSOpenGLLayer*) layer; - BOOL ready = NO; - int wr = 0; - pthread_mutex_lock(&l->renderLock); - SYNC_PRINT("{"); - do { - if([l getSwapInterval] <= 0) { - ready = !l->shallDraw; - } - if(NO == ready) { - if(0 < to_micros) { - #ifdef DBG_SYNC - struct timespec t0, t1, td, td2; - timespec_now(&t0); - #endif - struct timespec to_abs = l->lastWaitTime; - timespec_addmicros(&to_abs, to_micros); - #ifdef DBG_SYNC - timespec_subtract(&td, &to_abs, &t0); - fprintf(stderr, "(%ld) / ", timespec_milliseconds(&td)); - #endif - wr = pthread_cond_timedwait(&l->renderSignal, &l->renderLock, &to_abs); - #ifdef DBG_SYNC - timespec_now(&t1); - timespec_subtract(&td, &t1, &t0); - timespec_subtract(&td2, &t1, &l->lastWaitTime); - fprintf(stderr, "(%ld) / (%ld) ms", timespec_milliseconds(&td), timespec_milliseconds(&td2)); - #endif - } else { - pthread_cond_wait (&l->renderSignal, &l->renderLock); - } - ready = !l->shallDraw; - } - } while (NO == ready && 0 == wr) ; - SYNC_PRINT("-%d}", ready); - timespec_now(&l->lastWaitTime); - pthread_mutex_unlock(&l->renderLock); -} - -void setNSOpenGLLayerNeedsDisplay(NSOpenGLLayer* layer) { - MyNSOpenGLLayer* l = (MyNSOpenGLLayer*) layer; - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - pthread_mutex_lock(&l->renderLock); - l->shallDraw = YES; - if ( [NSThread isMainThread] == YES ) { - [l setNeedsDisplay]; - } else { - // can't wait, otherwise we may deadlock AWT - [l performSelectorOnMainThread:@selector(setNeedsDisplay) withObject:nil waitUntilDone:NO]; - } - SYNC_PRINT("."); - pthread_mutex_unlock(&l->renderLock); - // DBG_PRINT("MyNSOpenGLLayer::setNSOpenGLLayerNeedsDisplay %p\n", l); - [pool release]; -} - -void releaseNSOpenGLLayer(NSOpenGLLayer* layer) { - MyNSOpenGLLayer* l = (MyNSOpenGLLayer*) layer; - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - DBG_PRINT("MyNSOpenGLLayer::releaseNSOpenGLLayer.0: %p\n", l); - - if ( [NSThread isMainThread] == YES ) { - [l releaseLayer]; - } else { - [l performSelectorOnMainThread:@selector(releaseLayer) withObject:nil waitUntilDone:NO]; - } - - DBG_PRINT("MyNSOpenGLLayer::releaseNSOpenGLLayer.X: %p\n", l); - [pool release]; -} - diff --git a/src/jogl/native/macosx/MacOSXWindowSystemInterface.m b/src/jogl/native/macosx/MacOSXWindowSystemInterface.m index f774f8f4a..becd41bb2 100644 --- a/src/jogl/native/macosx/MacOSXWindowSystemInterface.m +++ b/src/jogl/native/macosx/MacOSXWindowSystemInterface.m @@ -696,6 +696,11 @@ void setContextTextureImageToPBuffer(NSOpenGLContext* ctx, NSOpenGLPixelBuffer* [pool release]; } +Bool isNSOpenGLPixelBuffer(uint64_t object) { + NSObject *nsObj = (NSObject*) (intptr_t) object; + return [nsObj isMemberOfClass:[NSOpenGLPixelBuffer class]]; +} + #include Bool imagesInitialized = false; static char libGLStr[] = "/System/Library/Frameworks/OpenGL.framework/Libraries/libGL.dylib"; @@ -746,38 +751,3 @@ void resetGammaRamp() { CGDisplayRestoreColorSyncSettings(); } -/*** - * The following static functions are copied out of NEWT's OSX impl. - * May need to push code to NativeWindow, to remove duplication. - */ -static NSScreen * NewtScreen_getNSScreenByIndex(int screen_idx) { - NSArray *screens = [NSScreen screens]; - if(screen_idx<0) screen_idx=0; - if(screen_idx>=[screens count]) screen_idx=0; - return (NSScreen *) [screens objectAtIndex: screen_idx]; -} -static CGDirectDisplayID NewtScreen_getCGDirectDisplayIDByNSScreen(NSScreen *screen) { - // Mind: typedef uint32_t CGDirectDisplayID; - however, we assume it's 64bit on 64bit ?! - NSDictionary * dict = [screen deviceDescription]; - NSNumber * val = (NSNumber *) [dict objectForKey: @"NSScreenNumber"]; - // [NSNumber integerValue] returns NSInteger which is 32 or 64 bit native size - return (CGDirectDisplayID) [val integerValue]; -} -static long GetDictionaryLong(CFDictionaryRef theDict, const void* key) -{ - long value = 0; - CFNumberRef numRef; - numRef = (CFNumberRef)CFDictionaryGetValue(theDict, key); - if (numRef != NULL) - CFNumberGetValue(numRef, kCFNumberLongType, &value); - return value; -} -#define CGDDGetModeRefreshRate(mode) GetDictionaryLong((mode), kCGDisplayRefreshRate) - -int getScreenRefreshRate(int scrn_idx) { - NSScreen *screen = NewtScreen_getNSScreenByIndex(scrn_idx); - CGDirectDisplayID display = NewtScreen_getCGDirectDisplayIDByNSScreen(screen); - CFDictionaryRef mode = CGDisplayCurrentMode(display); - return CGDDGetModeRefreshRate(mode); -} - diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/DelegatedUpstreamSurfaceHookMutableSize.java b/src/nativewindow/classes/com/jogamp/nativewindow/DelegatedUpstreamSurfaceHookMutableSize.java new file mode 100644 index 000000000..22c95f3dd --- /dev/null +++ b/src/nativewindow/classes/com/jogamp/nativewindow/DelegatedUpstreamSurfaceHookMutableSize.java @@ -0,0 +1,39 @@ +package com.jogamp.nativewindow; + +import javax.media.nativewindow.ProxySurface; +import javax.media.nativewindow.UpstreamSurfaceHook; + +public class DelegatedUpstreamSurfaceHookMutableSize extends UpstreamSurfaceHookMutableSize { + final UpstreamSurfaceHook upstream; + + /** + * @param upstream optional upstream UpstreamSurfaceHook used for {@link #create(ProxySurface)} and {@link #destroy(ProxySurface)}. + * @param width initial width + * @param height initial height + */ + public DelegatedUpstreamSurfaceHookMutableSize(UpstreamSurfaceHook upstream, int width, int height) { + super(width, height); + this.upstream = upstream; + } + + @Override + public final void create(ProxySurface s) { + if(null != upstream) { + upstream.create(s); + } + } + + @Override + public final void destroy(ProxySurface s) { + if(null != upstream) { + upstream.destroy(s); + } + } + + @Override + public String toString() { + return getClass().getSimpleName()+"[ "+ width + "x" + height + ", " + upstream + "]"; + } + +} + diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/DelegatedUpstreamSurfaceHookWithSurfaceSize.java b/src/nativewindow/classes/com/jogamp/nativewindow/DelegatedUpstreamSurfaceHookWithSurfaceSize.java new file mode 100644 index 000000000..85e24582c --- /dev/null +++ b/src/nativewindow/classes/com/jogamp/nativewindow/DelegatedUpstreamSurfaceHookWithSurfaceSize.java @@ -0,0 +1,54 @@ +package com.jogamp.nativewindow; + +import javax.media.nativewindow.NativeSurface; +import javax.media.nativewindow.ProxySurface; +import javax.media.nativewindow.UpstreamSurfaceHook; + +public class DelegatedUpstreamSurfaceHookWithSurfaceSize implements UpstreamSurfaceHook { + final UpstreamSurfaceHook upstream; + final NativeSurface surface; + + /** + * @param upstream optional upstream UpstreamSurfaceHook used for {@link #create(ProxySurface)} and {@link #destroy(ProxySurface)}. + * @param surface mandatory {@link NativeSurface} used for {@link #getWidth(ProxySurface)} and {@link #getHeight(ProxySurface)} + */ + public DelegatedUpstreamSurfaceHookWithSurfaceSize(UpstreamSurfaceHook upstream, NativeSurface surface) { + this.upstream = upstream; + this.surface = surface; + if(null == surface) { + throw new IllegalArgumentException("given surface is null"); + } + } + + @Override + public final void create(ProxySurface s) { + if(null != upstream) { + upstream.create(s); + } + } + + @Override + public final void destroy(ProxySurface s) { + if(null != upstream) { + upstream.destroy(s); + } + } + + @Override + public final int getWidth(ProxySurface s) { + return surface.getWidth(); + } + + @Override + public final int getHeight(ProxySurface s) { + return surface.getHeight(); + } + + @Override + public String toString() { + final String us_s = null != surface ? ( surface.getClass().getName() + ": 0x" + Long.toHexString(surface.getSurfaceHandle()) + " " +surface.getWidth() + "x" + surface.getHeight() ) : "nil"; + return getClass().getSimpleName()+"["+upstream+", "+us_s+"]"; + } + +} + diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/UpstreamSurfaceHookMutableSize.java b/src/nativewindow/classes/com/jogamp/nativewindow/UpstreamSurfaceHookMutableSize.java new file mode 100644 index 000000000..29c540ac4 --- /dev/null +++ b/src/nativewindow/classes/com/jogamp/nativewindow/UpstreamSurfaceHookMutableSize.java @@ -0,0 +1,45 @@ +package com.jogamp.nativewindow; + +import javax.media.nativewindow.ProxySurface; +import javax.media.nativewindow.UpstreamSurfaceHook; + +public class UpstreamSurfaceHookMutableSize implements UpstreamSurfaceHook.MutableSize { + int width, height; + + /** + * @param width initial width + * @param height initial height + */ + public UpstreamSurfaceHookMutableSize(int width, int height) { + this.width = width; + this.height = height; + } + + @Override + public final void setSize(int width, int height) { + this.width = width; + this.height = height; + } + + @Override + public final int getWidth(ProxySurface s) { + return width; + } + + @Override + public final int getHeight(ProxySurface s) { + return height; + } + @Override + public void create(ProxySurface s) { /* nop */ } + + @Override + public void destroy(ProxySurface s) { /* nop */ } + + @Override + public String toString() { + return getClass().getSimpleName()+"[ "+ width + "x" + height + "]"; + } + +} + diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/WrappedSurface.java b/src/nativewindow/classes/com/jogamp/nativewindow/WrappedSurface.java deleted file mode 100644 index b7f6ba45d..000000000 --- a/src/nativewindow/classes/com/jogamp/nativewindow/WrappedSurface.java +++ /dev/null @@ -1,78 +0,0 @@ -/** - * Copyright 2010 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ - -package com.jogamp.nativewindow; - -import javax.media.nativewindow.AbstractGraphicsConfiguration; -import javax.media.nativewindow.ProxySurface; - -public class WrappedSurface extends ProxySurface { - protected long surfaceHandle; - - public WrappedSurface(AbstractGraphicsConfiguration cfg, long handle, int initialWidth, int initialHeight, UpstreamSurfaceHook upstream) { - super(cfg, initialWidth, initialHeight, upstream); - surfaceHandle=handle; - } - - @Override - protected void invalidateImpl() { - surfaceHandle = 0; - } - - @Override - public final long getSurfaceHandle() { - return surfaceHandle; - } - - @Override - public final void setSurfaceHandle(long surfaceHandle) { - this.surfaceHandle=surfaceHandle; - } - - @Override - protected final int lockSurfaceImpl() { - return LOCK_SUCCESS; - } - - @Override - protected final void unlockSurfaceImpl() { - } - - @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+ - ", upstreamSurfaceHook "+ush_s+"]"; - } -} diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java b/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java index d4b927cf1..a62d08ccf 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/awt/JAWTWindow.java @@ -39,12 +39,14 @@ package com.jogamp.nativewindow.awt; import com.jogamp.common.util.locks.LockFactory; import com.jogamp.common.util.locks.RecursiveLock; +import com.jogamp.nativewindow.MutableGraphicsConfiguration; import java.awt.Component; import java.awt.Container; import java.applet.Applet; import javax.media.nativewindow.AbstractGraphicsConfiguration; import javax.media.nativewindow.AbstractGraphicsDevice; +import javax.media.nativewindow.CapabilitiesImmutable; import javax.media.nativewindow.NativeSurface; import javax.media.nativewindow.NativeWindow; import javax.media.nativewindow.NativeWindowException; @@ -110,21 +112,6 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface, this.offscreenSurfaceLayer = 0; } - @Override - public void setShallUseOffscreenLayer(boolean v) { - shallUseOffscreenLayer = v; - } - - @Override - public final boolean getShallUseOffscreenLayer() { - return shallUseOffscreenLayer; - } - - @Override - public final boolean isOffscreenLayerSurfaceEnabled() { - return isOffscreenLayerSurface; - } - protected synchronized void invalidate() { invalidateNative(); jawt = null; @@ -136,26 +123,29 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface, } protected abstract void invalidateNative(); - protected final void updateBounds(JAWT_Rectangle jawtBounds) { - if(DEBUG) { - final Rectangle jb = new Rectangle(jawtBounds.getX(), jawtBounds.getY(), jawtBounds.getWidth(), jawtBounds.getHeight()); - if(!bounds.equals(jb)) { + protected final boolean updateBounds(JAWT_Rectangle jawtBounds) { + final Rectangle jb = new Rectangle(jawtBounds.getX(), jawtBounds.getY(), jawtBounds.getWidth(), jawtBounds.getHeight()); + final boolean changed = !bounds.equals(jb); + + if(changed) { + if(DEBUG) { System.err.println("JAWTWindow.updateBounds: "+bounds+" -> "+jb); Thread.dumpStack(); } + bounds.setX(jawtBounds.getX()); + bounds.setY(jawtBounds.getY()); + bounds.setWidth(jawtBounds.getWidth()); + bounds.setHeight(jawtBounds.getHeight()); + + if(component instanceof Container) { + java.awt.Insets contInsets = ((Container)component).getInsets(); + insets.setLeftWidth(contInsets.left); + insets.setRightWidth(contInsets.right); + insets.setTopHeight(contInsets.top); + insets.setBottomHeight(contInsets.bottom); + } } - bounds.setX(jawtBounds.getX()); - bounds.setY(jawtBounds.getY()); - bounds.setWidth(jawtBounds.getWidth()); - bounds.setHeight(jawtBounds.getHeight()); - - if(component instanceof Container) { - java.awt.Insets contInsets = ((Container)component).getInsets(); - insets.setLeftWidth(contInsets.left); - insets.setRightWidth(contInsets.right); - insets.setTopHeight(contInsets.top); - insets.setBottomHeight(contInsets.bottom); - } + return changed; } /** @return the JAWT_DrawingSurfaceInfo's (JAWT_Rectangle) bounds, updated with lock */ @@ -181,9 +171,29 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface, return jawt; } - /** - * {@inheritDoc} - */ + // + // OffscreenLayerOption + // + + @Override + public void setShallUseOffscreenLayer(boolean v) { + shallUseOffscreenLayer = v; + } + + @Override + public final boolean getShallUseOffscreenLayer() { + return shallUseOffscreenLayer; + } + + @Override + public final boolean isOffscreenLayerSurfaceEnabled() { + return isOffscreenLayerSurface; + } + + // + // OffscreenLayerSurface + // + @Override public final void attachSurfaceLayer(final long layerHandle) throws NativeWindowException { if( !isOffscreenLayerSurfaceEnabled() ) { @@ -205,9 +215,6 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface, } protected abstract void attachSurfaceLayerImpl(final long layerHandle); - /** - * {@inheritDoc} - */ @Override public final void detachSurfaceLayer() throws NativeWindowException { if( !isOffscreenLayerSurfaceEnabled() ) { @@ -232,11 +239,21 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface, } protected abstract void detachSurfaceLayerImpl(final long layerHandle); + protected final long getAttachedSurfaceLayer() { + return offscreenSurfaceLayer; + } + @Override public final boolean isSurfaceLayerAttached() { return 0 != offscreenSurfaceLayer; } + @Override + public final void setChosenCapabilities(CapabilitiesImmutable caps) { + ((MutableGraphicsConfiguration)getGraphicsConfiguration()).setChosenCapabilities(caps); + getPrivateGraphicsConfiguration().setChosenCapabilities(caps); + } + // // SurfaceUpdateListener // @@ -381,7 +398,7 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface, public final AbstractGraphicsConfiguration getGraphicsConfiguration() { return config.getNativeGraphicsConfiguration(); } - + @Override public final long getDisplayHandle() { return getGraphicsConfiguration().getScreen().getDevice().getHandle(); @@ -393,13 +410,13 @@ public abstract class JAWTWindow implements NativeWindow, OffscreenLayerSurface, } @Override - public int getWidth() { + public final int getWidth() { return component.getWidth(); } @Override - public int getHeight() { - return component.getHeight(); + public final int getHeight() { + return component.getHeight(); } // diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/egl/EGLGraphicsDevice.java b/src/nativewindow/classes/com/jogamp/nativewindow/egl/EGLGraphicsDevice.java index 40042ec81..b824350ff 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/egl/EGLGraphicsDevice.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/egl/EGLGraphicsDevice.java @@ -67,8 +67,8 @@ public class EGLGraphicsDevice extends DefaultGraphicsDevice implements Cloneabl * Note that this is not an open connection, ie no native display handle exist. * This constructor exist to setup a default device connection/unit.
      */ - public EGLGraphicsDevice(String connection, int unitID) { - super(NativeWindowFactory.TYPE_EGL, connection, unitID); + public EGLGraphicsDevice() { + super(NativeWindowFactory.TYPE_EGL, AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT); this.nativeDisplayID[0] = 0 ; // EGL.EGL_DEFAULT_DISPLAY this.eglLifecycleCallback = null; } diff --git a/src/nativewindow/classes/javax/media/nativewindow/NativeSurface.java b/src/nativewindow/classes/javax/media/nativewindow/NativeSurface.java index cec7d4ec3..27462ae70 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/NativeSurface.java +++ b/src/nativewindow/classes/javax/media/nativewindow/NativeSurface.java @@ -124,8 +124,11 @@ public interface NativeSurface extends SurfaceUpdatedListener { /** * Provide a mechanism to utilize custom (pre-) swap surface * code. This method is called before the render toolkit (e.g. JOGL) - * swaps the buffer/surface. The implementation may itself apply the swapping, + * swaps the buffer/surface if double buffering is enabled. + *

      + * The implementation may itself apply the swapping, * in which case true shall be returned. + *

      * * @return true if this method completed swapping the surface, * otherwise false, in which case eg the GLDrawable diff --git a/src/nativewindow/classes/javax/media/nativewindow/OffscreenLayerSurface.java b/src/nativewindow/classes/javax/media/nativewindow/OffscreenLayerSurface.java index f7dbc6c27..f9800109c 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/OffscreenLayerSurface.java +++ b/src/nativewindow/classes/javax/media/nativewindow/OffscreenLayerSurface.java @@ -50,4 +50,7 @@ public interface OffscreenLayerSurface { /** Returns true if a surface layer is attached, otherwise false. */ public boolean isSurfaceLayerAttached(); + /** Sets the capabilities of this instance, allowing upstream API's to refine it, i.e. OpenGL related settings. */ + public void setChosenCapabilities(CapabilitiesImmutable caps); + } diff --git a/src/nativewindow/classes/javax/media/nativewindow/ProxySurface.java b/src/nativewindow/classes/javax/media/nativewindow/ProxySurface.java index 7fc9789c2..395fdc818 100644 --- a/src/nativewindow/classes/javax/media/nativewindow/ProxySurface.java +++ b/src/nativewindow/classes/javax/media/nativewindow/ProxySurface.java @@ -1,5 +1,5 @@ /** - * Copyright 2010 JogAmp Community. All rights reserved. + * Copyright 2012 JogAmp Community. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: @@ -29,242 +29,82 @@ package javax.media.nativewindow; import jogamp.nativewindow.Debug; -import jogamp.nativewindow.SurfaceUpdatedHelper; -import com.jogamp.common.util.locks.LockFactory; -import com.jogamp.common.util.locks.RecursiveLock; - -public abstract class ProxySurface implements NativeSurface, MutableSurface { +/** + * Provides a mutable {@link NativeSurface}, i.e. {@link MutableSurface}, while allowing an + * {@link UpstreamSurfaceHook} to influence the lifecycle and information. + * + * @see UpstreamSurfaceHook + * @see MutableSurface + * @see NativeSurface + */ +public interface ProxySurface extends MutableSurface { public static final boolean DEBUG = Debug.debug("ProxySurface"); /** - * Implementation specific bitvalue stating the upstream's {@link AbstractGraphicsDevice} is owned by this {@link ProxySurface}. - * @see #setImplBitfield(int) - * @see #getImplBitfield() + * Implementation specific bit-value stating this {@link ProxySurface} owns the upstream's surface handle + * @see #addUpstreamOptionBits(int) + * @see #getUpstreamOptionBits() */ - public static final int OWN_DEVICE = 1 << 7; + public static final int OPT_PROXY_OWNS_UPSTREAM_SURFACE = 1 << 6; + + /** + * Implementation specific bit-value stating this {@link ProxySurface} owns the upstream's {@link AbstractGraphicsDevice}. + * @see #addUpstreamOptionBits(int) + * @see #getUpstreamOptionBits() + */ + public static final int OPT_PROXY_OWNS_UPSTREAM_DEVICE = 1 << 7; /** * Implementation specific bitvalue stating the upstream's {@link NativeSurface} is an invisible window, i.e. maybe incomplete. - * @see #setImplBitfield(int) - * @see #getImplBitfield() + * @see #addUpstreamOptionBits(int) + * @see #getUpstreamOptionBits() */ - public static final int INVISIBLE_WINDOW = 1 << 8; + public static final int OPT_UPSTREAM_WINDOW_INVISIBLE = 1 << 8; - /** Interface allowing upstream caller to pass lifecycle actions and size info to a {@link ProxySurface} instance. */ - public interface UpstreamSurfaceHook { - /** called within {@link ProxySurface#createNotify()} within lock, before using surface. */ - public void create(ProxySurface s); - /** called within {@link ProxySurface#destroyNotify()} within lock, before clearing fields. */ - public void destroy(ProxySurface s); + /** Allow redefining the AbstractGraphicsConfiguration */ + public void setGraphicsConfiguration(AbstractGraphicsConfiguration cfg); - /** Returns the width of the upstream surface */ - public int getWidth(ProxySurface s); - /** Returns the height of the upstream surface */ - public int getHeight(ProxySurface s); - } + /** Returns the set {@link UpstreamSurfaceHook}, or null if not set. */ + public UpstreamSurfaceHook getUpstreamSurfaceHook(); - private final SurfaceUpdatedHelper surfaceUpdatedHelper = new SurfaceUpdatedHelper(); - private final AbstractGraphicsConfiguration config; // control access due to delegation - private final UpstreamSurfaceHook upstream; - public final int initialWidth; - public final int initialHeight; - private long surfaceHandle_old; - protected RecursiveLock surfaceLock = LockFactory.createRecursiveLock(); - protected long displayHandle; - protected int scrnIndex; - protected int implBitfield; - /** - * @param cfg the {@link AbstractGraphicsConfiguration} to be used - * @param initialWidth the initial width - * @param initialHeight the initial height + * Sets the {@link UpstreamSurfaceHook} and returns the previous value. */ - protected ProxySurface(AbstractGraphicsConfiguration cfg, int initialWidth, int initialHeight, UpstreamSurfaceHook upstream) { - if(null == cfg) { - throw new IllegalArgumentException("null config"); - } - this.config = cfg; - this.upstream = upstream; - this.initialWidth = initialWidth; - this.initialHeight = initialHeight; - this.displayHandle=config.getNativeGraphicsConfiguration().getScreen().getDevice().getHandle(); - this.surfaceHandle_old = 0; - this.implBitfield = 0; - } - - public final UpstreamSurfaceHook getUpstreamSurfaceHook() { return upstream; } + public void setUpstreamSurfaceHook(UpstreamSurfaceHook hook); + + /** + * Enables or disables the {@link UpstreamSurfaceHook} lifecycle functions + * {@link UpstreamSurfaceHook#create(ProxySurface)} and {@link UpstreamSurfaceHook#destroy(ProxySurface)}. + *

      + * Use this for small code blocks where the native resources shall not change, + * i.e. resizing a derived (OpenGL) drawable. + *

      + */ + public void enableUpstreamSurfaceHookLifecycle(boolean enable); /** - * If a valid {@link UpstreamSurfaceHook} instance is passed in the - * {@link ProxySurface#ProxySurface(AbstractGraphicsConfiguration, int, int, UpstreamSurfaceHook) constructor}, * {@link UpstreamSurfaceHook#create(ProxySurface)} is being issued and the proxy surface/window handles shall be set. */ - public void createNotify() { - if(null != upstream) { - upstream.create(this); - } - this.displayHandle=config.getNativeGraphicsConfiguration().getScreen().getDevice().getHandle(); - this.surfaceHandle_old = 0; - } + public void createNotify(); /** - * If a valid {@link UpstreamSurfaceHook} instance is passed in the - * {@link ProxySurface#ProxySurface(AbstractGraphicsConfiguration, int, int, UpstreamSurfaceHook) constructor}, - * {@link UpstreamSurfaceHook#destroy(ProxySurface)} is being issued and all fields are cleared. + * {@link UpstreamSurfaceHook#destroy(ProxySurface)} is being issued and all proxy surface/window handles shall be cleared. */ - public void destroyNotify() { - if(null != upstream) { - upstream.destroy(this); - invalidateImpl(); - } - this.displayHandle = 0; - this.surfaceHandle_old = 0; - } + public void destroyNotify(); - /** - * Must be overridden by implementations allowing having a {@link UpstreamSurfaceHook} being passed. - * @see #destroyNotify() - */ - protected void invalidateImpl() { - throw new InternalError("UpstreamSurfaceHook given, but required method not implemented."); - } + public StringBuilder getUpstreamOptionBits(StringBuilder sink); + public int getUpstreamOptionBits(); - @Override - public final long getDisplayHandle() { - return displayHandle; - } - - protected final AbstractGraphicsConfiguration getPrivateGraphicsConfiguration() { - return config; - } - - @Override - public final AbstractGraphicsConfiguration getGraphicsConfiguration() { - return config.getNativeGraphicsConfiguration(); - } - - @Override - public final int getScreenIndex() { - return getGraphicsConfiguration().getScreen().getIndex(); - } - - @Override - public abstract long getSurfaceHandle(); - - @Override - public abstract void setSurfaceHandle(long surfaceHandle); + /** Returns true if the give bit-mask v is set in this instance upstream-option-bits, otherwise false.*/ + public boolean containsUpstreamOptionBits(int v); - @Override - public final int getWidth() { - if(null != upstream) { - return upstream.getWidth(this); - } - return initialWidth; - } - - @Override - public final int getHeight() { - if(null != upstream) { - return upstream.getHeight(this); - } - return initialHeight; - } - - @Override - public boolean surfaceSwap() { - return false; - } - - @Override - public void addSurfaceUpdatedListener(SurfaceUpdatedListener l) { - surfaceUpdatedHelper.addSurfaceUpdatedListener(l); - } - - @Override - public void addSurfaceUpdatedListener(int index, SurfaceUpdatedListener l) throws IndexOutOfBoundsException { - surfaceUpdatedHelper.addSurfaceUpdatedListener(index, l); - } - - @Override - public void removeSurfaceUpdatedListener(SurfaceUpdatedListener l) { - surfaceUpdatedHelper.removeSurfaceUpdatedListener(l); - } - - @Override - public void surfaceUpdated(Object updater, NativeSurface ns, long when) { - surfaceUpdatedHelper.surfaceUpdated(updater, ns, when); - } - - @Override - public int lockSurface() throws NativeWindowException, RuntimeException { - surfaceLock.lock(); - int res = surfaceLock.getHoldCount() == 1 ? LOCK_SURFACE_NOT_READY : LOCK_SUCCESS; // new lock ? - - if ( LOCK_SURFACE_NOT_READY == res ) { - try { - final AbstractGraphicsDevice adevice = getGraphicsConfiguration().getScreen().getDevice(); - adevice.lock(); - try { - res = lockSurfaceImpl(); - if(LOCK_SUCCESS == res && surfaceHandle_old != getSurfaceHandle()) { - res = LOCK_SURFACE_CHANGED; - if(DEBUG) { - System.err.println("ProxySurface: surface change 0x"+Long.toHexString(surfaceHandle_old)+" -> 0x"+Long.toHexString(getSurfaceHandle())); - // Thread.dumpStack(); - } - } - } finally { - if (LOCK_SURFACE_NOT_READY >= res) { - adevice.unlock(); - } - } - } finally { - if (LOCK_SURFACE_NOT_READY >= res) { - surfaceLock.unlock(); - } - } - } - return res; - } - - @Override - public final void unlockSurface() { - surfaceLock.validateLocked(); - surfaceHandle_old = getSurfaceHandle(); - - if (surfaceLock.getHoldCount() == 1) { - final AbstractGraphicsDevice adevice = getGraphicsConfiguration().getScreen().getDevice(); - try { - unlockSurfaceImpl(); - } finally { - adevice.unlock(); - } - } - surfaceLock.unlock(); - } - - protected abstract int lockSurfaceImpl(); - - protected abstract void unlockSurfaceImpl() ; - - public final void validateSurfaceLocked() { - surfaceLock.validateLocked(); - } - - @Override - public final boolean isSurfaceLockedByOtherThread() { - return surfaceLock.isLockedByOtherThread(); - } - - @Override - public final Thread getSurfaceLockOwner() { - return surfaceLock.getOwner(); - } + /** Add the given bit-mask to this instance upstream-option-bits using bit-or w/ v.*/ + public void addUpstreamOptionBits(int v); - @Override - public abstract String toString(); + /** Clear the given bit-mask from this instance upstream-option-bits using bit-and w/ ~v*/ + public void clearUpstreamOptionBits(int v); - public int getImplBitfield() { return implBitfield; } - public void setImplBitfield(int v) { implBitfield=v; } + public StringBuilder toString(StringBuilder sink); + public String toString(); } diff --git a/src/nativewindow/classes/javax/media/nativewindow/UpstreamSurfaceHook.java b/src/nativewindow/classes/javax/media/nativewindow/UpstreamSurfaceHook.java new file mode 100644 index 000000000..6fe2e5364 --- /dev/null +++ b/src/nativewindow/classes/javax/media/nativewindow/UpstreamSurfaceHook.java @@ -0,0 +1,52 @@ +/** + * Copyright 2012 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package javax.media.nativewindow; + +/** + * Interface allowing upstream caller to pass lifecycle actions and size info + * to a {@link ProxySurface} instance. + */ +public interface UpstreamSurfaceHook { + /** called within {@link ProxySurface#createNotify()} within lock, before using surface. */ + public void create(ProxySurface s); + /** called within {@link ProxySurface#destroyNotify()} within lock, before clearing fields. */ + public void destroy(ProxySurface s); + + /** Returns the width of the upstream surface, used if {@link ProxySurface#UPSTREAM_PROVIDES_SIZE} is set. */ + public int getWidth(ProxySurface s); + /** Returns the height of the upstream surface, used if {@link ProxySurface#UPSTREAM_PROVIDES_SIZE} is set. */ + public int getHeight(ProxySurface s); + + /** + * {@link UpstreamSurfaceHook} w/ mutable size, allowing it's {@link ProxySurface} user to resize. + */ + public interface MutableSize extends UpstreamSurfaceHook { + public void setSize(int width, int height); + } +} diff --git a/src/nativewindow/classes/jogamp/nativewindow/ProxySurfaceImpl.java b/src/nativewindow/classes/jogamp/nativewindow/ProxySurfaceImpl.java new file mode 100644 index 000000000..63f56cbae --- /dev/null +++ b/src/nativewindow/classes/jogamp/nativewindow/ProxySurfaceImpl.java @@ -0,0 +1,326 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package jogamp.nativewindow; + +import javax.media.nativewindow.AbstractGraphicsConfiguration; +import javax.media.nativewindow.AbstractGraphicsDevice; +import javax.media.nativewindow.NativeSurface; +import javax.media.nativewindow.NativeWindowException; +import javax.media.nativewindow.ProxySurface; +import javax.media.nativewindow.SurfaceUpdatedListener; +import javax.media.nativewindow.UpstreamSurfaceHook; + + +import com.jogamp.common.util.locks.LockFactory; +import com.jogamp.common.util.locks.RecursiveLock; + +public abstract class ProxySurfaceImpl implements ProxySurface { + private final SurfaceUpdatedHelper surfaceUpdatedHelper = new SurfaceUpdatedHelper(); + protected long displayHandle; // convenient ref of config.screen.device.handle + private AbstractGraphicsConfiguration config; // control access due to delegation + private UpstreamSurfaceHook upstream; + private long surfaceHandle_old; + private RecursiveLock surfaceLock = LockFactory.createRecursiveLock(); + private int implBitfield; + private boolean upstreamSurfaceHookLifecycleEnabled; + + /** + * @param cfg the {@link AbstractGraphicsConfiguration} to be used + * @param upstream the {@link UpstreamSurfaceHook} to be used + * @param ownsDevice true if this {@link ProxySurface} instance + * owns the {@link AbstractGraphicsConfiguration}'s {@link AbstractGraphicsDevice}, + * otherwise false. Owning the device implies closing it at {@link #destroyNotify()}. + */ + protected ProxySurfaceImpl(AbstractGraphicsConfiguration cfg, UpstreamSurfaceHook upstream, boolean ownsDevice) { + if(null == cfg) { + throw new IllegalArgumentException("null AbstractGraphicsConfiguration"); + } + if(null == upstream) { + throw new IllegalArgumentException("null UpstreamSurfaceHook"); + } + this.config = cfg; + this.displayHandle=config.getNativeGraphicsConfiguration().getScreen().getDevice().getHandle(); + this.upstream = upstream; + this.surfaceHandle_old = 0; + this.implBitfield = 0; + this.upstreamSurfaceHookLifecycleEnabled = true; + if(ownsDevice) { + addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_DEVICE ); + } + } + + @Override + public final UpstreamSurfaceHook getUpstreamSurfaceHook() { return upstream; } + + @Override + public void setUpstreamSurfaceHook(UpstreamSurfaceHook hook) { + if(null == hook) { + throw new IllegalArgumentException("null UpstreamSurfaceHook"); + } + upstream = hook; + } + + @Override + public final void enableUpstreamSurfaceHookLifecycle(boolean enable) { + upstreamSurfaceHookLifecycleEnabled = enable; + } + + @Override + public void createNotify() { + if(upstreamSurfaceHookLifecycleEnabled) { + upstream.create(this); + } + this.displayHandle=config.getNativeGraphicsConfiguration().getScreen().getDevice().getHandle(); + this.surfaceHandle_old = 0; + } + + @Override + public void destroyNotify() { + if(upstreamSurfaceHookLifecycleEnabled) { + upstream.destroy(this); + if( containsUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_DEVICE ) ) { + final AbstractGraphicsDevice aDevice = getGraphicsConfiguration().getScreen().getDevice(); + aDevice.close(); + clearUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_DEVICE ); + } + invalidateImpl(); + } + this.displayHandle = 0; + this.surfaceHandle_old = 0; + } + + /** + * Must be overridden by implementations allowing having a {@link UpstreamSurfaceHook} being passed. + * @see #destroyNotify() + */ + protected void invalidateImpl() { + throw new InternalError("UpstreamSurfaceHook given, but required method not implemented."); + } + + @Override + public final long getDisplayHandle() { + return displayHandle; + } + + protected final AbstractGraphicsConfiguration getPrivateGraphicsConfiguration() { + return config; + } + + @Override + public final AbstractGraphicsConfiguration getGraphicsConfiguration() { + return config.getNativeGraphicsConfiguration(); + } + + @Override + public final void setGraphicsConfiguration(AbstractGraphicsConfiguration cfg) { + config = cfg; + } + + @Override + public final int getScreenIndex() { + return getGraphicsConfiguration().getScreen().getIndex(); + } + + @Override + public abstract long getSurfaceHandle(); + + @Override + public abstract void setSurfaceHandle(long surfaceHandle); + + @Override + public final int getWidth() { + return upstream.getWidth(this); + } + + @Override + public final int getHeight() { + return upstream.getHeight(this); + } + + @Override + public boolean surfaceSwap() { + return false; + } + + @Override + public void addSurfaceUpdatedListener(SurfaceUpdatedListener l) { + surfaceUpdatedHelper.addSurfaceUpdatedListener(l); + } + + @Override + public void addSurfaceUpdatedListener(int index, SurfaceUpdatedListener l) throws IndexOutOfBoundsException { + surfaceUpdatedHelper.addSurfaceUpdatedListener(index, l); + } + + @Override + public void removeSurfaceUpdatedListener(SurfaceUpdatedListener l) { + surfaceUpdatedHelper.removeSurfaceUpdatedListener(l); + } + + @Override + public void surfaceUpdated(Object updater, NativeSurface ns, long when) { + surfaceUpdatedHelper.surfaceUpdated(updater, ns, when); + } + + @Override + public int lockSurface() throws NativeWindowException, RuntimeException { + surfaceLock.lock(); + int res = surfaceLock.getHoldCount() == 1 ? LOCK_SURFACE_NOT_READY : LOCK_SUCCESS; // new lock ? + + if ( LOCK_SURFACE_NOT_READY == res ) { + try { + final AbstractGraphicsDevice adevice = getGraphicsConfiguration().getScreen().getDevice(); + adevice.lock(); + try { + res = lockSurfaceImpl(); + if(LOCK_SUCCESS == res && surfaceHandle_old != getSurfaceHandle()) { + res = LOCK_SURFACE_CHANGED; + if(DEBUG) { + System.err.println("ProxySurfaceImpl: surface change 0x"+Long.toHexString(surfaceHandle_old)+" -> 0x"+Long.toHexString(getSurfaceHandle())); + // Thread.dumpStack(); + } + } + } finally { + if (LOCK_SURFACE_NOT_READY >= res) { + adevice.unlock(); + } + } + } finally { + if (LOCK_SURFACE_NOT_READY >= res) { + surfaceLock.unlock(); + } + } + } + return res; + } + + @Override + public final void unlockSurface() { + surfaceLock.validateLocked(); + surfaceHandle_old = getSurfaceHandle(); + + if (surfaceLock.getHoldCount() == 1) { + final AbstractGraphicsDevice adevice = getGraphicsConfiguration().getScreen().getDevice(); + try { + unlockSurfaceImpl(); + } finally { + adevice.unlock(); + } + } + surfaceLock.unlock(); + } + + protected abstract int lockSurfaceImpl(); + + protected abstract void unlockSurfaceImpl() ; + + public final void validateSurfaceLocked() { + surfaceLock.validateLocked(); + } + + @Override + public final boolean isSurfaceLockedByOtherThread() { + return surfaceLock.isLockedByOtherThread(); + } + + @Override + public final Thread getSurfaceLockOwner() { + return surfaceLock.getOwner(); + } + + public final StringBuilder getUpstreamOptionBits(StringBuilder sink) { + if(null == sink) { + sink = new StringBuilder(); + } + sink.append("UOB[ "); + if(0 == implBitfield) { + sink.append("]"); + return sink; + } + boolean needsOr = false; + if( 0 != ( implBitfield & OPT_PROXY_OWNS_UPSTREAM_SURFACE ) ) { + sink.append("OWNS_SURFACE"); + needsOr = true; + } + if( 0 != ( implBitfield & OPT_PROXY_OWNS_UPSTREAM_DEVICE ) ) { + if(needsOr) { + sink.append(" | "); + } + sink.append("OWNS_DEVICE"); + needsOr = true; + } + if( 0 != ( implBitfield & OPT_UPSTREAM_WINDOW_INVISIBLE ) ) { + if(needsOr) { + sink.append(" | "); + } + sink.append("WINDOW_INVISIBLE"); + needsOr = true; + } + sink.append(" ]"); + return sink; + } + + @Override + public final int getUpstreamOptionBits() { return implBitfield; } + + @Override + public final boolean containsUpstreamOptionBits(int v) { + return v == ( implBitfield & v ) ; + } + + @Override + public final void addUpstreamOptionBits(int v) { implBitfield |= v; } + + @Override + public final void clearUpstreamOptionBits(int v) { implBitfield &= ~v; } + + @Override + public StringBuilder toString(StringBuilder sink) { + if(null == sink) { + sink = new StringBuilder(); + } + sink.append(getUpstreamSurfaceHook()). + append(", displayHandle 0x" + Long.toHexString(getDisplayHandle())). + append(", surfaceHandle 0x" + Long.toHexString(getSurfaceHandle())). + append(", size " + getWidth() + "x" + getHeight()).append(", "); + getUpstreamOptionBits(sink); + sink.append(", surfaceLock "+surfaceLock); + return sink; + } + + @Override + public String toString() { + StringBuilder msg = new StringBuilder(); + msg.append(getClass().getSimpleName()).append("[ "); + toString(msg); + msg.append(" ]"); + return msg.toString(); + } + +} diff --git a/src/nativewindow/classes/jogamp/nativewindow/WrappedSurface.java b/src/nativewindow/classes/jogamp/nativewindow/WrappedSurface.java new file mode 100644 index 000000000..e544bc61a --- /dev/null +++ b/src/nativewindow/classes/jogamp/nativewindow/WrappedSurface.java @@ -0,0 +1,95 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package jogamp.nativewindow; + +import javax.media.nativewindow.AbstractGraphicsConfiguration; +import javax.media.nativewindow.AbstractGraphicsDevice; +import javax.media.nativewindow.ProxySurface; +import javax.media.nativewindow.UpstreamSurfaceHook; + +import com.jogamp.nativewindow.UpstreamSurfaceHookMutableSize; + +public class WrappedSurface extends ProxySurfaceImpl { + protected long surfaceHandle; + + /** + * Utilizes a {@link UpstreamSurfaceHook.MutableSize} to hold the size information, + * which is being passed to the {@link ProxySurface} instance. + * + * @param cfg the {@link AbstractGraphicsConfiguration} to be used + * @param handle the wrapped pre-existing native surface handle, maybe 0 if not yet determined + * @param initialWidth + * @param initialHeight + * @param ownsDevice true if this {@link ProxySurface} instance + * owns the {@link AbstractGraphicsConfiguration}'s {@link AbstractGraphicsDevice}, + * otherwise false. Owning the device implies closing it at {@link #destroyNotify()}. + */ + public WrappedSurface(AbstractGraphicsConfiguration cfg, long handle, int initialWidth, int initialHeight, boolean ownsDevice) { + super(cfg, new UpstreamSurfaceHookMutableSize(initialWidth, initialHeight), ownsDevice); + surfaceHandle=handle; + } + + /** + * @param cfg the {@link AbstractGraphicsConfiguration} to be used + * @param handle the wrapped pre-existing native surface handle, maybe 0 if not yet determined + * @param upstream the {@link UpstreamSurfaceHook} to be used + * @param ownsDevice true if this {@link ProxySurface} instance + * owns the {@link AbstractGraphicsConfiguration}'s {@link AbstractGraphicsDevice}, + * otherwise false. + */ + public WrappedSurface(AbstractGraphicsConfiguration cfg, long handle, UpstreamSurfaceHook upstream, boolean ownsDevice) { + super(cfg, upstream, ownsDevice); + surfaceHandle=handle; + } + + @Override + protected void invalidateImpl() { + surfaceHandle = 0; + } + + @Override + public final long getSurfaceHandle() { + return surfaceHandle; + } + + @Override + public final void setSurfaceHandle(long surfaceHandle) { + this.surfaceHandle=surfaceHandle; + } + + @Override + protected final int lockSurfaceImpl() { + return LOCK_SUCCESS; + } + + @Override + protected final void unlockSurfaceImpl() { + } + +} diff --git a/src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java b/src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java index e81d61e0f..5fd242247 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java +++ b/src/nativewindow/classes/jogamp/nativewindow/jawt/macosx/MacOSXJAWTWindow.java @@ -51,7 +51,6 @@ import javax.media.nativewindow.NativeWindowException; import javax.media.nativewindow.MutableSurface; import javax.media.nativewindow.util.Point; -import com.jogamp.nativewindow.MutableGraphicsConfiguration; import com.jogamp.nativewindow.awt.JAWTWindow; import jogamp.nativewindow.jawt.JAWT; @@ -71,17 +70,18 @@ public class MacOSXJAWTWindow extends JAWTWindow implements MutableSurface { } protected void invalidateNative() { - surfaceHandle=0; + offscreenSurfaceHandle=0; + offscreenSurfaceHandleSet=false; if(isOffscreenLayerSurfaceEnabled()) { if(0 != rootSurfaceLayerHandle) { OSXUtil.DestroyCALayer(rootSurfaceLayerHandle); rootSurfaceLayerHandle = 0; } - if(0 != drawable) { - OSXUtil.DestroyNSWindow(drawable); - drawable = 0; + if(0 != windowHandle) { + OSXUtil.DestroyNSWindow(windowHandle); } } + windowHandle=0; } protected void attachSurfaceLayerImpl(final long layerHandle) { @@ -92,8 +92,14 @@ public class MacOSXJAWTWindow extends JAWTWindow implements MutableSurface { OSXUtil.RemoveCASublayer(rootSurfaceLayerHandle, layerHandle); } - public long getSurfaceHandle() { - return isOffscreenLayerSurfaceEnabled() ? surfaceHandle : super.getSurfaceHandle() ; + @Override + public final long getWindowHandle() { + return windowHandle; + } + + @Override + public final long getSurfaceHandle() { + return offscreenSurfaceHandleSet ? offscreenSurfaceHandle : drawable /* super.getSurfaceHandle() */ ; } public void setSurfaceHandle(long surfaceHandle) { @@ -103,7 +109,8 @@ public class MacOSXJAWTWindow extends JAWTWindow implements MutableSurface { if(DEBUG) { System.err.println("MacOSXJAWTWindow.setSurfaceHandle(): 0x"+Long.toHexString(surfaceHandle)); } - this.surfaceHandle = surfaceHandle; + this.offscreenSurfaceHandle = surfaceHandle; + this.offscreenSurfaceHandleSet = true; } protected JAWT fetchJAWTImpl() throws NativeWindowException { @@ -167,6 +174,7 @@ public class MacOSXJAWTWindow extends JAWTWindow implements MutableSurface { unlockSurfaceImpl(); return NativeWindow.LOCK_SURFACE_NOT_READY; } else { + windowHandle = OSXUtil.GetNSWindow(drawable); ret = NativeWindow.LOCK_SUCCESS; } } else { @@ -177,36 +185,46 @@ public class MacOSXJAWTWindow extends JAWTWindow implements MutableSurface { * The actual surface/ca-layer shall be created/attached * by the upper framework (JOGL) since they require more information. */ + String errMsg = null; if(0 == drawable) { - drawable = OSXUtil.CreateNSWindow(0, 0, getBounds().getWidth(), getBounds().getHeight()); - if(0 == drawable) { - unlockSurfaceImpl(); - throw new NativeWindowException("Unable to created dummy NSWindow (layered case)"); + windowHandle = OSXUtil.CreateNSWindow(0, 0, 64, 64); + if(0 == windowHandle) { + errMsg = "Unable to create dummy NSWindow (layered case)"; + } else { + drawable = OSXUtil.GetNSView(windowHandle); + if(0 == drawable) { + errMsg = "Null NSView of NSWindow 0x"+Long.toHexString(windowHandle); + } + } + if(null == errMsg) { + // fix caps reflecting offscreen! (no GL available here ..) + Capabilities caps = (Capabilities) getGraphicsConfiguration().getChosenCapabilities().cloneMutable(); + caps.setOnscreen(false); + setChosenCapabilities(caps); } - // fix caps reflecting offscreen! - Capabilities caps = (Capabilities) getPrivateGraphicsConfiguration().getChosenCapabilities().cloneMutable(); - caps.setOnscreen(false); - getPrivateGraphicsConfiguration().setChosenCapabilities(caps); - caps = (Capabilities) getGraphicsConfiguration().getChosenCapabilities().cloneMutable(); - caps.setOnscreen(false); - ((MutableGraphicsConfiguration)getGraphicsConfiguration()).setChosenCapabilities(caps); } - if(0 == rootSurfaceLayerHandle) { - rootSurfaceLayerHandle = OSXUtil.CreateCALayer(bounds.getX(), bounds.getY(), bounds.getWidth(), bounds.getHeight()); - if(0 == rootSurfaceLayerHandle) { - OSXUtil.DestroyNSWindow(drawable); - drawable = 0; - unlockSurfaceImpl(); - throw new NativeWindowException("Could not create root CALayer: "+this); + if(null == errMsg) { + if(0 == rootSurfaceLayerHandle) { + rootSurfaceLayerHandle = OSXUtil.CreateCALayer(bounds.getX(), bounds.getY(), bounds.getWidth(), bounds.getHeight()); + if(0 == rootSurfaceLayerHandle) { + errMsg = "Could not create root CALayer"; + } else if(!SetJAWTRootSurfaceLayer0(dsi.getBuffer(), rootSurfaceLayerHandle)) { + errMsg = "Could not set JAWT rootSurfaceLayerHandle 0x"+Long.toHexString(rootSurfaceLayerHandle); + } } - if(!SetJAWTRootSurfaceLayer0(dsi.getBuffer(), rootSurfaceLayerHandle)) { + } + if(null != errMsg) { + if(0 != rootSurfaceLayerHandle) { OSXUtil.DestroyCALayer(rootSurfaceLayerHandle); rootSurfaceLayerHandle = 0; - OSXUtil.DestroyNSWindow(drawable); - drawable = 0; - unlockSurfaceImpl(); - throw new NativeWindowException("Could not set JAWT rootSurfaceLayerHandle: "+this); } + if(0 != windowHandle) { + OSXUtil.DestroyNSWindow(windowHandle); + windowHandle = 0; + } + drawable = 0; + unlockSurfaceImpl(); + throw new NativeWindowException(errMsg+": "+this); } ret = NativeWindow.LOCK_SUCCESS; } @@ -264,7 +282,9 @@ public class MacOSXJAWTWindow extends JAWTWindow implements MutableSurface { private long rootSurfaceLayerHandle = 0; // attached to the JAWT_SurfaceLayer - private long surfaceHandle = 0; + private long windowHandle = 0; + private long offscreenSurfaceHandle = 0; + private boolean offscreenSurfaceHandleSet = false; // Workaround for instance of 4796548 private boolean firstLock = true; diff --git a/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXDummyUpstreamSurfaceHook.java b/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXDummyUpstreamSurfaceHook.java new file mode 100644 index 000000000..de3206c0c --- /dev/null +++ b/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXDummyUpstreamSurfaceHook.java @@ -0,0 +1,56 @@ +package jogamp.nativewindow.macosx; + +import javax.media.nativewindow.NativeSurface; +import javax.media.nativewindow.NativeWindowException; +import javax.media.nativewindow.ProxySurface; +import javax.media.nativewindow.UpstreamSurfaceHook; + +import com.jogamp.nativewindow.UpstreamSurfaceHookMutableSize; + +public class OSXDummyUpstreamSurfaceHook extends UpstreamSurfaceHookMutableSize { + long nsWindow; + + /** + * @param width the initial width as returned by {@link NativeSurface#getWidth()} via {@link UpstreamSurfaceHook#getWidth(ProxySurface)}, + * not the actual dummy surface width. + * The latter is platform specific and small + * @param height the initial height as returned by {@link NativeSurface#getHeight()} via {@link UpstreamSurfaceHook#getHeight(ProxySurface)}, + * not the actual dummy surface height, + * The latter is platform specific and small + */ + public OSXDummyUpstreamSurfaceHook(int width, int height) { + super(width, height); + nsWindow = 0; + } + + @Override + public final void create(ProxySurface s) { + if(0 == nsWindow && 0 == s.getSurfaceHandle()) { + nsWindow = OSXUtil.CreateNSWindow(0, 0, 64, 64); + if(0 == nsWindow) { + throw new NativeWindowException("Error NS window 0"); + } + long nsView = OSXUtil.GetNSView(nsWindow); + if(0 == nsView) { + throw new NativeWindowException("Error NS view 0"); + } + s.setSurfaceHandle(nsView); + s.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ); + } + s.addUpstreamOptionBits(ProxySurface.OPT_UPSTREAM_WINDOW_INVISIBLE); + } + + @Override + public final void destroy(ProxySurface s) { + if( s.containsUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ) ) { + if( 0 == nsWindow || 0 == s.getSurfaceHandle() ) { + throw new InternalError("Owns upstream surface, but no OSX view/window: "+s+", nsWindow 0x"+Long.toHexString(nsWindow)); + } + OSXUtil.DestroyNSWindow(nsWindow); + nsWindow = 0; + s.setSurfaceHandle(0); + s.clearUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ); + } + } + +} diff --git a/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java b/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java index 149ebdf4a..b7a83e133 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java +++ b/src/nativewindow/classes/jogamp/nativewindow/macosx/OSXUtil.java @@ -72,6 +72,10 @@ public class OSXUtil { return isNSView0(object); } + public static boolean isNSWindow(long object) { + return isNSWindow0(object); + } + /** * In case the windowOrView is top-level, * you shall set topLevel to true where @@ -114,6 +118,9 @@ public class OSXUtil { public static long GetNSView(long nsWindow) { return GetNSView0(nsWindow); } + public static long GetNSWindow(long nsView) { + return GetNSWindow0(nsView); + } public static long CreateCALayer(int x, int y, int width, int height) { return CreateCALayer0(x, y, width, height); @@ -149,6 +156,11 @@ public class OSXUtil { return IsMainThread0(); } + /** Returns the screen refresh rate in Hz. If unavailable, returns 60Hz. */ + public static int GetScreenRefreshRate(int scrn_idx) { + return GetScreenRefreshRate0(scrn_idx); + } + /*** private static boolean isAWTEDTMainThreadInit = false; private static boolean isAWTEDTMainThread; @@ -172,15 +184,18 @@ public class OSXUtil { private static native boolean initIDs0(); private static native boolean isNSView0(long object); + private static native boolean isNSWindow0(long object); private static native Object GetLocationOnScreen0(long windowOrView, int src_x, int src_y); private static native Object GetInsets0(long windowOrView); private static native long CreateNSWindow0(int x, int y, int width, int height); private static native void DestroyNSWindow0(long nsWindow); private static native long GetNSView0(long nsWindow); + private static native long GetNSWindow0(long nsView); private static native long CreateCALayer0(int x, int y, int width, int height); private static native void AddCASublayer0(long rootCALayer, long subCALayer); private static native void RemoveCASublayer0(long rootCALayer, long subCALayer); private static native void DestroyCALayer0(long caLayer); private static native void RunOnMainThread0(boolean waitUntilDone, Runnable runnable); private static native boolean IsMainThread0(); + private static native int GetScreenRefreshRate0(int scrn_idx); } diff --git a/src/nativewindow/classes/jogamp/nativewindow/windows/GDIDummyUpstreamSurfaceHook.java b/src/nativewindow/classes/jogamp/nativewindow/windows/GDIDummyUpstreamSurfaceHook.java new file mode 100644 index 000000000..aa5f3dac5 --- /dev/null +++ b/src/nativewindow/classes/jogamp/nativewindow/windows/GDIDummyUpstreamSurfaceHook.java @@ -0,0 +1,50 @@ +package jogamp.nativewindow.windows; + +import javax.media.nativewindow.NativeSurface; +import javax.media.nativewindow.NativeWindowException; +import javax.media.nativewindow.ProxySurface; +import javax.media.nativewindow.UpstreamSurfaceHook; + +import com.jogamp.nativewindow.UpstreamSurfaceHookMutableSize; + +public class GDIDummyUpstreamSurfaceHook extends UpstreamSurfaceHookMutableSize { + /** + * @param width the initial width as returned by {@link NativeSurface#getWidth()} via {@link UpstreamSurfaceHook#getWidth(ProxySurface)}, + * not the actual dummy surface width. + * The latter is platform specific and small + * @param height the initial height as returned by {@link NativeSurface#getHeight()} via {@link UpstreamSurfaceHook#getHeight(ProxySurface)}, + * not the actual dummy surface height, + * The latter is platform specific and small + */ + public GDIDummyUpstreamSurfaceHook(int width, int height) { + super(width, height); + } + + @Override + public final void create(ProxySurface s) { + final GDISurface ms = (GDISurface)s; + if(0 == ms.getWindowHandle()) { + final long windowHandle = GDIUtil.CreateDummyWindow(0, 0, 64, 64); + if(0 == windowHandle) { + throw new NativeWindowException("Error windowHandle 0, werr: "+GDI.GetLastError()); + } + ms.setWindowHandle(windowHandle); + ms.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ); + } + s.addUpstreamOptionBits(ProxySurface.OPT_UPSTREAM_WINDOW_INVISIBLE); + } + + @Override + public final void destroy(ProxySurface s) { + final GDISurface ms = (GDISurface)s; + if( ms.containsUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ) ) { + if( 0 == ms.getWindowHandle() ) { + throw new InternalError("Owns upstream surface, but no GDI window: "+ms); + } + GDI.ShowWindow(ms.getWindowHandle(), GDI.SW_HIDE); + GDIUtil.DestroyDummyWindow(ms.getWindowHandle()); + ms.setWindowHandle(0); + ms.clearUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ); + } + } +} diff --git a/src/nativewindow/classes/jogamp/nativewindow/windows/GDISurface.java b/src/nativewindow/classes/jogamp/nativewindow/windows/GDISurface.java index e368aa6a1..3db2b5fc9 100644 --- a/src/nativewindow/classes/jogamp/nativewindow/windows/GDISurface.java +++ b/src/nativewindow/classes/jogamp/nativewindow/windows/GDISurface.java @@ -29,9 +29,13 @@ package jogamp.nativewindow.windows; import javax.media.nativewindow.AbstractGraphicsConfiguration; +import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.nativewindow.NativeWindowException; import javax.media.nativewindow.ProxySurface; -import javax.media.nativewindow.ProxySurface.UpstreamSurfaceHook; +import javax.media.nativewindow.UpstreamSurfaceHook; + +import jogamp.nativewindow.ProxySurfaceImpl; +import jogamp.nativewindow.windows.GDI; /** @@ -40,12 +44,20 @@ import javax.media.nativewindow.ProxySurface.UpstreamSurfaceHook; * The latter will get and release the HDC. * The size via getWidth()/getHeight() is invalid. */ -public class GDISurface extends ProxySurface { +public class GDISurface extends ProxySurfaceImpl { protected long windowHandle; protected long surfaceHandle; - public GDISurface(AbstractGraphicsConfiguration cfg, long windowHandle, int initialWidth, int initialHeight, UpstreamSurfaceHook upstream) { - super(cfg, initialWidth, initialHeight, upstream); + /** + * @param cfg the {@link AbstractGraphicsConfiguration} to be used + * @param windowHandle the wrapped pre-existing native window handle, maybe 0 if not yet determined + * @param upstream the {@link UpstreamSurfaceHook} to be used + * @param ownsDevice true if this {@link ProxySurface} instance + * owns the {@link AbstractGraphicsConfiguration}'s {@link AbstractGraphicsDevice}, + * otherwise false. Owning the device implies closing it at {@link #destroyNotify()}. + */ + public GDISurface(AbstractGraphicsConfiguration cfg, long windowHandle, UpstreamSurfaceHook upstream, boolean ownsDevice) { + super(cfg, upstream, ownsDevice); this.windowHandle=windowHandle; this.surfaceHandle=0; } @@ -114,18 +126,4 @@ public class GDISurface extends ProxySurface { final public long getSurfaceHandle() { return surfaceHandle; } - - @Override - final public String toString() { - final UpstreamSurfaceHook ush = getUpstreamSurfaceHook(); - final String ush_s = null != ush ? ( ush.getClass().getName() + ": " + ush ) : "nil"; - return getClass().getSimpleName()+"[config "+getPrivateGraphicsConfiguration()+ - ", displayHandle 0x"+Long.toHexString(getDisplayHandle())+ - ", windowHandle 0x"+Long.toHexString(windowHandle)+ - ", surfaceHandle 0x"+Long.toHexString(getSurfaceHandle())+ - ", size "+getWidth()+"x"+getHeight()+ - ", surfaceLock "+surfaceLock+ - ", upstreamSurfaceHook "+ush_s+"]"; - } - } diff --git a/src/nativewindow/classes/jogamp/nativewindow/x11/X11DummyUpstreamSurfaceHook.java b/src/nativewindow/classes/jogamp/nativewindow/x11/X11DummyUpstreamSurfaceHook.java new file mode 100644 index 000000000..55a29dd5e --- /dev/null +++ b/src/nativewindow/classes/jogamp/nativewindow/x11/X11DummyUpstreamSurfaceHook.java @@ -0,0 +1,60 @@ +package jogamp.nativewindow.x11; + +import javax.media.nativewindow.NativeSurface; +import javax.media.nativewindow.NativeWindowException; +import javax.media.nativewindow.ProxySurface; +import javax.media.nativewindow.UpstreamSurfaceHook; + +import jogamp.nativewindow.x11.X11Lib; + +import com.jogamp.nativewindow.UpstreamSurfaceHookMutableSize; +import com.jogamp.nativewindow.x11.X11GraphicsConfiguration; +import com.jogamp.nativewindow.x11.X11GraphicsDevice; +import com.jogamp.nativewindow.x11.X11GraphicsScreen; + +public class X11DummyUpstreamSurfaceHook extends UpstreamSurfaceHookMutableSize { + /** + * @param width the initial width as returned by {@link NativeSurface#getWidth()} via {@link UpstreamSurfaceHook#getWidth(ProxySurface)}, + * not the actual dummy surface width. + * The latter is platform specific and small + * @param height the initial height as returned by {@link NativeSurface#getHeight()} via {@link UpstreamSurfaceHook#getHeight(ProxySurface)}, + * not the actual dummy surface height, + * The latter is platform specific and small + */ + public X11DummyUpstreamSurfaceHook(int width, int height) { + super(width, height); + } + + @Override + public final void create(ProxySurface s) { + final X11GraphicsConfiguration cfg = (X11GraphicsConfiguration) s.getGraphicsConfiguration(); + final X11GraphicsScreen screen = (X11GraphicsScreen) cfg.getScreen(); + final X11GraphicsDevice device = (X11GraphicsDevice) screen.getDevice(); + if(0 == device.getHandle()) { + device.open(); + s.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_DEVICE ); + } + if( 0 == s.getSurfaceHandle() ) { + final long windowHandle = X11Lib.CreateDummyWindow(device.getHandle(), screen.getIndex(), cfg.getXVisualID(), 64, 64); + if(0 == windowHandle) { + throw new NativeWindowException("Creating dummy window failed w/ "+cfg); + } + s.setSurfaceHandle(windowHandle); + s.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ); + } + s.addUpstreamOptionBits(ProxySurface.OPT_UPSTREAM_WINDOW_INVISIBLE); + } + + @Override + public final void destroy(ProxySurface s) { + if( s.containsUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ) ) { + final X11GraphicsDevice device = (X11GraphicsDevice) s.getGraphicsConfiguration().getScreen().getDevice(); + if( 0 == s.getSurfaceHandle() ) { + throw new InternalError("Owns upstream surface, but no X11 window: "+s); + } + X11Lib.DestroyDummyWindow(device.getHandle(), s.getSurfaceHandle()); + s.setSurfaceHandle(0); + s.clearUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ); + } + } +} diff --git a/src/nativewindow/native/macosx/OSXmisc.m b/src/nativewindow/native/macosx/OSXmisc.m index 2c853a43d..d6ae7ed31 100644 --- a/src/nativewindow/native/macosx/OSXmisc.m +++ b/src/nativewindow/native/macosx/OSXmisc.m @@ -119,6 +119,12 @@ Java_jogamp_nativewindow_macosx_OSXUtil_isNSView0(JNIEnv *env, jclass _unused, j return [nsObj isMemberOfClass:[NSView class]]; } +JNIEXPORT jboolean JNICALL +Java_jogamp_nativewindow_macosx_OSXUtil_isNSWindow0(JNIEnv *env, jclass _unused, jlong object) { + NSObject *nsObj = (NSObject*) (intptr_t) object; + return [nsObj isMemberOfClass:[NSWindow class]]; +} + /* * Class: Java_jogamp_nativewindow_macosx_OSXUtil * Method: getLocationOnScreen0 @@ -238,8 +244,10 @@ JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_CreateNSWindow0 [myWindow setPreservesContentDuringLiveResize: YES]; // Remove animations NS_DURING + if ( [myWindow respondsToSelector:@selector(setAnimationBehavior:)] ) { // Available >= 10.7 - Removes default animations [myWindow setAnimationBehavior: NSWindowAnimationBehaviorNone]; + } NS_HANDLER NS_ENDHANDLER @@ -278,11 +286,28 @@ JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_GetNSView0 NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NSWindow* win = (NSWindow*) ((intptr_t) window); - DBG_PRINT( "contentView0 - window: %p (START)\n", win); - jlong res = (jlong) ((intptr_t) [win contentView]); - DBG_PRINT( "contentView0 - window: %p (END)\n", win); + DBG_PRINT( "GetNSView(window: %p): %p\n", win, (void*) (intptr_t) res); + + [pool release]; + return res; +} + +/* + * Class: Java_jogamp_nativewindow_macosx_OSXUtil + * Method: GetNSWindow0 + * Signature: (J)J + */ +JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_GetNSWindow0 + (JNIEnv *env, jclass unused, jlong view) +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + NSView* v = (NSView*) ((intptr_t) view); + + jlong res = (jlong) ((intptr_t) [v window]); + + DBG_PRINT( "GetNSWindow(view: %p): %p\n", v, (void*) (intptr_t) res); [pool release]; return res; @@ -314,6 +339,8 @@ JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_CreateCALayer0 // no animations for add/remove/swap sublayers etc // doesn't work: [layer removeAnimationForKey: kCAOnOrderIn, kCAOnOrderOut, kCATransition] [layer removeAllAnimations]; + [layer setAutoresizingMask: (kCALayerWidthSizable|kCALayerHeightSizable)]; + [layer setNeedsDisplayOnBoundsChange: YES]; DBG_PRINT("CALayer::CreateCALayer.1: %p %lf/%lf %lfx%lf\n", layer, lRect.origin.x, lRect.origin.y, lRect.size.width, lRect.size.height); DBG_PRINT("CALayer::CreateCALayer.X: %p (refcnt %d)\n", layer, (int)[layer retainCount]); @@ -357,7 +384,11 @@ JNIEXPORT void JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_AddCASublayer0 // no animations for add/remove/swap sublayers etc // doesn't work: [layer removeAnimationForKey: kCAOnOrderIn, kCAOnOrderOut, kCATransition] [rootLayer removeAllAnimations]; + [rootLayer setAutoresizingMask: (kCALayerWidthSizable|kCALayerHeightSizable)]; + [rootLayer setNeedsDisplayOnBoundsChange: YES]; [subLayer removeAllAnimations]; + [subLayer setAutoresizingMask: (kCALayerWidthSizable|kCALayerHeightSizable)]; + [subLayer setNeedsDisplayOnBoundsChange: YES]; }]; DBG_PRINT("CALayer::AddCASublayer0.X: %p . %p (refcnt %d)\n", rootLayer, subLayer, (int)[subLayer retainCount]); JNF_COCOA_EXIT(env); @@ -404,6 +435,63 @@ JNIEXPORT void JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_DestroyCALayer0 JNF_COCOA_EXIT(env); } +/* + * Class: Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow + * Method: SetJAWTRootSurfaceLayer0 + * Signature: (JJ)Z + */ +JNIEXPORT jboolean JNICALL Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow_SetJAWTRootSurfaceLayer0 + (JNIEnv *env, jclass unused, jobject jawtDrawingSurfaceInfoBuffer, jlong caLayer) +{ + JNF_COCOA_ENTER(env); + JAWT_DrawingSurfaceInfo* dsi = (JAWT_DrawingSurfaceInfo*) (*env)->GetDirectBufferAddress(env, jawtDrawingSurfaceInfoBuffer); + if (NULL == dsi) { + NativewindowCommon_throwNewRuntimeException(env, "Argument \"jawtDrawingSurfaceInfoBuffer\" was not a direct buffer"); + return JNI_FALSE; + } + CALayer* layer = (CALayer*) (intptr_t) caLayer; + [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){ + id surfaceLayers = (id )dsi->platformInfo; + DBG_PRINT("CALayer::SetJAWTRootSurfaceLayer.0: %p -> %p (refcnt %d)\n", surfaceLayers.layer, layer, (int)[layer retainCount]); + surfaceLayers.layer = layer; // already incr. retain count + DBG_PRINT("CALayer::SetJAWTRootSurfaceLayer.X: %p (refcnt %d)\n", layer, (int)[layer retainCount]); + }]; + JNF_COCOA_EXIT(env); + return JNI_TRUE; +} + +/* + * Class: Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow + * Method: UnsetJAWTRootSurfaceLayer0 + * Signature: (JJ)Z +JNIEXPORT jboolean JNICALL Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow_UnsetJAWTRootSurfaceLayer0 + (JNIEnv *env, jclass unused, jobject jawtDrawingSurfaceInfoBuffer, jlong caLayer) +{ + JNF_COCOA_ENTER(env); + JAWT_DrawingSurfaceInfo* dsi = (JAWT_DrawingSurfaceInfo*) (*env)->GetDirectBufferAddress(env, jawtDrawingSurfaceInfoBuffer); + if (NULL == dsi) { + NativewindowCommon_throwNewRuntimeException(env, "Argument \"jawtDrawingSurfaceInfoBuffer\" was not a direct buffer"); + return JNI_FALSE; + } + CALayer* layer = (CALayer*) (intptr_t) caLayer; + { + id surfaceLayers = (id )dsi->platformInfo; + if(layer != surfaceLayers.layer) { + NativewindowCommon_throwNewRuntimeException(env, "Attached layer %p doesn't match given layer %p\n", surfaceLayers.layer, layer); + return JNI_FALSE; + } + } + // [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){ + id surfaceLayers = (id )dsi->platformInfo; + DBG_PRINT("CALayer::detachJAWTSurfaceLayer: (%p) %p -> NULL\n", layer, surfaceLayers.layer); + surfaceLayers.layer = NULL; + [layer release]; + // }]; + JNF_COCOA_EXIT(env); + return JNI_TRUE; +} + */ + @interface MainRunnable : NSObject { @@ -489,60 +577,65 @@ JNIEXPORT jboolean JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_IsMainThread0 return ( [NSThread isMainThread] == YES ) ? JNI_TRUE : JNI_FALSE ; } -/* - * Class: Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow - * Method: SetJAWTRootSurfaceLayer0 - * Signature: (JJ)Z +/*** + * The following static functions are copied out of NEWT's OSX impl. + * May need to push code to NativeWindow, to remove duplication. */ -JNIEXPORT jboolean JNICALL Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow_SetJAWTRootSurfaceLayer0 - (JNIEnv *env, jclass unused, jobject jawtDrawingSurfaceInfoBuffer, jlong caLayer) +static NSScreen * NewtScreen_getNSScreenByIndex(int screen_idx) { + NSArray *screens = [NSScreen screens]; + if(screen_idx<0) screen_idx=0; + if(screen_idx>=[screens count]) screen_idx=0; + return (NSScreen *) [screens objectAtIndex: screen_idx]; +} +static CGDirectDisplayID NewtScreen_getCGDirectDisplayIDByNSScreen(NSScreen *screen) { + // Mind: typedef uint32_t CGDirectDisplayID; - however, we assume it's 64bit on 64bit ?! + NSDictionary * dict = [screen deviceDescription]; + NSNumber * val = (NSNumber *) [dict objectForKey: @"NSScreenNumber"]; + // [NSNumber integerValue] returns NSInteger which is 32 or 64 bit native size + return (CGDirectDisplayID) [val integerValue]; +} +static long GetDictionaryLong(CFDictionaryRef theDict, const void* key) { - JNF_COCOA_ENTER(env); - JAWT_DrawingSurfaceInfo* dsi = (JAWT_DrawingSurfaceInfo*) (*env)->GetDirectBufferAddress(env, jawtDrawingSurfaceInfoBuffer); - if (NULL == dsi) { - NativewindowCommon_throwNewRuntimeException(env, "Argument \"jawtDrawingSurfaceInfoBuffer\" was not a direct buffer"); - return JNI_FALSE; - } - CALayer* layer = (CALayer*) (intptr_t) caLayer; - [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){ - id surfaceLayers = (id )dsi->platformInfo; - DBG_PRINT("CALayer::SetJAWTRootSurfaceLayer.0: %p -> %p (refcnt %d)\n", surfaceLayers.layer, layer, (int)[layer retainCount]); - surfaceLayers.layer = layer; // already incr. retain count - DBG_PRINT("CALayer::SetJAWTRootSurfaceLayer.X: %p (refcnt %d)\n", layer, (int)[layer retainCount]); - }]; - JNF_COCOA_EXIT(env); - return JNI_TRUE; + long value = 0; + CFNumberRef numRef; + numRef = (CFNumberRef)CFDictionaryGetValue(theDict, key); + if (numRef != NULL) + CFNumberGetValue(numRef, kCFNumberLongType, &value); + return value; } +#define CGDDGetModeRefreshRate(mode) GetDictionaryLong((mode), kCGDisplayRefreshRate) /* - * Class: Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow - * Method: UnsetJAWTRootSurfaceLayer0 - * Signature: (JJ)Z -JNIEXPORT jboolean JNICALL Java_jogamp_nativewindow_jawt_macosx_MacOSXJAWTWindow_UnsetJAWTRootSurfaceLayer0 - (JNIEnv *env, jclass unused, jobject jawtDrawingSurfaceInfoBuffer, jlong caLayer) + * Class: Java_jogamp_nativewindow_macosx_OSXUtil + * Method: GetScreenRefreshRate + * Signature: (I)I + */ +JNIEXPORT jint JNICALL Java_jogamp_nativewindow_macosx_OSXUtil_GetScreenRefreshRate0 + (JNIEnv *env, jclass unused, jint scrn_idx) { + int res = 0; JNF_COCOA_ENTER(env); - JAWT_DrawingSurfaceInfo* dsi = (JAWT_DrawingSurfaceInfo*) (*env)->GetDirectBufferAddress(env, jawtDrawingSurfaceInfoBuffer); - if (NULL == dsi) { - NativewindowCommon_throwNewRuntimeException(env, "Argument \"jawtDrawingSurfaceInfoBuffer\" was not a direct buffer"); - return JNI_FALSE; - } - CALayer* layer = (CALayer*) (intptr_t) caLayer; - { - id surfaceLayers = (id )dsi->platformInfo; - if(layer != surfaceLayers.layer) { - NativewindowCommon_throwNewRuntimeException(env, "Attached layer %p doesn't match given layer %p\n", surfaceLayers.layer, layer); - return JNI_FALSE; + // NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + NSScreen *screen = NewtScreen_getNSScreenByIndex((int)scrn_idx); + DBG_PRINT("GetScreenRefreshRate.0: screen %p\n", (void *)screen); + if(NULL != screen) { + CGDirectDisplayID display = NewtScreen_getCGDirectDisplayIDByNSScreen(screen); + DBG_PRINT("GetScreenRefreshRate.1: display %p\n", (void *)display); + if(0 != display) { + CFDictionaryRef mode = CGDisplayCurrentMode(display); + DBG_PRINT("GetScreenRefreshRate.2: mode %p\n", (void *)mode); + if(NULL != mode) { + res = CGDDGetModeRefreshRate(mode); + DBG_PRINT("GetScreenRefreshRate.3: res %d\n", res); + } } } - // [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){ - id surfaceLayers = (id )dsi->platformInfo; - DBG_PRINT("CALayer::detachJAWTSurfaceLayer: (%p) %p -> NULL\n", layer, surfaceLayers.layer); - surfaceLayers.layer = NULL; - [layer release]; - // }]; + if(0 == res) { + res = 60; // default .. (experienced on OSX 10.6.8) + } + fprintf(stderr, "GetScreenRefreshRate.X: %d\n", res); + // [pool release]; JNF_COCOA_EXIT(env); - return JNI_TRUE; + return res; } - */ diff --git a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java index 6f0028a77..89a749c51 100644 --- a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java +++ b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java @@ -68,6 +68,15 @@ import com.jogamp.newt.event.awt.AWTAdapter; import com.jogamp.newt.event.awt.AWTKeyAdapter; import com.jogamp.newt.event.awt.AWTMouseAdapter; +/** + * AWT {@link java.awt.Canvas Canvas} containing a NEWT {@link Window} using native parenting. + * + *
      Offscreen Layer Remarks
      + * + * {@link OffscreenLayerOption#setShallUseOffscreenLayer(boolean) setShallUseOffscreenLayer(true)} + * maybe called to use an offscreen drawable (FBO or PBuffer) allowing + * the underlying JAWT mechanism to composite the image, if supported. + */ @SuppressWarnings("serial") public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProtocol, OffscreenLayerOption { public static final boolean DEBUG = Debug.debug("Window"); diff --git a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java index 0fc1b4e89..a89ccaedb 100644 --- a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java +++ b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java @@ -51,6 +51,7 @@ import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLCapabilitiesImmutable; import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawable; import javax.media.opengl.GLDrawableFactory; import javax.media.opengl.GLEventListener; import javax.media.opengl.GLException; @@ -97,7 +98,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, false); + super(null, null, false /* always handle device lifecycle ourselves */); this.window = (WindowImpl) window; this.window.setHandleDestroyNotify(false); window.addWindowListener(new WindowAdapter() { @@ -107,8 +108,8 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind } @Override - public void windowResized(WindowEvent e) { - defaultWindowResizedOp(); + public void windowResized(WindowEvent e) { + defaultWindowResizedOp(getWidth(), getHeight()); } @Override @@ -201,11 +202,8 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind @Override public final CapabilitiesImmutable getChosenCapabilities() { - if (drawable == null) { - return window.getChosenCapabilities(); - } - - return drawable.getChosenGLCapabilities(); + final GLDrawable _drawable = drawable; + return null != _drawable ? _drawable.getChosenGLCapabilities() : window.getChosenCapabilities(); } @Override @@ -536,19 +534,24 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind return; } + final boolean done; final RecursiveLock lock = window.getLock(); lock.lock(); // sync: context/drawable could have been recreated/destroyed while animating try { if( null != context ) { // surface is locked/unlocked implicit by context's makeCurrent/release helper.invokeGL(drawable, context, defaultDisplayAction, defaultInitAction); - } else if( 0 display - setVisible(true); + done = true; + } else { + done = false; } } finally { lock.unlock(); } + if( !done && 0 display + setVisible(true); + } } //---------------------------------------------------------------------- diff --git a/src/newt/classes/com/jogamp/newt/swt/NewtCanvasSWT.java b/src/newt/classes/com/jogamp/newt/swt/NewtCanvasSWT.java index cada253bc..36bc3f28f 100644 --- a/src/newt/classes/com/jogamp/newt/swt/NewtCanvasSWT.java +++ b/src/newt/classes/com/jogamp/newt/swt/NewtCanvasSWT.java @@ -63,6 +63,9 @@ import com.jogamp.newt.Window; import com.jogamp.newt.event.WindowEvent; import com.jogamp.newt.util.EDTUtil; +/** + * SWT {@link Canvas} containing a NEWT {@link Window} using native parenting. + */ 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); diff --git a/src/newt/classes/jogamp/newt/OffscreenWindow.java b/src/newt/classes/jogamp/newt/OffscreenWindow.java index ba98ca3af..c6c1814f6 100644 --- a/src/newt/classes/jogamp/newt/OffscreenWindow.java +++ b/src/newt/classes/jogamp/newt/OffscreenWindow.java @@ -39,20 +39,16 @@ 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 MutableSurface { - long surfaceHandle = 0; - ProxySurface.UpstreamSurfaceHook upstreamHook; - ProxySurface dummySurface; + long surfaceHandle; public OffscreenWindow() { - upstreamHook = null; - dummySurface = null; + surfaceHandle = 0; } static long nextWindowHandle = 0x100; // start here - a marker @@ -62,17 +58,6 @@ public class OffscreenWindow extends WindowImpl implements MutableSurface { throw new NativeWindowException("Capabilities is onscreen"); } final AbstractGraphicsScreen aScreen = getScreen().getGraphicsScreen(); - /** Cannot use OpenGL here .. - if(capsRequested instanceof GLCapabilitiesImmutable) { - final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) capsRequested; - if(caps.isFBO() && GLContext.isFBOAvailable(aScreen.getDevice(), caps.getGLProfile()) ) { - final GLDrawableFactoryImpl factory = (GLDrawableFactoryImpl) GLDrawableFactory.getFactory(caps.getGLProfile()); - final GLCapabilitiesImmutable dummyCaps = GLGraphicsConfigurationUtil.fixOnscreenGLCapabilities(caps); - final ProxySurface dummySurface = factory.createDummySurfaceImpl(aScreen.getDevice(), false, dummyCaps, null, 64, 64); - upstreamHook = dummySurface.getUpstreamSurfaceHook(); - dummySurface.createNotify(); - } - } */ final AbstractGraphicsConfiguration cfg = GraphicsConfigurationFactory.getFactory(aScreen.getDevice(), capsRequested).chooseGraphicsConfiguration( capsRequested, capsRequested, capabilitiesChooser, aScreen, VisualIDHolder.VID_UNDEFINED); if (null == cfg) { @@ -83,6 +68,7 @@ public class OffscreenWindow extends WindowImpl implements MutableSurface { synchronized(OffscreenWindow.class) { setWindowHandle(nextWindowHandle++); } + visibleChanged(false, true); } protected void closeNativeImpl() { @@ -92,11 +78,6 @@ public class OffscreenWindow extends WindowImpl implements MutableSurface { @Override public synchronized void destroy() { super.destroy(); - if(null != dummySurface) { - dummySurface.destroyNotify(); - dummySurface = null; - upstreamHook = null; - } surfaceHandle = 0; } @@ -106,10 +87,6 @@ public class OffscreenWindow extends WindowImpl implements MutableSurface { @Override public long getSurfaceHandle() { - if(null != dummySurface) { - return dummySurface.getSurfaceHandle(); - // return upstreamHook.getWidth(); - } return surfaceHandle; } @@ -128,8 +105,8 @@ public class OffscreenWindow extends WindowImpl implements MutableSurface { } protected boolean reconfigureWindowImpl(int x, int y, int width, int height, int flags) { + sizeChanged(false, width, height, false); if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) ) { - sizeChanged(false, width, height, false); visibleChanged(false, 0 != ( FLAG_IS_VISIBLE & flags)); } else { /** diff --git a/src/newt/classes/jogamp/newt/WindowImpl.java b/src/newt/classes/jogamp/newt/WindowImpl.java index ad7195944..c1ac87d38 100644 --- a/src/newt/classes/jogamp/newt/WindowImpl.java +++ b/src/newt/classes/jogamp/newt/WindowImpl.java @@ -767,11 +767,15 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } } - public void setVisible(boolean visible) { + protected void setVisible(boolean wait, boolean visible) { if(DEBUG_IMPLEMENTATION) { System.err.println("Window setVisible: START ("+getThreadName()+") "+getX()+"/"+getY()+" "+getWidth()+"x"+getHeight()+", fs "+fullscreen+", windowHandle "+toHexString(windowHandle)+", visible: "+this.visible+" -> "+visible+", parentWindowHandle "+toHexString(parentWindowHandle)+", parentWindow "+(null!=parentWindow)); } - runOnEDTIfAvail(true, new VisibleAction(visible)); + runOnEDTIfAvail(wait, new VisibleAction(visible)); + } + + public void setVisible(boolean visible) { + setVisible(true, visible); } private class SetSizeAction implements Runnable { @@ -783,21 +787,12 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } public final void run() { - boolean recreate = false; final RecursiveLock _lock = windowLock; _lock.lock(); try { if ( !isFullscreen() && ( getWidth() != width || getHeight() != height ) ) { - recreate = isNativeValid() && !getGraphicsConfiguration().getChosenCapabilities().isOnscreen(); if(DEBUG_IMPLEMENTATION) { - System.err.println("Window setSize: START "+getWidth()+"x"+getHeight()+" -> "+width+"x"+height+", fs "+fullscreen+", windowHandle "+toHexString(windowHandle)+", visible "+visible+", recreate "+recreate); - } - if(recreate) { - // will trigger visibleAction:=2 -> create if wasVisible - final boolean wasVisible = WindowImpl.this.visible; - screen.addReference(); // retain screen - destroyAction.run(); - WindowImpl.this.visible = wasVisible; + System.err.println("Window setSize: START "+getWidth()+"x"+getHeight()+" -> "+width+"x"+height+", fs "+fullscreen+", windowHandle "+toHexString(windowHandle)+", visible "+visible); } int visibleAction; // 0 nop, 1 invisible, 2 visible (create) if ( isNativeValid() && 0>=width*height && visible ) { @@ -823,9 +818,6 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } } } finally { - if(recreate) { - screen.removeReference(); // bring back ref-count - } _lock.unlock(); } } @@ -940,11 +932,15 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer */ protected static boolean isOffscreenInstance(NativeWindow cWin, NativeWindow pWin) { boolean ofs = false; - if( null != cWin.getGraphicsConfiguration() ) { - ofs = !cWin.getGraphicsConfiguration().getChosenCapabilities().isOnscreen(); + final AbstractGraphicsConfiguration cWinCfg = cWin.getGraphicsConfiguration(); + if( null != cWinCfg ) { + ofs = !cWinCfg.getChosenCapabilities().isOnscreen(); } - if( !ofs && null != pWin && null != pWin.getGraphicsConfiguration() ) { - ofs |= !pWin.getGraphicsConfiguration().getChosenCapabilities().isOnscreen(); + if( !ofs && null != pWin ) { + final AbstractGraphicsConfiguration pWinCfg = pWin.getGraphicsConfiguration(); + if( null != pWinCfg ) { + ofs = !pWinCfg.getChosenCapabilities().isOnscreen(); + } } return ofs; } diff --git a/src/newt/classes/jogamp/newt/driver/android/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/android/WindowDriver.java index 276b0d070..f18520630 100644 --- a/src/newt/classes/jogamp/newt/driver/android/WindowDriver.java +++ b/src/newt/classes/jogamp/newt/driver/android/WindowDriver.java @@ -428,7 +428,7 @@ public class WindowDriver extends jogamp.newt.WindowImpl implements Callback2 { getX()+"/"+getY()+" "+nWidth+"x"+nHeight+", visible: "+isVisible()); if(isVisible()) { - setVisible(true); + setVisible(false, true); } } sizeChanged(false, aWidth, aHeight, false); diff --git a/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java index ea48569bf..d0c0b8b20 100644 --- a/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java +++ b/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java @@ -117,6 +117,7 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl return 0 != sscSurfaceHandle ? sscSurfaceHandle : surfaceHandle; } + @Override public void setSurfaceHandle(long surfaceHandle) { if(DEBUG_IMPLEMENTATION) { System.err.println("MacWindow.setSurfaceHandle(): 0x"+Long.toHexString(surfaceHandle)); @@ -170,13 +171,22 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl protected boolean reconfigureWindowImpl(int x, int y, int width, int height, int flags) { - final Point pS = getTopLevelLocationOnScreen(x, y); - isOffscreenInstance = 0 != sscSurfaceHandle || isOffscreenInstance(this, this.getParent()); + final boolean _isOffscreenInstance = isOffscreenInstance(this, this.getParent()); + isOffscreenInstance = 0 != sscSurfaceHandle || _isOffscreenInstance; + final PointImmutable pS = isOffscreenInstance ? new Point(0, 0) : getTopLevelLocationOnScreen(x, y); if(DEBUG_IMPLEMENTATION) { + final AbstractGraphicsConfiguration cWinCfg = this.getGraphicsConfiguration(); + final NativeWindow pWin = getParent(); + final AbstractGraphicsConfiguration pWinCfg = null != pWin ? pWin.getGraphicsConfiguration() : null; System.err.println("MacWindow reconfig: "+x+"/"+y+" -> "+pS+" - "+width+"x"+height+ - ", offscreenInstance "+isOffscreenInstance+ - ", "+getReconfigureFlagsAsString(null, flags)); + ",\n\t parent type "+(null != pWin ? pWin.getClass().getName() : null)+ + ",\n\t this-chosenCaps "+(null != cWinCfg ? cWinCfg.getChosenCapabilities() : null)+ + ",\n\t parent-chosenCaps "+(null != pWinCfg ? pWinCfg.getChosenCapabilities() : null)+ + ", isOffscreenInstance(sscSurfaceHandle "+toHexString(sscSurfaceHandle)+ + ", ioi: "+_isOffscreenInstance+ + ") -> "+isOffscreenInstance+ + "\n\t, "+getReconfigureFlagsAsString(null, flags)); } if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) && 0 == ( FLAG_IS_VISIBLE & flags) ) { @@ -190,7 +200,11 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl 0 != ( FLAG_CHANGE_DECORATION & flags) || 0 != ( FLAG_CHANGE_PARENTING & flags) || 0 != ( FLAG_CHANGE_FULLSCREEN & flags) ) { - createWindow(isOffscreenInstance, 0 != getWindowHandle(), pS, width, height, 0 != ( FLAG_IS_FULLSCREEN & flags)); + if(isOffscreenInstance) { + createWindow(true, 0 != getWindowHandle(), pS, 64, 64, false); + } else { + createWindow(false, 0 != getWindowHandle(), pS, width, height, 0 != ( FLAG_IS_FULLSCREEN & flags)); + } if(isVisible()) { flags |= FLAG_CHANGE_VISIBILITY; } } if(x>=0 && y>=0) { diff --git a/src/newt/native/MacWindow.m b/src/newt/native/MacWindow.m index e0330a563..b9c339285 100644 --- a/src/newt/native/MacWindow.m +++ b/src/newt/native/MacWindow.m @@ -94,7 +94,13 @@ static void changeContentView(JNIEnv *env, jobject javaWindowObject, NSView *pvi if(NULL!=oldNSView) { NS_DURING // Available >= 10.5 - Makes the menubar disapear - if([oldNSView isInFullScreenMode]) { + BOOL iifs; + if ( [oldNSView respondsToSelector:@selector(isInFullScreenMode)] ) { + iifs = [oldNSView isInFullScreenMode]; + } else { + iifs = NO; + } + if(iifs && [oldNSView respondsToSelector:@selector(exitFullScreenModeWithOptions:)] ) { [oldNSView exitFullScreenModeWithOptions: NULL]; } NS_HANDLER @@ -430,6 +436,8 @@ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_getScree if( -1 < mode_idx ) { prop[propIndex++] = mode_idx; } + int refreshRate = CGDDGetModeRefreshRate(mode); + int fRefreshRate = ( 0 < refreshRate ) ? refreshRate : 60; // default .. (experienced on OSX 10.6.8) prop[propIndex++] = 0; // set later for verification of iterator propIndexRes = propIndex; prop[propIndex++] = mWidth; @@ -437,14 +445,14 @@ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_getScree prop[propIndex++] = CGDDGetModeBitsPerPixel(mode); prop[propIndex++] = widthMM; prop[propIndex++] = heightMM; - prop[propIndex++] = CGDDGetModeRefreshRate(mode); + prop[propIndex++] = fRefreshRate; prop[propIndex++] = ccwRot; prop[propIndex - NUM_SCREEN_MODE_PROPERTIES_ALL] = ( -1 < mode_idx ) ? propIndex-1 : propIndex ; // count == NUM_SCREEN_MODE_PROPERTIES_ALL - DBG_PRINT( "getScreenMode0: Mode %d/%d (%d): %dx%d, %d bpp, %dx%d mm, %d Hz, rot %d ccw\n", + DBG_PRINT( "getScreenMode0: Mode %d/%d (%d): %dx%d, %d bpp, %dx%d mm, %d / %d Hz, rot %d ccw\n", (int)mode_idx, (int)numberOfAvailableModesRots, (int)numberOfAvailableModes, (int)prop[propIndexRes+0], (int)prop[propIndexRes+1], (int)prop[propIndexRes+2], - (int)prop[propIndexRes+3], (int)prop[propIndexRes+4], (int)prop[propIndexRes+5], (int)prop[propIndexRes+6]); + (int)prop[propIndexRes+3], (int)prop[propIndexRes+4], (int)prop[propIndexRes+5], refreshRate, (int)prop[propIndexRes+6]); jintArray properties = (*env)->NewIntArray(env, prop_num); if (properties == NULL) { @@ -516,6 +524,8 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_initIDs0 if(initialized) return JNI_TRUE; initialized = 1; + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + jclass c; c = (*env)->FindClass(env, ClazzNamePoint); if(NULL==c) { @@ -537,7 +547,10 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_initIDs0 // printf("Going to sleep for 10 seconds\n"); // sleep(10); - return (jboolean) [NewtMacWindow initNatives: env forClass: clazz]; + BOOL res = [NewtMacWindow initNatives: env forClass: clazz]; + [pool release]; + + return (jboolean) res; } /* @@ -602,8 +615,10 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_createWindow // Remove animations for child windows if(NULL != parentWindow) { NS_DURING - // Available >= 10.7 - Removes default animations - [myWindow setAnimationBehavior: NSWindowAnimationBehaviorNone]; + if ( [myWindow respondsToSelector:@selector(setAnimationBehavior:)] ) { + // Available >= 10.7 - Removes default animations + [myWindow setAnimationBehavior: NSWindowAnimationBehaviorNone]; + } NS_HANDLER NS_ENDHANDLER } @@ -658,8 +673,12 @@ NS_ENDHANDLER NS_DURING // concurrent view rendering // Available >= 10.6 - Makes the menubar disapear - [myWindow setAllowsConcurrentViewDrawing: YES]; - [myView setCanDrawConcurrently: YES]; + if ( [myWindow respondsToSelector:@selector(setAllowsConcurrentViewDrawing:)] ) { + [myWindow setAllowsConcurrentViewDrawing: YES]; + } + if ( [myView respondsToSelector:@selector(setCanDrawConcurrently:)] ) { + [myView setCanDrawConcurrently: YES]; + } NS_HANDLER NS_ENDHANDLER @@ -669,7 +688,9 @@ NS_ENDHANDLER NS_DURING // Available >= 10.5 - Makes the menubar disapear if(fullscreen) { - [myView enterFullScreenMode: myScreen withOptions:NULL]; + if ( [myView respondsToSelector:@selector(enterFullScreenMode:withOptions:)] ) { + [myView enterFullScreenMode: myScreen withOptions:NULL]; + } } NS_HANDLER NS_ENDHANDLER @@ -730,7 +751,13 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_close0 NS_DURING if(NULL!=mView) { // Available >= 10.5 - Makes the menubar disapear - if([mView isInFullScreenMode]) { + BOOL iifs; + if ( [mView respondsToSelector:@selector(isInFullScreenMode)] ) { + iifs = [mView isInFullScreenMode]; + } else { + iifs = NO; + } + if(iifs && [mView respondsToSelector:@selector(exitFullScreenModeWithOptions:)] ) { [mView exitFullScreenModeWithOptions: NULL]; } // Note: mWin's release will also release it's mView! diff --git a/src/test/com/jogamp/opengl/test/android/MovieCubeActivityLauncher0.java b/src/test/com/jogamp/opengl/test/android/MovieCubeActivityLauncher0.java index 4f24fc9b8..c4b74c56f 100644 --- a/src/test/com/jogamp/opengl/test/android/MovieCubeActivityLauncher0.java +++ b/src/test/com/jogamp/opengl/test/android/MovieCubeActivityLauncher0.java @@ -50,6 +50,8 @@ public class MovieCubeActivityLauncher0 extends LauncherUtil.BaseActivityLaunche // props.setProperty("jogamp.debug.NativeLibrary", "true"); // props.setProperty("jogamp.debug.NativeLibrary.Lookup", "true"); // props.setProperty("jogamp.debug.IOUtil", "true"); + // props.setProperty("jogamp.debug.Lock", "true"); + // props.setProperty("jogamp.debug.Lock.TraceLock", "true"); // props.setProperty("nativewindow.debug", "all"); props.setProperty("nativewindow.debug.GraphicsConfiguration", "true"); // props.setProperty("jogl.debug", "all"); diff --git a/src/test/com/jogamp/opengl/test/android/NEWTGraphUI1pActivityLauncher.java b/src/test/com/jogamp/opengl/test/android/NEWTGraphUI1pActivityLauncher.java index c75c229a8..576305835 100644 --- a/src/test/com/jogamp/opengl/test/android/NEWTGraphUI1pActivityLauncher.java +++ b/src/test/com/jogamp/opengl/test/android/NEWTGraphUI1pActivityLauncher.java @@ -14,23 +14,23 @@ public class NEWTGraphUI1pActivityLauncher extends LauncherUtil.BaseActivityLaun final OrderedProperties props = getProperties(); // props.setProperty("jogamp.debug.JNILibLoader", "true"); // props.setProperty("jogamp.debug.NativeLibrary", "true"); - // properties.setProperty("jogamp.debug.NativeLibrary.Lookup", "true"); - // properties.setProperty("jogamp.debug.IOUtil", "true"); - // properties.setProperty("nativewindow.debug", "all"); + // props.setProperty("jogamp.debug.NativeLibrary.Lookup", "true"); + // props.setProperty("jogamp.debug.IOUtil", "true"); + // props.setProperty("nativewindow.debug", "all"); props.setProperty("nativewindow.debug.GraphicsConfiguration", "true"); - // properties.setProperty("jogl.debug", "all"); - // properties.setProperty("jogl.debug.GLProfile", "true"); + // props.setProperty("jogl.debug", "all"); + // props.setProperty("jogl.debug.GLProfile", "true"); props.setProperty("jogl.debug.GLDrawable", "true"); props.setProperty("jogl.debug.GLContext", "true"); props.setProperty("jogl.debug.GLSLCode", "true"); props.setProperty("jogl.debug.CapabilitiesChooser", "true"); - // properties.setProperty("jogl.debug.GLSLState", "true"); - // properties.setProperty("jogl.debug.DebugGL", "true"); - // properties.setProperty("jogl.debug.TraceGL", "true"); - // properties.setProperty("newt.debug", "all"); + // props.setProperty("jogl.debug.GLSLState", "true"); + // props.setProperty("jogl.debug.DebugGL", "true"); + // props.setProperty("jogl.debug.TraceGL", "true"); + // props.setProperty("newt.debug", "all"); props.setProperty("newt.debug.Window", "true"); - // properties.setProperty("newt.debug.Window.MouseEvent", "true"); - // properties.setProperty("newt.debug.Window.KeyEvent", "true"); + // props.setProperty("newt.debug.Window.MouseEvent", "true"); + // props.setProperty("newt.debug.Window.KeyEvent", "true"); } @Override diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOAutoDrawableDeadlockAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOAutoDrawableDeadlockAWT.java new file mode 100644 index 000000000..eab1a37e3 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOAutoDrawableDeadlockAWT.java @@ -0,0 +1,128 @@ +/** + * Copyright 2011 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.opengl.test.junit.jogl.acore; + +import java.awt.EventQueue; +import java.lang.reflect.InvocationTargetException; + +import javax.media.opengl.DefaultGLCapabilitiesChooser; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLOffscreenAutoDrawable; +import javax.media.opengl.GLProfile; + +import jogamp.nativewindow.jawt.JAWTUtil; + +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.jogamp.common.util.RunnableTask; +import com.jogamp.opengl.test.junit.util.UITestCase; + +public class TestFBOAutoDrawableDeadlockAWT extends UITestCase { + static GLProfile glp; + static int width, height; + + @BeforeClass + public static void initClass() { + glp = GLProfile.getGL2ES2(); + Assert.assertNotNull( glp ); + width = 512; + height = 512; + } + + protected void runTestGL( GLCapabilities caps ) throws InterruptedException, InvocationTargetException { + final GLOffscreenAutoDrawable fbod = GLDrawableFactory.getFactory(caps.getGLProfile()).createOffscreenAutoDrawable( + null, + caps, new DefaultGLCapabilitiesChooser(), + 512, 512, + null + ); + + final boolean[] done = {false}; + final Runnable pbufferCreationAction = new Runnable() { + public void run() { + System.err.println("AA.1"); + fbod.display(); + done[ 0 ] = true; + System.err.println("AA.X"); + } + }; + + EventQueue.invokeAndWait(new Runnable() { + public void run() { + Assert.assertTrue(EventQueue.isDispatchThread()); + JAWTUtil.lockToolkit(); + try { + final RunnableTask rTask = new RunnableTask(pbufferCreationAction, new Object(), false); + System.err.println("BB.0: "+rTask.getSyncObject()); + synchronized (rTask.getSyncObject()) { + System.err.println("BB.1: "+rTask.getSyncObject()); + new Thread(rTask, Thread.currentThread().getName()+"-Pbuffer_Creation").start(); + try { + System.err.println("BB.2"); + rTask.getSyncObject().wait(); + System.err.println("BB.3"); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + System.err.println("BB.X"); + } + } finally { + JAWTUtil.unlockToolkit(); + } + } + }); + Assert.assertTrue(done[0]); + fbod.destroy(); + } + + @Test(timeout = 2000) // 2s timeout + public void testDeadlock() throws InterruptedException, InvocationTargetException { + GLCapabilities caps = new GLCapabilities( glp ); + runTestGL( caps ); + } + + static long duration = 500; // ms + + public static void main( String args[] ) { + for ( int i = 0; i < args.length; i++ ) { + if ( args[ i ].equals( "-time" ) ) { + i++; + try { + duration = Integer.parseInt( args[ i ] ); + } + catch ( Exception ex ) { + ex.printStackTrace(); + } + } + } + org.junit.runner.JUnitCore.main( TestFBOAutoDrawableDeadlockAWT.class.getName() ); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOAutoDrawableFactoryNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOAutoDrawableFactoryNEWT.java new file mode 100644 index 000000000..2dc547f39 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOAutoDrawableFactoryNEWT.java @@ -0,0 +1,375 @@ +/** + * 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.GLCapabilities; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLOffscreenAutoDrawable; +import javax.media.opengl.GLProfile; + +import org.junit.Assert; +import org.junit.Test; + +import com.jogamp.opengl.FBObject; +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.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.UITestCase; + +/** + * Toolkit agnostic {@link GLOffscreenAutoDrawable.FBO} tests using the + * {@link GLDrawableFactory#createOffscreenAutoDrawable(javax.media.nativewindow.AbstractGraphicsDevice, GLCapabilitiesImmutable, javax.media.opengl.GLCapabilitiesChooser, int, int, GLContext) factory model}. + *

      + * The created {@link GLOffscreenAutoDrawable.FBO} is being used to run the {@link GLEventListener}. + *

      + *

      + * Extensive FBO reconfiguration (size and sample buffer count) and validation are performed. + *

      + */ +public class TestFBOAutoDrawableFactoryNEWT extends UITestCase { + + static final int widthStep = 800/4; + static final int heightStep = 600/4; + volatile int szStep = 2; + + interface MyGLEventListener extends GLEventListener { + void setMakeSnapshot(); + } + + @Test + public void testGL2ES2_Demo1_SingleBuffer_Normal() throws InterruptedException { + final GLProfile glp = GLProfile.getGL2ES2(); + final GLCapabilities caps = new GLCapabilities(glp); + caps.setDoubleBuffered(false); + testGLFBODrawableImpl(caps, new GearsES2(0)); + } + + @Test + public void testGL2ES2_Demo1_DoubleBuffer_Normal() throws InterruptedException { + final GLProfile glp = GLProfile.getGL2ES2(); + final GLCapabilities caps = new GLCapabilities(glp); + caps.setDoubleBuffered(true); // default + testGLFBODrawableImpl(caps, new GearsES2(0)); + } + + @Test + public void testGL2ES2_Demo2MSAA4() throws InterruptedException { + final GLProfile glp = GLProfile.getGL2ES2(); + final GLCapabilities caps = new GLCapabilities(glp); + caps.setSampleBuffers(true); + caps.setNumSamples(4); + testGLFBODrawableImpl(caps, new MultisampleDemoES2(true)); + } + + @Test + public void testGL2ES2_FBODemoMSAA4() throws InterruptedException { + final GLProfile glp = GLProfile.getGL2ES2(); + final FBOMix2DemosES2 demo = new FBOMix2DemosES2(0); + demo.setDoRotation(false); + final GLCapabilities caps = new GLCapabilities(glp); + caps.setSampleBuffers(true); + caps.setNumSamples(4); + testGLFBODrawableImpl(caps, demo); + } + + @Test + public void testEGLES2_Demo0Normal() throws InterruptedException { + if( GLProfile.isAvailable(GLProfile.GLES2) ) { + final GLProfile glp = GLProfile.get(GLProfile.GLES2); + final GLCapabilities caps = new GLCapabilities(glp); + testGLFBODrawableImpl(caps, new GearsES2(0)); + } else { + System.err.println("EGL ES2 n/a"); + } + } + + @Test + public void testEGLES2_Demo0MSAA4() throws InterruptedException { + if( GLProfile.isAvailable(GLProfile.GLES2) ) { + final GLProfile glp = GLProfile.get(GLProfile.GLES2); + final GLCapabilities caps = new GLCapabilities(glp); + caps.setSampleBuffers(true); + caps.setNumSamples(4); + testGLFBODrawableImpl(caps, new GearsES2(0)); + } else { + System.err.println("EGL ES2 n/a"); + } + } + + void testGLFBODrawableImpl(GLCapabilities caps, GLEventListener demo) throws InterruptedException { + caps.setFBO(true); + final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile()); + final GLOffscreenAutoDrawable.FBO glad = (GLOffscreenAutoDrawable.FBO) + factory.createOffscreenAutoDrawable(null, caps, null, widthStep*szStep, heightStep*szStep, null); + Assert.assertNotNull(glad); + + System.out.println("Realized GLAD: "+glad); + System.out.println("Realized GLAD: "+glad.getChosenGLCapabilities()); + Assert.assertTrue("FBO drawable is initialized before ctx creation", !glad.isInitialized()); + + glad.display(); // initial display incl. init! + { + final GLContext context = glad.getContext(); + Assert.assertNotNull(context); + Assert.assertTrue(context.isCreated()); + } + Assert.assertTrue("FBO drawable is not initialized after ctx creation", glad.isInitialized()); + + // + // FBO incl. MSAA is fully initialized now + // + + final GLCapabilitiesImmutable chosenCaps = glad.getChosenGLCapabilities(); + System.out.println("Init GLAD: "+glad); + System.out.println("Init GLAD: "+chosenCaps); + + final FBObject fboFront = glad.getFBObject(GL.GL_FRONT); + final FBObject fboBack = glad.getFBObject(GL.GL_BACK); + + System.out.println("Init front FBO: "+fboFront); + System.out.println("Init back FBO: "+fboBack); + + Assert.assertTrue("FBO drawable is not initialized before ctx creation", glad.isInitialized()); + Assert.assertTrue("FBO Front is not initialized before ctx creation", fboFront.isInitialized()); + Assert.assertTrue("FBO Back is not initialized before ctx creation", fboBack.isInitialized()); + + if( chosenCaps.getDoubleBuffered() ) { + Assert.assertTrue("FBO are equal: "+fboFront+" == "+fboBack, !fboFront.equals(fboBack)); + Assert.assertNotSame(fboFront, fboBack); + } else { + Assert.assertTrue("FBO are not equal: "+fboFront+" != "+fboBack, fboFront.equals(fboBack)); + Assert.assertSame(fboFront, fboBack); + } + + final FBObject.TextureAttachment texAttachA, texAttachB; + + texAttachA = glad.getTextureBuffer(GL.GL_FRONT); + if(0==glad.getNumSamples()) { + texAttachB = glad.getTextureBuffer(GL.GL_BACK); + } else { + texAttachB = null; + } + + final FBObject.Colorbuffer colorA, colorB; + final FBObject.RenderAttachment depthA, depthB; + + colorA = fboFront.getColorbuffer(0); + Assert.assertNotNull(colorA); + colorB = fboBack.getColorbuffer(0); + Assert.assertNotNull(colorB); + + depthA = fboFront.getDepthAttachment(); + Assert.assertNotNull(depthA); + depthB = fboBack.getDepthAttachment(); + Assert.assertNotNull(depthB); + + glad.display(); // SWAP_ODD + + if( chosenCaps.getDoubleBuffered() ) { + // double buffer or MSAA + Assert.assertTrue("Color attachments are equal: "+colorB+" == "+colorA, !colorB.equals(colorA)); + Assert.assertNotSame(colorB, colorA); + Assert.assertTrue("Depth attachments are equal: "+depthB+" == "+depthA, !depthB.equals(depthA)); + Assert.assertNotSame(depthB, depthA); + } else { + // single buffer + Assert.assertEquals(colorA, colorB); + Assert.assertSame(colorA, colorB); + Assert.assertEquals(depthA, depthB); + Assert.assertSame(depthA, depthB); + } + + Assert.assertEquals(texAttachA, colorA); + Assert.assertSame(texAttachA, colorA); + if(0==glad.getNumSamples()) { + Assert.assertEquals(texAttachB, colorB); + Assert.assertSame(texAttachB, colorB); + } + + if( chosenCaps.getNumSamples() > 0 ) { + // MSAA + FBObject _fboFront = glad.getFBObject(GL.GL_FRONT); + FBObject _fboBack = glad.getFBObject(GL.GL_BACK); + Assert.assertTrue("FBO are not equal: "+fboFront+" != "+_fboFront, fboFront.equals(_fboFront)); + Assert.assertSame(fboFront, _fboFront); + Assert.assertTrue("FBO are not equal: "+fboBack+" != "+_fboBack, fboBack.equals(_fboBack)); + Assert.assertSame(fboBack, _fboBack); + } else if( chosenCaps.getDoubleBuffered() ) { + // real double buffer + FBObject _fboFront = glad.getFBObject(GL.GL_FRONT); + FBObject _fboBack = glad.getFBObject(GL.GL_BACK); + Assert.assertTrue("FBO are not equal: "+fboBack+" != "+_fboFront, fboBack.equals(_fboFront)); + Assert.assertSame(fboBack, _fboFront); + Assert.assertTrue("FBO are not equal: "+fboFront+" != "+_fboBack, fboFront.equals(_fboBack)); + Assert.assertSame(fboFront, _fboBack); + } else { + // single buffer + FBObject _fboFront = glad.getFBObject(GL.GL_FRONT); + FBObject _fboBack = glad.getFBObject(GL.GL_BACK); + Assert.assertTrue("FBO are not equal: "+fboFront+" != "+_fboFront, fboFront.equals(_fboFront)); + Assert.assertSame(fboFront, _fboFront); + Assert.assertTrue("FBO are not equal: "+fboBack+" != "+_fboFront, fboBack.equals(_fboFront)); + Assert.assertSame(fboBack, _fboFront); + Assert.assertTrue("FBO are not equal: "+fboBack+" != "+_fboBack, fboBack.equals(_fboBack)); + Assert.assertSame(fboBack, _fboBack); + Assert.assertTrue("FBO are not equal: "+fboFront+" != "+_fboBack, fboFront.equals(_fboBack)); + Assert.assertSame(fboFront, _fboBack); + } + + glad.addGLEventListener(demo); + + final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener(); + glad.addGLEventListener(snapshotGLEventListener); + + glad.display(); // - SWAP_EVEN + + // 1 - szStep = 2 + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); // - SWAP_ODD + + // 2, 3 (resize + display) + szStep = 1; + glad.setSize(widthStep*szStep, heightStep*szStep); // SWAP_EVEN + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); // - SWAP_ODD + glad.display(); // - SWAP_EVEN + { + // Check whether the attachment reference are still valid! + final FBObject _fboFront = glad.getFBObject(GL.GL_FRONT); + final FBObject _fboBack = glad.getFBObject(GL.GL_BACK); + System.out.println("Resize1.oldFront: "+fboFront); + System.out.println("Resize1.nowFront: "+_fboFront); + System.out.println("Resize1.oldBack : "+fboBack); + System.out.println("Resize1.nowBack : "+_fboBack); + Assert.assertEquals(fboFront, _fboFront); + Assert.assertSame(fboFront, _fboFront); + Assert.assertEquals(fboBack, _fboBack); + Assert.assertSame(fboBack, _fboBack); + + FBObject.Colorbuffer _color = _fboFront.getColorbuffer(0); + Assert.assertNotNull(_color); + Assert.assertEquals(colorA, _color); + Assert.assertSame(colorA, _color); + + FBObject.RenderAttachment _depth = _fboFront.getDepthAttachment(); + System.err.println("Resize1.oldDepth "+depthA); + System.err.println("Resize1.newDepth "+_depth); + Assert.assertNotNull(_depth); + + Assert.assertEquals(depthA, _depth); + Assert.assertSame(depthA, _depth); + _depth = _fboBack.getDepthAttachment(); + Assert.assertNotNull(_depth); + Assert.assertEquals(depthB, _depth); + Assert.assertSame(depthB, _depth); + + _color = _fboFront.getColorbuffer(colorA); + Assert.assertNotNull(_color); + Assert.assertEquals(colorA, _color); + Assert.assertSame(colorA, _color); + } + + // 4, 5 (resize + display) + szStep = 4; + glad.setSize(widthStep*szStep, heightStep*szStep); // SWAP_ODD + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); // - SWAP_EVEN + glad.display(); // - SWAP_ODD + { + // Check whether the attachment reference are still valid! + final FBObject _fboFront = glad.getFBObject(GL.GL_FRONT); + final FBObject _fboBack = glad.getFBObject(GL.GL_BACK); + System.out.println("Resize2.oldFront: "+fboFront); + System.out.println("Resize2.nowFront: "+_fboFront); + System.out.println("Resize2.oldBack : "+fboBack); + System.out.println("Resize2.nowBack : "+_fboBack); + if(chosenCaps.getDoubleBuffered() && 0==chosenCaps.getNumSamples()) { + // real double buffer + Assert.assertEquals(fboBack, _fboFront); + Assert.assertEquals(fboFront, _fboBack); + } else { + // single or MSAA + Assert.assertEquals(fboFront, _fboFront); + Assert.assertEquals(fboBack, _fboBack); + } + + FBObject.Colorbuffer _color = fboBack.getColorbuffer(0); + Assert.assertNotNull(_color); + Assert.assertEquals(colorB, _color); + Assert.assertSame(colorB, _color); + + FBObject.RenderAttachment _depth = fboBack.getDepthAttachment(); + Assert.assertNotNull(_depth); // MSAA back w/ depth + Assert.assertEquals(depthB, _depth); + Assert.assertSame(depthB, _depth); + + _depth = fboFront.getDepthAttachment(); + Assert.assertNotNull(_depth); + Assert.assertEquals(depthA, _depth); + Assert.assertSame(depthA, _depth); + + _color = fboBack.getColorbuffer(colorB); + Assert.assertNotNull(_color); + Assert.assertEquals(colorB, _color); + Assert.assertSame(colorB, _color); + } + + // 6 + 7 (samples + display) + glad.setNumSamples(glad.getGL(), chosenCaps.getNumSamples() > 0 ? 0 : 4); // triggers repaint + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); // actual screenshot + + // 8, 9 (resize + samples + display) + szStep = 3; + glad.setSize(widthStep*szStep, heightStep*szStep); + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + glad.destroy(); + System.out.println("Fin: "+glad); + } + + public static void main(String args[]) throws IOException { + org.junit.runner.JUnitCore.main(TestFBOAutoDrawableFactoryNEWT.class.getName()); + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBODrawableNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBODrawableNEWT.java deleted file mode 100644 index 7977347a7..000000000 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBODrawableNEWT.java +++ /dev/null @@ -1,272 +0,0 @@ -/** - * Copyright 2012 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ - -package com.jogamp.opengl.test.junit.jogl.acore; - -import java.io.IOException; - -import javax.media.opengl.GL; -import javax.media.opengl.GLAutoDrawable; -import javax.media.opengl.GLCapabilities; -import javax.media.opengl.GLContext; -import javax.media.opengl.GLDrawable; -import javax.media.opengl.GLDrawableFactory; -import javax.media.opengl.GLEventListener; -import javax.media.opengl.GLProfile; - -import jogamp.opengl.GLFBODrawableImpl; - -import org.junit.Assert; -import org.junit.Test; - -import com.jogamp.opengl.FBObject; -import com.jogamp.opengl.OffscreenAutoDrawable; -import com.jogamp.opengl.test.junit.jogl.demos.es2.FBOMix2DemosES2; -import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; -import com.jogamp.opengl.test.junit.jogl.demos.es2.MultisampleDemoES2; -import com.jogamp.opengl.test.junit.util.UITestCase; -import com.jogamp.opengl.util.GLReadBufferUtil; -import com.jogamp.opengl.util.texture.TextureIO; - -public class TestFBODrawableNEWT extends UITestCase { - - static final int widthStep = 800/4; - static final int heightStep = 600/4; - volatile int szStep = 2; - - @Test - public void testGL2ES2_Demo1Normal() throws InterruptedException { - final GLProfile glp = GLProfile.getGL2ES2(); - final GLCapabilities caps = new GLCapabilities(glp); - testGLFBODrawableImpl(caps, new GearsES2(0)); - } - - @Test - public void testGL2ES2_Demo1MSAA4() throws InterruptedException { - final GLProfile glp = GLProfile.getGL2ES2(); - final GLCapabilities caps = new GLCapabilities(glp); - caps.setSampleBuffers(true); - caps.setNumSamples(4); - testGLFBODrawableImpl(caps, new GearsES2(0)); - } - - @Test - public void testGL2ES2_Demo2Normal() throws InterruptedException { - final GLProfile glp = GLProfile.getGL2ES2(); - final GLCapabilities caps = new GLCapabilities(glp); - testGLFBODrawableImpl(caps, new MultisampleDemoES2(false)); - } - - @Test - public void testGL2ES2_Demo2MSAA4() throws InterruptedException { - final GLProfile glp = GLProfile.getGL2ES2(); - final GLCapabilities caps = new GLCapabilities(glp); - caps.setSampleBuffers(true); - caps.setNumSamples(4); - testGLFBODrawableImpl(caps, new MultisampleDemoES2(true)); - } - - @Test - public void testGL2ES2_FBODemoNormal() throws InterruptedException { - final GLProfile glp = GLProfile.getGL2ES2(); - final FBOMix2DemosES2 demo = new FBOMix2DemosES2(0); - demo.setDoRotation(false); - final GLCapabilities caps = new GLCapabilities(glp); - testGLFBODrawableImpl(caps, demo); - } - - @Test - public void testGL2ES2_FBODemoMSAA4() throws InterruptedException { - final GLProfile glp = GLProfile.getGL2ES2(); - final FBOMix2DemosES2 demo = new FBOMix2DemosES2(0); - demo.setDoRotation(false); - final GLCapabilities caps = new GLCapabilities(glp); - caps.setSampleBuffers(true); - caps.setNumSamples(4); - testGLFBODrawableImpl(caps, demo); - } - - @Test - public void testEGLES2_Demo0Normal() throws InterruptedException { - if( GLProfile.isAvailable(GLProfile.GLES2) ) { - final GLProfile glp = GLProfile.get(GLProfile.GLES2); - final GLCapabilities caps = new GLCapabilities(glp); - testGLFBODrawableImpl(caps, new GearsES2(0)); - } else { - System.err.println("EGL ES2 n/a"); - } - } - - @Test - public void testEGLES2_Demo0MSAA4() throws InterruptedException { - if( GLProfile.isAvailable(GLProfile.GLES2) ) { - final GLProfile glp = GLProfile.get(GLProfile.GLES2); - final GLCapabilities caps = new GLCapabilities(glp); - caps.setSampleBuffers(true); - caps.setNumSamples(4); - testGLFBODrawableImpl(caps, new GearsES2(0)); - } else { - System.err.println("EGL ES2 n/a"); - } - } - - boolean skipShot = false; - - void testGLFBODrawableImpl(GLCapabilities caps, GLEventListener demo) throws InterruptedException { - final GLReadBufferUtil screenshot = new GLReadBufferUtil(false, false); - caps.setFBO(true); - final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile()); - final GLDrawable fboDrawable = factory.createOffscreenDrawable(null, caps, null, widthStep*szStep, heightStep*szStep); - Assert.assertNotNull(fboDrawable); - Assert.assertTrue("Not an FBO Drawable", fboDrawable instanceof GLFBODrawableImpl); - - fboDrawable.setRealized(true); - Assert.assertTrue(fboDrawable.isRealized()); - - final FBObject fbo = ((GLFBODrawableImpl)fboDrawable).getFBObject(); - - System.out.println("Realized: "+fboDrawable); - System.out.println("Realized: "+fboDrawable.getChosenGLCapabilities()); - System.out.println("Realized: "+fbo); - - final GLContext context = fboDrawable.createContext(null); - Assert.assertNotNull(context); - - int res = context.makeCurrent(); - Assert.assertTrue(GLContext.CONTEXT_CURRENT_NEW==res || GLContext.CONTEXT_CURRENT==res); - context.release(); - - System.out.println("Post Create-Ctx: "+fbo); - final FBObject.Colorbuffer colorA = fbo.getColorbuffer(0); - Assert.assertNotNull(colorA); - final FBObject.RenderAttachment depthA = fbo.getDepthAttachment(); - Assert.assertNotNull(depthA); - - final OffscreenAutoDrawable glad = new OffscreenAutoDrawable(fboDrawable, context, true); - - glad.addGLEventListener(demo); - glad.addGLEventListener(new GLEventListener() { - volatile int displayCount=0; - volatile int reshapeCount=0; - public void init(GLAutoDrawable drawable) {} - public void dispose(GLAutoDrawable drawable) {} - public void display(GLAutoDrawable drawable) { - final GL gl = drawable.getGL(); - // System.err.println(Thread.currentThread().getName()+": ** display: "+displayCount+": step "+szStep+" "+drawable.getWidth()+"x"+drawable.getHeight()); - // System.err.println(Thread.currentThread().getName()+": ** FBO-THIS: "+fbo); - // System.err.println(Thread.currentThread().getName()+": ** FBO-SINK: "+fbo.getSamplingSinkFBO()); - // System.err.println(Thread.currentThread().getName()+": ** drawable-read: "+gl.getDefaultReadFramebuffer()); - if(skipShot) { - skipShot=false; - } else { - snapshot(getSimpleTestName("."), displayCount, "msaa"+fbo.getNumSamples(), gl, screenshot, TextureIO.PNG, null); - } - Assert.assertEquals(drawable.getWidth(), widthStep*szStep); - Assert.assertEquals(drawable.getHeight(), heightStep*szStep); - displayCount++; - } - public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { - System.err.println(Thread.currentThread().getName()+": ** reshape: "+reshapeCount+": step "+szStep+" "+width+"x"+height+" - "+drawable.getWidth()+"x"+drawable.getHeight()); - Assert.assertEquals(drawable.getWidth(), widthStep*szStep); - Assert.assertEquals(drawable.getHeight(), heightStep*szStep); - reshapeCount++; - } - }); - - // 0 - szStep = 2 - glad.display(); - - // 1, 2 (resize + display) - szStep = 1; - skipShot=true; - glad.setSize(widthStep*szStep, heightStep*szStep); - glad.display(); - Assert.assertEquals(glad.getWidth(), widthStep*szStep); - Assert.assertEquals(glad.getHeight(), heightStep*szStep); - { - // Check whether the attachment reference are still valid! - FBObject.Colorbuffer _colorA = fbo.getColorbuffer(0); - Assert.assertNotNull(_colorA); - Assert.assertTrue(colorA == _colorA); - Assert.assertTrue(colorA.equals(_colorA)); - FBObject.RenderAttachment _depthA = fbo.getDepthAttachment(); - Assert.assertNotNull(_depthA); - Assert.assertTrue(depthA == _depthA); - Assert.assertTrue(depthA.equals(_depthA)); - - _colorA = fbo.getColorbuffer(colorA); - Assert.assertNotNull(_colorA); - Assert.assertTrue(colorA == _colorA); - Assert.assertTrue(colorA.equals(_colorA)); - } - - // 3, 4 (resize + display) - szStep = 4; - skipShot=true; - glad.setSize(widthStep*szStep, heightStep*szStep); - glad.display(); - Assert.assertEquals(glad.getWidth(), widthStep*szStep); - Assert.assertEquals(glad.getHeight(), heightStep*szStep); - { - // Check whether the attachment reference are still valid! - FBObject.Colorbuffer _colorA = fbo.getColorbuffer(0); - Assert.assertNotNull(_colorA); - Assert.assertTrue(colorA == _colorA); - final FBObject.RenderAttachment _depthA = fbo.getDepthAttachment(); - Assert.assertNotNull(_depthA); - Assert.assertTrue(depthA == _depthA); - - _colorA = fbo.getColorbuffer(colorA); - Assert.assertNotNull(_colorA); - Assert.assertTrue(colorA == _colorA); - } - - // 5 - glad.display(); - Assert.assertEquals(glad.getWidth(), widthStep*szStep); - Assert.assertEquals(glad.getHeight(), heightStep*szStep); - - // 6, 7 (resize + display) - szStep = 3; - skipShot=true; - glad.setSize(widthStep*szStep, heightStep*szStep); - glad.display(); - Assert.assertEquals(glad.getWidth(), widthStep*szStep); - Assert.assertEquals(glad.getHeight(), heightStep*szStep); - - glad.destroy(); - System.out.println("Fin: "+fboDrawable); - - // final GLAutoDrawableDelegate glad = new GLAutoDrawableDelegate(fboDrawable, context); - } - - public static void main(String args[]) throws IOException { - org.junit.runner.JUnitCore.main(TestFBODrawableNEWT.class.getName()); - } - -} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMRTNEWT01.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMRTNEWT01.java index f7c83a03b..077baad43 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMRTNEWT01.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMRTNEWT01.java @@ -229,7 +229,7 @@ public class TestFBOMRTNEWT01 extends UITestCase { final NativeSurface ns = gl.getContext().getGLReadDrawable().getNativeSurface(); if(last_snap_size[0] != ns.getWidth() && last_snap_size[1] != ns.getHeight()) { gl.glFinish(); // sync .. no swap buffers yet! - snapshot(getSimpleTestName("."), step_i, null, gl, screenshot, TextureIO.PNG, null); // overwrite ok + snapshot(step_i, null, gl, screenshot, TextureIO.PNG, null); // overwrite ok last_snap_size[0] = ns.getWidth(); last_snap_size[1] = ns.getHeight(); } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMix2DemosES2NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMix2DemosES2NEWT.java index b384c9327..b3c542c63 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMix2DemosES2NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOMix2DemosES2NEWT.java @@ -106,7 +106,7 @@ public class TestFBOMix2DemosES2NEWT extends UITestCase { if(dw<800) { System.err.println("XXX: "+dw+"x"+dh+", c "+c); if(0 == c%3) { - snapshot(getSimpleTestName("."), i++, "msaa"+demo.getMSAA(), drawable.getGL(), screenshot, TextureIO.PNG, null); + snapshot(i++, "msaa"+demo.getMSAA(), drawable.getGL(), screenshot, TextureIO.PNG, null); } if( 3 == c ) { new Thread() { diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOOffThreadSharedContextMix2DemosES2NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOOffThreadSharedContextMix2DemosES2NEWT.java new file mode 100644 index 000000000..3ecf89bfc --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestFBOOffThreadSharedContextMix2DemosES2NEWT.java @@ -0,0 +1,298 @@ +/** + * Copyright 2012 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package com.jogamp.opengl.test.junit.jogl.acore; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + +import com.jogamp.newt.event.WindowEvent; +import com.jogamp.newt.event.WindowAdapter; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.test.junit.util.QuitAdapter; + +import com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.util.FPSAnimator; +import com.jogamp.opengl.util.GLReadBufferUtil; +import com.jogamp.opengl.util.texture.TextureIO; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.jogl.demos.es2.Mix2TexturesES2; +import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2; + +import javax.media.nativewindow.NativeSurface; +import javax.media.nativewindow.SurfaceUpdatedListener; +import javax.media.opengl.GL; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLOffscreenAutoDrawable; +import javax.media.opengl.GLProfile; + +import org.junit.Assert; +import org.junit.AfterClass; +import org.junit.Test; + +/** + * Toolkit agnostic {@link GLOffscreenAutoDrawable.FBO} tests using the + * {@link GLDrawableFactory#createOffscreenAutoDrawable(javax.media.nativewindow.AbstractGraphicsDevice, GLCapabilitiesImmutable, javax.media.opengl.GLCapabilitiesChooser, int, int, GLContext) factory model}. + *

      + * The created {@link GLOffscreenAutoDrawable.FBO} is being used to run the {@link GLEventListener}. + *

      + *

      + * This test simulates shared off-thread GL context / texture usage, + * where the producer use FBOs and delivers shared textures. + * The receiver blends the shared textures onscreen. + * In detail the test consist of: + *

        + *
      • 2 {@link GLOffscreenAutoDrawable.FBO} double buffered + *
          + *
        • each with their own {@link GLContext}, which is shares the {@link GLWindow} one (see below)
        • + *
        • both run within one {@link FPSAnimator} @ 30fps
        • + *
        • produce a texture
        • + *
        • notify the onscreen renderer about new textureID (swapping double buffer)
        • + *
      • + *
      • 1 onscreen {@link GLWindow} + *
          + *
        • shares it's {@link GLContext} w/ above FBOs
        • + *
        • running within one {@link Animator} at v-sync
        • + *
        • uses the shared FBO textures and blends them onscreen
        • + *
      • + *
      + *

      + */ +public class TestFBOOffThreadSharedContextMix2DemosES2NEWT extends UITestCase { + static long duration = 500; // ms + static int swapInterval = 1; + static boolean showFPS = false; + static boolean forceES2 = false; + static boolean mainRun = false; + + @AfterClass + public static void releaseClass() { + } + + protected void runTestGL(GLCapabilitiesImmutable caps) throws InterruptedException { + final GLReadBufferUtil screenshot = new GLReadBufferUtil(false, 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(256, 256); + } + // eager initialization of context + glWindow.setVisible(true); + glWindow.display(); + + final int fbod1_texUnit = 0; + final int fbod2_texUnit = 1; + + final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile()); + GLCapabilities fbodCaps = (GLCapabilities) caps.cloneMutable(); + // fbodCaps.setDoubleBuffered(false); + + final Mix2TexturesES2 mixerDemo = new Mix2TexturesES2(1, fbod1_texUnit, fbod2_texUnit); + + // FBOD1 + final GLOffscreenAutoDrawable.FBO fbod1 = (GLOffscreenAutoDrawable.FBO) + factory.createOffscreenAutoDrawable(null, fbodCaps, null, glWindow.getWidth(), glWindow.getHeight(), glWindow.getContext()); + fbod1.setUpstreamWidget(glWindow); // connect the real GLWindow (mouse/key) to offscreen! + fbod1.setTextureUnit(fbod1_texUnit); + { + GearsES2 demo0 = new GearsES2(-1); + fbod1.addGLEventListener(demo0); + demo0.setIgnoreFocus(true); + } + fbod1.getNativeSurface().addSurfaceUpdatedListener(new SurfaceUpdatedListener() { + @Override + public void surfaceUpdated(Object updater, NativeSurface ns, long when) { + mixerDemo.setTexID0(fbod1.getTextureBuffer(GL.GL_FRONT).getName()); + } }); + fbod1.display(); // init + System.err.println("FBOD1 "+fbod1); + Assert.assertTrue(fbod1.isInitialized()); + + // FBOD2 + final GLOffscreenAutoDrawable.FBO fbod2 = (GLOffscreenAutoDrawable.FBO) + factory.createOffscreenAutoDrawable(null, fbodCaps, null, glWindow.getWidth(), glWindow.getHeight(), glWindow.getContext()); + fbod2.setTextureUnit(fbod2_texUnit); + fbod2.addGLEventListener(new RedSquareES2(-1)); + fbod2.getNativeSurface().addSurfaceUpdatedListener(new SurfaceUpdatedListener() { + @Override + public void surfaceUpdated(Object updater, NativeSurface ns, long when) { + mixerDemo.setTexID1(fbod2.getTextureBuffer(GL.GL_FRONT).getName()); + } }); + fbod2.display(); // init + System.err.println("FBOD2 "+fbod2); + Assert.assertTrue(fbod2.isInitialized()); + + // preinit texIDs + mixerDemo.setTexID0(fbod1.getTextureBuffer(GL.GL_FRONT).getName()); + mixerDemo.setTexID1(fbod2.getTextureBuffer(GL.GL_FRONT).getName()); + + glWindow.addGLEventListener(mixerDemo); + glWindow.addGLEventListener(new GLEventListener() { + int i=0, c=0; + public void init(GLAutoDrawable drawable) {} + 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(8 == c) { + snapshot(i++, "msaa"+fbod1.getNumSamples(), drawable.getGL(), screenshot, TextureIO.PNG, null); + } + if(9 == c) { + c=0; + new Thread() { + @Override + public void run() { + glWindow.setSize(dw+256, dh+256); + } }.start(); + } + } + } + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { + fbod1.setSize(width, height); + fbod2.setSize(width, height); + } + }); + + final FPSAnimator animator0 = new FPSAnimator(30); + animator0.add(fbod1); + animator0.add(fbod2); + + final Animator animator1 = new Animator(); + animator1.add(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()); + } + }); + + animator0.start(); + animator1.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()); + + animator0.setUpdateFPSFrames(30, showFPS ? System.err : null); + animator1.setUpdateFPSFrames(60, showFPS ? System.err : null); + + while(!quitAdapter.shouldQuit() && animator1.isAnimating() && animator1.getTotalFPSDuration() + * The created {@link GLOffscreenAutoDrawable.FBO} is being used to run the {@link GLEventListener}. + *

      + *

      + * This test simulates shared on-thread GL context / texture usage, + * where the producer uses an FBO and delivers a shared texture. + * The receiver draws the shared texture onscreen. + * In detail the test consist of: + *

        + *
      • 1 {@link GLOffscreenAutoDrawable.FBO} double buffered + *
          + * + *
        • running within common {@link Animator} @ 60fps
        • + *
        • produce a texture
        • + *
        • notify the onscreen renderer about new textureID (swapping double buffer)
        • + *
      • + *
      • 1 onscreen {@link GLWindow} + *
          + *
        • shares it's {@link GLContext} w/ above FBO
        • + *
        • running within common {@link Animator} @ 60fps
        • + *
        • uses the shared FBO texture and draws it onscreen
        • + *
      • + *
      + *

      + */ +public class TestFBOOnThreadSharedContext1DemoES2NEWT extends UITestCase { + static long duration = 500; // ms + static int swapInterval = 1; + static boolean showFPS = false; + static boolean forceES2 = false; + static boolean mainRun = false; + + @AfterClass + public static void releaseClass() { + } + + protected void runTestGL(GLCapabilitiesImmutable caps) throws InterruptedException { + final GLReadBufferUtil screenshot = new GLReadBufferUtil(false, 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(256, 256); + } + // eager initialization of context + glWindow.setVisible(true); + glWindow.display(); + + final int fbod1_texUnit = 0; + + final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile()); + GLCapabilities fbodCaps = (GLCapabilities) caps.cloneMutable(); + // fbodCaps.setDoubleBuffered(false); + + final Mix2TexturesES2 mixerDemo = new Mix2TexturesES2(1, fbod1_texUnit, 0); + + // FBOD1 + final GLOffscreenAutoDrawable.FBO fbod1 = (GLOffscreenAutoDrawable.FBO) + factory.createOffscreenAutoDrawable(null, fbodCaps, null, glWindow.getWidth(), glWindow.getHeight(), glWindow.getContext()); + fbod1.setUpstreamWidget(glWindow); // connect the real GLWindow (mouse/key) to offscreen! + fbod1.setTextureUnit(fbod1_texUnit); + { + GearsES2 demo0 = new GearsES2(-1); + fbod1.addGLEventListener(demo0); + demo0.setIgnoreFocus(true); + } + fbod1.getNativeSurface().addSurfaceUpdatedListener(new SurfaceUpdatedListener() { + @Override + public void surfaceUpdated(Object updater, NativeSurface ns, long when) { + mixerDemo.setTexID0(fbod1.getTextureBuffer(GL.GL_FRONT).getName()); + } }); + fbod1.display(); // init + System.err.println("FBOD1 "+fbod1); + Assert.assertTrue(fbod1.isInitialized()); + + // preinit texIDs + mixerDemo.setTexID0(fbod1.getTextureBuffer(GL.GL_FRONT).getName()); + + glWindow.addWindowListener(new WindowAdapter() { + @Override + public void windowResized(WindowEvent e) { + fbod1.setSize(glWindow.getWidth(), glWindow.getHeight()); + } + }); + glWindow.addGLEventListener(mixerDemo); + glWindow.addGLEventListener(new GLEventListener() { + int i=0, c=0; + public void init(GLAutoDrawable drawable) {} + 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(8 == c) { + snapshot(i++, "msaa"+fbod1.getNumSamples(), drawable.getGL(), screenshot, TextureIO.PNG, null); + } + if(9 == c) { + c=0; + new Thread() { + @Override + public void run() { + glWindow.setSize(dw+256, dh+256); + } }.start(); + } + } + } + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { } + }); + + final Animator animator1 = new Animator(); + animator1.add(fbod1); + animator1.add(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()); + } + }); + + animator1.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()); + + animator1.setUpdateFPSFrames(60, showFPS ? System.err : null); + + while(!quitAdapter.shouldQuit() && animator1.isAnimating() && animator1.getTotalFPSDuration() + * Each test creates a {@link GLDrawable} using the + * {@link GLDrawableFactory#createGLDrawable(javax.media.nativewindow.NativeSurface) factory model}. + * The {@link GLContext} is derived {@link GLDrawable#createContext(GLContext) from the drawable}. + *

      + *

      + * Finally a {@link GLAutoDrawableDelegate} is created with the just created {@link GLDrawable} and {@link GLContext}. + * It is being used to run the {@link GLEventListener}. + *

      + */ +public class TestGLAutoDrawableDelegateOnOffscrnCapsNEWT extends UITestCase { + static final int widthStep = 800/4; + static final int heightStep = 600/4; + volatile int szStep = 2; + + static GLCapabilities getCaps(String profile) { + if( !GLProfile.isAvailable(profile) ) { + System.err.println("Profile "+profile+" n/a"); + return null; + } + return new GLCapabilities(GLProfile.get(profile)); + } + + void doTest(GLCapabilitiesImmutable reqGLCaps, GLEventListener demo) throws InterruptedException { + System.out.println("Requested GL Caps: "+reqGLCaps); + final GLDrawableFactory factory = GLDrawableFactory.getFactory(reqGLCaps.getGLProfile()); + + final boolean fboAvailable = factory.canCreateFBO(null, reqGLCaps.getGLProfile()); + final boolean pbufferAvailable = factory.canCreateGLPbuffer(null); + final GLCapabilitiesImmutable expGLCaps = GLGraphicsConfigurationUtil.fixGLCapabilities(reqGLCaps, fboAvailable, pbufferAvailable); + System.out.println("Expected GL Caps: "+expGLCaps); + // + // Create native windowing resources .. X11/Win/OSX + // + final Window window = NewtFactory.createWindow(reqGLCaps); + Assert.assertNotNull(window); + window.setSize(widthStep*szStep, heightStep*szStep); + window.setVisible(true); + Assert.assertTrue(AWTRobotUtil.waitForVisible(window, true)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(window, true)); + System.out.println("Window: "+window.getClass().getName()); + + // Check caps of NativeWindow config w/o GL + final CapabilitiesImmutable chosenCaps = window.getGraphicsConfiguration().getChosenCapabilities(); + System.out.println("Window Caps Pre_GL: "+chosenCaps); + Assert.assertNotNull(chosenCaps); + Assert.assertTrue(chosenCaps.getGreenBits()>5); + Assert.assertTrue(chosenCaps.getBlueBits()>5); + Assert.assertTrue(chosenCaps.getRedBits()>5); + + // + // Create native OpenGL resources .. XGL/WGL/CGL .. + // equivalent to GLAutoDrawable methods: setVisible(true) + // + final GLDrawable drawable = factory.createGLDrawable(window); + Assert.assertNotNull(drawable); + System.out.println("Drawable Pre-GL(0): "+drawable.getClass().getName()+", "+drawable.getNativeSurface().getClass().getName()); + + // + drawable.setRealized(true); + Assert.assertTrue(drawable.isRealized()); + + System.out.println("Window Caps PostGL : "+window.getGraphicsConfiguration().getChosenCapabilities()); + System.out.println("Drawable Post-GL(1): "+drawable.getClass().getName()+", "+drawable.getNativeSurface().getClass().getName()); + + // Check caps of GLDrawable after realization + final GLCapabilitiesImmutable chosenGLCaps = drawable.getChosenGLCapabilities(); + System.out.println("Chosen GL Caps(1): "+chosenGLCaps); + Assert.assertNotNull(chosenGLCaps); + Assert.assertTrue(chosenGLCaps.getGreenBits()>5); + Assert.assertTrue(chosenGLCaps.getBlueBits()>5); + Assert.assertTrue(chosenGLCaps.getRedBits()>5); + Assert.assertTrue(chosenGLCaps.getDepthBits()>4); + Assert.assertEquals(expGLCaps.isOnscreen(), chosenGLCaps.isOnscreen()); + Assert.assertEquals(expGLCaps.isFBO(), chosenGLCaps.isFBO()); + Assert.assertEquals(expGLCaps.isPBuffer(), chosenGLCaps.isPBuffer()); + Assert.assertEquals(expGLCaps.isBitmap(), chosenGLCaps.isBitmap()); + /** Single/Double buffer cannot be checked since result may vary .. + if(chosenGLCaps.isOnscreen() || chosenGLCaps.isFBO()) { + // dbl buffer may be disabled w/ offscreen pbuffer and bitmap + Assert.assertEquals(expGLCaps.getDoubleBuffered(), chosenGLCaps.getDoubleBuffered()); + } */ + + GLContext context = drawable.createContext(null); + Assert.assertNotNull(context); + int res = context.makeCurrent(); + Assert.assertTrue(GLContext.CONTEXT_CURRENT_NEW==res || GLContext.CONTEXT_CURRENT==res); + context.release(); + + System.out.println("Chosen GL Caps(2): "+drawable.getChosenGLCapabilities()); + System.out.println("Chosen GL CTX (2): "+context.getGLVersion()); + System.out.println("Drawable Post-GL(2): "+drawable.getClass().getName()+", "+drawable.getNativeSurface().getClass().getName()); + + final GLAutoDrawableDelegate glad = new GLAutoDrawableDelegate(drawable, context, window, false, null) { + @Override + protected void destroyImplInLock() { + super.destroyImplInLock(); // destroys drawable/context + window.destroy(); // destroys the actual window, incl. the device + } + }; + + window.addWindowListener(new WindowAdapter() { + @Override + public void windowRepaint(WindowUpdateEvent e) { + glad.windowRepaintOp(); + } + + @Override + public void windowResized(WindowEvent e) { + glad.windowResizedOp(window.getWidth(), window.getHeight()); + } + + @Override + public void windowDestroyNotify(WindowEvent e) { + glad.windowDestroyNotifyOp(); + } + }); + + glad.addGLEventListener(demo); + + final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener(); + glad.addGLEventListener(snapshotGLEventListener); + + glad.display(); // initial resize/display + + // 1 - szStep = 2 + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + // 2, 3 (resize + display) + szStep = 1; + window.setSize(widthStep*szStep, heightStep*szStep); + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + // 4, 5 (resize + display) + szStep = 4; + window.setSize(widthStep*szStep, heightStep*szStep); + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + Thread.sleep(50); + + glad.destroy(); + System.out.println("Fin Drawable: "+drawable); + System.out.println("Fin Window: "+window); + } + + @Test + public void testAvailableInfo() { + GLDrawableFactory f = GLDrawableFactory.getDesktopFactory(); + if(null != f) { + System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString()); + } + f = GLDrawableFactory.getEGLFactory(); + if(null != f) { + System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString()); + } + } + + @Test + public void testGL2OnScreenDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OnScreenSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenAutoDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenFBODblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenFBOSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenPbufferDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setPBuffer(true); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenPbufferSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setPBuffer(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenBitmapDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setBitmap(true); + doTest(reqGLCaps, new Gears(1)); + } + + @Test + public void testGL2OffScreenBitmapSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setBitmap(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new Gears(1)); + } + + @Test + public void testES2OnScreenDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OnScreenSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenAutoDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenFBODblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenFBOSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenPbufferDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setPBuffer(true); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenPbufferSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setPBuffer(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + /** Not implemented ! + @Test + public void testES2OffScreenBitmapDblBuf() throws InterruptedException { + if(!checkProfile(GLProfile.GLES2)) { + return; + } + final GLCapabilities reqGLCaps = new GLCapabilities(GLProfile.get(GLProfile.GLES2)); + reqGLCaps.setOnscreen(false); + reqGLCaps.setBitmap(true); + doTest(reqGLCaps, new GearsES2(1)); + } */ + + public static void main(String args[]) throws IOException { + org.junit.runner.JUnitCore.main(TestGLAutoDrawableDelegateOnOffscrnCapsNEWT.class.getName()); + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryOffscrnCapsNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryOffscrnCapsNEWT.java new file mode 100644 index 000000000..544d74aa5 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryOffscrnCapsNEWT.java @@ -0,0 +1,317 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package com.jogamp.opengl.test.junit.jogl.acore; + +import java.io.IOException; + +import javax.media.nativewindow.CapabilitiesImmutable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLOffscreenAutoDrawable; +import javax.media.opengl.GLProfile; + +import jogamp.opengl.GLGraphicsConfigurationUtil; + +import org.junit.Assert; +import org.junit.Test; + +import com.jogamp.opengl.JoglVersion; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.jogl.demos.gl2.Gears; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.UITestCase; + +/** + * Toolkit agnostic {@link GLOffscreenAutoDrawable} tests using the + * {@link GLDrawableFactory#createOffscreenAutoDrawable(javax.media.nativewindow.AbstractGraphicsDevice, GLCapabilitiesImmutable, javax.media.opengl.GLCapabilitiesChooser, int, int, GLContext) factory model}. + *

      + * The created {@link GLOffscreenAutoDrawable} is being used to run the {@link GLEventListener}. + *

      + */ +public class TestGLAutoDrawableFactoryOffscrnCapsNEWT extends UITestCase { + static final int widthStep = 800/4; + static final int heightStep = 600/4; + volatile int szStep = 2; + + static GLCapabilities getCaps(String profile) { + if( !GLProfile.isAvailable(profile) ) { + System.err.println("Profile "+profile+" n/a"); + return null; + } + return new GLCapabilities(GLProfile.get(profile)); + } + + void doTest(GLCapabilitiesImmutable reqGLCaps, GLEventListener demo) throws InterruptedException { + System.out.println("Requested GL Caps: "+reqGLCaps); + final GLDrawableFactory factory = GLDrawableFactory.getFactory(reqGLCaps.getGLProfile()); + + final boolean fboAvailable = factory.canCreateFBO(null, reqGLCaps.getGLProfile()); + final boolean pbufferAvailable = factory.canCreateGLPbuffer(null); + final GLCapabilitiesImmutable expGLCaps = GLGraphicsConfigurationUtil.fixGLCapabilities(reqGLCaps, fboAvailable, pbufferAvailable); + System.out.println("Expected GL Caps: "+expGLCaps); + + // + // Create native OpenGL resources .. XGL/WGL/CGL .. + // equivalent to GLAutoDrawable methods: setVisible(true) + // + final GLOffscreenAutoDrawable glad = factory.createOffscreenAutoDrawable(null, reqGLCaps, null, widthStep*szStep, heightStep*szStep, null); + + Assert.assertNotNull(glad); + System.out.println("Drawable Pre-GL(0): "+glad.getClass().getName()+", "+glad.getNativeSurface().getClass().getName()); + Assert.assertTrue(glad.isRealized()); + + // Check caps of NativeWindow config w/o GL + final CapabilitiesImmutable chosenCaps = glad.getChosenGLCapabilities(); + System.out.println("Drawable Caps Pre_GL : "+chosenCaps); + Assert.assertNotNull(chosenCaps); + Assert.assertTrue(chosenCaps.getGreenBits()>5); + Assert.assertTrue(chosenCaps.getBlueBits()>5); + Assert.assertTrue(chosenCaps.getRedBits()>5); + + glad.display(); // force native context creation + + // Check caps of GLDrawable after realization + final GLCapabilitiesImmutable chosenGLCaps = glad.getChosenGLCapabilities(); + System.out.println("Chosen GL Caps(1): "+chosenGLCaps); + System.out.println("Chosen GL CTX (1): "+glad.getContext().getGLVersion()); + + Assert.assertNotNull(chosenGLCaps); + Assert.assertTrue(chosenGLCaps.getGreenBits()>5); + Assert.assertTrue(chosenGLCaps.getBlueBits()>5); + Assert.assertTrue(chosenGLCaps.getRedBits()>5); + Assert.assertTrue(chosenGLCaps.getDepthBits()>4); + Assert.assertEquals(expGLCaps.isOnscreen(), chosenGLCaps.isOnscreen()); + Assert.assertEquals(expGLCaps.isFBO(), chosenGLCaps.isFBO()); + Assert.assertEquals(expGLCaps.isPBuffer(), chosenGLCaps.isPBuffer()); + Assert.assertEquals(expGLCaps.isBitmap(), chosenGLCaps.isBitmap()); + /** Single/Double buffer cannot be checked since result may vary .. + if(chosenGLCaps.isOnscreen() || chosenGLCaps.isFBO()) { + // dbl buffer may be disabled w/ offscreen pbuffer and bitmap + Assert.assertEquals(expGLCaps.getDoubleBuffered(), chosenGLCaps.getDoubleBuffered()); + } */ + + glad.addGLEventListener(demo); + + final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener(); + glad.addGLEventListener(snapshotGLEventListener); + + glad.display(); // initial resize/display + + // 1 - szStep = 2 + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + // 2, 3 (resize + display) + szStep = 1; + glad.setSize(widthStep*szStep, heightStep*szStep); + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + // 4, 5 (resize + display) + szStep = 4; + glad.setSize(widthStep*szStep, heightStep*szStep); + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + Thread.sleep(50); + + glad.destroy(); + System.out.println("Fin Drawable: "+glad); + } + + @Test + public void testAvailableInfo() { + GLDrawableFactory f = GLDrawableFactory.getDesktopFactory(); + if(null != f) { + System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString()); + } + f = GLDrawableFactory.getEGLFactory(); + if(null != f) { + System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString()); + } + } + + @Test + public void testGL2OffScreenAutoDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenFBODblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenFBOSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenFBOStencil() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + reqGLCaps.setStencilBits(1); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenFBOStencilMSAA() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + reqGLCaps.setStencilBits(1); + reqGLCaps.setSampleBuffers(true); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenPbufferDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setPBuffer(true); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenPbufferSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setPBuffer(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenBitmapDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setBitmap(true); + doTest(reqGLCaps, new Gears(1)); + } + + @Test + public void testGL2OffScreenBitmapSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setBitmap(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new Gears(1)); + } + + @Test + public void testES2OffScreenAutoDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenFBODblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenFBOSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenPbufferDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setPBuffer(true); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenPbufferSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setPBuffer(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + /** Not implemented ! + @Test + public void testES2OffScreenBitmapDblBuf() throws InterruptedException { + if(!checkProfile(GLProfile.GLES2)) { + return; + } + final GLCapabilities reqGLCaps = new GLCapabilities(GLProfile.get(GLProfile.GLES2)); + reqGLCaps.setOnscreen(false); + reqGLCaps.setBitmap(true); + doTest(reqGLCaps, new GearsES2(1)); + } */ + + public static void main(String args[]) throws IOException { + org.junit.runner.JUnitCore.main(TestGLAutoDrawableFactoryOffscrnCapsNEWT.class.getName()); + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableGLCanvasOnOffscrnCapsAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableGLCanvasOnOffscrnCapsAWT.java new file mode 100644 index 000000000..64a75716b --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableGLCanvasOnOffscrnCapsAWT.java @@ -0,0 +1,328 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package com.jogamp.opengl.test.junit.jogl.acore; + +import java.awt.Dimension; +import java.awt.Frame; +import java.io.IOException; + +import javax.media.nativewindow.CapabilitiesImmutable; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawable; +import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; +import javax.media.opengl.awt.GLCanvas; + +import jogamp.nativewindow.jawt.JAWTUtil; +import jogamp.opengl.GLGraphicsConfigurationUtil; + +import org.junit.Assert; +import org.junit.Assume; +import org.junit.Test; + +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.JoglVersion; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.UITestCase; + +/** + * Tests using a NEWT {@link GLWindow} {@link GLAutoDrawable auto drawable} for on- and offscreen cases. + *

      + * The NEWT {@link GLAutoDrawable} is being used to run the {@link GLEventListener}. + *

      + */ +public class TestGLAutoDrawableGLCanvasOnOffscrnCapsAWT extends UITestCase { + static final int widthStep = 800/4; + static final int heightStep = 600/4; + volatile int szStep = 2; + + static GLCapabilities getCaps(String profile) { + if( !GLProfile.isAvailable(profile) ) { + System.err.println("Profile "+profile+" n/a"); + return null; + } + return new GLCapabilities(GLProfile.get(profile)); + } + + static void setGLCanvasSize(final Frame frame, final GLCanvas glc, final int width, final int height) { + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + final Dimension new_sz = new Dimension(width, height); + glc.setMinimumSize(new_sz); + glc.setPreferredSize(new_sz); + glc.setSize(new_sz); + frame.pack(); + frame.validate(); + } } ); + } catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + } + + static interface MyGLEventListener extends GLEventListener { + void setMakeSnapshot(); + } + + void doTest(GLCapabilitiesImmutable reqGLCaps, GLEventListener demo) throws InterruptedException { + if(reqGLCaps.isOnscreen() && JAWTUtil.isOffscreenLayerRequired()) { + System.err.println("onscreen layer n/a"); + return; + } + if(!reqGLCaps.isOnscreen() && !JAWTUtil.isOffscreenLayerSupported()) { + System.err.println("offscreen layer n/a"); + return; + } + System.out.println("Requested GL Caps: "+reqGLCaps); + final GLDrawableFactory factory = GLDrawableFactory.getFactory(reqGLCaps.getGLProfile()); + + final boolean fboAvailable = factory.canCreateFBO(null, reqGLCaps.getGLProfile()); + final boolean pbufferAvailable = factory.canCreateGLPbuffer(null); + final GLCapabilitiesImmutable expGLCaps = GLGraphicsConfigurationUtil.fixGLCapabilities(reqGLCaps, fboAvailable, pbufferAvailable); + System.out.println("Expected GL Caps: "+expGLCaps); + // + // Create native windowing resources .. X11/Win/OSX + // + final GLCanvas glad = new GLCanvas(reqGLCaps); // will implicit trigger offscreen layer - if !onscreen && supported + Assert.assertNotNull(glad); + Dimension glc_sz = new Dimension(widthStep*szStep, heightStep*szStep); + glad.setMinimumSize(glc_sz); + glad.setPreferredSize(glc_sz); + glad.setSize(glc_sz); + final Frame frame = new Frame(getSimpleTestName(".")); + Assert.assertNotNull(frame); + frame.add(glad); + + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.pack(); + frame.setVisible(true); + }}); + } catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + + Assert.assertTrue(AWTRobotUtil.waitForVisible(glad, true)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(glad, true)); + System.out.println("Window: "+glad.getClass().getName()); + + // Check caps of NativeWindow config w/o GL + final CapabilitiesImmutable chosenCaps = glad.getChosenGLCapabilities(); + System.out.println("Window Caps Pre_GL: "+chosenCaps); + Assert.assertNotNull(chosenCaps); + Assert.assertTrue(chosenCaps.getGreenBits()>5); + Assert.assertTrue(chosenCaps.getBlueBits()>5); + Assert.assertTrue(chosenCaps.getRedBits()>5); + + glad.display(); // force native context creation + + // + // Create native OpenGL resources .. XGL/WGL/CGL .. + // equivalent to GLAutoDrawable methods: setVisible(true) + // + { + final GLDrawable actualDrawable = glad.getDelegatedDrawable(); + Assert.assertNotNull(actualDrawable); + System.out.println("Drawable Pre-GL(0): "+actualDrawable.getClass().getName()+", "+actualDrawable.getNativeSurface().getClass().getName()); + } + + System.out.println("Window Caps PostGL : "+glad.getChosenGLCapabilities()); + System.out.println("Drawable Post-GL(1): "+glad.getClass().getName()+", "+glad.getNativeSurface().getClass().getName()); + + // Check caps of GLDrawable after realization + final GLCapabilitiesImmutable chosenGLCaps = glad.getChosenGLCapabilities(); + System.out.println("Chosen GL Caps(1): "+chosenGLCaps); + Assert.assertNotNull(chosenGLCaps); + Assert.assertTrue(chosenGLCaps.getGreenBits()>5); + Assert.assertTrue(chosenGLCaps.getBlueBits()>5); + Assert.assertTrue(chosenGLCaps.getRedBits()>5); + Assert.assertTrue(chosenGLCaps.getDepthBits()>4); + Assert.assertEquals(expGLCaps.isOnscreen(), chosenGLCaps.isOnscreen()); + Assert.assertEquals(expGLCaps.isFBO(), chosenGLCaps.isFBO()); + Assert.assertEquals(expGLCaps.isPBuffer(), chosenGLCaps.isPBuffer()); + Assert.assertEquals(expGLCaps.isBitmap(), chosenGLCaps.isBitmap()); + /** Single/Double buffer cannot be checked since result may vary .. + if(chosenGLCaps.isOnscreen() || chosenGLCaps.isFBO()) { + // dbl buffer may be disabled w/ offscreen pbuffer and bitmap + Assert.assertEquals(expGLCaps.getDoubleBuffered(), chosenGLCaps.getDoubleBuffered()); + } */ + + { + GLContext context = glad.getContext(); + System.out.println("Chosen GL CTX (2): "+context.getGLVersion()); + Assert.assertNotNull(context); + Assert.assertTrue(context.isCreated()); + } + + System.out.println("Chosen GL Caps(2): "+glad.getChosenGLCapabilities()); + System.out.println("Drawable Post-GL(2): "+glad.getClass().getName()+", "+glad.getNativeSurface().getClass().getName()); + + glad.addGLEventListener(demo); + + final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener(); + glad.addGLEventListener(snapshotGLEventListener); + + glad.display(); // initial resize/display + + // 1 - szStep = 2 + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + // 2, 3 (resize + display) + szStep = 1; + setGLCanvasSize(frame, glad, widthStep*szStep, heightStep*szStep); + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + glad.display(); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + // 4, 5 (resize + display) + szStep = 4; + setGLCanvasSize(frame, glad, widthStep*szStep, heightStep*szStep); + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + glad.display(); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + Thread.sleep(50); + + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setVisible(false); + frame.remove(glad); + frame.dispose(); + }}); + } catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + System.out.println("Fin: "+glad); + } + + @Test + public void testAvailableInfo() { + GLDrawableFactory f = GLDrawableFactory.getDesktopFactory(); + if(null != f) { + System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString()); + } + f = GLDrawableFactory.getEGLFactory(); + if(null != f) { + System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString()); + } + } + + @Test + public void testGL2OnScreen() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenAuto() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenFBOMSAA() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + reqGLCaps.setSampleBuffers(true); + reqGLCaps.setNumSamples(4); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenPbuffer() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setPBuffer(true); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OnScreen() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenAuto() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenFBOMSAA() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + reqGLCaps.setSampleBuffers(true); + reqGLCaps.setNumSamples(4); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenPbuffer() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setPBuffer(true); + doTest(reqGLCaps, new GearsES2(1)); + } + + + public static void main(String args[]) throws IOException { + org.junit.runner.JUnitCore.main(TestGLAutoDrawableGLCanvasOnOffscrnCapsAWT.class.getName()); + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT.java new file mode 100644 index 000000000..37ec44566 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT.java @@ -0,0 +1,351 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package com.jogamp.opengl.test.junit.jogl.acore; + +import java.io.IOException; + +import javax.media.nativewindow.CapabilitiesImmutable; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawable; +import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; + +import jogamp.opengl.GLGraphicsConfigurationUtil; + +import org.junit.Assert; +import org.junit.Test; + +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.JoglVersion; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.jogl.demos.gl2.Gears; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.UITestCase; + +/** + * Tests using a NEWT {@link GLWindow} {@link GLAutoDrawable auto drawable} for on- and offscreen cases. + *

      + * The NEWT {@link GLAutoDrawable} is being used to run the {@link GLEventListener}. + *

      + */ +public class TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT extends UITestCase { + static final int widthStep = 800/4; + static final int heightStep = 600/4; + volatile int szStep = 2; + + static interface MyGLEventListener extends GLEventListener { + void setMakeSnapshot(); + } + + static GLCapabilities getCaps(String profile) { + if( !GLProfile.isAvailable(profile) ) { + System.err.println("Profile "+profile+" n/a"); + return null; + } + return new GLCapabilities(GLProfile.get(profile)); + } + + void doTest(GLCapabilitiesImmutable reqGLCaps, GLEventListener demo) throws InterruptedException { + System.out.println("Requested GL Caps: "+reqGLCaps); + final GLDrawableFactory factory = GLDrawableFactory.getFactory(reqGLCaps.getGLProfile()); + + final boolean fboAvailable = factory.canCreateFBO(null, reqGLCaps.getGLProfile()); + final boolean pbufferAvailable = factory.canCreateGLPbuffer(null); + final GLCapabilitiesImmutable expGLCaps = GLGraphicsConfigurationUtil.fixGLCapabilities(reqGLCaps, fboAvailable, pbufferAvailable); + System.out.println("Expected GL Caps: "+expGLCaps); + // + // Create native windowing resources .. X11/Win/OSX + // + final GLWindow glad = GLWindow.create(reqGLCaps); + Assert.assertNotNull(glad); + glad.setSize(widthStep*szStep, heightStep*szStep); + glad.setVisible(true); + Assert.assertTrue(AWTRobotUtil.waitForVisible(glad, true)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(glad, true)); + System.out.println("Window: "+glad.getClass().getName()); + + // Check caps of NativeWindow config w/o GL + final CapabilitiesImmutable chosenCaps = glad.getGraphicsConfiguration().getChosenCapabilities(); + System.out.println("Window Caps Pre_GL: "+chosenCaps); + Assert.assertNotNull(chosenCaps); + Assert.assertTrue(chosenCaps.getGreenBits()>5); + Assert.assertTrue(chosenCaps.getBlueBits()>5); + Assert.assertTrue(chosenCaps.getRedBits()>5); + + // + // Create native OpenGL resources .. XGL/WGL/CGL .. + // equivalent to GLAutoDrawable methods: setVisible(true) + // + { + final GLDrawable actualDrawable = glad.getDelegatedDrawable(); + Assert.assertNotNull(actualDrawable); + System.out.println("Drawable Pre-GL(0): "+actualDrawable.getClass().getName()+", "+actualDrawable.getNativeSurface().getClass().getName()); + } + + System.out.println("Window Caps PostGL : "+glad.getGraphicsConfiguration().getChosenCapabilities()); + System.out.println("Drawable Post-GL(1): "+glad.getClass().getName()+", "+glad.getNativeSurface().getClass().getName()); + + // Check caps of GLDrawable after realization + final GLCapabilitiesImmutable chosenGLCaps = glad.getChosenGLCapabilities(); + System.out.println("Chosen GL Caps(1): "+chosenGLCaps); + Assert.assertNotNull(chosenGLCaps); + Assert.assertTrue(chosenGLCaps.getGreenBits()>5); + Assert.assertTrue(chosenGLCaps.getBlueBits()>5); + Assert.assertTrue(chosenGLCaps.getRedBits()>5); + Assert.assertTrue(chosenGLCaps.getDepthBits()>4); + Assert.assertEquals(expGLCaps.isOnscreen(), chosenGLCaps.isOnscreen()); + Assert.assertEquals(expGLCaps.isFBO(), chosenGLCaps.isFBO()); + Assert.assertEquals(expGLCaps.isPBuffer(), chosenGLCaps.isPBuffer()); + Assert.assertEquals(expGLCaps.isBitmap(), chosenGLCaps.isBitmap()); + /** Single/Double buffer cannot be checked since result may vary .. + if(chosenGLCaps.isOnscreen() || chosenGLCaps.isFBO()) { + // dbl buffer may be disabled w/ offscreen pbuffer and bitmap + Assert.assertEquals(expGLCaps.getDoubleBuffered(), chosenGLCaps.getDoubleBuffered()); + } */ + + glad.display(); + { + GLContext context = glad.getContext(); + System.out.println("Chosen GL CTX (2): "+context.getGLVersion()); + Assert.assertNotNull(context); + Assert.assertTrue(context.isCreated()); + } + + System.out.println("Chosen GL Caps(2): "+glad.getChosenGLCapabilities()); + System.out.println("Drawable Post-GL(2): "+glad.getClass().getName()+", "+glad.getNativeSurface().getClass().getName()); + + glad.addGLEventListener(demo); + + final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener(); + glad.addGLEventListener(snapshotGLEventListener); + + glad.display(); // initial resize/display + + // 1 - szStep = 2 + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + // 2, 3 (resize + display) + szStep = 1; + glad.setSize(widthStep*szStep, heightStep*szStep); + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + // 4, 5 (resize + display) + szStep = 4; + glad.setSize(widthStep*szStep, heightStep*szStep); + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + Thread.sleep(50); + + glad.destroy(); + System.out.println("Fin: "+glad); + } + + @Test + public void testAvailableInfo() { + GLDrawableFactory f = GLDrawableFactory.getDesktopFactory(); + if(null != f) { + System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString()); + } + f = GLDrawableFactory.getEGLFactory(); + if(null != f) { + System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString()); + } + } + + @Test + public void testGL2OnScreenDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OnScreenSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenAutoDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenFBODblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenFBOSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenPbufferDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setPBuffer(true); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenPbufferSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setPBuffer(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenBitmapDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setBitmap(true); + doTest(reqGLCaps, new Gears(1)); + } + + @Test + public void testGL2OffScreenBitmapSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setBitmap(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new Gears(1)); + } + + @Test + public void testES2OnScreenDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OnScreenSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenAutoDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenFBODblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenFBOSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setFBO(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenPbufferDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setPBuffer(true); + doTest(reqGLCaps, new GearsES2(1)); + } + + @Test + public void testES2OffScreenPbufferSglBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2); + if(null == reqGLCaps) return; + reqGLCaps.setOnscreen(false); + reqGLCaps.setPBuffer(true); + reqGLCaps.setDoubleBuffered(false); + doTest(reqGLCaps, new GearsES2(1)); + } + + /** Not implemented ! + @Test + public void testES2OffScreenBitmapDblBuf() throws InterruptedException { + if(!checkProfile(GLProfile.GLES2)) { + return; + } + final GLCapabilities reqGLCaps = new GLCapabilities(GLProfile.get(GLProfile.GLES2)); + reqGLCaps.setOnscreen(false); + reqGLCaps.setBitmap(true); + doTest(reqGLCaps, new GearsES2(1)); + } */ + + public static void main(String args[]) throws IOException { + org.junit.runner.JUnitCore.main(TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT.class.getName()); + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableNewtCanvasAWTOnOffscrnCapsAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableNewtCanvasAWTOnOffscrnCapsAWT.java new file mode 100644 index 000000000..47fc99844 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableNewtCanvasAWTOnOffscrnCapsAWT.java @@ -0,0 +1,300 @@ +/** + * Copyright 2010 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package com.jogamp.opengl.test.junit.jogl.acore; + +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Frame; +import java.io.IOException; + +import javax.media.nativewindow.CapabilitiesImmutable; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawable; +import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; + +import jogamp.nativewindow.jawt.JAWTUtil; +import jogamp.opengl.GLGraphicsConfigurationUtil; + +import org.junit.Assert; +import org.junit.Assume; +import org.junit.Test; + +import com.jogamp.newt.awt.NewtCanvasAWT; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.JoglVersion; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.UITestCase; + +/** + * Tests using a NEWT {@link GLWindow} {@link GLAutoDrawable auto drawable} for on- and offscreen cases. + *

      + * The NEWT {@link GLAutoDrawable} is being used to run the {@link GLEventListener}. + *

      + */ +public class TestGLAutoDrawableNewtCanvasAWTOnOffscrnCapsAWT extends UITestCase { + static final int widthStep = 800/4; + static final int heightStep = 600/4; + volatile int szStep = 2; + + static GLCapabilities getCaps(String profile) { + if( !GLProfile.isAvailable(profile) ) { + System.err.println("Profile "+profile+" n/a"); + return null; + } + return new GLCapabilities(GLProfile.get(profile)); + } + + static void setComponentSize(final Frame frame, final Component comp, final int width, final int height) { + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + final Dimension new_sz = new Dimension(width, height); + comp.setMinimumSize(new_sz); + comp.setPreferredSize(new_sz); + comp.setSize(new_sz); + frame.pack(); + frame.validate(); + } } ); + } catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + } + + static interface MyGLEventListener extends GLEventListener { + void setMakeSnapshot(); + } + + void doTest(boolean offscreenLayer, GLCapabilitiesImmutable reqGLCaps, GLEventListener demo) throws InterruptedException { + if(!offscreenLayer && JAWTUtil.isOffscreenLayerRequired()) { + System.err.println("onscreen layer n/a"); + return; + } + if(offscreenLayer && !JAWTUtil.isOffscreenLayerSupported()) { + System.err.println("offscreen layer n/a"); + return; + } + System.out.println("Requested GL Caps: "+reqGLCaps); + final GLDrawableFactory factory = GLDrawableFactory.getFactory(reqGLCaps.getGLProfile()); + + final boolean fboAvailable = factory.canCreateFBO(null, reqGLCaps.getGLProfile()); + final boolean pbufferAvailable = factory.canCreateGLPbuffer(null); + final GLCapabilitiesImmutable expGLCaps = offscreenLayer ? + GLGraphicsConfigurationUtil.fixOffscreenGLCapabilities(reqGLCaps, fboAvailable, pbufferAvailable) : + GLGraphicsConfigurationUtil.fixGLCapabilities(reqGLCaps, fboAvailable, pbufferAvailable); + System.out.println("Expected GL Caps: "+expGLCaps); + + final GLWindow glad = GLWindow.create(reqGLCaps); + Assert.assertNotNull(glad); + + + final NewtCanvasAWT nca = new NewtCanvasAWT(glad); + Assert.assertNotNull(nca); + Dimension size0 = new Dimension(widthStep*szStep, heightStep*szStep); + nca.setShallUseOffscreenLayer(offscreenLayer); // trigger offscreen layer - if supported + nca.setPreferredSize(size0); + nca.setMinimumSize(size0); + nca.setSize(size0); + + final Frame frame = new Frame(getSimpleTestName(".")); + Assert.assertNotNull(frame); + frame.add(nca); + + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.pack(); + frame.setVisible(true); + }}); + } catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + + Assert.assertTrue(AWTRobotUtil.waitForVisible(glad, true)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(glad, true)); + System.out.println("Window: "+glad.getClass().getName()); + + // Check caps of NativeWindow config w/o GL + final CapabilitiesImmutable chosenCaps = glad.getChosenGLCapabilities(); + System.out.println("Window Caps Pre_GL: "+chosenCaps); + Assert.assertNotNull(chosenCaps); + Assert.assertTrue(chosenCaps.getGreenBits()>5); + Assert.assertTrue(chosenCaps.getBlueBits()>5); + Assert.assertTrue(chosenCaps.getRedBits()>5); + + glad.display(); // force native context creation + + // + // Create native OpenGL resources .. XGL/WGL/CGL .. + // equivalent to GLAutoDrawable methods: setVisible(true) + // + { + final GLDrawable actualDrawable = glad.getDelegatedDrawable(); + Assert.assertNotNull(actualDrawable); + System.out.println("Drawable Pre-GL(0): "+actualDrawable.getClass().getName()+", "+actualDrawable.getNativeSurface().getClass().getName()); + } + + System.out.println("Window Caps PostGL : "+glad.getChosenGLCapabilities()); + System.out.println("Drawable Post-GL(1): "+glad.getClass().getName()+", "+glad.getNativeSurface().getClass().getName()); + + // Check caps of GLDrawable after realization + final GLCapabilitiesImmutable chosenGLCaps = glad.getChosenGLCapabilities(); + System.out.println("Chosen GL Caps(1): "+chosenGLCaps); + Assert.assertNotNull(chosenGLCaps); + Assert.assertTrue(chosenGLCaps.getGreenBits()>5); + Assert.assertTrue(chosenGLCaps.getBlueBits()>5); + Assert.assertTrue(chosenGLCaps.getRedBits()>5); + Assert.assertTrue(chosenGLCaps.getDepthBits()>4); + Assert.assertEquals(expGLCaps.isOnscreen(), chosenGLCaps.isOnscreen()); + Assert.assertEquals(expGLCaps.isFBO(), chosenGLCaps.isFBO()); + Assert.assertEquals(expGLCaps.isPBuffer(), chosenGLCaps.isPBuffer()); + Assert.assertEquals(expGLCaps.isBitmap(), chosenGLCaps.isBitmap()); + /** Single/Double buffer cannot be checked since result may vary .. + if(chosenGLCaps.isOnscreen() || chosenGLCaps.isFBO()) { + // dbl buffer may be disabled w/ offscreen pbuffer and bitmap + Assert.assertEquals(expGLCaps.getDoubleBuffered(), chosenGLCaps.getDoubleBuffered()); + } */ + + { + GLContext context = glad.getContext(); + System.out.println("Chosen GL CTX (2): "+context.getGLVersion()); + Assert.assertNotNull(context); + Assert.assertTrue(context.isCreated()); + } + + System.out.println("Chosen GL Caps(2): "+glad.getChosenGLCapabilities()); + System.out.println("Drawable Post-GL(2): "+glad.getClass().getName()+", "+glad.getNativeSurface().getClass().getName()); + + glad.addGLEventListener(demo); + + final SnapshotGLEventListener snapshotGLEventListener = new SnapshotGLEventListener(); + glad.addGLEventListener(snapshotGLEventListener); + + glad.display(); // initial resize/display + + // 1 - szStep = 2 + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + // 2, 3 (resize + display) + szStep = 1; + setComponentSize(frame, nca, widthStep*szStep, heightStep*szStep); + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + glad.display(); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + // 4, 5 (resize + display) + szStep = 4; + setComponentSize(frame, nca, widthStep*szStep, heightStep*szStep); + Assert.assertTrue("Size not reached: Expected "+(widthStep*szStep)+"x"+(heightStep*szStep)+", Is "+glad.getWidth()+"x"+glad.getHeight(), + AWTRobotUtil.waitForSize(glad, widthStep*szStep, heightStep*szStep)); + glad.display(); + snapshotGLEventListener.setMakeSnapshot(); + glad.display(); + + Thread.sleep(50); + + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setVisible(false); + frame.remove(nca); + frame.dispose(); + }}); + } catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + glad.destroy(); + System.out.println("Fin: "+nca); + System.out.println("Fin: "+glad); + } + + @Test + public void testAvailableInfo() { + GLDrawableFactory f = GLDrawableFactory.getDesktopFactory(); + if(null != f) { + System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString()); + } + f = GLDrawableFactory.getEGLFactory(); + if(null != f) { + System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString()); + } + } + + @Test + public void testGL2OnScreenDblBuf() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + doTest(false, reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenLayerAuto() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + doTest(true, reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenFBOMSAA() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setFBO(true); + reqGLCaps.setOnscreen(true); // get native NEWT Window, not OffscreenWindow + reqGLCaps.setSampleBuffers(true); + reqGLCaps.setNumSamples(4); + doTest(true, reqGLCaps, new GearsES2(1)); + } + + @Test + public void testGL2OffScreenPbuffer() throws InterruptedException { + final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2); + if(null == reqGLCaps) return; + reqGLCaps.setPBuffer(true); + reqGLCaps.setOnscreen(true); // get native NEWT Window, not OffscreenWindow + doTest(true, reqGLCaps, new GearsES2(1)); + } + + public static void main(String args[]) throws IOException { + org.junit.runner.JUnitCore.main(TestGLAutoDrawableNewtCanvasAWTOnOffscrnCapsAWT.class.getName()); + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLCapabilities01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLCapabilities01NEWT.java deleted file mode 100644 index cd1107e25..000000000 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLCapabilities01NEWT.java +++ /dev/null @@ -1,266 +0,0 @@ -/** - * Copyright 2010 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ - -package com.jogamp.opengl.test.junit.jogl.acore; - -import java.io.IOException; - -import javax.media.nativewindow.CapabilitiesImmutable; -import javax.media.opengl.GLCapabilities; -import javax.media.opengl.GLCapabilitiesImmutable; -import javax.media.opengl.GLContext; -import javax.media.opengl.GLDrawable; -import javax.media.opengl.GLDrawableFactory; -import javax.media.opengl.GLEventListener; -import javax.media.opengl.GLProfile; - -import jogamp.opengl.GLGraphicsConfigurationUtil; - -import org.junit.Assert; -import org.junit.Test; - -import com.jogamp.newt.NewtFactory; -import com.jogamp.newt.Window; -import com.jogamp.opengl.JoglVersion; -import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; -import com.jogamp.opengl.test.junit.util.AWTRobotUtil; -import com.jogamp.opengl.test.junit.util.UITestCase; - -public class TestGLCapabilities01NEWT extends UITestCase { - static final int width = 100; - static final int height = 100; - - boolean checkProfile(String profile) { - if( !GLProfile.isAvailable(profile) ) { - System.err.println("Profile "+profile+" n/a"); - return false; - } - return true; - } - - void doTest(GLCapabilitiesImmutable reqGLCaps, GLEventListener demo) throws InterruptedException { - System.out.println("Requested GL Caps: "+reqGLCaps); - - final GLCapabilitiesImmutable expGLCaps; - if( GLGraphicsConfigurationUtil.isGLCapabilitiesOffscreenAutoSelection(reqGLCaps) ) { - final GLDrawableFactory f = GLDrawableFactory.getFactory(reqGLCaps.getGLProfile()); - final boolean fboAvailable = true ; // f.canCreateFBO(null, reqGLCaps.getGLProfile()); - final boolean pbufferAvailable = f.canCreateGLPbuffer(null); - expGLCaps = GLGraphicsConfigurationUtil.fixGLCapabilities(reqGLCaps, fboAvailable, pbufferAvailable); - } else { - expGLCaps = reqGLCaps; - } - System.out.println("Expected GL Caps: "+expGLCaps); - // - // Create native windowing resources .. X11/Win/OSX - // - final Window window = NewtFactory.createWindow(reqGLCaps); - Assert.assertNotNull(window); - window.setSize(width, height); - window.setVisible(true); - Assert.assertTrue(AWTRobotUtil.waitForVisible(window, true)); - Assert.assertTrue(AWTRobotUtil.waitForRealized(window, true)); - System.out.println("Window: "+window.getClass().getName()); - - // Check caps of NativeWindow config w/o GL - final CapabilitiesImmutable chosenCaps = window.getGraphicsConfiguration().getChosenCapabilities(); - System.out.println("Window Caps Pre_GL: "+chosenCaps); - Assert.assertNotNull(chosenCaps); - Assert.assertTrue(chosenCaps.getGreenBits()>5); - Assert.assertTrue(chosenCaps.getBlueBits()>5); - Assert.assertTrue(chosenCaps.getRedBits()>5); - - // - // Create native OpenGL resources .. XGL/WGL/CGL .. - // equivalent to GLAutoDrawable methods: setVisible(true) - // - final GLDrawableFactory factory = GLDrawableFactory.getFactory(reqGLCaps.getGLProfile()); - - final GLDrawable drawable = factory.createGLDrawable(window); - Assert.assertNotNull(drawable); - System.out.println("Drawable Pre-GL(0): "+drawable.getClass().getName()+", "+drawable.getNativeSurface().getClass().getName()); - - // - drawable.setRealized(true); - Assert.assertTrue(drawable.isRealized()); - - System.out.println("Window Caps PostGL : "+window.getGraphicsConfiguration().getChosenCapabilities()); - System.out.println("Drawable Post-GL(1): "+drawable.getClass().getName()+", "+drawable.getNativeSurface().getClass().getName()); - - // Check caps of GLDrawable after realization - final GLCapabilitiesImmutable chosenGLCaps = drawable.getChosenGLCapabilities(); - System.out.println("Chosen GL Caps(1): "+chosenGLCaps); - Assert.assertNotNull(chosenGLCaps); - Assert.assertTrue(chosenGLCaps.getGreenBits()>5); - Assert.assertTrue(chosenGLCaps.getBlueBits()>5); - Assert.assertTrue(chosenGLCaps.getRedBits()>5); - Assert.assertTrue(chosenGLCaps.getDepthBits()>4); - Assert.assertEquals(expGLCaps.isOnscreen(), chosenGLCaps.isOnscreen()); - Assert.assertEquals(expGLCaps.isFBO(), chosenGLCaps.isFBO()); - Assert.assertEquals(expGLCaps.isPBuffer(), chosenGLCaps.isPBuffer()); - Assert.assertEquals(expGLCaps.isBitmap(), chosenGLCaps.isBitmap()); - if(chosenGLCaps.isOnscreen() || chosenGLCaps.isFBO()) { - // dbl buffer may be disabled w/ offscreen pbuffer and bitmap - Assert.assertEquals(expGLCaps.getDoubleBuffered(), chosenGLCaps.getDoubleBuffered()); - } - - GLContext context = drawable.createContext(null); - Assert.assertNotNull(context); - int res = context.makeCurrent(); - Assert.assertTrue(GLContext.CONTEXT_CURRENT_NEW==res || GLContext.CONTEXT_CURRENT==res); - context.release(); - - System.out.println("Chosen GL Caps(2): "+drawable.getChosenGLCapabilities()); - System.out.println("Drawable Post-GL(2): "+drawable.getClass().getName()+", "+drawable.getNativeSurface().getClass().getName()); - - drawable.setRealized(false); - window.destroy(); - } - - @Test - public void testAvailableInfo() { - GLDrawableFactory f = GLDrawableFactory.getDesktopFactory(); - if(null != f) { - System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString()); - } - f = GLDrawableFactory.getEGLFactory(); - if(null != f) { - System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString()); - } - } - - @Test - public void testGL2OnScreenDblBuf() throws InterruptedException { - if(!checkProfile(GLProfile.GL2)) { - return; - } - final GLCapabilities reqGLCaps = new GLCapabilities(GLProfile.get(GLProfile.GL2)); - doTest(reqGLCaps, new GearsES2(1)); - } - - @Test - public void testGL2OffScreenAutoDblBuf() throws InterruptedException { - if(!checkProfile(GLProfile.GL2)) { - return; - } - final GLCapabilities reqGLCaps = new GLCapabilities(GLProfile.get(GLProfile.GL2)); - reqGLCaps.setOnscreen(false); - doTest(reqGLCaps, new GearsES2(1)); - } - - @Test - public void testGL2OffScreenFBODblBuf() throws InterruptedException { - if(!checkProfile(GLProfile.GL2)) { - return; - } - final GLCapabilities reqGLCaps = new GLCapabilities(GLProfile.get(GLProfile.GL2)); - reqGLCaps.setOnscreen(false); - reqGLCaps.setFBO(true); - doTest(reqGLCaps, new GearsES2(1)); - } - - @Test - public void testGL2OffScreenPbufferDblBuf() throws InterruptedException { - if(!checkProfile(GLProfile.GL2)) { - return; - } - final GLCapabilities reqGLCaps = new GLCapabilities(GLProfile.get(GLProfile.GL2)); - reqGLCaps.setOnscreen(false); - reqGLCaps.setPBuffer(true); - doTest(reqGLCaps, new GearsES2(1)); - } - - @Test - public void testGL2OffScreenBitmapDblBuf() throws InterruptedException { - if(!checkProfile(GLProfile.GL2)) { - return; - } - final GLCapabilities reqGLCaps = new GLCapabilities(GLProfile.get(GLProfile.GL2)); - reqGLCaps.setOnscreen(false); - reqGLCaps.setBitmap(true); - doTest(reqGLCaps, new GearsES2(1)); - } - - @Test - public void testES2OnScreenDblBuf() throws InterruptedException { - if(!checkProfile(GLProfile.GLES2)) { - return; - } - final GLCapabilities reqGLCaps = new GLCapabilities(GLProfile.get(GLProfile.GLES2)); - doTest(reqGLCaps, new GearsES2(1)); - } - - @Test - public void testES2OffScreenAutoDblBuf() throws InterruptedException { - if(!checkProfile(GLProfile.GLES2)) { - return; - } - final GLCapabilities reqGLCaps = new GLCapabilities(GLProfile.get(GLProfile.GLES2)); - reqGLCaps.setOnscreen(false); - doTest(reqGLCaps, new GearsES2(1)); - } - - @Test - public void testES2OffScreenFBODblBuf() throws InterruptedException { - if(!checkProfile(GLProfile.GLES2)) { - return; - } - final GLCapabilities reqGLCaps = new GLCapabilities(GLProfile.get(GLProfile.GLES2)); - reqGLCaps.setOnscreen(false); - reqGLCaps.setFBO(true); - doTest(reqGLCaps, new GearsES2(1)); - } - - @Test - public void testES2OffScreenPbufferDblBuf() throws InterruptedException { - if(!checkProfile(GLProfile.GLES2)) { - return; - } - final GLCapabilities reqGLCaps = new GLCapabilities(GLProfile.get(GLProfile.GLES2)); - reqGLCaps.setOnscreen(false); - reqGLCaps.setPBuffer(true); - doTest(reqGLCaps, new GearsES2(1)); - } - - /** Not implemented ! - @Test - public void testES2OffScreenBitmapDblBuf() throws InterruptedException { - if(!checkProfile(GLProfile.GLES2)) { - return; - } - final GLCapabilities reqGLCaps = new GLCapabilities(GLProfile.get(GLProfile.GLES2)); - reqGLCaps.setOnscreen(false); - reqGLCaps.setBitmap(true); - doTest(reqGLCaps, new GearsES2(1)); - } */ - - public static void main(String args[]) throws IOException { - org.junit.runner.JUnitCore.main(TestGLCapabilities01NEWT.class.getName()); - } - -} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextDrawableSwitchNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextDrawableSwitchNEWT.java index cece4c6d5..4c1130498 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextDrawableSwitchNEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLContextDrawableSwitchNEWT.java @@ -39,13 +39,14 @@ import com.jogamp.newt.event.WindowUpdateEvent; import com.jogamp.newt.opengl.GLWindow; import javax.media.opengl.GLAutoDrawable; -import javax.media.opengl.GLAutoDrawableDelegate; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLContext; import javax.media.opengl.GLDrawable; import javax.media.opengl.GLDrawableFactory; import javax.media.opengl.GLEventListener; import javax.media.opengl.GLProfile; + +import com.jogamp.opengl.GLAutoDrawableDelegate; import com.jogamp.opengl.util.Animator; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; @@ -81,14 +82,17 @@ public class TestGLContextDrawableSwitchNEWT extends UITestCase { Assert.assertTrue(AWTRobotUtil.waitForVisible(window, true)); Assert.assertTrue(AWTRobotUtil.waitForRealized(window, true)); - GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile()); - GLDrawable drawable = factory.createGLDrawable(window); + final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile()); + final GLDrawable drawable = factory.createGLDrawable(window); Assert.assertNotNull(drawable); drawable.setRealized(true); Assert.assertTrue(drawable.isRealized()); - final GLAutoDrawableDelegate glad = new GLAutoDrawableDelegate(drawable, null, window, false) { + final GLContext context = drawable.createContext(null); + Assert.assertNotNull(context); + + final GLAutoDrawableDelegate glad = new GLAutoDrawableDelegate(drawable, context, window, false, null) { @Override protected void destroyImplInLock() { super.destroyImplInLock(); @@ -104,7 +108,7 @@ public class TestGLContextDrawableSwitchNEWT extends UITestCase { } @Override public void windowResized(WindowEvent e) { - glad.windowResizedOp(); + glad.windowResizedOp(window.getWidth(), window.getHeight()); } @Override public void windowDestroyNotify(WindowEvent e) { @@ -123,9 +127,13 @@ public class TestGLContextDrawableSwitchNEWT extends UITestCase { GLAutoDrawable glad1 = createGLAutoDrawable(caps, 64, 64, width, height, quitAdapter); // no GLContext! GLAutoDrawable glad2 = createGLAutoDrawable(caps, 2*64+width, 64, width+100, height+100, quitAdapter); // no GLContext! - // create single context using glad1 and assign it to glad1 + // create single context using glad1 and assign it to glad1, + // after destroying the prev. context! { - GLContext singleCtx = glad1.createContext(null); + final GLContext oldCtx = glad1.getContext(); + Assert.assertNotNull(oldCtx); + oldCtx.destroy(); + final GLContext singleCtx = glad1.createContext(null); Assert.assertNotNull(singleCtx); int res = singleCtx.makeCurrent(); Assert.assertTrue(GLContext.CONTEXT_CURRENT_NEW==res || GLContext.CONTEXT_CURRENT==res); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLDrawable01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLDrawable01NEWT.java deleted file mode 100644 index a6e9cfb07..000000000 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLDrawable01NEWT.java +++ /dev/null @@ -1,171 +0,0 @@ -/** - * Copyright 2010 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ - -package com.jogamp.opengl.test.junit.jogl.acore; - -import java.io.IOException; - -import javax.media.nativewindow.CapabilitiesImmutable; -import javax.media.opengl.GL; -import javax.media.opengl.GLCapabilities; -import javax.media.opengl.GLCapabilitiesImmutable; -import javax.media.opengl.GLContext; -import javax.media.opengl.GLDrawable; -import javax.media.opengl.GLDrawableFactory; -import javax.media.opengl.GLProfile; - -import org.junit.Assert; -import org.junit.Test; - -import com.jogamp.newt.NewtFactory; -import com.jogamp.newt.Window; -import com.jogamp.opengl.test.junit.util.AWTRobotUtil; -import com.jogamp.opengl.test.junit.util.UITestCase; - -public class TestGLDrawable01NEWT extends UITestCase { - static final int width = 200, height = 200; - - void doTest(String profile, boolean onscreen, boolean fbo, boolean pbuffer) throws InterruptedException { - if( !GLProfile.isAvailable(profile) ) { - System.err.println("Profile "+profile+" n/a"); - return; - } - - final GLProfile glp = GLProfile.get(profile); - final GLCapabilities reqGLCaps = new GLCapabilities(glp); - - reqGLCaps.setOnscreen(onscreen); - reqGLCaps.setPBuffer(!onscreen && pbuffer); - reqGLCaps.setFBO(!onscreen && fbo); - reqGLCaps.setDoubleBuffered(onscreen); - // System.out.println("Requested: "+caps); - - // - // Create native windowing resources .. X11/Win/OSX - // - Window window = NewtFactory.createWindow(reqGLCaps); - Assert.assertNotNull(window); - window.setSize(width, height); - window.setVisible(true); - AWTRobotUtil.waitForVisible(window, true); - AWTRobotUtil.waitForRealized(window, true); - // System.out.println("Created: "+window); - - // Check caps of NativeWindow config w/o GL - final CapabilitiesImmutable chosenCaps = window.getGraphicsConfiguration().getChosenCapabilities(); - Assert.assertNotNull(chosenCaps); - Assert.assertTrue(chosenCaps.getGreenBits()>5); - Assert.assertTrue(chosenCaps.getBlueBits()>5); - Assert.assertTrue(chosenCaps.getRedBits()>5); - - // - // Create native OpenGL resources .. XGL/WGL/CGL .. - // equivalent to GLAutoDrawable methods: setVisible(true) - // - final GLDrawableFactory factory = GLDrawableFactory.getFactory(glp); - - final GLDrawable drawable = factory.createGLDrawable(window); - Assert.assertNotNull(drawable); - // System.out.println("Pre: "+drawable); - // - drawable.setRealized(true); - Assert.assertTrue(drawable.isRealized()); - - // Check caps of GLDrawable after realization - final GLCapabilitiesImmutable chosenGLCaps = drawable.getChosenGLCapabilities(); - Assert.assertNotNull(chosenGLCaps); - Assert.assertTrue(chosenGLCaps.getGreenBits()>5); - Assert.assertTrue(chosenGLCaps.getBlueBits()>5); - Assert.assertTrue(chosenGLCaps.getRedBits()>5); - Assert.assertTrue(chosenGLCaps.getDepthBits()>4); - Assert.assertEquals(reqGLCaps.isOnscreen(), chosenGLCaps.isOnscreen()); - Assert.assertEquals(reqGLCaps.isOnscreen(), chosenGLCaps.getDoubleBuffered()); // offscreen shall be !dbl-buffer - // System.out.println("Post: "+drawable); - - GLContext context = drawable.createContext(null); - Assert.assertNotNull(context); - // System.out.println(context); - - int res = context.makeCurrent(); - Assert.assertTrue(GLContext.CONTEXT_CURRENT_NEW==res || GLContext.CONTEXT_CURRENT==res); - - // draw something .. - final GL gl = context.getGL(); - gl.glClearColor(1, 1, 1, 1); - gl.glEnable(GL.GL_DEPTH_TEST); - Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); - gl.glViewport(0, 0, width, height); - gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); - Assert.assertEquals(GL.GL_NO_ERROR, gl.glGetError()); - - drawable.swapBuffers(); - context.release(); - - Thread.sleep(50); - - context.destroy(); - drawable.setRealized(false); - window.destroy(); - // System.out.println("Final: "+window); - } - - @Test - public void testGL2OnScreen() throws InterruptedException { - doTest(GLProfile.GL2, true, false, false); - } - - @Test - public void testES2OnScreen() throws InterruptedException { - doTest(GLProfile.GLES2, true, false, false); - } - - @Test - public void testGL2PBuffer() throws InterruptedException { - doTest(GLProfile.GL2, false, false, true); - } - - @Test - public void testES2PBuffer() throws InterruptedException { - doTest(GLProfile.GLES2, false, false, true); - } - - // @Test // TODO: FBO-Drawable via createGLDrawable and pre-exisiting NativeSurface - public void testGL2FBO() throws InterruptedException { - doTest(GLProfile.GL2, false, true, false); - } - - // @Test // TODO: FBO-Drawable via createGLDrawable and pre-exisiting NativeSurface - public void testES2FBO() throws InterruptedException { - doTest(GLProfile.GLES2, false, true, false); - } - - public static void main(String args[]) throws IOException { - org.junit.runner.JUnitCore.main(TestGLDrawable01NEWT.class.getName()); - } - -} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLExtensionQueryOffscreen.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLExtensionQueryOffscreen.java index e4245ef11..d4f3fece5 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLExtensionQueryOffscreen.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLExtensionQueryOffscreen.java @@ -32,14 +32,11 @@ import java.util.Collections; import java.util.SortedSet; import java.util.TreeSet; -import javax.media.nativewindow.AbstractGraphicsDevice; -import javax.media.opengl.DefaultGLCapabilitiesChooser; import javax.media.opengl.GL; -import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLCapabilities; -import javax.media.opengl.GLCapabilitiesChooser; import javax.media.opengl.GLContext; import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLOffscreenAutoDrawable; import javax.media.opengl.GLProfile; import jogamp.opengl.GLDrawableFactoryImpl; @@ -77,13 +74,11 @@ public class TestGLExtensionQueryOffscreen { @Test public void testJogl2ExtensionCheck2() { - GLCapabilities caps = new GLCapabilities(GLProfile.getDefault()); - GLDrawableFactory factory = GLDrawableFactory.getDesktopFactory(); - GLCapabilitiesChooser glCapsChooser = new DefaultGLCapabilitiesChooser(); - AbstractGraphicsDevice agd = factory.getDefaultDevice(); + final GLCapabilities caps = new GLCapabilities(GLProfile.getDefault()); + final GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile()); + final GLOffscreenAutoDrawable drawable = factory.createOffscreenAutoDrawable(null, caps, null, 256, 256, null); - GLAutoDrawable drawable = factory.createGLPbuffer(agd, caps, glCapsChooser, 256, 256, null); - GLContext context = drawable.getContext(); + final GLContext context = drawable.getContext(); context.makeCurrent(); String extensions; try { @@ -94,8 +89,8 @@ public class TestGLExtensionQueryOffscreen { String[] tabExtensions = extensions.split(" "); SortedSet setExtensions = new TreeSet(); Collections.addAll(setExtensions, tabExtensions); - System.out.println("DefaulContext: "+context); - System.out.println("DefaulContext: "+setExtensions); + System.out.println("DefaultContext: "+context); + System.out.println("DefaultContext: "+setExtensions); } } 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 33a9b7799..c1b7464e7 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 @@ -11,12 +11,14 @@ import javax.media.opengl.DefaultGLCapabilitiesChooser; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLCapabilitiesImmutable; import javax.media.opengl.GLDrawableFactory; +import javax.media.opengl.GLOffscreenAutoDrawable; import javax.media.opengl.GLPbuffer; import javax.media.opengl.GLProfile; /** * Tests the closing the device of GLWindow and GLPBuffer in JOGL */ +@SuppressWarnings("deprecation") public class TestNEWTCloseX11DisplayBug565 { @Test @@ -59,7 +61,7 @@ public class TestNEWTCloseX11DisplayBug565 { @Test - public void testX11WindowMemoryLeakOffscreenWindow() throws Exception { + public void testX11WindowMemoryLeakGLPbuffer() throws Exception { GLProfile.initSingleton(); // ensure shared resource runner is done try { for ( int j = 0; j < 10; j++ ) { @@ -100,6 +102,48 @@ public class TestNEWTCloseX11DisplayBug565 { } } + @Test + public void testX11WindowMemoryLeakFBOAutoDrawable() throws Exception { + GLProfile.initSingleton(); // ensure shared resource runner is done + try { + for ( int j = 0; j < 10; j++ ) { + final int open0; + if(NativeWindowFactory.TYPE_X11 == NativeWindowFactory.getNativeWindowType(false)) { + open0 = X11Util.getOpenDisplayConnectionNumber(); + } else { + open0 = 0; + } + final GLProfile glp = GLProfile.getDefault( ); + GLCapabilitiesImmutable caps = new GLCapabilities( glp ); + + + GLOffscreenAutoDrawable buffer = GLDrawableFactory.getFactory( glp ).createOffscreenAutoDrawable( + null, + caps, + new DefaultGLCapabilitiesChooser(), + 256, + 256, + null + ); + buffer.display(); + buffer.destroy(); + + if(NativeWindowFactory.TYPE_X11 == NativeWindowFactory.getNativeWindowType(false)) { + final int openD = X11Util.getOpenDisplayConnectionNumber() - open0; + if(openD > 0) { + X11Util.dumpOpenDisplayConnections(); + X11Util.dumpPendingDisplayConnections(); + Assert.assertEquals("New display connection didn't close", 0, openD); + } + } + } + } + catch ( Exception e ) { + e.printStackTrace(); + Assert.fail(e.getMessage()); + } + } + public static void main(String args[]) { org.junit.runner.JUnitCore.main(TestNEWTCloseX11DisplayBug565.class.getName()); } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestOffscreenLayer01GLCanvasAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestOffscreenLayer01GLCanvasAWT.java new file mode 100644 index 000000000..d181800c5 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestOffscreenLayer01GLCanvasAWT.java @@ -0,0 +1,236 @@ +/** + * Copyright 2011 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package com.jogamp.opengl.test.junit.jogl.acore; + +import java.awt.BorderLayout; +import java.awt.Button; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Frame; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; + +import javax.media.opengl.GLAnimatorControl; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.awt.GLCanvas; + +import jogamp.nativewindow.jawt.JAWTUtil; + +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.jogamp.common.os.Platform; +import com.jogamp.newt.Window; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.util.Animator; + +public class TestOffscreenLayer01GLCanvasAWT extends UITestCase { + static boolean useMSAA = false; + static boolean addComp = true; + static int swapInterval = 1; + static boolean shallUseOffscreenPBufferLayer = false; + static boolean noAnimation = false; + static Dimension frameSize0; + static Dimension frameSize1; + static Dimension preferredGLSize; + static long durationPerTest = 1000; + + @BeforeClass + public static void initClass() { + frameSize0 = new Dimension(500,300); + frameSize1 = new Dimension(800,600); + preferredGLSize = new Dimension(400,200); + } + + private void setupFrameAndShow(final Frame f, java.awt.Component comp) throws InterruptedException, InvocationTargetException { + + Container c = new Container(); + c.setLayout(new BorderLayout()); + c.add(new Button("north"), BorderLayout.NORTH); + c.add(new Button("south"), BorderLayout.SOUTH); + c.add(new Button("east"), BorderLayout.EAST); + c.add(new Button("west"), BorderLayout.WEST); + c.add(comp, BorderLayout.CENTER); + + f.setLayout(new BorderLayout()); + f.add(new Button("NORTH"), BorderLayout.NORTH); + f.add(new Button("SOUTH"), BorderLayout.SOUTH); + f.add(new Button("EAST"), BorderLayout.EAST); + f.add(new Button("WEST"), BorderLayout.WEST); + f.add(c, BorderLayout.CENTER); + + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + f.pack(); + f.validate(); + f.setVisible(true); + }}); + } + + private void end(GLAnimatorControl actrl, final Frame f, Window w) throws InterruptedException, InvocationTargetException { + actrl.stop(); + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + f.dispose(); + } } ); + if(null != w) { + w.destroy(); + } + } + + @Test + public void testInfo00() throws InterruptedException, InvocationTargetException { + System.err.println("Java Version: "+Platform.getJavaVersionNumber()); + System.err.println("OS Version: "+Platform.getOSVersionNumber()); + System.err.println("JAWTUtil.isOffscreenLayerRequired(): "+JAWTUtil.isOffscreenLayerRequired()); + System.err.println("JAWTUtil.isOffscreenLayerSupported(): "+JAWTUtil.isOffscreenLayerSupported()); + } + + @Test + public void testOffscreenLayerGLCanvas_OffscreenLayerWithOnscreenClass() throws InterruptedException, InvocationTargetException { + testOffscreenLayerGLCanvas_Impl(true); + } + + private void testOffscreenLayerGLCanvas_Impl(boolean offscreenLayer) throws InterruptedException, InvocationTargetException { + if(!offscreenLayer && JAWTUtil.isOffscreenLayerRequired()) { + System.err.println("onscreen layer n/a"); + return; + } + if(offscreenLayer && !JAWTUtil.isOffscreenLayerSupported()) { + System.err.println("offscreen layer n/a"); + return; + } + final Frame frame1 = new Frame("AWT Parent Frame"); + + GLCapabilities caps = new GLCapabilities(null); + if(useMSAA) { + caps.setNumSamples(4); + caps.setSampleBuffers(true); + } + if(shallUseOffscreenPBufferLayer) { + caps.setPBuffer(true); + caps.setOnscreen(true); // simulate normal behavior .. + } + final GLCanvas glc = new GLCanvas(caps); + glc.setShallUseOffscreenLayer(offscreenLayer); // trigger offscreen layer - if supported + glc.setPreferredSize(preferredGLSize); + glc.setMinimumSize(preferredGLSize); + glc.setSize(preferredGLSize); + + GearsES2 demo1 = new GearsES2(swapInterval); + if(noAnimation) { + demo1.setDoRotation(false); + } + glc.addGLEventListener(demo1); + + frame1.setSize(frameSize0); + setupFrameAndShow(frame1, glc); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glc, true)); + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(glc, true)); + Assert.assertEquals(JAWTUtil.isOffscreenLayerSupported() && offscreenLayer, + glc.isOffscreenLayerSurfaceEnabled()); + + GLAnimatorControl animator1 = new Animator(glc); + if(!noAnimation) { + animator1.start(); + } + animator1.setUpdateFPSFrames(60, System.err); + + Thread.sleep(durationPerTest/2); + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame1.setSize(frameSize1); + frame1.pack(); + frame1.validate(); + }}); + + Thread.sleep(durationPerTest/2); + + end(animator1, frame1, null); + } + + 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 + * {@link JFrame} . {@link Container}+ . {@link NewtCanvasAWT} . {@link GLWindow} + *

      + *

      + * + Container is the JFrame's implicit root content pane
      + *

      + */ public class TestFocus01SwingAWTRobot extends UITestCase { static int width, height; static long durationPerTest = 10; @@ -125,6 +135,10 @@ public class TestFocus01SwingAWTRobot extends UITestCase { AWTKeyAdapter buttonKA = new AWTKeyAdapter("Button"); button.addKeyListener(buttonKA); eventCountAdapters.add(buttonKA); + AWTMouseAdapter buttonMA = new AWTMouseAdapter("Button"); + button.addMouseListener(buttonMA); + eventCountAdapters.add(buttonMA); + frame1.getContentPane().add(button, BorderLayout.NORTH); frame1.setSize(width, height); javax.swing.SwingUtilities.invokeAndWait(new Runnable() { @@ -158,13 +172,18 @@ public class TestFocus01SwingAWTRobot extends UITestCase { Assert.assertEquals(false, newtCanvasAWTFA.focusGained()); System.err.println("FOCUS AWT Button sync"); AWTRobotUtil.assertKeyType(robot, java.awt.event.KeyEvent.VK_A, 2, button, buttonKA); + AWTRobotUtil.assertMouseClick(robot, java.awt.event.InputEvent.BUTTON1_MASK, 1, + button, buttonMA); + AWTRobotUtil.assertMouseClick(robot, java.awt.event.InputEvent.BUTTON1_MASK, 2, + button, buttonMA); // Request the AWT focus, which should automatically provide the NEWT window with focus. Thread.sleep(100); // allow event sync System.err.println("FOCUS NEWT Canvas/GLWindow request"); EventCountAdapterUtil.reset(eventCountAdapters); AWTRobotUtil.assertRequestFocusAndWait(robot, newtCanvasAWT, newtCanvasAWT.getNEWTChild(), glWindow1FA, buttonFA); - Assert.assertEquals(false, newtCanvasAWTFA.focusGained()); + Assert.assertTrue("Focus prev. gained, but NewtCanvasAWT didn't loose it. Gainer: "+glWindow1FA+"; Looser "+newtCanvasAWTFA, + AWTRobotUtil.waitForFocus(glWindow1FA, newtCanvasAWTFA)); System.err.println("FOCUS NEWT Canvas/GLWindow sync"); AWTRobotUtil.assertKeyType(robot, java.awt.event.KeyEvent.VK_A, 2, glWindow1, glWindow1KA); Assert.assertEquals("AWT parent canvas received keyboard events", 0, newtCanvasAWTKA.getCount()); diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestFocus02SwingAWTRobot.java b/src/test/com/jogamp/opengl/test/junit/newt/TestFocus02SwingAWTRobot.java index a0efa53ad..d8a9640c1 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/TestFocus02SwingAWTRobot.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/TestFocus02SwingAWTRobot.java @@ -56,6 +56,15 @@ import java.io.IOException; import com.jogamp.opengl.test.junit.util.*; import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +/** + * Testing focus traversal of an AWT component tree with {@link NewtCanvasAWT} attached. + *

      + * {@link JFrame} . {@link JPanel}+ . {@link Container} . {@link NewtCanvasAWT} . {@link GLWindow} + *

      + *

      + * + JPanel is set as JFrame's root content pane
      + *

      + */ public class TestFocus02SwingAWTRobot extends UITestCase { static int width, height; static long durationPerTest = 10; @@ -85,9 +94,6 @@ public class TestFocus02SwingAWTRobot extends UITestCase { ArrayList eventCountAdapters = new ArrayList(); - /** - * JFrame . JPanel . Container . NewtCanvasAWT . GLWindow - */ GLWindow glWindow1 = GLWindow.create(glCaps); glWindow1.setTitle("testWindowParenting01CreateVisibleDestroy"); GLEventListener demo1 = new GearsES2(); @@ -225,7 +231,9 @@ public class TestFocus02SwingAWTRobot extends UITestCase { System.err.println("FOCUS NEWT Canvas/GLWindow request"); EventCountAdapterUtil.reset(eventCountAdapters); AWTRobotUtil.assertRequestFocusAndWait(robot, newtCanvasAWT, newtCanvasAWT.getNEWTChild(), glWindow1FA, buttonNorthInnerFA); - Assert.assertTrue(AWTRobotUtil.waitForFocusCount(false, newtCanvasAWTFA)); + Assert.assertTrue("Focus prev. gained, but NewtCanvasAWT didn't loose it. Gainer: "+glWindow1FA+"; Looser "+newtCanvasAWTFA, + AWTRobotUtil.waitForFocus(glWindow1FA, newtCanvasAWTFA)); + Assert.assertEquals(false, newtCanvasAWTFA.focusGained()); Assert.assertEquals(false, buttonNorthOuterFA.focusGained()); Assert.assertEquals(false, jFrame1FA.focusGained()); diff --git a/src/test/com/jogamp/opengl/test/junit/newt/TestWindows01NEWT.java b/src/test/com/jogamp/opengl/test/junit/newt/TestWindows01NEWT.java index bf72348f9..e03b5e7d6 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/TestWindows01NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/TestWindows01NEWT.java @@ -33,7 +33,6 @@ import org.junit.BeforeClass; import org.junit.Test; import javax.media.nativewindow.*; -import javax.media.nativewindow.util.Point; import com.jogamp.newt.*; import java.io.IOException; diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/NewtAWTReparentingKeyAdapter.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/NewtAWTReparentingKeyAdapter.java index 473f2f584..f7881615d 100644 --- a/src/test/com/jogamp/opengl/test/junit/newt/parenting/NewtAWTReparentingKeyAdapter.java +++ b/src/test/com/jogamp/opengl/test/junit/newt/parenting/NewtAWTReparentingKeyAdapter.java @@ -36,7 +36,7 @@ import com.jogamp.newt.event.KeyAdapter; import com.jogamp.newt.event.KeyEvent; import com.jogamp.newt.opengl.GLWindow; -class NewtAWTReparentingKeyAdapter extends KeyAdapter { +public class NewtAWTReparentingKeyAdapter extends KeyAdapter { Frame frame; NewtCanvasAWT newtCanvasAWT; GLWindow glWindow; diff --git a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParentingOffscreenLayer01GLCanvasAWT.java b/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParentingOffscreenLayer01GLCanvasAWT.java deleted file mode 100644 index 4542fa47e..000000000 --- a/src/test/com/jogamp/opengl/test/junit/newt/parenting/TestParentingOffscreenLayer01GLCanvasAWT.java +++ /dev/null @@ -1,211 +0,0 @@ -/** - * Copyright 2011 JogAmp Community. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of JogAmp Community. - */ - -package com.jogamp.opengl.test.junit.newt.parenting; - -import java.awt.BorderLayout; -import java.awt.Button; -import java.awt.Container; -import java.awt.Dimension; -import java.awt.Frame; -import java.io.IOException; -import java.lang.reflect.InvocationTargetException; - -import javax.media.opengl.GLAnimatorControl; -import javax.media.opengl.GLCapabilities; -import javax.media.opengl.GLEventListener; -import javax.media.opengl.awt.GLCanvas; - -import jogamp.nativewindow.jawt.JAWTUtil; - -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Test; - -import com.jogamp.common.os.Platform; -import com.jogamp.newt.Window; -import com.jogamp.newt.opengl.GLWindow; -import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; -import com.jogamp.opengl.test.junit.util.AWTRobotUtil; -import com.jogamp.opengl.test.junit.util.MiscUtils; -import com.jogamp.opengl.test.junit.util.UITestCase; -import com.jogamp.opengl.util.Animator; - -public class TestParentingOffscreenLayer01GLCanvasAWT extends UITestCase { - static Dimension frameSize0; - static Dimension frameSize1; - static Dimension preferredGLSize; - static Dimension minGLSize; - static long durationPerTest = 1000; - - @BeforeClass - public static void initClass() { - frameSize0 = new Dimension(500,300); - frameSize1 = new Dimension(800,600); - preferredGLSize = new Dimension(400,200); - minGLSize = new Dimension(200,100); - } - - private void setupFrameAndShow(final Frame f, java.awt.Component comp) throws InterruptedException, InvocationTargetException { - - Container c = new Container(); - c.setLayout(new BorderLayout()); - c.add(new Button("north"), BorderLayout.NORTH); - c.add(new Button("south"), BorderLayout.SOUTH); - c.add(new Button("east"), BorderLayout.EAST); - c.add(new Button("west"), BorderLayout.WEST); - c.add(comp, BorderLayout.CENTER); - - f.setLayout(new BorderLayout()); - f.add(new Button("NORTH"), BorderLayout.NORTH); - f.add(new Button("SOUTH"), BorderLayout.SOUTH); - f.add(new Button("EAST"), BorderLayout.EAST); - f.add(new Button("WEST"), BorderLayout.WEST); - f.add(c, BorderLayout.CENTER); - - javax.swing.SwingUtilities.invokeAndWait(new Runnable() { - public void run() { - f.validate(); - f.setVisible(true); - }}); - } - private void end(GLAnimatorControl actrl, final Frame f, Window w) throws InterruptedException, InvocationTargetException { - actrl.stop(); - javax.swing.SwingUtilities.invokeAndWait(new Runnable() { - public void run() { - f.dispose(); - } } ); - if(null != w) { - w.destroy(); - } - } - - @Test - public void testInfo00() throws InterruptedException, InvocationTargetException { - System.err.println("Java Version: "+Platform.getJavaVersionNumber()); - System.err.println("OS Version: "+Platform.getOSVersionNumber()); - System.err.println("JAWTUtil.isOffscreenLayerRequired(): "+JAWTUtil.isOffscreenLayerRequired()); - System.err.println("JAWTUtil.isOffscreenLayerSupported(): "+JAWTUtil.isOffscreenLayerSupported()); - } - - @Test - public void testOnscreenLayerGLCanvas_Onscreen() throws InterruptedException, InvocationTargetException { - testOffscreenLayerGLCanvas_Impl(false); - } - - @Test - public void testOffscreenLayerGLCanvas_OffscreenLayerWithOnscreenClass() throws InterruptedException, InvocationTargetException { - testOffscreenLayerGLCanvas_Impl(true); - } - - private void testOffscreenLayerGLCanvas_Impl(boolean offscreenLayer) throws InterruptedException, InvocationTargetException { - if(!offscreenLayer && JAWTUtil.isOffscreenLayerRequired()) { - System.err.println("onscreen layer n/a"); - return; - } - if(offscreenLayer && !JAWTUtil.isOffscreenLayerSupported()) { - System.err.println("offscreen layer n/a"); - return; - } - final Frame frame1 = new Frame("AWT Parent Frame"); - - GLCapabilities glCaps = new GLCapabilities(null); - final GLCanvas glc = new GLCanvas(glCaps); - glc.setShallUseOffscreenLayer(offscreenLayer); // trigger offscreen layer - if supported - glc.setPreferredSize(preferredGLSize); - glc.setMinimumSize(minGLSize); - - GLEventListener demo1 = new GearsES2(1); - glc.addGLEventListener(demo1); - - frame1.setSize(frameSize0); - setupFrameAndShow(frame1, glc); - Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glc, true)); - Assert.assertEquals(true, AWTRobotUtil.waitForVisible(glc, true)); - Assert.assertEquals(JAWTUtil.isOffscreenLayerSupported() && offscreenLayer, - glc.isOffscreenLayerSurfaceEnabled()); - - GLAnimatorControl animator1 = new Animator(glc); - animator1.start(); - - Thread.sleep(durationPerTest/2); - javax.swing.SwingUtilities.invokeAndWait(new Runnable() { - public void run() { - frame1.setSize(frameSize1); - frame1.validate(); - }}); - - Thread.sleep(durationPerTest/2); - - end(animator1, frame1, null); - } - - 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; ivisible within TIME_OUT diff --git a/src/test/com/jogamp/opengl/test/junit/util/NEWTGLContext.java b/src/test/com/jogamp/opengl/test/junit/util/NEWTGLContext.java index 3f989bfa4..a76b67d57 100644 --- a/src/test/com/jogamp/opengl/test/junit/util/NEWTGLContext.java +++ b/src/test/com/jogamp/opengl/test/junit/util/NEWTGLContext.java @@ -70,8 +70,8 @@ public class NEWTGLContext { Assert.assertNotNull(window); window.setSize(width, height); window.setVisible(true); - AWTRobotUtil.waitForVisible(window, true); - AWTRobotUtil.waitForRealized(window, true); + Assert.assertTrue(AWTRobotUtil.waitForVisible(window, true)); + Assert.assertTrue(AWTRobotUtil.waitForRealized(window, true)); GLDrawableFactory factory = GLDrawableFactory.getFactory(caps.getGLProfile()); GLDrawable drawable = factory.createGLDrawable(window); 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 c07d5b741..c42d9ff62 100644 --- a/src/test/com/jogamp/opengl/test/junit/util/UITestCase.java +++ b/src/test/com/jogamp/opengl/test/junit/util/UITestCase.java @@ -29,12 +29,14 @@ package com.jogamp.opengl.test.junit.util; import java.io.File; -import java.io.PrintWriter; -import java.io.StringWriter; +import java.util.Iterator; +import java.util.List; import javax.media.opengl.GL; +import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLCapabilitiesImmutable; import javax.media.opengl.GLDrawable; +import javax.media.opengl.GLEventListener; import com.jogamp.common.util.locks.SingletonInstance; import com.jogamp.opengl.util.GLReadBufferUtil; @@ -47,6 +49,8 @@ import org.junit.After; import org.junit.AfterClass; import org.junit.Rule; import org.junit.rules.TestName; +import org.junit.runners.model.FrameworkMethod; +import org.junit.runners.model.TestClass; public abstract class UITestCase { @@ -58,9 +62,11 @@ public abstract class UITestCase { public static final long SINGLE_INSTANCE_LOCK_TO = 3*60*1000; // wait up to 3 min public static final long SINGLE_INSTANCE_LOCK_POLL = 1000; // poll every 1s - static volatile SingletonInstance singletonInstance; + private static volatile SingletonInstance singletonInstance; - static volatile boolean testSupported = true; + private static volatile boolean testSupported = true; + + private static volatile int maxMethodNameLen = 0; private static final synchronized void initSingletonInstance() { if( null == singletonInstance ) { @@ -77,6 +83,20 @@ public abstract class UITestCase { testSupported = v; } + public int getMaxTestNameLen() { + if(0 == maxMethodNameLen) { + int ml = 0; + final TestClass tc = new TestClass(getClass()); + final List testMethods = tc.getAnnotatedMethods(org.junit.Test.class); + for(Iterator iter=testMethods.iterator(); iter.hasNext(); ) { + final int l = iter.next().getName().length(); + if( ml < l ) { ml = l; } + } + maxMethodNameLen = ml; + } + return maxMethodNameLen; + } + public final String getTestMethodName() { return _unitTestName.getMethodName(); } @@ -120,13 +140,12 @@ 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: + * Takes a snapshot of the drawable's current front framebuffer. Example filenames: *
      -     * TestFBODrawableNEWT.test01-F_rgba-I_rgba-S0_default-GL2-n0004-0800x0600.png
      -     * TestFBODrawableNEWT.test01-F_rgba-I_rgba-S0_default-GL2-n0005-0800x0600.png
      +     * TestGLDrawableAutoDelegateOnOffscrnCapsNEWT.testES2OffScreenFBOSglBuf____-n0001-msaa0-GLES2_-sw-fbobject-Bdbl-Frgb__Irgb_-S00_default-0400x0300.png
      +     * TestGLDrawableAutoDelegateOnOffscrnCapsNEWT.testES2OffScreenPbufferDblBuf-n0003-msaa0-GLES2_-sw-pbuffer_-Bdbl-Frgb__Irgb_-S00_default-0200x0150.png
      +     * TestGLDrawableAutoDelegateOnOffscrnCapsNEWT.testGL2OffScreenPbufferSglBuf-n0003-msaa0-GL2___-hw-pbuffer_-Bone-Frgb__Irgb_-S00_default-0200x0150.png
            * 
      - * - * @param simpleTestName will be used as the filename prefix * @param sn sequential number * @param postSNDetail optional detail to be added to the filename after sn * @param gl the current GL context object. It's read drawable is being used as the pixel source and to gather some details which will end up in the filename. @@ -137,30 +156,80 @@ public abstract class UITestCase { * It shall not end with a directory separator, {@link File#separatorChar}. * If null the current working directory is being used. */ - public static void snapshot(String simpleTestName, int sn, String postSNDetail, GL gl, GLReadBufferUtil readBufferUtil, String fileSuffix, String destPath) { + public void snapshot(int sn, String postSNDetail, GL gl, GLReadBufferUtil readBufferUtil, String fileSuffix, String destPath) { if(null == fileSuffix) { fileSuffix = TextureIO.PNG; } - final StringWriter filenameSW = new StringWriter(); - { + final int maxSimpleTestNameLen = getMaxTestNameLen()+getClass().getSimpleName().length()+1; + final String simpleTestName = this.getSimpleTestName("."); + final String filenameBaseName; + { final GLDrawable drawable = gl.getContext().getGLReadDrawable(); final GLCapabilitiesImmutable caps = drawable.getChosenGLCapabilities(); + final String accel = caps.getHardwareAccelerated() ? "hw" : "sw" ; + final String scrnm; + if(caps.isOnscreen()) { + scrnm = "onscreen"; + } else if(caps.isFBO()) { + scrnm = "fbobject"; + } else if(caps.isPBuffer()) { + scrnm = "pbuffer_"; + } else if(caps.isBitmap()) { + scrnm = "bitmap__"; + } else { + scrnm = "unknown_"; + } + final String dblb = caps.getDoubleBuffered() ? "dbl" : "one"; final String F_pfmt = readBufferUtil.hasAlpha() ? "rgba" : "rgb_"; final String pfmt = caps.getAlphaBits() > 0 ? "rgba" : "rgb_"; - final String aaext = caps.getSampleExtension(); final int samples = caps.getNumSamples() ; + final String aaext = caps.getSampleExtension(); postSNDetail = null != postSNDetail ? "-"+postSNDetail : ""; - final PrintWriter pw = new PrintWriter(filenameSW); - pw.printf("%s-n%04d%s-F_%s-I_%s-S%d_%s-%s-%04dx%04d.%s", - simpleTestName, sn, postSNDetail, F_pfmt, pfmt, samples, aaext, drawable.getGLProfile().getName(), - drawable.getWidth(), drawable.getHeight(), fileSuffix); + + filenameBaseName = String.format("%-"+maxSimpleTestNameLen+"s-n%04d%s-%-6s-%s-%s-B%s-F%s_I%s-S%02d_%s-%04dx%04d.%s", + simpleTestName, sn, postSNDetail, drawable.getGLProfile().getName(), accel, + scrnm, dblb, F_pfmt, pfmt, samples, aaext, + drawable.getWidth(), drawable.getHeight(), fileSuffix).replace(' ', '_'); } - final String filename = null != destPath ? destPath + File.separator + filenameSW.toString() : filenameSW.toString(); - System.err.println(Thread.currentThread().getName()+": ** screenshot: "+filename); + final String filename = null != destPath ? destPath + File.separator + filenameBaseName : filenameBaseName; + System.err.println(Thread.currentThread().getName()+": ** screenshot: "+filename+", maxTestNameLen "+maxSimpleTestNameLen+", <"+simpleTestName+">"); gl.glFinish(); // just make sure rendering finished .. if(readBufferUtil.readPixels(gl, false)) { readBufferUtil.write(new File(filename)); } - } + } + + public class SnapshotGLEventListener implements GLEventListener { + private final GLReadBufferUtil screenshot; + private volatile boolean makeShot = false; + private volatile int displayCount=0; + private volatile int reshapeCount=0; + public SnapshotGLEventListener(GLReadBufferUtil screenshot) { + this.screenshot = screenshot; + } + public SnapshotGLEventListener() { + this.screenshot = new GLReadBufferUtil(false, false); + } + + public void init(GLAutoDrawable drawable) {} + public void dispose(GLAutoDrawable drawable) {} + public void display(GLAutoDrawable drawable) { + final GL gl = drawable.getGL(); + System.err.println(Thread.currentThread().getName()+": ** display: "+displayCount+": "+drawable.getWidth()+"x"+drawable.getHeight()+", makeShot "+makeShot); + if(makeShot) { + makeShot=false; + snapshot(displayCount, null, gl, screenshot, TextureIO.PNG, null); + } + displayCount++; + } + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { + System.err.println(Thread.currentThread().getName()+": ** reshape: "+reshapeCount+": "+width+"x"+height+" - "+drawable.getWidth()+"x"+drawable.getHeight()); + reshapeCount++; + } + public void setMakeSnapshot() { + makeShot=true; + } + }; + } -- cgit v1.2.3 From 13600772542d9d5ad65c6d73b3d568100d6445b6 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Fri, 21 Dec 2012 19:24:51 +0100 Subject: GLContextImpl: Make createContextARBImpl/setGLFunctionAvailability more robost while detecting erroneous queried GL version --- make/scripts/java-win64-dbg.bat | 2 +- make/scripts/tests-x64.bat | 4 +-- make/scripts/tests.sh | 6 ++-- src/jogl/classes/jogamp/opengl/GLContextImpl.java | 37 ++++++++++++++-------- src/jogl/classes/jogamp/opengl/egl/EGLContext.java | 2 +- .../jogamp/opengl/egl/EGLExternalContext.java | 2 +- .../macosx/cgl/MacOSXExternalCGLContext.java | 2 +- .../macosx/cgl/awt/MacOSXJava2DCGLContext.java | 2 +- .../windows/wgl/WindowsExternalWGLContext.java | 2 +- .../opengl/windows/wgl/WindowsWGLContext.java | 2 +- .../opengl/x11/glx/X11ExternalGLXContext.java | 2 +- .../jogamp/opengl/x11/glx/X11GLXContext.java | 4 +-- 12 files changed, 38 insertions(+), 29 deletions(-) (limited to 'src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java') diff --git a/make/scripts/java-win64-dbg.bat b/make/scripts/java-win64-dbg.bat index 7ececa5e4..c9f329421 100755 --- a/make/scripts/java-win64-dbg.bat +++ b/make/scripts/java-win64-dbg.bat @@ -21,7 +21,7 @@ echo CP_ALL %CP_ALL% REM set D_ARGS="-Djogl.debug.GLContext" "-Djogl.debug.FBObject" REM set D_ARGS="-Djogl.debug.GLDrawable" "-Djogl.debug.EGLDrawableFactory.DontQuery" REM set D_ARGS="-Djogl.debug.GLDrawable" "-Djogl.debug.EGLDrawableFactory.QueryNativeTK" -REM set D_ARGS="-Djogl.debug=all" "-Dnewt.debug=all" "-Dnativewindow.debug=all" +set D_ARGS="-Djogl.debug=all" "-Dnewt.debug=all" "-Dnativewindow.debug=all" REM set D_ARGS="-Djogl.debug=all" "-Dnewt.debug=all" "-Dnativewindow.debug=all" "-Djogamp.debug=all" "-Djogl.debug.EGLDrawableFactory.DontQuery" REM set D_ARGS="-Dnativewindow.debug.GraphicsConfiguration -Djogl.debug.CapabilitiesChooser -Djogl.debug.GLProfile" REM set D_ARGS="-Djogamp.debug.IOUtil" "-Djogl.debug.GLSLCode" "-Djogl.debug.GLMediaPlayer" diff --git a/make/scripts/tests-x64.bat b/make/scripts/tests-x64.bat index 719435d74..d5d2d8f4e 100755 --- a/make/scripts/tests-x64.bat +++ b/make/scripts/tests-x64.bat @@ -10,7 +10,7 @@ REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestSharedCon REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextListNEWT -time 5000 REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextListNEWT2 %* REM scripts\java-win64.bat com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextVBOES2NEWT %* -REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.acore.TestGLProfile01NEWT %* +scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.acore.TestGLProfile01NEWT %* REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.acore.TestGLProfile02NEWT %* REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.acore.TestGLContextDrawableSwitchNEWT %* @@ -22,7 +22,7 @@ REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.awt.TestBug551A REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.awt.TestAWT03GLCanvasRecreate01 REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.awt.TestAWTCardLayoutAnimatorStartStopBug532 %* REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.awt.TestJScrollPaneMixHwLw01AWT %* -scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.awt.TestBug642JSplitPaneMixHwLw01AWT %* +REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.awt.TestBug642JSplitPaneMixHwLw01AWT %* REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.gl2.newt.TestGearsNewtAWTWrapper %* REM scripts\java-win64-dbg.bat com.jogamp.opengl.test.junit.jogl.demos.gl2.newt.TestGearsNEWT -time 30000 diff --git a/make/scripts/tests.sh b/make/scripts/tests.sh index 11a2dc9ba..3d8b3bcfe 100755 --- a/make/scripts/tests.sh +++ b/make/scripts/tests.sh @@ -100,7 +100,7 @@ function jrun() { #D_ARGS="-Djogl.debug.GLContext.NoProfileAliasing" #D_ARGS="-Djogamp.debug=all" #D_ARGS="-Djogamp.debug=all -Dnativewindow.debug=all -Djogl.debug=all -Dnewt.debug=all" - #D_ARGS="-Dnativewindow.debug=all -Djogl.debug=all -Dnewt.debug=all" + D_ARGS="-Dnativewindow.debug=all -Djogl.debug=all -Dnewt.debug=all" #D_ARGS="-Djogl.debug=all -Dnewt.debug=all" #D_ARGS="-Djogl.debug.GLContext -Djogl.debug.GLDrawable -Dnativewindow.debug.GraphicsConfiguration" #D_ARGS="-Djogl.debug.GLDrawable" @@ -264,7 +264,7 @@ function testawtswt() { #testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestPMVMatrix02NEWT $* #testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestNEWTCloseX11DisplayBug565 $* #testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestMainVersionGLWindowNEWT $* -#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLProfile00NEWT $* +testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLProfile00NEWT $* #testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLProfile01NEWT $* #testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestShutdownCompleteNEWT $* #testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestInitConcurrent01NEWT $* @@ -278,7 +278,7 @@ function testawtswt() { #testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextVBOES2NEWT $* #testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLContextDrawableSwitchNEWT $* #testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLPointsNEWT $* -testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLUnitsNEWT $* +#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLUnitsNEWT $* #testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableDelegateOnOffscrnCapsNEWT $* #testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLAutoDrawableFactoryOffscrnCapsNEWT $* diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java index 24fc466b1..0a665f07e 100644 --- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java +++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java @@ -693,8 +693,7 @@ public abstract class GLContextImpl extends GLContext { * @see #createContextARBImpl * @see #destroyContextARBImpl */ - protected abstract long createContextARBImpl(long share, boolean direct, int ctxOptionFlags, - int major, int minor); + protected abstract long createContextARBImpl(long share, boolean direct, int ctxOptionFlags, int major, int minor); /** * Destroy the context created by {@link #createContextARBImpl}. @@ -757,7 +756,7 @@ public abstract class GLContextImpl extends GLContext { _ctp[0] |= additionalCtxCreationFlags; _ctx = createContextARBImpl(share, direct, _ctp[0], _major[0], _minor[0]); if(0!=_ctx) { - setGLFunctionAvailability(true, _major[0], _minor[0], _ctp[0]); + setGLFunctionAvailability(true, _major[0], _minor[0], _ctp[0], false); } } return _ctx; @@ -940,8 +939,7 @@ public abstract class GLContextImpl extends GLContext { _context = createContextARBImpl(share, direct, ctxOptionFlags, major[0], minor[0]); if(0 != _context) { - ok = true; - setGLFunctionAvailability(true, major[0], minor[0], ctxOptionFlags); + ok = setGLFunctionAvailability(true, major[0], minor[0], ctxOptionFlags, true); } else { ok = false; } @@ -1166,15 +1164,17 @@ public abstract class GLContextImpl extends GLContext { * @param major OpenGL major version * @param minor OpenGL minor version * @param ctxProfileBits OpenGL context profile and option bits, see {@link javax.media.opengl.GLContext#CTX_OPTION_ANY} - * + * @param strictVersionMatch if true and the ctx version (by string) is lower than the given major.minor version, + * method aborts and returns false, otherwise true. + * @return returns true if successful, otherwise false. See strictVersionMatch. * @see #setContextVersion * @see javax.media.opengl.GLContext#CTX_OPTION_ANY * @see javax.media.opengl.GLContext#CTX_PROFILE_COMPAT * @see javax.media.opengl.GLContext#CTX_IMPL_ES2_COMPAT */ - protected final void setGLFunctionAvailability(boolean force, int major, int minor, int ctxProfileBits) { + protected final boolean setGLFunctionAvailability(boolean force, int major, int minor, int ctxProfileBits, boolean strictVersionMatch) { if(null!=this.gl && null!=glProcAddressTable && !force) { - return; // already done and not forced + return true; // already done and not forced } if(null==this.gl || !verifyInstance(gl.getGLProfile(), "Impl", this.gl)) { @@ -1206,7 +1206,13 @@ public abstract class GLContextImpl extends GLContext { { final VersionNumber setGLVersionNumber = new VersionNumber(major, minor, 0); final VersionNumber strGLVersionNumber = getGLVersionNumber(ctxProfileBits, glVersion); - if( null != strGLVersionNumber && ( strGLVersionNumber.compareTo(setGLVersionNumber) <= 0 || 0 == major ) ) { + if( null != strGLVersionNumber && ( strGLVersionNumber.compareTo(setGLVersionNumber) < 0 || 0 == major ) ) { + if( 0 < major && strictVersionMatch ) { + if(DEBUG) { + System.err.println(getThreadName() + ": GLContext.setGLFuncAvail.X: FAIL, GL version mismatch: "+major+"."+minor+", ctp "+toHexString(ctxProfileBits)+", "+glVersion+", "+strGLVersionNumber); + } + return false; + } glVersionNumber = strGLVersionNumber; major = glVersionNumber.getMajor(); minor = glVersionNumber.getMinor(); @@ -1299,8 +1305,9 @@ public abstract class GLContextImpl extends GLContext { setDefaultSwapInterval(); if(DEBUG) { - System.err.println(getThreadName() + ": GLContext.setGLFuncAvail.X: "+contextFQN+" - "+GLContext.getGLVersion(ctxMajorVersion, ctxMinorVersion, ctxOptions, null)); + System.err.println(getThreadName() + ": GLContext.setGLFuncAvail.X: OK "+contextFQN+" - "+GLContext.getGLVersion(ctxMajorVersion, ctxMinorVersion, ctxOptions, null)); } + return true; } private final void setRendererQuirks(boolean hwAccel) { @@ -1380,16 +1387,18 @@ public abstract class GLContextImpl extends GLContext { } synchronized(mappedContextTypeObjectLock) { - ProcAddressTable table = mappedGLProcAddress.remove( contextFQN ); + final ProcAddressTable table = mappedGLProcAddress.remove( contextFQN ); if(DEBUG) { - System.err.println(getThreadName() + ": RM GLContext GL ProcAddressTable mapping key("+contextFQN+") -> "+table.hashCode()); + final int hc = null != table ? table.hashCode() : 0; + System.err.println(getThreadName() + ": RM GLContext GL ProcAddressTable mapping key("+contextFQN+") -> "+toHexString(hc)); } } synchronized(mappedContextTypeObjectLock) { - ExtensionAvailabilityCache eCache = mappedExtensionAvailabilityCache.remove( contextFQN ); + final ExtensionAvailabilityCache eCache = mappedExtensionAvailabilityCache.remove( contextFQN ); if(DEBUG) { - System.err.println(getThreadName() + ": RM GLContext GL ExtensionAvailabilityCache mapping key("+contextFQN+") -> "+eCache.hashCode()); + final int hc = null != eCache ? eCache.hashCode() : 0; + System.err.println(getThreadName() + ": RM GLContext GL ExtensionAvailabilityCache mapping key("+contextFQN+") -> "+toHexString(hc)); } } } diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLContext.java b/src/jogl/classes/jogamp/opengl/egl/EGLContext.java index deb3813b1..bd8e7dee9 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLContext.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLContext.java @@ -214,7 +214,7 @@ public abstract class EGLContext extends GLContextImpl { throw new GLException("Error making context " + toHexString(contextHandle) + " current: error code " + toHexString(EGL.eglGetError())); } - setGLFunctionAvailability(true, glProfile.usesNativeGLES2() ? 2 : 1, 0, CTX_PROFILE_ES); + setGLFunctionAvailability(true, glProfile.usesNativeGLES2() ? 2 : 1, 0, CTX_PROFILE_ES, false); return true; } diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLExternalContext.java b/src/jogl/classes/jogamp/opengl/egl/EGLExternalContext.java index 84bd705db..da8fb519d 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLExternalContext.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLExternalContext.java @@ -45,7 +45,7 @@ public class EGLExternalContext extends EGLContext { public EGLExternalContext(AbstractGraphicsScreen screen) { super(null, null); GLContextShareSet.contextCreated(this); - setGLFunctionAvailability(false, 0, 0, CTX_PROFILE_ES); + setGLFunctionAvailability(false, 0, 0, CTX_PROFILE_ES, false); getGLStateTracker().setEnabled(false); // external context usage can't track state in Java } diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java index 65ed5fc15..f121a2547 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java @@ -64,7 +64,7 @@ public class MacOSXExternalCGLContext extends MacOSXCGLContext { setOpenGLMode(isNSContext ? GLBackendType.NSOPENGL : GLBackendType.CGL ); this.contextHandle = handle; GLContextShareSet.contextCreated(this); - setGLFunctionAvailability(false, 0, 0, CTX_PROFILE_COMPAT); + setGLFunctionAvailability(false, 0, 0, CTX_PROFILE_COMPAT, false); getGLStateTracker().setEnabled(false); // external context usage can't track state in Java } diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/awt/MacOSXJava2DCGLContext.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/awt/MacOSXJava2DCGLContext.java index f41400d83..bd183b900 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/awt/MacOSXJava2DCGLContext.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/awt/MacOSXJava2DCGLContext.java @@ -97,7 +97,7 @@ public class MacOSXJava2DCGLContext extends MacOSXCGLContext implements Java2DGL } return false; } - setGLFunctionAvailability(true, 0, 0, CTX_PROFILE_COMPAT); // use GL_VERSION + setGLFunctionAvailability(true, 0, 0, CTX_PROFILE_COMPAT, false); // use GL_VERSION contextHandle = ctx; return true; } diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLContext.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLContext.java index f6cc2956d..84b29a09f 100644 --- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLContext.java +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLContext.java @@ -65,7 +65,7 @@ public class WindowsExternalWGLContext extends WindowsWGLContext { System.err.println(getThreadName() + ": Created external OpenGL context " + toHexString(ctx) + " for " + this); } GLContextShareSet.contextCreated(this); - setGLFunctionAvailability(false, 0, 0, CTX_PROFILE_COMPAT); // use GL_VERSION + setGLFunctionAvailability(false, 0, 0, CTX_PROFILE_COMPAT, false); // use GL_VERSION getGLStateTracker().setEnabled(false); // external context usage can't track state in Java } diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java index 92d75e3fd..a654cdd04 100644 --- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java @@ -308,7 +308,7 @@ public class WindowsWGLContext extends GLContextImpl { if (!WGL.wglMakeCurrent(drawable.getHandle(), temp_ctx)) { throw new GLException("Error making temp context current: 0x" + toHexString(temp_ctx) + ", werr: "+GDI.GetLastError()); } - setGLFunctionAvailability(true, 0, 0, CTX_PROFILE_COMPAT); // use GL_VERSION + setGLFunctionAvailability(true, 0, 0, CTX_PROFILE_COMPAT, false); // use GL_VERSION WGL.wglMakeCurrent(0, 0); // release temp context if( !createContextARBTried) { diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXContext.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXContext.java index bebb4e68a..12fa5786a 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXContext.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXContext.java @@ -64,7 +64,7 @@ public class X11ExternalGLXContext extends X11GLXContext { super(drawable, null); this.contextHandle = ctx; GLContextShareSet.contextCreated(this); - setGLFunctionAvailability(false, 0, 0, CTX_PROFILE_COMPAT); + setGLFunctionAvailability(false, 0, 0, CTX_PROFILE_COMPAT, false); getGLStateTracker().setEnabled(false); // external context usage can't track state in Java } diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java index bf1045132..5b0d32353 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java @@ -308,7 +308,7 @@ public abstract class X11GLXContext extends GLContextImpl { if (!glXMakeContextCurrent(display, drawable.getHandle(), drawableRead.getHandle(), contextHandle)) { throw new GLException(getThreadName()+": Error making temp context(0) current: display "+toHexString(display)+", context "+toHexString(contextHandle)+", drawable "+drawable); } - setGLFunctionAvailability(true, 0, 0, CTX_PROFILE_COMPAT); // use GL_VERSION + setGLFunctionAvailability(true, 0, 0, CTX_PROFILE_COMPAT, false); // use GL_VERSION isDirect = GLX.glXIsDirect(display, contextHandle); if (DEBUG) { System.err.println(getThreadName() + ": createContextImpl: OK (old-1) share "+share+", direct "+isDirect+"/"+direct); @@ -338,7 +338,7 @@ public abstract class X11GLXContext extends GLContextImpl { if (!glXMakeContextCurrent(display, drawable.getHandle(), drawableRead.getHandle(), temp_ctx)) { throw new GLException(getThreadName()+": Error making temp context(1) current: display "+toHexString(display)+", context "+toHexString(temp_ctx)+", drawable "+drawable); } - setGLFunctionAvailability(true, 0, 0, CTX_PROFILE_COMPAT); // use GL_VERSION + setGLFunctionAvailability(true, 0, 0, CTX_PROFILE_COMPAT, false); // use GL_VERSION glXMakeContextCurrent(display, 0, 0, 0); // release temp context if( !createContextARBTried ) { // is*Available calls are valid since setGLFunctionAvailability(..) was called -- cgit v1.2.3 From 6b924839b33dbf507dd9eebc0ad5b5fbf23f4fb2 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Wed, 13 Mar 2013 01:29:50 +0100 Subject: *External*Context Impl: Remove unused 'lastContext' field, incl. their makeCurrent() and release() override. Semantics of 'lastContext' are plain wrong, since release() override does claim the previous 'lastContext' is current at the end - however, it wasn't technically made current. --- .../jogamp/opengl/egl/EGLExternalContext.java | 25 +--------------------- .../macosx/cgl/MacOSXExternalCGLContext.java | 20 ----------------- .../windows/wgl/WindowsExternalWGLContext.java | 22 +------------------ .../opengl/x11/glx/X11ExternalGLXContext.java | 20 ----------------- 4 files changed, 2 insertions(+), 85 deletions(-) (limited to 'src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java') diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLExternalContext.java b/src/jogl/classes/jogamp/opengl/egl/EGLExternalContext.java index da8fb519d..4685e8bf1 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLExternalContext.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLExternalContext.java @@ -36,11 +36,11 @@ package jogamp.opengl.egl; import javax.media.opengl.*; + import jogamp.opengl.*; import javax.media.nativewindow.*; public class EGLExternalContext extends EGLContext { - private GLContext lastContext; public EGLExternalContext(AbstractGraphicsScreen screen) { super(null, null); @@ -49,29 +49,6 @@ public class EGLExternalContext extends EGLContext { getGLStateTracker().setEnabled(false); // external context usage can't track state in Java } - @Override - public int makeCurrent() throws GLException { - // Save last context if necessary to allow external GLContexts to - // talk to other GLContexts created by this library - GLContext cur = getCurrent(); - if (cur != null && cur != this) { - lastContext = cur; - setCurrent(null); - } - return super.makeCurrent(); - } - - @Override - public void release() throws GLException { - super.release(); - setCurrent(lastContext); - lastContext = null; - } - - @Override - protected void makeCurrentImpl() throws GLException { - } - @Override protected void releaseImpl() throws GLException { } diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java index f121a2547..d23d8a7e1 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java @@ -57,7 +57,6 @@ import jogamp.opengl.macosx.cgl.MacOSXCGLDrawable.GLBackendType; public class MacOSXExternalCGLContext extends MacOSXCGLContext { - private GLContext lastContext; private MacOSXExternalCGLContext(Drawable drawable, boolean isNSContext, long handle) { super(drawable, null); @@ -122,25 +121,6 @@ public class MacOSXExternalCGLContext extends MacOSXCGLContext { return true; } - @Override - public int makeCurrent() throws GLException { - // Save last context if necessary to allow external GLContexts to - // talk to other GLContexts created by this library - GLContext cur = getCurrent(); - if (cur != null && cur != this) { - lastContext = cur; - setCurrent(null); - } - return super.makeCurrent(); - } - - @Override - public void release() throws GLException { - super.release(); - setCurrent(lastContext); - lastContext = null; - } - @Override protected void makeCurrentImpl() throws GLException { } diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLContext.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLContext.java index 84b29a09f..a5893775a 100644 --- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLContext.java +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLContext.java @@ -56,8 +56,7 @@ import jogamp.nativewindow.windows.GDI; import jogamp.opengl.GLContextShareSet; public class WindowsExternalWGLContext extends WindowsWGLContext { - private GLContext lastContext; - + private WindowsExternalWGLContext(Drawable drawable, long ctx, WindowsWGLGraphicsConfiguration cfg) { super(drawable, null); this.contextHandle = ctx; @@ -105,25 +104,6 @@ public class WindowsExternalWGLContext extends WindowsWGLContext { return new WindowsExternalWGLContext(new Drawable(factory, new WrappedSurface(cfg, hdc, 64, 64, true)), ctx, cfg); } - @Override - public int makeCurrent() throws GLException { - // Save last context if necessary to allow external GLContexts to - // talk to other GLContexts created by this library - GLContext cur = getCurrent(); - if (cur != null && cur != this) { - lastContext = cur; - setCurrent(null); - } - return super.makeCurrent(); - } - - @Override - public void release() throws GLException { - super.release(); - setCurrent(lastContext); - lastContext = null; - } - @Override protected void makeCurrentImpl() throws GLException { } diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXContext.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXContext.java index 12fa5786a..72e84b05e 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXContext.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXContext.java @@ -58,7 +58,6 @@ import com.jogamp.common.nio.Buffers; import com.jogamp.nativewindow.x11.X11GraphicsScreen; public class X11ExternalGLXContext extends X11GLXContext { - private GLContext lastContext; private X11ExternalGLXContext(Drawable drawable, long ctx) { super(drawable, null); @@ -117,25 +116,6 @@ public class X11ExternalGLXContext extends X11GLXContext { return true; } - @Override - public int makeCurrent() throws GLException { - // Save last context if necessary to allow external GLContexts to - // talk to other GLContexts created by this library - GLContext cur = getCurrent(); - if (cur != null && cur != this) { - lastContext = cur; - setCurrent(null); - } - return super.makeCurrent(); - } - - @Override - public void release() throws GLException { - super.release(); - setCurrent(lastContext); - lastContext = null; - } - @Override protected void makeCurrentImpl() throws GLException { } -- cgit v1.2.3 From dc2deb071ca192594426791e95804a208e030ce3 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Fri, 25 Oct 2013 00:01:12 +0200 Subject: Bug 867 OSX [Common Code]: Trigger GLRendererQuirks.GL4NeedsGL3Request and make it sticky; Only alias profiles if HW-Accelerated! Only alias profiles if HW-Accelerated! GLContextImpl.mapGLVersions(..) shall not map a higher profile to a lower if it is a software renderer. +++ GLContextImpl.mapGLVersions(..) attempts to trigger GLRendererQuirks.GL4NeedsGL3Request if OSX 10.9 by creating a GL3 core context first. +++ GLContextImpl.setGLFunctionAvailability(): - On OSX 10.9: Detect GLRendererQuirks.GL4NeedsGL3Request and make it sticky (per device) while 'withinGLVersionsMapping' - Merge sticky quirks w/ local quirks +++ TestGearsES2NEWT: Add cmdline '-gl2' to force GL2 profile. --- make/scripts/tests.sh | 2 +- src/jogl/classes/jogamp/opengl/GLContextImpl.java | 146 ++++++++++++++------- src/jogl/classes/jogamp/opengl/egl/EGLContext.java | 4 +- .../jogamp/opengl/egl/EGLExternalContext.java | 2 +- .../macosx/cgl/MacOSXExternalCGLContext.java | 2 +- .../windows/wgl/WindowsExternalWGLContext.java | 2 +- .../opengl/windows/wgl/WindowsWGLContext.java | 2 +- .../opengl/x11/glx/X11ExternalGLXContext.java | 2 +- .../jogamp/opengl/x11/glx/X11GLXContext.java | 4 +- .../jogl/demos/es2/newt/TestGearsES2NEWT.java | 68 +++++----- 10 files changed, 149 insertions(+), 85 deletions(-) (limited to 'src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java') diff --git a/make/scripts/tests.sh b/make/scripts/tests.sh index fd79b028e..a1cb4d8e5 100644 --- a/make/scripts/tests.sh +++ b/make/scripts/tests.sh @@ -206,7 +206,7 @@ function jrun() { #D_ARGS="-Dnativewindow.debug.ToolkitLock" #D_ARGS="-Djogl.debug.graph.curve -Djogl.debug.GLSLCode -Djogl.debug.TraceGL" #D_ARGS="-Djogl.debug.graph.curve -Djogl.debug.GLSLState" - #D_ARGS="-Djogamp.debug.JNILibLoader -Djogamp.debug.TempJarCache -Djogamp.debug.JarUtil" + #D_ARGS="-Djogamp.debug.JNILibLoader -Djogamp.debug.TempJarCache -Djogamp.debug.JarUtil -Djogamp.debug.IOUtil" #D_ARGS="-Djogamp.debug.JNILibLoader -Djogamp.debug.TempFileCache -Djogamp.debug.TempJarCache -Djogamp.debug.JarUtil" #D_ARGS="-Djogamp.debug.JNILibLoader -Djogamp.debug.TempFileCache -Djogamp.debug.TempJarCache -Djogamp.debug.JarUtil -Djogamp.gluegen.UseTempJarCache=false" #D_ARGS="-Dnewt.test.EDTMainThread -Dnewt.debug.MainThread" diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java index 911a4c2be..241d5a217 100644 --- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java +++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java @@ -828,6 +828,9 @@ public abstract class GLContextImpl extends GLContext { final int[] reqMajorCTP = new int[] { 0, 0 }; getRequestMajorAndCompat(glCaps.getGLProfile(), reqMajorCTP); + if(DEBUG) { + System.err.println(getThreadName() + ": createContextARB: Requested "+GLContext.getGLVersion(reqMajorCTP[0], 0, reqMajorCTP[0], null)); + } int _major[] = { 0 }; int _minor[] = { 0 }; int _ctp[] = { 0 }; @@ -835,9 +838,12 @@ public abstract class GLContextImpl extends GLContext { if( GLContext.getAvailableGLVersion(device, reqMajorCTP[0], reqMajorCTP[1], _major, _minor, _ctp)) { _ctp[0] |= additionalCtxCreationFlags; + if(DEBUG) { + System.err.println(getThreadName() + ": createContextARB: Mapped "+GLContext.getGLVersion(_major[0], _minor[0], _ctp[0], null)); + } _ctx = createContextARBImpl(share, direct, _ctp[0], _major[0], _minor[0]); if(0!=_ctx) { - setGLFunctionAvailability(true, _major[0], _minor[0], _ctp[0], false); + setGLFunctionAvailability(true, _major[0], _minor[0], _ctp[0], false /* strictMatch */, false /* withinGLVersionsMapping */); } } return _ctx; @@ -857,67 +863,95 @@ public abstract class GLContextImpl extends GLContext { // Even w/ PROFILE_ALIASING, try to use true core GL profiles // ensuring proper user behavior across platforms due to different feature sets! // - if(!hasGL4) { + if( Platform.OSType.MACOS == Platform.getOSType() && + Platform.getOSVersionNumber().compareTo(Platform.OSXVersion.Mavericks) >= 0 ) { + /** + * OSX 10.9 GLRendererQuirks.GL4NeedsGL3Request, quirk is added as usual @ setRendererQuirks(..) + */ + if( !hasGL4 && !hasGL3 ) { + hasGL3 = createContextARBMapVersionsAvailable(3, CTX_PROFILE_CORE); // GL3 + success |= hasGL3; + if( hasGL3 ) { + final boolean isHWAccel = 0 == ( CTX_IMPL_ACCEL_SOFT & ctxOptions ); + if( isHWAccel && ctxVersion.getMajor() >= 4 ) { + // Gotcha: Creating a '3.2' ctx delivers a >= 4 ctx. + GLContext.mapAvailableGLVersion(device, 4, CTX_PROFILE_CORE, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions); + hasGL4 = true; + if(DEBUG) { + System.err.println("Quirk Triggerd: "+GLRendererQuirks.toString(GLRendererQuirks.GL4NeedsGL3Request)+": cause: OS "+Platform.getOSType()+", OS Version "+Platform.getOSVersionNumber()); + } + } + resetStates(false); // clean this context states, since creation was temporary + } + } + } + if( !hasGL4 ) { hasGL4 = createContextARBMapVersionsAvailable(4, CTX_PROFILE_CORE); // GL4 success |= hasGL4; - if(hasGL4) { - // Map all lower compatible profiles: GL3 - GLContext.mapAvailableGLVersion(device, 3, CTX_PROFILE_CORE, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions); - if(PROFILE_ALIASING) { - hasGL3 = true; + if( hasGL4 ) { + if( 0 == ( CTX_IMPL_ACCEL_SOFT & ctxOptions ) ) { + // Map hw-accel GL4 to all lower core profiles: GL3 + GLContext.mapAvailableGLVersion(device, 3, CTX_PROFILE_CORE, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions); + if( PROFILE_ALIASING ) { + hasGL3 = true; + } } resetStates(false); // clean context states, since creation was temporary } } - if(!hasGL3) { + if( !hasGL3 ) { hasGL3 = createContextARBMapVersionsAvailable(3, CTX_PROFILE_CORE); // GL3 success |= hasGL3; - if(hasGL3) { + if( hasGL3 ) { resetStates(false); // clean this context states, since creation was temporary } } - if(!hasGL4bc) { + if( !hasGL4bc ) { hasGL4bc = createContextARBMapVersionsAvailable(4, CTX_PROFILE_COMPAT); // GL4bc success |= hasGL4bc; - if(hasGL4bc) { - // Map all lower compatible profiles: GL3bc, GL2, GL4, GL3 - GLContext.mapAvailableGLVersion(device, 3, CTX_PROFILE_COMPAT, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions); - GLContext.mapAvailableGLVersion(device, 2, CTX_PROFILE_COMPAT, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions); - if(!hasGL4) { + if( hasGL4bc ) { + if( !hasGL4 ) { // last chance .. ignore hw-accel GLContext.mapAvailableGLVersion(device, 4, CTX_PROFILE_CORE, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions); + hasGL4 = true; } - if(!hasGL3) { + if( !hasGL3 ) { // last chance .. ignore hw-accel GLContext.mapAvailableGLVersion(device, 3, CTX_PROFILE_CORE, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions); - } - if(PROFILE_ALIASING) { - hasGL3bc = true; - hasGL2 = true; - hasGL4 = true; hasGL3 = true; } + if( 0 == ( CTX_IMPL_ACCEL_SOFT & ctxOptions ) ) { + // Map hw-accel GL4bc to all lower compatible profiles: GL3bc, GL2 + GLContext.mapAvailableGLVersion(device, 3, CTX_PROFILE_COMPAT, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions); + GLContext.mapAvailableGLVersion(device, 2, CTX_PROFILE_COMPAT, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions); + if(PROFILE_ALIASING) { + hasGL3bc = true; + hasGL2 = true; + } + } resetStates(false); // clean this context states, since creation was temporary } } - if(!hasGL3bc) { + if( !hasGL3bc ) { hasGL3bc = createContextARBMapVersionsAvailable(3, CTX_PROFILE_COMPAT); // GL3bc success |= hasGL3bc; - if(hasGL3bc) { - // Map all lower compatible profiles: GL2 and GL3 - GLContext.mapAvailableGLVersion(device, 2, CTX_PROFILE_COMPAT, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions); - if(!hasGL3) { + if( hasGL3bc ) { + if(!hasGL3) { // last chance .. ignore hw-accel GLContext.mapAvailableGLVersion(device, 3, CTX_PROFILE_CORE, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions); - } - if(PROFILE_ALIASING) { - hasGL2 = true; hasGL3 = true; } + if( 0 == ( CTX_IMPL_ACCEL_SOFT & ctxOptions ) ) { + // Map hw-accel GL3bc to all lower compatible profiles: GL2 + GLContext.mapAvailableGLVersion(device, 2, CTX_PROFILE_COMPAT, ctxVersion.getMajor(), ctxVersion.getMinor(), ctxOptions); + if(PROFILE_ALIASING) { + hasGL2 = true; + } + } resetStates(false); // clean this context states, since creation was temporary } } - if(!hasGL2) { + if( !hasGL2 ) { hasGL2 = createContextARBMapVersionsAvailable(2, CTX_PROFILE_COMPAT); // GL2 success |= hasGL2; - if(hasGL2) { + if( hasGL2 ) { resetStates(false); // clean this context states, since creation was temporary } } @@ -1022,7 +1056,7 @@ public abstract class GLContextImpl extends GLContext { _context = createContextARBImpl(share, direct, ctxOptionFlags, major[0], minor[0]); if(0 != _context) { - if( setGLFunctionAvailability(true, major[0], minor[0], ctxOptionFlags, true) ) { + if( setGLFunctionAvailability(true, major[0], minor[0], ctxOptionFlags, true /* strictMatch */, true /* withinGLVersionsMapping */) ) { break; } else { destroyContextARBImpl(_context); @@ -1291,14 +1325,15 @@ public abstract class GLContextImpl extends GLContext { * * @param force force the setting, even if is already being set. * This might be useful if you change the OpenGL implementation. - * @param major OpenGL major version - * @param minor OpenGL minor version - * @param ctxProfileBits OpenGL context profile and option bits, see {@link javax.media.opengl.GLContext#CTX_OPTION_ANY} - * @param strictMatch if true the ctx must + * @param major OpenGL major version + * @param minor OpenGL minor version + * @param ctxProfileBits OpenGL context profile and option bits, see {@link javax.media.opengl.GLContext#CTX_OPTION_ANY} + * @param strictMatch if true the ctx must *
        *
      • be greater or equal than the requested major.minor version, and
      • *
      • match the ctxProfileBits
      • *
      , otherwise method aborts and returns false. + * @param withinGLVersionsMapping TODO * @return returns true if successful, otherwise false. See strictMatch. * If false is returned, no data has been cached or mapped, i.e. ProcAddressTable, Extensions, Version, etc. * @see #setContextVersion @@ -1306,7 +1341,8 @@ public abstract class GLContextImpl extends GLContext { * @see javax.media.opengl.GLContext#CTX_PROFILE_COMPAT * @see javax.media.opengl.GLContext#CTX_IMPL_ES2_COMPAT */ - protected final boolean setGLFunctionAvailability(boolean force, int major, int minor, int ctxProfileBits, boolean strictMatch) { + protected final boolean setGLFunctionAvailability(boolean force, int major, int minor, int ctxProfileBits, + boolean strictMatch, boolean withinGLVersionsMapping) { if(null!=this.gl && null!=glProcAddressTable && !force) { return true; // already done and not forced } @@ -1322,7 +1358,7 @@ public abstract class GLContextImpl extends GLContext { final AbstractGraphicsConfiguration aconfig = drawable.getNativeSurface().getGraphicsConfiguration(); final AbstractGraphicsDevice adevice = aconfig.getScreen().getDevice(); - + final int reqMajor = major, reqMinor = minor, reqCtxProfileBits = ctxProfileBits; { final boolean initGLRendererAndGLVersionStringsOK = initGLRendererAndGLVersionStrings(); if( !initGLRendererAndGLVersionStringsOK ) { @@ -1424,7 +1460,10 @@ public abstract class GLContextImpl extends GLContext { return false; } if (DEBUG) { - System.err.println(getThreadName() + ": GLContext.setGLFuncAvail: Post version verification "+GLContext.getGLVersion(major, minor, ctxProfileBits, null)+", strictMatch "+strictMatch+", versionValidated "+versionValidated+", versionGL3IntFailed "+versionGL3IntFailed); + System.err.println(getThreadName() + ": GLContext.setGLFuncAvail: Post version verification req "+ + GLContext.getGLVersion(reqMajor, reqMinor, reqCtxProfileBits, null)+" -> has "+ + GLContext.getGLVersion(major, minor, ctxProfileBits, null)+ + ", strictMatch "+strictMatch+", versionValidated "+versionValidated+", versionGL3IntFailed "+versionGL3IntFailed); } if( major < 2 ) { // there is no ES2/3-compat for a profile w/ major < 2 @@ -1433,7 +1472,7 @@ public abstract class GLContextImpl extends GLContext { final VersionNumberString vendorVersion = GLVersionNumber.createVendorVersion(glVersion); - setRendererQuirks(adevice, major, minor, ctxProfileBits, vendorVersion); + setRendererQuirks(adevice, reqMajor, reqMinor, reqCtxProfileBits, major, minor, ctxProfileBits, vendorVersion, withinGLVersionsMapping); if( strictMatch && glRendererQuirks.exist(GLRendererQuirks.GLNonCompliant) ) { if(DEBUG) { @@ -1550,7 +1589,10 @@ public abstract class GLContextImpl extends GLContext { return true; } - private final void setRendererQuirks(final AbstractGraphicsDevice adevice, int major, int minor, int ctp, final VersionNumberString vendorVersion) { + private final void setRendererQuirks(final AbstractGraphicsDevice adevice, + int reqMajor, int reqMinor, int reqCTP, + int major, int minor, int ctp, final VersionNumberString vendorVersion, + boolean withinGLVersionsMapping) { int[] quirks = new int[GLRendererQuirks.COUNT + 1]; // + 1 ( NoFullFBOSupport ) int i = 0; @@ -1577,7 +1619,17 @@ public abstract class GLContextImpl extends GLContext { } quirks[i++] = quirk; } - + if( Platform.getOSVersionNumber().compareTo(Platform.OSXVersion.Mavericks) >= 0 && 3==reqMajor && 4==major ) { + final int quirk = GLRendererQuirks.GL4NeedsGL3Request; + if(DEBUG) { + System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: OS "+Platform.getOSType()+", OS Version "+Platform.getOSVersionNumber()+", req "+reqMajor+"."+reqMinor); + } + quirks[i++] = quirk; + if( withinGLVersionsMapping ) { + // Thread safe due to single threaded initialization! + GLRendererQuirks.addStickyDeviceQuirks(adevice, quirks, i-1, 1); + } + } if( isDriverNVIDIAGeForce ) { final VersionNumber osxVersionNVFlushClean = new VersionNumber(10,7,3); // < OSX 10.7.3 w/ NV needs glFlush if( Platform.getOSVersionNumber().compareTo(osxVersionNVFlushClean) < 0 ) { @@ -1587,8 +1639,7 @@ public abstract class GLContextImpl extends GLContext { } quirks[i++] = quirk; } - final VersionNumber osxVersionNVGLSLGood = new VersionNumber(10,7,0); // < OSX 10.7.0 w/ NV has instable GLSL - if( Platform.getOSVersionNumber().compareTo(osxVersionNVGLSLGood) < 0 ) { + if( Platform.getOSVersionNumber().compareTo(Platform.OSXVersion.Lion) < 0 ) { // < OSX 10.7.0 w/ NV has unstable GLSL final int quirk = GLRendererQuirks.GLSLNonCompliant; if(DEBUG) { System.err.println("Quirk: "+GLRendererQuirks.toString(quirk)+": cause: OS "+Platform.getOSType()+", OS Version "+Platform.getOSVersionNumber()+", Renderer "+glRenderer); @@ -1732,6 +1783,11 @@ public abstract class GLContextImpl extends GLContext { } glRendererQuirks = new GLRendererQuirks(quirks, 0, i); + GLRendererQuirks.pushStickyDeviceQuirks(adevice, glRendererQuirks); // Thread safe due to single threaded initialization! + if(DEBUG) { + System.err.println("Quirks local: "+glRendererQuirks); + System.err.println("Quirks sticky on "+adevice+": "+GLRendererQuirks.getStickyDeviceQuirks(adevice)); + } } private static final boolean hasFBOImpl(int major, int ctp, ExtensionAvailabilityCache extCache) { @@ -1785,7 +1841,7 @@ public abstract class GLContextImpl extends GLContext { if(!drawable.getChosenGLCapabilities().getHardwareAccelerated()) { isHardwareRasterizer = false; } else { - isHardwareRasterizer = ! ( glRendererLowerCase.contains("software") /* Mesa3D */ || + isHardwareRasterizer = ! ( glRendererLowerCase.contains("software") /* Mesa3D, Apple */ || glRendererLowerCase.contains("mesa x11") /* Mesa3D */ || glRendererLowerCase.contains("softpipe") /* Gallium */ || glRendererLowerCase.contains("llvmpipe") /* Gallium */ diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLContext.java b/src/jogl/classes/jogamp/opengl/egl/EGLContext.java index 3de910369..d8bb2e9eb 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLContext.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLContext.java @@ -222,7 +222,9 @@ public class EGLContext extends GLContextImpl { throw new GLException("Error making context " + toHexString(contextHandle) + " current: error code " + toHexString(EGL.eglGetError())); } - return setGLFunctionAvailability(true, contextVersionReq, 0, CTX_PROFILE_ES, contextVersionReq>=3); // strict match for es >= 3 + return setGLFunctionAvailability(true, contextVersionReq, 0, CTX_PROFILE_ES, + contextVersionReq>=3 /* strictMatch */, // strict match for es >= 3 + false /* withinGLVersionsMapping */); } @Override diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLExternalContext.java b/src/jogl/classes/jogamp/opengl/egl/EGLExternalContext.java index 4685e8bf1..d54a80ae3 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLExternalContext.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLExternalContext.java @@ -45,7 +45,7 @@ public class EGLExternalContext extends EGLContext { public EGLExternalContext(AbstractGraphicsScreen screen) { super(null, null); GLContextShareSet.contextCreated(this); - setGLFunctionAvailability(false, 0, 0, CTX_PROFILE_ES, false); + setGLFunctionAvailability(false, 0, 0, CTX_PROFILE_ES, false /* strictMatch */, false /* withinGLVersionsMapping */); // use GL_VERSION getGLStateTracker().setEnabled(false); // external context usage can't track state in Java } diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java index d23d8a7e1..a2cf334ce 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java @@ -63,7 +63,7 @@ public class MacOSXExternalCGLContext extends MacOSXCGLContext { setOpenGLMode(isNSContext ? GLBackendType.NSOPENGL : GLBackendType.CGL ); this.contextHandle = handle; GLContextShareSet.contextCreated(this); - setGLFunctionAvailability(false, 0, 0, CTX_PROFILE_COMPAT, false); + setGLFunctionAvailability(false, 0, 0, CTX_PROFILE_COMPAT, false /* strictMatch */, false /* withinGLVersionsMapping */); // use GL_VERSION getGLStateTracker().setEnabled(false); // external context usage can't track state in Java } diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLContext.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLContext.java index 966a8b28a..95d7d8b82 100644 --- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLContext.java +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLContext.java @@ -64,7 +64,7 @@ public class WindowsExternalWGLContext extends WindowsWGLContext { System.err.println(getThreadName() + ": Created external OpenGL context " + toHexString(ctx) + " for " + this); } GLContextShareSet.contextCreated(this); - setGLFunctionAvailability(false, 0, 0, CTX_PROFILE_COMPAT, false); // use GL_VERSION + setGLFunctionAvailability(false, 0, 0, CTX_PROFILE_COMPAT, false /* strictMatch */, false /* withinGLVersionsMapping */); // use GL_VERSION getGLStateTracker().setEnabled(false); // external context usage can't track state in Java } diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java index d936308af..82be3e2b9 100644 --- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java @@ -325,7 +325,7 @@ public class WindowsWGLContext extends GLContextImpl { if ( !WGL.wglMakeCurrent(drawable.getHandle(), temp_ctx) ) { throw new GLException("Error making temp context current: 0x" + toHexString(temp_ctx) + ", werr: "+GDI.GetLastError()); } - setGLFunctionAvailability(true, 0, 0, CTX_PROFILE_COMPAT, false); // use GL_VERSION + setGLFunctionAvailability(true, 0, 0, CTX_PROFILE_COMPAT, false /* strictMatch */, false /* withinGLVersionsMapping */); // use GL_VERSION WGL.wglMakeCurrent(0, 0); // release temp context if( !createContextARBTried ) { diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXContext.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXContext.java index ba88ff3c4..a04d1989d 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXContext.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXContext.java @@ -63,7 +63,7 @@ public class X11ExternalGLXContext extends X11GLXContext { super(drawable, null); this.contextHandle = ctx; GLContextShareSet.contextCreated(this); - setGLFunctionAvailability(false, 0, 0, CTX_PROFILE_COMPAT, false); + setGLFunctionAvailability(false, 0, 0, CTX_PROFILE_COMPAT, false /* strictMatch */, false /* withinGLVersionsMapping */); // use GL_VERSION getGLStateTracker().setEnabled(false); // external context usage can't track state in Java } diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java index 22a48e093..42bb6b964 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java @@ -320,7 +320,7 @@ public class X11GLXContext extends GLContextImpl { if ( !glXMakeContextCurrent(display, drawable.getHandle(), drawableRead.getHandle(), contextHandle) ) { throw new GLException(getThreadName()+": Error making temp context(0) current: display "+toHexString(display)+", context "+toHexString(contextHandle)+", drawable "+drawable); } - setGLFunctionAvailability(true, 0, 0, CTX_PROFILE_COMPAT, false); // use GL_VERSION + setGLFunctionAvailability(true, 0, 0, CTX_PROFILE_COMPAT, false /* strictMatch */, false /* withinGLVersionsMapping */); // use GL_VERSION isDirect = GLX.glXIsDirect(display, contextHandle); if (DEBUG) { System.err.println(getThreadName() + ": createContextImpl: OK (old-1) share "+share+", direct "+isDirect+"/"+direct); @@ -350,7 +350,7 @@ public class X11GLXContext extends GLContextImpl { if ( !glXMakeContextCurrent(display, drawable.getHandle(), drawableRead.getHandle(), temp_ctx) ) { throw new GLException(getThreadName()+": Error making temp context(1) current: display "+toHexString(display)+", context "+toHexString(temp_ctx)+", drawable "+drawable); } - setGLFunctionAvailability(true, 0, 0, CTX_PROFILE_COMPAT, false); // use GL_VERSION + setGLFunctionAvailability(true, 0, 0, CTX_PROFILE_COMPAT, false /* strictMatch */, false /* withinGLVersionsMapping */); // use GL_VERSION glXMakeContextCurrent(display, 0, 0, 0); // release temp context if( !createContextARBTried ) { // is*Available calls are valid since setGLFunctionAvailability(..) was called 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 74be176da..b54a2cd19 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 @@ -3,14 +3,14 @@ * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: - * + * * 1. Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. - * + * * 2. Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR @@ -20,12 +20,12 @@ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * + * * The views and conclusions contained in the software and documentation are those of the * authors and should not be interpreted as representing official policies, either expressed * or implied, of JogAmp Community. */ - + package com.jogamp.opengl.test.junit.jogl.demos.es2.newt; import java.io.IOException; @@ -70,7 +70,7 @@ import org.junit.FixMethodOrder; import org.junit.runners.MethodSorters; @FixMethodOrder(MethodSorters.NAME_ASCENDING) -public class TestGearsES2NEWT extends UITestCase { +public class TestGearsES2NEWT extends UITestCase { static int screenIdx = 0; static PointImmutable wpos; static DimensionImmutable wsize, rwsize=null; @@ -92,12 +92,13 @@ public class TestGearsES2NEWT extends UITestCase { static boolean forceES2 = false; static boolean forceES3 = false; static boolean forceGL3 = false; + static boolean forceGL2 = false; static boolean mainRun = false; static boolean exclusiveContext = false; static boolean useAnimator = true; static enum SysExit { none, testExit, testError, displayExit, displayError }; static SysExit sysExit = SysExit.none; - + @BeforeClass public static void initClass() { if(null == wsize) { @@ -129,7 +130,7 @@ public class TestGearsES2NEWT extends UITestCase { final GearsES2 demo = new GearsES2(swapInterval); demo.setPMVUseBackingArray(pmvUseBackingArray); glWindow.addGLEventListener(demo); - + final SnapshotGLEventListener snap = new SnapshotGLEventListener(); glWindow.addGLEventListener(snap); if(waitForKey) { @@ -154,7 +155,7 @@ public class TestGearsES2NEWT extends UITestCase { animator.setModeBits(false, Animator.MODE_EXPECT_AWT_RENDERING_THREAD); animator.setExclusiveContext(exclusiveContext); } - + QuitAdapter quitAdapter = new QuitAdapter(); //glWindow.addKeyListener(new TraceKeyAdapter(quitAdapter)); //glWindow.addWindowListener(new TraceWindowAdapter(quitAdapter)); @@ -167,9 +168,9 @@ public class TestGearsES2NEWT extends UITestCase { } public void windowMoved(WindowEvent e) { System.err.println("window moved: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()); - } + } }); - + glWindow.addKeyListener(new KeyAdapter() { @Override public void keyPressed(final KeyEvent e) { @@ -299,7 +300,7 @@ public class TestGearsES2NEWT extends UITestCase { throw new Error("test error send from GLEventListener"); } else if ( SysExit.displayExit == sysExit ) { System.err.println("exit(0) send from GLEventListener"); - System.exit(0); + System.exit(0); } } } else { @@ -307,29 +308,29 @@ public class TestGearsES2NEWT extends UITestCase { } } @Override - public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { } + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { } }); } - + glWindow.setVisible(true); if( useAnimator ) { animator.setUpdateFPSFrames(60, showFPS ? System.err : null); } - + 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()); - + snap.setMakeSnapshot(); if( null != rwsize ) { - Thread.sleep(500); // 500ms delay + Thread.sleep(500); // 500ms delay glWindow.setSize(rwsize.getWidth(), rwsize.getHeight()); System.err.println("window resize pos/siz: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getWidth()+"x"+glWindow.getHeight()+", "+glWindow.getInsets()); } - + snap.setMakeSnapshot(); - + final long t0 = System.currentTimeMillis(); long t1 = t0; while(!quitAdapter.shouldQuit() && t1-t0 Date: Wed, 30 Oct 2013 11:50:24 +0100 Subject: Bug 875: Safeguard setGLFunctionAvailability(.. strictMatch=false.. ) operation, throw InternalError if failing --- src/jogl/classes/jogamp/opengl/egl/EGLExternalContext.java | 5 ++++- .../classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java | 5 +++-- .../classes/jogamp/opengl/windows/wgl/WindowsExternalWGLContext.java | 5 +++-- src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java | 4 +++- src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXContext.java | 4 +++- src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java | 4 +++- 6 files changed, 19 insertions(+), 8 deletions(-) (limited to 'src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java') diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLExternalContext.java b/src/jogl/classes/jogamp/opengl/egl/EGLExternalContext.java index d54a80ae3..aff18fc81 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLExternalContext.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLExternalContext.java @@ -38,6 +38,7 @@ package jogamp.opengl.egl; import javax.media.opengl.*; import jogamp.opengl.*; + import javax.media.nativewindow.*; public class EGLExternalContext extends EGLContext { @@ -45,7 +46,9 @@ public class EGLExternalContext extends EGLContext { public EGLExternalContext(AbstractGraphicsScreen screen) { super(null, null); GLContextShareSet.contextCreated(this); - setGLFunctionAvailability(false, 0, 0, CTX_PROFILE_ES, false /* strictMatch */, false /* withinGLVersionsMapping */); // use GL_VERSION + if( !setGLFunctionAvailability(false, 0, 0, CTX_PROFILE_ES, false /* strictMatch */, false /* withinGLVersionsMapping */) ) { // use GL_VERSION + throw new InternalError("setGLFunctionAvailability !strictMatch failed"); + } getGLStateTracker().setEnabled(false); // external context usage can't track state in Java } diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java index a2cf334ce..5d036d45a 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java @@ -49,7 +49,6 @@ import javax.media.opengl.GLContext; import javax.media.opengl.GLDrawableFactory; import javax.media.opengl.GLException; - import jogamp.nativewindow.WrappedSurface; import jogamp.opengl.GLContextImpl; import jogamp.opengl.GLContextShareSet; @@ -63,7 +62,9 @@ public class MacOSXExternalCGLContext extends MacOSXCGLContext { setOpenGLMode(isNSContext ? GLBackendType.NSOPENGL : GLBackendType.CGL ); this.contextHandle = handle; GLContextShareSet.contextCreated(this); - setGLFunctionAvailability(false, 0, 0, CTX_PROFILE_COMPAT, false /* strictMatch */, false /* withinGLVersionsMapping */); // use GL_VERSION + if( !setGLFunctionAvailability(false, 0, 0, CTX_PROFILE_COMPAT, false /* strictMatch */, false /* withinGLVersionsMapping */) ) { // use GL_VERSION + throw new InternalError("setGLFunctionAvailability !strictMatch failed"); + } getGLStateTracker().setEnabled(false); // external context usage can't track state in Java } diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLContext.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLContext.java index 95d7d8b82..c46b3c9dd 100644 --- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLContext.java +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLContext.java @@ -50,7 +50,6 @@ import javax.media.opengl.GLDrawableFactory; import javax.media.opengl.GLException; import javax.media.opengl.GLProfile; - import jogamp.nativewindow.WrappedSurface; import jogamp.nativewindow.windows.GDI; import jogamp.opengl.GLContextShareSet; @@ -64,7 +63,9 @@ public class WindowsExternalWGLContext extends WindowsWGLContext { System.err.println(getThreadName() + ": Created external OpenGL context " + toHexString(ctx) + " for " + this); } GLContextShareSet.contextCreated(this); - setGLFunctionAvailability(false, 0, 0, CTX_PROFILE_COMPAT, false /* strictMatch */, false /* withinGLVersionsMapping */); // use GL_VERSION + if( !setGLFunctionAvailability(false, 0, 0, CTX_PROFILE_COMPAT, false /* strictMatch */, false /* withinGLVersionsMapping */) ) { // use GL_VERSION + throw new InternalError("setGLFunctionAvailability !strictMatch failed"); + } getGLStateTracker().setEnabled(false); // external context usage can't track state in Java } diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java index 82be3e2b9..b1e41624d 100644 --- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java @@ -325,7 +325,9 @@ public class WindowsWGLContext extends GLContextImpl { if ( !WGL.wglMakeCurrent(drawable.getHandle(), temp_ctx) ) { throw new GLException("Error making temp context current: 0x" + toHexString(temp_ctx) + ", werr: "+GDI.GetLastError()); } - setGLFunctionAvailability(true, 0, 0, CTX_PROFILE_COMPAT, false /* strictMatch */, false /* withinGLVersionsMapping */); // use GL_VERSION + if( !setGLFunctionAvailability(true, 0, 0, CTX_PROFILE_COMPAT, false /* strictMatch */, false /* withinGLVersionsMapping */) ) { // use GL_VERSION + throw new InternalError("setGLFunctionAvailability !strictMatch failed"); + } WGL.wglMakeCurrent(0, 0); // release temp context if( !createContextARBTried ) { diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXContext.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXContext.java index a04d1989d..9b7b0f5ae 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXContext.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXContext.java @@ -63,7 +63,9 @@ public class X11ExternalGLXContext extends X11GLXContext { super(drawable, null); this.contextHandle = ctx; GLContextShareSet.contextCreated(this); - setGLFunctionAvailability(false, 0, 0, CTX_PROFILE_COMPAT, false /* strictMatch */, false /* withinGLVersionsMapping */); // use GL_VERSION + if( !setGLFunctionAvailability(false, 0, 0, CTX_PROFILE_COMPAT, false /* strictMatch */, false /* withinGLVersionsMapping */) ) { // use GL_VERSION + throw new InternalError("setGLFunctionAvailability !strictMatch failed"); + } getGLStateTracker().setEnabled(false); // external context usage can't track state in Java } diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java index 42bb6b964..10f21f0c3 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java @@ -320,7 +320,9 @@ public class X11GLXContext extends GLContextImpl { if ( !glXMakeContextCurrent(display, drawable.getHandle(), drawableRead.getHandle(), contextHandle) ) { throw new GLException(getThreadName()+": Error making temp context(0) current: display "+toHexString(display)+", context "+toHexString(contextHandle)+", drawable "+drawable); } - setGLFunctionAvailability(true, 0, 0, CTX_PROFILE_COMPAT, false /* strictMatch */, false /* withinGLVersionsMapping */); // use GL_VERSION + if( !setGLFunctionAvailability(true, 0, 0, CTX_PROFILE_COMPAT, false /* strictMatch */, false /* withinGLVersionsMapping */) ) { // use GL_VERSION + throw new InternalError("setGLFunctionAvailability !strictMatch failed"); + } isDirect = GLX.glXIsDirect(display, contextHandle); if (DEBUG) { System.err.println(getThreadName() + ": createContextImpl: OK (old-1) share "+share+", direct "+isDirect+"/"+direct); -- cgit v1.2.3 From 7433e513c1f109f75aa34c224b1f5f14b612cba8 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Sat, 2 Nov 2013 16:26:02 +0100 Subject: GLContextImpl: Move sharedContextHandle check to makeCurrentWithinLock(..) and let it fail there instead of within impl. class, only pass the handle - simplifies and removes redundancy. --- make/scripts/tests.sh | 7 ++-- src/jogl/classes/jogamp/opengl/GLContextImpl.java | 17 +++++---- src/jogl/classes/jogamp/opengl/egl/EGLContext.java | 11 ++---- .../jogamp/opengl/macosx/cgl/MacOSXCGLContext.java | 32 +++++------------ .../opengl/macosx/cgl/MacOSXCGLDrawable.java | 5 ++- .../macosx/cgl/MacOSXExternalCGLContext.java | 3 +- .../opengl/windows/wgl/WindowsWGLContext.java | 40 ++++++++-------------- .../opengl/x11/glx/X11ExternalGLXContext.java | 3 +- .../jogamp/opengl/x11/glx/X11GLXContext.java | 33 +++++++----------- 9 files changed, 58 insertions(+), 93 deletions(-) (limited to 'src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java') diff --git a/make/scripts/tests.sh b/make/scripts/tests.sh index a93c2ed79..6fbba6adf 100644 --- a/make/scripts/tests.sh +++ b/make/scripts/tests.sh @@ -136,7 +136,7 @@ function jrun() { #D_ARGS="-Djogl.debug.DebugGL -Djogl.debug.TraceGL -Djogl.debug.GLContext.TraceSwitch -Djogl.debug=all" #D_ARGS="-Djogamp.debug.IOUtil -Djogl.debug.GLSLCode -Djogl.debug.GLMediaPlayer" #D_ARGS="-Djogl.debug.GLMediaPlayer -Djogl.debug.AudioSink" - D_ARGS="-Djogl.debug.GLMediaPlayer -Djogl.debug.GLMediaPlayer.Native" + #D_ARGS="-Djogl.debug.GLMediaPlayer -Djogl.debug.GLMediaPlayer.Native" #D_ARGS="-Djogl.debug.GLMediaPlayer" #D_ARGS="-Djogl.debug.GLMediaPlayer.StreamWorker.delay=25 -Djogl.debug.GLMediaPlayer" #D_ARGS="-Djogl.debug.GLMediaPlayer.Native" @@ -304,6 +304,7 @@ function testawtswt() { #testawt com.jogamp.opengl.test.junit.jogl.demos.es2.awt.TestGearsES2AWT $* #testawt com.jogamp.opengl.test.junit.jogl.demos.es2.awt.TestGearsES2GLJPanelAWT $* #testawt com.jogamp.opengl.test.junit.jogl.demos.es2.awt.TestGearsES2GLJPanelsAWT $* +#testawt com.jogamp.opengl.test.junit.jogl.demos.es2.awt.DemoGLJPanelGridAWT $* #testawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NewtCanvasAWT $* #testawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestLandscapeES2NewtCanvasAWT $* #testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT $* @@ -328,7 +329,7 @@ function testawtswt() { # av demos # #testnoawt jogamp.opengl.openal.av.ALDummyUsage $* -testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.av.MovieCube $* +#testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.av.MovieCube $* #testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.av.MovieSimple $* # @@ -384,7 +385,7 @@ testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.av.MovieCube $* #testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextVBOES2NEWT0 $* #testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextVBOES2NEWT1 $* #testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextVBOES2NEWT2 $* -#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextVBOES2NEWT3 $* +testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextVBOES2NEWT3 $* #testawt com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextVBOES2AWT3 $* #testawt com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextVBOES2AWT3b $* #testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestSharedContextVBOES2SWT3 $* diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java index 3f6eb01a0..d43da2c3e 100644 --- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java +++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java @@ -648,16 +648,19 @@ public abstract class GLContextImpl extends GLContext { } final GLContextImpl shareWith = (GLContextImpl) GLContextShareSet.getCreatedShare(this); + final long shareWithHandle; if (null != shareWith) { shareWith.getDrawableImpl().lockSurface(); - // FIXME: - // Contemplate whether we shall 'fail' creating this context - // if 0==shareWith.getHandle(), since at this point - // both context are locked and current values are available. + shareWithHandle = shareWith.getHandle(); + if (0 == shareWithHandle) { + throw new GLException("GLContextShareSet returned an invalid OpenGL context: "+this); + } + } else { + shareWithHandle = 0; } final boolean created; try { - created = createImpl(shareWith); // may throws exception if fails! + created = createImpl(shareWithHandle); // may throws exception if fails if( created && hasNoDefaultVAO() ) { final int[] tmp = new int[1]; final GL3ES3 gl3es3 = gl.getRootGL().getGL3ES3(); @@ -748,13 +751,13 @@ public abstract class GLContextImpl extends GLContext { * @return the valid and current context if successful, or null * @throws GLException */ - protected abstract boolean createImpl(GLContextImpl sharedWith) throws GLException ; + protected abstract boolean createImpl(long sharedWithHandle) throws GLException ; /** * Platform dependent but harmonized implementation of the ARB_create_context * mechanism to create a context.
      * - * This method is called from {@link #createContextARB}, {@link #createImpl(GLContextImpl)} .. {@link #makeCurrent()} .
      + * This method is called from {@link #createContextARB}, {@link #createImpl(long)} .. {@link #makeCurrent()} .
      * * The implementation shall verify this context with a * MakeContextCurrent call.
      diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLContext.java b/src/jogl/classes/jogamp/opengl/egl/EGLContext.java index 2eb277f3f..903a4c461 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLContext.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLContext.java @@ -155,12 +155,12 @@ public class EGLContext extends GLContextImpl { } @Override - protected boolean createImpl(GLContextImpl shareWith) throws GLException { + protected boolean createImpl(final long shareWithHandle) throws GLException { 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; + // 0 == EGL.EGL_NO_CONTEXT; if ( 0 == eglDisplay ) { throw new GLException("Error: attempted to create an OpenGL context without a display connection"); @@ -180,13 +180,6 @@ public class EGLContext extends GLContextImpl { } } - if (shareWith != null) { - shareWithHandle = shareWith.getHandle(); - if (shareWithHandle == 0) { - throw new GLException("GLContextShareSet returned an invalid OpenGL context"); - } - } - final IntBuffer contextAttrsNIO; final int contextVersionReq, contextVersionAttr; { diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java index 037aaca08..0d231b89d 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java @@ -286,35 +286,19 @@ public class MacOSXCGLContext extends GLContextImpl return false; } - protected long createImplPreset(GLContextImpl shareWith) throws GLException { - long share = 0; - if (shareWith != null) { - // Change our OpenGL mode to match that of any share context before we create ourselves - setOpenGLMode(((MacOSXCGLContext)shareWith).getOpenGLMode()); - share = shareWith.getHandle(); - if (share == 0) { - throw new GLException("GLContextShareSet returned a NULL OpenGL context"); - } - } - - MacOSXCGLGraphicsConfiguration config = (MacOSXCGLGraphicsConfiguration) drawable.getNativeSurface().getGraphicsConfiguration(); - GLCapabilitiesImmutable capabilitiesChosen = (GLCapabilitiesImmutable) config.getChosenCapabilities(); - GLProfile glp = capabilitiesChosen.getGLProfile(); + @Override + protected boolean createImpl(final long shareWithHandle) throws GLException { + final MacOSXCGLGraphicsConfiguration config = (MacOSXCGLGraphicsConfiguration) drawable.getNativeSurface().getGraphicsConfiguration(); + final GLCapabilitiesImmutable capabilitiesChosen = (GLCapabilitiesImmutable) config.getChosenCapabilities(); + final GLProfile glp = capabilitiesChosen.getGLProfile(); if( glp.isGLES1() || glp.isGLES2() || glp.isGLES3() || ( glp.isGL3() && !isLionOrLater ) || ( glp.isGL4() && !isMavericksOrLater ) ) { throw new GLException("OpenGL profile not supported on MacOSX "+Platform.getOSVersionNumber()+": "+glp); } - - if (DEBUG) { - System.err.println("Share context is " + toHexString(share) + " for " + this); + if( 0 != shareWithHandle && GLBackendType.NSOPENGL != getOpenGLMode() ) { + throw new GLException("Context sharing only supported in mode "+GLBackendType.NSOPENGL+": "+this); } - return share; - } - - @Override - protected boolean createImpl(GLContextImpl shareWith) throws GLException { - long share = createImplPreset(shareWith); - contextHandle = createContextARB(share, true); + contextHandle = createContextARB(shareWithHandle, true); return 0 != contextHandle; } diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawable.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawable.java index bb36a7219..448e3e221 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawable.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDrawable.java @@ -84,7 +84,10 @@ public abstract class MacOSXCGLDrawable extends GLDrawableImpl { // GLPbuffer, a GLJPanel and a GLCanvas simultaneously) but should // be enough to get things off the ground. public enum GLBackendType { - NSOPENGL(0), CGL(1); + /** Default OpenGL Backend */ + NSOPENGL(0), + /** Alternative OpenGL Backend, only used for external context! */ + CGL(1); public final int id; diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java index 5d036d45a..ebb0fc6d1 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java @@ -50,7 +50,6 @@ import javax.media.opengl.GLDrawableFactory; import javax.media.opengl.GLException; import jogamp.nativewindow.WrappedSurface; -import jogamp.opengl.GLContextImpl; import jogamp.opengl.GLContextShareSet; import jogamp.opengl.macosx.cgl.MacOSXCGLDrawable.GLBackendType; @@ -118,7 +117,7 @@ public class MacOSXExternalCGLContext extends MacOSXCGLContext { } @Override - protected boolean createImpl(GLContextImpl shareWith) throws GLException { + protected boolean createImpl(final long shareWithHandle) throws GLException { return true; } diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java index b1e41624d..b214252c1 100644 --- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java @@ -268,7 +268,7 @@ public class WindowsWGLContext extends GLContextImpl { * called by {@link #makeCurrentImpl()}. */ @Override - protected boolean createImpl(GLContextImpl shareWith) { + protected boolean createImpl(long shareWithHandle) { final AbstractGraphicsConfiguration config = drawable.getNativeSurface().getGraphicsConfiguration(); final AbstractGraphicsDevice device = config.getScreen().getDevice(); final WindowsWGLDrawableFactory factory = (WindowsWGLDrawableFactory)drawable.getFactoryImpl(); @@ -278,18 +278,7 @@ public class WindowsWGLContext extends GLContextImpl { isGLReadDrawableAvailable(); // trigger setup wglGLReadDrawableAvailable if (DEBUG) { - System.err.println(getThreadName() + ": createImpl: START "+glCaps+", share "+shareWith); - } - - // Windows can set up sharing of display lists after creation time - long share; - if ( null != shareWith ) { - share = shareWith.getHandle(); - if (share == 0) { - throw new GLException("GLContextShareSet returned an invalid OpenGL context"); - } - } else { - share = 0; + System.err.println(getThreadName() + ": createImpl: START "+glCaps+", share "+toHexString(shareWithHandle)); } boolean createContextARBTried = false; @@ -300,17 +289,17 @@ public class WindowsWGLContext extends GLContextImpl { if(GLContext.CONTEXT_NOT_CURRENT == sharedContext.makeCurrent()) { throw new GLException("Could not make Shared Context current: "+sharedContext); } - contextHandle = createContextARB(share, true); + contextHandle = createContextARB(shareWithHandle, true); sharedContext.release(); if (!wglMakeContextCurrent(drawable.getHandle(), drawableRead.getHandle(), contextHandle)) { throw new GLException("Cannot make previous verified context current: 0x" + toHexString(contextHandle) + ", werr: " + GDI.GetLastError()); } } else { - contextHandle = createContextARB(share, true); + contextHandle = createContextARB(shareWithHandle, true); } createContextARBTried = true; if ( DEBUG && 0 != contextHandle ) { - System.err.println(getThreadName() + ": createImpl: OK (ARB, using sharedContext) share "+share); + System.err.println(getThreadName() + ": createImpl: OK (ARB, using sharedContext) share "+toHexString(shareWithHandle)); } } @@ -343,17 +332,17 @@ public class WindowsWGLContext extends GLContextImpl { } if ( isProcCreateContextAttribsARBAvailable && isExtARBCreateContextAvailable ) { // initial ARB context creation - contextHandle = createContextARB(share, true); + contextHandle = createContextARB(shareWithHandle, true); createContextARBTried=true; if (DEBUG) { if( 0 != contextHandle ) { - System.err.println(getThreadName() + ": createContextImpl: OK (ARB, initial) share "+share); + System.err.println(getThreadName() + ": createContextImpl: OK (ARB, initial) share "+toHexString(shareWithHandle)); } else { - System.err.println(getThreadName() + ": createContextImpl: NOT OK (ARB, initial) - creation failed - share "+share); + System.err.println(getThreadName() + ": createContextImpl: NOT OK (ARB, initial) - creation failed - share "+toHexString(shareWithHandle)); } } } else if (DEBUG) { - System.err.println(getThreadName() + ": createContextImpl: NOT OK (ARB, initial) - extension not available - share "+share+ + System.err.println(getThreadName() + ": createContextImpl: NOT OK (ARB, initial) - extension not available - share "+toHexString(shareWithHandle)+ ", isProcCreateContextAttribsARBAvailable "+isProcCreateContextAttribsARBAvailable+", isExtGLXARBCreateContextAvailable "+isExtARBCreateContextAvailable); } } @@ -362,7 +351,7 @@ public class WindowsWGLContext extends GLContextImpl { } if( 0 != contextHandle ) { - share = 0; // mark as shared thx to the ARB create method + shareWithHandle = 0; // mark as shared thx to the ARB create method if( 0 != temp_ctx ) { WGL.wglMakeCurrent(0, 0); WGL.wglDeleteContext(temp_ctx); @@ -387,16 +376,17 @@ public class WindowsWGLContext extends GLContextImpl { WGL.wglDeleteContext(contextHandle); throw new GLException("Error making old context current: 0x" + toHexString(contextHandle) + ", werr: " + GDI.GetLastError()); } - if( 0 != share ) { + if( 0 != shareWithHandle ) { + // Windows can set up sharing of display lists after creation time if using GDI // Only utilize the classic GDI 'wglShareLists' shared context method // for traditional non ARB context. - if ( !WGL.wglShareLists(share, contextHandle) ) { - throw new GLException("wglShareLists(" + toHexString(share) + + if ( !WGL.wglShareLists(shareWithHandle, contextHandle) ) { + throw new GLException("wglShareLists(" + toHexString(shareWithHandle) + ", " + toHexString(contextHandle) + ") failed: werr " + GDI.GetLastError()); } } if (DEBUG) { - System.err.println(getThreadName() + ": createImpl: OK (old) share "+share); + System.err.println(getThreadName() + ": createImpl: OK (old) share "+toHexString(shareWithHandle)); } } diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXContext.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXContext.java index 9b7b0f5ae..ff9363ca0 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXContext.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXContext.java @@ -51,7 +51,6 @@ import javax.media.opengl.GLException; import javax.media.opengl.GLProfile; import jogamp.nativewindow.WrappedSurface; -import jogamp.opengl.GLContextImpl; import jogamp.opengl.GLContextShareSet; import com.jogamp.common.nio.Buffers; @@ -114,7 +113,7 @@ public class X11ExternalGLXContext extends X11GLXContext { } @Override - protected boolean createImpl(GLContextImpl shareWith) { + protected boolean createImpl(final long shareWithHandle) { return true; } diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java index 10f21f0c3..94620c4fc 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java @@ -283,7 +283,7 @@ public class X11GLXContext extends GLContextImpl { } @Override - protected boolean createImpl(GLContextImpl shareWith) { + protected boolean createImpl(final long shareWithHandle) { boolean direct = true; // try direct always isDirect = false; // fall back @@ -293,15 +293,8 @@ public class X11GLXContext extends GLContextImpl { final X11GLXContext sharedContext = (X11GLXContext) factory.getOrCreateSharedContext(device); long display = device.getHandle(); - final long share; - if ( null != shareWith ) { - share = shareWith.getHandle(); - if (share == 0) { - throw new GLException("GLContextShareSet returned an invalid OpenGL context"); - } - direct = GLX.glXIsDirect(display, share); - } else { - share = 0; + if ( 0 != shareWithHandle ) { + direct = GLX.glXIsDirect(display, shareWithHandle); } final GLCapabilitiesImmutable glCaps = (GLCapabilitiesImmutable) config.getChosenCapabilities(); @@ -313,7 +306,7 @@ public class X11GLXContext extends GLContextImpl { if(glp.isGL3()) { throw new GLException(getThreadName()+": Unable to create OpenGL >= 3.1 context"); } - contextHandle = GLX.glXCreateContext(display, config.getXVisualInfo(), share, direct); + contextHandle = GLX.glXCreateContext(display, config.getXVisualInfo(), shareWithHandle, direct); if ( 0 == contextHandle ) { throw new GLException(getThreadName()+": Unable to create context(0)"); } @@ -325,7 +318,7 @@ public class X11GLXContext extends GLContextImpl { } isDirect = GLX.glXIsDirect(display, contextHandle); if (DEBUG) { - System.err.println(getThreadName() + ": createContextImpl: OK (old-1) share "+share+", direct "+isDirect+"/"+direct); + System.err.println(getThreadName() + ": createContextImpl: OK (old-1) share "+toHexString(shareWithHandle)+", direct "+isDirect+"/"+direct); } return true; } @@ -334,10 +327,10 @@ public class X11GLXContext extends GLContextImpl { // utilize the shared context's GLXExt in case it was using the ARB method and it already exists if( null != sharedContext && sharedContext.isCreatedWithARBMethod() ) { - contextHandle = createContextARB(share, direct); + contextHandle = createContextARB(shareWithHandle, direct); createContextARBTried = true; if ( DEBUG && 0 != contextHandle ) { - System.err.println(getThreadName() + ": createContextImpl: OK (ARB, using sharedContext) share "+share); + System.err.println(getThreadName() + ": createContextImpl: OK (ARB, using sharedContext) share "+toHexString(shareWithHandle)); } } @@ -345,7 +338,7 @@ public class X11GLXContext extends GLContextImpl { if( 0 == contextHandle ) { // To use GLX_ARB_create_context, we have to make a temp context current, // so we are able to use GetProcAddress - temp_ctx = GLX.glXCreateNewContext(display, config.getFBConfig(), GLX.GLX_RGBA_TYPE, share, direct); + temp_ctx = GLX.glXCreateNewContext(display, config.getFBConfig(), GLX.GLX_RGBA_TYPE, shareWithHandle, direct); if ( 0 == temp_ctx ) { throw new GLException(getThreadName()+": Unable to create temp OpenGL context(1)"); } @@ -360,17 +353,17 @@ public class X11GLXContext extends GLContextImpl { final boolean isExtARBCreateContextAvailable = isExtensionAvailable("GLX_ARB_create_context"); if ( isProcCreateContextAttribsARBAvailable && isExtARBCreateContextAvailable ) { // initial ARB context creation - contextHandle = createContextARB(share, direct); + contextHandle = createContextARB(shareWithHandle, direct); createContextARBTried=true; if (DEBUG) { if( 0 != contextHandle ) { - System.err.println(getThreadName() + ": createContextImpl: OK (ARB, initial) share "+share); + System.err.println(getThreadName() + ": createContextImpl: OK (ARB, initial) share "+toHexString(shareWithHandle)); } else { - System.err.println(getThreadName() + ": createContextImpl: NOT OK (ARB, initial) - creation failed - share "+share); + System.err.println(getThreadName() + ": createContextImpl: NOT OK (ARB, initial) - creation failed - share "+toHexString(shareWithHandle)); } } } else if (DEBUG) { - System.err.println(getThreadName() + ": createContextImpl: NOT OK (ARB, initial) - extension not available - share "+share+ + System.err.println(getThreadName() + ": createContextImpl: NOT OK (ARB, initial) - extension not available - share "+toHexString(shareWithHandle)+ ", isProcCreateContextAttribsARBAvailable "+isProcCreateContextAttribsARBAvailable+", isExtGLXARBCreateContextAvailable "+isExtARBCreateContextAvailable); } } @@ -404,7 +397,7 @@ public class X11GLXContext extends GLContextImpl { throw new GLException(getThreadName()+": Error making context(1) current: display "+toHexString(display)+", context "+toHexString(contextHandle)+", drawable "+drawable); } if (DEBUG) { - System.err.println(getThreadName() + ": createContextImpl: OK (old-2) share "+share); + System.err.println(getThreadName() + ": createContextImpl: OK (old-2) share "+toHexString(shareWithHandle)); } } isDirect = GLX.glXIsDirect(display, contextHandle); -- cgit v1.2.3