Evas masking: Fix masking of maps in GL
authorJean-Philippe Andre <jp.andre@samsung.com>
Thu, 26 Feb 2015 11:42:45 +0000 (20:42 +0900)
committerJean-Philippe Andre <jp.andre@samsung.com>
Fri, 27 Feb 2015 04:06:09 +0000 (13:06 +0900)
This completes the transition to auto-scaled mask images when
using the GL engine. Now the shaders do the work on-the-fly of
resizing the mask.

src/modules/evas/engines/gl_common/evas_gl_common.h
src/modules/evas/engines/gl_common/evas_gl_context.c
src/modules/evas/engines/gl_common/evas_gl_image.c
src/modules/evas/engines/gl_common/shader/evas_gl_shaders.x
src/modules/evas/engines/gl_common/shader/map_mask_bgra_frag.shd
src/modules/evas/engines/gl_common/shader/map_mask_bgra_nomul_vert.shd
src/modules/evas/engines/gl_common/shader/map_mask_bgra_vert.shd
src/modules/evas/engines/gl_common/shader/map_mask_frag.shd
src/modules/evas/engines/gl_common/shader/map_mask_nomul_vert.shd
src/modules/evas/engines/gl_common/shader/map_mask_vert.shd

index b1ba6f3..7b3be65 100644 (file)
@@ -754,7 +754,7 @@ void             evas_gl_common_context_image_map_push(Evas_Engine_GL_Context *g
                                                        int npoints,
                                                        RGBA_Map_Point *p,
                                                        int clip, int cx, int cy, int cw, int ch,
-                                                       Evas_GL_Texture *mtex, int mx, int my, int mw, int mh, int mdx, int mdy, int mdw, int mdh,
+                                                       Evas_GL_Texture *mtex, int mx, int my, int mw, int mh, Eina_Bool mask_smooth,
                                                        int r, int g, int b, int a,
                                                        Eina_Bool smooth,
                                                        Eina_Bool tex_only,
index 2c756db..cb931de 100644 (file)
@@ -2404,8 +2404,7 @@ evas_gl_common_context_image_map_push(Evas_Engine_GL_Context *gc,
                                       int npoints,
                                       RGBA_Map_Point *p,
                                       int clip, int cx, int cy, int cw, int ch,
-                                      Evas_GL_Texture *mtex, int mx, int my, int mw, int mh,
-                                      int mdx, int mdy, int mdw, int mdh,
+                                      Evas_GL_Texture *mtex, int mx, int my, int mw, int mh, Eina_Bool mask_smooth,
                                       int r, int g, int b, int a,
                                       Eina_Bool smooth, Eina_Bool tex_only,
                                       Evas_Colorspace cspace)
@@ -2606,7 +2605,7 @@ evas_gl_common_context_image_map_push(Evas_Engine_GL_Context *gc,
    gc->pipe[pn].array.use_texm = !!mtex;
    gc->pipe[pn].array.use_texa = !!mtex;
    gc->pipe[pn].array.use_texsam = gc->pipe[pn].array.use_texm;
-   gc->pipe[pn].array.mask_smooth = EINA_FALSE;
+   gc->pipe[pn].array.mask_smooth = mask_smooth;
 
    pipe_region_expand(gc, pn, x, y, w, h);
    PIPE_GROW(gc, pn, 6);
@@ -2668,12 +2667,8 @@ evas_gl_common_context_image_map_push(Evas_Engine_GL_Context *gc,
 
    if (mtex)
      {
-        GLfloat glmdx = 0.f, glmdy = 0.f, glmdw = 1.f, glmdh = 1.f, yinv = -1.f;
-        GLfloat gw = gc->w, gh = gc->h;
-
-        // Note: I couldn't write any test case where it was necessary
-        // to know the mask position in its texture. Thus these unused vars.
-        (void) mx; (void) my; (void) mw; (void) mh;
+        double glmx, glmy, glmw, glmh, yinv = -1.f;
+        double gw = gc->w, gh = gc->h;
 
         if (!((gc->pipe[0].shader.surface == gc->def_surface) ||
               (!gc->pipe[0].shader.surface)))
@@ -2682,40 +2677,47 @@ evas_gl_common_context_image_map_push(Evas_Engine_GL_Context *gc,
              gh = gc->pipe[0].shader.surface->h;
              yinv = 1.f;
           }
-
-        if (gw) glmdx = (GLfloat) mdx / (GLfloat) gw;
-        if (gh) glmdy = (GLfloat) mdy / (GLfloat) gh;
-        if (mdw) glmdw = (GLfloat) gw / (GLfloat) mdw;
-        if (mdh) glmdh = (GLfloat) gh / (GLfloat) mdh;
-
-        // tex_coordm: mask x,y (on canvas)
-        PUSH_TEXM(pn, glmdx, glmdy);
-        PUSH_TEXM(pn, glmdx, glmdy);
-        PUSH_TEXM(pn, glmdx, glmdy);
-        PUSH_TEXM(pn, glmdx, glmdy);
-        PUSH_TEXM(pn, glmdx, glmdy);
-        PUSH_TEXM(pn, glmdx, glmdy);
-
-        // tex_sample: mask 1/w, 1/h
-        PUSH_TEXSAM(pn, glmdw, glmdh);
-        PUSH_TEXSAM(pn, glmdw, glmdh);
-        PUSH_TEXSAM(pn, glmdw, glmdh);
-        PUSH_TEXSAM(pn, glmdw, glmdh);
-        PUSH_TEXSAM(pn, glmdw, glmdh);
-        PUSH_TEXSAM(pn, glmdw, glmdh);
-
-        // tex_coorda: mask Y-invert flag
-        PUSH_TEXA(pn, 1.f, yinv);
-        PUSH_TEXA(pn, 1.f, yinv);
-        PUSH_TEXA(pn, 1.f, yinv);
-        PUSH_TEXA(pn, 1.f, yinv);
-        PUSH_TEXA(pn, 1.f, yinv);
-        PUSH_TEXA(pn, 1.f, yinv);
-
-        //DBG("Orig %d,%d - %dx%d --> %f,%f - %f x %f", mdx, mdy, mdw, mdh,
-        //    glmdx, glmdy, glmdw, glmdh);
-     }
-
+        if (!gw || !gh || !mw || !mh || !mtex->pt->w || !mtex->pt->h)
+          goto mask_error;
+
+        // vertex shader: tex_m = (X,Y) * tex_coordm + tex_sample
+        // tex_coordm
+        glmx = (double)((mtex->x * mw) - (mtex->w * mx)) / (double)(mw * mtex->pt->w);
+        glmy = (double)((mtex->y * mh) - (mtex->h * my)) / (double)(mh * mtex->pt->h);
+        PUSH_TEXM(pn, glmx, glmy);
+        PUSH_TEXM(pn, glmx, glmy);
+        PUSH_TEXM(pn, glmx, glmy);
+        PUSH_TEXM(pn, glmx, glmy);
+        PUSH_TEXM(pn, glmx, glmy);
+        PUSH_TEXM(pn, glmx, glmy);
+
+        // tex_sample
+        glmw = (double)(gw * mtex->w) / (double)(mw * mtex->pt->w);
+        glmh = (double)(gh * mtex->h) / (double)(mh * mtex->pt->h);
+        PUSH_TEXSAM(pn, glmw, glmh);
+        PUSH_TEXSAM(pn, glmw, glmh);
+        PUSH_TEXSAM(pn, glmw, glmh);
+        PUSH_TEXSAM(pn, glmw, glmh);
+        PUSH_TEXSAM(pn, glmw, glmh);
+        PUSH_TEXSAM(pn, glmw, glmh);
+
+        // tex_coorda: Y-invert flag
+        PUSH_TEXA(pn, 1.0, yinv);
+        PUSH_TEXA(pn, 1.0, yinv);
+        PUSH_TEXA(pn, 1.0, yinv);
+        PUSH_TEXA(pn, 1.0, yinv);
+        PUSH_TEXA(pn, 1.0, yinv);
+        PUSH_TEXA(pn, 1.0, yinv);
+
+        /*
+        DBG("Map mask: %d,%d %dx%d --> %f , %f - %f x %f @ %f %f [gc %dx%d, tex %d,%d %dx%d, pt %dx%d]",
+            mx, my, mw, mh,
+            glmx, glmy, glmw, glmh, 1.0, yinv,
+            gc->w, gc->h, mtex->x, mtex->y, mtex->w, mtex->h, mtex->pt->w, mtex->pt->h);
+        */
+     }
+
+mask_error:
    if (!flat)
      {
         shader_array_flush(gc);
index 2fdc608..c897bd2 100644 (file)
@@ -923,9 +923,11 @@ void
 evas_gl_common_image_map_draw(Evas_Engine_GL_Context *gc, Evas_GL_Image *im,
                               int npoints, RGBA_Map_Point *p, int smooth, int level EINA_UNUSED)
 {
-   int mmx = 0, mmy = 0, mmw = 0, mmh = 0, mdx = 0, mdy = 0, mdw = 0, mdh = 0;
-   Evas_GL_Texture *mtex = NULL;
-   RGBA_Draw_Context *dc;
+   int mx = 0, my = 0, mw = 0, mh = 0;
+   RGBA_Draw_Context *dc = gc->dc;
+   Eina_Bool mask_smooth = EINA_FALSE;
+   Evas_GL_Image *mask = dc->clip.mask;
+   Evas_GL_Texture *mtex = mask ? mask->tex : NULL;
    int r, g, b, a;
    int c, cx, cy, cw, ch;
 
@@ -951,30 +953,32 @@ evas_gl_common_image_map_draw(Evas_Engine_GL_Context *gc, Evas_GL_Image *im,
    if (!im->tex) return;
    im->tex->im = im;
 
-   if (dc->clip.mask)
+   if (mtex && mtex->pt && mtex->pt->w && mtex->pt->h)
      {
-        Evas_GL_Image *mask = dc->clip.mask;
-        double mx, my, mw, mh;
-
-        mdx = mx = dc->clip.mask_x;
-        mdy = my = dc->clip.mask_y;
-        mdw = mw = mask->w;
-        mdh = mh = mask->h;
-        if (c) RECTS_CLIP_TO_RECT(mx, my, mw, mh, cx, cy, cw, ch);
-        //RECTS_CLIP_TO_RECT(mx, my, mw, mh, dx, dy, dw, dh);
-        mmx = mx - dc->clip.mask_x;
-        mmy = my - dc->clip.mask_y;
-        mmw = mw;
-        mmh = mh;
-        mtex = mask->tex;
-        // TODO: implement support for scaled masks
-        //if (mask->scaled.origin)
-          //mask_smooth = mask->scaled.smooth;
+        // canvas coords
+        mx = dc->clip.mask_x;
+        my = dc->clip.mask_y;
+        if (mask->scaled.origin)
+          {
+             mw = mask->scaled.w;
+             mh = mask->scaled.h;
+             //scalex = mask->w / (double)mask->scaled.w;
+             //scaley = mask->h / (double)mask->scaled.h;
+             mask_smooth = mask->scaled.smooth;
+          }
+        else
+          {
+             mw = mask->w;
+             mh = mask->h;
+          }
+        //if (c) RECTS_CLIP_TO_RECT(mx, my, mw, mh, cx, cy, cw, ch);
+        //mx = mx - dc->clip.mask_x;
+        //my = my - dc->clip.mask_y;
      }
 
    evas_gl_common_context_image_map_push(gc, im->tex, npoints, p,
                                          c, cx, cy, cw, ch,
-                                         mtex, mmx, mmy, mmw, mmh, mdx, mdy, mdw, mdh,
+                                         mtex, mx, my, mw, mh, mask_smooth,
                                          r, g, b, a, smooth, im->tex_only,
                                          im->cs.space);
 }
index 4789e40..5abc028 100644 (file)
@@ -2715,7 +2715,6 @@ static const char const map_mask_frag_glsl[] =
    "varying vec4 col;\n"
    "void main()\n"
    "{\n"
-   "   // FIXME: Use mask coordinates within its texture\n"
    "   // FIXME: Fix Mach band effect using proper 4-point color interpolation\n"
    "   gl_FragColor = texture2D(tex, tex_c).bgra * texture2D(texm, tex_m).a *  col;\n"
    "}\n";
@@ -2741,10 +2740,9 @@ static const char const map_mask_vert_glsl[] =
    "   tex_c = tex_coord;\n"
    "   col = color;\n"
    "   // tex_coorda contains the Y-invert flag\n"
-   "   // tex_coordm contains the X,Y position of the mask\n"
-   "   // tex_sample contains the W,H size of the mask (inverted)\n"
-   "   vec4 mask_Position = mvp * vertex * vec4(tex_coorda.x * 0.5, tex_coorda.y * 0.5, 0.5, 0.5) + vec4(0.5, 0.5, 0, 0);\n"
-   "   tex_m = vec2(mask_Position.xy - tex_coordm) * tex_sample;\n"
+   "   // position on screen in [0..1] range of current pixel\n"
+   "   vec4 mask_Position = mvp * vertex * vec4(0.5, sign(tex_coorda.y) * 0.5, 0.5, 0.5) + vec4(0.5, 0.5, 0, 0);\n"
+   "   tex_m = mask_Position.xy * tex_sample + tex_coordm;\n"
    "}\n";
 Evas_GL_Program_Source shader_map_mask_vert_src =
 {
@@ -2787,10 +2785,9 @@ static const char const map_mask_nomul_vert_glsl[] =
    "   gl_Position = mvp * vertex;\n"
    "   tex_c = tex_coord;\n"
    "   // tex_coorda contains the Y-invert flag\n"
-   "   // tex_coordm contains the X,Y position of the mask\n"
-   "   // tex_sample contains the W,H size of the mask (inverted)\n"
-   "   vec4 mask_Position = mvp * vertex * vec4(tex_coorda.x * 0.5, tex_coorda.y * 0.5, 0.5, 0.5) + vec4(0.5, 0.5, 0, 0);\n"
-   "   tex_m = vec2(mask_Position.xy - tex_coordm) * tex_sample;\n"
+   "   // position on screen in [0..1] range of current pixel\n"
+   "   vec4 mask_Position = mvp * vertex * vec4(0.5, sign(tex_coorda.y) * 0.5, 0.5, 0.5) + vec4(0.5, 0.5, 0, 0);\n"
+   "   tex_m = mask_Position.xy * tex_sample + tex_coordm;\n"
    "}\n";
 Evas_GL_Program_Source shader_map_mask_nomul_vert_src =
 {
@@ -2812,7 +2809,6 @@ static const char const map_mask_bgra_frag_glsl[] =
    "varying vec4 col;\n"
    "void main()\n"
    "{\n"
-   "   // FIXME: Use mask coordinates within its texture\n"
    "   // FIXME: Fix Mach band effect using proper 4-point color interpolation\n"
    "   gl_FragColor = texture2D(tex, tex_c) * texture2D(texm, tex_m).a *  col;\n"
    "}\n";
@@ -2838,10 +2834,9 @@ static const char const map_mask_bgra_vert_glsl[] =
    "   tex_c = tex_coord;\n"
    "   col = color;\n"
    "   // tex_coorda contains the Y-invert flag\n"
-   "   // tex_coordm contains the X,Y position of the mask\n"
-   "   // tex_sample contains the W,H size of the mask (inverted)\n"
-   "   vec4 mask_Position = mvp * vertex * vec4(tex_coorda.x * 0.5, tex_coorda.y * 0.5, 0.5, 0.5) + vec4(0.5, 0.5, 0, 0);\n"
-   "   tex_m = vec2(mask_Position.xy - tex_coordm) * tex_sample;\n"
+   "   // position on screen in [0..1] range of current pixel\n"
+   "   vec4 mask_Position = mvp * vertex * vec4(0.5, sign(tex_coorda.y) * 0.5, 0.5, 0.5) + vec4(0.5, 0.5, 0, 0);\n"
+   "   tex_m = mask_Position.xy * tex_sample + tex_coordm;\n"
    "}\n";
 Evas_GL_Program_Source shader_map_mask_bgra_vert_src =
 {
@@ -2884,10 +2879,9 @@ static const char const map_mask_bgra_nomul_vert_glsl[] =
    "   gl_Position = mvp * vertex;\n"
    "   tex_c = tex_coord;\n"
    "   // tex_coorda contains the Y-invert flag\n"
-   "   // tex_coordm contains the X,Y position of the mask\n"
-   "   // tex_sample contains the W,H size of the mask (inverted)\n"
-   "   vec4 mask_Position = mvp * vertex * vec4(tex_coorda.x * 0.5, tex_coorda.y * 0.5, 0.5, 0.5) + vec4(0.5, 0.5, 0, 0);\n"
-   "   tex_m = vec2(mask_Position.xy - tex_coordm) * tex_sample;\n"
+   "   // position on screen in [0..1] range of current pixel\n"
+   "   vec4 mask_Position = mvp * vertex * vec4(0.5, sign(tex_coorda.y) * 0.5, 0.5, 0.5) + vec4(0.5, 0.5, 0, 0);\n"
+   "   tex_m = mask_Position.xy * tex_sample + tex_coordm;\n"
    "}\n";
 Evas_GL_Program_Source shader_map_mask_bgra_nomul_vert_src =
 {
index ed4fdf0..be952b7 100644 (file)
@@ -10,7 +10,6 @@ varying vec2 tex_c, tex_m;
 varying vec4 col;
 void main()
 {
-   // FIXME: Use mask coordinates within its texture
    // FIXME: Fix Mach band effect using proper 4-point color interpolation
    gl_FragColor = texture2D(tex, tex_c) * texture2D(texm, tex_m).a *  col;
 }
index 7e2b02e..49da5bc 100644 (file)
@@ -11,9 +11,7 @@ void main()
    tex_c = tex_coord;
 
    // tex_coorda contains the Y-invert flag
-   // tex_coordm contains the X,Y position of the mask
-   // tex_sample contains the W,H size of the mask (inverted)
-
-   vec4 mask_Position = mvp * vertex * vec4(tex_coorda.x * 0.5, tex_coorda.y * 0.5, 0.5, 0.5) + vec4(0.5, 0.5, 0, 0);
-   tex_m = vec2(mask_Position.xy - tex_coordm) * tex_sample;
+   // position on screen in [0..1] range of current pixel
+   vec4 mask_Position = mvp * vertex * vec4(0.5, sign(tex_coorda.y) * 0.5, 0.5, 0.5) + vec4(0.5, 0.5, 0, 0);
+   tex_m = mask_Position.xy * tex_sample + tex_coordm;
 }
index c1c132b..2d2afa9 100644 (file)
@@ -13,9 +13,7 @@ void main()
    col = color;
 
    // tex_coorda contains the Y-invert flag
-   // tex_coordm contains the X,Y position of the mask
-   // tex_sample contains the W,H size of the mask (inverted)
-
-   vec4 mask_Position = mvp * vertex * vec4(tex_coorda.x * 0.5, tex_coorda.y * 0.5, 0.5, 0.5) + vec4(0.5, 0.5, 0, 0);
-   tex_m = vec2(mask_Position.xy - tex_coordm) * tex_sample;
+   // position on screen in [0..1] range of current pixel
+   vec4 mask_Position = mvp * vertex * vec4(0.5, sign(tex_coorda.y) * 0.5, 0.5, 0.5) + vec4(0.5, 0.5, 0, 0);
+   tex_m = mask_Position.xy * tex_sample + tex_coordm;
 }
index 7a7579a..17e91f4 100644 (file)
@@ -10,7 +10,6 @@ varying vec2 tex_c, tex_m;
 varying vec4 col;
 void main()
 {
-   // FIXME: Use mask coordinates within its texture
    // FIXME: Fix Mach band effect using proper 4-point color interpolation
    gl_FragColor = texture2D(tex, tex_c).bgra * texture2D(texm, tex_m).a *  col;
 }
index 7e2b02e..49da5bc 100644 (file)
@@ -11,9 +11,7 @@ void main()
    tex_c = tex_coord;
 
    // tex_coorda contains the Y-invert flag
-   // tex_coordm contains the X,Y position of the mask
-   // tex_sample contains the W,H size of the mask (inverted)
-
-   vec4 mask_Position = mvp * vertex * vec4(tex_coorda.x * 0.5, tex_coorda.y * 0.5, 0.5, 0.5) + vec4(0.5, 0.5, 0, 0);
-   tex_m = vec2(mask_Position.xy - tex_coordm) * tex_sample;
+   // position on screen in [0..1] range of current pixel
+   vec4 mask_Position = mvp * vertex * vec4(0.5, sign(tex_coorda.y) * 0.5, 0.5, 0.5) + vec4(0.5, 0.5, 0, 0);
+   tex_m = mask_Position.xy * tex_sample + tex_coordm;
 }
index c1c132b..2d2afa9 100644 (file)
@@ -13,9 +13,7 @@ void main()
    col = color;
 
    // tex_coorda contains the Y-invert flag
-   // tex_coordm contains the X,Y position of the mask
-   // tex_sample contains the W,H size of the mask (inverted)
-
-   vec4 mask_Position = mvp * vertex * vec4(tex_coorda.x * 0.5, tex_coorda.y * 0.5, 0.5, 0.5) + vec4(0.5, 0.5, 0, 0);
-   tex_m = vec2(mask_Position.xy - tex_coordm) * tex_sample;
+   // position on screen in [0..1] range of current pixel
+   vec4 mask_Position = mvp * vertex * vec4(0.5, sign(tex_coorda.y) * 0.5, 0.5, 0.5) + vec4(0.5, 0.5, 0, 0);
+   tex_m = mask_Position.xy * tex_sample + tex_coordm;
 }