From fe47c613e3e07681a5366d6ec3f071fdc4ade65d Mon Sep 17 00:00:00 2001
From: Sven Gothel <sgothel@jausoft.com>
Date: Wed, 9 Apr 2014 09:09:51 +0200
Subject: Bug 801: Region Dirty Update; TextureSequence GLMediaPlayer Fix;
 Blending Fix ;

- Region Dirty Update
  - Split dirty -> ShapeDirty + StateDirty,
    where StateDirty forces re-rendering content
    w/o geometry update as req. for 2-pass mode.

- Fix TextureSequence (GLMediaPlayer) usage in RegionRenderer / GLRegion*
  - handle GL_TEXTURE_EXTERNAL_OES incl. Android ES3 bug
  - inject TextureSequence's shader stubs
  - shader: Use abstract lookup 'texture2D' -> 'gcuTexture2D'
  - flip scaled colorTexBBox if TextureSequence 'tex.getMustFlipVertically()'

  - TODO: Handle multiple TextureSequence shader programs!

- Fix Blending: GLRegion* / RegionRenderer / RenderState
  - Disable/Enable depth-writing w/ blending
  - Region impl. sets proper glBlendFunc*(..),
    i.e. 2-pass:
      - render2FBO: glClearColor(0f, 0f, 0f, 0f)
                    glBlendFuncSeparate(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA, GL.GL_ONE, GL.GL_ONE_MINUS_SRC_ALPHA)
      - renderFBO:  glBlendFunc(GL.GL_ONE, GL.GL_ONE_MINUS_SRC_ALPHA)
  - User code shall not set glClearColor(..) for 2-pass anymore

- Graph-UI Demo
  - UIShape:
    - Add MouseGestureListener, combining MouseListener + GestureListener
    - EventDetails -> PointerEventInfo
    - PointerEventInfo contains objPos (ray-intersection) and glWin-pos
    - Toggle:
      - Separate color (on/off) if enabled
      - Toggle on click if enabled

  - SceneUIController
    - Use PinchToZoomGesture and propagete same gesture to UIShape

    - Use AABBox.getRayIntersection(..) using 'real' shape coordinates
      for 1st picking.

    - Use shape PMV for secondary picking (drag, zoom 2-pointer, etc),
      see windowToShapeCoords(..)

    - Sort shapes according to z-value (render: ascending; picking: descending)

    - Only 'drag' if pointerId matches 1st pressed pointer
---
 .../graph/curve/opengl/VBORegion2PMSAAES2.java     | 62 ++++++++++++++++------
 .../graph/curve/opengl/VBORegion2PVBAAES2.java     | 57 ++++++++++++++++----
 .../jogamp/graph/curve/opengl/VBORegionSPES2.java  | 45 +++++++++++-----
 .../shader/curverenderer01-pass1-curve_simple.glsl |  8 +--
 .../curverenderer01-pass1-curve_simple.orig.glsl   | 14 ++++-
 .../opengl/shader/curverenderer01-segment-head.fp  |  3 --
 .../jogamp/graph/curve/opengl/shader/uniforms.glsl |  1 -
 7 files changed, 141 insertions(+), 49 deletions(-)

(limited to 'src/jogl/classes/jogamp/graph')

diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PMSAAES2.java b/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PMSAAES2.java
index 33527381d..b52308e05 100644
--- a/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PMSAAES2.java
+++ b/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PMSAAES2.java
@@ -46,6 +46,7 @@ import com.jogamp.opengl.math.geom.AABBox;
 import com.jogamp.opengl.util.GLArrayDataServer;
 import com.jogamp.opengl.util.glsl.ShaderProgram;
 import com.jogamp.opengl.util.texture.Texture;
