Evas masking: Font masking for GL

This commit is contained in:
Jean-Philippe Andre 2014-11-25 14:34:42 +09:00
parent 124ab102b7
commit 1fac1dcf57
9 changed files with 299 additions and 4 deletions

View File

@ -599,6 +599,8 @@ modules/evas/engines/gl_common/evas_gl_3d_shader.c
GL_SHADERS_GEN = \
modules/evas/engines/gl_common/shader/font_frag.shd \
modules/evas/engines/gl_common/shader/font_vert.shd \
modules/evas/engines/gl_common/shader/font_mask_frag.shd \
modules/evas/engines/gl_common/shader/font_mask_vert.shd \
modules/evas/engines/gl_common/shader/img_12_bgra_frag.shd \
modules/evas/engines/gl_common/shader/img_12_bgra_nomul_frag.shd \
modules/evas/engines/gl_common/shader/img_12_bgra_nomul_vert.shd \

View File

@ -729,6 +729,13 @@ void evas_gl_common_context_font_push(Evas_Engine_GL_Context *gc,
double sx, double sy, double sw, double sh,
int x, int y, int w, int h,
int r, int g, int b, int a);
void evas_gl_common_context_masked_font_push(Evas_Engine_GL_Context *gc,
Evas_GL_Texture *tex,
double sx, double sy, double sw, double sh,
int x, int y, int w, int h,
int r, int g, int b, int a,
Evas_GL_Texture *texa,
int mx, int my, int mw, int mh);
void evas_gl_common_context_yuv_push(Evas_Engine_GL_Context *gc,
Evas_GL_Texture *tex,
double sx, double sy, double sw, double sh,

View File

@ -856,6 +856,9 @@ evas_gl_common_context_new(void)
SHADER_TEXTURE_ADD(shared, IMG_MASK_NOMUL, tex);
SHADER_TEXTURE_ADD(shared, IMG_MASK_NOMUL, texa);
SHADER_TEXTURE_ADD(shared, FONT_MASK, tex);
SHADER_TEXTURE_ADD(shared, FONT_MASK, texa);
if (gc->state.current.cur_prog == PRG_INVALID)
glUseProgram(shared->shader[0].prog);
else glUseProgram(gc->state.current.cur_prog);
@ -1899,6 +1902,106 @@ evas_gl_common_context_image_push(Evas_Engine_GL_Context *gc,
}
}
void
evas_gl_common_context_masked_font_push(Evas_Engine_GL_Context *gc,
Evas_GL_Texture *tex,
double sx, double sy, double sw, double sh,
int x, int y, int w, int h,
int r, int g, int b, int a,
Evas_GL_Texture *texa,
int mx, int my, int mw, int mh)
{
int pnum, nv, nc, nu, na, i;
GLfloat tx1, tx2, ty1, ty2, t2x1, t2x2, t2y1, t2y2;
GLuint prog = gc->shared->shader[SHADER_FONT_MASK].prog;
int pn = 0;
pn = _evas_gl_common_context_push(RTYPE_FONT,
gc, tex,
prog,
x, y, w, h,
1,
0,
0, 0, 0, 0, 0);
gc->pipe[pn].region.type = RTYPE_FONT;
gc->pipe[pn].shader.cur_tex = tex->pt->texture;
gc->pipe[pn].shader.cur_texa = texa->pt->texture;
gc->pipe[pn].shader.cur_prog = prog;
gc->pipe[pn].shader.smooth = 0;
gc->pipe[pn].shader.blend = 1;
gc->pipe[pn].shader.render_op = gc->dc->render_op;
gc->pipe[pn].shader.clip = 0;
gc->pipe[pn].shader.cx = 0;
gc->pipe[pn].shader.cy = 0;
gc->pipe[pn].shader.cw = 0;
gc->pipe[pn].shader.ch = 0;
gc->pipe[pn].array.line = 0;
gc->pipe[pn].array.use_vertex = 1;
gc->pipe[pn].array.use_color = 1;
gc->pipe[pn].array.use_texuv = 1;
gc->pipe[pn].array.use_texuv2 = 0;
gc->pipe[pn].array.use_texuv3 = 0;
gc->pipe[pn].array.use_texa = 1; //
gc->pipe[pn].array.use_texsam = 0;
pipe_region_expand(gc, pn, x, y, w, h);
pnum = gc->pipe[pn].array.num;
nv = pnum * 3; nc = pnum * 4; nu = pnum * 2; na = pnum * 2;
gc->pipe[pn].array.num += 6;
array_alloc(gc, pn);
if (sw == 0.0)
{
tx1 = tex->sx1;
ty1 = tex->sy1;
tx2 = tex->sx2;
ty2 = tex->sy2;
}
else
{
tx1 = ((double)(tex->x) + sx) / (double)tex->pt->w;
ty1 = ((double)(tex->y) + sy) / (double)tex->pt->h;
tx2 = ((double)(tex->x) + sx + sw) / (double)tex->pt->w;
ty2 = ((double)(tex->y) + sy + sh) / (double)tex->pt->h;
}
t2x1 = (texa->x + mx) / (double)texa->pt->w;
t2y1 = (texa->y + my) / (double)texa->pt->h;
t2x2 = (texa->x + mx + mw) / (double)texa->pt->w;
t2y2 = (texa->y + my + mh) / (double)texa->pt->h;
PUSH_VERTEX(pn, x , y , 0);
PUSH_VERTEX(pn, x + w, y , 0);
PUSH_VERTEX(pn, x , y + h, 0);
PUSH_TEXUV(pn, tx1, ty1);
PUSH_TEXUV(pn, tx2, ty1);
PUSH_TEXUV(pn, tx1, ty2);
PUSH_TEXA(pn, t2x1, t2y1);
PUSH_TEXA(pn, t2x2, t2y1);
PUSH_TEXA(pn, t2x1, t2y2);
PUSH_VERTEX(pn, x + w, y , 0);
PUSH_VERTEX(pn, x + w, y + h, 0);
PUSH_VERTEX(pn, x , y + h, 0);
PUSH_TEXUV(pn, tx2, ty1);
PUSH_TEXUV(pn, tx2, ty2);
PUSH_TEXUV(pn, tx1, ty2);
PUSH_TEXA(pn, t2x2, t2y1);
PUSH_TEXA(pn, t2x2, t2y2);
PUSH_TEXA(pn, t2x1, t2y2);
for (i = 0; i < 6; i++)
{
PUSH_COLOR(pn, r, g, b, a);
}
}
void
evas_gl_common_context_font_push(Evas_Engine_GL_Context *gc,
Evas_GL_Texture *tex,

View File

@ -68,6 +68,7 @@ evas_gl_font_texture_draw(void *context, void *surface EINA_UNUSED, void *draw_c
int c, cx, cy, cw, ch;
int i;
int sx, sy, sw, sh;
double mx, my, mw, mh, mmx, mmy, mmw, mmh;
if (dc != gc->dc) return;
tex = fg->ext_dat;
@ -78,6 +79,42 @@ evas_gl_font_texture_draw(void *context, void *surface EINA_UNUSED, void *draw_c
g = (dc->col.col >> 8 ) & 0xff;
b = (dc->col.col ) & 0xff;
sx = 0; sy = 0; sw = tex->w, sh = tex->h;
if (gc->dc->clip.mask && (sw > 0) && (sh > 0))
{
// FIXME: This code path does not handle half the stuff the other path does...
Evas_GL_Image *mask = gc->dc->clip.mask;
int nx, ny, nw, nh, dx, dy, dw, dh;
nx = x; ny = y; nw = tex->w; nh = tex->h;
RECTS_CLIP_TO_RECT(nx, ny, nw, nh,
gc->dc->clip.x, gc->dc->clip.y,
gc->dc->clip.w, gc->dc->clip.h);
if ((nw < 1) || (nh < 1)) return;
ssx = (double)sx + ((double)(sw * (nx - x)) / (double)(tex->w));
ssy = (double)sy + ((double)(sh * (ny - y)) / (double)(tex->h));
ssw = ((double)sw * (double)(nw)) / (double)(tex->w);
ssh = ((double)sh * (double)(nh)) / (double)(tex->h);
dx = x; dy = y; dw = sw; dh = sh;
mx = gc->dc->clip.mask_x; my = gc->dc->clip.mask_y; mw = mask->w; mh = mask->h;
//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 = (double)(mx - gc->dc->clip.mask_x) + ((double)(mw * (nx - dx)) / (double)(dw));
mmy = (double)(my - gc->dc->clip.mask_y) + ((double)(mh * (ny - dy)) / (double)(dh));
mmw = ((double)mw * (double)(nw)) / (double)(dw);
mmh = ((double)mh * (double)(nh)) / (double)(dh);
evas_gl_common_context_masked_font_push(gc, tex,
ssx, ssy, ssw, ssh,
nx, ny, nw, nh,
r, g, b, a,
mask->tex, mmx, mmy, mmw, mmh);
return;
}
if ((!gc->dc->cutout.rects) ||
((gc->shared->info.tune.cutout.max > 0) &&
(gc->dc->cutout.active > gc->shared->info.tune.cutout.max)))

View File

@ -3,6 +3,7 @@
typedef enum {
SHADER_FONT,
SHADER_FONT_MASK,
SHADER_IMG_12_BGRA_NOMUL,
SHADER_IMG_12_BGRA,
SHADER_IMG_12_NOMUL,

View File

@ -48,6 +48,56 @@ Evas_GL_Program_Source shader_font_vert_src =
NULL, 0
};
/* Source: modules/evas/engines/gl_common/shader/font_mask_frag.shd */
static const char const font_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 tex;\n"
"uniform sampler2D texa;\n"
"varying vec4 col;\n"
"varying vec2 tex_c;\n"
"varying vec2 tex_a;\n"
"void main()\n"
"{\n"
" gl_FragColor = texture2D(tex, tex_c.xy).aaaa * texture2D(texa, tex_a.xy).aaaa * col;\n"
"}\n";
Evas_GL_Program_Source shader_font_mask_frag_src =
{
font_mask_frag_glsl,
NULL, 0
};
/* Source: modules/evas/engines/gl_common/shader/font_mask_vert.shd */
static const char const font_mask_vert_glsl[] =
"#ifdef GL_ES\n"
"precision highp float;\n"
"#endif\n"
"attribute vec4 vertex;\n"
"attribute vec4 color;\n"
"attribute vec2 tex_coord;\n"
"attribute vec2 tex_coorda;\n"
"uniform mat4 mvp;\n"
"varying vec4 col;\n"
"varying vec2 tex_c;\n"
"varying vec2 tex_a;\n"
"void main()\n"
"{\n"
" gl_Position = mvp * vertex;\n"
" col = color;\n"
" tex_c = tex_coord;\n"
" tex_a = tex_coorda;\n"
"}\n";
Evas_GL_Program_Source shader_font_mask_vert_src =
{
font_mask_vert_glsl,
NULL, 0
};
/* Source: modules/evas/engines/gl_common/shader/img_12_bgra_frag.shd */
static const char const img_12_bgra_frag_glsl[] =
"#ifdef GL_ES\n"
@ -2182,7 +2232,7 @@ Evas_GL_Program_Source shader_yuy2_vert_src =
};
/* Source: modules/evas/engines/gl_common/shader/img_mask_frag.shd */
static const char img_mask_frag_glsl[] =
static const char const img_mask_frag_glsl[] =
"#ifdef GL_ES\n"
"#ifdef GL_FRAGMENT_PRECISION_HIGH\n"
"precision highp float;\n"
@ -2207,7 +2257,7 @@ Evas_GL_Program_Source shader_img_mask_frag_src =
};
/* Source: modules/evas/engines/gl_common/shader/img_mask_vert.shd */
static const char img_mask_vert_glsl[] =
static const char const img_mask_vert_glsl[] =
"#ifdef GL_ES\n"
"precision highp float;\n"
"#endif\n"
@ -2233,7 +2283,7 @@ Evas_GL_Program_Source shader_img_mask_vert_src =
};
/* Source: modules/evas/engines/gl_common/shader/img_mask_nomul_frag.shd */
static const char img_mask_nomul_frag_glsl[] =
static const char const img_mask_nomul_frag_glsl[] =
"#ifdef GL_ES\n"
"#ifdef GL_FRAGMENT_PRECISION_HIGH\n"
"precision highp float;\n"
@ -2257,7 +2307,7 @@ Evas_GL_Program_Source shader_img_mask_nomul_frag_src =
};
/* Source: modules/evas/engines/gl_common/shader/img_mask_nomul_vert.shd */
static const char img_mask_nomul_vert_glsl[] =
static const char const img_mask_nomul_vert_glsl[] =
"#ifdef GL_ES\n"
"precision highp float;\n"
"#endif\n"
@ -2286,6 +2336,7 @@ static const struct {
const char *name;
} _shaders_source[] = {
{ SHADER_FONT, &(shader_font_vert_src), &(shader_font_frag_src), "font" },
{ SHADER_FONT_MASK, &(shader_font_mask_vert_src), &(shader_font_mask_frag_src), "font_mask" },
{ SHADER_IMG_12_BGRA_NOMUL, &(shader_img_12_bgra_nomul_vert_src), &(shader_img_12_bgra_nomul_frag_src), "img_12_bgra_nomul" },
{ SHADER_IMG_12_BGRA, &(shader_img_12_bgra_vert_src), &(shader_img_12_bgra_frag_src), "img_12_bgra" },
{ SHADER_IMG_12_NOMUL, &(shader_img_12_nomul_vert_src), &(shader_img_12_nomul_frag_src), "img_12_nomul" },

View File

@ -0,0 +1,17 @@
#ifdef GL_ES
#ifdef GL_FRAGMENT_PRECISION_HIGH
precision highp float;
#else
precision mediump float;
#endif
#endif
uniform sampler2D tex;
uniform sampler2D texa;
varying vec4 col;
varying vec2 tex_c;
varying vec2 tex_a;
void main()
{
gl_FragColor = texture2D(tex, tex_c.xy).aaaa * texture2D(texa, tex_a.xy).aaaa * col;
}

View File

@ -0,0 +1,19 @@
#ifdef GL_ES
precision highp float;
#endif
attribute vec4 vertex;
attribute vec4 color;
attribute vec2 tex_coord;
attribute vec2 tex_coorda;
uniform mat4 mvp;
varying vec4 col;
varying vec2 tex_c;
varying vec2 tex_a;
void main()
{
gl_Position = mvp * vertex;
col = color;
tex_c = tex_coord;
tex_a = tex_coorda;
}

View File

@ -1695,6 +1695,60 @@ eng_context_flush(void *data)
}
}
static void
eng_context_clip_image_unset(void *data EINA_UNUSED, void *context)
{
RGBA_Draw_Context *ctx = context;
Evas_GL_Image *im = ctx->clip.mask;
if (im && im->im)
{
#ifdef EVAS_CSERVE2
if (evas_cserve2_use_get())
evas_cache2_image_close(&im->im->cache_entry);
else
#endif
evas_cache_image_drop(&im->im->cache_entry);
// Is the above code safe? Hmmm...
//evas_unref_queue_image_put(EVAS???, &ctx->clip.ie->cache_entry);
}
ctx->clip.mask = NULL;
}
static void
eng_context_clip_image_set(void *data EINA_UNUSED, void *context, void *surface, int x, int y)
{
RGBA_Draw_Context *ctx = context;
Evas_GL_Image *im = surface;
if (ctx->clip.mask && ctx->clip.mask != surface)
eng_context_clip_image_unset(data, context);
ctx->clip.mask = surface;
ctx->clip.mask_x = x;
ctx->clip.mask_y = y;
if (im && im->im)
{
#ifdef EVAS_CSERVE2
if (evas_cserve2_use_get())
evas_cache2_image_ref(&im->im->cache_entry);
else
#endif
evas_cache_image_ref(&im->im->cache_entry);
}
}
static void
eng_context_clip_image_get(void *data EINA_UNUSED, void *context, void **ie, int *x, int *y)
{
RGBA_Draw_Context *ctx = context;
if (ie) *ie = ctx->clip.mask;
if (x) *x = ctx->clip.mask_x;
if (y) *y = ctx->clip.mask_y;
}
static void
eng_context_3d_use(void *data)
{
@ -1885,6 +1939,10 @@ module_open(Evas_Module *em)
func = pfunc;
/* now to override methods */
#define ORD(f) EVAS_API_OVERRIDE(f, &func, eng_)
ORD(context_clip_image_set);
ORD(context_clip_image_unset);
ORD(context_clip_image_get);
ORD(rectangle_draw);
ORD(line_draw);
ORD(polygon_point_add);