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 | |
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')
33 files changed, 609 insertions, 404 deletions
diff --git a/src/demos/com/jogamp/opengl/demos/graph/GPURegionGLListener00.java b/src/demos/com/jogamp/opengl/demos/graph/GPURegionGLListener00.java index 1f49bf8f5..c0f2a6bb1 100644 --- a/src/demos/com/jogamp/opengl/demos/graph/GPURegionGLListener00.java +++ b/src/demos/com/jogamp/opengl/demos/graph/GPURegionGLListener00.java @@ -34,6 +34,7 @@ import com.jogamp.opengl.GLAutoDrawable; import com.jogamp.opengl.GLProfile; import com.jogamp.opengl.fixedfunc.GLMatrixFunc; import com.jogamp.graph.curve.OutlineShape; +import com.jogamp.graph.curve.Region; import com.jogamp.graph.curve.opengl.GLRegion; import com.jogamp.graph.curve.opengl.RenderState; import com.jogamp.math.Vec4f; @@ -126,7 +127,7 @@ public class GPURegionGLListener00 extends GPURendererListenerBase01 { regionRenderer.setWeight(weight); } regionRenderer.enable(gl, true); - region.draw(gl, regionRenderer, getSampleCount()); + region.draw(gl, regionRenderer, Region.MAX_AA_QUALITY, getSampleCount()); regionRenderer.enable(gl, false); } } diff --git a/src/demos/com/jogamp/opengl/demos/graph/GPURegionGLListener01.java b/src/demos/com/jogamp/opengl/demos/graph/GPURegionGLListener01.java index 413adca80..55433f21a 100644 --- a/src/demos/com/jogamp/opengl/demos/graph/GPURegionGLListener01.java +++ b/src/demos/com/jogamp/opengl/demos/graph/GPURegionGLListener01.java @@ -33,6 +33,7 @@ import com.jogamp.opengl.GL2ES2; import com.jogamp.opengl.GLAutoDrawable; import com.jogamp.opengl.fixedfunc.GLMatrixFunc; import com.jogamp.graph.curve.OutlineShape; +import com.jogamp.graph.curve.Region; import com.jogamp.graph.curve.opengl.GLRegion; import com.jogamp.graph.curve.opengl.RenderState; import com.jogamp.math.Vec4f; @@ -291,7 +292,7 @@ public class GPURegionGLListener01 extends GPURendererListenerBase01 { regionRenderer.setWeight(weight); } regionRenderer.enable(gl, true); - region.draw(gl, regionRenderer, getSampleCount()); + region.draw(gl, regionRenderer, Region.MAX_AA_QUALITY, getSampleCount()); regionRenderer.enable(gl, false); } } diff --git a/src/demos/com/jogamp/opengl/demos/graph/GPURegionGLListener10.java b/src/demos/com/jogamp/opengl/demos/graph/GPURegionGLListener10.java index a802ce386..843da6d46 100644 --- a/src/demos/com/jogamp/opengl/demos/graph/GPURegionGLListener10.java +++ b/src/demos/com/jogamp/opengl/demos/graph/GPURegionGLListener10.java @@ -132,7 +132,7 @@ public class GPURegionGLListener10 extends GPURendererListenerBase01 { regionRenderer.setWeight(weight); } regionRenderer.enable(gl, true); - region.draw(gl, regionRenderer, getSampleCount()); + region.draw(gl, regionRenderer, Region.MAX_AA_QUALITY, getSampleCount()); regionRenderer.enable(gl, false); } diff --git a/src/demos/com/jogamp/opengl/demos/graph/TextRendererGLELBase.java b/src/demos/com/jogamp/opengl/demos/graph/TextRendererGLELBase.java index b515db2a9..c0dd2386b 100644 --- a/src/demos/com/jogamp/opengl/demos/graph/TextRendererGLELBase.java +++ b/src/demos/com/jogamp/opengl/demos/graph/TextRendererGLELBase.java @@ -32,7 +32,7 @@ import java.io.IOException; import com.jogamp.opengl.GL2ES2; import com.jogamp.opengl.GLAutoDrawable; import com.jogamp.opengl.GLEventListener; - +import com.jogamp.graph.curve.Region; import com.jogamp.graph.curve.opengl.GLRegion; import com.jogamp.graph.curve.opengl.RenderState; import com.jogamp.graph.curve.opengl.RegionRenderer; @@ -310,7 +310,7 @@ public abstract class TextRendererGLELBase implements GLEventListener { pmvMatrix.scaleMv(sxy, sxy, 1.0f); } renderer.enable(gl, true); - region.draw(gl, renderer, vbaaSampleCount); + region.draw(gl, renderer, Region.MAX_AA_QUALITY, vbaaSampleCount); renderer.enable(gl, false); if( !exclusivePMVMatrix ) { diff --git a/src/demos/com/jogamp/opengl/demos/graph/ui/UISceneDemo20.java b/src/demos/com/jogamp/opengl/demos/graph/ui/UISceneDemo20.java index 20642d737..eac90cf7d 100644 --- a/src/demos/com/jogamp/opengl/demos/graph/ui/UISceneDemo20.java +++ b/src/demos/com/jogamp/opengl/demos/graph/ui/UISceneDemo20.java @@ -570,20 +570,15 @@ public class UISceneDemo20 implements GLEventListener { public void mouseClicked(final MouseEvent e) { final Shape.EventInfo shapeEvent = (Shape.EventInfo) e.getAttachment(); if( shapeEvent.shape instanceof GraphShape ) { - int quality = ((GraphShape)shapeEvent.shape).getQuality(); - + int quality = ((GraphShape)shapeEvent.shape).getAAQuality(); if( shapeEvent.objPos.x() < shapeEvent.shape.getBounds().getCenter().x() ) { // left-half pressed - if( quality > 0 ) { - quality--; - } + quality--; } else { // right-half pressed - if( quality < Region.MAX_QUALITY ) { - quality++; - } + quality++; } - scene.setAllShapesQuality(quality); + scene.setAAQuality(quality); // validated / clipped } } } ); button.addMouseListener(dragZoomRotateListener); @@ -1082,7 +1077,7 @@ public class UISceneDemo20 implements GLEventListener { truePtSizeLabel.moveTo(dxMiddleAbs, dyTopLabelAbs - jogampLabel.getScaledLineHeight() - truePtSizeLabel.getScaledLineHeight(), dz); } { - final AABBox fbox = fontFPS.getGlyphBounds(scene.getStatusText(drawable, renderModes, fpsLabel.getQuality(), dpiV)); + final AABBox fbox = fontFPS.getGlyphBounds(scene.getStatusText(drawable, renderModes, fpsLabel.getAAQuality(), dpiV)); final float scale = sceneWidth / ( 1.4f * fbox.getWidth() ); // add 40% width fpsLabel.setScale(scale, scale, 1f); fpsLabel.moveTo(sceneBox.getMinX(), sceneBox.getMinY() + scale * ( fontFPS.getMetrics().getLineGap() - fontFPS.getMetrics().getDescent() ), 0f); @@ -1138,7 +1133,7 @@ public class UISceneDemo20 implements GLEventListener { if( fpsLabel.isVisible() ) { final String text; if( null == actionText ) { - text = scene.getStatusText(drawable, renderModes, fpsLabel.getQuality(), dpiV); + text = scene.getStatusText(drawable, renderModes, fpsLabel.getAAQuality(), dpiV); } else if( null != drawable.getAnimator() ) { text = Scene.getStatusText(drawable.getAnimator())+", "+actionText; } else { diff --git a/src/demos/com/jogamp/opengl/demos/graph/ui/UIShapeDemo01.java b/src/demos/com/jogamp/opengl/demos/graph/ui/UIShapeDemo01.java index 8f51467d4..63fb63442 100644 --- a/src/demos/com/jogamp/opengl/demos/graph/ui/UIShapeDemo01.java +++ b/src/demos/com/jogamp/opengl/demos/graph/ui/UIShapeDemo01.java @@ -297,10 +297,10 @@ public class UIShapeDemo01 implements GLEventListener { System.err.println("XXX: txt_box_em "+txt_box_em); System.err.println("XXX: txt_box_e2 "+txt_box_em2); System.err.println("XXX: txt_box_rg "+txt_box_r); - once = false; } pmv.popMv(); } + once = false; renderer.enable(gl, false); } static boolean once = true; diff --git a/src/demos/com/jogamp/opengl/demos/graph/ui/UITypeDemo01.java b/src/demos/com/jogamp/opengl/demos/graph/ui/UITypeDemo01.java index ff052ab1e..309f1d83f 100644 --- a/src/demos/com/jogamp/opengl/demos/graph/ui/UITypeDemo01.java +++ b/src/demos/com/jogamp/opengl/demos/graph/ui/UITypeDemo01.java @@ -330,7 +330,7 @@ public class UITypeDemo01 implements GLEventListener { if( null != glyph.getShape() ) { final GLRegion region = GLRegion.create(gl.getGLProfile(), renderModes, null, glyph.getShape()); region.addOutlineShape(glyph.getShape(), null, fg_color); - region.draw(gl, renderer, sampleCount); + region.draw(gl, renderer, Region.MAX_AA_QUALITY, sampleCount); region.destroy(gl); } if( once ) { diff --git a/src/graphui/classes/com/jogamp/graph/ui/GraphShape.java b/src/graphui/classes/com/jogamp/graph/ui/GraphShape.java index 869d63ec7..27e231aa5 100644 --- a/src/graphui/classes/com/jogamp/graph/ui/GraphShape.java +++ b/src/graphui/classes/com/jogamp/graph/ui/GraphShape.java @@ -58,7 +58,7 @@ public abstract class GraphShape extends Shape { protected int pass2TexUnit = GLRegion.DEFAULT_TWO_PASS_TEXTURE_UNIT; protected GLRegion region = null; protected float oshapeSharpness = OutlineShape.DEFAULT_SHARPNESS; - private int regionQuality = Region.MAX_QUALITY; + private int regionPass2Quality = Region.MAX_AA_QUALITY; private final List<GLRegion> dirtyRegions = new ArrayList<GLRegion>(); /** @@ -87,15 +87,13 @@ public abstract class GraphShape extends Shape { public final int getRenderModes() { return renderModes; } /** - * Sets the shape's Graph {@link Region}'s quality parameter. Default is {@link Region#MAX_QUALITY}. - * @param q Graph {@link Region}'s quality parameter, default is {@link Region#MAX_QUALITY}. + * Sets the shape's Graph {@link Region}'s pass2 AA-quality parameter. Default is {@link Region#MAX_AA_QUALITY}. + * @param q Graph {@link Region}'s pass2 AA-quality parameter, default is {@link Region#MAX_AA_QUALITY}. * @return this shape for chaining. */ - public final GraphShape setQuality(final int q) { - this.regionQuality = q; - if( null != region ) { - region.setQuality(q); - } + public final GraphShape setAAQuality(final int q) { + this.regionPass2Quality = q; + markStateDirty(); return this; } @@ -109,9 +107,9 @@ public abstract class GraphShape extends Shape { /** * Return the shape's Graph {@link Region}'s quality parameter. - * @see #setQuality(int) + * @see #setAAQuality(int) */ - public final int getQuality() { return regionQuality; } + public final int getAAQuality() { return regionPass2Quality; } /** * Sets the shape's Graph {@link OutlineShape}'s sharpness parameter. Default is {@link OutlineShape#DEFAULT_SHARPNESS}. @@ -168,12 +166,12 @@ public abstract class GraphShape extends Shape { @Override protected final void drawImpl0(final GL2ES2 gl, final RegionRenderer renderer, final int[] sampleCount, final Vec4f rgba) { renderer.setColorStatic(rgba); - region.draw(gl, renderer, sampleCount); + region.draw(gl, renderer, regionPass2Quality, sampleCount); } @Override protected final void drawToSelectImpl0(final GL2ES2 gl, final RegionRenderer renderer, final int[] sampleCount) { - region.draw(gl, renderer, sampleCount); + region.draw(gl, renderer, 0, sampleCount); } /** @@ -252,7 +250,6 @@ public abstract class GraphShape extends Shape { box.resize(h.x() + p.right, h.y() + p.top, l.z()); setRotationPivot( box.getCenter() ); } - region.setQuality(regionQuality); } else if( isStateDirty() ) { region.markStateDirty(); } diff --git a/src/graphui/classes/com/jogamp/graph/ui/Group.java b/src/graphui/classes/com/jogamp/graph/ui/Group.java index 025213f8d..2267b70cc 100644 --- a/src/graphui/classes/com/jogamp/graph/ui/Group.java +++ b/src/graphui/classes/com/jogamp/graph/ui/Group.java @@ -37,6 +37,8 @@ import com.jogamp.graph.curve.Region; import com.jogamp.graph.curve.opengl.RegionRenderer; import com.jogamp.graph.ui.layout.Padding; import com.jogamp.graph.ui.shapes.Rectangle; +import com.jogamp.math.FloatUtil; +import com.jogamp.math.Vec2f; import com.jogamp.math.Vec3f; import com.jogamp.math.Vec4f; import com.jogamp.math.geom.AABBox; @@ -75,9 +77,14 @@ public class Group extends Shape implements Container { } private final List<Shape> shapes = new CopyOnWriteArrayList<Shape>(); + private final Vec2f fixedSize = new Vec2f(); private Layout layouter; private Rectangle border = null; + private boolean relayoutOnDirtyShapes = true; + private boolean widgetMode = false; + boolean clipOnBox = false; + /** * Create a group of {@link Shape}s w/o {@link Group.Layout}. * <p> @@ -110,6 +117,14 @@ public class Group extends Shape implements Container { /** Set {@link Group.Layout}. */ public Group setLayout(final Layout l) { layouter = l; return this; } + /** Enforce size of this group to given dimension. */ + public Group setFixedSize(final Vec2f v) { fixedSize.set(v); return this; } + public Vec2f getFixedSize() { return fixedSize; } + + /** Enable {@link AABBox} clipping on {@link #getBounds()} for this group and its shapes. */ + public Group setClipOnBox(final boolean v) { clipOnBox = v; return this; } + public boolean getClipOnBox() { return clipOnBox; } + @Override public int getShapeCount() { return shapes.size(); } @@ -235,6 +250,10 @@ public class Group extends Shape implements Container { final Object[] shapesS = shapes.toArray(); Arrays.sort(shapesS, (Comparator)Shape.ZAscendingComparator); + final AABBox origClipBox = renderer.getClipBBox(); + if( clipOnBox ) { + renderer.setClipBBox( box.transform(pmv.getMv(), new AABBox()) ); // Mv pre-multiplied AABBox + } final int shapeCount = shapesS.length; for(int i=0; i<shapeCount; i++) { final Shape shape = (Shape) shapesS[i]; @@ -251,7 +270,11 @@ public class Group extends Shape implements Container { if( null != border ) { border.draw(gl, renderer, sampleCount); } + if( clipOnBox ) { + renderer.setClipBBox(origClipBox); + } } + @SuppressWarnings({ "unchecked", "rawtypes" }) @Override protected final void drawToSelectImpl0(final GL2ES2 gl, final RegionRenderer renderer, final int[] sampleCount) { @@ -277,11 +300,17 @@ public class Group extends Shape implements Container { } } - private boolean relayoutOnDirtyShapes = true; + /** + * Set relayout on dirty shapes mode, defaults to true. + * <p> + * If relayouting on dirty shape mode is enabler (default), + * {@link #isShapeDirty()} traverses through all shapes updating all dirty states of all its groups + * provoking a relayout if required. + * </p> + */ public void setRelayoutOnDirtyShapes(final boolean v) { relayoutOnDirtyShapes = v; } public boolean getRelayoutOnDirtyShapes() { return relayoutOnDirtyShapes; } - private boolean widgetMode = false; /** * Toggles widget behavior for this group and all its elements, default is disabled. * <p> @@ -341,6 +370,14 @@ public class Group extends Shape implements Container { return v[0]; } + /** + * {@inheritDoc} + * <p> + * If relayouting on dirty shape mode is enabler, see {@link #setRelayoutOnDirtyShapes(boolean)}, + * this method traverses through all shapes updating all dirty states of all its groups + * provoking a relayout if required. + * </p> + */ @Override protected boolean isShapeDirty() { if( relayoutOnDirtyShapes ) { @@ -364,21 +401,25 @@ public class Group extends Shape implements Container { // box has been reset final PMVMatrix4f pmv = new PMVMatrix4f(); - if( 0 == shapes.size() ) { - box.resize(0, 0, 0); - } else if( null != layouter ) { - for(final Shape s : shapes) { - if( needsRMs && null == firstGS && s instanceof GraphShape ) { - firstGS = (GraphShape)s; - } - layouter.preValidate(s); - if( null != gl ) { - s.validate(gl); - } else { - s.validate(glp); + if( null != layouter ) { + if( 0 == shapes.size() ) { + box.resize(0, 0, 0); + } else { + for(final Shape s : shapes) { + if( needsRMs && null == firstGS && s instanceof GraphShape ) { + firstGS = (GraphShape)s; + } + layouter.preValidate(s); + if( null != gl ) { + s.validate(gl); + } else { + s.validate(glp); + } } } layouter.layout(this, box, pmv); + } else if( 0 == shapes.size() ) { + box.resize(0, 0, 0); } else { final AABBox tsbox = new AABBox(); for(final Shape s : shapes) { @@ -405,6 +446,12 @@ public class Group extends Shape implements Container { box.resize(h.x() + p.right, h.y() + p.top, l.z()); setRotationPivot( box.getCenter() ); } + if( !FloatUtil.isZero(fixedSize.x()) && !FloatUtil.isZero(fixedSize.y()) ) { + final Vec3f low = box.getLow(); + final Vec3f high = new Vec3f(low); + high.add(fixedSize.x(), fixedSize.y(), 0); + box.setSize(low, high); + } if( hasBorder() ) { if( null == border ) { final int firstRMs = null != firstGS ? firstGS.getRenderModes() : 0; diff --git a/src/graphui/classes/com/jogamp/graph/ui/Scene.java b/src/graphui/classes/com/jogamp/graph/ui/Scene.java index 15ced642b..7748a4eb0 100644 --- a/src/graphui/classes/com/jogamp/graph/ui/Scene.java +++ b/src/graphui/classes/com/jogamp/graph/ui/Scene.java @@ -124,12 +124,6 @@ public final class Scene implements Container, GLEventListener { return FloatUtil.getZBufferEpsilon(zBits, setup.getSceneDist(), setup.getZNear()); } - /** Minimum 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_SAMPLE_COUNT = 1; - - /** Maximum 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_SAMPLE_COUNT = 8; - private static final boolean DEBUG = false; private final List<Shape> shapes = new CopyOnWriteArrayList<Shape>(); @@ -175,7 +169,7 @@ public final class Scene implements Container, GLEventListener { /** * Create a new scene with an internally created {@link RegionRenderer}, using {@link DefaultPMVMatrixSetup#DefaultPMVMatrixSetup()}. * @param sampleCount sample count for Graph Region AA {@link Region#getRenderModes() render-modes}: {@link Region#VBAA_RENDERING_BIT} or {@link Region#MSAA_RENDERING_BIT}, - * clipped to [{@link #MIN_SAMPLE_COUNT}..{@link #MAX_SAMPLE_COUNT}] + * clipped to [{@link Region#MIN_AA_SAMPLE_COUNT}..{@link Region#MAX_AA_SAMPLE_COUNT}] * @see #Scene(RegionRenderer, int) * @see #setSampleCount(int) */ @@ -187,7 +181,7 @@ public final class Scene implements Container, GLEventListener { * Create a new scene taking ownership of the given RegionRenderer, using {@link DefaultPMVMatrixSetup#DefaultPMVMatrixSetup()}. * @param renderer {@link RegionRenderer} to be owned * @param sampleCount sample count for Graph Region AA {@link Region#getRenderModes() render-modes}: {@link Region#VBAA_RENDERING_BIT} or {@link Region#MSAA_RENDERING_BIT}, - * clipped to [{@link #MIN_SAMPLE_COUNT}..{@link #MAX_SAMPLE_COUNT}] + * clipped to [{@link Region#MIN_AA_SAMPLE_COUNT}..{@link Region#MAX_AA_SAMPLE_COUNT}] * @see #setSampleCount(int) */ public Scene(final RegionRenderer renderer, final int sampleCount) { @@ -195,7 +189,7 @@ public final class Scene implements Container, GLEventListener { throw new IllegalArgumentException("Null RegionRenderer"); } this.renderer = renderer; - this.sampleCount[0] = Math.min(MAX_SAMPLE_COUNT, Math.max(sampleCount, MIN_SAMPLE_COUNT)); // clip + this.sampleCount[0] = Math.min(Region.MAX_AA_SAMPLE_COUNT, Math.max(sampleCount, Region.MIN_AA_SAMPLE_COUNT)); // clip this.screenshot = new GLReadBufferUtil(false, false); } @@ -369,36 +363,49 @@ public final class Scene implements Container, GLEventListener { public int getSampleCount() { return sampleCount[0]; } /** - * Sets sample count for Graph Region AA {@link Region#getRenderModes() render-modes}: {@link Region#VBAA_RENDERING_BIT} or {@link Region#MSAA_RENDERING_BIT} - * @param v sample count, clipped to [{@link #MIN_SAMPLE_COUNT}..{@link #MAX_SAMPLE_COUNT}] + * Sets pass2 AA sample count for Graph Region AA {@link Region#getRenderModes() render-modes}: {@link Region#VBAA_RENDERING_BIT} or {@link Region#MSAA_RENDERING_BIT} + * @param v pass2 AA sample count, clipped to [{@link Region#MIN_AA_SAMPLE_COUNT}..{@link Region#MAX_AA_SAMPLE_COUNT}] * @return clipped and set value */ public int setSampleCount(final int v) { - sampleCount[0] = Math.min(MAX_SAMPLE_COUNT, Math.max(v, MIN_SAMPLE_COUNT)); // clip - markAllShapesDirty(); + sampleCount[0] = Math.min(Region.MAX_AA_SAMPLE_COUNT, Math.max(v, Region.MIN_AA_SAMPLE_COUNT)); // clip + markStatesDirty(); return sampleCount[0]; } - public void setAllShapesQuality(final int q) { - for(int i=0; i<shapes.size(); i++) { - final Shape shape = shapes.get(i); - if( shape instanceof GraphShape ) { - ((GraphShape)shape).setQuality(q); + /** + * Sets pass2 AA-quality for Graph Region AA {@link Region#getRenderModes() render-modes}: {@link Region#VBAA_RENDERING_BIT} + * @param v pass2 AA-quality, clipped to [{@link Region#MIN_AA_QUALITY}..{@link Region#MAX_AA_QUALITY}] + * @return clipped and set value + */ + public void setAAQuality(final int v) { + final int q = Math.min(Region.MAX_AA_QUALITY, Math.max(v, Region.MIN_AA_QUALITY)); // clip + forAll((final Shape s) -> { + if( s instanceof GraphShape ) { + ((GraphShape)s).setAAQuality(q); } - } + return false; + }); } - public void setAllShapesSharpness(final float sharpness) { - for(int i=0; i<shapes.size(); i++) { - final Shape shape = shapes.get(i); - if( shape instanceof GraphShape ) { - ((GraphShape)shape).setSharpness(sharpness); + public void setSharpness(final float sharpness) { + forAll((final Shape s) -> { + if( s instanceof GraphShape ) { + ((GraphShape)s).setSharpness(sharpness); } - } + return false; + }); } - public void markAllShapesDirty() { - for(int i=0; i<shapes.size(); i++) { - shapes.get(i).markShapeDirty(); - } + public void markShapesDirty() { + forAll((final Shape s) -> { + s.markShapeDirty(); + return false; + }); + } + public void markStatesDirty() { + forAll((final Shape s) -> { + s.markStateDirty(); + return false; + }); } @Override diff --git a/src/graphui/classes/com/jogamp/graph/ui/Shape.java b/src/graphui/classes/com/jogamp/graph/ui/Shape.java index 3ba5dbb32..17b1f5344 100644 --- a/src/graphui/classes/com/jogamp/graph/ui/Shape.java +++ b/src/graphui/classes/com/jogamp/graph/ui/Shape.java @@ -536,9 +536,11 @@ public abstract class Shape { } } + /** Returns the shape's dirty state, see {@link #markShapeDirty()}. */ protected boolean isShapeDirty() { return 0 != ( dirty & DIRTY_SHAPE ) ; } + /** Returns the rendering dirty state, see {@link #markStateDirty()}. */ protected final boolean isStateDirty() { return 0 != ( dirty & DIRTY_STATE ) ; } 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(); diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PMSAAES2.java b/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PMSAAES2.java index 7abcf8818..416cf0b2b 100644 --- a/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PMSAAES2.java +++ b/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PMSAAES2.java @@ -27,6 +27,7 @@ */ package jogamp.graph.curve.opengl; +import java.io.File; import java.nio.FloatBuffer; import com.jogamp.opengl.GL2ES2; @@ -47,7 +48,9 @@ import com.jogamp.math.geom.AABBox; import com.jogamp.math.util.SyncMatrices4f16; import com.jogamp.opengl.FBObject; import com.jogamp.opengl.FBObject.Attachment; +import com.jogamp.opengl.FBObject.TextureAttachment; import com.jogamp.opengl.util.GLArrayDataServer; +import com.jogamp.opengl.util.GLReadBufferUtil; import com.jogamp.opengl.util.glsl.ShaderProgram; import com.jogamp.opengl.util.texture.Texture; import com.jogamp.opengl.util.texture.TextureSequence; @@ -55,6 +58,7 @@ import com.jogamp.opengl.util.texture.TextureSequence; public final class VBORegion2PMSAAES2 extends GLRegion { private static final boolean DEBUG_FBO_1 = false; private static final boolean DEBUG_FBO_2 = false; + private static final boolean SCREENSHOT_FBO = false; private final RenderState.ProgramLocal rsLocal; @@ -77,6 +81,8 @@ public final class VBORegion2PMSAAES2 extends GLRegion { private ShaderProgram spPass2 = null; private FBObject fbo; + private TextureAttachment texA; + private GLReadBufferUtil screenshot = SCREENSHOT_FBO ? new GLReadBufferUtil(true, false) : null; private int fboWidth = 0; private int fboHeight = 0; @@ -149,18 +155,9 @@ public final class VBORegion2PMSAAES2 extends GLRegion { indicesBuffer.enableBuffer(gl, false); vpc_ileave.seal(gl, true); vpc_ileave.enableBuffer(gl, false); - if( hasColorTexture && null != gcu_ColorTexUnit && colorTexSeq.isTextureAvailable() ) { TextureSequence.setTexCoordBBox(colorTexSeq.getLastTexture().getTexture(), box, isColorTextureLetterbox(), colorTexBBox, false); } - gca_FboVerticesAttr.seal(gl, false); - { - final FloatBuffer fb = (FloatBuffer)gca_FboVerticesAttr.getBuffer(); - fb.put( 2, box.getMinZ()); - fb.put( 5, box.getMinZ()); - fb.put( 8, box.getMinZ()); - fb.put(11, box.getMinZ()); - } // Pending gca_FboVerticesAttr-seal and fboPMVMatrix-setup, follow fboDirty // push data 2 GPU .. @@ -181,18 +178,18 @@ public final class VBORegion2PMSAAES2 extends GLRegion { * @param renderer * @param renderModes * @param pass1 - * @param quality + * @param pass2Quality * @param sampleCount */ - public void useShaderProgram(final GL2ES2 gl, final RegionRenderer renderer, final int curRenderModes, final boolean pass1, final int quality, final int sampleCount) { + public void useShaderProgram(final GL2ES2 gl, final RegionRenderer renderer, final int curRenderModes, final boolean pass1, final int pass2Quality, final int sampleCount) { final boolean isTwoPass = Region.isTwoPass( curRenderModes ); final boolean hasColorChannel = Region.hasColorChannel( curRenderModes ); final boolean hasColorTexture = Region.hasColorTexture( curRenderModes ) && null != colorTexSeq; final RenderState rs = renderer.getRenderState(); - final boolean hasAABBoxClipping = null != rs.getClipBBox(); + final boolean hasAABBoxClipping = null != rs.getClipBBox() && ( ( !isTwoPass && pass1 ) || ( isTwoPass && !pass1 ) ); - final boolean updateLocGlobal = renderer.useShaderProgram(gl, curRenderModes, pass1, quality, sampleCount, colorTexSeq); + final boolean updateLocGlobal = renderer.useShaderProgram(gl, curRenderModes, pass1, pass2Quality, sampleCount, colorTexSeq); final ShaderProgram sp = renderer.getRenderState().getShaderProgram(); final boolean updateLocLocal; if( pass1 ) { @@ -200,7 +197,7 @@ public final class VBORegion2PMSAAES2 extends GLRegion { spPass1 = sp; if( DEBUG ) { if( DEBUG_ALL_EVENT || updateLocLocal || updateLocGlobal ) { - System.err.println("XXX changedSP.p1 updateLocation loc "+updateLocLocal+" / glob "+updateLocGlobal); + System.err.println("XXX changedSP.p1 updateLocation loc "+updateLocLocal+" / glob "+updateLocGlobal+", sp "+sp.program()+" / "+sp.id()); } } if( updateLocLocal ) { @@ -209,13 +206,12 @@ public final class VBORegion2PMSAAES2 extends GLRegion { if( hasColorChannel && null != gca_ColorsAttr ) { rs.updateAttributeLoc(gl, true, gca_ColorsAttr, true); } - if( hasAABBoxClipping ) { - rs.updateUniformLoc(gl, true, gcu_ClipBBox, true); - } } - rsLocal.update(gl, rs, updateLocLocal, curRenderModes, true, true); if( isTwoPass ) { + rsLocal.update(gl, rs, updateLocLocal, curRenderModes, false, true, true); rs.updateUniformLoc(gl, updateLocLocal, gcu_PMVMatrix02, true); + } else { + rsLocal.update(gl, rs, updateLocLocal, curRenderModes, true, true, true); } if( hasColorTexture && null != gcu_ColorTexUnit ) { rs.updateUniformLoc(gl, updateLocLocal, gcu_ColorTexUnit, true); @@ -226,16 +222,19 @@ public final class VBORegion2PMSAAES2 extends GLRegion { spPass2 = sp; if( DEBUG ) { if( DEBUG_ALL_EVENT || updateLocLocal || updateLocGlobal ) { - System.err.println("XXX changedSP.p2 updateLocation loc "+updateLocLocal+" / glob "+updateLocGlobal); + System.err.println("XXX changedSP.p2 updateLocation loc "+updateLocLocal+" / glob "+updateLocGlobal+", sp "+sp.program()+" / "+sp.id()); } } if( updateLocLocal ) { rs.updateAttributeLoc(gl, true, gca_FboVerticesAttr, true); rs.updateAttributeLoc(gl, true, gca_FboTexCoordsAttr, true); } - rsLocal.update(gl, rs, updateLocLocal, curRenderModes, false, true); + rsLocal.update(gl, rs, updateLocLocal, curRenderModes, true, false, true); rs.updateUniformDataLoc(gl, updateLocLocal, false /* updateData */, gcu_FboTexUnit, true); // FIXME always update if changing tex-unit } + if( hasAABBoxClipping && updateLocLocal ) { + rs.updateUniformLoc(gl, true, gcu_ClipBBox, true); + } } private final AABBox drawWinBox = new AABBox(); @@ -244,7 +243,7 @@ public final class VBORegion2PMSAAES2 extends GLRegion { private static final int border = 2; // surrounding border, i.e. width += 2*border, height +=2*border @Override - protected void drawImpl(final GL2ES2 gl, final RegionRenderer renderer, final int curRenderModes, final int[/*1*/] sampleCount) { + protected void drawImpl(final GL2ES2 gl, final RegionRenderer renderer, final int curRenderModes, final int pass2Quality, final int[/*1*/] sampleCount) { if( 0 >= indicesBuffer.getElemCount() ) { if(DEBUG_INSTANCE) { System.err.printf("VBORegion2PMSAAES2.drawImpl: Empty%n"); @@ -260,8 +259,8 @@ public final class VBORegion2PMSAAES2 extends GLRegion { final RenderState rs = renderer.getRenderState(); final int vpWidth = renderer.getWidth(); final int vpHeight = renderer.getHeight(); - if(vpWidth <=0 || vpHeight <= 0 || null==sampleCount || sampleCount[0] <= 0) { - useShaderProgram(gl, renderer, curRenderModes, true, getQuality(), sampleCount[0]); + if(vpWidth <=0 || vpHeight <= 0 || sampleCount[0] < 0) { + useShaderProgram(gl, renderer, curRenderModes, true, pass2Quality, sampleCount[0]); renderRegion(gl, rs, curRenderModes); } else { if(0 > maxTexSize[0]) { @@ -311,9 +310,9 @@ public final class VBORegion2PMSAAES2 extends GLRegion { diffObjWidth, diffObjHeight, ratioObjWinWidth, ratioObjWinWidth, diffObjBorderWidth, diffObjBorderHeight); System.err.printf("XXX.MinMax win %s%n", drawWinBox.toString()); System.err.printf("XXX.MinMax view[%s] -> win[%.3f, %.3f], i[%d x %d], d[%.3f, %.3f], r[%f, %f]: FBO i[%d x %d], samples %d%n", - drawView, drawView, - winWidth, winHeight, targetWinWidth, targetWinHeight, diffWinWidth, - diffWinHeight, ratioWinWidth, ratioWinHeight, + drawView, + winWidth, winHeight, targetWinWidth, targetWinHeight, + diffWinWidth, diffWinHeight, ratioWinWidth, ratioWinHeight, targetFboWidth, targetFboHeight, sampleCount[0]); } @@ -331,30 +330,37 @@ public final class VBORegion2PMSAAES2 extends GLRegion { System.err.printf("XXX.Scale %d * [%f x %f]: %d x %d%n", sampleCount[0], winWidth, winHeight, targetFboWidth, targetFboHeight); } - if( hasDelta || fboDirty || isShapeDirty() || null == fbo || fbo.getNumSamples() != sampleCount[0] ) { + if( hasDelta || fboDirty || isShapeDirty() || null == fbo ) { // FIXME: rescale final float minX = box.getMinX()-diffObjBorderWidth; final float minY = box.getMinY()-diffObjBorderHeight; final float maxX = box.getMaxX()+diffObjBorderWidth+diffObjWidth; final float maxY = box.getMaxY()+diffObjBorderHeight+diffObjHeight; + final float minZ = box.getMinZ(); gca_FboVerticesAttr.seal(false); { final FloatBuffer fb = (FloatBuffer)gca_FboVerticesAttr.getBuffer(); - fb.put(0, minX); fb.put( 1, minY); - fb.put(3, minX); fb.put( 4, maxY); - fb.put(6, maxX); fb.put( 7, maxY); - fb.put(9, maxX); fb.put(10, minY); + fb.put(0, minX); fb.put( 1, minY); fb.put( 2, minZ); + fb.put(3, minX); fb.put( 4, maxY); fb.put( 5, minZ); + fb.put(6, maxX); fb.put( 7, maxY); fb.put( 8, minZ); + fb.put(9, maxX); fb.put(10, minY); fb.put(11, minZ); fb.position(12); } gca_FboVerticesAttr.seal(true); matP.setToOrtho(minX, maxX, minY, maxY, -1, 1); - useShaderProgram(gl, renderer, curRenderModes, true, getQuality(), sampleCount[0]); - renderRegion2FBO(gl, rs, curRenderModes, targetFboWidth, targetFboHeight, vpWidth, vpHeight, sampleCount); + useShaderProgram(gl, renderer, curRenderModes, true, pass2Quality, sampleCount[0]); + renderRegion2FBO(gl, rs, curRenderModes, + // (int)drawWinBox.getMinX(), (int)drawWinBox.getMinY(), targetFboWidth, targetFboHeight, + 0, 0, targetFboWidth, targetFboHeight, + vpWidth, vpHeight, sampleCount); } else if( isStateDirty() ) { - useShaderProgram(gl, renderer, curRenderModes, true, getQuality(), sampleCount[0]); - renderRegion2FBO(gl, rs, curRenderModes, targetFboWidth, targetFboHeight, vpWidth, vpHeight, sampleCount); + useShaderProgram(gl, renderer, curRenderModes, true, pass2Quality, sampleCount[0]); + renderRegion2FBO(gl, rs, curRenderModes, + // (int)drawWinBox.getMinX(), (int)drawWinBox.getMinY(), targetFboWidth, targetFboHeight, + 0, 0, targetFboWidth, targetFboHeight, + vpWidth, vpHeight, sampleCount); } - useShaderProgram(gl, renderer, curRenderModes, false, getQuality(), sampleCount[0]); + useShaderProgram(gl, renderer, curRenderModes, false, pass2Quality, sampleCount[0]); renderFBO(gl, rs, vpWidth, vpHeight, sampleCount[0]); } } @@ -376,9 +382,18 @@ public final class VBORegion2PMSAAES2 extends GLRegion { gl.glBlendFunc(GL.GL_ONE, GL.GL_ONE_MINUS_SRC_ALPHA); } + { + final AABBox cb = rs.getClipBBox(); + if( null != cb ) { + clipBBox[0] = cb.getMinX(); clipBBox[1] = cb.getMinY(); clipBBox[2] = cb.getMinZ(); + clipBBox[3] = cb.getMaxX(); clipBBox[4] = cb.getMaxY(); clipBBox[5] = cb.getMaxZ(); + gl.glUniform(gcu_ClipBBox); // Always update, since program maybe used by multiple regions + } + } + gl.glActiveTexture(GL.GL_TEXTURE0 + gcu_FboTexUnit.intValue()); - fbo.use(gl, fbo.getSamplingSink().getTextureAttachment()); + fbo.use(gl, texA); gca_FboVerticesAttr.enableBuffer(gl, true); gca_FboTexCoordsAttr.enableBuffer(gl, true); indicesFbo.bindBuffer(gl, true); // keeps VBO binding @@ -394,44 +409,58 @@ public final class VBORegion2PMSAAES2 extends GLRegion { } private void renderRegion2FBO(final GL2ES2 gl, final RenderState rs, final int curRenderModes, - final int targetFboWidth, final int targetFboHeight, + final int fboX, final int fboY, final int targetFboWidth, final int targetFboHeight, final int vpWidth, final int vpHeight, final int[] sampleCount) { if( 0 >= targetFboWidth || 0 >= targetFboHeight ) { - throw new IllegalArgumentException("fboSize must be greater than 0: "+targetFboWidth+"x"+targetFboHeight); + throw new IllegalArgumentException("targetFBOSize "+targetFboWidth+"x"+targetFboHeight+" must be greater than 0"); } - final boolean blendingEnabled = rs.isHintMaskSet(RenderState.BITHINT_BLENDING_ENABLED); + final int targetFboSamples = sampleCount[0] > 1 ? sampleCount[0] : 0; + final boolean fboSampleTypeMatch; + { + final int oldSampleCount = null != fbo ? fbo.getNumSamples() : 0; + fboSampleTypeMatch = ( oldSampleCount > 1 && targetFboSamples > 1 ) || ( oldSampleCount <= 1 && targetFboSamples <= 1 ); + } - if(null == fbo) { + if(null == fbo || !fboSampleTypeMatch) { + if( null != fbo ) { + fbo.destroy(gl); + } fboWidth = targetFboWidth; fboHeight = targetFboHeight; fbo = new FBObject(); - fbo.init(gl, fboWidth, fboHeight, sampleCount[0]); - sampleCount[0] = fbo.getNumSamples(); - fbo.attachColorbuffer(gl, 0, true); - if( !blendingEnabled ) { - // no depth-buffer w/ blending - fbo.attachRenderbuffer(gl, Attachment.Type.DEPTH, FBObject.DEFAULT_BITS); - } - final FBObject ssink = new FBObject(); - { - ssink.init(gl, fboWidth, fboHeight, 0); - // FIXME: shall not use bilinear (GL_LINEAR), due to MSAA ??? - // ssink.attachTexture2D(gl, 0, true, GL2ES2.GL_LINEAR, GL2ES2.GL_LINEAR, GL2ES2.GL_CLAMP_TO_EDGE, GL2ES2.GL_CLAMP_TO_EDGE); - ssink.attachTexture2D(gl, 0, true, GL.GL_NEAREST, GL.GL_NEAREST, GL.GL_CLAMP_TO_EDGE, GL.GL_CLAMP_TO_EDGE); + fbo.init(gl, targetFboWidth, targetFboHeight, targetFboSamples); + sampleCount[0] = Math.max(1, fbo.getNumSamples()); + if( 0 == targetFboSamples ) { + texA = fbo.attachTexture2D(gl, 0, true, GL.GL_LINEAR, GL.GL_LINEAR, GL.GL_CLAMP_TO_EDGE, GL.GL_CLAMP_TO_EDGE); if( !blendingEnabled ) { // no depth-buffer w/ blending - ssink.attachRenderbuffer(gl, Attachment.Type.DEPTH, FBObject.DEFAULT_BITS); + fbo.attachRenderbuffer(gl, Attachment.Type.DEPTH, FBObject.DEFAULT_BITS); } + } else { + fbo.attachColorbuffer(gl, 0, true); + if( !blendingEnabled ) { + // no depth-buffer w/ blending + fbo.attachRenderbuffer(gl, Attachment.Type.DEPTH, FBObject.DEFAULT_BITS); + } + final FBObject ssink = new FBObject(); + { + ssink.init(gl, targetFboWidth, targetFboHeight, 0); + texA = ssink.attachTexture2D(gl, 0, true, GL.GL_NEAREST, GL.GL_NEAREST, GL.GL_CLAMP_TO_EDGE, GL.GL_CLAMP_TO_EDGE); + if( !blendingEnabled ) { + // no depth-buffer w/ blending + ssink.attachRenderbuffer(gl, Attachment.Type.DEPTH, FBObject.DEFAULT_BITS); + } + } + fbo.setSamplingSink(ssink); + fbo.resetSamplingSink(gl); // validate } - fbo.setSamplingSink(ssink); - fbo.resetSamplingSink(gl); // validate if( DEBUG_FBO_1 ) { - System.err.printf("XXX.createFBO: blending %b, %dx%d%n%s%n", blendingEnabled, fboWidth, fboHeight, fbo.toString()); + System.err.printf("XXX.createFBO: blending %b, %dx%d%n%s%n", blendingEnabled, targetFboWidth, targetFboHeight, fbo.toString()); } - } else if( targetFboWidth != fboWidth || targetFboHeight != fboHeight || fbo.getNumSamples() != sampleCount[0] ) { - fbo.reset(gl, targetFboWidth, targetFboHeight, sampleCount[0]); - sampleCount[0] = fbo.getNumSamples(); + } else if( targetFboWidth != fboWidth || targetFboHeight != fboHeight || fbo.getNumSamples() != targetFboSamples ) { + fbo.reset(gl, targetFboWidth, targetFboHeight, targetFboSamples); + sampleCount[0] = Math.max(1, fbo.getNumSamples()); if( DEBUG_FBO_1 ) { System.err.printf("XXX.resetFBO: %dx%d -> %dx%d%n%s%n", fboWidth, fboHeight, targetFboWidth, targetFboHeight, fbo ); } @@ -441,7 +470,7 @@ public final class VBORegion2PMSAAES2 extends GLRegion { fbo.bind(gl); //render texture - gl.glViewport(0, 0, fboWidth, fboHeight); + gl.glViewport(fboX, fboY, targetFboWidth, targetFboHeight); if( blendingEnabled ) { gl.glClearColor(0f, 0f, 0f, 0.0f); gl.glClear(GL.GL_COLOR_BUFFER_BIT); // no depth-buffer w/ blending @@ -460,6 +489,14 @@ public final class VBORegion2PMSAAES2 extends GLRegion { renderRegion(gl, rs, curRenderModes); + if( SCREENSHOT_FBO ) { + screenshot.setReadBuffer(GL.GL_COLOR_ATTACHMENT0); + if(screenshot.readPixels(gl, fboX, fboY, targetFboWidth, targetFboHeight, false)) { + final File f = new File("screenshot_vboregion2pmsaa.png"); + screenshot.write(f); + } + } + fbo.unbind(gl); fboDirty = false; } @@ -469,14 +506,6 @@ public final class VBORegion2PMSAAES2 extends GLRegion { final boolean hasColorTexture = Region.hasColorTexture( curRenderModes ); gl.glUniform(gcu_PMVMatrix02); - { - final AABBox cb = rs.getClipBBox(); - if( null != cb ) { - clipBBox[0] = cb.getMinX(); clipBBox[1] = cb.getMinY(); clipBBox[2] = cb.getMinZ(); - clipBBox[3] = cb.getMaxX(); clipBBox[4] = cb.getMaxY(); clipBBox[5] = cb.getMaxZ(); - gl.glUniform(gcu_ClipBBox); // Always update, since program maybe used by multiple regions - } - } vpc_ileave.enableBuffer(gl, true); indicesBuffer.bindBuffer(gl, true); // keeps VBO binding @@ -507,6 +536,7 @@ public final class VBORegion2PMSAAES2 extends GLRegion { if(null != fbo) { fbo.destroy(gl); fbo = null; + texA = null; } if(null != gca_FboVerticesAttr) { gca_FboVerticesAttr.destroy(gl); @@ -520,6 +550,10 @@ public final class VBORegion2PMSAAES2 extends GLRegion { indicesFbo.destroy(gl); indicesFbo = null; } + if( null != screenshot ) { + screenshot.dispose(gl); + screenshot = null; + } spPass1 = null; // owned by RegionRenderer spPass2 = null; // owned by RegionRenderer } diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PVBAAES2.java b/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PVBAAES2.java index 389a1aca6..3517c7a6b 100644 --- a/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PVBAAES2.java +++ b/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PVBAAES2.java @@ -27,6 +27,7 @@ */ package jogamp.graph.curve.opengl; +import java.io.File; import java.nio.FloatBuffer; import com.jogamp.opengl.GL2ES2; @@ -38,7 +39,6 @@ import jogamp.graph.curve.opengl.shader.AttributeNames; import jogamp.graph.curve.opengl.shader.UniformNames; import jogamp.opengl.Debug; -import com.jogamp.common.util.PropertyAccess; import com.jogamp.graph.curve.Region; import com.jogamp.graph.curve.opengl.GLRegion; import com.jogamp.graph.curve.opengl.RegionRenderer; @@ -51,6 +51,7 @@ import com.jogamp.opengl.FBObject; import com.jogamp.opengl.FBObject.Attachment; import com.jogamp.opengl.FBObject.TextureAttachment; import com.jogamp.opengl.util.GLArrayDataServer; +import com.jogamp.opengl.util.GLReadBufferUtil; import com.jogamp.opengl.util.glsl.ShaderProgram; import com.jogamp.opengl.util.texture.Texture; import com.jogamp.opengl.util.texture.TextureSequence; @@ -58,37 +59,12 @@ import com.jogamp.opengl.util.texture.TextureSequence; public final class VBORegion2PVBAAES2 extends GLRegion { private static final boolean DEBUG_FBO_1 = false; private static final boolean DEBUG_FBO_2 = false; - - /** - * Boundary triggering FBO resize if - * <pre> - * fbo[Width|Height] - targetFbo[Width|Height] > RESIZE_BOUNDARY. - * </pre> - * <p> - * Increasing the FBO will add RESIZE_BOUNDARY/2. - * </p> - * <p> - * Reducing FBO resize to gain performance. - * </p> - * <p> - * Defaults to disabled since: - * - not working properly - * - FBO texture rendered > than desired size - * - FBO resize itself should be fast enough ?! - * </p> - */ - private static final int RESIZE_BOUNDARY; + private static final boolean SCREENSHOT_FBO = false; static { Debug.initSingleton(); - final String key = "jogl.debug.graph.curve.vbaa.resizeLowerBoundary"; - RESIZE_BOUNDARY = Math.max(0, PropertyAccess.getIntProperty(key, true, 0)); - if( RESIZE_BOUNDARY > 0 ) { - System.err.println("key: "+RESIZE_BOUNDARY); - } } - private final RenderState.ProgramLocal rsLocal; // Pass-1: @@ -112,6 +88,7 @@ public final class VBORegion2PVBAAES2 extends GLRegion { private FBObject fbo; private TextureAttachment texA; + private GLReadBufferUtil screenshot = SCREENSHOT_FBO ? new GLReadBufferUtil(true, false) : null; private int fboWidth = 0; private int fboHeight = 0; @@ -129,18 +106,18 @@ public final class VBORegion2PVBAAES2 extends GLRegion { * @param renderer * @param curRenderModes * @param pass1 - * @param quality + * @param pass2Quality * @param sampleCount */ - public void useShaderProgram(final GL2ES2 gl, final RegionRenderer renderer, final int curRenderModes, final boolean pass1, final int quality, final int sampleCount) { + public void useShaderProgram(final GL2ES2 gl, final RegionRenderer renderer, final int curRenderModes, final boolean pass1, final int pass2Quality, final int sampleCount) { final boolean isTwoPass = Region.isTwoPass( curRenderModes ); final boolean hasColorChannel = Region.hasColorChannel( curRenderModes ); final boolean hasColorTexture = Region.hasColorTexture( curRenderModes ) && null != colorTexSeq; final RenderState rs = renderer.getRenderState(); - final boolean hasAABBoxClipping = null != rs.getClipBBox(); + final boolean hasAABBoxClipping = null != rs.getClipBBox() && ( ( !isTwoPass && pass1 ) || ( isTwoPass && !pass1 ) ); - final boolean updateLocGlobal = renderer.useShaderProgram(gl, curRenderModes, pass1, quality, sampleCount, colorTexSeq); + final boolean updateLocGlobal = renderer.useShaderProgram(gl, curRenderModes, pass1, pass2Quality, sampleCount, colorTexSeq); final ShaderProgram sp = renderer.getRenderState().getShaderProgram(); final boolean updateLocLocal; if( pass1 ) { @@ -148,7 +125,7 @@ public final class VBORegion2PVBAAES2 extends GLRegion { spPass1 = sp; if( DEBUG ) { if( DEBUG_ALL_EVENT || updateLocLocal || updateLocGlobal ) { - System.err.println("XXX changedSP.p1 updateLocation loc "+updateLocLocal+" / glob "+updateLocGlobal); + System.err.println("XXX changedSP.p1 updateLocation loc "+updateLocLocal+" / glob "+updateLocGlobal+", sp "+sp.program()+" / "+sp.id()); } } if( updateLocLocal ) { @@ -157,13 +134,12 @@ public final class VBORegion2PVBAAES2 extends GLRegion { if( hasColorChannel && null != gca_ColorsAttr ) { rs.updateAttributeLoc(gl, true, gca_ColorsAttr, true); } - if( hasAABBoxClipping ) { - rs.updateUniformLoc(gl, true, gcu_ClipBBox, true); - } } - rsLocal.update(gl, rs, updateLocLocal, curRenderModes, true, true); if( isTwoPass ) { + rsLocal.update(gl, rs, updateLocLocal, curRenderModes, false, true, true); rs.updateUniformLoc(gl, updateLocLocal, gcu_PMVMatrix02, true); + } else { + rsLocal.update(gl, rs, updateLocLocal, curRenderModes, true, true, true); } if( hasColorTexture && null != gcu_ColorTexUnit ) { rs.updateUniformLoc(gl, updateLocLocal, gcu_ColorTexUnit, true); @@ -174,17 +150,20 @@ public final class VBORegion2PVBAAES2 extends GLRegion { spPass2 = sp; if( DEBUG ) { if( DEBUG_ALL_EVENT || updateLocLocal || updateLocGlobal ) { - System.err.println("XXX changedSP.p2 updateLocation loc "+updateLocLocal+" / glob "+updateLocGlobal); + System.err.println("XXX changedSP.p2 updateLocation loc "+updateLocLocal+" / glob "+updateLocGlobal+", sp "+sp.program()+" / "+sp.id()); } } if( updateLocLocal ) { rs.updateAttributeLoc(gl, true, gca_FboVerticesAttr, true); rs.updateAttributeLoc(gl, true, gca_FboTexCoordsAttr, true); } - rsLocal.update(gl, rs, updateLocLocal, curRenderModes, false, true); + rsLocal.update(gl, rs, updateLocLocal, curRenderModes, true, false, true); rs.updateUniformDataLoc(gl, updateLocLocal, false /* updateData */, gcu_FboTexUnit, true); // FIXME always update if changing tex-unit rs.updateUniformLoc(gl, updateLocLocal, gcu_FboTexSize, sampleCount > 1); // maybe optimized away for sampleCount <= 1 } + if( hasAABBoxClipping && updateLocLocal ) { + rs.updateUniformLoc(gl, true, gcu_ClipBBox, true); + } } public VBORegion2PVBAAES2(final GLProfile glp, final int renderModes, final TextureSequence colorTexSeq, final int pass2TexUnit, @@ -254,14 +233,6 @@ public final class VBORegion2PVBAAES2 extends GLRegion { if( hasColorTexture && null != gcu_ColorTexUnit && colorTexSeq.isTextureAvailable() ) { TextureSequence.setTexCoordBBox(colorTexSeq.getLastTexture().getTexture(), box, isColorTextureLetterbox(), colorTexBBox, false); } - gca_FboVerticesAttr.seal(gl, false); - { - final FloatBuffer fb = (FloatBuffer)gca_FboVerticesAttr.getBuffer(); - fb.put( 2, box.getMinZ()); - fb.put( 5, box.getMinZ()); - fb.put( 8, box.getMinZ()); - fb.put(11, box.getMinZ()); - } // Pending gca_FboVerticesAttr-seal and fboPMVMatrix-setup, follow fboDirty // push data 2 GPU .. @@ -278,7 +249,7 @@ public final class VBORegion2PVBAAES2 extends GLRegion { private static final int border = 2; // surrounding border, i.e. width += 2*border, height +=2*border @Override - protected void drawImpl(final GL2ES2 gl, final RegionRenderer renderer, final int curRenderModes, final int[/*1*/] sampleCount) { + protected void drawImpl(final GL2ES2 gl, final RegionRenderer renderer, final int curRenderModes, final int pass2Quality, final int[/*1*/] sampleCount) { if( 0 >= indicesBuffer.getElemCount() ) { if(DEBUG_INSTANCE) { System.err.printf("VBORegion2PVBAAES2.drawImpl: Empty%n"); @@ -294,8 +265,8 @@ public final class VBORegion2PVBAAES2 extends GLRegion { final RenderState rs = renderer.getRenderState(); final int vpWidth = renderer.getWidth(); final int vpHeight = renderer.getHeight(); - if(vpWidth <=0 || vpHeight <= 0 || null==sampleCount || sampleCount[0] <= 0) { - useShaderProgram(gl, renderer, curRenderModes, true, getQuality(), sampleCount[0]); + if(vpWidth <=0 || vpHeight <= 0 || sampleCount[0] < 0) { + useShaderProgram(gl, renderer, curRenderModes, true, pass2Quality, sampleCount[0]); renderRegion(gl, rs, curRenderModes); } else { if(0 > maxTexSize[0]) { @@ -355,8 +326,8 @@ public final class VBORegion2PVBAAES2 extends GLRegion { System.err.printf("XXX.MinMax win %s%n", drawWinBox.toString()); System.err.printf("XXX.MinMax view[%s] -> win[%.3f, %.3f], i[%d x %d], d[%.3f, %.3f], r[%f, %f]: FBO f[%.3f, %.3f], i[%d x %d], d[%.3f, %.3f], r[%f, %f], samples %d%n", drawView, - winWidth, winHeight, targetWinWidth, targetWinHeight, diffWinWidth, - diffWinHeight, ratioWinWidth, ratioWinHeight, + winWidth, winHeight, targetWinWidth, targetWinHeight, + diffWinWidth, diffWinHeight, ratioWinWidth, ratioWinHeight, renderFboWidth, renderFboHeight, targetFboWidth, targetFboHeight, diffFboWidth, diffFboHeight, ratioFboWidth, ratioFboHeight, sampleCount[0]); @@ -400,70 +371,35 @@ public final class VBORegion2PVBAAES2 extends GLRegion { } } - final int newFboWidth, newFboHeight, resizeCase; - if( 0 >= RESIZE_BOUNDARY ) { - // Resize w/o optimization - newFboWidth = targetFboWidth; - newFboHeight = targetFboHeight; - resizeCase = 0; - } else { - if( 0 >= fboWidth || 0 >= fboHeight || null == fbo ) { - // Case: New FBO - newFboWidth = targetFboWidth; - newFboHeight = targetFboHeight; - resizeCase = 1; - } else if( targetFboWidth > fboWidth || targetFboHeight > fboHeight ) { - // Case: Inscrease FBO Size, add boundary/2 if avail - newFboWidth = ( targetFboWidth + RESIZE_BOUNDARY/2 < maxTexSize[0] ) ? targetFboWidth + RESIZE_BOUNDARY/2 : targetFboWidth; - newFboHeight = ( targetFboHeight+ RESIZE_BOUNDARY/2 < maxTexSize[0] ) ? targetFboHeight + RESIZE_BOUNDARY/2 : targetFboHeight; - resizeCase = 2; - } else if( targetFboWidth < fboWidth && targetFboHeight < fboHeight && - fboWidth - targetFboWidth < RESIZE_BOUNDARY && - fboHeight - targetFboHeight < RESIZE_BOUNDARY ) { - // Case: Decreased FBO Size Request within boundary - newFboWidth = fboWidth; - newFboHeight = fboHeight; - resizeCase = 3; - } else { - // Case: Decreased-Size-Beyond-Boundary or No-Resize - newFboWidth = targetFboWidth; - newFboHeight = targetFboHeight; - resizeCase = 4; - } - } - final int dResizeWidth = newFboWidth - targetFboWidth; - final int dResizeHeight = newFboHeight - targetFboHeight; - final float diffObjResizeWidth = dResizeWidth*ratioObjWinWidth; - final float diffObjResizeHeight = dResizeHeight*ratioObjWinHeight; - if( DEBUG_FBO_1 ) { - System.err.printf("XXX.resizeFBO: case %d, has %dx%d > target %dx%d, resize: i[%d x %d], f[%.3f x %.3f] -> %dx%d%n", - resizeCase, fboWidth, fboHeight, targetFboWidth, targetFboHeight, - dResizeWidth, dResizeHeight, diffObjResizeWidth, diffObjResizeHeight, - newFboWidth, newFboHeight); - } - final float minX = box.getMinX()-diffObjBorderWidth; final float minY = box.getMinY()-diffObjBorderHeight; - final float maxX = box.getMaxX()+diffObjBorderWidth+diffObjWidth+diffObjResizeWidth; - final float maxY = box.getMaxY()+diffObjBorderHeight+diffObjHeight+diffObjResizeHeight; + final float maxX = box.getMaxX()+diffObjBorderWidth+diffObjWidth; + final float maxY = box.getMaxY()+diffObjBorderHeight+diffObjHeight; + final float minZ = box.getMinZ(); gca_FboVerticesAttr.seal(false); { final FloatBuffer fb = (FloatBuffer)gca_FboVerticesAttr.getBuffer(); - fb.put(0, minX); fb.put( 1, minY); - fb.put(3, minX); fb.put( 4, maxY); - fb.put(6, maxX); fb.put( 7, maxY); - fb.put(9, maxX); fb.put(10, minY); + fb.put(0, minX); fb.put( 1, minY); fb.put( 2, minZ); + fb.put(3, minX); fb.put( 4, maxY); fb.put( 5, minZ); + fb.put(6, maxX); fb.put( 7, maxY); fb.put( 8, minZ); + fb.put(9, maxX); fb.put(10, minY); fb.put(11, minZ); fb.position(12); } gca_FboVerticesAttr.seal(true); matP.setToOrtho(minX, maxX, minY, maxY, -1, 1); - useShaderProgram(gl, renderer, curRenderModes, true, getQuality(), sampleCount[0]); - renderRegion2FBO(gl, rs, curRenderModes, targetFboWidth, targetFboHeight, newFboWidth, newFboHeight, vpWidth, vpHeight, sampleCount[0]); + useShaderProgram(gl, renderer, curRenderModes, true, pass2Quality, sampleCount[0]); + renderRegion2FBO(gl, rs, curRenderModes, + // (int)drawWinBox.getMinX(), (int)drawWinBox.getMinY(), targetFboWidth, targetFboHeight, + 0, 0, targetFboWidth, targetFboHeight, + vpWidth, vpHeight, sampleCount[0]); } else if( isStateDirty() ) { - useShaderProgram(gl, renderer, curRenderModes, true, getQuality(), sampleCount[0]); - renderRegion2FBO(gl, rs, curRenderModes, targetFboWidth, targetFboHeight, fboWidth, fboHeight, vpWidth, vpHeight, sampleCount[0]); + useShaderProgram(gl, renderer, curRenderModes, true, pass2Quality, sampleCount[0]); + renderRegion2FBO(gl, rs, curRenderModes, + // (int)drawWinBox.getMinX(), (int)drawWinBox.getMinY(), targetFboWidth, targetFboHeight, + 0, 0, targetFboWidth, targetFboHeight, + vpWidth, vpHeight, sampleCount[0]); } - useShaderProgram(gl, renderer, curRenderModes, false, getQuality(), sampleCount[0]); + useShaderProgram(gl, renderer, curRenderModes, false, pass2Quality, sampleCount[0]); renderFBO(gl, rs, targetFboWidth, targetFboHeight, vpWidth, vpHeight, sampleCount[0]); } } @@ -483,6 +419,14 @@ public final class VBORegion2PVBAAES2 extends GLRegion { } gl.glUniform(gcu_FboTexSize); + { + final AABBox cb = rs.getClipBBox(); + if( null != cb ) { + clipBBox[0] = cb.getMinX(); clipBBox[1] = cb.getMinY(); clipBBox[2] = cb.getMinZ(); + clipBBox[3] = cb.getMaxX(); clipBBox[4] = cb.getMaxY(); clipBBox[5] = cb.getMaxZ(); + gl.glUniform(gcu_ClipBBox); // Always update, since program maybe used by multiple regions + } + } gl.glActiveTexture(GL.GL_TEXTURE0 + gcu_FboTexUnit.intValue()); @@ -502,54 +446,56 @@ public final class VBORegion2PVBAAES2 extends GLRegion { } private void renderRegion2FBO(final GL2ES2 gl, final RenderState rs, final int curRenderModes, - final int targetFboWidth, final int targetFboHeight, final int newFboWidth, final int newFboHeight, + final int fboX, final int fboY, final int targetFboWidth, final int targetFboHeight, final int vpWidth, final int vpHeight, final int sampleCount) { if( 0 >= targetFboWidth || 0 >= targetFboHeight ) { - throw new IllegalArgumentException("fboSize must be greater than 0: "+targetFboWidth+"x"+targetFboHeight); + throw new IllegalArgumentException("targetFBOSize "+targetFboWidth+"x"+targetFboHeight+" must be greater than 0"); } - final boolean blendingEnabled = rs.isHintMaskSet(RenderState.BITHINT_BLENDING_ENABLED); if(null == fbo) { - fboWidth = newFboWidth; - fboHeight = newFboHeight; + fboWidth = targetFboWidth; + fboHeight = targetFboHeight; final FloatBuffer fboTexSize = (FloatBuffer) gcu_FboTexSize.getBuffer(); { - fboTexSize.put(0, fboWidth); - fboTexSize.put(1, fboHeight); + fboTexSize.put(0, targetFboWidth); + fboTexSize.put(1, targetFboHeight); } fbo = new FBObject(); - fbo.init(gl, fboWidth, fboHeight, 0); - // Shall not use bilinear (GL_LINEAR), due to own VBAA. Result is smooth w/o it now! - // FIXME: FXAA requires bilinear filtering! - // texA = fbo.attachTexture2D(gl, 0, true, GL.GL_LINEAR, GL.GL_LINEAR, GL.GL_CLAMP_TO_EDGE, GL.GL_CLAMP_TO_EDGE); - texA = fbo.attachTexture2D(gl, 0, true, GL.GL_NEAREST, GL.GL_NEAREST, GL.GL_CLAMP_TO_EDGE, GL.GL_CLAMP_TO_EDGE); + fbo.init(gl, targetFboWidth, targetFboHeight, 0); + if( sampleCount > 1 ) { + // Shall not use bilinear (GL_LINEAR), due to own VBAA. Result is smooth w/o it now! + // FIXME: FXAA requires bilinear filtering! + texA = fbo.attachTexture2D(gl, 0, true, GL.GL_NEAREST, GL.GL_NEAREST, GL.GL_CLAMP_TO_EDGE, GL.GL_CLAMP_TO_EDGE); + } else { + texA = fbo.attachTexture2D(gl, 0, true, GL.GL_LINEAR, GL.GL_LINEAR, GL.GL_CLAMP_TO_EDGE, GL.GL_CLAMP_TO_EDGE); + } if( !blendingEnabled ) { // no depth-buffer w/ blending fbo.attachRenderbuffer(gl, Attachment.Type.DEPTH, FBObject.DEFAULT_BITS); } if( DEBUG_FBO_1 ) { - System.err.printf("XXX.createFBO: %dx%d%n%s%n", fboWidth, fboHeight, fbo.toString()); + System.err.printf("XXX.createFBO: %dx%d%n%s%n", targetFboWidth, targetFboHeight, fbo.toString()); } - } else if( newFboWidth != fboWidth || newFboHeight != fboHeight ) { - fbo.reset(gl, newFboWidth, newFboHeight, 0); + } else if( targetFboWidth != fboWidth || targetFboHeight != fboHeight ) { + fbo.reset(gl, targetFboWidth, targetFboHeight, 0); fbo.bind(gl); if( DEBUG_FBO_1 ) { - System.err.printf("XXX.resetFBO: %dx%d -> %dx%d, target %dx%d%n", fboWidth, fboHeight, newFboWidth, newFboHeight, targetFboWidth, targetFboHeight); + System.err.printf("XXX.resetFBO: %dx%d -> %dx%d%n%s%n", fboWidth, fboHeight, targetFboWidth, targetFboHeight, fbo.toString()); } - fboWidth = newFboWidth; - fboHeight = newFboHeight; + fboWidth = targetFboWidth; + fboHeight = targetFboHeight; final FloatBuffer fboTexSize = (FloatBuffer) gcu_FboTexSize.getBuffer(); { - fboTexSize.put(0, fboWidth); - fboTexSize.put(1, fboHeight); + fboTexSize.put(0, targetFboWidth); + fboTexSize.put(1, targetFboHeight); } } else { fbo.bind(gl); } //render texture - gl.glViewport(0, 0, fboWidth, fboHeight); + gl.glViewport(fboX, fboY, targetFboWidth, targetFboHeight); if( blendingEnabled ) { gl.glClearColor(0f, 0f, 0f, 0.0f); gl.glClear(GL.GL_COLOR_BUFFER_BIT); // no depth-buffer w/ blending @@ -564,6 +510,14 @@ public final class VBORegion2PVBAAES2 extends GLRegion { renderRegion(gl, rs, curRenderModes); + if( SCREENSHOT_FBO ) { + screenshot.setReadBuffer(GL.GL_COLOR_ATTACHMENT0); + if(screenshot.readPixels(gl, fboX, fboY, targetFboWidth, targetFboHeight, false)) { + final File f = new File("screenshot_vboregion2pvbaa.png"); + screenshot.write(f); + } + } + fbo.unbind(gl); fboDirty = false; } @@ -573,14 +527,6 @@ public final class VBORegion2PVBAAES2 extends GLRegion { final boolean hasColorTexture = Region.hasColorTexture( curRenderModes ); gl.glUniform(gcu_PMVMatrix02); - { - final AABBox cb = rs.getClipBBox(); - if( null != cb ) { - clipBBox[0] = cb.getMinX(); clipBBox[1] = cb.getMinY(); clipBBox[2] = cb.getMinZ(); - clipBBox[3] = cb.getMaxX(); clipBBox[4] = cb.getMaxY(); clipBBox[5] = cb.getMaxZ(); - gl.glUniform(gcu_ClipBBox); // Always update, since program maybe used by multiple regions - } - } vpc_ileave.enableBuffer(gl, true); indicesBuffer.bindBuffer(gl, true); // keeps VBO binding @@ -627,6 +573,10 @@ public final class VBORegion2PVBAAES2 extends GLRegion { indicesFbo.destroy(gl); indicesFbo = null; } + if( null != screenshot ) { + screenshot.dispose(gl); + screenshot = null; + } spPass1 = null; // owned by RegionRenderer spPass2 = null; // owned by RegionRenderer } diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/VBORegionSPES2.java b/src/jogl/classes/jogamp/graph/curve/opengl/VBORegionSPES2.java index 281757da4..26748136e 100644 --- a/src/jogl/classes/jogamp/graph/curve/opengl/VBORegionSPES2.java +++ b/src/jogl/classes/jogamp/graph/curve/opengl/VBORegionSPES2.java @@ -115,22 +115,22 @@ public final class VBORegionSPES2 extends GLRegion { * @param gl * @param renderer * @param curRenderModes - * @param quality + * @param pass2Quality */ - public void useShaderProgram(final GL2ES2 gl, final RegionRenderer renderer, final int curRenderModes, final int quality) { + public void useShaderProgram(final GL2ES2 gl, final RegionRenderer renderer, final int curRenderModes) { final boolean hasColorChannel = Region.hasColorChannel( curRenderModes ); final boolean hasColorTexture = Region.hasColorTexture( curRenderModes ) && null != colorTexSeq; final RenderState rs = renderer.getRenderState(); final boolean hasAABBoxClipping = null != rs.getClipBBox(); - final boolean updateLocGlobal = renderer.useShaderProgram(gl, curRenderModes, true, quality, 0, colorTexSeq); + final boolean updateLocGlobal = renderer.useShaderProgram(gl, curRenderModes, true, 0 /* pass2Quality */, 0 /* sampleCount */, colorTexSeq); final ShaderProgram sp = renderer.getRenderState().getShaderProgram(); final boolean updateLocLocal = !sp.equals(spPass1); spPass1 = sp; if( DEBUG ) { if( DEBUG_ALL_EVENT || updateLocLocal || updateLocGlobal ) { - System.err.println("XXX changedSP.p1 updateLocation loc "+updateLocLocal+" / glob "+updateLocGlobal); + System.err.println("XXX changedSP.p1 updateLocation loc "+updateLocLocal+" / glob "+updateLocGlobal+", sp "+sp.program()+" / "+sp.id()); } } if( updateLocLocal ) { @@ -143,7 +143,7 @@ public final class VBORegionSPES2 extends GLRegion { rs.updateUniformLoc(gl, true, gcu_ClipBBox, throwOnError); } } - rsLocal.update(gl, rs, updateLocLocal, curRenderModes, true, throwOnError); + rsLocal.update(gl, rs, updateLocLocal, curRenderModes, true, true, throwOnError); if( hasColorTexture && null != gcu_ColorTexUnit ) { rs.updateUniformLoc(gl, updateLocLocal, gcu_ColorTexUnit, throwOnError); rs.updateUniformLoc(gl, updateLocLocal, gcu_ColorTexBBox, throwOnError); @@ -152,11 +152,11 @@ public final class VBORegionSPES2 extends GLRegion { @Override - protected void drawImpl(final GL2ES2 gl, final RegionRenderer renderer, final int curRenderModes, final int[/*1*/] sampleCount) { + protected void drawImpl(final GL2ES2 gl, final RegionRenderer renderer, final int curRenderModes, final int pass2Quality, final int[/*1*/] sampleCount) { // final boolean hasColorChannel = Region.hasColorChannel( curRenderModes ); final boolean hasColorTexture = Region.hasColorTexture( curRenderModes ); - useShaderProgram(gl, renderer, curRenderModes, getQuality()); + useShaderProgram(gl, renderer, curRenderModes); { final AABBox cb = renderer.getClipBBox(); if( null != cb ) { diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass1.vp b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass1.vp index b9974b97d..cfec523e9 100644 --- a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass1.vp +++ b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass1.vp @@ -23,10 +23,7 @@ void main(void) gcv_CurveParam = gca_CurveParams; } #endif -#ifdef USE_AABBOX_CLIPPING - gcv_ClipBBoxCoord = (gcu_PMVMatrix02[1] * gca_Vertices).xyz; // Mv -#endif - + #ifdef USE_COLOR_TEXTURE gcv_ColorTexCoord = ( gca_Vertices.xy - gcu_ColorTexBBox[0] ) / ( gcu_ColorTexBBox[1] - gcu_ColorTexBBox[0] ); #endif diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-msaa.glsl b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-msaa.glsl index 36d70cbdf..3d4cdc887 100644 --- a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-msaa.glsl +++ b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-msaa.glsl @@ -1,4 +1,14 @@ - // Pass-2: Dump Texture + // Pass-2: Dump Texture +#ifdef USE_AABBOX_CLIPPING + if( is_inside(gcv_ClipBBoxCoord, gcu_ClipBBox[0], gcu_ClipBBox[1]) < 0.5 ) { + #if USE_DISCARD + discard; // discard freezes NV tegra2 compiler + #else + mgl_FragColor = vec4(0); + #endif + } else +#endif + { vec4 t = texture2D(gcu_FboTexUnit, gcv_FboTexCoord.st); #if USE_DISCARD if( 0.0 == t.a ) { @@ -9,4 +19,5 @@ #else mgl_FragColor = t; #endif + } diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-vbaa_bforce_even.glsl b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-vbaa_bforce_even.glsl index e83e21a55..5e14a1a23 100644 --- a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-vbaa_bforce_even.glsl +++ b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-vbaa_bforce_even.glsl @@ -1,6 +1,16 @@ - // Pass-2: AA on Texture - // Note: gcv_FboTexCoord is in center of sample pixels. + // Pass-2: AA on Texture + // Note: gcv_FboTexCoord is in center of sample pixels. +#ifdef USE_AABBOX_CLIPPING + if( is_inside(gcv_ClipBBoxCoord, gcu_ClipBBox[0], gcu_ClipBBox[1]) < 0.5 ) { + #if USE_DISCARD + discard; // discard freezes NV tegra2 compiler + #else + mgl_FragColor = vec4(0); + #endif + } else +#endif + { // float sample_count = gcu_FboTexSize.z; vec2 psize = 1.0 / gcu_FboTexSize.xy; // pixel size @@ -97,4 +107,5 @@ #else mgl_FragColor = t; #endif + } diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-vbaa_bforce_odd.glsl b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-vbaa_bforce_odd.glsl index a3c61e595..b7d2e0e4e 100644 --- a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-vbaa_bforce_odd.glsl +++ b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-vbaa_bforce_odd.glsl @@ -1,6 +1,16 @@ - // Pass-2: AA on Texture - // Note: gcv_FboTexCoord is in center of sample pixels. + // Pass-2: AA on Texture + // Note: gcv_FboTexCoord is in center of sample pixels. +#ifdef USE_AABBOX_CLIPPING + if( is_inside(gcv_ClipBBoxCoord, gcu_ClipBBox[0], gcu_ClipBBox[1]) < 0.5 ) { + #if USE_DISCARD + discard; // discard freezes NV tegra2 compiler + #else + mgl_FragColor = vec4(0); + #endif + } else +#endif + { // float sample_count = gcu_FboTexSize.z; vec2 psize = 1.0 / gcu_FboTexSize.xy; // pixel size @@ -88,4 +98,5 @@ #else mgl_FragColor = t; #endif + } diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-vbaa_flipquad3.glsl b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-vbaa_flipquad3.glsl index bc0044aab..da0306425 100644 --- a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-vbaa_flipquad3.glsl +++ b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2-vbaa_flipquad3.glsl @@ -4,6 +4,16 @@ // // Same as flipquad - but w/ rgss coordinates +#ifdef USE_AABBOX_CLIPPING + if( is_inside(gcv_ClipBBoxCoord, gcu_ClipBBox[0], gcu_ClipBBox[1]) < 0.5 ) { + #if USE_DISCARD + discard; // discard freezes NV tegra2 compiler + #else + mgl_FragColor = vec4(0); + #endif + } else +#endif + { // float sample_count = gcu_FboTexSize.z; vec2 psize = 1.0 / gcu_FboTexSize.xy; // pixel size @@ -108,4 +118,4 @@ #else mgl_FragColor = t; #endif - + } diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2.vp b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2.vp index 64857c9ce..e4087cbd6 100644 --- a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2.vp +++ b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass2.vp @@ -13,5 +13,10 @@ void main(void) { // gl_Position = gcu_PMVMatrix01[0] * gcu_PMVMatrix01[1] * vec4(gca_FboVertices, 1); gl_Position = gcu_PMVMatrix01[0] * gcu_PMVMatrix01[1] * gca_FboVertices; + +#ifdef USE_AABBOX_CLIPPING + gcv_ClipBBoxCoord = (gcu_PMVMatrix01[1] * gca_FboVertices).xyz; // Mv +#endif + gcv_FboTexCoord = gca_FboTexCoords; } diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-single.vp b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-single.vp index 9518834b0..2f07ad7d0 100644 --- a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-single.vp +++ b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-single.vp @@ -23,6 +23,7 @@ void main(void) gcv_CurveParam = gca_CurveParams; } #endif + #ifdef USE_AABBOX_CLIPPING gcv_ClipBBoxCoord = (gcu_PMVMatrix01[1] * gca_Vertices).xyz; // Mv #endif diff --git a/src/jogl/classes/jogamp/opengl/util/av/GLMediaPlayerImpl.java b/src/jogl/classes/jogamp/opengl/util/av/GLMediaPlayerImpl.java index 457157285..4a7e52c4f 100644 --- a/src/jogl/classes/jogamp/opengl/util/av/GLMediaPlayerImpl.java +++ b/src/jogl/classes/jogamp/opengl/util/av/GLMediaPlayerImpl.java @@ -65,7 +65,6 @@ import com.jogamp.common.util.WorkerThread; import com.jogamp.math.FloatUtil; import com.jogamp.opengl.GLExtensions; import com.jogamp.opengl.util.av.GLMediaPlayer; -import com.jogamp.opengl.util.av.GLMediaPlayer.Chapter; import com.jogamp.opengl.util.glsl.ShaderCode; import com.jogamp.opengl.util.texture.Texture; import com.jogamp.opengl.util.texture.TextureData; @@ -274,7 +273,7 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { protected int getAudioChannelLimit() { return userMaxChannels; } @Override - public String getRequiredExtensionsShaderStub() { + public final String getRequiredExtensionsShaderStub() { if(GLES2.GL_TEXTURE_EXTERNAL_OES == textureTarget) { return ShaderCode.createExtensionDirective(GLExtensions.OES_EGL_image_external, ShaderCode.ENABLE); } @@ -282,7 +281,7 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { } @Override - public String getTextureSampler2DType() { + public final String getTextureSampler2DType() { switch(textureTarget) { case GL.GL_TEXTURE_2D: case GL2GL3.GL_TEXTURE_RECTANGLE: @@ -305,6 +304,7 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { @Override public String setTextureLookupFunctionName(final String texLookupFuncName) throws IllegalStateException { textureLookupFunctionName = "texture2D"; + resetTextureFragmentShaderHashCode(); return textureLookupFunctionName; } @@ -332,18 +332,23 @@ public abstract class GLMediaPlayerImpl implements GLMediaPlayer { } @Override + public String getTextureFragmentShaderHashID() { + // return getTextureSampler2DType()+";"+getTextureLookupFunctionName()+";"+getTextureLookupFragmentShaderImpl(); + return getTextureSampler2DType()+";"+getTextureLookupFunctionName(); + } + + @Override public final int getTextureFragmentShaderHashCode() { if( State.Uninitialized == state ) { - textureFragmentShaderHashCode = 0; + resetTextureFragmentShaderHashCode(); return 0; } else if( 0 == textureFragmentShaderHashCode ) { - int hash = 31 + getTextureLookupFunctionName().hashCode(); - hash = ((hash << 5) - hash) + getTextureLookupFragmentShaderImpl().hashCode(); - hash = ((hash << 5) - hash) + getTextureSampler2DType().hashCode(); + final int hash = getTextureFragmentShaderHashID().hashCode(); textureFragmentShaderHashCode = hash; } return textureFragmentShaderHashCode; } + protected final void resetTextureFragmentShaderHashCode() { textureFragmentShaderHashCode = 0; } @Override public final int getDecodedFrameCount() { return decodedFrameCount; } diff --git a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGMediaPlayer.java b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGMediaPlayer.java index 78c20d90a..4e1effb02 100644 --- a/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGMediaPlayer.java +++ b/src/jogl/classes/jogamp/opengl/util/av/impl/FFMPEGMediaPlayer.java @@ -751,6 +751,7 @@ public class FFMPEGMediaPlayer extends GLMediaPlayerImpl { } else { textureLookupFunctionName = "ffmpegTexture2D"; } + resetTextureFragmentShaderHashCode(); return textureLookupFunctionName; } @@ -762,7 +763,10 @@ public class FFMPEGMediaPlayer extends GLMediaPlayerImpl { */ @Override public final String getTextureLookupFragmentShaderImpl() { - final float tc_w_1 = (float)getWidth() / (float)texWidth; + final float tc_w_1 = (float)getWidth() / (float)texWidth; + return getTextureLookupFragmentShaderImpl(tc_w_1); + } + private final String getTextureLookupFragmentShaderImpl(final float tc_w_1) { final String texLookupFuncName = getTextureLookupFunctionName(); if( texLookupFuncName.equals("texture2D") ) { throw new IllegalArgumentException("Build in 'texture2D' lookup-func-name not allowed!"); @@ -919,6 +923,12 @@ public class FFMPEGMediaPlayer extends GLMediaPlayerImpl { } @Override + public final String getTextureFragmentShaderHashID() { + // return getTextureSampler2DType()+";"+getTextureLookupFunctionName()+";"+getTextureLookupFragmentShaderImpl(1.0f); + return getTextureLookupFragmentShaderImpl(1.0f); // state-less shader code required using 1.0 + } + + @Override public final boolean resumeImpl() { if(0==moviePtr) { return false; diff --git a/src/test/com/jogamp/opengl/test/junit/graph/GPURegionGLListener01.java b/src/test/com/jogamp/opengl/test/junit/graph/GPURegionGLListener01.java index 1146d7a5f..68ddfbe0b 100644 --- a/src/test/com/jogamp/opengl/test/junit/graph/GPURegionGLListener01.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/GPURegionGLListener01.java @@ -32,6 +32,7 @@ import com.jogamp.opengl.GL; import com.jogamp.opengl.GL2ES2; import com.jogamp.opengl.GLAutoDrawable; import com.jogamp.graph.curve.OutlineShape; +import com.jogamp.graph.curve.Region; import com.jogamp.graph.curve.opengl.GLRegion; import com.jogamp.graph.curve.opengl.RenderState; import com.jogamp.math.Vec4f; @@ -289,7 +290,7 @@ public class GPURegionGLListener01 extends GPURendererListenerBase01 { regionRenderer.setWeight(weight); } regionRenderer.enable(gl, true); - region.draw(gl, regionRenderer, getSampleCount()); + region.draw(gl, regionRenderer, Region.MAX_AA_QUALITY, getSampleCount()); regionRenderer.enable(gl, false); } } diff --git a/src/test/com/jogamp/opengl/test/junit/graph/GPURegionGLListener10.java b/src/test/com/jogamp/opengl/test/junit/graph/GPURegionGLListener10.java index 78d17624c..efe3db1f9 100644 --- a/src/test/com/jogamp/opengl/test/junit/graph/GPURegionGLListener10.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/GPURegionGLListener10.java @@ -130,7 +130,7 @@ public class GPURegionGLListener10 extends GPURendererListenerBase01 { regionRenderer.setWeight(weight); } regionRenderer.enable(gl, true); - region.draw(gl, regionRenderer, getSampleCount()); + region.draw(gl, regionRenderer, Region.MAX_AA_QUALITY, getSampleCount()); regionRenderer.enable(gl, false); } diff --git a/src/test/com/jogamp/opengl/test/junit/graph/PerfTextRendererNEWT00.java b/src/test/com/jogamp/opengl/test/junit/graph/PerfTextRendererNEWT00.java index b5fe23920..8ef5f10d6 100644 --- a/src/test/com/jogamp/opengl/test/junit/graph/PerfTextRendererNEWT00.java +++ b/src/test/com/jogamp/opengl/test/junit/graph/PerfTextRendererNEWT00.java @@ -308,7 +308,7 @@ public class PerfTextRendererNEWT00 { pmv.loadMvIdentity(); pmv.translateMv(dx, dy, z0); pmv.scaleMv(fontScale, fontScale, 1f); - region.draw(gl, renderer, sampleCountIO); + region.draw(gl, renderer, Region.MAX_AA_QUALITY, sampleCountIO); final long t5 = Clock.currentNanos(); // text added to region if( null != perf ) { final long td_graph = t3 - t2; |