pepper: Add initial subsurface implementation
authorJaehoon Jeong <jh01.j@samsung.com>
Fri, 6 Nov 2015 05:55:27 +0000 (14:55 +0900)
committerJaehoon Jeong <jh01.j@samsung.com>
Fri, 6 Nov 2015 09:01:06 +0000 (18:01 +0900)
Change-Id: Icc0cc065a61d0cc46d58f58e7b740b86b7dcaa3d

src/lib/pepper/Makefile.am
src/lib/pepper/pepper-internal.h
src/lib/pepper/pepper.h
src/lib/pepper/subcompositor.c
src/lib/pepper/subsurface.c [new file with mode: 0644]
src/lib/pepper/surface.c

index d94cbbc353e3b12fbecdd2064724224c1c646b15..3084a0b63250bd73adf5e085a7374ad029deb180 100644 (file)
@@ -27,4 +27,5 @@ libpepper_la_SOURCES = pepper.h                 \
                        utils-map.c              \
                        utils-log.c              \
                        utils-vt.c               \
-                       subcompositor.c
+                       subcompositor.c          \
+                       subsurface.c
index 3abe89037f7df34545f5d39abe3267220c0f700d..8a6dbb07ad8602c30d2f1dde9ddb2257cb38e9de 100644 (file)
@@ -148,6 +148,12 @@ struct pepper_surface_state
     pepper_event_listener_t    *buffer_destroy_listener;
 };
 
+void
+pepper_surface_state_init(pepper_surface_state_t *state);
+
+void
+pepper_surface_state_fini(pepper_surface_state_t *state);
+
 struct pepper_surface
 {
     pepper_object_t         base;
@@ -180,6 +186,10 @@ struct pepper_surface
 
     char                   *role;
     pepper_list_t           view_list;
+
+    pepper_list_t           subsurface_list;
+    pepper_list_t           subsurface_pending_list;
+    pepper_subsurface_t    *sub;
 };
 
 pepper_surface_t *
@@ -234,6 +244,40 @@ pepper_subcompositor_create(pepper_compositor_t *compositor);
 void
 pepper_subcompositor_destroy(pepper_subcompositor_t *subcompositor);
 
+/* Subsurface */
+struct pepper_subsurface
+{
+    pepper_surface_t        *surface;
+    pepper_surface_t        *parent;
+    struct wl_resource      *resource;
+
+    double                   x, y;
+    pepper_list_t            parent_link;
+
+    /* This state is applied when the parent surface's wl_surface state is applied,
+     * regardless of the sub-surface's mode. */
+    struct
+    {
+        double               x, y;
+        pepper_list_t        parent_link;
+    } pending;
+
+    pepper_bool_t            synchronized;    /* commit behavior */
+
+    /* In sync mode, wl_surface.commit will apply the pending state into cache.
+     * And cached state will flush into surface's current when parent's wl_surface.commit called */
+    pepper_surface_state_t   cache;
+
+    pepper_event_listener_t *parent_destroy_listener;
+};
+
+pepper_subsurface_t *
+pepper_subsurface_create(pepper_surface_t *surface, pepper_surface_t *parent,
+                         struct wl_client *client, struct wl_resource *resource, uint32_t id);
+
+void
+pepper_subsurface_destroy(pepper_subsurface_t *subsurface);
+
 /* Input */
 struct pepper_pointer
 {
index 381b4b9a912adb53247fba0439b6cd266747f5b0..8eaa6090a481e83a34cb8152d5347cecc7d9487c 100644 (file)
@@ -92,6 +92,13 @@ typedef struct pepper_view              pepper_view_t;
  */
 typedef struct pepper_subcompositor     pepper_subcompositor_t;
 
+/**
+ * @typedef pepper_subsurface
+ *
+ * A #pepper_subsurface represents a wl_subsurface.
+ */
+typedef struct pepper_subsurface        pepper_subsurface_t;
+
 /**
  * @typedef pepper_seat_t
  *
index 6aeef955846269f9a5f2cc244468b0fbe6080cbb..289ae9eb4aeb947320776d9ce55f461b9b33c989 100644 (file)
@@ -13,7 +13,27 @@ subcompositor_get_subsurface(struct wl_client   *client,
                              struct wl_resource *surface_resource,
                              struct wl_resource *parent_resource)
 {
-    /* TODO */
+    pepper_subcompositor_t  *subcompositor = wl_resource_get_user_data(resource);
+    pepper_surface_t        *surface = wl_resource_get_user_data(surface_resource);
+    pepper_surface_t        *parent  = wl_resource_get_user_data(parent_resource);
+    pepper_subsurface_t     *subsurface;
+
+    if (surface->sub)
+    {
+        wl_resource_post_error(resource, WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE,
+                               "wl_subcompositor::get_subsurface() already requested");
+        return ;
+    }
+
+    if (surface == parent)
+    {
+        wl_resource_post_error(resource, WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE,
+                               "wl_subcompositor::get_subsurface() cannot assign parent for its own");
+        return ;
+    }
+
+    if (!pepper_subsurface_create(surface, parent, client, resource, id))
+        wl_resource_post_no_memory(resource);
 }
 
 static const struct wl_subcompositor_interface subcompositor_interface =
