aboutsummaryrefslogtreecommitdiffstats
path: root/src
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 /src
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.
Diffstat (limited to 'src')
-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
84 files changed, 10796 insertions, 217 deletions
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(),