e_blur: add first implementation of ds_tizen_blur interface 51/306251/1
authorChangyeon Lee <cyeon.lee@samsung.com>
Wed, 6 Dec 2023 03:38:36 +0000 (12:38 +0900)
committerChangyeon Lee <cyeon.lee@samsung.com>
Mon, 19 Feb 2024 07:33:16 +0000 (16:33 +0900)
Change-Id: Ie508e2c13fdd6bdc7e3566afd271793bf016a3ab

src/bin/Makefile.mk
src/bin/e_blur.c [new file with mode: 0644]
src/bin/e_blur_intern.h [new file with mode: 0644]
src/bin/e_comp_wl.c

index aa6254c..dfe25c0 100644 (file)
@@ -241,6 +241,7 @@ src/bin/e_input_event.c \
 src/bin/e_comp_wl_buffer.c \
 src/bin/e_compositor.c \
 src/bin/e_blender.c \
+src/bin/e_blur.c \
 src/bin/e_devicemgr_keyboard_grab.c \
 src/bin/e_subsurface_watcher.c \
 src/bin/e_tbm_gbm_server.c \
diff --git a/src/bin/e_blur.c b/src/bin/e_blur.c
new file mode 100644 (file)
index 0000000..35c81c2
--- /dev/null
@@ -0,0 +1,423 @@
+#include "e.h"
+#include <pixman.h>
+#include <libds-tizen/blur.h>
+
+typedef struct _E_Blur_Manager E_Blur_Manager;
+typedef struct _E_Blur E_Blur;
+typedef struct _E_Blur_Object E_Blur_Object;
+
+struct _E_Blur_Manager
+{
+   struct ds_tizen_blur_manager *tizen_blur_manager;
+
+   struct wl_listener destroy_listener;
+   struct wl_listener new_blur_listener;
+};
+
+struct _E_Blur
+{
+   struct ds_tizen_blur *tizen_blur;
+   struct wl_listener commit_listener;
+   struct wl_listener destroy_listener;
+
+   E_Client *ec;
+   E_Object_Delfn *ec_delfn;
+
+   pixman_region32_t region;
+   uint32_t radius;
+
+   Eina_List *blur_objs;
+};
+
+struct _E_Blur_Object
+{
+   int x, y, w, h;
+
+   Evas_Object *obj;
+};
+
+static E_Blur_Manager *_blur_manager = NULL;
+
+static void _e_blur_ec_set(E_Blur *blur, E_Client *ec);
+
+static E_Blur_Object *
+_e_blur_object_create(int x, int y, int w, int h)
+{
+   E_Blur_Object *blur_obj;
+   Evas_Object *obj;
+
+   blur_obj = E_NEW(E_Blur_Object, 1);
+   EINA_SAFETY_ON_FALSE_RETURN_VAL(blur_obj, NULL);
+
+   blur_obj->x = x;
+   blur_obj->y = y;
+   blur_obj->w = w;
+   blur_obj->h = h;
+
+   obj = evas_object_image_filled_add(e_comp->evas);
+   EINA_SAFETY_ON_NULL_GOTO(obj, fail);
+
+   evas_object_image_snapshot_set(obj, EINA_TRUE);
+   evas_object_name_set(obj, "blur_obj");
+
+   blur_obj->obj = obj;
+
+   return blur_obj;
+
+fail:
+   free(blur_obj);
+
+   return NULL;
+}
+
+static void
+_e_blur_object_destroy(E_Blur_Object *blur_obj)
+{
+   evas_object_del(blur_obj->obj);
+   free(blur_obj);
+}
+
+static void
+_e_blur_free(E_Blur *blur)
+{
+   E_Blur_Object *blur_obj;
+
+   ELOGF("E_BLUR", "E_Blur:%p Free", blur->ec, blur);
+
+   _e_blur_ec_set(blur, NULL);
+
+   EINA_LIST_FREE(blur->blur_objs, blur_obj)
+     _e_blur_object_destroy(blur_obj);
+
+   pixman_region32_fini(&blur->region);
+   free(blur);
+}
+
+static void
+_e_blur_object_geometry_set(E_Blur_Object *blur_obj, E_Client *ec)
+{
+   int ec_x, ec_y, ec_w, ec_h;
+   int evas_x, evas_y, evas_w, evas_h;
+   double scale_w, scale_h;
+
+   evas_object_geometry_get(ec->frame, &evas_x, &evas_y, &evas_w, &evas_h);
+
+   if (e_client_transform_core_enable_get(ec))
+     {
+        e_client_geometry_get(ec, &ec_x, &ec_y, &ec_w, &ec_h);
+
+        scale_w = (double)ec_w / (double)evas_w;
+        scale_h = (double)ec_h / (double)evas_h;
+
+        evas_object_geometry_set(blur_obj->obj,
+                                 ec_x + blur_obj->x,
+                                 ec_y + blur_obj->y,
+                                 (int)((double)blur_obj->w * scale_w),
+                                 (int)((double)blur_obj->h * scale_h));
+     }
+   else
+     {
+        evas_object_geometry_set(blur_obj->obj,
+                                 evas_x + blur_obj->x,
+                                 evas_y + blur_obj->y,
+                                 blur_obj->w,
+                                 blur_obj->h);
+     }
+}
+
+static void
+_e_blur_cb_ds_tizen_blur_commit(struct wl_listener *listener, void *data)
+{
+   E_Blur *blur;
+   E_Blur_Object *blur_obj;
+   pixman_box32_t *rects;
+   int rects_count, i;
+   char program[1024];
+   Eina_List *l;
+   struct ds_tizen_blur_state *state;
+
+   blur = container_of(listener, E_Blur, commit_listener);
+   if (!blur) return;
+   if (!blur->ec) return;
+
+   state = ds_tizen_blur_get_state(blur->tizen_blur);
+   if (!state) return;
+
+   blur->radius = state->radius;
+   pixman_region32_copy(&blur->region, &state->region);
+
+   if (blur->radius)
+     {
+        snprintf(program, sizeof(program), "blur (%d) padding_set (0)", blur->radius);
+     
+        if (state->committed & DS_TIZEN_BLUR_STATE_REGION)
+          {
+             EINA_LIST_FREE(blur->blur_objs, blur_obj)
+               _e_blur_object_destroy(blur_obj);
+     
+             rects = pixman_region32_rectangles(&blur->region, &rects_count);
+             for (i = 0; i < rects_count; i++)
+               {
+                  blur_obj = _e_blur_object_create(rects[i].x1,
+                                                   rects[i].y1,
+                                                   rects[i].x2 - rects[i].x1,
+                                                   rects[i].y2 - rects[i].y1);
+                  EINA_SAFETY_ON_NULL_RETURN(blur_obj);
+     
+                  _e_blur_object_geometry_set(blur_obj, blur->ec);
+     
+                  efl_gfx_filter_program_set(blur_obj->obj, program, "image_filter");
+                  evas_object_layer_set(blur_obj->obj, blur->ec->layer);
+                  evas_object_stack_below(blur_obj->obj, blur->ec->frame);
+     
+                  if (evas_object_visible_get(blur->ec->frame))
+                    evas_object_show(blur_obj->obj);
+     
+                  blur->blur_objs = eina_list_append(blur->blur_objs, blur_obj);
+     
+                  ELOGF("E_BLUR", "E_Blur:%p set blur_obj:%p %dx%d+%d+%d radius:%d",
+                        blur->ec, blur, blur_obj,
+                        blur_obj->w, blur_obj->h, blur_obj->x, blur_obj->y,
+                        blur->radius);
+               }
+          }
+        else if (state->committed & DS_TIZEN_BLUR_STATE_RADIUS)
+          {
+             EINA_LIST_FOREACH(blur->blur_objs, l, blur_obj)
+               {
+                  efl_gfx_filter_program_set(blur_obj->obj, program, "image_filter");
+     
+                  ELOGF("E_BLUR", "E_Blur:%p set blur_obj:%p radius:%d",
+                        blur->ec, blur, blur_obj, blur->radius);
+               }
+          }
+     }
+   else
+     {
+        EINA_LIST_FREE(blur->blur_objs, blur_obj)
+          _e_blur_object_destroy(blur_obj);
+     }
+}
+
+static void
+_e_blur_evas_cb_show(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
+{
+   E_Blur *blur;
+   Eina_List *l;
+   E_Blur_Object *blur_obj;
+
+   if (!(blur = data)) return;
+
+   EINA_LIST_FOREACH(blur->blur_objs, l, blur_obj)
+     evas_object_show(blur_obj->obj);
+}
+
+static void
+_e_blur_evas_cb_hide(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
+{
+   E_Blur *blur;
+   Eina_List *l;
+   E_Blur_Object *blur_obj;
+
+   if (!(blur = data)) return;
+
+   EINA_LIST_FOREACH(blur->blur_objs, l, blur_obj)
+     evas_object_hide(blur_obj->obj);
+}
+
+static void
+_e_blur_evas_cb_resize(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
+{
+   E_Blur *blur;
+   Eina_List *l;
+   E_Blur_Object *blur_obj;
+
+   if (!(blur = data)) return;
+
+   EINA_LIST_FOREACH(blur->blur_objs, l, blur_obj)
+     _e_blur_object_geometry_set(blur_obj, blur->ec);
+}
+
+static void
+_e_blur_evas_cb_move(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
+{
+   E_Blur *blur;
+   Eina_List *l;
+   E_Blur_Object *blur_obj;
+
+   if (!(blur = data)) return;
+
+   EINA_LIST_FOREACH(blur->blur_objs, l, blur_obj)
+     _e_blur_object_geometry_set(blur_obj, blur->ec);
+}
+
+static void
+_e_blur_evas_cb_restack(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
+{
+   E_Blur *blur;
+   Eina_List *l;
+   E_Blur_Object *blur_obj;
+
+   if (!(blur = data)) return;
+
+   EINA_LIST_FOREACH(blur->blur_objs, l, blur_obj)
+     evas_object_stack_below(blur_obj->obj, obj);
+}
+
+static void
+_e_blur_cb_ec_free(void *data, void *obj)
+{
+   E_Blur *blur = data;
+
+   blur->ec_delfn = NULL;
+   _e_blur_ec_set(blur, NULL);
+}
+
+static void
+_e_blur_ec_set(E_Blur *blur, E_Client *ec)
+{
+   if (blur->ec == ec) return;
+
+   if (blur->ec)
+     {
+        evas_object_event_callback_del(blur->ec->frame, EVAS_CALLBACK_SHOW,
+                                      _e_blur_evas_cb_show);
+        evas_object_event_callback_del(blur->ec->frame, EVAS_CALLBACK_HIDE,
+                                      _e_blur_evas_cb_hide);
+        evas_object_event_callback_del(blur->ec->frame, EVAS_CALLBACK_RESIZE,
+                                      _e_blur_evas_cb_resize);
+        evas_object_event_callback_del(blur->ec->frame, EVAS_CALLBACK_MOVE,
+                                      _e_blur_evas_cb_move);
+        evas_object_event_callback_del(blur->ec->frame, EVAS_CALLBACK_RESTACK,
+                                      _e_blur_evas_cb_restack);
+
+        if (blur->ec_delfn)
+          {
+             e_object_delfn_del(E_OBJECT(blur->ec), blur->ec_delfn);
+             blur->ec_delfn = NULL;
+          }
+
+        blur->ec = NULL;
+     }
+
+   if (ec)
+     {
+        evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_SHOW,
+                                       _e_blur_evas_cb_show, blur);
+        evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_HIDE,
+                                       _e_blur_evas_cb_hide, blur);
+        evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_RESIZE,
+                                       _e_blur_evas_cb_resize, blur);
+        evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_MOVE,
+                                       _e_blur_evas_cb_move, blur);
+        evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_RESTACK,
+                                       _e_blur_evas_cb_restack, blur);
+
+        blur->ec_delfn = e_object_delfn_add(E_OBJECT(ec),
+                                            _e_blur_cb_ec_free,
+                                            blur);
+        blur->ec = ec;
+     }
+}
+
+static void
+_e_blur_cb_ds_tizen_blur_destroy(struct wl_listener *listener, void *data)
+{
+   E_Blur *blur;
+
+   blur = wl_container_of(listener, blur, destroy_listener);
+   if (!blur) return;
+
+   _e_blur_free(blur);
+}
+
+static void
+_e_blur_manager_cb_new_blur(struct wl_listener *listener, void *data)
+{
+   E_Blur *blur = NULL;
+   E_Blur_Manager *blur_manager = _blur_manager;
+   struct ds_tizen_blur *tizen_blur = data;
+   struct ds_surface *surface;
+   struct wl_resource *surface_resource;
+   E_Client *ec;
+
+   if (!blur_manager)
+     {
+        ERR("blur is not initialized");
+        return;
+     }
+
+   surface = ds_tizen_blur_get_surface(tizen_blur);
+   EINA_SAFETY_ON_NULL_RETURN(surface);
+
+   surface_resource = ds_surface_get_wl_resource(surface);
+   EINA_SAFETY_ON_NULL_RETURN(surface_resource);
+
+   ec = e_client_from_surface_resource(surface_resource);
+   EINA_SAFETY_ON_NULL_RETURN(ec);
+
+   blur = E_NEW(E_Blur, 1);
+   EINA_SAFETY_ON_NULL_RETURN(blur);
+
+   blur->destroy_listener.notify = _e_blur_cb_ds_tizen_blur_destroy;
+   ds_tizen_blur_add_destroy_listener(tizen_blur, &blur->destroy_listener);
+
+   blur->commit_listener.notify = _e_blur_cb_ds_tizen_blur_commit;
+   ds_tizen_blur_add_commit_listener(tizen_blur, &blur->commit_listener);
+
+   blur->tizen_blur = tizen_blur;
+
+   pixman_region32_init_rect(&blur->region, 0, 0, ec->w, ec->h);
+
+   _e_blur_ec_set(blur, ec);
+
+   ELOGF("E_BLUR", "E_Blur:%p Create", ec, blur);
+
+   return;
+}
+
+static void
+_e_blur_manager_cb_destroy(struct wl_listener *listener, void *data)
+{
+   E_Blur_Manager *blur_manager;
+
+   blur_manager = container_of(listener, E_Blur_Manager, destroy_listener);
+
+   free(blur_manager);
+
+   _blur_manager = NULL;
+}
+
+EINTERN Eina_Bool
+e_blur_manager_init(void)
+{
+   E_Blur_Manager *blur_manager;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp_wl, EINA_FALSE);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp_wl->wl.disp, EINA_FALSE);
+
+   if (_blur_manager) return EINA_TRUE;
+
+   blur_manager = E_NEW(E_Blur_Manager, 1);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(blur_manager, EINA_FALSE);
+
+   blur_manager->tizen_blur_manager = ds_tizen_blur_manager_create(e_comp_wl->wl.disp);
+   EINA_SAFETY_ON_NULL_GOTO(blur_manager, fail);
+
+   blur_manager->destroy_listener.notify = _e_blur_manager_cb_destroy;
+   ds_tizen_blur_manager_add_destroy_listener(blur_manager->tizen_blur_manager,
+                                              &blur_manager->destroy_listener);
+
+   blur_manager->new_blur_listener.notify = _e_blur_manager_cb_new_blur;
+   ds_tizen_blur_manager_add_new_blur_listener(blur_manager->tizen_blur_manager,
+                                               &blur_manager->new_blur_listener);
+
+   _blur_manager = blur_manager;
+
+   return EINA_TRUE;
+
+fail:
+   free(blur_manager);
+
+   return EINA_FALSE;
+}
diff --git a/src/bin/e_blur_intern.h b/src/bin/e_blur_intern.h
new file mode 100644 (file)
index 0000000..354b194
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef E_BLUR_INTERN_H
+#define E_BLUR_INTERN_H
+
+#include "e_intern.h"
+
+EINTERN Eina_Bool e_blur_manager_init(void);
+
+#endif // E_BLUR_INTERN_H
index 5f29d18..de2edc7 100644 (file)
@@ -37,6 +37,7 @@
 #include "e_zone_intern.h"
 #include "e_hints_intern.h"
 #include "e_comp_input_intern.h"
+#include "e_blur_intern.h"
 
 #include <tizen-extension-server-protocol.h>
 #include <relative-pointer-unstable-v1-server-protocol.h>
@@ -3913,6 +3914,7 @@ e_comp_wl_init(void)
    e_presentation_time_init();
    ds_single_pixel_buffer_manager_v1_create(e_comp_wl->wl.disp);
    e_blender_init();
+   e_blur_manager_init();
 
    if (!e_foreign_global_init(e_comp_wl->wl.disp))
      ELOGF("COMP", "Failed to initialize the e_foreign global", NULL);