diff --git a/src/lib/pepper/subsurface.c b/src/lib/pepper/subsurface.c
new file mode 100644 (file)
index 0000000..ad46f2c
--- /dev/null
@@ -0,0 +1,136 @@
+#include "pepper-internal.h"
+
+static void
+subsurface_destroy(struct wl_client     *client,
+                   struct wl_resource   *resource)
+{
+    /* TODO */
+}
+
+static void
+subsurface_set_position(struct wl_client    *client,
+                        struct wl_resource  *resource,
+                        int32_t              x,
+                        int32_t              y)
+{
+    /* TODO */
+}
+
+static void
+subsurface_place_above(struct wl_client     *client,
+                       struct wl_resource   *resource,
+                       struct wl_resource   *sibling_resource)
+{
+    /* TODO */
+}
+
+static void
+subsurface_place_below(struct wl_client     *client,
+                       struct wl_resource   *resource,
+                       struct wl_resource   *sibling)
+{
+    /* TODO */
+}
+
+static void
+subsurface_set_sync(struct wl_client    *client,
+                    struct wl_resource  *resource)
+{
+    /* TODO */
+}
+
+static void
+subsurface_set_desync(struct wl_client      *client,
+                      struct wl_resource    *resource)
+{
+    /* TODO */
+}
+
+static struct wl_subsurface_interface subsurface_implementation =
+{
+    subsurface_destroy,
+    subsurface_set_position,
+    subsurface_place_above,
+    subsurface_place_below,
+    subsurface_set_sync,
+    subsurface_set_desync,
+};
+
+void
+pepper_subsurface_destroy(pepper_subsurface_t *subsurface)
+{
+    /* TODO */
+
+    pepper_surface_state_fini(&subsurface->cache);
+    pepper_list_remove(&subsurface->parent_link);
+    pepper_list_remove(&subsurface->pending.parent_link);
+
+    free(subsurface);
+}
+
+static void
+subsurface_resource_destroy_handler(struct wl_resource *resource)
+{
+    pepper_subsurface_t *sub = wl_resource_get_user_data(resource);
+    pepper_subsurface_destroy(sub);
+}
+
+static void
+handle_parent_destroy(pepper_event_listener_t *listener,
+                      pepper_object_t *object, uint32_t id, void *info, void *data)
+{
+    /* TODO */
+}
+
+pepper_subsurface_t *
+pepper_subsurface_create(pepper_surface_t   *surface,
+                         pepper_surface_t   *parent,
+                         struct wl_client   *client,
+                         struct wl_resource *resource,
+                         uint32_t            id)
+{
+    pepper_subsurface_t *subsurface = NULL;
+
+    if (!pepper_surface_set_role(surface, "wl_subsurface"))
+    {
+        wl_resource_post_error(resource, WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE,
+                               "cannot assign wl_subsurface role");
+        return NULL;
+    }
+
+    subsurface = calloc(1, sizeof(pepper_subsurface_t));
+    PEPPER_CHECK(subsurface, goto error, "calloc() failed.\n");
+
+    subsurface->resource = wl_resource_create(client, &wl_subsurface_interface,
+                                           wl_resource_get_version(resource), id);
+    PEPPER_CHECK(subsurface->resource, goto error, "wl_resource_create() failed\n");
+
+    wl_resource_set_implementation(subsurface->resource, &subsurface_implementation, subsurface,
+                                   subsurface_resource_destroy_handler);
+
+    subsurface->surface      = surface;
+    subsurface->parent       = parent;
+    subsurface->synchronized = PEPPER_TRUE;
+
+    subsurface->x            = subsurface->y         = 0.f;
+    subsurface->pending.x    = subsurface->pending.y = 0.f;
+
+    pepper_surface_state_init(&subsurface->cache);
+
+    pepper_object_add_event_listener(&parent->base, PEPPER_EVENT_OBJECT_DESTROY, 0,
+                                     handle_parent_destroy, subsurface);
+
+    /* subsurface_list is z-order sorted, youngest child is top-most */
+    pepper_list_insert(&parent->subsurface_list, &subsurface->parent_link);
+    pepper_list_insert(&parent->subsurface_pending_list, &subsurface->pending.parent_link);
+
+    surface->sub = subsurface;
+
+    return subsurface;
+
+error:
+    if (subsurface)
+        pepper_subsurface_destroy(subsurface);
+
+    return NULL;
+}
index 7d40dfe962a36faa9e522708e1c7ccaa1c18ed47..827ed1768be418dea0afbd95e794ca91c2e10e16 100644 (file)
@@ -60,7 +60,7 @@ surface_handle_buffer_destroy(pepper_event_listener_t *listener,
     surface_update_size(surface);
 }
 
-static void
+void
 pepper_surface_state_init(pepper_surface_state_t *state)
 {
     state->buffer = NULL;
@@ -76,7 +76,7 @@ pepper_surface_state_init(pepper_surface_state_t *state)
     wl_list_init(&state->frame_callback_list);
 }
 
-static void
+void
 pepper_surface_state_fini(pepper_surface_state_t *state)
 {
     struct wl_resource *callback, *next;
@@ -307,6 +307,8 @@ pepper_surface_create(pepper_compositor_t *compositor,
 
     wl_list_init(&surface->frame_callback_list);
     pepper_list_init(&surface->view_list);
+    pepper_list_init(&surface->subsurface_list);
+    pepper_list_init(&surface->subsurface_pending_list);
     pepper_object_emit_event(&compositor->base, PEPPER_EVENT_COMPOSITOR_SURFACE_ADD, surface);
 
     return surface;