jpeg pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=45548e8358b0affcaa9738ad1b5ae5b542c9349b

commit 45548e8358b0affcaa9738ad1b5ae5b542c9349b
Author: Jean-Philippe Andre <jp.an...@samsung.com>
Date:   Fri Mar 31 13:10:41 2017 +0900

    evas filters: Implement obscure support for gl blur
    
    This can help with performance when a large region of the
    filtered image (eg. snapshot) is fully hidden by an opaque
    object. For instance the window border is hidden by the
    opaque window content.
---
 .../evas/engines/gl_common/evas_gl_context.c       | 100 +++++++++--------
 .../engines/gl_generic/filters/gl_filter_blur.c    | 120 +++++++++++++++++----
 2 files changed, 159 insertions(+), 61 deletions(-)

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 d19eb69..b61cc6a 100644
--- a/src/modules/evas/engines/gl_common/evas_gl_context.c
+++ b/src/modules/evas/engines/gl_common/evas_gl_context.c
@@ -3139,13 +3139,17 @@ _filter_data_flush(Evas_Engine_GL_Context *gc, 
Evas_GL_Program *prog)
 }
 
 static inline void
-_filter_data_prepare(Evas_Engine_GL_Context *gc, int pn,
-                     Evas_GL_Program *prog, int count)
+_filter_data_alloc(Evas_Engine_GL_Context *gc, int pn, int count)
 {
    gc->pipe[pn].array.filter_data_count = count;
    if (count) gc->pipe[pn].array.filter_data = malloc(count * 2 * 
sizeof(GLfloat));
    else gc->pipe[pn].array.filter_data = NULL;
+}
 
