diff options
author | Sven Gothel <[email protected]> | 2019-06-23 08:03:04 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2019-06-23 08:03:04 +0200 |
commit | bba73bc096250a3c7fc036d84b1ea054d1b70b06 (patch) | |
tree | ed02575eac2a46bd49627444dcce972946ae8d2e /src/jogl/classes/jogamp/opengl | |
parent | 154e91978498d8b6db9ce34a1f06b298bcf4c361 (diff) |
iOS: Initial working commit supporting iOS (ipad pro 11)
using our OpenJFK 9 x86_64 and arm64 build.
Test demo class is 'com.jogamp.opengl.demos.ios.Hello',
residing in the new demo folder 'src/demos/com/jogamp/opengl/demos/ios/Hello.java'.
This commit does not yet include a working NEWT
specialization for iOS, but it shall followup soon.
Instead this commit demonstrates JOGL operating on
native UIWindow, UIView and CAEAGLLayer as provided by
Nativewindow's IOSUtil.
Test Video https://www.youtube.com/watch?v=Z4lUQNFTGMI
+++
Notable bug: The FBO used and sharing the COLORBUFFER RENDERBUFFER
memory resources with CAEAGLLayer to be displayed in the UIView
seemingly cannot handle GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT24
or GL_DEPTH_COMPONENT32 depth buffer - none at all (Device + Simulation).
Therefor the default demo GLEventListener chosen here
don't require a depth buffer ;-)
This issue can hopefully be mitigated with other means
than using a flat FBO sink similar to FBO multisampling.
Diffstat (limited to 'src/jogl/classes/jogamp/opengl')
13 files changed, 1444 insertions, 11 deletions
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); |