+import com.jogamp.opengl.util.texture.TextureCoords;
 import com.jogamp.opengl.util.texture.TextureSequence;
 
 public class VBORegion2PMSAAES2  extends GLRegion {
@@ -96,7 +97,7 @@ public class VBORegion2PMSAAES2  extends GLRegion {
      */
     public void useShaderProgram(final GL2ES2 gl, final RegionRenderer renderer, final int renderModes, final boolean pass1, final int quality, final int sampleCount) {
         final RenderState rs = renderer.getRenderState();
-        final boolean updateLocGlobal = renderer.useShaderProgram(gl, renderModes, pass1, quality, sampleCount);
+        final boolean updateLocGlobal = renderer.useShaderProgram(gl, renderModes, pass1, quality, sampleCount, colorTexSeq);
         final ShaderProgram sp = renderer.getRenderState().getShaderProgram();
         final boolean updateLocLocal;
         if( pass1 ) {
@@ -250,11 +251,22 @@ public class VBORegion2PMSAAES2  extends GLRegion {
             gca_ColorsAttr.seal(gl, true);
             gca_ColorsAttr.enableBuffer(gl, false);
         }
-        if( null != gcu_ColorTexUnit ) {
-            colorTexBBox[0] = box.getMinX();
-            colorTexBBox[1] = box.getMinY();
-            colorTexBBox[2] = box.getMaxX();
-            colorTexBBox[3] = box.getMaxY();
+        if( null != gcu_ColorTexUnit && colorTexSeq.isTextureAvailable() ) {
+            final TextureSequence.TextureFrame frame = colorTexSeq.getLastTexture();
+            final Texture tex = frame.getTexture();
+            final TextureCoords tc = tex.getImageTexCoords();
+            final float tcSx = 1f / ( tc.right() - tc.left() );
+            colorTexBBox[0] = box.getMinX() * tcSx;
+            colorTexBBox[2] = box.getMaxX() * tcSx;
+            if( tex.getMustFlipVertically() ) {
+                final float tcSy = 1f / ( tc.bottom() - tc.top() );
+                colorTexBBox[1] = box.getMaxY() * tcSy;
+                colorTexBBox[3] = box.getMinY() * tcSy;
+            } else {
+                final float tcSy = 1f / ( tc.top() - tc.bottom() );
+                colorTexBBox[1] = box.getMinY() * tcSy;
+                colorTexBBox[3] = box.getMaxY() * tcSy;
+            }
         }
         gca_FboVerticesAttr.seal(gl, false);
         {
@@ -364,9 +376,8 @@ public 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 || null == fbo || ( fbo != null && fbo.getNumSamples() != sampleCount[0] ) ) {
+            if( hasDelta || fboDirty || isShapeDirty() || null == fbo || ( fbo != null && fbo.getNumSamples() != sampleCount[0] ) ) {
                 // FIXME: rescale
-
                 final float minX = box.getMinX()-diffObjBorderWidth;
                 final float minY = box.getMinY()-diffObjBorderHeight;
                 final float maxX = box.getMaxX()+diffObjBorderWidth+diffObjWidth;
@@ -384,10 +395,10 @@ public class VBORegion2PMSAAES2  extends GLRegion {
                 FloatUtil.makeOrthof(pmvMatrix02, 0, true, minX, maxX, minY, maxY, -1, 1);
                 useShaderProgram(gl, renderer, getRenderModes(), true, getQuality(), sampleCount[0]);
                 renderRegion2FBO(gl, rs, targetFboWidth, targetFboHeight, vpWidth, vpHeight, sampleCount);
-            } else {
-                gca_FboTexCoordsAttr.setVBOWritten(false);
+            } else if( isStateDirty() ) {
+                useShaderProgram(gl, renderer, getRenderModes(), true, getQuality(), sampleCount[0]);
+                renderRegion2FBO(gl, rs, targetFboWidth, targetFboHeight, vpWidth, vpHeight, sampleCount);
             }
-            // System.out.println("Scale: " + matrix.glGetMatrixf().get(1+4*3) +" " + matrix.glGetMatrixf().get(2+4*3));
             useShaderProgram(gl, renderer, getRenderModes(), false, getQuality(), sampleCount[0]);
             renderFBO(gl, rs, vpWidth, vpHeight, sampleCount[0]);
         }
@@ -396,6 +407,11 @@ public class VBORegion2PMSAAES2  extends GLRegion {
     private void renderFBO(final GL2ES2 gl, final RenderState rs, final int width, final int height, final int sampleCount) {
         gl.glViewport(0, 0, width, height);
 
+        if( rs.isHintMaskSet(RenderState.BITHINT_BLENDING_ENABLED) ) {
+            // RGB is already multiplied w/ alpha via renderRegion2FBO(..)
+            gl.glBlendFunc(GL.GL_ONE, GL.GL_ONE_MINUS_SRC_ALPHA);
+        }
+
         gl.glActiveTexture(GL.GL_TEXTURE0 + gcu_FboTexUnit.intValue());
 
         fbo.use(gl, fbo.getSamplingSink());
@@ -419,6 +435,8 @@ public class VBORegion2PMSAAES2  extends GLRegion {
             throw new IllegalArgumentException("fboSize must be greater than 0: "+targetFboWidth+"x"+targetFboHeight);
         }
 
+        final boolean blendingEnabled = rs.isHintMaskSet(RenderState.BITHINT_BLENDING_ENABLED);
+
         if(null == fbo) {
             fboWidth  = targetFboWidth;
             fboHeight  = targetFboHeight;
@@ -433,7 +451,10 @@ public class VBORegion2PMSAAES2  extends GLRegion {
                 // 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, GL2ES2.GL_NEAREST, GL2ES2.GL_NEAREST, GL2ES2.GL_CLAMP_TO_EDGE, GL2ES2.GL_CLAMP_TO_EDGE);
-                ssink.attachRenderbuffer(gl, Attachment.Type.DEPTH, 24);
+                if( !blendingEnabled ) {
+                    // no depth-buffer w/ blending
+                    ssink.attachRenderbuffer(gl, Attachment.Type.DEPTH, 24);
+                }
             }
             fbo.setSamplingSink(ssink);
             fbo.resetSamplingSink(gl); // validate
@@ -453,9 +474,20 @@ public class VBORegion2PMSAAES2  extends GLRegion {
 
         //render texture
         gl.glViewport(0, 0, fboWidth, fboHeight);
+        if( blendingEnabled ) {
+            gl.glClearColor(0f, 0f, 0f, 0.0f);
+            gl.glClear(GL2ES2.GL_COLOR_BUFFER_BIT); // no depth-buffer w/ blending
+            // For already pre-multiplied alpha values, use:
+            // gl.glBlendFunc(GL.GL_ONE, GL.GL_ONE_MINUS_SRC_ALPHA);
+
+            // Multiply RGB w/ Alpha, preserve alpha for renderFBO(..)
+            gl.glBlendFuncSeparate(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA, GL.GL_ONE, GL.GL_ONE_MINUS_SRC_ALPHA);
+        } else {
+            gl.glClear(GL2ES2.GL_COLOR_BUFFER_BIT | GL2ES2.GL_DEPTH_BUFFER_BIT);
+        }
 
-        gl.glClear(GL2ES2.GL_COLOR_BUFFER_BIT | GL2ES2.GL_DEPTH_BUFFER_BIT);
         renderRegion(gl);
+
         fbo.unbind(gl);
         fboDirty = false;
     }
@@ -468,7 +500,7 @@ public class VBORegion2PMSAAES2  extends GLRegion {
             gca_ColorsAttr.enableBuffer(gl, true);
         }
         indicesBuffer.bindBuffer(gl, true); // keeps VBO binding
-        if( null != gcu_ColorTexUnit ) {
+        if( null != gcu_ColorTexUnit && colorTexSeq.isTextureAvailable() ) {
             final TextureSequence.TextureFrame frame = colorTexSeq.getNextTexture(gl);
             gl.glActiveTexture(GL.GL_TEXTURE0 + colorTexSeq.getTextureUnit());
             final Texture tex = frame.getTexture();
@@ -479,7 +511,7 @@ public class VBORegion2PMSAAES2  extends GLRegion {
                 gcu_ColorTexUnit.setData(colorTexUnit);
                 gl.glUniform(gcu_ColorTexUnit);
             }
-            gl.glUniform(gcu_ColorTexBBox); // FIXME: Only if changed!
+            gl.glUniform(gcu_ColorTexBBox); // Always update, since program maybe used by multiple regions
             gl.glDrawElements(GL2ES2.GL_TRIANGLES, indicesBuffer.getElementCount() * indicesBuffer.getComponentCount(), GL2ES2.GL_UNSIGNED_SHORT, 0);
             tex.disable(gl); // nop on core
         } else {
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PVBAAES2.java b/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PVBAAES2.java
index c623eddb7..cea292210 100644
--- a/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PVBAAES2.java
+++ b/src/jogl/classes/jogamp/graph/curve/opengl/VBORegion2PVBAAES2.java
@@ -49,6 +49,7 @@ import com.jogamp.opengl.math.geom.AABBox;
 import com.jogamp.opengl.util.GLArrayDataServer;
 import com.jogamp.opengl.util.glsl.ShaderProgram;
 import com.jogamp.opengl.util.texture.Texture;
+import com.jogamp.opengl.util.texture.TextureCoords;
 import com.jogamp.opengl.util.texture.TextureSequence;
 
 public class VBORegion2PVBAAES2  extends GLRegion {
@@ -131,7 +132,7 @@ public class VBORegion2PVBAAES2  extends GLRegion {
      */
     public void useShaderProgram(final GL2ES2 gl, final RegionRenderer renderer, final int renderModes, final boolean pass1, final int quality, final int sampleCount) {
         final RenderState rs = renderer.getRenderState();
-        final boolean updateLocGlobal = renderer.useShaderProgram(gl, renderModes, pass1, quality, sampleCount);
+        final boolean updateLocGlobal = renderer.useShaderProgram(gl, renderModes, pass1, quality, sampleCount, colorTexSeq);
         final ShaderProgram sp = renderer.getRenderState().getShaderProgram();
         final boolean updateLocLocal;
         if( pass1 ) {
@@ -295,11 +296,22 @@ public class VBORegion2PVBAAES2  extends GLRegion {
             gca_ColorsAttr.seal(gl, true);
             gca_ColorsAttr.enableBuffer(gl, false);
         }
-        if( null != gcu_ColorTexUnit ) {
-            colorTexBBox[0] = box.getMinX();
-            colorTexBBox[1] = box.getMinY();
-            colorTexBBox[2] = box.getMaxX();
-            colorTexBBox[3] = box.getMaxY();
+        if( null != gcu_ColorTexUnit && colorTexSeq.isTextureAvailable() ) {
+            final TextureSequence.TextureFrame frame = colorTexSeq.getLastTexture();
+            final Texture tex = frame.getTexture();
+            final TextureCoords tc = tex.getImageTexCoords();
+            final float tcSx = 1f / ( tc.right() - tc.left() );
+            colorTexBBox[0] = box.getMinX() * tcSx;
+            colorTexBBox[2] = box.getMaxX() * tcSx;
+            if( tex.getMustFlipVertically() ) {
+                final float tcSy = 1f / ( tc.bottom() - tc.top() );
+                colorTexBBox[1] = box.getMaxY() * tcSy;
+                colorTexBBox[3] = box.getMinY() * tcSy;
+            } else {
+                final float tcSy = 1f / ( tc.top() - tc.bottom() );
+                colorTexBBox[1] = box.getMinY() * tcSy;
+                colorTexBBox[3] = box.getMaxY() * tcSy;
+            }
         }
         gca_FboVerticesAttr.seal(gl, false);
         {
@@ -419,7 +431,7 @@ public class VBORegion2PVBAAES2  extends GLRegion {
                 System.err.printf("XXX.Scale %d * [%f x %f]: %d x %d%n",
                         sampleCount[0], winWidth, winHeight, targetFboWidth, targetFboHeight);
             }
-            if( hasDelta || fboDirty || null == fbo ) {
+            if( hasDelta || fboDirty || isShapeDirty() || null == fbo ) {
                 final int maxLength = Math.max(targetFboWidth, targetFboHeight);
                 if( maxLength > maxTexSize[0] ) {
                     if( targetFboWidth > targetFboHeight ) {
@@ -503,6 +515,9 @@ public class VBORegion2PVBAAES2  extends GLRegion {
                 FloatUtil.makeOrthof(pmvMatrix02, 0, true, minX, maxX, minY, maxY, -1, 1);
                 useShaderProgram(gl, renderer, getRenderModes(), true, getQuality(), sampleCount[0]);
                 renderRegion2FBO(gl, rs, targetFboWidth, targetFboHeight, newFboWidth, newFboHeight, vpWidth, vpHeight, sampleCount[0]);
+            } else if( isStateDirty() ) {
+                useShaderProgram(gl, renderer, getRenderModes(), true, getQuality(), sampleCount[0]);
+                renderRegion2FBO(gl, rs, targetFboWidth, targetFboHeight, fboWidth, fboHeight, vpWidth, vpHeight, sampleCount[0]);
             }
             useShaderProgram(gl, renderer, getRenderModes(), false, getQuality(), sampleCount[0]);
             renderFBO(gl, rs, targetFboWidth, targetFboHeight, vpWidth, vpHeight, sampleCount[0]);
@@ -513,6 +528,11 @@ public class VBORegion2PVBAAES2  extends GLRegion {
                            final int vpWidth, final int vpHeight, final int sampleCount) {
         gl.glViewport(0, 0, vpWidth, vpHeight);
 
+        if( rs.isHintMaskSet(RenderState.BITHINT_BLENDING_ENABLED) ) {
+            // RGB is already multiplied w/ alpha via renderRegion2FBO(..)
+            gl.glBlendFunc(GL.GL_ONE, GL.GL_ONE_MINUS_SRC_ALPHA);
+        }
+
         gl.glUniform(gcu_FboTexSize);
 
         gl.glActiveTexture(GL.GL_TEXTURE0 + gcu_FboTexUnit.intValue());
@@ -539,6 +559,8 @@ public class VBORegion2PVBAAES2  extends GLRegion {
             throw new IllegalArgumentException("fboSize must be greater than 0: "+targetFboWidth+"x"+targetFboHeight);
         }
 
+        final boolean blendingEnabled = rs.isHintMaskSet(RenderState.BITHINT_BLENDING_ENABLED);
+
         if(null == fbo) {
             fboWidth  = newFboWidth;
             fboHeight  = newFboHeight;
@@ -553,7 +575,10 @@ public class VBORegion2PVBAAES2  extends GLRegion {
             // FIXME: FXAA requires bilinear filtering!
             // texA = fbo.attachTexture2D(gl, 0, true, GL2ES2.GL_LINEAR, GL2ES2.GL_LINEAR, GL2ES2.GL_CLAMP_TO_EDGE, GL2ES2.GL_CLAMP_TO_EDGE);
             texA = fbo.attachTexture2D(gl, 0, true, GL2ES2.GL_NEAREST, GL2ES2.GL_NEAREST, GL2ES2.GL_CLAMP_TO_EDGE, GL2ES2.GL_CLAMP_TO_EDGE);
-            fbo.attachRenderbuffer(gl, Attachment.Type.DEPTH, 24);
+            if( !blendingEnabled ) {
+                // no depth-buffer w/ blending
+                fbo.attachRenderbuffer(gl, Attachment.Type.DEPTH, 24);
+            }
             if( DEBUG_FBO_1 ) {
                 System.err.printf("XXX.createFBO: %dx%d%n%s%n", fboWidth, fboHeight, fbo.toString());
             }
@@ -576,7 +601,17 @@ public class VBORegion2PVBAAES2  extends GLRegion {
 
         //render texture
         gl.glViewport(0, 0, fboWidth, fboHeight);
-        gl.glClear(GL2ES2.GL_COLOR_BUFFER_BIT | GL2ES2.GL_DEPTH_BUFFER_BIT);
+        if( blendingEnabled ) {
+            gl.glClearColor(0f, 0f, 0f, 0.0f);
+            gl.glClear(GL2ES2.GL_COLOR_BUFFER_BIT); // no depth-buffer w/ blending
+            // For already pre-multiplied alpha values, use:
+            // gl.glBlendFunc(GL.GL_ONE, GL.GL_ONE_MINUS_SRC_ALPHA);
+
+            // Multiply RGB w/ Alpha, preserve alpha for renderFBO(..)
+            gl.glBlendFuncSeparate(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA, GL.GL_ONE, GL.GL_ONE_MINUS_SRC_ALPHA);
+        } else {
+            gl.glClear(GL2ES2.GL_COLOR_BUFFER_BIT | GL2ES2.GL_DEPTH_BUFFER_BIT);
+        }
 
         renderRegion(gl);
 
@@ -593,7 +628,7 @@ public class VBORegion2PVBAAES2  extends GLRegion {
             gca_ColorsAttr.enableBuffer(gl, true);
         }
         indicesBuffer.bindBuffer(gl, true); // keeps VBO binding
-        if( null != gcu_ColorTexUnit ) {
+        if( null != gcu_ColorTexUnit && colorTexSeq.isTextureAvailable() ) {
             final TextureSequence.TextureFrame frame = colorTexSeq.getNextTexture(gl);
             gl.glActiveTexture(GL.GL_TEXTURE0 + colorTexSeq.getTextureUnit());
             final Texture tex = frame.getTexture();
@@ -604,7 +639,7 @@ public class VBORegion2PVBAAES2  extends GLRegion {
                 gcu_ColorTexUnit.setData(colorTexUnit);
                 gl.glUniform(gcu_ColorTexUnit);
             }
-            gl.glUniform(gcu_ColorTexBBox); // FIXME: Only if changed!
+            gl.glUniform(gcu_ColorTexBBox); // Always update, since program maybe used by multiple regions
             gl.glDrawElements(GL2ES2.GL_TRIANGLES, indicesBuffer.getElementCount() * indicesBuffer.getComponentCount(), GL2ES2.GL_UNSIGNED_SHORT, 0);
             tex.disable(gl); // nop on core
         } else {
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/VBORegionSPES2.java b/src/jogl/classes/jogamp/graph/curve/opengl/VBORegionSPES2.java
index 0ec139a0f..24d53c1a2 100644
--- a/src/jogl/classes/jogamp/graph/curve/opengl/VBORegionSPES2.java
+++ b/src/jogl/classes/jogamp/graph/curve/opengl/VBORegionSPES2.java
@@ -43,6 +43,7 @@ import com.jogamp.graph.curve.opengl.RenderState;
 import com.jogamp.opengl.util.GLArrayDataServer;
 import com.jogamp.opengl.util.glsl.ShaderProgram;
 import com.jogamp.opengl.util.texture.Texture;
+import com.jogamp.opengl.util.texture.TextureCoords;
 import com.jogamp.opengl.util.texture.TextureSequence;
 
 public class VBORegionSPES2 extends GLRegion {
@@ -149,11 +150,23 @@ public class VBORegionSPES2 extends GLRegion {
             gca_ColorsAttr.seal(gl, true);
             gca_ColorsAttr.enableBuffer(gl, false);
         }
-        if( null != gcu_ColorTexUnit ) {
-            colorTexBBox[0] = box.getMinX();
-            colorTexBBox[1] = box.getMinY();
-            colorTexBBox[2] = box.getMaxX();
-            colorTexBBox[3] = box.getMaxY();
+        if( null != gcu_ColorTexUnit && colorTexSeq.isTextureAvailable() ) {
+            final TextureSequence.TextureFrame frame = colorTexSeq.getLastTexture();
+            final Texture tex = frame.getTexture();
+            final TextureCoords tc = tex.getImageTexCoords();
+            final float tcSx = 1f / ( tc.right() - tc.left() );
+            colorTexBBox[0] = box.getMinX() * tcSx;
+            colorTexBBox[2] = box.getMaxX() * tcSx;
+            final float tcSy;
+            if( tex.getMustFlipVertically() ) {
+                tcSy = 1f / ( tc.bottom() - tc.top() );
+                colorTexBBox[1] = box.getMaxY() * tcSy;
+                colorTexBBox[3] = box.getMinY() * tcSy;
+            } else {
+                tcSy = 1f / ( tc.top() - tc.bottom() );
+                colorTexBBox[1] = box.getMinY() * tcSy;
+                colorTexBBox[3] = box.getMaxY() * tcSy;
+            }
         }
         indicesBuffer.seal(gl, true);
         indicesBuffer.enableBuffer(gl, false);
@@ -164,6 +177,7 @@ public class VBORegionSPES2 extends GLRegion {
         }
     }
 
+    private static final boolean throwOnError = false; // FIXME
     /**
      * <p>
      * Since multiple {@link Region}s may share one
@@ -177,7 +191,7 @@ public class VBORegionSPES2 extends GLRegion {
      */
     public void useShaderProgram(final GL2ES2 gl, final RegionRenderer renderer, final int renderModes, final int quality) {
         final RenderState rs = renderer.getRenderState();
-        final boolean updateLocGlobal = renderer.useShaderProgram(gl, renderModes, true, quality, 0);
+        final boolean updateLocGlobal = renderer.useShaderProgram(gl, renderModes, true, quality, 0, colorTexSeq);
         final ShaderProgram sp = renderer.getRenderState().getShaderProgram();
         final boolean updateLocLocal = !sp.equals(spPass1);
         spPass1 = sp;
@@ -185,16 +199,16 @@ public class VBORegionSPES2 extends GLRegion {
             System.err.println("XXX changedSP.p1 updateLocation loc "+updateLocLocal+" / glob "+updateLocGlobal);
         }
         if( updateLocLocal ) {
-            rs.updateAttributeLoc(gl, true, gca_VerticesAttr, true);
-            rs.updateAttributeLoc(gl, true, gca_CurveParamsAttr, true);
+            rs.updateAttributeLoc(gl, true, gca_VerticesAttr, throwOnError);
+            rs.updateAttributeLoc(gl, true, gca_CurveParamsAttr, throwOnError);
             if( null != gca_ColorsAttr ) {
-                rs.updateAttributeLoc(gl, true, gca_ColorsAttr, true);
+                rs.updateAttributeLoc(gl, true, gca_ColorsAttr, throwOnError);
             }
         }
-        rsLocal.update(gl, rs, updateLocLocal, renderModes, true, true);
+        rsLocal.update(gl, rs, updateLocLocal, renderModes, true, throwOnError);
         if( null != gcu_ColorTexUnit ) {
-            rs.updateUniformLoc(gl, updateLocLocal, gcu_ColorTexUnit, true);
-            rs.updateUniformLoc(gl, updateLocLocal, gcu_ColorTexBBox, true);
+            rs.updateUniformLoc(gl, updateLocLocal, gcu_ColorTexUnit, throwOnError);
+            rs.updateUniformLoc(gl, updateLocLocal, gcu_ColorTexBBox, throwOnError);
         }
     }
 
@@ -216,7 +230,12 @@ public class VBORegionSPES2 extends GLRegion {
             gca_ColorsAttr.enableBuffer(gl, true);
         }
         indicesBuffer.bindBuffer(gl, true); // keeps VBO binding
-        if( null != gcu_ColorTexUnit ) {
+
+        if( renderer.getRenderState().isHintMaskSet(RenderState.BITHINT_BLENDING_ENABLED) ) {
+            gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA);
+        }
+
+        if( null != gcu_ColorTexUnit && colorTexSeq.isTextureAvailable() ) {
             final TextureSequence.TextureFrame frame = colorTexSeq.getNextTexture(gl);
             gl.glActiveTexture(GL.GL_TEXTURE0 + colorTexSeq.getTextureUnit());
             final Texture tex = frame.getTexture();
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass1-curve_simple.glsl b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass1-curve_simple.glsl
index 83b312a0b..447242438 100644
--- a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass1-curve_simple.glsl
+++ b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass1-curve_simple.glsl
@@ -2,9 +2,9 @@
     if( gcv_CurveParam.x == 0.0 && gcv_CurveParam.y == 0.0 ) {
         // pass-1: Lines
 #if defined(USE_COLOR_TEXTURE) && defined(USE_COLOR_CHANNEL)
-        mgl_FragColor = texture2D(gcu_ColorTexUnit, gcv_ColorTexCoord.st) * gcv_Color * gcu_ColorStatic;
+        mgl_FragColor = gcuTexture2D(gcu_ColorTexUnit, gcv_ColorTexCoord.st) * gcv_Color * gcu_ColorStatic;
 #elif defined(USE_COLOR_TEXTURE)
-        mgl_FragColor = texture2D(gcu_ColorTexUnit, gcv_ColorTexCoord.st) * gcu_ColorStatic;
+        mgl_FragColor = gcuTexture2D(gcu_ColorTexUnit, gcv_ColorTexCoord.st) * gcu_ColorStatic;
 #elif defined(USE_COLOR_CHANNEL)
         mgl_FragColor = gcv_Color * gcu_ColorStatic;
 #else
@@ -22,10 +22,10 @@
 
         float a = clamp(0.5 - ( position/length(f) ) * sign(gcv_CurveParam.y), 0.0, 1.0);
 #if defined(USE_COLOR_TEXTURE) && defined(USE_COLOR_CHANNEL)
-        vec4 t = texture2D(gcu_ColorTexUnit, gcv_ColorTexCoord.st);
+        vec4 t = gcuTexture2D(gcu_ColorTexUnit, gcv_ColorTexCoord.st);
         mgl_FragColor = vec4(t.rgb * gcv_Color.rgb * gcu_ColorStatic.rgb, t.a * gcv_Color.a * gcu_ColorStatic.a * a);
 #elif defined(USE_COLOR_TEXTURE)
-        vec4 t = texture2D(gcu_ColorTexUnit, gcv_ColorTexCoord.st);
+        vec4 t = gcuTexture2D(gcu_ColorTexUnit, gcv_ColorTexCoord.st);
         mgl_FragColor = vec4(t.rgb * gcu_ColorStatic.rgb, t.a * gcu_ColorStatic.a * a);
 #elif defined(USE_COLOR_CHANNEL)
         mgl_FragColor = vec4(gcv_Color.rgb * gcu_ColorStatic.rgb, gcv_Color.a * gcu_ColorStatic.a * a);
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass1-curve_simple.orig.glsl b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass1-curve_simple.orig.glsl
index 92f0fc07b..fa2608365 100644
--- a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass1-curve_simple.orig.glsl
+++ b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-pass1-curve_simple.orig.glsl
@@ -3,7 +3,11 @@
 
     if( gcv_CurveParam.x == 0.0 && gcv_CurveParam.y == 0.0 ) {
         // pass-1: Lines
-#ifdef USE_COLOR_CHANNEL
+#if defined(USE_COLOR_TEXTURE) && defined(USE_COLOR_CHANNEL)
+        mgl_FragColor = gcuTexture2D(gcu_ColorTexUnit, gcv_ColorTexCoord.st) * gcv_Color * gcu_ColorStatic;
+#elif defined(USE_COLOR_TEXTURE)
+        mgl_FragColor = gcuTexture2D(gcu_ColorTexUnit, gcv_ColorTexCoord.st) * gcu_ColorStatic;
+#elif defined(USE_COLOR_CHANNEL)
         mgl_FragColor = gcv_Color * gcu_ColorStatic;
 #else
         mgl_FragColor = gcu_ColorStatic;
@@ -25,7 +29,13 @@
             float position = rtex.y - (rtex.x * (1.0 - rtex.x));
 
             float a = clamp(0.5 - ( position/length(f) ) * sign(gcv_CurveParam.y), 0.0, 1.0);
-#ifdef USE_COLOR_CHANNEL
+#if defined(USE_COLOR_TEXTURE) && defined(USE_COLOR_CHANNEL)
+            vec4 t = gcuTexture2D(gcu_ColorTexUnit, gcv_ColorTexCoord.st);
+            mgl_FragColor = vec4(t.rgb * gcv_Color.rgb * gcu_ColorStatic.rgb, t.a * gcv_Color.a * gcu_ColorStatic.a * a);
+#elif defined(USE_COLOR_TEXTURE)
+            vec4 t = gcuTexture2D(gcu_ColorTexUnit, gcv_ColorTexCoord.st);
+            mgl_FragColor = vec4(t.rgb * gcu_ColorStatic.rgb, t.a * gcu_ColorStatic.a * a);
+#elif defined(USE_COLOR_CHANNEL)
             mgl_FragColor = vec4(gcv_Color.rgb * gcu_ColorStatic.rgb, gcv_Color.a * gcu_ColorStatic.a * a);
 #else
             mgl_FragColor = vec4(gcu_ColorStatic.rgb, gcu_ColorStatic.a * a);
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-segment-head.fp b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-segment-head.fp
index 74a1dea4e..26e2bcf24 100644
--- a/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-segment-head.fp
+++ b/src/jogl/classes/jogamp/graph/curve/opengl/shader/curverenderer01-segment-head.fp
@@ -17,6 +17,3 @@
 
 #define GetSample(texUnit, texCoord, psize, cx, cy, offX, offY) texture2D(texUnit, texCoord + psize *  vec2(cx+offX, cy+offY))
 
-void main (void)
-{
-
diff --git a/src/jogl/classes/jogamp/graph/curve/opengl/shader/uniforms.glsl b/src/jogl/classes/jogamp/graph/curve/opengl/shader/uniforms.glsl
index ae7fa8490..cd014b732 100644
--- a/src/jogl/classes/jogamp/graph/curve/opengl/shader/uniforms.glsl
+++ b/src/jogl/classes/jogamp/graph/curve/opengl/shader/uniforms.glsl
@@ -7,7 +7,6 @@ uniform vec4    gcu_ColorStatic;
 uniform float   gcu_Weight;
 
 #ifdef USE_COLOR_TEXTURE
-    uniform sampler2D  gcu_ColorTexUnit;
     uniform vec4  gcu_ColorTexBBox;
 #endif
 
-- 
cgit v1.2.3