Evas masking: Add rectangle masking for GL
authorJean-Philippe Andre <jp.andre@samsung.com>
Tue, 2 Dec 2014 06:19:10 +0000 (15:19 +0900)
committerJean-Philippe Andre <jp.andre@samsung.com>
Wed, 7 Jan 2015 06:06:03 +0000 (15:06 +0900)
src/Makefile_Evas.am
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_polygon.c
src/modules/evas/engines/gl_common/evas_gl_rectangle.c
src/modules/evas/engines/gl_common/shader/evas_gl_enum.x
src/modules/evas/engines/gl_common/shader/evas_gl_shaders.x
src/modules/evas/engines/gl_common/shader/rect_mask_frag.shd [new file with mode: 0644]
src/modules/evas/engines/gl_common/shader/rect_mask_vert.shd [new file with mode: 0644]

index 78515ad..4ff091c 100644 (file)
@@ -699,6 +699,8 @@ modules/evas/engines/gl_common/shader/yuy2_mask_frag.shd \
 modules/evas/engines/gl_common/shader/yuy2_mask_vert.shd \
 modules/evas/engines/gl_common/shader/rgb_a_pair_mask_frag.shd \
 modules/evas/engines/gl_common/shader/rgb_a_pair_mask_vert.shd \
+modules/evas/engines/gl_common/shader/rect_mask_frag.shd \
+modules/evas/engines/gl_common/shader/rect_mask_vert.shd \
 $(NULL)
 
 EXTRA_DIST += \
