evas: add evas_map_direct_render_set 53/257753/7
authorShinwoo Kim <cinoo.kim@samsung.com>
Fri, 30 Apr 2021 09:31:44 +0000 (18:31 +0900)
committerShinwoo Kim <cinoo.kim@samsung.com>
Wed, 26 May 2021 01:02:04 +0000 (01:02 +0000)
This is for very special purpose interface to optimize memory usage of map.
This is for a smart object which has only one image object as its children.
The map will be applied to the image object instead of the smart object.

Change-Id: Ieceff3413aba7ac1c88aec694f47fb8c4dcc741d

src/lib/evas/Evas_Legacy.h
src/lib/evas/canvas/evas_map.c
src/lib/evas/canvas/evas_render.c
src/lib/evas/include/evas_private.h

index 3efe7fb..658313f 100755 (executable)
@@ -8578,6 +8578,25 @@ EAPI void evas_object_map_enable_set(Evas_Object *obj, Eina_Bool enabled);
  */
 EAPI Eina_Bool evas_object_map_enable_get(const Evas_Object *obj);
 
+//TIZEN_ONLY(20210503): Add evas_map_direct_render_set
+/**
+ * @brief Set direct render of map.
+ *
+ * This interface has very special purpose to optimize memory usage of map.
+ * It works when a map object has only one image object through its smart object tree.
+ * In this case, it regards the map has one image object which of buffer can be
+ * directly draw on the main surface so that it skips to create an additional frame
+ * buffer to composite the contents of the map. If the condition is not satisfied,
+ * map works as it's supposed to do in the default behavior.
+ *
+ * @param m map to enable direct render.
+ * @param direct_render @c true to enable direct render.
+ *
+ * @ingroup Evas_Object_Group
+ */
+EAPI void evas_map_direct_render_set(Evas_Map *m, Eina_Bool direct_render);
+//
+
 /**
  * @brief Apply an evas filter program on this text object.
  *
index 272a2b8..e7423ac 100644 (file)
@@ -207,6 +207,9 @@ _evas_map_copy(Evas_Map *dst, const Evas_Map *src)
    dst->alpha = src->alpha;
    dst->move_sync = src->move_sync;
    dst->persp = src->persp;
+   //TIZEN_ONLY(20210503): Add evas_map_direct_render_set
+   dst->direct_render = src->direct_render;
+   //
    return EINA_TRUE;
 }
 
@@ -220,6 +223,9 @@ _evas_map_dup(const Evas_Map *orig)
    copy->alpha = orig->alpha;
    copy->move_sync = orig->move_sync;
    copy->persp = orig->persp;
+   //TIZEN_ONLY(20210503): Add evas_map_direct_render_set
+   copy->direct_render = orig->direct_render;
+   //
    return copy;
 }
 
@@ -528,6 +534,18 @@ evas_object_map_enable_get(const Eo *eo_obj)
    return obj->map->cur.usemap;
 }
 
+//TIZEN_ONLY(20210503): Add evas_map_direct_render_set
+EAPI void
+evas_map_direct_render_set(Evas_Map *m, Eina_Bool direct_render)
+{
+   MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
+   return;
+   MAGIC_CHECK_END();
+
+   m->direct_render = !!direct_render;
+}
+//
+
 EAPI void
 evas_object_map_set(Evas_Object *eo_obj, const Evas_Map *map)
 {
index 5a863d8..077fcea 100644 (file)
@@ -1793,6 +1793,96 @@ _evas_render_mapped_mask(Evas_Public_Data *evas, Evas_Object_Protected_Data *obj
      }
 }
 
+//TIZEN_ONLY(20210503): Add evas_map_direct_render_set
+/* This function checks if there is only one image object, and returns it */
+static Eina_Bool
+_map_source_image_get(Evas_Object *eo_obj, Evas_Object **src_img)
+{
+   Eina_Bool ret;
+   Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
+   Evas_Object_Protected_Data *obj2;
+
+   if (obj->is_image_object)
+     {
+        if (*src_img)
+          {
+             /* more than one image object */
+             *src_img = NULL;
+             return EINA_FALSE;
+          }
+        *src_img = obj->object;
+     }
+   else if (obj->is_smart)
+     {
+        EINA_INLIST_FOREACH
+           (evas_object_smart_members_get_direct(eo_obj), obj2)
+             {
+                ret = _map_source_image_get(obj2->object, src_img);
+                if (!ret) return ret;
+             }
+     }
+
+   return EINA_TRUE;
+}
+
+static void
+_map_direct_render(Evas_Public_Data *evas, void *ctx, Evas_Object *src_img,
+                   int w, int h, Evas_Object_Protected_Data *obj,
+                   void *output, void *surface, int off_x, int off_y,
+                   Eina_Bool do_async)
+{
+   int i;
+   Evas_Map_Point points[4];
+   Evas_Map_Point *p;
+
+   Evas_Object_Protected_Data *src_img_pd = efl_data_scope_get(src_img, EFL_CANVAS_OBJECT_CLASS);
+   const Evas_Object_Map_Data *tmap = src_img_pd->map;
+
+   src_img_pd->map = obj->map;
+
+   for (i = 0; i < obj->map->cur.map->count; i++)
+     {
+        p = obj->map->cur.map->points + i;
+        points[i].u = p->u;
+        points[i].v = p->v;
+        switch (i)
+          {
+           case 0:
+             p->u = 0;
+             p->v = 0;
+             break;
+           case 1:
+             p->u = w;
+             p->v = 0;
+             break;
+           case 2:
+             p->u = w;
+             p->v = h;
+             break;
+           case 3:
+             p->u = 0;
+             p->v = h;
+             break;
+           default:
+             break;
+          }
+     }
+
+   src_img_pd->func->render(src_img, src_img_pd, src_img_pd->private_data,
+                            ENC, output, ctx, surface,
+                            off_x, off_y, do_async);
+
+   for (i = 0; i < obj->map->cur.map->count; i++)
+     {
+        p = obj->map->cur.map->points + i;
+        p->u = points[i].u;
+        p->v = points[i].v;
+     }
+
+   src_img_pd->map = tmap;
+}
+//
+
 Eina_Bool
 evas_render_mapped(Evas_Public_Data *evas, Evas_Object *eo_obj,
                    Evas_Object_Protected_Data *obj, void *context,
@@ -1952,6 +2042,36 @@ evas_render_mapped(Evas_Public_Data *evas, Evas_Object *eo_obj,
         int sw, sh;
         Eina_Bool changed = EINA_FALSE, rendered = EINA_FALSE, pchanged = EINA_FALSE;
 
+        //TIZEN_ONLY(20210503): Add evas_map_direct_render_set
+        int src_img_w = 0;
+        int src_img_h = 0;
+        Evas_Object *direct_render_src_img = NULL;
+        if (obj->map->cur.map->direct_render && obj->map->cur.map->count == 4)
+          {
+             _map_source_image_get(eo_obj, &direct_render_src_img);
+             if (direct_render_src_img)
+               {
+                  evas_object_image_size_get(direct_render_src_img,
+                                             &src_img_w, &src_img_h);
+                  if (src_img_w == 0 || src_img_h == 0)
+                    {
+                       direct_render_src_img = NULL;
+                    }
+                  else
+                    {
+                       /* direct render will work, surface is not necessary */
+                       if (obj->map->surface)
+                         {
+                            ENFN->image_free(ENC, obj->map->surface);
+                            EINA_COW_WRITE_BEGIN(evas_object_map_cow, obj->map, Evas_Object_Map_Data, map_write)
+                              map_write->surface = NULL;
+                            EINA_COW_WRITE_END(evas_object_map_cow, obj->map, map_write);
+                         }
+                    }
+               }
+          }
+        //
+
         clean_them = EINA_TRUE;
 
         sw = obj->cur->geometry.w;
@@ -1975,7 +2095,12 @@ evas_render_mapped(Evas_Public_Data *evas, Evas_Object *eo_obj,
                   EINA_COW_WRITE_END(evas_object_map_cow, obj->map, map_write);
                }
           }
+        //TIZEN_ONLY(20210503): Add evas_map_direct_render_set
+        /*
         if (!obj->map->surface)
+        */
+        if (!obj->map->surface && !direct_render_src_img)
+        //
           {
              EINA_COW_WRITE_BEGIN(evas_object_map_cow, obj->map, Evas_Object_Map_Data, map_write)
                {
@@ -2093,7 +2218,12 @@ evas_render_mapped(Evas_Public_Data *evas, Evas_Object *eo_obj,
         ENFN->context_clip_unset(ENC, ctx);
         //ENFN->context_multiplier_unset(ENC, ctx); // this probably should be here, too
 
+        //TIZEN_ONLY(20210503): Add evas_map_direct_render_set
+        /*
         if (obj->map->surface)
+        */
+        if (obj->map->surface || direct_render_src_img)
+        //
           {
              Evas_Object_Protected_Data *mask = obj->clip.mask;
 
@@ -2135,10 +2265,24 @@ evas_render_mapped(Evas_Public_Data *evas, Evas_Object *eo_obj,
                   _c = ENFN->context_clip_get(ENC, ctx, &_cx, &_cy, &_cw, &_ch);
                   RD(level, "  draw image map(clip: [%d] %d,%d %dx%d)\n", _c, _cx, _cy, _cw, _ch);
 #endif
+
+                  //TIZEN_ONLY(20210503): Add evas_map_direct_render_set
+                  if (direct_render_src_img)
+                    {
+                       _map_direct_render(evas, ctx, direct_render_src_img,
+                                          src_img_w, src_img_h, obj, output,
+                                          surface, off_x, off_y, do_async);
+                    }
+                  else
+                    {
+                  //
                   evas_draw_image_map_async_check
                     (obj, ENC, output, ctx, surface,
                      obj->map->surface, obj->map->spans,
                      obj->map->cur.map->smooth, 0, do_async);
+                  //TIZEN_ONLY(20210503): Add evas_map_direct_render_set
+                    }
+                  //
                }
           }
 
index aea246b..744de1b 100755 (executable)
@@ -605,6 +605,9 @@ struct _Evas_Map
    } persp;
    Eina_Bool             alpha : 1;
    Eina_Bool             smooth : 1;
+   //TIZEN_ONLY(20210503): Add evas_map_direct_render_set
+   Eina_Bool             direct_render : 1;
+   //
    struct {
       Eina_Bool          enabled : 1;
       Evas_Coord         diff_x, diff_y;