From: Changyeon Lee Date: Wed, 6 Dec 2023 03:38:36 +0000 (+0900) Subject: e_blur: add first implementation of ds_tizen_blur interface X-Git-Tag: accepted/tizen/unified/20240219.160457~1 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F51%2F306251%2F1;p=platform%2Fupstream%2Fenlightenment.git e_blur: add first implementation of ds_tizen_blur interface Change-Id: Ie508e2c13fdd6bdc7e3566afd271793bf016a3ab --- diff --git a/src/bin/Makefile.mk b/src/bin/Makefile.mk index aa6254c..dfe25c0 100644 --- a/src/bin/Makefile.mk +++ b/src/bin/Makefile.mk @@ -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 index 0000000..35c81c2 --- /dev/null +++ b/src/bin/e_blur.c @@ -0,0 +1,423 @@ +#include "e.h" +#include +#include + +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 index 0000000..354b194 --- /dev/null +++ b/src/bin/e_blur_intern.h @@ -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 diff --git a/src/bin/e_comp_wl.c b/src/bin/e_comp_wl.c index 5f29d18..de2edc7 100644 --- a/src/bin/e_comp_wl.c +++ b/src/bin/e_comp_wl.c @@ -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 #include @@ -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);