diff options
author | Sven Göthel <[email protected]> | 2024-01-14 04:19:10 +0100 |
---|---|---|
committer | Sven Göthel <[email protected]> | 2024-01-14 04:19:10 +0100 |
commit | 6363ae5fb6975a6f2e7c1093ce81f25b699e3e61 (patch) | |
tree | e19fb3347ea0562972c87b6b6fbbf771933646ae /src/jogl/classes/com/jogamp | |
parent | 3062f72c7b83cef71d8e6d471846449aba66d861 (diff) |
Graph/GraphUI: Revise Graph Region ShaderMapping, fix AABBox-Clipping for Pass2-AA, revise Pass2 AA Quality parameter ..
Misc:
- Graph VBORegion2PVBAAES2: Drop unused FBO rescale
- Move MIN/MAX QUALITY/SAMPLE from GraphUI Scene -> Graph Region
+++
Quality -> Pass2 AA Quality
- Drop quality field in region
- Pass quality to GLRegion.draw(..) similar to sampleCount
for dynamic shader and switch
- TODO: Pass quality parameter in TextRegionUtil's functions
Fix RegionRenderer Shader Mapping
- Use ShaderKey class to properly implement the hash value and equals method
- For this, TextureSequence.getTextureFragmentShaderHashID() has been added
to provide actual shader-snippet for the equals function
- All required criterias are included in the hash value and equals method
Fix AABBox Clipping for Pass-2 AA
- Clipping in pass2-AA must happen in pass2 on actual gcu_PMVMatrix01 (not ortho)
+++
GraphUI GraphShape
- Rename: [get,set]{->AA}Quality()
GraphUI Scene
- Rename: mark{All->}ShapesDirty(), set{AllShapes->}Sharpness(), set{AllShapes->AA}Quality()
- Fix setSampleCount(..), i.e. markStatesDirty() not markShapesDirty()
- Fix setAAQuality(), markShapesDirty() and markStatesDirty(): Use forAll(..) to traverse through all shapes and groups.
GraphUI Group
- Add setFixedSize()
- Add setClipOnBox()
- Document setRelayoutOnDirtyShapes(), isShapeDirty()
Diffstat (limited to 'src/jogl/classes/com/jogamp')
7 files changed, 208 insertions, 99 deletions
diff --git a/src/jogl/classes/com/jogamp/graph/curve/Region.java b/src/jogl/classes/com/jogamp/graph/curve/Region.java index 5b0f0a53b..f70dacbbc 100644 --- a/src/jogl/classes/com/jogamp/graph/curve/Region.java +++ b/src/jogl/classes/com/jogamp/graph/curve/Region.java @@ -72,6 +72,9 @@ public abstract class Region { * <p> * One pass `norm` rendering either using no AA or underlying full-screen AA (fsaa). * </p> + * <p> + * This mode-bit is a shader-key. + * </p> */ public static final int NORM_RENDERING_BIT = 0; @@ -79,9 +82,15 @@ public abstract class Region { * Rendering-Mode bit for {@link #getRenderModes() Region} * <p> * MSAA based Anti-Aliasing, a two pass region rendering, slower and more - * resource hungry (FBO), but providing fast MSAA in case + * resource hungry (FBO with sample buffer), but providing fast MSAA in case * the whole scene is not rendered with MSAA. * </p> + * <p> + * In case sample count is 1, no FBO sample buffer is used but a simple bilinear texture filter. + * </p> + * <p> + * This mode-bit is a shader-key. + * </p> */ public static final int MSAA_RENDERING_BIT = 1 << 0; @@ -92,6 +101,16 @@ public abstract class Region { * resource hungry (FBO), but AA is perfect. Otherwise the default fast one * pass MSAA region rendering is being used. * </p> + * <p> + * In case sample count is 1, no FBO supersampling is performed but a simple bilinear texture filter used. + * </p> + * <p> + * Depending on AA-quality, {@link #MAX_AA_QUALITY} denotes full 4x billinear filtering per sample + * and {@code 0} denotes 1x flipquad filtering per sample. + * </p> + * <p> + * This mode-bit is a shader-key. + * </p> */ public static final int VBAA_RENDERING_BIT = 1 << 1; @@ -105,6 +124,9 @@ public abstract class Region { * Otherwise the default weight 1.0 for uniform curve region rendering is * being applied. * </p> + * <p> + * This mode-bit is a shader-key. + * </p> */ public static final int VARWEIGHT_RENDERING_BIT = 1 << 8; @@ -115,6 +137,9 @@ public abstract class Region { * otherwise {@link com.jogamp.graph.curve.opengl.RegionRenderer#setColorStatic(com.jogamp.opengl.GL2ES2, float, float, float, float) static color} * can being used for a monotonic color. * </p> + * <p> + * This mode-bit is a shader-key. + * </p> * @see #getRenderModes() * @see #hasColorChannel() * @see #addOutlineShape(OutlineShape, AffineTransform, float[]) @@ -127,6 +152,9 @@ public abstract class Region { * <p> * If set, a color texture is used to determine the color. * </p> + * <p> + * This mode-bit is a shader-key. + * </p> * @see #COLORTEXTURE_LETTERBOX_RENDERING_BIT */ public static final int COLORTEXTURE_RENDERING_BIT = 1 << 10; @@ -137,13 +165,23 @@ public abstract class Region { * If set, a used {@link #COLORTEXTURE_RENDERING_BIT} color texture is added letter-box space to match aspect-ratio, otherwise it will be zoomed in. * </p> * <p> + * This mode-bit is not a shader-key. + * </p> + * <p> * Note that {@link #COLORTEXTURE_RENDERING_BIT} must also be set to even enable color texture. * </p> */ public static final int COLORTEXTURE_LETTERBOX_RENDERING_BIT = 1 << 11; - /** Default maximum {@link #getQuality() quality}, {@value}. */ - public static final int MAX_QUALITY = 1; + /** Minimum pass2 AA-quality rendering {@value} (default) for Graph Region AA {@link Region#getRenderModes() render-modes}: {@link #VBAA_RENDERING_BIT}. */ + public static final int MIN_AA_QUALITY = 0; + /** Maximum pass2 AA-quality rendering {@value} (default) for Graph Region AA {@link Region#getRenderModes() render-modes}: {@link #VBAA_RENDERING_BIT}. */ + public static final int MAX_AA_QUALITY = 1; + + /** Minimum pass2 AA sample count {@value} for Graph Region AA {@link Region#getRenderModes() render-modes}: {@link Region#VBAA_RENDERING_BIT} or {@link Region#MSAA_RENDERING_BIT}. */ + public static final int MIN_AA_SAMPLE_COUNT = 1; + /** Maximum pass2 AA sample count {@value} for Graph Region AA {@link Region#getRenderModes() render-modes}: {@link Region#VBAA_RENDERING_BIT} or {@link Region#MSAA_RENDERING_BIT}. */ + public static final int MAX_AA_SAMPLE_COUNT = 8; public static final int DEFAULT_TWO_PASS_TEXTURE_UNIT = 0; @@ -153,7 +191,6 @@ public abstract class Region { private final int renderModes; private final boolean use_int32_idx; private final int max_indices; - private int quality; private int dirty = DIRTY_SHAPE | DIRTY_STATE; private int numVertices = 0; protected final AABBox box = new AABBox(); @@ -265,7 +302,6 @@ public abstract class Region { } else { this.max_indices = GL_UINT16_MAX; } - this.quality = MAX_QUALITY; } /** Print implementation buffer stats like detailed and total size and capacity in bytes etc */ @@ -316,12 +352,6 @@ public abstract class Region { */ public final int getRenderModes() { return renderModes; } - /** See {@link #MAX_QUALITY} */ - public final int getQuality() { return quality; } - - /** See {@link #MAX_QUALITY} */ - public final void setQuality(final int q) { quality=q; } - protected final void clearImpl() { dirty = DIRTY_SHAPE | DIRTY_STATE; numVertices = 0; @@ -760,7 +790,7 @@ public abstract class Region { * Mark this region's shape dirty, * i.e. its vertices, triangles, lines and/or color-texture coordinates changed. * <p> - * The data will be re-uploaded to the GPU at next {@link GLRegion#draw(com.jogamp.opengl.GL2ES2, com.jogamp.graph.curve.opengl.RegionRenderer, int[]) draw(..)}. + * The data will be re-uploaded to the GPU at next {@link GLRegion#draw(com.jogamp.opengl.GL2ES2, com.jogamp.graph.curve.opengl.RegionRenderer, int, int[]) draw(..)}. * </p> * <p> * In 2-pass mode, this implies updating the FBO itself as well. @@ -798,6 +828,6 @@ public abstract class Region { @Override public String toString() { - return "Region[0x"+Integer.toHexString(hashCode())+", "+getRenderModeString(this.renderModes)+", q "+quality+", dirty "+dirty+", vertices "+numVertices+", box "+box+"]"; + return "Region[0x"+Integer.toHexString(hashCode())+", "+getRenderModeString(this.renderModes)+", dirty "+dirty+", vertices "+numVertices+", box "+box+"]"; } }
\ No newline at end of file diff --git a/src/jogl/classes/com/jogamp/graph/curve/opengl/GLRegion.java b/src/jogl/classes/com/jogamp/graph/curve/opengl/GLRegion.java index af8a54177..5849a8581 100644 --- a/src/jogl/classes/com/jogamp/graph/curve/opengl/GLRegion.java +++ b/src/jogl/classes/com/jogamp/graph/curve/opengl/GLRegion.java @@ -511,14 +511,15 @@ public abstract class GLRegion extends Region { * </p>
* @param gl current {@link GL2ES2}.
* @param renderer the {@link RegionRenderer} to be used
- * @param sampleCount desired multisampling sample count for vbaa- or msaa-rendering.
+ * @param pass2Quality pass2 AA-quality selector in the range [{@link Region#MIN_AA_QUALITY}..{@link Region#MAX_AA_QUALITY}] for Graph Region AA {@link Region#getRenderModes() render-modes}: {@link Region#VBAA_RENDERING_BIT}
+ * @param sampleCount desired pass2 AA-multisampling sample count in the typical range [{@link Region#MIN_AA_SAMPLE_COUNT}..{@link Region#MAX_AA_SAMPLE_COUNT}] for Graph Region AA {@link Region#getRenderModes() render-modes}: {@link Region#VBAA_RENDERING_BIT}, {@link Region#MSAA_RENDERING_BIT}
* Use -1 for glSelect mode, pass1 w/o any color texture nor channel, use static select color only.
* The actual used scample-count is written back when msaa-rendering is enabled, otherwise the store is untouched.
* @see RegionRenderer#enable(GL2ES2, boolean)
*/
- public final void draw(final GL2ES2 gl, final RegionRenderer renderer, final int[/*1*/] sampleCount) {
+ public final void draw(final GL2ES2 gl, final RegionRenderer renderer, final int pass2Quality, final int[/*1*/] sampleCount) {
final int curRenderModes;
- if( null == sampleCount || 0 == sampleCount[0] ) {
+ if( 0 == sampleCount[0] ) {
// no sampling, reduce to pass1
curRenderModes = getRenderModes() & ~( VBAA_RENDERING_BIT | MSAA_RENDERING_BIT );
} else if( 0 > sampleCount[0] ) {
@@ -528,6 +529,9 @@ public abstract class GLRegion extends Region { // normal 2-pass sampling
curRenderModes = getRenderModes();
}
+ // System.err.println("XXX.0 "+Region.getRenderModeString(getRenderModes(), sampleCount[0], 0)+": "+
+ // Region.getRenderModeString(lastRenderModes, sampleCount[0], 0)+" -> "+Region.getRenderModeString(curRenderModes, sampleCount[0], 0));
+
if( lastRenderModes != curRenderModes ) {
markShapeDirty();
markStateDirty();
@@ -535,7 +539,7 @@ public abstract class GLRegion extends Region { if( isShapeDirty() ) {
updateImpl(gl, renderer, curRenderModes);
}
- drawImpl(gl, renderer, curRenderModes, sampleCount);
+ drawImpl(gl, renderer, curRenderModes, pass2Quality, sampleCount);
clearDirtyBits(DIRTY_SHAPE|DIRTY_STATE);
lastRenderModes = curRenderModes;
}
@@ -549,5 +553,5 @@ public abstract class GLRegion extends Region { */
protected abstract void updateImpl(final GL2ES2 gl, final RegionRenderer renderer, final int curRenderModes);
- protected abstract void drawImpl(final GL2ES2 gl, final RegionRenderer renderer, final int curRenderModes, final int[/*1*/] sampleCount);
+ protected abstract void drawImpl(final GL2ES2 gl, final RegionRenderer renderer, final int curRenderModes, int pass2Quality, final int[/*1*/] sampleCount);
}
diff --git a/src/jogl/classes/com/jogamp/graph/curve/opengl/RegionRenderer.java b/src/jogl/classes/com/jogamp/graph/curve/opengl/RegionRenderer.java index c43dc7913..cf9ac637b 100644 --- a/src/jogl/classes/com/jogamp/graph/curve/opengl/RegionRenderer.java +++ b/src/jogl/classes/com/jogamp/graph/curve/opengl/RegionRenderer.java @@ -28,6 +28,7 @@ package com.jogamp.graph.curve.opengl; import java.io.IOException; +import java.util.HashMap; import java.util.Iterator; import com.jogamp.opengl.GL; @@ -44,7 +45,6 @@ import com.jogamp.opengl.util.glsl.ShaderCode; import com.jogamp.opengl.util.glsl.ShaderProgram; import com.jogamp.opengl.util.texture.TextureSequence; import com.jogamp.common.os.Platform; -import com.jogamp.common.util.IntObjectHashMap; import com.jogamp.graph.curve.Region; import com.jogamp.math.Recti; import com.jogamp.math.Vec4f; @@ -67,6 +67,7 @@ public final class RegionRenderer { protected static final boolean DEBUG = Region.DEBUG; protected static final boolean DEBUG_ALL_EVENT = Region.DEBUG_ALL_EVENT; protected static final boolean DEBUG_INSTANCE = Region.DEBUG_INSTANCE; + private static final boolean DEBUG_SHADER_MAP = DEBUG; /** * May be passed to @@ -91,7 +92,7 @@ public final class RegionRenderer { * and turning-on the {@link GL#GL_BLEND} state. * <p> * Implementation also sets {@link RegionRenderer#getRenderState() RenderState}'s {@link RenderState#BITHINT_BLENDING_ENABLED blending bit-hint}, - * which will cause {@link GLRegion#draw(GL2ES2, RegionRenderer, int[]) GLRegion's draw-method} + * which will cause {@link GLRegion#draw(GL2ES2, RegionRenderer, int, int[]) GLRegion's draw-method} * to set the proper {@link GL#glBlendFuncSeparate(int, int, int, int) blend-function} * and the clear-color to <i>transparent-black</i> in case of {@link Region#isTwoPass(int) multipass} FBO rendering. * </p> @@ -235,7 +236,7 @@ public final class RegionRenderer { * Initialize shader and bindings for GPU based rendering bound to the given GL object's GLContext * if not initialized yet. * <p>Disables the renderer via {@link #enable(GL2ES2, boolean)} to remove any side-effects, ie ShaderState incl. shader program.</p> - * <p>Shall be called once before at initialization before a {@code draw()} method, e.g. {@link RegionRenderer#draw(GL2ES2, Region, int)}</p> + * <p>Shall be called once before at initialization before a {@code draw()} method, e.g. {@link RegionRenderer#draw(GL2ES2, Region, int, int)}</p> * * @param gl referencing the current GLContext to which the ShaderState is bound to * @throws GLException if initialization failed @@ -273,8 +274,8 @@ public final class RegionRenderer { } return; } - for(final Iterator<IntObjectHashMap.Entry> i = shaderPrograms.iterator(); i.hasNext(); ) { - final ShaderProgram sp = (ShaderProgram) i.next().getValue(); + for(final Iterator<ShaderProgram> i = shaderPrograms.values().iterator(); i.hasNext(); ) { + final ShaderProgram sp = i.next(); sp.destroy(gl); } shaderPrograms.clear(); @@ -404,6 +405,8 @@ public final class RegionRenderer { private static final String SHADER_SRC_SUB = ""; private static final String SHADER_BIN_SUB = "bin"; + private static final String GLSL_PARAM_COMMENT_START = "\n// JogAmp Graph Parameter Start\n"; + private static final String GLSL_PARAM_COMMENT_END = "// JogAmp Graph Parameter End\n\n"; private static final String GLSL_USE_COLOR_CHANNEL = "#define USE_COLOR_CHANNEL 1\n"; private static final String GLSL_USE_COLOR_TEXTURE = "#define USE_COLOR_TEXTURE 1\n"; private static final String GLSL_USE_AABBOX_CLIPPING = "#define USE_AABBOX_CLIPPING 1\n"; @@ -478,9 +481,7 @@ public final class RegionRenderer { } public static ShaderModeSelector1 selectPass2(final int renderModes, final int quality, final int sampleCount) { - if( Region.isMSAA(renderModes) ) { - return PASS2_MSAA; - } else if( Region.isVBAA(renderModes) ) { + if( Region.isVBAA(renderModes) ) { if( 0 == quality ) { if( sampleCount < 2 ) { return PASS2_VBAA_QUAL0_SAMPLES1; @@ -505,14 +506,81 @@ public final class RegionRenderer { } } } else { - return null; + return PASS2_MSAA; // Region.isMSAA(renderModes) and default } } } - private final IntObjectHashMap shaderPrograms = new IntObjectHashMap(); - private static final int HIGH_MASK = Region.COLORCHANNEL_RENDERING_BIT | Region.COLORTEXTURE_RENDERING_BIT; - private static final int TWO_PASS_BIT = 1 << 31; + private static class ShaderKey { + final boolean isTwoPass; + final boolean pass1; + final ShaderModeSelector1 sms; + final boolean hasAABBoxClipping; // pass1 or pass2 + final boolean hasColorChannel; // pass1 only + final boolean hasColorTexture; // pass1 only + final String colorTexSeqID; + final int colorTexSeqHash; + + final String texLookupFuncName; + final int hashValue; + + ShaderKey(final int renderModes, final boolean pass1_, final int pass2Quality, final int sampleCount, final TextureSequence colorTexSeq, final boolean hasClipBBox) { + isTwoPass = Region.isTwoPass( renderModes ); + pass1 = pass1_; + sms = pass1 ? ShaderModeSelector1.selectPass1(renderModes) : + ShaderModeSelector1.selectPass2(renderModes, pass2Quality, sampleCount); + hasAABBoxClipping = hasClipBBox && ( ( !isTwoPass && pass1 ) || ( isTwoPass && !pass1 ) ); + hasColorChannel = pass1 && Region.hasColorChannel( renderModes ); + hasColorTexture = pass1 && Region.hasColorTexture( renderModes ) && null != colorTexSeq; + if( hasColorTexture ) { + texLookupFuncName = colorTexSeq.setTextureLookupFunctionName(gcuTexture2D); + colorTexSeqID = colorTexSeq.getTextureFragmentShaderHashID(); + colorTexSeqHash = colorTexSeq.getTextureFragmentShaderHashCode(); + } else { + texLookupFuncName = null; + colorTexSeqID = ""; + colorTexSeqHash = 0; + } + { + // 31 * x == (x << 5) - x + int hash = 31 * ( isTwoPass ? 1 : 0 ); + hash = ((hash << 5) - hash) + ( pass1 ? 1 : 0 ) ; + // hash = ((hash << 5) - hash) + pass2Quality; // included in sms + // hash = ((hash << 5) - hash) + sampleCount; // included in sms + hash = ((hash << 5) - hash) + sms.ordinal(); + hash = ((hash << 5) - hash) + ( hasAABBoxClipping ? 1 : 0 ); + hash = ((hash << 5) - hash) + ( hasColorChannel ? 1 : 0 ); + hash = ((hash << 5) - hash) + ( hasColorTexture ? 1 : 0 ); + hash = ((hash << 5) - hash) + colorTexSeqHash; + hashValue = hash; + } + } + @Override + public final int hashCode() { return hashValue; } + @Override + public final boolean equals(final Object other) { + if( this == other ) { return true; } + if( !(other instanceof ShaderKey) ) { + return false; + } + final ShaderKey o = (ShaderKey)other; + return isTwoPass == o.isTwoPass && + pass1 == o.pass1 && + // pass2Quality == o.pass2Quality && // included in sms + // sampleCount == o.sampleCount && // included in sms + sms.ordinal() == o.sms.ordinal() && + hasAABBoxClipping == o.hasAABBoxClipping && + hasColorChannel == o.hasColorChannel && + hasColorTexture == o.hasColorTexture && + colorTexSeqID.equals(o.colorTexSeqID); + } + @Override + public String toString() { + return "ShaderKey[hash 0x"+Integer.toHexString(hashValue)+", is2Pass "+isTwoPass+", pass1 "+pass1+ + ", has[clip "+hasAABBoxClipping+", colChan "+hasColorChannel+", colTex "+hasColorTexture+"], "+sms+"]"; + } + } + private final HashMap<ShaderKey, ShaderProgram> shaderPrograms = new HashMap<ShaderKey, ShaderProgram>(); /** * Generate, selects and caches the desired Curve-Graph {@link ShaderProgram} according to the given parameters. @@ -523,7 +591,7 @@ public final class RegionRenderer { * @param gl * @param renderModes * @param pass1 - * @param quality + * @param pass2Quality * @param sampleCount * @param colorTexSeq * @return true if a new shader program is being used and hence external uniform-data and -location, @@ -533,55 +601,31 @@ public final class RegionRenderer { * @see RenderState#getShaderProgram() */ public final boolean useShaderProgram(final GL2ES2 gl, final int renderModes, - final boolean pass1, final int quality, final int sampleCount, final TextureSequence colorTexSeq) { - final ShaderModeSelector1 sel1 = pass1 ? ShaderModeSelector1.selectPass1(renderModes) : - ShaderModeSelector1.selectPass2(renderModes, quality, sampleCount); - final boolean hasAABBoxClipping = null != getClipBBox(); - final boolean isTwoPass = Region.isTwoPass( renderModes ); - final boolean hasColorChannel = Region.hasColorChannel( renderModes ); - final boolean hasColorTexture = Region.hasColorTexture( renderModes ) && null != colorTexSeq; - final boolean isPass1ColorTexSeq = pass1 && hasColorTexture; - final int colorTexSeqHash; - final String texLookupFuncName; - if( isPass1ColorTexSeq ) { - texLookupFuncName = colorTexSeq.setTextureLookupFunctionName(gcuTexture2D); - colorTexSeqHash = colorTexSeq.getTextureFragmentShaderHashCode(); - } else { - texLookupFuncName = null; - colorTexSeqHash = 0; - } - final int shaderKey; - { - // 31 * x == (x << 5) - x - int hash = 31 + colorTexSeqHash; - hash = ((hash << 5) - hash) + sel1.ordinal(); - hash = ((hash << 5) - hash) + ( HIGH_MASK & renderModes ); - hash = ((hash << 5) - hash) + ( hasAABBoxClipping ? 1 : 0 ); - hash = ((hash << 5) - hash) + ( isTwoPass ? TWO_PASS_BIT : 0 ); - shaderKey = hash; - } + final boolean pass1, final int pass2Quality, final int sampleCount, final TextureSequence colorTexSeq) { + final ShaderKey shaderKey = new ShaderKey(renderModes, pass1, pass2Quality, sampleCount, colorTexSeq, null != getClipBBox()); /** if(DEBUG) { - System.err.printf("RegionRendererImpl01.useShaderProgram.0: renderModes %s, sel1 %s, key 0x%X (pass1 %b, q %d, samples %d) - Thread %s%n", - Region.getRenderModeString(renderModes), sel1, shaderKey, pass1, quality, sampleCount, Thread.currentThread()); + System.err.println("XXX "+Region.getRenderModeString(renderModes, sampleCount, 0)+", "+shaderKey); } */ - ShaderProgram sp = (ShaderProgram) shaderPrograms.get( shaderKey ); + ShaderProgram sp = shaderPrograms.get( shaderKey ); if( null != sp ) { final boolean spChanged = rs.setShaderProgram(gl, sp); - if( DEBUG ) { + if( DEBUG_SHADER_MAP ) { if( spChanged ) { - System.err.printf("RegionRendererImpl01.useShaderProgram.X1: GOT renderModes %s, sel1 %s, key 0x%X -> sp %d / %d (changed)%n", Region.getRenderModeString(renderModes), sel1, shaderKey, sp.program(), sp.id()); + System.err.printf("RegionRenderer.useShaderProgram.X1: GOT renderModes %s, %s -> sp %d / %d (changed)%n", + Region.getRenderModeString(renderModes), shaderKey, sp.program(), sp.id()); } else if( DEBUG_ALL_EVENT ) { - System.err.printf("RegionRendererImpl01.useShaderProgram.X1: GOT renderModes %s, sel1 %s, key 0x%X -> sp %d / %d (keep)%n", Region.getRenderModeString(renderModes), sel1, shaderKey, sp.program(), sp.id()); + System.err.printf("RegionRenderer.useShaderProgram.X1: GOT renderModes %s, %s -> sp %d / %d (keep)%n", + Region.getRenderModeString(renderModes), shaderKey, sp.program(), sp.id()); } } return spChanged; } final String versionedBaseName = getVersionedShaderName(); final String vertexShaderName; - if( isTwoPass ) { + if( shaderKey.isTwoPass ) { vertexShaderName = versionedBaseName+"-pass"+(pass1?1:2); } else { vertexShaderName = versionedBaseName+"-single"; @@ -589,30 +633,30 @@ public final class RegionRenderer { final ShaderCode rsVp = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, AttributeNames.class, SHADER_SRC_SUB, SHADER_BIN_SUB, vertexShaderName, true); final ShaderCode rsFp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, AttributeNames.class, SHADER_SRC_SUB, SHADER_BIN_SUB, versionedBaseName+"-segment-head", true); - if( isPass1ColorTexSeq && GLES2.GL_TEXTURE_EXTERNAL_OES == colorTexSeq.getTextureTarget() ) { + if( shaderKey.hasColorTexture && GLES2.GL_TEXTURE_EXTERNAL_OES == colorTexSeq.getTextureTarget() ) { if( !gl.isExtensionAvailable(GLExtensions.OES_EGL_image_external) ) { throw new GLException(GLExtensions.OES_EGL_image_external+" requested but not available"); } } - boolean supressGLSLVersionES30 = false; - if( isPass1ColorTexSeq && GLES2.GL_TEXTURE_EXTERNAL_OES == colorTexSeq.getTextureTarget() ) { + boolean preludeGLSLVersion = true; + if( shaderKey.hasColorTexture && GLES2.GL_TEXTURE_EXTERNAL_OES == colorTexSeq.getTextureTarget() ) { if( Platform.OSType.ANDROID == Platform.getOSType() && gl.isGLES3() ) { // Bug on Nexus 10, ES3 - Android 4.3, where // GL_OES_EGL_image_external extension directive leads to a failure _with_ '#version 300 es' ! // P0003: Extension 'GL_OES_EGL_image_external' not supported - supressGLSLVersionES30 = true; + preludeGLSLVersion = false; } } // // GLSL customization at top // - int posVp = rsVp.defaultShaderCustomization(gl, !supressGLSLVersionES30, true); + int posVp = rsVp.defaultShaderCustomization(gl, preludeGLSLVersion, true); // rsFp.defaultShaderCustomization(gl, true, true); - int posFp = supressGLSLVersionES30 ? 0 : rsFp.addGLSLVersion(gl); - if( isPass1ColorTexSeq ) { + int posFp = preludeGLSLVersion ? rsFp.addGLSLVersion(gl) : 0; + if( shaderKey.hasColorTexture ) { posFp = rsFp.insertShaderSource(0, posFp, colorTexSeq.getRequiredExtensionsShaderStub()); } - if( pass1 && supressGLSLVersionES30 || ( gl.isGLES2() && !gl.isGLES3() ) ) { + if( pass1 && !preludeGLSLVersion || ( gl.isGLES2() && !gl.isGLES3() ) ) { posFp = rsFp.insertShaderSource(0, posFp, ShaderCode.createExtensionDirective(GLExtensions.OES_standard_derivatives, ShaderCode.ENABLE)); } if( false ) { @@ -628,30 +672,36 @@ public final class RegionRenderer { // GLSL append from here on posFp = -1; + posVp = rsVp.insertShaderSource(0, posVp, GLSL_PARAM_COMMENT_START); + posFp = rsFp.insertShaderSource(0, posFp, GLSL_PARAM_COMMENT_START); + if( !gl.getContext().hasRendererQuirk(GLRendererQuirks.GLSLBuggyDiscard) ) { posFp = rsFp.insertShaderSource(0, posFp, GLSL_USE_DISCARD); } - if( hasAABBoxClipping ) { + if( shaderKey.hasAABBoxClipping ) { posVp = rsVp.insertShaderSource(0, posVp, GLSL_USE_AABBOX_CLIPPING); posFp = rsFp.insertShaderSource(0, posFp, GLSL_USE_AABBOX_CLIPPING); } - if( hasColorChannel ) { + if( shaderKey.hasColorChannel ) { posVp = rsVp.insertShaderSource(0, posVp, GLSL_USE_COLOR_CHANNEL); posFp = rsFp.insertShaderSource(0, posFp, GLSL_USE_COLOR_CHANNEL); } - if( isPass1ColorTexSeq ) { + if( shaderKey.hasColorTexture ) { rsVp.insertShaderSource(0, posVp, GLSL_USE_COLOR_TEXTURE); posFp = rsFp.insertShaderSource(0, posFp, GLSL_USE_COLOR_TEXTURE); } if( !pass1 ) { - posFp = rsFp.insertShaderSource(0, posFp, GLSL_DEF_SAMPLE_COUNT+sel1.sampleCount+"\n"); - posFp = rsFp.insertShaderSource(0, posFp, GLSL_CONST_SAMPLE_COUNT+sel1.sampleCount+".0;\n"); + posFp = rsFp.insertShaderSource(0, posFp, GLSL_DEF_SAMPLE_COUNT+shaderKey.sms.sampleCount+"\n"); + posFp = rsFp.insertShaderSource(0, posFp, GLSL_CONST_SAMPLE_COUNT+shaderKey.sms.sampleCount+".0;\n"); } + posVp = rsVp.insertShaderSource(0, posVp, GLSL_PARAM_COMMENT_END); + posFp = rsFp.insertShaderSource(0, posFp, GLSL_PARAM_COMMENT_END); + try { - if( isPass1ColorTexSeq || hasAABBoxClipping ) { + if( shaderKey.hasColorTexture || shaderKey.hasAABBoxClipping ) { posFp = rsFp.insertShaderSource(0, posFp, AttributeNames.class, "functions.glsl"); } posFp = rsFp.insertShaderSource(0, posFp, AttributeNames.class, "uniforms.glsl"); @@ -663,7 +713,7 @@ public final class RegionRenderer { throw new RuntimeException("Failed to read: includes"); } - if( isPass1ColorTexSeq ) { + if( shaderKey.hasColorTexture ) { posFp = rsFp.insertShaderSource(0, posFp, "uniform "+colorTexSeq.getTextureSampler2DType()+" "+UniformNames.gcu_ColorTexUnit+";\n"); posFp = rsFp.insertShaderSource(0, posFp, colorTexSeq.getTextureLookupFragmentShaderImpl()); } @@ -671,7 +721,7 @@ public final class RegionRenderer { posFp = rsFp.insertShaderSource(0, posFp, GLSL_MAIN_BEGIN); final String passS = pass1 ? "-pass1-" : "-pass2-"; - final String shaderSegment = versionedBaseName+passS+sel1.tech+sel1.sub+".glsl"; + final String shaderSegment = versionedBaseName+passS+shaderKey.sms.tech+shaderKey.sms.sub+".glsl"; if(DEBUG) { System.err.printf("RegionRendererImpl01.useShaderProgram.1: segment %s%n", shaderSegment); } @@ -685,8 +735,8 @@ public final class RegionRenderer { } posFp = rsFp.insertShaderSource(0, posFp, "}\n"); - if( isPass1ColorTexSeq ) { - rsFp.replaceInShaderSource(gcuTexture2D, texLookupFuncName); + if( shaderKey.hasColorTexture ) { + rsFp.replaceInShaderSource(gcuTexture2D, shaderKey.texLookupFuncName); } sp = new ShaderProgram(); @@ -703,9 +753,9 @@ public final class RegionRenderer { rs.setShaderProgram(gl, sp); shaderPrograms.put(shaderKey, sp); - if( DEBUG ) { - System.err.printf("RegionRendererImpl01.useShaderProgram.X1: PUT renderModes %s, sel1 %s, key 0x%X -> sp %d / %d (changed, new)%n", - Region.getRenderModeString(renderModes), sel1, shaderKey, sp.program(), sp.id()); + if( DEBUG_SHADER_MAP ) { + System.err.printf("RegionRenderer.useShaderProgram.X1: PUT renderModes %s, %s -> sp %d / %d (changed, new)%n", + Region.getRenderModeString(renderModes), shaderKey, sp.program(), sp.id()); // rsFp.dumpShaderSource(System.err); } return true; diff --git a/src/jogl/classes/com/jogamp/graph/curve/opengl/RenderState.java b/src/jogl/classes/com/jogamp/graph/curve/opengl/RenderState.java index ed4bc2585..24cab1b85 100644 --- a/src/jogl/classes/com/jogamp/graph/curve/opengl/RenderState.java +++ b/src/jogl/classes/com/jogamp/graph/curve/opengl/RenderState.java @@ -60,7 +60,7 @@ public class RenderState { * Shall be set via {@link #setHintMask(int)} and cleared via {@link #clearHintMask(int)}. * </p> * <p> - * If set, {@link GLRegion#draw(GL2ES2, RegionRenderer, int[]) GLRegion's draw-method} + * If set, {@link GLRegion#draw(GL2ES2, RegionRenderer, int, int[]) GLRegion's draw-method} * will set the proper {@link GL#glBlendFuncSeparate(int, int, int, int) blend-function} * and the clear-color to <i>transparent-black</i> in case of {@link Region#isTwoPass(int) multipass} FBO rendering. * </p> @@ -79,7 +79,7 @@ public class RenderState { * Shall be set via {@link #setHintMask(int)} and cleared via {@link #clearHintMask(int)}. * </p> * <p> - * {@link GLRegion#draw(GL2ES2, RegionRenderer, int[]) GLRegion's draw-method} + * {@link GLRegion#draw(GL2ES2, RegionRenderer, int, int[]) GLRegion's draw-method} * may toggle depth test, and reset it's state according to this hint. * </p> * <p> @@ -137,10 +137,12 @@ public class RenderState { * @param gl * @param updateLocation * @param renderModes + * @param setPMVMat01 TODO * @param throwOnError TODO * @return true if no error occurred, i.e. all locations found, otherwise false. */ - public final boolean update(final GL2ES2 gl, final RenderState rs, final boolean updateLocation, final int renderModes, final boolean pass1, final boolean throwOnError) { + public final boolean update(final GL2ES2 gl, final RenderState rs, final boolean updateLocation, final int renderModes, + final boolean setPMVMat01, final boolean pass1, final boolean throwOnError) { if( rs.id() != rsId ) { // Assignment of Renderstate buffers to uniforms (no copy, direct reference) gcu_PMVMatrix01.setData(rs.pmvMatrix.getSyncPMv()); @@ -150,7 +152,7 @@ public class RenderState { } boolean res = true; if( null != rs.sp && rs.sp.inUse() ) { - if( !Region.isTwoPass(renderModes) || !pass1 ) { + if( setPMVMat01 ) { final boolean r0 = rs.updateUniformDataLoc(gl, updateLocation, true, gcu_PMVMatrix01, throwOnError); res = res && r0; } diff --git a/src/jogl/classes/com/jogamp/graph/curve/opengl/TextRegionUtil.java b/src/jogl/classes/com/jogamp/graph/curve/opengl/TextRegionUtil.java index e6e4f3e0c..a0e342acd 100644 --- a/src/jogl/classes/com/jogamp/graph/curve/opengl/TextRegionUtil.java +++ b/src/jogl/classes/com/jogamp/graph/curve/opengl/TextRegionUtil.java @@ -231,7 +231,7 @@ public class TextRegionUtil { } else { renderer.setColorStatic(1, 1, 1, 1); } - region.draw(gl, renderer, sampleCount); + region.draw(gl, renderer, Region.MAX_AA_QUALITY, sampleCount); return res; } @@ -293,7 +293,7 @@ public class TextRegionUtil { } else { renderer.setColorStatic(1, 1, 1, 1); } - region.draw(gl, renderer, sampleCount); + region.draw(gl, renderer, Region.MAX_AA_QUALITY, sampleCount); region.destroy(gl); return res; } @@ -352,7 +352,7 @@ public class TextRegionUtil { } else { renderer.setColorStatic(1, 1, 1, 1); } - region.draw(gl, renderer, sampleCount); + region.draw(gl, renderer, Region.MAX_AA_QUALITY, sampleCount); return res; } diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/ImageSequence.java b/src/jogl/classes/com/jogamp/opengl/util/texture/ImageSequence.java index 2da2dcbfc..99704ced0 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/texture/ImageSequence.java +++ b/src/jogl/classes/com/jogamp/opengl/util/texture/ImageSequence.java @@ -159,6 +159,7 @@ public class ImageSequence implements TextureSequence { } else if(null != texLookupFuncName && texLookupFuncName.length()>0) { textureLookupFunctionName = texLookupFuncName; } + textureFragmentShaderHashCode = 0; return textureLookupFunctionName; } @@ -180,13 +181,22 @@ public class ImageSequence implements TextureSequence { } @Override + public String getTextureFragmentShaderHashID() { + // return getTextureSampler2DType()+";"+getTextureLookupFunctionName()+";"+getTextureLookupFragmentShaderImpl(); + if( useBuildInTexLookup ) { + return getTextureSampler2DType()+";"+getTextureLookupFunctionName(); + } else { + return getTextureLookupFragmentShaderImpl(); + } + } + + @Override public int getTextureFragmentShaderHashCode() { if( !isTextureAvailable() ) { textureFragmentShaderHashCode = 0; return 0; } else if( 0 == textureFragmentShaderHashCode ) { - int hash = 31 + getTextureLookupFragmentShaderImpl().hashCode(); - hash = ((hash << 5) - hash) + getTextureSampler2DType().hashCode(); + final int hash = getTextureFragmentShaderHashID().hashCode(); textureFragmentShaderHashCode = hash; } return textureFragmentShaderHashCode; diff --git a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureSequence.java b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureSequence.java index 8376f0fa5..6aa70f014 100644 --- a/src/jogl/classes/com/jogamp/opengl/util/texture/TextureSequence.java +++ b/src/jogl/classes/com/jogamp/opengl/util/texture/TextureSequence.java @@ -274,19 +274,31 @@ public interface TextureSequence { * @throws IllegalStateException if instance is not initialized * @see #getTextureLookupFunctionName() * @see #setTextureLookupFunctionName(String) + * @see #getTextureFragmentShaderHashID() * @see #getTextureFragmentShaderHashCode() * @see #getTextureSampler2DType() */ public String getTextureLookupFragmentShaderImpl() throws IllegalStateException; /** - * Returns the hash code of the strings: + * Returns the concatenated string representing the following values + * utilized for {@link #getTextureFragmentShaderHashCode()}. * <ul> + * <li>{@link #getTextureSampler2DType()}</li> * <li>{@link #getTextureLookupFunctionName()}</li> * <li>{@link #getTextureLookupFragmentShaderImpl()}</li> - * <li>{@link #getTextureSampler2DType()}</li> * </ul> * <p> + * To reduce string concatenating, implementation may simply return {@link #getTextureLookupFragmentShaderImpl()}, + * if it covers {@link #getTextureSampler2DType()} and {@link #getTextureLookupFunctionName()}. + * </p> + * @see #getTextureFragmentShaderHashCode() + */ + public String getTextureFragmentShaderHashID(); + + /** + * Returns the hash code of the string {@link #getTextureFragmentShaderHashID()}. + * <p> * User shall call {@link #setTextureLookupFunctionName(String)} first if intended. * </p> * <p> @@ -296,12 +308,13 @@ public interface TextureSequence { * <p> * </p> * <p> - * Implementation caches the resulting hash code, - * which must be reset to zero if {@link #isTextureAvailable() texture is not available}. + * Implementation caches the resulting hash code, which is reset by {@link #setTextureLookupFunctionName(String)} + * and this method if {@link #isTextureAvailable() texture is not available}. * </p> * @see #setTextureLookupFunctionName(String) * @see #getTextureLookupFunctionName() * @see #getTextureLookupFragmentShaderImpl() + * @see #getTextureFragmentShaderHashID() */ public int getTextureFragmentShaderHashCode(); |