Evas masking: Fix masking of maps in GL

This completes the transition to auto-scaled mask images when
using the GL engine. Now the shaders do the work on-the-fly of
resizing the mask.
This commit is contained in:
Jean-Philippe Andre 2015-02-26 20:42:45 +09:00
parent fab0d7f9d3
commit 0da6278af8
10 changed files with 90 additions and 100 deletions

View File

@ -754,7 +754,7 @@ void evas_gl_common_context_image_map_push(Evas_Engine_GL_Context *g
int npoints, int npoints,
RGBA_Map_Point *p, RGBA_Map_Point *p,
int clip, int cx, int cy, int cw, int ch, int clip, int cx, int cy, int cw, int ch,
Evas_GL_Texture *mtex, int mx, int my, int mw, int mh, int mdx, int mdy, int mdw, int mdh, Evas_GL_Texture *mtex, int mx, int my, int mw, int mh, Eina_Bool mask_smooth,
int r, int g, int b, int a, int r, int g, int b, int a,
Eina_Bool smooth, Eina_Bool smooth,
Eina_Bool tex_only, Eina_Bool tex_only,

View File

@ -2404,8 +2404,7 @@ evas_gl_common_context_image_map_push(Evas_Engine_GL_Context *gc,
int npoints, int npoints,
RGBA_Map_Point *p, RGBA_Map_Point *p,
int clip, int cx, int cy, int cw, int ch, int clip, int cx, int cy, int cw, int ch,
Evas_GL_Texture *mtex, int mx, int my, int mw, int mh, Evas_GL_Texture *mtex, int mx, int my, int mw, int mh, Eina_Bool mask_smooth,
int mdx, int mdy, int mdw, int mdh,
int r, int g, int b, int a, int r, int g, int b, int a,
Eina_Bool smooth, Eina_Bool tex_only, Eina_Bool smooth, Eina_Bool tex_only,
Evas_Colorspace cspace) Evas_Colorspace cspace)
@ -2606,7 +2605,7 @@ evas_gl_common_context_image_map_push(Evas_Engine_GL_Context *gc,
gc->pipe[pn].array.use_texm = !!mtex; gc->pipe[pn].array.use_texm = !!mtex;
gc->pipe[pn].array.use_texa = !!mtex; gc->pipe[pn].array.use_texa = !!mtex;
gc->pipe[pn].array.use_texsam = gc->pipe[pn].array.use_texm; gc->pipe[pn].array.use_texsam = gc->pipe[pn].array.use_texm;
gc->pipe[pn].array.mask_smooth = EINA_FALSE; gc->pipe[pn].array.mask_smooth = mask_smooth;
pipe_region_expand(gc, pn, x, y, w, h); pipe_region_expand(gc, pn, x, y, w, h);
PIPE_GROW(gc, pn, 6); PIPE_GROW(gc, pn, 6);
@ -2668,12 +2667,8 @@ evas_gl_common_context_image_map_push(Evas_Engine_GL_Context *gc,
if (mtex) if (mtex)
{ {
GLfloat glmdx = 0.f, glmdy = 0.f, glmdw = 1.f, glmdh = 1.f, yinv = -1.f; double glmx, glmy, glmw, glmh, yinv = -1.f;
GLfloat gw = gc->w, gh = gc->h; double gw = gc->w, gh = gc->h;
// Note: I couldn't write any test case where it was necessary
// to know the mask position in its texture. Thus these unused vars.
(void) mx; (void) my; (void) mw; (void) mh;
if (!((gc->pipe[0].shader.surface == gc->def_surface) || if (!((gc->pipe[0].shader.surface == gc->def_surface) ||
(!gc->pipe[0].shader.surface))) (!gc->pipe[0].shader.surface)))
@ -2682,40 +2677,47 @@ evas_gl_common_context_image_map_push(Evas_Engine_GL_Context *gc,
gh = gc->pipe[0].shader.surface->h; gh = gc->pipe[0].shader.surface->h;
yinv = 1.f; yinv = 1.f;
} }
if (!gw || !gh || !mw || !mh || !mtex->pt->w || !mtex->pt->h)
goto mask_error;
if (gw) glmdx = (GLfloat) mdx / (GLfloat) gw; // vertex shader: tex_m = (X,Y) * tex_coordm + tex_sample
if (gh) glmdy = (GLfloat) mdy / (GLfloat) gh; // tex_coordm
if (mdw) glmdw = (GLfloat) gw / (GLfloat) mdw; glmx = (double)((mtex->x * mw) - (mtex->w * mx)) / (double)(mw * mtex->pt->w);
if (mdh) glmdh = (GLfloat) gh / (GLfloat) mdh; glmy = (double)((mtex->y * mh) - (mtex->h * my)) / (double)(mh * mtex->pt->h);
PUSH_TEXM(pn, glmx, glmy);
PUSH_TEXM(pn, glmx, glmy);
PUSH_TEXM(pn, glmx, glmy);
PUSH_TEXM(pn, glmx, glmy);
PUSH_TEXM(pn, glmx, glmy);
PUSH_TEXM(pn, glmx, glmy);
// tex_coordm: mask x,y (on canvas) // tex_sample
PUSH_TEXM(pn, glmdx, glmdy); glmw = (double)(gw * mtex->w) / (double)(mw * mtex->pt->w);
PUSH_TEXM(pn, glmdx, glmdy); glmh = (double)(gh * mtex->h) / (double)(mh * mtex->pt->h);
PUSH_TEXM(pn, glmdx, glmdy); PUSH_TEXSAM(pn, glmw, glmh);
PUSH_TEXM(pn, glmdx, glmdy); PUSH_TEXSAM(pn, glmw, glmh);
PUSH_TEXM(pn, glmdx, glmdy); PUSH_TEXSAM(pn, glmw, glmh);
PUSH_TEXM(pn, glmdx, glmdy); PUSH_TEXSAM(pn, glmw, glmh);
PUSH_TEXSAM(pn, glmw, glmh);
PUSH_TEXSAM(pn, glmw, glmh);
// tex_sample: mask 1/w, 1/h // tex_coorda: Y-invert flag
PUSH_TEXSAM(pn, glmdw, glmdh); PUSH_TEXA(pn, 1.0, yinv);
PUSH_TEXSAM(pn, glmdw, glmdh); PUSH_TEXA(pn, 1.0, yinv);
PUSH_TEXSAM(pn, glmdw, glmdh); PUSH_TEXA(pn, 1.0, yinv);
PUSH_TEXSAM(pn, glmdw, glmdh); PUSH_TEXA(pn, 1.0, yinv);
PUSH_TEXSAM(pn, glmdw, glmdh); PUSH_TEXA(pn, 1.0, yinv);
PUSH_TEXSAM(pn, glmdw, glmdh); PUSH_TEXA(pn, 1.0, yinv);
// tex_coorda: mask Y-invert flag /*
PUSH_TEXA(pn, 1.f, yinv); DBG("Map mask: %d,%d %dx%d --> %f , %f - %f x %f @ %f %f [gc %dx%d, tex %d,%d %dx%d, pt %dx%d]",
PUSH_TEXA(pn, 1.f, yinv); mx, my, mw, mh,
PUSH_TEXA(pn, 1.f, yinv); glmx, glmy, glmw, glmh, 1.0, yinv,
PUSH_TEXA(pn, 1.f, yinv); gc->w, gc->h, mtex->x, mtex->y, mtex->w, mtex->h, mtex->pt->w, mtex->pt->h);
PUSH_TEXA(pn, 1.f, yinv); */
PUSH_TEXA(pn, 1.f, yinv);
//DBG("Orig %d,%d - %dx%d --> %f,%f - %f x %f", mdx, mdy, mdw, mdh,
// glmdx, glmdy, glmdw, glmdh);
} }
mask_error:
if (!flat) if (!flat)
{ {
shader_array_flush(gc); shader_array_flush(gc);

View File

@ -923,9 +923,11 @@ void
evas_gl_common_image_map_draw(Evas_Engine_GL_Context *gc, Evas_GL_Image *im, evas_gl_common_image_map_draw(Evas_Engine_GL_Context *gc, Evas_GL_Image *im,
int npoints, RGBA_Map_Point *p, int smooth, int level EINA_UNUSED) int npoints, RGBA_Map_Point *p, int smooth, int level EINA_UNUSED)
{ {
int mmx = 0, mmy = 0, mmw = 0, mmh = 0, mdx = 0, mdy = 0, mdw = 0, mdh = 0; int mx = 0, my = 0, mw = 0, mh = 0;
Evas_GL_Texture *mtex = NULL; RGBA_Draw_Context *dc = gc->dc;
RGBA_Draw_Context *dc; Eina_Bool mask_smooth = EINA_FALSE;
Evas_GL_Image *mask = dc->clip.mask;
Evas_GL_Texture *mtex = mask ? mask->tex : NULL;
int r, g, b, a; int r, g, b, a;
int c, cx, cy, cw, ch; int c, cx, cy, cw, ch;
@ -951,30 +953,32 @@ evas_gl_common_image_map_draw(Evas_Engine_GL_Context *gc, Evas_GL_Image *im,
if (!im->tex) return; if (!im->tex) return;
im->tex->im = im; im->tex->im = im;
if (dc->clip.mask) if (mtex && mtex->pt && mtex->pt->w && mtex->pt->h)
{ {
Evas_GL_Image *mask = dc->clip.mask; // canvas coords
double mx, my, mw, mh; mx = dc->clip.mask_x;
my = dc->clip.mask_y;
mdx = mx = dc->clip.mask_x; if (mask->scaled.origin)
mdy = my = dc->clip.mask_y; {
mdw = mw = mask->w; mw = mask->scaled.w;
mdh = mh = mask->h; mh = mask->scaled.h;
if (c) RECTS_CLIP_TO_RECT(mx, my, mw, mh, cx, cy, cw, ch); //scalex = mask->w / (double)mask->scaled.w;
//RECTS_CLIP_TO_RECT(mx, my, mw, mh, dx, dy, dw, dh); //scaley = mask->h / (double)mask->scaled.h;
mmx = mx - dc->clip.mask_x; mask_smooth = mask->scaled.smooth;
mmy = my - dc->clip.mask_y; }
mmw = mw; else
mmh = mh; {
mtex = mask->tex; mw = mask->w;
// TODO: implement support for scaled masks mh = mask->h;
//if (mask->scaled.origin) }
//mask_smooth = mask->scaled.smooth; //if (c) RECTS_CLIP_TO_RECT(mx, my, mw, mh, cx, cy, cw, ch);
//mx = mx - dc->clip.mask_x;
//my = my - dc->clip.mask_y;
} }
evas_gl_common_context_image_map_push(gc, im->tex, npoints, p, evas_gl_common_context_image_map_push(gc, im->tex, npoints, p,
c, cx, cy, cw, ch, c, cx, cy, cw, ch,
mtex, mmx, mmy, mmw, mmh, mdx, mdy, mdw, mdh, mtex, mx, my, mw, mh, mask_smooth,
r, g, b, a, smooth, im->tex_only, r, g, b, a, smooth, im->tex_only,
im->cs.space); im->cs.space);
} }

View File

@ -2715,7 +2715,6 @@ static const char const map_mask_frag_glsl[] =
"varying vec4 col;\n" "varying vec4 col;\n"
"void main()\n" "void main()\n"
"{\n" "{\n"
" // FIXME: Use mask coordinates within its texture\n"
" // FIXME: Fix Mach band effect using proper 4-point color interpolation\n" " // FIXME: Fix Mach band effect using proper 4-point color interpolation\n"
" gl_FragColor = texture2D(tex, tex_c).bgra * texture2D(texm, tex_m).a * col;\n" " gl_FragColor = texture2D(tex, tex_c).bgra * texture2D(texm, tex_m).a * col;\n"
"}\n"; "}\n";
@ -2741,10 +2740,9 @@ static const char const map_mask_vert_glsl[] =
" tex_c = tex_coord;\n" " tex_c = tex_coord;\n"
" col = color;\n" " col = color;\n"
" // tex_coorda contains the Y-invert flag\n" " // tex_coorda contains the Y-invert flag\n"
" // tex_coordm contains the X,Y position of the mask\n" " // position on screen in [0..1] range of current pixel\n"
" // tex_sample contains the W,H size of the mask (inverted)\n" " vec4 mask_Position = mvp * vertex * vec4(0.5, sign(tex_coorda.y) * 0.5, 0.5, 0.5) + vec4(0.5, 0.5, 0, 0);\n"
" vec4 mask_Position = mvp * vertex * vec4(tex_coorda.x * 0.5, tex_coorda.y * 0.5, 0.5, 0.5) + vec4(0.5, 0.5, 0, 0);\n" " tex_m = mask_Position.xy * tex_sample + tex_coordm;\n"
" tex_m = vec2(mask_Position.xy - tex_coordm) * tex_sample;\n"
"}\n"; "}\n";
Evas_GL_Program_Source shader_map_mask_vert_src = Evas_GL_Program_Source shader_map_mask_vert_src =
{ {
@ -2787,10 +2785,9 @@ static const char const map_mask_nomul_vert_glsl[] =
" gl_Position = mvp * vertex;\n" " gl_Position = mvp * vertex;\n"
" tex_c = tex_coord;\n" " tex_c = tex_coord;\n"
" // tex_coorda contains the Y-invert flag\n" " // tex_coorda contains the Y-invert flag\n"
" // tex_coordm contains the X,Y position of the mask\n" " // position on screen in [0..1] range of current pixel\n"
" // tex_sample contains the W,H size of the mask (inverted)\n" " vec4 mask_Position = mvp * vertex * vec4(0.5, sign(tex_coorda.y) * 0.5, 0.5, 0.5) + vec4(0.5, 0.5, 0, 0);\n"
" vec4 mask_Position = mvp * vertex * vec4(tex_coorda.x * 0.5, tex_coorda.y * 0.5, 0.5, 0.5) + vec4(0.5, 0.5, 0, 0);\n" " tex_m = mask_Position.xy * tex_sample + tex_coordm;\n"
" tex_m = vec2(mask_Position.xy - tex_coordm) * tex_sample;\n"
"}\n"; "}\n";
Evas_GL_Program_Source shader_map_mask_nomul_vert_src = Evas_GL_Program_Source shader_map_mask_nomul_vert_src =
{ {
@ -2812,7 +2809,6 @@ static const char const map_mask_bgra_frag_glsl[] =
"varying vec4 col;\n" "varying vec4 col;\n"
"void main()\n" "void main()\n"
"{\n" "{\n"
" // FIXME: Use mask coordinates within its texture\n"
" // FIXME: Fix Mach band effect using proper 4-point color interpolation\n" " // FIXME: Fix Mach band effect using proper 4-point color interpolation\n"
" gl_FragColor = texture2D(tex, tex_c) * texture2D(texm, tex_m).a * col;\n" " gl_FragColor = texture2D(tex, tex_c) * texture2D(texm, tex_m).a * col;\n"
"}\n"; "}\n";
@ -2838,10 +2834,9 @@ static const char const map_mask_bgra_vert_glsl[] =
" tex_c = tex_coord;\n" " tex_c = tex_coord;\n"
" col = color;\n" " col = color;\n"
" // tex_coorda contains the Y-invert flag\n" " // tex_coorda contains the Y-invert flag\n"
" // tex_coordm contains the X,Y position of the mask\n" " // position on screen in [0..1] range of current pixel\n"
" // tex_sample contains the W,H size of the mask (inverted)\n" " vec4 mask_Position = mvp * vertex * vec4(0.5, sign(tex_coorda.y) * 0.5, 0.5, 0.5) + vec4(0.5, 0.5, 0, 0);\n"
" vec4 mask_Position = mvp * vertex * vec4(tex_coorda.x * 0.5, tex_coorda.y * 0.5, 0.5, 0.5) + vec4(0.5, 0.5, 0, 0);\n" " tex_m = mask_Position.xy * tex_sample + tex_coordm;\n"
" tex_m = vec2(mask_Position.xy - tex_coordm) * tex_sample;\n"
"}\n"; "}\n";
Evas_GL_Program_Source shader_map_mask_bgra_vert_src = Evas_GL_Program_Source shader_map_mask_bgra_vert_src =
{ {
@ -2884,10 +2879,9 @@ static const char const map_mask_bgra_nomul_vert_glsl[] =
" gl_Position = mvp * vertex;\n" " gl_Position = mvp * vertex;\n"
" tex_c = tex_coord;\n" " tex_c = tex_coord;\n"
" // tex_coorda contains the Y-invert flag\n" " // tex_coorda contains the Y-invert flag\n"
" // tex_coordm contains the X,Y position of the mask\n" " // position on screen in [0..1] range of current pixel\n"
" // tex_sample contains the W,H size of the mask (inverted)\n" " vec4 mask_Position = mvp * vertex * vec4(0.5, sign(tex_coorda.y) * 0.5, 0.5, 0.5) + vec4(0.5, 0.5, 0, 0);\n"
" vec4 mask_Position = mvp * vertex * vec4(tex_coorda.x * 0.5, tex_coorda.y * 0.5, 0.5, 0.5) + vec4(0.5, 0.5, 0, 0);\n" " tex_m = mask_Position.xy * tex_sample + tex_coordm;\n"
" tex_m = vec2(mask_Position.xy - tex_coordm) * tex_sample;\n"
"}\n"; "}\n";
Evas_GL_Program_Source shader_map_mask_bgra_nomul_vert_src = Evas_GL_Program_Source shader_map_mask_bgra_nomul_vert_src =
{ {

View File

@ -10,7 +10,6 @@ varying vec2 tex_c, tex_m;
varying vec4 col; varying vec4 col;
void main() void main()
{ {
// FIXME: Use mask coordinates within its texture
// FIXME: Fix Mach band effect using proper 4-point color interpolation // FIXME: Fix Mach band effect using proper 4-point color interpolation
gl_FragColor = texture2D(tex, tex_c) * texture2D(texm, tex_m).a * col; gl_FragColor = texture2D(tex, tex_c) * texture2D(texm, tex_m).a * col;
} }

View File

@ -11,9 +11,7 @@ void main()
tex_c = tex_coord; tex_c = tex_coord;
// tex_coorda contains the Y-invert flag // tex_coorda contains the Y-invert flag
// tex_coordm contains the X,Y position of the mask // position on screen in [0..1] range of current pixel
// tex_sample contains the W,H size of the mask (inverted) vec4 mask_Position = mvp * vertex * vec4(0.5, sign(tex_coorda.y) * 0.5, 0.5, 0.5) + vec4(0.5, 0.5, 0, 0);
tex_m = mask_Position.xy * tex_sample + tex_coordm;
vec4 mask_Position = mvp * vertex * vec4(tex_coorda.x * 0.5, tex_coorda.y * 0.5, 0.5, 0.5) + vec4(0.5, 0.5, 0, 0);
tex_m = vec2(mask_Position.xy - tex_coordm) * tex_sample;
} }

View File

@ -13,9 +13,7 @@ void main()
col = color; col = color;
// tex_coorda contains the Y-invert flag // tex_coorda contains the Y-invert flag
// tex_coordm contains the X,Y position of the mask // position on screen in [0..1] range of current pixel
// tex_sample contains the W,H size of the mask (inverted) vec4 mask_Position = mvp * vertex * vec4(0.5, sign(tex_coorda.y) * 0.5, 0.5, 0.5) + vec4(0.5, 0.5, 0, 0);
tex_m = mask_Position.xy * tex_sample + tex_coordm;
vec4 mask_Position = mvp * vertex * vec4(tex_coorda.x * 0.5, tex_coorda.y * 0.5, 0.5, 0.5) + vec4(0.5, 0.5, 0, 0);
tex_m = vec2(mask_Position.xy - tex_coordm) * tex_sample;
} }

View File

@ -10,7 +10,6 @@ varying vec2 tex_c, tex_m;
varying vec4 col; varying vec4 col;
void main() void main()
{ {
// FIXME: Use mask coordinates within its texture
// FIXME: Fix Mach band effect using proper 4-point color interpolation // FIXME: Fix Mach band effect using proper 4-point color interpolation
gl_FragColor = texture2D(tex, tex_c).bgra * texture2D(texm, tex_m).a * col; gl_FragColor = texture2D(tex, tex_c).bgra * texture2D(texm, tex_m).a * col;
} }

View File

@ -11,9 +11,7 @@ void main()
tex_c = tex_coord; tex_c = tex_coord;
// tex_coorda contains the Y-invert flag // tex_coorda contains the Y-invert flag
// tex_coordm contains the X,Y position of the mask // position on screen in [0..1] range of current pixel
// tex_sample contains the W,H size of the mask (inverted) vec4 mask_Position = mvp * vertex * vec4(0.5, sign(tex_coorda.y) * 0.5, 0.5, 0.5) + vec4(0.5, 0.5, 0, 0);
tex_m = mask_Position.xy * tex_sample + tex_coordm;
vec4 mask_Position = mvp * vertex * vec4(tex_coorda.x * 0.5, tex_coorda.y * 0.5, 0.5, 0.5) + vec4(0.5, 0.5, 0, 0);
tex_m = vec2(mask_Position.xy - tex_coordm) * tex_sample;
} }

View File

@ -13,9 +13,7 @@ void main()
col = color; col = color;
// tex_coorda contains the Y-invert flag // tex_coorda contains the Y-invert flag
// tex_coordm contains the X,Y position of the mask // position on screen in [0..1] range of current pixel
// tex_sample contains the W,H size of the mask (inverted) vec4 mask_Position = mvp * vertex * vec4(0.5, sign(tex_coorda.y) * 0.5, 0.5, 0.5) + vec4(0.5, 0.5, 0, 0);
tex_m = mask_Position.xy * tex_sample + tex_coordm;
vec4 mask_Position = mvp * vertex * vec4(tex_coorda.x * 0.5, tex_coorda.y * 0.5, 0.5, 0.5) + vec4(0.5, 0.5, 0, 0);
tex_m = vec2(mask_Position.xy - tex_coordm) * tex_sample;
} }