From 3d2f1a3d9b04d4067ebe6008d2662c46ec694d7b Mon Sep 17 00:00:00 2001 From: Jean-Philippe Andre Date: Tue, 24 Jan 2017 14:23:03 +0900 Subject: [PATCH] evas filters: Implement mask filter in pure GL This reuses the existing mask infrastructure, but adds a color flag to use the whole RGBA range, rather than just the Alpha channel. Filters are still very slow (glReadPixels and non-optimized use of GL buffers...), but this is progress :) --- src/Makefile_Evas.am | 1 + src/lib/evas/canvas/evas_render.c | 2 +- src/lib/evas/include/evas_common_private.h | 1 + src/lib/evas/include/evas_private.h | 2 +- .../evas/engines/gl_common/evas_gl_common.h | 37 ++++-- .../evas/engines/gl_common/evas_gl_context.c | 49 +++++--- .../evas/engines/gl_common/evas_gl_font.c | 12 +- .../evas/engines/gl_common/evas_gl_image.c | 117 +++++++++++++++--- .../evas/engines/gl_common/evas_gl_line.c | 4 +- .../evas/engines/gl_common/evas_gl_polygon.c | 8 +- .../engines/gl_common/evas_gl_rectangle.c | 10 +- .../evas/engines/gl_common/evas_gl_shader.c | 38 +++--- .../gl_common/shader/evas_gl_shaders.x | 25 +++- .../engines/gl_common/shader/fragment.glsl | 25 +++- .../engines/gl_generic/evas_ector_gl_buffer.c | 24 ++-- .../gl_generic/evas_ector_gl_image_buffer.c | 30 ++++- .../evas/engines/gl_generic/evas_engine.c | 83 +------------ .../gl_generic/filters/gl_engine_filter.h | 14 +-- .../gl_generic/filters/gl_filter_blend.c | 13 +- .../gl_generic/filters/gl_filter_mask.c | 83 +++++++++++++ 20 files changed, 391 insertions(+), 187 deletions(-) create mode 100644 src/modules/evas/engines/gl_generic/filters/gl_filter_mask.c diff --git a/src/Makefile_Evas.am b/src/Makefile_Evas.am index 83557dfb92..aa2da76028 100644 --- a/src/Makefile_Evas.am +++ b/src/Makefile_Evas.am @@ -844,6 +844,7 @@ modules/evas/engines/gl_generic/evas_ector_gl_buffer.c \ modules/evas/engines/gl_generic/evas_ector_gl_image_buffer.c \ modules/evas/engines/gl_generic/filters/gl_engine_filter.h \ modules/evas/engines/gl_generic/filters/gl_filter_blend.c \ +modules/evas/engines/gl_generic/filters/gl_filter_mask.c \ $(NULL) evas_gl_generic_eolian_files = \ diff --git a/src/lib/evas/canvas/evas_render.c b/src/lib/evas/canvas/evas_render.c index a348f6eb0d..5de9847a07 100644 --- a/src/lib/evas/canvas/evas_render.c +++ b/src/lib/evas/canvas/evas_render.c @@ -2470,7 +2470,7 @@ evas_render_mask_subrender(Evas_Public_Data *evas, Eina_Bool smooth = evas_object_image_smooth_scale_get(mask->object); void *original = mask->func->engine_data_get(mask->object); void *scaled = ENFN->image_scaled_update - (ENDT, mdata->surface, original, w, h, smooth, EINA_TRUE, EVAS_COLORSPACE_GRY8); + (ENDT, mdata->surface, original, w, h, smooth, EVAS_COLORSPACE_GRY8); if (scaled) { done = EINA_TRUE; diff --git a/src/lib/evas/include/evas_common_private.h b/src/lib/evas/include/evas_common_private.h index a3558f6e55..829c5109c3 100644 --- a/src/lib/evas/include/evas_common_private.h +++ b/src/lib/evas/include/evas_common_private.h @@ -766,6 +766,7 @@ struct _RGBA_Draw_Context int mask_x, mask_y; Eina_Bool use : 1; Eina_Bool async : 1; + Eina_Bool mask_color : 1; // true if masking with color (eg. filters) } clip; struct { #ifdef HAVE_PIXMAN diff --git a/src/lib/evas/include/evas_private.h b/src/lib/evas/include/evas_private.h index 98c68a0b62..f3d74d280c 100644 --- a/src/lib/evas/include/evas_private.h +++ b/src/lib/evas/include/evas_private.h @@ -1491,7 +1491,7 @@ struct _Evas_Func Eina_Bool (*image_map_draw) (void *data, void *context, void *surface, void *image, RGBA_Map *m, int smooth, int level, Eina_Bool do_async); void *(*image_map_surface_new) (void *data, int w, int h, int alpha); void (*image_map_clean) (void *data, RGBA_Map *m); - void *(*image_scaled_update) (void *data, void *scaled, void *image, int dst_w, int dst_h, Eina_Bool smooth, Eina_Bool alpha, Evas_Colorspace cspace); + void *(*image_scaled_update) (void *data, void *scaled, void *image, int dst_w, int dst_h, Eina_Bool smooth, Evas_Colorspace cspace); void (*image_content_hint_set) (void *data, void *surface, int hint); int (*image_content_hint_get) (void *data, void *surface); 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 74d456e008..537361ca45 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_common.h +++ b/src/modules/evas/engines/gl_common/evas_gl_common.h @@ -556,58 +556,67 @@ void evas_gl_common_context_target_surface_set(Evas_Engine_GL_Conte void evas_gl_common_context_line_push(Evas_Engine_GL_Context *gc, int x1, int y1, int x2, int y2, int clip, int cx, int cy, int cw, int ch, - Evas_GL_Texture *mtex, int mx, int my, int mw, int mh, Eina_Bool mask_smooth, + Evas_GL_Texture *mtex, int mx, int my, int mw, int mh, + Eina_Bool mask_smooth, Eina_Bool mask_color, 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, - Evas_GL_Texture *mtex, int mx, int my, int mw, int mh, Eina_Bool mask_smooth); + Evas_GL_Texture *mtex, int mx, int my, int mw, int mh, + Eina_Bool mask_smooth, Eina_Bool mask_color); void evas_gl_common_context_image_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, - Evas_GL_Texture *mtex, int mx, int my, int mw, int mh, Eina_Bool mask_smooth, + Evas_GL_Texture *mtex, int mx, int my, int mw, int mh, + Eina_Bool mask_smooth, Eina_Bool mask_color, int r, int g, int b, int a, Eina_Bool smooth, Eina_Bool tex_only); void evas_gl_common_context_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, - Evas_GL_Texture *mtex, int mx, int my, int mw, int mh, Eina_Bool mask_smooth, + Evas_GL_Texture *mtex, int mx, int my, int mw, int mh, + Eina_Bool mask_smooth, Eina_Bool mask_color, int r, int g, int b, int a); void evas_gl_common_context_yuv_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, - Evas_GL_Texture *mtex, int mx, int my, int mw, int mh, Eina_Bool mask_smooth, + Evas_GL_Texture *mtex, int mx, int my, int mw, int mh, + Eina_Bool mask_smooth, Eina_Bool mask_color, int r, int g, int b, int a, Eina_Bool smooth); void evas_gl_common_context_yuv_709_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, - Evas_GL_Texture *mtex, int mx, int my, int mw, int mh, Eina_Bool mask_smooth, + Evas_GL_Texture *mtex, int mx, int my, int mw, int mh, + Eina_Bool mask_smooth, Eina_Bool mask_color, int r, int g, int b, int a, Eina_Bool smooth); void evas_gl_common_context_yuy2_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, - Evas_GL_Texture *mtex, int mx, int my, int mw, int mh, Eina_Bool mask_smooth, + Evas_GL_Texture *mtex, int mx, int my, int mw, int mh, + Eina_Bool mask_smooth, Eina_Bool mask_color, int r, int g, int b, int a, Eina_Bool smooth); void evas_gl_common_context_nv12_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, - Evas_GL_Texture *mtex, int mx, int my, int mw, int mh, Eina_Bool mask_smooth, + Evas_GL_Texture *mtex, int mx, int my, int mw, int mh, + Eina_Bool mask_smooth, Eina_Bool mask_color, int r, int g, int b, int a, Eina_Bool smooth); void evas_gl_common_context_rgb_a_pair_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, - Evas_GL_Texture *mtex, int mx, int my, int mw, int mh, Eina_Bool mask_smooth, + Evas_GL_Texture *mtex, int mx, int my, int mw, int mh, + Eina_Bool mask_smooth, Eina_Bool mask_color, int r, int g, int b, int a, Eina_Bool smooth); void evas_gl_common_context_image_map_push(Evas_Engine_GL_Context *gc, @@ -615,7 +624,8 @@ void evas_gl_common_context_image_map_push(Evas_Engine_GL_Context *g int npoints, RGBA_Map_Point *p, int clip, int cx, int cy, int cw, int ch, - Evas_GL_Texture *mtex, int mx, int my, int mw, int mh, Eina_Bool mask_smooth, + Evas_GL_Texture *mtex, int mx, int my, int mw, int mh, + Eina_Bool mask_smooth, Eina_Bool mask_color, int r, int g, int b, int a, Eina_Bool smooth, Eina_Bool tex_only, @@ -632,7 +642,7 @@ Evas_GL_Program *evas_gl_common_shader_program_get(Evas_Engine_GL_Context *gc, int sw, int sh, int w, int h, Eina_Bool smooth, Evas_GL_Texture *tex, Eina_Bool tex_only, Evas_GL_Texture *mtex, Eina_Bool mask_smooth, - int mw, int mh, + Eina_Bool mask_color, int mw, int mh, Shader_Sampling *psam, int *pnomul, Shader_Sampling *pmasksam); void evas_gl_common_shader_textures_bind(Evas_GL_Program *p); @@ -688,8 +698,9 @@ void evas_gl_common_image_dirty(Evas_GL_Image *im, unsigned int x, void evas_gl_common_image_update(Evas_Engine_GL_Context *gc, Evas_GL_Image *im); void 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); void evas_gl_common_image_draw(Evas_Engine_GL_Context *gc, Evas_GL_Image *im, int sx, int sy, int sw, int sh, int dx, int dy, int dw, int dh, int smooth); -Evas_GL_Image *evas_gl_common_image_surface_update(Evas_Engine_GL_Context *gc, Evas_GL_Image *im); -Evas_GL_Image *evas_gl_common_image_surface_detach(Evas_Engine_GL_Context *gc, Evas_GL_Image *im); +Evas_GL_Image *evas_gl_common_image_surface_update(Evas_GL_Image *im); +Evas_GL_Image *evas_gl_common_image_surface_detach(Evas_GL_Image *im); +Evas_GL_Image *evas_gl_common_image_virtual_scaled_get(Evas_GL_Image *scaled, Evas_GL_Image *image, int dst_w, int dst_h, Eina_Bool smooth); void *evas_gl_font_texture_new(void *gc, RGBA_Font_Glyph *fg); void evas_gl_font_texture_free(void *); 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 b0ddb5e0ba..df6af106f8 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_context.c +++ b/src/modules/evas/engines/gl_common/evas_gl_context.c @@ -1889,7 +1889,8 @@ void evas_gl_common_context_line_push(Evas_Engine_GL_Context *gc, int x1, int y1, int x2, int y2, int clip, int cx, int cy, int cw, int ch, - Evas_GL_Texture *mtex, int mx, int my, int mw, int mh, Eina_Bool mask_smooth, + Evas_GL_Texture *mtex, int mx, int my, int mw, int mh, + Eina_Bool mask_smooth, Eina_Bool mask_color, int r, int g, int b, int a) { Eina_Bool blend = EINA_FALSE; @@ -1907,7 +1908,7 @@ evas_gl_common_context_line_push(Evas_Engine_GL_Context *gc, prog = evas_gl_common_shader_program_get(gc, SHD_LINE, NULL, 0, r, g, b, a, 0, 0, 0, 0, EINA_FALSE, NULL, EINA_FALSE, - mtex, mask_smooth, mw, mh, NULL, NULL, &masksam); + mtex, mask_smooth, mask_color, mw, mh, NULL, NULL, &masksam); pn = _evas_gl_common_context_push(SHD_LINE, gc, NULL, mtex, @@ -1958,7 +1959,7 @@ evas_gl_common_context_rectangle_push(Evas_Engine_GL_Context *gc, int r, int g, int b, int a, Evas_GL_Texture *mtex, int mx, int my, int mw, int mh, - Eina_Bool mask_smooth) + Eina_Bool mask_smooth, Eina_Bool mask_color) { Eina_Bool blend = EINA_FALSE; Shader_Sampling masksam = SHD_SAM11; @@ -1971,7 +1972,7 @@ evas_gl_common_context_rectangle_push(Evas_Engine_GL_Context *gc, prog = evas_gl_common_shader_program_get(gc, SHD_RECT, NULL, 0, r, g, b, a, 0, 0, 0, 0, EINA_FALSE, NULL, EINA_FALSE, - mtex, mask_smooth, mw, mh, NULL, NULL, &masksam); + mtex, mask_smooth, mask_color, mw, mh, NULL, NULL, &masksam); pn = _evas_gl_common_context_push(SHD_RECT, @@ -2130,7 +2131,8 @@ evas_gl_common_context_image_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, - Evas_GL_Texture *mtex, int mx, int my, int mw, int mh, Eina_Bool mask_smooth, + Evas_GL_Texture *mtex, int mx, int my, int mw, int mh, + Eina_Bool mask_smooth, Eina_Bool mask_color, int r, int g, int b, int a, Eina_Bool smooth, Eina_Bool tex_only) { @@ -2167,7 +2169,7 @@ evas_gl_common_context_image_push(Evas_Engine_GL_Context *gc, prog = evas_gl_common_shader_program_get(gc, shd_in, NULL, 0, r, g, b, a, sw, sh, w, h, smooth, tex, tex_only, - mtex, mask_smooth, mw, mh, + mtex, mask_smooth, mask_color, mw, mh, &sam, &nomul, &masksam); if (tex->ptt) @@ -2378,7 +2380,8 @@ evas_gl_common_context_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, - Evas_GL_Texture *mtex, int mx, int my, int mw, int mh, Eina_Bool mask_smooth, + Evas_GL_Texture *mtex, int mx, int my, int mw, int mh, + Eina_Bool mask_smooth, Eina_Bool mask_color, int r, int g, int b, int a) { GLfloat tx1, tx2, ty1, ty2; @@ -2388,7 +2391,7 @@ evas_gl_common_context_font_push(Evas_Engine_GL_Context *gc, prog = evas_gl_common_shader_program_get(gc, SHD_FONT, NULL, 0, r, g, b, a, sw, sh, w, h, EINA_FALSE, tex, EINA_FALSE, - mtex, mask_smooth, mw, mh, + mtex, mask_smooth, mask_color, mw, mh, NULL, NULL, &masksam); pn = _evas_gl_common_context_push(SHD_FONT, @@ -2452,7 +2455,8 @@ evas_gl_common_context_yuv_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, - Evas_GL_Texture *mtex, int mx, int my, int mw, int mh, Eina_Bool mask_smooth, + Evas_GL_Texture *mtex, int mx, int my, int mw, int mh, + Eina_Bool mask_smooth, Eina_Bool mask_color, int r, int g, int b, int a, Eina_Bool smooth) { @@ -2467,7 +2471,7 @@ evas_gl_common_context_yuv_push(Evas_Engine_GL_Context *gc, prog = evas_gl_common_shader_program_get(gc, SHD_YUV, NULL, 0, r, g, b, a, w, h, w, h, smooth, tex, 0, - mtex, mask_smooth, mw, mh, + mtex, mask_smooth, mask_color, mw, mh, NULL, &nomul, &masksam); pn = _evas_gl_common_context_push(SHD_YUV, @@ -2531,7 +2535,8 @@ evas_gl_common_context_yuv_709_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, - Evas_GL_Texture *mtex, int mx, int my, int mw, int mh, Eina_Bool mask_smooth, + Evas_GL_Texture *mtex, int mx, int my, int mw, int mh, + Eina_Bool mask_smooth, Eina_Bool mask_color, int r, int g, int b, int a, Eina_Bool smooth) { @@ -2546,7 +2551,7 @@ evas_gl_common_context_yuv_709_push(Evas_Engine_GL_Context *gc, prog = evas_gl_common_shader_program_get(gc, SHD_YUV_709, NULL, 0, r, g, b, a, w, h, w, h, smooth, tex, 0, - mtex, mask_smooth, mw, mh, + mtex, mask_smooth, mask_color, mw, mh, NULL, &nomul, &masksam); pn = _evas_gl_common_context_push(SHD_YUV_709, @@ -2610,7 +2615,8 @@ evas_gl_common_context_yuy2_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, - Evas_GL_Texture *mtex, int mx, int my, int mw, int mh, Eina_Bool mask_smooth, + Evas_GL_Texture *mtex, int mx, int my, int mw, int mh, + Eina_Bool mask_smooth, Eina_Bool mask_color, int r, int g, int b, int a, Eina_Bool smooth) { @@ -2625,7 +2631,7 @@ evas_gl_common_context_yuy2_push(Evas_Engine_GL_Context *gc, prog = evas_gl_common_shader_program_get(gc, SHD_YUY2, NULL, 0, r, g, b, a, sw, sh, w, h, smooth, tex, 0, - mtex, mask_smooth, mw, mh, + mtex, mask_smooth, mask_color, mw, mh, NULL, &nomul, &masksam); pn = _evas_gl_common_context_push(SHD_YUY2, @@ -2687,7 +2693,8 @@ evas_gl_common_context_nv12_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, - Evas_GL_Texture *mtex, int mx, int my, int mw, int mh, Eina_Bool mask_smooth, + Evas_GL_Texture *mtex, int mx, int my, int mw, int mh, + Eina_Bool mask_smooth, Eina_Bool mask_color, int r, int g, int b, int a, Eina_Bool smooth) { @@ -2702,7 +2709,7 @@ evas_gl_common_context_nv12_push(Evas_Engine_GL_Context *gc, prog = evas_gl_common_shader_program_get(gc, SHD_NV12, NULL, 0, r, g, b, a, sw, sh, w, h, smooth, tex, 0, - mtex, mask_smooth, mw, mh, + mtex, mask_smooth, mask_color, mw, mh, NULL, &nomul, &masksam); pn = _evas_gl_common_context_push(SHD_NV12, @@ -2767,7 +2774,8 @@ evas_gl_common_context_rgb_a_pair_push(Evas_Engine_GL_Context *gc, double sx, double sy, double sw, double sh, int x, int y, int w, int h, - Evas_GL_Texture *mtex, int mx, int my, int mw, int mh, Eina_Bool mask_smooth, + Evas_GL_Texture *mtex, int mx, int my, int mw, int mh, + Eina_Bool mask_smooth, Eina_Bool mask_color, int r, int g, int b, int a, Eina_Bool smooth) @@ -2786,7 +2794,7 @@ evas_gl_common_context_rgb_a_pair_push(Evas_Engine_GL_Context *gc, prog = evas_gl_common_shader_program_get(gc, SHD_RGB_A_PAIR, NULL, 0, r, g, b, a, sw, sh, w, h, smooth, tex, 0, - mtex, mask_smooth, mw, mh, + mtex, mask_smooth, mask_color, mw, mh, NULL, &nomul, &masksam); pn = _evas_gl_common_context_push(SHD_RGB_A_PAIR, @@ -2851,7 +2859,8 @@ evas_gl_common_context_image_map_push(Evas_Engine_GL_Context *gc, int npoints, RGBA_Map_Point *p, int clip, int cx, int cy, int cw, int ch, - Evas_GL_Texture *mtex, int mx, int my, int mw, int mh, Eina_Bool mask_smooth, + Evas_GL_Texture *mtex, int mx, int my, int mw, int mh, + Eina_Bool mask_smooth, Eina_Bool mask_color, int r, int g, int b, int a, Eina_Bool smooth, Eina_Bool tex_only, Evas_Colorspace cspace) @@ -2916,7 +2925,7 @@ evas_gl_common_context_image_map_push(Evas_Engine_GL_Context *gc, } prog = evas_gl_common_shader_program_get(gc, type, p, npoints, r, g, b, a, w, h, w, h, smooth, tex, tex_only, - mtex, mask_smooth, mw, mh, + mtex, mask_smooth, mask_color, mw, mh, NULL, &nomul, &masksam); x = w = (p[0].x >> FP); diff --git a/src/modules/evas/engines/gl_common/evas_gl_font.c b/src/modules/evas/engines/gl_common/evas_gl_font.c index 5a5fdeb730..1b3e35b607 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_font.c +++ b/src/modules/evas/engines/gl_common/evas_gl_font.c @@ -71,6 +71,7 @@ evas_gl_font_texture_draw(void *context, void *surface EINA_UNUSED, void *draw_c int sx, sy, sw, sh; double mx = 0.0, my = 0.0, mw = 0.0, mh = 0.0; Eina_Bool mask_smooth = EINA_FALSE; + Eina_Bool mask_color = EINA_FALSE; if (dc != gc->dc) return; tex = fg->ext_dat; @@ -94,6 +95,7 @@ evas_gl_font_texture_draw(void *context, void *surface EINA_UNUSED, void *draw_c mw = mask->w; mh = mask->h; mask_smooth = mask->scaled.smooth; + mask_color = gc->dc->clip.mask_color; } else mtex = NULL; } @@ -117,7 +119,7 @@ evas_gl_font_texture_draw(void *context, void *surface EINA_UNUSED, void *draw_c 0.0, 0.0, 0.0, 0.0, // sx, sy, sw, sh, x, y, tex->w, tex->h, - mtex, mx, my, mw, mh, mask_smooth, + mtex, mx, my, mw, mh, mask_smooth, mask_color, r, g, b, a); return; } @@ -128,7 +130,7 @@ evas_gl_font_texture_draw(void *context, void *surface EINA_UNUSED, void *draw_c evas_gl_common_context_font_push(gc, tex, ssx, ssy, ssw, ssh, nx, ny, nw, nh, - mtex, mx, my, mw, mh, mask_smooth, + mtex, mx, my, mw, mh, mask_smooth, mask_color, r, g, b, a); } else @@ -137,7 +139,7 @@ evas_gl_font_texture_draw(void *context, void *surface EINA_UNUSED, void *draw_c 0.0, 0.0, 0.0, 0.0, // sx, sy, sw, sh, x, y, tex->w, tex->h, - mtex, mx, my, mw, mh, mask_smooth, + mtex, mx, my, mw, mh, mask_smooth, mask_color, r, g, b, a); } return; @@ -167,7 +169,7 @@ evas_gl_font_texture_draw(void *context, void *surface EINA_UNUSED, void *draw_c 0.0, 0.0, 0.0, 0.0, // sx, sy, sw, sh, x, y, tex->w, tex->h, - mtex, mx, my, mw, mh, mask_smooth, + mtex, mx, my, mw, mh, mask_smooth, mask_color, r, g, b, a); continue; } @@ -178,7 +180,7 @@ evas_gl_font_texture_draw(void *context, void *surface EINA_UNUSED, void *draw_c evas_gl_common_context_font_push(gc, tex, ssx, ssy, ssw, ssh, nx, ny, nw, nh, - mtex, mx, my, mw, mh, mask_smooth, + mtex, mx, my, mw, mh, mask_smooth, mask_color, r, g, b, a); } evas_common_draw_context_cutouts_free(_evas_gl_common_cutout_rects); diff --git a/src/modules/evas/engines/gl_common/evas_gl_image.c b/src/modules/evas/engines/gl_common/evas_gl_image.c index e42203151a..4a89ff62d8 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_image.c +++ b/src/modules/evas/engines/gl_common/evas_gl_image.c @@ -1042,13 +1042,14 @@ evas_gl_common_image_update(Evas_Engine_GL_Context *gc, Evas_GL_Image *im) } Evas_GL_Image * -evas_gl_common_image_surface_update(Evas_Engine_GL_Context *gc, Evas_GL_Image *im) +evas_gl_common_image_surface_update(Evas_GL_Image *im) { + Evas_Engine_GL_Context *gc; Evas_GL_Image *glim = NULL; Eina_Bool alpha; int w, h; - if (!gc || !im || !im->im || !im->im->image.data) + if (!im || !im->gc || !im->im || !im->im->image.data) goto fail; if (im->im->cache_entry.space == EFL_GFX_COLORSPACE_ARGB8888) @@ -1057,6 +1058,7 @@ evas_gl_common_image_surface_update(Evas_Engine_GL_Context *gc, Evas_GL_Image *i alpha = EINA_TRUE; else goto fail; + gc = im->gc; w = im->im->cache_entry.w; h = im->im->cache_entry.h; glim = evas_gl_common_image_surface_new(gc, w, h, EINA_TRUE, EINA_FALSE); @@ -1101,7 +1103,7 @@ fail: } Evas_GL_Image * -evas_gl_common_image_surface_detach(Evas_Engine_GL_Context *gc EINA_UNUSED, Evas_GL_Image *im) +evas_gl_common_image_surface_detach(Evas_GL_Image *im) { if (!im || !im->im) return im; @@ -1111,6 +1113,85 @@ evas_gl_common_image_surface_detach(Evas_Engine_GL_Context *gc EINA_UNUSED, Evas return im; } +Evas_GL_Image * +evas_gl_common_image_virtual_scaled_get(Evas_GL_Image *scaled, Evas_GL_Image *image, + int dst_w, int dst_h, Eina_Bool smooth) +{ + Evas_GL_Image *dst = scaled, *newdst; + Evas_GL_Image *src = image; + Evas_Engine_GL_Context *gc; + Eina_Bool reffed = EINA_FALSE; + + if (!src) return NULL; + + // masking will work only with single texture images + switch (src->cs.space) + { + case EVAS_COLORSPACE_AGRY88: + case EVAS_COLORSPACE_ARGB8888: + case EVAS_COLORSPACE_GRY8: + case EVAS_COLORSPACE_RGBA8_ETC2_EAC: + case EVAS_COLORSPACE_RGBA_S3TC_DXT1: + case EVAS_COLORSPACE_RGBA_S3TC_DXT2: + case EVAS_COLORSPACE_RGBA_S3TC_DXT3: + case EVAS_COLORSPACE_RGBA_S3TC_DXT4: + case EVAS_COLORSPACE_RGBA_S3TC_DXT5: + break; + default: + DBG("cspace %d can't be used for masking's fast path", src->cs.space); + return NULL; + } + + gc = src->gc; + if (dst && (dst->scaled.origin == src) && + (dst->w == dst_w) && (dst->h == dst_h)) + return dst; + + evas_gl_common_image_update(gc, src); + if (!src->tex) + { + ERR("No source texture."); + return NULL; + } + + newdst = calloc(1, sizeof(Evas_GL_Image)); + if (!newdst) return NULL; + + if (dst) + { + if (dst->scaled.origin == src) + { + if (dst->references == 1) + { + dst->w = dst_w; + dst->h = dst_h; + dst->scaled.smooth = smooth; + free(newdst); + return dst; + } + src->references++; + reffed = EINA_TRUE; + } + evas_gl_common_image_free(dst); + } + + newdst->references = 1; + newdst->gc = gc; + newdst->cs.space = src->cs.space; + newdst->alpha = src->alpha; + newdst->w = dst_w; + newdst->h = dst_h; + newdst->tex = src->tex; + newdst->tex->references++; + newdst->tex_only = 1; + + if (!reffed) src->references++; + newdst->scaled.origin = src; + newdst->scaled.smooth = smooth; + + return newdst; +} + void 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) @@ -1120,6 +1201,7 @@ evas_gl_common_image_map_draw(Evas_Engine_GL_Context *gc, Evas_GL_Image *im, Eina_Bool mask_smooth = EINA_FALSE; Evas_GL_Image *mask = dc->clip.mask; Evas_GL_Texture *mtex = NULL; + Eina_Bool mask_color = EINA_FALSE; int r, g, b, a; int c, cx, cy, cw, ch; @@ -1155,13 +1237,14 @@ evas_gl_common_image_map_draw(Evas_Engine_GL_Context *gc, Evas_GL_Image *im, mw = mask->w; mh = mask->h; mask_smooth = mask->scaled.smooth; + mask_color = dc->clip.mask_color; } else mtex = NULL; } evas_gl_common_context_image_map_push(gc, im->tex, npoints, p, c, cx, cy, cw, ch, - mtex, mx, my, mw, mh, mask_smooth, + mtex, mx, my, mw, mh, mask_smooth, mask_color, r, g, b, a, smooth, im->tex_only, im->cs.space); } @@ -1182,6 +1265,7 @@ _evas_gl_common_image_push(Evas_Engine_GL_Context *gc, Evas_GL_Image *im, double ssx, ssy, ssw, ssh; Evas_GL_Texture *mtex = NULL; Eina_Bool mask_smooth = EINA_FALSE; + Eina_Bool mask_color = EINA_FALSE; int nx, ny, nw, nh; nx = dx; ny = dy; nw = dw; nh = dh; @@ -1202,6 +1286,7 @@ _evas_gl_common_image_push(Evas_Engine_GL_Context *gc, Evas_GL_Image *im, mw = mask->w; mh = mask->h; mask_smooth = mask->scaled.smooth; + mask_color = gc->dc->clip.mask_color; } else mtex = NULL; } @@ -1213,7 +1298,7 @@ _evas_gl_common_image_push(Evas_Engine_GL_Context *gc, Evas_GL_Image *im, im->tex, sx, sy, sw, sh, dx, dy, dw, dh, - mtex, mx, my, mw, mh, mask_smooth, + mtex, mx, my, mw, mh, mask_smooth, mask_color, r, g, b, a, smooth); else if (yuv_709) @@ -1221,7 +1306,7 @@ _evas_gl_common_image_push(Evas_Engine_GL_Context *gc, Evas_GL_Image *im, im->tex, sx, sy, sw, sh, dx, dy, dw, dh, - mtex, mx, my, mw, mh, mask_smooth, + mtex, mx, my, mw, mh, mask_smooth, mask_color, r, g, b, a, smooth); else if (yuy2) @@ -1229,7 +1314,7 @@ _evas_gl_common_image_push(Evas_Engine_GL_Context *gc, Evas_GL_Image *im, im->tex, sx, sy, sw, sh, dx, dy, dw, dh, - mtex, mx, my, mw, mh, mask_smooth, + mtex, mx, my, mw, mh, mask_smooth, mask_color, r, g, b, a, smooth); else if (nv12) @@ -1237,7 +1322,7 @@ _evas_gl_common_image_push(Evas_Engine_GL_Context *gc, Evas_GL_Image *im, im->tex, sx, sy, sw, sh, dx, dy, dw, dh, - mtex, mx, my, mw, mh, mask_smooth, + mtex, mx, my, mw, mh, mask_smooth, mask_color, r, g, b, a, smooth); else if (rgb_a_pair) @@ -1245,7 +1330,7 @@ _evas_gl_common_image_push(Evas_Engine_GL_Context *gc, Evas_GL_Image *im, im->tex, sx, sy, sw, sh, dx, dy, dw, dh, - mtex, mx, my, mw, mh, mask_smooth, + mtex, mx, my, mw, mh, mask_smooth, mask_color, r, g, b, a, smooth); else @@ -1253,7 +1338,7 @@ _evas_gl_common_image_push(Evas_Engine_GL_Context *gc, Evas_GL_Image *im, im->tex, sx, sy, sw, sh, dx, dy, dw, dh, - mtex, mx, my, mw, mh, mask_smooth, + mtex, mx, my, mw, mh, mask_smooth, mask_color, r, g, b, a, smooth, im->tex_only); return; @@ -1269,7 +1354,7 @@ _evas_gl_common_image_push(Evas_Engine_GL_Context *gc, Evas_GL_Image *im, im->tex, ssx, ssy, ssw, ssh, nx, ny, nw, nh, - mtex, mx, my, mw, mh, mask_smooth, + mtex, mx, my, mw, mh, mask_smooth, mask_color, r, g, b, a, smooth); else if (yuv_709) @@ -1277,7 +1362,7 @@ _evas_gl_common_image_push(Evas_Engine_GL_Context *gc, Evas_GL_Image *im, im->tex, ssx, ssy, ssw, ssh, nx, ny, nw, nh, - mtex, mx, my, mw, mh, mask_smooth, + mtex, mx, my, mw, mh, mask_smooth, mask_color, r, g, b, a, smooth); else if (yuy2) @@ -1285,7 +1370,7 @@ _evas_gl_common_image_push(Evas_Engine_GL_Context *gc, Evas_GL_Image *im, im->tex, ssx, ssy, ssw, ssh, nx, ny, nw, nh, - mtex, mx, my, mw, mh, mask_smooth, + mtex, mx, my, mw, mh, mask_smooth, mask_color, r, g, b, a, smooth); else if (nv12) @@ -1293,7 +1378,7 @@ _evas_gl_common_image_push(Evas_Engine_GL_Context *gc, Evas_GL_Image *im, im->tex, ssx, ssy, ssw, ssh, nx, ny, nw, nh, - mtex, mx, my, mw, mh, mask_smooth, + mtex, mx, my, mw, mh, mask_smooth, mask_color, r, g, b, a, smooth); else if (rgb_a_pair) @@ -1301,7 +1386,7 @@ _evas_gl_common_image_push(Evas_Engine_GL_Context *gc, Evas_GL_Image *im, im->tex, ssx, ssy, ssw, ssh, nx, ny, nw, nh, - mtex, mx, my, mw, mh, mask_smooth, + mtex, mx, my, mw, mh, mask_smooth, mask_color, r, g, b, a, smooth); else @@ -1309,7 +1394,7 @@ _evas_gl_common_image_push(Evas_Engine_GL_Context *gc, Evas_GL_Image *im, im->tex, ssx, ssy, ssw, ssh, nx, ny, nw, nh, - mtex, mx, my, mw, mh, mask_smooth, + mtex, mx, my, mw, mh, mask_smooth, mask_color, r, g, b, a, smooth, im->tex_only); } diff --git a/src/modules/evas/engines/gl_common/evas_gl_line.c b/src/modules/evas/engines/gl_common/evas_gl_line.c index 1b7def125f..892be20260 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_line.c +++ b/src/modules/evas/engines/gl_common/evas_gl_line.c @@ -12,6 +12,7 @@ evas_gl_common_line_draw(Evas_Engine_GL_Context *gc, int x1, int y1, int x2, int const int OFFSET_HACK_ARM = 2; Evas_GL_Texture *mtex = NULL; Eina_Bool mask_smooth = EINA_FALSE; + Eina_Bool mask_color = EINA_FALSE; int mx = 0, my = 0, mw = 0, mh = 0; Evas_GL_Image *mask; @@ -48,6 +49,7 @@ evas_gl_common_line_draw(Evas_Engine_GL_Context *gc, int x1, int y1, int x2, int mw = mask->w; mh = mask->h; mask_smooth = mask->scaled.smooth; + mask_color = gc->dc->clip.mask_color; } else mtex = NULL; } @@ -97,6 +99,6 @@ evas_gl_common_line_draw(Evas_Engine_GL_Context *gc, int x1, int y1, int x2, int evas_gl_common_context_line_push(gc, x1, y1, x2, y2, c, cx, cy, cw, ch, - mtex, mx, my, mw, mh, mask_smooth, + mtex, mx, my, mw, mh, mask_smooth, mask_color, r, g, b, a); } 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 4552d663a3..839dc61339 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_polygon.c +++ b/src/modules/evas/engines/gl_common/evas_gl_polygon.c @@ -133,6 +133,7 @@ evas_gl_common_poly_draw(Evas_Engine_GL_Context *gc, Evas_GL_Polygon *poly, int int x = 0, y = 0, w = 0, h = 0; Evas_GL_Texture *mtex = NULL; Eina_Bool mask_smooth = EINA_FALSE; + Eina_Bool mask_color = EINA_FALSE; int mx = 0, my = 0, mw = 0, mh = 0; Evas_GL_Image *mask; @@ -165,6 +166,7 @@ evas_gl_common_poly_draw(Evas_Engine_GL_Context *gc, Evas_GL_Polygon *poly, int mw = mask->w; mh = mask->h; mask_smooth = mask->scaled.smooth; + mask_color = gc->dc->clip.mask_color; } else mtex = NULL; } @@ -291,7 +293,8 @@ evas_gl_common_poly_draw(Evas_Engine_GL_Context *gc, Evas_GL_Polygon *poly, int h = 1; evas_gl_common_context_rectangle_push(gc, x, y, w, h, cr, cg, cb, ca, - mtex, mx, my, mw, mh, mask_smooth); + mtex, mx, my, mw, mh, + mask_smooth, mask_color); } } else @@ -315,7 +318,8 @@ evas_gl_common_poly_draw(Evas_Engine_GL_Context *gc, Evas_GL_Polygon *poly, int if ((w > 0) && (h > 0)) evas_gl_common_context_rectangle_push(gc, x, y, w, h, cr, cg, cb, ca, - mtex, mx, my, mw, mh, mask_smooth); + mtex, mx, my, mw, mh, + mask_smooth, mask_color); } } } 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 04bdc1ae48..a188467b58 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_rectangle.c +++ b/src/modules/evas/engines/gl_common/evas_gl_rectangle.c @@ -8,6 +8,7 @@ evas_gl_common_rect_draw(Evas_Engine_GL_Context *gc, int x, int y, int w, int h) int mx = 0, my = 0, mw = 0, mh = 0; Eina_Bool mask_smooth = EINA_FALSE; Evas_GL_Image *mask = gc->dc->clip.mask; + Eina_Bool mask_color = EINA_FALSE; Evas_GL_Texture *mtex = NULL; if ((w <= 0) || (h <= 0)) return; @@ -42,6 +43,7 @@ evas_gl_common_rect_draw(Evas_Engine_GL_Context *gc, int x, int y, int w, int h) mw = mask->w; mh = mask->h; mask_smooth = mask->scaled.smooth; + mask_color = gc->dc->clip.mask_color; } else mtex = NULL; } @@ -50,7 +52,9 @@ evas_gl_common_rect_draw(Evas_Engine_GL_Context *gc, int x, int y, int w, int h) ((gc->shared->info.tune.cutout.max > 0) && (gc->dc->cutout.active > gc->shared->info.tune.cutout.max))) { - evas_gl_common_context_rectangle_push(gc, x, y, w, h, cr, cg, cb, ca, mtex, mx, my, mw, mh, mask_smooth); + evas_gl_common_context_rectangle_push + (gc, x, y, w, h, cr, cg, cb, ca, + mtex, mx, my, mw, mh, mask_smooth, mask_color); } else { @@ -64,7 +68,9 @@ 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, mtex, mx, my, mw, mh, mask_smooth); + evas_gl_common_context_rectangle_push + (gc, r->x, r->y, r->w, r->h, cr, cg, cb, ca, + mtex, mx, my, mw, mh, mask_smooth, mask_color); } } evas_common_draw_context_cutouts_free(_evas_gl_common_cutout_rects); diff --git a/src/modules/evas/engines/gl_common/evas_gl_shader.c b/src/modules/evas/engines/gl_common/evas_gl_shader.c index cc22155dce..f4a8e6980c 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_shader.c +++ b/src/modules/evas/engines/gl_common/evas_gl_shader.c @@ -28,19 +28,20 @@ typedef enum { SHADER_FLAG_MASKSAM12 = (1 << (SHADER_FLAG_MASKSAM_BITSHIFT + 0)), SHADER_FLAG_MASKSAM21 = (1 << (SHADER_FLAG_MASKSAM_BITSHIFT + 1)), SHADER_FLAG_MASKSAM22 = (1 << (SHADER_FLAG_MASKSAM_BITSHIFT + 2)), - SHADER_FLAG_IMG = (1 << 9), - SHADER_FLAG_BIGENDIAN = (1 << 10), - SHADER_FLAG_YUV = (1 << 11), - SHADER_FLAG_YUY2 = (1 << 12), - SHADER_FLAG_NV12 = (1 << 13), - SHADER_FLAG_YUV_709 = (1 << 14), - SHADER_FLAG_EXTERNAL = (1 << 15), - SHADER_FLAG_AFILL = (1 << 16), - SHADER_FLAG_NOMUL = (1 << 17), - SHADER_FLAG_ALPHA = (1 << 18), - SHADER_FLAG_RGB_A_PAIR = (1 << 19), + SHADER_FLAG_MASK_COLOR = (1 << 9), + SHADER_FLAG_IMG = (1 << 10), + SHADER_FLAG_BIGENDIAN = (1 << 11), + SHADER_FLAG_YUV = (1 << 12), + SHADER_FLAG_YUY2 = (1 << 13), + SHADER_FLAG_NV12 = (1 << 14), + SHADER_FLAG_YUV_709 = (1 << 15), + SHADER_FLAG_EXTERNAL = (1 << 16), + SHADER_FLAG_AFILL = (1 << 17), + SHADER_FLAG_NOMUL = (1 << 18), + SHADER_FLAG_ALPHA = (1 << 19), + SHADER_FLAG_RGB_A_PAIR = (1 << 20), } Shader_Flag; -#define SHADER_FLAG_COUNT 20 +#define SHADER_FLAG_COUNT 21 static const char *_shader_flags[SHADER_FLAG_COUNT] = { "TEX", @@ -52,6 +53,7 @@ static const char *_shader_flags[SHADER_FLAG_COUNT] = { "MASKSAM12", "MASKSAM21", "MASKSAM22", + "MASK_COLOR", "IMG", "BIGENDIAN", "YUV", @@ -707,7 +709,7 @@ evas_gl_common_shader_flags_get(Evas_GL_Shared *shared, Shader_Type type, int sw, int sh, int w, int h, Eina_Bool smooth, Evas_GL_Texture *tex, Eina_Bool tex_only, Evas_GL_Texture *mtex, Eina_Bool mask_smooth, - int mw, int mh, + Eina_Bool mask_color, int mw, int mh, Shader_Sampling *psam, int *pnomul, Shader_Sampling *pmasksam) { Shader_Sampling sam = SHD_SAM11, masksam = SHD_SAM11; @@ -740,6 +742,12 @@ evas_gl_common_shader_flags_get(Evas_GL_Shared *shared, Shader_Type type, flags |= (1 << (SHADER_FLAG_MASKSAM_BITSHIFT + masksam - 1)); } + // mask color mode + if (mtex && mask_color) + { + flags |= SHADER_FLAG_MASK_COLOR; + } + switch (type) { case SHD_RECT: @@ -899,7 +907,7 @@ evas_gl_common_shader_program_get(Evas_Engine_GL_Context *gc, int sw, int sh, int w, int h, Eina_Bool smooth, Evas_GL_Texture *tex, Eina_Bool tex_only, Evas_GL_Texture *mtex, Eina_Bool mask_smooth, - int mw, int mh, + Eina_Bool mask_color, int mw, int mh, Shader_Sampling *psam, int *pnomul, Shader_Sampling *pmasksam) { @@ -908,7 +916,7 @@ evas_gl_common_shader_program_get(Evas_Engine_GL_Context *gc, flags = evas_gl_common_shader_flags_get(gc->shared, type, map_points, npoints, r, g, b, a, sw, sh, w, h, smooth, tex, tex_only, - mtex, mask_smooth, mw, mh, + mtex, mask_smooth, mask_color, mw, mh, psam, pnomul, pmasksam); p = eina_hash_find(gc->shared->shaders_hash, &flags); if (!p) 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 195ed19bb6..8cae1481b5 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 @@ -131,19 +131,38 @@ static const char fragment_glsl[] = " c = vec4(1, 1, 1, 1);\n" "#endif\n" "#ifdef SHD_MASK\n" + "# ifndef SHD_MASK_COLOR\n" + " // Classic mask: alpha only\n" " float ma;\n" - "# if defined(SHD_MASKSAM12) || defined(SHD_MASKSAM21)\n" + "# if defined(SHD_MASKSAM12) || defined(SHD_MASKSAM21)\n" " float ma00 = texture2D(texm, tex_m + masktex_s[0]).a;\n" " float ma01 = texture2D(texm, tex_m + masktex_s[1]).a;\n" " ma = (ma00 + ma01) / maskdiv_s;\n" - "# elif defined(SHD_MASKSAM22)\n" + "# elif defined(SHD_MASKSAM22)\n" " float ma00 = texture2D(texm, tex_m + masktex_s[0]).a;\n" " float ma01 = texture2D(texm, tex_m + masktex_s[1]).a;\n" " float ma10 = texture2D(texm, tex_m + masktex_s[2]).a;\n" " float ma11 = texture2D(texm, tex_m + masktex_s[3]).a;\n" " ma = (ma00 + ma01 + ma10 + ma11) / maskdiv_s;\n" - "# else\n" + "# else\n" " ma = texture2D(texm, tex_m).a;\n" + "# endif\n" + "# else\n" + " // Full color mask\n" + " vec4 ma;\n" + "# if defined(SHD_MASKSAM12) || defined(SHD_MASKSAM21)\n" + " vec4 ma00 = texture2D(texm, tex_m + masktex_s[0]);\n" + " vec4 ma01 = texture2D(texm, tex_m + masktex_s[1]);\n" + " ma = (ma00 + ma01) / maskdiv_s;\n" + "# elif defined(SHD_MASKSAM22)\n" + " vec4 ma00 = texture2D(texm, tex_m + masktex_s[0]);\n" + " vec4 ma01 = texture2D(texm, tex_m + masktex_s[1]);\n" + " vec4 ma10 = texture2D(texm, tex_m + masktex_s[2]);\n" + " vec4 ma11 = texture2D(texm, tex_m + masktex_s[3]);\n" + " ma = (ma00 + ma01 + ma10 + ma11) / maskdiv_s;\n" + "# else\n" + " ma = texture2D(texm, tex_m);\n" + "# endif\n" "# endif\n" "#endif\n" "#ifdef SHD_AFILL\n" diff --git a/src/modules/evas/engines/gl_common/shader/fragment.glsl b/src/modules/evas/engines/gl_common/shader/fragment.glsl index c20dc71fc7..7de74a2e80 100644 --- a/src/modules/evas/engines/gl_common/shader/fragment.glsl +++ b/src/modules/evas/engines/gl_common/shader/fragment.glsl @@ -132,19 +132,38 @@ void main() #endif #ifdef SHD_MASK +# ifndef SHD_MASK_COLOR + // Classic mask: alpha only float ma; -# if defined(SHD_MASKSAM12) || defined(SHD_MASKSAM21) +# if defined(SHD_MASKSAM12) || defined(SHD_MASKSAM21) float ma00 = texture2D(texm, tex_m + masktex_s[0]).a; float ma01 = texture2D(texm, tex_m + masktex_s[1]).a; ma = (ma00 + ma01) / maskdiv_s; -# elif defined(SHD_MASKSAM22) +# elif defined(SHD_MASKSAM22) float ma00 = texture2D(texm, tex_m + masktex_s[0]).a; float ma01 = texture2D(texm, tex_m + masktex_s[1]).a; float ma10 = texture2D(texm, tex_m + masktex_s[2]).a; float ma11 = texture2D(texm, tex_m + masktex_s[3]).a; ma = (ma00 + ma01 + ma10 + ma11) / maskdiv_s; -# else +# else ma = texture2D(texm, tex_m).a; +# endif +# else + // Full color mask + vec4 ma; +# if defined(SHD_MASKSAM12) || defined(SHD_MASKSAM21) + vec4 ma00 = texture2D(texm, tex_m + masktex_s[0]); + vec4 ma01 = texture2D(texm, tex_m + masktex_s[1]); + ma = (ma00 + ma01) / maskdiv_s; +# elif defined(SHD_MASKSAM22) + vec4 ma00 = texture2D(texm, tex_m + masktex_s[0]); + vec4 ma01 = texture2D(texm, tex_m + masktex_s[1]); + vec4 ma10 = texture2D(texm, tex_m + masktex_s[2]); + vec4 ma11 = texture2D(texm, tex_m + masktex_s[3]); + ma = (ma00 + ma01 + ma10 + ma11) / maskdiv_s; +# else + ma = texture2D(texm, tex_m); +# endif # endif #endif diff --git a/src/modules/evas/engines/gl_generic/evas_ector_gl_buffer.c b/src/modules/evas/engines/gl_generic/evas_ector_gl_buffer.c index d4657b9dd4..d948634bc6 100644 --- a/src/modules/evas/engines/gl_generic/evas_ector_gl_buffer.c +++ b/src/modules/evas/engines/gl_generic/evas_ector_gl_buffer.c @@ -143,8 +143,16 @@ _image_get(Evas_Ector_GL_Buffer_Data *pd, Eina_Bool render) if (pd->maps != NULL) fail("Image is currently mapped!"); + if (!pd->glim || !pd->glim->tex || !pd->glim->tex->pt) + fail("Image has no texture!"); + evas_gl_common_image_ref(pd->glim); - if (render) pd->was_render = EINA_TRUE; + if (render) + { + if (!pd->glim->tex->pt->fb) + fail("Image has no FBO!"); + pd->was_render = EINA_TRUE; + } return pd->glim; on_fail: @@ -174,13 +182,8 @@ _evas_ector_gl_buffer_evas_ector_buffer_engine_image_release(Eo *obj EINA_UNUSED EINA_SAFETY_ON_FALSE_RETURN_VAL(pd->glim == image, EINA_FALSE); if (pd->was_render) - { - Render_Engine_GL_Generic *re = pd->evas->engine.data.output; - Evas_Engine_GL_Context *gc; + pd->glim = evas_gl_common_image_surface_detach(pd->glim); - gc = re->window_gl_context_get(re->software.ob); - pd->glim = evas_gl_common_image_surface_detach(gc, pd->glim); - } evas_gl_common_image_free(pd->glim); return EINA_TRUE; @@ -307,14 +310,11 @@ _evas_ector_gl_buffer_ector_buffer_unmap(Eo *obj EINA_UNUSED, Evas_Ector_GL_Buff EINA_INLIST_REMOVE(pd->maps, map); if (map->mode & ECTOR_BUFFER_ACCESS_FLAG_WRITE) { - Render_Engine_GL_Generic *re = pd->evas->engine.data.output; Evas_GL_Image *old_glim = pd->glim; - Evas_Engine_GL_Context *gc; int W, H; W = pd->glim->w; H = pd->glim->h; - gc = re->window_gl_context_get(re->software.ob); if (map->cspace == EFL_GFX_COLORSPACE_GRY8) _pixels_gry8_to_argb_convert(map->image_data, map->base_data, W * H); @@ -322,13 +322,13 @@ _evas_ector_gl_buffer_ector_buffer_unmap(Eo *obj EINA_UNUSED, Evas_Ector_GL_Buff if (map->im) { MAP_DUMP(map->im, "out_w_free"); - pd->glim = evas_gl_common_image_surface_update(gc, map->im); + pd->glim = evas_gl_common_image_surface_update(map->im); evas_gl_common_image_free(old_glim); } else { MAP_DUMP(old_glim, "out_w_nofree"); - pd->glim = evas_gl_common_image_surface_update(gc, old_glim); + pd->glim = evas_gl_common_image_surface_update(old_glim); } } else diff --git a/src/modules/evas/engines/gl_generic/evas_ector_gl_image_buffer.c b/src/modules/evas/engines/gl_generic/evas_ector_gl_image_buffer.c index 6e1666cf74..3d3bb2eb66 100644 --- a/src/modules/evas/engines/gl_generic/evas_ector_gl_image_buffer.c +++ b/src/modules/evas/engines/gl_generic/evas_ector_gl_image_buffer.c @@ -54,6 +54,8 @@ struct _Evas_Ector_GL_Image_Buffer_Data #define EINA_INLIST_REMOVE(l,i) do { l = (__typeof__(l)) eina_inlist_remove(EINA_INLIST_GET(l), EINA_INLIST_GET(i)); } while (0) #define EINA_INLIST_APPEND(l,i) do { l = (__typeof__(l)) eina_inlist_append(EINA_INLIST_GET(l), EINA_INLIST_GET(i)); } while (0) +#define fail(fmt, ...) do { ERR(fmt, ##__VA_ARGS__); goto on_fail; } while (0) + /* FIXME: Conversion routines don't belong here */ static inline void _pixels_argb_to_gry8_convert(uint8_t *dst, const uint32_t *src, int len) @@ -68,24 +70,48 @@ _pixels_argb_to_gry8_convert(uint8_t *dst, const uint32_t *src, int len) EOLIAN static void _evas_ector_gl_image_buffer_evas_ector_buffer_engine_image_set(Eo *obj, Evas_Ector_GL_Image_Buffer_Data *pd, - Evas *evas, void *image) + Evas *eo_evas, void *image) { Evas_GL_Image *im = image; + Evas_Public_Data *evas; EINA_SAFETY_ON_FALSE_RETURN(!pd->glim); EINA_SAFETY_ON_NULL_RETURN(im); - pd->evas = efl_data_xref(evas, EVAS_CANVAS_CLASS, obj); + evas = efl_data_xref(eo_evas, EVAS_CANVAS_CLASS, obj); + if (!im->tex) + { + Render_Engine_GL_Generic *re = pd->evas->engine.data.output; + Evas_Engine_GL_Context *gc; + + gc = re->window_gl_context_get(re->software.ob); + evas_gl_common_image_update(gc, im); + + if (!im->tex) + fail("Image has no texture!"); + } + + pd->evas = evas; evas_gl_common_image_ref(im); pd->glim = im; + +on_fail: + efl_data_xunref(eo_evas, evas, obj); + return; } EOLIAN static void * _evas_ector_gl_image_buffer_evas_ector_buffer_drawable_image_get(Eo *obj EINA_UNUSED, Evas_Ector_GL_Image_Buffer_Data *pd) { + if (!pd->glim->tex) + fail("Image has no texture!"); + evas_gl_common_image_ref(pd->glim); return pd->glim; + +on_fail: + return NULL; } EOLIAN static Eina_Bool diff --git a/src/modules/evas/engines/gl_generic/evas_engine.c b/src/modules/evas/engines/gl_generic/evas_engine.c index 296da981a2..6c840f65d7 100644 --- a/src/modules/evas/engines/gl_generic/evas_engine.c +++ b/src/modules/evas/engines/gl_generic/evas_engine.c @@ -1284,93 +1284,20 @@ eng_image_map_clean(void *data EINA_UNUSED, RGBA_Map *m EINA_UNUSED) static void * eng_image_map_surface_new(void *data, int w, int h, int alpha) { - Evas_Engine_GL_Context *gl_context; Render_Engine_GL_Generic *re = data; + Evas_Engine_GL_Context *gl_context; re->window_use(re->software.ob); gl_context = re->window_gl_context_get(re->software.ob); return evas_gl_common_image_surface_new(gl_context, w, h, alpha, EINA_FALSE); } -static void * +void * eng_image_scaled_update(void *data EINA_UNUSED, void *scaled, void *image, - int dst_w, int dst_h, - Eina_Bool smooth, Eina_Bool alpha, + int dst_w, int dst_h, Eina_Bool smooth, Evas_Colorspace cspace EINA_UNUSED) { - Evas_GL_Image *dst = scaled, *newdst; - Evas_GL_Image *src = image; - Evas_Engine_GL_Context *gc; - Eina_Bool reffed = EINA_FALSE; - - if (!src) return NULL; - - // masking will work only with single texture images - switch (src->cs.space) - { - case EVAS_COLORSPACE_AGRY88: - case EVAS_COLORSPACE_ARGB8888: - case EVAS_COLORSPACE_GRY8: - case EVAS_COLORSPACE_RGBA8_ETC2_EAC: - case EVAS_COLORSPACE_RGBA_S3TC_DXT1: - case EVAS_COLORSPACE_RGBA_S3TC_DXT2: - case EVAS_COLORSPACE_RGBA_S3TC_DXT3: - case EVAS_COLORSPACE_RGBA_S3TC_DXT4: - case EVAS_COLORSPACE_RGBA_S3TC_DXT5: - break; - default: - DBG("cspace %d can't be used for masking's fast path", src->cs.space); - return NULL; - } - - gc = src->gc; - if (dst && (dst->scaled.origin == src) && - (dst->w == dst_w) && (dst->h == dst_h)) - return dst; - - evas_gl_common_image_update(gc, src); - if (!src->tex) - { - ERR("No source texture."); - return NULL; - } - - newdst = calloc(1, sizeof(Evas_GL_Image)); - if (!newdst) return NULL; - - if (dst) - { - if (dst->scaled.origin == src) - { - if (dst->references == 1) - { - dst->w = dst_w; - dst->h = dst_h; - dst->scaled.smooth = smooth; - free(newdst); - return dst; - } - src->references++; - reffed = EINA_TRUE; - } - evas_gl_common_image_free(dst); - } - - newdst->references = 1; - newdst->gc = gc; - newdst->cs.space = src->cs.space; - newdst->alpha = alpha; - newdst->w = dst_w; - newdst->h = dst_h; - newdst->tex = src->tex; - newdst->tex->references++; - newdst->tex_only = 1; - - if (!reffed) src->references++; - newdst->scaled.origin = src; - newdst->scaled.smooth = smooth; - - return newdst; + return evas_gl_common_image_virtual_scaled_get(scaled, image, dst_w, dst_h, smooth); } static void @@ -3107,7 +3034,7 @@ _gfx_filter_func_get(Evas_Filter_Command *cmd) //case EVAS_FILTER_MODE_CURVE: funcptr = gl_filter_curve_func_get(cmd); break; //case EVAS_FILTER_MODE_DISPLACE: funcptr = gl_filter_displace_func_get(cmd); break; //case EVAS_FILTER_MODE_FILL: funcptr = gl_filter_fill_func_get(cmd); break; - //case EVAS_FILTER_MODE_MASK: funcptr = gl_filter_mask_func_get(cmd); break; + case EVAS_FILTER_MODE_MASK: funcptr = gl_filter_mask_func_get(cmd); break; //case EVAS_FILTER_MODE_TRANSFORM: funcptr = gl_filter_transform_func_get(cmd); break; default: return NULL; } diff --git a/src/modules/evas/engines/gl_generic/filters/gl_engine_filter.h b/src/modules/evas/engines/gl_generic/filters/gl_engine_filter.h index 9cbf4f1766..6b6e45b2f1 100644 --- a/src/modules/evas/engines/gl_generic/filters/gl_engine_filter.h +++ b/src/modules/evas/engines/gl_generic/filters/gl_engine_filter.h @@ -10,13 +10,13 @@ extern int _evas_engine_GL_log_dom; typedef Eina_Bool (* GL_Filter_Apply_Func) (Render_Engine_GL_Generic *re, Evas_Filter_Command *cmd); GL_Filter_Apply_Func gl_filter_blend_func_get(Evas_Filter_Command *cmd); -//Software_Filter_Func gl_filter_blur_func_get(Evas_Filter_Command *cmd); -//Software_Filter_Func gl_filter_bump_func_get(Evas_Filter_Command *cmd); -//Software_Filter_Func gl_filter_curve_func_get(Evas_Filter_Command *cmd); -//Software_Filter_Func gl_filter_displace_func_get(Evas_Filter_Command *cmd); -//Software_Filter_Func gl_filter_fill_func_get(Evas_Filter_Command *cmd); -//Software_Filter_Func gl_filter_mask_func_get(Evas_Filter_Command *cmd); -//Software_Filter_Func gl_filter_transform_func_get(Evas_Filter_Command *cmd); +//GL_Filter_Apply_Func gl_filter_blur_func_get(Evas_Filter_Command *cmd); +//GL_Filter_Apply_Func gl_filter_bump_func_get(Evas_Filter_Command *cmd); +//GL_Filter_Apply_Func gl_filter_curve_func_get(Evas_Filter_Command *cmd); +//GL_Filter_Apply_Func gl_filter_displace_func_get(Evas_Filter_Command *cmd); +//GL_Filter_Apply_Func gl_filter_fill_func_get(Evas_Filter_Command *cmd); +GL_Filter_Apply_Func gl_filter_mask_func_get(Evas_Filter_Command *cmd); +//GL_Filter_Apply_Func gl_filter_transform_func_get(Evas_Filter_Command *cmd); #undef DBG #undef INF diff --git a/src/modules/evas/engines/gl_generic/filters/gl_filter_blend.c b/src/modules/evas/engines/gl_generic/filters/gl_filter_blend.c index d9977bf8bd..4af89f1087 100644 --- a/src/modules/evas/engines/gl_generic/filters/gl_filter_blend.c +++ b/src/modules/evas/engines/gl_generic/filters/gl_filter_blend.c @@ -164,20 +164,17 @@ _gl_filter_blend(Render_Engine_GL_Generic *re, Evas_Filter_Command *cmd) Evas_GL_Image *image, *surface; RGBA_Draw_Context *dc_save; + DEBUG_TIME_BEGIN(); + re->window_use(re->software.ob); gc = re->window_gl_context_get(re->software.ob); image = evas_ector_buffer_drawable_image_get(cmd->input->buffer); - EINA_SAFETY_ON_NULL_RETURN_VAL(image, EINA_FALSE); - EINA_SAFETY_ON_NULL_RETURN_VAL(image->tex, EINA_FALSE); surface = evas_ector_buffer_render_image_get(cmd->output->buffer); - EINA_SAFETY_ON_NULL_RETURN_VAL(surface, EINA_FALSE); - EINA_SAFETY_ON_NULL_RETURN_VAL(surface->tex, EINA_FALSE); - EINA_SAFETY_ON_NULL_RETURN_VAL(surface->tex->pt, EINA_FALSE); - EINA_SAFETY_ON_FALSE_RETURN_VAL(surface->tex->pt->fb != 0, EINA_FALSE); + evas_gl_common_context_target_surface_set(gc, surface); dc_save = gc->dc; @@ -185,6 +182,8 @@ _gl_filter_blend(Render_Engine_GL_Generic *re, Evas_Filter_Command *cmd) evas_common_draw_context_set_multiplier(gc->dc, cmd->draw.R, cmd->draw.G, cmd->draw.B, cmd->draw.A); gc->dc->render_op = _gfx_to_evas_render_op(cmd->draw.rop); + // FIXME: Maybe need to clear buffer in case of COPY mode? + DBG("blend %d @%p -> %d @%p", cmd->input->id, cmd->input->buffer, cmd->output->id, cmd->output->buffer); _mapped_blend(gc, image, cmd->draw.fillmode, 0, 0, image->w, image->h, @@ -196,6 +195,8 @@ _gl_filter_blend(Render_Engine_GL_Generic *re, Evas_Filter_Command *cmd) evas_ector_buffer_engine_image_release(cmd->input->buffer, image); evas_ector_buffer_engine_image_release(cmd->output->buffer, surface); + DEBUG_TIME_END(); + return EINA_TRUE; } diff --git a/src/modules/evas/engines/gl_generic/filters/gl_filter_mask.c b/src/modules/evas/engines/gl_generic/filters/gl_filter_mask.c new file mode 100644 index 0000000000..37f534d791 --- /dev/null +++ b/src/modules/evas/engines/gl_generic/filters/gl_filter_mask.c @@ -0,0 +1,83 @@ +#include "gl_engine_filter.h" + +static Eina_Bool +_gl_filter_mask(Render_Engine_GL_Generic *re, Evas_Filter_Command *cmd) +{ + Evas_Engine_GL_Context *gc; + Evas_GL_Image *image, *surface, *orig_mask, *use_mask = NULL; + RGBA_Draw_Context *dc_save; + int x, y, w, h, mask_w, mask_h; + + DEBUG_TIME_BEGIN(); + + w = cmd->input->w; + h = cmd->input->h; + + image = evas_ector_buffer_drawable_image_get(cmd->input->buffer); + EINA_SAFETY_ON_NULL_RETURN_VAL(image, EINA_FALSE); + + orig_mask = evas_ector_buffer_drawable_image_get(cmd->mask->buffer); + EINA_SAFETY_ON_NULL_RETURN_VAL(orig_mask, EINA_FALSE); + + surface = evas_ector_buffer_render_image_get(cmd->output->buffer); + EINA_SAFETY_ON_NULL_RETURN_VAL(surface, EINA_FALSE); + + DBG("mask %d @%p + %d %p -> %d @%p", cmd->input->id, cmd->input->buffer, + cmd->mask->id, cmd->mask->buffer, cmd->output->id, cmd->output->buffer); + + re->window_use(re->software.ob); + gc = re->window_gl_context_get(re->software.ob); + evas_gl_common_context_target_surface_set(gc, surface); + + dc_save = gc->dc; + gc->dc = evas_common_draw_context_new(); + evas_common_draw_context_set_multiplier(gc->dc, cmd->draw.R, cmd->draw.G, cmd->draw.B, cmd->draw.A); + evas_common_draw_context_clip_clip(gc->dc, 0, 0, w, h); + + mask_w = (cmd->draw.fillmode & EVAS_FILTER_FILL_MODE_STRETCH_X) ? w : cmd->mask->w; + mask_h = (cmd->draw.fillmode & EVAS_FILTER_FILL_MODE_STRETCH_Y) ? h : cmd->mask->h; + use_mask = evas_gl_common_image_virtual_scaled_get(NULL, orig_mask, mask_w, mask_h, EINA_TRUE); + + gc->dc->clip.mask = use_mask; + gc->dc->clip.mask_color = !cmd->mask->alpha_only; + + for (y = 0; y < h; y += mask_h) + for (x = 0; x < w; x += mask_w) + { + int sw, sh; + + sw = MIN(mask_w, w - x); + sh = MIN(mask_h, h - y); + gc->dc->clip.mask_x = x; + gc->dc->clip.mask_y = y; + + evas_gl_common_image_draw(gc, image, x, y, sw, sh, x, y, sw, sh, EINA_TRUE); + } + + evas_gl_common_image_free(use_mask); + evas_common_draw_context_free(gc->dc); + gc->dc = dc_save; + + evas_ector_buffer_engine_image_release(cmd->input->buffer, image); + evas_ector_buffer_engine_image_release(cmd->mask->buffer, orig_mask); + evas_ector_buffer_engine_image_release(cmd->output->buffer, surface); + + DEBUG_TIME_END(); + + return EINA_TRUE; +} + +GL_Filter_Apply_Func +gl_filter_mask_func_get(Evas_Filter_Command *cmd) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(cmd, NULL); + EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->input, NULL); + EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->mask, NULL); + EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->output, NULL); + EINA_SAFETY_ON_FALSE_RETURN_VAL((cmd->input->w > 0) && (cmd->input->h > 0), NULL); + EINA_SAFETY_ON_FALSE_RETURN_VAL((cmd->mask->w > 0) && (cmd->mask->h > 0), NULL); + EINA_SAFETY_ON_FALSE_RETURN_VAL(cmd->input->w == cmd->output->w, NULL); + EINA_SAFETY_ON_FALSE_RETURN_VAL(cmd->input->h == cmd->output->h, NULL); + + return _gl_filter_mask; +}