diff options
Diffstat (limited to 'src/jogl/classes')
46 files changed, 1360 insertions, 784 deletions
diff --git a/src/jogl/classes/com/jogamp/opengl/FBObject.java b/src/jogl/classes/com/jogamp/opengl/FBObject.java index 40b45ead2..17589aa0e 100644 --- a/src/jogl/classes/com/jogamp/opengl/FBObject.java +++ b/src/jogl/classes/com/jogamp/opengl/FBObject.java @@ -31,6 +31,7 @@ package com.jogamp.opengl; import java.util.Arrays; import javax.media.opengl.GL; +import javax.media.opengl.GL2ES2; import javax.media.opengl.GL2GL3; import javax.media.opengl.GL3; import javax.media.opengl.GLBase; @@ -812,7 +813,7 @@ public class FBObject { maxColorAttachments = 1; if( fullFBOSupport || NV_fbo_color_attachments ) { try { - gl.glGetIntegerv(GL2GL3.GL_MAX_COLOR_ATTACHMENTS, val, 0); + gl.glGetIntegerv(GL2ES2.GL_MAX_COLOR_ATTACHMENTS, val, 0); realMaxColorAttachments = 1 <= val[0] ? val[0] : 1; // cap minimum to 1 } catch (GLException gle) { gle.printStackTrace(); } } @@ -2283,7 +2284,8 @@ public class FBObject { /** Returns the framebuffer name to render to. */ public final int getWriteFramebuffer() { return fbName; } /** Returns the framebuffer name to read from. Depending on multisampling, this may be a different framebuffer. */ - public final int getReadFramebuffer() { return ( samples > 0 ) ? samplingSink.getReadFramebuffer() : fbName; } + public final int getReadFramebuffer() { return ( samples > 0 ) ? samplingSink.getReadFramebuffer() : fbName; } + public final int getDefaultReadBuffer() { return GL.GL_COLOR_ATTACHMENT0; } /** Return the number of color/texture attachments */ public final int getColorAttachmentCount() { return colorAttachmentCount; } /** Return the stencil {@link RenderAttachment} attachment, if exist. Maybe share the same {@link Attachment#getName()} as {@link #getDepthAttachment()}, if packed depth-stencil is being used. */ diff --git a/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java b/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java index 0320c63ae..4ba4def9a 100644 --- a/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java +++ b/src/jogl/classes/com/jogamp/opengl/swt/GLCanvas.java @@ -207,7 +207,7 @@ public class GLCanvas extends Canvas implements GLAutoDrawable { // so we can continue with the destruction. try { if( !GLCanvas.this.isDisposed() ) { - helper.disposeGL(GLCanvas.this, context); + helper.disposeGL(GLCanvas.this, context, true); } else { context.destroy(); } diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataClient.java b/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataClient.java index 88cb3303f..e0bbbc33c 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataClient.java +++ b/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataClient.java @@ -1,3 +1,30 @@ +/** + * Copyright 2010 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; @@ -120,6 +147,17 @@ public class GLArrayDataClient extends GLArrayDataWrapper implements GLArrayData return adc; } + @Override + public void associate(Object obj, boolean enable) { + if(obj instanceof ShaderState) { + if(enable) { + shaderState = (ShaderState)obj; + } else { + shaderState = null; + } + } + } + // // Data read access // @@ -157,7 +195,7 @@ public class GLArrayDataClient extends GLArrayDataWrapper implements GLArrayData seal(seal); enableBuffer(gl, seal); } - + @Override public void enableBuffer(GL gl, boolean enable) { if( enableBufferAlways || bufferEnabled != enable ) { @@ -166,16 +204,7 @@ public class GLArrayDataClient extends GLArrayDataWrapper implements GLArrayData // init/generate VBO name if not done yet init_vbo(gl); } - final Object ext; - if(usesGLSL) { - ext = ShaderState.getShaderState(gl); - if(null == ext) { - throw new GLException("A ShaderState must be bound to the GL context, use 'ShaderState.setShaderState(gl)'"); - } - } else { - ext = null; - } - glArrayHandler.enableState(gl, enable, ext); + glArrayHandler.enableState(gl, enable, usesGLSL ? shaderState : null); bufferEnabled = enable; } } @@ -297,6 +326,8 @@ public class GLArrayDataClient extends GLArrayDataWrapper implements GLArrayData ", index "+index+ ", location "+location+ ", isVertexAttribute "+isVertexAttribute+ + ", usesGLSL "+usesGLSL+ + ", usesShaderState "+(null!=shaderState)+ ", dataType 0x"+Integer.toHexString(componentType)+ ", bufferClazz "+componentClazz+ ", elements "+getElementCount()+ @@ -421,5 +452,7 @@ public class GLArrayDataClient extends GLArrayDataWrapper implements GLArrayData protected GLArrayHandler glArrayHandler; protected boolean usesGLSL; + protected ShaderState shaderState; + } diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataServer.java b/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataServer.java index c9dd98751..7e7d27b36 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataServer.java +++ b/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataServer.java @@ -1,3 +1,30 @@ +/** + * Copyright 2010 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; @@ -332,6 +359,8 @@ public class GLArrayDataServer extends GLArrayDataClient implements GLArrayDataE ", index "+index+ ", location "+location+ ", isVertexAttribute "+isVertexAttribute+ + ", usesGLSL "+usesGLSL+ + ", usesShaderState "+(null!=shaderState)+ ", dataType 0x"+Integer.toHexString(componentType)+ ", bufferClazz "+componentClazz+ ", elements "+getElementCount()+ diff --git a/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataWrapper.java b/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataWrapper.java index f4a197be1..7d08ad08f 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataWrapper.java +++ b/src/jogl/classes/com/jogamp/opengl/util/GLArrayDataWrapper.java @@ -1,3 +1,30 @@ +/** + * Copyright 2010 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; @@ -97,53 +124,91 @@ public class GLArrayDataWrapper implements GLArrayData { return glp.isValidArrayDataType(getIndex(), getComponentCount(), getComponentType(), isVertexAttribute(), throwException); } + @Override + public void associate(Object obj, boolean enable) { + // nop + } + // // Data read access // + @Override public final boolean isVertexAttribute() { return isVertexAttribute; } + @Override public final int getIndex() { return index; } + @Override public final int getLocation() { return location; } - public final void setLocation(int v) { location = v; } + @Override + public final int setLocation(int v) { location = v; return location; } + @Override + public final int setLocation(GL2ES2 gl, int program) { + location = gl.glGetAttribLocation(program, name); + return location; + } + + @Override + public final int setLocation(GL2ES2 gl, int program, int location) { + this.location = location; + gl.glBindAttribLocation(program, location, name); + return location; + } + + @Override public final String getName() { return name; } + @Override public final long getVBOOffset() { return vboEnabled?vboOffset:0; } + @Override public final int getVBOName() { return vboEnabled?vboName:0; } + @Override public final boolean isVBO() { return vboEnabled; } + @Override public final int getVBOUsage() { return vboEnabled?vboUsage:0; } + @Override public final int getVBOTarget() { return vboEnabled?vboTarget:0; } + @Override public final Buffer getBuffer() { return buffer; } + @Override public final int getComponentCount() { return components; } + @Override public final int getComponentType() { return componentType; } + @Override public final int getComponentSizeInBytes() { return componentByteSize; } + @Override public final int getElementCount() { if(null==buffer) return 0; return ( buffer.position()==0 ) ? ( buffer.limit() / components ) : ( buffer.position() / components ) ; } + + @Override public final int getSizeInBytes() { if(null==buffer) return 0; return ( buffer.position()==0 ) ? ( buffer.limit() * componentByteSize ) : ( buffer.position() * componentByteSize ) ; } + @Override public final boolean getNormalized() { return normalized; } + @Override public final int getStride() { return strideB; } - public final Class getBufferClass() { return componentClazz; } + public final Class<?> getBufferClass() { return componentClazz; } + @Override public void destroy(GL gl) { buffer = null; vboName=0; @@ -152,6 +217,7 @@ public class GLArrayDataWrapper implements GLArrayData { alive = false; } + @Override public String toString() { return "GLArrayDataWrapper["+name+ ", index "+index+ @@ -172,7 +238,7 @@ public class GLArrayDataWrapper implements GLArrayData { "]"; } - public static final Class getBufferClass(int dataType) { + public static final Class<?> getBufferClass(int dataType) { switch(dataType) { case GL.GL_BYTE: case GL.GL_UNSIGNED_BYTE: @@ -189,6 +255,7 @@ public class GLArrayDataWrapper implements GLArrayData { } } + @Override public void setName(String newName) { location = -1; name = newName; @@ -310,14 +377,13 @@ public class GLArrayDataWrapper implements GLArrayData { protected String name; protected int components; protected int componentType; - protected Class componentClazz; + protected Class<?> componentClazz; protected int componentByteSize; protected boolean normalized; protected int strideB; // stride in bytes protected int strideL; // stride in logical components protected Buffer buffer; protected boolean isVertexAttribute; - protected long vboOffset; protected int vboName; protected boolean vboEnabled; diff --git a/src/jogl/classes/com/jogamp/opengl/util/ImmModeSink.java b/src/jogl/classes/com/jogamp/opengl/util/ImmModeSink.java index f01896b96..27ce7d8ec 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/ImmModeSink.java +++ b/src/jogl/classes/com/jogamp/opengl/util/ImmModeSink.java @@ -35,7 +35,7 @@ import com.jogamp.opengl.util.glsl.ShaderState; * via {@link #glEnd(GL, boolean) glEnd(gl, false)} for deferred rendering via {@link #draw(GL, boolean)}. * </p> * <a name="storageDetails"><h5>Buffer storage and it's creation via {@link #createFixed(int, int, int, int, int, int, int, int, int, int) createFixed(..)} - * and {@link #createGLSL(int, int, int, int, int, int, int, int, int, int) createGLSL(..)}</h5></a> + * and {@link #createGLSL(int, int, int, int, int, int, int, int, int, int, ShaderState) createGLSL(..)}</h5></a> * <p> * If unsure whether <i>colors</i>, <i>normals</i> and <i>textures</i> will be used, * simply add them with an expected component count. @@ -82,13 +82,11 @@ public class ImmModeSink { int glBufferUsage) { return new ImmModeSink(initialElementCount, vComps, vDataType, cComps, cDataType, nComps, nDataType, tComps, tDataType, - false, glBufferUsage); + false, glBufferUsage, null, 0); } /** - * Uses a GL2ES2 GLSL shader immediate mode sink. - * To issue the draw() command, - * a ShaderState must be current, using ShaderState.glUseProgram(). + * Uses a GL2ES2 GLSL shader immediate mode sink, utilizing the given ShaderState. * <p> * See <a href="#storageDetails"> buffer storage details</a>. * </p> @@ -104,7 +102,7 @@ public class ImmModeSink { * @param tDataType optional texture-coordinate data type, e.g. {@link GL#GL_FLOAT} * @param glBufferUsage VBO <code>usage</code> parameter for {@link GL#glBufferData(int, long, Buffer, int)}, e.g. {@link GL#GL_STATIC_DRAW}, * set to <code>0</code> for no VBO usage - * + * @param st ShaderState to locate the vertex attributes * @see #draw(GL, boolean) * @see com.jogamp.opengl.util.glsl.ShaderState#useProgram(GL2ES2, boolean) * @see com.jogamp.opengl.util.glsl.ShaderState#getCurrentShaderState() @@ -114,12 +112,45 @@ public class ImmModeSink { int cComps, int cDataType, int nComps, int nDataType, int tComps, int tDataType, - int glBufferUsage) { + int glBufferUsage, ShaderState st) { return new ImmModeSink(initialElementCount, vComps, vDataType, cComps, cDataType, nComps, nDataType, tComps, tDataType, - true, glBufferUsage); + true, glBufferUsage, st, 0); } + /** + * Uses a GL2ES2 GLSL shader immediate mode sink, utilizing the given shader-program. + * <p> + * See <a href="#storageDetails"> buffer storage details</a>. + * </p> + * + * @param initialElementCount initial buffer size, if subsequent mutable operations are about to exceed the buffer size, the buffer will grow about the initial size. + * @param vComps mandatory vertex component count, should be 2, 3 or 4. + * @param vDataType mandatory vertex data type, e.g. {@link GL#GL_FLOAT} + * @param cComps optional color component count, may be 0, 3 or 4 + * @param cDataType optional color data type, e.g. {@link GL#GL_FLOAT} + * @param nComps optional normal component count, may be 0, 3 or 4 + * @param nDataType optional normal data type, e.g. {@link GL#GL_FLOAT} + * @param tComps optional texture-coordinate component count, may be 0, 2 or 3 + * @param tDataType optional texture-coordinate data type, e.g. {@link GL#GL_FLOAT} + * @param glBufferUsage VBO <code>usage</code> parameter for {@link GL#glBufferData(int, long, Buffer, int)}, e.g. {@link GL#GL_STATIC_DRAW}, + * set to <code>0</code> for no VBO usage + * @param shaderProgram shader-program name to locate the vertex attributes + * @see #draw(GL, boolean) + * @see com.jogamp.opengl.util.glsl.ShaderState#useProgram(GL2ES2, boolean) + * @see com.jogamp.opengl.util.glsl.ShaderState#getCurrentShaderState() + */ + public static ImmModeSink createGLSL(int initialElementCount, + int vComps, int vDataType, + int cComps, int cDataType, + int nComps, int nDataType, + int tComps, int tDataType, + int glBufferUsage, int shaderProgram) { + return new ImmModeSink(initialElementCount, + vComps, vDataType, cComps, cDataType, nComps, nDataType, tComps, tDataType, + true, glBufferUsage, null, shaderProgram); + } + public void destroy(GL gl) { destroyList(gl); @@ -330,10 +361,10 @@ public class ImmModeSink { int cComps, int cDataType, int nComps, int nDataType, int tComps, int tDataType, - boolean useGLSL, int glBufferUsage) { - vboSet = new VBOSet(initialElementCount, - vComps, vDataType, cComps, cDataType, nComps, nDataType, tComps, tDataType, - useGLSL, glBufferUsage); + boolean useGLSL, int glBufferUsage, ShaderState st, int shaderProgram) { + vboSet = new VBOSet(initialElementCount, + vComps, vDataType, cComps, cDataType, nComps, nDataType, tComps, tDataType, + useGLSL, glBufferUsage, st, shaderProgram); this.vboSetList = new ArrayList<VBOSet>(); } @@ -349,7 +380,7 @@ public class ImmModeSink { * Sets the additional element count if buffer resize is required, * defaults to <code>initialElementCount</code> of factory method. * @see #createFixed(int, int, int, int, int, int, int, int, int, int) - * @see #createGLSL(int, int, int, int, int, int, int, int, int, int) + * @see #createGLSL(int, int, int, int, int, int, int, int, int, int, ShaderState) */ public void setResizeElementCount(int v) { vboSet.setResizeElementCount(v); } @@ -369,9 +400,19 @@ public class ImmModeSink { int cComps, int cDataType, int nComps, int nDataType, int tComps, int tDataType, - boolean useGLSL, int glBufferUsage) { + boolean useGLSL, int glBufferUsage, ShaderState st, int shaderProgram) { + // final .. this.glBufferUsage=glBufferUsage; this.initialElementCount=initialElementCount; + this.useVBO = 0 != glBufferUsage; + this.useGLSL=useGLSL; + this.shaderState = st; + this.shaderProgram = shaderProgram; + + if(useGLSL && null == shaderState && 0 == shaderProgram) { + throw new IllegalArgumentException("Using GLSL but neither a valid shader-program nor ShaderState has been passed!"); + } + // variable .. this.resizeElementCount=initialElementCount; this.vDataType=vDataType; this.vDataTypeSigned=GLBuffers.isSignedGLType(vDataType); @@ -389,8 +430,6 @@ public class ImmModeSink { this.tDataTypeSigned=GLBuffers.isSignedGLType(tDataType); this.tComps=tComps; this.tCompsBytes=tComps * GLBuffers.sizeOfGLType(tDataType); - this.useGLSL=useGLSL; - this.useVBO = 0 != glBufferUsage; this.vboName = 0; this.vCount=0; @@ -414,6 +453,7 @@ public class ImmModeSink { this.bufferEnabled=false; this.bufferWritten=false; this.bufferWrittenOnce=false; + this.glslLocationSet = false; } protected int getResizeElementCount() { return resizeElementCount; } @@ -423,7 +463,8 @@ public class ImmModeSink { protected final VBOSet regenerate(GL gl) { return new VBOSet(initialElementCount, vComps, - vDataType, cComps, cDataType, nComps, nDataType, tComps, tDataType, useGLSL, glBufferUsage); + vDataType, cComps, cDataType, nComps, nDataType, tComps, tDataType, + useGLSL, glBufferUsage, shaderState, shaderProgram); } protected void checkSeal(boolean test) throws GLException { @@ -439,10 +480,27 @@ public class ImmModeSink { } } + private boolean usingShaderProgram = false; + + protected void useShaderProgram(GL2ES2 gl, boolean force) { + if( force || !usingShaderProgram ) { + if(null != shaderState) { + shaderState.useProgram(gl, true); + } else /* if( 0 != shaderProgram) */ { + gl.glUseProgram(shaderProgram); + } + usingShaderProgram = true; + } + } + protected void draw(GL gl, Buffer indices, boolean disableBufferAfterDraw, int i) { enableBuffer(gl, true); - + + if(null != shaderState || 0 != shaderProgram) { + useShaderProgram(gl.getGL2ES2(), false); + } + if(DEBUG_DRAW) { System.err.println("ImmModeSink.draw["+i+"].0 (disableBufferAfterDraw: "+disableBufferAfterDraw+"):\n\t"+this); } @@ -788,6 +846,51 @@ public class ImmModeSink { } } + public void setShaderProgram(int program) { + if(null == shaderState && 0 == program) { + throw new IllegalArgumentException("Not allowed to zero shader program if no ShaderState is set"); + } + shaderProgram = program; + glslLocationSet = false; // enforce location reset! + } + + /** + * @param gl + * @return true if all locations for all used arrays are found (min 1 array), otherwise false. + * Also sets 'glslLocationSet' to the return value! + */ + private boolean resetGLSLArrayLocation(GL2ES2 gl) { + int iA = 0; + int iL = 0; + + if(null != vArrayData) { + iA++; + if( vArrayData.setLocation(gl, shaderProgram) >= 0 ) { + iL++; + } + } + if(null != cArrayData) { + iA++; + if( cArrayData.setLocation(gl, shaderProgram) >= 0 ) { + iL++; + } + } + if(null != nArrayData) { + iA++; + if( nArrayData.setLocation(gl, shaderProgram) >= 0 ) { + iL++; + } + } + if(null != tArrayData) { + iA++; + if( tArrayData.setLocation(gl, shaderProgram) >= 0 ) { + iL++; + } + } + glslLocationSet = iA == iL; + return glslLocationSet; + } + public void destroy(GL gl) { reset(gl); @@ -868,8 +971,13 @@ public class ImmModeSink { checkSeal(true); } bufferEnabled = enable; - if(useGLSL) { - enableBufferGLSL(gl, enable); + if(useGLSL) { + useShaderProgram(gl.getGL2ES2(), true); + if(null != shaderState) { + enableBufferGLSLShaderState(gl, enable); + } else { + enableBufferGLSLSimple(gl, enable); + } } else { enableBufferFixed(gl, enable); } @@ -901,7 +1009,7 @@ public class ImmModeSink { } } - public void enableBufferFixed(GL gl, boolean enable) { + private void enableBufferFixed(GL gl, boolean enable) { GL2ES1 glf = gl.getGL2ES1(); final boolean useV = vComps>0 && vElems>0 ; @@ -969,11 +1077,75 @@ public class ImmModeSink { } } - public void enableBufferGLSL(GL gl, boolean enable) { - ShaderState st = ShaderState.getShaderState(gl); - if(null==st) { - throw new GLException("No ShaderState in "+gl); - } + private void enableBufferGLSLShaderState(GL gl, boolean enable) { + GL2ES2 glsl = gl.getGL2ES2(); + + final boolean useV = vComps>0 && vElems>0 ; + final boolean useC = cComps>0 && cElems>0 ; + final boolean useN = nComps>0 && nElems>0 ; + final boolean useT = tComps>0 && tElems>0 ; + + if(DEBUG_DRAW) { + System.err.println("ImmModeSink.enableGLSL.A.0 "+enable+": use [ v "+useV+", c "+useC+", n "+useN+", t "+useT+"], "+getElemUseCountStr()+", "+buffer); + } + + if(enable) { + if(useVBO) { + if(0 == vboName) { + throw new InternalError("Using VBO but no vboName"); + } + glsl.glBindBuffer(GL.GL_ARRAY_BUFFER, vboName); + if(!bufferWritten) { + writeBuffer(gl); + } + } + bufferWritten=true; + } + + if(useV) { + if(enable) { + shaderState.enableVertexAttribArray(glsl, vArrayData); + shaderState.vertexAttribPointer(glsl, vArrayData); + } else { + shaderState.disableVertexAttribArray(glsl, vArrayData); + } + } + if(useC) { + if(enable) { + shaderState.enableVertexAttribArray(glsl, cArrayData); + shaderState.vertexAttribPointer(glsl, cArrayData); + } else { + shaderState.disableVertexAttribArray(glsl, cArrayData); + } + } + if(useN) { + if(enable) { + shaderState.enableVertexAttribArray(glsl, nArrayData); + shaderState.vertexAttribPointer(glsl, nArrayData); + } else { + shaderState.disableVertexAttribArray(glsl, nArrayData); + } + } + if(useT) { + if(enable) { + shaderState.enableVertexAttribArray(glsl, tArrayData); + shaderState.vertexAttribPointer(glsl, tArrayData); + } else { + shaderState.disableVertexAttribArray(glsl, tArrayData); + } + } + glslLocationSet = true; // ShaderState does set the location implicit + + if(enable && useVBO) { + glsl.glBindBuffer(GL.GL_ARRAY_BUFFER, 0); + } + + if(DEBUG_DRAW) { + System.err.println("ImmModeSink.enableGLSL.A.X "); + } + } + + private void enableBufferGLSLSimple(GL gl, boolean enable) { GL2ES2 glsl = gl.getGL2ES2(); final boolean useV = vComps>0 && vElems>0 ; @@ -982,7 +1154,20 @@ public class ImmModeSink { final boolean useT = tComps>0 && tElems>0 ; if(DEBUG_DRAW) { - System.err.println("ImmModeSink.enableGLSL.0 "+enable+": use [ v "+useV+", c "+useC+", n "+useN+", t "+useT+"], "+getElemUseCountStr()+", "+buffer); + System.err.println("ImmModeSink.enableGLSL.B.0 "+enable+": use [ v "+useV+", c "+useC+", n "+useN+", t "+useT+"], "+getElemUseCountStr()+", "+buffer); + } + + if(!glslLocationSet) { + if( !resetGLSLArrayLocation(glsl) ) { + if(DEBUG_DRAW) { + final int vLoc = null != vArrayData ? vArrayData.getLocation() : -1; + final int cLoc = null != cArrayData ? cArrayData.getLocation() : -1; + final int nLoc = null != nArrayData ? nArrayData.getLocation() : -1; + final int tLoc = null != tArrayData ? tArrayData.getLocation() : -1; + System.err.println("ImmModeSink.enableGLSL.B.X attribute locations in shader program "+shaderProgram+", incomplete ["+vLoc+", "+cLoc+", "+nLoc+", "+tLoc+"] - glslLocationSet "+glslLocationSet); + } + return; + } } if(enable) { @@ -1000,34 +1185,34 @@ public class ImmModeSink { if(useV) { if(enable) { - st.enableVertexAttribArray(glsl, vArrayData); - st.vertexAttribPointer(glsl, vArrayData); + glsl.glEnableVertexAttribArray(vArrayData.getLocation()); + glsl.glVertexAttribPointer(vArrayData); } else { - st.disableVertexAttribArray(glsl, vArrayData); + glsl.glDisableVertexAttribArray(vArrayData.getLocation()); } } if(useC) { if(enable) { - st.enableVertexAttribArray(glsl, cArrayData); - st.vertexAttribPointer(glsl, cArrayData); + glsl.glEnableVertexAttribArray(cArrayData.getLocation()); + glsl.glVertexAttribPointer(cArrayData); } else { - st.disableVertexAttribArray(glsl, cArrayData); + glsl.glDisableVertexAttribArray(cArrayData.getLocation()); } } if(useN) { if(enable) { - st.enableVertexAttribArray(glsl, nArrayData); - st.vertexAttribPointer(glsl, nArrayData); + glsl.glEnableVertexAttribArray(nArrayData.getLocation()); + glsl.glVertexAttribPointer(nArrayData); } else { - st.disableVertexAttribArray(glsl, nArrayData); + glsl.glDisableVertexAttribArray(nArrayData.getLocation()); } } if(useT) { if(enable) { - st.enableVertexAttribArray(glsl, tArrayData); - st.vertexAttribPointer(glsl, tArrayData); + glsl.glEnableVertexAttribArray(tArrayData.getLocation()); + glsl.glVertexAttribPointer(tArrayData); } else { - st.disableVertexAttribArray(glsl, tArrayData); + glsl.glDisableVertexAttribArray(tArrayData.getLocation()); } } @@ -1036,11 +1221,16 @@ public class ImmModeSink { } if(DEBUG_DRAW) { - System.err.println("ImmModeSink.enableGLSL.X "); + System.err.println("ImmModeSink.enableGLSL.B.X "); } } - + public String toString() { + final String glslS = useGLSL ? + ", useShaderState "+(null!=shaderState)+ + ", shaderProgram "+shaderProgram+ + ", glslLocationSet "+glslLocationSet : ""; + return "VBOSet[mode "+mode+ ", modeOrig "+modeOrig+ ", use/count "+getElemUseCountStr()+ @@ -1049,6 +1239,8 @@ public class ImmModeSink { ", bufferEnabled "+bufferEnabled+ ", bufferWritten "+bufferWritten+" (once "+bufferWrittenOnce+")"+ ", useVBO "+useVBO+", vboName "+vboName+ + ", useGLSL "+useGLSL+ + glslS+ ",\n\t"+vArrayData+ ",\n\t"+cArrayData+ ",\n\t"+nArrayData+ @@ -1264,7 +1456,9 @@ public class ImmModeSink { } final private int glBufferUsage, initialElementCount; - final private boolean useVBO; + final private boolean useVBO, useGLSL; + final private ShaderState shaderState; + private int shaderProgram; private int mode, modeOrig, resizeElementCount; private ByteBuffer buffer; @@ -1286,8 +1480,9 @@ public class ImmModeSink { private Buffer vertexArray, colorArray, normalArray, textCoordArray; private GLArrayDataWrapper vArrayData, cArrayData, nArrayData, tArrayData; - private boolean sealed, sealedGL, useGLSL; + private boolean sealed, sealedGL; private boolean bufferEnabled, bufferWritten, bufferWrittenOnce; + private boolean glslLocationSet; } } diff --git a/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderState.java b/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderState.java index ff8982ddf..9d71ee276 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderState.java +++ b/src/jogl/classes/com/jogamp/opengl/util/glsl/ShaderState.java @@ -35,7 +35,6 @@ import java.util.Iterator; import javax.media.opengl.GL; import javax.media.opengl.GL2ES2; import javax.media.opengl.GLArrayData; -import javax.media.opengl.GLContext; import javax.media.opengl.GLException; import javax.media.opengl.GLUniformData; @@ -58,7 +57,6 @@ import com.jogamp.opengl.util.GLArrayDataEditable; */ public class ShaderState { public static final boolean DEBUG = Debug.isPropertyDefined("jogl.debug.GLSLState", true); - private static final String currentStateKey = "jogamp.opengl.glsl.ShaderState" ; public ShaderState() { } @@ -68,46 +66,6 @@ public class ShaderState { public void setVerbose(boolean v) { verbose = DEBUG || v; } /** - * Fetches the current shader state from this thread (TLS) current GLContext - * - * @see com.jogamp.opengl.util.glsl.ShaderState#useProgram(GL2ES2, boolean) - * @see com.jogamp.opengl.util.glsl.ShaderState#getShaderState(GL) - * @see com.jogamp.opengl.util.glsl.ShaderState#setShaderState(GL) - * @see com.jogamp.opengl.util.glsl.ShaderState#getCurrentShaderState() - */ - public static ShaderState getCurrentShaderState() { - return getShaderState(GLContext.getCurrentGL()); - } - - /** - * Gets the shader state attached to the GL object's GLContext - * - * @param gl the GL object referencing the GLContext - * - * @see com.jogamp.opengl.util.glsl.ShaderState#useProgram(GL2ES2, boolean) - * @see com.jogamp.opengl.util.glsl.ShaderState#getShaderState(GL) - * @see com.jogamp.opengl.util.glsl.ShaderState#setShaderState(GL) - * @see com.jogamp.opengl.util.glsl.ShaderState#getCurrentShaderState() - */ - public static ShaderState getShaderState(GL gl) { - return (ShaderState) gl.getContext().getAttachedObject(currentStateKey); - } - - /** - * Attaches the shader state to the GL object's GLContext - * - * @param gl the GL object referencing the GLContext - * - * @see com.jogamp.opengl.util.glsl.ShaderState#useProgram(GL2ES2, boolean) - * @see com.jogamp.opengl.util.glsl.ShaderState#getShaderState(GL) - * @see com.jogamp.opengl.util.glsl.ShaderState#setShaderState(GL) - * @see com.jogamp.opengl.util.glsl.ShaderState#getCurrentShaderState() - */ - public final ShaderState setShaderState(GL gl) { - return (ShaderState) gl.getContext().attachObject(currentStateKey, this); - } - - /** * Returns the attached user object for the given name to this ShaderState. */ public final Object getAttachedObject(String name) { @@ -135,19 +93,14 @@ public class ShaderState { /** * Turns the shader program on or off.<br> - * Puts this ShaderState to to the thread local storage (TLS), - * if <code>on</code> is <code>true</code>. * * @throws GLException if no program is attached * * @see com.jogamp.opengl.util.glsl.ShaderState#useProgram(GL2ES2, boolean) - * @see com.jogamp.opengl.util.glsl.ShaderState#getShaderState(GL) - * @see com.jogamp.opengl.util.glsl.ShaderState#getCurrentShaderState() */ public synchronized void useProgram(GL2ES2 gl, boolean on) throws GLException { if(null==shaderProgram) { throw new GLException("No program is attached"); } if(on) { - setShaderState(gl); if(shaderProgram.linked()) { shaderProgram.useProgram(gl, true); if(resetAllShaderData) { @@ -332,6 +285,10 @@ public class ShaderState { return activeAttribDataMap.get(name); } + public boolean isActiveAttribute(GLArrayData attribute) { + return attribute == activeAttribDataMap.get(attribute.getName()); + } + /** * Binds or unbinds the {@link GLArrayData} lifecycle to this ShaderState. * @@ -343,11 +300,14 @@ public class ShaderState { * * <p>The data will not be transfered to the GPU, use {@link #vertexAttribPointer(GL2ES2, GLArrayData)} additionally.</p> * + * <p>The data will also be {@link GLArrayData#associate(Object, boolean) associated} with this ShaderState.</p> + * * @param attribute the {@link GLArrayData} which lifecycle shall be managed * @param own true if <i>owning</i> shall be performs, false if <i>disowning</i>. * * @see #bindAttribLocation(GL2ES2, int, String) * @see #getAttribute(String) + * @see GLArrayData#associate(Object, boolean) */ public void ownAttribute(GLArrayData attribute, boolean own) { if(own) { @@ -359,6 +319,7 @@ public class ShaderState { } else { managedAttributes.remove(attribute); } + attribute.associate(this, own); } public boolean ownsAttribute(GLArrayData attribute) { @@ -402,8 +363,12 @@ public class ShaderState { * @see #getAttribute(String) */ public void bindAttribLocation(GL2ES2 gl, int location, GLArrayData data) { - bindAttribLocation(gl, location, data.getName()); - data.setLocation(location); + if(null==shaderProgram) throw new GLException("No program is attached"); + if(shaderProgram.linked()) throw new GLException("Program is already linked"); + final String name = data.getName(); + final Integer loc = new Integer(location); + activeAttribLocationMap.put(name, loc); + data.setLocation(gl, shaderProgram.program(), location); activeAttribDataMap.put(data.getName(), data); } @@ -465,8 +430,27 @@ public class ShaderState { * @see #getAttribute(String) */ public int getAttribLocation(GL2ES2 gl, GLArrayData data) { - int location = getAttribLocation(gl, data.getName()); - data.setLocation(location); + if(null==shaderProgram) throw new GLException("No program is attached"); + final String name = data.getName(); + int location = getCachedAttribLocation(name); + if(0<=location) { + data.setLocation(location); + } else { + if(!shaderProgram.linked()) throw new GLException("Program is not linked"); + location = data.setLocation(gl, shaderProgram.program()); + if(0<=location) { + Integer idx = new Integer(location); + activeAttribLocationMap.put(name, idx); + if(DEBUG) { + System.err.println("ShaderState: glGetAttribLocation: "+name+", loc: "+location); + } + } else if(verbose) { + System.err.println("ShaderState: glGetAttribLocation failed, no location for: "+name+", loc: "+location); + if(DEBUG) { + Thread.dumpStack(); + } + } + } activeAttribDataMap.put(data.getName(), data); return location; } @@ -873,6 +857,7 @@ public class ShaderState { if(!shaderProgram.inUse()) throw new GLException("Program is not in use"); int location = getCachedUniformLocation(name); if(0>location) { + if(!shaderProgram.linked()) throw new GLException("Program is not linked"); location = gl.glGetUniformLocation(shaderProgram.program(), name); if(0<=location) { Integer idx = new Integer(location); @@ -886,7 +871,7 @@ public class ShaderState { } return location; } - + /** * Validates and returns the location of a shader uniform.<br> * Uses either the cached value {@link #getCachedUniformLocation(String)} if valid, @@ -908,9 +893,25 @@ public class ShaderState { * @see ShaderProgram#glReplaceShader */ public int getUniformLocation(GL2ES2 gl, GLUniformData data) { - int location = getUniformLocation(gl, data.getName()); - data.setLocation(location); - activeUniformDataMap.put(data.getName(), data); + if(!shaderProgram.inUse()) throw new GLException("Program is not in use"); + final String name = data.getName(); + int location = getCachedUniformLocation(name); + if(0<=location) { + data.setLocation(location); + } else { + if(!shaderProgram.linked()) throw new GLException("Program is not linked"); + location = data.setLocation(gl, shaderProgram.program()); + if(0<=location) { + Integer idx = new Integer(location); + activeUniformLocationMap.put(name, idx); + } else if(verbose) { + System.err.println("ShaderState: glUniform failed, no location for: "+name+", index: "+location); + if(DEBUG) { + Thread.dumpStack(); + } + } + } + activeUniformDataMap.put(name, data); return location; } diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/PNGImage.java b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/PNGImage.java index d8d6f7daa..d9be4ce31 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/texture/spi/PNGImage.java +++ b/src/jogl/classes/com/jogamp/opengl/util/texture/spi/PNGImage.java @@ -144,7 +144,7 @@ public class PNGImage { /** Returns the dpi of the image. */ public double[] getDpi() { return dpi; } - /** Returns the OpenGL format for this texture; e.g. GL.GL_BGR or GL.GL_BGRA. */ + /** Returns the OpenGL format for this texture; e.g. GL.GL_LUMINANCE, GL.GL_RGB or GL.GL_RGBA. */ public int getGLFormat() { return glFormat; } /** Returns the OpenGL data type: GL.GL_UNSIGNED_BYTE. */ diff --git a/src/jogl/classes/javax/media/opengl/GLArrayData.java b/src/jogl/classes/javax/media/opengl/GLArrayData.java index 5d17f6874..8e1383031 100644 --- a/src/jogl/classes/javax/media/opengl/GLArrayData.java +++ b/src/jogl/classes/javax/media/opengl/GLArrayData.java @@ -30,6 +30,8 @@ package javax.media.opengl; import java.nio.Buffer; +import javax.media.opengl.fixedfunc.GLPointerFunc; + /** * * The total number of bytes hold by the referenced buffer is: @@ -38,6 +40,19 @@ import java.nio.Buffer; */ public interface GLArrayData { /** + * Implementation and type dependent object association. + * <p> + * One currently known use case is to associate a {@link com.jogamp.opengl.util.glsl.ShaderState ShaderState} + * to an GLSL aware vertex attribute object, allowing to use the ShaderState to handle it's + * data persistence, location and state change.<br/> + * This is implicitly done via {@link com.jogamp.opengl.util.glsl.ShaderState#ownAttribute(GLArrayData, boolean) shaderState.ownAttribute(GLArrayData, boolean)}. + * </p> + * @param obj implementation and type dependent association + * @param enable pass true to enable the association and false to disable it. + */ + public void associate(Object obj, boolean enable); + + /** * Returns true if this data set is intended for a GLSL vertex shader attribute, * otherwise false, ie intended for fixed function vertex pointer */ @@ -47,10 +62,10 @@ public interface GLArrayData { * The index of the predefined array index, see list below, * or -1 in case of a shader attribute array. * - * @see javax.media.opengl.GL2#GL_VERTEX_ARRAY - * @see javax.media.opengl.GL2#GL_NORMAL_ARRAY - * @see javax.media.opengl.GL2#GL_COLOR_ARRAY - * @see javax.media.opengl.GL2#GL_TEXTURE_COORD_ARRAY + * @see GLPointerFunc#GL_VERTEX_ARRAY + * @see GLPointerFunc#GL_NORMAL_ARRAY + * @see GLPointerFunc#GL_COLOR_ARRAY + * @see GLPointerFunc#GL_TEXTURE_COORD_ARRAY */ public int getIndex(); @@ -61,6 +76,11 @@ public interface GLArrayData { /** * Set a new name for this array. + * <p> + * This clears the location, i.e. sets it to -1. + * </p> + * @see #setLocation(int) + * @see #setLocation(GL2ES2, int) */ public void setName(String newName); @@ -72,14 +92,37 @@ public interface GLArrayData { public int getLocation(); /** - * Sets the determined location of the shader attribute - * This is usually done within ShaderState. + * Sets the given location of the shader attribute * + * @return the given location * @see com.jogamp.opengl.util.glsl.ShaderState#vertexAttribPointer(GL2ES2, GLArrayData) */ - public void setLocation(int v); + public int setLocation(int v); /** + * Retrieves the location of the shader attribute from the linked shader program. + * <p> + * No validation is performed within the implementation. + * </p> + * @param gl + * @param program + * @return ≥0 denotes a valid attribute location as found and used in the given shader program. + * <0 denotes an invalid location, i.e. not found or used in the given shader program. + */ + public int setLocation(GL2ES2 gl, int program); + + /** + * Binds the location of the shader attribute to the given location for the unlinked shader program. + * <p> + * No validation is performed within the implementation. + * </p> + * @param gl + * @param program + * @return the given location + */ + public int setLocation(GL2ES2 gl, int program, int location); + + /** * Determines whether the data is server side (VBO) and enabled, * or a client side array (false). */ diff --git a/src/jogl/classes/javax/media/opengl/GLBase.java b/src/jogl/classes/javax/media/opengl/GLBase.java index 9bcee819a..82bb06b9c 100644 --- a/src/jogl/classes/javax/media/opengl/GLBase.java +++ b/src/jogl/classes/javax/media/opengl/GLBase.java @@ -432,6 +432,19 @@ public interface GLBase { * </p> */ public int getDefaultReadFramebuffer(); - + + /** + * Returns the default color buffer within the current bound + * {@link #getDefaultReadFramebuffer()}, i.e. GL_READ_FRAMEBUFFER​, + * which will be used as the source for pixel reading commands, + * like {@link GL#glReadPixels(int, int, int, int, int, int, java.nio.Buffer)} etc. + * <p> + * For offscreen framebuffer objects this is {@link GL#GL_COLOR_ATTACHMENT0}, + * otherwise this is {@link GL#GL_FRONT} for single buffer configurations + * and {@link GL#GL_BACK} for double buffer configurations. + * </p> + */ + public int getDefaultReadBuffer(); + } diff --git a/src/jogl/classes/javax/media/opengl/GLContext.java b/src/jogl/classes/javax/media/opengl/GLContext.java index de10a2815..235003c38 100644 --- a/src/jogl/classes/javax/media/opengl/GLContext.java +++ b/src/jogl/classes/javax/media/opengl/GLContext.java @@ -970,6 +970,32 @@ public abstract class GLContext { */ public abstract int getDefaultReadFramebuffer(); + /** + * Returns the default color buffer within the current bound + * {@link #getDefaultReadFramebuffer()}, i.e. GL_READ_FRAMEBUFFER​, + * which will be used as the source for pixel reading commands, + * like {@link GL#glReadPixels(int, int, int, int, int, int, java.nio.Buffer)} etc. + * <p> + * For offscreen framebuffer objects this is {@link GL#GL_COLOR_ATTACHMENT0}, + * otherwise this is {@link GL#GL_FRONT} for single buffer configurations + * and {@link GL#GL_BACK} for double buffer configurations. + * </p> + */ + public abstract int getDefaultReadBuffer(); + + /** On some platforms the mismatch between OpenGL's coordinate + system (origin at bottom left) and the window system's + coordinate system (origin at top left) necessitates a vertical + flip of pixels read from offscreen contexts. + <p> + Default impl. is <code>true</code>. + </p> + */ + public abstract boolean isGLOrientationFlippedVertical(); + + /** Get the default pixel data type, as required by e.g. {@link GL#glReadPixels(int, int, int, int, int, int, java.nio.Buffer)}. */ + public abstract int getDefaultPixelDataType(); + /** * @return The extension implementing the GLDebugOutput feature, * either <i>GL_ARB_debug_output</i> or <i>GL_AMD_debug_output</i>. diff --git a/src/jogl/classes/javax/media/opengl/GLFBODrawable.java b/src/jogl/classes/javax/media/opengl/GLFBODrawable.java index 079d9af5c..4d6c7c20e 100644 --- a/src/jogl/classes/javax/media/opengl/GLFBODrawable.java +++ b/src/jogl/classes/javax/media/opengl/GLFBODrawable.java @@ -101,7 +101,8 @@ public interface GLFBODrawable extends GLDrawable { void setTextureUnit(int unit); /** - * Set a new sample size + * Set the number of sample buffers if using MSAA + * * @param gl GL context object bound to this drawable, will be made current during operation. * A prev. current context will be make current after operation. * @param newSamples new sample size @@ -113,6 +114,25 @@ public interface GLFBODrawable extends GLDrawable { * @return the number of sample buffers if using MSAA, otherwise 0 */ int getNumSamples(); + + /** + * Sets the number of buffers (FBO) being used if using {@link GLCapabilities#getDoubleBuffered() double buffering}. + * <p> + * If {@link GLCapabilities#getDoubleBuffered() double buffering} is not chosen, this is a NOP. + * </p> + * <p> + * Must be called before {@link #isInitialized() initialization}, otherwise an exception is thrown. + * </p> + * @return the new number of buffers (FBO) used, maybe different than the requested <code>bufferCount</code> (see above) + * @throws GLException if already initialized, see {@link #isInitialized()}. + */ + int setNumBuffers(int bufferCount) throws GLException; + + /** + * @return the number of buffers (FBO) being used. 1 if not using {@link GLCapabilities#getDoubleBuffered() double buffering}, + * otherwise ≥ 2, depending on {@link #setNumBuffers(int)}. + */ + int getNumBuffers(); /** * @return the used {@link DoubleBufferMode} diff --git a/src/jogl/classes/javax/media/opengl/GLUniformData.java b/src/jogl/classes/javax/media/opengl/GLUniformData.java index 18a422670..60d0c58bf 100644 --- a/src/jogl/classes/javax/media/opengl/GLUniformData.java +++ b/src/jogl/classes/javax/media/opengl/GLUniformData.java @@ -147,10 +147,26 @@ public class GLUniformData { public int getLocation() { return location; } /** - * Sets the determined location of the shader uniform. + * Sets the given location of the shader uniform. + * @return the given location */ - public GLUniformData setLocation(int location) { this.location=location; return this; } + public int setLocation(int location) { this.location=location; return location; } + /** + * Retrieves the location of the shader uniform from the linked shader program. + * <p> + * No validation is performed within the implementation. + * </p> + * @param gl + * @param program + * @return ≥0 denotes a valid uniform location as found and used in the given shader program. + * <0 denotes an invalid location, i.e. not found or used in the given shader program. + */ + public int setLocation(GL2ES2 gl, int program) { + location = gl.glGetUniformLocation(program, name); + return location; + } + public Object getObject() { return data; } diff --git a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java index a40cdcf88..efdc69ed8 100644 --- a/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java +++ b/src/jogl/classes/javax/media/opengl/awt/GLCanvas.java @@ -915,7 +915,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing // Catch dispose GLExceptions by GLEventListener, just 'print' them // so we can continue with the destruction. try { - helper.disposeGL(GLCanvas.this, context); + helper.disposeGL(GLCanvas.this, context, true); } catch (GLException gle) { gle.printStackTrace(); } @@ -1024,7 +1024,9 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing final RecursiveLock _lock = lock; _lock.lock(); try { - helper.invokeGL(drawable, context, displayAction, initAction); + if( null != drawable && drawable.isRealized() ) { + helper.invokeGL(drawable, context, displayAction, initAction); + } } finally { _lock.unlock(); } @@ -1037,7 +1039,7 @@ public class GLCanvas extends Canvas implements AWTGLAutoDrawable, WindowClosing final RecursiveLock _lock = lock; _lock.lock(); try { - if(null != drawable) { + if( null != drawable && drawable.isRealized() ) { drawable.swapBuffers(); } } finally { diff --git a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java index dcfc1f0dd..23dedaa66 100644 --- a/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java +++ b/src/jogl/classes/javax/media/opengl/awt/GLJPanel.java @@ -49,10 +49,8 @@ import java.awt.GraphicsEnvironment; import java.awt.Rectangle; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; -import java.awt.image.DataBufferByte; import java.awt.image.DataBufferInt; import java.beans.Beans; -import java.nio.ByteBuffer; import java.nio.IntBuffer; import java.util.List; @@ -73,7 +71,7 @@ import javax.media.opengl.GLDrawable; import javax.media.opengl.GLDrawableFactory; import javax.media.opengl.GLEventListener; import javax.media.opengl.GLException; -import javax.media.opengl.GLPbuffer; +import javax.media.opengl.GLFBODrawable; import javax.media.opengl.GLProfile; import javax.media.opengl.GLRunnable; import javax.media.opengl.Threading; @@ -86,10 +84,11 @@ import jogamp.opengl.GLDrawableHelper; import jogamp.opengl.GLDrawableImpl; import jogamp.opengl.awt.Java2D; import jogamp.opengl.awt.Java2DGLContext; +import jogamp.opengl.util.glsl.GLSLTextureRaster; import com.jogamp.nativewindow.awt.AWTWindowClosingProtocol; import com.jogamp.opengl.FBObject; -import com.jogamp.opengl.util.GLBuffers; +import com.jogamp.opengl.util.GLPixelStorageModes; // FIXME: Subclasses need to call resetGLFunctionAvailability() on their // context whenever the displayChanged() function is called on their @@ -122,14 +121,17 @@ import com.jogamp.opengl.util.GLBuffers; * </P> */ -@SuppressWarnings({ "serial", "deprecation" }) +@SuppressWarnings("serial") public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosingProtocol { private static final boolean DEBUG = Debug.debug("GLJPanel"); private GLDrawableHelper helper = new GLDrawableHelper(); private volatile boolean isInitialized; + // // Data used for either pbuffers or pixmap-based offscreen surfaces + // + /** Single buffered offscreen caps */ private GLCapabilitiesImmutable offscreenCaps; private GLProfile glProfile; private GLDrawableFactoryImpl factory; @@ -150,16 +152,6 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing // Used by all backends either directly or indirectly to hook up callbacks private Updater updater = new Updater(); - // Turns off the pbuffer-based backend (used by default, unless the - // Java 2D / OpenGL pipeline is in use) - private static boolean hardwareAccelerationDisabled = - Debug.isPropertyDefined("jogl.gljpanel.nohw", true); - - // Turns off the fallback to software-based rendering from - // pbuffer-based rendering - private static boolean softwareRenderingDisabled = - Debug.isPropertyDefined("jogl.gljpanel.nosw", true); - // Indicates whether the Java 2D OpenGL pipeline is enabled private boolean oglPipelineEnabled = Java2D.isOGLPipelineActive() && @@ -354,7 +346,8 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing // re-creating it -- tricky to do properly while the context is // current if (handleReshape) { - handleReshape(); + handleReshape = false; + sendReshape = handleReshape(); } updater.setGraphics(g); @@ -395,8 +388,10 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing called on all registered {@link GLEventListener}s. Subclasses which override this method must call super.reshape() in their reshape() method in order to function properly. <P> - - <DL><DD><CODE>reshape</CODE> in class <CODE>java.awt.Component</CODE></DD></DL> */ + * + * {@inheritDoc} + */ + @SuppressWarnings("deprecation") @Override public void reshape(int x, int y, int width, int height) { super.reshape(x, y, width, height); @@ -618,12 +613,18 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing @Override public NativeSurface getNativeSurface() { - throw new GLException("FIXME"); + if(null != backend) { + return backend.getDrawable().getNativeSurface(); + } + return null; } @Override public long getHandle() { - throw new GLException("FIXME"); + if(null != backend) { + return backend.getDrawable().getNativeSurface().getSurfaceHandle(); + } + return 0; } @Override @@ -636,13 +637,11 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing // private void createAndInitializeBackend() { - if (panelWidth == 0 || - panelHeight == 0) { + if ( 0 >= panelWidth || 0 >= panelHeight ) { // See whether we have a non-zero size yet and can go ahead with // initialization - if (reshapeWidth == 0 || - reshapeHeight == 0) { - return; + if (0 >= reshapeWidth || 0 >= reshapeHeight ) { + return; } // Pull down reshapeWidth and reshapeHeight into panelWidth and @@ -652,29 +651,18 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing panelHeight = reshapeHeight; } - do { - if (backend == null) { + if ( null == backend ) { if (oglPipelineEnabled) { - backend = new J2DOGLBackend(); + backend = new J2DOGLBackend(); } else { - if (!hardwareAccelerationDisabled && - factory.canCreateGLPbuffer(null)) { - backend = new PbufferBackend(); - } else { - if (softwareRenderingDisabled) { - throw new GLException("Fallback to software rendering disabled by user"); - } - backend = new SoftwareBackend(); - } + backend = new OffscreenBackend(); } - } + isInitialized = false; + } - if (!isInitialized) { + if (!isInitialized) { backend.initialize(); - } - // The backend might set itself to null, indicating it punted to - // a different implementation -- try again - } while (backend == null); + } awtWindowClosingProtocol.addClosingListenerOneShot(); } @@ -689,7 +677,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing return awtWindowClosingProtocol.setDefaultCloseOperation(op); } - private void handleReshape() { + private boolean handleReshape() { panelWidth = reshapeWidth; panelHeight = reshapeHeight; @@ -698,9 +686,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing panelWidth + "," + panelHeight + ")"); } - sendReshape = true; - backend.handleReshape(); - handleReshape = false; + return backend.handleReshape(); } // This is used as the GLEventListener for the pbuffer-based backend @@ -762,16 +748,17 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing public void run() { if ( null != backend ) { final GLContext _context = backend.getContext(); + final boolean backendDestroy = !backend.isUsingOwnLifecycle(); if( null != _context && _context.isCreated() ) { // Catch dispose GLExceptions by GLEventListener, just 'print' them // so we can continue with the destruction. try { - helper.disposeGL(GLJPanel.this, _context); + helper.disposeGL(GLJPanel.this, _context, !backendDestroy); } catch (GLException gle) { gle.printStackTrace(); } } - if ( !backend.isUsingOwnThreadManagment() ) { + if ( backendDestroy ) { backend.destroy(); backend = null; isInitialized = false; @@ -815,15 +802,6 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing } }; - private int getNextPowerOf2(int number) { - // Workaround for problems where 0 width or height are transiently - // seen during layout - if (number == 0) { - return 2; - } - return GLBuffers.getNextPowerOf2(number); - } - private int getGLInteger(GL gl, int which) { int[] tmp = new int[1]; gl.glGetIntegerv(which, tmp, 0); @@ -843,7 +821,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing // / JOGL bridge static interface Backend { // Create, Destroy, .. - public boolean isUsingOwnThreadManagment(); + public boolean isUsingOwnLifecycle(); // Called each time the backend needs to initialize itself public void initialize(); @@ -876,7 +854,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing // Called to handle a reshape event. When this is called, the // OpenGL context associated with the backend is not current, to // make it easier to destroy and re-create pbuffers if necessary. - public void handleReshape(); + public boolean handleReshape(); // Called before the OpenGL work is done in init() and display(). // If false is returned, this render is aborted. @@ -894,12 +872,11 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing // Base class used by both the software (pixmap) and pbuffer // backends, both of which rely on reading back the OpenGL frame // buffer and drawing it with a BufferedImage - abstract class AbstractReadbackBackend implements Backend { + class OffscreenBackend implements Backend { // This image is exactly the correct size to render into the panel protected BufferedImage offscreenImage; // One of these is used to store the read back pixels before storing // in the BufferedImage - protected ByteBuffer readBackBytes; protected IntBuffer readBackInts; protected int readBackWidthInPixels; protected int readBackHeightInPixels; @@ -907,12 +884,118 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing private int glFormat; private int glType; + // Implementation using software rendering + private GLDrawableImpl offscreenDrawable; + private FBObject fboFlipped; + private GLSLTextureRaster glslTextureRaster; + private final int fboTextureUnit = 0; + + private GLContextImpl offscreenContext; + private boolean flippedVertical; + // For saving/restoring of OpenGL state during ReadPixels - private int[] swapbytes = new int[1]; - private int[] rowlength = new int[1]; - private int[] skiprows = new int[1]; - private int[] skippixels = new int[1]; - private int[] alignment = new int[1]; + private final GLPixelStorageModes psm = new GLPixelStorageModes(); + + @Override + public boolean isUsingOwnLifecycle() { return false; } + + @Override + public void initialize() { + if(DEBUG) { + System.err.println(getThreadName()+": OffscreenBackend: initialize()"); + } + try { + offscreenDrawable = (GLDrawableImpl) factory.createOffscreenDrawable( + null /* default platform device */, + offscreenCaps, + chooser, + panelWidth, panelHeight); + offscreenDrawable.setRealized(true); + offscreenContext = (GLContextImpl) offscreenDrawable.createContext(shareWith); + offscreenContext.setContextCreationFlags(additionalCtxCreationFlags); + if( GLContext.CONTEXT_NOT_CURRENT < offscreenContext.makeCurrent() ) { + isInitialized = true; + final GL gl = offscreenContext.getGL(); + flippedVertical = offscreenContext.isGLOrientationFlippedVertical(); + final GLCapabilitiesImmutable chosenCaps = offscreenDrawable.getChosenGLCapabilities(); + if( chosenCaps.isFBO() && flippedVertical && gl.isGL2ES2() ) { + helper.setAutoSwapBufferMode(false); + final GLFBODrawable fboDrawable = (GLFBODrawable) offscreenDrawable; + try { + fboFlipped = new FBObject(); + fboFlipped.reset(gl, fboDrawable.getWidth(), fboDrawable.getHeight(), 0, false); + fboFlipped.attachTexture2D(gl, 0, chosenCaps.getAlphaBits()>0); + // fboFlipped.attachRenderbuffer(gl, Attachment.Type.DEPTH, 24); + glslTextureRaster = new GLSLTextureRaster(fboTextureUnit, true); + glslTextureRaster.init(gl.getGL2ES2()); + glslTextureRaster.reshape(gl.getGL2ES2(), 0, 0, fboDrawable.getWidth(), fboDrawable.getHeight()); + } catch (Exception ex) { + ex.printStackTrace(); + if(null != glslTextureRaster) { + glslTextureRaster.dispose(gl.getGL2ES2()); + glslTextureRaster = null; + } + if(null != fboFlipped) { + fboFlipped.destroy(gl); + fboFlipped = null; + } + } + } else { + fboFlipped = null; + glslTextureRaster = null; + } + offscreenContext.release(); + } else { + isInitialized = false; + } + } finally { + if( !isInitialized ) { + if(null != offscreenContext) { + offscreenContext.destroy(); + offscreenContext = null; + } + if(null != offscreenDrawable) { + offscreenDrawable.setRealized(false); + offscreenDrawable = null; + } + } + } + } + + @Override + public void destroy() { + if(DEBUG) { + System.err.println(getThreadName()+": OffscreenBackend: destroy() - offscreenContext: "+(null!=offscreenContext)+" - offscreenDrawable: "+(null!=offscreenDrawable)); + } + if ( null != offscreenContext && offscreenContext.isCreated() ) { + if( GLContext.CONTEXT_NOT_CURRENT < offscreenContext.makeCurrent() ) { + try { + final GL gl = offscreenContext.getGL(); + if(null != glslTextureRaster) { + glslTextureRaster.dispose(gl.getGL2ES2()); + } + if(null != fboFlipped) { + fboFlipped.destroy(gl); + } + } finally { + offscreenContext.destroy(); + } + } + } + offscreenContext = null; + glslTextureRaster = null; + fboFlipped = null; + offscreenContext = null; + + if (offscreenDrawable != null) { + final AbstractGraphicsDevice adevice = offscreenDrawable.getNativeSurface().getGraphicsConfiguration().getScreen().getDevice(); + offscreenDrawable.setRealized(false); + offscreenDrawable = null; + if(null != adevice) { + adevice.close(); + } + } + } @Override public void setOpaque(boolean opaque) { @@ -935,128 +1018,85 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing if (isDisplay) { // Must now copy pixels from offscreen context into surface if (offscreenImage == null) { - if (panelWidth > 0 && panelHeight > 0) { - // It looks like NVidia's drivers (at least the ones on my - // notebook) are buggy and don't allow a sub-rectangle to be - // read from a pbuffer...this doesn't really matter because - // it's the Graphics.drawImage() calls that are the - // bottleneck - - int awtFormat = 0; - - // Should be more flexible in these BufferedImage formats; - // perhaps see what the preferred image types are on the - // given platform - if (isOpaque()) { - awtFormat = BufferedImage.TYPE_INT_RGB; - } else { - awtFormat = BufferedImage.TYPE_INT_ARGB; - } - - offscreenImage = new BufferedImage(panelWidth, - panelHeight, - awtFormat); - switch (awtFormat) { - case BufferedImage.TYPE_3BYTE_BGR: - glFormat = GL2.GL_BGR; - glType = GL.GL_UNSIGNED_BYTE; - readBackBytes = ByteBuffer.allocate(readBackWidthInPixels * readBackHeightInPixels * 3); - break; - - case BufferedImage.TYPE_INT_RGB: - case BufferedImage.TYPE_INT_ARGB: - glFormat = GL.GL_BGRA; - glType = getGLPixelType(); + if (0 >= panelWidth || 0 >= panelHeight ) { + return; + } + final boolean withAlpha = !isOpaque(); + + glFormat = GL.GL_BGRA; + glType = GL.GL_UNSIGNED_BYTE; // offscreenContext.getDefaultPixelDataType(); + + if(!flippedVertical || null != glslTextureRaster) { + offscreenImage = new BufferedImage(panelWidth, panelHeight, withAlpha ? BufferedImage.TYPE_INT_ARGB : BufferedImage.TYPE_INT_RGB); + final int[] readBackIntBuffer = ((DataBufferInt) offscreenImage.getRaster().getDataBuffer()).getData(); + readBackInts = IntBuffer.wrap(readBackIntBuffer); + } else { + offscreenImage = new BufferedImage(panelWidth, panelHeight, withAlpha ? BufferedImage.TYPE_INT_ARGB : BufferedImage.TYPE_INT_RGB); readBackInts = IntBuffer.allocate(readBackWidthInPixels * readBackHeightInPixels); - break; - - default: - // FIXME: Support more off-screen image types (current - // offscreen context implementations don't use others, and - // some of the OpenGL formats aren't supported in the 1.1 - // headers, which we're currently using) - throw new GLException("Unsupported offscreen image type " + awtFormat); - } + } + if(DEBUG) { + System.err.println(getThreadName()+": OffscreenBackend postGL offscreenImage-init: flippedVertical "+flippedVertical+", glslTextureRaster "+(null!=glslTextureRaster)); } } - if (offscreenImage != null) { - GL2 gl = getGL().getGL2(); - // Save current modes - gl.glGetIntegerv(GL2.GL_PACK_SWAP_BYTES, swapbytes, 0); - gl.glGetIntegerv(GL2.GL_PACK_ROW_LENGTH, rowlength, 0); - gl.glGetIntegerv(GL2.GL_PACK_SKIP_ROWS, skiprows, 0); - gl.glGetIntegerv(GL2.GL_PACK_SKIP_PIXELS, skippixels, 0); - gl.glGetIntegerv(GL2.GL_PACK_ALIGNMENT, alignment, 0); - - gl.glPixelStorei(GL2.GL_PACK_SWAP_BYTES, GL.GL_FALSE); - gl.glPixelStorei(GL2.GL_PACK_ROW_LENGTH, readBackWidthInPixels); - gl.glPixelStorei(GL2.GL_PACK_SKIP_ROWS, 0); - gl.glPixelStorei(GL2.GL_PACK_SKIP_PIXELS, 0); - gl.glPixelStorei(GL2.GL_PACK_ALIGNMENT, 1); - - // Actually read the pixels. - gl.glReadBuffer(GL2.GL_FRONT); - if (readBackBytes != null) { - gl.glReadPixels(0, 0, readBackWidthInPixels, readBackHeightInPixels, glFormat, glType, readBackBytes); - } else if (readBackInts != null) { + final GL gl = offscreenContext.getGL(); + + // Save current modes + psm.setAlignment(gl, 1, 1); + if(gl.isGL2GL3()) { + final GL2GL3 gl2gl3 = gl.getGL2GL3(); + gl2gl3.glPixelStorei(GL2GL3.GL_PACK_ROW_LENGTH, readBackWidthInPixels); + gl2gl3.glReadBuffer(gl2gl3.getDefaultReadBuffer()); + } + + if(null != glslTextureRaster) { // implies flippedVertical + // perform vert-flipping via OpenGL/FBO + final GLFBODrawable fboDrawable = (GLFBODrawable)offscreenDrawable; + final FBObject.TextureAttachment fboTex = fboDrawable.getTextureBuffer(GL.GL_FRONT); + + fboDrawable.swapBuffers(); + fboFlipped.bind(gl); + + // gl.glActiveTexture(fboDrawable.getTextureUnit()); // implicit! + 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, readBackWidthInPixels, readBackHeightInPixels, glFormat, glType, readBackInts); - } - // Restore saved modes. - gl.glPixelStorei(GL2.GL_PACK_SWAP_BYTES, swapbytes[0]); - gl.glPixelStorei(GL2.GL_PACK_ROW_LENGTH, rowlength[0]); - gl.glPixelStorei(GL2.GL_PACK_SKIP_ROWS, skiprows[0]); - gl.glPixelStorei(GL2.GL_PACK_SKIP_PIXELS, skippixels[0]); - gl.glPixelStorei(GL2.GL_PACK_ALIGNMENT, alignment[0]); - - if (readBackBytes != null || readBackInts != null) { - // Copy temporary data into raster of BufferedImage for faster - // blitting Note that we could avoid this copy in the cases - // where !offscreenContext.offscreenImageNeedsVerticalFlip(), - // but that's the software rendering path which is very slow - // anyway - Object src = null; - Object dest = null; - int srcIncr = 0; - int destIncr = 0; - - if (readBackBytes != null) { - src = readBackBytes.array(); - dest = ((DataBufferByte) offscreenImage.getRaster().getDataBuffer()).getData(); - srcIncr = readBackWidthInPixels * 3; - destIncr = offscreenImage.getWidth() * 3; - } else { - src = readBackInts.array(); - dest = ((DataBufferInt) offscreenImage.getRaster().getDataBuffer()).getData(); - srcIncr = readBackWidthInPixels; - destIncr = offscreenImage.getWidth(); + fboFlipped.unbind(gl); + } else { + gl.glReadPixels(0, 0, readBackWidthInPixels, readBackHeightInPixels, glFormat, glType, readBackInts); + + if ( flippedVertical ) { + // Copy temporary data into raster of BufferedImage for faster + // blitting Note that we could avoid this copy in the cases + // where !offscreenContext.offscreenImageNeedsVerticalFlip(), + // but that's the software rendering path which is very slow + // anyway + final Object src = readBackInts.array(); + final Object dest = ((DataBufferInt) offscreenImage.getRaster().getDataBuffer()).getData(); + final int srcIncr = readBackWidthInPixels; + final int destIncr = offscreenImage.getWidth(); + int srcPos = 0; + int destPos = (offscreenImage.getHeight() - 1) * destIncr; + for (; destPos >= 0; srcPos += srcIncr, destPos -= destIncr) { + System.arraycopy(src, srcPos, dest, destPos, destIncr); + } } + } - if (flipVertically()) { - int srcPos = 0; - int destPos = (offscreenImage.getHeight() - 1) * destIncr; - for (; destPos >= 0; srcPos += srcIncr, destPos -= destIncr) { - System.arraycopy(src, srcPos, dest, destPos, destIncr); - } - } else { - int srcPos = 0; - int destEnd = destIncr * offscreenImage.getHeight(); - for (int destPos = 0; destPos < destEnd; srcPos += srcIncr, destPos += destIncr) { - System.arraycopy(src, srcPos, dest, destPos, destIncr); - } - } + // Restore saved modes. + psm.restore(gl); - // Note: image will be drawn back in paintComponent() for - // correctness on all platforms - } - } + // Note: image will be drawn back in paintComponent() for + // correctness on all platforms } } @Override public void doPaintComponent(Graphics g) { - doPaintComponentImpl(); + helper.invokeGL(offscreenDrawable, offscreenContext, updaterDisplayAction, updaterInitAction); + if (offscreenImage != null) { // Draw resulting image in one shot g.drawImage(offscreenImage, 0, 0, @@ -1066,57 +1106,52 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing } } - protected abstract void doPaintComponentImpl(); - protected abstract int getGLPixelType(); - protected abstract boolean flipVertically(); - } - - class SoftwareBackend extends AbstractReadbackBackend { - // Implementation using software rendering - private GLDrawableImpl offscreenDrawable; - private GLContextImpl offscreenContext; - - @Override - public boolean isUsingOwnThreadManagment() { return false; } - @Override - public void initialize() { - if(DEBUG) { - System.err.println(getThreadName()+": SoftwareBackend: initialize()"); - } - // Fall-through path: create an offscreen context instead - offscreenDrawable = (GLDrawableImpl) factory.createOffscreenDrawable( - null /* default platform device */, - offscreenCaps, - chooser, - Math.max(1, panelWidth), - Math.max(1, panelHeight)); - offscreenDrawable.setRealized(true); - offscreenContext = (GLContextImpl) offscreenDrawable.createContext(shareWith); - offscreenContext.setContextCreationFlags(additionalCtxCreationFlags); - - isInitialized = true; - } + public boolean handleReshape() { + /** FIXME: Shall we utilize such resize optimization (snippet kept alive from removed pbuffer backend) ? + // Use factor larger than 2 during shrinks for some hysteresis + float shrinkFactor = 2.5f; + if ( (panelWidth > readBackWidthInPixels) || (panelHeight > readBackHeightInPixels) || + (panelWidth < (readBackWidthInPixels / shrinkFactor)) || (panelHeight < (readBackHeightInPixels / shrinkFactor))) { + if (DEBUG) { + System.err.println(getThreadName()+": Resizing offscreen from (" + readBackWidthInPixels + ", " + readBackHeightInPixels + ") " + + " to fit (" + panelWidth + ", " + panelHeight + ")"); + } + } */ + + GLDrawableImpl _drawable = offscreenDrawable; + { + final GLDrawableImpl _drawableNew = GLDrawableHelper.resizeOffscreenDrawable(_drawable, offscreenContext, panelWidth, panelHeight); + if(_drawable != _drawableNew) { + // write back + _drawable = _drawableNew; + offscreenDrawable = _drawableNew; + } + } + panelWidth = _drawable.getWidth(); + panelHeight = _drawable.getHeight(); + readBackWidthInPixels = panelWidth; + readBackHeightInPixels = panelHeight; + + if( null != glslTextureRaster ) { + if( GLContext.CONTEXT_NOT_CURRENT < offscreenContext.makeCurrent() ) { + try { + final GL gl = offscreenContext.getGL(); + fboFlipped.reset(gl, _drawable.getWidth(), _drawable.getHeight(), 0, false); + glslTextureRaster.reshape(gl.getGL2ES2(), 0, 0, _drawable.getWidth(), _drawable.getHeight()); + } finally { + offscreenContext.release(); + } + } + } - @Override - public void destroy() { - if(DEBUG) { - System.err.println(getThreadName()+": SoftwareBackend: destroy() - offscreenContext: "+(null!=offscreenContext)+" - offscreenDrawable: "+(null!=offscreenDrawable)); - } - if (offscreenContext != null) { - offscreenContext.destroy(); - offscreenContext = null; - } - if (offscreenDrawable != null) { - final AbstractGraphicsDevice adevice = offscreenDrawable.getNativeSurface().getGraphicsConfiguration().getScreen().getDevice(); - offscreenDrawable.setRealized(false); - offscreenDrawable = null; - if(null != adevice) { - adevice.close(); + if (offscreenImage != null) { + offscreenImage.flush(); + offscreenImage = null; } - } + return _drawable.isRealized(); } - + @Override public GLContext createContext(GLContext shareWith) { return (null != offscreenDrawable) ? offscreenDrawable.createContext(shareWith) : null; @@ -1152,201 +1187,6 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing } return offscreenDrawable.getGLProfile(); } - - @Override - public void handleReshape() { - destroy(); - initialize(); - readBackWidthInPixels = Math.max(1, panelWidth); - readBackHeightInPixels = Math.max(1, panelHeight); - - if (offscreenImage != null) { - offscreenImage.flush(); - offscreenImage = null; - } - } - - @Override - protected void doPaintComponentImpl() { - helper.invokeGL(offscreenDrawable, offscreenContext, updaterDisplayAction, updaterInitAction); - } - - @Override - protected int getGLPixelType() { - return offscreenContext.getOffscreenContextPixelDataType(); - } - - @Override - protected boolean flipVertically() { - return offscreenContext.offscreenImageNeedsVerticalFlip(); - } - } - - class PbufferBackend extends AbstractReadbackBackend { - private GLPbuffer pbuffer; - private int pbufferWidth = 256; - private int pbufferHeight = 256; - - @Override - public boolean isUsingOwnThreadManagment() { return false; } - - @Override - public void initialize() { - if (pbuffer != null) { - throw new InternalError("Creating pbuffer twice without destroying it (memory leak / correctness bug)"); - } - if(DEBUG) { - System.err.println(getThreadName()+": PbufferBackend: initialize()"); - } - try { - pbuffer = factory.createGLPbuffer(null /* default platform device */, - offscreenCaps, - null, - pbufferWidth, - pbufferHeight, - shareWith); - pbuffer.setContextCreationFlags(additionalCtxCreationFlags); - pbuffer.addGLEventListener(updater); - isInitialized = true; - } catch (GLException e) { - if (DEBUG) { - e.printStackTrace(); - System.err.println(getThreadName()+": GLJPanel: Falling back on software rendering because of problems creating pbuffer"); - } - hardwareAccelerationDisabled = true; - backend = null; - isInitialized = false; - createAndInitializeBackend(); - } - } - - @Override - public void destroy() { - if(DEBUG) { - System.err.println(getThreadName()+": PbufferBackend: destroy() - pbuffer: "+(null!=pbuffer)); - } - if (pbuffer != null) { - pbuffer.destroy(); - pbuffer = null; - } - } - - @Override - public GLContext createContext(GLContext shareWith) { - return (null != pbuffer) ? pbuffer.createContext(shareWith) : null; - } - - @Override - public void setContext(GLContext ctx) { - if (pbuffer == null || Beans.isDesignTime()) { - return; - } - pbuffer.setContext(ctx); - } - - @Override - public GLContext getContext() { - // Workaround for crashes in NetBeans GUI builder - if (null == pbuffer || Beans.isDesignTime()) { - return null; - } - return pbuffer.getContext(); - } - - @Override - public GLDrawable getDrawable() { - return pbuffer; - } - - @Override - public GLCapabilitiesImmutable getChosenGLCapabilities() { - if (pbuffer == null) { - return null; - } - return pbuffer.getChosenGLCapabilities(); - } - - @Override - public GLProfile getGLProfile() { - if (pbuffer == null) { - return null; - } - return pbuffer.getGLProfile(); - } - - @Override - public void handleReshape() { - // Use factor larger than 2 during shrinks for some hysteresis - float shrinkFactor = 2.5f; - if ((panelWidth > pbufferWidth) || (panelHeight > pbufferHeight) || - (panelWidth < (pbufferWidth / shrinkFactor)) || (panelHeight < (pbufferHeight / shrinkFactor))) { - if (DEBUG) { - System.err.println(getThreadName()+": Resizing pbuffer from (" + pbufferWidth + ", " + pbufferHeight + ") " + - " to fit (" + panelWidth + ", " + panelHeight + ")"); - } - // Must destroy and recreate pbuffer to fit - if (pbuffer != null) { - // Watch for errors during pbuffer destruction (due to - // buggy / bad OpenGL drivers, in particular SiS) and fall - // back to software rendering - try { - pbuffer.destroy(); - } catch (GLException e) { - hardwareAccelerationDisabled = true; - backend = null; - isInitialized = false; - // Just disabled hardware acceleration during this resize operation; do a fixup - readBackWidthInPixels = Math.max(1, panelWidth); - readBackHeightInPixels = Math.max(1, panelHeight); - if (DEBUG) { - System.err.println(getThreadName()+": Warning: falling back to software rendering due to bugs in OpenGL drivers"); - e.printStackTrace(); - } - createAndInitializeBackend(); - return; - } - } - pbuffer = null; - isInitialized = false; - pbufferWidth = getNextPowerOf2(panelWidth); - pbufferHeight = getNextPowerOf2(panelHeight); - if (DEBUG && !hardwareAccelerationDisabled) { - System.err.println(getThreadName()+": New pbuffer size is (" + pbufferWidth + ", " + pbufferHeight + ")"); - } - initialize(); - } - - // It looks like NVidia's drivers (at least the ones on my - // notebook) are buggy and don't allow a rectangle of less than - // the pbuffer's width to be read...this doesn't really matter - // because it's the Graphics.drawImage() calls that are the - // bottleneck. Should probably make the size of the offscreen - // image be the exact size of the pbuffer to save some work on - // resize operations... - readBackWidthInPixels = pbufferWidth; - readBackHeightInPixels = panelHeight; - - if (offscreenImage != null) { - offscreenImage.flush(); - offscreenImage = null; - } - } - - @Override - protected void doPaintComponentImpl() { - pbuffer.display(); - } - - @Override - protected int getGLPixelType() { - // This seems to be a good choice on all platforms - return GL2.GL_UNSIGNED_INT_8_8_8_8_REV; - } - - @Override - protected boolean flipVertically() { - return true; - } } class J2DOGLBackend implements Backend { @@ -1399,7 +1239,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing private GraphicsConfiguration workaroundConfig; @Override - public boolean isUsingOwnThreadManagment() { return true; } + public boolean isUsingOwnLifecycle() { return true; } @Override public void initialize() { @@ -1472,8 +1312,9 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing } @Override - public void handleReshape() { + public boolean handleReshape() { // Empty in this implementation + return true; } @Override @@ -1618,7 +1459,7 @@ public class GLJPanel extends JPanel implements AWTGLAutoDrawable, WindowClosing // Cause OpenGL pipeline to flush its results because // otherwise it's possible we will buffer up multiple frames' // rendering results, resulting in apparent mouse lag - GL gl = getGL(); + GL gl = joglContext.getGL(); gl.glFinish(); if (Java2D.isFBOEnabled() && diff --git a/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java b/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java index 68fbe3dd5..cbb7cd699 100644 --- a/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java +++ b/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java @@ -228,7 +228,7 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, FPSCounter { // Catch dispose GLExceptions by GLEventListener, just 'print' them // so we can continue with the destruction. try { - helper.disposeGL(this, context); + helper.disposeGL(this, context, true); } catch (GLException gle) { gle.printStackTrace(); } diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java index 65b523394..f61b55497 100644 --- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java +++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java @@ -448,7 +448,7 @@ public abstract class GLContextImpl extends GLContext { */ @Override public int makeCurrent() throws GLException { - boolean unlockContextAndDrawable = false; + boolean unlockContextAndDrawable = true; int res = CONTEXT_NOT_CURRENT; // Note: the surface is locked within [makeCurrent .. swap .. release] @@ -457,50 +457,51 @@ public abstract class GLContextImpl extends GLContext { return CONTEXT_NOT_CURRENT; } try { + if (0 == drawable.getHandle()) { + throw new GLException("drawable has invalid handle: "+drawable); + } if (NativeSurface.LOCK_SURFACE_CHANGED == lockRes) { drawable.updateHandle(); } - lock.lock(); - try { - // One context can only be current by one thread, - // and one thread can only have one context current! - final GLContext current = getCurrent(); - if (current != null) { - if (current == this) { - // Assume we don't need to make this context current again - // For Mac OS X, however, we need to update the context to track resizes - drawableUpdatedNotify(); - if(TRACE_SWITCH) { - System.err.println(getThreadName() +": GLContext.ContextSwitch: obj " + toHexString(hashCode()) + ", ctx "+toHexString(contextHandle)+", surf "+toHexString(drawable.getHandle())+" - keep - CONTEXT_CURRENT - "+lock); + if ( drawable.isRealized() ) { + lock.lock(); + try { + // One context can only be current by one thread, + // and one thread can only have one context current! + final GLContext current = getCurrent(); + if (current != null) { + if (current == this) { + // Assume we don't need to make this context current again + // For Mac OS X, however, we need to update the context to track resizes + drawableUpdatedNotify(); + if(TRACE_SWITCH) { + System.err.println(getThreadName() +": GLContext.ContextSwitch: obj " + toHexString(hashCode()) + ", ctx "+toHexString(contextHandle)+", surf "+toHexString(drawable.getHandle())+" - keep - CONTEXT_CURRENT - "+lock); + } + return CONTEXT_CURRENT; + } else { + current.release(); } - return CONTEXT_CURRENT; - } else { - current.release(); } + res = makeCurrentWithinLock(lockRes); + unlockContextAndDrawable = CONTEXT_NOT_CURRENT == res; + + /** + * FIXME: refactor dependence on Java 2D / JOGL bridge + if ( tracker != null && res == CONTEXT_CURRENT_NEW ) { + // Increase reference count of GLObjectTracker + tracker.ref(); + } + */ + } catch (RuntimeException e) { + unlockContextAndDrawable = true; + throw e; + } finally { + if (unlockContextAndDrawable) { + lock.unlock(); + } } - if (0 == drawable.getHandle()) { - throw new GLException("drawable has invalid handle: "+drawable); - } - res = makeCurrentWithinLock(lockRes); - unlockContextAndDrawable = CONTEXT_NOT_CURRENT == res; - - /** - * FIXME: refactor dependence on Java 2D / JOGL bridge - if ((tracker != null) && - (res == CONTEXT_CURRENT_NEW)) { - // Increase reference count of GLObjectTracker - tracker.ref(); - } - */ - } catch (RuntimeException e) { - unlockContextAndDrawable = true; - throw e; - } finally { - if (unlockContextAndDrawable) { - lock.unlock(); - } - } + } /* if ( drawable.isRealized() ) */ } catch (RuntimeException e) { unlockContextAndDrawable = true; throw e; @@ -511,8 +512,8 @@ public abstract class GLContextImpl extends GLContext { } if (res == CONTEXT_NOT_CURRENT) { - if(TRACE_SWITCH) { - System.err.println(getThreadName() +": GLContext.ContextSwitch: obj " + toHexString(hashCode()) + ", ctx "+toHexString(contextHandle)+", surf "+toHexString(drawable.getHandle())+" - switch - CONTEXT_NOT_CURRENT - "+lock); + if(DEBUG || TRACE_SWITCH) { + System.err.println(getThreadName() +": GLContext.ContextSwitch: obj " + toHexString(hashCode()) + ", ctx "+toHexString(contextHandle)+", surf "+toHexString(drawable.getHandle())+", drawable.isRealized() "+drawable.isRealized()+" - switch - CONTEXT_NOT_CURRENT - "+lock); } } else { setCurrent(this); @@ -693,8 +694,7 @@ public abstract class GLContextImpl extends GLContext { * @see #createContextARBImpl * @see #destroyContextARBImpl */ - protected abstract long createContextARBImpl(long share, boolean direct, int ctxOptionFlags, - int major, int minor); + protected abstract long createContextARBImpl(long share, boolean direct, int ctxOptionFlags, int major, int minor); /** * Destroy the context created by {@link #createContextARBImpl}. @@ -757,7 +757,7 @@ public abstract class GLContextImpl extends GLContext { _ctp[0] |= additionalCtxCreationFlags; _ctx = createContextARBImpl(share, direct, _ctp[0], _major[0], _minor[0]); if(0!=_ctx) { - setGLFunctionAvailability(true, _major[0], _minor[0], _ctp[0]); + setGLFunctionAvailability(true, _major[0], _minor[0], _ctp[0], false); } } return _ctx; @@ -940,8 +940,7 @@ public abstract class GLContextImpl extends GLContext { _context = createContextARBImpl(share, direct, ctxOptionFlags, major[0], minor[0]); if(0 != _context) { - ok = true; - setGLFunctionAvailability(true, major[0], minor[0], ctxOptionFlags); + ok = setGLFunctionAvailability(true, major[0], minor[0], ctxOptionFlags, true); } else { ok = false; } @@ -1166,15 +1165,17 @@ public abstract class GLContextImpl extends GLContext { * @param major OpenGL major version * @param minor OpenGL minor version * @param ctxProfileBits OpenGL context profile and option bits, see {@link javax.media.opengl.GLContext#CTX_OPTION_ANY} - * + * @param strictVersionMatch if <code>true</code> and the ctx version (by string) is lower than the given major.minor version, + * method aborts and returns <code>false</code>, otherwise <code>true</code>. + * @return returns <code>true</code> if successful, otherwise <code>false</code>. See <code>strictVersionMatch</code>. * @see #setContextVersion * @see javax.media.opengl.GLContext#CTX_OPTION_ANY * @see javax.media.opengl.GLContext#CTX_PROFILE_COMPAT * @see javax.media.opengl.GLContext#CTX_IMPL_ES2_COMPAT */ - protected final void setGLFunctionAvailability(boolean force, int major, int minor, int ctxProfileBits) { + protected final boolean setGLFunctionAvailability(boolean force, int major, int minor, int ctxProfileBits, boolean strictVersionMatch) { if(null!=this.gl && null!=glProcAddressTable && !force) { - return; // already done and not forced + return true; // already done and not forced } if(null==this.gl || !verifyInstance(gl.getGLProfile(), "Impl", this.gl)) { @@ -1206,7 +1207,13 @@ public abstract class GLContextImpl extends GLContext { { final VersionNumber setGLVersionNumber = new VersionNumber(major, minor, 0); final VersionNumber strGLVersionNumber = getGLVersionNumber(ctxProfileBits, glVersion); - if( null != strGLVersionNumber && ( strGLVersionNumber.compareTo(setGLVersionNumber) <= 0 || 0 == major ) ) { + if( null != strGLVersionNumber && ( strGLVersionNumber.compareTo(setGLVersionNumber) < 0 || 0 == major ) ) { + if( 0 < major && strictVersionMatch ) { + if(DEBUG) { + System.err.println(getThreadName() + ": GLContext.setGLFuncAvail.X: FAIL, GL version mismatch: "+major+"."+minor+", ctp "+toHexString(ctxProfileBits)+", "+glVersion+", "+strGLVersionNumber); + } + return false; + } glVersionNumber = strGLVersionNumber; major = glVersionNumber.getMajor(); minor = glVersionNumber.getMinor(); @@ -1299,8 +1306,9 @@ public abstract class GLContextImpl extends GLContext { setDefaultSwapInterval(); if(DEBUG) { - System.err.println(getThreadName() + ": GLContext.setGLFuncAvail.X: "+contextFQN+" - "+GLContext.getGLVersion(ctxMajorVersion, ctxMinorVersion, ctxOptions, null)); + System.err.println(getThreadName() + ": GLContext.setGLFuncAvail.X: OK "+contextFQN+" - "+GLContext.getGLVersion(ctxMajorVersion, ctxMinorVersion, ctxOptions, null)); } + return true; } private final void setRendererQuirks(boolean hwAccel) { @@ -1380,16 +1388,18 @@ public abstract class GLContextImpl extends GLContext { } synchronized(mappedContextTypeObjectLock) { - ProcAddressTable table = mappedGLProcAddress.remove( contextFQN ); + final ProcAddressTable table = mappedGLProcAddress.remove( contextFQN ); if(DEBUG) { - System.err.println(getThreadName() + ": RM GLContext GL ProcAddressTable mapping key("+contextFQN+") -> "+table.hashCode()); + final int hc = null != table ? table.hashCode() : 0; + System.err.println(getThreadName() + ": RM GLContext GL ProcAddressTable mapping key("+contextFQN+") -> "+toHexString(hc)); } } synchronized(mappedContextTypeObjectLock) { - ExtensionAvailabilityCache eCache = mappedExtensionAvailabilityCache.remove( contextFQN ); + final ExtensionAvailabilityCache eCache = mappedExtensionAvailabilityCache.remove( contextFQN ); if(DEBUG) { - System.err.println(getThreadName() + ": RM GLContext GL ExtensionAvailabilityCache mapping key("+contextFQN+") -> "+eCache.hashCode()); + final int hc = null != eCache ? eCache.hashCode() : 0; + System.err.println(getThreadName() + ": RM GLContext GL ExtensionAvailabilityCache mapping key("+contextFQN+") -> "+toHexString(hc)); } } } @@ -1513,15 +1523,46 @@ public abstract class GLContextImpl extends GLContext { throw new GLException("Not supported on non-pbuffer contexts"); } - /** On some platforms the mismatch between OpenGL's coordinate - system (origin at bottom left) and the window system's - coordinate system (origin at top left) necessitates a vertical - flip of pixels read from offscreen contexts. */ - public abstract boolean offscreenImageNeedsVerticalFlip(); + @Override + public boolean isGLOrientationFlippedVertical() { + return true; + } - /** Only called for offscreen contexts; needed by glReadPixels */ - public abstract int getOffscreenContextPixelDataType(); + @Override + public int getDefaultPixelDataType() { + if(!pixelDataTypeEvaluated) { + synchronized(this) { + if(!pixelDataTypeEvaluated) { + evalPixelDataType(); + pixelDataTypeEvaluated = true; + } + } + } + return pixelDataType; + } + private volatile boolean pixelDataTypeEvaluated = false; + int /* pixelDataInternalFormat, */ pixelDataFormat, pixelDataType; + + private final void evalPixelDataType() { + /* if(isGL2GL3() && 3 == components) { + pixelDataInternalFormat=GL.GL_RGB; + pixelDataFormat=GL.GL_RGB; + pixelDataType = GL.GL_UNSIGNED_BYTE; + } else */ if(isGLES2Compatible() || isExtensionAvailable(GLExtensions.OES_read_format)) { + final int[] glImplColorReadVals = new int[] { 0, 0 }; + gl.glGetIntegerv(GL.GL_IMPLEMENTATION_COLOR_READ_FORMAT, glImplColorReadVals, 0); + gl.glGetIntegerv(GL.GL_IMPLEMENTATION_COLOR_READ_TYPE, glImplColorReadVals, 1); + // pixelDataInternalFormat = (4 == components) ? GL.GL_RGBA : GL.GL_RGB; + pixelDataFormat = glImplColorReadVals[0]; + pixelDataType = glImplColorReadVals[1]; + } else { + // RGBA read is safe for all GL profiles + // pixelDataInternalFormat = (4 == components) ? GL.GL_RGBA : GL.GL_RGB; + pixelDataFormat=GL.GL_RGBA; + pixelDataType = GL.GL_UNSIGNED_BYTE; + } + } //---------------------------------------------------------------------- // Helpers for buffer object optimizations @@ -1599,8 +1640,10 @@ public abstract class GLContextImpl extends GLContext { @Override public final int getDefaultDrawFramebuffer() { return drawable.getDefaultDrawFramebuffer(); } @Override - public final int getDefaultReadFramebuffer() { return drawable.getDefaultReadFramebuffer(); } - + public final int getDefaultReadFramebuffer() { return drawable.getDefaultReadFramebuffer(); } + @Override + public final int getDefaultReadBuffer() { return drawable.getDefaultReadBuffer(gl); } + //--------------------------------------------------------------------------- // GL_ARB_debug_output, GL_AMD_debug_output helpers // diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java b/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java index 0f8b6b816..dc5d50cf2 100644 --- a/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java +++ b/src/jogl/classes/jogamp/opengl/GLDrawableHelper.java @@ -398,7 +398,7 @@ public class GLDrawableHelper { * </p> * <p> * Please consider using {@link #disposeAllGLEventListener(GLAutoDrawable, GLContext, boolean)} - * or {@link #disposeGL(GLAutoDrawable, GLContext)} + * or {@link #disposeGL(GLAutoDrawable, GLContext, boolean)} * for correctness, i.e. encapsulating all calls w/ makeCurrent etc. * </p> * @param autoDrawable @@ -826,12 +826,16 @@ public class GLDrawableHelper { /** * Principal helper method which runs * {@link #disposeAllGLEventListener(GLAutoDrawable, boolean) disposeAllGLEventListener(autoDrawable, false)} - * with the context made current <b>and</b> destroys the context afterwards while holding the lock. + * with the context made current. + * <p> + * If <code>destroyContext</code> is <code>true</code> the context is destroyed in the end while holding the lock.<br/> + * </p> * @param autoDrawable * @param context + * @param destroyContext destroy context in the end while holding the lock */ public final void disposeGL(final GLAutoDrawable autoDrawable, - final GLContext context) { + final GLContext context, boolean destroyContext) { // Support for recursive makeCurrent() calls as well as calling // other drawables' display() methods from within another one's GLContext lastContext = GLContext.getCurrent(); @@ -858,7 +862,11 @@ public class GLDrawableHelper { } } finally { try { - context.destroy(); + if(destroyContext) { + context.destroy(); + } else { + context.release(); + } flushGLRunnables(); } catch (Exception e) { System.err.println("Catched: "+e.getMessage()); diff --git a/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java b/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java index df7f742aa..2d062eaf1 100644 --- a/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java +++ b/src/jogl/classes/jogamp/opengl/GLDrawableImpl.java @@ -76,7 +76,7 @@ public abstract class GLDrawableImpl implements GLDrawable { @Override public final void swapBuffers() throws GLException { - if( !realized ) { + if( !realized ) { // volatile OK (locked below) return; // destroyed already } int lockRes = lockSurface(); // it's recursive, so it's ok within [makeCurrent .. release] @@ -87,17 +87,19 @@ public abstract class GLDrawableImpl implements GLDrawable { if (NativeSurface.LOCK_SURFACE_CHANGED == lockRes) { updateHandle(); } - final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable)surface.getGraphicsConfiguration().getChosenCapabilities(); - if ( caps.getDoubleBuffered() ) { - if(!surface.surfaceSwap()) { - swapBuffersImpl(true); - } - } else { - final GLContext ctx = GLContext.getCurrent(); - if(null!=ctx && ctx.getGLDrawable()==this) { - ctx.getGL().glFlush(); + if( realized ) { // volatile OK + final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable)surface.getGraphicsConfiguration().getChosenCapabilities(); + if ( caps.getDoubleBuffered() ) { + if(!surface.surfaceSwap()) { + swapBuffersImpl(true); + } + } else { + final GLContext ctx = GLContext.getCurrent(); + if(null!=ctx && ctx.getGLDrawable()==this) { + ctx.getGL().glFlush(); + } + swapBuffersImpl(false); } - swapBuffersImpl(false); } } finally { unlockSurface(); @@ -160,12 +162,11 @@ public abstract class GLDrawableImpl implements GLDrawable { } @Override - public final synchronized void setRealized(boolean realizedArg) { - if ( realized != realizedArg ) { + public final void setRealized(boolean realizedArg) { + if ( realized != realizedArg ) { // volatile: OK (locked below) if(DEBUG) { System.err.println(getThreadName() + ": setRealized: "+getClass().getSimpleName()+" "+realized+" -> "+realizedArg); } - realized = realizedArg; AbstractGraphicsDevice aDevice = surface.getGraphicsConfiguration().getScreen().getDevice(); if(realizedArg) { if(surface instanceof ProxySurface) { @@ -178,12 +179,15 @@ public abstract class GLDrawableImpl implements GLDrawable { aDevice.lock(); } try { - if(realizedArg) { - setRealizedImpl(); - updateHandle(); - } else { - destroyHandle(); - setRealizedImpl(); + if ( realized != realizedArg ) { // volatile: OK + realized = realizedArg; + if(realizedArg) { + setRealizedImpl(); + updateHandle(); + } else { + destroyHandle(); + setRealizedImpl(); + } } } finally { if(realizedArg) { @@ -199,6 +203,7 @@ public abstract class GLDrawableImpl implements GLDrawable { System.err.println(getThreadName() + ": setRealized: "+getClass().getName()+" "+this.realized+" == "+realizedArg); } } + /** * Platform specific realization of drawable */ @@ -244,10 +249,19 @@ public abstract class GLDrawableImpl implements GLDrawable { /** Callback for special implementations, allowing GLContext to fetch a custom default render framebuffer. Defaults to zero.*/ protected int getDefaultDrawFramebuffer() { return 0; } /** Callback for special implementations, allowing GLContext to fetch a custom default read framebuffer. Defaults to zero. */ - protected int getDefaultReadFramebuffer() { return 0; } + protected int getDefaultReadFramebuffer() { return 0; } + /** Callback for special implementations, allowing GLContext to fetch a custom default read buffer of current framebuffer. */ + protected int getDefaultReadBuffer(GL gl) { + if(gl.isGLES() || getChosenGLCapabilities().getDoubleBuffered()) { + // Note-1: Neither ES1 nor ES2 supports selecting the read buffer via glReadBuffer + // Note-2: ES3 only supports GL_BACK, GL_NONE or GL_COLOR_ATTACHMENT0+i + return GL.GL_BACK; + } + return GL.GL_FRONT ; + } @Override - public final synchronized boolean isRealized() { + public final boolean isRealized() { return realized; } @@ -297,6 +311,6 @@ public abstract class GLDrawableImpl implements GLDrawable { // result of calling show() on the main thread. To work around this // we prevent any JAWT or OpenGL operations from being done until // addNotify() is called on the surface. - protected boolean realized; + protected volatile boolean realized; } diff --git a/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java b/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java index 7a468a41e..b72f79868 100644 --- a/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java +++ b/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java @@ -302,6 +302,9 @@ public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable { protected final int getDefaultReadFramebuffer() { return initialized ? fbos[fboIFront].getReadFramebuffer() : 0; } @Override + protected final int getDefaultReadBuffer(GL gl) { return initialized ? fbos[fboIFront].getDefaultReadBuffer() : GL.GL_COLOR_ATTACHMENT0 ; } + + @Override protected final void setRealizedImpl() { final MutableGraphicsConfiguration msConfig = (MutableGraphicsConfiguration) surface.getGraphicsConfiguration(); if(realized) { @@ -435,6 +438,17 @@ public class GLFBODrawableImpl extends GLDrawableImpl implements GLFBODrawable { } } + @Override + public final int setNumBuffers(int bufferCount) throws GLException { + // FIXME: Implement + return bufferCount; + } + + @Override + public final int getNumBuffers() { + return bufferCount; + } + /** // TODO: Add or remove TEXTURE (only) DoubleBufferMode support @Override public final DoubleBufferMode getDoubleBufferMode() { diff --git a/src/jogl/classes/jogamp/opengl/GLOffscreenAutoDrawableImpl.java b/src/jogl/classes/jogamp/opengl/GLOffscreenAutoDrawableImpl.java index 7701f209f..59a00170d 100644 --- a/src/jogl/classes/jogamp/opengl/GLOffscreenAutoDrawableImpl.java +++ b/src/jogl/classes/jogamp/opengl/GLOffscreenAutoDrawableImpl.java @@ -95,6 +95,16 @@ public class GLOffscreenAutoDrawableImpl extends GLAutoDrawableDelegate implemen windowRepaintOp(); } + @Override + public final int setNumBuffers(int bufferCount) throws GLException { + return ((GLFBODrawableImpl)drawable).setNumBuffers(bufferCount); + } + + @Override + public final int getNumBuffers() { + return ((GLFBODrawableImpl)drawable).getNumBuffers(); + } + /** // TODO: Add or remove TEXTURE (only) DoubleBufferMode support @Override public DoubleBufferMode getDoubleBufferMode() { diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLContext.java b/src/jogl/classes/jogamp/opengl/egl/EGLContext.java index 84aeaa94a..bd8e7dee9 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLContext.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLContext.java @@ -214,7 +214,7 @@ public abstract class EGLContext extends GLContextImpl { throw new GLException("Error making context " + toHexString(contextHandle) + " current: error code " + toHexString(EGL.eglGetError())); } - setGLFunctionAvailability(true, glProfile.usesNativeGLES2() ? 2 : 1, 0, CTX_PROFILE_ES); + setGLFunctionAvailability(true, glProfile.usesNativeGLES2() ? 2 : 1, 0, CTX_PROFILE_ES, false); return true; } @@ -344,14 +344,4 @@ public abstract class EGLContext extends GLContextImpl { public ByteBuffer glAllocateMemoryNV(int arg0, float arg1, float arg2, float arg3) { throw new GLException("Should not call this"); } - - @Override - public boolean offscreenImageNeedsVerticalFlip() { - throw new GLException("Should not call this"); - } - - @Override - public int getOffscreenContextPixelDataType() { - throw new GLException("Should not call this"); - } } diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLExternalContext.java b/src/jogl/classes/jogamp/opengl/egl/EGLExternalContext.java index 84bd705db..da8fb519d 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLExternalContext.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLExternalContext.java @@ -45,7 +45,7 @@ public class EGLExternalContext extends EGLContext { public EGLExternalContext(AbstractGraphicsScreen screen) { super(null, null); GLContextShareSet.contextCreated(this); - setGLFunctionAvailability(false, 0, 0, CTX_PROFILE_ES); + setGLFunctionAvailability(false, 0, 0, CTX_PROFILE_ES, false); getGLStateTracker().setEnabled(false); // external context usage can't track state in Java } diff --git a/src/jogl/classes/jogamp/opengl/egl/EGLPbufferDrawable.java b/src/jogl/classes/jogamp/opengl/egl/EGLPbufferDrawable.java index eb7e320c8..9e5d9327b 100644 --- a/src/jogl/classes/jogamp/opengl/egl/EGLPbufferDrawable.java +++ b/src/jogl/classes/jogamp/opengl/egl/EGLPbufferDrawable.java @@ -41,7 +41,6 @@ package jogamp.opengl.egl; import javax.media.nativewindow.NativeSurface; -import javax.media.nativewindow.MutableSurface; import javax.media.opengl.GLContext; public class EGLPbufferDrawable extends EGLDrawable { diff --git a/src/jogl/classes/jogamp/opengl/glu/GLUquadricImpl.java b/src/jogl/classes/jogamp/opengl/glu/GLUquadricImpl.java index 62ff3aa09..7cd7da53e 100644 --- a/src/jogl/classes/jogamp/opengl/glu/GLUquadricImpl.java +++ b/src/jogl/classes/jogamp/opengl/glu/GLUquadricImpl.java @@ -120,6 +120,7 @@ import javax.media.opengl.glu.GLU; import javax.media.opengl.glu.GLUquadric; import com.jogamp.opengl.util.ImmModeSink; +import com.jogamp.opengl.util.glsl.ShaderState; /** * GLUquadricImpl.java @@ -140,22 +141,26 @@ public class GLUquadricImpl implements GLUquadric { private boolean immModeSinkImmediate; public int normalType; public GL gl; + public ShaderState shaderState; + public int shaderProgram; public static final boolean USE_NORM = true; public static final boolean USE_TEXT = false; private ImmModeSink immModeSink=null; - public GLUquadricImpl(GL gl, boolean useGLSL) { + public GLUquadricImpl(GL gl, boolean useGLSL, ShaderState st, int shaderProgram) { this.gl=gl; this.useGLSL = useGLSL; - drawStyle = GLU.GLU_FILL; - orientation = GLU.GLU_OUTSIDE; - textureFlag = false; - normals = GLU.GLU_SMOOTH; - normalType = gl.isGLES1()?GL.GL_BYTE:GL.GL_FLOAT; - immModeSinkImmediate=true; - immModeSinkEnabled=!gl.isGL2(); + this.drawStyle = GLU.GLU_FILL; + this.orientation = GLU.GLU_OUTSIDE; + this.textureFlag = false; + this.normals = GLU.GLU_SMOOTH; + this.normalType = gl.isGLES1()?GL.GL_BYTE:GL.GL_FLOAT; + this.immModeSinkImmediate=true; + this.immModeSinkEnabled=!gl.isGL2(); + this.shaderState = st; + this.shaderProgram = shaderProgram; replaceImmModeSink(); } @@ -191,12 +196,21 @@ public class GLUquadricImpl implements GLUquadric { ImmModeSink res = immModeSink; if(useGLSL) { - immModeSink = ImmModeSink.createGLSL (32, - 3, GL.GL_FLOAT, // vertex - 0, GL.GL_FLOAT, // color - USE_NORM?3:0, normalType, // normal - USE_TEXT?2:0, GL.GL_FLOAT, // texCoords - GL.GL_STATIC_DRAW); + if(null != shaderState) { + immModeSink = ImmModeSink.createGLSL (32, + 3, GL.GL_FLOAT, // vertex + 0, GL.GL_FLOAT, // color + USE_NORM?3:0, normalType, // normal + USE_TEXT?2:0, GL.GL_FLOAT, // texCoords + GL.GL_STATIC_DRAW, shaderState); + } else { + immModeSink = ImmModeSink.createGLSL (32, + 3, GL.GL_FLOAT, // vertex + 0, GL.GL_FLOAT, // color + USE_NORM?3:0, normalType, // normal + USE_TEXT?2:0, GL.GL_FLOAT, // texCoords + GL.GL_STATIC_DRAW, shaderProgram); + } } else { immModeSink = ImmModeSink.createFixed(32, 3, GL.GL_FLOAT, // vertex diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java index cde9841b8..838a0387d 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java @@ -164,7 +164,7 @@ public abstract class MacOSXCGLContext extends GLContextImpl pmvMatrix.glMatrixMode(PMVMatrix.GL_MODELVIEW); pmvMatrix.glLoadIdentity(); final GLUniformData pmvMatrixUniform = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf()); // P, Mv - pmvMatrixUniform.setLocation( gl.glGetUniformLocation( sp.program(), pmvMatrixUniform.getName() ) ); + pmvMatrixUniform.setLocation(gl, sp.program()); gl.glUniform(pmvMatrixUniform); sp.useProgram(gl, false); @@ -420,20 +420,6 @@ public abstract class MacOSXCGLContext extends GLContextImpl return super.isExtensionAvailable(glExtensionName); } - @Override - public int getOffscreenContextPixelDataType() { - throw new GLException("Should not call this"); - } - - public int getOffscreenContextReadBuffer() { - throw new GLException("Should not call this"); - } - - @Override - public boolean offscreenImageNeedsVerticalFlip() { - throw new GLException("Should not call this"); - } - // Support for "mode switching" as described in MacOSXCGLDrawable public void setOpenGLMode(GLBackendType mode) { if (mode == openGLMode) { diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java index 65ed5fc15..f121a2547 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXExternalCGLContext.java @@ -64,7 +64,7 @@ public class MacOSXExternalCGLContext extends MacOSXCGLContext { setOpenGLMode(isNSContext ? GLBackendType.NSOPENGL : GLBackendType.CGL ); this.contextHandle = handle; GLContextShareSet.contextCreated(this); - setGLFunctionAvailability(false, 0, 0, CTX_PROFILE_COMPAT); + setGLFunctionAvailability(false, 0, 0, CTX_PROFILE_COMPAT, false); getGLStateTracker().setEnabled(false); // external context usage can't track state in Java } diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOffscreenCGLContext.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOffscreenCGLContext.java index 7b13ce22e..f2e636796 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOffscreenCGLContext.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXOffscreenCGLContext.java @@ -49,18 +49,8 @@ public class MacOSXOffscreenCGLContext extends MacOSXPbufferCGLContext } @Override - public int getOffscreenContextPixelDataType() { - GL gl = getGL(); + public int getDefaultPixelDataType() { + final GL gl = getGL(); return gl.isGL2GL3()?GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV:GL.GL_UNSIGNED_SHORT_5_5_5_1; } - - @Override - public int getOffscreenContextReadBuffer() { - return GL.GL_FRONT; - } - - @Override - public boolean offscreenImageNeedsVerticalFlip() { - return true; - } } diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLDrawable.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLDrawable.java index 668e463a2..ddff43031 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLDrawable.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXPbufferCGLDrawable.java @@ -131,7 +131,7 @@ public class MacOSXPbufferCGLDrawable extends MacOSXCGLDrawable { MacOSXCGLDrawableFactory.SharedResource sr = ((MacOSXCGLDrawableFactory)factory).getOrCreateOSXSharedResource(config.getScreen().getDevice()); if (DEBUG) { - System.out.println("Pbuffer config: " + config); + System.out.println(getThreadName()+": Pbuffer config: " + config); if(null != sr) { System.out.println("Pbuffer NPOT Texure avail: "+sr.isNPOTTextureAvailable()); System.out.println("Pbuffer RECT Texture avail: "+sr.isRECTTextureAvailable()); diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/awt/MacOSXJava2DCGLContext.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/awt/MacOSXJava2DCGLContext.java index f41400d83..bd183b900 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/awt/MacOSXJava2DCGLContext.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/awt/MacOSXJava2DCGLContext.java @@ -97,7 +97,7 @@ public class MacOSXJava2DCGLContext extends MacOSXCGLContext implements Java2DGL } return false; } - setGLFunctionAvailability(true, 0, 0, CTX_PROFILE_COMPAT); // use GL_VERSION + setGLFunctionAvailability(true, 0, 0, CTX_PROFILE_COMPAT, false); // use GL_VERSION contextHandle = ctx; return true; } diff --git a/src/jogl/classes/jogamp/opengl/util/GLArrayHandler.java b/src/jogl/classes/jogamp/opengl/util/GLArrayHandler.java index a6314a216..1a4ca345b 100644 --- a/src/jogl/classes/jogamp/opengl/util/GLArrayHandler.java +++ b/src/jogl/classes/jogamp/opengl/util/GLArrayHandler.java @@ -31,9 +31,9 @@ package jogamp.opengl.util; import javax.media.opengl.*; /** - * Handles consistency of buffer data and array state. - * Implementations shall consider buffer types (VBO, ..), interleaved, etc. - * They also need to consider array state types, i.e. fixed function or GLSL. + * Handles consistency of buffer data and array state.<br/> + * Implementations shall consider buffer types (VBO, ..), interleaved, etc.<br/> + * They also need to consider array state types, i.e. fixed function or GLSL.<br/> */ public interface GLArrayHandler { diff --git a/src/jogl/classes/jogamp/opengl/util/glsl/GLSLArrayHandler.java b/src/jogl/classes/jogamp/opengl/util/glsl/GLSLArrayHandler.java index 79bed90c9..3c468f358 100644 --- a/src/jogl/classes/jogamp/opengl/util/glsl/GLSLArrayHandler.java +++ b/src/jogl/classes/jogamp/opengl/util/glsl/GLSLArrayHandler.java @@ -44,8 +44,8 @@ import com.jogamp.opengl.util.glsl.ShaderState; * Used for 1:1 GLSL arrays, i.e. where the buffer data * represents this array only. */ -public class GLSLArrayHandler extends GLVBOArrayHandler implements GLArrayHandler { - +public class GLSLArrayHandler extends GLVBOArrayHandler implements GLArrayHandler { + public GLSLArrayHandler(GLArrayDataEditable ad) { super(ad); } @@ -60,8 +60,14 @@ public class GLSLArrayHandler extends GLVBOArrayHandler implements GLArrayHandle public final void enableState(GL gl, boolean enable, Object ext) { final GL2ES2 glsl = gl.getGL2ES2(); - final ShaderState st = (ShaderState) ext; - + if( null != ext ) { + enableShaderState(glsl, enable, (ShaderState)ext); + } else { + enableSimple(glsl, enable); + } + } + + private final void enableShaderState(GL2ES2 glsl, boolean enable, ShaderState st) { if(enable) { /* * This would be the non optimized code path: @@ -108,5 +114,57 @@ public class GLSLArrayHandler extends GLVBOArrayHandler implements GLArrayHandle st.disableVertexAttribArray(glsl, ad); } } + + private final void enableSimple(GL2ES2 glsl, boolean enable) { + final int location = ad.getLocation(); + if( 0 > location ) { + return; + } + if(enable) { + /* + * This would be the non optimized code path: + * + if(ad.isVBO()) { + glsl.glBindBuffer(ad.getVBOTarget(), ad.getVBOName()); + if(!ad.isVBOWritten()) { + if(null!=buffer) { + glsl.glBufferData(ad.getVBOTarget(), ad.getSizeInBytes(), buffer, ad.getVBOUsage()); + } + ad.setVBOWritten(true); + } + } + st.vertexAttribPointer(glsl, ad); + */ + final Buffer buffer = ad.getBuffer(); + if(ad.isVBO()) { + // bind and refresh the VBO / vertex-attr only if necessary + if(!ad.isVBOWritten()) { + glsl.glBindBuffer(ad.getVBOTarget(), ad.getVBOName()); + if(null!=buffer) { + glsl.glBufferData(ad.getVBOTarget(), ad.getSizeInBytes(), buffer, ad.getVBOUsage()); + } + ad.setVBOWritten(true); + glsl.glVertexAttribPointer(ad); + glsl.glBindBuffer(ad.getVBOTarget(), 0); + } else { + // didn't experience a performance hit on this query .. + // (using ShaderState's location query above to validate the location) + final int[] qi = new int[1]; + glsl.glGetVertexAttribiv(location, GL2ES2.GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, qi, 0); + if(ad.getVBOName() != qi[0]) { + glsl.glBindBuffer(ad.getVBOTarget(), ad.getVBOName()); + glsl.glVertexAttribPointer(ad); + glsl.glBindBuffer(ad.getVBOTarget(), 0); + } + } + } else if(null!=buffer) { + glsl.glVertexAttribPointer(ad); + } + + glsl.glEnableVertexAttribArray(location); + } else { + glsl.glDisableVertexAttribArray(location); + } + } } diff --git a/src/jogl/classes/jogamp/opengl/util/glsl/GLSLArrayHandlerFlat.java b/src/jogl/classes/jogamp/opengl/util/glsl/GLSLArrayHandlerFlat.java index c5beb7dd0..855406db3 100644 --- a/src/jogl/classes/jogamp/opengl/util/glsl/GLSLArrayHandlerFlat.java +++ b/src/jogl/classes/jogamp/opengl/util/glsl/GLSLArrayHandlerFlat.java @@ -53,9 +53,13 @@ public class GLSLArrayHandlerFlat implements GLArrayHandlerFlat { public final void syncData(GL gl, Object ext) { final GL2ES2 glsl = gl.getGL2ES2(); - final ShaderState st = (ShaderState) ext; - - st.vertexAttribPointer(glsl, ad); + if( null != ext ) { + ((ShaderState)ext).vertexAttribPointer(glsl, ad); + } else { + if( 0 <= ad.getLocation() ) { + glsl.glVertexAttribPointer(ad); + } + } /** * Due to probable application VBO switching, this might not make any sense .. * @@ -75,13 +79,22 @@ public class GLSLArrayHandlerFlat implements GLArrayHandlerFlat { public final void enableState(GL gl, boolean enable, Object ext) { final GL2ES2 glsl = gl.getGL2ES2(); - final ShaderState st = (ShaderState) ext; - - if(enable) { - st.enableVertexAttribArray(glsl, ad); + if( null != ext ) { + final ShaderState st = (ShaderState)ext; + if(enable) { + st.enableVertexAttribArray(glsl, ad); + } else { + st.disableVertexAttribArray(glsl, ad); + } } else { - st.disableVertexAttribArray(glsl, ad); + final int location = ad.getLocation(); + if( 0 <= location ) { + if(enable) { + glsl.glEnableVertexAttribArray(location); + } else { + glsl.glDisableVertexAttribArray(location); + } + } } } } - diff --git a/src/jogl/classes/jogamp/opengl/util/glsl/GLSLTextureRaster.java b/src/jogl/classes/jogamp/opengl/util/glsl/GLSLTextureRaster.java new file mode 100644 index 000000000..20c251635 --- /dev/null +++ b/src/jogl/classes/jogamp/opengl/util/glsl/GLSLTextureRaster.java @@ -0,0 +1,195 @@ +/** + * Copyright 2012 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 jogamp.opengl.util.glsl; + +import java.nio.FloatBuffer; + +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 javax.media.opengl.GL; +import javax.media.opengl.GL2ES2; +import javax.media.opengl.GLArrayData; +import javax.media.opengl.GLException; +import javax.media.opengl.GLUniformData; +import javax.media.opengl.fixedfunc.GLMatrixFunc; + +public class GLSLTextureRaster { + private final boolean textureVertFlipped; + private final int textureUnit; + + private ShaderProgram sp; + private PMVMatrix pmvMatrix; + private GLUniformData pmvMatrixUniform; + private GLUniformData activeTexUniform; + private GLArrayDataServer interleavedVBO; + + public GLSLTextureRaster(int textureUnit, boolean textureVertFlipped) { + this.textureVertFlipped = textureVertFlipped; + this.textureUnit = textureUnit; + } + + public int getTextureUnit() { return textureUnit; } + + static final String shaderBasename = "texture01_xxx"; + static final String shaderSrcPath = "../../shader"; + static final String shaderBinPath = "../../shader/bin"; + + public void init(GL2ES2 gl) { + // Create & Compile the shader objects + final ShaderCode rsVp = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, this.getClass(), + shaderSrcPath, shaderBinPath, shaderBasename, true); + final ShaderCode rsFp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, this.getClass(), + shaderSrcPath, shaderBinPath, shaderBasename, true); + rsVp.defaultShaderCustomization(gl, true, ShaderCode.es2_default_precision_vp); + rsFp.defaultShaderCustomization(gl, true, ShaderCode.es2_default_precision_fp); + + // Create & Link the shader program + sp = new ShaderProgram(); + sp.add(rsVp); + sp.add(rsFp); + if(!sp.link(gl, System.err)) { + throw new GLException("Couldn't link program: "+sp); + } + sp.useProgram(gl, true); + + // setup mgl_PMVMatrix + pmvMatrix = new PMVMatrix(); + pmvMatrix.glMatrixMode(PMVMatrix.GL_PROJECTION); + pmvMatrix.glLoadIdentity(); + pmvMatrix.glMatrixMode(PMVMatrix.GL_MODELVIEW); + pmvMatrix.glLoadIdentity(); + pmvMatrixUniform = new GLUniformData("mgl_PMVMatrix", 4, 4, pmvMatrix.glGetPMvMatrixf()); // P, Mv + if( pmvMatrixUniform.setLocation(gl, sp.program()) < 0 ) { + throw new GLException("Couldn't locate "+pmvMatrixUniform+" in shader: "+sp); + } + gl.glUniform(pmvMatrixUniform); + + activeTexUniform = new GLUniformData("mgl_Texture0", textureUnit); + if( activeTexUniform.setLocation(gl, sp.program()) < 0 ) { + throw new GLException("Couldn't locate "+activeTexUniform+" in shader: "+sp); + } + gl.glUniform(activeTexUniform); + + final float[] s_quadTexCoords; + if( textureVertFlipped ) { + s_quadTexCoords = s_quadTexCoords01; + } else { + s_quadTexCoords = s_quadTexCoords00; + } + + interleavedVBO = GLArrayDataServer.createGLSLInterleaved(3+2, GL.GL_FLOAT, false, 2*4, GL.GL_STATIC_DRAW); + { + final GLArrayData vArrayData = interleavedVBO.addGLSLSubArray("mgl_Vertex", 3, GL.GL_ARRAY_BUFFER); + if( vArrayData.setLocation(gl, sp.program()) < 0 ) { + throw new GLException("Couldn't locate "+vArrayData+" in shader: "+sp); + } + final GLArrayData tArrayData = interleavedVBO.addGLSLSubArray("mgl_MultiTexCoord", 2, GL.GL_ARRAY_BUFFER); + if( tArrayData.setLocation(gl, sp.program()) < 0 ) { + throw new GLException("Couldn't locate "+tArrayData+" in shader: "+sp); + } + final FloatBuffer ib = (FloatBuffer)interleavedVBO.getBuffer(); + for(int i=0; i<4; i++) { + ib.put(s_quadVertices, i*3, 3); + ib.put(s_quadTexCoords, i*2, 2); + } + } + interleavedVBO.seal(gl, true); + interleavedVBO.enableBuffer(gl, false); + + sp.useProgram(gl, false); + } + + public void reshape(GL2ES2 gl, int x, int y, int width, int height) { + if(null != sp) { + 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(); + + sp.useProgram(gl, true); + gl.glUniform(pmvMatrixUniform); + sp.useProgram(gl, false); + } + } + + public void dispose(GL2ES2 gl) { + if(null != pmvMatrixUniform) { + pmvMatrixUniform = null; + } + if(null != pmvMatrix) { + pmvMatrix.destroy(); + pmvMatrix=null; + } + if(null != interleavedVBO) { + interleavedVBO.destroy(gl); + interleavedVBO=null; + } + if(null != sp) { + sp.destroy(gl); + sp=null; + } + } + + public void display(GL2ES2 gl) { + if(null != sp) { + sp.useProgram(gl, true); + interleavedVBO.enableBuffer(gl, true); + + gl.glDrawArrays(GL.GL_TRIANGLE_STRIP, 0, 4); + + interleavedVBO.enableBuffer(gl, false); + sp.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_quadTexCoords00 = { + 0f, 0f, // LB + 1f, 0f, // RB + 0f, 1f, // LT + 1f, 1f // RT + }; + private static final float[] s_quadTexCoords01 = { + 0f, 1f, // LB + 1f, 1f, // RB + 0f, 0f, // LT + 1f, 0f // RT + }; +} + diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsBitmapWGLContext.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsBitmapWGLContext.java index 51341a098..c8aac7f7b 100644 --- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsBitmapWGLContext.java +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsBitmapWGLContext.java @@ -49,18 +49,12 @@ public class WindowsBitmapWGLContext extends WindowsWGLContext { } @Override - public int getOffscreenContextPixelDataType() { + public int getDefaultPixelDataType() { return GL.GL_UNSIGNED_BYTE; } @Override - public int getOffscreenContextReadBuffer() { - // On Windows these contexts are always single-buffered - return GL.GL_FRONT; - } - - @Override - public boolean offscreenImageNeedsVerticalFlip() { + public boolean isGLOrientationFlippedVertical() { // We can take care of this in the DIB creation (see below) return false; } diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsBitmapWGLDrawable.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsBitmapWGLDrawable.java index cf6f43b1c..6993191f6 100644 --- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsBitmapWGLDrawable.java +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsBitmapWGLDrawable.java @@ -79,7 +79,7 @@ public class WindowsBitmapWGLDrawable extends WindowsWGLDrawable { int werr; NativeSurface ns = getNativeSurface(); if(DEBUG) { - System.err.println("WindowsBitmapWGLDrawable (1): "+ns); + System.err.println(getThreadName()+": WindowsBitmapWGLDrawable (1): "+ns); } WindowsWGLGraphicsConfiguration config = (WindowsWGLGraphicsConfiguration)ns.getGraphicsConfiguration(); GLCapabilitiesImmutable capabilities = (GLCapabilitiesImmutable)config.getRequestedCapabilities(); @@ -141,7 +141,7 @@ public class WindowsBitmapWGLDrawable extends WindowsWGLDrawable { } ((MutableSurface)ns).setSurfaceHandle(hdc); if(DEBUG) { - System.err.println("WindowsBitmapWGLDrawable (2): "+ns); + System.err.println(getThreadName()+": WindowsBitmapWGLDrawable (2): "+ns); } if ((origbitmap = GDI.SelectObject(hdc, hbitmap)) == 0) { diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLContext.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLContext.java index f6cc2956d..84b29a09f 100644 --- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLContext.java +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsExternalWGLContext.java @@ -65,7 +65,7 @@ public class WindowsExternalWGLContext extends WindowsWGLContext { System.err.println(getThreadName() + ": Created external OpenGL context " + toHexString(ctx) + " for " + this); } GLContextShareSet.contextCreated(this); - setGLFunctionAvailability(false, 0, 0, CTX_PROFILE_COMPAT); // use GL_VERSION + setGLFunctionAvailability(false, 0, 0, CTX_PROFILE_COMPAT, false); // use GL_VERSION getGLStateTracker().setEnabled(false); // external context usage can't track state in Java } diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLDrawable.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLDrawable.java index 7a512c85f..6c7893c3e 100644 --- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLDrawable.java +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsPbufferWGLDrawable.java @@ -131,7 +131,7 @@ public class WindowsPbufferWGLDrawable extends WindowsWGLDrawable { WGLExt wglExt = ((WindowsWGLContext)sharedResource.getContext()).getWGLExt(); if (DEBUG) { - System.out.println("Pbuffer config: " + config); + System.out.println(getThreadName()+": Pbuffer config: " + config); } final int winattrPbuffer = GLGraphicsConfigurationUtil.getExclusiveWinAttributeBits(false /* onscreen */, false /* fbo */, true /* pbuffer */, false /* bitmap */); @@ -146,8 +146,8 @@ public class WindowsPbufferWGLDrawable extends WindowsWGLDrawable { final AbstractGraphicsDevice device = config.getScreen().getDevice(); if (DEBUG) { - System.out.println("Pbuffer parentHdc = " + toHexString(sharedHdc)); - System.out.println("Pbuffer chosenCaps: " + chosenCaps); + System.out.println(getThreadName()+": Pbuffer parentHdc = " + toHexString(sharedHdc)); + System.out.println(getThreadName()+": Pbuffer chosenCaps: " + chosenCaps); } if(!WindowsWGLGraphicsConfiguration.GLCapabilities2AttribList(chosenCaps, diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java index 57f16522c..a654cdd04 100644 --- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLContext.java @@ -308,7 +308,7 @@ public class WindowsWGLContext extends GLContextImpl { if (!WGL.wglMakeCurrent(drawable.getHandle(), temp_ctx)) { throw new GLException("Error making temp context current: 0x" + toHexString(temp_ctx) + ", werr: "+GDI.GetLastError()); } - setGLFunctionAvailability(true, 0, 0, CTX_PROFILE_COMPAT); // use GL_VERSION + setGLFunctionAvailability(true, 0, 0, CTX_PROFILE_COMPAT, false); // use GL_VERSION WGL.wglMakeCurrent(0, 0); // release temp context if( !createContextARBTried) { @@ -538,20 +538,6 @@ public class WindowsWGLContext extends GLContextImpl { } @Override - public int getOffscreenContextPixelDataType() { - throw new GLException("Should not call this"); - } - - public int getOffscreenContextReadBuffer() { - throw new GLException("Should not call this"); - } - - @Override - public boolean offscreenImageNeedsVerticalFlip() { - throw new GLException("Should not call this"); - } - - @Override public void bindPbufferToTexture() { throw new GLException("Should not call this"); } diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawable.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawable.java index 3b3f0c123..8b8cb2052 100644 --- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawable.java +++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawable.java @@ -67,7 +67,7 @@ public abstract class WindowsWGLDrawable extends GLDrawableImpl { WindowsWGLGraphicsConfiguration config = (WindowsWGLGraphicsConfiguration)ns.getGraphicsConfiguration(); config.updateGraphicsConfiguration(getFactory(), ns, null); if (DEBUG) { - System.err.println("WindowsWGLDrawable.setRealized(true): "+config); + System.err.println(getThreadName()+": WindowsWGLDrawable.setRealized(true): "+config); } } } diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXContext.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXContext.java index bebb4e68a..12fa5786a 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXContext.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11ExternalGLXContext.java @@ -64,7 +64,7 @@ public class X11ExternalGLXContext extends X11GLXContext { super(drawable, null); this.contextHandle = ctx; GLContextShareSet.contextCreated(this); - setGLFunctionAvailability(false, 0, 0, CTX_PROFILE_COMPAT); + setGLFunctionAvailability(false, 0, 0, CTX_PROFILE_COMPAT, false); getGLStateTracker().setEnabled(false); // external context usage can't track state in Java } diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java index 76e0bc15c..5b0d32353 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXContext.java @@ -308,7 +308,7 @@ public abstract class X11GLXContext extends GLContextImpl { if (!glXMakeContextCurrent(display, drawable.getHandle(), drawableRead.getHandle(), contextHandle)) { throw new GLException(getThreadName()+": Error making temp context(0) current: display "+toHexString(display)+", context "+toHexString(contextHandle)+", drawable "+drawable); } - setGLFunctionAvailability(true, 0, 0, CTX_PROFILE_COMPAT); // use GL_VERSION + setGLFunctionAvailability(true, 0, 0, CTX_PROFILE_COMPAT, false); // use GL_VERSION isDirect = GLX.glXIsDirect(display, contextHandle); if (DEBUG) { System.err.println(getThreadName() + ": createContextImpl: OK (old-1) share "+share+", direct "+isDirect+"/"+direct); @@ -338,7 +338,7 @@ public abstract class X11GLXContext extends GLContextImpl { if (!glXMakeContextCurrent(display, drawable.getHandle(), drawableRead.getHandle(), temp_ctx)) { throw new GLException(getThreadName()+": Error making temp context(1) current: display "+toHexString(display)+", context "+toHexString(temp_ctx)+", drawable "+drawable); } - setGLFunctionAvailability(true, 0, 0, CTX_PROFILE_COMPAT); // use GL_VERSION + setGLFunctionAvailability(true, 0, 0, CTX_PROFILE_COMPAT, false); // use GL_VERSION glXMakeContextCurrent(display, 0, 0, 0); // release temp context if( !createContextARBTried ) { // is*Available calls are valid since setGLFunctionAvailability(..) was called @@ -619,20 +619,6 @@ public abstract class X11GLXContext extends GLContextImpl { } @Override - public int getOffscreenContextPixelDataType() { - throw new GLException("Should not call this"); - } - - public int getOffscreenContextReadBuffer() { - throw new GLException("Should not call this"); - } - - @Override - public boolean offscreenImageNeedsVerticalFlip() { - throw new GLException("Should not call this"); - } - - @Override public void bindPbufferToTexture() { throw new GLException("Should not call this"); } diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawable.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawable.java index 8c642777d..155c00c4c 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawable.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11GLXDrawable.java @@ -63,7 +63,7 @@ public abstract class X11GLXDrawable extends GLDrawableImpl { config.updateGraphicsConfiguration(); if (DEBUG) { - System.err.println("X11GLXDrawable.setRealized(true): "+config); + System.err.println(getThreadName()+": X11GLXDrawable.setRealized(true): "+config); } } } diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11PbufferGLXDrawable.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11PbufferGLXDrawable.java index 28db2ade9..d2d0c6789 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11PbufferGLXDrawable.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11PbufferGLXDrawable.java @@ -54,6 +54,7 @@ import javax.media.opengl.GLPbuffer; import com.jogamp.common.nio.Buffers; +@SuppressWarnings("deprecation") public class X11PbufferGLXDrawable extends X11GLXDrawable { protected X11PbufferGLXDrawable(GLDrawableFactory factory, NativeSurface target) { /* GLCapabilities caps, @@ -82,6 +83,9 @@ public class X11PbufferGLXDrawable extends X11GLXDrawable { GLX.glXDestroyPbuffer(ns.getDisplayHandle(), ns.getSurfaceHandle()); } ((MutableSurface)ns).setSurfaceHandle(0); + if (DEBUG) { + System.err.println(getThreadName()+": Destroyed pbuffer " + this); + } } private void createPbuffer() { @@ -92,7 +96,7 @@ public class X11PbufferGLXDrawable extends X11GLXDrawable { final long display = aDevice.getHandle(); if (DEBUG) { - System.out.println("Pbuffer config: " + config); + System.out.println(getThreadName()+": Pbuffer config: " + config); } if (display==0) { @@ -131,7 +135,7 @@ public class X11PbufferGLXDrawable extends X11GLXDrawable { ms.setSurfaceHandle(pbuffer); if (DEBUG) { - System.err.println("Created pbuffer " + this); + System.err.println(getThreadName()+": Created pbuffer " + this); } } diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11PixmapGLXContext.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11PixmapGLXContext.java index 96d0f18dc..1cfb7e427 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11PixmapGLXContext.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11PixmapGLXContext.java @@ -50,24 +50,9 @@ public class X11PixmapGLXContext extends X11GLXContext { } @Override - public int getOffscreenContextPixelDataType() { + public int getDefaultPixelDataType() { GL gl = getGL(); return gl.isGL2GL3()?GL2GL3.GL_UNSIGNED_INT_8_8_8_8_REV:GL.GL_UNSIGNED_SHORT_5_5_5_1; } - @Override - public int getOffscreenContextReadBuffer() { - GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable)drawable.getNativeSurface().getGraphicsConfiguration().getChosenCapabilities(); - if (caps.getDoubleBuffered()) { - return GL.GL_BACK; - } - return GL.GL_FRONT; - } - - @Override - public boolean offscreenImageNeedsVerticalFlip() { - // There doesn't seem to be a way to do this in the construction - // of the Pixmap or GLXPixmap - return true; - } } diff --git a/src/jogl/classes/jogamp/opengl/x11/glx/X11PixmapGLXDrawable.java b/src/jogl/classes/jogamp/opengl/x11/glx/X11PixmapGLXDrawable.java index 04627724c..ab25e4ef4 100644 --- a/src/jogl/classes/jogamp/opengl/x11/glx/X11PixmapGLXDrawable.java +++ b/src/jogl/classes/jogamp/opengl/x11/glx/X11PixmapGLXDrawable.java @@ -95,7 +95,7 @@ public class X11PixmapGLXDrawable extends X11GLXDrawable { } ((MutableSurface)ns).setSurfaceHandle(drawable); if (DEBUG) { - System.err.println("Created pixmap " + toHexString(pixmap) + + System.err.println(getThreadName()+": Created pixmap " + toHexString(pixmap) + ", GLXPixmap " + toHexString(drawable) + ", display " + toHexString(dpy)); } @@ -109,7 +109,7 @@ public class X11PixmapGLXDrawable extends X11GLXDrawable { long drawable = ns.getSurfaceHandle(); if (DEBUG) { - System.err.println("Destroying pixmap " + toHexString(pixmap) + + System.err.println(getThreadName()+": Destroying pixmap " + toHexString(pixmap) + ", GLXPixmap " + toHexString(drawable) + ", display " + toHexString(display)); } |