diff options
Diffstat (limited to 'src')
6 files changed, 239 insertions, 150 deletions
diff --git a/src/demos/com/jogamp/opengl/demos/ios/Hello.java b/src/demos/com/jogamp/opengl/demos/ios/Hello.java index d593dd3bc..9982d7d1f 100644 --- a/src/demos/com/jogamp/opengl/demos/ios/Hello.java +++ b/src/demos/com/jogamp/opengl/demos/ios/Hello.java @@ -37,6 +37,8 @@ import com.jogamp.nativewindow.UpstreamWindowHookMutableSizePos; import com.jogamp.common.GlueGenVersion; import com.jogamp.opengl.JoglVersion; import com.jogamp.opengl.demos.es2.RedSquareES2; +import com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.util.AnimatorBase; import jogamp.nativewindow.WrappedWindow; import jogamp.nativewindow.ios.IOSUtil; @@ -61,9 +63,9 @@ public class Hello { public static void main(final String[] args) { int width = 832, height = 480; // ipad pro 11: 2388x1668 px (scale: 2) - int fboDepthBits = 0; // CAEAGLLayer fails with depth 16 + 24 in Simulation + int fboDepthBits = -1; // CAEAGLLayer fails with depth 16 + 24 in Simulation; -1 means don't change boolean exitJVM = false; - String demoName = "com.jogamp.opengl.demos.es2.LandscapeES2"; + String demoName = "com.jogamp.opengl.demos.es2.GearsES2"; for(int i=0; i<args.length; i++) { if(args[i].equals("-exit")) { exitJVM = true; @@ -119,9 +121,9 @@ public class Hello { // 1) Config .. final GLProfile glp = GLProfile.getGL2ES2(); final GLCapabilities reqCaps = new GLCapabilities(glp); - reqCaps.setOnscreen(true); - reqCaps.setDoubleBuffered(false); - reqCaps.setDepthBits(fboDepthBits); + if( 0 <= fboDepthBits) { + reqCaps.setDepthBits(fboDepthBits); + } System.out.println("Requested GL Caps: "+reqCaps); final GLDrawableFactoryImpl factory = (GLDrawableFactoryImpl) GLDrawableFactory.getFactory(glp); @@ -170,14 +172,20 @@ public class Hello { System.out.println("Choosen demo "+demo.getClass().getName()); glad.addGLEventListener(demo); - for(int i=0; i<60*10; i++) { // 10s w/ 60fps - glad.display(); // force native context creation + final Animator animator = new Animator(); + // animator.setExclusiveContext(exclusiveContext); + animator.setUpdateFPSFrames(60, System.err); + animator.add(glad); + animator.start(); + + for(int i=0; i<10; i++) { // 10s try { - Thread.sleep(16); + Thread.sleep(1000); } catch (final InterruptedException e) { e.printStackTrace(); } } + animator.stop(); } finally { if( null != glad ) { diff --git a/src/jogl/classes/com/jogamp/opengl/FBObject.java b/src/jogl/classes/com/jogamp/opengl/FBObject.java index 00a560fc7..a559445c7 100644 --- a/src/jogl/classes/com/jogamp/opengl/FBObject.java +++ b/src/jogl/classes/com/jogamp/opengl/FBObject.java @@ -42,7 +42,6 @@ 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; @@ -165,6 +164,32 @@ public class FBObject { } } }; + /** + * Interface abstraction to allow custom definitions of {@link Attachment}'s storage. + * <p> + * Please see {@link #setStorage(GL, Attachment)} for details. + * </p> + */ + public static interface StorageDefinition { + /** + * Set or create the {@link Attachment}'s storage after generating its name and binding it to the target. + * Typical examples for standard definitions as implemented in {@link Attachment} specializations are: + * <pre> + * // Renderbuffer (Color, Debt, Stencil, ..) storage definition w/o multisamples + * gl.glRenderbufferStorage(GL.GL_RENDERBUFFER, a.format, a.getWidth(), a.getHeight()); + * // Renderbuffer (Color, Debt, Stencil, ..) storage definition with multisamples + * gl.glRenderbufferStorageMultisample(GL.GL_RENDERBUFFER, samples, a.format, a.getWidth(), a.getHeight()); + * // TextureAttachment + * gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, format, getWidth(), getHeight(), 0, dataFormat, dataType, null); + * </pre> + * The storage is setup within {@link Attachment#initialize(GL)} and hence the {@link Attachment} + * instance's {@link Attachment#setStorageDefinition(StorageDefinition)}. + * + * @param gl current {@link GL} instance + * @param a instance of the {@link Attachment} this {@link StorageDefinition} has been assigned to via {@link Attachment#setStorageDefinition(StorageDefinition)}. + */ + public void setStorage(final GL gl, final Attachment a); + } /** immutable type [{@link #COLOR}, {@link #DEPTH}, {@link #STENCIL}, {@link #COLOR_TEXTURE}, {@link #DEPTH_TEXTURE}, {@link #STENCIL_TEXTURE} ] */ public final Type type; @@ -176,6 +201,9 @@ public class FBObject { private int name; + /** Every implementation needs to have set their default instance via {@link #setStorageDefinition(StorageDefinition). */ + private StorageDefinition storageDefinition; + protected Attachment(final Type type, final int iFormat, final int width, final int height, final int name) { this.type = type; this.format = iFormat; @@ -185,6 +213,17 @@ public class FBObject { } /** + * Override implementation default {@link StorageDefinition} + * @see {@link StorageDefinition#setStorage(GL, Attachment)} + */ + public void setStorageDefinition(final StorageDefinition sd) { this.storageDefinition = sd; } + + /** + * Accessor to call {@link StorageDefinition#setStorage(GL, Attachment)} within {@link #initialize(GL)} for implementations of {@link Attachment}. + */ + protected final void setStorage(final GL gl) { storageDefinition.setStorage(gl, this); } + + /** * Writes the internal format to the given GLCapabilities object. * @param caps the destination for format bits * @param rgba8Avail whether rgba8 is available @@ -372,6 +411,7 @@ public class FBObject { */ public RenderAttachment(final Type type, final int iFormat, final int samples, final int width, final int height, final int name) { super(validateType(type), iFormat, width, height, name); + this.setStorageDefinition(defStorageDefinition); this.samples = samples; } @@ -432,11 +472,7 @@ public class FBObject { setName(name[0]); gl.glBindRenderbuffer(GL.GL_RENDERBUFFER, getName()); - if( samples > 0 ) { - ((GL2ES3)gl).glRenderbufferStorageMultisample(GL.GL_RENDERBUFFER, samples, format, getWidth(), getHeight()); - } else { - gl.glRenderbufferStorage(GL.GL_RENDERBUFFER, format, getWidth(), getHeight()); - } + setStorage(gl); if( checkError ) { final int glerr = gl.glGetError(); if(GL.GL_NO_ERROR != glerr) { @@ -451,6 +487,16 @@ public class FBObject { } return init; } + private final StorageDefinition defStorageDefinition = new StorageDefinition() { + @Override + public void setStorage(final GL gl, final Attachment a) { + // a == this.super for this instance + if( samples > 0 ) { + gl.glRenderbufferStorageMultisample(GL.GL_RENDERBUFFER, samples, format, getWidth(), getHeight()); + } else { + gl.glRenderbufferStorage(GL.GL_RENDERBUFFER, format, getWidth(), getHeight()); + } + } }; @Override public void free(final GL gl) { @@ -482,49 +528,6 @@ public class FBObject { public final TextureAttachment getTextureAttachment() { throw new GLException("Not a TextureAttachment, but ColorAttachment"); } @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 */ @@ -548,6 +551,7 @@ public class FBObject { public TextureAttachment(final Type type, final int iFormat, final int width, final int height, final int dataFormat, final int dataType, final int magFilter, final int minFilter, final int wrapS, final int wrapT, final int name) { super(validateType(type), iFormat, width, height, name); + this.setStorageDefinition(defStorageDefinition); this.dataFormat = dataFormat; this.dataType = dataType; this.magFilter = magFilter; @@ -604,7 +608,7 @@ public class FBObject { int glerr = gl.glGetError(); if(GL.GL_NO_ERROR == glerr) { preTexImage2D = false; - gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, format, getWidth(), getHeight(), 0, dataFormat, dataType, null); + setStorage(gl); glerr = gl.glGetError(); } if(GL.GL_NO_ERROR != glerr) { @@ -613,7 +617,7 @@ public class FBObject { throw new GLException("GL Error "+toHexString(glerr)+" while creating (pre TexImage2D "+preTexImage2D+") "+this); } } else { - gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, format, getWidth(), getHeight(), 0, dataFormat, dataType, null); + setStorage(gl); } if(DEBUG) { System.err.println("Attachment.init.X: "+this); @@ -621,6 +625,12 @@ public class FBObject { } return init; } + private final StorageDefinition defStorageDefinition = new StorageDefinition() { + @Override + public void setStorage(final GL gl, final Attachment a) { + // a == this.super for this instance + gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, format, getWidth(), getHeight(), 0, dataFormat, dataType, null); + } }; @Override public void free(final GL gl) { diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java b/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java index 2e108d3ce..fad77d76d 100644 --- a/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java +++ b/src/jogl/classes/jogamp/opengl/GLDrawableFactoryImpl.java @@ -55,6 +55,7 @@ import com.jogamp.nativewindow.OffscreenLayerSurface; import com.jogamp.nativewindow.ProxySurface; import com.jogamp.nativewindow.MutableSurface; import com.jogamp.nativewindow.UpstreamSurfaceHook; +import com.jogamp.opengl.FBObject; import com.jogamp.opengl.GLAutoDrawable; import com.jogamp.opengl.GLCapabilities; import com.jogamp.opengl.GLCapabilitiesChooser; @@ -68,7 +69,6 @@ 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; @@ -76,9 +76,6 @@ 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 Independent Bitmaps on Windows, pixmaps on X11). Direct access to @@ -264,6 +261,36 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { */ public abstract GLDynamicLookupHelper getGLDynamicLookupHelper(final int majorVersion, final int contextOptions); + /** + * Extends definition of {@link FBObject.Attachment.StorageDefinition} + * for general onscreen FBO layer storage requirements. + * <p> + * Implementations are allowed to specialize {@link FBObject.Attachment.StorageDefinition} + * for the special use-case of: + * <ul> + * <li>Using an underlying {@link FBObject} for onscreen rendering, hence {@link #createGLDrawable(NativeSurface)}, and</li> + * <li>Using a special <i>color renderbuffer storage</i> instead of the default {@link FBObject} <i>internal offscreen</i> storage.</li> + * </ul> + * </p> + * @see {@link FBObject.Attachment.StorageDefinition} + * @see {@link FBObject.Attachment#setStorageDefinition(FBObject.Attachment.StorageDefinition)} + */ + public static interface OnscreenFBOColorbufferStorageDefinition extends FBObject.Attachment.StorageDefinition { + /** + * Returns true if underlying implementation supports double buffering + */ + public boolean isDoubleBufferSupported(); + /** + * Texture-Unit to be used for the FBO colorbuffer. + * <p> + * If a valid unit is returned, i.e. >= 0, a color texturebuffer is used, otherwise a color renderbuffer. + * </p> + */ + public int getTextureUnit(); + } + + protected OnscreenFBOColorbufferStorageDefinition getOnscreenFBOColorbufStorageDef() { return null; } + //--------------------------------------------------------------------------- // Dispatching GLDrawable construction in respect to the NativeSurface Capabilities // @@ -273,29 +300,41 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { throw new IllegalArgumentException("Null target"); } final MutableGraphicsConfiguration config = (MutableGraphicsConfiguration) target.getGraphicsConfiguration(); + final GLCapabilitiesImmutable reqCaps = (GLCapabilitiesImmutable) config.getRequestedCapabilities(); final GLCapabilitiesImmutable chosenCaps = (GLCapabilitiesImmutable) config.getChosenCapabilities(); final AbstractGraphicsDevice adevice = config.getScreen().getDevice(); final boolean isFBOAvailable = GLContext.isFBOAvailable(adevice, chosenCaps.getGLProfile()); GLDrawable result = null; adevice.lock(); try { + final OnscreenFBOColorbufferStorageDefinition onscreenFBOColorbufStorageDef = getOnscreenFBOColorbufStorageDef(); final boolean forceOnscreenFBOLayer; - final boolean useFBORendertarget; - if( chosenCaps.isOnscreen() && Platform.OSType.IOS == PlatformPropsImpl.OS_TYPE ) // FIXME: avoid hardcoding? - { + final int fboTextureUnit; + if( reqCaps.isOnscreen() && null != onscreenFBOColorbufStorageDef) { forceOnscreenFBOLayer = true; - useFBORendertarget = true; + fboTextureUnit = onscreenFBOColorbufStorageDef.getTextureUnit(); } else { forceOnscreenFBOLayer = false; - useFBORendertarget = false; + fboTextureUnit = 0; // assume texture unit 0 (default) is used at all } final OffscreenLayerSurface ols = NativeWindowFactory.getOffscreenLayerSurface(target, true); if(null != ols || forceOnscreenFBOLayer ) { - final GLCapabilitiesImmutable chosenCapsMod = GLGraphicsConfigurationUtil.fixOffscreenGLCapabilities(chosenCaps, this, adevice); - - // layered surface -> Offscreen/[FBO|PBuffer] - if( !chosenCapsMod.isFBO() && !chosenCapsMod.isPBuffer() ) { - throw new GLException("Neither FBO nor Pbuffer is available for "+chosenCapsMod+", "+target); + final GLCapabilitiesImmutable chosenCapsMod0 = GLGraphicsConfigurationUtil.fixOffscreenGLCapabilities(chosenCaps, this, adevice); + final GLCapabilitiesImmutable chosenCapsMod; + if( forceOnscreenFBOLayer && !onscreenFBOColorbufStorageDef.isDoubleBufferSupported() ) { + chosenCapsMod = GLGraphicsConfigurationUtil.fixDoubleBufferedGLCapabilities(chosenCapsMod0, false); + } else { + chosenCapsMod = chosenCapsMod0; + } + if( forceOnscreenFBOLayer ) { + if( !chosenCapsMod.isFBO() ) { + throw new GLException("FBO is not available for "+chosenCapsMod+", "+target); + } + } else { + // layered surface -> Offscreen/[FBO|PBuffer] + if( !chosenCapsMod.isFBO() && !chosenCapsMod.isPBuffer() ) { + throw new GLException("Neither FBO nor Pbuffer is available for "+chosenCapsMod+", "+target); + } } config.setChosenCapabilities(chosenCapsMod); if( null != ols ) { @@ -303,10 +342,11 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { } if(DEBUG) { System.err.println("GLDrawableFactoryImpl.createGLDrawable -> OnscreenDrawable -> Offscreen-Layer"); + System.err.println("requestedCaps: "+reqCaps); 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("forceOnscreenFBOLayer: **** "+forceOnscreenFBOLayer+", fboTextureUnit "+fboTextureUnit); System.err.println("Target: **** "+target); ExceptionUtils.dumpStack(System.err); } @@ -314,7 +354,11 @@ 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, useFBORendertarget?-1:0); + final GLFBODrawableImpl fboDrawable = (GLFBODrawableImpl) createFBODrawableImpl(target, chosenCapsMod, fboTextureUnit); + if( forceOnscreenFBOLayer ) { + fboDrawable.setColorRenderbufferStorageDef(onscreenFBOColorbufStorageDef); + } + result = fboDrawable; } else { result = createOffscreenDrawableImpl(target); } @@ -523,7 +567,13 @@ public abstract class GLDrawableFactoryImpl extends GLDrawableFactory { } } - /** Creates a platform independent unrealized FBO offscreen GLDrawable */ + /** + * Creates a platform independent unrealized FBO offscreen GLDrawable + * @param dummySurface used for dummy-drawable and as surface for {@link GLFBODrawable} + * @param fboCaps + * @param textureUnit if valid, i.e. >= 0, signals using a color texturebuffer {@link GLFBODrawable#FBOMODE_USE_TEXTURE}, otherwise a color renderbuffer is used. + * @return + */ protected final GLFBODrawable createFBODrawableImpl(final NativeSurface dummySurface, final GLCapabilitiesImmutable fboCaps, final int textureUnit) { final GLDrawableImpl dummyDrawable = createOnscreenDrawableImpl(dummySurface); return new GLFBODrawableImpl(this, dummyDrawable, dummySurface, fboCaps, textureUnit); diff --git a/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java b/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java index 64cca7bdd..ea226b407 100644 --- a/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java +++ b/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java @@ -76,6 +76,7 @@ public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable { // private DoubleBufferMode doubleBufferMode; // TODO: Add or remove TEXTURE (only) DoubleBufferMode support + private FBObject.Attachment.StorageDefinition colorRenderbufferStorageDef; private SwapBufferContext swapBufferContext; public static interface SwapBufferContext { @@ -87,7 +88,7 @@ public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable { * @param parent * @param surface * @param fboCaps the requested FBO capabilities - * @param textureUnit if valid, i.e. >= 0, signals {@link #FBOMODE_USE_TEXTURE}, otherwise a color renderbuffer is assumed + * @param textureUnit if valid, i.e. >= 0, signals using a color texturebuffer {@link GLFBODrawable#FBOMODE_USE_TEXTURE}, otherwise a color renderbuffer is used. */ protected GLFBODrawableImpl(final GLDrawableFactoryImpl factory, final GLDrawableImpl parent, final NativeSurface surface, final GLCapabilitiesImmutable fboCaps, final int textureUnit) { @@ -100,6 +101,7 @@ public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable { this.texUnit = textureUnit>=0 ? textureUnit : 0; this.samples = fboCaps.getNumSamples(); this.fboResetQuirk = false; + this.colorRenderbufferStorageDef = null; this.swapBufferContext = null; } @@ -117,7 +119,11 @@ public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable { throw new InternalError("Sample number mismatch: "+samples+", fbos["+idx+"] "+fbo); } if(samples > 0 || !useTexture) { - fbo.attachColorbuffer(gl, 0, useAlpha); + final FBObject.ColorAttachment ca = fbo.createColorAttachment(useAlpha); + if( null != colorRenderbufferStorageDef ) { + ca.setStorageDefinition(colorRenderbufferStorageDef); + } + fbo.attachColorbuffer(gl, 0, ca); } else { fbo.attachTexture2D(gl, 0, useAlpha); } @@ -135,7 +141,11 @@ public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable { { ssink.init(gl, width, height, 0); if( !useTexture ) { - ssink.attachColorbuffer(gl, 0, useAlpha); + final FBObject.ColorAttachment ca = ssink.createColorAttachment(useAlpha); + if( null != colorRenderbufferStorageDef ) { + ca.setStorageDefinition(colorRenderbufferStorageDef); + } + ssink.attachColorbuffer(gl, 0, ca); } else { ssink.attachTexture2D(gl, 0, useAlpha); } @@ -249,6 +259,24 @@ public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable { swapBufferContext = sbc; } + /** + * Inject custom {@link FBObject.Attachment.StorageDefinition} specialization for the use-case of: + * <ul> + * <li>Using a special <i>color renderbuffer storage</i> instead of the default {@link FBObject} <i>internal offscreen</i> storage.</li> + * </ul> + * @see {@link FBObject.Attachment.StorageDefinition} + * @see {@link FBObject.Attachment#setStorageDefinition(FBObject.Attachment.StorageDefinition)} + */ + public final void setColorRenderbufferStorageDef(final FBObject.Attachment.StorageDefinition sd) { + colorRenderbufferStorageDef = sd; + if(DEBUG) { + System.err.println("EAGL.FBODrawable: setColorRenderbufferStorageDef"); + } + } + public final boolean hasColorRenderbufferStorageDef(final FBObject.Attachment.StorageDefinition sd) { + return sd == colorRenderbufferStorageDef; + } + private final void reset(final GL gl, final int idx, final int width, final int height, final int samples, final boolean useAlpha, final int depthBits, final int stencilBits) { if( !fboResetQuirk ) { diff --git a/src/jogl/classes/jogamp/opengl/ios/eagl/IOSEAGLContext.java b/src/jogl/classes/jogamp/opengl/ios/eagl/IOSEAGLContext.java index 57c20d465..e3b7a64a7 100644 --- a/src/jogl/classes/jogamp/opengl/ios/eagl/IOSEAGLContext.java +++ b/src/jogl/classes/jogamp/opengl/ios/eagl/IOSEAGLContext.java @@ -34,19 +34,18 @@ 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.GLDrawableFactoryImpl; import jogamp.opengl.GLDrawableImpl; import jogamp.opengl.GLDynamicLookupHelper; import jogamp.opengl.GLFBODrawableImpl; +import jogamp.opengl.GLDrawableFactoryImpl.OnscreenFBOColorbufferStorageDefinition; import jogamp.opengl.GLFBODrawableImpl.SwapBufferContext; import jogamp.opengl.DummyGLExtProcAddressTable; import jogamp.opengl.ios.eagl.IOSEAGLDrawable.GLBackendType; @@ -100,8 +99,6 @@ public class IOSEAGLContext extends GLContextImpl // CGL extension functions. private DummyGLExtProcAddressTable cglExtProcAddressTable; - private int lastWidth, lastHeight; - protected IOSEAGLContext(final GLDrawableImpl drawable, final GLContext shareWith) { super(drawable, shareWith); @@ -194,11 +191,6 @@ public class IOSEAGLContext extends GLContextImpl @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); } @@ -221,50 +213,48 @@ public class IOSEAGLContext extends GLContextImpl @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; - } + // NOTE to resize: GLFBODrawableImpl.resetSize(GL) called from many + // high level instances in the GLDrawable* space, + // e.g. GLAutoDrawableBase's defaultWindowResizedOp(..) } @Override protected void associateDrawable(final boolean bound) { // context stuff depends on drawable stuff - if(bound) { + final GLFBODrawableImpl fboDrawable; + final boolean taggedOnscreenFBOEAGLLayer; + { final GLDrawableImpl drawable = getDrawableImpl(); - if( drawable instanceof GLFBODrawableImpl ) { - final GLFBODrawableImpl fboDrawable = (GLFBODrawableImpl) drawable; + final GLDrawableFactoryImpl factory = drawable.getFactoryImpl(); + final IOSEAGLDrawableFactory iosFactory = (factory instanceof IOSEAGLDrawableFactory) ? (IOSEAGLDrawableFactory) factory : null; + final OnscreenFBOColorbufferStorageDefinition onscreenFBOColorbufStorageDef = (null != iosFactory) ? iosFactory.getOnscreenFBOColorbufStorageDef() : null; + + fboDrawable = (drawable instanceof GLFBODrawableImpl) ? (GLFBODrawableImpl)drawable : null; + taggedOnscreenFBOEAGLLayer = (null != fboDrawable && null != onscreenFBOColorbufStorageDef) ? + fboDrawable.hasColorRenderbufferStorageDef(onscreenFBOColorbufStorageDef) : false; + } + if( DEBUG ) { + System.err.println(getThreadName() + ": IOSEAGLContext.associateDrawable(bound "+bound+"): taggedOnscreenFBOEAGLLayer "+taggedOnscreenFBOEAGLLayer+ + ", hasFBODrawable "+(null != fboDrawable)+", drawable: "+getDrawableImpl().getClass().getName()); + } + if(bound) { + if( taggedOnscreenFBOEAGLLayer ) { + // Done in GLDrawableFactory.createGDrawable(..) for onscreen drawables: + // fboDrawable.setColorRenderbufferStorageDef(iosFactory.getOnscreenFBOColorbufStorageDef()); 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"); + if( taggedOnscreenFBOEAGLLayer ) { + EAGL.eaglBindDrawableStorageToRenderbuffer(contextHandle, GL.GL_RENDERBUFFER, 0); + } } } @@ -361,40 +351,6 @@ public class IOSEAGLContext extends GLContextImpl @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; diff --git a/src/jogl/classes/jogamp/opengl/ios/eagl/IOSEAGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/ios/eagl/IOSEAGLDrawableFactory.java index 3c3f1edb8..71904d1a6 100644 --- a/src/jogl/classes/jogamp/opengl/ios/eagl/IOSEAGLDrawableFactory.java +++ b/src/jogl/classes/jogamp/opengl/ios/eagl/IOSEAGLDrawableFactory.java @@ -41,6 +41,7 @@ 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.FBObject; import com.jogamp.opengl.GL; import com.jogamp.opengl.GLCapabilities; import com.jogamp.opengl.GLCapabilitiesChooser; @@ -52,6 +53,7 @@ import com.jogamp.opengl.GLProfile; import jogamp.nativewindow.WrappedSurface; import jogamp.nativewindow.ios.IOSDummyUpstreamSurfaceHook; +import jogamp.nativewindow.ios.IOSUtil; import jogamp.opengl.GLContextImpl; import jogamp.opengl.GLDrawableFactoryImpl; import jogamp.opengl.GLDrawableImpl; @@ -62,6 +64,8 @@ import jogamp.opengl.SharedResourceRunner; import com.jogamp.nativewindow.GenericUpstreamSurfacelessHook; import com.jogamp.opengl.GLExtensions; import com.jogamp.opengl.GLRendererQuirks; +import com.jogamp.opengl.FBObject.Attachment; +import com.jogamp.opengl.FBObject.Attachment.StorageDefinition; public class IOSEAGLDrawableFactory extends GLDrawableFactoryImpl { private static final boolean DEBUG_SHAREDCTX = DEBUG || GLContext.DEBUG; @@ -343,6 +347,39 @@ public class IOSEAGLDrawableFactory extends GLDrawableFactoryImpl { } @Override + protected final OnscreenFBOColorbufferStorageDefinition getOnscreenFBOColorbufStorageDef() { return onscreenGLDrawableFBOColorRenderbufferStorageDef; } + private final OnscreenFBOColorbufferStorageDefinition onscreenGLDrawableFBOColorRenderbufferStorageDef = new OnscreenFBOColorbufferStorageDefinition() { + @Override + public final void setStorage(final GL gl, final Attachment a) { + final int samples = ((FBObject.RenderAttachment) a).getSamples(); + if( samples > 0 ) { + gl.glRenderbufferStorageMultisample(GL.GL_RENDERBUFFER, samples, a.format, a.getWidth(), a.getHeight()); + } else { + // gl.glRenderbufferStorage(GL.GL_RENDERBUFFER, a.format, a.getWidth(), a.getHeight()); + final long eaglLayer = IOSUtil.GetCAEAGLLayer(gl.getContext().getGLDrawable().getNativeSurface().getSurfaceHandle()); + EAGL.eaglBindDrawableStorageToRenderbuffer(gl.getContext().getHandle(), GL.GL_RENDERBUFFER, eaglLayer); + if( DEBUG ) { + System.err.println("EAGL.eaglBindDrawableStorageToRenderbuffer: ctx 0x"+Long.toHexString(gl.getContext().getHandle()) + + ", eaglLayer 0x"+Long.toHexString(eaglLayer)); + } + } + } + @Override + public final boolean isDoubleBufferSupported() { + return false; + } + @Override + public final int getTextureUnit() { + return -1; // force using a color renderbuffer + } }; + + /** + * {@inheritDoc} + * <p> + * This IOS <i>onscreen drawable</i> implementation actually is only a dummy implementation + * </p> + */ + @Override protected GLDrawableImpl createOnscreenDrawableImpl(final NativeSurface target) { if (target == null) { throw new IllegalArgumentException("Null target"); |