ector_software_rasterizer: Implement mask blending function.
authorJunsuChoi <jsuya.choi@samsung.com>
Thu, 11 Apr 2019 10:12:40 +0000 (19:12 +0900)
committerShinwoo Kim <cinoo.kim@samsung.com>
Wed, 17 Apr 2019 01:09:36 +0000 (10:09 +0900)
Summary:
Add Mask blend function(Add, Substract, Intersect, Difference)
this blending function only use mask blending case.

Test Plan: N/A

Reviewers: Hermet

Reviewed By: Hermet

Subscribers: cedric, kimcinoo, #reviewers, smohanty, #committers

Tags: #efl

Differential Revision: https://phab.enlightenment.org/D8509

src/lib/ector/software/ector_software_rasterizer.c

index d9b33512485d5d7324b84d6b18f0c850bfa702d5..b2b5779f69c5721f528432ab15e2600fcc695ccd 100644 (file)
 
 #include "draw.h"
 
+//FIXME: This enum add temporarily to help understanding of additional code
+//related to masking in prepare_mask.
+//This needs to be formally declared through the eo class.
+typedef enum _EFL_CANVAS_VG_NODE_BLEND_TYPE
+{
+   EFL_CANVAS_VG_NODE_BLEND_TYPE_NONE = 0,
+   EFL_CANVAS_VG_NODE_BLEND_TYPE_ALPHA,
+   EFL_CANVAS_VG_NODE_BLEND_TYPE_ALPHA_INV,
+   EFL_CANVAS_VG_NODE_BLEND_TYPE_MASK_ADD,
+   EFL_CANVAS_VG_NODE_BLEND_TYPE_MASK_SUBSTRACT,
+   EFL_CANVAS_VG_NODE_BLEND_TYPE_MASK_INTERSECT,
+   EFL_CANVAS_VG_NODE_BLEND_TYPE_MASK_DIFFERENCE
+}EFL_CANVAS_VG_NODE_BLEND_TYPE;
+//
+
 static void
-_blend_color_argb(int count, const SW_FT_Span *spans, void *user_data)
+_blend_argb(int count, const SW_FT_Span *spans, void *user_data)
 {
    Span_Data *sd = user_data;
    uint32_t color, *buffer, *target;
@@ -34,7 +49,7 @@ _blend_color_argb(int count, const SW_FT_Span *spans, void *user_data)
 }
 
 static void
