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 = \ GL_SHADERS_GEN = \
modules/evas/engines/gl_common/shader/font_frag.shd \ 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_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_frag.shd \
modules/evas/engines/gl_common/shader/img_12_bgra_nomul_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 \ 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, double sx, double sy, double sw, double sh,
int x, int y, int w, int h, int x, int y, int w, int h,
int r, int g, int b, int a); 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, void evas_gl_common_context_yuv_push(Evas_Engine_GL_Context *gc,
Evas_GL_Texture *tex, Evas_GL_Texture *tex,
double sx, double sy, double sw, double sh, 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, tex);
SHADER_TEXTURE_ADD(shared, IMG_MASK_NOMUL, texa); 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) if (gc->state.current.cur_prog == PRG_INVALID)
glUseProgram(shared->shader[0].prog); glUseProgram(shared->shader[0].prog);
else glUseProgram(gc->state.current.cur_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 void
evas_gl_common_context_font_push(Evas_Engine_GL_Context *gc, evas_gl_common_context_font_push(Evas_Engine_GL_Context *gc,
Evas_GL_Texture *tex, 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 c, cx, cy, cw, ch;
int i; int i;
int sx, sy, sw, sh; int sx, sy, sw, sh;
double mx, my, mw, mh, mmx, mmy, mmw, mmh;
if (dc != gc->dc) return; if (dc != gc->dc) return;
tex = fg->ext_dat; 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; g = (dc->col.col >> 8 ) & 0xff;
b = (dc->col.col ) & 0xff; b = (dc->col.col ) & 0xff;
sx = 0; sy = 0; sw = tex->w, sh = tex->h; 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) || if ((!gc->dc->cutout.rects) ||
((gc->shared->info.tune.cutout.max > 0) && ((gc->shared->info.tune.cutout.max > 0) &&
(gc->dc->cutout.active > gc->shared->info.tune.cutout.max))) (gc->dc->cutout.active > gc->shared->info.tune.cutout.max)))

View File

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

View File

@ -48,6 +48,56 @@ Evas_GL_Program_Source shader_font_vert_src =
NULL, 0 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 */ /* Source: modules/evas/engines/gl_common/shader/img_12_bgra_frag.shd */
static const char const img_12_bgra_frag_glsl[] = static const char const img_12_bgra_frag_glsl[] =
"#ifdef GL_ES\n" "#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 */ /* 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_ES\n"
"#ifdef GL_FRAGMENT_PRECISION_HIGH\n" "#ifdef GL_FRAGMENT_PRECISION_HIGH\n"
"precision highp float;\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 */ /* 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" "#ifdef GL_ES\n"
"precision highp float;\n" "precision highp float;\n"
"#endif\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 */ /* 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_ES\n"
"#ifdef GL_FRAGMENT_PRECISION_HIGH\n" "#ifdef GL_FRAGMENT_PRECISION_HIGH\n"
"precision highp float;\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 */ /* 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" "#ifdef GL_ES\n"
"precision highp float;\n" "precision highp float;\n"
"#endif\n" "#endif\n"
@ -2286,6 +2336,7 @@ static const struct {
const char *name; const char *name;
} _shaders_source[] = { } _shaders_source[] = {
{ SHADER_FONT, &(shader_font_vert_src), &(shader_font_frag_src), "font" }, { 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_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_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" }, { 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 static void
eng_context_3d_use(void *data) eng_context_3d_use(void *data)
{ {
@ -1885,6 +1939,10 @@ module_open(Evas_Module *em)
func = pfunc; func = pfunc;
/* now to override methods */ /* now to override methods */
#define ORD(f) EVAS_API_OVERRIDE(f, &func, eng_) #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(rectangle_draw);
ORD(line_draw); ORD(line_draw);
ORD(polygon_point_add); ORD(polygon_point_add);