diff options
Diffstat (limited to 'src/jogl')
5 files changed, 109 insertions, 23 deletions
diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLDrawableUtil.java b/src/jogl/classes/com/jogamp/opengl/util/GLDrawableUtil.java index ec6d54d66..cf88e7bf6 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/GLDrawableUtil.java +++ b/src/jogl/classes/com/jogamp/opengl/util/GLDrawableUtil.java @@ -30,6 +30,8 @@ package com.jogamp.opengl.util; import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.opengl.GLAnimatorControl; import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLBase; +import javax.media.opengl.GLCapabilitiesImmutable; import javax.media.opengl.GLContext; import javax.media.opengl.GLDrawable; import javax.media.opengl.GLEventListener; @@ -168,4 +170,23 @@ public class GLDrawableUtil { if(bIsPaused) { bAnim.resume(); } } + /** + * Determines whether the chosen {@link GLCapabilitiesImmutable} + * requires a {@link GLDrawable#swapBuffers() swap-buffers} + * before reading pixels. + * <p> + * Usually one uses the {@link GLBase#getDefaultReadBuffer() default-read-buffer} + * in which case {@link GLDrawable#swapBuffers() swap-buffers} shall happen <b>after</b> calling reading pixels, the default. + * </p> + * <p> + * However, <i>multisampling</i> offscreen {@link javax.media.opengl.GLFBODrawable}s + * utilize {@link GLDrawable#swapBuffers() swap-buffers} to <i>downsample</i> + * the multisamples into the readable sampling sink. + * In this case, we require {@link GLDrawable#swapBuffers() swap-buffers} <b>before</b> reading pixels. + * </p> + * @return chosenCaps.isFBO() && chosenCaps.getSampleBuffers() + */ + public static final boolean swapBuffersBeforeRead(final GLCapabilitiesImmutable chosenCaps) { + return chosenCaps.isFBO() && chosenCaps.getSampleBuffers(); + } } diff --git a/src/jogl/classes/com/jogamp/opengl/util/TileRendererBase.java b/src/jogl/classes/com/jogamp/opengl/util/TileRendererBase.java index 22f5c017c..dabde83dd 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/TileRendererBase.java +++ b/src/jogl/classes/com/jogamp/opengl/util/TileRendererBase.java @@ -412,22 +412,11 @@ public abstract class TileRendererBase { * requires a <i>pre-{@link GLDrawable#swapBuffers() swap-buffers}</i> * before accessing the results, i.e. before {@link #endTile(GL)}. * <p> - * Usually one uses the {@link GL#getDefaultReadBuffer() default-read-buffer}, i.e. - * {@link GL#GL_FRONT} for single-buffer and {@link GL#GL_BACK} for double-buffer {@link GLDrawable}s - * and {@link GL#GL_COLOR_ATTACHMENT0} for offscreen framebuffer objects.<br> - * Here {@link GLDrawable#swapBuffers() swap-buffers} shall happen <b>after</b> calling {@link #endTile(GL)}, the default. + * See {@link GLDrawableUtil#swapBuffersBeforeRead(GLCapabilitiesImmutable)}. * </p> - * <p> - * However, <i>multisampling</i> offscreen {@link GLFBODrawable}s - * utilize {@link GLDrawable#swapBuffers() swap-buffers} to <i>downsample</i> - * the multisamples into the readable sampling sink. - * In this case, we require a {@link GLDrawable#swapBuffers() swap-buffers} <b>before</b> calling {@link #endTile(GL)}. - * </p> - * @param chosenCaps the chosen {@link GLCapabilitiesImmutable} - * @return chosenCaps.isFBO() && chosenCaps.getSampleBuffers() */ public final boolean reqPreSwapBuffers(GLCapabilitiesImmutable chosenCaps) { - return chosenCaps.isFBO() && chosenCaps.getSampleBuffers(); + return GLDrawableUtil.swapBuffersBeforeRead(chosenCaps); } /** diff --git a/src/jogl/classes/javax/media/opengl/GLBase.java b/src/jogl/classes/javax/media/opengl/GLBase.java index 2d6aed139..3f0c77949 100644 --- a/src/jogl/classes/javax/media/opengl/GLBase.java +++ b/src/jogl/classes/javax/media/opengl/GLBase.java @@ -627,14 +627,24 @@ public interface GLBase { * Returns the default color buffer within the current bound * {@link #getDefaultReadFramebuffer()}, i.e. GL_READ_FRAMEBUFFER, * which will be used as the source for pixel reading commands, - * like {@link GL#glReadPixels(int, int, int, int, int, int, java.nio.Buffer)} etc. + * like {@link GL#glReadPixels(int, int, int, int, int, int, java.nio.Buffer) glReadPixels} etc. * <p> * For offscreen framebuffer objects this is {@link GL#GL_COLOR_ATTACHMENT0}, * otherwise this is {@link GL#GL_FRONT} for single buffer configurations * and {@link GL#GL_BACK} for double buffer configurations. * </p> + * <p> + * Note-1: Neither ES1 nor ES2 supports selecting the read buffer via glReadBuffer + * and {@link GL#GL_BACK} is the default. + * </p> + * <p> + * Note-2: ES3 only supports {@link GL#GL_BACK}, {@link GL#GL_NONE} or {@link GL#GL_COLOR_ATTACHMENT0}+i + * </p> + * <p> + * Note-3: See {@link com.jogamp.opengl.util.GLDrawableUtil#swapBuffersBeforeRead(GLCapabilitiesImmutable) swapBuffersBeforeRead} + * for read-pixels and swap-buffers implications. + * </p> */ public int getDefaultReadBuffer(); - } diff --git a/src/jogl/classes/javax/media/opengl/GLContext.java b/src/jogl/classes/javax/media/opengl/GLContext.java index 9245d10c2..9a4311772 100644 --- a/src/jogl/classes/javax/media/opengl/GLContext.java +++ b/src/jogl/classes/javax/media/opengl/GLContext.java @@ -1277,12 +1277,23 @@ public abstract class GLContext { * Returns the default color buffer within the current bound * {@link #getDefaultReadFramebuffer()}, i.e. GL_READ_FRAMEBUFFER​, * which will be used as the source for pixel reading commands, - * like {@link GL#glReadPixels(int, int, int, int, int, int, java.nio.Buffer)} etc. + * like {@link GL#glReadPixels(int, int, int, int, int, int, java.nio.Buffer) glReadPixels} etc. * <p> * For offscreen framebuffer objects this is {@link GL#GL_COLOR_ATTACHMENT0}, * otherwise this is {@link GL#GL_FRONT} for single buffer configurations * and {@link GL#GL_BACK} for double buffer configurations. * </p> + * <p> + * Note-1: Neither ES1 nor ES2 supports selecting the read buffer via glReadBuffer + * and {@link GL#GL_BACK} is the default. + * </p> + * <p> + * Note-2: ES3 only supports {@link GL#GL_BACK}, {@link GL#GL_NONE} or {@link GL#GL_COLOR_ATTACHMENT0}+i + * </p> + * <p> + * Note-3: See {@link com.jogamp.opengl.util.GLDrawableUtil#swapBuffersBeforeRead(GLCapabilitiesImmutable) swapBuffersBeforeRead} + * for read-pixels and swap-buffers implications. + * </p> */ public abstract int getDefaultReadBuffer(); diff --git a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java index c80b405b5..adc0a0d23 100644 --- a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java +++ b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java @@ -60,6 +60,7 @@ import java.util.List; import javax.media.nativewindow.AbstractGraphicsDevice; import javax.media.nativewindow.NativeSurface; +import javax.media.nativewindow.SurfaceUpdatedListener; import javax.media.nativewindow.WindowClosingProtocol; import javax.media.opengl.GL; import javax.media.opengl.GL2; @@ -223,6 +224,8 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing } private final GLDrawableHelper helper; + private boolean autoSwapBufferMode; + private volatile boolean isInitialized; // @@ -357,6 +360,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing if( null != shareWith ) { helper.setSharedContext(null, shareWith); } + autoSwapBufferMode = helper.getAutoSwapBufferMode(); this.setFocusable(true); // allow keyboard input! this.addHierarchyListener(hierarchyListener); @@ -944,12 +948,22 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing @Override public void setAutoSwapBufferMode(boolean enable) { - helper.setAutoSwapBufferMode(enable); + this.autoSwapBufferMode = enable; + boolean backendHandlesSwapBuffer = false; + if( isInitialized ) { + final Backend b = backend; + if ( null != b ) { + backendHandlesSwapBuffer= b.handlesSwapBuffer(); + } + } + if( !backendHandlesSwapBuffer ) { + helper.setAutoSwapBufferMode(enable); + } } @Override public boolean getAutoSwapBufferMode() { - return helper.getAutoSwapBufferMode(); + return autoSwapBufferMode; } @Override @@ -1355,6 +1369,14 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing public boolean preGL(Graphics g); /** + * Return true if backend handles 'swap buffer' itself + * and hence the helper's setAutoSwapBuffer(enable) shall not be called. + * In this case {@link GLJPanel#autoSwapBufferMode} is being used + * in the backend to determine whether to swap buffers or not. + */ + public boolean handlesSwapBuffer(); + + /** * Shall invoke underlying drawable's swapBuffer. */ public void swapBuffers(); @@ -1394,6 +1416,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing private volatile GLContextImpl offscreenContext; // volatile: avoid locking for read-only access private boolean flipVertical; + private int frameCount = 0; // For saving/restoring of OpenGL state during ReadPixels private final GLPixelStorageModes psm = new GLPixelStorageModes(); @@ -1417,7 +1440,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing @Override public final void initialize() { if(DEBUG) { - System.err.println(getThreadName()+": OffscreenBackend: initialize()"); + System.err.println(getThreadName()+": OffscreenBackend: initialize() - frameCount "+frameCount); } try { final GLContext[] shareWith = { null }; @@ -1430,10 +1453,20 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing chooser, panelWidth, panelHeight); offscreenDrawable.setRealized(true); + if( DEBUG ) { + offscreenDrawable.getNativeSurface().addSurfaceUpdatedListener(new SurfaceUpdatedListener() { + @Override + public final void surfaceUpdated(Object updater, NativeSurface ns, long when) { + System.err.println(getThreadName()+": OffscreenBackend.swapBuffers - frameCount "+frameCount); + } } ); + } + offscreenContext = (GLContextImpl) offscreenDrawable.createContext(shareWith[0]); offscreenContext.setContextCreationFlags(additionalCtxCreationFlags); if( GLContext.CONTEXT_NOT_CURRENT < offscreenContext.makeCurrent() ) { isInitialized = true; + helper.setAutoSwapBufferMode(false); // we handle swap-buffers, see handlesSwapBuffer() + final GL gl = offscreenContext.getGL(); flipVertical = !GLJPanel.this.skipGLOrientationVerticalFlip && offscreenDrawable.isGLOriented(); final GLCapabilitiesImmutable chosenCaps = offscreenDrawable.getChosenGLCapabilities(); @@ -1493,7 +1526,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing @Override public final void destroy() { if(DEBUG) { - System.err.println(getThreadName()+": OffscreenBackend: destroy() - offscreenContext: "+(null!=offscreenContext)+" - offscreenDrawable: "+(null!=offscreenDrawable)); + System.err.println(getThreadName()+": OffscreenBackend: destroy() - offscreenContext: "+(null!=offscreenContext)+" - offscreenDrawable: "+(null!=offscreenDrawable)+" - frameCount "+frameCount); } if ( null != offscreenContext && offscreenContext.isCreated() ) { if( GLContext.CONTEXT_NOT_CURRENT < offscreenContext.makeCurrent() ) { @@ -1554,6 +1587,11 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing } @Override + public final boolean handlesSwapBuffer() { + return true; + } + + @Override public final void swapBuffers() { final GLDrawable d = offscreenDrawable; if( null != d ) { @@ -1564,9 +1602,14 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing @Override public final void postGL(Graphics g, boolean isDisplay) { if (isDisplay) { - // offscreenDrawable is already swapped, - // either by GLDrawableHelper.invoke or user's GLEL according to auto-swap-buffer-mode. - + if(DEBUG) { + System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.0: - frameCount "+frameCount); + } + if( autoSwapBufferMode ) { + // Since we only use a single-buffer non-MSAA or double-buffered MSAA offscreenDrawable, + // we can always swap! + offscreenDrawable.swapBuffers(); + } final GL gl = offscreenContext.getGL(); final int componentCount; @@ -1645,6 +1688,9 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing } // Must now copy pixels from offscreen context into surface + if(DEBUG) { + System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL.readPixels: - frameCount "+frameCount); + } // Save current modes psm.setAlignment(gl, alignment, alignment); @@ -1731,9 +1777,13 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing helper.invokeGL(offscreenDrawable, offscreenContext, updaterDisplayAction, updaterInitAction); if ( null != alignedImage ) { + if( DEBUG ) { + System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.doPaintComponent.drawImage: - frameCount "+frameCount); + } // Draw resulting image in one shot g.drawImage(alignedImage, 0, 0, alignedImage.getWidth(), alignedImage.getHeight(), null); // Null ImageObserver since image data is ready. } + frameCount++; } @Override @@ -2078,6 +2128,11 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing } @Override + public final boolean handlesSwapBuffer() { + return false; + } + + @Override public final void swapBuffers() { final GLDrawable d = joglDrawable; if( null != d ) { |