index 37873d2..421bd14 100644 (file)
@@ -720,7 +720,8 @@ void              evas_gl_common_context_line_push(Evas_Engine_GL_Context *gc,
                                                    int r, int g, int b, int a);
 void              evas_gl_common_context_rectangle_push(Evas_Engine_GL_Context *gc,
                                                         int x, int y, int w, int h,
-                                                        int r, int g, int b, int a);
+                                                        int r, int g, int b, int a,
+                                                        Evas_GL_Texture *mtex, int mx, int my, int mw, int mh);
 void              evas_gl_common_context_image_push(Evas_Engine_GL_Context *gc,
                                                     Evas_GL_Texture *tex,
                                                     double sx, double sy, double sw, double sh,
index ae5f114..2adc874 100644 (file)
@@ -883,6 +883,8 @@ evas_gl_common_context_new(void)
         SHADER_TEXTURE_ADD(shared, FONT_MASK, tex);
         SHADER_TEXTURE_ADD(shared, FONT_MASK, texm);
 
+        SHADER_TEXTURE_ADD(shared, RECT_MASK, texm);
+
         if (gc->state.current.cur_prog == PRG_INVALID)
            glUseProgram(shared->shader[0].prog);
         else glUseProgram(gc->state.current.cur_prog);
@@ -1569,15 +1571,25 @@ evas_gl_common_context_line_push(Evas_Engine_GL_Context *gc,
 void
 evas_gl_common_context_rectangle_push(Evas_Engine_GL_Context *gc,
                                       int x, int y, int w, int h,
-                                      int r, int g, int b, int a)
+                                      int r, int g, int b, int a,
+                                      Evas_GL_Texture *mtex,
+                                      int mx, int my, int mw, int mh)
 {
    Eina_Bool blend = EINA_FALSE;
    GLuint prog = gc->shared->shader[SHADER_RECT].prog;
+   GLuint mtexid = 0;
    int pn = 0;
 
    if (!(gc->dc->render_op == EVAS_RENDER_COPY) && (a < 255))
      blend = EINA_TRUE;
 
+   if (mtex)
+     {
+        blend = EINA_TRUE;
+        mtexid = mtex->pt->texture;
+        prog = gc->shared->shader[SHADER_RECT_MASK].prog;
+     }
+
 again:
    vertex_array_size_check(gc, gc->state.top_pipe, 6);
    pn = gc->state.top_pipe;
@@ -1586,6 +1598,7 @@ again:
      {
         gc->pipe[pn].region.type = RTYPE_RECT;
         gc->pipe[pn].shader.cur_tex = 0;
+        gc->pipe[pn].shader.cur_texm = mtexid;
         gc->pipe[pn].shader.cur_prog = prog;
         gc->pipe[pn].shader.blend = blend;
         gc->pipe[pn].shader.render_op = gc->dc->render_op;
@@ -1602,7 +1615,7 @@ again:
         gc->pipe[pn].array.use_texuv3 = 0;
         gc->pipe[pn].array.use_texa = 0;
         gc->pipe[pn].array.use_texsam = 0;
-        gc->pipe[pn].array.use_texm = 0;
+        gc->pipe[pn].array.use_texm = !!mtex;
      }
    else
      {
@@ -1612,6 +1625,7 @@ again:
           {
              if ((gc->pipe[i].region.type == RTYPE_RECT)
                  && (gc->pipe[i].shader.cur_tex == 0)
+                 && (gc->pipe[i].shader.cur_texm == mtexid)
                  && (gc->pipe[i].shader.cur_prog == prog)
                  && (gc->pipe[i].shader.blend == blend)
                  && (gc->pipe[i].shader.render_op == gc->dc->render_op)
@@ -1635,6 +1649,7 @@ again:
              gc->state.top_pipe = pn;
              gc->pipe[pn].region.type = RTYPE_RECT;
              gc->pipe[pn].shader.cur_tex = 0;
+             gc->pipe[pn].shader.cur_texm = mtexid;
              gc->pipe[pn].shader.cur_prog = prog;
              gc->pipe[pn].shader.blend = blend;
              gc->pipe[pn].shader.render_op = gc->dc->render_op;
@@ -1651,11 +1666,12 @@ again:
              gc->pipe[pn].array.use_texuv3 = 0;
              gc->pipe[pn].array.use_texa = 0;
              gc->pipe[pn].array.use_texsam = 0;
-             gc->pipe[pn].array.use_texm = 0;
+             gc->pipe[pn].array.use_texm = !!mtex;
          }
      }
 #else
    if ((gc->pipe[pn].shader.cur_tex != 0)
+       || (gc->pipe[pn].shader.cur_texm != mtexid)
        || (gc->pipe[pn].shader.cur_prog != prog)
        || (gc->pipe[pn].shader.blend != blend)
        || (gc->pipe[pn].shader.render_op != gc->dc->render_op)
@@ -1665,6 +1681,7 @@ again:
         shader_array_flush(gc);
         pn = gc->state.top_pipe;
         gc->pipe[pn].shader.cur_tex = 0;
+        gc->pipe[pn].shader.cur_texm = mtexid;
         gc->pipe[pn].shader.cur_prog = prog;
         gc->pipe[pn].shader.blend = blend;
         gc->pipe[pn].shader.render_op = gc->dc->render_op;
@@ -1684,7 +1701,7 @@ again:
    gc->pipe[pn].array.use_texuv3 = 0;
    gc->pipe[pn].array.use_texa = 0;
    gc->pipe[pn].array.use_texsam = 0;
-   gc->pipe[pn].array.use_texm = 0;
+   gc->pipe[pn].array.use_texm = !!mtex;
 #endif
 
    pipe_region_expand(gc, pn, x, y, w, h);
@@ -1698,6 +1715,8 @@ again:
    PUSH_VERTEX(pn, x + w, y + h, 0);
    PUSH_VERTEX(pn, x    , y + h, 0);
 
+   PUSH_MASK(pn, mtex, mx, my, mw, mh);
+
    PUSH_6_COLORS(pn, r, g, b, a);
 }
 
@@ -3175,7 +3194,7 @@ shader_array_flush(Evas_Engine_GL_Context *gc)
           }
         else
           {
-             GLint MASK_TEXTURE = GL_TEXTURE1;
+             GLint MASK_TEXTURE = GL_TEXTURE0;
 
              if (gc->pipe[i].array.use_texuv)
                {
@@ -3184,6 +3203,8 @@ shader_array_flush(Evas_Engine_GL_Context *gc)
                   glVertexAttribPointer(SHAD_TEXUV, 2, GL_FLOAT, GL_FALSE, 0,
                                         (void *)texuv_ptr);
                   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+
+                  MASK_TEXTURE += 1;
                }
              else
                {
index afaaad5..0e5dd7f 100644 (file)
@@ -139,6 +139,8 @@ evas_gl_common_poly_draw(Evas_Engine_GL_Context *gc, Evas_GL_Polygon *poly, int
    Evas_GL_Polygon_Point *pt;
    Eina_Inlist *spans;
 
+   // TODO: Implement masking support (not very important right now)
+
    /* save out clip info */
    c = gc->dc->clip.use; cx = gc->dc->clip.x; cy = gc->dc->clip.y; cw = gc->dc->clip.w; ch = gc->dc->clip.h;
 
@@ -268,7 +270,9 @@ evas_gl_common_poly_draw(Evas_Engine_GL_Context *gc, Evas_GL_Polygon *poly, int
                   y = span->y;
                   w = span->w;
                   h = 1;
-                  evas_gl_common_context_rectangle_push(gc, x, y, w, h, cr, cg, cb, ca);
+                  evas_gl_common_context_rectangle_push(gc, x, y, w, h,
+                                                        cr, cg, cb, ca,
+                                                        NULL, 0, 0, 0, 0);
                }
           }
         else
@@ -290,7 +294,9 @@ evas_gl_common_poly_draw(Evas_Engine_GL_Context *gc, Evas_GL_Polygon *poly, int
                                  h = 1;
                                  RECTS_CLIP_TO_RECT(x, y, w, h, r->x, r->y, r->w, r->h);
                                  if ((w > 0) && (h > 0))
-                                   evas_gl_common_context_rectangle_push(gc, x, y, w, h, cr, cg, cb, ca);
+                                   evas_gl_common_context_rectangle_push(gc, x, y, w, h,
+                                                                         cr, cg, cb, ca,
+                                                                         NULL, 0, 0, 0, 0);
                               }
                          }
                     }
index b9ae03a..7ef30fc 100644 (file)
@@ -5,6 +5,8 @@ evas_gl_common_rect_draw(Evas_Engine_GL_Context *gc, int x, int y, int w, int h)
 {
    Cutout_Rect  *r;
    int          c, cx, cy, cw, ch, cr, cg, cb, ca, i;
+   double mx = 0, my = 0, mw = 0, mh = 0;
+   Evas_GL_Texture *mtex = NULL;
 
    if ((w <= 0) || (h <= 0)) return;
    if (!(RECTS_INTERSECT(x, y, w, h, 0, 0, gc->w, gc->h))) return;
@@ -26,9 +28,21 @@ evas_gl_common_rect_draw(Evas_Engine_GL_Context *gc, int x, int y, int w, int h)
                            gc->dc->clip.w, gc->dc->clip.h);
      }
 
+   if (gc->dc->clip.mask)
+     {
+        Evas_GL_Image *mask = gc->dc->clip.mask;
+
+        mx = gc->dc->clip.mask_x; mw = mask->w;
+        my = gc->dc->clip.mask_y; mh = mask->h;
+        RECTS_CLIP_TO_RECT(mx, my, mw, mh, cx, cy, cw, ch);
+        mx -= gc->dc->clip.mask_x;
+        my -= gc->dc->clip.mask_y;
+        mtex = mask->tex;
+     }
+
    if (!gc->dc->cutout.rects)
      {
-        evas_gl_common_context_rectangle_push(gc, x, y, w, h, cr, cg, cb, ca);
+        evas_gl_common_context_rectangle_push(gc, x, y, w, h, cr, cg, cb, ca, mtex, mx, my, mw, mh);
      }
    else
      {
@@ -42,7 +56,7 @@ evas_gl_common_rect_draw(Evas_Engine_GL_Context *gc, int x, int y, int w, int h)
                   r = _evas_gl_common_cutout_rects->rects + i;
                   if ((r->w > 0) && (r->h > 0))
                     {
-                       evas_gl_common_context_rectangle_push(gc, r->x, r->y, r->w, r->h, cr, cg, cb, ca);
+                       evas_gl_common_context_rectangle_push(gc, r->x, r->y, r->w, r->h, cr, cg, cb, ca, mtex, mx, my, mw, mh);
                     }
                }
              evas_common_draw_context_cutouts_free(_evas_gl_common_cutout_rects);
index d1227ef..6f0fb93 100644 (file)
@@ -53,5 +53,6 @@ typedef enum {
    SHADER_NV12_MASK,
    SHADER_YUY2_MASK,
    SHADER_RGB_A_PAIR_MASK,
+   SHADER_RECT_MASK,
    SHADER_LAST
 } Evas_GL_Shader;
index 08b8867..555bfa8 100644 (file)
@@ -2656,6 +2656,51 @@ Evas_GL_Program_Source shader_rgb_a_pair_mask_vert_src =
    NULL, 0
 };
 
