Evas masking: Implement image masking for GL engines

This commit is contained in:
Jean-Philippe Andre 2014-11-24 20:24:25 +09:00
parent 62f3170874
commit 124ab102b7
10 changed files with 383 additions and 9 deletions

View File

@ -680,7 +680,12 @@ modules/evas/engines/gl_common/shader/yuv_vert.shd \
modules/evas/engines/gl_common/shader/yuy2_frag.shd \
modules/evas/engines/gl_common/shader/yuy2_nomul_frag.shd \
modules/evas/engines/gl_common/shader/yuy2_nomul_vert.shd \
modules/evas/engines/gl_common/shader/yuy2_vert.shd
modules/evas/engines/gl_common/shader/yuy2_vert.shd \
modules/evas/engines/gl_common/shader/img_mask_frag.shd \
modules/evas/engines/gl_common/shader/img_mask_vert.shd \
modules/evas/engines/gl_common/shader/img_mask_nomul_frag.shd \
modules/evas/engines/gl_common/shader/img_mask_nomul_vert.shd \
$(NULL)
EXTRA_DIST += \
modules/evas/engines/gl_common/shader/gen_shaders.sh \

View File

@ -762,6 +762,15 @@ void evas_gl_common_context_image_map_push(Evas_Engine_GL_Context *g
Eina_Bool smooth,
Eina_Bool tex_only,
Evas_Colorspace cspace);
void evas_gl_common_context_masked_image_push(Evas_Engine_GL_Context *gc,
Evas_GL_Texture *tex,
Evas_GL_Texture *mask_tex,
double sx, double sy,
double sw, double sh,
int x, int y, int w, int h,
int mx, int my, int mw, int mh,
int r, int g, int b, int a,
Eina_Bool smooth, Eina_Bool tex_only);
int evas_gl_common_shader_program_init(Evas_GL_Shared *shared);
void evas_gl_common_shader_program_init_done(void);

View File

