From: Changyeon Lee Date: Wed, 5 Jul 2023 07:02:53 +0000 (+0900) Subject: e_blender: add first implementation of wtz-blender protocol X-Git-Tag: accepted/tizen/unified/20230727.055142~4 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F94%2F296294%2F1;p=platform%2Fupstream%2Fenlightenment.git e_blender: add first implementation of wtz-blender protocol Change-Id: I0da822db416ca4a81c5d5d15ae78dcdf05e2da5a --- diff --git a/configure.ac b/configure.ac index abd871d..943840f 100755 --- a/configure.ac +++ b/configure.ac @@ -380,7 +380,7 @@ if test "x${e_cv_want_wayland_only}" != "xno" || test "x${e_cv_want_wayland_clie tizen-launch-server tizen-surface-server tizen-dpms-server eom-server presentation-time-server tizen-hwc-server linux-explicit-synchronization-unstable-v1-server wtz-foreign-server wtz-screen-server wtz-shell-server relative-pointer-unstable-v1-server pointer-constraints-unstable-v1-server - single-pixel-buffer-v1-server], + single-pixel-buffer-v1-server wtz-blender-server], [ have_wayland=yes AC_DEFINE_UNQUOTED([HAVE_WAYLAND],[1],[enable wayland support]) diff --git a/packaging/enlightenment.spec b/packaging/enlightenment.spec index 64be05c..a94a93a 100644 --- a/packaging/enlightenment.spec +++ b/packaging/enlightenment.spec @@ -68,6 +68,7 @@ BuildRequires: pkgconfig(relative-pointer-unstable-v1-server) BuildRequires: pkgconfig(glib-2.0) BuildRequires: pkgconfig(gobject-2.0) BuildRequires: pkgconfig(single-pixel-buffer-v1-server) +BuildRequires: pkgconfig(wtz-blender-server) Requires: libwayland-extension-server # for gtest/gmock diff --git a/src/bin/Makefile.mk b/src/bin/Makefile.mk index 2448908..a928aac 100644 --- a/src/bin/Makefile.mk +++ b/src/bin/Makefile.mk @@ -142,7 +142,8 @@ src/bin/e_map.h \ src/bin/e_wtz_shell.h \ src/bin/e_device.h \ src/bin/e_input_event.h \ -src/bin/e_single_pixel_buffer.h +src/bin/e_single_pixel_buffer.h \ +src/bin/e_blender.h enlightenment_src = \ src/bin/e_actions.c \ @@ -276,7 +277,8 @@ src/bin/e_device.c \ src/bin/e_input_event.c \ src/bin/e_single_pixel_buffer.c \ src/bin/e_comp_wl_buffer.c \ -src/bin/e_compositor.c +src/bin/e_compositor.c \ +src/bin/e_blender.c src_bin_enlightenment_CPPFLAGS = $(E_CPPFLAGS) -DEFL_BETA_API_SUPPORT -DEFL_EO_API_SUPPORT -DE_LOGGING=2 @WAYLAND_CFLAGS@ $(TTRACE_CFLAGS) $(DLOG_CFLAGS) $(PIXMAN_CFLAGS) $(POLICY_CFLAGS) $(EGL_CFLAGS) if HAVE_LIBGOMP diff --git a/src/bin/e_blender.c b/src/bin/e_blender.c new file mode 100644 index 0000000..093f388 --- /dev/null +++ b/src/bin/e_blender.c @@ -0,0 +1,361 @@ +#include "e.h" +#include + +static E_Blender *_blender = NULL; + +static void _e_blend_surface_set(E_Blend *blend, struct wl_resource *surface); + +static void +_e_blend_cb_destroy(struct wl_client *client, + struct wl_resource *resource) +{ + wl_resource_destroy(resource); +} + +static void +_e_blend_cb_set_alpha(struct wl_client *client, + struct wl_resource *resource, + uint32_t value) +{ + E_Blend *blend; + + blend = wl_resource_get_user_data(resource); + if (!blend) return; + if (!blend->surface) return; + if (blend->alpha == value) return; + + blend->alpha = value; + blend->changed = EINA_TRUE; + + ELOGF("E_BLENDER", "E_Blend:%p set alpha:%x", + e_client_from_surface_resource(blend->surface), blend, value); +} + +static void +_e_blend_cb_set_equation(struct wl_client *client, + struct wl_resource *resource, + uint32_t equation) +{ + E_Blend *blend; + + blend = wl_resource_get_user_data(resource); + if (!blend) return; + if (!blend->surface) return; + if (blend->equation == equation) return; + + if ((equation != WTZ_BLEND_EQUATION_PREMULTIPLIED) && + (equation != WTZ_BLEND_EQUATION_NONE)) + { + wl_resource_post_error(resource, WTZ_BLEND_ERROR_INVALID_EQUATION, + "Invalid equation"); + return; + } + + blend->equation = equation; + blend->changed = EINA_TRUE; + + ELOGF("E_BLENDER", "E_Blend:%p set equation:%d", + e_client_from_surface_resource(blend->surface), blend, equation); +} + +static const struct wtz_blend_interface _e_blend_implementation = { + _e_blend_cb_destroy, + _e_blend_cb_set_alpha, + _e_blend_cb_set_equation, +}; + +static void +_e_blend_free(E_Blend *blend) +{ + ELOGF("E_BLENDER", "E_Blend:%p Free", + blend->surface ? e_client_from_surface_resource(blend->surface) : NULL, + blend); + + _e_blend_surface_set(blend, NULL); + free(blend); +} + +static void +_e_blend_cb_surface_destroy(struct wl_listener *listener, void *data) +{ + E_Blend *blend; + + blend = container_of(listener, E_Blend, surface_destroy_listener); + + if (blend->resource) + _e_blend_surface_set(blend, NULL); + else + _e_blend_free(blend); +} + +static void +_e_blend_cb_surface_state_commit(struct wl_listener *listener, void *data) +{ + E_Blend *blend; + E_Client *ec; + int a, r, g, b; + + blend = container_of(listener, E_Blend, surface_state_commit_listener); + if (!blend->changed) return; + + ec = e_client_from_surface_resource(blend->surface); + if (!ec) return; + + if (!blend->resource) + { + e_comp_object_render_op_set(ec->frame, EVAS_RENDER_BLEND); + evas_object_color_set(ec->frame, 255, 255, 255, 255); + _e_blend_free(blend); + return; + } + + if (!ec->argb) return; + + a = r = g = b = 255; + a = (int)((blend->alpha / (double)0xffffffff) * a); + evas_color_argb_premul(a, &r, &g, &b); + + evas_object_color_set(ec->frame, r, g, b, a); + + if (blend->equation == WTZ_BLEND_EQUATION_PREMULTIPLIED) + e_comp_object_render_op_set(ec->frame, EVAS_RENDER_BLEND); + else if (blend->equation == WTZ_BLEND_EQUATION_NONE) + e_comp_object_render_op_set(ec->frame, EVAS_RENDER_COPY); + + blend->changed = EINA_FALSE; +} + +static void +_e_blend_surface_set(E_Blend *blend, struct wl_resource *surface) +{ + E_Client *ec; + E_Comp_Client_Data *cdata; + + if (blend->surface == surface) return; + + if (blend->surface_destroy_listener.notify) + { + wl_list_remove(&blend->surface_destroy_listener.link); + blend->surface_destroy_listener.notify = NULL; + } + + if (blend->surface_state_commit_listener.notify) + { + wl_list_remove(&blend->surface_state_commit_listener.link); + blend->surface_state_commit_listener.notify = NULL; + } + + blend->surface = NULL; + + if (surface) + { + ec = e_client_from_surface_resource(surface); + EINA_SAFETY_ON_NULL_RETURN(ec); + + cdata = e_client_cdata_get(ec); + EINA_SAFETY_ON_NULL_RETURN(cdata); + + blend->surface = surface; + + blend->surface_destroy_listener.notify = _e_blend_cb_surface_destroy; + wl_resource_add_destroy_listener(surface, &blend->surface_destroy_listener); + + blend->surface_state_commit_listener.notify = _e_blend_cb_surface_state_commit; + wl_signal_add(&cdata->state_commit_signal, &blend->surface_state_commit_listener); + } +} + +static void +_e_blend_cb_resource_destroy(struct wl_resource *resource) +{ + E_Blend *blend; + Evas_Render_Op render_op; + E_Client *ec; + int a; + + blend = wl_resource_get_user_data(resource); + if (!blend) return; + + if (blend->surface) + { + ec = e_client_from_surface_resource(blend->surface); + if (ec) + { + e_comp_object_color_get(ec->frame, NULL, NULL, NULL, &a); + render_op = e_comp_object_render_op_get(ec->frame); + if ((a != 255) || (render_op != EVAS_RENDER_BLEND)) + { + blend->resource = NULL; + blend->changed = EINA_TRUE; + return; + } + } + } + + _e_blend_free(blend); +} + +static void +_e_blender_cb_destroy(struct wl_client *client, + struct wl_resource *resource) +{ + wl_resource_destroy(resource); +} + +static E_Blend * +_e_blender_blend_get_from_surface(struct wl_resource *surface) +{ + E_Blend *blend; + struct wl_listener *listener; + + listener = wl_resource_get_destroy_listener(surface, _e_blend_cb_surface_destroy); + if (!listener) return NULL; + + return wl_container_of(listener, blend, surface_destroy_listener); +} + +static void +_e_blender_cb_get_blend(struct wl_client *client, struct wl_resource *resource, + uint32_t id, struct wl_resource *surface) +{ + E_Client *ec; + E_Blend *blend = NULL; + E_Blender *blender = _blender; + + if (!blender) + { + ERR("blender is not initialized"); + return; + } + + ec = e_client_from_surface_resource(surface); + if ((!ec) || (e_object_is_del(E_OBJECT(ec)))) + { + wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT, + "invalid wl_surface resource:%u", + (unsigned int)wl_resource_get_id(surface)); + goto fail; + } + + blend = _e_blender_blend_get_from_surface(surface); + if (blend) + { + if (blend->resource) + { + wl_resource_post_error(resource, WTZ_BLENDER_ERROR_BLEND_EXISTS, + "blend object already exists"); + goto fail; + } + else + { + _e_blend_free(blend); + } + } + + blend = E_NEW(E_Blend, 1); + if (!blend) + { + wl_client_post_no_memory(client); + goto fail; + } + + blend->resource = wl_resource_create(client, + &wtz_blend_interface, + wl_resource_get_version(resource), + id); + if (!blend->resource) + { + wl_client_post_no_memory(client); + goto fail; + } + + wl_resource_set_implementation(blend->resource, + &_e_blend_implementation, + blend, + _e_blend_cb_resource_destroy); + + blend->alpha = 0xffffffff; + _e_blend_surface_set(blend, surface); + + ELOGF("E_BLENDER", "E_Blend:%p Create", ec, blend); + + return; + +fail: + if (blend) + free(blend); + + return; +} + +static const struct wtz_blender_interface _e_blender_implementation = { + _e_blender_cb_destroy, + _e_blender_cb_get_blend, +}; + +static void +_e_blender_cb_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id) +{ + struct wl_resource *resource; + E_Blender *blender; + + blender = _blender; + if (!blender) return; + + resource = wl_resource_create(client, &wtz_blender_interface, version, id); + if (!resource) + { + wl_client_post_no_memory(client); + return; + } + + wl_resource_set_implementation(resource, &_e_blender_implementation, + blender, NULL); +} + +EINTERN Eina_Bool +e_blender_init(void) +{ + E_Blender *blender; + + 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 (_blender) return EINA_TRUE; + + blender = E_NEW(E_Blender, 1); + EINA_SAFETY_ON_NULL_RETURN_VAL(blender, EINA_FALSE); + + blender->global = wl_global_create(e_comp_wl->wl.disp, + &wtz_blender_interface, + 1, + blender, + _e_blender_cb_bind); + EINA_SAFETY_ON_NULL_GOTO(blender->global, fail); + + _blender = blender; + + return EINA_TRUE; + +fail: + if (blender->global) + wl_global_destroy(blender->global); + + E_FREE(blender); + + return EINA_FALSE; +} + +EINTERN void +e_blender_shutdown(void) +{ + E_Blender *blender; + + blender = _blender; + if (!blender) return; + + wl_global_destroy(blender->global); + E_FREE(blender); + + _blender = NULL; +} diff --git a/src/bin/e_blender.h b/src/bin/e_blender.h new file mode 100644 index 0000000..96a36c3 --- /dev/null +++ b/src/bin/e_blender.h @@ -0,0 +1,32 @@ +#ifdef E_TYPEDEFS + +typedef struct _E_Blender E_Blender; +typedef struct _E_Blend E_Blend; + +#else +#ifndef E_BLENDER_H +#define E_BLENDER_H + +struct _E_Blender +{ + struct wl_global *global; +}; + +struct _E_Blend +{ + struct wl_resource *resource; + + struct wl_resource *surface; + struct wl_listener surface_destroy_listener; + struct wl_listener surface_state_commit_listener; + + uint32_t alpha; + uint32_t equation; + Eina_Bool changed; +}; + +EINTERN Eina_Bool e_blender_init(void); +EINTERN void e_blender_shutdown(void); + +#endif // E_BLENDER_H +#endif diff --git a/src/bin/e_comp_object.c b/src/bin/e_comp_object.c index 7769832..49f7d44 100644 --- a/src/bin/e_comp_object.c +++ b/src/bin/e_comp_object.c @@ -6615,3 +6615,19 @@ e_comp_object_color_get(Evas_Object *obj, int *r, int *g, int *b, int *a) evas_object_color_get(obj, r, g, b, a); } } + +EINTERN void +e_comp_object_render_op_set(Evas_Object *obj, Evas_Render_Op op) +{ + API_ENTRY; + + evas_object_render_op_set(cw->obj, op); +} + +EINTERN Evas_Render_Op +e_comp_object_render_op_get(Evas_Object *obj) +{ + API_ENTRY EVAS_RENDER_BLEND; + + return evas_object_render_op_get(cw->obj); +} diff --git a/src/bin/e_comp_object.h b/src/bin/e_comp_object.h index dd7f10f..dc786f8 100644 --- a/src/bin/e_comp_object.h +++ b/src/bin/e_comp_object.h @@ -211,6 +211,9 @@ E_API void e_comp_object_render_update_unlock(Evas_Object *obj); E_API Eina_Bool e_comp_object_render_update_lock_get(Evas_Object *obj); E_API void e_comp_object_color_get(Evas_Object *obj, int *r, int *g, int *b, int *a); + +EINTERN void e_comp_object_render_op_set(Evas_Object *obj, Evas_Render_Op op); +EINTERN Evas_Render_Op e_comp_object_render_op_get(Evas_Object *obj); #endif #endif diff --git a/src/bin/e_comp_wl.c b/src/bin/e_comp_wl.c index 02da8ad..3054773 100644 --- a/src/bin/e_comp_wl.c +++ b/src/bin/e_comp_wl.c @@ -3803,6 +3803,7 @@ e_comp_wl_init(void) _e_comp_wl_move_resize_init(); e_presentation_time_init(); e_single_pixel_buffer_manager_init(); + e_blender_init(); if (!e_foreign_global_init(e_comp_wl->wl.disp)) ELOGF("COMP", "Failed to initialize the e_foreign global", NULL); @@ -3854,6 +3855,7 @@ e_comp_wl_shutdown(void) E_FREE_LIST(hooks, e_client_hook_del); _e_comp_wl_gl_shutdown(); + e_blender_shutdown(); e_single_pixel_buffer_manager_shutdown(); e_presentation_time_shutdown(); e_comp_wl_renderer_shutdown(); diff --git a/src/bin/e_hwc_window.c b/src/bin/e_hwc_window.c index c90e395..2058618 100644 --- a/src/bin/e_hwc_window.c +++ b/src/bin/e_hwc_window.c @@ -73,6 +73,8 @@ typedef enum _E_Hwc_Window_Restriction E_HWC_WINDOW_RESTRICTION_EFFECT_RUNNING, E_HWC_WINDOW_RESTRICTION_RENDER_UPDATE_LOCK, E_HWC_WINDOW_RESTRICTION_DESK_ZOOM, + E_HWC_WINDOW_RESTRICTION_BLEND_ALPHA, + E_HWC_WINDOW_RESTRICTION_BLEND_EQUATION, } E_Hwc_Window_Restriction; static Eina_Bool ehw_trace = EINA_FALSE; @@ -2059,6 +2061,8 @@ e_hwc_window_device_state_available_update(E_Hwc_Window *hwc_window) E_Hwc_Window_Restriction restriction = E_HWC_WINDOW_RESTRICTION_NONE; E_Desk *desk; E_Zone *zone; + int alpha; + Evas_Render_Op render_op; EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, EINA_FALSE); @@ -2238,6 +2242,21 @@ e_hwc_window_device_state_available_update(E_Hwc_Window *hwc_window) goto finish; } + e_comp_object_color_get(ec->frame, NULL, NULL, NULL, &alpha); + if (alpha != 255) + { + restriction = E_HWC_WINDOW_RESTRICTION_BLEND_ALPHA; + available = EINA_FALSE; + goto finish; + } + + render_op = e_comp_object_render_op_get(ec->frame); + if (render_op != EVAS_RENDER_BLEND) + { + restriction = E_HWC_WINDOW_RESTRICTION_BLEND_EQUATION; + available = EINA_FALSE; + goto finish; + } finish: hwc_window->restriction = restriction; @@ -2611,6 +2630,10 @@ e_hwc_window_restriction_string_get(E_Hwc_Window *hwc_window) return "render update lock"; case E_HWC_WINDOW_RESTRICTION_DESK_ZOOM: return "desk zoom"; + case E_HWC_WINDOW_RESTRICTION_BLEND_ALPHA: + return "blend alpha"; + case E_HWC_WINDOW_RESTRICTION_BLEND_EQUATION: + return "blend equation"; default: return "UNKNOWN"; } diff --git a/src/bin/e_includes.h b/src/bin/e_includes.h index a8ea192..c33be3f 100644 --- a/src/bin/e_includes.h +++ b/src/bin/e_includes.h @@ -88,3 +88,4 @@ #include "e_comp_wl_renderer.h" #include "e_map.h" #include "e_single_pixel_buffer.h" +#include "e_blender.h"