Evas filters: Reduce padding to the minimum acceptable
authorJean-Philippe Andre <jp.andre@samsung.com>
Fri, 13 Dec 2013 07:21:59 +0000 (16:21 +0900)
committerJean-Philippe Andre <jp.andre@samsung.com>
Fri, 7 Feb 2014 08:33:16 +0000 (17:33 +0900)
Padding was brutally calculated by suming ALL the filters'
individual paddings. Now we try to be a bit smarter and propagate
the padding between buffers in the filter chain.

src/lib/evas/filters/evas_filter_parser.c

index 57e99b0..9417540 100644 (file)
@@ -50,6 +50,9 @@ typedef struct _Buffer
    Eina_Stringshare *name;
    Eina_Stringshare *proxy;
    int cid; // Transient value
+   struct {
+      int l, r, t, b; // Used for padding calculation. Can change over time.
+   } pad;
    Eina_Bool alpha : 1;
 } Buffer;
 
@@ -71,8 +74,7 @@ struct _Evas_Filter_Instruction
    Eina_Inlist /* Instruction_Param */ *params;
    struct
    {
-      void (* update) (Evas_Filter_Instruction *, int *, int *, int *, int *);
-      int l, r, t, b;
+      void (* update) (Evas_Filter_Program *, Evas_Filter_Instruction *, int *, int *, int *, int *);
    } pad;
    Eina_Bool valid : 1;
 };
@@ -705,23 +707,35 @@ _blend_instruction_prepare(Evas_Filter_Instruction *instr)
 }
 
 static void
-_blur_padding_update(Evas_Filter_Instruction *instr,
-                     int *l, int *r, int *t, int *b)
+_blur_padding_update(Evas_Filter_Program *pgm, Evas_Filter_Instruction *instr,
+                     int *padl, int *padr, int *padt, int *padb)
 {
    Eina_Bool yset;
-   int rx = 0, ry = 0;
-   const char *typestr;
+   int rx, ry, l, r, t, b;
+   const char *typestr, *inbuf, *outbuf;
+   Buffer *in, *out;
 
+   // TODO/FIXME: Add ox, oy support
    rx = _instruction_param_geti(instr, "rx", NULL);
    ry = _instruction_param_geti(instr, "ry", &yset);
    typestr = _instruction_param_gets(instr, "type", NULL);
+   inbuf = _instruction_param_gets(instr, "src", NULL);
+   outbuf = _instruction_param_gets(instr, "dst", NULL);
+
+   in = _buffer_get(pgm, inbuf);
+   out = _buffer_get(pgm, outbuf);
+   EINA_SAFETY_ON_NULL_RETURN(in);
+   EINA_SAFETY_ON_NULL_RETURN(out);
 
    if (typestr && !strcasecmp(typestr, "motion"))
      {
+        CRIT("Motion blur not implemented yet!");
+        /*
         instr->pad.l = (rx < 0) ? (-rx) : 0;
         instr->pad.r = (rx > 0) ? (rx) : 0;
         instr->pad.t = (ry < 0) ? (-ry) : 0;
         instr->pad.b = (ry > 0) ? (ry) : 0;
+        */
      }
    else
      {
@@ -729,15 +743,20 @@ _blur_padding_update(Evas_Filter_Instruction *instr,
         if (rx < 0) rx = 0;
         if (ry < 0) ry = 0;
 
-        instr->pad.l = rx;
-        instr->pad.r = rx;
-        instr->pad.t = ry;
-        instr->pad.b = ry;
+        l = rx + in->pad.l;
+        r = rx + in->pad.r;
+        t = ry + in->pad.t;
+        b = ry + in->pad.b;
+
+        if (out->pad.l < l) out->pad.l = l;
+        if (out->pad.r < r) out->pad.r = r;
+        if (out->pad.t < t) out->pad.t = t;
+        if (out->pad.b < b) out->pad.b = b;
 
-        if (l) *l += rx;
-        if (r) *r += rx;
-        if (t) *t += ry;
-        if (b) *b += ry;
+        if (padl) *padl = rx;
+        if (padr) *padr = rx;
+        if (padt) *padt = ry;
+        if (padb) *padb = ry;
      }
 }
 
@@ -815,21 +834,38 @@ _curve_instruction_prepare(Evas_Filter_Instruction *instr)
 }
 
 static void