@ -851,6 +851,11 @@ evas_gl_common_context_new(void)
SHADER_TEXTURE_ADD(shared, RGB_A_PAIR_NOMUL, tex);
SHADER_TEXTURE_ADD(shared, RGB_A_PAIR_NOMUL, texa);
SHADER_TEXTURE_ADD(shared, IMG_MASK, tex);
SHADER_TEXTURE_ADD(shared, IMG_MASK, texa);
SHADER_TEXTURE_ADD(shared, IMG_MASK_NOMUL, tex);
SHADER_TEXTURE_ADD(shared, IMG_MASK_NOMUL, texa);
if (gc->state.current.cur_prog == PRG_INVALID)
glUseProgram(shared->shader[0].prog);
else glUseProgram(gc->state.current.cur_prog);
@ -2645,6 +2650,109 @@ evas_gl_common_context_image_map_push(Evas_Engine_GL_Context *gc,
}
}
void
evas_gl_common_context_masked_image_push(Evas_Engine_GL_Context *gc,
Evas_GL_Texture *tex,
Evas_GL_Texture *mask_tex,
double sx, double sy,
double sw, double sh,
int x, int y, int w, int h,
int mx, int my, int mw, int mh,
int r, int g, int b, int a,
Eina_Bool smooth, Eina_Bool tex_only)
{
// FIXME: How to implement support for yuv, rgb_a_pair & map stuff?
// NOTE: If image (tex) has no alpha this is very similar to RGB+A pair
// FIXME: Optimize for image vs. texture?
(void)tex_only;
int pnum, nv, nc, nu, na, i;
GLfloat tx1, tx2, ty1, ty2, t2x1, t2x2, t2y1, t2y2;
GLuint prog;
int pn;
// TODO: Big IF here (image type, etc --> needs tons of new shaders!)
prog = gc->shared->shader[evas_gl_common_shader_choice
(0, NULL, r, g, b, a, SHADER_IMG_MASK_NOMUL, SHADER_IMG_MASK)].prog;
pn = _evas_gl_common_context_push(RTYPE_IMAGE,
gc, tex,
prog,
x, y, w, h,
EINA_TRUE,
smooth,
EINA_FALSE, 0, 0, 0, 0);
gc->pipe[pn].region.type = RTYPE_IMAGE;
gc->pipe[pn].shader.cur_tex = tex->pt->texture;
gc->pipe[pn].shader.cur_texa = mask_tex->pt->texture;
gc->pipe[pn].shader.cur_prog = prog;
gc->pipe[pn].shader.smooth = smooth;
gc->pipe[pn].shader.blend = EINA_TRUE;
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 = EINA_TRUE;
// if nomul... dont need this
gc->pipe[pn].array.use_color = EINA_TRUE;
gc->pipe[pn].array.use_texuv = EINA_TRUE;
gc->pipe[pn].array.use_texuv2 = EINA_FALSE;
gc->pipe[pn].array.use_texuv3 = EINA_FALSE;
gc->pipe[pn].array.use_texa = EINA_TRUE;
gc->pipe[pn].array.use_texsam = EINA_FALSE;
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);
tx1 = (tex->x + sx) / (double)tex->pt->w;
ty1 = (tex->y + sy) / (double)tex->pt->h;
tx2 = (tex->x + sx + sw) / (double)tex->pt->w;
ty2 = (tex->y + sy + sh) / (double)tex->pt->h;
t2x1 = (mask_tex->x + mx) / (double)mask_tex->pt->w;
t2y1 = (mask_tex->y + my) / (double)mask_tex->pt->h;
t2x2 = (mask_tex->x + mx + mw) / (double)mask_tex->pt->w;
t2y2 = (mask_tex->y + my + mh) / (double)mask_tex->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);
}
}
EAPI void
evas_gl_common_context_flush(Evas_Engine_GL_Context *gc)
{
@ -3103,7 +3211,6 @@ shader_array_flush(Evas_Engine_GL_Context *gc)
glDisableVertexAttribArray(SHAD_TEXUV);
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
}
if (gc->pipe[i].array.use_texa)
{
glEnableVertexAttribArray(SHAD_TEXA);
@ -3145,6 +3252,7 @@ shader_array_flush(Evas_Engine_GL_Context *gc)
else
{
glDisableVertexAttribArray(SHAD_TEXA);
}
if (gc->pipe[i].array.use_texsam)
{

View File

@ -957,10 +957,13 @@ _evas_gl_common_image_push(Evas_Engine_GL_Context *gc, Evas_GL_Image *im,
int dx, int dy, int dw, int dh,
int sx, int sy, int sw, int sh,
int cx, int cy, int cw, int ch,
int r, int g, int b, int a, Eina_Bool smooth,
int r, int g, int b, int a,
Evas_GL_Image *mask, int mask_x, int mask_y,
Eina_Bool smooth,
Eina_Bool yuv, Eina_Bool yuy2, Eina_Bool nv12,
Eina_Bool rgb_a_pair)
{
double mx, my, mw, mh, mmx, mmy, mmw, mmh;
double ssx, ssy, ssw, ssh;
int nx, ny, nw, nh;
@ -969,9 +972,30 @@ _evas_gl_common_image_push(Evas_Engine_GL_Context *gc, Evas_GL_Image *im,
cx, cy, cw, ch);
if ((nw < 1) || (nh < 1)) return;
if (!im->tex) return;
if ((nx == dx) && (ny == dy) && (nw == dw) && (nh == dh))
{
if (yuv)
/* Apply mask on image */
if (mask)
{
// FIXME/TODO: support for yuv, yuy2, nv12, rgb_a with masks
mx = mask_x; my = 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 - mask_x) + ((double)(mw * (nx - dx)) / (double)(dw));
mmy = (double)(my - 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_image_push(gc, im->tex, mask->tex,
sx, sy, sw, sh,
dx, dy, dw, dh,
mmx, mmy, mmw, mmh,
r, g, b, a,
smooth, im->tex_only);
}
else if (yuv)
evas_gl_common_context_yuv_push(gc,
im->tex,
sx, sy, sw, sh,
@ -1014,7 +1038,27 @@ _evas_gl_common_image_push(Evas_Engine_GL_Context *gc, Evas_GL_Image *im,
ssw = ((double)sw * (double)(nw)) / (double)(dw);
ssh = ((double)sh * (double)(nh)) / (double)(dh);
if (yuv)
/* Apply mask on image */
if (mask)
{
// FIXME/TODO: support for yuv, yuy2, nv12, rgb_a with masks
mx = mask_x; my = 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 - mask_x) + ((double)(mw * (nx - dx)) / (double)(dw));
mmy = (double)(my - 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_image_push(gc, im->tex, mask->tex,
ssx, ssy, ssw, ssh,
nx, ny, nw, nh,
mmx, mmy, mmw, mmh,
r, g, b, a,
smooth, im->tex_only);
}
else if (yuv)
evas_gl_common_context_yuv_push(gc,
im->tex,
ssx, ssy, ssw, ssh,
@ -1063,6 +1107,8 @@ evas_gl_common_image_draw(Evas_Engine_GL_Context *gc, Evas_GL_Image *im, int sx,
Eina_Bool yuy2 = EINA_FALSE;
Eina_Bool nv12 = EINA_FALSE;
Eina_Bool rgb_a_pair = EINA_FALSE;
Evas_GL_Image *mask;
int mask_x, mask_y;
if (sw < 1) sw = 1;
if (sh < 1) sh = 1;
@ -1079,6 +1125,22 @@ evas_gl_common_image_draw(Evas_Engine_GL_Context *gc, Evas_GL_Image *im, int sx,
r = g = b = a = 255;
}
// Prepare mask image, if there is one
mask = dc->clip.mask;
mask_x = dc->clip.mask_x;
mask_y = dc->clip.mask_y;
if (mask)
{
evas_gl_common_image_update(gc, im);
if (!mask->tex)
{
ERR("Failed to apply mask image");
mask = NULL;
mask_x = 0;
mask_y = 0;
}
}
evas_gl_common_image_update(gc, im);
if (!im->tex)
{
@ -1112,14 +1174,28 @@ evas_gl_common_image_draw(Evas_Engine_GL_Context *gc, Evas_GL_Image *im, int sx,
((gc->shared->info.tune.cutout.max > 0) &&
(gc->dc->cutout.active > gc->shared->info.tune.cutout.max)))
{
if (gc->dc->clip.use)
if (mask)
{
_evas_gl_common_image_push(gc, im,
dx, dy, dw, dh,
sx, sy, sw, sh,
gc->dc->clip.x, gc->dc->clip.y,
gc->dc->clip.w, gc->dc->clip.h,
r, g, b, a, smooth,
r, g, b, a,
mask, mask_x, mask_y,
smooth,
yuv, yuy2, nv12, rgb_a_pair);
}
else if (gc->dc->clip.use)
{
_evas_gl_common_image_push(gc, im,
dx, dy, dw, dh,
sx, sy, sw, sh,
gc->dc->clip.x, gc->dc->clip.y,
gc->dc->clip.w, gc->dc->clip.h,
r, g, b, a,
mask, mask_x, mask_y,
smooth,
yuv, yuy2, nv12, rgb_a_pair);
}
else
@ -1128,7 +1204,9 @@ evas_gl_common_image_draw(Evas_Engine_GL_Context *gc, Evas_GL_Image *im, int sx,
dx, dy, dw, dh,
sx, sy, sw, sh,
dx, dy, dw, dh,
r, g, b, a, smooth,
r, g, b, a,
mask, mask_x, mask_y,
smooth,
yuv, yuy2, nv12, rgb_a_pair);
}
return;
@ -1153,7 +1231,9 @@ evas_gl_common_image_draw(Evas_Engine_GL_Context *gc, Evas_GL_Image *im, int sx,
dx, dy, dw, dh,
sx, sy, sw, sh,
rct->x, rct->y, rct->w, rct->h,
r, g, b, a, smooth,
r, g, b, a,
mask, mask_x, mask_y,
smooth,
yuv, yuy2, nv12, rgb_a_pair);
}
evas_common_draw_context_cutouts_free(_evas_gl_common_cutout_rects);

View File

@ -44,5 +44,7 @@ typedef enum {
SHADER_YUV,
SHADER_YUY2_NOMUL,
SHADER_YUY2,
SHADER_IMG_MASK,
SHADER_IMG_MASK_NOMUL,
SHADER_LAST
} Evas_GL_Shader;

View File

@ -2181,6 +2181,104 @@ Evas_GL_Program_Source shader_yuy2_vert_src =
NULL, 0
};
/* Source: modules/evas/engines/gl_common/shader/img_mask_frag.shd */
static const char img_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 coord_c;\n"
"varying vec2 coord_a;\n"
"void main()\n"
"{\n"
" gl_FragColor.rgb = col.rgb * texture2D(tex, coord_c.xy).rgb * texture2D(texa, coord_a).g;\n"
" gl_FragColor.a = col.a * texture2D(tex, coord_c.xy).a * texture2D(texa, coord_a).g;\n"
"}\n";
Evas_GL_Program_Source shader_img_mask_frag_src =
{
img_mask_frag_glsl,
NULL, 0
};
/* Source: modules/evas/engines/gl_common/shader/img_mask_vert.shd */
static const char img_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 coord_c;\n"
"varying vec2 coord_a;\n"
"void main()\n"
"{\n"
" gl_Position = mvp * vertex;\n"
" col = color;\n"
" coord_c = tex_coord;\n"
" coord_a = tex_coorda;\n"
"}\n";
Evas_GL_Program_Source shader_img_mask_vert_src =
{
img_mask_vert_glsl,
NULL, 0
};
/* Source: modules/evas/engines/gl_common/shader/img_mask_nomul_frag.shd */
static const char img_mask_nomul_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 vec2 coord_c;\n"
"varying vec2 coord_a;\n"
"void main()\n"
"{\n"
" gl_FragColor.rgb = texture2D(tex, coord_c.xy).rgb * texture2D(texa, coord_a).g;\n"
" gl_FragColor.a = texture2D(tex, coord_c.xy).a * texture2D(texa, coord_a).g;\n"
"}\n";
Evas_GL_Program_Source shader_img_mask_nomul_frag_src =
{
img_mask_nomul_frag_glsl,
NULL, 0
};
/* Source: modules/evas/engines/gl_common/shader/img_mask_nomul_vert.shd */
static const char img_mask_nomul_vert_glsl[] =
"#ifdef GL_ES\n"
"precision highp float;\n"
"#endif\n"
"attribute vec4 vertex;\n"
"attribute vec2 tex_coord;\n"
"attribute vec2 tex_coorda;\n"
"uniform mat4 mvp;\n"
"varying vec2 coord_c;\n"
"varying vec2 coord_a;\n"
"void main()\n"
"{\n"
" gl_Position = mvp * vertex;\n"
" coord_c = tex_coord;\n"
" coord_a = tex_coorda;\n"
"}\n";
Evas_GL_Program_Source shader_img_mask_nomul_vert_src =
{
img_mask_nomul_vert_glsl,
NULL, 0
};
static const struct {
Evas_GL_Shader id;
Evas_GL_Program_Source *vert;
@ -2229,5 +2327,7 @@ static const struct {
{ SHADER_YUV, &(shader_yuv_vert_src), &(shader_yuv_frag_src), "yuv" },
{ SHADER_YUY2_NOMUL, &(shader_yuy2_nomul_vert_src), &(shader_yuy2_nomul_frag_src), "yuy2_nomul" },
{ SHADER_YUY2, &(shader_yuy2_vert_src), &(shader_yuy2_frag_src), "yuy2" },
{ SHADER_IMG_MASK, &(shader_img_mask_vert_src), &(shader_img_mask_frag_src), "img_mask" },
{ SHADER_IMG_MASK_NOMUL, &(shader_img_mask_nomul_vert_src), &(shader_img_mask_nomul_frag_src), "img_mask_nomul" },
};

View File

@ -0,0 +1,18 @@
#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 coord_c;
varying vec2 coord_a;
void main()
{
gl_FragColor.rgb = col.rgb * texture2D(tex, coord_c.xy).rgb * texture2D(texa, coord_a).g;
gl_FragColor.a = col.a * texture2D(tex, coord_c.xy).a * texture2D(texa, coord_a).g;
}

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 vec2 coord_c;
varying vec2 coord_a;
void main()
{
gl_FragColor.rgb = texture2D(tex, coord_c.xy).rgb * texture2D(texa, coord_a).g;
gl_FragColor.a = texture2D(tex, coord_c.xy).a * texture2D(texa, coord_a).g;
}

View File

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

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 coord_c;
varying vec2 coord_a;
void main()
{
gl_Position = mvp * vertex;
col = color;
coord_c = tex_coord;
coord_a = tex_coorda;
}