diff options
Diffstat (limited to 'src/jogl/classes/jogamp/opengl/ios/eagl/IOSEAGLDrawableFactory.java')
-rw-r--r-- | src/jogl/classes/jogamp/opengl/ios/eagl/IOSEAGLDrawableFactory.java | 453 |
1 files changed, 453 insertions, 0 deletions
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(); + } + +} |