diff options
Diffstat (limited to 'src/jogl')
20 files changed, 1867 insertions, 114 deletions
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; +} + |