+/* Source: modules/evas/engines/gl_common/shader/rect_mask_frag.shd */
+static const char const rect_mask_frag_glsl[] =
+   "#ifdef GL_ES\n"
+   "#ifdef GL_FRAGMENT_PRECISION_HIGH\n"
+   "precision highp float;\n"
+   "#else\n"
+   "precision mediump float;\n"
+   "#endif\n"
+   "#endif\n"
+   "uniform sampler2D texm;\n"
+   "varying vec4 col;\n"
+   "varying vec4 coord_m;\n"
+   "void main()\n"
+   "{\n"
+   "   gl_FragColor = texture2D(texm, coord_m.xy).a * col;\n"
+   "}\n";
+Evas_GL_Program_Source shader_rect_mask_frag_src =
+{
+   rect_mask_frag_glsl,
+   NULL, 0
+};
+
+/* Source: modules/evas/engines/gl_common/shader/rect_mask_vert.shd */
+static const char const rect_mask_vert_glsl[] =
+   "#ifdef GL_ES\n"
+   "precision highp float;\n"
+   "#endif\n"
+   "attribute vec4 vertex;\n"
+   "attribute vec4 color;\n"
+   "attribute vec4 tex_coordm;\n"
+   "uniform mat4 mvp;\n"
+   "varying vec4 col;\n"
+   "varying vec4 coord_m;\n"
+   "void main()\n"
+   "{\n"
+   "   gl_Position = mvp * vertex;\n"
+   "   col = color;\n"
+   "   coord_m = tex_coordm;\n"
+   "}\n";
+Evas_GL_Program_Source shader_rect_mask_vert_src =
+{
+   rect_mask_vert_glsl,
+   NULL, 0
+};
+
 static const struct {
    Evas_GL_Shader id;
    Evas_GL_Program_Source *vert;
@@ -2713,5 +2758,6 @@ static const struct {
    { SHADER_NV12_MASK, &(shader_nv12_mask_vert_src), &(shader_nv12_mask_frag_src), "nv12_mask" },
    { SHADER_YUY2_MASK, &(shader_yuy2_mask_vert_src), &(shader_yuy2_mask_frag_src), "yuy2_mask" },
    { SHADER_RGB_A_PAIR_MASK, &(shader_rgb_a_pair_mask_vert_src), &(shader_rgb_a_pair_mask_frag_src), "rgb_a_pair_mask" },
+   { SHADER_RECT_MASK, &(shader_rect_mask_vert_src), &(shader_rect_mask_frag_src), "rect_mask" },
 };
 
diff --git a/src/modules/evas/engines/gl_common/shader/rect_mask_frag.shd b/src/modules/evas/engines/gl_common/shader/rect_mask_frag.shd
new file mode 100644 (file)
index 0000000..e278ea6
--- /dev/null
@@ -0,0 +1,14 @@
+#ifdef GL_ES
+#ifdef GL_FRAGMENT_PRECISION_HIGH
+precision highp float;
+#else
+precision mediump float;
+#endif
+#endif
+uniform sampler2D texm;
+varying vec4 col;
+varying vec4 coord_m;
+void main()
+{
+   gl_FragColor = texture2D(texm, coord_m.xy).a * col;
+}
diff --git a/src/modules/evas/engines/gl_common/shader/rect_mask_vert.shd b/src/modules/evas/engines/gl_common/shader/rect_mask_vert.shd
new file mode 100644 (file)
index 0000000..4a1dd2c
--- /dev/null
@@ -0,0 +1,15 @@
+#ifdef GL_ES
+precision highp float;
+#endif
+attribute vec4 vertex;
+attribute vec4 color;
+attribute vec4 tex_coordm;
+uniform mat4 mvp;
+varying vec4 col;
+varying vec4 coord_m;
+void main()
+{
+   gl_Position = mvp * vertex;
+   col = color;
+   coord_m = tex_coordm;
+}