From 44387b60a35836cf21e8d215be0d298a6b843431 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Andre Date: Tue, 2 Dec 2014 15:19:10 +0900 Subject: [PATCH] Evas masking: Add rectangle masking for GL --- src/Makefile_Evas.am | 2 + .../evas/engines/gl_common/evas_gl_common.h | 3 +- .../evas/engines/gl_common/evas_gl_context.c | 31 +++++++++++-- .../evas/engines/gl_common/evas_gl_polygon.c | 10 +++- .../engines/gl_common/evas_gl_rectangle.c | 18 +++++++- .../engines/gl_common/shader/evas_gl_enum.x | 1 + .../gl_common/shader/evas_gl_shaders.x | 46 +++++++++++++++++++ .../gl_common/shader/rect_mask_frag.shd | 14 ++++++ .../gl_common/shader/rect_mask_vert.shd | 15 ++++++ 9 files changed, 130 insertions(+), 10 deletions(-) create mode 100644 src/modules/evas/engines/gl_common/shader/rect_mask_frag.shd create mode 100644 src/modules/evas/engines/gl_common/shader/rect_mask_vert.shd diff --git a/src/Makefile_Evas.am b/src/Makefile_Evas.am index 78515ad622..4ff091c099 100644 --- a/src/Makefile_Evas.am +++ b/src/Makefile_Evas.am @@ -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 += \ diff --git a/src/modules/evas/engines/gl_common/evas_gl_common.h b/src/modules/evas/engines/gl_common/evas_gl_common.h index 37873d24fe..421bd14918 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_common.h +++ b/src/modules/evas/engines/gl_common/evas_gl_common.h @@ -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, diff --git a/src/modules/evas/engines/gl_common/evas_gl_context.c b/src/modules/evas/engines/gl_common/evas_gl_context.c index ae5f11469e..2adc874e2f 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_context.c +++ b/src/modules/evas/engines/gl_common/evas_gl_context.c @@ -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 { diff --git a/src/modules/evas/engines/gl_common/evas_gl_polygon.c b/src/modules/evas/engines/gl_common/evas_gl_polygon.c index afaaad586e..0e5dd7f83a 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_polygon.c +++ b/src/modules/evas/engines/gl_common/evas_gl_polygon.c @@ -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); } } } diff --git a/src/modules/evas/engines/gl_common/evas_gl_rectangle.c b/src/modules/evas/engines/gl_common/evas_gl_rectangle.c index b9ae03ab34..7ef30fc149 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_rectangle.c +++ b/src/modules/evas/engines/gl_common/evas_gl_rectangle.c @@ -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); diff --git a/src/modules/evas/engines/gl_common/shader/evas_gl_enum.x b/src/modules/evas/engines/gl_common/shader/evas_gl_enum.x index d1227ef9c6..6f0fb93d1d 100644 --- a/src/modules/evas/engines/gl_common/shader/evas_gl_enum.x +++ b/src/modules/evas/engines/gl_common/shader/evas_gl_enum.x @@ -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; diff --git a/src/modules/evas/engines/gl_common/shader/evas_gl_shaders.x b/src/modules/evas/engines/gl_common/shader/evas_gl_shaders.x index 08b88675d4..555bfa8335 100644 --- a/src/modules/evas/engines/gl_common/shader/evas_gl_shaders.x +++ b/src/modules/evas/engines/gl_common/shader/evas_gl_shaders.x @@ -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 index 0000000000..e278ea63e7 --- /dev/null +++ b/src/modules/evas/engines/gl_common/shader/rect_mask_frag.shd @@ -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 index 0000000000..4a1dd2cc8c --- /dev/null +++ b/src/modules/evas/engines/gl_common/shader/rect_mask_vert.shd @@ -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; +}