+static inline void
+_filter_data_prepare(Evas_Engine_GL_Context *gc EINA_UNUSED,
+                     Evas_GL_Program *prog, int count)
+{
    if (!prog->filter) prog->filter = calloc(1, sizeof(*prog->filter));
    if (!prog->filter->attribute.known_locations)
      {
@@ -3224,7 +3228,8 @@ 
evas_gl_common_filter_displace_push(Evas_Engine_GL_Context *gc,
    // displace properties
    gc->pipe[pn].shader.filter.map_tex = map_tex->pt->texture;
    gc->pipe[pn].shader.filter.map_nearest = nearest;
-   _filter_data_prepare(gc, pn, prog, 3);
+   _filter_data_prepare(gc, prog, 3);
+   _filter_data_alloc(gc, pn, 3);
 
    sx = x;
    sy = y;
@@ -3439,7 +3444,7 @@ evas_gl_common_filter_blur_push(Evas_Engine_GL_Context 
*gc,
                                 const double * const offsets, int count,
                                 double radius, Eina_Bool horiz)
 {
-   double ox1, oy1, ox2, oy2, ox3, oy3, ox4, oy4, pw, ph;
+   double ox1, oy1, ox2, oy2, ox3, oy3, ox4, oy4, pw, ph, texlen;
    GLfloat tx1, ty1, tx2, ty2, tx3, ty3, tx4, ty4;
    GLfloat offsetx, offsety;
    int r, g, b, a, nomul = 0, pn;
@@ -3447,11 +3452,10 @@ evas_gl_common_filter_blur_push(Evas_Engine_GL_Context 
*gc,
    Eina_Bool blend = EINA_TRUE;
    Eina_Bool smooth = EINA_TRUE;
    Shader_Type type = horiz ? SHD_FILTER_BLUR_X : SHD_FILTER_BLUR_Y;
+   Eina_Bool update_uniforms = EINA_FALSE;
    GLuint *map_tex_data;
    double sum;
 
-   //shader_array_flush(gc);
-
    r = R_VAL(&gc->dc->mul.col);
    g = G_VAL(&gc->dc->mul.col);
    b = B_VAL(&gc->dc->mul.col);
@@ -3463,39 +3467,13 @@ evas_gl_common_filter_blur_push(Evas_Engine_GL_Context 
*gc,
                                             sw, sh, dw, dh, smooth, tex, 
EINA_FALSE,
                                             NULL, EINA_FALSE, EINA_FALSE, 0, 0,
                                             NULL, &nomul, NULL);
+
    _filter_data_flush(gc, prog);
    EINA_SAFETY_ON_NULL_RETURN(prog);
 
-   pn = _evas_gl_common_context_push(type, gc, tex, NULL, prog,
-                                     sx, sy, dw, dh, blend, smooth,
-                                     0, 0, 0, 0, 0, EINA_FALSE);
-
-   gc->pipe[pn].region.type = type;
-   gc->pipe[pn].shader.prog = prog;
-   gc->pipe[pn].shader.cur_tex = tex->pt->texture;
-   gc->pipe[pn].shader.cur_texm = 0;
-   gc->pipe[pn].shader.tex_target = GL_TEXTURE_2D;
-   gc->pipe[pn].shader.smooth = smooth;
-   gc->pipe[pn].shader.mask_smooth = 0;
-   gc->pipe[pn].shader.blend = blend;
-   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 = !nomul;
-   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_texsam = 0;
-   gc->pipe[pn].array.use_mask = 0;
-   gc->pipe[pn].array.use_masksam = 0;
-
-   pipe_region_expand(gc, pn, dx, dy, dw, dh);
-   PIPE_GROW(gc, pn, 6);
+   pw = tex->pt->w;
+   ph = tex->pt->h;
+   texlen = horiz ? pw : ph;
 
    /* Convert double data to RGBA pixel data.
     *
@@ -3525,7 +3503,7 @@ evas_gl_common_filter_blur_push(Evas_Engine_GL_Context 
*gc,
      }
 
    // Prepare attributes & uniforms
-   _filter_data_prepare(gc, pn, prog, 0);
+   _filter_data_prepare(gc, prog, 0);
    if (!prog->filter->uniform.known_locations)
      {
         prog->filter->uniform.known_locations = EINA_TRUE;
@@ -3534,6 +3512,47 @@ evas_gl_common_filter_blur_push(Evas_Engine_GL_Context 
*gc,
         prog->filter->uniform.blur_div_loc = glGetUniformLocation(prog->prog, 
"blur_div");
      }
 
+   if ((prog->filter->uniform.blur_count_value != count - 1) ||
+       (!EINA_FLT_EQ(prog->filter->uniform.blur_texlen_value, texlen)) ||
+       (!EINA_FLT_EQ(prog->filter->uniform.blur_div_value, sum)))
+     {
+        update_uniforms = EINA_TRUE;
+        shader_array_flush(gc);
+     }
+
+   pn = _evas_gl_common_context_push(type, gc, tex, NULL, prog,
+                                     sx, sy, dw, dh, blend, smooth,
+                                     0, 0, 0, 0, 0, EINA_FALSE);
+
+   gc->pipe[pn].region.type = type;
+   gc->pipe[pn].shader.prog = prog;
+   gc->pipe[pn].shader.cur_tex = tex->pt->texture;
+   gc->pipe[pn].shader.cur_texm = 0;
+   gc->pipe[pn].shader.tex_target = GL_TEXTURE_2D;
+   gc->pipe[pn].shader.smooth = smooth;
+   gc->pipe[pn].shader.mask_smooth = 0;
+   gc->pipe[pn].shader.blend = blend;
+   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 = !nomul;
+   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_texsam = 0;
+   gc->pipe[pn].array.use_mask = 0;
+   gc->pipe[pn].array.use_masksam = 0;
+
+   pipe_region_expand(gc, pn, dx, dy, dw, dh);
+   PIPE_GROW(gc, pn, 6);
+
+   _filter_data_alloc(gc, pn, 0);
+
    // Synchronous upload of Nx2 RGBA texture
    if (!EINA_DBL_EQ(prog->filter->blur_radius, radius))
      {
@@ -3553,10 +3572,10 @@ evas_gl_common_filter_blur_push(Evas_Engine_GL_Context 
*gc,
         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, count, 2, 0, GL_RGBA, 
GL_UNSIGNED_BYTE, map_tex_data);
      }
 
-   //if (update_uniforms)
+   if (update_uniforms)
      {
         prog->filter->uniform.blur_count_value = count - 1;
-        prog->filter->uniform.blur_texlen_value = horiz ? sw : sh;
+        prog->filter->uniform.blur_texlen_value = texlen;
         prog->filter->uniform.blur_div_value = sum;
         glUseProgram(prog->prog);
         glUniform1i(prog->filter->uniform.blur_count_loc, 
prog->filter->uniform.blur_count_value);
@@ -3569,9 +3588,6 @@ evas_gl_common_filter_blur_push(Evas_Engine_GL_Context 
*gc,
    gc->pipe[pn].shader.filter.map_nearest = EINA_TRUE;
    gc->pipe[pn].shader.filter.map_delete = EINA_FALSE;
 
-   pw = tex->pt->w;
-   ph = tex->pt->h;
-
    ox1 = sx;
    oy1 = sy;
    ox2 = sx + sw;
diff --git a/src/modules/evas/engines/gl_generic/filters/gl_filter_blur.c 
b/src/modules/evas/engines/gl_generic/filters/gl_filter_blur.c
index a1fc0ed..8c78f8c 100644
--- a/src/modules/evas/engines/gl_generic/filters/gl_filter_blur.c
+++ b/src/modules/evas/engines/gl_generic/filters/gl_filter_blur.c
@@ -81,6 +81,36 @@ _gaussian_interpolate(double **weights, double **offsets, 
double radius)
    return count;
 }
 
+static inline Eina_Rectangle
+_rect(int x, int y, int w, int h, int maxw, int maxh)
+{
+   Eina_Rectangle rect;
+
+   if (x < 0)
+     {
+        w -= (-x);
+        x = 0;
+     }
+   if (y < 0)
+     {
+        h -= (-y);
+        y = 0;
+     }
+   if ((x + w) > maxw) w = maxw - x;
+   if ((y + h) > maxh) h = maxh - y;
+   if (w < 0) w = 0;
+   if (h < 0) h = 0;
+
+   rect.x = x;
+   rect.y = y;
+   rect.w = w;
+   rect.h = h;
+   return rect;
+}
+
+#define S_RECT(_x, _y, _w, _h) _rect(_x, _y, _w, _h, s_w, s_h)
+#define D_RECT(_x, _y, _w, _h) _rect(_x, _y, _w, _h, d_w, d_h)
+
 static Eina_Bool
 _gl_filter_blur(Render_Engine_GL_Generic *re, Evas_Filter_Command *cmd)
 {
@@ -89,11 +119,19 @@ _gl_filter_blur(Render_Engine_GL_Generic *re, 
Evas_Filter_Command *cmd)
    RGBA_Draw_Context *dc_save;
    Eina_Bool horiz;
    double sx, sy, sw, sh, ssx, ssy, ssw, ssh, dx, dy, dw, dh, radius;
-   int nx, ny, nw, nh, count = 0;
+   double s_w, s_h, d_w, d_h;
+   Eina_Rectangle s_ob, d_ob, s_region[4], d_region[4];
+   int nx, ny, nw, nh, regions, count = 0;
    double *weights, *offsets;
 
    DEBUG_TIME_BEGIN();
 
+   s_w = cmd->input->w;
+   s_h = cmd->input->h;
+   d_w = cmd->output->w;
+   d_h = cmd->output->h;
+   EINA_SAFETY_ON_FALSE_RETURN_VAL(s_w && s_h && d_w && d_h, EINA_FALSE);
+
    re->window_use(re->software.ob);
    gc = re->window_gl_context_get(re->software.ob);
 
@@ -121,22 +159,6 @@ _gl_filter_blur(Render_Engine_GL_Generic *re, 
Evas_Filter_Command *cmd)
        cmd->output->id, cmd->output->buffer,
        radius, horiz ? "X" : "Y");
 
-   sx = 0;
-   sy = 0;
-   sw = cmd->input->w;
-   sh = cmd->input->h;
-   dx = cmd->draw.ox;
-   dy = cmd->draw.oy;
-   dw = cmd->output->w;
-   dh = cmd->output->h;
-
-   nx = dx; ny = dy; nw = dw; nh = dh;
-   RECTS_CLIP_TO_RECT(nx, ny, nw, nh, 0, 0, cmd->output->w, cmd->output->h);
-   ssx = (double)sx + ((double)(sw * (nx - dx)) / (double)(dw));
-   ssy = (double)sy + ((double)(sh * (ny - dy)) / (double)(dh));
-   ssw = ((double)sw * (double)(nw)) / (double)(dw);
-   ssh = ((double)sh * (double)(nh)) / (double)(dh);
-
    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);
@@ -148,8 +170,68 @@ _gl_filter_blur(Render_Engine_GL_Generic *re, 
Evas_Filter_Command *cmd)
      gc->dc->render_op = _gfx_to_evas_render_op(cmd->draw.rop);
 
    count = _gaussian_interpolate(&weights, &offsets, radius);
-   evas_gl_common_filter_blur_push(gc, image->tex, ssx, ssy, ssw, ssh, dx, dy, 
dw, dh,
-                                   weights, offsets, count, radius, horiz);
+
+   d_ob = cmd->ctx->obscured.effective;
+   s_ob.x = d_ob.x * s_w / d_w;
+   s_ob.y = d_ob.y * s_h / d_h;
+   s_ob.w = d_ob.w * s_w / d_w;
+   s_ob.h = d_ob.h * s_h / d_h;
+   if (!d_ob.w || !d_ob.h)
+     {
+        s_region[0] = S_RECT(0, 0, s_w, s_h);
+        d_region[0] = D_RECT(0, 0, d_w, d_h);
+        regions = 1;
+     }
+   else if (horiz)
+     {
+        // top (full), left, right, bottom (full)
+        s_region[0] = S_RECT(0, 0, s_w, s_ob.y);
+        d_region[0] = D_RECT(0, 0, d_w, d_ob.y);
+        s_region[1] = S_RECT(0, s_ob.y, s_ob.x, s_ob.h);
+        d_region[1] = D_RECT(0, d_ob.y, d_ob.x, d_ob.h);
+        s_region[2] = S_RECT(s_ob.x + s_ob.w, s_ob.y, s_w - s_ob.x - s_ob.w, 
s_ob.h);
+        d_region[2] = D_RECT(d_ob.x + d_ob.w, d_ob.y, d_w - d_ob.x - d_ob.w, 
d_ob.h);
+        s_region[3] = S_RECT(0, s_ob.y + s_ob.h, s_w, s_h - s_ob.y - s_ob.h);
+        d_region[3] = D_RECT(0, d_ob.y + d_ob.h, d_w, d_h - d_ob.y - d_ob.h);
+        regions = 4;
+     }
+   else
+     {
+        // left (full), top, bottom, right (full)
+        s_region[0] = S_RECT(0, 0, s_ob.x, s_h);
+        d_region[0] = D_RECT(0, 0, d_ob.x, d_h);
+        s_region[1] = S_RECT(s_ob.x, 0, s_ob.w, s_ob.y);
+        d_region[1] = D_RECT(d_ob.x, 0, d_ob.w, d_ob.y);
+        s_region[2] = S_RECT(s_ob.x, s_ob.y + s_ob.h, s_ob.w, s_h - s_ob.y - 
s_ob.h);
+        d_region[2] = D_RECT(d_ob.x, d_ob.y + d_ob.h, d_ob.w, d_h - d_ob.y - 
d_ob.h);
+        s_region[3] = S_RECT(s_ob.x + s_ob.w, 0, s_w - s_ob.x - s_ob.w, s_h);
+        d_region[3] = D_RECT(d_ob.x + d_ob.w, 0, d_w - d_ob.x - d_ob.w, d_h);
+        regions = 4;
+     }
+
+   for (int k = 0; k < regions; k++)
+     {
+        sx = s_region[k].x;
+        sy = s_region[k].y;
+        sw = s_region[k].w;
+        sh = s_region[k].h;
+
+        dx = d_region[k].x + cmd->draw.ox;
+        dy = d_region[k].y + cmd->draw.oy;
+        dw = d_region[k].w;
+        dh = d_region[k].h;
+
+        nx = dx; ny = dy; nw = dw; nh = dh;
+        RECTS_CLIP_TO_RECT(nx, ny, nw, nh, 0, 0, d_w, d_h);
+        ssx = (double)sx + ((double)(sw * (nx - dx)) / (double)(dw));
+        ssy = (double)sy + ((double)(sh * (ny - dy)) / (double)(dh));
+        ssw = ((double)sw * (double)(nw)) / (double)(dw);
+        ssh = ((double)sh * (double)(nh)) / (double)(dh);
+
+        evas_gl_common_filter_blur_push(gc, image->tex, ssx, ssy, ssw, ssh, 
dx, dy, dw, dh,
+                                        weights, offsets, count, radius, 
horiz);
+     }
+
    free(weights);
    free(offsets);
 

-- 


Reply via email to