e_blender: add first implementation of wtz-blender protocol 94/296294/1
authorChangyeon Lee <cyeon.lee@samsung.com>
Wed, 5 Jul 2023 07:02:53 +0000 (16:02 +0900)
committerTizen Window System <tizen.windowsystem@gmail.com>
Tue, 25 Jul 2023 04:45:13 +0000 (13:45 +0900)
Change-Id: I0da822db416ca4a81c5d5d15ae78dcdf05e2da5a

configure.ac
packaging/enlightenment.spec
src/bin/Makefile.mk
src/bin/e_blender.c [new file with mode: 0644]
src/bin/e_blender.h [new file with mode: 0644]
src/bin/e_comp_object.c
src/bin/e_comp_object.h
src/bin/e_comp_wl.c
src/bin/e_hwc_window.c
src/bin/e_includes.h

index abd871d..943840f 100755 (executable)
@@ -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])
index 64be05c..a94a93a 100644 (file)
@@ -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
index 2448908..a928aac 100644 (file)
@@ -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 (file)
index 0000000..093f388
--- /dev/null
@@ -0,0 +1,361 @@
+#include "e.h"
+#include <wtz-blender-server-protocol.h>
+
+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 (file)
index 0000000..96a36c3
--- /dev/null
@@ -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
index 7769832..49f7d44 100644 (file)
@@ -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);
+}
index dd7f10f..dc786f8 100644 (file)
@@ -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
 
index 02da8ad..3054773 100644 (file)
@@ -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();
index c90e395..2058618 100644 (file)
@@ -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";
     }
index a8ea192..c33be3f 100644 (file)
@@ -88,3 +88,4 @@
 #include "e_comp_wl_renderer.h"
 #include "e_map.h"
 #include "e_single_pixel_buffer.h"
+#include "e_blender.h"