-_blend_color_argb_with_maskA(int count, const SW_FT_Span *spans, void *user_data)
+_blend_alpha(int count, const SW_FT_Span *spans, void *user_data)
 {
    Span_Data *sd = user_data;
    const int pix_stride = sd->raster_buffer->stride / 4;
@@ -77,7 +92,7 @@ _blend_color_argb_with_maskA(int count, const SW_FT_Span *spans, void *user_data
 }
 
 static void
-_blend_color_argb_with_maskInvA(int count, const SW_FT_Span *spans, void *user_data)
+_blend_alpha_inv(int count, const SW_FT_Span *spans, void *user_data)
 {
    Span_Data *sd = user_data;
    const int pix_stride = sd->raster_buffer->stride / 4;
@@ -120,6 +135,122 @@ _blend_color_argb_with_maskInvA(int count, const SW_FT_Span *spans, void *user_d
      }
 }
 
+static void
+_blend_mask_add(int count, const SW_FT_Span *spans, void *user_data)
+{
+   Span_Data *sd = user_data;
+   Ector_Software_Buffer_Base_Data *mask = sd->mask;
+
+   uint32_t color = DRAW_MUL4_SYM(sd->color, sd->mul_col);
+   RGBA_Comp_Func_Solid comp_func = efl_draw_func_solid_span_get(sd->op, color);
+   uint32_t *mbuffer = mask->pixels.u32;
+
+   while (count--)
+     {
+        uint32_t *ttarget = alloca(sizeof(uint32_t) * spans->len);
+        memset(ttarget, 0x00, sizeof(uint32_t) * spans->len);
+        uint32_t *mtarget = mbuffer + ((mask->generic->w * spans->y) + spans->x);
+        comp_func(ttarget, spans->len, color, spans->coverage);
+        for (int i = 0; i < spans->len; i++)
+          {
+             double adst = A_VAL(&mtarget[i]) == 0 ? 0 : (double)(A_VAL(&mtarget[i])) / (double)255;
+             double asrc = A_VAL(&ttarget[i]) == 0 ? 0 : (double)(A_VAL(&ttarget[i])) / (double)255;
+             uint32_t aout = (int)(((adst * (1 - asrc)) + asrc) * 255);
+             mtarget[i] = (aout<<24) + (0x00FFFFFF & mtarget[i]);
+          }
+        ++spans;
+     }
+}
+
+static void
+_blend_mask_sub(int count, const SW_FT_Span *spans, void *user_data)
+{
+   Span_Data *sd = user_data;
+   Ector_Software_Buffer_Base_Data *mask = sd->mask;
+
+   uint32_t color = DRAW_MUL4_SYM(sd->color, sd->mul_col);
+   RGBA_Comp_Func_Solid comp_func = efl_draw_func_solid_span_get(sd->op, color);
+   uint32_t *mtarget = mask->pixels.u32;
+
+   int tsize = sd->raster_buffer->generic->w * sd->raster_buffer->generic->h;
+   uint32_t *tbuffer = alloca(sizeof(uint32_t) * tsize);
+   memset(tbuffer, 0x00, sizeof(uint32_t) * tsize);
+
+   while (count--)
+     {
+        uint32_t *ttarget = tbuffer + ((mask->generic->w  * spans->y) + spans->x);
+        comp_func(ttarget, spans->len, color, spans->coverage);
+        ++spans;
+     }
+
+   for(int i = 0; i < tsize; i++)
+     {
+        double adst = A_VAL(&mtarget[i]) == 0 ? 0 : (double)(A_VAL(&mtarget[i])) / (double)255;
+        double asrc = A_VAL(&tbuffer[i]) == 0 ? 0 : (double)(A_VAL(&tbuffer[i])) / (double)255;
+        uint32_t aout = (int)((adst * (1 - asrc)) * 255);
+        mtarget[i] = (aout<<24) + (0x00FFFFFF & mtarget[i]);
+     }
+}
+
+
+static void
+_blend_mask_ins(int count, const SW_FT_Span *spans, void *user_data)
+{
+   Span_Data *sd = user_data;
+   Ector_Software_Buffer_Base_Data *mask = sd->mask;
+
+   uint32_t color = DRAW_MUL4_SYM(sd->color, sd->mul_col);
+   RGBA_Comp_Func_Solid comp_func = efl_draw_func_solid_span_get(sd->op, color);
+   uint32_t *mtarget = mask->pixels.u32;
+
+   int tsize = sd->raster_buffer->generic->w * sd->raster_buffer->generic->h;
+   uint32_t *tbuffer = alloca(sizeof(uint32_t) * tsize);
+   memset(tbuffer, 0x00, sizeof(uint32_t) * tsize);
+
+   while (count--)
+     {
+        uint32_t *ttarget = tbuffer + ((mask->generic->w  * spans->y) + spans->x);
+        comp_func(ttarget, spans->len, color, spans->coverage);
+        ++spans;
+     }
+
+   for(int i = 0; i < tsize; i++)
+     {
+        double adst = A_VAL(&mtarget[i]) == 0 ? 0 : (double)(A_VAL(&mtarget[i])) / (double)255;
+        double asrc = A_VAL(&tbuffer[i]) == 0 ? 0 : (double)(A_VAL(&tbuffer[i])) / (double)255;
+        uint32_t aout = (int)((adst * asrc) * 255);
+        mtarget[i] = (aout<<24) + (0x00FFFFFF & mtarget[i]);
+     }
+}
+
+
+static void
+_blend_mask_diff(int count, const SW_FT_Span *spans, void *user_data)
+{
+   Span_Data *sd = user_data;
+   Ector_Software_Buffer_Base_Data *mask = sd->mask;
+
+   uint32_t color = DRAW_MUL4_SYM(sd->color, sd->mul_col);
+   RGBA_Comp_Func_Solid comp_func = efl_draw_func_solid_span_get(sd->op, color);
+   uint32_t *mbuffer = mask->pixels.u32;
+
+   while (count--)
+     {
+        uint32_t *ttarget = alloca(sizeof(uint32_t) * spans->len);
+        memset(ttarget, 0x00, sizeof(uint32_t) * spans->len);
+        uint32_t *mtarget = mbuffer + ((mask->generic->w * spans->y) + spans->x);
+        comp_func(ttarget, spans->len, color, spans->coverage);
+        for (int i = 0; i < spans->len; i++)
+          {
+             double adst = A_VAL(&mtarget[i]) == 0 ? 0 : (double)(A_VAL(&mtarget[i])) / (double)255;
+             double asrc = A_VAL(&ttarget[i]) == 0 ? 0 : (double)(A_VAL(&ttarget[i])) / (double)255;
+             uint32_t aout = (int)((((1 - adst) * asrc) + ((1 - asrc) * adst)) * 255);
+             mtarget[i] = (aout<<24) + (0x00FFFFFF & mtarget[i]);
+          }
+        ++spans;
+     }
+}
+
 #define BLEND_GRADIENT_BUFFER_SIZE 2048
 
 typedef void (*src_fetch) (unsigned int *buffer, Span_Data *data, int y, int x, int length);
@@ -362,14 +493,32 @@ _adjust_span_fill_methods(Span_Data *spdata)
         case Solid:
           {
              if (spdata->mask)
-                {
-                   if (spdata->mask_op == 2)
-                     spdata->unclipped_blend = &_blend_color_argb_with_maskInvA;
-                   else
-                     spdata->unclipped_blend = &_blend_color_argb_with_maskA;
-                }
+               {
+                  switch (spdata->mask_op)
+                    {
+                     default:
+                     case EFL_CANVAS_VG_NODE_BLEND_TYPE_ALPHA:
+                        spdata->unclipped_blend = &_blend_alpha;
+                        break;
+                     case EFL_CANVAS_VG_NODE_BLEND_TYPE_ALPHA_INV:
+                        spdata->unclipped_blend = &_blend_alpha_inv;
+                        break;
+                     case EFL_CANVAS_VG_NODE_BLEND_TYPE_MASK_ADD:
+                        spdata->unclipped_blend = &_blend_mask_add;
+                        break;
+                     case EFL_CANVAS_VG_NODE_BLEND_TYPE_MASK_SUBSTRACT:
+                        spdata->unclipped_blend = &_blend_mask_sub;
+                        break;
+                     case EFL_CANVAS_VG_NODE_BLEND_TYPE_MASK_INTERSECT:
+                        spdata->unclipped_blend = &_blend_mask_ins;
+                        break;
+                     case EFL_CANVAS_VG_NODE_BLEND_TYPE_MASK_DIFFERENCE:
+                        spdata->unclipped_blend = &_blend_mask_diff;
+                        break;
+                    }
+               }
              else
-                spdata->unclipped_blend = &_blend_color_argb;
+                spdata->unclipped_blend = &_blend_argb;
            }
           break;
         case LinearGradient:
@@ -378,6 +527,10 @@ _adjust_span_fill_methods(Span_Data *spdata)
           break;
      }
 
+  //FIXME: Mask and mask case is not use clipping.
+  if (spdata->mask_op >= EFL_CANVAS_VG_NODE_BLEND_TYPE_MASK_ADD)
+     spdata->clip.enabled = EINA_FALSE;
+
    // Clipping Function
    if (spdata->clip.enabled)
      {