aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2019-06-23 08:03:04 +0200
committerSven Gothel <[email protected]>2019-06-23 08:03:04 +0200
commitbba73bc096250a3c7fc036d84b1ea054d1b70b06 (patch)
treeed02575eac2a46bd49627444dcce972946ae8d2e
parent154e91978498d8b6db9ce34a1f06b298bcf4c361 (diff)
iOS: Initial working commit supporting iOS (ipad pro 11)
using our OpenJFK 9 x86_64 and arm64 build. Test demo class is 'com.jogamp.opengl.demos.ios.Hello', residing in the new demo folder 'src/demos/com/jogamp/opengl/demos/ios/Hello.java'. This commit does not yet include a working NEWT specialization for iOS, but it shall followup soon. Instead this commit demonstrates JOGL operating on native UIWindow, UIView and CAEAGLLayer as provided by Nativewindow's IOSUtil. Test Video https://www.youtube.com/watch?v=Z4lUQNFTGMI +++ Notable bug: The FBO used and sharing the COLORBUFFER RENDERBUFFER memory resources with CAEAGLLayer to be displayed in the UIView seemingly cannot handle GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT24 or GL_DEPTH_COMPONENT32 depth buffer - none at all (Device + Simulation). Therefor the default demo GLEventListener chosen here don't require a depth buffer ;-) This issue can hopefully be mitigated with other means than using a flat FBO sink similar to FBO multisampling.
-rw-r--r--.classpath1
-rw-r--r--make/build-common.xml36
-rw-r--r--make/build-jogl.xml94
-rw-r--r--make/build-nativewindow.xml102
-rw-r--r--make/build-newt.xml58
-rw-r--r--make/build-test.xml53
-rw-r--r--make/build.xml14
-rw-r--r--make/config/jogl/eagl-ios.cfg43
-rwxr-xr-xmake/scripts/make.jogl.all.ios.amd64.sh35
-rwxr-xr-xmake/scripts/make.jogl.all.ios.arm64.sh35
-rwxr-xr-xmake/scripts/make.jogl.all.macosx.sh4
-rwxr-xr-xmake/scripts/setenv-jogl.sh4
-rwxr-xr-xmake/scripts/tests-osx-x64.sh4
-rwxr-xr-xmake/scripts/tests-x64.sh2
-rw-r--r--make/scripts/tests.sh9
-rw-r--r--make/stub_includes/ios/OpenGLES/EAGL.h13
-rw-r--r--make/stub_includes/ios/OpenGLES/EAGLDrawable.h2
-rw-r--r--make/stub_includes/ios/QuartzCore/CAEAGLLayer.h1
-rw-r--r--make/stub_includes/ios/QuartzCore/CALayer.h1
-rw-r--r--make/stub_includes/ios/UIKit/UIKit.h1
-rw-r--r--make/stub_includes/ios/window-system1.c2
-rw-r--r--make/stub_includes/macosx/UIKit/NSOpenGL.h3
-rw-r--r--make/stub_includes/macosx/UIKit/NSOpenGLLayer.h1
-rw-r--r--make/stub_includes/macosx/UIKit/NSOpenGLView.h1
-rw-r--r--make/stub_includes/macosx/UIKit/UIView.h1
-rw-r--r--make/stub_includes/opengl/ios-window-system.h51
-rw-r--r--src/demos/com/jogamp/opengl/demos/GearsObject.java336
-rw-r--r--src/demos/com/jogamp/opengl/demos/PointsDemo.java48
-rw-r--r--src/demos/com/jogamp/opengl/demos/es2/GearsES2.java673
-rw-r--r--src/demos/com/jogamp/opengl/demos/es2/GearsObjectES2.java146
-rw-r--r--src/demos/com/jogamp/opengl/demos/es2/LandscapeES2.java187
-rw-r--r--src/demos/com/jogamp/opengl/demos/es2/PointsDemoES2.java208
-rw-r--r--src/demos/com/jogamp/opengl/demos/es2/RedSquareES2.java274
-rw-r--r--src/demos/com/jogamp/opengl/demos/es2/shader/PointsShader.fp53
-rw-r--r--src/demos/com/jogamp/opengl/demos/es2/shader/PointsShader.vp53
-rw-r--r--src/demos/com/jogamp/opengl/demos/es2/shader/RedSquareShader.fp16
-rw-r--r--src/demos/com/jogamp/opengl/demos/es2/shader/RedSquareShader.java73
-rw-r--r--src/demos/com/jogamp/opengl/demos/es2/shader/RedSquareShader.vp18
-rw-r--r--src/demos/com/jogamp/opengl/demos/es2/shader/RedSquareShader2.fp16
-rw-r--r--src/demos/com/jogamp/opengl/demos/es2/shader/default.vp24
-rw-r--r--src/demos/com/jogamp/opengl/demos/es2/shader/elektronenmultiplizierer_development.fp389
-rw-r--r--src/demos/com/jogamp/opengl/demos/es2/shader/elektronenmultiplizierer_port.fp242
-rw-r--r--src/demos/com/jogamp/opengl/demos/es2/shader/fbo-mrt-1.fp16
-rw-r--r--src/demos/com/jogamp/opengl/demos/es2/shader/fbo-mrt-1.vp19
-rw-r--r--src/demos/com/jogamp/opengl/demos/es2/shader/fbo-mrt-2.fp22
-rw-r--r--src/demos/com/jogamp/opengl/demos/es2/shader/fbo-mrt-2.vp21
-rw-r--r--src/demos/com/jogamp/opengl/demos/es2/shader/gears.fp48
-rw-r--r--src/demos/com/jogamp/opengl/demos/es2/shader/gears.vp45
-rw-r--r--src/demos/com/jogamp/opengl/demos/es2/shader/landscape.fp339
-rw-r--r--src/demos/com/jogamp/opengl/demos/es2/shader/landscape.vp11
-rw-r--r--src/demos/com/jogamp/opengl/demos/es2/shader/mgl_default_xxx.fp16
-rw-r--r--src/demos/com/jogamp/opengl/demos/es2/shader/mgl_default_xxx.vp18
-rw-r--r--src/demos/com/jogamp/opengl/demos/es2/shader/ruler.fp33
-rw-r--r--src/demos/com/jogamp/opengl/demos/es2/shader/texsequence_xxx.fp30
-rw-r--r--src/demos/com/jogamp/opengl/demos/es2/shader/texsequence_xxx.vp22
-rw-r--r--src/demos/com/jogamp/opengl/demos/es2/shader/texture01_xxx.fp28
-rw-r--r--src/demos/com/jogamp/opengl/demos/es2/shader/texture01_xxx.vp22
-rw-r--r--src/demos/com/jogamp/opengl/demos/es2/shader/texture02_xxx.fp28
-rw-r--r--src/demos/com/jogamp/opengl/demos/ios/Hello.java196
-rw-r--r--src/demos/com/jogamp/opengl/demos/ios/Hello0.java20
-rw-r--r--src/jogl/classes/com/jogamp/opengl/FBObject.java48
-rw-r--r--src/jogl/classes/com/jogamp/opengl/GLDrawableFactory.java83
-rw-r--r--src/jogl/classes/com/jogamp/opengl/GLProfile.java178
-rw-r--r--src/jogl/classes/com/jogamp/opengl/JoglVersion.java13
-rw-r--r--src/jogl/classes/jogamp/opengl/DummyGLExtProcAddressTable.java61
-rw-r--r--src/jogl/classes/jogamp/opengl/GLContextImpl.java11
-rw-r--r--src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java77
-rw-r--r--src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java6
-rw-r--r--src/jogl/classes/jogamp/opengl/egl/EGLGLnDynamicLibraryBundleInfo.java2
-rw-r--r--src/jogl/classes/jogamp/opengl/ios/eagl/IOSEAGLContext.java477
-rw-r--r--src/jogl/classes/jogamp/opengl/ios/eagl/IOSEAGLDrawable.java90
-rw-r--r--src/jogl/classes/jogamp/opengl/ios/eagl/IOSEAGLDrawableFactory.java453
-rw-r--r--src/jogl/classes/jogamp/opengl/ios/eagl/IOSEAGLDynamicLibraryBundleInfo.java83
-rw-r--r--src/jogl/classes/jogamp/opengl/ios/eagl/IOSEAGLGraphicsConfiguration.java62
-rw-r--r--src/jogl/classes/jogamp/opengl/ios/eagl/IOSEAGLGraphicsConfigurationFactory.java87
-rw-r--r--src/jogl/classes/jogamp/opengl/ios/eagl/IOSOnscreenEAGLDrawable.java45
-rw-r--r--src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDynamicLibraryBundleInfo.java1
-rw-r--r--src/jogl/native/JVM_JNI8.c43
-rw-r--r--src/jogl/native/ios/IOSWindowSystemInterface.h42
-rw-r--r--src/jogl/native/ios/IOSWindowSystemInterface.m119
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/NativeWindowFactory.java17
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/ios/IOSGraphicsDevice.java46
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/javafx/JFXAccessor.java2
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/ios/IOSDummyUpstreamSurfaceHook.java83
-rw-r--r--src/nativewindow/classes/jogamp/nativewindow/ios/IOSUtil.java333
-rw-r--r--src/nativewindow/native/JVM_JNI8.c47
-rw-r--r--src/nativewindow/native/ios/CAEAGLLayered.h50
-rw-r--r--src/nativewindow/native/ios/CAEAGLLayered.m66
-rw-r--r--src/nativewindow/native/ios/IOSmisc.m813
-rw-r--r--src/nativewindow/native/ios/NativeWindowProtocols.h59
-rw-r--r--src/nativewindow/native/macosx/OSXmisc.m16
-rw-r--r--src/newt/classes/jogamp/newt/driver/ios/DisplayDriver.java91
-rw-r--r--src/newt/classes/jogamp/newt/driver/ios/MacKeyUtil.java426
-rw-r--r--src/newt/classes/jogamp/newt/driver/ios/ScreenDriver.java225
-rw-r--r--src/newt/classes/jogamp/newt/driver/ios/WindowDriver.java812
-rw-r--r--src/newt/native/IOSNewtUIWindow.h152
-rw-r--r--src/newt/native/IOSNewtUIWindow.m783
-rw-r--r--src/newt/native/IOSUIWindow.m1161
-rw-r--r--src/newt/native/JVM_JNI8.c42
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableDelegateOnOffscrnCapsNEWT.java4
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryES2OffscrnCapsNEWT.java12
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryGL2OffscrnCapsNEWT.java12
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryGLProfileDeviceNEWT.java20
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryGLnBitmapCapsNEWT.java12
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableGLCanvasOnOffscrnCapsAWT.java12
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT.java12
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableNewtCanvasAWTOnOffscrnCapsAWT.java12
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLProfile00NEWT.java12
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLProfile01NEWT.java4
-rw-r--r--src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedExternalContextAWT.java6
110 files changed, 11303 insertions, 281 deletions
diff --git a/.classpath b/.classpath
index 04a8dac8e..46fb778f0 100644
--- a/.classpath
+++ b/.classpath
@@ -33,6 +33,7 @@
</classpathentry>
<classpathentry kind="src" path="src/oculusvr/classes"/>
<classpathentry kind="src" path="oculusvr-sdk/jogl/src/classes"/>
+ <classpathentry kind="src" path="src/demos"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry combineaccessrules="false" kind="src" path="/gluegen"/>
<classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/Ant"/>
diff --git a/make/build-common.xml b/make/build-common.xml
index 7ba8f74fc..84a2e3014 100644
--- a/make/build-common.xml
+++ b/make/build-common.xml
@@ -93,16 +93,22 @@
<property name="archive.name" value="jogl-${jogl.version}-${os.and.arch}" />
<property name="archive" value="${build}/${archive.name}" />
+ <condition property="setup.noAWT">
+ <or>
+ <istrue value="${isIOS}" />
+ </or>
+ </condition>
<condition property="setup.noNativeAWT">
<or>
<isset property="setup.noAWT"/>
- <isset property="isAndroid"/>
+ <istrue value="${isAndroid}" />
</or>
</condition>
<condition property="setup.noNativeDesktop">
<or>
- <isset property="isAndroid"/>
+ <istrue value="${isAndroid}" />
+ <istrue value="${isIOS}" />
</or>
</condition>
@@ -140,13 +146,12 @@
<istrue value="${isLinuxX86}" /> <!-- no more supported since SWT 4.10 -->
</condition>
<condition property="swt.jar" value="${project.root}/make/lib/swt/gtk-linux-x86_64/swt.jar">
- <istrue value="${isLinuxARM64}" /> <!-- FIXME JAU .. hack -->
- </condition>
- <condition property="swt.jar" value="${project.root}/make/lib/swt/gtk-linux-x86_64/swt.jar">
- <istrue value="${isLinuxARMv6}" /> <!-- FIXME JAU .. hack -->
- </condition>
- <condition property="swt.jar" value="${project.root}/make/lib/swt/gtk-linux-x86_64/swt.jar">
- <istrue value="${isAndroid}" /> <!-- FIXME JAU .. hack -->
+ <or>
+ <istrue value="${isLinuxARM64}" /> <!-- FIXME JAU .. hack -->
+ <istrue value="${isLinuxARMv6}" /> <!-- FIXME JAU .. hack -->
+ <istrue value="${isAndroid}" /> <!-- FIXME JAU .. hack -->
+ <istrue value="${isIOS}" /> <!-- FIXME JAU .. hack -->
+ </or>
</condition>
<property name="swt-cocoa-macosx-x86_64.jar" value="${project.root}/make/lib/swt/cocoa-macosx-x86_64/swt.jar"/>
<condition property="swt.jar" value="${swt-cocoa-macosx-x86_64.jar}">
@@ -252,6 +257,7 @@
<property name="results.test" value="${build}/test/results" />
<property name="build.test" value="${build}/test/build" />
<property name="obj.test" value="${build.test}/obj"/>
+ <property name="build.demos" value="${build}/demos/build" />
<condition property="obj.custom" value="${custom.libdir}${path.separator}" else="">
<isset property="custom.libdir"/>
@@ -282,6 +288,7 @@
<property name="nativewindow-os-x11.jar" value="${build.nativewindow}/nativewindow-os-x11.jar" />
<property name="nativewindow-os-win.jar" value="${build.nativewindow}/nativewindow-os-win.jar" />
<property name="nativewindow-os-osx.jar" value="${build.nativewindow}/nativewindow-os-osx.jar" />
+ <property name="nativewindow-os-ios.jar" value="${build.nativewindow}/nativewindow-os-ios.jar" />
<path id="nativewindow_all_atoms.classpath">
<pathelement location="${nativewindow.jar}" />
@@ -289,12 +296,14 @@
<pathelement location="${nativewindow-os-x11.jar}" />
<pathelement location="${nativewindow-os-win.jar}" />
<pathelement location="${nativewindow-os-osx.jar}" />
+ <pathelement location="${nativewindow-os-ios.jar}" />
</path>
<path id="nativewindow_all-noawt_atoms.classpath">
<pathelement location="${nativewindow.jar}" />
<pathelement location="${nativewindow-os-x11.jar}" />
<pathelement location="${nativewindow-os-win.jar}" />
<pathelement location="${nativewindow-os-osx.jar}" />
+ <pathelement location="${nativewindow-os-ios.jar}" />
</path>
<path id="nativewindow_core_atoms.classpath">
<pathelement location="${nativewindow.jar}" />
@@ -314,6 +323,7 @@
<property name="jogl-os-x11.jar" value="${build.jogl}/jogl-os-x11.jar" />
<property name="jogl-os-win.jar" value="${build.jogl}/jogl-os-win.jar" />
<property name="jogl-os-osx.jar" value="${build.jogl}/jogl-os-osx.jar" />
+ <property name="jogl-os-ios.jar" value="${build.jogl}/jogl-os-ios.jar" />
<property name="jogl-os-android.jar" value="${build.jogl}/jogl-os-android.jar" />
<property name="jogl-gldesktop.jar" value="${build.jogl}/jogl-gldesktop.jar" />
<property name="jogl-gldesktop-dbg.jar" value="${build.jogl}/jogl-gldesktop-dbg.jar" />
@@ -337,6 +347,7 @@
<pathelement location="${jogl-os-x11.jar}" />
<pathelement location="${jogl-os-win.jar}" />
<pathelement location="${jogl-os-osx.jar}" />
+ <pathelement location="${jogl-os-ios.jar}" />
<pathelement location="${jogl-gldesktop.jar}" />
<pathelement location="${jogl-gldesktop-dbg.jar}" />
<pathelement location="${jogl-glu.jar}" />
@@ -355,6 +366,7 @@
<pathelement location="${jogl-os-x11.jar}" />
<pathelement location="${jogl-os-win.jar}" />
<pathelement location="${jogl-os-osx.jar}" />
+ <pathelement location="${jogl-os-ios.jar}" />
<pathelement location="${jogl-gldesktop.jar}" />
<pathelement location="${jogl-gldesktop-dbg.jar}" />
<pathelement location="${jogl-glu.jar}" />
@@ -371,6 +383,7 @@
<pathelement location="${jogl-glu.jar}" />
<pathelement location="${jogl-util-fixedfuncemu.jar}" />
<pathelement location="${jogl-os-x11.jar}" />
+ <pathelement location="${jogl-os-ios.jar}" />
<pathelement location="${jogl-omx.jar}" />
</path>
<path id="jogl_all-android_atoms.classpath">
@@ -397,6 +410,7 @@
<property name="newt-driver-x11.jar" value="${build.newt}/newt-driver-x11.jar" />
<property name="newt-driver-win.jar" value="${build.newt}/newt-driver-win.jar" />
<property name="newt-driver-osx.jar" value="${build.newt}/newt-driver-osx.jar" />
+ <property name="newt-driver-ios.jar" value="${build.newt}/newt-driver-ios.jar" />
<property name="newt-driver-android.jar" value="${build.newt}/newt-driver-android.jar" /> <!-- excluded from all -->
<property name="newt-driver-kd.jar" value="${build.newt}/newt-driver-kd.jar" /> <!-- excluded from all -->
<property name="newt-driver-intelgdl.jar" value="${build.newt}/newt-driver-intelgdl.jar" /> <!-- excluded from all -->
@@ -412,6 +426,7 @@
<pathelement location="${newt-driver-x11.jar}" />
<pathelement location="${newt-driver-win.jar}" />
<pathelement location="${newt-driver-osx.jar}" />
+ <pathelement location="${newt-driver-ios.jar}" />
<pathelement location="${newt-driver-bcm-vc.jar}" />
</path>
<path id="newt_all-noawt_atoms.classpath">
@@ -421,6 +436,7 @@
<pathelement location="${newt-driver-x11.jar}" />
<pathelement location="${newt-driver-win.jar}" />
<pathelement location="${newt-driver-osx.jar}" />
+ <pathelement location="${newt-driver-ios.jar}" />
<pathelement location="${newt-driver-bcm-vc.jar}" />
</path>
<path id="newt_all-mobile_atoms.classpath">
@@ -429,6 +445,7 @@
<pathelement location="${newt-driver-linux.jar}" />
<pathelement location="${newt-driver-x11.jar}" />
<pathelement location="${newt-driver-win.jar}" />
+ <pathelement location="${newt-driver-ios.jar}" />
<pathelement location="${newt-driver-bcm-vc.jar}" />
</path>
<path id="newt_all-android_atoms.classpath">
@@ -449,6 +466,7 @@
<property name="jogl-test.jar" value="${jar}/jogl-test.jar"/>
<property name="jogl-test-android.jar" value="${jar}/jogl-test-android.jar"/>
<property name="jogl-test-android.apk" value="${jar}/jogl-test-android.apk"/>
+ <property name="jogl-demos-mobile.jar" value="${jar}/jogl-demos-mobile.jar"/>
<!-- JavaSE combinations . AWT -->
<property name="jogl-all.jar" value="${jar}/jogl-all.jar" />
diff --git a/make/build-jogl.xml b/make/build-jogl.xml
index 1d867c56b..db80c298c 100644
--- a/make/build-jogl.xml
+++ b/make/build-jogl.xml
@@ -113,15 +113,18 @@
<property name="java.part.sdk"
value="com/jogamp/opengl/util/glsl/sdk/**"/>
- <property name="java.part.glx"
+ <property name="java.part.x11.glx"
value="jogamp/opengl/x11/glx/*"/>
- <property name="java.part.wgl"
+ <property name="java.part.win.wgl"
value="jogamp/opengl/windows/wgl/*"/>
- <property name="java.part.cgl"
+ <property name="java.part.osx.cgl"
value="jogamp/opengl/macosx/cgl/*"/>
+ <property name="java.part.ios.eagl"
+ value="jogamp/opengl/ios/eagl/*"/>
+
<property name="java.part.android"
value="jogamp/opengl/android/**"/>
@@ -188,9 +191,6 @@
<property name="java.part.nonjava"
value="${java.part.core.shadercode} ${java.part.util.shadercode} ${java.part.util.fixedfuncemu.shadercode} ${java.part.util.graph.shadercode} ${java.part.util.graph.fonts}"/>
- <property name="java.part.all-desktop"
- value="${java.part.sdk} ${java.part.glx} ${java.part.wgl} ${java.part.cgl} ${java.part.gldesktop} ${java.part.glu.gldesktop} ${java.part.util.gldesktop}"/>
-
<!-- condition excludes -->
<condition property="java.excludes.awt"
@@ -347,6 +347,7 @@
<mkdir dir="${src.generated.java}" />
<mkdir dir="${src.generated.c}" />
<mkdir dir="${src.generated.c}/MacOSX" />
+ <mkdir dir="${src.generated.c}/iOS" />
<mkdir dir="${src.generated.c}/Windows" />
<mkdir dir="${src.generated.c}/X11" />
<mkdir dir="${src.generated.c.openmax}" />
@@ -709,7 +710,7 @@
</gluegen>
</target>
- <target name="java.generate.platform.glext">
+ <target name="java.generate.platform.glext" if="glext.platform.cfg">
<echo message="Generating platform-specific OpenGL extension class: ${window.os.system}" />
<antcall target="java.generate.copy2temp" inheritRefs="true" />
<gluegen src="${glext.platform.header}"
@@ -862,6 +863,13 @@
<param name="glext.platform.header" value="${stub.includes}/macosx/cglext.c" />
</antcall>
+ <antcall target="java.generate.gl.platforms" inheritRefs="true">
+ <param name="window.os.system" value="ios"/>
+ <param name="window.os1.cfg" value="${config.jogl}/eagl-ios.cfg" />
+ <!-- param name="glext.platform.cfg" value="${config.jogl}/eagl-ext.cfg" /-->
+ <!-- param name="glext.platform.header" value="${stub.includes}/ios/eagl-ext.c" /-->
+ </antcall>
+
<!-- Generate GLU class -->
<antcall target="java.generate.glu.base" inheritrefs="true" />
<antcall target="java.generate.glu.GL2ES1" inheritrefs="true" />
@@ -1280,6 +1288,26 @@
<linkerarg value="Cg"/>
</linker-->
+ <linker id="linker.cfg.ios.amd64.jogl" extends="linker.cfg.ios.amd64">
+ <!-- linkerarg value="-v" / -->
+ <linkerarg value="-weak_framework" />
+ <linkerarg value="UIKit" />
+ <linkerarg value="-weak_framework" />
+ <linkerarg value="QuartzCore" />
+ <linkerarg value="-weak_framework" />
+ <linkerarg value="OpenGLES" />
+ </linker>
+
+ <linker id="linker.cfg.ios.arm64.jogl" extends="linker.cfg.ios.arm64">
+ <!-- linkerarg value="-v" / -->
+ <linkerarg value="-weak_framework" />
+ <linkerarg value="UIKit" />
+ <linkerarg value="-weak_framework" />
+ <linkerarg value="QuartzCore" />
+ <linkerarg value="-weak_framework" />
+ <linkerarg value="OpenGLES" />
+ </linker>
+
<linker id="linker.cfg.hpux.jogl" extends="linker.cfg.hpux">
<syslibset dir="/opt/graphics/OpenGL/lib" libs="GL, GLU"/>
<syslibset dir="/usr/lib" libs="X11"/>
@@ -1426,8 +1454,18 @@
<property name="compiler.cfg.id" value="compiler.cfg.macosx" />
<property name="linker.cfg.id.os" value="linker.cfg.macosx.jogl" />
</target>
+
+ <target name="c.configure.ios.amd64" if="isIOSAmd64">
+ <property name="compiler.cfg.id" value="compiler.cfg.ios.amd64" />
+ <property name="linker.cfg.id.os" value="linker.cfg.ios.amd64.jogl" />
+ </target>
+
+ <target name="c.configure.ios.arm64" if="isIOSArm64">
+ <property name="compiler.cfg.id" value="compiler.cfg.ios.arm64" />
+ <property name="linker.cfg.id.os" value="linker.cfg.ios.arm64.jogl" />
+ </target>
- <target name="c.configure.2" depends="c.configure.win32,c.configure.linux,c.configure.android,c.configure.solaris32,c.configure.solaris.sparcv9,c.configure.solaris.amd64,c.configure.macosx,c.configure.freebsd,c.configure.hpux" />
+ <target name="c.configure.2" depends="c.configure.win32,c.configure.linux,c.configure.android,c.configure.solaris32,c.configure.solaris.sparcv9,c.configure.solaris.amd64,c.configure.macosx,c.configure.ios.amd64, c.configure.ios.arm64, c.configure.freebsd,c.configure.hpux" />
<target name="c.configure" depends="c.configure.1,c.configure.2" />
@@ -1467,12 +1505,11 @@
<fileset dir="${project.root}" includes="${rootrel.src.c.libav}/*"/>
</sourcefiles>
<targetfiles>
- <fileset dir="${obj.joglsub}" includes="lib@{output.lib.name}.so"/>
- <fileset dir="${obj.joglsub}" includes="@{output.lib.name}.dll"/>
- <fileset dir="${obj.joglsub}" includes="lib@{output.lib.name}.dylib"/>
+ <fileset dir="${obj.joglsub}" includes="${native.library.prefix}@{output.lib.name}.${native.library.suffix}"/>
</targetfiles>
<sequential>
- <cc outtype="shared"
+ <cc outtype="${output.lib.type}"
+ usehighleveltool="true"
objdir="${obj.joglsub}"
outfile="${obj.joglsub}/@{output.lib.name}"
optimize="${c.compiler.optimise}"
@@ -1502,6 +1539,9 @@
<linker extends="@{linker.cfg.id}">
</linker>
</cc>
+ <gluegen.make.libsymbols builddir="${build}"
+ nativelib="${obj.joglsub}/${native.library.prefix}@{output.lib.name}.${native.library.suffix}"
+ symbolsfile="${obj.joglsub}/${native.library.prefix}@{output.lib.name}.symbols"/>
</sequential>
</outofdate>
</sequential>
@@ -1529,15 +1569,17 @@
</patternset>
<patternset id="c.src.files.jogl.desktop">
+ <include name="${rootrel.src.c}/JVM_JNI8.c"/>
<include name="${rootrel.src.c}/JoglCommon.c"/>
<include name="${rootrel.src.c}/GLContext.c"/>
<include name="${rootrel.src.c}/EGLContext.c"/>
<include name="${rootrel.src.c}/GLDebugMessageHandler.c"/>
- <include name="${rootrel.src.c}/timespec.c" if="isOSX"/> <!-- currently only used for OSX -->
+ <include name="${rootrel.src.c}/timespec.c" if="isOSX"/> <!-- currently only used for OSX, iOS -->
<include name="${rootrel.src.c}/macosx/MacOSXCustomCGLCode.c" if="isOSX"/>
<include name="${rootrel.src.c}/macosx/MacOSXWindowSystemInterface.m" if="isOSX"/>
<include name="${rootrel.src.c}/macosx/MacOSXWindowSystemInterface-calayer.m" if="isOSX"/>
<include name="${rootrel.src.c}/macosx/ContextUpdater.m" if="isOSX"/>
+ <!-- include name="${rootrel.src.c}/ios/lalalala.m" if="isIOS"/ -->
<include name="${rootrel.src.c}/GLXGetProcAddressARB.c" if="isX11"/>
<!-- FIXME: the Mixer should be moved to another library -->
<!--include name="${rootrel.src.c}/Mixer.cpp" if="isWindows"/-->
@@ -1556,11 +1598,14 @@
</patternset>
<patternset id="c.src.files.jogl.mobile">
+ <include name="${rootrel.src.c}/JVM_JNI8.c"/>
<include name="${rootrel.src.c}/JoglCommon.c"/>
<include name="${rootrel.src.c}/GLContext.c"/>
<include name="${rootrel.src.c}/EGLContext.c"/>
<include name="${rootrel.src.c}/GLDebugMessageHandler.c"/>
<include name="${rootrel.src.c}/GLXGetProcAddressARB.c" if="isX11"/>
+ <include name="${rootrel.src.c}/timespec.c" if="isIOS"/> <!-- currently only used for OSX, iOS -->
+ <include name="${rootrel.src.c}/ios/IOSWindowSystemInterface.m" if="isIOS"/>
<include name="${rootrel.src.c.libav}/ffmpeg_static.c"/>
<include name="${rootrel.src.c.libav}/ffmpeg_dshow.c"/>
<include name="${rootrel.src.c.openmax}/omx_tool.c" if="setup.addNativeOpenMAX"/>
@@ -1573,6 +1618,7 @@
<include name="${rootrel.generated.c.jogl}/es1/GLES1Impl_JNI.c"/>
<!--include name="${rootrel.generated.c.jogl}/GLU_JNI.c"/ EMPTY -->
<!--include name="${rootrel.generated.c.jogl}/es1/GLUes1_JNI.c" EMPTY /-->
+ <include name="${rootrel.generated.c.jogl}/iOS/*.c" if="isIOS"/>
</patternset>
<patternset id="c.src.files.cg">
@@ -1589,12 +1635,11 @@
<fileset dir="${obj.joglsub}" includes="*jogl_ffmpegv08*, *jogl_ffmpegv09*, *jogl_ffmpegv10*"/> <!-- requires linkage -->
</sourcefiles>
<targetfiles>
- <fileset dir="${obj.jogl}" includes="lib@{output.lib.name}.so"/>
- <fileset dir="${obj.jogl}" includes="@{output.lib.name}.dll"/>
- <fileset dir="${obj.jogl}" includes="lib@{output.lib.name}.dylib"/>
+ <fileset dir="${obj.jogl}" includes="${native.library.prefix}@{output.lib.name}.${native.library.suffix}"/>
</targetfiles>
<sequential>
- <cc outtype="shared"
+ <cc outtype="${output.lib.type}"
+ usehighleveltool="true"
objdir="${obj.joglsub}"
outfile="${obj.jogl}/@{output.lib.name}"
optimize="${c.compiler.optimise}"
@@ -1621,9 +1666,11 @@
<!-- This is for the generated headers for handwritten C code -->
<includepath path="${src.c}"/>
<includepath path="${nativewindow.src.c}/macosx" if="isOSX"/>
+ <includepath path="${nativewindow.src.c}/ios" if="isIOS"/>
<includepath path="${src.generated.c}" />
<includepath path="${src.generated.c}/X11" if="isX11"/>
<includepath path="${src.generated.c}/MacOSX" if="isOSX"/>
+ <includepath path="${src.generated.c}/iOS" if="isIOS"/>
<includepath path="${src.generated.c}/Windows" if="isWindows"/>
<includepath path="${src.generated.c.libav}" />
<includepath path="${src.generated.c.openmax}" if="setup.addNativeOpenMAX"/>
@@ -1645,6 +1692,10 @@
<param name="dest" value="${obj.jogl}/@{output.lib.name}.dll" />
</antcall>
+ <gluegen.make.libsymbols builddir="${build}"
+ nativelib="${obj.jogl}/${native.library.prefix}@{output.lib.name}.${native.library.suffix}"
+ symbolsfile="${obj.jogl}/${native.library.prefix}@{output.lib.name}.symbols"/>
+
<!-- this stripping may be called more than once on the same library dir,
but that should cause no harm, and doing it here inside outofdate
prevents the JARs from always being rebuilt even if no source code changes -->
@@ -1771,13 +1822,13 @@
<target name="build-jars-os-desktop-javase" depends="setup-manifestfile">
<jar manifest="${build.jogl}/manifest.mf" destfile="${jogl-os-x11.jar}" filesonly="true">
- <fileset dir="${classes}" includes="${java.part.glx}"/>
+ <fileset dir="${classes}" includes="${java.part.x11.glx}"/>
</jar>
<jar manifest="${build.jogl}/manifest.mf" destfile="${jogl-os-win.jar}" filesonly="true">
- <fileset dir="${classes}" includes="${java.part.wgl}" />
+ <fileset dir="${classes}" includes="${java.part.win.wgl}" />
</jar>
<jar manifest="${build.jogl}/manifest.mf" destfile="${jogl-os-osx.jar}" filesonly="true">
- <fileset dir="${classes}" includes="${java.part.cgl}"/>
+ <fileset dir="${classes}" includes="${java.part.osx.cgl}"/>
</jar>
</target>
@@ -1788,6 +1839,9 @@
</target>
<target name="build-jars-mobile-javase" depends="setup-manifestfile">
+ <jar manifest="${build.jogl}/manifest.mf" destfile="${jogl-os-ios.jar}" filesonly="true">
+ <fileset dir="${classes}" includes="${java.part.ios.eagl}"/>
+ </jar>
<jar manifest="${build.jogl}/manifest.mf" destfile="${jogl-glmobile.jar}" filesonly="true">
<fileset dir="${classes}"
includes="${java.part.egl} ${java.part.es1} ${java.part.es2es3}"
diff --git a/make/build-nativewindow.xml b/make/build-nativewindow.xml
index d13ca09b8..1f40f3535 100644
--- a/make/build-nativewindow.xml
+++ b/make/build-nativewindow.xml
@@ -81,10 +81,12 @@
<property name="java.part.macosx"
value="com/jogamp/nativewindow/macosx/* jogamp/nativewindow/macosx/*" />
+ <property name="java.part.ios"
+ value="com/jogamp/nativewindow/ios/* jogamp/nativewindow/ios/*" />
+
<!-- condition excludes -->
- <condition property="java.excludes.awt"
- value="${java.part.awt}">
+ <condition property="java.excludes.awt" value="${java.part.awt}">
<isset property="setup.noAWT"/>
</condition>
@@ -170,6 +172,7 @@
<mkdir dir="${src.generated.java}" />
<mkdir dir="${src.generated.c}" />
<mkdir dir="${src.generated.c}/MacOSX" />
+ <mkdir dir="${src.generated.c}/iOS" />
<mkdir dir="${src.generated.c}/Windows" />
<mkdir dir="${src.generated.c}/X11" />
<mkdir dir="${classes}" />
@@ -235,7 +238,8 @@
</gluegen>
</target>
- <target name="java.generate.jawt" unless="setup.noAWT">
+ <!-- target name="java.generate.jawt" unless="setup.noAWT" -->
+ <target name="java.generate.jawt" if="jawt.cfg" unless="setup.noAWT">
<!-- NOTE: the "literalInclude" in this GlueGen call is simply to
- get around the fact that neither FileSet nor DirSet can
- handle different drives in an effective manner. -->
@@ -259,6 +263,7 @@
<dirset id="stub.includes.fileset.platform" dir="." includes="${stub.includes}/${window.os.system}/** ${stub.includes.gluegen}/gluegen/** ${stub.includes}/khr/**" />
<antcall target="java.generate.windowlib" inheritRefs="true" />
<antcall target="java.generate.jawt" inheritRefs="true" />
+ <antcall target="java.generate.copy2temp" inheritRefs="true" />
</target>
<!--
@@ -298,6 +303,14 @@
<param name="jni.platform.sub" value="macosx" />
</antcall>
+ <echo message="Generating platform-specifics: iOS (nop)" /> <!-- actually nothing gets generated -->
+ <antcall target="java.generate.platforms" inheritRefs="true">
+ <param name="window.os.system" value="ios"/>
+ <!-- param name="jawt.cfg" value="${config.nativewindow}/jawt-ios.cfg" / --> <!-- n/a -->
+ <!-- param name="jawt.platform.header" value="${stub.includes.gluegen}/jni/ios/jawt_md.h" / --> <!-- n/a -->
+ <!-- param name="jni.platform.sub" value="ios" / --> <!-- n/a -->
+ </antcall>
+
<!-- Inform the user that the generators have successfully created
- the necessary Java files -->
<echo message="" />
@@ -371,6 +384,14 @@
<compiler id="compiler.cfg.macosx.nativewindow" extends="compiler.cfg.macosx">
</compiler>
+ <compiler id="compiler.cfg.ios.amd64.nativewindow" extends="compiler.cfg.ios.amd64">
+ <!-- compilerarg value="-v" / -->
+ </compiler>
+
+ <compiler id="compiler.cfg.ios.arm64.nativewindow" extends="compiler.cfg.ios.arm64">
+ <!-- compilerarg value="-v" / -->
+ </compiler>
+
<!-- linker configuration -->
<linker id="linker.cfg.freebsd.nativewindow.x11" extends="linker.cfg.freebsd">
@@ -461,6 +482,26 @@
<linkerarg value="Cocoa" />
</linker>
+ <linker id="linker.cfg.ios.amd64.nativewindow" extends="linker.cfg.ios.amd64">
+ <!-- linkerarg value="-v" / -->
+ <linkerarg value="-weak_framework" />
+ <linkerarg value="UIKit" />
+ <linkerarg value="-weak_framework" />
+ <linkerarg value="QuartzCore" />
+ <linkerarg value="-weak_framework" />
+ <linkerarg value="OpenGLES" /> <!-- hack to inject CAEAGLLayer.self into UIView's layerClass -->
+ </linker>
+
+ <linker id="linker.cfg.ios.arm64.nativewindow" extends="linker.cfg.ios.arm64">
+ <!-- linkerarg value="-v" / -->
+ <linkerarg value="-weak_framework" />
+ <linkerarg value="UIKit" />
+ <linkerarg value="-weak_framework" />
+ <linkerarg value="QuartzCore" />
+ <linkerarg value="-weak_framework" />
+ <linkerarg value="OpenGLES" /> <!-- hack to inject CAEAGLLayer.self into UIView's layerClass -->
+ </linker>
+
<linker id="linker.cfg.hpux.nativewindow" extends="linker.cfg.hpux">
<syslibset dir="/usr/lib" libs="X11"/>
<syslibset dir="/usr/lib" libs="Xrender"/>
@@ -608,7 +649,17 @@
<property name="linker.cfg.id.oswin" value="linker.cfg.macosx.nativewindow" />
</target>
- <target name="c.configure.2" depends="c.configure.win32,c.configure.linux,c.configure.android,c.configure.solaris32,c.configure.solaris.sparcv9,c.configure.solaris.amd64,c.configure.macosx,c.configure.freebsd,c.configure.hpux" />
+ <target name="c.configure.ios.amd64" if="isIOSAmd64">
+ <property name="compiler.cfg.id" value="compiler.cfg.ios.amd64.nativewindow" />
+ <property name="linker.cfg.id.oswin" value="linker.cfg.ios.amd64.nativewindow" />
+ </target>
+
+ <target name="c.configure.ios.arm64" if="isIOSArm64">
+ <property name="compiler.cfg.id" value="compiler.cfg.ios.arm64.nativewindow" />
+ <property name="linker.cfg.id.oswin" value="linker.cfg.ios.arm64.nativewindow" />
+ </target>
+
+ <target name="c.configure.2" depends="c.configure.win32,c.configure.linux,c.configure.android,c.configure.solaris32,c.configure.solaris.sparcv9,c.configure.solaris.amd64,c.configure.macosx,c.configure.ios.amd64,c.configure.ios.arm64,c.configure.freebsd,c.configure.hpux" />
<target name="c.configure" depends="c.configure.1,c.configure.2" />
@@ -658,6 +709,7 @@
<include name="${rootrel.src.c}/x11/Xmisc.c"/>
<include name="${rootrel.src.c}/x11/XineramaHelper.c"/>
<include name="${rootrel.src.c}/NativewindowCommon.c"/>
+ <include name="${rootrel.src.c}/JVM_JNI8.c"/>
</patternset>
<patternset id="c.src.files.windows">
@@ -665,11 +717,20 @@
<include name="${rootrel.src.c}/win32/GDImisc.c"/>
<include name="${rootrel.src.c}/win32/WindowsDWM.c"/>
<include name="${rootrel.src.c}/NativewindowCommon.c"/>
+ <include name="${rootrel.src.c}/JVM_JNI8.c"/>
</patternset>
<patternset id="c.src.files.macosx">
<include name="${rootrel.src.c}/macosx/OSXmisc.m"/>
<include name="${rootrel.src.c}/NativewindowCommon.c"/>
+ <include name="${rootrel.src.c}/JVM_JNI8.c"/>
+ </patternset>
+
+ <patternset id="c.src.files.ios">
+ <include name="${rootrel.src.c}/ios/CAEAGLLayered.m"/>
+ <include name="${rootrel.src.c}/ios/IOSmisc.m"/>
+ <include name="${rootrel.src.c}/NativewindowCommon.c"/>
+ <include name="${rootrel.src.c}/JVM_JNI8.c"/>
</patternset>
<echo message="Compiling @{output.lib.name}" />
@@ -682,12 +743,11 @@
<fileset dir="${project.root}"><patternset refid="@{c.compiler.src.files}"/></fileset>
</sourcefiles>
<targetfiles>
- <fileset dir="${obj.nativewindow}" includes="lib@{output.lib.name}.so"/>
- <fileset dir="${obj.nativewindow}" includes="@{output.lib.name}.dll"/>
- <fileset dir="${obj.nativewindow}" includes="lib@{output.lib.name}.dylib"/>
+ <fileset dir="${obj.nativewindow}" includes="${native.library.prefix}@{output.lib.name}.${native.library.suffix}"/>
</targetfiles>
<sequential>
- <cc outtype="shared"
+ <cc outtype="${output.lib.type}"
+ usehighleveltool="true"
objdir="${obj.nativewindow}"
outfile="${obj.nativewindow}/@{output.lib.name}"
optimize="${c.compiler.optimise}"
@@ -706,10 +766,12 @@
<includepath path="${src.generated.c}" />
<includepath path="${src.generated.c}/X11" if="isX11"/>
<includepath path="${src.generated.c}/MacOSX" if="isOSX"/>
+ <includepath path="${src.generated.c}/iOS" if="isIOS"/>
<includepath path="stub_includes/win32" if="isWindows"/>
<includepath path="${src.generated.c}/Windows" if="isWindows"/>
<includepath path="${src.c}/x11" if="isX11"/>
<includepath path="${src.c}/macosx" if="isOSX"/>
+ <includepath path="${src.c}/ios" if="isIOS"/>
<includepath path="${src.c}/win32" if="isWindows"/>
<includepath path="${src.c}"/>
@@ -730,6 +792,10 @@
<param name="dest" value="${obj.nativewindow}/@{output.lib.name}.dll" />
</antcall>
+ <gluegen.make.libsymbols builddir="${build}"
+ nativelib="${obj.nativewindow}/${native.library.prefix}@{output.lib.name}.${native.library.suffix}"
+ symbolsfile="${obj.nativewindow}/${native.library.prefix}@{output.lib.name}.symbols"/>
+
<!-- this stripping may be called more than once on the same library dir,
but that should cause no harm, and doing it here inside outofdate
prevents the JARs from always being rebuilt even if no source code changes -->
@@ -777,7 +843,16 @@
linker.cfg.id="${linker.cfg.id.oswin}"/>
</target>
- <target name="c.build.nativewindow.windowlib" depends="c.build.nativewindow.windowlib.x11, c.build.nativewindow.windowlib.windows, c.build.nativewindow.windowlib.macosx"/>
+ <target name="c.build.nativewindow.windowlib.ios" if="isIOS">
+ <javah destdir="${src.generated.c}/iOS" classpath="${javah.classpath}" class="jogamp.nativewindow.ios.IOSUtil" />
+
+ <c.build c.compiler.src.files="c.src.files.ios"
+ output.lib.name="nativewindow_ios"
+ compiler.cfg.id="${compiler.cfg.id}"
+ linker.cfg.id="${linker.cfg.id.oswin}"/>
+ </target>
+
+ <target name="c.build.nativewindow.windowlib" depends="c.build.nativewindow.windowlib.x11, c.build.nativewindow.windowlib.windows, c.build.nativewindow.windowlib.macosx, c.build.nativewindow.windowlib.ios"/>
<target name="c.manifest" if="isVC8Family">
<!-- exec mt, the Microsoft Manifest Tool, to include DLL manifests in order to resolve the location of msvcr80.dll -->
@@ -852,7 +927,14 @@
</jar>
</target>
- <target name="build-jars-javase" depends="setup-manifestfile,build-jars-awt,build-jars-x11,build-jars-windows,build-jars-macosx">
+ <target name="build-jars-ios" depends="setup-manifestfile">
+ <jar manifest="${build.nativewindow}/manifest.mf" destfile="${nativewindow-os-ios.jar}" filesonly="true">
+ <fileset dir="${classes}"
+ includes="${java.part.ios}" />
+ </jar>
+ </target>
+
+ <target name="build-jars-javase" depends="setup-manifestfile,build-jars-awt,build-jars-x11,build-jars-windows,build-jars-macosx,build-jars-ios">
<jar manifest="${build.nativewindow}/manifest.mf" destfile="${nativewindow.jar}" filesonly="true">
<fileset dir="${classes}"
includes="${java.part.core}"
diff --git a/make/build-newt.xml b/make/build-newt.xml
index d0dfdcf32..6c2defaca 100644
--- a/make/build-newt.xml
+++ b/make/build-newt.xml
@@ -79,6 +79,7 @@
<and>
<isfalse value="${isWindows}" />
<isfalse value="${isOSX}" />
+ <isfalse value="${isIOS}" />
<isfalse value="${isX11}" />
<isfalse value="${isAndroid}" />
<isfalse value="${setup.addNativeKD}" />
@@ -90,6 +91,7 @@
<echo message="setup.noOpenGL: ${setup.noOpenGL}" />
<echo message="isWindows: ${isWindows}" />
<echo message="isOSX: ${isOSX}" />
+ <echo message="isIOS: ${isIOS}" />
<echo message="isX11: ${isX11}" />
<echo message="isAndroid: ${isAndroid}" />
<echo message="setup.addNativeKD: ${setup.addNativeKD}" />
@@ -132,6 +134,9 @@
<property name="java.part.driver.macosx"
value="jogamp/newt/driver/macosx/**"/>
+ <property name="java.part.driver.ios"
+ value="jogamp/newt/driver/ios/**"/>
+
<property name="java.part.driver.kd"
value="jogamp/newt/driver/kd/**"/>
@@ -226,6 +231,7 @@
<mkdir dir="${src.generated.c}/Android" />
<mkdir dir="${src.generated.c}/X11" />
<mkdir dir="${src.generated.c}/MacOSX" />
+ <mkdir dir="${src.generated.c}/iOS" />
<mkdir dir="${src.generated.c}/Windows" />
<mkdir dir="${src.generated.c}/KD" />
<mkdir dir="${src.generated.c}/IntelGDL" />
@@ -418,6 +424,26 @@
<linkerarg value="Cocoa" />
</linker>
+ <linker id="linker.cfg.ios.amd64.newt" extends="linker.cfg.ios.amd64">
+ <!-- linkerarg value="-v" / -->
+ <linkerarg value="-weak_framework" />
+ <linkerarg value="UIKit" />
+ <linkerarg value="-weak_framework" />
+ <linkerarg value="QuartzCore" />
+ <linkerarg value="-weak_framework" />
+ <linkerarg value="OpenGLES" /> <!-- hack to get the CAEAGL in .. -->
+ </linker>
+
+ <linker id="linker.cfg.ios.arm64.newt" extends="linker.cfg.ios.arm64">
+ <!-- linkerarg value="-v" / -->
+ <linkerarg value="-weak_framework" />
+ <linkerarg value="UIKit" />
+ <linkerarg value="-weak_framework" />
+ <linkerarg value="QuartzCore" />
+ <linkerarg value="-weak_framework" />
+ <linkerarg value="OpenGLES" /> <!-- hack to get the CAEAGL in .. -->
+ </linker>
+
<linker id="linker.cfg.hpux.newt" extends="linker.cfg.hpux">
<syslibset dir="/usr/lib" libs="X11"/>
</linker>
@@ -612,7 +638,17 @@
<property name="linker.cfg.id.oswin" value="linker.cfg.macosx.newt" />
</target>
- <target name="c.configure.2" depends="c.configure.win32,c.configure.linux,c.configure.android,c.configure.solaris32,c.configure.solaris.sparcv9,c.configure.solaris.amd64,c.configure.macosx,c.configure.freebsd,c.configure.hpux" />
+ <target name="c.configure.ios.amd64" if="isIOSAmd64">
+ <property name="compiler.cfg.id" value="compiler.cfg.ios.amd64" />
+ <property name="linker.cfg.id.oswin" value="linker.cfg.ios.amd64.newt" />
+ </target>
+
+ <target name="c.configure.ios.arm64" if="isIOSArm64">
+ <property name="compiler.cfg.id" value="compiler.cfg.ios.arm64" />
+ <property name="linker.cfg.id.oswin" value="linker.cfg.ios.arm64.newt" />
+ </target>
+
+ <target name="c.configure.2" depends="c.configure.win32,c.configure.linux,c.configure.android,c.configure.solaris32,c.configure.solaris.sparcv9,c.configure.solaris.amd64,c.configure.macosx,c.configure.ios.amd64,c.configure.ios.arm64,c.configure.freebsd,c.configure.hpux" />
<target name="c.configure" depends="c.configure.1,c.configure.2" />
@@ -637,12 +673,15 @@
<condition property="c.compiler.use-debug"><istrue value="${c.compiler.debug}"/></condition>
<patternset id="c.src.files.newt">
+ <include name="${rootrel.src.c}/JVM_JNI8.c" />
<include name="${rootrel.src.c}/NewtCommon.c" />
<!-- include name="${rootrel.src.c}/timespec.c" /--> <!-- currently used for X11 and OSX with special PERF DEBUG MODE-->
<include name="${rootrel.src.c}/WindowsWindow.c" if="isWindows"/>
<include name="${rootrel.src.c}/WindowsEDID.c" if="isWindows"/>
<include name="${rootrel.src.c}/MacWindow.m" if="isOSX"/>
<include name="${rootrel.src.c}/NewtMacWindow.m" if="isOSX"/>
+ <include name="${rootrel.src.c}/IOSUIWindow.m" if="isIOS"/>
+ <include name="${rootrel.src.c}/IOSNewtUIWindow.m" if="isIOS"/>
<include name="${rootrel.src.c}/AndroidWindow.c" if="isAndroid"/>
<include name="${rootrel.src.c}/X11Display.c" if="isX11"/>
<!-- include name="${rootrel.src.c}/X11Event.c" if="isX11"/-->
@@ -666,12 +705,11 @@
<fileset dir="${project.root}"><patternset refid="@{c.compiler.src.files}"/></fileset>
</sourcefiles>
<targetfiles>
- <fileset dir="${obj.newt}" includes="lib@{output.lib.name}.so"/>
- <fileset dir="${obj.newt}" includes="@{output.lib.name}.dll"/>
- <fileset dir="${obj.newt}" includes="lib@{output.lib.name}.dylib"/>
+ <fileset dir="${obj.newt}" includes="${native.library.prefix}@{output.lib.name}.${native.library.suffix}"/>
</targetfiles>
<sequential>
- <cc outtype="shared"
+ <cc outtype="${output.lib.type}"
+ usehighleveltool="true"
objdir="${obj.newt}"
outfile="${obj.newt}/@{output.lib.name}"
optimize="${c.compiler.optimise}"
@@ -695,6 +733,7 @@
<includepath path="${src.generated.c}/Android" if="isAndroid"/>
<includepath path="${src.generated.c}/X11" if="isX11"/>
<includepath path="${src.generated.c}/MacOSX" if="isOSX"/>
+ <includepath path="${src.generated.c}/iOS" if="isIOS"/>
<includepath path="${src.generated.c}/Windows" if="isWindows"/>
<includepath path="${src.generated.c}/KD" if="setup.addNativeKD" />
<includepath path="${src.generated.c}/IntelGDL" if="setup.addNativeIntelGDL" />
@@ -719,6 +758,10 @@
<param name="dest" value="${obj.newt}/@{output.lib.name}.dll" />
</antcall>
+ <gluegen.make.libsymbols builddir="${build}"
+ nativelib="${obj.newt}/${native.library.prefix}@{output.lib.name}.${native.library.suffix}"
+ symbolsfile="${obj.newt}/${native.library.prefix}@{output.lib.name}.symbols"/>
+
<!-- this stripping may be called more than once on the same library dir,
but that should cause no harm, and doing it here inside outofdate
prevents the JARs from always being rebuilt even if no source code changes -->
@@ -741,6 +784,7 @@
<javah destdir="${src.generated.c}/Windows" classpath="${javah.classpath}" class="jogamp.newt.driver.windows.WindowDriver, jogamp.newt.driver.windows.ScreenDriver, jogamp.newt.driver.windows.DisplayDriver" />
<javah destdir="${src.generated.c}/MacOSX" classpath="${javah.classpath}" class="jogamp.newt.driver.macosx.WindowDriver, jogamp.newt.driver.macosx.ScreenDriver, jogamp.newt.driver.macosx.DisplayDriver" />
+ <javah destdir="${src.generated.c}/iOS" classpath="${javah.classpath}" class="jogamp.newt.driver.ios.WindowDriver, jogamp.newt.driver.ios.ScreenDriver, jogamp.newt.driver.ios.DisplayDriver" />
<javah destdir="${src.generated.c}/X11" classpath="${javah.classpath}" class="jogamp.newt.driver.x11.WindowDriver, jogamp.newt.driver.x11.ScreenDriver, jogamp.newt.driver.x11.RandR11, jogamp.newt.driver.x11.RandR13, jogamp.newt.driver.x11.DisplayDriver" />
</target>
@@ -844,6 +888,10 @@
<fileset dir="${classes}"
includes="${java.part.driver.macosx}"/>
</jar>
+ <jar manifest="${build.newt}/manifest.mf" destfile="${newt-driver-ios.jar}" filesonly="true">
+ <fileset dir="${classes}"
+ includes="${java.part.driver.ios}"/>
+ </jar>
<jar manifest="${build.newt}/manifest.mf" destfile="${newt-driver-kd.jar}" filesonly="true">
<fileset dir="${classes}"
includes="${java.part.driver.kd}"/>
diff --git a/make/build-test.xml b/make/build-test.xml
index eed264e6b..547a0d8d1 100644
--- a/make/build-test.xml
+++ b/make/build-test.xml
@@ -22,11 +22,13 @@
<target name="declare.common" description="Declare properties" depends="common.init">
<property name="rootrel.src.test" value="src/test" />
<property name="src.test" value="${project.root}/${rootrel.src.test}" />
+ <property name="src.demos" value="${project.root}/src/demos" />
<property name="classes" value="${build.test}/classes" />
<property name="classes.path" location="${classes}"/> <!-- absolute path -->
+ <property name="classes.demos" value="${build.demos}/classes" />
- <property name="java.part.test.all" value="com/jogamp/** jogamp/**"/>
+ <property name="java.part.demo.mobile" value="com/jogamp/opengl/demos/demos/**"/>
<property name="java.part.test.android" value="com/jogamp/opengl/test/android/**"/>
<property name="java.part.test.oculusvr" value="com/jogamp/opengl/test/junit/jogl/stereo/ovr/**"/>
<property name="java.dir.test" value="com/jogamp/opengl/test"/>
@@ -49,6 +51,7 @@
<target name="clean" description="Remove all build products" depends="declare.common">
<delete includeEmptyDirs="true" quiet="true">
<fileset dir="${build.test}" />
+ <fileset dir="${build.demos}" />
<fileset dir="." includes="*.ps" />
<fileset dir="." includes="*.pdf" />
<fileset dir="." includes="*.png" />
@@ -56,6 +59,7 @@
<fileset dir="." includes="*.tga" />
<fileset dir="." includes="hs_err_pid*.log" />
<fileset file="${jogl-test.jar}" />
+ <fileset file="${jogl-demos-mobile.jar}" />
</delete>
</target>
@@ -64,7 +68,44 @@
- Build/run tests/junit.
-->
- <target name="test.compile.javase.generic">
+ <target name="make.demos.mobile">
+ <javac destdir="${classes.demos}"
+ fork="yes"
+ includeAntRuntime="false"
+ memoryMaximumSize="${javac.memorymax}"
+ encoding="UTF-8"
+ source="${target.sourcelevel}"
+ target="${target.targetlevel}"
+ bootclasspath="${target.rt.jar}"
+ debug="${javacdebug}" debuglevel="${javacdebuglevel}">
+ <classpath refid="junit_jogl_newt.compile.classpath"/>
+ <src path="${src.demos}" />
+ </javac>
+ <copy file="joglversion-test"
+ tofile="${build.test}/manifest-demo-mobile.mf"
+ overwrite="true">
+ <filterset>
+ <filter token="VERSION" value="${jogamp.version}"/>
+ <filter token="BUILD_VERSION" value="${jogl.version}"/>
+ <filter token="SCM_BRANCH" value="${jogl.build.branch}"/>
+ <filter token="SCM_COMMIT" value="${jogl.build.commit}"/>
+ <filter token="BASEVERSION" value="${jogamp.version.base}"/>
+ <filter token="JAR_CODEBASE_TAG" value="${jogamp.jar.codebase}"/>
+ </filterset>
+ </copy>
+ <!-- include any resource files that tests may require -->
+ <copy todir="${classes.demos}">
+ <fileset dir="${src.demos}">
+ <exclude name="**/*.java"/>
+ </fileset>
+ </copy>
+ <jar manifest="${build.test}/manifest-demo-mobile.mf" destfile="${jogl-demos-mobile.jar}" filesonly="true">
+ <fileset dir="${classes.demos}"
+ includes="**"/>
+ <fileset dir="resources/assets-test" includes="**" />
+ </jar>
+ </target>
+ <target name="test.compile.javase.generic" unless="setup.noAWT">
<javac destdir="${classes}"
excludes="${java.part.test.android} ${java.part.test.oculusvr}"
fork="yes"
@@ -95,7 +136,7 @@
<src path="${src.test}" />
</javac>
</target>
- <target name="test.compile.javase" depends="test.compile.javase.generic, test.compile.javase.oculusvr">
+ <target name="test.compile.javase" depends="test.compile.javase.generic, test.compile.javase.oculusvr" unless="setup.noAWT">
<copy file="joglversion-test"
tofile="${build.test}/manifest-test.mf"
overwrite="true">
@@ -120,7 +161,7 @@
</jar>
</target>
- <target name="test.compile.android" if="android-jars.available">
+ <target name="test.compile.android" if="android-jars.available" unless="setup.noAWT">
<!-- Perform the junit pass Java Android compile -->
<javac destdir="${classes}"
excludes="${java.part.test.oculusvr}"
@@ -157,7 +198,7 @@
</jar>
</target>
- <target name="test.package.android" depends="test.compile.android" if="isAndroid">
+ <target name="test.package.android" depends="test.compile.android" if="isAndroid" unless="setup.noAWT">
<aapt.signed
assetsdir="resources/assets-test"
jarsrcdir="${src}/test"
@@ -176,6 +217,7 @@
<!-- Create the required output directories. -->
<mkdir dir="${obj.test}" />
<mkdir dir="${classes}" />
+ <mkdir dir="${classes.demos}" />
<property name="jogl-test.jar.path" location="${jogl-test.jar}"/> <!-- absolute path -->
<echo message="jogl-test.jar ${jogl-test.jar.path}"/>
@@ -198,6 +240,7 @@
<exclude name="**/*.java"/>
</fileset>
</copy>
+ <antcall target="make.demos.mobile" inheritRefs="true" inheritAll="true"/>
<antcall target="test.compile.javase" inheritRefs="true" inheritAll="true"/>
<antcall target="test.package.android" inheritRefs="true" inheritAll="true"/>
</target>
diff --git a/make/build.xml b/make/build.xml
index 14c1a3c09..876d8be60 100644
--- a/make/build.xml
+++ b/make/build.xml
@@ -20,15 +20,15 @@
<ant antfile="build-test.xml" target="test.compile" inheritRefs="true" inheritAll="true"/>
</target>
- <target name="test.auto.run" description="Run automated tests (junit and others) in nativewindow, jogl and newt projects">
+ <target name="test.auto.run" description="Run automated tests (junit and others) in nativewindow, jogl and newt projects" if="${build.dynamiclibs}">
<ant antfile="build-test.xml" target="test.auto.run" inheritRefs="true" inheritAll="true"/>
</target>
- <target name="junit.run" description="Run automated junit tests in nativewindow, jogl and newt projects">
+ <target name="junit.run" description="Run automated junit tests in nativewindow, jogl and newt projects" if="${build.dynamiclibs}">
<ant antfile="build-test.xml" target="junit.run" inheritRefs="true" inheritAll="true"/>
</target>
- <target name="test.manual.run" description="Run manual operated tests in nativewindow, jogl and newt projects">
+ <target name="test.manual.run" description="Run manual operated tests in nativewindow, jogl and newt projects" if="${build.dynamiclibs}">
<ant antfile="build-test.xml" target="test.manual.run" inheritRefs="true" inheritAll="true"/>
</target>
@@ -53,6 +53,7 @@
<ant antfile="build-test.xml" target="clean" inheritRefs="true" inheritAll="true"/>
<delete includeEmptyDirs="true" quiet="true" failonerror="false">
<fileset dir="${build}" />
+ <fileset dir="${project.root}/build-temp" />
<fileset dir="." includes="*.tga" />
</delete>
<delete includeEmptyDirs="true" quiet="true" dir="${jar}" failonerror="false" />
@@ -141,7 +142,7 @@
</jar>
</target>
- <target name="one.jar.dir" depends="one.jar.dir.prep,one.jar.dir.android" unless="one.dir.skip">
+ <target name="one.jar.dir.awt" unless="setup.noAWT">
<jar manifest="${build}/manifest-all.mf" destfile="${jogl-all.jar}" filesonly="true" excludes="META-INF/*">
<archives>
<zips>
@@ -152,6 +153,9 @@
</zips>
</archives>
</jar>
+ </target>
+ <target name="one.jar.dir" depends="one.jar.dir.prep,one.jar.dir.android" unless="one.dir.skip">
+ <antcall target="one.jar.dir.awt" inheritRefs="true" inheritAll="true"/>
<jar manifest="${build}/manifest-all.mf" destfile="${jogl-all-noawt.jar}" filesonly="true" excludes="META-INF/*">
<archives>
<zips>
@@ -259,7 +263,7 @@
- This must be called after all of the build targets complete.
-->
- <target name="developer-src-zip" depends="init">
+ <target name="developer-src-zip" depends="init" if="build.archiveon">
<!--delete includeEmptyDirs="true" quiet="true" failonerror="false">
<fileset dir="${build}" includes="jogl-java-src.zip" />
</delete-->
diff --git a/make/config/jogl/eagl-ios.cfg b/make/config/jogl/eagl-ios.cfg
new file mode 100644
index 000000000..2714cb6a3
--- /dev/null
+++ b/make/config/jogl/eagl-ios.cfg
@@ -0,0 +1,43 @@
+# This .cfg file is used to generate the interface to the CGL routines
+# used internally by the MacOSXGLContext implementation.
+JavaOutputDir gensrc/classes
+NativeOutputDir gensrc/native/jogl/iOS
+
+# For easier debugging of GLSemHeader, i.e. less debug output
+#DropAllGLDocHeader true
+
+Package jogamp.opengl.ios.eagl
+JavaClass EAGL
+Style AllStatic
+Include gl-common.cfg
+Include gl-common-extensions.cfg
+Include gl-desktop.cfg
+
+# Only NIO direct function, no arrays ..
+NIOOnly __ALL__
+NIODirectOnly __ALL__
+
+GLSemHeader OpenGLES/EAGL.h
+
+Opaque long void *
+
+# Opaque directives for low-level CGL binding (for Java2D/JOGL bridge)
+Opaque long EAGLContext *
+Opaque long EAGLSharegroup *
+Opaque long EAGLDrawable *
+
+Opaque long CALayer *
+Opaque long CAEAGLLayer *
+Opaque long UIView *
+
+CustomCCode #include <machine/types.h>
+CustomCCode #include "ios-window-system.h"
+
+#IncludeAs CustomJavaCode EAGL eagl-ios-CustomJavaCode.java
+
+# Implement the first argument to getProcAddress as String instead
+# of byte[]
+ArgumentIsString getProcAddress 0
+
+Import com.jogamp.common.util.Function
+Import jogamp.nativewindow.ios.IOSUtil
diff --git a/make/scripts/make.jogl.all.ios.amd64.sh b/make/scripts/make.jogl.all.ios.amd64.sh
new file mode 100755
index 000000000..8ea91b984
--- /dev/null
+++ b/make/scripts/make.jogl.all.ios.amd64.sh
@@ -0,0 +1,35 @@
+#! /bin/sh
+
+if [ -e /opt-share/etc/profile.ant ] ; then
+ . /opt-share/etc/profile.ant
+fi
+
+# -Dc.compiler.debug=true
+#
+# -Dtarget.sourcelevel=1.6 \
+# -Dtarget.targetlevel=1.6 \
+# -Dtarget.rt.jar=/opt-share/jre1.6.0_30/lib/rt.jar \
+
+# Force OSX SDK 10.6, if desired
+# export SDKROOT=macosx10.6
+
+export SDKROOT=iphonesimulator12.2
+xcrun --show-sdk-path
+
+JAVA_HOME=`/usr/libexec/java_home -version 1.8`
+PATH=$JAVA_HOME/bin:$PATH
+export JAVA_HOME PATH
+which java
+java -version
+
+export SOURCE_LEVEL=1.6
+export TARGET_LEVEL=1.6
+export TARGET_RT_JAR=/opt-share/jre1.6.0_30/lib/rt.jar
+
+#export JOGAMP_JAR_CODEBASE="Codebase: *.jogamp.org"
+export JOGAMP_JAR_CODEBASE="Codebase: *.goethel.localnet"
+
+ant \
+ -Drootrel.build=build-ios-amd64 \
+ -DisIOSAmd64=true \
+ $* 2>&1 | tee make.jogl.all.ios-amd64.log
diff --git a/make/scripts/make.jogl.all.ios.arm64.sh b/make/scripts/make.jogl.all.ios.arm64.sh
new file mode 100755
index 000000000..8a101adf2
--- /dev/null
+++ b/make/scripts/make.jogl.all.ios.arm64.sh
@@ -0,0 +1,35 @@
+#! /bin/sh
+
+if [ -e /opt-share/etc/profile.ant ] ; then
+ . /opt-share/etc/profile.ant
+fi
+
+# -Dc.compiler.debug=true
+#
+# -Dtarget.sourcelevel=1.6 \
+# -Dtarget.targetlevel=1.6 \
+# -Dtarget.rt.jar=/opt-share/jre1.6.0_30/lib/rt.jar \
+
+# Force OSX SDK 10.6, if desired
+# export SDKROOT=macosx10.6
+
+export SDKROOT=iphoneos12.2
+xcrun --show-sdk-path
+
+JAVA_HOME=`/usr/libexec/java_home -version 1.8`
+PATH=$JAVA_HOME/bin:$PATH
+export JAVA_HOME PATH
+which java
+java -version
+
+export SOURCE_LEVEL=1.6
+export TARGET_LEVEL=1.6
+export TARGET_RT_JAR=/opt-share/jre1.6.0_30/lib/rt.jar
+
+#export JOGAMP_JAR_CODEBASE="Codebase: *.jogamp.org"
+export JOGAMP_JAR_CODEBASE="Codebase: *.goethel.localnet"
+
+ant \
+ -Drootrel.build=build-ios-arm64 \
+ -DisIOSArm64=true \
+ $* 2>&1 | tee make.jogl.all.ios-arm64.log
diff --git a/make/scripts/make.jogl.all.macosx.sh b/make/scripts/make.jogl.all.macosx.sh
index 94b7f13b3..d9db72045 100755
--- a/make/scripts/make.jogl.all.macosx.sh
+++ b/make/scripts/make.jogl.all.macosx.sh
@@ -7,8 +7,8 @@ fi
# Force OSX SDK 10.6, if desired
# export SDKROOT=macosx10.6
-JAVA_HOME=`/usr/libexec/java_home`
-#JAVA_HOME=`/usr/libexec/java_home -version 1.8`
+#JAVA_HOME=`/usr/libexec/java_home`
+JAVA_HOME=`/usr/libexec/java_home -version 1.8`
#JAVA_HOME=`/usr/libexec/java_home -version 1.7`
#JAVA_HOME=`/usr/libexec/java_home -version 1.6`
PATH=$JAVA_HOME/bin:$PATH
diff --git a/make/scripts/setenv-jogl.sh b/make/scripts/setenv-jogl.sh
index 79db4f9b1..cbc85760d 100755
--- a/make/scripts/setenv-jogl.sh
+++ b/make/scripts/setenv-jogl.sh
@@ -72,9 +72,7 @@ fi
JOAL_DIR=`dirname $joalpf`
JOAL_BUILDDIR="$JOAL_DIR"/"$JOGL_BUILDDIR_BASE"
if [ ! -e "$JOAL_BUILDDIR" ] ; then
- echo JOAL_BUILDDIR "$JOAL_BUILDDIR" does not exist
- print_usage
- exit
+ echo JOAL_BUILDDIR "$JOAL_BUILDDIR" does not exist \(warning\)
fi
JOAL_JAR="$JOAL_BUILDDIR"/jar/joal.jar
diff --git a/make/scripts/tests-osx-x64.sh b/make/scripts/tests-osx-x64.sh
index f0d8ffacf..949adc045 100755
--- a/make/scripts/tests-osx-x64.sh
+++ b/make/scripts/tests-osx-x64.sh
@@ -4,8 +4,8 @@
#export DYLD_LIBRARY_PATH=$HOME/ffmpeg-2.2.3/lib:$DYLD_LIBRARY_PATH
export DYLD_LIBRARY_PATH=/usr/local/Cellar/ffmpeg/2.8/lib:$DYLD_LIBRARY_PATH
-JAVA_HOME=`/usr/libexec/java_home`
-#JAVA_HOME=`/usr/libexec/java_home -version 1.8`
+#JAVA_HOME=`/usr/libexec/java_home`
+JAVA_HOME=`/usr/libexec/java_home -version 1.8`
#JAVA_HOME=`/usr/libexec/java_home -version 1.7`
#JAVA_HOME=`/usr/libexec/java_home -version 1.7.0_25`
#JAVA_HOME=`/usr/libexec/java_home -version 1.6.0`
diff --git a/make/scripts/tests-x64.sh b/make/scripts/tests-x64.sh
index 52216502f..e7301aef5 100755
--- a/make/scripts/tests-x64.sh
+++ b/make/scripts/tests-x64.sh
@@ -1,5 +1,7 @@
#! /bin/bash
+#set -x
+
SDIR=`dirname $0`
#export LD_LIBRARY_PATH=$HOME/libav-0.8/lib:$LD_LIBRARY_PATH
diff --git a/make/scripts/tests.sh b/make/scripts/tests.sh
index bad31647a..0342f7da3 100644
--- a/make/scripts/tests.sh
+++ b/make/scripts/tests.sh
@@ -5,6 +5,8 @@ if [ -z "$1" -o -z "$2" -o -z "$3" ] ; then
exit 0
fi
+#set -x
+
javaexe="$1"
shift
javaxargs=$1
@@ -97,6 +99,7 @@ function jrun() {
swton=$1
shift
+ D_ARGS="-Djogl.debug.GLProfile"
#D_ARGS="-Djogl.debug.DebugGL"
#D_ARGS="-Djogl.debug.TraceGL"
#D_ARGS="-Djogl.debug.DebugGL -Djogl.debug.TraceGL"
@@ -435,7 +438,7 @@ function testawtswt() {
#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLVersionParsing00NEWT $*
#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestMainVersionGLWindowNEWT $*
#testawt com.jogamp.opengl.test.junit.jogl.acore.TestMainVersionGLCanvasAWT $*
-#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.TestGLProfile02NEWTNoARBCtx $*
#testnoawt com.jogamp.opengl.test.junit.jogl.acore.TestGLProfile03NEWTOffscreen $*
@@ -754,7 +757,7 @@ function testawtswt() {
#testawt com.jogamp.opengl.test.bugs.Bug735Inv2AppletAWT $*
#testawt com.jogamp.opengl.test.bugs.Bug735Inv3AppletAWT $*
#testawt com.jogamp.opengl.test.bugs.Bug735Inv4AWT $*
-
+#
#
# SWT (testswt)
#
@@ -762,7 +765,7 @@ function testawtswt() {
#testswt com.jogamp.opengl.test.junit.jogl.swt.TestSWTAccessor02NewtGLWindow $*
#testswt com.jogamp.opengl.test.junit.jogl.swt.TestNewtCanvasSWTGLn $*
#testswt com.jogamp.opengl.test.junit.jogl.swt.TestSWTJOGLGLCanvas01GLn $*
-testswt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NewtCanvasSWT $*
+#testswt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NewtCanvasSWT $*
#testswt com.jogamp.opengl.test.junit.jogl.demos.es2.swt.TestGearsES2SWT $*
#testswt com.jogamp.opengl.test.junit.jogl.swt.TestSWTEclipseGLCanvas01GLn $*
#testswt com.jogamp.opengl.test.junit.jogl.swt.TestBug672NewtCanvasSWTSashForm $*
diff --git a/make/stub_includes/ios/OpenGLES/EAGL.h b/make/stub_includes/ios/OpenGLES/EAGL.h
new file mode 100644
index 000000000..050843a99
--- /dev/null
+++ b/make/stub_includes/ios/OpenGLES/EAGL.h
@@ -0,0 +1,13 @@
+typedef struct _EAGLContext EAGLContext;
+typedef struct _EAGLSharegroup EAGLSharegroup;
+typedef struct _EAGLDrawable EAGLDrawable;
+
+typedef enum _EAGLRenderingAPI
+{
+ kEAGLRenderingAPIOpenGLES1 = 1,
+ kEAGLRenderingAPIOpenGLES2 = 2,
+ kEAGLRenderingAPIOpenGLES3 = 3,
+} EAGLRenderingAPI;
+
+void EAGLGetVersion(unsigned int* major, unsigned int* minor);
+
diff --git a/make/stub_includes/ios/OpenGLES/EAGLDrawable.h b/make/stub_includes/ios/OpenGLES/EAGLDrawable.h
new file mode 100644
index 000000000..6282c155e
--- /dev/null
+++ b/make/stub_includes/ios/OpenGLES/EAGLDrawable.h
@@ -0,0 +1,2 @@
+typedef struct _EAGLDrawable EAGLDrawable;
+
diff --git a/make/stub_includes/ios/QuartzCore/CAEAGLLayer.h b/make/stub_includes/ios/QuartzCore/CAEAGLLayer.h
new file mode 100644
index 000000000..67f2a53c4
--- /dev/null
+++ b/make/stub_includes/ios/QuartzCore/CAEAGLLayer.h
@@ -0,0 +1 @@
+typedef struct _CAEAGLLayer CAEAGLLayer;
diff --git a/make/stub_includes/ios/QuartzCore/CALayer.h b/make/stub_includes/ios/QuartzCore/CALayer.h
new file mode 100644
index 000000000..a5a6579a6
--- /dev/null
+++ b/make/stub_includes/ios/QuartzCore/CALayer.h
@@ -0,0 +1 @@
+typedef struct _CALayer CALayer;
diff --git a/make/stub_includes/ios/UIKit/UIKit.h b/make/stub_includes/ios/UIKit/UIKit.h
new file mode 100644
index 000000000..155fdc932
--- /dev/null
+++ b/make/stub_includes/ios/UIKit/UIKit.h
@@ -0,0 +1 @@
+typedef struct _UIView UIView;
diff --git a/make/stub_includes/ios/window-system1.c b/make/stub_includes/ios/window-system1.c
new file mode 100644
index 000000000..d53c9e27d
--- /dev/null
+++ b/make/stub_includes/ios/window-system1.c
@@ -0,0 +1,2 @@
+#include "ios-window-system.h"
+
diff --git a/make/stub_includes/macosx/UIKit/NSOpenGL.h b/make/stub_includes/macosx/UIKit/NSOpenGL.h
new file mode 100644
index 000000000..1b7656dc1
--- /dev/null
+++ b/make/stub_includes/macosx/UIKit/NSOpenGL.h
@@ -0,0 +1,3 @@
+typedef struct _NSOpenGLPixelFormat NSOpenGLPixelFormat;
+typedef struct _NSOpenGLContext NSOpenGLContext;
+typedef struct _NSOpenGLPixelBuffer NSOpenGLPixelBuffer;
diff --git a/make/stub_includes/macosx/UIKit/NSOpenGLLayer.h b/make/stub_includes/macosx/UIKit/NSOpenGLLayer.h
new file mode 100644
index 000000000..2e5e81a68
--- /dev/null
+++ b/make/stub_includes/macosx/UIKit/NSOpenGLLayer.h
@@ -0,0 +1 @@
+typedef struct _NSOpenGLLayer NSOpenGLLayer;
diff --git a/make/stub_includes/macosx/UIKit/NSOpenGLView.h b/make/stub_includes/macosx/UIKit/NSOpenGLView.h
new file mode 100644
index 000000000..6492287df
--- /dev/null
+++ b/make/stub_includes/macosx/UIKit/NSOpenGLView.h
@@ -0,0 +1 @@
+typedef struct _NSOpenGLView NSOpenGLView;
diff --git a/make/stub_includes/macosx/UIKit/UIView.h b/make/stub_includes/macosx/UIKit/UIView.h
new file mode 100644
index 000000000..5d3acf658
--- /dev/null
+++ b/make/stub_includes/macosx/UIKit/UIView.h
@@ -0,0 +1 @@
+typedef struct _NSView NSView;
diff --git a/make/stub_includes/opengl/ios-window-system.h b/make/stub_includes/opengl/ios-window-system.h
new file mode 100644
index 000000000..ae4f1884d
--- /dev/null
+++ b/make/stub_includes/opengl/ios-window-system.h
@@ -0,0 +1,51 @@
+/**
+ * Copyright 2019 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.
+ */
+#include <UIKit/UIKit.h>
+#include <OpenGLES/EAGLDrawable.h>
+#include <QuartzCore/CAEAGLLayer.h>
+#include <OpenGLES/EAGL.h>
+#include <gluegen_stdint.h>
+
+typedef int Bool;
+
+EAGLContext * eaglCreateContext(EAGLRenderingAPI api);
+EAGLContext * eaglCreateContextShared(EAGLRenderingAPI api, EAGLSharegroup* sharegroup);
+Bool eaglDeleteContext(EAGLContext *ctx, Bool releaseOnMainThread);
+
+EAGLRenderingAPI eaglGetRenderingAPI(EAGLContext* ctx);
+EAGLSharegroup * eaglGetSharegroup(EAGLContext *ctx);
+Bool eaglIsContextMultiThreaded(EAGLContext* ctx);
+void eaglSetContextMultiThreaded(EAGLContext* ctx, Bool v); /* spawn off load to new GL worker thread if true */
+
+EAGLContext* eaglGetCurrentContext(void);
+Bool eaglMakeCurrentContext(EAGLContext* ctx);
+
+Bool eaglBindDrawableStorageToRenderbuffer(EAGLContext* ctx, int renderbufferTarget, CAEAGLLayer /* EAGLDrawable */ * drawable);
+Bool eaglPresentRenderbuffer(EAGLContext* ctx, int renderbufferTarget);
+
+void* getProcAddress(const char *procName);
diff --git a/src/demos/com/jogamp/opengl/demos/GearsObject.java b/src/demos/com/jogamp/opengl/demos/GearsObject.java
new file mode 100644
index 000000000..6ae4d87b4
--- /dev/null
+++ b/src/demos/com/jogamp/opengl/demos/GearsObject.java
@@ -0,0 +1,336 @@
+/**
+ * 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.demos;
+
+import java.nio.FloatBuffer;
+
+import com.jogamp.opengl.GL;
+
+import com.jogamp.common.nio.Buffers;
+import com.jogamp.opengl.util.GLArrayDataServer;
+
+/**
+ * GearsObject.java <BR>
+ * @author Brian Paul (converted to Java by Ron Cemer and Sven Gothel) <P>
+ */
+public abstract class GearsObject {
+ public static final FloatBuffer red = Buffers.newDirectFloatBuffer( new float[] { 0.8f, 0.1f, 0.0f, 0.7f } );
+ public static final FloatBuffer green = Buffers.newDirectFloatBuffer( new float[] { 0.0f, 0.8f, 0.2f, 0.7f } );
+ public static final FloatBuffer blue = Buffers.newDirectFloatBuffer( new float[] { 0.2f, 0.2f, 1.0f, 0.7f } );
+ public static final float M_PI = (float)Math.PI;
+
+ public final FloatBuffer gearColor;
+ public GLArrayDataServer frontFace;
+ public GLArrayDataServer frontSide;
+ public GLArrayDataServer backFace;
+ public GLArrayDataServer backSide;
+ public GLArrayDataServer outwardFace;
+ public GLArrayDataServer insideRadiusCyl;
+ public boolean isShared;
+ protected boolean validateBuffers = false;
+
+ public abstract GLArrayDataServer createInterleaved(boolean useMappedBuffers, int comps, int dataType, boolean normalized, int initialSize, int vboUsage);
+ public abstract void addInterleavedVertexAndNormalArrays(GLArrayDataServer array, int components);
+ public abstract void draw(GL gl, float x, float y, float angle);
+
+ private GLArrayDataServer createInterleavedClone(final GLArrayDataServer ads) {
+ final GLArrayDataServer n = new GLArrayDataServer(ads);
+ n.setInterleavedOffset(0);
+ return n;
+ }
+
+ private void init(final GL gl, final GLArrayDataServer array) {
+ array.enableBuffer(gl, true);
+ array.enableBuffer(gl, false);
+ }
+
+ public void destroy(final GL gl) {
+ if(!isShared) {
+ // could be already destroyed by shared configuration
+ if(null != frontFace) {
+ frontFace.destroy(gl);
+ }
+ if(null != frontSide) {
+ frontSide.destroy(gl);
+ }
+ if(null != backFace) {
+ backFace.destroy(gl);
+ }
+ if(null != backSide) {
+ backSide.destroy(gl);
+ }
+ if(null != outwardFace) {
+ outwardFace.destroy(gl);
+ }
+ if(null != insideRadiusCyl) {
+ insideRadiusCyl.destroy(gl);
+ }
+ }
+ frontFace=null;
+ frontSide=null;
+ backFace=null;
+ backSide=null;
+ outwardFace=null;
+ insideRadiusCyl=null;
+ isShared = false;
+ }
+
+ public GearsObject ( final GearsObject shared ) {
+ isShared = true;
+ validateBuffers = shared.validateBuffers;
+ frontFace = createInterleavedClone(shared.frontFace);
+ addInterleavedVertexAndNormalArrays(frontFace, 3);
+ backFace = createInterleavedClone(shared.backFace);
+ addInterleavedVertexAndNormalArrays(backFace, 3);
+ frontSide = createInterleavedClone(shared.frontSide);
+ addInterleavedVertexAndNormalArrays(frontSide, 3);
+ backSide= createInterleavedClone(shared.backSide);
+ addInterleavedVertexAndNormalArrays(backSide, 3);
+ outwardFace = createInterleavedClone(shared.outwardFace);
+ addInterleavedVertexAndNormalArrays(outwardFace, 3);
+ insideRadiusCyl = createInterleavedClone(shared.insideRadiusCyl);
+ addInterleavedVertexAndNormalArrays(insideRadiusCyl, 3);
+ gearColor = shared.gearColor;
+ }
+
+ public GearsObject (
+ final GL gl,
+ final boolean useMappedBuffers,
+ final FloatBuffer gearColor,
+ final float inner_radius,
+ final float outer_radius,
+ final float width, final int teeth, final float tooth_depth, final boolean validateBuffers)
+ {
+ final float dz = width * 0.5f;
+ int i;
+ float r0, r1, r2;
+ float angle, da;
+ float u, v, len;
+ final float s[] = new float[5];
+ final float c[] = new float[5];
+ final float normal[] = new float[3];
+ // final int tris_per_tooth = 32;
+
+ this.validateBuffers = validateBuffers;
+ this.isShared = false;
+ this.gearColor = gearColor;
+
+ r0 = inner_radius;
+ r1 = outer_radius - tooth_depth / 2.0f;
+ r2 = outer_radius + tooth_depth / 2.0f;
+
+ da = 2.0f * (float) Math.PI / teeth / 4.0f;
+
+ s[4] = 0; // sin(0f)
+ c[4] = 1; // cos(0f)
+
+ final int vboUsage = GL.GL_STATIC_DRAW;
+
+ frontFace = createInterleaved(useMappedBuffers, 6, GL.GL_FLOAT, false, 4*teeth+2, vboUsage);
+ addInterleavedVertexAndNormalArrays(frontFace, 3);
+ backFace = createInterleaved(useMappedBuffers, 6, GL.GL_FLOAT, false, 4*teeth+2, vboUsage);
+ addInterleavedVertexAndNormalArrays(backFace, 3);
+ frontSide = createInterleaved(useMappedBuffers, 6, GL.GL_FLOAT, false, 6*teeth, vboUsage);
+ addInterleavedVertexAndNormalArrays(frontSide, 3);
+ backSide = createInterleaved(useMappedBuffers, 6, GL.GL_FLOAT, false, 6*teeth, vboUsage);
+ addInterleavedVertexAndNormalArrays(backSide, 3);
+ outwardFace = createInterleaved(useMappedBuffers, 6, GL.GL_FLOAT, false, 4*4*teeth+2, vboUsage);
+ addInterleavedVertexAndNormalArrays(outwardFace, 3);
+ insideRadiusCyl = createInterleaved(useMappedBuffers, 6, GL.GL_FLOAT, false, 2*teeth+2, vboUsage);
+ addInterleavedVertexAndNormalArrays(insideRadiusCyl, 3);
+
+ if( useMappedBuffers ) {
+ frontFace.mapStorage(gl, GL.GL_WRITE_ONLY);
+ backFace.mapStorage(gl, GL.GL_WRITE_ONLY);
+ frontSide.mapStorage(gl, GL.GL_WRITE_ONLY);
+ backSide.mapStorage(gl, GL.GL_WRITE_ONLY);
+ outwardFace.mapStorage(gl, GL.GL_WRITE_ONLY);
+ insideRadiusCyl.mapStorage(gl, GL.GL_WRITE_ONLY);
+ }
+
+ for (i = 0; i < teeth; i++) {
+ angle = i * 2.0f * M_PI / teeth;
+ sincos(angle + da * 0f, s, 0, c, 0);
+ sincos(angle + da * 1f, s, 1, c, 1);
+ sincos(angle + da * 2f, s, 2, c, 2);
+ sincos(angle + da * 3f, s, 3, c, 3);
+
+ /* front */
+ normal[0] = 0.0f;
+ normal[1] = 0.0f;
+ normal[2] = 1.0f;
+
+ /* front face - GL.GL_TRIANGLE_STRIP */
+ vert(frontFace, r0 * c[0], r0 * s[0], dz, normal);
+ vert(frontFace, r1 * c[0], r1 * s[0], dz, normal);
+ vert(frontFace, r0 * c[0], r0 * s[0], dz, normal);
+ vert(frontFace, r1 * c[3], r1 * s[3], dz, normal);
+
+ /* front sides of teeth - GL.GL_TRIANGLES */
+ vert(frontSide, r1 * c[0], r1 * s[0], dz, normal);
+ vert(frontSide, r2 * c[1], r2 * s[1], dz, normal);
+ vert(frontSide, r2 * c[2], r2 * s[2], dz, normal);
+ vert(frontSide, r1 * c[0], r1 * s[0], dz, normal);
+ vert(frontSide, r2 * c[2], r2 * s[2], dz, normal);
+ vert(frontSide, r1 * c[3], r1 * s[3], dz, normal);
+
+ /* back */
+ normal[0] = 0.0f;
+ normal[1] = 0.0f;
+ normal[2] = -1.0f;
+
+ /* back face - GL.GL_TRIANGLE_STRIP */
+ vert(backFace, r1 * c[0], r1 * s[0], -dz, normal);
+ vert(backFace, r0 * c[0], r0 * s[0], -dz, normal);
+ vert(backFace, r1 * c[3], r1 * s[3], -dz, normal);
+ vert(backFace, r0 * c[0], r0 * s[0], -dz, normal);
+
+ /* back sides of teeth - GL.GL_TRIANGLES*/
+ vert(backSide, r1 * c[3], r1 * s[3], -dz, normal);
+ vert(backSide, r2 * c[2], r2 * s[2], -dz, normal);
+ vert(backSide, r2 * c[1], r2 * s[1], -dz, normal);
+ vert(backSide, r1 * c[3], r1 * s[3], -dz, normal);
+ vert(backSide, r2 * c[1], r2 * s[1], -dz, normal);
+ vert(backSide, r1 * c[0], r1 * s[0], -dz, normal);
+
+ /* outward faces of teeth */
+ u = r2 * c[1] - r1 * c[0];
+ v = r2 * s[1] - r1 * s[0];
+ len = (float)Math.sqrt(u * u + v * v);
+ u /= len;
+ v /= len;
+ normal[0] = v;
+ normal[1] = -u;
+ normal[2] = 0.0f;
+
+ vert(outwardFace, r1 * c[0], r1 * s[0], dz, normal);
+ vert(outwardFace, r1 * c[0], r1 * s[0], -dz, normal);
+ vert(outwardFace, r2 * c[1], r2 * s[1], dz, normal);
+ vert(outwardFace, r2 * c[1], r2 * s[1], -dz, normal);
+
+ normal[0] = c[0];
+ normal[1] = s[0];
+ vert(outwardFace, r2 * c[1], r2 * s[1], dz, normal);
+ vert(outwardFace, r2 * c[1], r2 * s[1], -dz, normal);
+ vert(outwardFace, r2 * c[2], r2 * s[2], dz, normal);
+ vert(outwardFace, r2 * c[2], r2 * s[2], -dz, normal);
+
+ normal[0] = ( r1 * s[3] - r2 * s[2] );
+ normal[1] = ( r1 * c[3] - r2 * c[2] ) * -1.0f ;
+ vert(outwardFace, r2 * c[2], r2 * s[2], dz, normal);
+ vert(outwardFace, r2 * c[2], r2 * s[2], -dz, normal);
+ vert(outwardFace, r1 * c[3], r1 * s[3], dz, normal);
+ vert(outwardFace, r1 * c[3], r1 * s[3], -dz, normal);
+
+ normal[0] = c[0];
+ normal[1] = s[0];
+ vert(outwardFace, r1 * c[3], r1 * s[3], dz, normal);
+ vert(outwardFace, r1 * c[3], r1 * s[3], -dz, normal);
+ vert(outwardFace, r1 * c[0], r1 * s[0], dz, normal);
+ vert(outwardFace, r1 * c[0], r1 * s[0], -dz, normal);
+
+ /* inside radius cylinder */
+ normal[0] = c[0] * -1.0f;
+ normal[1] = s[0] * -1.0f;
+ normal[2] = 0.0f;
+ vert(insideRadiusCyl, r0 * c[0], r0 * s[0], -dz, normal);
+ vert(insideRadiusCyl, r0 * c[0], r0 * s[0], dz, normal);
+ }
+ /* finish front face */
+ normal[0] = 0.0f;
+ normal[1] = 0.0f;
+ normal[2] = 1.0f;
+ vert(frontFace, r0 * c[4], r0 * s[4], dz, normal);
+ vert(frontFace, r1 * c[4], r1 * s[4], dz, normal);
+ frontFace.seal(true);
+
+ /* finish back face */
+ normal[2] = -1.0f;
+ vert(backFace, r1 * c[4], r1 * s[4], -dz, normal);
+ vert(backFace, r0 * c[4], r0 * s[4], -dz, normal);
+ backFace.seal(true);
+
+ backSide.seal(true);
+ frontSide.seal(true);
+
+ /* finish outward face */
+ sincos(da * 1f, s, 1, c, 1);
+ u = r2 * c[1] - r1 * c[4];
+ v = r2 * s[1] - r1 * s[4];
+ len = (float)Math.sqrt(u * u + v * v);
+ u /= len;
+ v /= len;
+ normal[0] = v;
+ normal[1] = -u;
+ normal[2] = 0.0f;
+ vert(outwardFace, r1 * c[4], r1 * s[4], dz, normal);
+ vert(outwardFace, r1 * c[4], r1 * s[4], -dz, normal);
+ outwardFace.seal(true);
+
+ /* finish inside radius cylinder */
+ normal[0] = c[4] * -1.0f;
+ normal[1] = s[4] * -1.0f;
+ normal[2] = 0.0f;
+ vert(insideRadiusCyl, r0 * c[4], r0 * s[4], -dz, normal);
+ vert(insideRadiusCyl, r0 * c[4], r0 * s[4], dz, normal);
+ insideRadiusCyl.seal(true);
+
+ if( useMappedBuffers ) {
+ frontFace.unmapStorage(gl);
+ backFace.unmapStorage(gl);
+ frontSide.unmapStorage(gl);
+ backSide.unmapStorage(gl);
+ outwardFace.unmapStorage(gl);
+ insideRadiusCyl.unmapStorage(gl);
+ } else {
+ /** Init VBO and data .. */
+ init(gl, frontFace);
+ init(gl, frontSide);
+ init(gl, backFace);
+ init(gl, backSide);
+ init(gl, outwardFace);
+ init(gl, insideRadiusCyl);
+ }
+ }
+
+ @Override
+ public String toString() {
+ final int ffVBO = null != frontFace ? frontFace.getVBOName() : 0;
+ final int fsVBO = null != frontSide ? frontSide.getVBOName() : 0;
+ final int bfVBO = null != backFace ? backFace.getVBOName() : 0;
+ final int bsVBO = null != backSide ? backSide.getVBOName() : 0;
+ return "GearsObj[0x"+Integer.toHexString(hashCode())+", vbo ff "+ffVBO+", fs "+fsVBO+", bf "+bfVBO+", bs "+bsVBO+"]";
+ }
+
+ static void vert(final GLArrayDataServer array, final float x, final float y, final float z, final float n[]) {
+ array.putf(x);
+ array.putf(y);
+ array.putf(z);
+ array.putf(n[0]);
+ array.putf(n[1]);
+ array.putf(n[2]);
+ }
+
+ static void sincos(final float x, final float sin[], final int sinIdx, final float cos[], final int cosIdx) {
+ sin[sinIdx] = (float) Math.sin(x);
+ cos[cosIdx] = (float) Math.cos(x);
+ }
+}
diff --git a/src/demos/com/jogamp/opengl/demos/PointsDemo.java b/src/demos/com/jogamp/opengl/demos/PointsDemo.java
new file mode 100644
index 000000000..749d37114
--- /dev/null
+++ b/src/demos/com/jogamp/opengl/demos/PointsDemo.java
@@ -0,0 +1,48 @@
+/**
+ * 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.demos;
+
+import com.jogamp.opengl.GLEventListener;
+
+public abstract class PointsDemo implements GLEventListener {
+ int swapInterval = 0;
+ final int edge = 8; // 8*8
+
+ public PointsDemo(final int swapInterval) {
+ this.swapInterval = swapInterval;
+ }
+
+ public PointsDemo() {
+ this.swapInterval = 1;
+ }
+
+ public abstract void setSmoothPoints(boolean v);
+
+ public abstract void setPointParams(float minSize, float maxSize, float distAttenConst, float distAttenLinear, float distAttenQuadratic, float fadeThreshold);
+
+}
diff --git a/src/demos/com/jogamp/opengl/demos/es2/GearsES2.java b/src/demos/com/jogamp/opengl/demos/es2/GearsES2.java
new file mode 100644
index 000000000..a2d0f5db7
--- /dev/null
+++ b/src/demos/com/jogamp/opengl/demos/es2/GearsES2.java
@@ -0,0 +1,673 @@
+/**
+ * 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.demos.es2;
+
+import com.jogamp.common.nio.Buffers;
+import com.jogamp.newt.Window;
+import com.jogamp.newt.event.GestureHandler;
+import com.jogamp.newt.event.KeyAdapter;
+import com.jogamp.newt.event.KeyEvent;
+import com.jogamp.newt.event.KeyListener;
+import com.jogamp.newt.event.MouseEvent;
+import com.jogamp.newt.event.MouseListener;
+import com.jogamp.newt.event.PinchToZoomGesture;
+import com.jogamp.newt.event.GestureHandler.GestureEvent;
+import com.jogamp.opengl.GLRendererQuirks;
+import com.jogamp.opengl.JoglVersion;
+import com.jogamp.opengl.math.FloatUtil;
+import com.jogamp.opengl.math.Quaternion;
+import com.jogamp.opengl.math.VectorUtil;
+import com.jogamp.opengl.util.CustomGLEventListener;
+import com.jogamp.opengl.util.PMVMatrix;
+import com.jogamp.opengl.util.TileRendererBase;
+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.stereo.EyeParameter;
+import com.jogamp.opengl.util.stereo.ViewerPose;
+import com.jogamp.opengl.util.stereo.StereoGLEventListener;
+
+import java.nio.FloatBuffer;
+
+import com.jogamp.nativewindow.NativeWindow;
+import com.jogamp.opengl.GL;
+import com.jogamp.opengl.GL2ES2;
+import com.jogamp.opengl.GLAnimatorControl;
+import com.jogamp.opengl.GLAutoDrawable;
+import com.jogamp.opengl.GLUniformData;
+import com.jogamp.opengl.fixedfunc.GLMatrixFunc;
+
+import com.jogamp.opengl.demos.GearsObject;
+
+/**
+ * GearsES2.java <BR>
+ * @author Brian Paul (converted to Java by Ron Cemer and Sven Gothel) <P>
+ */
+public class GearsES2 implements StereoGLEventListener, TileRendererBase.TileRendererListener {
+ private final FloatBuffer lightPos = Buffers.newDirectFloatBuffer( new float[] { 5.0f, 5.0f, 10.0f } );
+
+ private ShaderState st = null;
+ private PMVMatrix pmvMatrix = null;
+ private GLUniformData pmvMatrixUniform = null;
+ private GLUniformData colorU = null;
+ private float view_rotx = 20.0f, view_roty = 30.0f;
+ private boolean flipVerticalInGLOrientation = false;
+ private final boolean customRendering = false;
+
+ private final float view_rotz = 0.0f;
+ private float panX = 0.0f, panY = 0.0f, panZ=0.0f;
+ private volatile GearsObjectES2 gear1=null, gear2=null, gear3=null;
+ private GearsES2 sharedGears = null;
+ private Object syncObjects = null;
+ private boolean useMappedBuffers = false;
+ private boolean validateBuffers = false;
+ private volatile boolean usesSharedGears = false;
+ private FloatBuffer gear1Color=GearsObject.red, gear2Color=GearsObject.green, gear3Color=GearsObject.blue;
+ private float angle = 0.0f;
+ private int swapInterval = 0;
+ // private MouseListener gearsMouse = new TraceMouseAdapter(new GearsMouseAdapter());
+ public MouseListener gearsMouse = new GearsMouseAdapter();
+ public KeyListener gearsKeys = new GearsKeyAdapter();
+ private TileRendererBase tileRendererInUse = null;
+ private boolean doRotateBeforePrinting;
+
+ private boolean doRotate = true;
+ private float[] clearColor = null;
+ private boolean clearBuffers = true;
+ private boolean verbose = true;
+ private volatile boolean isInit = false;
+
+ private PinchToZoomGesture pinchToZoomGesture = null;
+
+
+ public GearsES2(final int swapInterval) {
+ this.swapInterval = swapInterval;
+ }
+
+ public GearsES2() {
+ this.swapInterval = 1;
+ }
+
+ @Override
+ public void addTileRendererNotify(final TileRendererBase tr) {
+ tileRendererInUse = tr;
+ doRotateBeforePrinting = doRotate;
+ setDoRotation(false);
+ }
+ @Override
+ public void removeTileRendererNotify(final TileRendererBase tr) {
+ tileRendererInUse = null;
+ setDoRotation(doRotateBeforePrinting);
+ }
+ @Override
+ public void startTileRendering(final TileRendererBase tr) {
+ System.err.println("GearsES2.startTileRendering: "+sid()+""+tr);
+ }
+ @Override
+ public void endTileRendering(final TileRendererBase tr) {
+ System.err.println("GearsES2.endTileRendering: "+sid()+""+tr);
+ }
+
+ public void setDoRotation(final boolean rotate) { this.doRotate = rotate; }
+ public void setClearBuffers(final boolean v) { clearBuffers = v; }
+ public void setVerbose(final boolean v) { verbose = v; }
+ public void setFlipVerticalInGLOrientation(final boolean v) { flipVerticalInGLOrientation=v; }
+
+ /** float[4] */
+ public void setClearColor(final float[] clearColor) {
+ this.clearColor = clearColor;
+ }
+
+ public void setGearsColors(final FloatBuffer gear1Color, final FloatBuffer gear2Color, final FloatBuffer gear3Color) {
+ this.gear1Color = gear1Color;
+ this.gear2Color = gear2Color;
+ this.gear3Color = gear3Color;
+ }
+
+ public void setSharedGears(final GearsES2 shared) {
+ sharedGears = shared;
+ }
+
+ public void setSyncObjects(final Object sync) {
+ syncObjects = sync;
+ }
+
+ /**
+ * @return gear1
+ */
+ public GearsObjectES2 getGear1() { return gear1; }
+
+ /**
+ * @return gear2
+ */
+ public GearsObjectES2 getGear2() { return gear2; }
+
+ /**
+ * @return gear3
+ */
+ public GearsObjectES2 getGear3() { return gear3; }
+
+ public boolean usesSharedGears() { return usesSharedGears; }
+
+ public void setUseMappedBuffers(final boolean v) { useMappedBuffers = v; }
+ public void setValidateBuffers(final boolean v) { validateBuffers = v; }
+
+ public PMVMatrix getPMVMatrix() {
+ return pmvMatrix;
+ }
+
+ private static final int TIME_OUT = 2000; // 2s
+ private static final int POLL_DIVIDER = 20; // TO/20
+ private static final int TIME_SLICE = TIME_OUT / POLL_DIVIDER ;
+
+ /**
+ * @return True if this GLEventListener became initialized within TIME_OUT 2s
+ */
+ public boolean waitForInit(final boolean initialized) throws InterruptedException {
+ int wait;
+ for (wait=0; wait<POLL_DIVIDER && initialized != isInit ; wait++) {
+ Thread.sleep(TIME_SLICE);
+ }
+ return wait<POLL_DIVIDER;
+ }
+
+ private final String sid() { return "0x"+Integer.toHexString(hashCode()); }
+
+ @Override
+ public void init(final GLAutoDrawable drawable) {
+ if(null != sharedGears && !sharedGears.isInit() ) {
+ System.err.println(Thread.currentThread()+" GearsES2.init.0 "+sid()+": pending shared Gears .. re-init later XXXXX");
+ drawable.setGLEventListenerInitState(this, false);
+ return;
+ }
+
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+ if(verbose) {
+ System.err.println(Thread.currentThread()+" GearsES2.init.0 "+sid()+": tileRendererInUse "+tileRendererInUse+", "+this);
+ System.err.println("GearsES2 init "+sid()+" on "+Thread.currentThread());
+ System.err.println("Chosen GLCapabilities: " + drawable.getChosenGLCapabilities());
+ System.err.println("INIT GL IS: " + gl.getClass().getName());
+ System.err.println(JoglVersion.getGLStrings(gl, null, false).toString());
+ }
+ if( !gl.hasGLSL() ) {
+ System.err.println("No GLSL available, no rendering.");
+ return;
+ }
+
+ st = new ShaderState();
+ // st.setVerbose(true);
+ final ShaderCode vp0 = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, this.getClass(), "shader",
+ "shader/bin", "gears", true);
+ final ShaderCode fp0 = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, this.getClass(), "shader",
+ "shader/bin", "gears", true);
+ vp0.defaultShaderCustomization(gl, true, true);
+ fp0.defaultShaderCustomization(gl, true, true);
+ final ShaderProgram sp0 = new ShaderProgram();
+ sp0.add(gl, vp0, System.err);
+ sp0.add(gl, fp0, System.err);
+ st.attachShaderProgram(gl, sp0, true);
+ // Use debug pipeline
+ // drawable.setGL(new DebugGL(drawable.getGL()));
+
+ pmvMatrix = new PMVMatrix();
+ st.attachObject("pmvMatrix", pmvMatrix);
+ pmvMatrixUniform = new GLUniformData("pmvMatrix", 4, 4, pmvMatrix.glGetPMvMvitMatrixf()); // P, Mv, Mvi and Mvit
+ st.ownUniform(pmvMatrixUniform);
+ st.uniform(gl, pmvMatrixUniform);
+
+ final GLUniformData lightU = new GLUniformData("lightPos", 3, lightPos);
+ st.ownUniform(lightU);
+ st.uniform(gl, lightU);
+
+ colorU = new GLUniformData("color", 4, GearsObject.red);
+ st.ownUniform(colorU);
+ st.uniform(gl, colorU);
+
+ if( null != sharedGears ) {
+ gear1 = new GearsObjectES2(sharedGears.getGear1(), st, pmvMatrix, pmvMatrixUniform, colorU);
+ gear2 = new GearsObjectES2(sharedGears.getGear2(), st, pmvMatrix, pmvMatrixUniform, colorU);
+ gear3 = new GearsObjectES2(sharedGears.getGear3(), st, pmvMatrix, pmvMatrixUniform, colorU);
+ usesSharedGears = true;
+ if(verbose) {
+ System.err.println("gear1 "+sid()+" created w/ share: "+sharedGears.getGear1()+" -> "+gear1);
+ System.err.println("gear2 "+sid()+" created w/ share: "+sharedGears.getGear2()+" -> "+gear2);
+ System.err.println("gear3 "+sid()+" created w/ share: "+sharedGears.getGear3()+" -> "+gear3);
+ }
+ if( gl.getContext().hasRendererQuirk(GLRendererQuirks.NeedSharedObjectSync) ) {
+ syncObjects = sharedGears;
+ System.err.println("Shared GearsES2: Synchronized Objects due to quirk "+GLRendererQuirks.toString(GLRendererQuirks.NeedSharedObjectSync));
+ } else if( null == syncObjects ) {
+ syncObjects = new Object();
+ System.err.println("Shared GearsES2: Unsynchronized Objects");
+ }
+ } else {
+ gear1 = new GearsObjectES2(gl, useMappedBuffers, st, gear1Color, 1.0f, 4.0f, 1.0f, 20, 0.7f, pmvMatrix, pmvMatrixUniform, colorU, validateBuffers);
+ if(verbose) {
+ System.err.println("gear1 "+sid()+" created: "+gear1);
+ }
+
+ gear2 = new GearsObjectES2(gl, useMappedBuffers, st, gear2Color, 0.5f, 2.0f, 2.0f, 10, 0.7f, pmvMatrix, pmvMatrixUniform, colorU, validateBuffers);
+ if(verbose) {
+ System.err.println("gear2 "+sid()+" created: "+gear2);
+ }
+
+ gear3 = new GearsObjectES2(gl, useMappedBuffers, st, gear3Color, 1.3f, 2.0f, 0.5f, 10, 0.7f, pmvMatrix, pmvMatrixUniform, colorU, validateBuffers);
+ if(verbose) {
+ System.err.println("gear3 "+sid()+" created: "+gear2);
+ }
+ if( null == syncObjects ) {
+ syncObjects = new Object();
+ }
+ }
+
+ final Object upstreamWidget = drawable.getUpstreamWidget();
+ if (upstreamWidget instanceof Window) {
+ final Window window = (Window) upstreamWidget;
+ window.addMouseListener(gearsMouse);
+ window.addKeyListener(gearsKeys);
+ window.addGestureListener(pinchToZoomListener);
+ pinchToZoomGesture = new PinchToZoomGesture(drawable.getNativeSurface(), false);
+ window.addGestureHandler(pinchToZoomGesture);
+ }
+
+ st.useProgram(gl, false);
+
+ gl.glFinish(); // make sure .. for shared context (impacts OSX 10.9)
+
+ isInit = true;
+ if(verbose) {
+ System.err.println(Thread.currentThread()+" GearsES2.init.X "+sid()+" FIN "+this);
+ }
+ }
+
+ public final boolean isInit() { return isInit; }
+
+ private final GestureHandler.GestureListener pinchToZoomListener = new GestureHandler.GestureListener() {
+ @Override
+ public void gestureDetected(final GestureEvent gh) {
+ final PinchToZoomGesture.ZoomEvent ze = (PinchToZoomGesture.ZoomEvent) gh;
+ final float zoom = ze.getZoom(); // * ( ze.getTrigger().getPointerCount() - 1 ); <- too much ..
+ panZ = zoom * 30f - 30f; // [0 .. 2] -> [-30f .. 30f]
+ }
+ };
+
+ @Override
+ public void reshape(final GLAutoDrawable glad, final int x, final int y, final int width, final int height) {
+ if( !isInit ) { return; }
+ final GL2ES2 gl = glad.getGL().getGL2ES2();
+ gl.setSwapInterval(swapInterval);
+ reshapeImpl(gl, x, y, width, height, width, height);
+ }
+
+ @Override
+ public void reshapeTile(final TileRendererBase tr,
+ final int tileX, final int tileY, final int tileWidth, final int tileHeight,
+ final int imageWidth, final int imageHeight) {
+ if( !isInit ) { return; }
+ final GL2ES2 gl = tr.getAttachedDrawable().getGL().getGL2ES2();
+ gl.setSwapInterval(0);
+ reshapeImpl(gl, tileX, tileY, tileWidth, tileHeight, imageWidth, imageHeight);
+ }
+
+ private float zNear = 5f;
+ private float zFar = 10000f;
+ private float zViewDist = 40.0f;
+
+ public void setZ(final float zNear, final float zFar, final float zViewDist) {
+ this.zNear = zNear;
+ this.zFar = zFar;
+ this.zViewDist = zViewDist;
+ }
+
+ void reshapeImpl(final GL2ES2 gl, final int tileX, final int tileY, final int tileWidth, final int tileHeight, final int imageWidth, final int imageHeight) {
+ final boolean msaa = gl.getContext().getGLDrawable().getChosenGLCapabilities().getSampleBuffers();
+ if(verbose) {
+ System.err.println(Thread.currentThread()+" GearsES2.reshape "+sid()+" "+tileX+"/"+tileY+" "+tileWidth+"x"+tileHeight+" of "+imageWidth+"x"+imageHeight+", swapInterval "+swapInterval+", drawable 0x"+Long.toHexString(gl.getContext().getGLDrawable().getHandle())+", msaa "+msaa+", tileRendererInUse "+tileRendererInUse);
+ }
+
+ if( !gl.hasGLSL() ) {
+ return;
+ }
+
+ // compute projection parameters 'normal'
+ float left, right, bottom, top;
+ if( imageHeight > imageWidth ) {
+ final float a = (float)imageHeight / (float)imageWidth;
+ left = -1.0f;
+ right = 1.0f;
+ bottom = -a;
+ top = a;
+ } else {
+ final float a = (float)imageWidth / (float)imageHeight;
+ left = -a;
+ right = a;
+ bottom = -1.0f;
+ top = 1.0f;
+ }
+ final float w = right - left;
+ final float h = top - bottom;
+
+ // compute projection parameters 'tiled'
+ final float l = left + tileX * w / imageWidth;
+ final float r = l + tileWidth * w / imageWidth;
+ final float b = bottom + tileY * h / imageHeight;
+ final float t = b + tileHeight * h / imageHeight;
+
+ final float _w = r - l;
+ final float _h = t - b;
+ if(verbose) {
+ System.err.println(">> GearsES2 "+sid()+", angle "+angle+", [l "+left+", r "+right+", b "+bottom+", t "+top+"] "+w+"x"+h+" -> [l "+l+", r "+r+", b "+b+", t "+t+"] "+_w+"x"+_h+", v-flip "+flipVerticalInGLOrientation);
+ }
+
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
+ pmvMatrix.glLoadIdentity();
+ if( flipVerticalInGLOrientation && gl.getContext().getGLDrawable().isGLOriented() ) {
+ pmvMatrix.glScalef(1f, -1f, 1f);
+ }
+ pmvMatrix.glFrustumf(l, r, b, t, zNear, zFar);
+
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
+ pmvMatrix.glLoadIdentity();
+ pmvMatrix.glTranslatef(0.0f, 0.0f, -zViewDist);
+ st.useProgram(gl, true);
+ st.uniform(gl, pmvMatrixUniform);
+ st.useProgram(gl, false);
+ }
+ // private boolean useAndroidDebug = false;
+
+ private final float[] mat4Tmp1 = new float[16];
+ private final float[] mat4Tmp2 = new float[16];
+ private final float[] vec3Tmp1 = new float[3];
+ private final float[] vec3Tmp2 = new float[3];
+ private final float[] vec3Tmp3 = new float[3];
+
+ private static final float[] vec3ScalePos = new float[] { 20f, 20f, 20f };
+
+ @Override
+ public void reshapeForEye(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height,
+ final EyeParameter eyeParam, final ViewerPose viewerPose) {
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
+ final float[] mat4Projection = FloatUtil.makePerspective(mat4Tmp1, 0, true, eyeParam.fovhv, zNear, zFar);
+ if( flipVerticalInGLOrientation && gl.getContext().getGLDrawable().isGLOriented() ) {
+ pmvMatrix.glLoadIdentity();
+ pmvMatrix.glScalef(1f, -1f, 1f);
+ pmvMatrix.glMultMatrixf(mat4Projection, 0);
+ } else {
+ pmvMatrix.glLoadMatrixf(mat4Projection, 0);
+ }
+
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
+
+ final Quaternion rollPitchYaw = new Quaternion();
+ // private final float eyeYaw = FloatUtil.PI; // 180 degrees in radians
+ // rollPitchYaw.rotateByAngleY(eyeYaw);
+ // final float[] shiftedEyePos = rollPitchYaw.rotateVector(vec3Tmp1, 0, viewerPose.position, 0);
+ final float[] shiftedEyePos = VectorUtil.copyVec3(vec3Tmp1, 0, viewerPose.position, 0);
+ VectorUtil.scaleVec3(shiftedEyePos, shiftedEyePos, vec3ScalePos); // amplify viewerPose position
+ VectorUtil.addVec3(shiftedEyePos, shiftedEyePos, eyeParam.positionOffset);
+
+ rollPitchYaw.mult(viewerPose.orientation);
+ final float[] up = rollPitchYaw.rotateVector(vec3Tmp2, 0, VectorUtil.VEC3_UNIT_Y, 0);
+ final float[] forward = rollPitchYaw.rotateVector(vec3Tmp3, 0, VectorUtil.VEC3_UNIT_Z_NEG, 0);
+ final float[] center = VectorUtil.addVec3(forward, shiftedEyePos, forward);
+
+ final float[] mLookAt = FloatUtil.makeLookAt(mat4Tmp1, 0, shiftedEyePos, 0, center, 0, up, 0, mat4Tmp2);
+ final float[] mViewAdjust = FloatUtil.makeTranslation(mat4Tmp2, true, eyeParam.distNoseToPupilX, eyeParam.distMiddleToPupilY, eyeParam.eyeReliefZ);
+ final float[] mat4Modelview = FloatUtil.multMatrix(mViewAdjust, mLookAt);
+
+ pmvMatrix.glLoadMatrixf(mat4Modelview, 0);
+ pmvMatrix.glTranslatef(0.0f, 0.0f, -zViewDist);
+ st.useProgram(gl, true);
+ st.uniform(gl, pmvMatrixUniform);
+ st.useProgram(gl, false);
+ }
+
+ @Override
+ public void dispose(final GLAutoDrawable drawable) {
+ if( !isInit ) { return; }
+ isInit = false;
+ if(verbose) {
+ System.err.println(Thread.currentThread()+" GearsES2.dispose "+sid()+": tileRendererInUse "+tileRendererInUse);
+ }
+ final Object upstreamWidget = drawable.getUpstreamWidget();
+ if (upstreamWidget instanceof Window) {
+ final Window window = (Window) upstreamWidget;
+ window.removeMouseListener(gearsMouse);
+ window.removeKeyListener(gearsKeys);
+ window.removeGestureHandler(pinchToZoomGesture);
+ pinchToZoomGesture = null;
+ window.removeGestureListener(pinchToZoomListener);
+ }
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+ if( !gl.hasGLSL() ) {
+ return;
+ }
+ st.useProgram(gl, false);
+ gear1.destroy(gl);
+ gear1 = null;
+ gear2.destroy(gl);
+ gear2 = null;
+ gear3.destroy(gl);
+ gear3 = null;
+ pmvMatrix = null;
+ colorU = null;
+ st.destroy(gl);
+ st = null;
+ sharedGears = null;
+ syncObjects = null;
+
+ if(verbose) {
+ System.err.println(Thread.currentThread()+" GearsES2.dispose "+sid()+" FIN");
+ }
+ }
+
+ @Override
+ public void display(final GLAutoDrawable drawable) {
+ display(drawable, 0);
+ }
+
+ @Override
+ public void display(final GLAutoDrawable drawable, final int flags) {
+ if( !isInit ) { return; }
+ if(null != sharedGears && !sharedGears.isInit() ) { return; }
+ final GLAnimatorControl anim = drawable.getAnimator();
+ if( verbose && ( null == anim || !anim.isAnimating() ) ) {
+ System.err.println(Thread.currentThread()+" GearsES2.display "+sid()+" "+drawable.getSurfaceWidth()+"x"+drawable.getSurfaceHeight()+", swapInterval "+swapInterval+", drawable 0x"+Long.toHexString(drawable.getHandle()));
+ }
+
+ final boolean repeatedFrame = 0 != ( CustomGLEventListener.DISPLAY_REPEAT & flags );
+ final boolean dontClear = 0 != ( CustomGLEventListener.DISPLAY_DONTCLEAR & flags );
+
+ // Turn the gears' teeth
+ if( doRotate && !repeatedFrame ) {
+ angle += 0.5f;
+ }
+
+ // Get the GL corresponding to the drawable we are animating
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+
+ final boolean hasFocus;
+ final Object upstreamWidget = drawable.getUpstreamWidget();
+ if(upstreamWidget instanceof NativeWindow) {
+ hasFocus = ((NativeWindow)upstreamWidget).hasFocus();
+ } else {
+ hasFocus = true;
+ }
+
+ if( clearBuffers && !dontClear ) {
+ if( null != clearColor ) {
+ gl.glClearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]);
+ } else if( null != tileRendererInUse ) {
+ gl.glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
+ } else {
+ gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+ }
+ gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
+ }
+ if( !gl.hasGLSL() ) {
+ return;
+ }
+
+ setGLStates(gl, true);
+
+ st.useProgram(gl, true);
+ pmvMatrix.glPushMatrix();
+ pmvMatrix.glTranslatef(panX, panY, panZ);
+ pmvMatrix.glRotatef(view_rotx, 1.0f, 0.0f, 0.0f);
+ pmvMatrix.glRotatef(view_roty, 0.0f, 1.0f, 0.0f);
+ pmvMatrix.glRotatef(view_rotz, 0.0f, 0.0f, 1.0f);
+
+ synchronized ( syncObjects ) {
+ gear1.draw(gl, -3.0f, -2.0f, 1f * angle - 0f);
+ gear2.draw(gl, 3.1f, -2.0f, -2f * angle - 9.0f);
+ gear3.draw(gl, -3.1f, 4.2f, -2f * angle - 25.0f);
+ }
+ pmvMatrix.glPopMatrix();
+ st.useProgram(gl, false);
+
+ setGLStates(gl, false);
+ }
+
+ public void setGLStates(final GL2ES2 gl, final boolean enable) {
+ // Culling only possible if we do not flip the projection matrix
+ final boolean useCullFace = ! ( flipVerticalInGLOrientation && gl.getContext().getGLDrawable().isGLOriented() || customRendering );
+ if( enable ) {
+ gl.glEnable(GL.GL_DEPTH_TEST);
+ if( useCullFace ) {
+ gl.glEnable(GL.GL_CULL_FACE);
+ }
+ } else {
+ gl.glDisable(GL.GL_DEPTH_TEST);
+ if( useCullFace ) {
+ gl.glDisable(GL.GL_CULL_FACE);
+ }
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "GearsES2[obj "+sid()+" isInit "+isInit+", usesShared "+usesSharedGears+", 1 "+gear1+", 2 "+gear2+", 3 "+gear3+", sharedGears "+sharedGears+"]";
+ }
+
+ class GearsKeyAdapter extends KeyAdapter {
+ public void keyPressed(final KeyEvent e) {
+ final int kc = e.getKeyCode();
+ if(KeyEvent.VK_LEFT == kc) {
+ view_roty -= 1;
+ } else if(KeyEvent.VK_RIGHT == kc) {
+ view_roty += 1;
+ } else if(KeyEvent.VK_UP == kc) {
+ view_rotx -= 1;
+ } else if(KeyEvent.VK_DOWN == kc) {
+ view_rotx += 1;
+ }
+ }
+ }
+
+ class GearsMouseAdapter implements MouseListener{
+ private int prevMouseX, prevMouseY;
+
+ @Override
+ public void mouseClicked(final MouseEvent e) {
+ }
+
+ @Override
+ public void mouseEntered(final MouseEvent e) {
+ }
+
+ @Override
+ public void mouseExited(final MouseEvent e) {
+ }
+
+ @Override
+ public void mouseWheelMoved(final MouseEvent e) {
+ final float[] rot = e.getRotation();
+ if( e.isControlDown() ) {
+ // alternative zoom
+ final float incr = e.isShiftDown() ? rot[0] : rot[1] * 0.5f ;
+ panZ += incr;
+ System.err.println("panZ.2: incr "+incr+", dblZoom "+e.isShiftDown()+" -> "+panZ);
+ } else {
+ // panning
+ panX -= rot[0]; // positive -> left
+ panY += rot[1]; // positive -> up
+ }
+ }
+
+ public void mousePressed(final MouseEvent e) {
+ if( e.getPointerCount()==1 ) {
+ prevMouseX = e.getX();
+ prevMouseY = e.getY();
+ } else if( e.getPointerCount() == 4 ) {
+ final Object src = e.getSource();
+ if( e.getPressure(0, true) > 0.7f && src instanceof Window) { // show Keyboard
+ ((Window) src).setKeyboardVisible(true);
+ }
+ }
+ }
+
+ public void mouseReleased(final MouseEvent e) {
+ }
+
+ public void mouseMoved(final MouseEvent e) {
+ if( e.isConfined() ) {
+ navigate(e);
+ } else {
+ // track prev. position so we don't have 'jumps'
+ // in case we move to confined navigation.
+ prevMouseX = e.getX();
+ prevMouseY = e.getY();
+ }
+ }
+
+ public void mouseDragged(final MouseEvent e) {
+ navigate(e);
+ }
+
+ private void navigate(final MouseEvent e) {
+ final int x = e.getX();
+ final int y = e.getY();
+
+ int width, height;
+ final Object source = e.getSource();
+ Window window = null;
+ if(source instanceof Window) {
+ window = (Window) source;
+ width=window.getSurfaceWidth();
+ height=window.getSurfaceHeight();
+ } else if (source instanceof GLAutoDrawable) {
+ final GLAutoDrawable glad = (GLAutoDrawable) source;
+ width = glad.getSurfaceWidth();
+ height = glad.getSurfaceHeight();
+ } else {
+ throw new RuntimeException("Event source neither Window nor Component: "+source);
+ }
+ final float thetaY = 360.0f * ( (float)(x-prevMouseX)/(float)width);
+ final float thetaX = 360.0f * ( (float)(prevMouseY-y)/(float)height);
+ view_rotx += thetaX;
+ view_roty += thetaY;
+ prevMouseX = x;
+ prevMouseY = y;
+ // System.err.println("rotXY.1: "+view_rotx+"/"+view_roty+", source "+e);
+ }
+ }
+}
diff --git a/src/demos/com/jogamp/opengl/demos/es2/GearsObjectES2.java b/src/demos/com/jogamp/opengl/demos/es2/GearsObjectES2.java
new file mode 100644
index 000000000..7266240b1
--- /dev/null
+++ b/src/demos/com/jogamp/opengl/demos/es2/GearsObjectES2.java
@@ -0,0 +1,146 @@
+/**
+ * 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.demos.es2;
+
+import java.nio.FloatBuffer;
+
+import com.jogamp.opengl.GL;
+import com.jogamp.opengl.GL2ES2;
+import com.jogamp.opengl.GLBufferStorage;
+import com.jogamp.opengl.GLException;
+import com.jogamp.opengl.GLUniformData;
+
+import com.jogamp.opengl.util.GLArrayDataServer;
+import com.jogamp.opengl.util.PMVMatrix;
+import com.jogamp.opengl.util.glsl.ShaderState;
+
+import com.jogamp.opengl.demos.GearsObject;
+
+/**
+ * GearsObjectES2.java <BR>
+ * @author Brian Paul (converted to Java by Ron Cemer and Sven Gothel) <P>
+ */
+public class GearsObjectES2 extends GearsObject {
+ final PMVMatrix pmvMatrix;
+ final GLUniformData pmvMatrixUniform;
+ final GLUniformData colorUniform;
+ final ShaderState st;
+
+ public GearsObjectES2(final GL gl, final boolean useMappedBuffers, final ShaderState st, final FloatBuffer gearColor,
+ final float inner_radius, final float outer_radius,
+ final float width,
+ final int teeth,
+ final float tooth_depth, final PMVMatrix pmvMatrix, final GLUniformData pmvMatrixUniform, final GLUniformData colorUniform, final boolean validateBuffers)
+ {
+ super(gl, useMappedBuffers, gearColor, inner_radius, outer_radius, width, teeth, tooth_depth, validateBuffers);
+ this.pmvMatrix = pmvMatrix;
+ this.pmvMatrixUniform = pmvMatrixUniform;
+ this.colorUniform = colorUniform;
+ this.st = st;
+ associate(st);
+ }
+
+ public GearsObjectES2(final GearsObjectES2 shared,
+ final ShaderState st,
+ final PMVMatrix pmvMatrix,
+ final GLUniformData pmvMatrixUniform, final GLUniformData colorUniform)
+ {
+ super(shared);
+ this.pmvMatrix = pmvMatrix;
+ this.pmvMatrixUniform = pmvMatrixUniform;
+ this.colorUniform = colorUniform;
+ this.st = st;
+ associate(st);
+ }
+
+ private void associate(final ShaderState st) {
+ frontFace.associate(st, true);
+ frontSide.associate(st, true);
+ backFace.associate(st, true);
+ backSide.associate(st, true);
+ outwardFace.associate(st, true);
+ insideRadiusCyl.associate(st, true);
+ }
+
+ @Override
+ public GLArrayDataServer createInterleaved(final boolean useMappedBuffers, final int comps, final int dataType, final boolean normalized, final int initialSize, final int vboUsage) {
+ if( useMappedBuffers ) {
+ return GLArrayDataServer.createGLSLInterleavedMapped(comps, dataType, normalized, initialSize, vboUsage);
+ } else {
+ return GLArrayDataServer.createGLSLInterleaved(comps, dataType, normalized, initialSize, vboUsage);
+ }
+ }
+
+ @Override
+ public void addInterleavedVertexAndNormalArrays(final GLArrayDataServer array, final int components) {
+ array.addGLSLSubArray("vertices", components, GL.GL_ARRAY_BUFFER);
+ array.addGLSLSubArray("normals", components, GL.GL_ARRAY_BUFFER);
+ }
+
+ private void draw(final GL2ES2 gl, final GLArrayDataServer array, final int mode, final int face) {
+ if( !isShared || gl.glIsBuffer(array.getVBOName()) ) {
+ if( validateBuffers ) {
+ array.bindBuffer(gl, true);
+ final int bufferTarget = array.getVBOTarget();
+ final int bufferName = array.getVBOName();
+ final long bufferSize = array.getSizeInBytes();
+ final int hasBufferName = gl.getBoundBuffer(bufferTarget);
+ final GLBufferStorage hasStorage = gl.getBufferStorage(hasBufferName);
+ final boolean ok = bufferName == hasBufferName &&
+ bufferName == hasStorage.getName() &&
+ bufferSize == hasStorage.getSize();
+ if( !ok ) {
+ throw new GLException("GLBufferStorage Validation Error: Target[exp 0x"+Integer.toHexString(bufferTarget)+", has 0x"+Integer.toHexString(bufferTarget)+
+ ", Name[exp "+bufferName+", has "+hasBufferName+", Size exp "+bufferSize+", Storage "+hasStorage+"]");
+ }
+ }
+ array.enableBuffer(gl, true);
+ // System.err.println("XXX Draw face "+face+" of "+this);
+ gl.glDrawArrays(mode, 0, array.getElementCount());
+ array.enableBuffer(gl, false);
+ }
+ }
+
+ @Override
+ public void draw(final GL _gl, final float x, final float y, final float angle) {
+ final GL2ES2 gl = _gl.getGL2ES2();
+ pmvMatrix.glPushMatrix();
+ pmvMatrix.glTranslatef(x, y, 0f);
+ pmvMatrix.glRotatef(angle, 0f, 0f, 1f);
+ if( pmvMatrix.update() ) {
+ st.uniform(gl, pmvMatrixUniform);
+ } else {
+ throw new InternalError("PMVMatrix.update() returns false after mutable operations");
+ }
+
+ colorUniform.setData(gearColor);
+ st.uniform(gl, colorUniform);
+
+ draw(gl, frontFace, GL.GL_TRIANGLE_STRIP, 0);
+ draw(gl, frontSide, GL.GL_TRIANGLES, 1);
+ draw(gl, backFace, GL.GL_TRIANGLE_STRIP, 2);
+ draw(gl, backSide, GL.GL_TRIANGLES, 3);
+ draw(gl, outwardFace, GL.GL_TRIANGLE_STRIP, 4);
+ draw(gl, insideRadiusCyl, GL.GL_TRIANGLE_STRIP, 5);
+
+ pmvMatrix.glPopMatrix();
+ }
+}
diff --git a/src/demos/com/jogamp/opengl/demos/es2/LandscapeES2.java b/src/demos/com/jogamp/opengl/demos/es2/LandscapeES2.java
new file mode 100644
index 000000000..0a42ae302
--- /dev/null
+++ b/src/demos/com/jogamp/opengl/demos/es2/LandscapeES2.java
@@ -0,0 +1,187 @@
+/**
+ * Copyright 2013 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.demos.es2;
+
+import com.jogamp.opengl.util.GLArrayDataServer;
+import com.jogamp.opengl.util.glsl.ShaderCode;
+import com.jogamp.opengl.util.glsl.ShaderProgram;
+import com.jogamp.opengl.util.glsl.ShaderState;
+import java.nio.FloatBuffer;
+
+import com.jogamp.opengl.GL;
+import com.jogamp.opengl.GL2ES2;
+import com.jogamp.opengl.GLAutoDrawable;
+import com.jogamp.opengl.GLEventListener;
+import com.jogamp.opengl.GLUniformData;
+
+/**
+ * LandscapeES2
+ */
+public class LandscapeES2 implements GLEventListener {
+ private int swapInterval = 0;
+ private boolean verbose = true;
+
+ static public final int TARGET_FPS = 120;
+ private long millisOffset;
+ private int frameCount;
+ private float frameRate;
+ private ShaderCode vertShader;
+ private ShaderCode fragShader;
+ private ShaderProgram shaderProg;
+ private ShaderState shaderState;
+ private float[] resolution;
+ private GLUniformData resolutionUni;
+ private GLUniformData timeUni;
+ private GLArrayDataServer vertices;
+
+ private int fcount = 0, lastm = 0;
+ private final int fint = 1;
+
+ public LandscapeES2(final int swapInterval) {
+ this.swapInterval = swapInterval;
+ }
+
+ public LandscapeES2() {
+ this.swapInterval = 1;
+ }
+
+ public void setVerbose(final boolean v) { verbose = v; }
+
+ public void init(final GLAutoDrawable drawable) {
+ System.err.println(Thread.currentThread()+" LandscapeES2.init ...");
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+
+ if(verbose) {
+ System.err.println("LandscapeES2 init on "+Thread.currentThread());
+ System.err.println("Chosen GLCapabilities: " + drawable.getChosenGLCapabilities());
+ System.err.println("INIT GL IS: " + gl.getClass().getName());
+ System.err.println("GL_VENDOR: " + gl.glGetString(GL.GL_VENDOR));
+ System.err.println("GL_RENDERER: " + gl.glGetString(GL.GL_RENDERER));
+ System.err.println("GL_VERSION: " + gl.glGetString(GL.GL_VERSION));
+ System.err.println("GL GLSL: "+gl.hasGLSL()+", has-compiler-func: "+gl.isFunctionAvailable("glCompileShader")+", version "+(gl.hasGLSL() ? gl.glGetString(GL2ES2.GL_SHADING_LANGUAGE_VERSION) : "none")+", "+gl.getContext().getGLSLVersionNumber());
+ System.err.println("GL FBO: basic "+ gl.hasBasicFBOSupport()+", full "+gl.hasFullFBOSupport());
+ System.err.println("GL Profile: "+gl.getGLProfile());
+ System.err.println("GL Renderer Quirks:" + gl.getContext().getRendererQuirks().toString());
+ System.err.println("GL:" + gl + ", " + gl.getContext().getGLVersion());
+ }
+
+ vertShader = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, this.getClass(), "shader", "shader/bin", "landscape", true);
+ fragShader = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, this.getClass(), "shader", "shader/bin", "landscape", true);
+ vertShader.defaultShaderCustomization(gl, true, true);
+ fragShader.defaultShaderCustomization(gl, true, true);
+ shaderProg = new ShaderProgram();
+ shaderProg.add(gl, vertShader, System.err);
+ shaderProg.add(gl, fragShader, System.err);
+
+ shaderState = new ShaderState();
+ shaderState.attachShaderProgram(gl, shaderProg, true);
+
+ resolution = new float[] { drawable.getSurfaceWidth(), drawable.getSurfaceHeight(), 0};
+ resolutionUni = new GLUniformData("iResolution", 3, FloatBuffer.wrap(resolution));
+ shaderState.ownUniform(resolutionUni);
+ shaderState.uniform(gl, resolutionUni);
+
+ timeUni = new GLUniformData("iGlobalTime", 0.0f);
+ shaderState.ownUniform(timeUni);
+
+ vertices = GLArrayDataServer.createGLSL("inVertex", 2, GL.GL_FLOAT, false, 4, GL.GL_STATIC_DRAW);
+ vertices.putf(-1.0f); vertices.putf(-1.0f);
+ vertices.putf(+1.0f); vertices.putf(-1.0f);
+ vertices.putf(-1.0f); vertices.putf(+1.0f);
+ vertices.putf(+1.0f); vertices.putf(+1.0f);
+ vertices.seal(gl, true);
+ shaderState.ownAttribute(vertices, true);
+ shaderState.useProgram(gl, false);
+
+ millisOffset = System.currentTimeMillis();
+
+ System.err.println(Thread.currentThread()+" LandscapeES2.init FIN");
+ }
+
+ public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {
+ System.err.println(Thread.currentThread()+" LandscapeES2.reshape "+x+"/"+y+" "+width+"x"+height+", swapInterval "+swapInterval+", drawable 0x"+Long.toHexString(drawable.getHandle()));
+
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+
+ gl.setSwapInterval(swapInterval); // in case switching the drawable (impl. may bound attribute there)
+
+ shaderState.useProgram(gl, true);
+
+ resolution[0] = drawable.getSurfaceWidth();
+ resolution[1] = drawable.getSurfaceHeight();
+ shaderState.uniform(gl, resolutionUni);
+
+ shaderState.useProgram(gl, false);
+ }
+
+ public void dispose(final GLAutoDrawable drawable) {
+ System.err.println(Thread.currentThread()+" LandscapeES2.dispose ... ");
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+ shaderState.useProgram(gl, false);
+ shaderState.destroy(gl);
+ shaderState = null;
+
+ System.err.println(Thread.currentThread()+" LandscapeES2.dispose FIN");
+ }
+
+ public void display(final GLAutoDrawable drawable) {
+ final GL2ES2 gl = drawable.getGL().getGL2ES2();
+ // Shader fills complete framebuffer regardless of DEPTH, no Clear required.
+ // gl.glClearColor(0.5f, 0.1f, 0.1f, 1);
+ // gl.glClear(GL.GL_COLOR_BUFFER_BIT);
+
+ shaderState.useProgram(gl, true);
+
+ timeUni.setData((System.currentTimeMillis() - millisOffset) / 1000.0f);
+ shaderState.uniform(gl, timeUni);
+ vertices.enableBuffer(gl, true);
+ gl.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 4);
+ vertices.enableBuffer(gl, false);
+
+ shaderState.useProgram(gl, false);
+
+ // Compute current framerate and printout.
+ frameCount++;
+ fcount += 1;
+ final int m = (int) (System.currentTimeMillis() - millisOffset);
+ if (m - lastm > 1000 * fint) {
+ frameRate = (float)(fcount) / fint;
+ fcount = 0;
+ lastm = m;
+ }
+ if (frameCount % TARGET_FPS == 0) {
+ System.out.println("FrameCount: " + frameCount + " - " + "FrameRate: " + frameRate);
+ }
+ }
+
+ boolean confinedFixedCenter = false;
+
+ public void setConfinedFixedCenter(final boolean v) {
+ confinedFixedCenter = v;
+ }
+}
diff --git a/src/demos/com/jogamp/opengl/demos/es2/PointsDemoES2.java b/src/demos/com/jogamp/opengl/demos/es2/PointsDemoES2.java
new file mode 100644
index 000000000..0b4dac9b2
--- /dev/null
+++ b/src/demos/com/jogamp/opengl/demos/es2/PointsDemoES2.java
@@ -0,0 +1,208 @@
+/**
+ * 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.demos.es2;
+
+import java.nio.FloatBuffer;
+
+import com.jogamp.common.nio.Buffers;
+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;
+
+import com.jogamp.opengl.GL;
+import com.jogamp.opengl.GL2ES1;
+import com.jogamp.opengl.GL2ES2;
+import com.jogamp.opengl.GL2GL3;
+import com.jogamp.opengl.GLAutoDrawable;
+import com.jogamp.opengl.GLUniformData;
+import com.jogamp.opengl.fixedfunc.GLMatrixFunc;
+
+import com.jogamp.opengl.demos.PointsDemo;
+
+public class PointsDemoES2 extends PointsDemo {
+ ShaderState st;
+ PMVMatrix pmvMatrix;
+ GLUniformData pmvMatrixUniform;
+ GLArrayDataServer vertices ;
+ GLArrayDataServer pointSizes ;
+ private int swapInterval = 0;
+ final int edge = 8; // 8*8
+ /** vec4[2]: { (sz, smooth, attnMinSz, attnMaxSz), (attnCoeff(3), attnFadeTs) } */
+ private static final String mgl_PointParams = "mgl_PointParams";
+
+ /** ( pointSize, pointSmooth, attn. pointMinSize, attn. pointMaxSize ) , ( attenuation coefficients 1f 0f 0f, attenuation fade theshold 1f ) */
+ private final FloatBuffer pointParams = Buffers.newDirectFloatBuffer(new float[] { 1.0f, 0.0f, 0.0f, 4096.0f, 1.0f, 0.0f, 0.0f, 1.0f });
+
+ public PointsDemoES2(final int swapInterval) {
+ this.swapInterval = swapInterval;
+ }
+
+ public PointsDemoES2() {
+ this.swapInterval = 1;
+ }
+
+ public void setSmoothPoints(final boolean v) {
+ pointParams.put(1, v ? 1.0f : 0.0f);
+ }
+
+ public void setPointParams(final float minSize, final float maxSize, final float distAttenConst, final float distAttenLinear, final float distAttenQuadratic, final float fadeThreshold) {
+ pointParams.put(2, minSize);
+ pointParams.put(3, maxSize);
+ pointParams.put(4+0, distAttenConst);
+ pointParams.put(4+1, distAttenLinear);
+ pointParams.put(4+2, distAttenQuadratic);
+ pointParams.put(4+3, fadeThreshold);
+ }
+
+ public void init(final GLAutoDrawable glad) {
+ final GL2ES2 gl = glad.getGL().getGL2ES2();
+
+ System.err.println("GL_VENDOR: " + gl.glGetString(GL.GL_VENDOR));
+ System.err.println("GL_RENDERER: " + gl.glGetString(GL.GL_RENDERER));
+ System.err.println("GL_VERSION: " + gl.glGetString(GL.GL_VERSION));
+ System.err.println("GL GLSL: "+gl.hasGLSL()+", has-compiler-func: "+gl.isFunctionAvailable("glCompileShader")+", version "+(gl.hasGLSL() ? gl.glGetString(GL2ES2.GL_SHADING_LANGUAGE_VERSION) : "none"));
+ System.err.println("GL Profile: "+gl.getGLProfile());
+
+ st = new ShaderState();
+ st.setVerbose(true);
+ final ShaderCode vp0 = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, this.getClass(), "shader",
+ "shader/bin", "PointsShader", true);
+ final ShaderCode fp0 = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, this.getClass(), "shader",
+ "shader/bin", "PointsShader", true);
+ vp0.defaultShaderCustomization(gl, true, true);
+ fp0.defaultShaderCustomization(gl, true, true);
+ final ShaderProgram sp0 = new ShaderProgram();
+ sp0.add(gl, vp0, System.err);
+ sp0.add(gl, fp0, System.err);
+ st.attachShaderProgram(gl, sp0, true);
+
+ // setup mgl_PMVMatrix
+ pmvMatrix = new PMVMatrix();
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
+ pmvMatrix.glLoadIdentity();
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
+ pmvMatrix.glLoadIdentity();
+ pmvMatrixUniform = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf()); // P, Mv
+ st.ownUniform(pmvMatrixUniform);
+ st.uniform(gl, pmvMatrixUniform);
+
+ st.uniform(gl, new GLUniformData(mgl_PointParams, 4, pointParams));
+
+ final GLUniformData colorStaticUniform = new GLUniformData("mgl_ColorStatic", 4, Buffers.newDirectFloatBuffer(new float[] { 1.0f, 1.0f, 1.0f, 1.0f }) );
+ st.uniform(gl, colorStaticUniform);
+ st.ownUniform(colorStaticUniform);
+
+ // Allocate Vertex Array
+ vertices = GLArrayDataServer.createGLSL("mgl_Vertex", 3, GL.GL_FLOAT, false, edge*edge, GL.GL_STATIC_DRAW);
+ pointSizes = GLArrayDataServer.createGLSL("mgl_PointSize", 1, GL.GL_FLOAT, false, edge*edge, GL.GL_STATIC_DRAW);
+ for(int i=0; i<edge; i++) {
+ for(int j=0; j<edge; j++) {
+ final float x = -3+j*0.7f;
+ final float y = -3+i*0.7f;
+ final float p = (i*edge+j)*0.5f;
+ // System.err.println("["+j+"/"+i+"]: "+x+"/"+y+": "+p);
+ vertices.putf(x); vertices.putf(y); vertices.putf( 0);
+ pointSizes.putf(p);
+ }
+ }
+ vertices.seal(gl, true);
+ st.ownAttribute(vertices, true);
+ vertices.enableBuffer(gl, false);
+ pointSizes.seal(gl, true);
+ st.ownAttribute(pointSizes, true);
+ pointSizes.enableBuffer(gl, false);
+
+ // OpenGL Render Settings
+ gl.glEnable(GL.GL_DEPTH_TEST);
+ st.useProgram(gl, false);
+ }
+
+ public void display(final GLAutoDrawable glad) {
+ final GL2ES2 gl = glad.getGL().getGL2ES2();
+ gl.glClearColor(0f, 0f, 0f, 0f);
+ gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
+ st.useProgram(gl, true);
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
+ pmvMatrix.glLoadIdentity();
+ pmvMatrix.glTranslatef(0, 0, -10);
+ st.uniform(gl, pmvMatrixUniform);
+
+ final GLUniformData ud = st.getUniform(mgl_PointParams);
+ if(null!=ud) {
+ // same data object
+ st.uniform(gl, ud);
+ }
+
+ vertices.enableBuffer(gl, true);
+ pointSizes.enableBuffer(gl, true);
+
+ if(gl.isGL2GL3()) {
+ gl.glEnable(GL2GL3.GL_VERTEX_PROGRAM_POINT_SIZE);
+ }
+ if(gl.isGL2ES1()) {
+ gl.glEnable(GL2ES1.GL_POINT_SPRITE); // otherwise no gl_PointCoord
+ }
+ gl.glEnable ( GL.GL_BLEND );
+ gl.glBlendFunc ( GL.GL_SRC_ALPHA, GL.GL_ONE );
+
+ gl.glDrawArrays(GL.GL_POINTS, 0, edge*edge);
+
+ if(gl.isGL2GL3()) {
+ gl.glDisable(GL2GL3.GL_VERTEX_PROGRAM_POINT_SIZE);
+ }
+
+ pointSizes.enableBuffer(gl, false);
+ vertices.enableBuffer(gl, false);
+ st.useProgram(gl, false);
+ }
+
+ public void reshape(final GLAutoDrawable glad, final int x, final int y, final int width, final int height) {
+ // Thread.dumpStack();
+ final GL2ES2 gl = glad.getGL().getGL2ES2();
+
+ gl.setSwapInterval(swapInterval); // in case switching the drawable (impl. may bound attribute there)
+
+ st.useProgram(gl, true);
+ // Set location in front of camera
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
+ pmvMatrix.glLoadIdentity();
+ pmvMatrix.gluPerspective(45.0F, ( (float) width / (float) height ) / 1.0f, 1.0F, 100.0F);
+ //pmvMatrix.glOrthof(-4.0f, 4.0f, -4.0f, 4.0f, 1.0f, 100.0f);
+ st.uniform(gl, pmvMatrixUniform);
+ st.useProgram(gl, false);
+ }
+
+ public void dispose(final GLAutoDrawable glad) {
+ final GL2ES2 gl = glad.getGL().getGL2ES2();
+ st.destroy(gl);
+ st = null;
+ pmvMatrix = null;
+ }
+}
diff --git a/src/demos/com/jogamp/opengl/demos/es2/RedSquareES2.java b/src/demos/com/jogamp/opengl/demos/es2/RedSquareES2.java
new file mode 100644
index 000000000..a6e1f5cd9
--- /dev/null
+++ b/src/demos/com/jogamp/opengl/demos/es2/RedSquareES2.java
@@ -0,0 +1,274 @@
+/**
+ * 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.demos.es2;
+
+import com.jogamp.opengl.JoglVersion;
+import com.jogamp.opengl.util.GLArrayDataServer;
+import com.jogamp.opengl.util.PMVMatrix;
+import com.jogamp.opengl.util.TileRendererBase;
+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.GL;
+import com.jogamp.opengl.GL2ES2;
+import com.jogamp.opengl.GLAutoDrawable;
+import com.jogamp.opengl.GLEventListener;
+import com.jogamp.opengl.GLUniformData;
+import com.jogamp.opengl.fixedfunc.GLMatrixFunc;
+
+public class RedSquareES2 implements GLEventListener, TileRendererBase.TileRendererListener {
+ private ShaderState st;
+ private PMVMatrix pmvMatrix;
+ private GLUniformData pmvMatrixUniform;
+ private GLArrayDataServer vertices ;
+ private GLArrayDataServer colors ;
+ private long t0;
+ private int swapInterval = 0;
+ private float aspect = 1.0f;
+ private boolean doRotate = true;
+ private boolean verbose = true;
+ private boolean clearBuffers = true;
+ private TileRendererBase tileRendererInUse = null;
+ private boolean doRotateBeforePrinting;
+
+ public RedSquareES2(final int swapInterval) {
+ this.swapInterval = swapInterval;
+ }
+
+ public RedSquareES2() {
+ this.swapInterval = 1;
+ }
+
+ @Override
+ public void addTileRendererNotify(final TileRendererBase tr) {
+ tileRendererInUse = tr;
+ doRotateBeforePrinting = doRotate;
+ setDoRotation(false);
+ }
+ @Override
+ public void removeTileRendererNotify(final TileRendererBase tr) {
+ tileRendererInUse = null;
+ setDoRotation(doRotateBeforePrinting);
+ }
+ @Override
+ public void startTileRendering(final TileRendererBase tr) {
+ System.err.println("RedSquareES2.startTileRendering: "+tr);
+ }
+ @Override
+ public void endTileRendering(final TileRendererBase tr) {
+ System.err.println("RedSquareES2.endTileRendering: "+tr);
+ }
+
+ public void setAspect(final float aspect) { this.aspect = aspect; }
+ public void setDoRotation(final boolean rotate) { this.doRotate = rotate; }
+ public void setClearBuffers(final boolean v) { clearBuffers = v; }
+ public void setVerbose(final boolean v) { verbose = v; }
+
+ @Override
+ public void init(final GLAutoDrawable glad) {
+ if(verbose) {
+ System.err.println(Thread.currentThread()+" RedSquareES2.init: tileRendererInUse "+tileRendererInUse);
+ }
+ final GL2ES2 gl = glad.getGL().getGL2ES2();
+
+ if(verbose) {
+ System.err.println("RedSquareES2 init on "+Thread.currentThread());
+ System.err.println("Chosen GLCapabilities: " + glad.getChosenGLCapabilities());
+ System.err.println("INIT GL IS: " + gl.getClass().getName());
+ System.err.println(JoglVersion.getGLStrings(gl, null, false).toString());
+ }
+ if( !gl.hasGLSL() ) {
+ System.err.println("No GLSL available, no rendering.");
+ return;
+ }
+ st = new ShaderState();
+ st.setVerbose(true);
+ final ShaderCode vp0 = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, this.getClass(), "shader",
+ "shader/bin", "RedSquareShader", true);
+ final ShaderCode fp0 = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, this.getClass(), "shader",
+ "shader/bin", "RedSquareShader", true);
+ vp0.defaultShaderCustomization(gl, true, true);
+ fp0.defaultShaderCustomization(gl, true, true);
+ final ShaderProgram sp0 = new ShaderProgram();
+ sp0.add(gl, vp0, System.err);
+ sp0.add(gl, fp0, System.err);
+ st.attachShaderProgram(gl, sp0, true);
+
+ // setup mgl_PMVMatrix
+ pmvMatrix = new PMVMatrix();
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
+ pmvMatrix.glLoadIdentity();
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
+ pmvMatrix.glLoadIdentity();
+ pmvMatrixUniform = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf()); // P, Mv
+ st.ownUniform(pmvMatrixUniform);
+ st.uniform(gl, pmvMatrixUniform);
+
+ // Allocate Vertex Array
+ vertices = GLArrayDataServer.createGLSL("mgl_Vertex", 3, GL.GL_FLOAT, false, 4, GL.GL_STATIC_DRAW);
+ vertices.putf(-2); vertices.putf( 2); vertices.putf( 0);
+ vertices.putf( 2); vertices.putf( 2); vertices.putf( 0);
+ vertices.putf(-2); vertices.putf(-2); vertices.putf( 0);
+ vertices.putf( 2); vertices.putf(-2); vertices.putf( 0);
+ vertices.seal(gl, true);
+ st.ownAttribute(vertices, true);
+ vertices.enableBuffer(gl, false);
+
+ // Allocate Color Array
+ colors= GLArrayDataServer.createGLSL("mgl_Color", 4, GL.GL_FLOAT, false, 4, GL.GL_STATIC_DRAW);
+ colors.putf(1); colors.putf(0); colors.putf(0); colors.putf(1);
+ colors.putf(0); colors.putf(0); colors.putf(1); colors.putf(1);
+ colors.putf(1); colors.putf(0); colors.putf(0); colors.putf(1);
+ colors.putf(1); colors.putf(0); colors.putf(0); colors.putf(1);
+ colors.seal(gl, true);
+ st.ownAttribute(colors, true);
+ colors.enableBuffer(gl, false);
+
+ // OpenGL Render Settings
+ gl.glEnable(GL.GL_DEPTH_TEST);
+ st.useProgram(gl, false);
+
+ t0 = System.currentTimeMillis();
+ if(verbose) {
+ System.err.println(Thread.currentThread()+" RedSquareES2.init FIN");
+ }
+ }
+
+ @Override
+ public void display(final GLAutoDrawable glad) {
+ final long t1 = System.currentTimeMillis();
+
+ final GL2ES2 gl = glad.getGL().getGL2ES2();
+ if( clearBuffers ) {
+ if( null != tileRendererInUse ) {
+ gl.glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
+ } else {
+ gl.glClearColor(0, 0, 0, 0);
+ }
+ gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
+ }
+ if( !gl.hasGLSL() ) {
+ return;
+ }
+ st.useProgram(gl, true);
+ // One rotation every four seconds
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
+ pmvMatrix.glLoadIdentity();
+ pmvMatrix.glTranslatef(0, 0, -10);
+ if(doRotate) {
+ final float ang = ((t1 - t0) * 360.0F) / 4000.0F;
+ pmvMatrix.glRotatef(ang, 0, 0, 1);
+ pmvMatrix.glRotatef(ang, 0, 1, 0);
+ }
+ st.uniform(gl, pmvMatrixUniform);
+
+ // Draw a square
+ vertices.enableBuffer(gl, true);
+ colors.enableBuffer(gl, true);
+ gl.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 4);
+ vertices.enableBuffer(gl, false);
+ colors.enableBuffer(gl, false);
+ st.useProgram(gl, false);
+ }
+
+ @Override
+ public void reshape(final GLAutoDrawable glad, final int x, final int y, final int width, final int height) {
+ final GL2ES2 gl = glad.getGL().getGL2ES2();
+ gl.setSwapInterval(swapInterval);
+ reshapeImpl(gl, x, y, width, height, width, height);
+ }
+
+ @Override
+ public void reshapeTile(final TileRendererBase tr,
+ final int tileX, final int tileY, final int tileWidth, final int tileHeight,
+ final int imageWidth, final int imageHeight) {
+ final GL2ES2 gl = tr.getAttachedDrawable().getGL().getGL2ES2();
+ gl.setSwapInterval(0);
+ reshapeImpl(gl, tileX, tileY, tileWidth, tileHeight, imageWidth, imageHeight);
+ }
+
+ void reshapeImpl(final GL2ES2 gl, final int tileX, final int tileY, final int tileWidth, final int tileHeight, final int imageWidth, final int imageHeight) {
+ if(verbose) {
+ System.err.println(Thread.currentThread()+" RedSquareES2.reshape "+tileX+"/"+tileY+" "+tileWidth+"x"+tileHeight+" of "+imageWidth+"x"+imageHeight+", swapInterval "+swapInterval+", drawable 0x"+Long.toHexString(gl.getContext().getGLDrawable().getHandle())+", tileRendererInUse "+tileRendererInUse);
+ }
+ // Thread.dumpStack();
+ if( !gl.hasGLSL() ) {
+ return;
+ }
+
+ st.useProgram(gl, true);
+ // Set location in front of camera
+ pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
+ pmvMatrix.glLoadIdentity();
+
+ // compute projection parameters 'normal' perspective
+ final float fovy=45f;
+ final float aspect2 = ( (float) imageWidth / (float) imageHeight ) / aspect;
+ final float zNear=1f;
+ final float zFar=100f;
+
+ // compute projection parameters 'normal' frustum
+ final float top=(float)Math.tan(fovy*((float)Math.PI)/360.0f)*zNear;
+ final float bottom=-1.0f*top;
+ final float left=aspect2*bottom;
+ final float right=aspect2*top;
+ final float w = right - left;
+ final float h = top - bottom;
+
+ // compute projection parameters 'tiled'
+ final float l = left + tileX * w / imageWidth;
+ final float r = l + tileWidth * w / imageWidth;
+ final float b = bottom + tileY * h / imageHeight;
+ final float t = b + tileHeight * h / imageHeight;
+
+ pmvMatrix.glFrustumf(l, r, b, t, zNear, zFar);
+ //pmvMatrix.glOrthof(-4.0f, 4.0f, -4.0f, 4.0f, 1.0f, 100.0f);
+ st.uniform(gl, pmvMatrixUniform);
+ st.useProgram(gl, false);
+
+ System.err.println(Thread.currentThread()+" RedSquareES2.reshape FIN");
+ }
+
+ @Override
+ public void dispose(final GLAutoDrawable glad) {
+ if(verbose) {
+ System.err.println(Thread.currentThread()+" RedSquareES2.dispose: tileRendererInUse "+tileRendererInUse);
+ }
+ final GL2ES2 gl = glad.getGL().getGL2ES2();
+ if( !gl.hasGLSL() ) {
+ return;
+ }
+ st.destroy(gl);
+ st = null;
+ pmvMatrix = null;
+ if(verbose) {
+ System.err.println(Thread.currentThread()+" RedSquareES2.dispose FIN");
+ }
+ }
+}
diff --git a/src/demos/com/jogamp/opengl/demos/es2/shader/PointsShader.fp b/src/demos/com/jogamp/opengl/demos/es2/shader/PointsShader.fp
new file mode 100644
index 000000000..82268958f
--- /dev/null
+++ b/src/demos/com/jogamp/opengl/demos/es2/shader/PointsShader.fp
@@ -0,0 +1,53 @@
+
+#if __VERSION__ >= 130
+ #define varying in
+ out vec4 mgl_FragColor;
+#else
+ #define mgl_FragColor gl_FragColor
+#endif
+
+#ifdef GL_ES
+ #define MEDIUMP mediump
+#else
+ #define MEDIUMP
+#endif
+
+// [0].rgba: 0, smooth, attnMinSz, attnMaxSz
+// [1].rgba: attnCoeff(3), attnFadeTs
+uniform MEDIUMP vec4 mgl_PointParams[2];
+
+#define pointSmooth (mgl_PointParams[0].g)
+
+varying vec4 frontColor;
+
+// #define TEST 1
+
+void main (void)
+{
+ mgl_FragColor = frontColor;
+
+ if( pointSmooth > 0.5 ) {
+ // smooth (AA)
+ const float border = 0.90; // take/give 10% for AA
+
+ // origin to 0/0, [-1/-1 .. 1/1]
+ vec2 pointPos = 2.0 * gl_PointCoord - 1.0 ;
+ float r = length( pointPos ); // one-circle sqrt(x * x + y * y), range: in-circle [0..1], out >1
+ float r1 = 1.0 - ( step(border, r) * 10.0 * ( r - border ) ) ; // [0..1]
+ #ifndef TEST
+ if( r1 < 0.0 ) {
+ discard;
+ }
+ #endif
+
+ #ifndef TEST
+ mgl_FragColor.a *= r1;
+ #else
+ mgl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
+ mgl_FragColor.r = r1 < 0.0 ? 1.0 : 0.0;
+ mgl_FragColor.g = r > 1.0 ? 1.0 : 0.0;
+ mgl_FragColor.b = r > border ? 1.0 : 0.0;
+ #endif
+ }
+}
+
diff --git a/src/demos/com/jogamp/opengl/demos/es2/shader/PointsShader.vp b/src/demos/com/jogamp/opengl/demos/es2/shader/PointsShader.vp
new file mode 100644
index 000000000..562874785
--- /dev/null
+++ b/src/demos/com/jogamp/opengl/demos/es2/shader/PointsShader.vp
@@ -0,0 +1,53 @@
+
+#if __VERSION__ >= 130
+ #define attribute in
+ #define varying out
+#endif
+
+#ifdef GL_ES
+ #define MEDIUMP mediump
+#else
+ #define MEDIUMP
+#endif
+
+uniform vec4 mgl_ColorStatic;
+uniform mat4 mgl_PMVMatrix[4]; // P, Mv, Mvi and Mvit (transpose(inverse(ModelView)) == normalMatrix)
+
+// [0].rgba: 0, smooth, attnMinSz, attnMaxSz
+// [1].rgba: attnCoeff(3), attnFadeTs
+uniform MEDIUMP vec4 mgl_PointParams[2];
+
+#define pointSmooth (mgl_PointParams[0].g)
+#define pointSizeMin (mgl_PointParams[0].b)
+#define pointSizeMax (mgl_PointParams[0].a)
+#define pointDistanceConstantAtten (mgl_PointParams[1].r)
+#define pointDistanceLinearAtten (mgl_PointParams[1].g)
+#define pointDistanceQuadraticAtten (mgl_PointParams[1].b)
+#define pointFadeThresholdSize (mgl_PointParams[1].a)
+
+attribute vec4 mgl_Vertex;
+attribute float mgl_PointSize;
+
+varying vec4 frontColor;
+
+void main(void)
+{
+ frontColor = mgl_ColorStatic;
+
+ vec4 eyeCoord = mgl_PMVMatrix[1] * mgl_Vertex;
+ gl_Position = mgl_PMVMatrix[0] * eyeCoord;
+
+ float dist = distance(eyeCoord, vec4(0.0, 0.0, 0.0, 1.0));
+ float atten = sqrt( 1.0 / ( pointDistanceConstantAtten +
+ ( pointDistanceLinearAtten +
+ pointDistanceQuadraticAtten * dist
+ ) * dist
+ )
+ );
+ float size = clamp(mgl_PointSize * atten, pointSizeMin, pointSizeMax);
+ gl_PointSize = max(size, pointFadeThresholdSize);
+
+ float fade = min(size, pointFadeThresholdSize) / pointFadeThresholdSize;
+ frontColor.a *= fade * fade;
+}
+
diff --git a/src/demos/com/jogamp/opengl/demos/es2/shader/RedSquareShader.fp b/src/demos/com/jogamp/opengl/demos/es2/shader/RedSquareShader.fp
new file mode 100644
index 000000000..60b92401e
--- /dev/null
+++ b/src/demos/com/jogamp/opengl/demos/es2/shader/RedSquareShader.fp
@@ -0,0 +1,16 @@
+// Copyright 2010 JogAmp Community. All rights reserved.
+
+#if __VERSION__ >= 130
+ #define varying in
+ out vec4 mgl_FragColor;
+#else
+ #define mgl_FragColor gl_FragColor
+#endif
+
+varying vec4 frontColor;
+
+void main (void)
+{
+ mgl_FragColor = frontColor;
+}
+
diff --git a/src/demos/com/jogamp/opengl/demos/es2/shader/RedSquareShader.java b/src/demos/com/jogamp/opengl/demos/es2/shader/RedSquareShader.java
new file mode 100644
index 000000000..1f07ef1db
--- /dev/null
+++ b/src/demos/com/jogamp/opengl/demos/es2/shader/RedSquareShader.java
@@ -0,0 +1,73 @@
+/**
+ * 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.demos.es2.shader;
+
+public class RedSquareShader {
+ public static final String VERTEX_SHADER_TEXT =
+ " #ifdef GL_ES\n" +
+ " precision mediump float;\n" +
+ " precision mediump int;\n" +
+ "#endif\n" +
+ "\n" +
+ "#if __VERSION__ >= 130\n" +
+ " #define attribute in\n" +
+ " #define varying out\n" +
+ "#endif\n"+
+ "\n" +
+ "uniform mat4 mgl_PMVMatrix[2];\n" +
+ "attribute vec4 mgl_Vertex;\n" +
+ "attribute vec4 mgl_Color;\n" +
+ "varying vec4 frontColor;\n" +
+ "\n" +
+ "void main(void)\n" +
+ "{\n" +
+ " frontColor=mgl_Color;\n" +
+ " gl_Position = mgl_PMVMatrix[0] * mgl_PMVMatrix[1] * mgl_Vertex;\n" +
+ "}\n" ;
+
+ public static final String FRAGMENT_SHADER_TEXT =
+ " #ifdef GL_ES\n" +
+ " precision mediump float;\n" +
+ " precision mediump int;\n" +
+ "#endif\n" +
+ "\n" +
+ "#if __VERSION__ >= 130\n" +
+ " #define varying in\n" +
+ " out vec4 mgl_FragColor;\n" +
+ "#else\n" +
+ " #define mgl_FragColor gl_FragColor\n" +
+ "#endif\n" +
+ "\n" +
+ "varying vec4 frontColor;\n" +
+ "\n" +
+ "void main (void)\n" +
+ "{\n" +
+ " mgl_FragColor = frontColor;\n" +
+ "}\n" ;
+}
diff --git a/src/demos/com/jogamp/opengl/demos/es2/shader/RedSquareShader.vp b/src/demos/com/jogamp/opengl/demos/es2/shader/RedSquareShader.vp
new file mode 100644
index 000000000..9283dd7bd
--- /dev/null
+++ b/src/demos/com/jogamp/opengl/demos/es2/shader/RedSquareShader.vp
@@ -0,0 +1,18 @@
+// Copyright 2010 JogAmp Community. All rights reserved.
+
+#if __VERSION__ >= 130
+ #define attribute in
+ #define varying out
+#endif
+
+uniform mat4 mgl_PMVMatrix[2];
+attribute vec4 mgl_Vertex;
+attribute vec4 mgl_Color;
+varying vec4 frontColor;
+
+void main(void)
+{
+ frontColor=mgl_Color;
+ gl_Position = mgl_PMVMatrix[0] * mgl_PMVMatrix[1] * mgl_Vertex;
+}
+
diff --git a/src/demos/com/jogamp/opengl/demos/es2/shader/RedSquareShader2.fp b/src/demos/com/jogamp/opengl/demos/es2/shader/RedSquareShader2.fp
new file mode 100644
index 000000000..25a2df2d7
--- /dev/null
+++ b/src/demos/com/jogamp/opengl/demos/es2/shader/RedSquareShader2.fp
@@ -0,0 +1,16 @@
+// Copyright 2010 JogAmp Community. All rights reserved.
+
+#if __VERSION__ >= 130
+ #define varying in
+ out vec4 mgl_FragColor;
+#else
+ #define mgl_FragColor gl_FragColor
+#endif
+
+varying vec4 frontColor;
+
+void main (void)
+{
+ mgl_FragColor = vec4(0.0, frontColor.g, frontColor.b, 1.0);
+}
+
diff --git a/src/demos/com/jogamp/opengl/demos/es2/shader/default.vp b/src/demos/com/jogamp/opengl/demos/es2/shader/default.vp
new file mode 100644
index 000000000..2037086f1
--- /dev/null
+++ b/src/demos/com/jogamp/opengl/demos/es2/shader/default.vp
@@ -0,0 +1,24 @@
+//Copyright 2010 JogAmp Community. All rights reserved.
+
+#if __VERSION__ >= 130
+ #define attribute in
+ #define varying out
+#endif
+
+#ifdef GL_ES
+ #define MEDIUMP mediump
+ #define HIGHP highp
+ #define LOWP lowp
+#else
+ #define MEDIUMP
+ #define HIGHP
+ #define LOWP
+#endif
+
+uniform HIGHP mat4 gcu_PMVMatrix[3]; // P, Mv, and Mvi
+attribute HIGHP vec4 gca_Vertices;
+
+void main(void)
+{
+ gl_Position = gcu_PMVMatrix[0] * gcu_PMVMatrix[1] * gca_Vertices;
+}
diff --git a/src/demos/com/jogamp/opengl/demos/es2/shader/elektronenmultiplizierer_development.fp b/src/demos/com/jogamp/opengl/demos/es2/shader/elektronenmultiplizierer_development.fp
new file mode 100644
index 000000000..60f054b46
--- /dev/null
+++ b/src/demos/com/jogamp/opengl/demos/es2/shader/elektronenmultiplizierer_development.fp
@@ -0,0 +1,389 @@
+/**
+ * Copyright 2011 JogAmp Community. All rights reserved.
+ *
+ * Details see: src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/ElektronenMultiplizierer.java
+ */
+
+/**
+ * http://www.youtube.com/user/DemoscenePassivist
+ * author: Dominik Stroehlein (DemoscenePassivist)
+ **/
+
+#if __VERSION__ >= 130
+ #define varying in
+ out vec4 mgl_FragColor;
+ #define texture2D texture
+#else
+ #define mgl_FragColor gl_FragColor
+#endif
+
+#ifdef GL_ES
+ precision mediump float;
+ precision mediump sampler2D;
+ precision mediump int;
+#endif
+
+uniform int en; //effectnumber
+uniform float et; //effecttime
+uniform sampler2D fb; //fbotexture
+uniform float br; //brightness
+uniform float tm; //time
+uniform vec2 resolution;//screen resolution/fbo resolution
+
+float camerafocallengthdode;
+vec3 camerapositiondode;
+vec2 sizedode;
+vec3 backgroundcolor = vec3(0,0.6,0.46);
+mat3 worldrotationxyz;
+mat3 fractalplanerotationx;
+mat3 fractalplanerotationy;
+mat3 camerarotationdode;
+vec2 oglFragCoord;
+
+//fractal formula used for sphreretracing/distance-estimation
+//dodecahedron serpinski (knighty)
+//http://www.fractalforums.com/index.php?topic=3158.msg16982#msg16982
+//normal vectors for the dodecahedra-siepinski folding planes are:
+//(phi^2, 1, -phi), (-phi, phi^2, 1), (1, -phi, phi^2), (-phi*(1+phi), phi^2-1, 1+phi), (1+phi, -phi*(1+phi), phi^2-1) and x=0, y=0, z=0 planes.
+
+//const pre-calc
+const float phi = 1.618;
+// Using math functions in initializers fails on MacOSX
+// const float _IKVNORM_ = 1.0 / sqrt(pow(phi * (1.0 + phi), 2.0) + pow(phi * phi - 1.0, 2.0) + pow(1.0 + phi, 2.0));
+const float _IKVNORM_ = 0.190989113930771;
+const float _C1_ = phi * (1.0 + phi) * _IKVNORM_;
+const float _C2_ = (phi * phi - 1.0) * _IKVNORM_;
+const float _1C_ = (1.0 + phi) * _IKVNORM_;
+const vec3 phi3 = vec3(0.5, 0.5 / phi, 0.5 * phi);
+const vec3 c3 = vec3(_C1_, _C2_, _1C_);
+
+vec3 distancefunction(vec3 w) {
+//!P center scale offset ...
+ vec3 offset;
+ if (en==6) {
+ offset = vec3(0.61,0.1*et,0.99);
+ } else {
+ offset = vec3(0.61,0.0,0.99);
+ }
+//!P center scale \0/ this is awesome for fadeins !!!
+ float scale = 2.;
+ w *= worldrotationxyz;
+ float d, t;
+ float md = 1000.0, cd = 0.0;
+//!P iterations (8) ... 2x see below
+ for (int i = 0; i < 8; i++) {
+ w *= fractalplanerotationx;
+ w = abs(w);
+ t = w.x * phi3.z + w.y * phi3.y - w.z * phi3.x;
+ if (t < 0.0) { w += vec3(-2.0, -2.0, 2.0) * t * phi3.zyx; }
+ t = -w.x * phi3.x + w.y * phi3.z + w.z * phi3.y;
+ if (t < 0.0) { w += vec3(2.0, -2.0, -2.0) * t * phi3.xzy; }
+ t = w.x * phi3.y - w.y * phi3.x + w.z * phi3.z;
+ if (t < 0.0) { w += vec3(-2.0, 2.0, -2.0) * t * phi3.yxz; }
+ t = -w.x * c3.x + w.y * c3.y + w.z * c3.z;
+ if (t < 0.0) { w += vec3(2.0, -2.0, -2.0) * t * c3.xyz; }
+ t = w.x * c3.z - w.y * c3.x + w.z * c3.y;
+ if (t < 0.0) { w += vec3(-2.0, 2.0, -2.0) * t * c3.zxy; }
+ w *= fractalplanerotationy;
+ w *= scale;
+ w -= offset * (scale - 1.0);
+ //accumulate minimum orbit for coloring ...
+ d = dot(w, w);
+//!P iterations for coloring (4)
+ if (i < 4) {
+ md = min(md, d);
+ cd = d;
+ }
+ }
+//!P max iterations (8)
+ return vec3((length(w) - 2.0) * pow(scale, -8.0), md, cd);
+}
+
+//calculate ray direction fragment coordinates
+vec3 raydirection(vec2 pixel) {
+ vec2 p = (0.5*sizedode-pixel)/vec2(sizedode.x,-sizedode.y);
+//!P aspect ratio of dode
+ p.x *= sizedode.x/sizedode.y;
+//!P vec3 w = vec3(0, 0, 1), vec3 v = vec3(0, 1, 0), vec3 u = vec3(1, 0, 0);
+ vec3 d = (p.x * vec3(1, 0, 0)+p.y * vec3(0, 1, 0)-camerafocallengthdode * vec3(0, 0, 1));
+ return normalize(camerarotationdode * d);
+}
+
+//iq's fake ambient occlusion
+//http://www.iquilezles.org/www/material/nvscene2008/rwwtt.pdf
+//http://www.iquilezles.org/www/articles/ao/ao.htm
+float ambientocclusion(vec3 p, vec3 n, float eps) {
+ float o = 1.0;
+//!P ao spread (10.6)
+// spreads the output color intensity
+ eps *= 10.6;
+//!P ao intensity (0.16)
+ float k = 0.16 / eps;
+ //add little start distance to the surface
+ float d = 2.0 * eps;
+//!P ao iterations (5) ...
+ for (int i = 0; i < 5; ++i) {
+ o -= (d - distancefunction(p + n * d).x) * k;
+ d += eps;
+ //fade ao when distance to the surface increases
+ k *= 0.5;
+ }
+ return clamp(o, 0.0, 1.0);
+}
+
+vec4 render(vec2 pixel) {
+ vec3 ray_direction = raydirection(pixel);
+//!P minimum ray length (6e-5)
+ float ray_length = 6e-5;
+ vec3 ray = camerapositiondode + ray_length * ray_direction;
+//!P minimum epsilon (6e-7) ...
+ float eps = 6e-7;
+ vec3 dist;
+ vec3 normal = vec3(0);
+ int steps = 0;
+ bool hit = false;
+ float minmarch = 0.0;
+//!P maxmarch = 10000.0;
+ float maxmarch = 25.0;
+//!P field of view scale = (1.0 / sqrt(1.0 + camerafocallengthdode * camerafocallengthdode))
+//!P detail of surface approximation = 1.22
+//!P pixelscale = (1.0 / min(sizedode.x, sizedode.y))
+ float epsfactor = 2.0 * (1.0 / sqrt(1.0 + camerafocallengthdode * camerafocallengthdode)) * (1.0 / min(sizedode.x, sizedode.y)) * 1.22;
+ ray_length = minmarch;
+ ray = camerapositiondode + ray_length * ray_direction;
+//!P max number of raymarching steps (90);
+ for (int i = 0; i < 90; i++) {
+ steps = i;
+ dist = distancefunction(ray);
+//!P X-) questionable surface smoothing (0.53)
+ dist.x *= 0.53;
+ //backtrack previous step and check if it was only a "fussel"
+ if (hit && dist.x < eps || ray_length > maxmarch || ray_length < minmarch) {
+ steps--;
+ break;
+ }
+ hit = false;
+ ray_length += dist.x;
+ ray = camerapositiondode + ray_length * ray_direction;
+ eps = ray_length * epsfactor;
+ if (dist.x < eps || ray_length < minmarch) {
+ hit = true;
+ }
+ }
+ //\0/ there is a hit!
+ vec4 color = vec4(backgroundcolor,0.5);
+ if (hit) {
+ float aof = 1.0;
+ if (steps < 1 || ray_length < minmarch) {
+ normal = normalize(ray);
+ } else {
+ //gradient in x,y and z direction for intersection point
+ //!P minimum normal (1.5e-7)
+ float e = max(eps * 0.5, 1.5e-7);
+ normal = normalize(vec3(
+ distancefunction(ray + vec3(e, 0, 0)).x - distancefunction(ray - vec3(e, 0, 0)).x,
+ distancefunction(ray + vec3(0, e, 0)).x - distancefunction(ray - vec3(0, e, 0)).x,
+ distancefunction(ray + vec3(0, 0, e)).x - distancefunction(ray - vec3(0, 0, e)).x
+ ));
+ aof = ambientocclusion(ray, normal, eps);
+ }
+//!P hardcoded light position vec3(-50,150,-25)
+ float diffuse = max(dot(normal, normalize(vec3(-50,150,-25) - ray)), 0.0);
+//blinn/phong specular stuff ...
+//!P specular exponent (4)
+//!P specularity (0.8)
+//!P diffuse color vec3(0.45) 2x in one line ...
+//!P ambient color vec2 ambientcolor = vec2(0.5,0.3)
+ color.rgb = (mix(vec3(0.5), backgroundcolor, 0.3) * vec3(0.45) + vec3(0.45) * diffuse + pow(diffuse, 4.) * 0.8)*aof;
+ color.a = 1.0;
+ }
+//!P fog factor = 0.01
+ color.rgb = mix(backgroundcolor, color.rgb, exp(-pow(ray_length, 2.0) * 0.01));
+ return color;
+}
+
+mat3 xmatrixrotation(float angle) {
+ return mat3(
+ vec3(1.0, 0.0, 0.0),
+ vec3(0.0, cos(angle), sin(angle)),
+ vec3(0.0, -sin(angle), cos(angle))
+ );
+}
+
+mat3 ymatrixrotation(float angle) {
+ return mat3(
+ vec3(cos(angle), 0.0, -sin(angle)),
+ vec3( 0.0, 1.0, 0.0),
+ vec3(sin(angle), 0.0, cos(angle))
+ );
+}
+
+vec4 raymarch_orbittrap_image(vec2 fragcoord) {
+ //do the matrix calculations by hand X-)
+ //as mat4 constructor and arithmetic assignments are
+ //currently broken (2010-09-21) on ATI cards i found
+ //a workaround using vec4 constructors wich works on
+ //both NVIDIA+ATI --- MAGIC. DO NOT TOUCH! -=#:-)
+ mat3 identitymatrix = mat3(1,0,0,0,1,0,0,0,1);
+ float sin_phi = sin(0.1*tm);
+ float cos_phi = cos(0.1*tm);
+ mat3 zrot = mat3(
+ vec3( cos_phi, sin_phi, 0.0),
+ vec3(-sin_phi, cos_phi, 0.0),
+ vec3( 0.0, 0.0, 1.0)
+ );
+ vec2 position;
+ float fractalplanex_var;
+ float fractalplaney_var;
+ position = oglFragCoord.xy;
+ camerafocallengthdode = 1.0;
+ if (en==2) {
+ sizedode = vec2(384,384);
+ camerapositiondode = vec3(0.0,0.0,-2.7);
+ } else if (en==3) {
+ camerapositiondode = vec3(0.0,0.0,-2.7*(10.-et));
+ } else if (en==4) {
+ camerapositiondode = vec3(0.0,0.0,-2.7*(10.-9.3));
+ fractalplanex_var = et;
+ fractalplaney_var = 0.0;
+ } else if (en==5) {
+ //inside effect
+ camerapositiondode = vec3(0.0,0.0,-0.05);
+ fractalplanex_var = 1.06;
+ fractalplaney_var = -1.0-et;
+ } else if (en==6) {
+ camerapositiondode = vec3(0.0,0.0,-2.7*(10.-9.5));
+ fractalplanex_var = et;
+ fractalplaney_var = sin(et*0.03)-1.0;
+ } else if (en==7) {
+ sizedode = vec2(384,384);
+ fractalplanex_var = et;
+ fractalplaney_var = sin(et*0.93)-1.0;
+ camerapositiondode = vec3(0.0,0.0,-2.7);
+ }
+ worldrotationxyz = xmatrixrotation(0.1*tm)*ymatrixrotation(0.1*tm)*zrot*identitymatrix;
+ fractalplanerotationx = xmatrixrotation(fractalplanex_var)*identitymatrix;
+ fractalplanerotationy = xmatrixrotation(fractalplaney_var)*identitymatrix;
+ camerarotationdode = ymatrixrotation(3.14)*identitymatrix;
+ vec4 color = render(position);
+ return color;
+}
+
+//----------------------------------------------------------------------------------------------------------
+
+vec4 orbitmapping(vec4 c, vec2 w) {
+//!P orbit trap scale and offset
+ vec2 orbittrapoffset = vec2(0.24,-0.24);
+ float orbittrapscale;
+ if (en==0) {
+ //julia set ...
+ orbittrapscale = 0.625;
+ } else {
+ //mandlebrot ...
+ orbittrapscale = 0.325;
+ }
+ vec2 sp = 0.5 + (w / orbittrapscale - orbittrapoffset);
+ vec4 s = texture2D(fb, sp);
+ if (s.a > 0.0) {
+ c = mix(c, s, s.a);
+ }
+ return c;
+}
+
+vec4 orbittrap(vec2 z) {
+ float powerjulia = 2.;
+ vec3 colorjulia = vec3(1.0);
+ vec4 color = vec4(colorjulia, 0.0);
+ float n = 0.0;
+ vec2 c;
+ if (en==0) {
+ //julia mode ...
+//!P use offset-julia from 2.25 to 2.5
+ c = vec2(sin(et+2.07)*0.05,cos(et+2.07));
+ } else {
+ //mandelbrot mode ...
+ c = z;
+ }
+//!P max iterations for julia (128) ... 2x parameter - see below!
+ for (int i = 0; i<128; i++) {
+ n += 1.0;
+ float r = pow(length(z), powerjulia);
+ float a = powerjulia * atan(z.y, z.x);
+ z = vec2(cos(a) * r, sin(a) * r) +c;
+//!P min iterations for julia (1.0) ...
+ if (n >= 1.0) {
+ color = orbitmapping(color, z);
+//!P orbit trap alpha precision (0.6) ...
+ if (color.a >= 0.6) {
+ break;
+ }
+ }
+ }
+//!P max iterations for julia (128.0) ...
+ float blend = clamp(1.0 - (n / 128.0) * 2.0, 0.0, 1.0);
+ color.rgb = mix(colorjulia, color.rgb, blend);
+ return color;
+}
+
+void main() {
+ vec2 sizejulia = resolution;
+ sizedode = sizejulia;
+ oglFragCoord = gl_FragCoord.xy;
+ vec4 color;
+ if (en==0 || en==1) {
+ //render 2d julia/mandelbrot
+//!P camera position for julia ...
+ vec3 camerapositionjulia;
+ if (en==0) {
+ //julia
+ camerapositionjulia = vec3(-0.2,-0.515,0.095347+(et*1.75));
+ } else {
+ //mandelbrot
+ camerapositionjulia = vec3(0.325895,0.049551,0.0005+et);
+ }
+//!P absolute output size of julia orbit trap ...
+ vec2 z = ((oglFragCoord.xy - (sizejulia * 0.5)) / sizejulia) *
+ vec2(sizejulia.x/sizejulia.y, 1.0) * //aspect ratio
+ camerapositionjulia.z +
+ camerapositionjulia.xy;
+ color = orbittrap(z);
+ } else {
+ color = raymarch_orbittrap_image(oglFragCoord.xy);
+ }
+ if (en==2 || en==7) {
+ mgl_FragColor = color;
+ } else {
+ //do normal rendering ...
+ //analog-tv distortion ...
+ vec2 position = oglFragCoord.xy / sizejulia.xy;
+ position.y *=-1.0;
+ vec3 color_tv = color.rgb;
+ //contrast
+ color_tv = clamp(color_tv*0.5+0.5*color_tv*color_tv*1.2,0.0,1.0);
+ //circular vignette fade
+ color_tv *= 0.5 + 0.5*16.0*position.x*position.y*(1.0-position.x)*(-1.0-position.y);
+ //color shift
+ if (en==0 || en==3) {
+ color_tv *= vec3(0.8,1.0,0.7); //green
+ }
+ if (en==1 || en==4) {
+ color_tv *= vec3(0.95,0.85,1.0); //blue
+ }
+ if (en==5) {
+ color_tv *= vec3(1.0,0.7,1.0); //purple
+ }
+
+ if (en==6) {
+ color_tv *= vec3(0.7,1.0,1.0); //cyan
+ }
+ if (en==2) {
+ color_tv *= vec3(1.0,1.0,0.7); //yellow
+ }
+ //tvlines effect
+ color_tv *= 0.9+0.1*sin(1.5*tm+position.y*1000.0);
+ //tv flicker effect
+ color_tv *= 0.97+0.13*sin(2.5*tm);
+ color_tv *= br;
+ mgl_FragColor = vec4(color_tv,1.0);
+ }
+}
diff --git a/src/demos/com/jogamp/opengl/demos/es2/shader/elektronenmultiplizierer_port.fp b/src/demos/com/jogamp/opengl/demos/es2/shader/elektronenmultiplizierer_port.fp
new file mode 100644
index 000000000..77c34f74f
--- /dev/null
+++ b/src/demos/com/jogamp/opengl/demos/es2/shader/elektronenmultiplizierer_port.fp
@@ -0,0 +1,242 @@
+/**
+ * Copyright 2011 JogAmp Community. All rights reserved.
+ *
+ * Details see: src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/ElektronenMultiplizierer.java
+ */
+
+/**
+ * http://www.youtube.com/user/DemoscenePassivist
+ * author: Dominik Stroehlein (DemoscenePassivist)
+ **/
+
+//When I wrote this, only God and I understood what I was doing ...
+// ... now only God knows! X-)
+
+#if __VERSION__ >= 130
+ #define varying in
+ out vec4 mgl_FragColor;
+ #define texture2D texture
+#else
+ #define mgl_FragColor gl_FragColor
+#endif
+
+uniform int en;
+uniform float et;
+uniform sampler2D fb;
+uniform float br,tm;
+uniform vec2 resolution;
+float v;
+vec3 n;
+vec2 e;
+vec3 f=vec3(0,.6,.46);
+mat3 i,m,r,y;
+vec2 c;
+const float x=1.618,t=1./sqrt(pow(x*(1.+x),2.)+pow(x*x-1.,2.)+pow(1.+x,2.)),z=x*(1.+x)*t,s=(x*x-1.)*t,w=(1.+x)*t;
+const vec3 a=vec3(.5,.5/x,.5*x),p=vec3(z,s,w);
+vec3 l(vec3 v) {
+ vec3 n;
+ if(en==6)
+ n=vec3(.61,.1*et,.99);
+ else
+ n=vec3(.61,0.,.99);
+ float e=2.;
+ v*=i;
+ float f,x,c=1000.,y=0.;
+ for(int z=0;z<8;z++) {
+ v*=m;
+ v=abs(v);
+ x=v.x*a.z+v.y*a.y-v.z*a.x;
+ if(x<0.)
+ v+=vec3(-2.,-2.,2.)*x*a.zyx;
+ x=-v.x*a.x+v.y*a.z+v.z*a.y;
+ if(x<0.)
+ v+=vec3(2.,-2.,-2.)*x*a.xzy;
+ x=v.x*a.y-v.y*a.x+v.z*a.z;
+ if(x<0.)
+ v+=vec3(-2.,2.,-2.)*x*a.yxz;
+ x=-v.x*p.x+v.y*p.y+v.z*p.z;
+ if(x<0.)
+ v+=vec3(2.,-2.,-2.)*x*p.xyz;
+ x=v.x*p.z-v.y*p.x+v.z*p.y;
+ if(x<0.)
+ v+=vec3(-2.,2.,-2.)*x*p.zxy;
+ v*=r;
+ v*=e;
+ v-=n*(e-1.);
+ f=dot(v,v);
+ if(z<4)
+ c=min(c,f),y=f;
+ }
+ return vec3((length(v)-2.)*pow(e,-8.),c,y);
+}
+vec3 b(vec2 x) {
+ vec2 n=(.5*e-x)/vec2(e.x,-e.y);
+ n.x*=e.x/e.y;
+ vec3 a=n.x*vec3(1,0,0)+n.y*vec3(0,1,0)-v*vec3(0,0,1);
+ return normalize(y*a);
+}
+float b(vec3 e,vec3 x,float v) {
+ float n=1.;
+ v*=10.6;
+ float t=.16/v,y=2.*v;
+ for(int i=0;i<5;++i)
+ n-=(y-l(e+x*y).x)*t,y+=v,t*=.5;
+ return clamp(n,0.,1.);
+}
+vec4 h(vec2 x) {
+ vec3 a=b(x);
+ float i=6e-05;
+ vec3 y=n+i*a;
+ float c=6e-07;
+ vec3 m,z=vec3(0);
+ int r=0;
+ bool t=false;
+ float s=0.,w=25.,p=2.*(1./sqrt(1.+v*v))*(1./min(e.x,e.y))*1.22;
+ i=s;
+ y=n+i*a;
+ for(int g=0;g<90;g++) {
+ r=g;
+ m=l(y);
+ m.x*=.53;
+ if(t&&m.x<c||i>w||i<s) {
+ r--;
+ break;
+ }
+ t=false;
+ i+=m.x;
+ y=n+i*a;
+ c=i*p;
+ if(m.x<c||i<s)
+ t=true;
+ }
+ vec4 g=vec4(f,.5);
+ if(t) {
+ float d=1.;
+ if(r<1||i<s)
+ z=normalize(y);
+ else {
+ float h=max(c*.5,1.5e-07);
+ z=normalize(vec3(l(y+vec3(h,0,0)).x-l(y-vec3(h,0,0)).x,l(y+vec3(0,h,0)).x-l(y-vec3(0,h,0)).x,l(y+vec3(0,0,h)).x-l(y-vec3(0,0,h)).x));
+ d=b(y,z,c);
+ }
+ float h=max(dot(z,normalize(vec3(-66,162,-30)-y)),0.);
+ g.xyz=(mix(vec3(.5),f,.3)*vec3(.45)+vec3(.45)*h+pow(h,4.)*.8)*d;
+ g.w=1.;
+ }
+ g.xyz=mix(f,g.xyz,exp(-pow(i,2.)*.01));
+ return g;
+}
+mat3 g(float e) {
+ return mat3(vec3(1.,0.,0.),vec3(0.,cos(e),sin(e)),vec3(0.,-sin(e),cos(e)));
+}
+mat3 d(float e) {
+ return mat3(vec3(cos(e),0.,-sin(e)),vec3(0.,1.,0.),vec3(sin(e),0.,cos(e)));
+}
+vec4 D(vec2 x) {
+ mat3 a=mat3(1,0,0,0,1,0,0,0,1);
+ float t=sin(.1*tm),z=cos(.1*tm);
+ mat3 p=mat3(vec3(z,t,0.),vec3(-t,z,0.),vec3(0.,0.,1.));
+ vec2 f;
+ float s,w;
+ f=c.xy;
+ v=1.;
+ if(en==2)
+ e=vec2(384,384),n=vec3(0.,0.,-2.7);
+ if(en==3)
+ n=vec3(0.,0.,-2.7*(10.-et));
+ if(en==4)
+ n=vec3(0.,0.,-1.89),s=et,w=0.;
+ if(en==5)
+ n=vec3(0.,0.,-.05),s=1.06,w=-1.-et;
+ if(en==6)
+ n=vec3(0.,0.,-1.35),s=et,w=sin(et*.03)-1.;
+ if(en==7)
+ e=vec2(384,384),s=et,w=sin(et*.93)-1.,n=vec3(0.,0.,-2.7);
+ i=g(.1*tm)*d(.1*tm)*p*a;
+ m=g(s)*a;
+ r=g(w)*a;
+ y=d(3.14)*a;
+ vec4 l=h(f);
+ if(l.w<.00392) {
+ discard;
+ }
+ return l;
+}
+vec4 D(vec4 e,vec2 x) {
+ vec2 n=vec2(.24,-.24);
+ float y;
+ if(en==0)
+ y=.625;
+ else
+ y=.325;
+ vec2 v=.5+(x/y-n);
+ vec4 c=texture2D(fb,v);
+ if(c.w>0.)
+ e=mix(e,c,c.w);
+ return e;
+}
+vec4 o(vec2 v) {
+ float n=2.;
+ vec3 e=vec3(1.);
+ vec4 i=vec4(e,0.);
+ float y=0.;
+ vec2 x;
+ if(en==0)
+ x=vec2(sin(et+2.07)*.05,cos(et+2.07));
+ else
+ x=v;
+ for(int f=0;f<128;f++) {
+ y+=1.;
+ float t=pow(length(v),n),c=n*atan(v.y,v.x);
+ v=vec2(cos(c)*t,sin(c)*t)+x;
+ if(y>=1.) {
+ i=D(i,v);
+ if(i.w>=.6) {
+ break;
+ }
+ }
+ }
+ float c=clamp(1.-y/128.*2.,0.,1.);
+ i.xyz=mix(e,i.xyz,c);
+ return i;
+}
+void main() {
+ //vec2 v=vec2(640.0,480.0);
+ vec2 v =resolution;
+ e=v;
+ c=gl_FragCoord.xy;
+ vec4 n;
+ if(en==0||en==1) {
+ vec3 a;
+ if(en==0)
+ a=vec3(-.2,-.515,.095347+et*1.75);
+ else
+ a=vec3(.325895,.049551,.0005+et);
+ vec2 x=(c.xy-v*.5)/v*vec2(v.x/v.y,1.)*a.z+a.xy;
+ n=o(x);
+ } else
+ n=D(c.xy);
+ if(en==2||en==7)
+ mgl_FragColor=n;
+ else {
+ vec2 i=c.xy/v.xy;
+ i.y*=-1.;
+ vec3 x=n.xyz;
+ x=clamp(x*.5+.5*x*x*1.2,0.,1.);
+ x*=.5+8.*i.x*i.y*(1.-i.x)*(-1.-i.y);
+ if(en==0||en==3)
+ x*=vec3(.8,1.,.7);
+ if(en==1||en==4)
+ x*=vec3(.95,.85,1.);
+ if(en==5)
+ x*=vec3(1.,.7,1.);
+ if(en==6)
+ x*=vec3(.7,1.,1.);
+ if(en==2)
+ x*=vec3(1.,1.,.7);
+ x*=.9+.1*sin(1.5*tm+i.y*1000.);
+ x*=.97+.13*sin(2.5*tm);
+ x*=br;
+ mgl_FragColor=vec4(x,1.);
+ }
+}
diff --git a/src/demos/com/jogamp/opengl/demos/es2/shader/fbo-mrt-1.fp b/src/demos/com/jogamp/opengl/demos/es2/shader/fbo-mrt-1.fp
new file mode 100644
index 000000000..563e0a4b0
--- /dev/null
+++ b/src/demos/com/jogamp/opengl/demos/es2/shader/fbo-mrt-1.fp
@@ -0,0 +1,16 @@
+//Copyright 2010 JogAmp Community. All rights reserved.
+
+#if __VERSION__ >= 130
+ #define varying in
+ out vec4 mgl_FragData[2];
+#else
+ #define mgl_FragData gl_FragData
+#endif
+
+varying vec4 frontColor;
+
+void main (void)
+{
+ mgl_FragData[0] = vec4( frontColor.r, 0.0, 0.0, 1.0 );
+ mgl_FragData[1] = vec4( 0.0, frontColor.g, 0.0, 1.0 );
+}
diff --git a/src/demos/com/jogamp/opengl/demos/es2/shader/fbo-mrt-1.vp b/src/demos/com/jogamp/opengl/demos/es2/shader/fbo-mrt-1.vp
new file mode 100644
index 000000000..4cab59c64
--- /dev/null
+++ b/src/demos/com/jogamp/opengl/demos/es2/shader/fbo-mrt-1.vp
@@ -0,0 +1,19 @@
+// Copyright 2010 JogAmp Community. All rights reserved.
+
+#if __VERSION__ >= 130
+ #define attribute in
+ #define varying out
+#endif
+
+uniform mat4 gcu_PMVMatrix[2]; // P, Mv, and Mvi
+attribute vec4 gca_Vertices;
+attribute vec4 gca_Colors;
+
+varying vec4 frontColor;
+
+void main(void)
+{
+ frontColor = gca_Colors;
+ gl_Position = gcu_PMVMatrix[0] * gcu_PMVMatrix[1] * gca_Vertices;
+}
+
diff --git a/src/demos/com/jogamp/opengl/demos/es2/shader/fbo-mrt-2.fp b/src/demos/com/jogamp/opengl/demos/es2/shader/fbo-mrt-2.fp
new file mode 100644
index 000000000..510096d66
--- /dev/null
+++ b/src/demos/com/jogamp/opengl/demos/es2/shader/fbo-mrt-2.fp
@@ -0,0 +1,22 @@
+//Copyright 2010 JogAmp Community. All rights reserved.
+
+#if __VERSION__ >= 130
+ #define varying in
+ out vec4 mgl_FragData[2];
+ #define texture2D texture
+#else
+ #define mgl_FragData gl_FragData
+#endif
+
+uniform sampler2D gcs_TexUnit0;
+uniform sampler2D gcs_TexUnit1;
+
+varying vec4 frontColor;
+varying vec2 texCoord;
+
+void main (void)
+{
+ vec2 rg = texture2D(gcs_TexUnit0, texCoord).rg + texture2D(gcs_TexUnit1, texCoord).rg;
+ float b = frontColor.b - length(rg);
+ mgl_FragData[0] = vec4( rg, b, 1.0 );
+}
diff --git a/src/demos/com/jogamp/opengl/demos/es2/shader/fbo-mrt-2.vp b/src/demos/com/jogamp/opengl/demos/es2/shader/fbo-mrt-2.vp
new file mode 100644
index 000000000..89290b05a
--- /dev/null
+++ b/src/demos/com/jogamp/opengl/demos/es2/shader/fbo-mrt-2.vp
@@ -0,0 +1,21 @@
+//Copyright 2010 JogAmp Community. All rights reserved.
+
+#if __VERSION__ >= 130
+ #define attribute in
+ #define varying out
+#endif
+
+uniform mat4 gcu_PMVMatrix[2]; // P, Mv, and Mvi
+attribute vec4 gca_Vertices;
+attribute vec4 gca_Colors;
+attribute vec2 gca_TexCoords;
+
+varying vec4 frontColor;
+varying vec2 texCoord;
+
+void main(void)
+{
+ frontColor = gca_Colors;
+ texCoord = gca_TexCoords;
+ gl_Position = gcu_PMVMatrix[0] * gcu_PMVMatrix[1] * gca_Vertices;
+}
diff --git a/src/demos/com/jogamp/opengl/demos/es2/shader/gears.fp b/src/demos/com/jogamp/opengl/demos/es2/shader/gears.fp
new file mode 100644
index 000000000..14328dc1e
--- /dev/null
+++ b/src/demos/com/jogamp/opengl/demos/es2/shader/gears.fp
@@ -0,0 +1,48 @@
+// Copyright (C) 2011 JogAmp Community. All rights reserved.
+// Details see GearsES2.java
+
+#if __VERSION__ >= 130
+ #define varying in
+ out vec4 mgl_FragColor;
+#else
+ #define mgl_FragColor gl_FragColor
+#endif
+
+uniform vec4 color;
+
+varying vec3 normal;
+varying vec4 position;
+varying vec3 lightDir;
+varying float attenuation;
+varying vec3 cameraDir;
+
+// Defining The Material Colors
+const vec4 matAmbient = vec4(0.2, 0.2, 0.2, 1.0); // orig default
+const vec4 matDiffuse = vec4(0.8, 0.8, 0.8, 1.0); // orig default
+// const vec4 matSpecular = vec4(0.0, 0.0, 0.0, 1.0); // orig default
+const vec4 matSpecular = vec4(0.8, 0.8, 0.8, 1.0);
+// const float matShininess = 0.0; // orig default
+const float matShininess = 0.5;
+
+void main()
+{
+ vec4 ambient = color * matAmbient;
+ vec4 specular = vec4(0.0);
+
+ float lambertTerm = dot(normal, lightDir);
+ vec4 diffuse = color * lambertTerm * attenuation * matDiffuse;
+ if (lambertTerm > 0.0) {
+ float NdotHV;
+ /*
+ vec3 halfDir = normalize (lightDir + cameraDir);
+ NdotHV = max(0.0, dot(normal, halfDir));
+ */
+ vec3 E = normalize(-position.xyz);
+ vec3 R = reflect(-lightDir, normal);
+ NdotHV = max(0.0, dot(R, E));
+
+ specular += color * pow(NdotHV, matShininess) * attenuation * matSpecular;
+ }
+
+ mgl_FragColor = ambient + diffuse + specular ;
+}
diff --git a/src/demos/com/jogamp/opengl/demos/es2/shader/gears.vp b/src/demos/com/jogamp/opengl/demos/es2/shader/gears.vp
new file mode 100644
index 000000000..24f4f9c52
--- /dev/null
+++ b/src/demos/com/jogamp/opengl/demos/es2/shader/gears.vp
@@ -0,0 +1,45 @@
+// Copyright (C) 2011 JogAmp Community. All rights reserved.
+// Details see GearsES2.java
+
+#if __VERSION__ >= 130
+ #define attribute in
+ #define varying out
+#endif
+
+uniform mat4 pmvMatrix[4]; // P, Mv, Mvi and Mvit
+uniform vec3 lightPos;
+
+attribute vec4 vertices;
+attribute vec4 normals;
+
+varying vec3 normal;
+varying vec4 position;
+varying vec3 lightDir;
+varying float attenuation;
+varying vec3 cameraDir;
+
+const float constantAttenuation = 0.5; // 1.0;
+const float linearAttenuation = 0.001; // 0.0;
+const float quadraticAttenuation= 0.0002; // 0.0;
+
+void main(void)
+{
+ // Transforming The Vertex Position To ModelView-Space
+ position = pmvMatrix[1] * vertices; // vertex eye position
+
+ // incl. projection
+ gl_Position = pmvMatrix[0] * position;
+
+ // Transforming The Normal To ModelView-Space
+ normal = normalize((pmvMatrix[3] * normals).xyz);
+
+ // Calculating The Vector From The Vertex Position To The Light Position
+ lightDir = lightPos - position.xyz;
+ float d = length(lightDir);
+ attenuation = 1.0 / (
+ constantAttenuation +
+ linearAttenuation * d +
+ quadraticAttenuation * d * d );
+ lightDir = normalize(lightDir);
+ cameraDir = normalize((pmvMatrix[2] * vec4(0,0,0,1.0)).xyz - vertices.xyz);
+}
diff --git a/src/demos/com/jogamp/opengl/demos/es2/shader/landscape.fp b/src/demos/com/jogamp/opengl/demos/es2/shader/landscape.fp
new file mode 100644
index 000000000..b19c057d3
--- /dev/null
+++ b/src/demos/com/jogamp/opengl/demos/es2/shader/landscape.fp
@@ -0,0 +1,339 @@
+// Elevated shader
+// https://www.shadertoy.com/view/MdX3Rr by inigo quilez
+
+#if __VERSION__ >= 130
+ #define varying in
+ out vec4 mgl_FragColor;
+#else
+ #define mgl_FragColor gl_FragColor
+#endif
+
+uniform vec3 iResolution;
+uniform float iGlobalTime;
+
+// Created by inigo quilez - iq/2013
+// License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
+
+//stereo thanks to Croqueteer
+//#define STEREO
+
+mat3 m = mat3( 0.00, 0.80, 0.60,
+ -0.80, 0.36, -0.48,
+ -0.60, -0.48, 0.64 );
+
+float hash( float n )
+{
+ return fract(sin(n)*43758.5453123);
+}
+
+
+float noise( in vec3 x )
+{
+ vec3 p = floor(x);
+ vec3 f = fract(x);
+
+ f = f*f*(3.0-2.0*f);
+
+ float n = p.x + p.y*57.0 + 113.0*p.z;
+
+ float res = mix(mix(mix( hash(n+ 0.0), hash(n+ 1.0),f.x),
+ mix( hash(n+ 57.0), hash(n+ 58.0),f.x),f.y),
+ mix(mix( hash(n+113.0), hash(n+114.0),f.x),
+ mix( hash(n+170.0), hash(n+171.0),f.x),f.y),f.z);
+ return res;
+}
+
+
+
+
+vec3 noised( in vec2 x )
+{
+ vec2 p = floor(x);
+ vec2 f = fract(x);
+
+ vec2 u = f*f*(3.0-2.0*f);
+
+ float n = p.x + p.y*57.0;
+
+ float a = hash(n+ 0.0);
+ float b = hash(n+ 1.0);
+ float c = hash(n+ 57.0);
+ float d = hash(n+ 58.0);
+ return vec3(a+(b-a)*u.x+(c-a)*u.y+(a-b-c+d)*u.x*u.y,
+ 30.0*f*f*(f*(f-2.0)+1.0)*(vec2(b-a,c-a)+(a-b-c+d)*u.yx));
+
+}
+
+float noise( in vec2 x )
+{
+ vec2 p = floor(x);
+ vec2 f = fract(x);
+
+ f = f*f*(3.0-2.0*f);
+
+ float n = p.x + p.y*57.0;
+
+ float res = mix(mix( hash(n+ 0.0), hash(n+ 1.0),f.x),
+ mix( hash(n+ 57.0), hash(n+ 58.0),f.x),f.y);
+
+ return res;
+}
+
+float fbm( vec3 p )
+{
+ float f = 0.0;
+
+ f += 0.5000*noise( p ); p = m*p*2.02;
+ f += 0.2500*noise( p ); p = m*p*2.03;
+ f += 0.1250*noise( p ); p = m*p*2.01;
+ f += 0.0625*noise( p );
+
+ return f/0.9375;
+}
+
+mat2 m2 = mat2(1.6,-1.2,1.2,1.6);
+
+float fbm( vec2 p )
+{
+ float f = 0.0;
+
+ f += 0.5000*noise( p ); p = m2*p*2.02;
+ f += 0.2500*noise( p ); p = m2*p*2.03;
+ f += 0.1250*noise( p ); p = m2*p*2.01;
+ f += 0.0625*noise( p );
+
+ return f/0.9375;
+}
+
+float terrain( in vec2 x )
+{
+ vec2 p = x*0.003;
+ float a = 0.0;
+ float b = 1.0;
+ vec2 d = vec2(0.0);
+ for(int i=0;i<5; i++)
+ {
+ vec3 n = noised(p);
+ d += n.yz;
+ a += b*n.x/(1.0+dot(d,d));
+ b *= 0.5;
+ p=mat2(1.6,-1.2,1.2,1.6)*p;
+ }
+
+ return 140.0*a;
+}
+
+float terrain2( in vec2 x )
+{
+ vec2 p = x*0.003;
+ float a = 0.0;
+ float b = 1.0;
+ vec2 d = vec2(0.0);
+ for(int i=0;i<14; i++)
+ {
+ vec3 n = noised(p);
+ d += n.yz;
+ a += b*n.x/(1.0+dot(d,d));
+ b *= 0.5;
+ p=m2*p;
+ }
+
+ return 140.0*a;
+}
+
+
+float map( in vec3 p )
+{
+ float h = terrain(p.xz);
+
+ float ss = 0.03;
+ float hh = h*ss;
+ float fh = fract(hh);
+ float ih = floor(hh);
+ fh = mix( sqrt(fh), fh, smoothstep(50.0,140.0,h) );
+ h = (ih+fh)/ss;
+
+ return p.y - h;
+}
+
+float map2( in vec3 p )
+{
+ float h = terrain2(p.xz);
+
+
+ float ss = 0.03;
+ float hh = h*ss;
+ float fh = fract(hh);
+ float ih = floor(hh);
+ fh = mix( sqrt(fh), fh, smoothstep(50.0,140.0,h) );
+ h = (ih+fh)/ss;
+
+ return p.y - h;
+}
+
+bool jinteresct(in vec3 rO, in vec3 rD, out float resT )
+{
+ float h = 0.0;
+ float t = 0.0;
+ for( int j=0; j<120; j++ )
+ {
+ //if( t>2000.0 ) break;
+
+ vec3 p = rO + t*rD;
+if( p.y>300.0 ) break;
+ h = map( p );
+
+ if( h<0.1 )
+ {
+ resT = t;
+ return true;
+ }
+ t += max(0.1,0.5*h);
+
+ }
+
+ if( h<5.0 )
+ {
+ resT = t;
+ return true;
+ }
+ return false;
+}
+
+float sinteresct(in vec3 rO, in vec3 rD )
+{
+ float res = 1.0;
+ float t = 0.0;
+ for( int j=0; j<50; j++ )
+ {
+ //if( t>1000.0 ) break;
+ vec3 p = rO + t*rD;
+
+ float h = map( p );
+
+ if( h<0.1 )
+ {
+ return 0.0;
+ }
+ res = min( res, 16.0*h/t );
+ t += h;
+
+ }
+
+ return clamp( res, 0.0, 1.0 );
+}
+
+vec3 calcNormal( in vec3 pos, float t )
+{
+ float e = 0.001;
+ e = 0.001*t;
+ vec3 eps = vec3(e,0.0,0.0);
+ vec3 nor;
+ nor.x = map2(pos+eps.xyy) - map2(pos-eps.xyy);
+ nor.y = map2(pos+eps.yxy) - map2(pos-eps.yxy);
+ nor.z = map2(pos+eps.yyx) - map2(pos-eps.yyx);
+ return normalize(nor);
+}
+
+vec3 camPath( float time )
+{
+ vec2 p = 600.0*vec2( cos(1.4+0.37*time),
+ cos(3.2+0.31*time) );
+
+ return vec3( p.x, 0.0, p.y );
+}
+
+void main(void)
+{
+ vec2 xy = -1.0 + 2.0*gl_FragCoord.xy / iResolution.xy;
+
+ vec2 s = xy*vec2(1.75,1.0);
+
+ #ifdef STEREO
+ float isCyan = mod(gl_FragCoord.x + mod(gl_FragCoord.y,2.0),2.0);
+ #endif
+
+ float time = iGlobalTime*.15;
+
+ vec3 light1 = normalize( vec3( 0.4, 0.22, 0.6 ) );
+ vec3 light2 = vec3( -0.707, 0.000, -0.707 );
+
+
+ vec3 campos = camPath( time );
+ vec3 camtar = camPath( time + 3.0 );
+ campos.y = terrain( campos.xz ) + 15.0;
+ camtar.y = campos.y*0.5;
+
+ float roll = 0.1*cos(0.1*time);
+ vec3 cw = normalize(camtar-campos);
+ vec3 cp = vec3(sin(roll), cos(roll),0.0);
+ vec3 cu = normalize(cross(cw,cp));
+ vec3 cv = normalize(cross(cu,cw));
+ vec3 rd = normalize( s.x*cu + s.y*cv + 1.6*cw );
+
+ #ifdef STEREO
+ campos += 2.0*cu*isCyan; // move camera to the right - the rd vector is still good
+ #endif
+
+ float sundot = clamp(dot(rd,light1),0.0,1.0);
+ vec3 col;
+ float t;
+ if( !jinteresct(campos,rd,t) )
+ {
+ col = 0.9*vec3(0.97,.99,1.0)*(1.0-0.3*rd.y);
+ col += 0.2*vec3(0.8,0.7,0.5)*pow( sundot, 4.0 );
+ }
+ else
+ {
+ vec3 pos = campos + t*rd;
+
+ vec3 nor = calcNormal( pos, t );
+
+ float dif1 = clamp( dot( light1, nor ), 0.0, 1.0 );
+ float dif2 = clamp( 0.2 + 0.8*dot( light2, nor ), 0.0, 1.0 );
+ float sh = 1.0;
+ if( dif1>0.001 )
+ sh = sinteresct(pos+light1*20.0,light1);
+
+ vec3 dif1v = vec3(dif1);
+ dif1v *= vec3( sh, sh*sh*0.5+0.5*sh, sh*sh );
+
+ float r = noise( 7.0*pos.xz );
+
+ col = (r*0.25+0.75)*0.9*mix( vec3(0.10,0.05,0.03), vec3(0.13,0.10,0.08), clamp(terrain2( vec2(pos.x,pos.y*48.0))/200.0,0.0,1.0) );
+ col = mix( col, 0.17*vec3(0.5,.23,0.04)*(0.50+0.50*r),smoothstep(0.70,0.9,nor.y) );
+ col = mix( col, 0.10*vec3(0.2,.30,0.00)*(0.25+0.75*r),smoothstep(0.95,1.0,nor.y) );
+ col *= 0.75;
+ // snow
+ #if 1
+ float h = smoothstep(55.0,80.0,pos.y + 25.0*fbm(0.01*pos.xz) );
+ float e = smoothstep(1.0-0.5*h,1.0-0.1*h,nor.y);
+ float o = 0.3 + 0.7*smoothstep(0.0,0.1,nor.x+h*h);
+ float s = h*e*o;
+ s = smoothstep( 0.1, 0.9, s );
+ col = mix( col, 0.4*vec3(0.6,0.65,0.7), s );
+ #endif
+
+
+ vec3 brdf = 2.0*vec3(0.17,0.19,0.20)*clamp(nor.y,0.0,1.0);
+ brdf += 6.0*vec3(1.00,0.95,0.80)*dif1v;
+ brdf += 2.0*vec3(0.20,0.20,0.20)*dif2;
+
+ col *= brdf;
+
+ float fo = 1.0-exp(-pow(0.0015*t,1.5));
+ vec3 fco = vec3(0.7) + 0.6*vec3(0.8,0.7,0.5)*pow( sundot, 4.0 );
+ col = mix( col, fco, fo );
+ }
+
+ col = sqrt(col);
+
+ vec2 uv = xy*0.5+0.5;
+ col *= 0.7 + 0.3*pow(16.0*uv.x*uv.y*(1.0-uv.x)*(1.0-uv.y),0.1);
+
+ #ifdef STEREO
+ col *= vec3( isCyan, 1.0-isCyan, 1.0-isCyan );
+ #endif
+
+ mgl_FragColor = vec4(col,1.0);
+}
diff --git a/src/demos/com/jogamp/opengl/demos/es2/shader/landscape.vp b/src/demos/com/jogamp/opengl/demos/es2/shader/landscape.vp
new file mode 100644
index 000000000..fc698f2a8
--- /dev/null
+++ b/src/demos/com/jogamp/opengl/demos/es2/shader/landscape.vp
@@ -0,0 +1,11 @@
+
+#if __VERSION__ >= 130
+ #define attribute in
+ #define varying out
+#endif
+
+attribute vec2 inVertex;
+
+void main() {
+ gl_Position = vec4(inVertex, 0, 1);
+} \ No newline at end of file
diff --git a/src/demos/com/jogamp/opengl/demos/es2/shader/mgl_default_xxx.fp b/src/demos/com/jogamp/opengl/demos/es2/shader/mgl_default_xxx.fp
new file mode 100644
index 000000000..a2abf9e2c
--- /dev/null
+++ b/src/demos/com/jogamp/opengl/demos/es2/shader/mgl_default_xxx.fp
@@ -0,0 +1,16 @@
+// Copyright 2012 JogAmp Community. All rights reserved.
+
+#if __VERSION__ >= 130
+ #define varying in
+ out vec4 mgl_FragColor;
+#else
+ #define mgl_FragColor gl_FragColor
+#endif
+
+varying vec4 frontColor;
+
+void main (void)
+{
+ mgl_FragColor = frontColor;
+}
+
diff --git a/src/demos/com/jogamp/opengl/demos/es2/shader/mgl_default_xxx.vp b/src/demos/com/jogamp/opengl/demos/es2/shader/mgl_default_xxx.vp
new file mode 100644
index 000000000..98e7916ab
--- /dev/null
+++ b/src/demos/com/jogamp/opengl/demos/es2/shader/mgl_default_xxx.vp
@@ -0,0 +1,18 @@
+//Copyright 2012 JogAmp Community. All rights reserved.
+
+#if __VERSION__ >= 130
+ #define attribute in
+ #define varying out
+#endif
+
+uniform mat4 mgl_PMVMatrix[2]; // P, Mv
+attribute vec4 mgl_Vertex;
+attribute vec4 mgl_Color;
+
+varying vec4 frontColor;
+
+void main(void)
+{
+ frontColor = mgl_Color;
+ gl_Position = mgl_PMVMatrix[0] * mgl_PMVMatrix[1] * mgl_Vertex;
+}
diff --git a/src/demos/com/jogamp/opengl/demos/es2/shader/ruler.fp b/src/demos/com/jogamp/opengl/demos/es2/shader/ruler.fp
new file mode 100644
index 000000000..f16a3eeb1
--- /dev/null
+++ b/src/demos/com/jogamp/opengl/demos/es2/shader/ruler.fp
@@ -0,0 +1,33 @@
+//Copyright 2010 JogAmp Community. All rights reserved.
+
+#if __VERSION__ >= 130
+ #define varying in
+ out vec4 mgl_FragColor;
+#else
+ #define mgl_FragColor gl_FragColor
+#endif
+
+#ifdef GL_ES
+ #define MEDIUMP mediump
+ #define HIGHP highp
+ #define LOWP lowp
+#else
+ #define MEDIUMP
+ #define HIGHP
+ #define LOWP
+#endif
+
+uniform MEDIUMP vec3 gcu_RulerColor;
+uniform MEDIUMP vec2 gcu_RulerPixFreq;
+
+const MEDIUMP vec2 onev2 = vec2(1.0, 1.0);
+
+void main (void)
+{
+ MEDIUMP vec2 c = step( onev2, mod(gl_FragCoord.xy, gcu_RulerPixFreq) );
+ if( c.s == 0.0 || c.t == 0.0 ) {
+ mgl_FragColor = vec4(gcu_RulerColor, 1.0);
+ } else {
+ discard;
+ }
+}
diff --git a/src/demos/com/jogamp/opengl/demos/es2/shader/texsequence_xxx.fp b/src/demos/com/jogamp/opengl/demos/es2/shader/texsequence_xxx.fp
new file mode 100644
index 000000000..e4f21f95f
--- /dev/null
+++ b/src/demos/com/jogamp/opengl/demos/es2/shader/texsequence_xxx.fp
@@ -0,0 +1,30 @@
+// Copyright 2012 JogAmp Community. All rights reserved.
+
+#if __VERSION__ >= 130
+ #define varying in
+ out vec4 mgl_FragColor;
+ #define texture2D texture
+#else
+ #define mgl_FragColor gl_FragColor
+#endif
+
+varying vec2 mgl_texCoord;
+varying vec4 frontColor;
+
+// Insert dynamic code after the following tag:
+// TEXTURE-SEQUENCE-CODE-BEGIN
+// TEXTURE-SEQUENCE-CODE-END
+
+void main (void)
+{
+ vec4 texColor;
+ if(0.0 <= mgl_texCoord.t && mgl_texCoord.t<=1.0) {
+ texColor = myTexture2D(mgl_ActiveTexture, mgl_texCoord);
+ } else {
+ texColor = vec4(1, 1, 1, 1);
+ }
+
+ // mix frontColor with texture ..
+ mgl_FragColor = vec4(frontColor*texColor);
+}
+
diff --git a/src/demos/com/jogamp/opengl/demos/es2/shader/texsequence_xxx.vp b/src/demos/com/jogamp/opengl/demos/es2/shader/texsequence_xxx.vp
new file mode 100644
index 000000000..1030dab47
--- /dev/null
+++ b/src/demos/com/jogamp/opengl/demos/es2/shader/texsequence_xxx.vp
@@ -0,0 +1,22 @@
+// Copyright 2012 JogAmp Community. All rights reserved.
+
+#if __VERSION__ >= 130
+ #define attribute in
+ #define varying out
+#endif
+
+uniform mat4 mgl_PMVMatrix[2];
+// uniform mat4 mgl_STMatrix;
+attribute vec4 mgl_Vertex;
+attribute vec4 mgl_Color;
+attribute vec4 mgl_MultiTexCoord;
+varying vec4 frontColor;
+varying vec2 mgl_texCoord;
+
+void main(void)
+{
+ frontColor=mgl_Color;
+ // mgl_texCoord = (mgl_STMatrix * mgl_MultiTexCoord).st;
+ mgl_texCoord = mgl_MultiTexCoord.st;
+ gl_Position = mgl_PMVMatrix[0] * mgl_PMVMatrix[1] * mgl_Vertex;
+}
diff --git a/src/demos/com/jogamp/opengl/demos/es2/shader/texture01_xxx.fp b/src/demos/com/jogamp/opengl/demos/es2/shader/texture01_xxx.fp
new file mode 100644
index 000000000..93f252cd6
--- /dev/null
+++ b/src/demos/com/jogamp/opengl/demos/es2/shader/texture01_xxx.fp
@@ -0,0 +1,28 @@
+// Copyright 2012 JogAmp Community. All rights reserved.
+
+#if __VERSION__ >= 130
+ #define varying in
+ out vec4 mgl_FragColor;
+ #define texture2D texture
+#else
+ #define mgl_FragColor gl_FragColor
+#endif
+
+varying vec2 mgl_texCoord;
+varying vec4 frontColor;
+
+uniform sampler2D mgl_ActiveTexture;
+
+void main (void)
+{
+ vec4 texColor;
+ if(0.0 <= mgl_texCoord.t && mgl_texCoord.t<=1.0) {
+ texColor = texture2D(mgl_ActiveTexture, mgl_texCoord);
+ } else {
+ discard;
+ }
+
+ // mix frontColor with texture .. pre-multiplying texture alpha
+ mgl_FragColor = vec4( mix( frontColor.rgb, texColor.rgb, texColor.a ), frontColor.a );
+}
+
diff --git a/src/demos/com/jogamp/opengl/demos/es2/shader/texture01_xxx.vp b/src/demos/com/jogamp/opengl/demos/es2/shader/texture01_xxx.vp
new file mode 100644
index 000000000..1030dab47
--- /dev/null
+++ b/src/demos/com/jogamp/opengl/demos/es2/shader/texture01_xxx.vp
@@ -0,0 +1,22 @@
+// Copyright 2012 JogAmp Community. All rights reserved.
+
+#if __VERSION__ >= 130
+ #define attribute in
+ #define varying out
+#endif
+
+uniform mat4 mgl_PMVMatrix[2];
+// uniform mat4 mgl_STMatrix;
+attribute vec4 mgl_Vertex;
+attribute vec4 mgl_Color;
+attribute vec4 mgl_MultiTexCoord;
+varying vec4 frontColor;
+varying vec2 mgl_texCoord;
+
+void main(void)
+{
+ frontColor=mgl_Color;
+ // mgl_texCoord = (mgl_STMatrix * mgl_MultiTexCoord).st;
+ mgl_texCoord = mgl_MultiTexCoord.st;
+ gl_Position = mgl_PMVMatrix[0] * mgl_PMVMatrix[1] * mgl_Vertex;
+}
diff --git a/src/demos/com/jogamp/opengl/demos/es2/shader/texture02_xxx.fp b/src/demos/com/jogamp/opengl/demos/es2/shader/texture02_xxx.fp
new file mode 100644
index 000000000..10073e85c
--- /dev/null
+++ b/src/demos/com/jogamp/opengl/demos/es2/shader/texture02_xxx.fp
@@ -0,0 +1,28 @@
+// Copyright 2012 JogAmp Community. All rights reserved.
+
+#if __VERSION__ >= 130
+ #define varying in
+ out vec4 mgl_FragColor;
+ #define texture2D texture
+#else
+ #define mgl_FragColor gl_FragColor
+#endif
+
+varying vec2 mgl_texCoord;
+varying vec4 frontColor;
+
+uniform sampler2D mgl_Texture0;
+uniform sampler2D mgl_Texture1;
+
+const vec4 One = vec4(1.0, 1.0, 1.0, 1.0);
+
+void main (void)
+{
+ vec4 texColor0 = texture2D(mgl_Texture0, mgl_texCoord);
+ vec4 texColor1 = texture2D(mgl_Texture1, mgl_texCoord);
+
+ // mgl_FragColor = ( ( texColor0 + texColor1 ) / 2.0 ) * frontColor;
+ // mgl_FragColor = mix(texColor0, texColor1, One/2.0) * frontColor;
+ mgl_FragColor = min(One, mix(texColor0, texColor1, One/2.0) * 1.6) * frontColor;
+}
+
diff --git a/src/demos/com/jogamp/opengl/demos/ios/Hello.java b/src/demos/com/jogamp/opengl/demos/ios/Hello.java
new file mode 100644
index 000000000..d593dd3bc
--- /dev/null
+++ b/src/demos/com/jogamp/opengl/demos/ios/Hello.java
@@ -0,0 +1,196 @@
+/**
+ * Copyright 2019 Gothel Software e.K. 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 Gothel Software e.K. ``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 Gothel Software e.K. 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 Gothel Software e.K.
+ */
+package com.jogamp.opengl.demos.ios;
+
+import com.jogamp.common.util.ReflectionUtil;
+import com.jogamp.common.util.VersionUtil;
+import com.jogamp.nativewindow.AbstractGraphicsScreen;
+import com.jogamp.nativewindow.MutableGraphicsConfiguration;
+import com.jogamp.nativewindow.NativeWindowFactory;
+import com.jogamp.nativewindow.UpstreamWindowHookMutableSizePos;
+
+import com.jogamp.common.GlueGenVersion;
+import com.jogamp.opengl.JoglVersion;
+import com.jogamp.opengl.demos.es2.RedSquareES2;
+
+import jogamp.nativewindow.WrappedWindow;
+import jogamp.nativewindow.ios.IOSUtil;
+import jogamp.opengl.GLDrawableFactoryImpl;
+
+import com.jogamp.opengl.GLAutoDrawableDelegate;
+import com.jogamp.opengl.GLCapabilities;
+import com.jogamp.opengl.GLCapabilitiesImmutable;
+import com.jogamp.opengl.GLDrawable;
+import com.jogamp.opengl.GLDrawableFactory;
+import com.jogamp.opengl.GLEventListener;
+import com.jogamp.opengl.GLProfile;
+
+public class Hello {
+
+ private static int parseInt(final String s, final int def) {
+ try {
+ return Integer.parseInt(s);
+ } catch (final NumberFormatException nfe) {}
+ return def;
+ }
+
+ public static void main(final String[] args) {
+ int width = 832, height = 480; // ipad pro 11: 2388x1668 px (scale: 2)
+ int fboDepthBits = 0; // CAEAGLLayer fails with depth 16 + 24 in Simulation
+ boolean exitJVM = false;
+ String demoName = "com.jogamp.opengl.demos.es2.LandscapeES2";
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-exit")) {
+ exitJVM = true;
+ } else if(args[i].equals("-demo") && i+1<args.length) {
+ demoName = args[++i];
+ } else if(args[i].equals("-width") && i+1<args.length) {
+ width = parseInt(args[++i], width);
+ } else if(args[i].equals("-height") && i+1<args.length) {
+ height = parseInt(args[++i], height);
+ } else if(args[i].equals("-fboDepthBits") && i+1<args.length) {
+ fboDepthBits = parseInt(args[++i], fboDepthBits);
+ } else {
+ System.err.println("ignoring arg["+i+"]: "+args[i]);
+ }
+ }
+ System.out.println("Hello JogAmp World: exitJVM "+exitJVM+", size "+width+"x"+height+", fboDepthBits "+fboDepthBits+", demo "+demoName);
+ System.out.println("os.name: <"+System.getProperty("os.name")+">");
+ System.out.println("os.version: <"+System.getProperty("os.version")+">");
+ System.out.println("os.arch: <"+System.getProperty("os.arch")+">");
+ System.out.println("java.vendor: <"+System.getProperty("java.vendor")+">");
+ System.out.println("java.vendor.url: <"+System.getProperty("java.vendor.url")+">");
+ System.out.println("java.version: <"+System.getProperty("java.version")+">");
+ System.out.println("java.vm.name: <"+System.getProperty("java.vm.name")+">");
+ System.out.println("java.runtime.name: <"+System.getProperty("java.runtime.name")+">");
+ System.out.println("");
+ System.out.println(VersionUtil.getPlatformInfo());
+ System.out.println("");
+ System.out.println("Version Info:");
+ System.out.println(GlueGenVersion.getInstance());
+ System.out.println("");
+ System.out.println("Full Manifest:");
+ System.out.println(GlueGenVersion.getInstance().getFullManifestInfo(null));
+
+ System.out.println("");
+ System.err.println("mark-01");
+ System.err.println("");
+ System.err.println(JoglVersion.getInstance());
+ System.err.println("");
+ System.err.println("mark-02");
+ System.err.println("");
+ GLProfile.initSingleton();
+ System.err.println("");
+ System.err.println("mark-03");
+ System.out.println("");
+ System.out.println(JoglVersion.getDefaultOpenGLInfo(GLProfile.getDefaultDevice(), null, true));
+ System.out.println("");
+ System.err.println("mark-04");
+ System.err.println("");
+
+ GLAutoDrawableDelegate glad = null;
+ final long uiWindow = IOSUtil.CreateUIWindow(0, 0, width, height);
+ try {
+ // 1) Config ..
+ final GLProfile glp = GLProfile.getGL2ES2();
+ final GLCapabilities reqCaps = new GLCapabilities(glp);
+ reqCaps.setOnscreen(true);
+ reqCaps.setDoubleBuffered(false);
+ reqCaps.setDepthBits(fboDepthBits);
+ System.out.println("Requested GL Caps: "+reqCaps);
+ final GLDrawableFactoryImpl factory = (GLDrawableFactoryImpl) GLDrawableFactory.getFactory(glp);
+
+ // 2) Create native window and wrap it around out NativeWindow structure
+ final long uiView = IOSUtil.GetUIView(uiWindow, true);
+ final long caeaglLayer = IOSUtil.GetCAEAGLLayer(uiView);
+ System.out.println("EAGL: UIWindow 0x"+Long.toHexString(uiWindow));
+ System.out.println("EAGL: UIView 0x"+Long.toHexString(uiView));
+ System.out.println("EAGL: EAGLLayer 0x"+Long.toHexString(caeaglLayer));
+ System.out.println("isUIWindow "+IOSUtil.isUIWindow(uiWindow)+", isUIView "+IOSUtil.isUIView(uiView)+
+ ", isCAEAGLLayer "+IOSUtil.isCAEAGLLayer(caeaglLayer));
+ final AbstractGraphicsScreen aScreen = NativeWindowFactory.createScreen(NativeWindowFactory.createDevice(null, true /* own */), -1);
+ final UpstreamWindowHookMutableSizePos hook = new UpstreamWindowHookMutableSizePos(0, 0, width, height, width, height);
+ final MutableGraphicsConfiguration config = new MutableGraphicsConfiguration(aScreen, reqCaps, reqCaps);
+ final WrappedWindow nativeWindow = new WrappedWindow(config, uiView, hook, true, uiWindow);
+
+ // 3) Create a GLDrawable ..
+ final GLDrawable drawable = factory.createGLDrawable(nativeWindow);
+ drawable.setRealized(true);
+ // final GLOffscreenAutoDrawable glad = factory.createOffscreenAutoDrawable(aScreen.getDevice(), reqCaps, null, width, height);
+ glad = new GLAutoDrawableDelegate(drawable, null, nativeWindow, false, null) {
+ @Override
+ protected void destroyImplInLock() {
+ super.destroyImplInLock(); // destroys drawable/context
+ nativeWindow.destroy(); // destroys the actual window, incl. the device
+ IOSUtil.DestroyUIWindow(uiWindow);
+ }
+ };
+ glad.display(); // force native context creation
+
+ // Check caps of GLDrawable after realization
+ final GLCapabilitiesImmutable chosenCaps = glad.getChosenGLCapabilities();
+ System.out.println("Choosen GL Caps: "+chosenCaps);
+
+ GLEventListener demo = null;
+ {
+ try {
+ demo = (GLEventListener) ReflectionUtil.createInstance(demoName, Hello.class.getClassLoader());
+ } catch( final Exception e ) {
+ System.err.println(e.getMessage()+" using: <"+demoName+">");
+ }
+ if( null == demo ) {
+ demo = new RedSquareES2();
+ }
+ }
+ System.out.println("Choosen demo "+demo.getClass().getName());
+ glad.addGLEventListener(demo);
+
+ for(int i=0; i<60*10; i++) { // 10s w/ 60fps
+ glad.display(); // force native context creation
+ try {
+ Thread.sleep(16);
+ } catch (final InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+
+ } finally {
+ if( null != glad ) {
+ glad.destroy();
+ }
+ }
+
+ System.err.println("");
+ System.err.println("mark-05");
+ System.err.println("");
+
+ if( exitJVM ) {
+ System.exit(0);
+ }
+ }
+}
diff --git a/src/demos/com/jogamp/opengl/demos/ios/Hello0.java b/src/demos/com/jogamp/opengl/demos/ios/Hello0.java
new file mode 100644
index 000000000..045914855
--- /dev/null
+++ b/src/demos/com/jogamp/opengl/demos/ios/Hello0.java
@@ -0,0 +1,20 @@
+package com.jogamp.opengl.demos.ios;
+
+import com.jogamp.opengl.GLProfile;
+
+import jogamp.nativewindow.ios.IOSUtil;
+
+public class Hello0 {
+ public static void main(final String[] args) {
+ System.out.println("Hello JogAmp World");
+ GLProfile.initSingleton();
+ {
+ IOSUtil.RunOnMainThread(true, false, new Runnable() {
+ @Override
+ public void run() {
+ IOSUtil.CreateGLViewDemoA();
+ } } );
+ }
+ }
+
+}
diff --git a/src/jogl/classes/com/jogamp/opengl/FBObject.java b/src/jogl/classes/com/jogamp/opengl/FBObject.java
index c36727fe4..00a560fc7 100644
--- a/src/jogl/classes/com/jogamp/opengl/FBObject.java
+++ b/src/jogl/classes/com/jogamp/opengl/FBObject.java
@@ -34,7 +34,6 @@ import com.jogamp.opengl.GL;
import com.jogamp.opengl.GL2ES2;
import com.jogamp.opengl.GL2ES3;
import com.jogamp.opengl.GL2GL3;
-import com.jogamp.opengl.GL3;
import com.jogamp.opengl.GLBase;
import com.jogamp.opengl.GLCapabilities;
import com.jogamp.opengl.GLCapabilitiesImmutable;
@@ -43,6 +42,7 @@ import com.jogamp.opengl.GLException;
import com.jogamp.opengl.GLProfile;
import jogamp.opengl.Debug;
+import jogamp.opengl.ios.eagl.EAGL;
import com.jogamp.common.ExceptionUtils;
import com.jogamp.common.util.PropertyAccess;
@@ -483,6 +483,48 @@ public class FBObject {
@Override
public final ColorAttachment getColorAttachment() { return this; }
+ @Override
+ public boolean initialize(final GL gl) throws GLException {
+ final boolean init = 0 == getName();
+ if( init ) {
+ final boolean checkError = DEBUG || GLContext.DEBUG_GL;
+ if( checkError ) {
+ checkPreGLError(gl);
+ }
+ final int[] name = new int[] { -1 };
+ gl.glGenRenderbuffers(1, name, 0);
+ setName(name[0]);
+
+ gl.glBindRenderbuffer(GL.GL_RENDERBUFFER, getName());
+ if( getSamples() > 0 ) {
+ ((GL2ES3)gl).glRenderbufferStorageMultisample(GL.GL_RENDERBUFFER, getSamples(), format, getWidth(), getHeight());
+ } else {
+ // FIXME: Need better way to inject the IOS EAGL Layer into FBObject
+ // FIXME: May want to implement optional injection of a BufferStorage SPI?
+ final GLContext ctx = gl.getContext();
+ final Long iosEAGLLayer = (Long) ctx.getAttachedObject("IOS_EAGL_LAYER");
+ if( null != iosEAGLLayer ) {
+ EAGL.eaglBindDrawableStorageToRenderbuffer(gl.getContext().contextHandle, GL.GL_RENDERBUFFER, iosEAGLLayer.longValue());
+ } else {
+ gl.glRenderbufferStorage(GL.GL_RENDERBUFFER, format, getWidth(), getHeight());
+ }
+ }
+ if( checkError ) {
+ final int glerr = gl.glGetError();
+ if(GL.GL_NO_ERROR != glerr) {
+ gl.glDeleteRenderbuffers(1, name, 0);
+ setName(0);
+ throw new GLException("GL Error "+toHexString(glerr)+" while creating "+this);
+ }
+ }
+ if(DEBUG) {
+ System.err.println("Attachment.init.X: "+this);
+ }
+ }
+ return init;
+ }
+
+
}
/** Texture FBO attachment */
@@ -1250,7 +1292,7 @@ public class FBObject {
return("FBO missing read buffer");
case GL.GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
return("FBO missing multisample buffer");
- case GL3.GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS:
+ case GL3ES3.GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS:
return("FBO missing layer targets");
case GL.GL_FRAMEBUFFER_UNSUPPORTED:
@@ -1281,7 +1323,7 @@ public class FBObject {
case GL2GL3.GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
case GL2GL3.GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
case GL.GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
- case GL3.GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS:
+ case GL3ES3.GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS:
if(0 == colorbufferCount || null == depth) {
// we are in transition
return true;
diff --git a/src/jogl/classes/com/jogamp/opengl/GLDrawableFactory.java b/src/jogl/classes/com/jogamp/opengl/GLDrawableFactory.java
index 51da34ce0..1fe42a332 100644
--- a/src/jogl/classes/com/jogamp/opengl/GLDrawableFactory.java
+++ b/src/jogl/classes/com/jogamp/opengl/GLDrawableFactory.java
@@ -43,6 +43,7 @@ package com.jogamp.opengl;
import java.util.ArrayList;
import java.util.List;
+import com.jogamp.common.os.Platform;
import com.jogamp.common.util.PropertyAccess;
import com.jogamp.common.util.ReflectionUtil;
import com.jogamp.opengl.GLAutoDrawableDelegate;
@@ -57,6 +58,7 @@ import com.jogamp.nativewindow.NativeWindowFactory;
import com.jogamp.nativewindow.ProxySurface;
import com.jogamp.nativewindow.UpstreamSurfaceHook;
+import jogamp.common.os.PlatformPropsImpl;
import jogamp.opengl.Debug;
/** <p> Provides a virtual machine- and operating system-independent
@@ -137,6 +139,8 @@ public abstract class GLDrawableFactory {
factoryClassName = "jogamp.opengl.windows.wgl.WindowsWGLDrawableFactory";
} else if ( nwt == NativeWindowFactory.TYPE_MACOSX ) {
factoryClassName = "jogamp.opengl.macosx.cgl.MacOSXCGLDrawableFactory";
+ } else if ( nwt == NativeWindowFactory.TYPE_IOS ) {
+ factoryClassName = "jogamp.opengl.ios.eagl.IOSEAGLDrawableFactory";
} else {
// may use egl*Factory ..
if (DEBUG || GLProfile.DEBUG) {
@@ -144,7 +148,7 @@ public abstract class GLDrawableFactory {
}
}
}
- if ( !GLProfile.disableOpenGLDesktop ) {
+ if ( !GLProfile.disableOpenGLDesktop || GLProfile.disabledEGL ) {
if ( null != factoryClassName ) {
if (DEBUG || GLProfile.DEBUG) {
System.err.println("GLDrawableFactory.static - Native OS Factory for: "+nwt+": "+factoryClassName);
@@ -168,7 +172,7 @@ public abstract class GLDrawableFactory {
System.err.println("Info: GLDrawableFactory.static - Desktop GLDrawableFactory - disabled!");
}
- if(!GLProfile.disableOpenGLES) {
+ if(!GLProfile.disableOpenGLES && !GLProfile.disabledEGL) {
try {
tmp = (GLDrawableFactory) ReflectionUtil.createInstance("jogamp.opengl.egl.EGLDrawableFactory", cl);
} catch (final Exception jre) {
@@ -434,6 +438,15 @@ public abstract class GLDrawableFactory {
/**
* Returns the sole GLDrawableFactory instance for the desktop (X11, WGL, ..) if exist or null
+ * <p>
+ * To fetch the appropriate {@link GLDrawableFactory} for native desktop
+ * or mobile, use {@link #getFactory(boolean)}.
+ * </p>
+ * <p>
+ * It is possible that the desktop {@link GLDrawableFactory} will be used for
+ * native mobile GL profiles, e.g. {@link Platform.OSType#IOS}.
+ * </p>
+ * @return the matching {@link GLDrawableFactory} or {@code null} if none is available
*/
public static GLDrawableFactory getDesktopFactory() {
GLProfile.initSingleton();
@@ -441,7 +454,16 @@ public abstract class GLDrawableFactory {
}
/**
- * Returns the sole GLDrawableFactory instance for EGL if exist or null
+ * Returns the sole {@link GLDrawableFactory} instance for EGL if exist or null.
+ * <p>
+ * To fetch the appropriate {@link GLDrawableFactory} for native desktop
+ * or mobile, use {@link #getFactory(boolean)}.
+ * </p>
+ * <p>
+ * It is possible that a non EGL {@link GLDrawableFactory} will be used for
+ * native mobile GL profiles, e.g. {@link Platform.OSType#IOS}.
+ * </p>
+ * @return the matching {@link GLDrawableFactory} or {@code null} if none is available
*/
public static GLDrawableFactory getEGLFactory() {
GLProfile.initSingleton();
@@ -449,34 +471,61 @@ public abstract class GLDrawableFactory {
}
/**
- * Returns the sole GLDrawableFactory instance.
+ * Returns the sole {@link GLDrawableFactory} instance.
*
- * @param glProfile GLProfile to determine the factory type, ie EGLDrawableFactory,
- * or one of the native GLDrawableFactory's, ie X11/GLX, Windows/WGL or MacOSX/CGL.
+ * @param glProfile GLProfile to determine the factory type, ie for native mobile GL or native desktop GL.
+ * @return the matching {@link GLDrawableFactory}
+ * @throws GLException if no matching {@link GLDrawableFactory} exists
*/
public static GLDrawableFactory getFactory(final GLProfile glProfile) throws GLException {
- return getFactoryImpl(glProfile.getImplName());
+ final GLDrawableFactory f = getFactoryImpl(glProfile.getImplName());
+ if( null != f ) {
+ return f;
+ }
+ throw new GLException("No GLDrawableFactory available for profile: "+glProfile);
}
-
- protected static GLDrawableFactory getFactoryImpl(final String glProfileImplName) throws GLException {
- if ( GLProfile.usesNativeGLES(glProfileImplName) ) {
- if(null!=eglFactory) {
+ /**
+ * Returns the sole {@link GLDrawableFactory} instance, either for mobile if {@code usesNativeGLES} is true,
+ * or for desktop otherwise.
+ * @param useNativeGLES request native mobile GLES support if true
+ * @return the matching {@link GLDrawableFactory} or {@code null} if none is available
+ */
+ public static GLDrawableFactory getFactory(final boolean useNativeGLES) {
+ GLProfile.initSingleton();
+ return getFactoryImpl( useNativeGLES );
+ }
+ protected static GLDrawableFactory getFactoryImpl(final String glProfileImplName) {
+ return getFactoryImpl( GLProfile.usesNativeGLES(glProfileImplName) );
+ }
+ protected static GLDrawableFactory getFactoryImpl(final boolean useNativeGLES) {
+ if( useNativeGLES ) {
+ if(null!=eglFactory && eglFactory.hasOpenGLESSupport() ) {
return eglFactory;
}
- } else if(null!=nativeOSFactory) {
- return nativeOSFactory;
+ if(null!=nativeOSFactory && nativeOSFactory.hasOpenGLESSupport() ) {
+ return nativeOSFactory;
+ }
+ } else {
+ if(null!=nativeOSFactory && nativeOSFactory.hasOpenGLDesktopSupport() ) {
+ return nativeOSFactory;
+ }
}
- throw new GLException("No GLDrawableFactory available for profile: "+glProfileImplName);
+ return null;
}
-
- protected static GLDrawableFactory getFactoryImpl(final AbstractGraphicsDevice device) throws GLException {
+ /**
+ * Returns the sole {@link GLDrawableFactory} matching the given {@link AbstractGraphicsDevice} instance,
+ * which will be suitable either for native mobile or native desktop.
+ * @param device the queries {@link AbstractGraphicsDevice} seeking for its matching factory
+ * @return the matching {@link GLDrawableFactory} or {@code null} if none is available
+ */
+ public static GLDrawableFactory getFactory(final AbstractGraphicsDevice device) {
if(null != nativeOSFactory && nativeOSFactory.getIsDeviceCompatible(device)) {
return nativeOSFactory;
}
if(null != eglFactory && eglFactory.getIsDeviceCompatible(device)) {
return eglFactory;
}
- throw new GLException("No native platform GLDrawableFactory, nor EGLDrawableFactory available: "+device);
+ return null;
}
/**
diff --git a/src/jogl/classes/com/jogamp/opengl/GLProfile.java b/src/jogl/classes/com/jogamp/opengl/GLProfile.java
index e19535e5d..0e0d45444 100644
--- a/src/jogl/classes/com/jogamp/opengl/GLProfile.java
+++ b/src/jogl/classes/com/jogamp/opengl/GLProfile.java
@@ -86,7 +86,7 @@ public class GLProfile {
* and if one platform may have a buggy implementation,
* setting the property <code>jogl.disable.openglcore</code> disables querying possible existing native OpenGL core profiles.
* <p>
- * This exclusion is disabled for {@link Platform.OSType#MACOS}.
+ * This exclusion is disabled for {@link Platform.OSType#MACOS} and {@link Platform.OSType#IOS}.
* </p>
*/
public static final boolean disableOpenGLCore;
@@ -99,7 +99,7 @@ public class GLProfile {
* This exclusion also disables {@link #disableOpenGLES OpenGL ES}.
* </p>
* <p>
- * This exclusion is disabled for {@link Platform.OSType#MACOS}.
+ * This exclusion is disabled for {@link Platform.OSType#MACOS} and {@link Platform.OSType#IOS}.
* </p>
*/
public static final boolean disableOpenGLARBContext;
@@ -119,6 +119,13 @@ public class GLProfile {
public static final boolean disableOpenGLDesktop;
/**
+ * In case no EGL implementation is available
+ * like on the {@link Platform.OSType#IOS} platform,
+ * this is set to {@code true}.
+ */
+ public static final boolean disabledEGL;
+
+ /**
* Disable surfaceless OpenGL context capability and its probing
* by setting the property <code>jogl.disable.surfacelesscontext</code>.
* <p>
@@ -145,11 +152,13 @@ public class GLProfile {
static {
// Also initializes TempJarCache if shall be used.
Platform.initSingleton();
- final boolean isOSX = Platform.OSType.MACOS == Platform.getOSType();
+ final boolean isIOS = Platform.OSType.IOS == Platform.getOSType();
+ final boolean isOSXorIOS = Platform.OSType.MACOS == Platform.getOSType() || isIOS;
DEBUG = Debug.debug("GLProfile");
- disableOpenGLCore = PropertyAccess.isPropertyDefined("jogl.disable.openglcore", true) && !isOSX;
- disableOpenGLARBContext = PropertyAccess.isPropertyDefined("jogl.disable.openglarbcontext", true) && !isOSX;
+ disabledEGL = isIOS;
+ disableOpenGLCore = PropertyAccess.isPropertyDefined("jogl.disable.openglcore", true) && !isOSXorIOS;
+ disableOpenGLARBContext = PropertyAccess.isPropertyDefined("jogl.disable.openglarbcontext", true) && !isOSXorIOS;
disableOpenGLES = disableOpenGLARBContext || PropertyAccess.isPropertyDefined("jogl.disable.opengles", true);
disableOpenGLDesktop = PropertyAccess.isPropertyDefined("jogl.disable.opengldesktop", true);
disableSurfacelessContext = PropertyAccess.isPropertyDefined("jogl.disable.surfacelesscontext", true);
@@ -243,7 +252,7 @@ public class GLProfile {
initLock.unlock();
}
if(DEBUG) {
- if( justInitialized && ( hasGL234Impl || hasGL234OnEGLImpl || hasGLES1Impl || hasGLES3Impl ) ) {
+ if( justInitialized && ( hasGL234Impl || hasGL234OnMobileImpl || hasGLES1Impl || hasGLES3Impl ) ) {
System.err.println(JoglVersion.getDefaultOpenGLInfo(defaultDevice, null, true));
}
}
@@ -671,6 +680,18 @@ public class GLProfile {
public static final String[] GL_PROFILE_LIST_MIN_DESKTOP = new String[] { GL2, GL3bc, GL4bc, GL3, GL4 };
/**
+ * Order of maximum original mobile profiles.
+ *
+ * <ul>
+ * <li> GLES3 </li>
+ * <li> GLES2 </li>
+ * <li> GLES1 </li>
+ * </ul>
+ *
+ */
+ public static final String[] GL_PROFILE_LIST_MAX_MOBILE = new String[] { GLES3, GLES2, GLES1 };
+
+ /**
* Order of maximum fixed function profiles
*
* <ul>
@@ -1627,10 +1648,10 @@ public class GLProfile {
private static /*final*/ boolean hasDesktopGLFactory;
private static /*final*/ boolean hasGL234Impl;
- private static /*final*/ boolean hasEGLFactory;
+ private static /*final*/ boolean hasMobileFactory;
private static /*final*/ boolean hasGLES3Impl;
private static /*final*/ boolean hasGLES1Impl;
- private static /*final*/ boolean hasGL234OnEGLImpl;
+ private static /*final*/ boolean hasGL234OnMobileImpl;
private static /*final*/ Constructor<?> ctorGL234Impl;
private static /*final*/ Constructor<?> ctorGLES3Impl;
private static /*final*/ Constructor<?> ctorGLES1Impl;
@@ -1638,7 +1659,7 @@ public class GLProfile {
private static /*final*/ Constructor<?> ctorGLES3ProcAddr;
private static /*final*/ Constructor<?> ctorGLES1ProcAddr;
- private static /*final*/ GLDrawableFactoryImpl eglFactory = null;
+ private static /*final*/ GLDrawableFactoryImpl mobileFactory = null;
private static /*final*/ GLDrawableFactoryImpl desktopFactory = null;
private static /*final*/ AbstractGraphicsDevice defaultDevice = null;
@@ -1683,7 +1704,7 @@ public class GLProfile {
ctorGL234ProcAddr = null;
}
}
- hasGL234OnEGLImpl = hasGL234Impl;
+ hasGL234OnMobileImpl = hasGL234Impl;
// depends on hasEGLFactory
{
@@ -1748,7 +1769,7 @@ public class GLProfile {
try {
desktopFactory = (GLDrawableFactoryImpl) GLDrawableFactory.getFactoryImpl(GL2);
if(null != desktopFactory) {
- final DesktopGLDynamicLookupHelper glLookupHelper = (DesktopGLDynamicLookupHelper) desktopFactory.getGLDynamicLookupHelper(2, GLContext.CTX_PROFILE_COMPAT);
+ final GLDynamicLookupHelper glLookupHelper = desktopFactory.getGLDynamicLookupHelper(2, GLContext.CTX_PROFILE_COMPAT);
hasGL234Impl = null!=glLookupHelper && glLookupHelper.isLibComplete() && hasGL234Impl;
hasDesktopGLFactory = hasGL234Impl;
}
@@ -1777,48 +1798,46 @@ public class GLProfile {
defaultDesktopDevice = desktopFactory.getDefaultDevice();
}
- if ( ReflectionUtil.isClassAvailable("jogamp.opengl.egl.EGLDrawableFactory", classloader) ) {
- t=null;
- try {
- eglFactory = (GLDrawableFactoryImpl) GLDrawableFactory.getFactoryImpl(GLES2);
- if(null != eglFactory) {
- // update hasGLES1Impl, hasGLES3Impl, hasGL234OnEGLImpl based on library completion
- final GLDynamicLookupHelper es2DynLookup = eglFactory.getGLDynamicLookupHelper(2, GLContext.CTX_PROFILE_ES);
- final GLDynamicLookupHelper es1DynLookup = eglFactory.getGLDynamicLookupHelper(1, GLContext.CTX_PROFILE_ES);
- final GLDynamicLookupHelper glXDynLookup = eglFactory.getGLDynamicLookupHelper(3, GLContext.CTX_PROFILE_CORE);
- hasGLES3Impl = null!=es2DynLookup && es2DynLookup.isLibComplete() && hasGLES3Impl;
- hasGLES1Impl = null!=es1DynLookup && es1DynLookup.isLibComplete() && hasGLES1Impl;
- hasGL234OnEGLImpl = null!=glXDynLookup && glXDynLookup.isLibComplete() && hasGL234OnEGLImpl;
- hasEGLFactory = hasGLES3Impl || hasGLES1Impl || hasGL234OnEGLImpl;
- }
- } catch (final LinkageError le) {
- t=le;
- } catch (final SecurityException se) {
- t=se;
- } catch (final NullPointerException npe) {
- t=npe;
- } catch (final RuntimeException re) {
- t=re;
+ t=null;
+ try {
+ mobileFactory = (GLDrawableFactoryImpl) GLDrawableFactory.getFactoryImpl(GLES2);
+ if(null != mobileFactory) {
+ // update hasGLES1Impl, hasGLES3Impl, hasGL234OnEGLImpl based on library completion
+ final GLDynamicLookupHelper es2DynLookup = mobileFactory.getGLDynamicLookupHelper(2, GLContext.CTX_PROFILE_ES);
+ final GLDynamicLookupHelper es1DynLookup = mobileFactory.getGLDynamicLookupHelper(1, GLContext.CTX_PROFILE_ES);
+ final GLDynamicLookupHelper glXDynLookup = mobileFactory.getGLDynamicLookupHelper(3, GLContext.CTX_PROFILE_CORE);
+ hasGLES3Impl = null!=es2DynLookup && es2DynLookup.isLibComplete() && hasGLES3Impl;
+ hasGLES1Impl = null!=es1DynLookup && es1DynLookup.isLibComplete() && hasGLES1Impl;
+ hasGL234OnMobileImpl = null!=glXDynLookup && glXDynLookup.isLibComplete() && hasGL234OnMobileImpl;
+ hasMobileFactory = hasGLES3Impl || hasGLES1Impl || hasGL234OnMobileImpl;
}
- if(DEBUG) {
- if(null!=t) {
- t.printStackTrace();
- }
+ } catch (final LinkageError le) {
+ t=le;
+ } catch (final SecurityException se) {
+ t=se;
+ } catch (final NullPointerException npe) {
+ t=npe;
+ } catch (final RuntimeException re) {
+ t=re;
+ }
+ if(DEBUG) {
+ if(null!=t) {
+ t.printStackTrace();
}
}
- final AbstractGraphicsDevice defaultEGLDevice;
- if(null == eglFactory) {
- hasEGLFactory = false;
- hasGL234OnEGLImpl= false;
+ final AbstractGraphicsDevice defaultMobileDevice;
+ if(null == mobileFactory) {
+ hasMobileFactory = false;
+ hasGL234OnMobileImpl= false;
hasGLES3Impl = false;
hasGLES1Impl = false;
- defaultEGLDevice = null;
+ defaultMobileDevice = null;
if(DEBUG) {
- System.err.println("Info: GLProfile.init - EGL GLDrawable factory not available");
+ System.err.println("Info: GLProfile.init - Mobile GLDrawable factory not available");
}
} else {
- defaultEGLDevice = eglFactory.getDefaultDevice();
+ defaultMobileDevice = mobileFactory.getDefaultDevice();
}
if( null != defaultDesktopDevice ) {
@@ -1826,10 +1845,10 @@ public class GLProfile {
if(DEBUG) {
System.err.println("Info: GLProfile.init - Default device is desktop derived: "+defaultDevice);
}
- } else if ( null != defaultEGLDevice ) {
- defaultDevice = defaultEGLDevice;
+ } else if ( null != defaultMobileDevice ) {
+ defaultDevice = defaultMobileDevice;
if(DEBUG) {
- System.err.println("Info: GLProfile.init - Default device is EGL derived: "+defaultDevice);
+ System.err.println("Info: GLProfile.init - Default device is mobile derived: "+defaultDevice);
}
} else {
if(DEBUG) {
@@ -1839,22 +1858,22 @@ public class GLProfile {
}
// we require to initialize the EGL device 1st, if available
- final boolean addedEGLProfile = null != defaultEGLDevice ? initProfilesForDevice(defaultEGLDevice) : false;
+ final boolean addedMobileProfile = null != defaultMobileDevice ? initProfilesForDevice(defaultMobileDevice) : false;
final boolean addedDesktopProfile = null != defaultDesktopDevice ? initProfilesForDevice(defaultDesktopDevice) : false;
- final boolean addedAnyProfile = addedEGLProfile || addedDesktopProfile ;
+ final boolean addedAnyProfile = addedMobileProfile || addedDesktopProfile ;
if(DEBUG) {
- System.err.println("GLProfile.init addedAnyProfile "+addedAnyProfile+" (desktop: "+addedDesktopProfile+", egl "+addedEGLProfile+")");
+ System.err.println("GLProfile.init addedAnyProfile "+addedAnyProfile+" (desktop: "+addedDesktopProfile+", mobile "+addedMobileProfile+")");
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 hasMobileFactory "+hasMobileFactory);
System.err.println("GLProfile.init hasGLES1Impl "+hasGLES1Impl);
System.err.println("GLProfile.init hasGLES3Impl "+hasGLES3Impl);
- System.err.println("GLProfile.init hasGL234OnEGLImpl "+hasGL234OnEGLImpl);
+ System.err.println("GLProfile.init hasGL234OnEGLImpl "+hasGL234OnMobileImpl);
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 defaultDevice Mobile "+defaultMobileDevice);
System.err.println("GLProfile.init profile order "+array2String(GL_PROFILE_LIST_ALL));
}
}
@@ -1869,22 +1888,25 @@ public class GLProfile {
}
initLock.lock();
try {
- final GLDrawableFactory factory = GLDrawableFactory.getFactoryImpl(device);
- factory.enterThreadCriticalZone();
- try {
- return initProfilesForDeviceCritical(device);
- } finally {
- factory.leaveThreadCriticalZone();
+ final GLDrawableFactory factory = GLDrawableFactory.getFactory(device);
+ if( null != factory ) {
+ factory.enterThreadCriticalZone();
+ try {
+ return initProfilesForDeviceCritical(device);
+ } finally {
+ factory.leaveThreadCriticalZone();
+ }
}
} finally {
initLock.unlock();
}
+ return false;
}
private static boolean initProfilesForDeviceCritical(final AbstractGraphicsDevice device) {
final boolean isSet = GLContext.getAvailableGLVersionsSet(device);
if(DEBUG) {
- System.err.println("Info: GLProfile.initProfilesForDevice: "+device+" ("+device.getClass().getName()+"), isSet "+isSet+", hasDesktopGLFactory "+hasDesktopGLFactory+", hasEGLFactory "+hasEGLFactory);
+ System.err.println("Info: GLProfile.initProfilesForDevice: "+device+" ("+device.getClass().getName()+"), isSet "+isSet+", hasDesktopGLFactory "+hasDesktopGLFactory+", hasEGLFactory "+hasMobileFactory);
}
if(isSet) {
// Avoid recursion and check whether impl. is sane!
@@ -1899,7 +1921,7 @@ public class GLProfile {
HashMap<String, GLProfile> mappedDesktopProfiles = null;
boolean addedDesktopProfile = false;
HashMap<String, GLProfile> mappedEGLProfiles = null;
- boolean addedEGLProfile = false;
+ boolean addedMobileProfile = false;
final boolean deviceIsDesktopCompatible = hasDesktopGLFactory && desktopFactory.getIsDeviceCompatible(device);
@@ -1930,20 +1952,20 @@ public class GLProfile {
}
}
- final boolean deviceIsEGLCompatible = hasEGLFactory && eglFactory.getIsDeviceCompatible(device);
+ final boolean deviceIsMobileCompatible = hasMobileFactory && mobileFactory.getIsDeviceCompatible(device);
// also test GLES1, GLES2 and GLES3 on desktop, since we have implementations / emulations available.
- if( deviceIsEGLCompatible ) {
+ if( deviceIsMobileCompatible ) {
// 1st pretend we have all EGL profiles ..
computeProfileMap(device, true /* desktopCtxUndef*/, true /* esCtxUndef */);
// Triggers eager initialization of share context in GLDrawableFactory for the device,
// hence querying all available GLProfiles
- final Thread sharedResourceThread = eglFactory.getSharedResourceThread();
+ final Thread sharedResourceThread = mobileFactory.getSharedResourceThread();
if(null != sharedResourceThread) {
initLock.addOwner(sharedResourceThread);
}
- final boolean eglSharedCtxAvail = eglFactory.createSharedResource(device);
+ final boolean eglSharedCtxAvail = mobileFactory.createSharedResource(device);
if(null != sharedResourceThread) {
initLock.removeOwner(sharedResourceThread);
}
@@ -1952,28 +1974,28 @@ public class GLProfile {
throw new InternalError("Available GLVersions not set for "+device);
}
mappedEGLProfiles = computeProfileMap(device, false /* desktopCtxUndef*/, false /* esCtxUndef */);
- addedEGLProfile = mappedEGLProfiles.size() > 0;
+ addedMobileProfile = mappedEGLProfiles.size() > 0;
}
if (DEBUG) {
- System.err.println("GLProfile.initProfilesForDevice: "+device+": egl Shared Ctx "+eglSharedCtxAvail+
- ", profiles: "+(addedEGLProfile ? mappedEGLProfiles.size() : 0));
+ System.err.println("GLProfile.initProfilesForDevice: "+device+": mobile Shared Ctx "+eglSharedCtxAvail+
+ ", profiles: "+(addedMobileProfile ? mappedEGLProfiles.size() : 0));
}
}
- if( !addedDesktopProfile && !addedEGLProfile ) {
+ if( !addedDesktopProfile && !addedMobileProfile ) {
setProfileMap(device, new HashMap<String /*GLProfile_name*/, GLProfile>()); // empty
if(DEBUG) {
System.err.println("GLProfile: device could not be initialized: "+device);
System.err.println("GLProfile: compatible w/ desktop: "+deviceIsDesktopCompatible+
- ", egl "+deviceIsEGLCompatible);
+ ", mobile "+deviceIsMobileCompatible);
System.err.println("GLProfile: desktoplFactory "+desktopFactory);
- System.err.println("GLProfile: eglFactory "+eglFactory);
+ System.err.println("GLProfile: mobileFactory "+mobileFactory);
System.err.println("GLProfile: hasGLES1Impl "+hasGLES1Impl);
System.err.println("GLProfile: hasGLES3Impl "+hasGLES3Impl);
}
} else {
final HashMap<String, GLProfile> mappedAllProfiles = new HashMap<String, GLProfile>();
- if( addedEGLProfile ) {
+ if( addedMobileProfile ) {
mappedAllProfiles.putAll(mappedEGLProfiles);
}
if( addedDesktopProfile ) {
@@ -1985,7 +2007,7 @@ public class GLProfile {
GLContext.setAvailableGLVersionsSet(device, true);
if (DEBUG) {
- System.err.println("GLProfile.initProfilesForDevice: "+device.getUniqueID()+": added profile(s): desktop "+addedDesktopProfile+", egl "+addedEGLProfile);
+ System.err.println("GLProfile.initProfilesForDevice: "+device.getUniqueID()+": added profile(s): desktop "+addedDesktopProfile+", mobile "+addedMobileProfile);
System.err.println("GLProfile.initProfilesForDevice: "+device.getUniqueID()+": "+glAvailabilityToString(device));
if(addedDesktopProfile) {
dumpGLInfo(desktopFactory, device);
@@ -1993,16 +2015,16 @@ public class GLProfile {
for(int i=0; i<availCaps.size(); i++) {
System.err.println(availCaps.get(i));
}
- } else if(addedEGLProfile) {
- dumpGLInfo(eglFactory, device);
- final List<GLCapabilitiesImmutable> availCaps = eglFactory.getAvailableCapabilities(device);
+ } else if(addedMobileProfile) {
+ dumpGLInfo(mobileFactory, device);
+ final List<GLCapabilitiesImmutable> availCaps = mobileFactory.getAvailableCapabilities(device);
for(int i=0; i<availCaps.size(); i++) {
System.err.println(availCaps.get(i));
}
}
}
- return addedDesktopProfile || addedEGLProfile;
+ return addedDesktopProfile || addedMobileProfile;
}
private static void dumpGLInfo(final GLDrawableFactoryImpl factory, final AbstractGraphicsDevice device) {
@@ -2106,7 +2128,7 @@ public class GLProfile {
* Returns the profile implementation
*/
private static String computeProfileImpl(final AbstractGraphicsDevice device, final String profile, final boolean desktopCtxUndef, final boolean esCtxUndef, final boolean isHardwareRasterizer[]) {
- final boolean hasAnyGL234Impl = hasGL234Impl || hasGL234OnEGLImpl;
+ final boolean hasAnyGL234Impl = hasGL234Impl || hasGL234OnMobileImpl;
final boolean hardwareRasterizer[] = new boolean[1];
if ( GL2ES1 == profile ) {
final boolean gles1Available;
diff --git a/src/jogl/classes/com/jogamp/opengl/JoglVersion.java b/src/jogl/classes/com/jogamp/opengl/JoglVersion.java
index 560d99025..92511dc11 100644
--- a/src/jogl/classes/com/jogamp/opengl/JoglVersion.java
+++ b/src/jogl/classes/com/jogamp/opengl/JoglVersion.java
@@ -69,11 +69,12 @@ public class JoglVersion extends JogampVersion {
return toString(gl, null).toString();
}
- public static StringBuilder getAvailableCapabilitiesInfo(final GLDrawableFactory factory, final AbstractGraphicsDevice device, StringBuilder sb) {
+ public static StringBuilder getAvailableCapabilitiesInfo(final AbstractGraphicsDevice device, StringBuilder sb) {
if(null==sb) {
sb = new StringBuilder();
}
boolean done = false;
+ final GLDrawableFactory factory = GLDrawableFactory.getFactory(device);
if(null!=factory) {
try {
final List<GLCapabilitiesImmutable> availCaps = factory.getAvailableCapabilities(device);
@@ -100,10 +101,12 @@ public class JoglVersion extends JogampVersion {
device = GLProfile.getDefaultDevice();
}
sb.append(Platform.getNewline()).append(Platform.getNewline());
- sb.append("Desktop Capabilities: ").append(Platform.getNewline());
- getAvailableCapabilitiesInfo(GLDrawableFactory.getDesktopFactory(), device, sb);
- sb.append("EGL Capabilities: ").append(Platform.getNewline());
- getAvailableCapabilitiesInfo(GLDrawableFactory.getEGLFactory(), device, sb);
+ try {
+ sb.append("Capabilities for ").append(device.toString()).append(Platform.getNewline());
+ getAvailableCapabilitiesInfo(device, sb);
+ } catch (final GLException gle) {
+ System.err.println(gle.getMessage());
+ }
return sb;
}
diff --git a/src/jogl/classes/jogamp/opengl/DummyGLExtProcAddressTable.java b/src/jogl/classes/jogamp/opengl/DummyGLExtProcAddressTable.java
new file mode 100644
index 000000000..1cde06e3c
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/DummyGLExtProcAddressTable.java
@@ -0,0 +1,61 @@
+/**
+ * Copyright 2019 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 com.jogamp.gluegen.runtime.ProcAddressTable;
+import com.jogamp.common.util.SecurityUtil;
+
+/**
+ * Representing the non-existing platform GL extension, i.e. a dummy type.
+ * <p>
+ * This table is a cache of pointers to the dynamically-linkable C library.
+ * </p>
+ * @see ProcAddressTable
+ */
+public final class DummyGLExtProcAddressTable extends ProcAddressTable {
+
+ public DummyGLExtProcAddressTable(){ super(); }
+
+ public DummyGLExtProcAddressTable(final com.jogamp.gluegen.runtime.FunctionAddressResolver resolver){ super(resolver); }
+
+ @Override
+ protected boolean isFunctionAvailableImpl(final String functionNameUsr) throws IllegalArgumentException {
+ return false;
+ }
+ @Override
+ public long getAddressFor(final String functionNameUsr) throws SecurityException, IllegalArgumentException {
+ SecurityUtil.checkAllLinkPermission();
+ final String functionNameBase = com.jogamp.gluegen.runtime.opengl.GLNameResolver.normalizeVEN(com.jogamp.gluegen.runtime.opengl.GLNameResolver.normalizeARB(functionNameUsr, true), true);
+ // The user is calling a bogus function or one which is not
+ // runtime linked
+ throw new RuntimeException(
+ "WARNING: Address field query failed for \"" + functionNameBase + "\"/\"" + functionNameUsr +
+ "\"; it's either statically linked or address field is not a known " +
+ "function");
+ }
+}
diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
index 6866374bc..84c62b95d 100644
--- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java
@@ -2442,10 +2442,13 @@ public abstract class GLContextImpl extends GLContext {
GLRendererQuirks.pushStickyDeviceQuirks(factoryDefaultDevice, quirks);
}
if( isES ) {
- final AbstractGraphicsDevice eglFactoryDefaultDevice = GLDrawableFactory.getEGLFactory().getDefaultDevice();
- if( !GLRendererQuirks.areSameStickyDevice(eglFactoryDefaultDevice, adevice) &&
- !GLRendererQuirks.areSameStickyDevice(eglFactoryDefaultDevice, factoryDefaultDevice) ) {
- GLRendererQuirks.pushStickyDeviceQuirks(eglFactoryDefaultDevice, quirks);
+ final GLDrawableFactory mobileFactory = GLDrawableFactory.getFactory(true);
+ if( null != factory ) {
+ final AbstractGraphicsDevice esFactoryDefaultDevice = mobileFactory.getDefaultDevice();
+ if( !GLRendererQuirks.areSameStickyDevice(esFactoryDefaultDevice, adevice) &&
+ !GLRendererQuirks.areSameStickyDevice(esFactoryDefaultDevice, factoryDefaultDevice) ) {
+ GLRendererQuirks.pushStickyDeviceQuirks(esFactoryDefaultDevice, quirks);
+ }
}
}
}
diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java b/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java
index dfe6bdd9f..2e108d3ce 100644
--- a/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java
@@ -68,12 +68,16 @@ import com.jogamp.opengl.GLOffscreenAutoDrawable;
import com.jogamp.opengl.GLProfile;
import com.jogamp.common.ExceptionUtils;
+import com.jogamp.common.os.Platform;
import com.jogamp.nativewindow.MutableGraphicsConfiguration;
import com.jogamp.nativewindow.DelegatedUpstreamSurfaceHookWithSurfaceSize;
+import com.jogamp.nativewindow.GenericUpstreamSurfacelessHook;
import com.jogamp.nativewindow.UpstreamSurfaceHookMutableSize;
import com.jogamp.opengl.GLAutoDrawableDelegate;
import com.jogamp.opengl.GLRendererQuirks;
+import jogamp.common.os.PlatformPropsImpl;
+
/** Extends GLDrawableFactory with a few methods for handling
typically software-accelerated offscreen rendering (Device
@@ -275,8 +279,18 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
GLDrawable result = null;
adevice.lock();
try {
+ final boolean forceOnscreenFBOLayer;
+ final boolean useFBORendertarget;
+ if( chosenCaps.isOnscreen() && Platform.OSType.IOS == PlatformPropsImpl.OS_TYPE ) // FIXME: avoid hardcoding?
+ {
+ forceOnscreenFBOLayer = true;
+ useFBORendertarget = true;
+ } else {
+ forceOnscreenFBOLayer = false;
+ useFBORendertarget = false;
+ }
final OffscreenLayerSurface ols = NativeWindowFactory.getOffscreenLayerSurface(target, true);
- if(null != ols) {
+ if(null != ols || forceOnscreenFBOLayer ) {
final GLCapabilitiesImmutable chosenCapsMod = GLGraphicsConfigurationUtil.fixOffscreenGLCapabilities(chosenCaps, this, adevice);
// layered surface -> Offscreen/[FBO|PBuffer]
@@ -284,12 +298,15 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
throw new GLException("Neither FBO nor Pbuffer is available for "+chosenCapsMod+", "+target);
}
config.setChosenCapabilities(chosenCapsMod);
- ols.setChosenCapabilities(chosenCapsMod);
+ if( null != ols ) {
+ ols.setChosenCapabilities(chosenCapsMod);
+ }
if(DEBUG) {
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("forceOnscreenFBOLayer: **** "+forceOnscreenFBOLayer+", useFBORendertarget "+useFBORendertarget);
System.err.println("Target: **** "+target);
ExceptionUtils.dumpStack(System.err);
}
@@ -297,7 +314,7 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
throw new IllegalArgumentException("Passed NativeSurface must implement SurfaceChangeable for offscreen layered surface: "+target);
}
if( chosenCapsMod.isFBO() ) {
- result = createFBODrawableImpl(target, chosenCapsMod, 0);
+ result = createFBODrawableImpl(target, chosenCapsMod, useFBORendertarget?-1:0);
} else {
result = createOffscreenDrawableImpl(target);
}
@@ -433,6 +450,60 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory {
new UpstreamSurfaceHookMutableSize(width, height) ) );
}
+ /**
+ * Quick path to produce a Surfaceless resizable FBO Drawable.
+ * <p>
+ * Caller has to be sure Surfaceless context as well as FBO is supported
+ * on the platform, no checks will be made.
+ * </p>
+ * @param device2Use actual device to be used
+ * @param capsRequested
+ * @param width
+ * @param height
+ */
+ protected final GLFBODrawableImpl createSurfacelessFBODrawable(final AbstractGraphicsDevice device2Use,
+ final GLCapabilitiesImmutable capsRequested,
+ final int width, final int height) {
+ if(width<=0 || height<=0) {
+ throw new GLException("initial size must be positive (were (" + width + " x " + height + "))");
+ }
+ final GLCapabilities capsChosen = (GLCapabilities) capsRequested.cloneMutable();
+ {
+ capsChosen.setOnscreen(false);
+ capsChosen.setFBO( true );
+ capsChosen.setPBuffer( false );
+ capsChosen.setBitmap( false );
+ }
+ // final ProxySurface surface = createSurfacelessImpl(device2Use, false, glCapsMin, capsRequested, null, width, height);
+ final GLCapabilitiesImmutable surfaceCaps = GLGraphicsConfigurationUtil.fixOnscreenGLCapabilities(capsRequested);
+ final ProxySurface surface = createMutableSurfaceImpl(device2Use, false /* createNewDevice */, surfaceCaps, capsRequested, null, new GenericUpstreamSurfacelessHook(width, height));
+
+ final GLDrawableImpl dummyDrawable = createOnscreenDrawableImpl(surface);
+ return new GLFBODrawableImpl.ResizeableImpl(this, dummyDrawable, surface, capsChosen, 0);
+ }
+ /**
+ * Quick path to produce a Surfaceless Drawable.
+ * <p>
+ * Caller has to be sure Surfaceless context is supported
+ * on the platform, no checks will be made.
+ * </p>
+ * @param device2Use actual device to be used
+ * @param capsRequested
+ * @param width
+ * @param height
+ */
+ protected final GLDrawableImpl createSurfacelessDrawable(final AbstractGraphicsDevice device2Use,
+ final GLCapabilitiesImmutable capsRequested,
+ final int width, final int height) {
+ if(width<=0 || height<=0) {
+ throw new GLException("initial size must be positive (were (" + width + " x " + height + "))");
+ }
+ // final ProxySurface surface = createSurfacelessImpl(device2Use, false, glCapsMin, capsRequested, null, width, height);
+ final GLCapabilitiesImmutable surfaceCaps = GLGraphicsConfigurationUtil.fixOnscreenGLCapabilities(capsRequested);
+ final ProxySurface surface = createMutableSurfaceImpl(device2Use, false /* createNewDevice */, surfaceCaps, capsRequested, null, new GenericUpstreamSurfacelessHook(width, height));
+ return createOnscreenDrawableImpl(surface);
+ }
+
@Override
public final GLDrawable createDummyDrawable(final AbstractGraphicsDevice deviceReq, final boolean createNewDevice, final GLCapabilitiesImmutable capsRequested, final GLCapabilitiesChooser chooser) {
final AbstractGraphicsDevice device = createNewDevice ? getOrCreateSharedDevice(deviceReq) : deviceReq;
diff --git a/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java b/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java
index cddaebe25..64cca7bdd 100644
--- a/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java
+++ b/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java
@@ -87,17 +87,17 @@ public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable {
* @param parent
* @param surface
* @param fboCaps the requested FBO capabilities
- * @param textureUnit
+ * @param textureUnit if valid, i.e. >= 0, signals {@link #FBOMODE_USE_TEXTURE}, otherwise a color renderbuffer is assumed
*/
protected GLFBODrawableImpl(final GLDrawableFactoryImpl factory, final GLDrawableImpl parent, final NativeSurface surface,
final GLCapabilitiesImmutable fboCaps, final int textureUnit) {
super(factory, surface, fboCaps, false);
this.initialized = false;
- this.fboModeBits = FBOMODE_USE_TEXTURE;
+ this.fboModeBits = textureUnit>=0 ? FBOMODE_USE_TEXTURE : 0;
this.parent = parent;
this.origParentChosenCaps = getChosenGLCapabilities(); // just to avoid null, will be reset at initialize(..)
- this.texUnit = textureUnit;
+ this.texUnit = textureUnit>=0 ? textureUnit : 0;
this.samples = fboCaps.getNumSamples();
this.fboResetQuirk = false;
this.swapBufferContext = null;
diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLGLnDynamicLibraryBundleInfo.java b/src/jogl/classes/jogamp/opengl/egl/EGLGLnDynamicLibraryBundleInfo.java
index 6a3a20100..b30a901f4 100644
--- a/src/jogl/classes/jogamp/opengl/egl/EGLGLnDynamicLibraryBundleInfo.java
+++ b/src/jogl/classes/jogamp/opengl/egl/EGLGLnDynamicLibraryBundleInfo.java
@@ -59,7 +59,7 @@ public final class EGLGLnDynamicLibraryBundleInfo extends EGLDynamicLibraryBundl
if( Platform.OSType.MACOS == osType ) {
libsGL.add("/System/Library/Frameworks/OpenGL.framework/Libraries/libGL.dylib");
libsGL.add("GL");
- } else if( Platform.OSType.WINDOWS == Platform.getOSType() ) {
+ } else if( Platform.OSType.WINDOWS == osType ) {
libsGL.add("OpenGL32");
} else {
// this is the default lib name, according to the spec
diff --git a/src/jogl/classes/jogamp/opengl/ios/eagl/IOSEAGLContext.java b/src/jogl/classes/jogamp/opengl/ios/eagl/IOSEAGLContext.java
new file mode 100644
index 000000000..57c20d465
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/ios/eagl/IOSEAGLContext.java
@@ -0,0 +1,477 @@
+/**
+ * Copyright 2019 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.ios.eagl;
+
+import java.util.Map;
+
+import com.jogamp.nativewindow.AbstractGraphicsConfiguration;
+import com.jogamp.nativewindow.AbstractGraphicsDevice;
+import com.jogamp.nativewindow.MutableGraphicsConfiguration;
+import com.jogamp.nativewindow.OffscreenLayerSurface;
+import com.jogamp.opengl.FBObject;
+import com.jogamp.opengl.GL;
+import com.jogamp.opengl.GLCapabilitiesImmutable;
+import com.jogamp.opengl.GLContext;
+import com.jogamp.opengl.GLException;
+import com.jogamp.opengl.GLFBODrawable;
+import com.jogamp.opengl.GLProfile;
+
+import jogamp.nativewindow.ios.IOSUtil;
+import jogamp.opengl.GLContextImpl;
+import jogamp.opengl.GLDrawableImpl;
+import jogamp.opengl.GLDynamicLookupHelper;
+import jogamp.opengl.GLFBODrawableImpl;
+import jogamp.opengl.GLFBODrawableImpl.SwapBufferContext;
+import jogamp.opengl.DummyGLExtProcAddressTable;
+import jogamp.opengl.ios.eagl.IOSEAGLDrawable.GLBackendType;
+
+import com.jogamp.common.os.Platform;
+import com.jogamp.gluegen.runtime.ProcAddressTable;
+import com.jogamp.gluegen.runtime.opengl.GLProcAddressResolver;
+import com.jogamp.opengl.GLRendererQuirks;
+
+public class IOSEAGLContext extends GLContextImpl
+{
+ // Abstract interface for implementation of this context
+ protected interface GLBackendImpl {
+ /** Indicating CALayer, i.e. onscreen rendering using offscreen layer. */
+ boolean isUsingCAEAGLLayer();
+ long create(long share, int ctp, int major, int minor);
+ boolean destroy(long ctx);
+ void associateDrawable(boolean bound);
+ boolean makeCurrent(long ctx);
+ boolean release(long ctx);
+ }
+
+ static boolean isGLProfileSupported(final int ctp, final int major, final int minor) {
+ if( 0 == ( CTX_PROFILE_ES & ctp ) ) {
+ // only ES profiles supported
+ return false;
+ }
+ return true;
+ }
+ static int GLProfile2EAGLProfileValue(final int ctp, final int major, final int minor) {
+ if(!isGLProfileSupported(ctp, major, minor)) {
+ throw new GLException("OpenGL profile not supported.0: "+getGLVersion(major, minor, ctp, "@GLProfile2EAGLProfileValue"));
+ }
+ switch( major ) {
+ case 1:
+ return EAGL.kEAGLRenderingAPIOpenGLES1;
+ case 2:
+ return EAGL.kEAGLRenderingAPIOpenGLES2;
+ case 3:
+ return EAGL.kEAGLRenderingAPIOpenGLES3;
+ }
+ throw new GLException("OpenGL profile not supported.1: "+getGLVersion(major, minor, ctp, "@GLProfile2EAGLProfileValue"));
+ }
+
+ private boolean haveSetOpenGLMode = false;
+ private GLBackendType openGLMode = GLBackendType.CAEAGL_LAYER;
+
+ // Implementation object (either NSOpenGL-based or CGL-based)
+ protected GLBackendImpl impl;
+
+ // CGL extension functions.
+ private DummyGLExtProcAddressTable cglExtProcAddressTable;
+
+ private int lastWidth, lastHeight;
+
+ protected IOSEAGLContext(final GLDrawableImpl drawable,
+ final GLContext shareWith) {
+ super(drawable, shareWith);
+ initOpenGLImpl(getOpenGLMode());
+ }
+
+ @Override
+ protected void resetStates(final boolean isInit) {
+ // no inner state _cglExt = null;
+ super.resetStates(isInit);
+ }
+
+ @Override
+ public Object getPlatformGLExtensions() {
+ return null;
+ }
+
+ @Override
+ public final ProcAddressTable getPlatformExtProcAddressTable() {
+ return getCGLExtProcAddressTable();
+ }
+
+ public final DummyGLExtProcAddressTable getCGLExtProcAddressTable() {
+ return cglExtProcAddressTable;
+ }
+
+ @Override
+ protected Map<String, String> getFunctionNameMap() { return null; }
+
+ @Override
+ protected Map<String, String> getExtensionNameMap() { return null; }
+
+ @Override
+ protected long createContextARBImpl(final long share, final boolean direct, final int ctp, final int major, final int minor) {
+ if(!isGLProfileSupported(ctp, major, minor)) {
+ if(DEBUG) {
+ System.err.println(getThreadName() + ": createContextARBImpl: Not supported "+getGLVersion(major, minor, ctp, "@creation on iOS "+Platform.getOSVersionNumber()));
+ }
+ return 0;
+ }
+
+ // Will throw exception upon error
+ long ctx = impl.create(share, ctp, major, minor);
+ if(0 != ctx) {
+ if (!impl.makeCurrent(ctx)) {
+ if(DEBUG) {
+ System.err.println(getThreadName() + ": createContextARB couldn't make current "+getGLVersion(major, minor, ctp, "@creation"));
+ }
+ impl.release(ctx);
+ impl.destroy(ctx);
+ ctx = 0;
+ } else if(DEBUG) {
+ System.err.println(getThreadName() + ": createContextARBImpl: OK "+getGLVersion(major, minor, ctp, "@creation")+", share "+share+", direct "+direct+" on iOS "+Platform.getOSVersionNumber());
+ }
+ } else if(DEBUG) {
+ System.err.println(getThreadName() + ": createContextARBImpl: NO "+getGLVersion(major, minor, ctp, "@creation on iOS "+Platform.getOSVersionNumber()));
+ }
+ return ctx;
+ }
+
+ @Override
+ protected void destroyContextARBImpl(final long _context) {
+ impl.release(_context);
+ impl.destroy(_context);
+ }
+
+ @Override
+ public final boolean isGLReadDrawableAvailable() {
+ return false;
+ }
+
+ @Override
+ protected boolean createImpl(final long shareWithHandle) throws GLException {
+ final MutableGraphicsConfiguration config = (MutableGraphicsConfiguration) drawable.getNativeSurface().getGraphicsConfiguration();
+ final AbstractGraphicsDevice device = config.getScreen().getDevice();
+ final GLCapabilitiesImmutable glCaps = (GLCapabilitiesImmutable) config.getChosenCapabilities();
+ final GLProfile glp = glCaps.getGLProfile();
+ final boolean createContextARBAvailable = isCreateContextARBAvail(device);
+ if(DEBUG) {
+ System.err.println(getThreadName() + ": IOSEAGLContext.createImpl: START "+glCaps+", share "+toHexString(shareWithHandle));
+ System.err.println(getThreadName() + ": Use ARB[avail["+getCreateContextARBAvailStr(device)+
+ "] -> "+createContextARBAvailable+"]]");
+ }
+ if( !glp.isGLES() ) {
+ throw new GLException("Desktop OpenGL profile not supported on iOS "+Platform.getOSVersionNumber()+": "+glp);
+ }
+ contextHandle = createContextARB(shareWithHandle, true);
+ return 0 != contextHandle;
+ }
+
+ @Override
+ protected void makeCurrentImpl() throws GLException {
+ /** FIXME: won't work w/ special drawables (like FBO) - check for CGL mode regressions!
+ *
+ if (getOpenGLMode() != ((IOSEAGLDrawable)drawable).getOpenGLMode()) {
+ setOpenGLMode(((IOSEAGLDrawable)drawable).getOpenGLMode());
+ } */
+ if ( !impl.makeCurrent(contextHandle) ) {
+ throw new GLException("Error making Context current: "+this);
+ }
+ drawableUpdatedNotify();
+ }
+
+ @Override
+ protected void releaseImpl() throws GLException {
+ if (!impl.release(contextHandle)) {
+ throw new GLException("Error releasing OpenGL Context: "+this);
+ }
+ }
+
+ @Override
+ protected void destroyImpl() throws GLException {
+ if(!impl.destroy(contextHandle)) {
+ throw new GLException("Error destroying OpenGL Context: "+this);
+ }
+ }
+
+ @Override
+ protected void drawableUpdatedNotify() throws GLException {
+ if( drawable.getChosenGLCapabilities().isOnscreen() ) {
+ final int w = drawable.getSurfaceWidth();
+ final int h = drawable.getSurfaceHeight();
+ // final boolean sizeChanged = w != lastWidth || h != lastHeight;
+ if(drawable instanceof GLFBODrawable) {
+ final GLFBODrawable fbod = (GLFBODrawable) drawable;
+ final FBObject.Colorbuffer col = fbod.getColorbuffer(GL.GL_FRONT); // FIXME GL_BACK swap ..
+ final int renderbuffer = col.getName();
+ EAGL.eaglPresentRenderbuffer(contextHandle, renderbuffer);
+ }
+ // TODO: Check for resize ...
+ lastWidth = w;
+ lastHeight = h;
+ }
+ }
+
+ @Override
+ protected void associateDrawable(final boolean bound) {
+ // context stuff depends on drawable stuff
+ if(bound) {
+ final GLDrawableImpl drawable = getDrawableImpl();
+ if( drawable instanceof GLFBODrawableImpl ) {
+ final GLFBODrawableImpl fboDrawable = (GLFBODrawableImpl) drawable;
+ fboDrawable.setSwapBufferContext(new SwapBufferContext() {
+ @Override
+ public void swapBuffers(final boolean doubleBuffered) {
+ EAGL.eaglPresentRenderbuffer(contextHandle, GL.GL_RENDERBUFFER);
+ } } );
+ }
+ // FIXME: Need better way to inject the IOS EAGL Layer into FBObject
+ // FIXME: May want to implement optional injection of a BufferStorage SPI?
+ // FBObject.ColorAttachment.initialize(GL): EAGL.eaglBindDrawableStorageToRenderbuffer(contextHandle, GL.GL_RENDERBUFFER, eaglLayer);
+ final long eaglLayer = IOSUtil.GetCAEAGLLayer(drawable.getNativeSurface().getSurfaceHandle());
+ System.err.println("EAGL: Ctx attach EAGLLayer 0x"+Long.toHexString(eaglLayer));
+ attachObject("IOS_EAGL_LAYER", new Long(eaglLayer));
+
+ super.associateDrawable(true); // 1) init drawable stuff (FBO init, ..)
+ impl.associateDrawable(true); // 2) init context stuff
+ } else {
+ impl.associateDrawable(false); // 1) free context stuff
+ super.associateDrawable(false); // 2) free drawable stuff
+
+ EAGL.eaglBindDrawableStorageToRenderbuffer(contextHandle, GL.GL_RENDERBUFFER, 0);
+ detachObject("IOS_EAGL_LAYER");
+ }
+ }
+
+ @Override
+ protected void copyImpl(final GLContext source, final int mask) throws GLException {
+ throw new GLException("copyImpl n/a: "+this);
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * Ignoring {@code contextFQN}, using {@code iOS}-{@link AbstractGraphicsDevice#getUniqueID()}.
+ * </p>
+ */
+ @Override
+ protected final void updateGLXProcAddressTable(final String contextFQN, final GLDynamicLookupHelper dlh) {
+ if( null == dlh ) {
+ throw new GLException("No GLDynamicLookupHelper for "+this);
+ }
+ final AbstractGraphicsConfiguration aconfig = drawable.getNativeSurface().getGraphicsConfiguration();
+ final AbstractGraphicsDevice adevice = aconfig.getScreen().getDevice();
+ final String key = "iOS-"+adevice.getUniqueID();
+ if (DEBUG) {
+ System.err.println(getThreadName() + ": Initializing EAGL extension address table: "+key);
+ }
+ ProcAddressTable table = null;
+ synchronized(mappedContextTypeObjectLock) {
+ table = mappedGLXProcAddress.get( key );
+ }
+ if(null != table) {
+ cglExtProcAddressTable = (DummyGLExtProcAddressTable) table;
+ if(DEBUG) {
+ System.err.println(getThreadName() + ": GLContext CGL ProcAddressTable reusing key("+key+") -> "+toHexString(table.hashCode()));
+ }
+ } else {
+ cglExtProcAddressTable = new DummyGLExtProcAddressTable(new GLProcAddressResolver());
+ resetProcAddressTable(getCGLExtProcAddressTable(), dlh);
+ synchronized(mappedContextTypeObjectLock) {
+ mappedGLXProcAddress.put(key, getCGLExtProcAddressTable());
+ if(DEBUG) {
+ System.err.println(getThreadName() + ": GLContext CGL ProcAddressTable mapping key("+key+") -> "+toHexString(getCGLExtProcAddressTable().hashCode()));
+ }
+ }
+ }
+ }
+
+ @Override
+ protected final StringBuilder getPlatformExtensionsStringImpl() {
+ return new StringBuilder();
+ }
+
+ // Support for "mode switching" as described in IOSEAGLDrawable
+ public void setOpenGLMode(final GLBackendType mode) {
+ if (mode == openGLMode) {
+ return;
+ }
+ if (haveSetOpenGLMode) {
+ throw new GLException("Can't switch between using EAGL and ... more than once");
+ }
+ destroyImpl();
+ ((IOSEAGLDrawable)drawable).setOpenGLMode(mode);
+ if (DEBUG) {
+ System.err.println("IOSEAGLContext: Switching context mode " + openGLMode + " -> " + mode);
+ }
+ initOpenGLImpl(mode);
+ openGLMode = mode;
+ haveSetOpenGLMode = true;
+ }
+ public final GLBackendType getOpenGLMode() { return openGLMode; }
+
+ protected void initOpenGLImpl(final GLBackendType backend) {
+ switch (backend) {
+ case CAEAGL_LAYER:
+ impl = new CAEAGLLayerImpl();
+ break;
+ default:
+ throw new InternalError("Illegal implementation mode " + backend);
+ }
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append(getClass().getSimpleName());
+ sb.append(" [");
+ super.append(sb);
+ sb.append("] ");
+ return sb.toString();
+ }
+
+ class CAEAGLLayerImpl implements GLBackendImpl {
+ private final OffscreenLayerSurface backingLayerHost = null;
+
+ @Override
+ public boolean isUsingCAEAGLLayer() { return null != backingLayerHost; }
+
+ /** Only returns a valid UIView. If !UIView, return null and mark isFBO or isSurfaceless. */
+ private long getUIViewHandle(final boolean[] isFBO, final boolean[] isSurfaceless) {
+ final long uiViewHandle;
+ if(drawable instanceof GLFBODrawableImpl) {
+ uiViewHandle = 0;
+ isFBO[0] = true;
+ isSurfaceless[0] = false;
+ if(DEBUG) {
+ System.err.println("UI viewHandle.1: GLFBODrawableImpl drawable: isFBO "+isFBO[0]+", isSurfaceless "+isSurfaceless[0]+", "+drawable.getClass().getName()+",\n\t"+drawable);
+ }
+ } else {
+ final long drawableHandle = drawable.getHandle();
+ final boolean isUIView = IOSUtil.isUIView(drawableHandle);
+ final boolean isUIWindow = IOSUtil.isUIWindow(drawableHandle);
+ isFBO[0] = false;
+ isSurfaceless[0] = false;
+
+ if( isUIView ) {
+ uiViewHandle = drawableHandle;
+ } else if( isUIWindow ) {
+ uiViewHandle = IOSUtil.GetUIView(drawableHandle, true /* only EAGL */);
+ } else if( isSurfaceless() ) {
+ isSurfaceless[0] = true;
+ uiViewHandle = 0;
+ } else {
+ throw new GLException("Drawable's handle neither NSView, NSWindow nor PBuffer: drawableHandle "+toHexString(drawableHandle)+", isNSView "+isUIView+", isNSWindow "+isUIWindow+", isFBO "+isFBO[0]+", "+drawable.getClass().getName()+",\n\t"+drawable);
+ }
+ if(DEBUG) {
+ System.err.println("NS viewHandle.2: drawableHandle "+toHexString(drawableHandle)+" -> nsViewHandle "+toHexString(uiViewHandle)+": isNSView "+isUIView+", isNSWindow "+isUIWindow+", isFBO "+isFBO[0]+", isSurfaceless "+isSurfaceless[0]+", "+drawable.getClass().getName()+",\n\t"+drawable);
+ }
+ }
+ return uiViewHandle;
+ }
+
+ @Override
+ public long create(final long share, final int ctp, final int major, final int minor) {
+ long ctx = 0;
+ final MutableGraphicsConfiguration config = (MutableGraphicsConfiguration) drawable.getNativeSurface().getGraphicsConfiguration();
+ final GLCapabilitiesImmutable chosenCaps = (GLCapabilitiesImmutable)config.getChosenCapabilities();
+ // Create new context
+ if (DEBUG) {
+ System.err.println("Share context for EAGL-based context is " + toHexString(share));
+ }
+ final boolean isFBO = drawable instanceof GLFBODrawableImpl;
+ final int api = GLProfile2EAGLProfileValue(ctp, major, minor);
+ if( 0 != share ) {
+ ctx = EAGL.eaglCreateContextShared(api, EAGL.eaglGetSharegroup(share));
+ } else {
+ ctx = EAGL.eaglCreateContext(api);
+ }
+ if (0 != ctx) {
+ final GLCapabilitiesImmutable fixedCaps;
+ if( isFBO ) {
+ fixedCaps = chosenCaps;
+ } else {
+ if( DEBUG ) {
+ System.err.println("Warning: CAEAGLLayer w/ non FBO caps");
+ }
+ fixedCaps = chosenCaps;
+ }
+ if(DEBUG) {
+ 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 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 surface native-handle: "+toHexString(drawable.getNativeSurface().getSurfaceHandle()));
+ // Thread.dumpStack();
+ }
+ config.setChosenCapabilities(fixedCaps);
+ if(DEBUG) {
+ System.err.println("EAGL create fixedCaps: "+fixedCaps);
+ }
+ }
+ return ctx;
+ }
+
+ @Override
+ public boolean destroy(final long ctx) {
+ return EAGL.eaglDeleteContext(ctx, true /* releaseOnMainThread */);
+ }
+
+ @Override
+ public void associateDrawable(final boolean bound) {
+ }
+
+ @Override
+ public boolean makeCurrent(final long ctx) {
+ return EAGL.eaglMakeCurrentContext(ctx);
+ }
+
+ @Override
+ public boolean release(final long ctx) {
+ try {
+ if( hasRendererQuirk(GLRendererQuirks.GLFlushBeforeRelease) && null != IOSEAGLContext.this.getGLProcAddressTable() ) {
+ gl.glFlush();
+ }
+ } catch (final GLException gle) {
+ if(DEBUG) {
+ System.err.println("IOSEAGLContext.CGLImpl.release: INFO: glFlush() caught exception:");
+ gle.printStackTrace();
+ }
+ }
+ return EAGL.eaglMakeCurrentContext(0);
+ }
+ }
+
+ @Override
+ protected Integer setSwapIntervalImpl2(final int interval) {
+ // TODO
+ return null;
+ }
+}
diff --git a/src/jogl/classes/jogamp/opengl/ios/eagl/IOSEAGLDrawable.java b/src/jogl/classes/jogamp/opengl/ios/eagl/IOSEAGLDrawable.java
new file mode 100644
index 000000000..a851e60c6
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/ios/eagl/IOSEAGLDrawable.java
@@ -0,0 +1,90 @@
+/**
+ * Copyright 2019 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.ios.eagl;
+
+import com.jogamp.nativewindow.NativeSurface;
+import com.jogamp.opengl.GL;
+import com.jogamp.opengl.GLContext;
+import com.jogamp.opengl.GLDrawableFactory;
+import com.jogamp.opengl.GLException;
+
+import jogamp.opengl.GLDrawableImpl;
+
+public abstract class IOSEAGLDrawable extends GLDrawableImpl {
+ public enum GLBackendType {
+ /** Default OpenGL Backend */
+ CAEAGL_LAYER(0);
+
+ public final int id;
+
+ GLBackendType(final int id){
+ this.id = id;
+ }
+ }
+
+ private boolean haveSetOpenGLMode = false;
+ private GLBackendType openGLMode = GLBackendType.CAEAGL_LAYER;
+
+ public IOSEAGLDrawable(final GLDrawableFactory factory, final NativeSurface comp, final boolean realized) {
+ super(factory, comp, realized);
+ initOpenGLImpl(getOpenGLMode());
+ }
+
+ @Override
+ protected void setRealizedImpl() {
+ }
+
+ @Override
+ protected void associateContext(final GLContext ctx, final boolean bound) {
+ }
+
+ @Override
+ protected final void swapBuffersImpl(final boolean doubleBuffered) {
+ }
+
+ // Support for "mode switching" as described in MacOSXCGLDrawable
+ public void setOpenGLMode(final GLBackendType mode) {
+ if (mode == openGLMode) {
+ return;
+ }
+ if (haveSetOpenGLMode) {
+ throw new GLException("Can't switch between using NSOpenGLPixelBuffer and CGLPBufferObj more than once");
+ }
+ setRealized(false);
+ if (DEBUG) {
+ System.err.println("MacOSXCGLDrawable: Switching context mode " + openGLMode + " -> " + mode);
+ }
+ initOpenGLImpl(mode);
+ openGLMode = mode;
+ haveSetOpenGLMode = true;
+ }
+ public final GLBackendType getOpenGLMode() { return openGLMode; }
+
+ protected void initOpenGLImpl(final GLBackendType backend) { /* nop */ }
+
+}
diff --git a/src/jogl/classes/jogamp/opengl/ios/eagl/IOSEAGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/ios/eagl/IOSEAGLDrawableFactory.java
new file mode 100644
index 000000000..3c3f1edb8
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/ios/eagl/IOSEAGLDrawableFactory.java
@@ -0,0 +1,453 @@
+/**
+ * Copyright 2019 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.ios.eagl;
+
+import java.nio.Buffer;
+import java.nio.ShortBuffer;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+
+import com.jogamp.nativewindow.AbstractGraphicsDevice;
+import com.jogamp.nativewindow.AbstractGraphicsScreen;
+import com.jogamp.nativewindow.DefaultGraphicsScreen;
+import com.jogamp.nativewindow.NativeSurface;
+import com.jogamp.nativewindow.ProxySurface;
+import com.jogamp.nativewindow.UpstreamSurfaceHook;
+import com.jogamp.nativewindow.ios.IOSGraphicsDevice;
+import com.jogamp.opengl.GL;
+import com.jogamp.opengl.GLCapabilities;
+import com.jogamp.opengl.GLCapabilitiesChooser;
+import com.jogamp.opengl.GLCapabilitiesImmutable;
+import com.jogamp.opengl.GLContext;
+import com.jogamp.opengl.GLDrawable;
+import com.jogamp.opengl.GLException;
+import com.jogamp.opengl.GLProfile;
+
+import jogamp.nativewindow.WrappedSurface;
+import jogamp.nativewindow.ios.IOSDummyUpstreamSurfaceHook;
+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.nativewindow.GenericUpstreamSurfacelessHook;
+import com.jogamp.opengl.GLExtensions;
+import com.jogamp.opengl.GLRendererQuirks;
+
+public class IOSEAGLDrawableFactory extends GLDrawableFactoryImpl {
+ private static final boolean DEBUG_SHAREDCTX = DEBUG || GLContext.DEBUG;
+
+ private static GLDynamicLookupHelper iosEAGLDynamicLookupHelper = null;
+
+ public IOSEAGLDrawableFactory() {
+ super();
+
+ synchronized(IOSEAGLDrawableFactory.class) {
+ if(null==iosEAGLDynamicLookupHelper) {
+ GLDynamicLookupHelper tmp = null;
+ try {
+ tmp = new GLDynamicLookupHelper(new IOSEAGLDynamicLibraryBundleInfo());
+ } catch (final GLException gle) {
+ if(DEBUG) {
+ gle.printStackTrace();
+ }
+ }
+ if(null!=tmp && tmp.isLibComplete()) {
+ iosEAGLDynamicLookupHelper = tmp;
+ }
+ }
+ }
+
+ defaultDevice = new IOSGraphicsDevice(AbstractGraphicsDevice.DEFAULT_UNIT);
+
+ if(null!=iosEAGLDynamicLookupHelper) {
+ // Register our GraphicsConfigurationFactory implementations
+ // The act of constructing them causes them to be registered
+ IOSEAGLGraphicsConfigurationFactory.registerFactory();
+ sharedMap = new HashMap<String, SharedResource>();
+ }
+ }
+
+ @Override
+ protected final boolean isComplete() {
+ return null != iosEAGLDynamicLookupHelper;
+ }
+
+ @Override
+ protected final void shutdownImpl() {
+ if( DEBUG ) {
+ System.err.println("IOSEAGLDrawableFactory.shutdown");
+ }
+ if(null != sharedMap) {
+ sharedMap.clear();
+ sharedMap = null;
+ }
+ defaultDevice = null;
+ /**
+ * Pulling away the native library may cause havoc ..
+ *
+ macOSXCGLDynamicLookupHelper.destroy();
+ */
+ iosEAGLDynamicLookupHelper = null;
+ }
+
+ @Override
+ public final GLDynamicLookupHelper getGLDynamicLookupHelper(final int majorVersion, final int contextOptions) {
+ return iosEAGLDynamicLookupHelper;
+ }
+
+ private HashMap<String, SharedResource> sharedMap = new HashMap<String, SharedResource>();
+ private IOSGraphicsDevice defaultDevice;
+
+ static class SharedResource implements SharedResourceRunner.Resource {
+ // private IOSEAGLDrawable drawable;
+ // private IOSEAGLContext context;
+ private final GLRendererQuirks glRendererQuirks;
+ IOSGraphicsDevice device;
+ boolean valid;
+ boolean hasNPOTTextures;
+ boolean hasRECTTextures;
+ boolean hasAppleFloatPixels;
+
+ SharedResource(final IOSGraphicsDevice device, final boolean valid,
+ final boolean hasNPOTTextures, final boolean hasRECTTextures, final boolean hasAppletFloatPixels
+ /* IOSEAGLDrawable draw, IOSEAGLContext ctx */, final GLRendererQuirks glRendererQuirks) {
+ // drawable = draw;
+ // this.context = ctx;
+ this.glRendererQuirks = glRendererQuirks;
+ this.device = device;
+ this.valid = valid;
+ this.hasNPOTTextures = hasNPOTTextures;
+ this.hasRECTTextures = hasRECTTextures;
+ this.hasAppleFloatPixels = hasAppletFloatPixels;
+ }
+ @Override
+ public final boolean isAvailable() {
+ return valid;
+ }
+ @Override
+ public final IOSGraphicsDevice getDevice() { return device; }
+ // final IOSEAGLContext getContext() { return context; }
+ final boolean isNPOTTextureAvailable() { return hasNPOTTextures; }
+ final boolean isRECTTextureAvailable() { return hasRECTTextures; }
+ final boolean isAppleFloatPixelsAvailable() { return hasAppleFloatPixels; }
+ @Override
+ public final AbstractGraphicsScreen getScreen() {
+ return null;
+ }
+ @Override
+ public final GLDrawableImpl getDrawable() {
+ return null;
+ }
+ @Override
+ public GLContextImpl getContext() {
+ return null;
+ }
+ @Override
+ public GLRendererQuirks getRendererQuirks(final GLProfile glp) {
+ return glRendererQuirks;
+ }
+ }
+
+ @Override
+ public final AbstractGraphicsDevice getDefaultDevice() {
+ return defaultDevice;
+ }
+
+ @Override
+ public final boolean getIsDeviceCompatible(final AbstractGraphicsDevice device) {
+ if(null!=iosEAGLDynamicLookupHelper && device instanceof IOSGraphicsDevice) {
+ return true;
+ }
+ return false;
+ }
+
+ private final HashSet<String> devicesTried = new HashSet<String>();
+
+ private boolean getDeviceTried(final String connection) {
+ synchronized (devicesTried) {
+ return devicesTried.contains(connection);
+ }
+ }
+ private void addDeviceTried(final String connection) {
+ synchronized (devicesTried) {
+ devicesTried.add(connection);
+ }
+ }
+ private void removeDeviceTried(final String connection) {
+ synchronized (devicesTried) {
+ devicesTried.remove(connection);
+ }
+ }
+
+ @Override
+ protected final SharedResource getOrCreateSharedResourceImpl(final AbstractGraphicsDevice adevice) {
+ final String connection = adevice.getConnection();
+ SharedResource sr;
+ synchronized(sharedMap) {
+ sr = sharedMap.get(connection);
+ }
+ if(null==sr && !getDeviceTried(connection)) {
+ addDeviceTried(connection);
+ final IOSGraphicsDevice device = new IOSGraphicsDevice(adevice.getUnitID());
+ GLDrawable drawable = null;
+ GLDrawable zeroDrawable = null;
+ GLContextImpl context = null;
+ boolean contextIsCurrent = false;
+ device.lock();
+ try {
+ final GLProfile glp = GLProfile.get(device, GLProfile.GL_PROFILE_LIST_MAX_MOBILE, false);
+ if (null == glp) {
+ throw new GLException("Couldn't get default GLProfile for device: "+device);
+ }
+ final GLCapabilitiesImmutable caps = new GLCapabilities(glp);
+ // drawable = createSurfacelessFBODrawable(device, caps, 64, 64);
+ drawable = createSurfacelessDrawable(device, caps, 64, 64);
+
+ drawable.setRealized(true);
+
+ context = (IOSEAGLContext) drawable.createContext(null);
+ if (null == context) {
+ throw new GLException("Couldn't create shared context for drawable: "+drawable);
+ }
+ contextIsCurrent = GLContext.CONTEXT_NOT_CURRENT != context.makeCurrent();
+
+ final boolean allowsSurfacelessCtx;
+ final boolean hasNPOTTextures;
+ final boolean hasRECTTextures;
+ final boolean hasAppleFloatPixels;
+ final GLRendererQuirks glRendererQuirks;
+ if( contextIsCurrent ) {
+ // We allow probing surfaceless for even the compatible 2.1 context,
+ // which we probably have right here - since OSX may support this.
+ // Otherwise, we cannot map the quirk to the device.
+ if( probeSurfacelessCtx(context, false /* restoreDrawable */) ) {
+ allowsSurfacelessCtx = true;
+ zeroDrawable = context.getGLDrawable();
+ } else {
+ allowsSurfacelessCtx = false;
+ }
+ final GL gl = context.getGL();
+ hasNPOTTextures = gl.isNPOTTextureAvailable();
+ hasRECTTextures = gl.isExtensionAvailable(GLExtensions.EXT_texture_rectangle);
+ hasAppleFloatPixels = gl.isExtensionAvailable(GLExtensions.APPLE_float_pixels);
+ glRendererQuirks = context.getRendererQuirks();
+ } else {
+ allowsSurfacelessCtx = false;
+ hasNPOTTextures = false;
+ hasRECTTextures = false;
+ hasAppleFloatPixels = false;
+ glRendererQuirks = null;
+ }
+ sr = new SharedResource(device, contextIsCurrent, hasNPOTTextures, hasRECTTextures, hasAppleFloatPixels, glRendererQuirks);
+ if ( DEBUG_SHAREDCTX ) {
+ System.err.println("SharedDevice: " + device);
+ System.err.println("SharedContext: " + context + ", madeCurrent " + contextIsCurrent);
+ System.err.println(" NPOT "+hasNPOTTextures+", RECT "+hasRECTTextures+", FloatPixels "+hasAppleFloatPixels);
+ System.err.println(" allowsSurfacelessCtx "+allowsSurfacelessCtx);
+ System.err.println(" glRendererQuirks "+glRendererQuirks);
+ }
+ synchronized(sharedMap) {
+ sharedMap.put(connection, sr);
+ }
+ } catch (final Throwable t) {
+ throw new GLException("IOSEAGLDrawableFactory - Could not initialize shared resources for "+adevice, t);
+ } finally {
+ if( null != context ) {
+ try {
+ context.destroy();
+ } catch (final GLException gle) {
+ if ( DEBUG_SHAREDCTX ) {
+ System.err.println("IOSEAGLDrawableFactory.createShared: INFO: destroy caught exception:");
+ gle.printStackTrace();
+ }
+ }
+ }
+ if( null != zeroDrawable ) {
+ zeroDrawable.setRealized(false);
+ }
+ if( null != drawable ) {
+ drawable.setRealized(false);
+ }
+ device.unlock();
+ removeDeviceTried(connection);
+ }
+ }
+ return sr;
+ }
+
+ @Override
+ protected final Thread getSharedResourceThread() {
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * This factory never supports native desktop OpenGL profiles.
+ * </p>
+ */
+ @Override
+ public final boolean hasOpenGLDesktopSupport() { return false; }
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * This factory always supports native GLES profiles.
+ * </p>
+ */
+ @Override
+ public final boolean hasOpenGLESSupport() { return true; }
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * Always returns false.
+ * </p>
+ */
+ @Override
+ public final boolean hasMajorMinorCreateContextARB() { return false; }
+
+ @Override
+ protected List<GLCapabilitiesImmutable> getAvailableCapabilitiesImpl(final AbstractGraphicsDevice device) {
+ return IOSEAGLGraphicsConfiguration.getAvailableCapabilities(this, device);
+ }
+
+ @Override
+ protected GLDrawableImpl createOnscreenDrawableImpl(final NativeSurface target) {
+ if (target == null) {
+ throw new IllegalArgumentException("Null target");
+ }
+ return new IOSOnscreenEAGLDrawable(this, target);
+ }
+
+ @Override
+ protected GLDrawableImpl createOffscreenDrawableImpl(final NativeSurface target) {
+ throw new GLException("Only FBO is supported for offscreen");
+ }
+
+ @Override
+ public boolean canCreateGLPbuffer(final AbstractGraphicsDevice device, final GLProfile glp) {
+ return false;
+ }
+
+ @Override
+ protected ProxySurface createMutableSurfaceImpl(final AbstractGraphicsDevice deviceReq, final boolean createNewDevice,
+ final GLCapabilitiesImmutable capsChosen, final GLCapabilitiesImmutable capsRequested,
+ final GLCapabilitiesChooser chooser, final UpstreamSurfaceHook upstreamHook) {
+ final IOSGraphicsDevice device;
+ if( createNewDevice || !(deviceReq instanceof IOSGraphicsDevice) ) {
+ device = new IOSGraphicsDevice(deviceReq.getUnitID());
+ } else {
+ device = (IOSGraphicsDevice)deviceReq;
+ }
+ final AbstractGraphicsScreen screen = new DefaultGraphicsScreen(device, 0);
+ final IOSEAGLGraphicsConfiguration config = IOSEAGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsChosen, capsRequested, chooser, screen, true);
+ if(null == config) {
+ throw new GLException("Choosing GraphicsConfiguration failed w/ "+capsChosen+" on "+screen);
+ }
+ return new WrappedSurface(config, 0, upstreamHook, createNewDevice);
+ }
+
+ @Override
+ public final ProxySurface createDummySurfaceImpl(final AbstractGraphicsDevice deviceReq, final boolean createNewDevice,
+ GLCapabilitiesImmutable chosenCaps, final GLCapabilitiesImmutable requestedCaps, final GLCapabilitiesChooser chooser, final int width, final int height) {
+ chosenCaps = GLGraphicsConfigurationUtil.fixOnscreenGLCapabilities(chosenCaps);
+ return createMutableSurfaceImpl(deviceReq, createNewDevice, chosenCaps, requestedCaps, chooser,
+ new IOSDummyUpstreamSurfaceHook(width, height));
+ }
+
+ @Override
+ public final ProxySurface createSurfacelessImpl(final AbstractGraphicsDevice deviceReq, final boolean createNewDevice,
+ GLCapabilitiesImmutable chosenCaps, final GLCapabilitiesImmutable requestedCaps, final GLCapabilitiesChooser chooser, final int width, final int height) {
+ chosenCaps = GLGraphicsConfigurationUtil.fixOnscreenGLCapabilities(chosenCaps);
+ return createMutableSurfaceImpl(deviceReq, createNewDevice, chosenCaps, requestedCaps, chooser, new GenericUpstreamSurfacelessHook(width, height));
+ }
+
+ @Override
+ protected ProxySurface createProxySurfaceImpl(final AbstractGraphicsDevice deviceReq, final int screenIdx, final long windowHandle, final GLCapabilitiesImmutable capsRequested, final GLCapabilitiesChooser chooser, final UpstreamSurfaceHook upstream) {
+ final IOSGraphicsDevice device = new IOSGraphicsDevice(deviceReq.getUnitID());
+ final AbstractGraphicsScreen screen = new DefaultGraphicsScreen(device, screenIdx);
+ final IOSEAGLGraphicsConfiguration config = IOSEAGLGraphicsConfigurationFactory.chooseGraphicsConfigurationStatic(capsRequested, capsRequested, chooser, screen, true);
+ return new WrappedSurface(config, windowHandle, upstream, true);
+ }
+
+ @Override
+ protected GLContext createExternalGLContextImpl() {
+ throw new GLException("Not implemented");
+ }
+
+ @Override
+ public boolean canCreateExternalGLDrawable(final AbstractGraphicsDevice device) {
+ return false;
+ }
+
+ @Override
+ protected GLDrawable createExternalGLDrawableImpl() {
+ throw new GLException("Not implemented");
+ }
+
+ //------------------------------------------------------
+ // Gamma-related functionality
+ //
+
+ private static final int GAMMA_RAMP_LENGTH = 256;
+
+ /** Returns the length of the computed gamma ramp for this OS and
+ hardware. Returns 0 if gamma changes are not supported. */
+ @Override
+ protected int getGammaRampLength(final NativeSurface surface) {
+ return GAMMA_RAMP_LENGTH;
+ }
+
+ @Override
+ protected boolean setGammaRamp(final NativeSurface surface, final float[] ramp) {
+ // final FloatBuffer rampNIO = Buffers.newDirectFloatBuffer(ramp);
+ return false; // TODO CGL.setGammaRamp(ramp.length, rampNIO, rampNIO, rampNIO);
+ }
+
+ @Override
+ protected Buffer getGammaRamp(final NativeSurface surface) {
+ return ShortBuffer.allocate(0); // return a dummy gamma ramp default for reset
+ }
+
+ @Override
+ protected void resetGammaRamp(final NativeSurface surface, final Buffer originalGammaRamp) {
+ // TODO CGL.resetGammaRamp();
+ }
+
+ @Override
+ protected final void resetGammaRamp(final DeviceScreenID deviceScreenID, final Buffer originalGammaRamp) {
+ // TODO CGL.resetGammaRamp();
+ }
+
+}
diff --git a/src/jogl/classes/jogamp/opengl/ios/eagl/IOSEAGLDynamicLibraryBundleInfo.java b/src/jogl/classes/jogamp/opengl/ios/eagl/IOSEAGLDynamicLibraryBundleInfo.java
new file mode 100644
index 000000000..c418cd682
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/ios/eagl/IOSEAGLDynamicLibraryBundleInfo.java
@@ -0,0 +1,83 @@
+/**
+ * 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.ios.eagl;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import jogamp.opengl.GLDynamicLibraryBundleInfo;
+
+public final class IOSEAGLDynamicLibraryBundleInfo extends GLDynamicLibraryBundleInfo {
+ private static final List<String> glueLibNames;
+ static {
+ glueLibNames = new ArrayList<String>();
+ glueLibNames.add("jogl_mobile");
+ }
+ protected IOSEAGLDynamicLibraryBundleInfo() {
+ super();
+ }
+
+ @Override
+ public boolean shallLookupGlobal() { return true; }
+
+ @Override
+ public final List<List<String>> getToolLibNames() {
+ final List<List<String>> libsList = new ArrayList<List<String>>();
+ final List<String> libsGL = new ArrayList<String>();
+ libsGL.add("OpenGLES"); // actually used '/Library/Frameworks/OpenGLES.framework/OpenGLES'
+ libsList.add(libsGL);
+ return libsList;
+ }
+
+ @Override
+ public final List<String> getToolGetProcAddressFuncNameList() {
+ return null;
+ /** OSX manual says: NSImage use is discouraged
+ List res = new ArrayList();
+ res.add("GetProcAddress"); // dummy
+ return res; */
+ }
+
+ @Override
+ public final long toolGetProcAddress(final long toolGetProcAddressHandle, final String funcName) {
+ // return EAGL.getProcAddress(funcName);
+ return 0;
+ }
+
+ @Override
+ public final List<String> getGlueLibNames() {
+ return glueLibNames;
+ }
+
+ @Override
+ public boolean useToolGetProcAdressFirst(final String funcName) {
+ return true;
+ }
+}
+
diff --git a/src/jogl/classes/jogamp/opengl/ios/eagl/IOSEAGLGraphicsConfiguration.java b/src/jogl/classes/jogamp/opengl/ios/eagl/IOSEAGLGraphicsConfiguration.java
new file mode 100644
index 000000000..18e597065
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/ios/eagl/IOSEAGLGraphicsConfiguration.java
@@ -0,0 +1,62 @@
+/**
+ * Copyright 2019 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.ios.eagl;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.jogamp.nativewindow.AbstractGraphicsDevice;
+import com.jogamp.nativewindow.AbstractGraphicsScreen;
+import com.jogamp.opengl.GLCapabilitiesImmutable;
+import com.jogamp.opengl.GLException;
+
+import com.jogamp.nativewindow.MutableGraphicsConfiguration;
+
+public class IOSEAGLGraphicsConfiguration extends MutableGraphicsConfiguration implements Cloneable {
+
+ IOSEAGLGraphicsConfiguration(final AbstractGraphicsScreen screen,
+ final GLCapabilitiesImmutable capsChosen, final GLCapabilitiesImmutable capsRequested) {
+ super(screen, capsChosen, capsRequested);
+ }
+
+ @Override
+ public Object clone() {
+ return super.clone();
+ }
+
+ protected static List<GLCapabilitiesImmutable> getAvailableCapabilities(final IOSEAGLDrawableFactory factory, final AbstractGraphicsDevice device) {
+ final IOSEAGLDrawableFactory.SharedResource sharedResource = factory.getOrCreateSharedResourceImpl(device);
+ if(null == sharedResource) {
+ throw new GLException("Shared resource for device n/a: "+device);
+ }
+ // MacOSXGraphicsDevice osxDevice = sharedResource.getDevice();
+ return new ArrayList<GLCapabilitiesImmutable>(0);
+ }
+}
+
diff --git a/src/jogl/classes/jogamp/opengl/ios/eagl/IOSEAGLGraphicsConfigurationFactory.java b/src/jogl/classes/jogamp/opengl/ios/eagl/IOSEAGLGraphicsConfigurationFactory.java
new file mode 100644
index 000000000..3a4f1a354
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/ios/eagl/IOSEAGLGraphicsConfigurationFactory.java
@@ -0,0 +1,87 @@
+/**
+ * Copyright 2019 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.ios.eagl;
+
+import jogamp.opengl.GLGraphicsConfigurationFactory;
+import jogamp.opengl.GLGraphicsConfigurationUtil;
+
+import com.jogamp.nativewindow.AbstractGraphicsConfiguration;
+import com.jogamp.nativewindow.AbstractGraphicsDevice;
+import com.jogamp.nativewindow.AbstractGraphicsScreen;
+import com.jogamp.nativewindow.CapabilitiesChooser;
+import com.jogamp.nativewindow.CapabilitiesImmutable;
+import com.jogamp.nativewindow.GraphicsConfigurationFactory;
+import com.jogamp.opengl.GLCapabilitiesChooser;
+import com.jogamp.opengl.GLCapabilitiesImmutable;
+import com.jogamp.opengl.GLDrawableFactory;
+
+
+public class IOSEAGLGraphicsConfigurationFactory extends GLGraphicsConfigurationFactory {
+ static void registerFactory() {
+ GraphicsConfigurationFactory.registerFactory(com.jogamp.nativewindow.ios.IOSGraphicsDevice.class, GLCapabilitiesImmutable.class, new IOSEAGLGraphicsConfigurationFactory());
+ }
+ private IOSEAGLGraphicsConfigurationFactory() {
+ }
+
+ @Override
+ protected AbstractGraphicsConfiguration chooseGraphicsConfigurationImpl(
+ final CapabilitiesImmutable capsChosen, final CapabilitiesImmutable capsRequested,
+ final CapabilitiesChooser chooser, final AbstractGraphicsScreen absScreen, final int nativeVisualID) {
+
+ if (absScreen == null) {
+ throw new IllegalArgumentException("AbstractGraphicsScreen is null");
+ }
+
+ if (! (capsChosen instanceof GLCapabilitiesImmutable) ) {
+ throw new IllegalArgumentException("This NativeWindowFactory accepts only GLCapabilities objects - chosen");
+ }
+
+ if (! (capsRequested instanceof GLCapabilitiesImmutable) ) {
+ throw new IllegalArgumentException("This NativeWindowFactory accepts only GLCapabilities objects - requested");
+ }
+
+ if (chooser != null && !(chooser instanceof GLCapabilitiesChooser)) {
+ throw new IllegalArgumentException("This NativeWindowFactory accepts only GLCapabilitiesChooser objects");
+ }
+
+ return chooseGraphicsConfigurationStatic((GLCapabilitiesImmutable)capsChosen, (GLCapabilitiesImmutable)capsRequested, (GLCapabilitiesChooser)chooser, absScreen, false);
+ }
+
+ static IOSEAGLGraphicsConfiguration chooseGraphicsConfigurationStatic(GLCapabilitiesImmutable capsChosen,
+ final GLCapabilitiesImmutable capsRequested,
+ final GLCapabilitiesChooser chooser,
+ final AbstractGraphicsScreen absScreen, final boolean usePBuffer) {
+ if (absScreen == null) {
+ throw new IllegalArgumentException("AbstractGraphicsScreen is null");
+ }
+ final AbstractGraphicsDevice device = absScreen.getDevice();
+ capsChosen = GLGraphicsConfigurationUtil.fixGLCapabilities( capsChosen, GLDrawableFactory.getDesktopFactory(), device);
+
+ return new IOSEAGLGraphicsConfiguration(absScreen, capsChosen, capsRequested);
+ }
+}
diff --git a/src/jogl/classes/jogamp/opengl/ios/eagl/IOSOnscreenEAGLDrawable.java b/src/jogl/classes/jogamp/opengl/ios/eagl/IOSOnscreenEAGLDrawable.java
new file mode 100644
index 000000000..04b80a858
--- /dev/null
+++ b/src/jogl/classes/jogamp/opengl/ios/eagl/IOSOnscreenEAGLDrawable.java
@@ -0,0 +1,45 @@
+/**
+ * Copyright 2019 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.ios.eagl;
+
+import com.jogamp.nativewindow.NativeSurface;
+import com.jogamp.opengl.GLContext;
+import com.jogamp.opengl.GLDrawableFactory;
+
+public class IOSOnscreenEAGLDrawable extends IOSEAGLDrawable {
+
+ protected IOSOnscreenEAGLDrawable(final GLDrawableFactory factory, final NativeSurface component) {
+ super(factory, component, false);
+ }
+
+ @Override
+ public GLContext createContext(final GLContext shareWith) {
+ return new IOSEAGLContext(this, shareWith);
+ }
+
+}
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDynamicLibraryBundleInfo.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDynamicLibraryBundleInfo.java
index 5cf4f36a1..c5fc4e74a 100644
--- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDynamicLibraryBundleInfo.java
+++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLDynamicLibraryBundleInfo.java
@@ -42,6 +42,7 @@ public final class MacOSXCGLDynamicLibraryBundleInfo extends DesktopGLDynamicLib
public final List<List<String>> getToolLibNames() {
final List<List<String>> libsList = new ArrayList<List<String>>();
final List<String> libsGL = new ArrayList<String>();
+ // libsGL.add("OpenGL"); // Actual canonical lib. TODO re-validate?
libsGL.add("/System/Library/Frameworks/OpenGL.framework/Libraries/libGL.dylib");
libsGL.add("GL");
libsList.add(libsGL);
diff --git a/src/jogl/native/JVM_JNI8.c b/src/jogl/native/JVM_JNI8.c
new file mode 100644
index 000000000..1131088cf
--- /dev/null
+++ b/src/jogl/native/JVM_JNI8.c
@@ -0,0 +1,43 @@
+/**
+ * Copyright 2019 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.
+ */
+
+#include <stdio.h> //required by android to identify NULL
+#include <jni.h>
+
+#if defined (JNI_VERSION_1_8)
+
+JNIEXPORT jint JNICALL JNI_OnLoad_jogl_mobile(JavaVM *vm, void *reserved) { return JNI_VERSION_1_8; }
+JNIEXPORT jint JNICALL JNI_OnLoad_jogl_desktop(JavaVM *vm, void *reserved) { return JNI_VERSION_1_8; }
+JNIEXPORT jint JNICALL JNI_OnLoad_jogl_cg(JavaVM *vm, void *reserved) { return JNI_VERSION_1_8; }
+
+JNIEXPORT void JNICALL JNI_OnUnload_jogl_mobile(JavaVM *vm, void *reserved) { }
+JNIEXPORT void JNICALL JNI_OnUnload_jogl_desktop(JavaVM *vm, void *reserved) { }
+JNIEXPORT void JNICALL JNI_OnUnload_jogl_cg(JavaVM *vm, void *reserved) { }
+
+#endif /* defined (JNI_VERSION_1_8) */
+
diff --git a/src/jogl/native/ios/IOSWindowSystemInterface.h b/src/jogl/native/ios/IOSWindowSystemInterface.h
new file mode 100644
index 000000000..c50a663a0
--- /dev/null
+++ b/src/jogl/native/ios/IOSWindowSystemInterface.h
@@ -0,0 +1,42 @@
+/**
+ * Copyright 2019 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.
+ */
+#import <UIKit/UIKit.h>
+#import <OpenGLES/EAGL.h>
+#import <jni.h>
+
+// #define VERBOSE_ON 1
+
+#ifdef VERBOSE_ON
+ #define DBG_PRINT(...) NSLog(@ __VA_ARGS__)
+ // #define DBG_PRINT(...) fprintf(stderr, __VA_ARGS__); fflush(stderr)
+#else
+ #define DBG_PRINT(...)
+#endif
+
+#import "ios-window-system.h"
+
diff --git a/src/jogl/native/ios/IOSWindowSystemInterface.m b/src/jogl/native/ios/IOSWindowSystemInterface.m
new file mode 100644
index 000000000..95c10c269
--- /dev/null
+++ b/src/jogl/native/ios/IOSWindowSystemInterface.m
@@ -0,0 +1,119 @@
+/**
+ * Copyright 2019 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.
+ */
+#include <AvailabilityMacros.h>
+
+#import "IOSWindowSystemInterface.h"
+
+EAGLContext * eaglCreateContext(EAGLRenderingAPI api) {
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+
+ DBG_PRINT("createEAGLContext.0: api %d\n", api);
+
+ EAGLContext* ctx = [[EAGLContext alloc] initWithAPI:api];
+
+ DBG_PRINT("createEAGLContext.X: ctx: %p\n", ctx);
+ [pool release];
+ return ctx;
+}
+
+EAGLContext * eaglCreateContextShared(EAGLRenderingAPI api, EAGLSharegroup* sharegroup) {
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+
+ DBG_PRINT("createEAGLContext.0: api %d, sharegroup %p\n", api, sharegroup);
+
+ EAGLContext* ctx = [[EAGLContext alloc] initWithAPI:api sharegroup:sharegroup];
+
+ DBG_PRINT("createEAGLContext.X: ctx: %p\n", ctx);
+ [pool release];
+ return ctx;
+}
+
+Bool eaglDeleteContext(EAGLContext *ctx, Bool releaseOnMainThread) {
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+
+ DBG_PRINT("deleteEAGLContext.0: ctx %p, releaseOnMainThread %d\n", ctx, releaseOnMainThread);
+ if(releaseOnMainThread && NO == [NSThread isMainThread]) {
+ [ctx performSelectorOnMainThread:@selector(release) withObject:nil waitUntilDone:NO];
+ } else {
+ // ??? On OSX would hangs for ~10s for 1 of a shared context set or offscreen context, set releaseOnMainThread=true
+ [ctx release];
+ }
+ [pool release];
+ return true;
+}
+
+EAGLRenderingAPI eaglGetRenderingAPI(EAGLContext* ctx) {
+ return [ctx API];
+}
+EAGLSharegroup * eaglGetSharegroup(EAGLContext *ctx) {
+ return [ctx sharegroup];
+}
+Bool eaglIsContextMultiThreaded(EAGLContext* ctx) {
+ return [ctx isMultiThreaded];
+}
+void eaglSetContextMultiThreaded(EAGLContext* ctx, Bool v) {
+ [ctx setMultiThreaded: v];
+}
+
+EAGLContext* eaglGetCurrentContext(void) {
+ return [EAGLContext currentContext];
+}
+Bool eaglMakeCurrentContext(EAGLContext* ctx) {
+ return [EAGLContext setCurrentContext: ctx];
+}
+Bool eaglBindDrawableStorageToRenderbuffer(EAGLContext* ctx, int renderbufferTarget, CAEAGLLayer /* EAGLDrawable */ * drawable) {
+ return [ctx renderbufferStorage: renderbufferTarget fromDrawable: drawable];
+}
+Bool eaglPresentRenderbuffer(EAGLContext* ctx, int renderbufferTarget) {
+ return [ctx presentRenderbuffer: renderbufferTarget];
+}
+
+#include <dlfcn.h>
+Bool imagesInitialized = false;
+static char libGLESStr[] = "/System/Library/Frameworks/OpenGLES.framework/Libraries/libGLES.dylib";
+static void * *libGLESImage;
+void* getProcAddress(const char *procname) {
+ if (imagesInitialized == false) {
+ imagesInitialized = true;
+ libGLESImage = dlopen(libGLESStr, RTLD_LAZY | RTLD_GLOBAL);
+ }
+ if(NULL == libGLESImage) {
+ return NULL;
+ }
+
+ char underscoreName[512] = "_";
+ void * res = NULL;
+ strcat(underscoreName, procname);
+
+ res = dlsym(libGLESImage, underscoreName);
+ if( NULL == res ) {
+ // try smth else ..
+ }
+ return res;
+}
+
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/NativeWindowFactory.java b/src/nativewindow/classes/com/jogamp/nativewindow/NativeWindowFactory.java
index 323bc8c86..8e00d318c 100644
--- a/src/nativewindow/classes/com/jogamp/nativewindow/NativeWindowFactory.java
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/NativeWindowFactory.java
@@ -52,6 +52,7 @@ import jogamp.nativewindow.NativeWindowFactoryImpl;
import jogamp.nativewindow.ToolkitProperties;
import jogamp.nativewindow.ResourceToolkitLock;
import jogamp.nativewindow.WrappedWindow;
+import jogamp.nativewindow.ios.IOSUtil;
import jogamp.nativewindow.macosx.OSXUtil;
import jogamp.nativewindow.windows.GDIUtil;
import jogamp.nativewindow.x11.X11Lib;
@@ -65,6 +66,7 @@ import com.jogamp.nativewindow.UpstreamWindowHookMutableSizePos;
import com.jogamp.nativewindow.awt.AWTGraphicsDevice;
import com.jogamp.nativewindow.awt.AWTGraphicsScreen;
import com.jogamp.nativewindow.egl.EGLGraphicsDevice;
+import com.jogamp.nativewindow.ios.IOSGraphicsDevice;
import com.jogamp.nativewindow.macosx.MacOSXGraphicsDevice;
import com.jogamp.nativewindow.windows.WindowsGraphicsDevice;
import com.jogamp.nativewindow.x11.X11GraphicsDevice;
@@ -100,6 +102,9 @@ public abstract class NativeWindowFactory {
/** Mac OS X type, as retrieved with {@link #getNativeWindowType(boolean)}. String is canonical via {@link String#intern()}. */
public static final String TYPE_MACOSX = ".macosx";
+ /** iOS type, as retrieved with {@link #getNativeWindowType(boolean)}. String is canonical via {@link String#intern()}. */
+ public static final String TYPE_IOS = ".iOS";
+
/** Generic AWT type, as retrieved with {@link #getNativeWindowType(boolean)}. String is canonical via {@link String#intern()}. */
public static final String TYPE_AWT = ".awt";
@@ -120,6 +125,8 @@ public abstract class NativeWindowFactory {
private static final String X11UtilClassName = "jogamp.nativewindow.x11.X11Util";
/** {@link jogamp.nativewindow.macosx.OSXUtil} implements {@link ToolkitProperties}. */
private static final String OSXUtilClassName = "jogamp.nativewindow.macosx.OSXUtil";
+ /** {@link jogamp.nativewindow.ios.IOSUtil} implements {@link ToolkitProperties}. */
+ private static final String IOSUtilClassName = "jogamp.nativewindow.ios.IOSUtil";
/** {@link jogamp.nativewindow.windows.GDIUtil} implements {@link ToolkitProperties}. */
private static final String GDIClassName = "jogamp.nativewindow.windows.GDIUtil";
@@ -143,6 +150,8 @@ public abstract class NativeWindowFactory {
return TYPE_ANDROID;
case MACOS:
return TYPE_MACOSX;
+ case IOS:
+ return TYPE_IOS;
case WINDOWS:
return TYPE_WINDOWS;
case OPENKODE:
@@ -204,6 +213,8 @@ public abstract class NativeWindowFactory {
clazzName = GDIClassName;
} else if( TYPE_MACOSX == nativeWindowingTypePure ) {
clazzName = OSXUtilClassName;
+ } else if( TYPE_IOS == nativeWindowingTypePure ) {
+ clazzName = IOSUtilClassName;
} else {
clazzName = null;
}
@@ -294,6 +305,8 @@ public abstract class NativeWindowFactory {
clazzName = GDIClassName;
} else if( TYPE_MACOSX == nativeWindowingTypePure ) {
clazzName = OSXUtilClassName;
+ } else if( TYPE_IOS == nativeWindowingTypePure ) {
+ clazzName = IOSUtilClassName;
} else {
clazzName = null;
}
@@ -677,6 +690,8 @@ public abstract class NativeWindowFactory {
return new WindowsGraphicsDevice(AbstractGraphicsDevice.DEFAULT_UNIT);
} else if( NativeWindowFactory.TYPE_MACOSX == nwt ) {
return new MacOSXGraphicsDevice(AbstractGraphicsDevice.DEFAULT_UNIT);
+ } else if( NativeWindowFactory.TYPE_IOS == nwt ) {
+ return new IOSGraphicsDevice(AbstractGraphicsDevice.DEFAULT_UNIT);
} else if( NativeWindowFactory.TYPE_EGL == nwt ) {
final EGLGraphicsDevice device;
if( own ) {
@@ -742,6 +757,8 @@ public abstract class NativeWindowFactory {
return GDIUtil.GetRelativeLocation(nw.getWindowHandle(), 0, 0, 0);
} else if( NativeWindowFactory.TYPE_MACOSX == nwt ) {
return OSXUtil.GetLocationOnScreen(nw.getWindowHandle(), 0, 0);
+ } else if( NativeWindowFactory.TYPE_IOS == nwt ) {
+ return IOSUtil.GetLocationOnScreen(nw.getWindowHandle(), 0, 0);
/**
* FIXME: Needs service provider interface (SPI) for TK dependent implementation
} else if( NativeWindowFactory.TYPE_BCM_VC_IV == nwt ) {
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/ios/IOSGraphicsDevice.java b/src/nativewindow/classes/com/jogamp/nativewindow/ios/IOSGraphicsDevice.java
new file mode 100644
index 000000000..0a4354c9d
--- /dev/null
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/ios/IOSGraphicsDevice.java
@@ -0,0 +1,46 @@
+/**
+ * Copyright 2019 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.ios;
+
+import com.jogamp.nativewindow.*;
+
+/** Encapsulates a graphics device on IOS platforms.
+ */
+public class IOSGraphicsDevice extends DefaultGraphicsDevice implements Cloneable {
+ /** Constructs a new IOSGraphicsDevice */
+ public IOSGraphicsDevice(final int unitID) {
+ super(NativeWindowFactory.TYPE_IOS, AbstractGraphicsDevice.DEFAULT_CONNECTION, unitID);
+ }
+
+ @Override
+ public Object clone() {
+ return super.clone();
+ }
+}
+
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/javafx/JFXAccessor.java b/src/nativewindow/classes/com/jogamp/nativewindow/javafx/JFXAccessor.java
index bffabdd5a..9d38b1f4b 100644
--- a/src/nativewindow/classes/com/jogamp/nativewindow/javafx/JFXAccessor.java
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/javafx/JFXAccessor.java
@@ -62,6 +62,7 @@ public class JFXAccessor {
private static final String nwt;
private static final boolean isOSX;
+ private static final boolean isIOS;
private static final boolean isWindows;
private static final boolean isX11;
@@ -130,6 +131,7 @@ public class JFXAccessor {
nwt = NativeWindowFactory.getNativeWindowType(false);
isOSX = NativeWindowFactory.TYPE_MACOSX == nwt;
+ isIOS = NativeWindowFactory.TYPE_IOS == nwt;
isWindows = NativeWindowFactory.TYPE_WINDOWS == nwt;
isX11 = NativeWindowFactory.TYPE_X11 == nwt;
diff --git a/src/nativewindow/classes/jogamp/nativewindow/ios/IOSDummyUpstreamSurfaceHook.java b/src/nativewindow/classes/jogamp/nativewindow/ios/IOSDummyUpstreamSurfaceHook.java
new file mode 100644
index 000000000..a61287f8b
--- /dev/null
+++ b/src/nativewindow/classes/jogamp/nativewindow/ios/IOSDummyUpstreamSurfaceHook.java
@@ -0,0 +1,83 @@
+/**
+ * Copyright 2019 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.ios;
+
+import com.jogamp.nativewindow.NativeSurface;
+import com.jogamp.nativewindow.NativeWindowException;
+import com.jogamp.nativewindow.ProxySurface;
+import com.jogamp.nativewindow.UpstreamSurfaceHook;
+
+import com.jogamp.nativewindow.UpstreamSurfaceHookMutableSize;
+
+public class IOSDummyUpstreamSurfaceHook extends UpstreamSurfaceHookMutableSize {
+ long uiWindow;
+
+ /**
+ * @param width the initial width as returned by {@link NativeSurface#getSurfaceWidth()} via {@link UpstreamSurfaceHook#getSurfaceWidth(ProxySurface)},
+ * not the actual dummy surface width.
+ * The latter is platform specific and small
+ * @param height the initial height as returned by {@link NativeSurface#getSurfaceHeight()} via {@link UpstreamSurfaceHook#getSurfaceHeight(ProxySurface)},
+ * not the actual dummy surface height,
+ * The latter is platform specific and small
+ */
+ public IOSDummyUpstreamSurfaceHook(final int width, final int height) {
+ super(width, height);
+ uiWindow = 0;
+ }
+
+ @Override
+ public final void create(final ProxySurface s) {
+ if(0 == uiWindow && 0 == s.getSurfaceHandle()) {
+ uiWindow = IOSUtil.CreateUIWindow(0, 0, 64, 64);
+ if(0 == uiWindow) {
+ throw new NativeWindowException("Error UI window 0");
+ }
+ final long uiView = IOSUtil.GetUIView(uiWindow, true);
+ if(0 == uiView) {
+ throw new NativeWindowException("Error UI view 0");
+ }
+ s.setSurfaceHandle(uiView);
+ s.addUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE );
+ }
+ s.addUpstreamOptionBits(ProxySurface.OPT_UPSTREAM_WINDOW_INVISIBLE);
+ }
+
+ @Override
+ public final void destroy(final ProxySurface s) {
+ if( s.containsUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE ) ) {
+ if( 0 == uiWindow || 0 == s.getSurfaceHandle() ) {
+ throw new InternalError("Owns upstream surface, but no IOS view/window: "+s+", uiWindow 0x"+Long.toHexString(uiWindow));
+ }
+ IOSUtil.DestroyUIWindow(uiWindow);
+ uiWindow = 0;
+ s.setSurfaceHandle(0);
+ s.clearUpstreamOptionBits( ProxySurface.OPT_PROXY_OWNS_UPSTREAM_SURFACE );
+ }
+ }
+
+}
diff --git a/src/nativewindow/classes/jogamp/nativewindow/ios/IOSUtil.java b/src/nativewindow/classes/jogamp/nativewindow/ios/IOSUtil.java
new file mode 100644
index 000000000..bd4b36239
--- /dev/null
+++ b/src/nativewindow/classes/jogamp/nativewindow/ios/IOSUtil.java
@@ -0,0 +1,333 @@
+/**
+ * Copyright 2019 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.ios;
+
+import com.jogamp.nativewindow.NativeWindowException;
+import com.jogamp.nativewindow.NativeWindowFactory;
+import com.jogamp.nativewindow.util.Insets;
+import com.jogamp.nativewindow.util.Point;
+import com.jogamp.common.util.Function;
+import com.jogamp.common.util.FunctionTask;
+import com.jogamp.common.util.InterruptedRuntimeException;
+import com.jogamp.common.util.RunnableTask;
+
+import jogamp.nativewindow.Debug;
+import jogamp.nativewindow.NWJNILibLoader;
+import jogamp.nativewindow.ToolkitProperties;
+
+public class IOSUtil implements ToolkitProperties {
+ private static boolean isInit = false;
+ private static final boolean DEBUG = Debug.debug("IOSUtil");
+
+ /** FIXME HiDPI: OSX unique and maximum value {@value} */
+ public static final int MAX_PIXELSCALE = 2;
+
+ /**
+ * Called by {@link NativeWindowFactory#initSingleton()}
+ * @see ToolkitProperties
+ */
+ public static synchronized void initSingleton() {
+ if(!isInit) {
+ if(DEBUG) {
+ System.out.println("IOSUtil.initSingleton()");
+ }
+ if(!NWJNILibLoader.loadNativeWindow("ios")) {
+ throw new NativeWindowException("NativeWindow IOS native library load error.");
+ }
+
+ if( !initIDs0() ) {
+ throw new NativeWindowException("IOS: Could not initialized native stub");
+ }
+ isInit = true;
+ }
+ }
+
+ /**
+ * Called by {@link NativeWindowFactory#shutdown()}
+ * @see ToolkitProperties
+ */
+ public static void shutdown() { }
+
+ /**
+ * Called by {@link NativeWindowFactory#initSingleton()}
+ * @see ToolkitProperties
+ */
+ public static boolean requiresToolkitLock() { return false; }
+
+ /**
+ * Called by {@link NativeWindowFactory#initSingleton()}
+ * @see ToolkitProperties
+ */
+ public static final boolean hasThreadingIssues() { return false; }
+
+ public static boolean isCALayer(final long object) {
+ return 0 != object ? isCALayer0(object) : false;
+ }
+
+ public static boolean isCAEAGLLayer(final long object) {
+ return 0 != object ? isCAEAGLLayer0(object) : false;
+ }
+
+ public static boolean isUIView(final long object) {
+ return 0 != object ? isUIView0(object) : false;
+ }
+
+ public static boolean isUIWindow(final long object) {
+ return 0 != object ? isUIWindow0(object) : false;
+ }
+
+ /**
+ * @param windowOrView
+ * @param src_x
+ * @param src_y
+ * @return top-left client-area position in window units
+ */
+ public static Point GetLocationOnScreen(final long windowOrView, final int src_x, final int src_y) {
+ return (Point) GetLocationOnScreen0(windowOrView, src_x, src_y);
+ }
+
+ public static Insets GetInsets(final long windowOrView) {
+ return (Insets) GetInsets0(windowOrView);
+ }
+
+ public static double GetPixelScaleByDisplayID(final int displayID) {
+ if( 0 != displayID ) {
+ return GetPixelScale1(displayID);
+ } else {
+ return 1.0; // default
+ }
+ }
+ public static double GetPixelScale(final long windowOrView) {
+ if( 0 != windowOrView ) {
+ return GetPixelScale2(windowOrView);
+ } else {
+ return 1.0; // default
+ }
+ }
+
+ public static long CreateUIWindow(final int x, final int y, final int width, final int height) {
+ final long res[] = { 0 };
+ RunOnMainThread(true, false /* kickNSApp */, new Runnable() {
+ @Override
+ public void run() {
+ res[0] = CreateUIWindow0(x, y, width, height);
+ } } );
+ return res[0];
+ }
+ public static void DestroyUIWindow(final long uiWindow) {
+ DestroyUIWindow0(uiWindow);
+ }
+ public static long GetCALayer(final long uiView) {
+ return 0 != uiView ? GetCALayer0(uiView) : 0;
+ }
+ public static long GetCAEAGLLayer(final long uiView) {
+ return 0 != uiView ? GetCAEAGLLayer0(uiView) : 0;
+ }
+ public static long GetUIView(final long uiWindow, final boolean onlyEAGL) {
+ return 0 != uiWindow ? GetUIView0(uiWindow, onlyEAGL) : 0;
+ }
+ public static long GetUIWindow(final long uiView) {
+ return 0 != uiView ? GetUIWindow0(uiView) : 0;
+ }
+
+ /**
+ * Set the UIView's pixelScale / contentScale for HiDPI
+ *
+ * @param uiView the mutable UIView instance
+ * @param contentScaleFactor scale for HiDPI support: pixel-dim = window-dim x scale
+ */
+ public static void SetUIViewPixelScale(final long uiView, final float contentScaleFactor) {
+ SetUIViewPixelScale0(uiView, contentScaleFactor);
+ }
+ /**
+ * Get the UIView's pixelScale / contentScale for HiDPI
+ *
+ * @param uiView the UIView instance
+ * @return used scale for HiDPI support: pixel-dim = window-dim x scale
+ */
+ public static float GetUIViewPixelScale(final long uiView) {
+ return GetUIViewPixelScale0(uiView);
+ }
+
+ /**
+ * Set root and sub CALayer pixelScale / contentScale for HiDPI
+ *
+ * @param rootCALayer the root surface layer, maybe null.
+ * @param subCALayer the client surface layer, maybe null.
+ * @param contentsScale scale for HiDPI support: pixel-dim = window-dim x scale
+ */
+ public static void SetCALayerPixelScale(final long rootCALayer, final long subCALayer, final float contentsScale) {
+ if( 0==rootCALayer && 0==subCALayer ) {
+ return;
+ }
+ SetCALayerPixelScale0(rootCALayer, subCALayer, contentsScale);
+ }
+ /**
+ * Get the CALayer's pixelScale / contentScale for HiDPI
+ *
+ * @param caLayer the CALayer instance
+ * @return used scale for HiDPI support: pixel-dim = window-dim x scale
+ */
+ public static float GetCALayerPixelScale(final long caLayer) {
+ return GetCALayerPixelScale0(caLayer);
+ }
+
+ /**
+ * Run on OSX UI main thread.
+ * <p>
+ * 'waitUntilDone' is implemented on Java site via lock/wait on {@link RunnableTask} to not freeze OSX main thread.
+ * </p>
+ *
+ * @param waitUntilDone
+ * @param kickNSApp if <code>true</code> issues {@link #KickUIApp()}
+ * @param runnable
+ */
+ public static void RunOnMainThread(final boolean waitUntilDone, final boolean kickNSApp, final Runnable runnable) {
+ if( IsMainThread0() ) {
+ runnable.run(); // don't leave the JVM
+ } else {
+ // Utilize Java side lock/wait and simply pass the Runnable async to OSX main thread,
+ // otherwise we may freeze the OSX main thread.
+ final Object sync = new Object();
+ final RunnableTask rt = new RunnableTask( runnable, waitUntilDone ? sync : null, true, waitUntilDone ? null : System.err );
+ synchronized(sync) {
+ RunOnMainThread0(kickNSApp, rt);
+ if( waitUntilDone ) {
+ while( rt.isInQueue() ) {
+ try {
+ sync.wait();
+ } catch (final InterruptedException ie) {
+ throw new InterruptedRuntimeException(ie);
+ }
+ final Throwable throwable = rt.getThrowable();
+ if(null!=throwable) {
+ throw new RuntimeException(throwable);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Run later on ..
+ * @param onMain if true, run on main-thread, otherwise on the current OSX thread.
+ * @param runnable
+ * @param delay delay to run the runnable in milliseconds
+ */
+ public static void RunLater(final boolean onMain, final Runnable runnable, final int delay) {
+ RunLater0(onMain, false /* kickNSApp */, new RunnableTask( runnable, null, true, System.err ), delay);
+ }
+
+ private static Runnable _nop = new Runnable() { @Override public void run() {}; };
+
+ /** Issues a {@link #RunOnMainThread(boolean, boolean, Runnable)} w/ an <i>NOP</i> runnable, while waiting until done and issuing {@link #KickUIApp()}. */
+ public static void WaitUntilFinish() {
+ RunOnMainThread(true, true /* kickNSApp */, _nop);
+ }
+
+ /**
+ * Run on OSX UI main thread.
+ * <p>
+ * 'waitUntilDone' is implemented on Java site via lock/wait on {@link FunctionTask} to not freeze OSX main thread.
+ * </p>
+ *
+ * @param waitUntilDone
+ * @param kickUIApp if <code>true</code> issues {@link #KickUIApp()}
+ * @param func
+ */
+ public static <R,A> R RunOnMainThread(final boolean waitUntilDone, final boolean kickUIApp, final Function<R,A> func, final A... args) {
+ if( IsMainThread0() ) {
+ return func.eval(args); // don't leave the JVM
+ } else {
+ // Utilize Java side lock/wait and simply pass the Runnable async to OSX main thread,
+ // otherwise we may freeze the OSX main thread.
+ final Object sync = new Object();
+ final FunctionTask<R,A> rt = new FunctionTask<R,A>( func, waitUntilDone ? sync : null, true, waitUntilDone ? null : System.err );
+ synchronized(sync) {
+ rt.setArgs(args);
+ RunOnMainThread0(kickUIApp, rt);
+ if( waitUntilDone ) {
+ while( rt.isInQueue() ) {
+ try {
+ sync.wait();
+ } catch (final InterruptedException ie) {
+ throw new InterruptedRuntimeException(ie);
+ }
+ final Throwable throwable = rt.getThrowable();
+ if(null!=throwable) {
+ throw new RuntimeException(throwable);
+ }
+ }
+ }
+ }
+ return rt.getResult();
+ }
+ }
+
+ public static boolean IsMainThread() {
+ return IsMainThread0();
+ }
+
+ /** Returns the screen refresh rate in Hz. If unavailable, returns 60Hz. */
+ public static int GetScreenRefreshRate(final int scrn_idx) {
+ return GetScreenRefreshRate0(scrn_idx);
+ }
+
+ public static void CreateGLViewDemoA() {
+ CreateGLViewDemoA0();
+ }
+
+ private static native boolean initIDs0();
+ private static native boolean isCALayer0(long object);
+ private static native boolean isCAEAGLLayer0(long object);
+ private static native boolean isUIView0(long object);
+ private static native boolean isUIWindow0(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 double GetPixelScale1(int displayID);
+ private static native double GetPixelScale2(long windowOrView);
+ private static native long CreateUIWindow0(int x, int y, int width, int height);
+ private static native void DestroyUIWindow0(long uiWindow);
+ private static native long GetCALayer0(long uiView);
+ private static native long GetCAEAGLLayer0(long uiView);
+ private static native long GetUIView0(long uiWindow, boolean onlyEAGL);
+ private static native long GetUIWindow0(long uiView);
+ private static native void SetUIViewPixelScale0(final long uiView, final float contentScaleFactor);
+ private static native float GetUIViewPixelScale0(final long uiView);
+ private static native void SetCALayerPixelScale0(long rootCALayer, long subCALayer, float contentsScale);
+ private static native float GetCALayerPixelScale0(final long caLayer);
+
+ private static native void RunOnMainThread0(boolean kickNSApp, Runnable runnable);
+ private static native void RunLater0(boolean onMain, boolean kickNSApp, Runnable runnable, int delay);
+ private static native void KickUIApp0();
+ private static native boolean IsMainThread0();
+ private static native int GetScreenRefreshRate0(int scrn_idx);
+ private static native void CreateGLViewDemoA0();
+
+}
diff --git a/src/nativewindow/native/JVM_JNI8.c b/src/nativewindow/native/JVM_JNI8.c
new file mode 100644
index 000000000..a7b4e5d90
--- /dev/null
+++ b/src/nativewindow/native/JVM_JNI8.c
@@ -0,0 +1,47 @@
+/**
+ * Copyright 2019 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.
+ */
+
+#include <stdio.h> //required by android to identify NULL
+#include <jni.h>
+
+#if defined (JNI_VERSION_1_8)
+
+JNIEXPORT jint JNICALL JNI_OnLoad_nativewindow_awt(JavaVM *vm, void *reserved) { return JNI_VERSION_1_8; }
+JNIEXPORT jint JNICALL JNI_OnLoad_nativewindow_x11(JavaVM *vm, void *reserved) { return JNI_VERSION_1_8; }
+JNIEXPORT jint JNICALL JNI_OnLoad_nativewindow_win32(JavaVM *vm, void *reserved) { return JNI_VERSION_1_8; }
+JNIEXPORT jint JNICALL JNI_OnLoad_nativewindow_macosx(JavaVM *vm, void *reserved) { return JNI_VERSION_1_8; }
+JNIEXPORT jint JNICALL JNI_OnLoad_nativewindow_ios(JavaVM *vm, void *reserved) { return JNI_VERSION_1_8; }
+
+JNIEXPORT void JNICALL JNI_OnUnload_nativewindow_awt(JavaVM *vm, void *reserved) { }
+JNIEXPORT void JNICALL JNI_OnUnload_nativewindow_x11(JavaVM *vm, void *reserved) { }
+JNIEXPORT void JNICALL JNI_OnUnload_nativewindow_win32(JavaVM *vm, void *reserved) { }
+JNIEXPORT void JNICALL JNI_OnUnload_nativewindow_macosx(JavaVM *vm, void *reserved) { }
+JNIEXPORT void JNICALL JNI_OnUnload_nativewindow_ios(JavaVM *vm, void *reserved) { }
+
+#endif /* defined (JNI_VERSION_1_8) */
+
diff --git a/src/nativewindow/native/ios/CAEAGLLayered.h b/src/nativewindow/native/ios/CAEAGLLayered.h
new file mode 100644
index 000000000..fe94dc907
--- /dev/null
+++ b/src/nativewindow/native/ios/CAEAGLLayered.h
@@ -0,0 +1,50 @@
+/**
+ * Copyright 2019 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.
+ */
+
+#ifndef CAEAGL_LAYERED_H
+#define CAEAGL_LAYERED_H 1
+
+#import <UIKit/UIKit.h>
+#import <QuartzCore/QuartzCore.h>
+
+#include "NativewindowCommon.h"
+
+@interface CAEAGLUIView : UIView
+{
+}
+// override
++ (Class)layerClass;
+
++ (CAEAGLUIView*) findCAEAGLUIView: (UIWindow*) win
+ startIdx: (int) sidx;
+
++ (UIView*) getUIView: (UIWindow*) win
+ startIdx: (int) sidx;
+@end /* interface CAEAGLUIView */
+
+#endif
diff --git a/src/nativewindow/native/ios/CAEAGLLayered.m b/src/nativewindow/native/ios/CAEAGLLayered.m
new file mode 100644
index 000000000..3d378e997
--- /dev/null
+++ b/src/nativewindow/native/ios/CAEAGLLayered.m
@@ -0,0 +1,66 @@
+/**
+ * Copyright 2019 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.
+ */
+
+#include "CAEAGLLayered.h"
+
+@implementation CAEAGLUIView
+// override
++ (Class)layerClass {
+ return CAEAGLLayer.self;
+}
+/**
+override class var layerClass : AnyClass {
+ return CAEAGLLayer.self
+}
+*/
++ (CAEAGLUIView*) findCAEAGLUIView: (UIWindow*) win
+ startIdx: (int) sidx
+{
+ NSArray* subviews = [win subviews];
+ if(NULL != subviews) {
+ for(int i=sidx; i<[subviews count]; i++) {
+ UIView* sub = [subviews objectAtIndex: i];
+ if( [sub isKindOfClass:[CAEAGLUIView class]] ) {
+ return (CAEAGLUIView*)sub;
+ }
+ }
+ }
+ return (CAEAGLUIView*)NULL;
+}
++ (UIView*) getUIView: (UIWindow*) win
+ startIdx: (int) sidx
+{
+ NSArray* subviews = [win subviews];
+ if(NULL != subviews) {
+ if( sidx<[subviews count] ) {
+ return [subviews objectAtIndex: sidx];
+ }
+ }
+ return (UIView*)NULL;
+}
+@end /* implementation CAEAGLUIView */
diff --git a/src/nativewindow/native/ios/IOSmisc.m b/src/nativewindow/native/ios/IOSmisc.m
new file mode 100644
index 000000000..5826b9eef
--- /dev/null
+++ b/src/nativewindow/native/ios/IOSmisc.m
@@ -0,0 +1,813 @@
+/**
+ * Copyright 2019 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.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <unistd.h>
+
+#include "CAEAGLLayered.h"
+
+#import "NativeWindowProtocols.h"
+
+#include "jogamp_nativewindow_ios_IOSUtil.h"
+
+// #define VERBOSE 1
+//
+#ifdef VERBOSE
+ // #define DBG_PRINT(...) NSLog(@ ## __VA_ARGS__)
+ #define DBG_PRINT(...) fprintf(stderr, __VA_ARGS__); fflush(stderr)
+#else
+ #define DBG_PRINT(...)
+#endif
+
+// #define VERBOSE2 1
+//
+#ifdef VERBOSE2
+ #define DBG_PRINT2(...) fprintf(stderr, __VA_ARGS__); fflush(stderr)
+#else
+ #define DBG_PRINT2(...)
+#endif
+
+// #define DBG_LIFECYCLE 1
+
+static const char * const ClazzNameRunnable = "java/lang/Runnable";
+static jmethodID runnableRunID = NULL;
+
+static const char * const ClazzAnyCstrName = "<init>";
+
+static const char * const ClazzNamePoint = "com/jogamp/nativewindow/util/Point";
+static const char * const ClazzNamePointCstrSignature = "(II)V";
+static jclass pointClz = NULL;
+static jmethodID pointCstr = NULL;
+
+static const char * const ClazzNameInsets = "com/jogamp/nativewindow/util/Insets";
+static const char * const ClazzNameInsetsCstrSignature = "(IIII)V";
+static jclass insetsClz = NULL;
+static jmethodID insetsCstr = NULL;
+
+JNIEXPORT jboolean JNICALL
+Java_jogamp_nativewindow_ios_IOSUtil_initIDs0(JNIEnv *env, jclass _unused) {
+ if( NativewindowCommon_init(env) ) {
+ jclass c;
+ c = (*env)->FindClass(env, ClazzNamePoint);
+ if(NULL==c) {
+ NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_ios_IOSUtil_initIDs0: can't find %s", ClazzNamePoint);
+ }
+ pointClz = (jclass)(*env)->NewGlobalRef(env, c);
+ (*env)->DeleteLocalRef(env, c);
+ if(NULL==pointClz) {
+ NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_ios_IOSUtil_initIDs0: can't use %s", ClazzNamePoint);
+ }
+ pointCstr = (*env)->GetMethodID(env, pointClz, ClazzAnyCstrName, ClazzNamePointCstrSignature);
+ if(NULL==pointCstr) {
+ NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_ios_IOSUtil_initIDs0: can't fetch %s.%s %s",
+ ClazzNamePoint, ClazzAnyCstrName, ClazzNamePointCstrSignature);
+ }
+
+ c = (*env)->FindClass(env, ClazzNameInsets);
+ if(NULL==c) {
+ NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_ios_IOSUtil_initIDs0: can't find %s", ClazzNameInsets);
+ }
+ insetsClz = (jclass)(*env)->NewGlobalRef(env, c);
+ (*env)->DeleteLocalRef(env, c);
+ if(NULL==insetsClz) {
+ NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_ios_IOSUtil_initIDs0: can't use %s", ClazzNameInsets);
+ }
+ insetsCstr = (*env)->GetMethodID(env, insetsClz, ClazzAnyCstrName, ClazzNameInsetsCstrSignature);
+ if(NULL==insetsCstr) {
+ NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_ios_IOSUtil_initIDs0: can't fetch %s.%s %s",
+ ClazzNameInsets, ClazzAnyCstrName, ClazzNameInsetsCstrSignature);
+ }
+
+ c = (*env)->FindClass(env, ClazzNameRunnable);
+ if(NULL==c) {
+ NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_ios_IOSUtil_initIDs0: can't find %s", ClazzNameRunnable);
+ }
+ runnableRunID = (*env)->GetMethodID(env, c, "run", "()V");
+ if(NULL==runnableRunID) {
+ NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_ios_IOSUtil_initIDs0: can't fetch %s.run()V", ClazzNameRunnable);
+ }
+ }
+ return JNI_TRUE;
+}
+
+JNIEXPORT jboolean JNICALL
+Java_jogamp_nativewindow_ios_IOSUtil_isCAEAGLLayer0(JNIEnv *env, jclass _unused, jlong object) {
+ NSObject *nsObj = (NSObject*) (intptr_t) object;
+ jboolean u = [nsObj isKindOfClass:[CAEAGLLayer class]];
+ DBG_PRINT( "isEAGLCALayer(obj: %p): %s -> %d\n", nsObj, [[nsObj description] UTF8String], u);
+ return u;
+}
+
+JNIEXPORT jboolean JNICALL
+Java_jogamp_nativewindow_ios_IOSUtil_isCALayer0(JNIEnv *env, jclass _unused, jlong object) {
+ NSObject *nsObj = (NSObject*) (intptr_t) object;
+ jboolean u = [nsObj isKindOfClass:[CALayer class]];
+ DBG_PRINT( "isCALayer(obj: %p): %s -> %d\n", nsObj, [[nsObj description] UTF8String], u);
+ return u;
+}
+
+JNIEXPORT jboolean JNICALL
+Java_jogamp_nativewindow_ios_IOSUtil_isUIView0(JNIEnv *env, jclass _unused, jlong object) {
+ NSObject *nsObj = (NSObject*) (intptr_t) object;
+ jboolean u = [nsObj isKindOfClass:[UIView class]];
+ DBG_PRINT( "isUIView(obj: %p): %s -> %d\n", nsObj, [[nsObj description] UTF8String], u);
+ return u;
+}
+
+JNIEXPORT jboolean JNICALL
+Java_jogamp_nativewindow_ios_IOSUtil_isUIWindow0(JNIEnv *env, jclass _unused, jlong object) {
+ NSObject *nsObj = (NSObject*) (intptr_t) object;
+ jboolean u = [nsObj isKindOfClass:[UIWindow class]];
+ DBG_PRINT( "isUIWindow(obj: %p): %s -> %d\n", nsObj, [[nsObj description] UTF8String], u);
+ return u;
+}
+
+/*
+ * Class: Java_jogamp_nativewindow_ios_IOSUtil
+ * Method: getLocationOnScreen0
+ * Signature: (JII)Lcom/jogamp/nativewindow/util/Point;
+ */
+JNIEXPORT jobject JNICALL Java_jogamp_nativewindow_ios_IOSUtil_GetLocationOnScreen0
+ (JNIEnv *env, jclass unused, jlong winOrView, jint src_x, jint src_y)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+
+ /**
+ * return location in 0/0 top-left space,
+ * OSX NSView is 0/0 bottom-left space naturally
+ * iOS UIView is 0/0 top-left space naturally
+ */
+ NSObject *nsObj = (NSObject*) (intptr_t) winOrView;
+ UIWindow* win = NULL;
+
+ if( [nsObj isKindOfClass:[UIWindow class]] ) {
+ win = (UIWindow*) nsObj;
+ } else if( nsObj != NULL && [nsObj isKindOfClass:[UIView class]] ) {
+ UIView* view = (UIView*) nsObj;
+ win = [view window];
+ if( NULL == win ) {
+ NativewindowCommon_throwNewRuntimeException(env, "view has null window, view %p\n", nsObj);
+ }
+ } else {
+ NativewindowCommon_throwNewRuntimeException(env, "neither win nor view %p\n", nsObj);
+ }
+ CGPoint p = CGPointMake(src_x, src_y);
+ UIScreen* screen = [win screen];
+ CGPoint pS = [win convertPoint: p toCoordinateSpace: screen.fixedCoordinateSpace];
+
+#ifdef VERBOSE_ON
+ CGRect winFrame = [self frame];
+ DBG_PRINT( "GetLocationOnScreen0(window: %p):: point-in[%d/%d], winFrame[%d/%d %dx%d] -> %d/%d\n",
+ win,
+ (int)p.x, (int)p.y,
+ (int)winFrame.origin.x, (int)winFrame.origin.y, (int)winFrame.size.width, (int)winFrame.size.height,
+ (int)pS.x, (int)pS.y);
+#endif
+
+ jobject res = (*env)->NewObject(env, pointClz, pointCstr, (jint)pS.x, (jint)pS.y);
+
+ [pool release];
+
+ return res;
+}
+
+/*
+ * Class: Java_jogamp_nativewindow_ios_IOSUtil
+ * Method: getInsets0
+ * Signature: (J)Lcom/jogamp/nativewindow/util/Insets;
+ */
+JNIEXPORT jobject JNICALL Java_jogamp_nativewindow_ios_IOSUtil_GetInsets0
+ (JNIEnv *env, jclass unused, jlong winOrView)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+
+ NSObject *nsObj = (NSObject*) (intptr_t) winOrView;
+ UIWindow* win = NULL;
+ jint il,ir,it,ib;
+
+ if( [nsObj isKindOfClass:[UIWindow class]] ) {
+ win = (UIWindow*) nsObj;
+ } else if( nsObj != NULL && [nsObj isKindOfClass:[UIView class]] ) {
+ UIView* view = (UIView*) nsObj;
+ win = [view window];
+ if( NULL == win ) {
+ NativewindowCommon_throwNewRuntimeException(env, "view has null window, view %p\n", nsObj);
+ }
+ } else {
+ NativewindowCommon_throwNewRuntimeException(env, "neither win nor view %p\n", nsObj);
+ }
+
+ UIEdgeInsets uiInsets = [win safeAreaInsets];
+ il = uiInsets.left;
+ ir = uiInsets.right;
+ it = uiInsets.top;
+ ib = uiInsets.bottom;
+ /**
+ CGRect frameRect = [win frame];
+ CGRect contentRect = [win contentRectForFrameRect: frameRect];
+
+ // note: this is a simplistic implementation which doesn't take
+ // into account DPI and scaling factor
+ CGFloat l = contentRect.origin.x - frameRect.origin.x;
+ il = (jint)l; // l
+ ir = (jint)(frameRect.size.width - (contentRect.size.width + l)); // r
+ it = (jint)(frameRect.size.height - contentRect.size.height); // t
+ ib = (jint)(contentRect.origin.y - frameRect.origin.y); // b
+ */
+
+ jobject res = (*env)->NewObject(env, insetsClz, insetsCstr, il, ir, it, ib);
+
+ [pool release];
+
+ return res;
+}
+
+/*
+ * Class: Java_jogamp_nativewindow_ios_IOSUtil
+ * Method: GetPixelScale1
+ * Signature: (I)D
+ */
+JNIEXPORT jdouble JNICALL Java_jogamp_nativewindow_ios_IOSUtil_GetPixelScale1
+ (JNIEnv *env, jclass unused, jint displayID)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+
+ CGFloat pixelScale = 1.0; // default
+ // UIScreen *screen = IOSUtil_getUIScreenByCGDirectDisplayID((CGDirectDisplayID)displayID);
+ UIScreen *screen = [UIScreen mainScreen];
+ if( NULL != screen ) {
+NS_DURING
+ // Available >= 10.7
+ pixelScale = [screen scale]; // HiDPI scaling
+NS_HANDLER
+NS_ENDHANDLER
+ }
+ [pool release];
+
+ return (jdouble)pixelScale;
+}
+
+/*
+ * Class: Java_jogamp_nativewindow_ios_IOSUtil
+ * Method: GetPixelScale1
+ * Signature: (J)D
+ */
+JNIEXPORT jdouble JNICALL Java_jogamp_nativewindow_ios_IOSUtil_GetPixelScale2
+ (JNIEnv *env, jclass unused, jlong winOrView)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+
+ NSObject *nsObj = (NSObject*) (intptr_t) winOrView;
+ UIScreen *screen = NULL;
+
+ if( [nsObj isKindOfClass:[UIWindow class]] ) {
+ UIWindow* win = (UIWindow*) nsObj;
+ screen = [win screen];
+ } else if( nsObj != NULL && [nsObj isKindOfClass:[UIView class]] ) {
+ UIView* view = (UIView*) nsObj;
+ UIWindow* win = [view window];
+ if( NULL == win ) {
+ NativewindowCommon_throwNewRuntimeException(env, "view has null window, view %p\n", nsObj);
+ }
+ screen = [win screen];
+ } else {
+ NativewindowCommon_throwNewRuntimeException(env, "neither win nor view %p\n", nsObj);
+ }
+
+ CGFloat pixelScale = 1.0; // default
+NS_DURING
+ // Available >= 10.7
+ pixelScale = [screen scale]; // HiDPI scaling
+NS_HANDLER
+NS_ENDHANDLER
+
+ [pool release];
+
+ return (jdouble)pixelScale;
+}
+
+/*
+ * Class: Java_jogamp_nativewindow_ios_IOSUtil
+ * Method: CreateUIWindow0
+ * Signature: (IIIIZ)J
+ */
+JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_ios_IOSUtil_CreateUIWindow0
+ (JNIEnv *env, jclass unused, jint x, jint y, jint width, jint height)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ [CATransaction begin];
+ CGRect boundsWin = CGRectMake(x, y, width, height);
+ CGRect boundsView = CGRectMake(0, 0, width, height);
+
+ // Allocate the window
+ UIWindow *myWindow = [[[[UIWindow alloc] initWithFrame:boundsWin] autorelease] retain];
+ myWindow.rootViewController = [[[UIViewController alloc] initWithNibName:nil bundle:nil] autorelease];
+ [myWindow setBackgroundColor: [UIColor redColor]];
+
+ // n/a iOS [myWindow setPreservesContentDuringLiveResize: YES];
+
+ // FIXME invisible .. (we keep it visible for testing)
+ // FIXME [myWindow setOpaque: NO];
+ // FIXME [myWindow setBackgroundColor: [UIColor clearColor]];
+ [myWindow makeKeyAndVisible];
+
+ CAEAGLUIView *uiView = [[CAEAGLUIView alloc] initWithFrame:boundsView];
+ CAEAGLLayer* l = (CAEAGLLayer*)[uiView layer];
+ [l setOpaque: YES];
+
+ [myWindow addSubview: uiView];
+
+ [CATransaction commit];
+ [pool release];
+ return (jlong) ((intptr_t) myWindow);
+}
+
+/*
+ * Class: Java_jogamp_nativewindow_ios_IOSUtil
+ * Method: DestroyUIWindow0
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_nativewindow_ios_IOSUtil_DestroyUIWindow0
+ (JNIEnv *env, jclass unused, jlong nsWindow)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ [CATransaction begin];
+
+NS_DURING
+ UIWindow* mWin = (UIWindow*) ((intptr_t) nsWindow);
+ [mWin resignKeyWindow];
+ [mWin setHidden: YES];
+ NSArray* subviews = [mWin subviews];
+ if(NULL != subviews) {
+ for(int i=0; i<[subviews count]; i++) {
+ UIView* sub = [subviews objectAtIndex: i];
+ [sub setHidden: YES];
+ [sub release];
+ }
+ }
+ [mWin release];
+NS_HANDLER
+ // On killing or terminating the process [UIWindow _close], rarely
+ // throws an NSRangeException while ordering out menu items
+NS_ENDHANDLER
+
+ [CATransaction commit];
+ [pool release];
+}
+
+/*
+ * Class: Java_jogamp_nativewindow_ios_IOSUtil
+ * Method: GetCALayer0
+ * Signature: (J)J
+ */
+JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_ios_IOSUtil_GetCALayer0
+ (JNIEnv *env, jclass unused, jlong view)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ UIView* uiView = (UIWindow*) ((intptr_t) view);
+
+ jlong res = (jlong) ((intptr_t) (CALayer *) [uiView layer]);
+
+ DBG_PRINT( "GetCALayer(view: %p): %p\n", uiView, (void*) (intptr_t) res);
+
+ [pool release];
+ return res;
+}
+
+/*
+ * Class: Java_jogamp_nativewindow_ios_IOSUtil
+ * Method: GetCAEAGLLayer0
+ * Signature: (J)J
+ */
+JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_ios_IOSUtil_GetCAEAGLLayer0
+ (JNIEnv *env, jclass unused, jlong view)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ UIView* uiView = (UIWindow*) ((intptr_t) view);
+
+ CALayer* l = [uiView layer];
+ jboolean isRes = [l isKindOfClass:[CAEAGLLayer class]];
+ jlong res = isRes ? (jlong) ((intptr_t) l) : 0;
+
+ DBG_PRINT( "GetCAEAGLLayer(view: %p): CALayer %p, CAEAGLLayer %p (%d)\n", uiView, l, (void*) (intptr_t) res, isRes);
+
+ [pool release];
+ return res;
+}
+
+/*
+ * Class: Java_jogamp_nativewindow_ios_IOSUtil
+ * Method: GetUIView0
+ * Signature: (J)J
+ */
+JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_ios_IOSUtil_GetUIView0
+ (JNIEnv *env, jclass unused, jlong window, jboolean onlyCAEAGLUIView)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ UIWindow* win = (UIWindow*) ((intptr_t) window);
+ jlong res;
+
+ if( onlyCAEAGLUIView ) {
+ CAEAGLUIView* v0 = [CAEAGLUIView findCAEAGLUIView: win
+ startIdx: 0];
+ res = (jlong) ((intptr_t) v0);
+ } else {
+ UIView* v0 = [CAEAGLUIView getUIView: win startIdx: 0];
+ res = (jlong) ((intptr_t) v0);
+ }
+
+ DBG_PRINT( "GetUIView(window: %p): %p\n", win, (void*) (intptr_t) res);
+
+ [pool release];
+ return res;
+}
+
+/*
+ * Class: Java_jogamp_nativewindow_ios_IOSUtil
+ * Method: GetUIWindow0
+ * Signature: (J)J
+ */
+JNIEXPORT jlong JNICALL Java_jogamp_nativewindow_ios_IOSUtil_GetUIWindow0
+ (JNIEnv *env, jclass unused, jlong view)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ UIView* v = (UIView*) ((intptr_t) view);
+
+ jlong res = (jlong) ((intptr_t) [v window]);
+
+ DBG_PRINT( "GetUIWindow(view: %p): %p\n", v, (void*) (intptr_t) res);
+
+ [pool release];
+ return res;
+}
+
+/*
+ * Class: Java_jogamp_nativewindow_ios_IOSUtil
+ * Method: SetUIViewPixelScale0
+ * Signature: (JF)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_nativewindow_ios_IOSUtil_SetUIViewPixelScale0
+ (JNIEnv *env, jclass unused, jlong view, jfloat contentScale)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ UIView* v = (UIView*) ((intptr_t) view);
+
+NS_DURING
+ if( NULL != v ) {
+ [v setContentScaleFactor: (CGFloat)contentScale];
+ }
+NS_HANDLER
+NS_ENDHANDLER
+
+ [pool release];
+}
+/*
+ * Class: Java_jogamp_nativewindow_ios_IOSUtil
+ * Method: GetUIViewPixelScale0
+ * Signature: (J)F
+ */
+JNIEXPORT jfloat JNICALL Java_jogamp_nativewindow_ios_IOSUtil_GetUIViewPixelScale0
+ (JNIEnv *env, jclass unused, jlong view)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ UIView* v = (UIView*) ((intptr_t) view);
+ jfloat r = 0.0f;
+
+NS_DURING
+ if( NULL != v ) {
+ r = [v contentScaleFactor];
+ }
+NS_HANDLER
+NS_ENDHANDLER
+
+ [pool release];
+ return r;
+}
+
+/*
+ * Class: Java_jogamp_nativewindow_ios_IOSUtil
+ * Method: SetCALayerPixelScale0
+ * Signature: (JJF)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_nativewindow_ios_IOSUtil_SetCALayerPixelScale0
+ (JNIEnv *env, jclass unused, jlong rootCALayer, jlong subCALayer, jfloat contentsScale)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ CALayer* rootLayer = (CALayer*) ((intptr_t) rootCALayer);
+ CALayer* subLayer = (CALayer*) ((intptr_t) subCALayer);
+
+ [CATransaction begin];
+ [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
+
+NS_DURING
+ if( NULL != rootLayer ) {
+ [rootLayer setContentsScale: (CGFloat)contentsScale];
+ }
+ if( NULL != subLayer ) {
+ [subLayer setContentsScale: (CGFloat)contentsScale];
+ }
+NS_HANDLER
+NS_ENDHANDLER
+
+ [CATransaction commit];
+
+ [pool release];
+}
+/*
+ * Class: Java_jogamp_nativewindow_ios_IOSUtil
+ * Method: GetCALayerPixelScale0
+ * Signature: (J)F
+ */
+JNIEXPORT jfloat JNICALL Java_jogamp_nativewindow_ios_IOSUtil_GetCALayerPixelScale0
+ (JNIEnv *env, jclass unused, jlong caLayer)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ CALayer* v = (CALayer*) ((intptr_t) caLayer);
+ jfloat r = 0.0f;
+
+NS_DURING
+ if( NULL != v ) {
+ r = [v contentsScale];
+ }
+NS_HANDLER
+NS_ENDHANDLER
+
+ [pool release];
+ return r;
+}
+
+@interface MainRunnable : NSObject
+
+{
+ jobject runnableObj;
+}
+
+- (id) initWithRunnable: (jobject)runnable;
+- (void) jRun;
+
+#ifdef DBG_LIFECYCLE
+- (id)retain;
+- (oneway void)release;
+- (void)dealloc;
+#endif
+
+
+@end
+
+@implementation MainRunnable
+
+- (id) initWithRunnable: (jobject)runnable
+{
+ runnableObj = runnable;
+ return [super init];
+}
+
+- (void) jRun
+{
+ int shallBeDetached = 0;
+ JNIEnv* env = NativewindowCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached);
+ DBG_PRINT2("MainRunnable.1 env: %d\n", (int)(NULL!=env));
+ if(NULL!=env) {
+ DBG_PRINT2("MainRunnable.1.0\n");
+ (*env)->CallVoidMethod(env, runnableObj, runnableRunID);
+ DBG_PRINT2("MainRunnable.1.1\n");
+ (*env)->DeleteGlobalRef(env, runnableObj);
+
+ DBG_PRINT2("MainRunnable.1.3\n");
+ // detaching thread not required - daemon
+ // NativewindowCommon_ReleaseJNIEnv(shallBeDetached);
+ }
+ DBG_PRINT2("MainRunnable.X\n");
+}
+
+#ifdef DBG_LIFECYCLE
+
+- (id)retain
+{
+ DBG_PRINT2("MainRunnable::retain.0: %p (refcnt %d)\n", self, (int)[self retainCount]);
+ id o = [super retain];
+ DBG_PRINT2("MainRunnable::retain.X: %p (refcnt %d)\n", o, (int)[o retainCount]);
+ return o;
+}
+
+- (oneway void)release
+{
+ DBG_PRINT2("MainRunnable::release.0: %p (refcnt %d)\n", self, (int)[self retainCount]);
+ [super release];
+ // DBG_PRINT2("MainRunnable::release.X: %p (refcnt %d)\n", self, (int)[self retainCount]);
+}
+
+- (void)dealloc
+{
+ DBG_PRINT2("MainRunnable::dealloc.0 %p (refcnt %d)\n", self, (int)[self retainCount]);
+ [super dealloc];
+ // DBG_PRINT2("MainRunnable.dealloc.X: %p\n", self);
+}
+
+#endif
+
+@end
+
+// #define UIApp [UIApplication sharedApplication]
+// #define NSApp [NSApplication sharedApplication]
+
+static void RunOnThread (JNIEnv *env, jobject runnable, BOOL onMain, jint delayInMS)
+{
+ BOOL isMainThread = [NSThread isMainThread];
+ BOOL forkOnMain = onMain && ( NO == isMainThread || 0 < delayInMS );
+ // UIApplication * UIApp = [UIApplication sharedApplication];
+
+ DBG_PRINT2( "RunOnThread0: forkOnMain %d [onMain %d, delay %dms, isMainThread %d], UIApp %d, UIApp-isRunning %d\n",
+ (int)forkOnMain, (int)onMain, (int)delayInMS, (int)isMainThread, (int)(NULL!=UIApp), (int)([UIApp applicationState]));
+
+ if ( forkOnMain ) {
+ jobject runnableObj = (*env)->NewGlobalRef(env, runnable);
+
+ DBG_PRINT2( "RunOnThread.1.0\n");
+ MainRunnable * mr = [[MainRunnable alloc] initWithRunnable: runnableObj];
+
+ if( onMain ) {
+ [mr performSelectorOnMainThread:@selector(jRun) withObject:nil waitUntilDone:NO];
+ } else {
+ NSTimeInterval delay = (double)delayInMS/1000.0;
+ [mr performSelector:@selector(jRun) withObject:nil afterDelay:delay];
+ }
+ DBG_PRINT2( "RunOnThread.1.1\n");
+
+ [mr release];
+ DBG_PRINT2( "RunOnThread.1.2\n");
+
+ } else {
+ DBG_PRINT2( "RunOnThread.2\n");
+ (*env)->CallVoidMethod(env, runnable, runnableRunID);
+ }
+ DBG_PRINT2( "RunOnThread.X\n");
+}
+
+static void IOSUtil_KickUIApp() {
+ // UIApplication * UIApp = [UIApplication sharedApplication];
+ /*** iOS-FIXME: UIEvent creation and post n/a !!!
+ UIEvent* event = [UIEvent otherEventWithType: UIApplicationDefined
+ location: NSMakePoint(0,0)
+ modifierFlags: 0
+ timestamp: 0.0
+ windowNumber: 0
+ context: nil
+ subtype: 0
+ data1: 0
+ data2: 0];
+ [UIApp postEvent: event atStart: true];
+ */
+}
+
+/**
+ * Class: Java_jogamp_nativewindow_ios_IOSUtil
+ * Method: RunOnMainThread0
+ * Signature: (ZLjava/lang/Runnable;)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_nativewindow_ios_IOSUtil_RunOnMainThread0
+ (JNIEnv *env, jclass unused, jboolean kickUIApp, jobject runnable)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ RunOnThread (env, runnable, YES, 0);
+ if( kickUIApp ) {
+ IOSUtil_KickUIApp();
+ }
+ [pool release];
+}
+
+/*
+ * Class: Java_jogamp_nativewindow_ios_IOSUtil
+ * Method: RunLater0
+ * Signature: (ZZLjava/lang/Runnable;I)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_nativewindow_ios_IOSUtil_RunLater0
+ (JNIEnv *env, jclass unused, jboolean onMain, jboolean kickUIApp, jobject runnable, jint delay)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ RunOnThread (env, runnable, onMain ? YES : NO, delay);
+ if( kickUIApp ) {
+ IOSUtil_KickUIApp();
+ }
+ [pool release];
+}
+
+/*
+ * Class: Java_jogamp_nativewindow_ios_IOSUtil
+ * Method: IsMainThread0
+ * Signature: (V)Z
+ */
+JNIEXPORT jboolean JNICALL Java_jogamp_nativewindow_ios_IOSUtil_IsMainThread0
+ (JNIEnv *env, jclass unused)
+{
+ return ( [NSThread isMainThread] == YES ) ? JNI_TRUE : JNI_FALSE ;
+}
+
+#define EAGL_TEST 1
+
+#ifdef EAGL_TEST
+#include <OpenGLES/ES2/gl.h>
+#include <OpenGLES/ES2/glext.h>
+
+@interface GLView : UIView
+{
+ CAEAGLLayer *glLayer;
+ EAGLContext *glContext;
+ GLuint renderbuffer;
+}
+@end
+@implementation GLView
++ (Class)layerClass
+{
+ return [CAEAGLLayer class];
+}
+
+- (id)initWithFrame:(CGRect)frame
+{
+ if (self = [super initWithFrame:frame]) {
+ [self initGL];
+ [self render];
+ }
+
+ return self;
+}
+
+- (void)render
+{
+ glClearColor(150.0/255.0, 200.0/255.0, 255.0/255.0, 1.0);
+
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ [glContext presentRenderbuffer:GL_RENDERBUFFER];
+}
+
+- (void)initGL
+{
+ glLayer = (CAEAGLLayer *)self.layer;
+ glLayer.opaque = YES;
+
+ glContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
+ if (!glContext) {
+ NSLog(@"Unable to create EAGLContext");
+ exit(1);
+ }
+ if (![EAGLContext setCurrentContext:glContext]) {
+ NSLog(@"Unable to set current EAGLContext");
+ exit(1);
+ }
+ glGenRenderbuffers(1, &renderbuffer);
+ glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
+ [glContext renderbufferStorage:GL_RENDERBUFFER fromDrawable:glLayer];
+
+ GLuint framebuffer;
+ glGenFramebuffers(1, &framebuffer);
+ glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer);
+}
+@end
+#endif /* EAGL_TEST */
+
+JNIEXPORT void JNICALL Java_jogamp_nativewindow_ios_IOSUtil_CreateGLViewDemoA0
+ (JNIEnv *env, jclass unused)
+{
+#ifdef EAGL_TEST
+ CGRect boundsW2 = CGRectMake(500, 10, 320, 320);
+ CGRect boundsV2 = CGRectMake(0, 0, 320, 320);
+ UIWindow* window2 = [[[[UIWindow alloc] initWithFrame:boundsW2] autorelease] retain];
+ window2.rootViewController = [[[UIViewController alloc] initWithNibName:nil bundle:nil] autorelease];
+ [window2 setBackgroundColor: [UIColor redColor]];
+ [window2 makeKeyAndVisible];
+
+ GLView *glView = [[GLView alloc] initWithFrame:boundsV2];
+ [window2 addSubview:glView];
+#endif /* EAGL_TEST */
+}
+
diff --git a/src/nativewindow/native/ios/NativeWindowProtocols.h b/src/nativewindow/native/ios/NativeWindowProtocols.h
new file mode 100644
index 000000000..b27afc70d
--- /dev/null
+++ b/src/nativewindow/native/ios/NativeWindowProtocols.h
@@ -0,0 +1,59 @@
+/**
+ * Copyright 2019 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.
+ */
+
+#ifndef NATIVEWINDOWPROTOCOLS_H
+#define NATIVEWINDOWPROTOCOLS_H 1
+
+/**
+ * CALayer size needs to be set using the AWT component size.
+ * See detailed description in JAWTUtil.java and sync w/ changed.
+ */
+#define NW_DEDICATEDFRAME_QUIRK_SIZE ( 1 << 0 )
+
+/**
+ * CALayer position needs to be set to zero.
+ * See detailed description in JAWTUtil.java and sync w/ changed.
+ */
+#define NW_DEDICATEDFRAME_QUIRK_POSITION ( 1 << 1 )
+
+/**
+ * CALayer position needs to be derived from AWT position.
+ * in relation to super CALayer.
+ * See detailed description in JAWTUtil.java and sync w/ changed.
+ */
+#define NW_DEDICATEDFRAME_QUIRK_LAYOUT ( 1 << 2 )
+
+// n/a iOS #import <Foundation/NSGeometry.h>
+#import <UIKit/UIGeometry.h>
+
+@protocol NWDedicatedFrame
+- (void)setDedicatedFrame:(CGRect)dFrame quirks:(int)quirks;
+@end
+
+#endif /* NATIVEWINDOWPROTOCOLS_H_ */
+
diff --git a/src/nativewindow/native/macosx/OSXmisc.m b/src/nativewindow/native/macosx/OSXmisc.m
index c04ba786e..fb15c43b9 100644
--- a/src/nativewindow/native/macosx/OSXmisc.m
+++ b/src/nativewindow/native/macosx/OSXmisc.m
@@ -81,41 +81,41 @@ Java_jogamp_nativewindow_macosx_OSXUtil_initIDs0(JNIEnv *env, jclass _unused) {
jclass c;
c = (*env)->FindClass(env, ClazzNamePoint);
if(NULL==c) {
- NativewindowCommon_FatalError(env, "FatalError Java_jogamp_newt_driver_macosx_MacWindow_initIDs0: can't find %s", ClazzNamePoint);
+ NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_macosx_OSXUtil_initIDs0: can't find %s", ClazzNamePoint);
}
pointClz = (jclass)(*env)->NewGlobalRef(env, c);
(*env)->DeleteLocalRef(env, c);
if(NULL==pointClz) {
- NativewindowCommon_FatalError(env, "FatalError Java_jogamp_newt_driver_macosx_MacWindow_initIDs0: can't use %s", ClazzNamePoint);
+ NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_macosx_OSXUtil_initIDs0: can't use %s", ClazzNamePoint);
}
pointCstr = (*env)->GetMethodID(env, pointClz, ClazzAnyCstrName, ClazzNamePointCstrSignature);
if(NULL==pointCstr) {
- NativewindowCommon_FatalError(env, "FatalError Java_jogamp_newt_driver_macosx_MacWindow_initIDs0: can't fetch %s.%s %s",
+ NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_macosx_OSXUtil_initIDs0: can't fetch %s.%s %s",
ClazzNamePoint, ClazzAnyCstrName, ClazzNamePointCstrSignature);
}
c = (*env)->FindClass(env, ClazzNameInsets);
if(NULL==c) {
- NativewindowCommon_FatalError(env, "FatalError Java_jogamp_newt_driver_macosx_MacWindow_initIDs0: can't find %s", ClazzNameInsets);
+ NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_macosx_OSXUtil_initIDs0: can't find %s", ClazzNameInsets);
}
insetsClz = (jclass)(*env)->NewGlobalRef(env, c);
(*env)->DeleteLocalRef(env, c);
if(NULL==insetsClz) {
- NativewindowCommon_FatalError(env, "FatalError Java_jogamp_newt_driver_macosx_MacWindow_initIDs0: can't use %s", ClazzNameInsets);
+ NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_macosx_OSXUtil_initIDs0: can't use %s", ClazzNameInsets);
}
insetsCstr = (*env)->GetMethodID(env, insetsClz, ClazzAnyCstrName, ClazzNameInsetsCstrSignature);
if(NULL==insetsCstr) {
- NativewindowCommon_FatalError(env, "FatalError Java_jogamp_newt_driver_macosx_MacWindow_initIDs0: can't fetch %s.%s %s",
+ NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_macosx_OSXUtil_initIDs0: can't fetch %s.%s %s",
ClazzNameInsets, ClazzAnyCstrName, ClazzNameInsetsCstrSignature);
}
c = (*env)->FindClass(env, ClazzNameRunnable);
if(NULL==c) {
- NativewindowCommon_FatalError(env, "FatalError Java_jogamp_newt_driver_macosx_MacWindow_initIDs0: can't find %s", ClazzNameRunnable);
+ NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_macosx_OSXUtil_initIDs0: can't find %s", ClazzNameRunnable);
}
runnableRunID = (*env)->GetMethodID(env, c, "run", "()V");
if(NULL==runnableRunID) {
- NativewindowCommon_FatalError(env, "FatalError Java_jogamp_newt_driver_macosx_MacWindow_initIDs0: can't fetch %s.run()V", ClazzNameRunnable);
+ NativewindowCommon_FatalError(env, "FatalError Java_jogamp_nativewindow_macosx_OSXUtil_initIDs0: can't fetch %s.run()V", ClazzNameRunnable);
}
}
return JNI_TRUE;
diff --git a/src/newt/classes/jogamp/newt/driver/ios/DisplayDriver.java b/src/newt/classes/jogamp/newt/driver/ios/DisplayDriver.java
new file mode 100644
index 000000000..d2bb6de02
--- /dev/null
+++ b/src/newt/classes/jogamp/newt/driver/ios/DisplayDriver.java
@@ -0,0 +1,91 @@
+/**
+ * Copyright 2019 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package jogamp.newt.driver.ios;
+
+import com.jogamp.nativewindow.AbstractGraphicsDevice;
+import com.jogamp.nativewindow.NativeWindowException;
+import com.jogamp.nativewindow.ios.IOSGraphicsDevice;
+import com.jogamp.nativewindow.util.PixelFormat;
+
+import jogamp.newt.DisplayImpl;
+import jogamp.newt.NEWTJNILibLoader;
+
+public class DisplayDriver extends DisplayImpl {
+
+ static {
+ NEWTJNILibLoader.loadNEWT();
+
+ if(!initUIApplication0()) {
+ throw new NativeWindowException("Failed to initialize native Application hook");
+ }
+ if(!WindowDriver.initIDs0()) {
+ throw new NativeWindowException("Failed to initialize jmethodIDs");
+ }
+ if(DEBUG) {
+ System.err.println("MacDisplay.init App and IDs OK "+Thread.currentThread().getName());
+ }
+ }
+
+ public static void initSingleton() {
+ // just exist to ensure static init has been run
+ }
+
+ public DisplayDriver() {
+ }
+
+ @Override
+ public PixelFormat getNativePointerIconPixelFormat() { return PixelFormat.RGBA8888; }
+
+ @Override
+ protected void dispatchMessagesNative() {
+ // nop
+ }
+
+ @Override
+ protected void createNativeImpl() {
+ aDevice = new IOSGraphicsDevice(AbstractGraphicsDevice.DEFAULT_UNIT);
+ }
+
+ @Override
+ protected void closeNativeImpl(final AbstractGraphicsDevice aDevice) {
+ aDevice.close();
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * NOTE: MUST BE DIRECT BUFFER, since NSBitmapImageRep uses buffer directly!
+ * </p>
+ */
+ @Override
+ public final boolean getNativePointerIconForceDirectNIO() { return true; }
+
+ private static native boolean initUIApplication0();
+}
+
diff --git a/src/newt/classes/jogamp/newt/driver/ios/MacKeyUtil.java b/src/newt/classes/jogamp/newt/driver/ios/MacKeyUtil.java
new file mode 100644
index 000000000..e65602959
--- /dev/null
+++ b/src/newt/classes/jogamp/newt/driver/ios/MacKeyUtil.java
@@ -0,0 +1,426 @@
+/**
+ * Copyright 2019 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+package jogamp.newt.driver.ios;
+
+import com.jogamp.newt.event.KeyEvent;
+
+public class MacKeyUtil {
+
+ //
+ // KeyCodes (Layout Dependent)
+ //
+ private static final short kVK_ANSI_A = 0x00;
+ private static final short kVK_ANSI_S = 0x01;
+ private static final short kVK_ANSI_D = 0x02;
+ private static final short kVK_ANSI_F = 0x03;
+ private static final short kVK_ANSI_H = 0x04;
+ private static final short kVK_ANSI_G = 0x05;
+ private static final short kVK_ANSI_Z = 0x06;
+ private static final short kVK_ANSI_X = 0x07;
+ private static final short kVK_ANSI_C = 0x08;
+ private static final short kVK_ANSI_V = 0x09;
+ private static final short kVK_ANSI_B = 0x0B;
+ private static final short kVK_ANSI_Q = 0x0C;
+ private static final short kVK_ANSI_W = 0x0D;
+ private static final short kVK_ANSI_E = 0x0E;
+ private static final short kVK_ANSI_R = 0x0F;
+ private static final short kVK_ANSI_Y = 0x10;
+ private static final short kVK_ANSI_T = 0x11;
+ private static final short kVK_ANSI_1 = 0x12;
+ private static final short kVK_ANSI_2 = 0x13;
+ private static final short kVK_ANSI_3 = 0x14;
+ private static final short kVK_ANSI_4 = 0x15;
+ private static final short kVK_ANSI_6 = 0x16;
+ private static final short kVK_ANSI_5 = 0x17;
+ private static final short kVK_ANSI_Equal = 0x18;
+ private static final short kVK_ANSI_9 = 0x19;
+ private static final short kVK_ANSI_7 = 0x1A;
+ private static final short kVK_ANSI_Minus = 0x1B;
+ private static final short kVK_ANSI_8 = 0x1C;
+ private static final short kVK_ANSI_0 = 0x1D;
+ private static final short kVK_ANSI_RightBracket = 0x1E;
+ private static final short kVK_ANSI_O = 0x1F;
+ private static final short kVK_ANSI_U = 0x20;
+ private static final short kVK_ANSI_LeftBracket = 0x21;
+ private static final short kVK_ANSI_I = 0x22;
+ private static final short kVK_ANSI_P = 0x23;
+ private static final short kVK_ANSI_L = 0x25;
+ private static final short kVK_ANSI_J = 0x26;
+ private static final short kVK_ANSI_Quote = 0x27;
+ private static final short kVK_ANSI_K = 0x28;
+ private static final short kVK_ANSI_Semicolon = 0x29;
+ private static final short kVK_ANSI_Backslash = 0x2A;
+ private static final short kVK_ANSI_Comma = 0x2B;
+ private static final short kVK_ANSI_Slash = 0x2C;
+ private static final short kVK_ANSI_N = 0x2D;
+ private static final short kVK_ANSI_M = 0x2E;
+ private static final short kVK_ANSI_Period = 0x2F;
+ private static final short kVK_ANSI_Grave = 0x32;
+ private static final short kVK_ANSI_KeypadDecimal = 0x41;
+ private static final short kVK_ANSI_KeypadMultiply = 0x43;
+ private static final short kVK_ANSI_KeypadPlus = 0x45;
+ private static final short kVK_ANSI_KeypadClear = 0x47;
+ private static final short kVK_ANSI_KeypadDivide = 0x4B;
+ private static final short kVK_ANSI_KeypadEnter = 0x4C;
+ private static final short kVK_ANSI_KeypadMinus = 0x4E;
+ private static final short kVK_ANSI_KeypadEquals = 0x51;
+ private static final short kVK_ANSI_Keypad0 = 0x52;
+ private static final short kVK_ANSI_Keypad1 = 0x53;
+ private static final short kVK_ANSI_Keypad2 = 0x54;
+ private static final short kVK_ANSI_Keypad3 = 0x55;
+ private static final short kVK_ANSI_Keypad4 = 0x56;
+ private static final short kVK_ANSI_Keypad5 = 0x57;
+ private static final short kVK_ANSI_Keypad6 = 0x58;
+ private static final short kVK_ANSI_Keypad7 = 0x59;
+ private static final short kVK_ANSI_Keypad8 = 0x5B;
+ private static final short kVK_ANSI_Keypad9 = 0x5C;
+
+ //
+ // KeyCodes (Layout Independent)
+ //
+ private static final short kVK_Return = 0x24;
+ private static final short kVK_Tab = 0x30;
+ private static final short kVK_Space = 0x31;
+ private static final short kVK_Delete = 0x33;
+ private static final short kVK_Escape = 0x35;
+ private static final short kVK_Command = 0x37;
+ private static final short kVK_Shift = 0x38;
+ private static final short kVK_CapsLock = 0x39;
+ private static final short kVK_Option = 0x3A;
+ private static final short kVK_Control = 0x3B;
+ private static final short kVK_RightShift = 0x3C;
+ private static final short kVK_RightOption = 0x3D;
+ private static final short kVK_RightControl = 0x3E;
+ // private static final short kVK_Function = 0x3F;
+ private static final short kVK_F17 = 0x40;
+ // private static final short kVK_VolumeUp = 0x48;
+ // private static final short kVK_VolumeDown = 0x49;
+ // private static final short kVK_Mute = 0x4A;
+ private static final short kVK_F18 = 0x4F;
+ private static final short kVK_F19 = 0x50;
+ private static final short kVK_F20 = 0x5A;
+ private static final short kVK_F5 = 0x60;
+ private static final short kVK_F6 = 0x61;
+ private static final short kVK_F7 = 0x62;
+ private static final short kVK_F3 = 0x63;
+ private static final short kVK_F8 = 0x64;
+ private static final short kVK_F9 = 0x65;
+ private static final short kVK_F11 = 0x67;
+ private static final short kVK_F13 = 0x69;
+ private static final short kVK_F16 = 0x6A;
+ private static final short kVK_F14 = 0x6B;
+ private static final short kVK_F10 = 0x6D;
+ private static final short kVK_F12 = 0x6F;
+ private static final short kVK_F15 = 0x71;
+ private static final short kVK_Help = 0x72;
+ private static final short kVK_Home = 0x73;
+ private static final short kVK_PageUp = 0x74;
+ private static final short kVK_ForwardDelete = 0x75;
+ private static final short kVK_F4 = 0x76;
+ private static final short kVK_End = 0x77;
+ private static final short kVK_F2 = 0x78;
+ private static final short kVK_PageDown = 0x79;
+ private static final short kVK_F1 = 0x7A;
+ private static final short kVK_LeftArrow = 0x7B;
+ private static final short kVK_RightArrow = 0x7C;
+ private static final short kVK_DownArrow = 0x7D;
+ private static final short kVK_UpArrow = 0x7E;
+
+ //
+ // Key constants handled differently on Mac OS X than other platforms
+ //
+ private static final char NSUpArrowFunctionKey = 0xF700;
+ private static final char NSDownArrowFunctionKey = 0xF701;
+ private static final char NSLeftArrowFunctionKey = 0xF702;
+ private static final char NSRightArrowFunctionKey = 0xF703;
+ private static final char NSF1FunctionKey = 0xF704;
+ private static final char NSF2FunctionKey = 0xF705;
+ private static final char NSF3FunctionKey = 0xF706;
+ private static final char NSF4FunctionKey = 0xF707;
+ private static final char NSF5FunctionKey = 0xF708;
+ private static final char NSF6FunctionKey = 0xF709;
+ private static final char NSF7FunctionKey = 0xF70A;
+ private static final char NSF8FunctionKey = 0xF70B;
+ private static final char NSF9FunctionKey = 0xF70C;
+ private static final char NSF10FunctionKey = 0xF70D;
+ private static final char NSF11FunctionKey = 0xF70E;
+ private static final char NSF12FunctionKey = 0xF70F;
+ private static final char NSF13FunctionKey = 0xF710;
+ private static final char NSF14FunctionKey = 0xF711;
+ private static final char NSF15FunctionKey = 0xF712;
+ private static final char NSF16FunctionKey = 0xF713;
+ private static final char NSF17FunctionKey = 0xF714;
+ private static final char NSF18FunctionKey = 0xF715;
+ private static final char NSF19FunctionKey = 0xF716;
+ private static final char NSF20FunctionKey = 0xF717;
+ private static final char NSF21FunctionKey = 0xF718;
+ private static final char NSF22FunctionKey = 0xF719;
+ private static final char NSF23FunctionKey = 0xF71A;
+ private static final char NSF24FunctionKey = 0xF71B;
+ /**
+ private static final char NSF25FunctionKey = 0xF71C;
+ private static final char NSF26FunctionKey = 0xF71D;
+ private static final char NSF27FunctionKey = 0xF71E;
+ private static final char NSF28FunctionKey = 0xF71F;
+ private static final char NSF29FunctionKey = 0xF720;
+ private static final char NSF30FunctionKey = 0xF721;
+ private static final char NSF31FunctionKey = 0xF722;
+ private static final char NSF32FunctionKey = 0xF723;
+ private static final char NSF33FunctionKey = 0xF724;
+ private static final char NSF34FunctionKey = 0xF725;
+ private static final char NSF35FunctionKey = 0xF726;
+ */
+ private static final char NSInsertFunctionKey = 0xF727;
+ private static final char NSDeleteFunctionKey = 0xF728;
+ private static final char NSHomeFunctionKey = 0xF729;
+ private static final char NSBeginFunctionKey = 0xF72A;
+ private static final char NSEndFunctionKey = 0xF72B;
+ private static final char NSPageUpFunctionKey = 0xF72C;
+ private static final char NSPageDownFunctionKey = 0xF72D;
+ private static final char NSPrintScreenFunctionKey = 0xF72E;
+ private static final char NSScrollLockFunctionKey = 0xF72F;
+ private static final char NSPauseFunctionKey = 0xF730;
+ // private static final char NSSysReqFunctionKey = 0xF731;
+ // private static final char NSBreakFunctionKey = 0xF732;
+ // private static final char NSResetFunctionKey = 0xF733;
+ private static final char NSStopFunctionKey = 0xF734;
+ /**
+ private static final char NSMenuFunctionKey = 0xF735;
+ private static final char NSUserFunctionKey = 0xF736;
+ private static final char NSSystemFunctionKey = 0xF737;
+ private static final char NSPrintFunctionKey = 0xF738;
+ private static final char NSClearLineFunctionKey = 0xF739;
+ private static final char NSClearDisplayFunctionKey = 0xF73A;
+ private static final char NSInsertLineFunctionKey = 0xF73B;
+ private static final char NSDeleteLineFunctionKey = 0xF73C;
+ private static final char NSInsertCharFunctionKey = 0xF73D;
+ private static final char NSDeleteCharFunctionKey = 0xF73E;
+ private static final char NSPrevFunctionKey = 0xF73F;
+ private static final char NSNextFunctionKey = 0xF740;
+ private static final char NSSelectFunctionKey = 0xF741;
+ private static final char NSExecuteFunctionKey = 0xF742;
+ private static final char NSUndoFunctionKey = 0xF743;
+ private static final char NSRedoFunctionKey = 0xF744;
+ private static final char NSFindFunctionKey = 0xF745;
+ private static final char NSHelpFunctionKey = 0xF746;
+ private static final char NSModeSwitchFunctionKey = 0xF747;
+ */
+
+ static short validateKeyCode(final short keyCode, final char keyChar) {
+ // OS X Virtual Keycodes
+ switch(keyCode) {
+ //
+ // KeyCodes (Layout Dependent)
+ //
+ case kVK_ANSI_A: return KeyEvent.VK_A;
+ case kVK_ANSI_S: return KeyEvent.VK_S;
+ case kVK_ANSI_D: return KeyEvent.VK_D;
+ case kVK_ANSI_F: return KeyEvent.VK_F;
+ case kVK_ANSI_H: return KeyEvent.VK_H;
+ case kVK_ANSI_G: return KeyEvent.VK_G;
+ case kVK_ANSI_Z: return KeyEvent.VK_Z;
+ case kVK_ANSI_X: return KeyEvent.VK_X;
+ case kVK_ANSI_C: return KeyEvent.VK_C;
+ case kVK_ANSI_V: return KeyEvent.VK_V;
+ case kVK_ANSI_B: return KeyEvent.VK_B;
+ case kVK_ANSI_Q: return KeyEvent.VK_Q;
+ case kVK_ANSI_W: return KeyEvent.VK_W;
+ case kVK_ANSI_E: return KeyEvent.VK_E;
+ case kVK_ANSI_R: return KeyEvent.VK_R;
+ case kVK_ANSI_Y: return KeyEvent.VK_Y;
+ case kVK_ANSI_T: return KeyEvent.VK_T;
+ case kVK_ANSI_1: return KeyEvent.VK_1;
+ case kVK_ANSI_2: return KeyEvent.VK_2;
+ case kVK_ANSI_3: return KeyEvent.VK_3;
+ case kVK_ANSI_4: return KeyEvent.VK_4;
+ case kVK_ANSI_6: return KeyEvent.VK_6;
+ case kVK_ANSI_5: return KeyEvent.VK_5;
+ case kVK_ANSI_Equal: return KeyEvent.VK_EQUALS;
+ case kVK_ANSI_9: return KeyEvent.VK_9;
+ case kVK_ANSI_7: return KeyEvent.VK_7;
+ case kVK_ANSI_Minus: return KeyEvent.VK_MINUS;
+ case kVK_ANSI_8: return KeyEvent.VK_8;
+ case kVK_ANSI_0: return KeyEvent.VK_0;
+ case kVK_ANSI_RightBracket: return KeyEvent.VK_CLOSE_BRACKET;
+ case kVK_ANSI_O: return KeyEvent.VK_O;
+ case kVK_ANSI_U: return KeyEvent.VK_U;
+ case kVK_ANSI_LeftBracket: return KeyEvent.VK_OPEN_BRACKET;
+ case kVK_ANSI_I: return KeyEvent.VK_I;
+ case kVK_ANSI_P: return KeyEvent.VK_P;
+ case kVK_ANSI_L: return KeyEvent.VK_L;
+ case kVK_ANSI_J: return KeyEvent.VK_J;
+ case kVK_ANSI_Quote: return KeyEvent.VK_QUOTE;
+ case kVK_ANSI_K: return KeyEvent.VK_K;
+ case kVK_ANSI_Semicolon: return KeyEvent.VK_SEMICOLON;
+ case kVK_ANSI_Backslash: return KeyEvent.VK_BACK_SLASH;
+ case kVK_ANSI_Comma: return KeyEvent.VK_COMMA;
+ case kVK_ANSI_Slash: return KeyEvent.VK_SLASH;
+ case kVK_ANSI_N: return KeyEvent.VK_N;
+ case kVK_ANSI_M: return KeyEvent.VK_M;
+ case kVK_ANSI_Period: return KeyEvent.VK_PERIOD;
+ case kVK_ANSI_Grave: return KeyEvent.VK_BACK_QUOTE; // KeyEvent.VK_DEAD_GRAVE
+ case kVK_ANSI_KeypadDecimal: return KeyEvent.VK_DECIMAL;
+ case kVK_ANSI_KeypadMultiply: return KeyEvent.VK_MULTIPLY;
+ case kVK_ANSI_KeypadPlus: return KeyEvent.VK_PLUS;
+ case kVK_ANSI_KeypadClear: return KeyEvent.VK_CLEAR;
+ case kVK_ANSI_KeypadDivide: return KeyEvent.VK_DIVIDE;
+ case kVK_ANSI_KeypadEnter: return KeyEvent.VK_ENTER;
+ case kVK_ANSI_KeypadMinus: return KeyEvent.VK_MINUS;
+ case kVK_ANSI_KeypadEquals: return KeyEvent.VK_EQUALS;
+ case kVK_ANSI_Keypad0: return KeyEvent.VK_0;
+ case kVK_ANSI_Keypad1: return KeyEvent.VK_1;
+ case kVK_ANSI_Keypad2: return KeyEvent.VK_2;
+ case kVK_ANSI_Keypad3: return KeyEvent.VK_3;
+ case kVK_ANSI_Keypad4: return KeyEvent.VK_4;
+ case kVK_ANSI_Keypad5: return KeyEvent.VK_5;
+ case kVK_ANSI_Keypad6: return KeyEvent.VK_6;
+ case kVK_ANSI_Keypad7: return KeyEvent.VK_7;
+ case kVK_ANSI_Keypad8: return KeyEvent.VK_8;
+ case kVK_ANSI_Keypad9: return KeyEvent.VK_9;
+
+ //
+ // KeyCodes (Layout Independent)
+ //
+ case kVK_Return: return KeyEvent.VK_ENTER;
+ case kVK_Tab: return KeyEvent.VK_TAB;
+ case kVK_Space: return KeyEvent.VK_SPACE;
+ case kVK_Delete: return KeyEvent.VK_BACK_SPACE;
+ case kVK_Escape: return KeyEvent.VK_ESCAPE;
+ case kVK_Command: return KeyEvent.VK_WINDOWS;
+ case kVK_Shift: return KeyEvent.VK_SHIFT;
+ case kVK_CapsLock: return KeyEvent.VK_CAPS_LOCK;
+ case kVK_Option: return KeyEvent.VK_ALT;
+ case kVK_Control: return KeyEvent.VK_CONTROL;
+ case kVK_RightShift: return KeyEvent.VK_SHIFT;
+ case kVK_RightOption: return KeyEvent.VK_ALT_GRAPH;
+ case kVK_RightControl: return KeyEvent.VK_CONTROL;
+ // case kVK_Function: return KeyEvent.VK_F;
+ case kVK_F17: return KeyEvent.VK_F17;
+ // case kVK_VolumeUp:
+ // case kVK_VolumeDown:
+ // case kVK_Mute:
+ case kVK_F18: return KeyEvent.VK_F18;
+ case kVK_F19: return KeyEvent.VK_F19;
+ case kVK_F20: return KeyEvent.VK_F20;
+ case kVK_F5: return KeyEvent.VK_F5;
+ case kVK_F6: return KeyEvent.VK_F6;
+ case kVK_F7: return KeyEvent.VK_F7;
+ case kVK_F3: return KeyEvent.VK_F3;
+ case kVK_F8: return KeyEvent.VK_F8;
+ case kVK_F9: return KeyEvent.VK_F9;
+ case kVK_F11: return KeyEvent.VK_F11;
+ case kVK_F13: return KeyEvent.VK_F13;
+ case kVK_F16: return KeyEvent.VK_F16;
+ case kVK_F14: return KeyEvent.VK_F14;
+ case kVK_F10: return KeyEvent.VK_F10;
+ case kVK_F12: return KeyEvent.VK_F12;
+ case kVK_F15: return KeyEvent.VK_F15;
+ case kVK_Help: return KeyEvent.VK_HELP;
+ case kVK_Home: return KeyEvent.VK_HOME;
+ case kVK_PageUp: return KeyEvent.VK_PAGE_UP;
+ case kVK_ForwardDelete: return KeyEvent.VK_DELETE;
+ case kVK_F4: return KeyEvent.VK_F4;
+ case kVK_End: return KeyEvent.VK_END;
+ case kVK_F2: return KeyEvent.VK_F2;
+ case kVK_PageDown: return KeyEvent.VK_PAGE_DOWN;
+ case kVK_F1: return KeyEvent.VK_F1;
+ case kVK_LeftArrow: return KeyEvent.VK_LEFT;
+ case kVK_RightArrow: return KeyEvent.VK_RIGHT;
+ case kVK_DownArrow: return KeyEvent.VK_DOWN;
+ case kVK_UpArrow: return KeyEvent.VK_UP;
+ }
+
+ switch (keyChar) {
+ case NSUpArrowFunctionKey: return KeyEvent.VK_UP;
+ case NSDownArrowFunctionKey: return KeyEvent.VK_DOWN;
+ case NSLeftArrowFunctionKey: return KeyEvent.VK_LEFT;
+ case NSRightArrowFunctionKey: return KeyEvent.VK_RIGHT;
+ case NSF1FunctionKey: return KeyEvent.VK_F1;
+ case NSF2FunctionKey: return KeyEvent.VK_F2;
+ case NSF3FunctionKey: return KeyEvent.VK_F3;
+ case NSF4FunctionKey: return KeyEvent.VK_F4;
+ case NSF5FunctionKey: return KeyEvent.VK_F5;
+ case NSF6FunctionKey: return KeyEvent.VK_F6;
+ case NSF7FunctionKey: return KeyEvent.VK_F7;
+ case NSF8FunctionKey: return KeyEvent.VK_F8;
+ case NSF9FunctionKey: return KeyEvent.VK_F9;
+ case NSF10FunctionKey: return KeyEvent.VK_F10;
+ case NSF11FunctionKey: return KeyEvent.VK_F11;
+ case NSF12FunctionKey: return KeyEvent.VK_F12;
+ case NSF13FunctionKey: return KeyEvent.VK_F13;
+ case NSF14FunctionKey: return KeyEvent.VK_F14;
+ case NSF15FunctionKey: return KeyEvent.VK_F15;
+ case NSF16FunctionKey: return KeyEvent.VK_F16;
+ case NSF17FunctionKey: return KeyEvent.VK_F17;
+ case NSF18FunctionKey: return KeyEvent.VK_F18;
+ case NSF19FunctionKey: return KeyEvent.VK_F19;
+ case NSF20FunctionKey: return KeyEvent.VK_F20;
+ case NSF21FunctionKey: return KeyEvent.VK_F21;
+ case NSF22FunctionKey: return KeyEvent.VK_F22;
+ case NSF23FunctionKey: return KeyEvent.VK_F23;
+ case NSF24FunctionKey: return KeyEvent.VK_F24;
+ case NSInsertFunctionKey: return KeyEvent.VK_INSERT;
+ case NSDeleteFunctionKey: return KeyEvent.VK_DELETE;
+ case NSHomeFunctionKey: return KeyEvent.VK_HOME;
+ case NSBeginFunctionKey: return KeyEvent.VK_BEGIN;
+ case NSEndFunctionKey: return KeyEvent.VK_END;
+ case NSPageUpFunctionKey: return KeyEvent.VK_PAGE_UP;
+ case NSPageDownFunctionKey: return KeyEvent.VK_PAGE_DOWN;
+ case NSPrintScreenFunctionKey: return KeyEvent.VK_PRINTSCREEN;
+ case NSScrollLockFunctionKey: return KeyEvent.VK_SCROLL_LOCK;
+ case NSPauseFunctionKey: return KeyEvent.VK_PAUSE;
+ // Not handled:
+ // NSSysReqFunctionKey
+ // NSBreakFunctionKey
+ // NSResetFunctionKey
+ case NSStopFunctionKey: return KeyEvent.VK_STOP;
+ // Not handled:
+ // NSMenuFunctionKey
+ // NSUserFunctionKey
+ // NSSystemFunctionKey
+ // NSPrintFunctionKey
+ // NSClearLineFunctionKey
+ // NSClearDisplayFunctionKey
+ // NSInsertLineFunctionKey
+ // NSDeleteLineFunctionKey
+ // NSInsertCharFunctionKey
+ // NSDeleteCharFunctionKey
+ // NSPrevFunctionKey
+ // NSNextFunctionKey
+ // NSSelectFunctionKey
+ // NSExecuteFunctionKey
+ // NSUndoFunctionKey
+ // NSRedoFunctionKey
+ // NSFindFunctionKey
+ // NSHelpFunctionKey
+ // NSModeSwitchFunctionKey
+ }
+
+ return (short) keyChar; // let's hope for the best (compatibility of keyChar/keyCode's)
+ }
+}
diff --git a/src/newt/classes/jogamp/newt/driver/ios/ScreenDriver.java b/src/newt/classes/jogamp/newt/driver/ios/ScreenDriver.java
new file mode 100644
index 000000000..47280865d
--- /dev/null
+++ b/src/newt/classes/jogamp/newt/driver/ios/ScreenDriver.java
@@ -0,0 +1,225 @@
+/**
+ * Copyright 2019 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package jogamp.newt.driver.ios;
+
+import com.jogamp.nativewindow.DefaultGraphicsScreen;
+import com.jogamp.nativewindow.util.Rectangle;
+
+import jogamp.nativewindow.ios.IOSUtil;
+import jogamp.newt.MonitorModeProps;
+import jogamp.newt.ScreenImpl;
+
+import com.jogamp.common.util.ArrayHashSet;
+import com.jogamp.newt.Display;
+import com.jogamp.newt.MonitorDevice;
+import com.jogamp.newt.MonitorMode;
+import com.jogamp.opengl.math.FloatUtil;
+
+public class ScreenDriver extends ScreenImpl {
+
+ static {
+ DisplayDriver.initSingleton();
+ }
+
+ public ScreenDriver() {
+ }
+
+ @Override
+ protected void createNativeImpl() {
+ aScreen = new DefaultGraphicsScreen(getDisplay().getGraphicsDevice(), screen_idx);
+ }
+
+ @Override
+ protected void closeNativeImpl() { }
+
+ private MonitorMode getMonitorModeImpl(final MonitorModeProps.Cache cache, final int crt_id, final int mode_idx) {
+ final int[] modeProps = getMonitorMode0(crt_id, mode_idx);
+ final MonitorMode res;
+ if (null == modeProps || 0 >= modeProps.length) {
+ res = null;
+ } else {
+ res = MonitorModeProps.streamInMonitorMode(null, cache, modeProps, 0);
+ }
+ return res;
+ }
+
+ class CrtProps {
+ CrtProps() {
+ crtIDs = getMonitorDeviceIds0();
+ count = crtIDs.length;
+ pixelScaleArray = new float[count];
+ propsOrigArray = new int[count][];
+ propsFixedArray = new int[count][];
+
+ //
+ // Gather whole topology of monitors (NSScreens)
+ //
+ for(int crtIdx=0; crtIdx<count; crtIdx++) {
+ final int crt_id = crtIDs[crtIdx];
+ final float pixelScaleRaw = (float)IOSUtil.GetPixelScaleByDisplayID(crt_id);
+ pixelScaleArray[crtIdx] = FloatUtil.isZero(pixelScaleRaw, FloatUtil.EPSILON) ? 1.0f : pixelScaleRaw;
+ propsOrigArray[crtIdx] = getMonitorProps0(crt_id);
+ if ( null == propsOrigArray[crtIdx] ) {
+ throw new InternalError("Could not gather device props "+crtIdx+"/"+count+" -> "+Display.toHexString(crt_id));
+ }
+ // copy orig -> fixed
+ final int propsLen = propsOrigArray[crtIdx].length;
+ propsFixedArray[crtIdx] = new int[propsLen];
+ System.arraycopy(propsOrigArray[crtIdx], 0, propsFixedArray[crtIdx], 0, propsLen);
+ }
+
+ //
+ // Fix scaled viewport w/ pixelScale of each monitorProps,
+ // i.e. size by its own pixelScale and x/y offset by querying it's neighbors.
+ //
+ for(int crtIdx=0; crtIdx<count; crtIdx++) {
+ final int[] thisMonitorProps = propsFixedArray[crtIdx];
+ final int x = thisMonitorProps[MonitorModeProps.IDX_MONITOR_DEVICE_VIEWPORT+0];
+ final int y = thisMonitorProps[MonitorModeProps.IDX_MONITOR_DEVICE_VIEWPORT+1];
+ final float thisPixelScale = pixelScaleArray[crtIdx];
+ thisMonitorProps[MonitorModeProps.IDX_MONITOR_DEVICE_VIEWPORT+2] *= thisPixelScale; // fix width
+ thisMonitorProps[MonitorModeProps.IDX_MONITOR_DEVICE_VIEWPORT+3] *= thisPixelScale; // fix height
+ if( 0 != x ) {
+ // find matching viewport width for x-offset to apply it's pixelSize
+ for(int i=0; i<count; i++) {
+ if( i != crtIdx && x == propsOrigArray[i][MonitorModeProps.IDX_MONITOR_DEVICE_VIEWPORT+2] ) {
+ thisMonitorProps[MonitorModeProps.IDX_MONITOR_DEVICE_VIEWPORT+0] *= pixelScaleArray[i];
+ break;
+ }
+ }
+ }
+ if( 0 != y ) {
+ // find matching viewport height for y-offset to apply it's pixelSize
+ for(int i=0; i<count; i++) {
+ if( i != crtIdx && y == propsOrigArray[i][MonitorModeProps.IDX_MONITOR_DEVICE_VIEWPORT+3] ) {
+ thisMonitorProps[MonitorModeProps.IDX_MONITOR_DEVICE_VIEWPORT+1] *= pixelScaleArray[i];
+ break;
+ }
+ }
+ }
+ }
+ }
+ int getIndex(final int crt_id) {
+ for(int i=0; i<count; i++) {
+ if( crt_id == crtIDs[i] ) {
+ return i;
+ }
+ }
+ return -1;
+ }
+ final int count;
+ final int[] crtIDs;
+ final float[] pixelScaleArray;
+ final int[][] propsOrigArray;
+ final int[][] propsFixedArray;
+ }
+
+ @Override
+ protected final void collectNativeMonitorModesAndDevicesImpl(final MonitorModeProps.Cache cache) {
+ final CrtProps crtProps = new CrtProps();
+
+ //
+ // Collect all monitorModes for all monitorDevices
+ //
+ for(int crtIdx=0; crtIdx<crtProps.count; crtIdx++) {
+ final int crt_id = crtProps.crtIDs[crtIdx];
+ final ArrayHashSet<MonitorMode> supportedModes =
+ new ArrayHashSet<MonitorMode>(false, ArrayHashSet.DEFAULT_INITIAL_CAPACITY, ArrayHashSet.DEFAULT_LOAD_FACTOR);
+ int modeIdx = 0;
+ {
+ // Get all supported modes for this monitorDevice
+ MonitorMode mode;
+ while( true ) {
+ mode = getMonitorModeImpl(cache, crt_id, modeIdx);
+ if( null != mode ) {
+ if( mode.getSurfaceSize().getBitsPerPixel() >= 24 ) { // drop otherwise
+ supportedModes.getOrAdd(mode);
+ }
+ modeIdx++; // next mode on same monitor
+ } else {
+ break; // done with modes on this monitor
+ }
+ }
+ }
+ if( 0 >= modeIdx ) {
+ throw new InternalError("Could not gather single mode of device "+crtIdx+"/"+crtProps.count+" -> "+Display.toHexString(crt_id));
+ }
+ final MonitorMode currentMode = getMonitorModeImpl(cache, crt_id, -1);
+ if ( null == currentMode ) {
+ throw new InternalError("Could not gather current mode of device "+crtIdx+"/"+crtProps.count+" -> "+Display.toHexString(crt_id)+", but gathered "+modeIdx+" modes");
+ }
+ // merge monitor-props + supported modes
+ final float pixelScale = crtProps.pixelScaleArray[crtIdx];
+ MonitorModeProps.streamInMonitorDevice(cache, this, currentMode,
+ new float[] { pixelScale, pixelScale },
+ supportedModes, crtProps.propsFixedArray[crtIdx], 0, null);
+ }
+ }
+
+ @Override
+ protected boolean updateNativeMonitorDeviceViewportImpl(final MonitorDevice monitor, final float[] pixelScale, final Rectangle viewportPU, final Rectangle viewportWU) {
+ final CrtProps crtProps = new CrtProps();
+ final int crt_id = monitor.getId();
+ if( 0 == crt_id ) {
+ throw new IllegalArgumentException("Invalid monitor id "+Display.toHexString(crt_id));
+ }
+ final int crt_idx = crtProps.getIndex(crt_id);
+ if( 0 > crt_idx || crt_idx >= crtProps.count ) {
+ throw new IndexOutOfBoundsException("monitor id "+crt_idx+" not within [0.."+(crtProps.count-1)+"]");
+ }
+ final int[] fixedMonitorProps = crtProps.propsFixedArray[crt_idx];
+ int offset = MonitorModeProps.IDX_MONITOR_DEVICE_VIEWPORT;
+ viewportPU.set(fixedMonitorProps[offset++], fixedMonitorProps[offset++], fixedMonitorProps[offset++], fixedMonitorProps[offset++]);
+ viewportWU.set(fixedMonitorProps[offset++], fixedMonitorProps[offset++], fixedMonitorProps[offset++], fixedMonitorProps[offset++]);
+ final float _pixelScale = crtProps.pixelScaleArray[crt_idx];
+ pixelScale[0] = _pixelScale;
+ pixelScale[1] = _pixelScale;
+ return true;
+ }
+
+ @Override
+ protected MonitorMode queryCurrentMonitorModeImpl(final MonitorDevice monitor) {
+ return getMonitorModeImpl(null, monitor.getId(), -1);
+ }
+
+ @Override
+ protected boolean setCurrentMonitorModeImpl(final MonitorDevice monitor, final MonitorMode mode) {
+ return setMonitorMode0(monitor.getId(), mode.getId(), mode.getRotation());
+ }
+
+ @Override
+ protected int validateScreenIndex(final int idx) {
+ return 0; // big-desktop w/ multiple monitor attached, only one screen available
+ }
+
+ private native int[] getMonitorDeviceIds0();
+ private native int[] getMonitorProps0(int crt_id);
+ private native int[] getMonitorMode0(int crt_id, int mode_idx);
+ private native boolean setMonitorMode0(int crt_id, int nativeId, int rot);
+}
diff --git a/src/newt/classes/jogamp/newt/driver/ios/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/ios/WindowDriver.java
new file mode 100644
index 000000000..2a257436a
--- /dev/null
+++ b/src/newt/classes/jogamp/newt/driver/ios/WindowDriver.java
@@ -0,0 +1,812 @@
+/**
+ * Copyright 2019 JogAmp Community. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are
+ * permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list
+ * of conditions and the following disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are those of the
+ * authors and should not be interpreted as representing official policies, either expressed
+ * or implied, of JogAmp Community.
+ */
+
+package jogamp.newt.driver.ios;
+
+import com.jogamp.common.util.InterruptSource;
+import com.jogamp.nativewindow.AbstractGraphicsConfiguration;
+import com.jogamp.nativewindow.GraphicsConfigurationFactory;
+import com.jogamp.nativewindow.NativeWindow;
+import com.jogamp.nativewindow.NativeWindowException;
+import com.jogamp.nativewindow.MutableSurface;
+import com.jogamp.nativewindow.ScalableSurface;
+import com.jogamp.nativewindow.VisualIDHolder;
+import com.jogamp.nativewindow.util.Point;
+import com.jogamp.nativewindow.util.PointImmutable;
+
+import jogamp.nativewindow.SurfaceScaleUtils;
+import jogamp.nativewindow.ios.IOSUtil;
+import jogamp.newt.ScreenImpl;
+import jogamp.newt.WindowImpl;
+import jogamp.newt.driver.DriverClearFocus;
+import jogamp.newt.driver.DriverUpdatePosition;
+
+import com.jogamp.newt.event.InputEvent;
+import com.jogamp.newt.event.KeyEvent;
+import com.jogamp.newt.event.MonitorEvent;
+import com.jogamp.opengl.math.FloatUtil;
+
+public class WindowDriver extends WindowImpl implements MutableSurface, DriverClearFocus, DriverUpdatePosition {
+
+ static {
+ DisplayDriver.initSingleton();
+ }
+
+ public WindowDriver() {
+ }
+
+ private boolean updatePixelScale(final boolean sendEvent, final boolean defer, final boolean deferOffThread,
+ final float newPixelScaleRaw, final float maxPixelScaleRaw) {
+ final float[] newPixelScale = new float[2];
+ {
+ final float _newPixelScale = FloatUtil.isZero(newPixelScaleRaw, FloatUtil.EPSILON) ? ScalableSurface.IDENTITY_PIXELSCALE : newPixelScaleRaw;
+ newPixelScale[0]= _newPixelScale;
+ newPixelScale[1]= _newPixelScale;
+ final float _maxPixelScale = FloatUtil.isZero(maxPixelScaleRaw, FloatUtil.EPSILON) ? ScalableSurface.IDENTITY_PIXELSCALE : maxPixelScaleRaw;
+ maxPixelScale[0]= _maxPixelScale;
+ maxPixelScale[1]= _maxPixelScale;
+ }
+ // We keep minPixelScale at [1f, 1f]!
+
+ if( SurfaceScaleUtils.setNewPixelScale(hasPixelScale, hasPixelScale, newPixelScale, minPixelScale, maxPixelScale, DEBUG_IMPLEMENTATION ? getClass().getName() : null) ) {
+ if( sendEvent ) {
+ if( deferOffThread ) {
+ superSizeChangedOffThread(defer, getWidth(), getHeight(), true);
+ } else {
+ super.sizeChanged(defer, getWidth(), getHeight(), true);
+ }
+ } else {
+ defineSize(getWidth(), getHeight());
+ }
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ private boolean updatePixelScaleByDisplayID(final boolean sendEvent) {
+ final float maxPixelScaleRaw = (float) IOSUtil.GetPixelScaleByDisplayID(getDisplayID());
+ if( DEBUG_IMPLEMENTATION ) {
+ System.err.println("WindowDriver.updatePixelScale.1: "+hasPixelScale[0]+", "+maxPixelScaleRaw+" (max)");
+ }
+ return updatePixelScale(sendEvent, true /* defer */, false /*offthread */, maxPixelScaleRaw, maxPixelScaleRaw);
+ }
+
+ private boolean updatePixelScaleByWindowHandle(final boolean sendEvent) {
+ final long handle = getWindowHandle();
+ if( 0 != handle ) {
+ final float maxPixelScaleRaw = (float)IOSUtil.GetPixelScale(handle);
+ if( DEBUG_IMPLEMENTATION ) {
+ System.err.println("WindowDriver.updatePixelScale.2: "+hasPixelScale[0]+", "+maxPixelScaleRaw+" (max)");
+ }
+ return updatePixelScale(sendEvent, true /* defer */, false /*offthread */, maxPixelScaleRaw, maxPixelScaleRaw);
+ } else {
+ return false;
+ }
+ }
+
+ /** Called from native code */
+ protected void updatePixelScale(final boolean defer, final float newPixelScaleRaw, final float maxPixelScaleRaw) {
+ if( DEBUG_IMPLEMENTATION ) {
+ System.err.println("WindowDriver.updatePixelScale.3: "+hasPixelScale[0]+" (has) -> "+newPixelScaleRaw+" (new), "+maxPixelScaleRaw+" (max), drop "+!isNativeValid());
+ }
+ if( isNativeValid() ) {
+ updatePixelScale(true /* sendEvent*/, defer, true /*offthread */, newPixelScaleRaw, maxPixelScaleRaw);
+ }
+ }
+
+ @Override
+ protected final void instantiationFinishedImpl() {
+ updatePixelScaleByDisplayID(false /* sendEvent*/);
+ }
+
+ @Override
+ protected void setScreen(final ScreenImpl newScreen) { // never null !
+ super.setScreen(newScreen);
+ updatePixelScaleByDisplayID(false /* sendEvent*/); // caller (reparent, ..) will send reshape event
+ }
+
+ @Override
+ protected void monitorModeChanged(final MonitorEvent me, final boolean success) {
+ updatePixelScaleByWindowHandle(false /* sendEvent*/); // send reshape event itself
+ }
+
+ @Override
+ public final boolean setSurfaceScale(final float[] pixelScale) {
+ super.setSurfaceScale(pixelScale);
+
+ boolean changed = false;
+ if( isNativeValid() ) {
+ if( isOffscreenInstance ) {
+ final NativeWindow pWin = getParent();
+ if( pWin instanceof ScalableSurface ) {
+ final ScalableSurface sSurf = (ScalableSurface)pWin;
+ sSurf.setSurfaceScale(reqPixelScale);
+ sSurf.getMaximumSurfaceScale(maxPixelScale);
+ sSurf.getMinimumSurfaceScale(minPixelScale);
+ final float[] pPixelScale = sSurf.getCurrentSurfaceScale(new float[2]);
+ changed = updatePixelScale(true /* sendEvent */, true /* defer */, true /*offthread */, pPixelScale[0], maxPixelScale[0]); // HiDPI: uniformPixelScale
+ } else {
+ // just notify updated pixelScale if offscreen
+ changed = updatePixelScale(true /* sendEvent */, true /* defer */, true /*offthread */, reqPixelScale[0], maxPixelScale[0]); // HiDPI: uniformPixelScale
+ }
+ } else {
+ // set pixelScale in native code, will issue an update updatePixelScale(..)
+ // hence we pre-query whether pixel-scale will change, without affecting current state 'hasPixelScale'!
+ final float[] _hasPixelScale = new float[2];
+ System.arraycopy(hasPixelScale, 0, _hasPixelScale, 0, 2);
+ if( SurfaceScaleUtils.setNewPixelScale(_hasPixelScale, _hasPixelScale, reqPixelScale, minPixelScale, maxPixelScale, DEBUG_IMPLEMENTATION ? getClass().getName() : null) ) {
+ IOSUtil.RunOnMainThread(true, false, new Runnable() {
+ @Override
+ public void run() {
+ setPixelScale0(getWindowHandle(), surfaceHandle, _hasPixelScale[0]); // HiDPI: uniformPixelScale
+ }
+ } );
+ changed = true;
+ }
+ }
+ }
+ if( DEBUG_IMPLEMENTATION ) {
+ System.err.println("WindowDriver.setPixelScale: min["+minPixelScale[0]+", "+minPixelScale[1]+"], max["+
+ maxPixelScale[0]+", "+maxPixelScale[1]+"], req["+
+ reqPixelScale[0]+", "+reqPixelScale[1]+"] -> result["+
+ hasPixelScale[0]+", "+hasPixelScale[1]+"] - changed "+changed+", realized "+isNativeValid());
+ }
+ return changed;
+ }
+
+ @Override
+ protected void createNativeImpl() {
+ final AbstractGraphicsConfiguration cfg = GraphicsConfigurationFactory.getFactory(getScreen().getDisplay().getGraphicsDevice(), capsRequested).chooseGraphicsConfiguration(
+ capsRequested, capsRequested, capabilitiesChooser, getScreen().getGraphicsScreen(), VisualIDHolder.VID_UNDEFINED);
+ if (null == cfg) {
+ throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this);
+ }
+ setGraphicsConfiguration(cfg);
+ reconfigureWindowImpl(getX(), getY(), getWidth(), getHeight(), getReconfigureMask(CHANGE_MASK_VISIBILITY, true));
+ if ( !isNativeValid() ) {
+ throw new NativeWindowException("Error creating window");
+ }
+ }
+
+ @Override
+ protected void closeNativeImpl() {
+ try {
+ if(DEBUG_IMPLEMENTATION) { System.err.println("MacWindow.CloseAction "+Thread.currentThread().getName()); }
+ final long handle = getWindowHandle();
+ visibleChanged(true, false);
+ setWindowHandle(0);
+ surfaceHandle = 0;
+ sscSurfaceHandle = 0;
+ isOffscreenInstance = false;
+ resizeAnimatorPaused = false;
+ if (0 != handle) {
+ IOSUtil.RunOnMainThread(false, true /* kickNSApp */, new Runnable() {
+ @Override
+ public void run() {
+ close0( handle );
+ } });
+ }
+ } catch (final Throwable t) {
+ if(DEBUG_IMPLEMENTATION) {
+ final Exception e = new Exception("Warning: closeNative failed - "+Thread.currentThread().getName(), t);
+ e.printStackTrace();
+ }
+ }
+ }
+
+ @Override
+ protected int lockSurfaceImpl() {
+ /**
+ * if( isOffscreenInstance ) {
+ * return LOCK_SUCCESS;
+ * }
+ */
+ final long w = getWindowHandle();
+ final long v = surfaceHandle;
+ if( 0 != v && 0 != w ) {
+ return lockSurface0(w, v) ? LOCK_SUCCESS : LOCK_SURFACE_NOT_READY;
+ }
+ return LOCK_SURFACE_NOT_READY;
+ }
+
+ @Override
+ protected void unlockSurfaceImpl() {
+ /**
+ * if( isOffscreenInstance ) {
+ * return;
+ * }
+ */
+ final long w = getWindowHandle();
+ final long v = surfaceHandle;
+ if(0 != w && 0 != v) {
+ if( !unlockSurface0(w, v) ) {
+ throw new NativeWindowException("Failed to unlock surface, probably not locked!");
+ }
+ }
+ }
+
+ @Override
+ public final long getSurfaceHandle() {
+ return 0 != sscSurfaceHandle ? sscSurfaceHandle : surfaceHandle;
+ }
+
+ @Override
+ public void setSurfaceHandle(final long surfaceHandle) {
+ if(DEBUG_IMPLEMENTATION) {
+ System.err.println("MacWindow.setSurfaceHandle(): 0x"+Long.toHexString(surfaceHandle));
+ }
+ sscSurfaceHandle = surfaceHandle;
+ if ( isNativeValid() ) {
+ if (0 != sscSurfaceHandle) {
+ IOSUtil.RunOnMainThread(false, false, new Runnable() {
+ @Override
+ public void run() {
+ orderOut0( 0 != getParentWindowHandle() ? getParentWindowHandle() : getWindowHandle() );
+ } } );
+ } /** this is done by recreation!
+ else if (isVisible()){
+ IOSUtil.RunOnMainThread(false, new Runnable() {
+ public void run() {
+ orderFront0( 0!=getParentWindowHandle() ? getParentWindowHandle() : getWindowHandle() );
+ } } );
+ } */
+ }
+ }
+
+ @Override
+ protected void setTitleImpl(final String title) {
+ IOSUtil.RunOnMainThread(false, false, new Runnable() {
+ @Override
+ public void run() {
+ setTitle0(getWindowHandle(), title);
+ } } );
+ }
+
+ @Override
+ protected void requestFocusImpl(final boolean force) {
+ final boolean _isFullscreen = isFullscreen();
+ final boolean _isOffscreenInstance = isOffscreenInstance;
+ if(DEBUG_IMPLEMENTATION) {
+ System.err.println("MacWindow: requestFocusImpl(), isOffscreenInstance "+_isOffscreenInstance+", isFullscreen "+_isFullscreen);
+ }
+ if(!_isOffscreenInstance) {
+ IOSUtil.RunOnMainThread(false, false, new Runnable() {
+ @Override
+ public void run() {
+ requestFocus0(getWindowHandle(), force);
+ if(_isFullscreen) {
+ // 'NewtMacWindow::windowDidBecomeKey()' is not always called in fullscreen-mode!
+ focusChanged(false, true);
+ }
+ } } );
+ } else {
+ focusChanged(false, true);
+ }
+ }
+
+ @Override
+ public final void clearFocus() {
+ if(DEBUG_IMPLEMENTATION) {
+ System.err.println("MacWindow: clearFocus(), isOffscreenInstance "+isOffscreenInstance);
+ }
+ if(!isOffscreenInstance) {
+ IOSUtil.RunOnMainThread(false, false, new Runnable() {
+ @Override
+ public void run() {
+ resignFocus0(getWindowHandle());
+ } } );
+ } else {
+ focusChanged(false, false);
+ }
+ }
+
+ private boolean useParent(final NativeWindow parent) { return null != parent && 0 != parent.getWindowHandle(); }
+
+ @Override
+ public void updatePosition(final int x, final int y) {
+ final long handle = getWindowHandle();
+ if( 0 != handle && !isOffscreenInstance ) {
+ final NativeWindow parent = getParent();
+ final boolean useParent = useParent(parent);
+ final Point p0S;
+ if( useParent ) {
+ p0S = getLocationOnScreenByParent(x, y, parent);
+ } else {
+ p0S = (Point) getLocationOnScreen0(handle, x, y);
+ }
+ if(DEBUG_IMPLEMENTATION) {
+ final int pX=parent.getX(), pY=parent.getY();
+ System.err.println("MacWindow: updatePosition() parent["+useParent+" "+pX+"/"+pY+"] "+x+"/"+y+" -> "+x+"/"+y+" rel-client-pos, "+p0S+" screen-client-pos");
+ }
+ IOSUtil.RunOnMainThread(false, false, new Runnable() {
+ @Override
+ public void run() {
+ setWindowClientTopLeftPoint0(getWindowHandle(), p0S.getX(), p0S.getY(), isVisible());
+ } } );
+ // no native event (fullscreen, some reparenting)
+ positionChanged(true, x, y);
+ }
+ }
+
+ @Override
+ protected final int getSupportedReconfigMaskImpl() {
+ return minimumReconfigStateMask |
+ STATE_MASK_CHILDWIN |
+ STATE_MASK_UNDECORATED |
+ STATE_MASK_ALWAYSONTOP |
+ STATE_MASK_ALWAYSONBOTTOM |
+ STATE_MASK_STICKY |
+ STATE_MASK_RESIZABLE |
+ STATE_MASK_MAXIMIZED_VERT |
+ STATE_MASK_MAXIMIZED_HORZ |
+ STATE_MASK_POINTERVISIBLE |
+ STATE_MASK_POINTERCONFINED;
+ }
+
+ @Override
+ protected boolean reconfigureWindowImpl(int _x, int _y, int _width, int _height, final int flags) {
+ final boolean _isOffscreenInstance = isOffscreenInstance(this, this.getParent());
+ isOffscreenInstance = 0 != sscSurfaceHandle || _isOffscreenInstance;
+ final PointImmutable pClientLevelOnSreen;
+ if( isOffscreenInstance ) {
+ _x = 0; _y = 0;
+ pClientLevelOnSreen = new Point(0, 0);
+ } else {
+ final NativeWindow parent = getParent();
+ if( useParent(parent) ) {
+ pClientLevelOnSreen = getLocationOnScreenByParent(_x, _y, parent);
+ } else {
+ if( 0 != ( ( CHANGE_MASK_MAXIMIZED_HORZ | CHANGE_MASK_MAXIMIZED_VERT ) & flags ) ) {
+ final int[] posSize = { _x, _y, _width, _height };
+ reconfigMaximizedManual(flags, posSize, getInsets());
+ _x = posSize[0];
+ _y = posSize[1];
+ _width = posSize[2];
+ _height = posSize[3];
+ }
+ pClientLevelOnSreen = new Point(_x, _y);
+ }
+ }
+ final int x=_x, y=_y;
+ final int width=_width, height=_height;
+
+ final boolean hasFocus = hasFocus();
+
+ 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.0: "+x+"/"+y+" -> clientPosOnScreen "+pClientLevelOnSreen+" - "+width+"x"+height+
+ ", "+getReconfigStateMaskString(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);
+ // Thread.dumpStack();
+ }
+
+ if( 0 != ( CHANGE_MASK_VISIBILITY & flags) &&
+ 0 == ( STATE_MASK_VISIBLE & flags) )
+ {
+ if ( !isOffscreenInstance ) {
+ IOSUtil.RunOnMainThread(false, false, new Runnable() {
+ @Override
+ public void run() {
+ orderOut0(getWindowHandle());
+ visibleChanged(true, false);
+ } } );
+ } else {
+ visibleChanged(true, false);
+ }
+ }
+ final long oldWindowHandle = getWindowHandle();
+ if( ( 0 == oldWindowHandle && 0 != ( STATE_MASK_VISIBLE & flags) ) ||
+ 0 != ( CHANGE_MASK_PARENTING & flags) ||
+ 0 != ( CHANGE_MASK_DECORATION & flags) ||
+ 0 != ( CHANGE_MASK_ALWAYSONTOP & flags) ||
+ 0 != ( CHANGE_MASK_ALWAYSONBOTTOM & flags) ||
+ 0 != ( CHANGE_MASK_RESIZABLE & flags) ||
+ 0 != ( CHANGE_MASK_FULLSCREEN & flags) ) {
+ if(isOffscreenInstance) {
+ createWindow(true, 0 != oldWindowHandle, pClientLevelOnSreen, 64, 64, flags);
+ } else {
+ createWindow(false, 0 != oldWindowHandle, pClientLevelOnSreen, width, height, flags);
+ }
+ // no native event (fullscreen, some reparenting)
+ updatePixelScaleByWindowHandle(false /* sendEvent */);
+ if( isOffscreenInstance) {
+ super.sizeChanged(false, width, height, true);
+ positionChanged(false, x, y);
+ } else {
+ updateSizePosInsets0(getWindowHandle(), false);
+ }
+ visibleChanged(false, 0 != ( STATE_MASK_VISIBLE & flags));
+ if( hasFocus ) {
+ requestFocusImpl(true);
+ }
+ } else if( 0 != oldWindowHandle ) {
+ if( width>0 && height>0 ) {
+ if( !isOffscreenInstance ) {
+ IOSUtil.RunOnMainThread(true, false, new Runnable() {
+ @Override
+ public void run() {
+ setWindowClientTopLeftPointAndSize0(oldWindowHandle,
+ pClientLevelOnSreen.getX(), pClientLevelOnSreen.getY(),
+ width, height, 0 != ( STATE_MASK_VISIBLE & flags));
+ } } );
+ updateSizePosInsets0(oldWindowHandle, false);
+ } else { // else offscreen size is realized via recreation
+ // no native event (fullscreen, some reparenting)
+ super.sizeChanged(false, width, height, false);
+ positionChanged(false, x, y);
+ }
+ }
+ if( 0 != ( CHANGE_MASK_VISIBILITY & flags) &&
+ 0 != ( STATE_MASK_VISIBLE & flags) )
+ {
+ if( !isOffscreenInstance ) {
+ IOSUtil.RunOnMainThread(false, false, new Runnable() {
+ @Override
+ public void run() {
+ orderFront0(getWindowHandle());
+ visibleChanged(true, true);
+ } } );
+ } else {
+ visibleChanged(true, true);
+ }
+ }
+ } else {
+ throw new InternalError("Null windowHandle but no re-creation triggered, check visibility: "+getStateMaskString());
+ }
+ if(DEBUG_IMPLEMENTATION) {
+ System.err.println("MacWindow reconfig.X: "+getLocationOnScreenImpl(0, 0)+" "+getWidth()+"x"+getHeight()+", insets "+getInsets()+", "+getStateMaskString());
+ }
+ return true;
+ }
+
+ @Override
+ protected Point getLocationOnScreenImpl(final int x, final int y) {
+ final NativeWindow parent = getParent();
+ if( useParent(parent) ) {
+ return getLocationOnScreenByParent(x, y, parent);
+ } else {
+ final long windowHandle = getWindowHandle();
+ if( !isOffscreenInstance && 0 != windowHandle ) {
+ return (Point) getLocationOnScreen0(windowHandle, x, y);
+ } else {
+ return new Point(x, y);
+ }
+ }
+ }
+
+ private Point getLocationOnScreenByParent(final int x, final int y, final NativeWindow parent) {
+ return new Point(x, y).translate( parent.getLocationOnScreen(null) );
+ }
+
+ /** Callback for native screen position change event of the client area. */
+ protected void screenPositionChanged(final boolean defer, final int newX, final int newY) {
+ // passed coordinates are in screen position of the client area
+ if( isNativeValid() ) {
+ final NativeWindow parent = getParent();
+ if( !useParent(parent) || isOffscreenInstance ) {
+ if(DEBUG_IMPLEMENTATION) {
+ System.err.println("MacWindow.positionChanged.0 (Screen Pos - TOP): ("+getThreadName()+"): (defer: "+defer+") "+getX()+"/"+getY()+" -> "+newX+"/"+newY);
+ }
+ positionChanged(defer, newX, newY);
+ } else {
+ final Runnable action = new Runnable() {
+ public void run() {
+ // screen position -> rel child window position
+ final Point absPos = new Point(newX, newY);
+ final Point parentOnScreen = parent.getLocationOnScreen(null);
+ absPos.translate( parentOnScreen.scale(-1, -1) );
+ if(DEBUG_IMPLEMENTATION) {
+ System.err.println("MacWindow.positionChanged.1 (Screen Pos - CHILD): ("+getThreadName()+"): (defer: "+defer+") "+getX()+"/"+getY()+" -> absPos "+newX+"/"+newY+", parentOnScreen "+parentOnScreen+" -> "+absPos);
+ }
+ positionChanged(false, absPos.getX(), absPos.getY());
+ } };
+ if( defer ) {
+ new InterruptSource.Thread(null, action).start();
+ } else {
+ action.run();
+ }
+
+ }
+ } else if(DEBUG_IMPLEMENTATION) {
+ System.err.println("MacWindow.positionChanged.2 (Screen Pos - IGN): ("+getThreadName()+"): (defer: "+defer+") "+getX()+"/"+getY()+" -> "+newX+"/"+newY);
+ }
+ }
+
+ @Override
+ protected void sizeChanged(final boolean defer, final int newWidth, final int newHeight, final boolean force) {
+ if(force || getWidth() != newWidth || getHeight() != newHeight) {
+ if( isNativeValid() && !isOffscreenInstance ) {
+ final NativeWindow parent = getParent();
+ final boolean useParent = useParent(parent);
+ if( useParent ) {
+ final int x=getX(), y=getY();
+ final Point p0S = getLocationOnScreenByParent(x, y, parent);
+ if(DEBUG_IMPLEMENTATION) {
+ System.err.println("MacWindow: sizeChanged() parent["+useParent+" "+x+"/"+y+"] "+getX()+"/"+getY()+" "+newWidth+"x"+newHeight+" -> "+p0S+" screen-client-pos");
+ }
+ IOSUtil.RunOnMainThread(false, false, new Runnable() {
+ @Override
+ public void run() {
+ setWindowClientTopLeftPoint0(getWindowHandle(), p0S.getX(), p0S.getY(), isVisible());
+ } } );
+ }
+ }
+ superSizeChangedOffThread(defer, newWidth, newHeight, force);
+ }
+ }
+ private void superSizeChangedOffThread(final boolean defer, final int newWidth, final int newHeight, final boolean force) {
+ if( defer ) {
+ new InterruptSource.Thread() {
+ public void run() {
+ WindowDriver.super.sizeChanged(false /* defer */, newWidth, newHeight, force);
+ } }.start();
+ } else {
+ WindowDriver.super.sizeChanged(false /* defer */, newWidth, newHeight, force);
+ }
+ }
+
+ //
+ // Accumulated actions
+ //
+
+ /** Triggered by implementation's WM events to update the client-area position, size and insets. */
+ protected void sizeScreenPosInsetsChanged(final boolean defer,
+ final int newX, final int newY,
+ final int newWidth, final int newHeight,
+ final int left, final int right, final int top, final int bottom,
+ final boolean force,
+ final boolean withinLiveResize) {
+ final LifecycleHook lh = getLifecycleHook();
+ if( withinLiveResize && !resizeAnimatorPaused && null!=lh ) {
+ resizeAnimatorPaused = lh.pauseRenderingAction();
+ }
+ sizeChanged(defer, newWidth, newHeight, force);
+ screenPositionChanged(defer, newX, newY);
+ insetsChanged(defer, left, right, top, bottom);
+ if( !withinLiveResize && resizeAnimatorPaused ) {
+ resizeAnimatorPaused = false;
+ if( null!=lh ) {
+ lh.resumeRenderingAction();
+ }
+ }
+ }
+
+ @Override
+ protected final void doMouseEvent(final boolean enqueue, final boolean wait, final short eventType, final int modifiers,
+ final int x, final int y, final short button, final float[] rotationXYZ, final float rotationScale) {
+ super.doMouseEvent(enqueue, wait, eventType, modifiers,
+ SurfaceScaleUtils.scale(x, getPixelScaleX()),
+ SurfaceScaleUtils.scale(y, getPixelScaleY()), button, rotationXYZ, rotationScale);
+ }
+
+ @Override
+ public final void sendKeyEvent(final short eventType, final int modifiers, final short keyCode, final short keySym, final char keyChar) {
+ throw new InternalError("XXX: Adapt Java Code to Native Code Changes");
+ }
+
+ @Override
+ public final void enqueueKeyEvent(final boolean wait, final short eventType, final int modifiers, final short _keyCode, final short _keySym, final char keyChar) {
+ throw new InternalError("XXX: Adapt Java Code to Native Code Changes");
+ }
+
+ protected final void enqueueKeyEvent(final boolean wait, final short eventType, int modifiers, final short _keyCode, final char keyChar, final char keySymChar) {
+ // Note that we send the key char for the key code on this
+ // platform -- we do not get any useful key codes out of the system
+ final short keyCode = MacKeyUtil.validateKeyCode(_keyCode, keyChar);
+ final short keySym;
+ {
+ final short _keySym = KeyEvent.NULL_CHAR != keySymChar ? KeyEvent.utf16ToVKey(keySymChar) : KeyEvent.VK_UNDEFINED;
+ keySym = KeyEvent.VK_UNDEFINED != _keySym ? _keySym : keyCode;
+ }
+ /**
+ {
+ final boolean isModifierKeyCode = KeyEvent.isModifierKey(keyCode);
+ System.err.println("*** handleKeyEvent: event "+KeyEvent.getEventTypeString(eventType)+
+ ", keyCode 0x"+Integer.toHexString(_keyCode)+" -> 0x"+Integer.toHexString(keyCode)+
+ ", keySymChar '"+keySymChar+"', 0x"+Integer.toHexString(keySymChar)+" -> 0x"+Integer.toHexString(keySym)+
+ ", mods "+toHexString(modifiers)+
+ ", was: pressed "+isKeyPressed(keyCode)+", isModifierKeyCode "+isModifierKeyCode+
+ ", nativeValid "+isNativeValid()+", isOffscreen "+isOffscreenInstance);
+ } */
+
+ // OSX delivery order is PRESSED (t0), RELEASED (t1) and TYPED (t2) -> NEWT order: PRESSED (t0) and RELEASED (t1)
+ // Auto-Repeat: OSX delivers only PRESSED, inject auto-repeat RELEASE key _before_ PRESSED
+ switch(eventType) {
+ case KeyEvent.EVENT_KEY_RELEASED:
+ if( isKeyCodeTracked(keyCode) ) {
+ setKeyPressed(keyCode, false);
+ }
+ break;
+ case KeyEvent.EVENT_KEY_PRESSED:
+ if( isKeyCodeTracked(keyCode) ) {
+ if( setKeyPressed(keyCode, true) ) {
+ // key was already pressed
+ modifiers |= InputEvent.AUTOREPEAT_MASK;
+ super.enqueueKeyEvent(wait, KeyEvent.EVENT_KEY_RELEASED, modifiers, keyCode, keySym, keyChar); // RELEASED
+ }
+ }
+ break;
+ }
+ super.enqueueKeyEvent(wait, eventType, modifiers, keyCode, keySym, keyChar);
+ }
+
+ protected int getDisplayID() {
+ if( !isOffscreenInstance ) {
+ return getDisplayID0(getWindowHandle());
+ }
+ return 0;
+ }
+
+ //----------------------------------------------------------------------
+ // Internals only
+ //
+
+ private void createWindow(final boolean offscreenInstance, final boolean recreate,
+ final PointImmutable pS, final int width, final int height,
+ final int flags)
+ {
+ final long parentWinHandle = getParentWindowHandle();
+ final long preWinHandle = getWindowHandle();
+
+ if(DEBUG_IMPLEMENTATION) {
+ System.err.println("MacWindow.createWindow on thread "+Thread.currentThread().getName()+
+ ": offscreen "+offscreenInstance+", recreate "+recreate+
+ ", pS "+pS+", "+width+"x"+height+", state "+getReconfigStateMaskString(flags)+
+ ", preWinHandle "+toHexString(preWinHandle)+", parentWin "+toHexString(parentWinHandle)+
+ ", surfaceHandle "+toHexString(surfaceHandle));
+ // Thread.dumpStack();
+ }
+
+ try {
+ if( 0 != preWinHandle ) {
+ setWindowHandle(0);
+ if( 0 == surfaceHandle ) {
+ throw new NativeWindowException("Internal Error - create w/ window, but no Newt NSView");
+ }
+ IOSUtil.RunOnMainThread(false, false /* kickNSApp */, new Runnable() {
+ @Override
+ public void run() {
+ changeContentView0(parentWinHandle, preWinHandle, 0);
+ close0( preWinHandle );
+ } });
+ } else {
+ if( 0 != surfaceHandle ) {
+ throw new NativeWindowException("Internal Error - create w/o window, but has Newt NSView");
+ }
+ surfaceHandle = createView0(pS.getX(), pS.getY(), width, height);
+ if( 0 == surfaceHandle ) {
+ throw new NativeWindowException("Could not create native view "+Thread.currentThread().getName()+" "+this);
+ }
+ }
+
+ final int windowStyle;
+ {
+ int ws = 0;
+ if( 0 != ( STATE_MASK_UNDECORATED & flags) || offscreenInstance ) {
+ ws = NSBorderlessWindowMask;
+ } else {
+ ws = NSTitledWindowMask|NSClosableWindowMask|NSMiniaturizableWindowMask;
+ if( 0 != ( STATE_MASK_RESIZABLE & flags) ) {
+ ws |= NSResizableWindowMask;
+ }
+ }
+ windowStyle = ws;
+ }
+ // Blocking initialization on main-thread!
+ final long[] newWin = { 0 };
+ IOSUtil.RunOnMainThread(true, false /* kickNSApp */, new Runnable() {
+ @Override
+ public void run() {
+ newWin[0] = createWindow0( pS.getX(), pS.getY(), width, height,
+ 0 != ( STATE_MASK_FULLSCREEN & flags),
+ windowStyle,
+ NSBackingStoreBuffered, surfaceHandle);
+ if ( newWin[0] != 0 ) {
+ final boolean isOpaque = getGraphicsConfiguration().getChosenCapabilities().isBackgroundOpaque() && !offscreenInstance;
+ initWindow0( parentWinHandle, newWin[0], pS.getX(), pS.getY(), width, height, reqPixelScale[0] /* HiDPI uniformPixelScale */,
+ isOpaque,
+ !offscreenInstance && 0 != ( STATE_MASK_ALWAYSONTOP & flags),
+ !offscreenInstance && 0 != ( STATE_MASK_ALWAYSONBOTTOM & flags),
+ !offscreenInstance && 0 != ( STATE_MASK_VISIBLE & flags),
+ surfaceHandle);
+ if( offscreenInstance ) {
+ orderOut0(0!=parentWinHandle ? parentWinHandle : newWin[0]);
+ } else {
+ setTitle0(newWin[0], getTitle());
+ }
+ }
+ } });
+
+ if ( newWin[0] == 0 ) {
+ throw new NativeWindowException("Could not create native window "+Thread.currentThread().getName()+" "+this);
+ }
+ setWindowHandle( newWin[0] );
+ } catch (final Exception ie) {
+ ie.printStackTrace();
+ }
+ }
+
+ protected static native boolean initIDs0();
+ private native long createView0(int x, int y, int w, int h);
+ private native long createWindow0(int x, int y, int w, int h, boolean fullscreen, int windowStyle, int backingStoreType, long view);
+ /** Must be called on Main-Thread */
+ private native void initWindow0(long parentWindow, long window, int x, int y, int w, int h, float reqPixelScale,
+ boolean opaque, boolean atop, boolean abottom, boolean visible, long view);
+
+ private native int getDisplayID0(long window);
+ private native void setPixelScale0(long window, long view, float reqPixelScale);
+ private native boolean lockSurface0(long window, long view);
+ private native boolean unlockSurface0(long window, long view);
+ /** Must be called on Main-Thread */
+ private native void requestFocus0(long window, boolean force);
+ /** Must be called on Main-Thread */
+ private native void resignFocus0(long window);
+ /** Must be called on Main-Thread. In case this is a child window and parent is still visible, orderBack(..) is issued instead of orderOut(). */
+ private native void orderOut0(long window);
+ /** Must be called on Main-Thread */
+ private native void orderFront0(long window);
+ /** Must be called on Main-Thread */
+ private native void close0(long window);
+ /** Must be called on Main-Thread */
+ private native void setTitle0(long window, String title);
+ private native long contentView0(long window);
+ /** Must be called on Main-Thread */
+ private native void changeContentView0(long parentWindowOrView, long window, long view);
+ /** Must be called on Main-Thread */
+ private native void setWindowClientTopLeftPointAndSize0(long window, int x, int y, int w, int h, boolean display);
+ /** Must be called on Main-Thread */
+ private native void setWindowClientTopLeftPoint0(long window, int x, int y, boolean display);
+ /** Triggers {@link #sizeScreenPosInsetsChanged(boolean, int, int, int, int, int, int, int, int, boolean)} */
+ private native void updateSizePosInsets0(long window, boolean defer);
+ private static native Object getLocationOnScreen0(long windowHandle, int src_x, int src_y);
+
+ // Window styles
+ private static final int NSBorderlessWindowMask = 0;
+ private static final int NSTitledWindowMask = 1 << 0;
+ private static final int NSClosableWindowMask = 1 << 1;
+ private static final int NSMiniaturizableWindowMask = 1 << 2;
+ private static final int NSResizableWindowMask = 1 << 3;
+
+ // Window backing store types
+ private static final int NSBackingStoreRetained = 0;
+ private static final int NSBackingStoreNonretained = 1;
+ private static final int NSBackingStoreBuffered = 2;
+
+ private volatile long surfaceHandle = 0;
+ private long sscSurfaceHandle = 0;
+ private boolean isOffscreenInstance = false;
+ private boolean resizeAnimatorPaused = false;
+}
diff --git a/src/newt/native/IOSNewtUIWindow.h b/src/newt/native/IOSNewtUIWindow.h
new file mode 100644
index 000000000..27ca7f3c7
--- /dev/null
+++ b/src/newt/native/IOSNewtUIWindow.h
@@ -0,0 +1,152 @@
+/**
+ * Copyright 2019 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.
+ */
+
+#import <UIKit/UIKit.h>
+#import <QuartzCore/QuartzCore.h>
+#import <pthread.h>
+#import "jni.h"
+
+#include "NewtCommon.h"
+
+// #define VERBOSE_ON 1
+
+#ifdef VERBOSE_ON
+ #define DBG_PRINT(...) NSLog(@ __VA_ARGS__) ; fflush(stderr)
+ // #define DBG_PRINT(...) fprintf(stderr, __VA_ARGS__); fflush(stderr)
+#else
+ #define DBG_PRINT(...)
+#endif
+
+// #define DBG_LIFECYCLE 1
+
+@interface NewtUIView : UIView
+{
+ jobject javaWindowObject;
+
+ volatile BOOL destroyNotifySent;
+ volatile int softLockCount;
+ pthread_mutex_t softLockSync;
+
+ BOOL modsDown[4]; // shift, ctrl, alt/option, win/command
+}
+
+- (id)initWithFrame:(CGRect)frameRect;
+
+#ifdef DBG_LIFECYCLE
+- (void) release;
+#endif
+- (void) dealloc;
+
+/* Register or deregister (NULL) the java Window object,
+ ie, if NULL, no events are send */
+- (void) setJavaWindowObject: (jobject) javaWindowObj;
+- (jobject) getJavaWindowObject;
+
+- (void) setDestroyNotifySent: (BOOL) v;
+- (BOOL) getDestroyNotifySent;
+
+- (BOOL) softLock;
+- (BOOL) softUnlock;
+
+- (void) drawRect:(CGRect)dirtyRect;
+- (BOOL) acceptsFirstResponder;
+- (BOOL) becomeFirstResponder;
+- (BOOL) resignFirstResponder;
+
+- (void) sendMouseEvent: (UIEvent*) event eventType: (jshort) evType;
+- (CGPoint) screenPos2NewtClientWinPos: (CGPoint) p;
+
+- (void) handleFlagsChanged:(NSUInteger) mods;
+- (void) handleFlagsChanged:(int) keyMask keyIndex: (int) keyIdx keyCode: (int) keyCode modifiers: (NSUInteger) mods;
+- (void) sendKeyEvent: (UIEvent*) event eventType: (jshort) evType;
+- (void) sendKeyEvent: (jshort) keyCode characters: (NSString*) chars modifiers: (NSUInteger)mods eventType: (jshort) evType;
+
+@end
+
+@interface NewtUIWindow : UIWindow
+{
+ BOOL realized;
+ jboolean withinLiveResize;
+@public
+ BOOL hasPresentationSwitch;
+ NSUInteger defaultPresentationOptions;
+ NSUInteger fullscreenPresentationOptions;
+ BOOL isFullscreenWindow;
+ int cachedInsets[4]; // l, r, t, b
+}
+
++ (BOOL) initNatives: (JNIEnv*) env forClass: (jobject) clazz;
+
+- (id) initWithFrame: (CGRect) contentRect
+ styleMask: (NSUInteger) windowStyle
+ backing: (NSUInteger) bufferingType
+ defer: (BOOL) deferCreation
+ isFullscreenWindow:(BOOL)isfs;
+#ifdef DBG_LIFECYCLE
+- (void) release;
+#endif
+- (void) dealloc;
+- (void) setRealized: (BOOL)v;
+- (BOOL) isRealized;
+
+- (void) setAlwaysOn: (BOOL)top bottom:(BOOL)bottom;
+
+- (void) updateInsets: (JNIEnv*) env jwin: (jobject) javaWin;
+- (void) updateSizePosInsets: (JNIEnv*) env jwin: (jobject) javaWin defer: (jboolean)defer;
+- (void) attachToParent: (UIWindow*) parent;
+- (void) detachFromParent: (UIWindow*) parent;
+
+- (CGPoint) newtRelClientTLWinPos2AbsTLScreenPos: (CGPoint) p;
+- (CGSize) newtClientSize2TLSize: (CGSize) nsz;
+- (CGPoint) getLocationOnScreen: (CGPoint) p;
+
+- (void) focusChanged: (BOOL) gained;
+
+- (void) flagsChanged: (UIEvent *) theEvent;
+- (BOOL) acceptsMouseMovedEvents;
+- (BOOL) acceptsFirstResponder;
+- (BOOL) becomeFirstResponder;
+- (BOOL) resignFirstResponder;
+- (BOOL) canBecomeKeyWindow;
+- (void) becomeKeyWindow;
+- (void) resignKeyWindow;
+- (void) windowDidBecomeKey: (NSNotification *) notification;
+- (void) windowDidResignKey: (NSNotification *) notification;
+
+- (void) windowWillStartLiveResize: (NSNotification *) notification;
+- (void) windowDidEndLiveResize: (NSNotification *) notification;
+- (CGSize) windowWillResize: (UIWindow *)sender toSize:(CGSize)frameSize;
+- (void) windowDidResize: (NSNotification*) notification;
+- (void) sendResizeEvent;
+
+- (void) windowDidMove: (NSNotification*) notification;
+- (BOOL) windowClosingImpl: (BOOL) force;
+- (BOOL) windowShouldClose: (id) sender;
+- (void) windowWillClose: (NSNotification*) notification;
+
+@end
diff --git a/src/newt/native/IOSNewtUIWindow.m b/src/newt/native/IOSNewtUIWindow.m
new file mode 100644
index 000000000..6c5031efc
--- /dev/null
+++ b/src/newt/native/IOSNewtUIWindow.m
@@ -0,0 +1,783 @@
+/**
+ * Copyright 2019 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.
+ */
+
+#import "IOSNewtUIWindow.h"
+#import "InputEvent.h"
+#import "KeyEvent.h"
+#import "MouseEvent.h"
+
+#include <CoreFoundation/CoreFoundation.h>
+
+#include <math.h>
+
+#define PRINTF(...) NSLog(@ __VA_ARGS__)
+
+static jmethodID enqueueMouseEventID = NULL;
+static jmethodID enqueueKeyEventID = NULL;
+static jmethodID requestFocusID = NULL;
+
+static jmethodID insetsChangedID = NULL;
+static jmethodID sizeChangedID = NULL;
+static jmethodID sizeScreenPosInsetsChangedID = NULL;
+static jmethodID updatePixelScaleID = NULL;
+static jmethodID visibleChangedID = NULL;
+static jmethodID screenPositionChangedID = NULL;
+static jmethodID focusChangedID = NULL;
+static jmethodID windowDestroyNotifyID = NULL;
+static jmethodID windowRepaintID = NULL;
+
+// Need to enqueue all events to EDT,
+// since we may operate on AWT-AppKit (Main Thread)
+// and direct issuing 'requestFocus()' would deadlock:
+// AWT-AppKit
+// AWT-EventQueue-0
+
+@implementation NewtUIView
+
+- (id)initWithFrame:(CGRect)frameRect
+{
+ id res = [super initWithFrame:frameRect];
+ javaWindowObject = NULL;
+
+ destroyNotifySent = NO;
+ softLockCount = 0;
+
+ pthread_mutexattr_t softLockSyncAttr;
+ pthread_mutexattr_init(&softLockSyncAttr);
+ pthread_mutexattr_settype(&softLockSyncAttr, PTHREAD_MUTEX_RECURSIVE);
+ pthread_mutex_init(&softLockSync, &softLockSyncAttr); // recursive
+
+ modsDown[0] = NO; // shift
+ modsDown[1] = NO; // ctrl
+ modsDown[2] = NO; // alt
+ modsDown[3] = NO; // win
+
+ DBG_PRINT("NewtUIView::create: %p (refcnt %d)\n", res, (int)[res retainCount]);
+ return res;
+}
+
+#ifdef DBG_LIFECYCLE
+- (void) release
+{
+ DBG_PRINT("NewtUIView::release.0: %p (refcnt %d)\n", self, (int)[self retainCount]);
+ [super release];
+}
+#endif
+
+- (void) dealloc
+{
+ DBG_PRINT("NewtUIView::dealloc.0: %p (refcnt %d), ptrTrackingTag %d\n", self, (int)[self retainCount], (int)ptrTrackingTag);
+#ifdef DBG_LIFECYCLE
+ NSLog(@"%@",[NSThread callStackSymbols]);
+#endif
+ if( 0 < softLockCount ) {
+ NSLog(@"NewtUIView::dealloc: softLock still hold @ dealloc!\n");
+ }
+
+ pthread_mutex_destroy(&softLockSync);
+ DBG_PRINT("NewtUIView::dealloc.X: %p\n", self);
+ [super dealloc];
+}
+
+- (void) setJavaWindowObject: (jobject) javaWindowObj
+{
+ javaWindowObject = javaWindowObj;
+}
+
+- (jobject) getJavaWindowObject
+{
+ return javaWindowObject;
+}
+
+- (void) setDestroyNotifySent: (BOOL) v
+{
+ destroyNotifySent = v;
+}
+
+- (BOOL) getDestroyNotifySent
+{
+ return destroyNotifySent;
+}
+
+- (BOOL) softLock
+{
+ // DBG_PRINT("*************** softLock.0: %p\n", (void*)pthread_self());
+ int err;
+ if( 0 != ( err = pthread_mutex_lock(&softLockSync) ) ) {
+ NSLog(@"NewtUIView::softLock failed: errCode %d - %@", err, [NSThread callStackSymbols]);
+ return NO;
+ }
+ softLockCount++;
+ // DBG_PRINT("*************** softLock.X: %p\n", (void*)pthread_self());
+ return 0 < softLockCount;
+}
+
+- (BOOL) softUnlock
+{
+ // DBG_PRINT("*************** softUnlock: %p\n", (void*)pthread_self());
+ softLockCount--;
+ int err;
+ if( 0 != ( err = pthread_mutex_unlock(&softLockSync) ) ) {
+ softLockCount++;
+ NSLog(@"NewtUIView::softUnlock failed: Not locked by current thread - errCode %d - %@", err, [NSThread callStackSymbols]);
+ return NO;
+ }
+ return YES;
+}
+
+- (void) drawRect:(CGRect)dirtyRect
+{
+ DBG_PRINT("*************** dirtyRect: %p %lf/%lf %lfx%lf\n",
+ javaWindowObject, dirtyRect.origin.x, dirtyRect.origin.y, dirtyRect.size.width, dirtyRect.size.height);
+
+ if(NULL==javaWindowObject) {
+ DBG_PRINT("drawRect: null javaWindowObject\n");
+ return;
+ }
+ int shallBeDetached = 0;
+ JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached);
+ if(NULL==env) {
+ DBG_PRINT("drawRect: null JNIEnv\n");
+ return;
+ }
+
+ CGRect viewFrame = [self frame];
+
+ (*env)->CallVoidMethod(env, javaWindowObject, windowRepaintID, JNI_TRUE, // defer ..
+ (int)dirtyRect.origin.x, (int)viewFrame.size.height - (int)dirtyRect.origin.y,
+ (int)dirtyRect.size.width, (int)dirtyRect.size.height);
+
+ // detaching thread not required - daemon
+ // NewtCommon_ReleaseJNIEnv(shallBeDetached);
+}
+
+- (BOOL) acceptsFirstResponder
+{
+ return YES;
+}
+
+- (BOOL) becomeFirstResponder
+{
+ DBG_PRINT( "*************** View.becomeFirstResponder\n");
+ return [super becomeFirstResponder];
+}
+
+- (BOOL) resignFirstResponder
+{
+ DBG_PRINT( "*************** View.resignFirstResponder\n");
+ return [super resignFirstResponder];
+}
+
+- (void) sendMouseEvent: (UIEvent*) event eventType: (jshort) evType
+{
+ if (javaWindowObject == NULL) {
+ DBG_PRINT("sendMouseEvent: null javaWindowObject\n");
+ return;
+ }
+ int shallBeDetached = 0;
+ JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached);
+ if(NULL==env) {
+ DBG_PRINT("sendMouseEvent: null JNIEnv\n");
+ return;
+ }
+ jint javaMods[] = { 0 } ;
+ javaMods[0] = 0; // TODO mods2JavaMods([event modifierFlags]);
+
+ // convert to 1-based button number (or use zero if no button is involved)
+ // TODO: detect mouse button when mouse wheel scrolled
+ jshort javaButtonNum = 1;
+ jfloat scrollDeltaY = 0.0f;
+ /**
+ switch ([event type]) {
+ case NSLeftMouseDown:
+ case NSLeftMouseUp:
+ case NSLeftMouseDragged:
+ javaButtonNum = 1;
+ break;
+ case NSRightMouseDown:
+ case NSRightMouseUp:
+ case NSRightMouseDragged:
+ javaButtonNum = 3;
+ break;
+ case NSOtherMouseDown:
+ case NSOtherMouseUp:
+ case NSOtherMouseDragged:
+ javaButtonNum = 2;
+ break;
+ default:
+ javaButtonNum = 0;
+ break;
+ } */
+ CGPoint location = CGPointMake(0,0); // TODO [self screenPos2NewtClientWinPos: [UIEvent mouseLocation]];
+
+ (*env)->CallVoidMethod(env, javaWindowObject, enqueueMouseEventID, JNI_FALSE,
+ evType, javaMods[0],
+ (jint) location.x, (jint) location.y,
+ javaButtonNum, scrollDeltaY);
+
+ // detaching thread not required - daemon
+ // NewtCommon_ReleaseJNIEnv(shallBeDetached);
+}
+
+- (CGPoint) screenPos2NewtClientWinPos: (CGPoint) p
+{
+ CGRect viewFrame = [self frame];
+
+ CGRect r;
+ r.origin.x = p.x;
+ r.origin.y = p.y;
+ r.size.width = 0;
+ r.size.height = 0;
+ // CGRect rS = [[self window] convertRectFromScreen: r]; // 10.7
+ CGPoint oS = r.origin; // TODO [[self window] convertScreenToBase: r.origin];
+ oS.y = viewFrame.size.height - oS.y; // y-flip
+ return oS;
+}
+
+- (void) handleFlagsChanged:(NSUInteger) mods
+{
+ // TODO [self handleFlagsChanged: NSShiftKeyMask keyIndex: 0 keyCode: kVK_Shift modifiers: mods];
+ // TODO [self handleFlagsChanged: NSControlKeyMask keyIndex: 1 keyCode: kVK_Control modifiers: mods];
+ // TODO [self handleFlagsChanged: NSAlternateKeyMask keyIndex: 2 keyCode: kVK_Option modifiers: mods];
+ // TODO [self handleFlagsChanged: NSCommandKeyMask keyIndex: 3 keyCode: kVK_Command modifiers: mods];
+}
+
+- (void) handleFlagsChanged:(int) keyMask keyIndex: (int) keyIdx keyCode: (int) keyCode modifiers: (NSUInteger) mods
+{
+ if ( NO == modsDown[keyIdx] && 0 != ( mods & keyMask ) ) {
+ modsDown[keyIdx] = YES;
+ [self sendKeyEvent: (jshort)keyCode characters: NULL modifiers: mods|keyMask eventType: (jshort)EVENT_KEY_PRESSED];
+ } else if ( YES == modsDown[keyIdx] && 0 == ( mods & keyMask ) ) {
+ modsDown[keyIdx] = NO;
+ [self sendKeyEvent: (jshort)keyCode characters: NULL modifiers: mods|keyMask eventType: (jshort)EVENT_KEY_RELEASED];
+ }
+}
+
+- (void) sendKeyEvent: (UIEvent*) event eventType: (jshort) evType
+{
+ jshort keyCode = 0; // TODO (jshort) [event keyCode];
+ NSString* chars = NULL; // TODO [event charactersIgnoringModifiers];
+ NSUInteger mods = 0; // TODO [event modifierFlags];
+ [self sendKeyEvent: keyCode characters: chars modifiers: mods eventType: evType];
+}
+
+- (void) sendKeyEvent: (jshort) keyCode characters: (NSString*) chars modifiers: (NSUInteger)mods eventType: (jshort) evType
+{
+ if (javaWindowObject == NULL) {
+ DBG_PRINT("sendKeyEvent: null javaWindowObject\n");
+ return;
+ }
+ int shallBeDetached = 0;
+ JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached);
+ if(NULL==env) {
+ DBG_PRINT("sendKeyEvent: null JNIEnv\n");
+ return;
+ }
+
+ int i;
+ int len = NULL != chars ? [chars length] : 0;
+ jint javaMods = 0; // TODO mods2JavaMods(mods);
+
+ if(len > 0) {
+ // printable chars
+ for (i = 0; i < len; i++) {
+ // Note: the key code in the UIEvent does not map to anything we can use
+ UniChar keyChar = (UniChar) [chars characterAtIndex: i];
+ UniChar keySymChar = 0; // TODO CKCH_CharForKeyCode(keyCode);
+
+ DBG_PRINT("sendKeyEvent: %d/%d code 0x%X, char 0x%X, mods 0x%X/0x%X -> keySymChar 0x%X\n", i, len, (int)keyCode, (int)keyChar,
+ (int)mods, (int)javaMods, (int)keySymChar);
+
+ (*env)->CallVoidMethod(env, javaWindowObject, enqueueKeyEventID, JNI_FALSE,
+ evType, javaMods, keyCode, (jchar)keyChar, (jchar)keySymChar);
+ }
+ } else {
+ // non-printable chars
+ jchar keyChar = (jchar) 0;
+
+ DBG_PRINT("sendKeyEvent: code 0x%X\n", (int)keyCode);
+
+ (*env)->CallVoidMethod(env, javaWindowObject, enqueueKeyEventID, JNI_FALSE,
+ evType, javaMods, keyCode, keyChar, keyChar);
+ }
+
+ // detaching thread not required - daemon
+ // NewtCommon_ReleaseJNIEnv(shallBeDetached);
+}
+
+@end
+
+@implementation NewtUIWindow
+
++ (BOOL) initNatives: (JNIEnv*) env forClass: (jclass) clazz
+{
+ enqueueMouseEventID = (*env)->GetMethodID(env, clazz, "enqueueMouseEvent", "(ZSIIISF)V");
+ enqueueKeyEventID = (*env)->GetMethodID(env, clazz, "enqueueKeyEvent", "(ZSISCC)V");
+ sizeChangedID = (*env)->GetMethodID(env, clazz, "sizeChanged", "(ZIIZ)V");
+ updatePixelScaleID = (*env)->GetMethodID(env, clazz, "updatePixelScale", "(ZFF)V");
+ visibleChangedID = (*env)->GetMethodID(env, clazz, "visibleChanged", "(ZZ)V");
+ insetsChangedID = (*env)->GetMethodID(env, clazz, "insetsChanged", "(ZIIII)V");
+ sizeScreenPosInsetsChangedID = (*env)->GetMethodID(env, clazz, "sizeScreenPosInsetsChanged", "(ZIIIIIIIIZZ)V");
+ screenPositionChangedID = (*env)->GetMethodID(env, clazz, "screenPositionChanged", "(ZII)V");
+ focusChangedID = (*env)->GetMethodID(env, clazz, "focusChanged", "(ZZ)V");
+ windowDestroyNotifyID = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "(Z)Z");
+ windowRepaintID = (*env)->GetMethodID(env, clazz, "windowRepaint", "(ZIIII)V");
+ requestFocusID = (*env)->GetMethodID(env, clazz, "requestFocus", "(Z)V");
+ if (enqueueMouseEventID && enqueueKeyEventID && sizeChangedID && updatePixelScaleID && visibleChangedID &&
+ insetsChangedID && sizeScreenPosInsetsChangedID &&
+ screenPositionChangedID && focusChangedID && windowDestroyNotifyID && requestFocusID && windowRepaintID)
+ {
+ // TODO CKCH_CreateDictionaries();
+ return YES;
+ }
+ return NO;
+}
+
+- (id) initWithFrame: (CGRect) contentRect
+ styleMask: (NSUInteger) windowStyle
+ backing: (NSUInteger) bufferingType
+ defer: (BOOL) deferCreation
+ isFullscreenWindow:(BOOL)isfs
+{
+ /**
+ id res = [super initWithContentRect: contentRect
+ styleMask: windowStyle
+ backing: bufferingType
+ defer: deferCreation];
+ */
+ id res = [super initWithFrame: contentRect];
+ // OSX 10.6
+ /** TODO
+ if ( [NSApp respondsToSelector:@selector(currentSystemPresentationOptions)] &&
+ [NSApp respondsToSelector:@selector(setPresentationOptions:)] ) {
+ hasPresentationSwitch = YES;
+ defaultPresentationOptions = [NSApp currentSystemPresentationOptions];
+ fullscreenPresentationOptions =
+ // NSApplicationPresentationDefault|
+ // NSApplicationPresentationAutoHideDock|
+ NSApplicationPresentationHideDock|
+ // NSApplicationPresentationAutoHideMenuBar|
+ NSApplicationPresentationHideMenuBar|
+ NSApplicationPresentationDisableAppleMenu|
+ // NSApplicationPresentationDisableProcessSwitching|
+ // NSApplicationPresentationDisableSessionTermination|
+ NSApplicationPresentationDisableHideApplication|
+ // NSApplicationPresentationDisableMenuBarTransparency|
+ // NSApplicationPresentationFullScreen| // OSX 10.7
+ 0 ;
+ } else {
+ */
+ hasPresentationSwitch = NO;
+ defaultPresentationOptions = 0;
+ fullscreenPresentationOptions = 0;
+ // }
+
+ isFullscreenWindow = NO; // TODO isfs;
+ // Why is this necessary? Without it we don't get any of the
+ // delegate methods like resizing and window movement.
+ // TODO [self setDelegate: self];
+
+ cachedInsets[0] = 0; // l
+ cachedInsets[1] = 0; // r
+ cachedInsets[2] = 0; // t
+ cachedInsets[3] = 0; // b
+
+ realized = YES;
+ withinLiveResize = JNI_FALSE;
+ DBG_PRINT("NewtWindow::create: %p, realized %d, hasPresentationSwitch %d[defaultOptions 0x%X, fullscreenOptions 0x%X], (refcnt %d)\n",
+ res, realized, (int)hasPresentationSwitch, (int)defaultPresentationOptions, (int)fullscreenPresentationOptions, (int)[res retainCount]);
+ return res;
+}
+
+#ifdef DBG_LIFECYCLE
+- (void) release
+{
+ DBG_PRINT("NewtWindow::release.0: %p (refcnt %d)\n", self, (int)[self retainCount]);
+ // NSLog(@"%@",[NSThread callStackSymbols]);
+ [super release];
+}
+#endif
+
+- (void) dealloc
+{
+ DBG_PRINT("NewtWindow::dealloc.0: %p (refcnt %d)\n", self, (int)[self retainCount]);
+#ifdef DBG_LIFECYCLE
+ NSLog(@"%@",[NSThread callStackSymbols]);
+#endif
+
+ /**
+ NewtUIView* mView = (NewtUIView *)self; // TODO [self contentView];
+ if( NULL != mView ) {
+ [mView release];
+ }
+ */
+ [super dealloc];
+ DBG_PRINT("NewtWindow::dealloc.X: %p\n", self);
+}
+
+- (void) setRealized: (BOOL)v
+{
+ realized = v;
+}
+
+- (BOOL) isRealized
+{
+ return realized;
+}
+
+- (void) setAlwaysOn: (BOOL)top bottom:(BOOL)bottom
+{
+ /**
+ if( top ) {
+ DBG_PRINT( "*************** setAlwaysOn -> top\n");
+ [self setLevel: kCGMaximumWindowLevel];
+ } else if ( bottom ) {
+ DBG_PRINT( "*************** setAlwaysOn -> bottom\n");
+ [self setLevel: kCGDesktopIconWindowLevel]; // w/ input
+ } else {
+ DBG_PRINT( "*************** setAlwaysOn -> normal\n");
+ [self setLevel:NSNormalWindowLevel];
+ } */
+}
+
+- (void) updateInsets: (JNIEnv*) env jwin: (jobject) javaWin
+{
+ /**
+ CGRect frameRect = [self frame];
+ CGRect contentRect = [self contentRectForFrameRect: frameRect];
+
+ // note: this is a simplistic implementation which doesn't take
+ // into account DPI and scaling factor
+ CGFloat l = contentRect.origin.x - frameRect.origin.x;
+ cachedInsets[0] = (int)l; // l
+ cachedInsets[1] = (int)(frameRect.size.width - (contentRect.size.width + l)); // r
+ cachedInsets[2] = (jint)(frameRect.size.height - contentRect.size.height); // t
+ cachedInsets[3] = (jint)(contentRect.origin.y - frameRect.origin.y); // b
+ */
+ UIEdgeInsets uiInsets = [self safeAreaInsets];
+ cachedInsets[0] = uiInsets.left;
+ cachedInsets[1] = uiInsets.right;
+ cachedInsets[2] = uiInsets.top;
+ cachedInsets[3] = uiInsets.bottom;
+ DBG_PRINT( "updateInsets: [ l %d, r %d, t %d, b %d ]\n", cachedInsets[0], cachedInsets[1], cachedInsets[2], cachedInsets[3]);
+
+ if( NULL != env && NULL != javaWin ) {
+ (*env)->CallVoidMethod(env, javaWin, insetsChangedID, JNI_FALSE, cachedInsets[0], cachedInsets[1], cachedInsets[2], cachedInsets[3]);
+ }
+}
+
+- (void) updateSizePosInsets: (JNIEnv*) env jwin: (jobject) javaWin defer: (jboolean)defer
+{
+ // update insets on every window resize for lack of better hook place
+ [self updateInsets: NULL jwin:NULL];
+
+ CGRect frameRect = [self frame];
+
+ UIScreen* screen = [self screen];
+ CGPoint pS = [self convertPoint: frameRect.origin toCoordinateSpace: screen.fixedCoordinateSpace];
+
+ DBG_PRINT( "updateSize: [ w %d, h %d ], liveResize %d\n", (jint) frameRect.size.width, (jint) frameRect.size.height, (jint)withinLiveResize);
+ DBG_PRINT( "updatePos: [ x %d, y %d ]\n", (jint) pS.x, (jint) pS.y);
+
+ if( NULL != env && NULL != javaWin ) {
+ (*env)->CallVoidMethod(env, javaWin, sizeScreenPosInsetsChangedID, defer,
+ (jint) pS.x, (jint) pS.y,
+ (jint) frameRect.size.width, (jint) frameRect.size.height,
+ cachedInsets[0], cachedInsets[1], cachedInsets[2], cachedInsets[3],
+ JNI_FALSE, // force
+ withinLiveResize
+ );
+ }
+}
+
+
+- (void) attachToParent: (UIWindow*) parent
+{
+ /** TODO
+ DBG_PRINT( "attachToParent.1\n");
+ [parent addChildWindow: self ordered: UIWindowAbove];
+ DBG_PRINT( "attachToParent.2\n");
+ [self setParentWindow: parent];
+ DBG_PRINT( "attachToParent.X\n");
+ */
+}
+
+- (void) detachFromParent: (UIWindow*) parent
+{
+ /** TODO
+ DBG_PRINT( "detachFromParent.1\n");
+ [self setParentWindow: nil];
+ if(NULL != parent) {
+ DBG_PRINT( "detachFromParent.2\n");
+ [parent removeChildWindow: self];
+ }
+ DBG_PRINT( "detachFromParent.X\n");
+ */
+}
+
+/**
+ * p rel client window position w/ top-left origin
+ * returns: abs screen position w/ bottom-left origin
+ */
+- (CGPoint) newtRelClientTLWinPos2AbsTLScreenPos: (CGPoint) p
+{
+ return [self getLocationOnScreen: p];
+}
+
+- (CGSize) newtClientSize2TLSize: (CGSize) nsz
+{
+ CGSize topSZ = { nsz.width, nsz.height + cachedInsets[2] + cachedInsets[3] }; // height + insets.top + insets.bottom
+ return topSZ;
+}
+
+/**
+ * p rel client window position w/ top-left origin
+ * returns: location in 0/0 top-left space.
+ */
+- (CGPoint) getLocationOnScreen: (CGPoint) p
+{
+ UIScreen* screen = [self screen];
+ CGPoint pS = [self convertPoint: p toCoordinateSpace: screen.fixedCoordinateSpace];
+
+#ifdef VERBOSE_ON
+ CGRect winFrame = [self frame];
+ DBG_PRINT( "getLocationOnScreen: point-in[%d/%d], winFrame[%d/%d %dx%d] -> %d/%d\n",
+ (int)p.x, (int)p.y,
+ (int)winFrame.origin.x, (int)winFrame.origin.y, (int)winFrame.size.width, (int)winFrame.size.height,
+ (int)pS.x, (int)pS.y);
+#endif
+
+ return pS;
+}
+
+- (void) focusChanged: (BOOL) gained
+{
+ DBG_PRINT( "focusChanged: gained %d\n", gained);
+ NewtUIView* newtView = (NewtUIView *) self; // TODO [self contentView];
+ jobject javaWindowObject = [newtView getJavaWindowObject];
+ if (javaWindowObject == NULL) {
+ DBG_PRINT("focusChanged: null javaWindowObject\n");
+ return;
+ }
+ int shallBeDetached = 0;
+ JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached);
+ if(NULL==env) {
+ DBG_PRINT("focusChanged: null JNIEnv\n");
+ return;
+ }
+
+ (*env)->CallVoidMethod(env, javaWindowObject, focusChangedID, JNI_FALSE, (gained == YES) ? JNI_TRUE : JNI_FALSE);
+
+ // detaching thread not required - daemon
+ // NewtCommon_ReleaseJNIEnv(shallBeDetached);
+}
+
+- (void) flagsChanged:(UIEvent *) theEvent
+{
+ NSUInteger mods = [theEvent modifierFlags];
+ NewtUIView* newtView = (NewtUIView *) [self contentView];
+ if( [newtView isKindOfClass:[NewtUIView class]] ) {
+ [newtView handleFlagsChanged: mods];
+ }
+}
+
+- (BOOL) acceptsMouseMovedEvents
+{
+ return YES;
+}
+
+- (BOOL) acceptsFirstResponder
+{
+ return YES;
+}
+
+- (BOOL) becomeFirstResponder
+{
+ DBG_PRINT( "*************** Win.becomeFirstResponder\n");
+ return [super becomeFirstResponder];
+}
+
+- (BOOL) resignFirstResponder
+{
+ DBG_PRINT( "*************** Win.resignFirstResponder\n");
+ return [super resignFirstResponder];
+}
+
+- (BOOL) canBecomeKeyWindow
+{
+ // Even if the window is borderless, we still want it to be able
+ // to become the key window to receive keyboard events
+ return YES;
+}
+
+- (void) becomeKeyWindow
+{
+ DBG_PRINT( "*************** becomeKeyWindow\n");
+ [super becomeKeyWindow];
+}
+
+- (void) resignKeyWindow
+{
+ DBG_PRINT( "*************** resignKeyWindow: isFullscreen %d\n", (int)isFullscreenWindow);
+ if(!isFullscreenWindow) {
+ [super resignKeyWindow];
+ }
+}
+
+- (void) windowDidResignKey: (NSNotification *) notification
+{
+ DBG_PRINT( "*************** windowDidResignKey\n");
+ // Implicit mouse exit by OS X
+ [self focusChanged: NO];
+}
+
+- (void) windowWillStartLiveResize: (NSNotification *) notification
+{
+ DBG_PRINT( "*************** windowWillStartLiveResize\n");
+ withinLiveResize = JNI_TRUE;
+}
+- (void) windowDidEndLiveResize: (NSNotification *) notification
+{
+ DBG_PRINT( "*************** windowDidEndLiveResize\n");
+ withinLiveResize = JNI_FALSE;
+ [self sendResizeEvent];
+}
+- (CGSize) windowWillResize: (UIWindow *)sender toSize:(CGSize)frameSize
+{
+ DBG_PRINT( "*************** windowWillResize %lfx%lf\n", frameSize.width, frameSize.height);
+ return frameSize;
+}
+- (void)windowDidResize: (NSNotification*) notification
+{
+ DBG_PRINT( "*************** windowDidResize\n");
+ [self sendResizeEvent];
+}
+
+- (void) sendResizeEvent
+{
+ jobject javaWindowObject = NULL;
+ int shallBeDetached = 0;
+ JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached);
+
+ if( NULL == env ) {
+ DBG_PRINT("windowDidResize: null JNIEnv\n");
+ return;
+ }
+ NewtUIView* newtView = (NewtUIView *) [self contentView];
+ if( [newtView isKindOfClass:[NewtUIView class]] ) {
+ javaWindowObject = [newtView getJavaWindowObject];
+ }
+ if( NULL != javaWindowObject ) {
+ [self updateSizePosInsets: env jwin: javaWindowObject defer:JNI_TRUE];
+ }
+ // detaching thread not required - daemon
+ // NewtCommon_ReleaseJNIEnv(shallBeDetached);
+}
+
+- (void)windowDidMove: (NSNotification*) notification
+{
+ NewtUIView* newtView = (NewtUIView *) [self contentView];
+ if( ! [newtView isKindOfClass:[NewtUIView class]] ) {
+ return;
+ }
+ jobject javaWindowObject = [newtView getJavaWindowObject];
+ if (javaWindowObject == NULL) {
+ DBG_PRINT("windowDidMove: null javaWindowObject\n");
+ return;
+ }
+ int shallBeDetached = 0;
+ JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached);
+ if(NULL==env) {
+ DBG_PRINT("windowDidMove: null JNIEnv\n");
+ return;
+ }
+
+ CGPoint p0 = { 0, 0 };
+ p0 = [self getLocationOnScreen: p0];
+ DBG_PRINT( "windowDidMove: [ x %d, y %d ]\n", (jint) p0.x, (jint) p0.y);
+ (*env)->CallVoidMethod(env, javaWindowObject, screenPositionChangedID, JNI_TRUE, (jint) p0.x, (jint) p0.y);
+
+ // detaching thread not required - daemon
+ // NewtCommon_ReleaseJNIEnv(shallBeDetached);
+}
+
+- (BOOL)windowShouldClose: (id) sender
+{
+ return [self windowClosingImpl: NO];
+}
+
+- (void)windowWillClose: (NSNotification*) notification
+{
+ [self windowClosingImpl: YES];
+}
+
+- (BOOL) windowClosingImpl: (BOOL) force
+{
+ jboolean closed = JNI_FALSE;
+
+ NewtUIView* newtView = (NewtUIView *) [self contentView];
+ if( ! [newtView isKindOfClass:[NewtUIView class]] ) {
+ return NO;
+ }
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ [newtView cursorHide: NO enter: -1];
+
+ if( false == [newtView getDestroyNotifySent] ) {
+ jobject javaWindowObject = [newtView getJavaWindowObject];
+ DBG_PRINT( "*************** windowWillClose.0: %p\n", (void *)(intptr_t)javaWindowObject);
+ if (javaWindowObject == NULL) {
+ DBG_PRINT("windowWillClose: null javaWindowObject\n");
+ [pool release];
+ return NO;
+ }
+ int shallBeDetached = 0;
+ JNIEnv* env = NewtCommon_GetJNIEnv(1 /* asDaemon */, &shallBeDetached);
+ if(NULL==env) {
+ DBG_PRINT("windowWillClose: null JNIEnv\n");
+ [pool release];
+ return NO;
+ }
+ [newtView setDestroyNotifySent: true]; // earmark assumption of being closed
+ closed = (*env)->CallBooleanMethod(env, javaWindowObject, windowDestroyNotifyID, force ? JNI_TRUE : JNI_FALSE);
+ if(!force && !closed) {
+ // not closed on java side, not force -> clear flag
+ [newtView setDestroyNotifySent: false];
+ }
+
+ // detaching thread not required - daemon
+ // NewtCommon_ReleaseJNIEnv(shallBeDetached);
+ DBG_PRINT( "*************** windowWillClose.X: %p, closed %d\n", (void *)(intptr_t)javaWindowObject, (int)closed);
+ } else {
+ DBG_PRINT( "*************** windowWillClose (skip)\n");
+ }
+ [pool release];
+ return JNI_TRUE == closed ? YES : NO ;
+}
+
+@end
+
diff --git a/src/newt/native/IOSUIWindow.m b/src/newt/native/IOSUIWindow.m
new file mode 100644
index 000000000..780c2344f
--- /dev/null
+++ b/src/newt/native/IOSUIWindow.m
@@ -0,0 +1,1161 @@
+/**
+ * Copyright 2019 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.
+ */
+
+#import <inttypes.h>
+
+#import "jogamp_newt_driver_ios_WindowDriver.h"
+#import "IOSNewtUIWindow.h"
+
+#import "MouseEvent.h"
+#import "KeyEvent.h"
+#import "ScreenMode.h"
+
+#import <stdio.h>
+
+#ifdef DBG_PERF
+ #include "timespec.h"
+#endif
+
+static const char * const ClazzNamePoint = "com/jogamp/nativewindow/util/Point";
+static const char * const ClazzAnyCstrName = "<init>";
+static const char * const ClazzNamePointCstrSignature = "(II)V";
+static jclass pointClz = NULL;
+static jmethodID pointCstr = NULL;
+
+static NSString* jstringToNSString(JNIEnv* env, jstring jstr)
+{
+ const jchar* jstrChars = (*env)->GetStringChars(env, jstr, NULL);
+ NSString* str = [[NSString alloc] initWithCharacters: jstrChars length: (*env)->GetStringLength(env, jstr)];
+ (*env)->ReleaseStringChars(env, jstr, jstrChars);
+ return str;
+}
+
+static void setWindowClientTopLeftPoint(NewtUIWindow* mWin, jint x, jint y, BOOL doDisplay) {
+ DBG_PRINT( "setWindowClientTopLeftPoint.0 - window: %p %d/%d, display %d\n", mWin, (int)x, (int)y, (int)doDisplay);
+ CGPoint pS = CGPointMake(x, y);
+ CGRect rect = [mWin frame];
+ rect.origin = pS;
+
+ [mWin setFrame: rect];
+ DBG_PRINT( "setWindowClientTopLeftPoint.X: %d/%d\n", (int)pS.x, (int)pS.y);
+
+ if( doDisplay ) {
+ // TODO UIView* mView = [mWin contentView];
+ // TODO [mWin invalidateCursorRectsForView: mView];
+ }
+}
+
+static void setWindowClientTopLeftPointAndSize(NewtUIWindow* mWin, jint x, jint y, jint width, jint height, BOOL doDisplay) {
+ DBG_PRINT( "setWindowClientTopLeftPointAndSize.0 - window: %p %d/%d %dx%d, display %d\n", mWin, (int)x, (int)y, (int)width, (int)height, (int)doDisplay);
+ CGRect rect = CGRectMake(x, y, width, height);
+ DBG_PRINT( "setWindowClientTopLeftPointAndSize.1: %d/%d %dx%d\n", (int)rect.origin.x, (int)rect.origin.y, (int)rect.size.width, (int)rect.size.height);
+
+ // TODO [mWin setFrame: rect display:doDisplay];
+ [mWin setFrame: rect];
+ DBG_PRINT( "setWindowClientTopLeftPointAndSize.X: %d/%d %dx%d\n", (int)rect.origin.x, (int)rect.origin.y, (int)rect.size.width, (int)rect.size.height);
+
+ // -> display:YES
+ // if( doDisplay ) {
+ // UIView* mView = [mWin contentView];
+ // [mWin invalidateCursorRectsForView: mView];
+ // }
+}
+
+#ifdef VERBOSE_ON
+static int getRetainCount(NSObject * obj) {
+ return ( NULL == obj ) ? -1 : (int)([obj retainCount]) ;
+}
+#endif
+
+static void setJavaWindowObject(JNIEnv *env, jobject newJavaWindowObject, NewtUIView *view, BOOL enable) {
+ DBG_PRINT( "setJavaWindowObject.0: View %p\n", view);
+ if( !enable) {
+ jobject globJavaWindowObject = [view getJavaWindowObject];
+ if( NULL != globJavaWindowObject ) {
+ DBG_PRINT( "setJavaWindowObject.1: View %p - Clear old javaWindowObject %p\n", view, globJavaWindowObject);
+ (*env)->DeleteGlobalRef(env, globJavaWindowObject);
+ [view setJavaWindowObject: NULL];
+ }
+ } else if( NULL != newJavaWindowObject ) {
+ DBG_PRINT( "setJavaWindowObject.2: View %p - Set new javaWindowObject %p\n", view, newJavaWindowObject);
+ jobject globJavaWindowObject = (*env)->NewGlobalRef(env, newJavaWindowObject);
+ [view setJavaWindowObject: globJavaWindowObject];
+ }
+ DBG_PRINT( "setJavaWindowObject.X: View %p\n", view);
+}
+
+static void changeContentView(JNIEnv *env, jobject javaWindowObject, UIView *pview, NewtUIWindow *win, NewtUIView *newView, BOOL setJavaWindow) {
+ UIView* oldUIView = NULL; // TODO [win contentView];
+ NewtUIView* oldNewtUIView = NULL;
+#ifdef VERBOSE_ON
+ int dbgIdx = 1;
+#endif
+
+ if( [oldUIView isKindOfClass:[NewtUIView class]] ) {
+ oldNewtUIView = (NewtUIView *) oldUIView;
+ }
+
+ DBG_PRINT( "changeContentView.%d win %p, view (%p,%d (%d) -> %p,%d), parent view %p\n",
+ dbgIdx++, win, oldUIView, getRetainCount(oldUIView), NULL!=oldNewtUIView, newView, getRetainCount(newView), pview);
+
+ if( NULL!=oldUIView ) {
+NS_DURING
+ // Available >= 10.5 - Makes the menubar disapear
+ BOOL iifs = NO; // TODO [oldUIView isInFullScreenMode];
+ if( iifs ) {
+ // TODO [oldUIView exitFullScreenModeWithOptions: NULL];
+ }
+NS_HANDLER
+NS_ENDHANDLER
+ DBG_PRINT( "changeContentView.%d win %p, view (%p,%d (%d) -> %p,%d)\n",
+ dbgIdx++, win, oldUIView, getRetainCount(oldUIView), NULL!=oldNewtUIView, newView, getRetainCount(newView));
+
+ if( NULL != oldNewtUIView ) {
+ [oldNewtUIView setDestroyNotifySent: false];
+ setJavaWindowObject(env, NULL, oldNewtUIView, NO);
+ }
+ // TODO [oldUIView removeFromSuperviewWithoutNeedingDisplay];
+ }
+ DBG_PRINT( "changeContentView.%d win %p, view (%p,%d -> %p,%d), isHidden %d, isHiddenOrHasHiddenAncestor: %d\n",
+ dbgIdx++, win, oldUIView, getRetainCount(oldUIView), newView, getRetainCount(newView), [newView isHidden], [newView isHiddenOrHasHiddenAncestor]);
+
+ if( NULL!=newView ) {
+ [newView setDestroyNotifySent: false];
+ if( setJavaWindow ) {
+ setJavaWindowObject(env, javaWindowObject, newView, YES);
+ }
+
+ DBG_PRINT( "changeContentView.%d win %p, view (%p,%d -> %p,%d)\n",
+ dbgIdx++, win, oldUIView, getRetainCount(oldUIView), newView, getRetainCount(newView));
+
+ if(NULL!=pview) {
+ // TODO [pview addSubview: newView positioned: UIWindowAbove relativeTo: nil];
+ }
+ }
+ DBG_PRINT( "changeContentView.%d win %p, view (%p,%d -> %p,%d), isHidden %d, isHiddenOrHasHiddenAncestor: %d\n",
+ dbgIdx++, win, oldUIView, getRetainCount(oldUIView), newView, getRetainCount(newView), [newView isHidden], [newView isHiddenOrHasHiddenAncestor]);
+
+ // TODO [win setContentView: newView];
+
+ DBG_PRINT( "changeContentView.%d win %p, view (%p,%d -> %p,%d), isHidden %d, isHiddenOrHasHiddenAncestor: %d\n",
+ dbgIdx++, win, oldUIView, getRetainCount(oldUIView), newView, getRetainCount(newView), [newView isHidden], [newView isHiddenOrHasHiddenAncestor]);
+
+ // make sure the insets are updated in the java object
+ [win updateInsets: env jwin:javaWindowObject];
+
+ DBG_PRINT( "changeContentView.X win %p, view (%p,%d -> %p,%d)\n",
+ win, oldUIView, getRetainCount(oldUIView), newView, getRetainCount(newView));
+}
+
+/*
+ * Class: jogamp_newt_driver_ios_DisplayDriver
+ * Method: initIDs
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_ios_DisplayDriver_initUIApplication0
+ (JNIEnv *env, jclass clazz)
+{
+ static int initialized = 0;
+
+ if(initialized) return JNI_TRUE;
+ initialized = 1;
+
+ NewtCommon_init(env);
+
+ // Initialize the shared NSApplication instance
+ [UIApplication sharedApplication];
+
+ // Need this when debugging, as it is necessary to attach gdb to
+ // the running java process -- "gdb java" doesn't work
+ // printf("Going to sleep for 10 seconds\n");
+ // sleep(10);
+
+ return (jboolean) JNI_TRUE;
+}
+
+static void NewtScreen_dump() {
+#ifdef VERBOSE_ON
+ NSArray *screens = [UIScreen screens];
+ int i;
+ for(i=0; i<[screens count]; i++) {
+ UIScreen * screen = (UIScreen *) [screens objectAtIndex: i];
+ CGRect screenFrame = [screen frame];
+ CGRect screenVisibleFrame = [screen visibleFrame];
+ CGFloat pixelScale = 1.0; // default
+ pixelScale = [screen scale]; // HiDPI scaling
+ UIWindowDepth depth = [screen depth]; // an (int) value!
+ DBG_PRINT( "UIScreen #%d (%p): Frame %lf/%lf %lfx%lf (vis %lf/%lf %lfx%lf), scale %lf, depth %d\n",
+ i, screen,
+ screenFrame.origin.x, screenFrame.origin.y, screenFrame.size.width, screenFrame.size.height,
+ screenVisibleFrame.origin.x, screenVisibleFrame.origin.y, screenVisibleFrame.size.width, screenVisibleFrame.size.height,
+ pixelScale, depth);
+ }
+#endif
+}
+
+// Duplicate each Mode by all possible rotations (4):
+// For each real-mode: [mode, 0], [mode, 90], [mode, 180], [mode, 270]
+#define ROTMODES_PER_REALMODE 1
+
+/*
+ * Class: jogamp_newt_driver_ios_ScreenDriver
+ * Method: getMonitorDeviceIds0
+ * Signature: ()I
+ */
+JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_ios_ScreenDriver_getMonitorDeviceIds0
+ (JNIEnv *env, jobject obj)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ NSArray *screens = [UIScreen screens];
+ int count = [screens count];
+ int32_t displayIDs[count];
+ int i;
+ for(i=0; i<count; i++) {
+ // UIScreen * screen = (UIScreen *) [screens objectAtIndex: i];
+ displayIDs[i] = i; // TODO no unique screen name?
+ }
+ jintArray properties = (*env)->NewIntArray(env, count);
+ if (properties == NULL) {
+ NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", count);
+ }
+ (*env)->SetIntArrayRegion(env, properties, 0, count, displayIDs);
+ [pool release];
+ return properties;
+}
+
+/*
+ * Class: jogamp_newt_driver_ios_ScreenDriver
+ * Method: getMonitorProps0
+ * Signature: (I)[I
+ */
+JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_ios_ScreenDriver_getMonitorProps0
+ (JNIEnv *env, jobject obj, jint crt_id)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+
+#ifdef DBG_PERF
+ struct timespec t0, t1, td;
+ long td_ms;
+ timespec_now(&t0);
+#endif
+
+#ifdef DBG_PERF
+ timespec_now(&t1); timespec_subtract(&td, &t1, &t0); td_ms = timespec_milliseconds(&td);
+ fprintf(stderr, "MacScreen_getMonitorProps0.1: %ld ms\n", td_ms); fflush(NULL);
+#endif
+ NSArray *screens = [UIScreen screens];
+ int count = [screens count];
+ UIScreen * screen = (UIScreen *) [screens objectAtIndex: crt_id];
+ if( NULL == screen ) {
+ [pool release];
+ return NULL;
+ }
+ BOOL isPrimary = 0 == crt_id;
+#ifdef DBG_PERF
+ timespec_now(&t1); timespec_subtract(&td, &t1, &t0); td_ms = timespec_milliseconds(&td);
+ fprintf(stderr, "MacScreen_getMonitorProps0.2: %ld ms\n", td_ms); fflush(NULL);
+#endif
+
+ UIScreenMode * screenMode = [screen currentMode];
+ CGSize sizeMM = CGSizeMake(161.0, 228.0); // TODO ???
+#ifdef DBG_PERF
+ timespec_now(&t1); timespec_subtract(&td, &t1, &t0); td_ms = timespec_milliseconds(&td);
+ fprintf(stderr, "MacScreen_getMonitorProps0.3: %ld ms\n", td_ms); fflush(NULL);
+#endif
+
+ CGRect dBounds = [screen bounds];
+#ifdef VERBOSE_ON
+ DBG_PRINT( "getMonitorProps0: crt_id 0x%X (prim %d), top-left displayBounds[%d/%d %dx%d]\n",
+ (int)crt_id, isPrimary,
+ (int)dBounds.origin.x, (int)dBounds.origin.y, (int)dBounds.size.width, (int)dBounds.size.height);
+#endif
+
+ jsize propCount = MIN_MONITOR_DEVICE_PROPERTIES - 1 - NUM_MONITOR_MODE_PROPERTIES;
+ jint prop[ propCount ];
+ int offset = 0;
+ prop[offset++] = propCount;
+ prop[offset++] = crt_id;
+ prop[offset++] = 0; // isClone
+ prop[offset++] = isPrimary ? 1 : 0; // isPrimary
+ prop[offset++] = (jint) sizeMM.width;
+ prop[offset++] = (jint) sizeMM.height;
+ prop[offset++] = (jint) dBounds.origin.x; // rotated viewport x (pixel units, will be fixed in java code)
+ prop[offset++] = (jint) dBounds.origin.y; // rotated viewport y (pixel units, will be fixed in java code)
+ prop[offset++] = (jint) dBounds.size.width; // rotated viewport width (pixel units, will be fixed in java code)
+ prop[offset++] = (jint) dBounds.size.height; // rotated viewport height (pixel units, will be fixed in java code)
+ prop[offset++] = (jint) dBounds.origin.x; // rotated viewport x (window units, will be fixed in java code)
+ prop[offset++] = (jint) dBounds.origin.y; // rotated viewport y (window units, will be fixed in java code)
+ prop[offset++] = (jint) dBounds.size.width; // rotated viewport width (window units, will be fixed in java code)
+ prop[offset++] = (jint) dBounds.size.height; // rotated viewport height (window units, will be fixed in java code)
+
+ jintArray properties = (*env)->NewIntArray(env, propCount);
+ if (properties == NULL) {
+ NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", propCount);
+ }
+ (*env)->SetIntArrayRegion(env, properties, 0, propCount, prop);
+
+ [pool release];
+
+ return properties;
+}
+
+/*
+ * Class: jogamp_newt_driver_ios_ScreenDriver
+ * Method: getMonitorMode0
+ * Signature: (II)[I
+ */
+JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_ios_ScreenDriver_getMonitorMode0
+ (JNIEnv *env, jobject obj, jint crt_id, jint mode_idx)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+
+ NSArray<UIScreen*> *screens = [UIScreen screens];
+ int count = [screens count];
+ UIScreen * screen = (UIScreen *) [screens objectAtIndex: crt_id];
+ if( NULL == screen ) {
+ [pool release];
+ return NULL;
+ }
+ CGFloat pixelScale = 1.0; // default
+NS_DURING
+ // Available >= 10.7
+ pixelScale = [screen scale]; // HiDPI scaling
+NS_HANDLER
+NS_ENDHANDLER
+
+ NSArray<UIScreenMode*> *availableModes = [screen availableModes];
+ int numberOfAvailableModes = [availableModes count];
+ CFIndex numberOfAvailableModesRots = ROTMODES_PER_REALMODE * numberOfAvailableModes;
+ int currentCCWRot = 0;
+ jint ccwRot = 0;
+ int nativeId = 0;
+ UIScreenMode * mode = NULL;
+
+#ifdef VERBOSE_ON
+ if(0 >= mode_idx) {
+ // only for current mode (-1) and first mode (scanning)
+ DBG_PRINT( "getScreenMode0: crtID 0x%X (s %p, pscale %lf), mode %d, avail: %d/%d, current rot %d ccw\n",
+ (uint32_t)displayID, screen, pixelScale, (int)mode_idx, (int)numberOfAvailableModes, (int)numberOfAvailableModesRots, currentCCWRot);
+ }
+#endif
+
+ if(numberOfAvailableModesRots<=mode_idx) {
+ // n/a - end of modes
+ DBG_PRINT( "getScreenMode0: end of modes: mode %d, avail: %d/%d\n",
+ (int)mode_idx, (int)numberOfAvailableModes, (int)numberOfAvailableModesRots);
+ [pool release];
+ return NULL;
+ } else if(-1 < mode_idx) {
+ // only at initialization time, where index >= 0
+ nativeId = mode_idx / ROTMODES_PER_REALMODE;
+ ccwRot = mode_idx % ROTMODES_PER_REALMODE * 90;
+ mode = (UIScreenMode*) [availableModes objectAtIndex: nativeId];
+ } else {
+ // current mode
+ mode = [screen currentMode];
+ ccwRot = 0;
+ nativeId = 0;
+ }
+ // mode = CGDisplayModeRetain(mode); // 10.6 on CGDisplayModeRef
+
+ CGSize mSize = [mode size];
+ int mWidth = (int)mSize.width;
+ int mHeight = (int)mSize.height;
+ if( -1 == mode_idx ) {
+ mWidth *= (int)pixelScale; // accomodate HiDPI
+ mHeight *= (int)pixelScale; // accomodate HiDPI
+ }
+
+ // swap width and height, since OSX reflects rotated dimension, we don't
+ if ( 90 == currentCCWRot || 270 == currentCCWRot ) {
+ int tempWidth = mWidth;
+ mWidth = mHeight;
+ mHeight = tempWidth;
+ }
+
+ jint prop[ NUM_MONITOR_MODE_PROPERTIES_ALL ];
+ int propIndex = 0;
+
+ int refreshRate = 60; // TODO
+ int fRefreshRate = ( 0 < refreshRate ) ? refreshRate : 60; // default .. (experienced on OSX 10.6.8)
+ prop[propIndex++] = NUM_MONITOR_MODE_PROPERTIES_ALL;
+ prop[propIndex++] = mWidth;
+ prop[propIndex++] = mHeight;
+ prop[propIndex++] = 32; // TODO CGDDGetModeBitsPerPixel(mode);
+ prop[propIndex++] = fRefreshRate * 100; // Hz*100
+ prop[propIndex++] = 0; // flags
+ prop[propIndex++] = nativeId;
+ prop[propIndex++] = ccwRot;
+
+ DBG_PRINT( "getScreenMode0: Mode %d/%d (%d): %dx%d, %d bpp, %d / %d Hz, nativeId %d, rot %d ccw\n",
+ (int)mode_idx, (int)numberOfAvailableModesRots, (int)numberOfAvailableModes,
+ (int)prop[1], (int)prop[2], (int)prop[3],
+ (int)prop[4], refreshRate, (int)prop[6], (int)prop[7]);
+
+ jintArray properties = (*env)->NewIntArray(env, NUM_MONITOR_MODE_PROPERTIES_ALL);
+ if (properties == NULL) {
+ NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size %d", NUM_MONITOR_MODE_PROPERTIES_ALL);
+ }
+ (*env)->SetIntArrayRegion(env, properties, 0, NUM_MONITOR_MODE_PROPERTIES_ALL, prop);
+
+ // CGDisplayModeRelease(mode); // 10.6 on CGDisplayModeRef
+ [pool release];
+
+ return properties;
+}
+
+/*
+ * Class: jogamp_newt_driver_ios_ScreenDriver
+ * Method: setMonitorMode0
+ * Signature: (III)Z
+ */
+JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_ios_ScreenDriver_setMonitorMode0
+ (JNIEnv *env, jobject object, jint crt_id, jint nativeId, jint ccwRot)
+{
+ return false;
+}
+
+/*
+ * Class: jogamp_newt_driver_ios_WindowDriver
+ * Method: initIDs
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_ios_WindowDriver_initIDs0
+ (JNIEnv *env, jclass clazz)
+{
+ static int initialized = 0;
+
+ if(initialized) return JNI_TRUE;
+ initialized = 1;
+
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+
+ NewtScreen_dump();
+
+ jclass c;
+ c = (*env)->FindClass(env, ClazzNamePoint);
+ if(NULL==c) {
+ NewtCommon_FatalError(env, "FatalError Java_jogamp_newt_driver_ios_WindowDriver_initIDs0: can't find %s", ClazzNamePoint);
+ }
+ pointClz = (jclass)(*env)->NewGlobalRef(env, c);
+ (*env)->DeleteLocalRef(env, c);
+ if(NULL==pointClz) {
+ NewtCommon_FatalError(env, "FatalError Java_jogamp_newt_driver_ios_WindowDriver_initIDs0: can't use %s", ClazzNamePoint);
+ }
+ pointCstr = (*env)->GetMethodID(env, pointClz, ClazzAnyCstrName, ClazzNamePointCstrSignature);
+ if(NULL==pointCstr) {
+ NewtCommon_FatalError(env, "FatalError Java_jogamp_newt_driver_ios_WindowDriver_initIDs0: can't fetch %s.%s %s",
+ ClazzNamePoint, ClazzAnyCstrName, ClazzNamePointCstrSignature);
+ }
+
+ // Need this when debugging, as it is necessary to attach gdb to
+ // the running java process -- "gdb java" doesn't work
+ // printf("Going to sleep for 10 seconds\n");
+ // sleep(10);
+
+ BOOL res = [NewtUIWindow initNatives: env forClass: clazz];
+ [pool release];
+
+ return (jboolean) res;
+}
+
+/**
+ * Class: jogamp_newt_driver_ios_WindowDriver
+ * Method: createView0
+ * Signature: (IIII)J
+ */
+JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_ios_WindowDriver_createView0
+ (JNIEnv *env, jobject jthis, jint x, jint y, jint w, jint h)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+
+ DBG_PRINT( "createView0 - %p (this), %d/%d %dx%d (START)\n",
+ (void*)(intptr_t)jthis, (int)x, (int)y, (int)w, (int)h);
+
+ CGRect rectView = CGRectMake(0, 0, w, h);
+ NewtUIView *myView = [[NewtUIView alloc] initWithFrame: rectView] ;
+ DBG_PRINT( "createView0.X - new view: %p\n", myView);
+
+ [pool release];
+
+ return (jlong) (intptr_t) myView;
+}
+
+/**
+ * Method creates a deferred un-initialized Window, hence no special invocation required inside method.
+ *
+ * Class: jogamp_newt_driver_ios_WindowDriver
+ * Method: createWindow0
+ * Signature: (IIIIZIIJ)J
+ */
+JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_ios_WindowDriver_createWindow0
+ (JNIEnv *env, jobject jthis, jint x, jint y, jint w, jint h,
+ jboolean fullscreen, jint styleMask, jint bufferingType, jlong jview)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ NewtUIView* myView = (NewtUIView*) (intptr_t) jview ;
+
+ DBG_PRINT( "createWindow0 - %p (this), %d/%d %dx%d, fs %d, style %X, buffType %X, view %p (START)\n",
+ (void*)(intptr_t)jthis, (int)x, (int)y, (int)w, (int)h, (int)fullscreen,
+ (int)styleMask, (int)bufferingType, myView);
+ (void)myView;
+
+ if (fullscreen) {
+ // TODO styleMask = NSBorderlessWindowMask;
+ }
+ CGRect rectWin = CGRectMake(x, y, w, h);
+
+ // Allocate the window
+ NewtUIWindow* myWindow = [[NewtUIWindow alloc] initWithContentRect: rectWin
+ styleMask: (NSUInteger) styleMask
+ backing: 0 // TODO (NSBackingStoreType) bufferingType
+ defer: YES
+ isFullscreenWindow: fullscreen];
+ // DBG_PRINT( "createWindow0.1 - %p, isVisible %d\n", myWindow, [myWindow isVisible]);
+
+ DBG_PRINT( "createWindow0.X - %p, isVisible %d\n", myWindow, [myWindow isVisible]);
+
+ [pool release];
+
+ return (jlong) ((intptr_t) myWindow);
+}
+
+JNIEXPORT jint JNICALL Java_jogamp_newt_driver_ios_WindowDriver_getDisplayID0(JNIEnv *env, jobject jthis, jlong window) {
+ NewtUIWindow* myWindow = (NewtUIWindow*) ((intptr_t) window);
+ if( NULL == myWindow ) {
+ DBG_PRINT( "getDisplayID0 - NULL NEWT win - abort\n");
+ return 0;
+ }
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ UIScreen *screen = [myWindow screen];
+ int32_t displayID = 0; // TODO (int32_t)NewtScreen_getCGDirectDisplayIDByUIScreen(screen);
+ [pool release];
+ return (jint) displayID;
+}
+
+/**
+ * Method is called on Main-Thread, hence no special invocation required inside method.
+ *
+ * Class: jogamp_newt_driver_ios_WindowDriver
+ * Method: initWindow0
+ * Signature: (JJIIIIFZZZJ)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_ios_WindowDriver_initWindow0
+ (JNIEnv *env, jobject jthis, jlong parent, jlong window, jint x, jint y, jint w, jint h, jfloat reqPixelScale,
+ jboolean opaque, jboolean atop, jboolean abottom, jboolean visible, jlong jview)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ NewtUIWindow* myWindow = (NewtUIWindow*) ((intptr_t) window);
+ NewtUIView* myView = (NewtUIView*) (intptr_t) jview ;
+ BOOL fullscreen = myWindow->isFullscreenWindow;
+
+ DBG_PRINT( "initWindow0 - %p (this), %p (parent), %p (window), %d/%d %dx%d, reqPixScale %f, opaque %d, atop %d, abottom %d, fs %d, visible %d, view %p (START)\n",
+ (void*)(intptr_t)jthis, (void*)(intptr_t)parent, myWindow, (int)x, (int)y, (int)w, (int)h, (float)reqPixelScale,
+ (int) opaque, (int)atop, (int)abottom, (int)fullscreen, (int)visible, myView);
+
+ // TODO [myWindow setReleasedWhenClosed: NO]; // We control UIWindow destruction!
+ // TODO [myWindow setPreservesContentDuringLiveResize: NO];
+
+ NSObject* nsParentObj = (NSObject*) ((intptr_t) parent);
+ UIWindow* parentWindow = NULL;
+ UIView* parentView = NULL;
+ if( nsParentObj != NULL && [nsParentObj isKindOfClass:[UIWindow class]] ) {
+ parentWindow = (UIWindow*) nsParentObj;
+ parentView = (UIView*)nsParentObj;
+ DBG_PRINT( "initWindow0 - Parent is UIWindow : %p (win) -> %p (view) \n", parentWindow, parentView);
+ } else if( nsParentObj != NULL && [nsParentObj isKindOfClass:[UIView class]] ) {
+ parentView = (UIView*) nsParentObj;
+ parentWindow = [parentView window];
+ DBG_PRINT( "initWindow0 - Parent is UIView : %p -(view) > %p (win) \n", parentView, parentWindow);
+ } else {
+ DBG_PRINT( "initWindow0 - Parent is neither UIWindow nor UIView : %p\n", nsParentObj);
+ }
+ DBG_PRINT( "initWindow0 - is visible.1: %d\n", [myWindow isVisible]);
+
+ // Remove animations for child windows
+ if(NULL != parentWindow) {
+ [UIView setAnimationsEnabled: NO];
+ }
+
+#ifdef VERBOSE_ON
+ int dbgIdx = 1;
+#endif
+ if(opaque) {
+ [myWindow setOpaque: YES];
+ DBG_PRINT( "initWindow0.%d\n", dbgIdx++);
+ if (!fullscreen) {
+ // TODO [myWindow setShowsResizeIndicator: YES];
+ }
+ DBG_PRINT( "initWindow0.%d\n", dbgIdx++);
+ } else {
+ [myWindow setOpaque: NO];
+ [myWindow setBackgroundColor: [UIColor clearColor]];
+ }
+ [myWindow setAlwaysOn: atop bottom:abottom];
+
+ // specify we want mouse-moved events
+ // TODO [myWindow setAcceptsMouseMovedEvents:YES];
+
+ DBG_PRINT( "initWindow0.%d - %p view %p, isVisible %d\n",
+ dbgIdx++, myWindow, myView, [myWindow isVisible]);
+
+ // Set the content view
+ changeContentView(env, jthis, parentView, myWindow, myView, NO);
+ // TODO [myWindow setInitialFirstResponder: myView];
+
+ DBG_PRINT( "initWindow0.%d - %p view %p, isVisible %d\n",
+ dbgIdx++, myWindow, myView, [myWindow isVisible]);
+
+ if(NULL!=parentWindow) {
+ [myWindow attachToParent: parentWindow];
+ }
+
+ DBG_PRINT( "initWindow0.%d - %p view %p, isVisible %d, visible %d\n",
+ dbgIdx++, myWindow, myView, [myWindow isVisible], visible);
+
+ // Immediately re-position this window based on an upper-left coordinate system
+ setWindowClientTopLeftPointAndSize(myWindow, x, y, w, h, NO);
+
+ DBG_PRINT( "initWindow0.%d - %p view %p, isVisible %d\n",
+ dbgIdx++, myWindow, myView, [myWindow isVisible]);
+
+ // TODO [myWindow setAllowsConcurrentViewDrawing: YES];
+
+ DBG_PRINT( "initWindow0.%d - %p view %p, isVisible %d\n",
+ dbgIdx++, myWindow, myView, [myWindow isVisible]);
+
+ // TODO [myView setCanDrawConcurrently: YES];
+
+ DBG_PRINT( "initWindow0.%d - %p view %p, isVisible %d\n",
+ dbgIdx++, myWindow, myView, [myWindow isVisible]);
+
+ // visible on front
+ if( visible ) {
+ // TODO [myWindow orderFront: myWindow];
+ }
+
+ DBG_PRINT( "initWindow0.%d - %p view %p, isVisible %d\n",
+ dbgIdx++, myWindow, myView, [myWindow isVisible]);
+
+ // force surface creation
+ // [myView lockFocus];
+ // [myView unlockFocus];
+
+ // Set the next responder to be the window so that we can forward
+ // right mouse button down events
+ // TODO [myView setNextResponder: myWindow];
+
+ DBG_PRINT( "initWindow0.%d - %p (this), %p (parent): new window: %p, view %p\n",
+ dbgIdx++, (void*)(intptr_t)jthis, (void*)(intptr_t)parent, myWindow, myView);
+
+ [myView setDestroyNotifySent: false];
+ setJavaWindowObject(env, jthis, myView, YES);
+
+ DBG_PRINT( "initWindow0.%d - %p (this), %p (parent): new window: %p, view %p\n",
+ dbgIdx++, (void*)(intptr_t)jthis, (void*)(intptr_t)parent, myWindow, myView);
+
+NS_DURING
+ if( fullscreen ) {
+ /**
+ * See Bug 914: We don't use exclusive fullscreen anymore (capturing display)
+ * allowing ALT-TAB to allow process/app switching!
+ * Shall have no penalty on modern GPU and is also recommended, see bottom box @
+ * <https://developer.apple.com/library/mac/documentation/graphicsimaging/Conceptual/QuartzDisplayServicesConceptual/Articles/DisplayCapture.html>
+ *
+ UIScreen *myScreen = NewtScreen_getUIScreenByCoord(x, y);
+ if( NULL != myScreen ) {
+ if ( [myView respondsToSelector:@selector(enterFullScreenMode:withOptions:)] ) {
+ // Available >= 10.5 - Makes the menubar disapear
+ [myView enterFullScreenMode: myScreen withOptions:NULL];
+ }
+ }
+ */
+ if( myWindow->hasPresentationSwitch ) {
+ DBG_PRINT( "initWindow0.%d - %p view %p, setPresentationOptions 0x%X\n",
+ dbgIdx++, myWindow, myView, (int)myWindow->fullscreenPresentationOptions);
+ // TODO [NSApp setPresentationOptions: myWindow->fullscreenPresentationOptions];
+ }
+ }
+NS_HANDLER
+NS_ENDHANDLER
+
+ DBG_PRINT( "initWindow0.%d - %p (this), %p (parent): new window: %p, view %p\n",
+ dbgIdx++, (void*)(intptr_t)jthis, (void*)(intptr_t)parent, myWindow, myView);
+
+ [pool release];
+ DBG_PRINT( "initWindow0.X - %p (this), %p (parent): new window: %p, view %p\n",
+ (void*)(intptr_t)jthis, (void*)(intptr_t)parent, myWindow, myView);
+}
+
+/**
+ * Method is called on Main-Thread, hence no special invocation required inside method.
+ *
+ * Class: jogamp_newt_driver_ios_WindowDriver
+ * Method: setPixelScale0
+ * Signature: (JJF)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_ios_WindowDriver_setPixelScale0
+ (JNIEnv *env, jobject jthis, jlong window, jlong view, jfloat reqPixelScale)
+{
+ NewtUIWindow* myWindow = (NewtUIWindow*) ((intptr_t) window);
+ if( NULL == myWindow ) {
+ DBG_PRINT( "setPixelScale0 - NULL NEWT win - abort\n");
+ return;
+ }
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ NewtUIView* myView = (NewtUIView*) (intptr_t) view ;
+#ifdef VERBOSE_ON
+ int dbgIdx = 1;
+#endif
+ DBG_PRINT( "setPixelScale0 - %p (this), %p (window), view %p, reqPixScale %f (START)\n",
+ (void*)(intptr_t)jthis, myWindow, myView, (float)reqPixelScale);
+ (void)myWindow;
+
+ DBG_PRINT( "setPixelScale0.%d - %p (this), window: %p, view %p\n",
+ dbgIdx++, (void*)(intptr_t)jthis, myWindow, myView);
+
+ [pool release];
+ DBG_PRINT( "setPixelScale0.X - %p (this), window: %p, view %p\n",
+ (void*)(intptr_t)jthis, myWindow, myView);
+}
+
+/**
+ * Method is called on Main-Thread, hence no special invocation required inside method.
+ *
+ * Class: jogamp_newt_driver_ios_WindowDriver
+ * Method: close0
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_ios_WindowDriver_close0
+ (JNIEnv *env, jobject unused, jlong window)
+{
+ NewtUIWindow* mWin = (NewtUIWindow*) ((intptr_t) window);
+ if( NULL == mWin ) {
+ DBG_PRINT( "windowClose.0 - NULL NEWT win - abort\n");
+ return;
+ }
+ BOOL isNSWin = [mWin isKindOfClass:[UIWindow class]];
+ BOOL isNewtWin = [mWin isKindOfClass:[NewtUIWindow class]];
+ UIWindow *pWin = NULL; // TODO [mWin parentWindow];
+ DBG_PRINT( "windowClose.0 - %p [isUIWindow %d, isNewtWin %d], parent %p\n", mWin, isNSWin, isNewtWin, pWin);
+ (void)isNSWin; // silence
+ if( !isNewtWin ) {
+ NewtCommon_throwNewRuntimeException(env, "Not a NewtUIWindow %p", mWin);
+ return;
+ }
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ NewtUIView* mView = (NewtUIView *)mWin; // TODO [mWin contentView];
+ BOOL fullscreen = mWin->isFullscreenWindow;
+ BOOL destroyNotifySent, isUIView, isNewtUIView;
+ if( NULL != mView ) {
+ isUIView = [mView isKindOfClass:[UIView class]];
+ isNewtUIView = [mView isKindOfClass:[NewtUIView class]];
+ destroyNotifySent = isNewtUIView ? [mView getDestroyNotifySent] : false;
+ } else {
+ isUIView = false;
+ isNewtUIView = false;
+ destroyNotifySent = false;
+ }
+
+ DBG_PRINT( "windowClose.0 - %p, destroyNotifySent %d, view %p [isUIView %d, isNewtUIView %d], fullscreen %d, parent %p\n",
+ mWin, destroyNotifySent, mView, isUIView, isNewtUIView, (int)fullscreen, pWin);
+
+ [mWin setRealized: NO];
+
+ if( isNewtUIView ) {
+ // cleanup view
+ [mView setDestroyNotifySent: true];
+ setJavaWindowObject(env, NULL, mView, NO);
+ }
+
+NS_DURING
+ /**
+ * See Bug 914: We don't use exclusive fullscreen anymore (capturing display)
+ * See initWindow0(..) above ..
+ if(NULL!=mView) {
+ 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!
+ DBG_PRINT( "windowClose.1a - %p view %p, fullscreen %d, hasPresSwitch %d, defaultPresentationOptions 0x%X\n",
+ mWin, mView, (int)fullscreen, (int)mWin->hasPresentationSwitch, (int)mWin->defaultPresentationOptions);
+
+ if( fullscreen && mWin->hasPresentationSwitch ) {
+ DBG_PRINT( "windowClose.1b - %p view %p, setPresentationOptions 0x%X\n",
+ mWin, mView, (int)mWin->defaultPresentationOptions);
+ // TODO [NSApp setPresentationOptions: mWin->defaultPresentationOptions];
+ }
+NS_HANDLER
+NS_ENDHANDLER
+
+ if(NULL!=pWin) {
+ [mWin detachFromParent: pWin];
+ }
+ // TODO [mWin orderOut: mWin];
+ [mWin setHidden: YES]; // no release, close n/a, .. well: ref count counts :-(
+
+ DBG_PRINT( "windowClose.2 - %p view %p, parent %p\n", mWin, mView, pWin);
+
+ [mWin release];
+
+ DBG_PRINT( "windowClose.Xp\n");
+
+ [pool release];
+}
+
+/*
+ * Class: Java_jogamp_newt_driver_ios_WindowDriver
+ * Method: lockSurface0
+ * Signature: (JJ)Z
+ */
+JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_ios_WindowDriver_lockSurface0
+ (JNIEnv *env, jclass clazz, jlong window, jlong view)
+{
+ NewtUIWindow *mWin = (NewtUIWindow*) ((intptr_t) window);
+ if(NO == [mWin isRealized]) {
+ return JNI_FALSE;
+ }
+ NewtUIView * mView = (NewtUIView *) ((intptr_t) view);
+ return [mView softLock] == YES ? JNI_TRUE : JNI_FALSE;
+ /** deadlocks, since we render independent of focus
+ return [mView lockFocusIfCanDraw] == YES ? JNI_TRUE : JNI_FALSE; */
+}
+
+/*
+ * Class: Java_jogamp_newt_driver_ios_WindowDriver
+ * Method: unlockSurface0
+ * Signature: (JJ)Z
+ */
+JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_ios_WindowDriver_unlockSurface0
+ (JNIEnv *env, jclass clazz, jlong window, jlong view)
+{
+ // NewtUIWindow *mWin = (NewtUIWindow*) ((intptr_t) window);
+ (void) window;
+ NewtUIView * mView = (NewtUIView *) ((intptr_t) view);
+ return [mView softUnlock] == YES ? JNI_TRUE : JNI_FALSE;
+ /** deadlocks, since we render independent of focus
+ [mView unlockFocus]; */
+}
+
+/*
+ * Class: jogamp_newt_driver_ios_WindowDriver
+ * Method: requestFocus0
+ * Signature: (JZ)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_ios_WindowDriver_requestFocus0
+ (JNIEnv *env, jobject window, jlong w, jboolean force)
+{
+ UIWindow* mWin = (UIWindow*) ((intptr_t) w);
+ if( NULL == mWin ) {
+ DBG_PRINT( "requestFocus - NULL NEWT win - abort\n");
+ return;
+ }
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+#ifdef VERBOSE_ON
+ BOOL hasFocus = [mWin isKeyWindow];
+#endif
+ DBG_PRINT( "requestFocus - window: %p, force %d, hasFocus %d (START)\n", mWin, force, hasFocus);
+
+ // TODO [mWin setAcceptsMouseMovedEvents: YES];
+ // TODO [mWin makeFirstResponder: nil];
+ // TODO [mWin orderFrontRegardless];
+ [mWin makeKeyWindow];
+
+ DBG_PRINT( "requestFocus - window: %p, force %d (END)\n", mWin, force);
+
+ [pool release];
+}
+
+/*
+ * Class: jogamp_newt_driver_ios_WindowDriver
+ * Method: resignFocus0
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_ios_WindowDriver_resignFocus0
+ (JNIEnv *env, jobject window, jlong w)
+{
+ UIWindow* mWin = (UIWindow*) ((intptr_t) w);
+ if( NULL == mWin ) {
+ DBG_PRINT( "resignFocus0 - NULL NEWT win - abort\n");
+ return;
+ }
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ UIWindow* pWin = NULL; // TODO [mWin parentWindow];
+ BOOL hasFocus = [mWin isKeyWindow];
+
+ DBG_PRINT( "resignFocus0 - window: %p, parent %p, hasFocus %d (START)\n", mWin, pWin, hasFocus );
+ if( hasFocus ) {
+ if(NULL != pWin) {
+ // [mWin makeFirstResponder: pWin];
+ [pWin makeKeyWindow];
+ } else {
+ [pWin resignKeyWindow];
+ }
+ }
+ DBG_PRINT( "resignFocus0 - window: %p (END)\n", mWin);
+
+ [pool release];
+}
+
+/*
+ * Class: jogamp_newt_driver_ios_WindowDriver
+ * Method: orderFront0
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_ios_WindowDriver_orderFront0
+ (JNIEnv *env, jobject unused, jlong window)
+{
+ UIWindow* mWin = (UIWindow*) ((intptr_t) window);
+ if( NULL == mWin ) {
+ DBG_PRINT( "orderFront0 - NULL NEWT win - abort\n");
+ return;
+ }
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ UIWindow* pWin = NULL; // TODO [mWin parentWindow];
+
+ DBG_PRINT( "orderFront0 - window: (parent %p) %p visible %d (START)\n", pWin, mWin, [mWin isVisible]);
+
+ if( NULL == pWin ) {
+ // TODO [mWin orderFrontRegardless];
+ } else {
+ // TODO [mWin orderWindow: UIWindowAbove relativeTo: [pWin windowNumber]];
+ }
+
+ DBG_PRINT( "orderFront0 - window: (parent %p) %p (END)\n", pWin, mWin);
+
+ [pool release];
+}
+
+/*
+ * Class: jogamp_newt_driver_ios_WindowDriver
+ * Method: orderOut
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_ios_WindowDriver_orderOut0
+ (JNIEnv *env, jobject unused, jlong window)
+{
+ UIWindow* mWin = (UIWindow*) ((intptr_t) window);
+ if( NULL == mWin ) {
+ DBG_PRINT( "orderOut0 - NULL NEWT win - abort\n");
+ return;
+ }
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ UIWindow* pWin = NULL; // TODO [mWin parentWindow];
+
+ DBG_PRINT( "orderOut0 - window: (parent %p) %p visible %d (START)\n", pWin, mWin, [mWin isVisible]);
+
+ if( NULL == pWin ) {
+ // TODO [mWin orderOut: mWin];
+ } else {
+ // TODO [mWin orderWindow: UIWindowOut relativeTo: [pWin windowNumber]];
+ }
+
+ DBG_PRINT( "orderOut0 - window: (parent %p) %p (END)\n", pWin, mWin);
+
+ [pool release];
+}
+
+/*
+ * Class: jogamp_newt_driver_ios_WindowDriver
+ * Method: setTitle0
+ * Signature: (JLjava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_ios_WindowDriver_setTitle0
+ (JNIEnv *env, jobject unused, jlong window, jstring title)
+{
+ UIWindow* win = (UIWindow*) ((intptr_t) window);
+ if( NULL == win ) {
+ DBG_PRINT( "setTitle0 - NULL NEWT win - abort\n");
+ return;
+ }
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+
+ DBG_PRINT( "setTitle0 - window: %p (START)\n", win);
+
+ NSString* str = jstringToNSString(env, title);
+ [str autorelease];
+ // TODO [win setTitle: str];
+
+ DBG_PRINT( "setTitle0 - window: %p (END)\n", win);
+
+ [pool release];
+}
+
+/*
+ * Class: jogamp_newt_driver_ios_WindowDriver
+ * Method: contentView0
+ * Signature: (J)J
+ */
+JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_ios_WindowDriver_contentView0
+ (JNIEnv *env, jobject unused, jlong window)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ UIWindow* win = (UIWindow*) ((intptr_t) window);
+ UIView* nsView = (UIView*)win; // TODO [win contentView];
+ NewtUIView* newtView = NULL;
+
+ if( [nsView isKindOfClass:[NewtUIView class]] ) {
+ newtView = (NewtUIView *) nsView;
+ }
+
+ DBG_PRINT( "contentView0 - window: %p, view: %p, newtView %p\n", win, nsView, newtView);
+
+ jlong res = (jlong) ((intptr_t) nsView);
+
+ [pool release];
+ return res;
+}
+
+/**
+ * Method is called on Main-Thread, hence no special invocation required inside method.
+ *
+ * Class: jogamp_newt_driver_ios_WindowDriver
+ * Method: changeContentView
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_ios_WindowDriver_changeContentView0
+ (JNIEnv *env, jobject jthis, jlong parentWindowOrView, jlong window, jlong jview)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+
+ NewtUIView* newView = (NewtUIView *) ((intptr_t) jview);
+ NewtUIWindow* win = (NewtUIWindow*) ((intptr_t) window);
+
+ DBG_PRINT( "changeContentView0.0 - win %p, view (%p,%d)\n",
+ win, newView, getRetainCount(newView));
+
+ NSObject *nsParentObj = (NSObject*) ((intptr_t) parentWindowOrView);
+ UIView* pView = NULL;
+ if( NULL != nsParentObj ) {
+ if( [nsParentObj isKindOfClass:[UIWindow class]] ) {
+ UIWindow * pWin = (UIWindow*) nsParentObj;
+ pView = (UIView*)pWin; // TODO [pWin contentView];
+ } else if( [nsParentObj isKindOfClass:[UIView class]] ) {
+ pView = (UIView*) nsParentObj;
+ }
+ }
+
+ changeContentView(env, jthis, pView, win, newView, YES);
+
+ DBG_PRINT( "changeContentView0.X\n");
+
+ [pool release];
+}
+
+/*
+ * Class: jogamp_newt_driver_ios_WindowDriver
+ * Method: updateSizePosInsets0
+ * Signature: (JZ)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_ios_WindowDriver_updateSizePosInsets0
+ (JNIEnv *env, jobject jthis, jlong window, jboolean defer)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ NewtUIWindow* mWin = (NewtUIWindow*) ((intptr_t) window);
+
+ DBG_PRINT( "updateSizePosInsets - window: %p, defer %d (START)\n", mWin, (int)defer);
+
+ [mWin updateSizePosInsets: env jwin:jthis defer:defer];
+
+ DBG_PRINT( "updateSizePosInsets - window: %p, defer %d (END)\n", mWin, (int)defer);
+
+ [pool release];
+}
+
+/*
+ * Class: jogamp_newt_driver_ios_WindowDriver
+ * Method: setWindowClientTopLeftPointAndSize0
+ * Signature: (JIIIIZ)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_ios_WindowDriver_setWindowClientTopLeftPointAndSize0
+ (JNIEnv *env, jobject unused, jlong window, jint x, jint y, jint w, jint h, jboolean display)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+ NewtUIWindow* mWin = (NewtUIWindow*) ((intptr_t) window);
+
+ DBG_PRINT( "setWindowClientTopLeftPointAndSize - window: %p (START)\n", mWin);
+
+ setWindowClientTopLeftPointAndSize(mWin, x, y, w, h, display);
+
+ DBG_PRINT( "setWindowClientTopLeftPointAndSize - window: %p (END)\n", mWin);
+
+ [pool release];
+}
+
+/*
+ * Class: jogamp_newt_driver_ios_WindowDriver
+ * Method: setWindowClientTopLeftPoint0
+ * Signature: (JIIZ)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_ios_WindowDriver_setWindowClientTopLeftPoint0
+ (JNIEnv *env, jobject unused, jlong window, jint x, jint y, jboolean display)
+{
+ NewtUIWindow* mWin = (NewtUIWindow*) ((intptr_t) window);
+ if( NULL == mWin ) {
+ DBG_PRINT( "setWindowClientTopLeftPoint - NULL NEWT win - abort\n");
+ return;
+ }
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+
+ DBG_PRINT( "setWindowClientTopLeftPoint - window: %p (START)\n", mWin);
+
+ setWindowClientTopLeftPoint(mWin, x, y, display);
+
+ DBG_PRINT( "setWindowClientTopLeftPoint - window: %p (END)\n", mWin);
+
+ [pool release];
+}
+
+/*
+ * Class: jogamp_newt_driver_ios_WindowDriver
+ * Method: getLocationOnScreen0
+ * Signature: (JII)Lcom/jogamp/nativewindow/util/Point;
+ */
+JNIEXPORT jobject JNICALL Java_jogamp_newt_driver_ios_WindowDriver_getLocationOnScreen0
+ (JNIEnv *env, jclass unused, jlong win, jint src_x, jint src_y)
+{
+ NewtUIWindow *mWin = (NewtUIWindow*) (intptr_t) win;
+ if( NULL == mWin ) {
+ DBG_PRINT( "getLocationOnScreen0 - NULL NEWT win - abort\n");
+ return NULL;
+ }
+ if( ![mWin isKindOfClass:[NewtUIWindow class]] ) {
+ NewtCommon_throwNewRuntimeException(env, "Not a NewtUIWindow %p", mWin);
+ return NULL;
+ }
+ CGPoint p0 = [mWin getLocationOnScreen: CGPointMake(src_x, src_y)];
+ return (*env)->NewObject(env, pointClz, pointCstr, (jint)p0.x, (jint)p0.y);
+}
+
diff --git a/src/newt/native/JVM_JNI8.c b/src/newt/native/JVM_JNI8.c
new file mode 100644
index 000000000..c023cb0f0
--- /dev/null
+++ b/src/newt/native/JVM_JNI8.c
@@ -0,0 +1,42 @@
+/**
+ * Copyright 2019 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.
+ */
+
+#include <stdio.h> //required by android to identify NULL
+#include <jni.h>
+
+#if defined (JNI_VERSION_1_8)
+
+JNIEXPORT jint JNICALL JNI_OnLoad_newt(JavaVM *vm, void *reserved) {
+ return JNI_VERSION_1_8;
+}
+
+JNIEXPORT void JNICALL JNI_OnUnload_newt(JavaVM *vm, void *reserved) {
+}
+
+#endif /* defined (JNI_VERSION_1_8) */
+
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableDelegateOnOffscrnCapsNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableDelegateOnOffscrnCapsNEWT.java
index 4f666920a..c24254b89 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableDelegateOnOffscrnCapsNEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableDelegateOnOffscrnCapsNEWT.java
@@ -235,11 +235,11 @@ public class TestGLAutoDrawableDelegateOnOffscrnCapsNEWT extends UITestCase {
@Test
public void testAvailableInfo() {
- GLDrawableFactory f = GLDrawableFactory.getDesktopFactory();
+ GLDrawableFactory f = GLDrawableFactory.getFactory(false);
if(null != f) {
System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString());
}
- f = GLDrawableFactory.getEGLFactory();
+ f = GLDrawableFactory.getFactory(true);
if(null != f) {
System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString());
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryES2OffscrnCapsNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryES2OffscrnCapsNEWT.java
index 7cef9e448..1ca099cb1 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryES2OffscrnCapsNEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryES2OffscrnCapsNEWT.java
@@ -155,18 +155,6 @@ public class TestGLAutoDrawableFactoryES2OffscrnCapsNEWT extends UITestCase {
}
@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 testES2OffScreenAutoDblBuf() throws InterruptedException {
final GLCapabilities reqGLCaps = getCaps(GLProfile.GLES2);
if(null == reqGLCaps) return;
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryGL2OffscrnCapsNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryGL2OffscrnCapsNEWT.java
index a23e81d69..26ef2b0af 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryGL2OffscrnCapsNEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryGL2OffscrnCapsNEWT.java
@@ -155,18 +155,6 @@ public class TestGLAutoDrawableFactoryGL2OffscrnCapsNEWT extends UITestCase {
}
@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;
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryGLProfileDeviceNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryGLProfileDeviceNEWT.java
index 9934ae862..0e132526c 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryGLProfileDeviceNEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryGLProfileDeviceNEWT.java
@@ -129,21 +129,21 @@ public class TestGLAutoDrawableFactoryGLProfileDeviceNEWT extends UITestCase {
@Test
public void test00AvailableInfo() {
- GLDrawableFactory f = GLDrawableFactory.getDesktopFactory();
+ GLDrawableFactory f = GLDrawableFactory.getFactory(false);
if(null != f) {
System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString());
}
- f = GLDrawableFactory.getEGLFactory();
+ f = GLDrawableFactory.getFactory(true);
if(null != f) {
System.err.println(JoglVersion.getDefaultOpenGLInfo(f.getDefaultDevice(), null, true).toString());
}
}
@Test
- public void test01ES2OnEGL() throws InterruptedException {
- final GLDrawableFactory factory = GLDrawableFactory.getEGLFactory();
+ public void test01ES2OnMobile() throws InterruptedException {
+ final GLDrawableFactory factory = GLDrawableFactory.getFactory(true);
if( null == factory ) {
- System.err.println("EGL Factory n/a");
+ System.err.println("Mobile Factory n/a");
return;
}
final AbstractGraphicsDevice prodDevice = factory.getDefaultDevice();
@@ -163,10 +163,10 @@ public class TestGLAutoDrawableFactoryGLProfileDeviceNEWT extends UITestCase {
}
@Test
- public void test02GLOnEGL() throws InterruptedException {
- final GLDrawableFactory factory = GLDrawableFactory.getEGLFactory();
+ public void test02GLOnMobile() throws InterruptedException {
+ final GLDrawableFactory factory = GLDrawableFactory.getFactory(true);
if( null == factory ) {
- System.err.println("EGL Factory n/a");
+ System.err.println("Mobile Factory n/a");
return;
}
final AbstractGraphicsDevice prodDevice = factory.getDefaultDevice();
@@ -189,7 +189,7 @@ public class TestGLAutoDrawableFactoryGLProfileDeviceNEWT extends UITestCase {
@Test
public void test11ES2OnDesktop() throws InterruptedException {
- final GLDrawableFactory deskFactory = GLDrawableFactory.getDesktopFactory();
+ final GLDrawableFactory deskFactory = GLDrawableFactory.getFactory(false);
if( null == deskFactory ) {
System.err.println("Desktop Factory n/a");
return;
@@ -217,7 +217,7 @@ public class TestGLAutoDrawableFactoryGLProfileDeviceNEWT extends UITestCase {
@Test
public void test12GLOnDesktop() throws InterruptedException {
- final GLDrawableFactory factory = GLDrawableFactory.getDesktopFactory();
+ final GLDrawableFactory factory = GLDrawableFactory.getFactory(false);
if( null == factory ) {
System.err.println("Desktop Factory n/a");
return;
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryGLnBitmapCapsNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryGLnBitmapCapsNEWT.java
index 6a7b09be1..efbb847db 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryGLnBitmapCapsNEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableFactoryGLnBitmapCapsNEWT.java
@@ -146,18 +146,6 @@ public class TestGLAutoDrawableFactoryGLnBitmapCapsNEWT extends UITestCase {
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());
- }
- }
-
// Might be reduced to !double-buff
@Test
public void testGL2OffScreenBitmapDblBuf() throws InterruptedException {
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
index 6138ce6ee..f521f45ec 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableGLCanvasOnOffscrnCapsAWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableGLCanvasOnOffscrnCapsAWT.java
@@ -245,18 +245,6 @@ public class TestGLAutoDrawableGLCanvasOnOffscrnCapsAWT extends UITestCase {
}
@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;
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
index 34148501d..d4bd227db 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT.java
@@ -188,18 +188,6 @@ public class TestGLAutoDrawableGLWindowOnOffscrnCapsNEWT extends UITestCase {
}
@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 testGL2OnScreenSglBuf() throws InterruptedException {
final GLCapabilities reqGLCaps = getCaps(GLProfile.GL2);
if(null == reqGLCaps) return;
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
index ce968751e..339d27a3e 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableNewtCanvasAWTOnOffscrnCapsAWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLAutoDrawableNewtCanvasAWTOnOffscrnCapsAWT.java
@@ -258,18 +258,6 @@ public class TestGLAutoDrawableNewtCanvasAWTOnOffscrnCapsAWT extends UITestCase
}
@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;
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLProfile00NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLProfile00NEWT.java
index edb681d01..987dcaf9c 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLProfile00NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLProfile00NEWT.java
@@ -67,7 +67,7 @@ public class TestGLProfile00NEWT extends UITestCase {
public void test11DumpDesktopGLInfo() throws InterruptedException {
Assert.assertTrue("JOGL is not initialized ...", GLProfile.isInitialized());
System.err.println("Desktop");
- final GLDrawableFactory desktopFactory = GLDrawableFactory.getDesktopFactory();
+ final GLDrawableFactory desktopFactory = GLDrawableFactory.getFactory(false);
if( null != desktopFactory ) {
System.err.println(JoglVersion.getDefaultOpenGLInfo(desktopFactory.getDefaultDevice(), null, false));
System.err.println(Platform.getNewline()+Platform.getNewline()+Platform.getNewline());
@@ -77,12 +77,12 @@ public class TestGLProfile00NEWT extends UITestCase {
}
@Test
- public void test12DumpEGLGLInfo() throws InterruptedException {
+ public void test12DumpMobileGLInfo() throws InterruptedException {
Assert.assertTrue("JOGL is not initialized ...", GLProfile.isInitialized());
- System.err.println("EGL");
- final GLDrawableFactory eglFactory = GLDrawableFactory.getEGLFactory();
- if( null != eglFactory ) {
- System.err.println(JoglVersion.getDefaultOpenGLInfo(eglFactory.getDefaultDevice(), null, false));
+ System.err.println("ES");
+ final GLDrawableFactory esFactory = GLDrawableFactory.getFactory(true);
+ if( null != esFactory ) {
+ System.err.println(JoglVersion.getDefaultOpenGLInfo(esFactory.getDefaultDevice(), null, false));
} else {
System.err.println("\tNULL");
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLProfile01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLProfile01NEWT.java
index 2921e8102..f2f35012d 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLProfile01NEWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestGLProfile01NEWT.java
@@ -54,11 +54,11 @@ public class TestGLProfile01NEWT extends GLProfile0XBase {
System.err.println(JoglVersion.getInstance());
System.err.println(NewtVersion.getInstance());
- final GLDrawableFactory deskFactory = GLDrawableFactory.getDesktopFactory();
+ final GLDrawableFactory deskFactory = GLDrawableFactory.getFactory(false);
if( null != deskFactory ) {
System.err.println(JoglVersion.getDefaultOpenGLInfo(deskFactory.getDefaultDevice(), null, true).toString());
}
- final GLDrawableFactory eglFactory = GLDrawableFactory.getEGLFactory();
+ final GLDrawableFactory eglFactory = GLDrawableFactory.getFactory(true);
if( null != eglFactory ) {
System.err.println(JoglVersion.getDefaultOpenGLInfo(eglFactory.getDefaultDevice(), null, true).toString());
}
diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedExternalContextAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedExternalContextAWT.java
index 0987b2978..3c2607249 100644
--- a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedExternalContextAWT.java
+++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestSharedExternalContextAWT.java
@@ -47,7 +47,7 @@ public class TestSharedExternalContextAWT {
System.err.println("Master Thread Start: "+Thread.currentThread().getName());
final GLProfile glProfile = GLProfile.getDefault();
final GLCapabilities caps = new GLCapabilities(glProfile);
- final GLAutoDrawable buffer = GLDrawableFactory.getDesktopFactory().createOffscreenAutoDrawable(
+ final GLAutoDrawable buffer = GLDrawableFactory.getFactory(false).createOffscreenAutoDrawable(
GLProfile.getDefaultDevice(), caps, null, 512, 512
);
// The listener will set up the context sharing in its init() method.
@@ -127,7 +127,7 @@ public class TestSharedExternalContextAWT {
System.err.println(); System.err.println();
System.err.println("Master (orig) Ct: "+drawable.getContext());
// Create the external context on the caller thread.
- final GLContext master = GLDrawableFactory.getDesktopFactory().createExternalGLContext();
+ final GLContext master = GLDrawableFactory.getFactory(false).createExternalGLContext();
System.err.println(); System.err.println();
System.err.println("External Context: "+master);
@@ -137,7 +137,7 @@ public class TestSharedExternalContextAWT {
// FIXME: We actually need to hook into GLContext make-current lock
// masterLock.lock();
try {
- fOffscreenDrawable = GLDrawableFactory.getDesktopFactory().createOffscreenAutoDrawable(
+ fOffscreenDrawable = GLDrawableFactory.getFactory(false).createOffscreenAutoDrawable(
GLProfile.getDefaultDevice(),
new GLCapabilities(GLProfile.getDefault()),
null, // new DefaultGLCapabilitiesChooser(),