aboutsummaryrefslogtreecommitdiffstats
path: root/src/jogl
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2013-09-20 12:18:48 +0200
committerSven Gothel <[email protected]>2013-09-20 12:18:48 +0200
commitc427ed22244df44b71a0f1f000b0f93e56c283c2 (patch)
treee40dffaf9f3e2776a84413794f27b677318dc186 /src/jogl
parent51df3f354a700454498371c0565bfcd6c0d3bf5f (diff)
Fix Bug 826: GLJPanel: Fully restore TextureState and Viewport
In FBO mode save TextureState of current texture-unit, as well as for the fbo texture-unit if the latter is a different. In glslTextureRaster mode for verical flip (using FBO), set the viewport to drawable size if before flipping and restore afterward - if equired. TestGLJPanelTextureStateAWT fully tests use cases: - Keep texture bound w/ same or other texture-unit - Use 2 viewports within one drawable and keep it
Diffstat (limited to 'src/jogl')
-rw-r--r--src/jogl/classes/com/jogamp/opengl/util/texture/TextureState.java167
-rw-r--r--src/jogl/classes/javax/media/opengl/awt/GLJPanel.java53
2 files changed, 213 insertions, 7 deletions
diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureState.java b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureState.java
new file mode 100644
index 000000000..4a5d368e3
--- /dev/null
+++ b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureState.java
@@ -0,0 +1,167 @@
+/**
+ * Copyright 2013 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 com.jogamp.opengl.util.texture;
+
+import javax.media.opengl.GL;
+import javax.media.opengl.GL2ES2;
+import javax.media.opengl.GL2GL3;
+import javax.media.opengl.GL3;
+import javax.media.opengl.GLException;
+
+/**
+ * Preserves a [ texture-unit, texture-target ] state.
+ * <p>
+ * The states keys are the retrieved active texture-unit and the given texture-target
+ * for which the following states are being queried:
+ * <pre>
+ * - texture-object
+ * - GL.GL_TEXTURE_MAG_FILTER
+ * - GL.GL_TEXTURE_MIN_FILTER
+ * - GL.GL_TEXTURE_WRAP_S
+ * - GL.GL_TEXTURE_WRAP_T
+ * </pre>
+ */
+public class TextureState {
+ /**
+ * Returns the <code>pname</code> to query the <code>textureTarget</code> currently bound to the active texture-unit.
+ * <p>
+ * Returns <code>0</code> is <code>textureTarget</code> is not supported.
+ * </p>
+ */
+ public static final int getTextureTargetQueryName(int textureTarget) {
+ final int texBindQName;
+ switch(textureTarget) {
+ case GL.GL_TEXTURE_2D: texBindQName = GL.GL_TEXTURE_BINDING_2D; break;
+ case GL.GL_TEXTURE_CUBE_MAP: texBindQName = GL.GL_TEXTURE_BINDING_CUBE_MAP; break;
+ case GL2ES2.GL_TEXTURE_3D: texBindQName = GL2ES2.GL_TEXTURE_BINDING_3D; break;
+ case GL2GL3.GL_TEXTURE_1D: texBindQName = GL2GL3.GL_TEXTURE_BINDING_1D; break;
+ case GL2GL3.GL_TEXTURE_1D_ARRAY: texBindQName = GL2GL3.GL_TEXTURE_BINDING_1D_ARRAY; break;
+ case GL2GL3.GL_TEXTURE_2D_ARRAY: texBindQName = GL2GL3.GL_TEXTURE_BINDING_2D_ARRAY; break;
+ case GL2GL3.GL_TEXTURE_RECTANGLE: texBindQName = GL2GL3.GL_TEXTURE_BINDING_RECTANGLE; break;
+ case GL2GL3.GL_TEXTURE_BUFFER: texBindQName = GL2GL3.GL_TEXTURE_BINDING_BUFFER; break;
+ case GL3.GL_TEXTURE_2D_MULTISAMPLE: texBindQName = GL3.GL_TEXTURE_BINDING_2D_MULTISAMPLE; break;
+ case GL3.GL_TEXTURE_2D_MULTISAMPLE_ARRAY: texBindQName = GL3.GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY; break;
+ default: texBindQName = 0;
+ }
+ return texBindQName;
+ }
+
+ private final int target;
+ /**
+ * <pre>
+ * 0 - unit
+ * 1 - texture object
+ * 2 - GL.GL_TEXTURE_MAG_FILTER
+ * 3 - GL.GL_TEXTURE_MIN_FILTER
+ * 4 - GL.GL_TEXTURE_WRAP_S
+ * 5 - GL.GL_TEXTURE_WRAP_T
+ * </pre>
+ */
+ private final int[] state = new int[] { 0, 0, 0, 0, 0, 0 };
+
+ private static final String toHexString(int i) { return "0x"+Integer.toHexString(i); }
+
+ private static final int activeTexture(GL gl) {
+ final int[] vi = { 0 };
+ gl.glGetIntegerv(GL.GL_ACTIVE_TEXTURE, vi, 0);
+ return vi[0];
+ }
+
+ /**
+ * Creates a texture state for the retrieved active texture-unit and the given texture-target.
+ * See {@link TextureState}.
+ * @param gl current GL context's GL object
+ * @param textureTarget
+ * @throws GLException if textureTarget is not supported
+ */
+ public TextureState(GL gl, int textureTarget) throws GLException {
+ this(gl, activeTexture(gl), textureTarget);
+ }
+
+ /**
+ * Creates a texture state for the given active texture-unit and the given texture-target.
+ * See {@link TextureState}.
+ * @param gl current GL context's GL object
+ * @param textureUnit of range [ {@link GL#GL_TEXTURE0}.. ]
+ * @param textureTarget
+ * @throws GLException if textureTarget is not supported
+ */
+ public TextureState(GL gl, int textureUnit, int textureTarget) throws GLException {
+ target = textureTarget;
+ state[0] = textureUnit;
+ final int texBindQName = getTextureTargetQueryName(textureTarget);
+ if( 0 == texBindQName ) {
+ throw new GLException("Unsupported textureTarget "+toHexString(textureTarget));
+ }
+ gl.glGetIntegerv(texBindQName, state, 1);
+ gl.glGetTexParameteriv(target, GL.GL_TEXTURE_MAG_FILTER, state, 2);
+ gl.glGetTexParameteriv(target, GL.GL_TEXTURE_MIN_FILTER, state, 3);
+ gl.glGetTexParameteriv(target, GL.GL_TEXTURE_WRAP_S, state, 4);
+ gl.glGetTexParameteriv(target, GL.GL_TEXTURE_WRAP_T, state, 5);
+ }
+
+ /**
+ * Restores the texture-unit's texture-target state.
+ * <p>
+ * First the texture-unit is activated, then all states are restored.
+ * </p>
+ * @param gl current GL context's GL object
+ */
+ public final void restore(GL gl) {
+ gl.glActiveTexture(state[0]);
+ gl.glBindTexture(target, state[1]);
+ gl.glTexParameteri(target, GL.GL_TEXTURE_MAG_FILTER, state[2]);
+ gl.glTexParameteri(target, GL.GL_TEXTURE_MIN_FILTER, state[3]);
+ gl.glTexParameteri(target, GL.GL_TEXTURE_WRAP_S, state[4]);
+ gl.glTexParameteri(target, GL.GL_TEXTURE_WRAP_T, state[5]);
+ }
+
+ /** Returns the texture-unit of this state, key value. Unit is of range [ {@link GL#GL_TEXTURE0}.. ]. */
+ public final int getUnit() { return state[0]; }
+ /** Returns the texture-target of this state, key value. */
+ public final int getTarget() { return target; }
+
+ /** Returns the state's texture-object. */
+ public final int getObject() { return state[1]; }
+ /** Returns the state's mag-filter param. */
+ public final int getMagFilter() { return state[2]; }
+ /** Returns the state's min-filter param. */
+ public final int getMinFilter() { return state[3]; }
+ /** Returns the state's wrap-s param. */
+ public final int getWrapS() { return state[4]; }
+ /** Returns the state's wrap-t param. */
+ public final int getWrapT() { return state[5]; }
+
+
+ public final String toString() {
+ return "TextureState[unit "+(state[0] - GL.GL_TEXTURE0)+", target "+toHexString(target)+
+ ": obj "+toHexString(state[1])+
+ ", filter[mag "+toHexString(state[2])+", min "+toHexString(state[3])+"], "+
+ ": wrap[s "+toHexString(state[4])+", t "+toHexString(state[5])+"]]";
+ }
+}
diff --git a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
index e9d1b38d2..61ff4997e 100644
--- a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
+++ b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java
@@ -101,6 +101,7 @@ import com.jogamp.opengl.util.TileRenderer;
import com.jogamp.opengl.util.awt.AWTGLPixelBuffer;
import com.jogamp.opengl.util.awt.AWTGLPixelBuffer.AWTGLPixelBufferProvider;
import com.jogamp.opengl.util.awt.AWTGLPixelBuffer.SingleAWTGLPixelBufferProvider;
+import com.jogamp.opengl.util.texture.TextureState;
/** A lightweight Swing component which provides OpenGL rendering
support. Provided for compatibility with Swing user interfaces
@@ -1219,6 +1220,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
// Implementation using software rendering
private GLDrawableImpl offscreenDrawable;
+ private boolean offscreenIsFBO;
private FBObject fboFlipped;
private GLSLTextureRaster glslTextureRaster;
@@ -1264,7 +1266,8 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
final GL gl = offscreenContext.getGL();
flipVertical = offscreenDrawable.isGLOriented();
final GLCapabilitiesImmutable chosenCaps = offscreenDrawable.getChosenGLCapabilities();
- if( USE_GLSL_TEXTURE_RASTERIZER && chosenCaps.isFBO() && flipVertical && gl.isGL2ES2() ) {
+ offscreenIsFBO = chosenCaps.isFBO();
+ if( USE_GLSL_TEXTURE_RASTERIZER && offscreenIsFBO && flipVertical && gl.isGL2ES2() ) {
final boolean _autoSwapBufferMode = helper.getAutoSwapBufferMode();
helper.setAutoSwapBufferMode(false);
final GLFBODrawable fboDrawable = (GLFBODrawable) offscreenDrawable;
@@ -1344,6 +1347,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
adevice.close();
}
}
+ offscreenIsFBO = false;
if( null != readBackIntsForCPUVFlip ) {
readBackIntsForCPUVFlip.clear();
@@ -1420,10 +1424,23 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
readBackInts = readBackIntsForCPUVFlip;
}
- if( DEBUG_VIEWPORT ) {
- int[] vp = new int[] { 0, 0, 0, 0 };
- gl.glGetIntegerv(GL.GL_VIEWPORT, vp, 0);
- System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL: Viewport: "+vp[0]+"/"+vp[1]+" "+vp[2]+"x"+vp[3]);
+ final TextureState usrTexState, fboTexState;
+ final int fboTexUnit = GL.GL_TEXTURE0 + ( offscreenIsFBO ? ((GLFBODrawable)offscreenDrawable).getTextureUnit() : 0 );
+
+ if( offscreenIsFBO ) {
+ usrTexState = new TextureState(gl, GL.GL_TEXTURE_2D);
+ if( fboTexUnit != usrTexState.getUnit() ) {
+ // glActiveTexture(..) + glBindTexture(..) are implicit performed in GLFBODrawableImpl's
+ // swapBuffers/contextMadeCurent -> swapFBOImpl.
+ // We need to cache the texture unit's bound texture-id before it's overwritten.
+ gl.glActiveTexture(fboTexUnit);
+ fboTexState = new TextureState(gl, fboTexUnit, GL.GL_TEXTURE_2D);
+ } else {
+ fboTexState = usrTexState;
+ }
+ } else {
+ usrTexState = null;
+ fboTexState = null;
}
// Must now copy pixels from offscreen context into surface
@@ -1439,6 +1456,20 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
offscreenDrawable.swapBuffers();
if(null != glslTextureRaster) { // implies flippedVertical
+ final boolean viewportChange;
+ final int[] usrViewport = new int[] { 0, 0, 0, 0 };
+ gl.glGetIntegerv(GL.GL_VIEWPORT, usrViewport, 0);
+ viewportChange = 0 != usrViewport[0] || 0 != usrViewport[1] ||
+ offscreenDrawable.getWidth() != usrViewport[2] || offscreenDrawable.getHeight() != usrViewport[3];
+ if( DEBUG_VIEWPORT ) {
+ System.err.println(getThreadName()+": GLJPanel.OffscreenBackend.postGL: Viewport: change "+viewportChange+
+ ", "+usrViewport[0]+"/"+usrViewport[1]+" "+usrViewport[2]+"x"+usrViewport[3]+
+ " -> 0/0 "+offscreenDrawable.getWidth()+"x"+offscreenDrawable.getHeight());
+ }
+ if( viewportChange ) {
+ gl.glViewport(0, 0, offscreenDrawable.getWidth(), offscreenDrawable.getHeight());
+ }
+
// perform vert-flipping via OpenGL/FBO
final GLFBODrawable fboDrawable = (GLFBODrawable)offscreenDrawable;
final FBObject.TextureAttachment fboTex = fboDrawable.getTextureBuffer(GL.GL_FRONT);
@@ -1446,12 +1477,17 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
fboFlipped.bind(gl);
// gl.glActiveTexture(GL.GL_TEXTURE0 + fboDrawable.getTextureUnit()); // implicit by GLFBODrawableImpl: swapBuffers/contextMadeCurent -> swapFBOImpl
- gl.glBindTexture(GL.GL_TEXTURE_2D, fboTex.getName());
+ gl.glBindTexture(GL.GL_TEXTURE_2D, fboTex.getName());
// gl.glClear(GL.GL_DEPTH_BUFFER_BIT); // fboFlipped runs w/o DEPTH!
+
glslTextureRaster.display(gl.getGL2ES2());
gl.glReadPixels(0, 0, panelWidth, panelHeight, pixelAttribs.format, pixelAttribs.type, readBackInts);
-
+
fboFlipped.unbind(gl);
+ if( viewportChange ) {
+ gl.glViewport(usrViewport[0], usrViewport[1], usrViewport[2], usrViewport[3]);
+ }
+ fboTexState.restore(gl);
} else {
gl.glReadPixels(0, 0, panelWidth, panelHeight, pixelAttribs.format, pixelAttribs.type, readBackInts);
@@ -1471,6 +1507,9 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing
}
}
}
+ if( offscreenIsFBO && fboTexUnit != usrTexState.getUnit() ) {
+ usrTexState.restore(gl);
+ }
// Restore saved modes.
psm.restore(gl);