-_displace_padding_update(Evas_Filter_Instruction *instr,
-                         int *l, int *r, int *t, int *b)
+_displace_padding_update(Evas_Filter_Program *pgm,
+                         Evas_Filter_Instruction *instr,
+                         int *padl, int *padr, int *padt, int *padb)
 {
    int intensity = 0;
+   int l, r, t, b;
+   const char *inbuf, *outbuf;
+   Buffer *in, *out;
 
    intensity = _instruction_param_geti(instr, "intensity", NULL);
-   instr->pad.l = intensity;
-   instr->pad.r = intensity;
-   instr->pad.t = intensity;
-   instr->pad.b = intensity;
-
-   if (l) *l += intensity;
-   if (r) *r += intensity;
-   if (t) *t += intensity;
-   if (b) *b += intensity;
+   inbuf = _instruction_param_gets(instr, "src", NULL);
+   outbuf = _instruction_param_gets(instr, "dst", NULL);
+
+   in = _buffer_get(pgm, inbuf);
+   out = _buffer_get(pgm, outbuf);
+   EINA_SAFETY_ON_NULL_RETURN(in);
+   EINA_SAFETY_ON_NULL_RETURN(out);
+
+   l = intensity + in->pad.l;
+   r = intensity + in->pad.r;
+   t = intensity + in->pad.t;
+   b = intensity + in->pad.b;
+
+   if (out->pad.l < l) out->pad.l = l;
+   if (out->pad.r < r) out->pad.r = r;
+   if (out->pad.t < t) out->pad.t = t;
+   if (out->pad.b < b) out->pad.b = b;
+
+   if (padl) *padl = l;
+   if (padr) *padr = r;
+   if (padt) *padt = t;
+   if (padb) *padb = b;
 }
 
 static Eina_Bool
@@ -880,23 +916,39 @@ _fill_instruction_prepare(Evas_Filter_Instruction *instr)
 }
 
 static void
-_grow_padding_update(Evas_Filter_Instruction *instr,
-                     int *l, int *r, int *t, int *b)
+_grow_padding_update(Evas_Filter_Program *pgm, Evas_Filter_Instruction *instr,
+                     int *padl, int *padr, int *padt, int *padb)
 {
-   int radius = 0;
+   const char *inbuf, *outbuf;
+   Buffer *in, *out;
+   int l, r, t, b;
+   int radius;
 
    radius = _instruction_param_geti(instr, "radius", NULL);
+   inbuf = _instruction_param_gets(instr, "src", NULL);
+   outbuf = _instruction_param_gets(instr, "dst", NULL);
+
+   in = _buffer_get(pgm, inbuf);
+   out = _buffer_get(pgm, outbuf);
+   EINA_SAFETY_ON_NULL_RETURN(in);
+   EINA_SAFETY_ON_NULL_RETURN(out);
+
    if (radius < 0) radius = 0;
 
-   instr->pad.l = radius;
-   instr->pad.r = radius;
-   instr->pad.t = radius;
-   instr->pad.b = radius;
+   l = radius + in->pad.l;
+   r = radius + in->pad.r;
+   t = radius + in->pad.t;
+   b = radius + in->pad.b;
+
+   if (padl) *padl = l;
+   if (padr) *padr = r;
+   if (padt) *padt = t;
+   if (padb) *padb = b;
 
-   if (l) *l += radius;
-   if (r) *r += radius;
-   if (t) *t += radius;
-   if (b) *b += radius;
+   if (out->pad.l < l) out->pad.l = l;
+   if (out->pad.r < r) out->pad.r = r;
+   if (out->pad.t < t) out->pad.t = t;
+   if (out->pad.b < b) out->pad.b = b;
 }
 
 static Eina_Bool
@@ -1142,17 +1194,30 @@ evas_filter_program_padding_get(Evas_Filter_Program *pgm,
 {
    Evas_Filter_Instruction *instr;
    int pl = 0, pr = 0, pt = 0, pb = 0;
+   int maxl = 0, maxr = 0, maxt = 0, maxb = 0;
+   Buffer *buf;
 
    EINA_SAFETY_ON_NULL_RETURN_VAL(pgm, EINA_FALSE);
 
+   // Reset all paddings
+   EINA_INLIST_FOREACH(pgm->buffers, buf)
+     buf->pad.l = buf->pad.r = buf->pad.t = buf->pad.b = 0;
+
+   // Accumulate paddings
    EINA_INLIST_FOREACH(pgm->instructions, instr)
      if (instr->pad.update)
-       instr->pad.update(instr, &pl, &pr, &pt, &pb);
+       {
+          instr->pad.update(pgm, instr, &pl, &pr, &pt, &pb);
+          if (pl > maxl) maxl = pl;
+          if (pr > maxr) maxr = pr;
+          if (pt > maxt) maxt = pt;
+          if (pb > maxb) maxb = pb;
+       }
 
-   if (l) *l = pl;
-   if (r) *r = pr;
-   if (t) *t = pt;
-   if (b) *b = pb;
+   if (l) *l = maxl;
+   if (r) *r = maxr;
+   if (t) *t = maxt;
+   if (b) *b = maxb;
 
    return EINA_TRUE;
 }