diff options
author | Sven Gothel <[email protected]> | 2013-09-20 12:18:48 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2013-09-20 12:18:48 +0200 |
commit | c427ed22244df44b71a0f1f000b0f93e56c283c2 (patch) | |
tree | e40dffaf9f3e2776a84413794f27b677318dc186 /src | |
parent | 51df3f354a700454498371c0565bfcd6c0d3bf5f (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')
15 files changed, 897 insertions, 57 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); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLJPanelTextureStateAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLJPanelTextureStateAWT.java new file mode 100644 index 000000000..2d4c6da4d --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/awt/TestGLJPanelTextureStateAWT.java @@ -0,0 +1,282 @@ +/** + * 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.test.junit.jogl.awt; + + +import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2; +import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2; +import com.jogamp.opengl.test.junit.jogl.demos.es2.TextureDraw02ES2ListenerFBO; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.QuitAdapter; +import com.jogamp.opengl.test.junit.util.UITestCase; + +import javax.media.opengl.GL; +import javax.media.opengl.GL2ES2; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLProfile; +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.awt.GLJPanel; +import javax.swing.JFrame; + +import com.jogamp.opengl.util.texture.TextureIO; +import com.jogamp.opengl.util.texture.TextureState; +import com.jogamp.opengl.util.Animator; +import com.jogamp.opengl.util.GLReadBufferUtil; + +import java.awt.Dimension; + +import java.io.IOException; + +import org.junit.Assert; +import org.junit.Assume; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +/** + * Unit test for bug 826, test {@link GLJPanel}'s {@link TextureState} save and restore. + */ +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestGLJPanelTextureStateAWT extends UITestCase { + static boolean showFPS = false; + static long duration = 100; // ms + + @BeforeClass + public static void initClass() { + } + + public void testImpl(final boolean keepTextureBound, final int texUnit) + throws InterruptedException, IOException + { + final GLReadBufferUtil screenshot = new GLReadBufferUtil(true, false); + GLProfile glp; + if(GLProfile.isAvailable(GLProfile.GL2ES2)) { + glp = GLProfile.getGL2ES2(); + } else { + System.err.println(getSimpleTestName(".")+": GLProfile n/a"); + return; + } + final GLCapabilities caps = new GLCapabilities(glp); + + final GLJPanel glc = new GLJPanel(caps); + Dimension glc_sz = new Dimension(800, 400); + glc.setMinimumSize(glc_sz); + glc.setPreferredSize(glc_sz); + final JFrame frame = new JFrame("TestGLJPanelTextureStateAWT"); + Assert.assertNotNull(frame); + frame.getContentPane().add(glc); + + final TextureDraw02ES2ListenerFBO gle0; + { + final GearsES2 gle0sub = new GearsES2( 0 ); + // gle1sub.setClearBuffers(false); + gle0 = new TextureDraw02ES2ListenerFBO(gle0sub, 1, texUnit ) ; + } + gle0.setKeepTextureBound(keepTextureBound); + gle0.setClearBuffers(false); + + final RedSquareES2 gle1 = new RedSquareES2( 1 ) ; + gle1.setClearBuffers(false); + + glc.addGLEventListener(new GLEventListener() { + int gle0X, gle0Y, gle0W, gle0H; + int gle1X, gle1Y, gle1W, gle1H; + int tX, tY, tW, tH; + int shot = 0; + + void setupTex(GL gl) { + // Note: FBObject uses diff defaults, i.e.: GL_NEAREST and GL_CLAMP_TO_EDGE + if( keepTextureBound ) { + gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR); + gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR); + gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, GL.GL_REPEAT); + gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, GL.GL_REPEAT); + } + } + + @Override + public void init(GLAutoDrawable drawable) { + // Initialize w/ arbitrary values ! + GL2ES2 gl = drawable.getGL().getGL2ES2(); + gl.glActiveTexture(GL.GL_TEXTURE0 + 1); + gl.glBindTexture(GL.GL_TEXTURE_2D, 0); + gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR); + gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_NEAREST); + gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, GL.GL_REPEAT); + gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, GL.GL_REPEAT); + gl.glActiveTexture(GL.GL_TEXTURE0 + 0); + gl.glBindTexture(GL.GL_TEXTURE_2D, 0); + gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR); + gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_NEAREST); + gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, GL.GL_REPEAT); + gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, GL.GL_REPEAT); + + gle0.init(drawable); + gle1.init(drawable); + setupTex(gl); + } + + @Override + public void dispose(GLAutoDrawable drawable) { + gle0.dispose(drawable); + gle1.dispose(drawable); + } + @Override + public void display(GLAutoDrawable drawable) { + GL2ES2 gl = drawable.getGL().getGL2ES2(); + + gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); + + // restore viewport test + final int[] viewport = new int[] { 0, 0, 0, 0 }; + gl.glGetIntegerv(GL.GL_VIEWPORT, viewport, 0); + if( gle0X != viewport[0] || gle0Y != viewport[1] || gle0W != viewport[2] || gle0H != viewport[3] ) { + final String msg = "Expected "+viewport[0]+"/"+viewport[1]+" "+viewport[2]+"x"+viewport[3]+ + ", actual "+gle0X+"/"+gle0Y+" "+gle0W+"x"+gle0H; + Assert.assertTrue("Viewport not restored: "+msg, false); + } + + // gl.glViewport(gle0X, gle0Y, gle0W, gle0H); // restore viewport test + gle0.display(drawable); + + gl.glViewport(gle1X, gle1Y, gle1W, gle1H); + gle1.display(drawable); + + shot++; + if( 4 == shot ) { + gl.glViewport(tX, tY, tW, tH); + snapshot(0, null, drawable.getGL(), screenshot, TextureIO.PNG, null); + } + + gl.glViewport(gle0X, gle0Y, gle0W, gle0H); // restore viewport test + + final TextureState ts = new TextureState(drawable.getGL(), GL.GL_TEXTURE_2D); + // System.err.println("XXX: "+ts); + Assert.assertEquals("Texture unit changed", GL.GL_TEXTURE0+texUnit, ts.getUnit()); + if( keepTextureBound ) { + Assert.assertEquals("Texture mag-filter changed", GL.GL_LINEAR, ts.getMagFilter()); + Assert.assertEquals("Texture mag-filter changed", GL.GL_LINEAR, ts.getMinFilter()); + Assert.assertEquals("Texture wrap-s changed", GL.GL_REPEAT, ts.getWrapS()); + Assert.assertEquals("Texture wrap-t changed", GL.GL_REPEAT, ts.getWrapT()); + } + } + final int border = 5; + @Override + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { + gle0X = x + border; + gle0Y = y; + gle0W = width/2 - 2*border; + gle0H = height; + + gle1X = gle0X + gle0W + 2*border; + gle1Y = y; + gle1W = width/2 - 2*border; + gle1H = height; + + tX = x; + tY = y; + tW = width; + tH = height; + + GL2ES2 gl = drawable.getGL().getGL2ES2(); + gl.glViewport(gle0X, gle0Y, gle0W, gle0H); + gle0.reshape(drawable, gle0X, gle0Y, gle0W, gle0H); + + gl.glViewport(gle1X, gle1Y, gle1W, gle1H); + gle1.reshape(drawable, gle1X, gle1Y, gle1W, gle1H); + + gl.glViewport(gle0X, gle0Y, gle0W, gle0H); // restore viewport test + + if( keepTextureBound ) { + setupTex(gl); + } + } + }); + + Animator animator = new Animator(glc); + animator.setUpdateFPSFrames(60, showFPS ? System.err : null); + QuitAdapter quitAdapter = new QuitAdapter(); + new com.jogamp.newt.event.awt.AWTKeyAdapter(quitAdapter).addTo(glc); + new com.jogamp.newt.event.awt.AWTWindowAdapter(quitAdapter).addTo(glc); + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.pack(); + frame.setVisible(true); + }}); + } catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + animator.start(); + + while(!quitAdapter.shouldQuit() && animator.isAnimating() && animator.getTotalFPSDuration()<duration) { + Thread.sleep(100); + } + + animator.stop(); + try { + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setVisible(false); + frame.remove(glc); + frame.dispose(); + }}); + } catch( Throwable throwable ) { + throwable.printStackTrace(); + Assume.assumeNoException( throwable ); + } + } + + @Test + public void test01_texUnit0_keepTex0_ES2() throws InterruptedException, IOException { + testImpl(false /* keepTextureBound */, 0 /* texUnit */); + } + @Test + public void test02_texUnit0_keepTex1_ES2() throws InterruptedException, IOException { + testImpl(true /* keepTextureBound */, 0 /* texUnit */); + } + @Test + public void test03_texUnit1_keepTex1_ES2() throws InterruptedException, IOException { + testImpl(true /* keepTextureBound */, 1 /* texUnit */); + } + + public static void main(String args[]) throws IOException { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + duration = MiscUtils.atol(args[i], duration); + } + } + org.junit.runner.JUnitCore.main(TestGLJPanelTextureStateAWT.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/TextureDraw01Accessor.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/TextureDraw01Accessor.java index b9ac9faad..7283a204e 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/TextureDraw01Accessor.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/TextureDraw01Accessor.java @@ -31,5 +31,6 @@ package com.jogamp.opengl.test.junit.jogl.demos; import com.jogamp.opengl.util.texture.Texture; public interface TextureDraw01Accessor { + public void setKeepTextureBound(boolean v); public Texture getTexture(); } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/TextureDraw01ES2Listener.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/TextureDraw01ES2Listener.java index 55d0a4775..8aa3a006c 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/TextureDraw01ES2Listener.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/TextureDraw01ES2Listener.java @@ -51,6 +51,8 @@ import javax.media.opengl.fixedfunc.GLMatrixFunc; public class TextureDraw01ES2Listener implements GLEventListener, TextureDraw01Accessor { TextureData textureData; Texture texture; + int textureUnit; + boolean keepTextureBound; ShaderState st; PMVMatrix pmvMatrix; @@ -58,14 +60,45 @@ public class TextureDraw01ES2Listener implements GLEventListener, TextureDraw01A GLArrayDataServer interleavedVBO; float[] clearColor = new float[] { 1.0f, 1.0f, 1.0f, 1.0f }; - public TextureDraw01ES2Listener(TextureData td) { + /** + * + * @param td + * @param textureUnit of range [0..] + */ + public TextureDraw01ES2Listener(TextureData td, int textureUnit) { this.textureData = td; + this.textureUnit = textureUnit; + this.keepTextureBound = false; } public void setClearColor(float[] clearColor) { this.clearColor = clearColor; } + @Override + public void setKeepTextureBound(boolean v) { + this.keepTextureBound = v; + } + @Override + public Texture getTexture( ) { + return this.texture; + } + + /** + public void setTextureData(GL gl, TextureData textureData ) { + if(null!=texture) { + texture.disable(gl); + texture.destroy(gl); + } + if(null!=this.textureData) { + this.textureData.destroy(); + } + this.textureData = textureData; + this.texture = TextureIO.newTexture(this.textureData); + + // fix VBO ! + } */ + static final String shaderBasename = "texture01_xxx"; private void initShader(GL2ES2 gl, boolean use_program) { @@ -90,6 +123,7 @@ public class TextureDraw01ES2Listener implements GLEventListener, TextureDraw01A st.attachShaderProgram(gl, sp, use_program); } + @Override public void init(GLAutoDrawable glad) { if(null!=textureData) { this.texture = TextureIO.newTexture(glad.getGL(), textureData); @@ -110,7 +144,7 @@ public class TextureDraw01ES2Listener implements GLEventListener, TextureDraw01A if(!st.uniform(gl, pmvMatrixUniform)) { throw new GLException("Error setting PMVMatrix in shader: "+st); } - if(!st.uniform(gl, new GLUniformData("mgl_ActiveTexture", 0))) { + if(!st.uniform(gl, new GLUniformData("mgl_ActiveTexture", textureUnit))) { throw new GLException("Error setting mgl_ActiveTexture in shader: "+st); } @@ -140,33 +174,19 @@ public class TextureDraw01ES2Listener implements GLEventListener, TextureDraw01A // OpenGL Render Settings gl.glClearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]); gl.glEnable(GL2ES2.GL_DEPTH_TEST); - st.useProgram(gl, false); - } - - public Texture getTexture( ) { - return this.texture; - } - - /** - public void setTextureData(GL gl, TextureData textureData ) { - if(null!=texture) { - texture.disable(gl); - texture.destroy(gl); - } - if(null!=this.textureData) { - this.textureData.destroy(); - } - this.textureData = textureData; - this.texture = TextureIO.newTexture(this.textureData); - // fix VBO ! - } */ + if( keepTextureBound && null != texture ) { + gl.glActiveTexture(GL.GL_TEXTURE0 + textureUnit); + texture.enable(gl); + texture.bind(gl); + } + st.useProgram(gl, false); + } + @Override public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { GL2ES2 gl = drawable.getGL().getGL2ES2(); - gl.glViewport(0, 0, width, height); - // Clear background to white gl.glClearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]); if(null != st) { @@ -183,6 +203,7 @@ public class TextureDraw01ES2Listener implements GLEventListener, TextureDraw01A } } + @Override public void dispose(GLAutoDrawable drawable) { GL2ES2 gl = drawable.getGL().getGL2ES2(); if(null!=texture) { @@ -200,6 +221,7 @@ public class TextureDraw01ES2Listener implements GLEventListener, TextureDraw01A st=null; } + @Override public void display(GLAutoDrawable drawable) { GL2ES2 gl = drawable.getGL().getGL2ES2(); @@ -207,13 +229,17 @@ public class TextureDraw01ES2Listener implements GLEventListener, TextureDraw01A st.useProgram(gl, true); interleavedVBO.enableBuffer(gl, true); - gl.glActiveTexture(GL.GL_TEXTURE0); - texture.enable(gl); - texture.bind(gl); + if( !keepTextureBound && null != texture ) { + gl.glActiveTexture(GL.GL_TEXTURE0 + textureUnit); + texture.enable(gl); + texture.bind(gl); + } gl.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 4); - texture.disable(gl); + if( !keepTextureBound && null != texture ) { + texture.disable(gl); + } interleavedVBO.enableBuffer(gl, false); st.useProgram(gl, false); } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/TextureDraw02ES2ListenerFBO.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/TextureDraw02ES2ListenerFBO.java new file mode 100644 index 000000000..aac0080f2 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/TextureDraw02ES2ListenerFBO.java @@ -0,0 +1,285 @@ +/** + * Copyright (C) 2011 JogAmp Community. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.jogamp.opengl.test.junit.jogl.demos.es2; + +import java.nio.FloatBuffer; + +import javax.media.opengl.GL; +import javax.media.opengl.GL2ES2; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLEventListener; +import javax.media.opengl.GLUniformData; +import javax.media.opengl.fixedfunc.GLMatrixFunc; + +import com.jogamp.opengl.FBObject; +import com.jogamp.opengl.FBObject.TextureAttachment; +import com.jogamp.opengl.FBObject.Attachment.Type; +import com.jogamp.opengl.util.GLArrayDataServer; +import com.jogamp.opengl.util.PMVMatrix; +import com.jogamp.opengl.util.glsl.ShaderCode; +import com.jogamp.opengl.util.glsl.ShaderProgram; +import com.jogamp.opengl.util.glsl.ShaderState; + +public class TextureDraw02ES2ListenerFBO implements GLEventListener { + private final GLEventListener demo; + private final int swapInterval; + private boolean clearBuffers = true; + private int numSamples; + int textureUnit; + boolean keepTextureBound; + + private final ShaderState st; + private final PMVMatrix pmvMatrix; + + private final FBObject fbo0; + + private TextureAttachment fbo0Tex; + + private ShaderProgram sp0; + private GLUniformData pmvMatrixUniform; + private GLArrayDataServer interleavedVBO; + private GLUniformData texUnit0; + + public TextureDraw02ES2ListenerFBO(GLEventListener demo, int swapInterval, int textureUnit) { + this.demo = demo; + this.swapInterval = swapInterval; + this.textureUnit = textureUnit; + this.keepTextureBound = false; + + st = new ShaderState(); + // st.setVerbose(true); + pmvMatrix = new PMVMatrix(); + + fbo0 = new FBObject(); + + numSamples = 0; + } + + public void setClearBuffers(boolean v) { clearBuffers = v; } + + public void setKeepTextureBound(boolean v) { + this.keepTextureBound = v; + } + public void setMSAA(int numSamples) { + this.numSamples=numSamples; + } + public int getMSAA() { return numSamples; } + + @Override + public void init(GLAutoDrawable drawable) { + final GL2ES2 gl = drawable.getGL().getGL2ES2(); + + demo.init(drawable); + + final ShaderCode vp0 = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, TextureDraw02ES2ListenerFBO.class, "shader", + "shader/bin", "texture01_xxx", true); + final ShaderCode fp0 = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, TextureDraw02ES2ListenerFBO.class, "shader", + "shader/bin", "texture02_xxx", true); + vp0.defaultShaderCustomization(gl, true, true); + fp0.defaultShaderCustomization(gl, true, true); + + sp0 = new ShaderProgram(); + sp0.add(gl, vp0, System.err); + sp0.add(gl, fp0, System.err); + st.attachShaderProgram(gl, sp0, true); + + pmvMatrixUniform = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf()); + st.ownUniform(pmvMatrixUniform); + st.uniform(gl, pmvMatrixUniform); + + interleavedVBO = GLArrayDataServer.createGLSLInterleaved(3+4+2, GL.GL_FLOAT, false, 3*4, GL.GL_STATIC_DRAW); + { + interleavedVBO.addGLSLSubArray("mgl_Vertex", 3, GL.GL_ARRAY_BUFFER); + interleavedVBO.addGLSLSubArray("mgl_Color", 4, GL.GL_ARRAY_BUFFER); + //interleavedVBO.addGLSLSubArray("mgl_Normal", 3, GL.GL_ARRAY_BUFFER); + interleavedVBO.addGLSLSubArray("mgl_MultiTexCoord", 2, GL.GL_ARRAY_BUFFER); + + FloatBuffer ib = (FloatBuffer)interleavedVBO.getBuffer(); + + for(int i=0; i<4; i++) { + ib.put(s_quadVertices, i*3, 3); + ib.put(s_quadColors, i*4, 4); + //ib.put(s_cubeNormals, i*3, 3); + ib.put(s_quadTexCoords, i*2, 2); + } + } + interleavedVBO.seal(gl, true); + interleavedVBO.enableBuffer(gl, false); + st.ownAttribute(interleavedVBO, true); + + texUnit0 = new GLUniformData("mgl_Texture0", textureUnit); + st.ownUniform(texUnit0); + st.uniform(gl, texUnit0); + + st.useProgram(gl, false); + + gl.glEnable(GL2ES2.GL_DEPTH_TEST); + } + + private void initFBOs(GL gl, int width, int height) { + // remove all texture attachments, since MSAA uses just color-render-buffer + // and non-MSAA uses texture2d-buffer + fbo0.detachAllColorbuffer(gl); + + fbo0.reset(gl, width, height, numSamples, false); + numSamples = fbo0.getNumSamples(); + + if(numSamples>0) { + fbo0.attachColorbuffer(gl, 0, true); + fbo0.resetSamplingSink(gl); + fbo0Tex = fbo0.getSamplingSink(); + } else { + fbo0Tex = fbo0.attachTexture2D(gl, 0, true); + } + numSamples=fbo0.getNumSamples(); + fbo0.attachRenderbuffer(gl, Type.DEPTH, 24); + fbo0.unbind(gl); + } + + private void resetFBOs(GL gl, int width, int height) { + fbo0.reset(gl, width, height, numSamples, true); + numSamples = fbo0.getNumSamples(); + if(numSamples>0) { + fbo0Tex = fbo0.getSamplingSink(); + } else { + fbo0Tex = (TextureAttachment) fbo0.getColorbuffer(0); + } + } + + @Override + public void dispose(GLAutoDrawable drawable) { + final GL2ES2 gl = drawable.getGL().getGL2ES2(); + demo.dispose(drawable); + fbo0.destroy(gl); + st.destroy(gl); + + fbo0Tex = null; + sp0 = null; + pmvMatrixUniform = null; + interleavedVBO = null; + } + + @Override + public void display(GLAutoDrawable drawable) { + final GL2ES2 gl = drawable.getGL().getGL2ES2(); + + if( fbo0.getNumSamples() != numSamples ) { + System.err.println("**** NumSamples: "+fbo0.getNumSamples()+" -> "+numSamples); + resetFBOs(gl, drawable.getWidth(), drawable.getHeight()); + } + + if(0 < numSamples) { + gl.glEnable(GL.GL_MULTISAMPLE); + } + + fbo0.bind(gl); + demo.display(drawable); + fbo0.unbind(gl); + + st.useProgram(gl, true); + if( clearBuffers ) { + gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); + } + + if( !keepTextureBound ) { + gl.glActiveTexture(GL.GL_TEXTURE0 + texUnit0.intValue()); + fbo0.use(gl, fbo0Tex); + if( !gl.isGLcore() ) { + gl.glEnable(GL.GL_TEXTURE_2D); + } + } + gl.glActiveTexture(GL.GL_TEXTURE0 + texUnit0.intValue()); + interleavedVBO.enableBuffer(gl, true); + + gl.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 4); + + interleavedVBO.enableBuffer(gl, false); + + if( !keepTextureBound ) { + fbo0.unuse(gl); + } + + st.useProgram(gl, false); + } + + @Override + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { + final GL2ES2 gl = drawable.getGL().getGL2ES2(); + + if(-1 != swapInterval) { + gl.setSwapInterval(swapInterval); // in case switching the drawable (impl. may bound attribute there) + } + + if( !fbo0.isInitialized() ) { + System.err.println("**** Reshape.Init: "+width+"x"+height); + initFBOs(gl, width, height); + } else { + System.err.println("**** Reshape.Reset: "+width+"x"+height); + if( keepTextureBound ) { + fbo0.unuse(gl); + } + resetFBOs(gl, width, height); + } + + fbo0.bind(gl); + demo.reshape(drawable, x, y, width, height); + fbo0.unbind(gl); + + if( keepTextureBound ) { + gl.glActiveTexture(GL.GL_TEXTURE0 + texUnit0.intValue()); + fbo0.use(gl, fbo0Tex); + if( !gl.isGLcore() ) { + gl.glEnable(GL.GL_TEXTURE_2D); + } + } + + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); + pmvMatrix.glLoadIdentity(); + pmvMatrix.glOrthof(-1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 10.0f); + + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); + pmvMatrix.glLoadIdentity(); + + st.useProgram(gl, true); + st.uniform(gl, pmvMatrixUniform); + st.useProgram(gl, false); + + } + + private static final float[] s_quadVertices = { + -1f, -1f, 0f, // LB + 1f, -1f, 0f, // RB + -1f, 1f, 0f, // LT + 1f, 1f, 0f // RT + }; + private static final float[] s_quadColors = { + 1f, 1f, 1f, 1f, + 1f, 1f, 1f, 1f, + 1f, 1f, 1f, 1f, + 1f, 1f, 1f, 1f }; + private static final float[] s_quadTexCoords = { + 0f, 0f, // LB + 1f, 0f, // RB + 0f, 1f, // LT + 1f, 1f // RT + }; +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/TextureDraw01GL2Listener.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/TextureDraw01GL2Listener.java index af30c265b..fb8e6bfa3 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/TextureDraw01GL2Listener.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/gl2/TextureDraw01GL2Listener.java @@ -43,21 +43,35 @@ public class TextureDraw01GL2Listener implements GLEventListener, TextureDraw01A private GLU glu = new GLU(); private TextureData textureData; private Texture texture; + boolean keepTextureBound; public TextureDraw01GL2Listener(TextureData td) { this.textureData = td; + this.keepTextureBound = false; } + @Override + public void setKeepTextureBound(boolean v) { + this.keepTextureBound = v; + } + @Override + public Texture getTexture( ) { + return this.texture; + } + + @Override public void init(GLAutoDrawable drawable) { + GL2 gl = drawable.getGL().getGL2(); if(null!=textureData) { this.texture = TextureIO.newTexture(drawable.getGL(), textureData); + if( keepTextureBound ) { + texture.enable(gl); + texture.bind(gl); + } } } - public Texture getTexture( ) { - return this.texture; - } - + @Override public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { GL2 gl = drawable.getGL().getGL2(); gl.glMatrixMode(GL2ES1.GL_PROJECTION); @@ -67,6 +81,7 @@ public class TextureDraw01GL2Listener implements GLEventListener, TextureDraw01A gl.glLoadIdentity(); } + @Override public void dispose(GLAutoDrawable drawable) { GL2 gl = drawable.getGL().getGL2(); if(null!=texture) { @@ -78,13 +93,16 @@ public class TextureDraw01GL2Listener implements GLEventListener, TextureDraw01A } } + @Override public void display(GLAutoDrawable drawable) { GL2 gl = drawable.getGL().getGL2(); // draw one quad with the texture if(null!=texture) { - texture.enable(gl); - texture.bind(gl); + if( !keepTextureBound ) { + texture.enable(gl); + texture.bind(gl); + } gl.glTexEnvi(GL2.GL_TEXTURE_ENV, GL2.GL_TEXTURE_ENV_MODE, GL2.GL_REPLACE); TextureCoords coords = texture.getImageTexCoords(); gl.glBegin(GL2.GL_QUADS); @@ -97,7 +115,9 @@ public class TextureDraw01GL2Listener implements GLEventListener, TextureDraw01A gl.glTexCoord2f(coords.left(), coords.top()); gl.glVertex3f(0, 1, 0); gl.glEnd(); - texture.disable(gl); + if( !keepTextureBound ) { + texture.disable(gl); + } } } } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/DemoGL2ES1TextureImmModeSink.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/DemoGL2ES1TextureImmModeSink.java index 75a98ed1e..3e58d3c79 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/util/DemoGL2ES1TextureImmModeSink.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/DemoGL2ES1TextureImmModeSink.java @@ -58,9 +58,11 @@ public class DemoGL2ES1TextureImmModeSink implements GLEventListener, TextureDra private GLU glu = new GLU(); private TextureData textureData; private Texture texture; + boolean keepTextureBound; public DemoGL2ES1TextureImmModeSink() { this.ims = ImmModeSink.createFixed(32, 3, GL.GL_FLOAT, 4, GL.GL_FLOAT, 0, GL.GL_FLOAT, 2, GL.GL_FLOAT, GL.GL_STATIC_DRAW); + this.keepTextureBound = false; } public void setForceFFPEmu(boolean forceFFPEmu, boolean verboseFFPEmu, boolean debugFFPEmu, boolean traceFFPEmu) { @@ -70,6 +72,17 @@ public class DemoGL2ES1TextureImmModeSink implements GLEventListener, TextureDra this.traceFFPEmu = traceFFPEmu; } + + @Override + public void setKeepTextureBound(boolean v) { + this.keepTextureBound = v; + } + @Override + public Texture getTexture( ) { + return this.texture; + } + + @Override public void init(GLAutoDrawable drawable) { GL _gl = drawable.getGL(); if(debugFFPEmu) { @@ -87,15 +100,16 @@ public class DemoGL2ES1TextureImmModeSink implements GLEventListener, TextureDra InputStream testTextureStream = testTextureUrlConn.getInputStream(); textureData = TextureIO.newTextureData(gl.getGLProfile(), testTextureStream , false /* mipmap */, TextureIO.PNG); texture = TextureIO.newTexture(gl, textureData); + if( keepTextureBound && null != texture ) { + texture.enable(gl); + texture.bind(gl); + } } catch (Exception e) { e.printStackTrace(); } } - public Texture getTexture( ) { - return this.texture; - } - + @Override public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { GL2ES1 gl = drawable.getGL().getGL2ES1(); gl.glMatrixMode(GL2ES1.GL_PROJECTION); @@ -105,6 +119,7 @@ public class DemoGL2ES1TextureImmModeSink implements GLEventListener, TextureDra gl.glLoadIdentity(); } + @Override public void dispose(GLAutoDrawable drawable) { GL2ES1 gl = drawable.getGL().getGL2ES1(); if(null!=texture) { @@ -116,13 +131,16 @@ public class DemoGL2ES1TextureImmModeSink implements GLEventListener, TextureDra } } + @Override public void display(GLAutoDrawable drawable) { GL2ES1 gl = drawable.getGL().getGL2ES1(); // draw one quad with the texture if(null!=texture) { - texture.enable(gl); - texture.bind(gl); + if( !keepTextureBound ) { + texture.enable(gl); + texture.bind(gl); + } // gl.glTexEnvi(GL.GL_TEXTURE_ENV, GL2.GL_TEXTURE_ENV_MODE, GL2.GL_REPLACE); TextureCoords coords = texture.getImageTexCoords(); ims.glBegin(ImmModeSink.GL_QUADS); @@ -135,7 +153,9 @@ public class DemoGL2ES1TextureImmModeSink implements GLEventListener, TextureDra ims.glTexCoord2f(coords.left(), coords.top()); ims.glVertex3f(0, 1, 0); ims.glEnd(gl); - texture.disable(gl); + if( !keepTextureBound ) { + texture.disable(gl); + } } } } diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGImage01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGImage01NEWT.java index 8289cc381..c92174a77 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGImage01NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGImage01NEWT.java @@ -108,7 +108,7 @@ public class TestJPEGImage01NEWT extends UITestCase { // load texture from file inside current GL context to match the way // the bug submitter was doing it - final GLEventListener gle = new TextureDraw01ES2Listener( texData ) ; + final GLEventListener gle = new TextureDraw01ES2Listener( texData, 0 ) ; glad.addGLEventListener(gle); glad.addGLEventListener(new GLEventListener() { boolean shot = false; diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGJoglAWTCompareNewtAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGJoglAWTCompareNewtAWT.java index 653923bc4..dbb4002a3 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGJoglAWTCompareNewtAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGJoglAWTCompareNewtAWT.java @@ -137,7 +137,7 @@ public class TestJPEGJoglAWTCompareNewtAWT extends UITestCase { // load texture from file inside current GL context to match the way // the bug submitter was doing it - final GLEventListener gle = new TextureDraw01ES2Listener( texData ) ; + final GLEventListener gle = new TextureDraw01ES2Listener( texData, 0 ) ; glad1.addGLEventListener(gle); glad1.addGLEventListener(new GLEventListener() { boolean shot = false; @@ -193,7 +193,7 @@ public class TestJPEGJoglAWTCompareNewtAWT extends UITestCase { // the bug submitter was doing it final GLEventListener gle; if( texData != null ) { - gle = new TextureDraw01ES2Listener( texData ) ; + gle = new TextureDraw01ES2Listener( texData, 0 ) ; glad1.addGLEventListener(gle); } else { gle = null; diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGTextureFromFileNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGTextureFromFileNEWT.java index 13686cc22..60855e5be 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGTextureFromFileNEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestJPEGTextureFromFileNEWT.java @@ -184,7 +184,7 @@ public class TestJPEGTextureFromFileNEWT extends UITestCase { // load texture from file inside current GL context to match the way // the bug submitter was doing it - final GLEventListener gle = useFFP ? new TextureDraw01GL2Listener( texData ) : new TextureDraw01ES2Listener( texData ) ; + final GLEventListener gle = useFFP ? new TextureDraw01GL2Listener( texData ) : new TextureDraw01ES2Listener( texData, 0 ) ; glad.addGLEventListener(gle); glad.addGLEventListener(new GLEventListener() { boolean shot = false; diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGImage01NEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGImage01NEWT.java index 91ace8420..29e041908 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGImage01NEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGImage01NEWT.java @@ -109,7 +109,7 @@ public class TestPNGImage01NEWT extends UITestCase { // load texture from file inside current GL context to match the way // the bug submitter was doing it - final TextureDraw01ES2Listener gle = new TextureDraw01ES2Listener( texData ) ; + final TextureDraw01ES2Listener gle = new TextureDraw01ES2Listener( texData, 0 ) ; // gle.setClearColor(new float[] { 1.0f, 0.0f, 0.0f, 1.0f } ); glad.addGLEventListener(gle); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGTextureFromFileAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGTextureFromFileAWT.java index 6a15300a7..191d67d31 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGTextureFromFileAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGTextureFromFileAWT.java @@ -133,7 +133,7 @@ public class TestPNGTextureFromFileAWT extends UITestCase { // load texture from file inside current GL context to match the way // the bug submitter was doing it - final GLEventListener gle = useFFP ? new TextureDraw01GL2Listener( texData ) : new TextureDraw01ES2Listener( texData ) ; + final GLEventListener gle = useFFP ? new TextureDraw01GL2Listener( texData ) : new TextureDraw01ES2Listener( texData, 0 ) ; glc.addGLEventListener(gle); glc.addGLEventListener(new GLEventListener() { boolean shot = false; diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGTextureFromFileNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGTextureFromFileNEWT.java index 1bc526429..ce363b612 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGTextureFromFileNEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestPNGTextureFromFileNEWT.java @@ -174,7 +174,7 @@ public class TestPNGTextureFromFileNEWT extends UITestCase { // load texture from file inside current GL context to match the way // the bug submitter was doing it - final GLEventListener gle = useFFP ? new TextureDraw01GL2Listener( texData ) : new TextureDraw01ES2Listener( texData ) ; + final GLEventListener gle = useFFP ? new TextureDraw01GL2Listener( texData ) : new TextureDraw01ES2Listener( texData, 0 ) ; glad.addGLEventListener(gle); glad.addGLEventListener(new GLEventListener() { boolean shot = false; diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestTGATextureFromFileNEWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestTGATextureFromFileNEWT.java index 3e1acdb39..859e4e4b5 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestTGATextureFromFileNEWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/util/texture/TestTGATextureFromFileNEWT.java @@ -105,7 +105,7 @@ public class TestTGATextureFromFileNEWT extends UITestCase { // load texture from file inside current GL context to match the way // the bug submitter was doing it - final GLEventListener gle = useFFP ? new TextureDraw01GL2Listener( texData ) : new TextureDraw01ES2Listener( texData ) ; + final GLEventListener gle = useFFP ? new TextureDraw01GL2Listener( texData ) : new TextureDraw01ES2Listener( texData, 0 ) ; glad.addGLEventListener(gle); glad.addGLEventListener(new GLEventListener() { boolean shot = false; |