diff options
author | Sven Gothel <[email protected]> | 2013-11-07 15:30:26 +0100 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2013-11-07 15:30:26 +0100 |
commit | 8f1373e15eef1fb8bd00dfe500a2eddc71a74d7e (patch) | |
tree | b1f0f19ce68f3ae7809404112800a418fdd7247b | |
parent | 144b9ef5a433b2a93f5503b1c935c8f7ec61a0de (diff) |
Android ES3 Movie Demos: Add workaround for: P0003: Extension 'GL_OES_EGL_image_external' not supported
+ // Bug on Nexus 10, ES3 - Android 4.3, where
+ // GL_OES_EGL_image_external extension directive leads to a failure _with_ '#version 300 es' !
+ // P0003: Extension 'GL_OES_EGL_image_external' not supported
+ preludeGLSLVersion = false;
5 files changed, 229 insertions, 205 deletions
diff --git a/src/jogl/classes/com/jogamp/opengl/util/av/GLMediaPlayer.java b/src/jogl/classes/com/jogamp/opengl/util/av/GLMediaPlayer.java index f0864f949..b0a645cbb 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/av/GLMediaPlayer.java +++ b/src/jogl/classes/com/jogamp/opengl/util/av/GLMediaPlayer.java @@ -318,9 +318,6 @@ public interface GLMediaPlayer extends TextureSequence { public int getTextureCount(); - /** Returns the texture target used by implementation. */ - public int getTextureTarget(); - /** Sets the texture unit. Defaults to 0. */ public void setTextureUnit(int u); diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureSequence.java b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureSequence.java index 6f1dd4c64..6c2949c2b 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureSequence.java +++ b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureSequence.java @@ -163,6 +163,9 @@ public interface TextureSequence { public void newFrameAvailable(T ts, TextureFrame newFrame, long when); } + /** Returns the texture target used by implementation. */ + public int getTextureTarget(); + /** Return the texture unit used to render the current frame. */ public int getTextureUnit(); diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/TextureSequenceDemo01.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/TextureSequenceDemo01.java index ab3899a7b..38d4d8be8 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/TextureSequenceDemo01.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/TextureSequenceDemo01.java @@ -13,16 +13,16 @@ import com.jogamp.opengl.util.texture.TextureIO; import com.jogamp.opengl.util.texture.TextureSequence; public class TextureSequenceDemo01 implements TextureSequence { - TextureSequence.TextureFrame frame = null; + TextureSequence.TextureFrame frame = null; int textureUnit = 0; protected int[] texMinMagFilter = { GL.GL_NEAREST, GL.GL_NEAREST }; protected int[] texWrapST = { GL.GL_CLAMP_TO_EDGE, GL.GL_CLAMP_TO_EDGE }; final boolean useBuildInTexLookup; - + public TextureSequenceDemo01(boolean useBuildInTexLookup) { this.useBuildInTexLookup = useBuildInTexLookup; } - + public void initGLResources(GL gl) throws GLException { if(null == frame) { TextureData texData = null; @@ -38,24 +38,29 @@ public class TextureSequenceDemo01 implements TextureSequence { frame = new TextureSequence.TextureFrame(tex); tex.bind(gl); gl.glTexParameteri(tex.getTarget(), GL.GL_TEXTURE_MIN_FILTER, texMinMagFilter[0]); - gl.glTexParameteri(tex.getTarget(), GL.GL_TEXTURE_MAG_FILTER, texMinMagFilter[1]); + gl.glTexParameteri(tex.getTarget(), GL.GL_TEXTURE_MAG_FILTER, texMinMagFilter[1]); gl.glTexParameteri(tex.getTarget(), GL.GL_TEXTURE_WRAP_S, texWrapST[0]); gl.glTexParameteri(tex.getTarget(), GL.GL_TEXTURE_WRAP_T, texWrapST[1]); } } - + public void destroyGLResources(GL gl) { if(null != frame) { frame.getTexture().destroy(gl); frame = null; } } - + public void destroy(GL gl) throws GLException { frame.getTexture().destroy(gl); - frame = null; + frame = null; + } + + @Override + public int getTextureTarget() { + return GL.GL_TEXTURE_2D; } - + @Override public int getTextureUnit() { return textureUnit; @@ -80,19 +85,19 @@ public class TextureSequenceDemo01 implements TextureSequence { public TextureSequence.TextureFrame getNextTexture(GL gl) throws IllegalStateException { return frame; } - + @Override public String getRequiredExtensionsShaderStub() throws IllegalStateException { return "// TextTextureSequence: No extensions required\n"; } - + @Override public String getTextureSampler2DType() throws IllegalStateException { return "sampler2D" ; - } - + } + private String textureLookupFunctionName = "myTexture2D"; - + @Override public String getTextureLookupFunctionName(String desiredFuncName) throws IllegalStateException { if(useBuildInTexLookup) { @@ -103,7 +108,7 @@ public class TextureSequenceDemo01 implements TextureSequence { } return textureLookupFunctionName; } - + @Override public String getTextureLookupFragmentShaderImpl() throws IllegalStateException { if(useBuildInTexLookup) { diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/TextureSequenceCubeES2.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/TextureSequenceCubeES2.java index a2d3eb6bf..616aa52c3 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/TextureSequenceCubeES2.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/TextureSequenceCubeES2.java @@ -3,14 +3,14 @@ * * 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 @@ -20,7 +20,7 @@ * 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. @@ -39,6 +39,7 @@ import javax.media.opengl.GLProfile; import javax.media.opengl.GLUniformData; import javax.media.opengl.fixedfunc.GLMatrixFunc; +import com.jogamp.common.os.Platform; import com.jogamp.newt.Window; import com.jogamp.newt.event.MouseAdapter; import com.jogamp.newt.event.MouseEvent; @@ -73,19 +74,20 @@ public class TextureSequenceCubeES2 implements GLEventListener { // private float zoom0=-5.0f, zoom=zoom0; // private float view_rotx = 20.0f, view_roty = 30.0f, view_rotz = 0.0f; private float zoom=-2.3f; - private float view_rotx = 0.0f, view_roty = 0.0f, view_rotz = 0.0f; + private float view_rotx = 0.0f, view_roty = 0.0f; + private final float view_rotz = 0.0f; int[] vboNames = new int[4]; boolean innerCube; - + private final MouseListener mouseAction = new MouseAdapter() { int lx = 0; int ly = 0; boolean first = false; public void mousePressed(MouseEvent e) { - first = true; + first = true; } - public void mouseMoved(MouseEvent e) { + public void mouseMoved(MouseEvent e) { first = false; } public void mouseDragged(MouseEvent e) { @@ -102,7 +104,7 @@ public class TextureSequenceCubeES2 implements GLEventListener { height=comp.getHeight(); } else { throw new RuntimeException("Event source neither Window nor Component: "+source); - } + } if(e.getPointerCount()==2) { // 2 pointers zoom .. if(first) { @@ -112,14 +114,14 @@ public class TextureSequenceCubeES2 implements GLEventListener { } int nv = Math.abs(e.getY(0)-e.getY(1)); int dy = nv - lx; - + { final float o = zoom; - final float d = 40f*Math.signum(dy)/(float)height; + final float d = 40f*Math.signum(dy)/height; zoom += d; System.err.println("zoom.d: "+o+" + "+d+" -> "+zoom); } - + lx = nv; } else { // 1 pointer rotate @@ -136,7 +138,7 @@ public class TextureSequenceCubeES2 implements GLEventListener { lx = nx; ly = ny; } - } + } public void mouseWheelMoved(MouseEvent e) { // System.err.println("XXX "+e); if( !e.isShiftDown() ) { @@ -147,31 +149,44 @@ public class TextureSequenceCubeES2 implements GLEventListener { } } }; - + static final String shaderBasename = "texsequence_xxx"; static final String myTextureLookupName = "myTexture2D"; - + private void initShader(GL2ES2 gl) { // Create & Compile the shader objects - ShaderCode rsVp = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, this.getClass(), + ShaderCode rsVp = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, this.getClass(), "shader", "shader/bin", shaderBasename, true); - ShaderCode rsFp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, this.getClass(), + ShaderCode rsFp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, this.getClass(), "shader", "shader/bin", shaderBasename, true); - rsVp.defaultShaderCustomization(gl, true, true); - int rsFpPos = rsFp.addGLSLVersion(gl); + boolean preludeGLSLVersion = true; + if( GLES2.GL_TEXTURE_EXTERNAL_OES == texSeq.getTextureTarget() ) { + if( !gl.isExtensionAvailable(GLExtensions.OES_EGL_image_external) ) { + throw new GLException(GLExtensions.OES_EGL_image_external+" requested but not available"); + } + if( Platform.OSType.ANDROID == Platform.getOSType() && gl.isGLES3() ) { + // Bug on Nexus 10, ES3 - Android 4.3, where + // GL_OES_EGL_image_external extension directive leads to a failure _with_ '#version 300 es' ! + // P0003: Extension 'GL_OES_EGL_image_external' not supported + preludeGLSLVersion = false; + } + } + rsVp.defaultShaderCustomization(gl, preludeGLSLVersion, true); + + int rsFpPos = preludeGLSLVersion ? rsFp.addGLSLVersion(gl) : 0; rsFpPos = rsFp.insertShaderSource(0, rsFpPos, texSeq.getRequiredExtensionsShaderStub()); rsFpPos = rsFp.addDefaultShaderPrecision(gl, rsFpPos); - - final String texLookupFuncName = texSeq.getTextureLookupFunctionName(myTextureLookupName); + + final String texLookupFuncName = texSeq.getTextureLookupFunctionName(myTextureLookupName); rsFp.replaceInShaderSource(myTextureLookupName, texLookupFuncName); - + // Inject TextureSequence shader details final StringBuilder sFpIns = new StringBuilder(); sFpIns.append("uniform ").append(texSeq.getTextureSampler2DType()).append(" mgl_ActiveTexture;\n"); sFpIns.append(texSeq.getTextureLookupFragmentShaderImpl()); rsFp.insertShaderSource(0, "TEXTURE-SEQUENCE-CODE-BEGIN", 0, sFpIns); - + // Create & Link the shader program ShaderProgram sp = new ShaderProgram(); sp.add(rsVp); @@ -184,9 +199,9 @@ public class TextureSequenceCubeES2 implements GLEventListener { st = new ShaderState(); st.attachShaderProgram(gl, sp, false); } - + GLArrayDataServer interleavedVBO, cubeIndicesVBO; - + public void init(GLAutoDrawable drawable) { GL2ES2 gl = drawable.getGL().getGL2ES2(); System.err.println(JoglVersion.getGLInfo(gl, null)); @@ -195,15 +210,10 @@ public class TextureSequenceCubeES2 implements GLEventListener { return; } final Texture tex= frame.getTexture(); - - final boolean useExternalTexture = GLES2.GL_TEXTURE_EXTERNAL_OES == tex.getTarget(); - if(useExternalTexture && !gl.isExtensionAvailable(GLExtensions.OES_EGL_image_external)) { - throw new GLException(GLExtensions.OES_EGL_image_external+" requested but not available"); - } - + initShader(gl); - // Push the 1st uniform down the path + // Push the 1st uniform down the path st.useProgram(gl, true); pmvMatrix = new PMVMatrix(); @@ -215,10 +225,10 @@ public class TextureSequenceCubeES2 implements GLEventListener { if(!st.uniform(gl, new GLUniformData("mgl_ActiveTexture", texSeq.getTextureUnit()))) { throw new GLException("Error setting mgl_ActiveTexture in shader: "+st); } - - + + // calculate centered tex coords w/ aspect ratio - float[] fixedCubeTexCoords = new float[s_cubeTexCoords.length]; + float[] fixedCubeTexCoords = new float[s_cubeTexCoords.length]; { final float aspect = tex.getAspectRatio(); final TextureCoords tc = tex.getImageTexCoords(); @@ -242,27 +252,27 @@ public class TextureSequenceCubeES2 implements GLEventListener { } } } - + interleavedVBO = GLArrayDataServer.createGLSLInterleaved(3+4+2, GL.GL_FLOAT, false, 3*6*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_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<6*4; i++) { ib.put(s_cubeVertices, i*3, 3); - ib.put(s_cubeColors, i*4, 4); + ib.put(s_cubeColors, i*4, 4); //ib.put(s_cubeNormals, i*3, 3); ib.put(fixedCubeTexCoords, i*2, 2); - } + } } interleavedVBO.seal(gl, true); interleavedVBO.enableBuffer(gl, false); st.ownAttribute(interleavedVBO, true); - + cubeIndicesVBO = GLArrayDataServer.createData(6, GL.GL_UNSIGNED_SHORT, 6, GL.GL_STATIC_DRAW, GL.GL_ELEMENT_ARRAY_BUFFER); for(int i=0; i<6*6; i++) { cubeIndicesVBO.puts(s_cubeIndices[i]); @@ -270,26 +280,26 @@ public class TextureSequenceCubeES2 implements GLEventListener { cubeIndicesVBO.seal(gl, true); cubeIndicesVBO.enableBuffer(gl, false); st.ownAttribute(cubeIndicesVBO, true); - - + + gl.glEnable(GL2ES2.GL_DEPTH_TEST); st.useProgram(gl, false); final Object upstreamWidget = drawable.getUpstreamWidget(); - if (upstreamWidget instanceof Window) { + if (upstreamWidget instanceof Window) { final Window window = (Window) upstreamWidget; window.addMouseListener(mouseAction); } else if (GLProfile.isAWTAvailable() && upstreamWidget instanceof java.awt.Component) { final java.awt.Component comp = (java.awt.Component) upstreamWidget; new com.jogamp.newt.event.awt.AWTMouseAdapter(mouseAction).addTo(comp); } - + // Let's show the completed shader state .. System.out.println("iVBO: "+interleavedVBO); System.out.println(st); } - + public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { GL2ES2 gl = drawable.getGL().getGL2ES2(); @@ -318,8 +328,8 @@ public class TextureSequenceCubeES2 implements GLEventListener { st.useProgram(gl, false); } } - - + + private void reshapePMV(int width, int height) { if(null != pmvMatrix) { pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); @@ -332,7 +342,7 @@ public class TextureSequenceCubeES2 implements GLEventListener { nearPlaneNormalized = 0f; } System.err.println("XXX0: Perspective nearPlaneNormalized: "+nearPlaneNormalized); - + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); pmvMatrix.glLoadIdentity(); pmvMatrix.glTranslatef(0, 0, zoom); @@ -344,7 +354,7 @@ public class TextureSequenceCubeES2 implements GLEventListener { public void dispose(GLAutoDrawable drawable) { GL2ES2 gl = drawable.getGL().getGL2ES2(); - texSeq = null; + texSeq = null; pmvMatrixUniform = null; if( null != pmvMatrix ) { pmvMatrix.destroy(); @@ -361,13 +371,13 @@ public class TextureSequenceCubeES2 implements GLEventListener { GL2ES2 gl = drawable.getGL().getGL2ES2(); gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); - + if( null == st ) { return; } - + st.useProgram(gl, true); - + pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); pmvMatrix.glLoadIdentity(); pmvMatrix.glTranslatef(0, 0, zoom); @@ -383,18 +393,18 @@ public class TextureSequenceCubeES2 implements GLEventListener { tex = texFrame.getTexture(); gl.glActiveTexture(GL.GL_TEXTURE0+texSeq.getTextureUnit()); tex.enable(gl); - tex.bind(gl); + tex.bind(gl); } } cubeIndicesVBO.bindBuffer(gl, true); // keeps VBO binding gl.glDrawElements(GL2ES2.GL_TRIANGLES, cubeIndicesVBO.getElementCount() * cubeIndicesVBO.getComponentCount(), GL2ES2.GL_UNSIGNED_SHORT, 0); cubeIndicesVBO.bindBuffer(gl, false); - + if(null != tex) { - tex.disable(gl); + tex.disable(gl); } interleavedVBO.enableBuffer(gl, false); - st.useProgram(gl, false); + st.useProgram(gl, false); } static final float[] light_position = { -50.f, 50.f, 50.f, 0.f }; @@ -406,18 +416,18 @@ public class TextureSequenceCubeES2 implements GLEventListener { private static final float[] s_cubeVertices = /* f b t b r l */ { -1f, 1f, 1f, 1f, -1f, 1f, 1f, 1f, 1f, -1f, -1f, 1f, - + -1f, 1f, -1f, 1f, -1f, -1f, 1f, 1f, -1f, -1f, -1f, -1f, - + -1f, -1f, 1f, 1f, -1f, -1f, 1f, -1f, 1f, -1f, -1f, -1f, - + -1f, 1f, 1f, 1f, 1f, -1f, 1f, 1f, 1f, -1f, 1f, -1f, - + 1f, -1f, 1f, 1f, 1f, -1f, 1f, 1f, 1f, 1f, -1f, -1f, - + -1f, -1f, 1f, -1f, 1f, -1f, -1f, 1f, 1f, -1f, -1f, -1f }; - + private static final float[] s_cubeTexCoords = { // LT RB RT LB 0f, 1f, 1f, 0f, 1f, 1f, 0f, 0f, @@ -436,39 +446,39 @@ public class TextureSequenceCubeES2 implements GLEventListener { private static final float[] s_cubeColors = { 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, - + 40f/255f, 80f/255f, 160f/255f, 255f/255f, 40f/255f, 80f/255f, 160f/255f, 255f/255f, 40f/255f, 80f/255f, 160f/255f, 255f/255f, 40f/255f, 80f/255f, 160f/255f, 255f/255f, - + 40f/255f, 80f/255f, 160f/255f, 255f/255f, 40f/255f, 80f/255f, 160f/255f, 255f/255f, - 40f/255f, 80f/255f, 160f/255f, 255f/255f, 40f/255f, 80f/255f, 160f/255f, 255f/255f, - + 40f/255f, 80f/255f, 160f/255f, 255f/255f, 40f/255f, 80f/255f, 160f/255f, 255f/255f, + 128f/255f, 128f/255f, 128f/255f, 255f/255f, 128f/255f, 128f/255f, 128f/255f, 255f/255f, 128f/255f, 128f/255f, 128f/255f, 255f/255f, 128f/255f, 128f/255f, 128f/255f, 255f/255f, - + 255f/255f, 110f/255f, 10f/255f, 255f/255f, 255f/255f, 110f/255f, 10f/255f, 255f/255f, 255f/255f, 110f/255f, 10f/255f, 255f/255f, 255f/255f, 110f/255f, 10f/255f, 255f/255f, - + 255f/255f, 70f/255f, 60f/255f, 255f/255f, 255f/255f, 70f/255f, 60f/255f, 255f/255f, 255f/255f, 70f/255f, 60f/255f, 255f/255f, 255f/255f, 70f/255f, 60f/255f, 255f/255f }; - + /* private static final float[] s_cubeNormals = { 0f, 0f, 1f, 0f, 0f, 1f, 0f, 0f, 1f, 0f, 0f, 1f, - + 0f, 0f, -1f, 0f, 0f, -1f, 0f, 0f, -1f, 0f, 0f, -1f, - + 0f, -1f, 0f, 0f, -1f, 0f, 0f, -1f, 0f, 0f, -1f, 0f, - + 0f, 1f, 0f, 0f, 1f, 0f, 0f, 1f, 0f, 0f, 1f, 0f, - + 1f, 0f, 0f, 1f, 0f, 0f, 1f, 0f, 0f, 1f, 0f, 0f, - + -1f, 0f, 0f, -1f, 0f, 0f, -1f, 0f, 0f, -1f, 0f, 0f };*/ - private static final short[] s_cubeIndices = + private static final short[] s_cubeIndices = { 0, 3, 1, 2, 0, 1, /* front */ 6, 5, 4, 5, 7, 4, /* back */ diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieSimple.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieSimple.java index a087e7e46..897079ec2 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieSimple.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/av/MovieSimple.java @@ -3,14 +3,14 @@ * * 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 @@ -20,7 +20,7 @@ * 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. @@ -44,6 +44,7 @@ import javax.media.opengl.GLProfile; import javax.media.opengl.GLUniformData; import javax.media.opengl.fixedfunc.GLMatrixFunc; +import com.jogamp.common.os.Platform; import com.jogamp.newt.Window; import com.jogamp.newt.event.KeyAdapter; import com.jogamp.newt.event.KeyEvent; @@ -74,12 +75,12 @@ import com.jogamp.opengl.util.texture.TextureSequence; import com.jogamp.opengl.util.texture.TextureSequence.TextureFrame; /** - * Simple planar movie player w/ orthogonal 1:1 projection. + * Simple planar movie player w/ orthogonal 1:1 projection. */ public class MovieSimple implements GLEventListener { public static final int EFFECT_NORMAL = 0; public static final int EFFECT_GRADIENT_BOTTOM2TOP = 1<<1; - public static final int EFFECT_TRANSPARENT = 1<<3; + public static final int EFFECT_TRANSPARENT = 1<<3; private static boolean waitForKey = false; private int winWidth, winHeight; @@ -96,9 +97,9 @@ public class MovieSimple implements GLEventListener { private int swapInterval = 1; private GLMediaPlayer mPlayer; - private boolean mPlayerShared; + private final boolean mPlayerShared; private boolean mPlayerScaleOrig; - private float[] verts = null; + private float[] verts = null; private GLArrayDataServer interleavedVBO; private volatile boolean resetGLState = false; @@ -107,7 +108,7 @@ public class MovieSimple implements GLEventListener { private GLUniformData pmvMatrixUniform; private static final String shaderBasename = "texsequence_xxx"; private static final String myTextureLookupName = "myTexture2D"; - + /** Blender's Big Buck Bunny Trailer: 24f 640p VP8, Vorbis 44100Hz mono, WebM/Matroska Stream. */ public static final URI defURI; static { @@ -119,7 +120,7 @@ public class MovieSimple implements GLEventListener { } defURI = _defURI; } - + private final MouseListener mouseAction = new MouseAdapter() { public void mousePressed(MouseEvent e) { if(e.getY()<=winHeight/2 && null!=mPlayer && 1 == e.getClickCount()) { @@ -144,16 +145,16 @@ public class MovieSimple implements GLEventListener { public void mouseDragged(MouseEvent e) { int x = e.getX(); int y = e.getY(); - + if(y>winHeight/2) { final float dp = (float)(x-prevMouseX)/(float)winWidth; - mPlayer.seek(mPlayer.getVideoPTS() + (int) (mPlayer.getDuration() * dp)); + mPlayer.seek(mPlayer.getVideoPTS() + (int) (mPlayer.getDuration() * dp)); } else { mPlayer.play(); - rotate = 1; + rotate = 1; zoom = zoom1; } - + prevMouseX = x; // prevMouseY = y; } @@ -164,12 +165,12 @@ public class MovieSimple implements GLEventListener { } } }; - + private final KeyListener keyAction = new KeyAdapter() { public void keyReleased(KeyEvent e) { if( e.isAutoRepeat() ) { return; - } + } System.err.println("MC "+e); int pts0 = mPlayer.getVideoPTS(); int pts1 = 0; @@ -195,7 +196,7 @@ public class MovieSimple implements GLEventListener { break; } case KeyEvent.VK_MULTIPLY: - mPlayer.setPlaySpeed(1.0f); + mPlayer.setPlaySpeed(1.0f); break; case KeyEvent.VK_SUBTRACT: { float playSpeed = mPlayer.getPlaySpeed(); @@ -204,7 +205,7 @@ public class MovieSimple implements GLEventListener { } else { playSpeed -= 0.1f; } - mPlayer.setPlaySpeed(playSpeed); + mPlayer.setPlaySpeed(playSpeed); } break; case KeyEvent.VK_ADD: { float playSpeed = mPlayer.getPlaySpeed(); @@ -213,7 +214,7 @@ public class MovieSimple implements GLEventListener { } else { playSpeed += 0.1f; } - mPlayer.setPlaySpeed(playSpeed); + mPlayer.setPlaySpeed(playSpeed); } break; case KeyEvent.VK_M: { float audioVolume = mPlayer.getAudioVolume(); @@ -222,27 +223,27 @@ public class MovieSimple implements GLEventListener { } else { audioVolume = 1f; } - mPlayer.setAudioVolume(audioVolume); + mPlayer.setAudioVolume(audioVolume); } break; } - + if( 0 != pts1 ) { mPlayer.seek(pts1); } - } + } }; - - /** - * Default constructor which also issues {@link #initStream(URI, int, int, int)} w/ default values + + /** + * Default constructor which also issues {@link #initStream(URI, int, int, int)} w/ default values * and polls until the {@link GLMediaPlayer} is {@link GLMediaPlayer.State#Initialized}. * If {@link GLMediaEventListener#EVENT_CHANGE_EOS} is reached, the stream is started over again. * <p> * This default constructor is merely useful for some <i>drop-in</i> test, e.g. using an applet. - * </p> + * </p> */ public MovieSimple() { this(null); - + mPlayer.addEventListener(new GLMediaEventListener() { @Override public void newFrameAvailable(GLMediaPlayer ts, TextureFrame newFrame, long when) { } @@ -259,7 +260,7 @@ public class MovieSimple implements GLEventListener { mPlayer.seek(0); mPlayer.play(); } - } + } }); initStream(defURI, GLMediaPlayer.STREAM_ID_AUTO, GLMediaPlayer.STREAM_ID_AUTO, 3 /* textureCount */); StreamException se = null; @@ -285,50 +286,63 @@ public class MovieSimple implements GLEventListener { } System.out.println("pC.1a shared "+mPlayerShared+", "+mPlayer); } - + public void initStream(URI streamLoc, int vid, int aid, int textureCount) { mPlayer.initStream(streamLoc, vid, aid, textureCount); System.out.println("pC.1b "+mPlayer); } - + public void setSwapInterval(int v) { this.swapInterval = v; } - + public GLMediaPlayer getGLMediaPlayer() { return mPlayer; } - + public void setScaleOrig(boolean v) { mPlayerScaleOrig = v; } - + /** defaults to true */ public void setOrthoProjection(boolean v) { orthoProjection=v; } public boolean getOrthoProjection() { return orthoProjection; } - + public boolean hasEffect(int e) { return 0 != ( effects & e ) ; } public void setEffects(int e) { effects = e; }; public void setTransparency(float alpha) { this.effects |= EFFECT_TRANSPARENT; this.alpha = alpha; - } + } public void resetGLState() { resetGLState = true; } - + private void initShader(GL2ES2 gl) { // Create & Compile the shader objects - ShaderCode rsVp = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, MovieSimple.class, + ShaderCode rsVp = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, MovieSimple.class, "../shader", "../shader/bin", shaderBasename, true); - ShaderCode rsFp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, MovieSimple.class, + ShaderCode rsFp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, MovieSimple.class, "../shader", "../shader/bin", shaderBasename, true); - rsVp.defaultShaderCustomization(gl, true, true); - int rsFpPos = rsFp.addGLSLVersion(gl); + boolean preludeGLSLVersion = true; + if( GLES2.GL_TEXTURE_EXTERNAL_OES == mPlayer.getTextureTarget() ) { + if( !gl.isExtensionAvailable(GLExtensions.OES_EGL_image_external) ) { + throw new GLException(GLExtensions.OES_EGL_image_external+" requested but not available"); + } + if( Platform.OSType.ANDROID == Platform.getOSType() && gl.isGLES3() ) { + // Bug on Nexus 10, ES3 - Android 4.3, where + // GL_OES_EGL_image_external extension directive leads to a failure _with_ '#version 300 es' ! + // P0003: Extension 'GL_OES_EGL_image_external' not supported + preludeGLSLVersion = false; + } + } + rsVp.defaultShaderCustomization(gl, preludeGLSLVersion, true); + + int rsFpPos = preludeGLSLVersion ? rsFp.addGLSLVersion(gl) : 0; rsFpPos = rsFp.insertShaderSource(0, rsFpPos, mPlayer.getRequiredExtensionsShaderStub()); rsFpPos = rsFp.addDefaultShaderPrecision(gl, rsFpPos); - - final String texLookupFuncName = mPlayer.getTextureLookupFunctionName(myTextureLookupName); + + final String texLookupFuncName = mPlayer.getTextureLookupFunctionName(myTextureLookupName); rsFp.replaceInShaderSource(myTextureLookupName, texLookupFuncName); - + // Inject TextureSequence shader details final StringBuilder sFpIns = new StringBuilder(); sFpIns.append("uniform ").append(mPlayer.getTextureSampler2DType()).append(" mgl_ActiveTexture;\n"); @@ -350,7 +364,7 @@ public class MovieSimple implements GLEventListener { @Override public void init(GLAutoDrawable drawable) { - if(null == mPlayer) { + if(null == mPlayer) { throw new InternalError("mPlayer null"); } if( GLMediaPlayer.State.Uninitialized == mPlayer.getState() ) { @@ -360,21 +374,20 @@ public class MovieSimple implements GLEventListener { throw new IllegalStateException("mPlayer has no VID/stream selected: "+mPlayer); } resetGLState = false; - + zoom0 = orthoProjection ? 0f : -2.5f; zoom1 = orthoProjection ? 0f : -5f; - zoom = zoom0; + zoom = zoom0; GL2ES2 gl = drawable.getGL().getGL2ES2(); System.err.println(JoglVersion.getGLInfo(gl, null)); System.err.println("Alpha: "+alpha+", opaque "+drawable.getChosenGLCapabilities().isBackgroundOpaque()+ ", "+drawable.getClass().getName()+", "+drawable); - + if(waitForKey) { UITestCase.waitForKey("Init>"); - } + } final Texture tex; - boolean useExternalTexture = false; try { System.out.println("p0 "+mPlayer+", shared "+mPlayerShared); if(!mPlayerShared && GLMediaPlayer.State.Initialized == mPlayer.getState() ) { @@ -386,10 +399,6 @@ public class MovieSimple implements GLEventListener { throw new InternalError("XXX: "+mPlayer); } tex = mPlayer.getLastTexture().getTexture(); - useExternalTexture = GLES2.GL_TEXTURE_EXTERNAL_OES == tex.getTarget(); - if(useExternalTexture && !gl.isExtensionAvailable(GLExtensions.OES_EGL_image_external)) { - throw new GLException(GLExtensions.OES_EGL_image_external+" requested but not available"); - } if(!mPlayerShared) { mPlayer.setTextureMinMagFilter( new int[] { GL.GL_NEAREST, GL.GL_LINEAR } ); } @@ -401,15 +410,15 @@ public class MovieSimple implements GLEventListener { } throw new GLException(glex); } - + initShader(gl); - // Push the 1st uniform down the path + // Push the 1st uniform down the path st.useProgram(gl, true); int[] viewPort = new int[] { 0, 0, drawable.getWidth(), drawable.getHeight()}; pmvMatrix = new PMVMatrix(); - reshapePMV(viewPort[2], viewPort[3]); + reshapePMV(viewPort[2], viewPort[3]); pmvMatrixUniform = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf()); if(!st.uniform(gl, pmvMatrixUniform)) { throw new GLException("Error setting PMVMatrix in shader: "+st); @@ -417,17 +426,17 @@ public class MovieSimple implements GLEventListener { if(!st.uniform(gl, new GLUniformData("mgl_ActiveTexture", mPlayer.getTextureUnit()))) { throw new GLException("Error setting mgl_ActiveTexture in shader: "+st); } - + float dWidth = drawable.getWidth(); float dHeight = drawable.getHeight(); float mWidth = mPlayer.getWidth(); - float mHeight = mPlayer.getHeight(); + float mHeight = mPlayer.getHeight(); float mAspect = mWidth/mHeight; System.err.println("XXX0: mov aspect: "+mAspect); float xs, ys; if(orthoProjection) { if(mPlayerScaleOrig && mWidth < dWidth && mHeight < dHeight) { - xs = mWidth/2f; ys = xs / mAspect; + xs = mWidth/2f; ys = xs / mAspect; } else { xs = dWidth/2f; ys = xs / mAspect; // w>h } @@ -453,16 +462,16 @@ public class MovieSimple implements GLEventListener { } 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_MultiTexCoord", 2, GL.GL_ARRAY_BUFFER); + { + interleavedVBO.addGLSLSubArray("mgl_Vertex", 3, GL.GL_ARRAY_BUFFER); + interleavedVBO.addGLSLSubArray("mgl_Color", 4, GL.GL_ARRAY_BUFFER); + interleavedVBO.addGLSLSubArray("mgl_MultiTexCoord", 2, GL.GL_ARRAY_BUFFER); } updateInterleavedVBO(gl, tex); - + st.ownAttribute(interleavedVBO, true); gl.glClearColor(0.3f, 0.3f, 0.3f, 0.3f); - + gl.glEnable(GL2ES2.GL_DEPTH_TEST); st.useProgram(gl, false); @@ -474,11 +483,11 @@ public class MovieSimple implements GLEventListener { if(!mPlayerShared) { mPlayer.play(); System.out.println("play.0 "+mPlayer); - } + } startTime = System.currentTimeMillis(); - + final Object upstreamWidget = drawable.getUpstreamWidget(); - if (upstreamWidget instanceof Window) { + if (upstreamWidget instanceof Window) { final Window window = (Window) upstreamWidget; window.addMouseListener(mouseAction); window.addKeyListener(keyAction); @@ -486,7 +495,7 @@ public class MovieSimple implements GLEventListener { winHeight = window.getHeight(); } } - + protected void updateInterleavedVBO(GL gl, Texture tex) { final float ss = 1f, ts = 1f; // scale tex-coord final boolean wasEnabled = interleavedVBO.enabled(); @@ -498,7 +507,7 @@ public class MovieSimple implements GLEventListener { System.err.println("XXX0: "+tc); System.err.println("XXX0: tex aspect: "+tex.getAspectRatio()); System.err.println("XXX0: tex y-flip: "+tex.getMustFlipVertically()); - + // left-bottom ib.put(verts[0]); ib.put(verts[1]); ib.put(verts[2]); if( hasEffect(EFFECT_GRADIENT_BOTTOM2TOP) ) { @@ -507,11 +516,11 @@ public class MovieSimple implements GLEventListener { ib.put( 1); ib.put( 1); ib.put( 1); ib.put(alpha); } ib.put( tc.left() *ss); ib.put( tc.bottom() *ts); - + // right-bottom ib.put(verts[3]); ib.put(verts[1]); ib.put(verts[2]); if( hasEffect(EFFECT_GRADIENT_BOTTOM2TOP) ) { - ib.put( 0); ib.put( 0); ib.put( 0); ib.put(alpha); + ib.put( 0); ib.put( 0); ib.put( 0); ib.put(alpha); } else { ib.put( 1); ib.put( 1); ib.put( 1); ib.put(alpha); } @@ -525,22 +534,22 @@ public class MovieSimple implements GLEventListener { ib.put( 1); ib.put( 1); ib.put( 1); ib.put(alpha); } ib.put( tc.left() *ss); ib.put( tc.top() *ts); - + // right-top ib.put(verts[3]); ib.put(verts[4]); ib.put(verts[2]); if( hasEffect(EFFECT_GRADIENT_BOTTOM2TOP) ) { ib.put( 1); ib.put( 1); ib.put( 1); ib.put(alpha); } else { ib.put( 1); ib.put( 1); ib.put( 1); ib.put(alpha); - } - ib.put( tc.right() *ss); ib.put( tc.top() *ts); + } + ib.put( tc.right() *ss); ib.put( tc.top() *ts); } interleavedVBO.seal(gl, true); if( !wasEnabled ) { interleavedVBO.enableBuffer(gl, false); } } - + @Override public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { final GL2ES2 gl = drawable.getGL().getGL2ES2(); @@ -550,23 +559,23 @@ public class MovieSimple implements GLEventListener { if(null == mPlayer) { return; } winWidth = width; winHeight = height; - + if(null != st) { reshapePMV(width, height); st.useProgram(gl, true); st.uniform(gl, pmvMatrixUniform); st.useProgram(gl, false); } - + System.out.println("pR "+mPlayer); } - + private void reshapePMV(int width, int height) { pmvMatrix.glMatrixMode(GLMatrixFunc.GL_PROJECTION); pmvMatrix.glLoadIdentity(); if(orthoProjection) { - final float fw = (float) width / 2f; - final float fh = (float) height/ 2f; + final float fw = width / 2f; + final float fh = height/ 2f; pmvMatrix.glOrthof(-fw, fw, -fh, fh, -1.0f, 1.0f); nearPlaneNormalized = 0f; } else { @@ -577,26 +586,26 @@ public class MovieSimple implements GLEventListener { pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); pmvMatrix.glLoadIdentity(); - pmvMatrix.glTranslatef(0, 0, zoom0); + pmvMatrix.glTranslatef(0, 0, zoom0); } @Override public void dispose(GLAutoDrawable drawable) { disposeImpl(drawable, true); } - + private void disposeImpl(GLAutoDrawable drawable, boolean disposePlayer) { if(null == mPlayer) { return; } - + final Object upstreamWidget = drawable.getUpstreamWidget(); - if (upstreamWidget instanceof Window) { + if (upstreamWidget instanceof Window) { final Window window = (Window) upstreamWidget; window.removeMouseListener(mouseAction); window.removeKeyListener(keyAction); } - - System.out.println("pD.1 "+mPlayer+", disposePlayer "+disposePlayer); - GL2ES2 gl = drawable.getGL().getGL2ES2(); + + System.out.println("pD.1 "+mPlayer+", disposePlayer "+disposePlayer); + GL2ES2 gl = drawable.getGL().getGL2ES2(); if( disposePlayer ) { if(!mPlayerShared) { mPlayer.destroy(gl); @@ -616,11 +625,11 @@ public class MovieSimple implements GLEventListener { } long lastPerfPos = 0; - + @Override public void display(GLAutoDrawable drawable) { if(null == mPlayer) { return; } - + if( resetGLState ) { resetGLState = false; System.err.println("XXX resetGLState"); @@ -628,35 +637,35 @@ public class MovieSimple implements GLEventListener { init(drawable); reshape(drawable, 0, 0, drawable.getWidth(), drawable.getHeight()); } - + final long currentPos = System.currentTimeMillis(); if( currentPos - lastPerfPos > 2000 ) { System.err.println( mPlayer.getPerfString() ); - lastPerfPos = currentPos; - } - - GL2ES2 gl = drawable.getGL().getGL2ES2(); + lastPerfPos = currentPos; + } + + GL2ES2 gl = drawable.getGL().getGL2ES2(); gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); if(null == st) { return; } - + st.useProgram(gl, true); pmvMatrix.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); pmvMatrix.glLoadIdentity(); pmvMatrix.glTranslatef(0, 0, zoom); if(rotate > 0) { - final float ang = ((float) (System.currentTimeMillis() - startTime) * 360.0f) / 8000.0f; + final float ang = ((System.currentTimeMillis() - startTime) * 360.0f) / 8000.0f; pmvMatrix.glRotatef(ang, 0, 0, 1); } else { rotate = 0; } st.uniform(gl, pmvMatrixUniform); interleavedVBO.enableBuffer(gl, true); - Texture tex = null; + Texture tex = null; if(null!=mPlayer) { final TextureSequence.TextureFrame texFrame; if(mPlayerShared) { @@ -686,7 +695,7 @@ public class MovieSimple implements GLEventListener { int textureCount = 3; // default - threaded boolean ortho = true; boolean zoom = false; - + boolean forceES2 = false; boolean forceES3 = false; boolean forceGL3 = false; @@ -694,10 +703,10 @@ public class MovieSimple implements GLEventListener { int vid = GLMediaPlayer.STREAM_ID_AUTO; int aid = GLMediaPlayer.STREAM_ID_AUTO; final boolean origSize; - + String url_s=null; { - boolean _origSize = false; + boolean _origSize = false; for(int i=0; i<args.length; i++) { if(args[i].equals("-vid")) { i++; @@ -754,12 +763,12 @@ public class MovieSimple implements GLEventListener { System.err.println("forceGL3 "+forceGL3); System.err.println("forceGLDef "+forceGLDef); System.err.println("swapInterval "+swapInterval); - + final MovieSimple ms = new MovieSimple(null); ms.setSwapInterval(swapInterval); ms.setScaleOrig(!zoom); ms.setOrthoProjection(ortho); - + try { final GLProfile glp; if(forceGLDef) { @@ -772,15 +781,15 @@ public class MovieSimple implements GLEventListener { glp = GLProfile.get(GLProfile.GLES2); } else { glp = GLProfile.getGL2ES2(); - } + } System.err.println("GLProfile: "+glp); GLCapabilities caps = new GLCapabilities(glp); - final GLWindow window = GLWindow.create(caps); + final GLWindow window = GLWindow.create(caps); final Animator anim = new Animator(window); window.addWindowListener(new WindowAdapter() { public void windowDestroyed(WindowEvent e) { anim.stop(); - } + } }); window.setSize(width, height); window.setVisible(true); @@ -791,13 +800,13 @@ public class MovieSimple implements GLEventListener { new Thread() { public void run() { window.destroy(); - } }.start(); + } }.start(); } - + @Override public void newFrameAvailable(GLMediaPlayer ts, TextureFrame newFrame, long when) { } - + @Override public void attributesChanged(final GLMediaPlayer mp, int event_mask, long when) { System.err.println("MovieSimple AttributesChanges: events_mask 0x"+Integer.toHexString(event_mask)+", when "+when); @@ -829,7 +838,7 @@ public class MovieSimple implements GLEventListener { if( 0 != ( ( GLMediaEventListener.EVENT_CHANGE_ERR | GLMediaEventListener.EVENT_CHANGE_EOS ) & event_mask ) ) { final StreamException se = ms.mPlayer.getStreamException(); if( null != se ) { - se.printStackTrace(); + se.printStackTrace(); } destroyWindow(); } |