devilhorns pushed a commit to branch master.

commit 65fb88c7731ce6ae3b0145cd3bdc4866b15b3fbb
Author: Chris Michael <[email protected]>
Date:   Tue Apr 9 11:31:50 2013 +0100

    Add code to create, destroy, and otherwise handle the wayland region
    interface and wayland surface interface.
    
    Signed-off-by: Chris Michael <[email protected]>
---
 src/bin/e_comp_wl.c | 400 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 400 insertions(+)

diff --git a/src/bin/e_comp_wl.c b/src/bin/e_comp_wl.c
index 6210ac2..f00049c 100644
--- a/src/bin/e_comp_wl.c
+++ b/src/bin/e_comp_wl.c
@@ -36,6 +36,26 @@ static void _e_comp_wl_pointer_unmap(E_Wayland_Surface *ews);
 /* pointer interface prototypes */
 static void _e_comp_wl_pointer_cb_cursor_set(struct wl_client *client, struct 
wl_resource *resource, unsigned int serial, struct wl_resource 
*surface_resource, int x, int y);
 
+/* region interface prototypes */
+static void _e_comp_wl_region_cb_destroy(struct wl_client *client EINA_UNUSED, 
struct wl_resource *resource);
+static void _e_comp_wl_region_cb_add(struct wl_client *client EINA_UNUSED, 
struct wl_resource *resource, int x, int y, int w, int h);
+static void _e_comp_wl_region_cb_subtract(struct wl_client *client 
EINA_UNUSED, struct wl_resource *resource, int x, int y, int w, int h);
+
+/* surface function prototypes */
+static void _e_comp_wl_surface_cb_pending_buffer_destroy(struct wl_listener 
*listener, void *data EINA_UNUSED);
+static void _e_comp_wl_surface_cb_frame_destroy(struct wl_resource *resource);
+static void _e_comp_wl_surface_buffer_reference(E_Wayland_Surface *ews, struct 
wl_buffer *buffer);
+static void _e_comp_wl_surface_buffer_reference_cb_destroy(struct wl_listener 
*listener, void *data EINA_UNUSED);
+
+/* surface interface prototypes */
+static void _e_comp_wl_surface_cb_destroy(struct wl_client *client 
EINA_UNUSED, struct wl_resource *resource);
+static void _e_comp_wl_surface_cb_attach(struct wl_client *client EINA_UNUSED, 
struct wl_resource *resource, struct wl_resource *buffer_resource, int x, int 
y);
+static void _e_comp_wl_surface_cb_damage(struct wl_client *client EINA_UNUSED, 
struct wl_resource *resource, int x, int y, int w, int h);
+static void _e_comp_wl_surface_cb_frame(struct wl_client *client, struct 
wl_resource *resource, unsigned int callback);
+static void _e_comp_wl_surface_cb_opaque_region_set(struct wl_client *client 
EINA_UNUSED, struct wl_resource *resource, struct wl_resource *region_resource);
+static void _e_comp_wl_surface_cb_input_region_set(struct wl_client *client 
EINA_UNUSED, struct wl_resource *resource, struct wl_resource *region_resource);
+static void _e_comp_wl_surface_cb_commit(struct wl_client *client EINA_UNUSED, 
struct wl_resource *resource);
+
 /* local wayland interfaces */
 static const struct wl_compositor_interface _e_compositor_interface = 
 {
@@ -55,6 +75,25 @@ static const struct wl_pointer_interface 
_e_pointer_interface =
    _e_comp_wl_pointer_cb_cursor_set
 };
 
+static const struct wl_region_interface _e_region_interface = 
+{
+   _e_comp_wl_region_cb_destroy,
+   _e_comp_wl_region_cb_add,
+   _e_comp_wl_region_cb_subtract
+};
+
+static const struct wl_surface_interface _e_surface_interface = 
+{
+   _e_comp_wl_surface_cb_destroy,
+   _e_comp_wl_surface_cb_attach,
+   _e_comp_wl_surface_cb_damage,
+   _e_comp_wl_surface_cb_frame,
+   _e_comp_wl_surface_cb_opaque_region_set,
+   _e_comp_wl_surface_cb_input_region_set,
+   _e_comp_wl_surface_cb_commit,
+   NULL // cb_buffer_transform_set
+};
+
 /* local variables */
 
 /* external variables */
@@ -255,25 +294,146 @@ _e_comp_wl_cb_idle(void *data EINA_UNUSED)
 static void 
 _e_comp_wl_cb_surface_create(struct wl_client *client, struct wl_resource 
*resource, unsigned int id)
 {
+   E_Wayland_Surface *ews = NULL;
+
+   /* try to allocate space for a new surface */
+   if (!(ews = E_NEW(E_Wayland_Surface, 1)))
+     {
+        wl_resource_post_no_memory(resource);
+        return;
+     }
 
+   /* initialize the destroy signal */
+   wl_signal_init(&ews->wl.surface.resource.destroy_signal);
+
+   /* initialize the link */
+   wl_list_init(&ews->wl.link);
+
+   /* initialize the lists of frames */
+   wl_list_init(&ews->wl.frames);
+   wl_list_init(&ews->pending.frames);
+
+   /* set destroy function for pending buffers */
+   ews->pending.buffer_destroy.notify = 
+     _e_comp_wl_surface_cb_pending_buffer_destroy;
+
+   /* initialize regions */
+   pixman_region32_init(&ews->region.opaque);
+   pixman_region32_init(&ews->region.damage);
+   pixman_region32_init(&ews->region.clip);
+   pixman_region32_init_rect(&ews->region.input, INT32_MIN, INT32_MIN, 
+                             UINT32_MAX, UINT32_MAX);
+
+   /* initialize pending regions */
+   pixman_region32_init(&ews->pending.opaque);
+   pixman_region32_init(&ews->pending.damage);
+   pixman_region32_init_rect(&ews->pending.input, INT32_MIN, INT32_MIN, 
+                             UINT32_MAX, UINT32_MAX);
+
+   /* set some properties of the surface */
+   ews->wl.surface.resource.destroy = _e_comp_wl_cb_surface_destroy;
+   ews->wl.surface.resource.object.id = id;
+   ews->wl.surface.resource.object.interface = &wl_surface_interface;
+   ews->wl.surface.resource.object.implementation = 
+     (void (**)(void))&_e_surface_interface;
+   ews->wl.surface.resource.data = ews;
+
+   /* add this surface to the client */
+   wl_client_add_resource(client, &ews->wl.surface.resource);
+
+   /* add this surface to the list of surfaces */
+   _e_wl_comp->surfaces = eina_list_append(_e_wl_comp->surfaces, ews);
 }
 
 static void 
 _e_comp_wl_cb_surface_destroy(struct wl_resource *resource)
 {
+   E_Wayland_Surface *ews = NULL;
+   E_Wayland_Surface_Frame_Callback *cb = NULL, *ncb = NULL;
+
+   /* try to get the surface from this resource */
+   if (!(ews = container_of(resource, E_Wayland_Surface, wl.surface.resource)))
+     return;
+
+   /* if this surface is mapped, unmap it */
+   if (ews->mapped)
+     {
+        if (ews->unmap) ews->unmap(ews);
+     }
+
+   /* loop any pending surface frame callbacks and destroy them */
+   wl_list_for_each_safe(cb, ncb, &ews->pending.frames, wl.link)
+     wl_resource_destroy(&cb->wl.resource);
+
+   /* clear any pending regions */
+   pixman_region32_fini(&ews->pending.damage);
+   pixman_region32_fini(&ews->pending.opaque);
+   pixman_region32_fini(&ews->pending.input);
 
+   /* remove the pending buffer from the list */
+   if (ews->pending.buffer)
+     wl_list_remove(&ews->pending.buffer_destroy.link);
+
+   /* dereference any existing buffers */
+   _e_comp_wl_surface_buffer_reference(ews, NULL);
+
+   /* clear any active regions */
+   pixman_region32_fini(&ews->region.damage);
+   pixman_region32_fini(&ews->region.opaque);
+   pixman_region32_fini(&ews->region.input);
+   pixman_region32_fini(&ews->region.clip);
+
+   /* loop any active surface frame callbacks and destroy them */
+   wl_list_for_each_safe(cb, ncb, &ews->wl.frames, wl.link)
+     wl_resource_destroy(&cb->wl.resource);
+
+   /* remove this surface from the compositor's list of surfaces */
+   _e_wl_comp->surfaces = eina_list_remove(_e_wl_comp->surfaces, ews);
+
+   /* free the allocated surface structure */
+   E_FREE(ews);
 }
 
 static void 
 _e_comp_wl_cb_region_create(struct wl_client *client, struct wl_resource 
*resource, unsigned int id)
 {
+   E_Wayland_Region *ewr = NULL;
+
+   /* try to allocate space for a new region */
+   if (!(ewr = E_NEW_RAW(E_Wayland_Region, 1)))
+     {
+        wl_resource_post_no_memory(resource);
+        return;
+     }
+
+   pixman_region32_init(&ewr->region);
+
+   /* set some properties of the region */
+   ewr->wl.resource.destroy = _e_comp_wl_cb_region_destroy;
+   ewr->wl.resource.object.id = id;
+   ewr->wl.resource.object.interface = &wl_region_interface;
+   ewr->wl.resource.object.implementation = 
+     (void (**)(void))&_e_region_interface;
+   ewr->wl.resource.data = ewr;
 
+   /* add this region to the client */
+   wl_client_add_resource(client, &ewr->wl.resource);
 }
 
 static void 
 _e_comp_wl_cb_region_destroy(struct wl_resource *resource)
 {
+   E_Wayland_Region *ewr = NULL;
 
+   /* try to get the region from this resource */
+   if (!(ewr = container_of(resource, E_Wayland_Region, wl.resource)))
+     return;
+
+   /* tell pixman we are finished with this region */
+   pixman_region32_fini(&ewr->region);
+
+   /* free the allocated region structure */
+   E_FREE(ewr);
 }
 
 /* input functions */
@@ -876,3 +1036,243 @@ _e_comp_wl_pointer_cb_cursor_set(struct wl_client 
*client, struct wl_resource *r
         _e_comp_wl_pointer_configure(ews, 0, 0, bw, bh);
      }
 }
+
+/* region interface functions */
+static void 
+_e_comp_wl_region_cb_destroy(struct wl_client *client EINA_UNUSED, struct 
wl_resource *resource)
+{
+   wl_resource_destroy(resource);
+}
+
+static void 
+_e_comp_wl_region_cb_add(struct wl_client *client EINA_UNUSED, struct 
wl_resource *resource, int x, int y, int w, int h)
+{
+   E_Wayland_Region *ewr = NULL;
+
+   /* try to cast the resource data to our region structure */
+   if (!(ewr = resource->data)) return;
+
+   /* tell pixman to union this region with any previous one */
+   pixman_region32_union_rect(&ewr->region, &ewr->region, x, y, w, h);
+}
+
+static void 
+_e_comp_wl_region_cb_subtract(struct wl_client *client EINA_UNUSED, struct 
wl_resource *resource, int x, int y, int w, int h)
+{
+   E_Wayland_Region *ewr = NULL;
+   pixman_region32_t region;
+
+   /* try to cast the resource data to our region structure */
+   if (!(ewr = resource->data)) return;
+
+   /* ask pixman to create a new temporary rect */
+   pixman_region32_init_rect(&region, x, y, w, h);
+
+   /* ask pixman to subtract this temp rect from the existing region */
+   pixman_region32_subtract(&ewr->region, &ewr->region, &region);
+
+   /* tell pixman we are finished with the temporary rect */
+   pixman_region32_fini(&region);
+}
+
+/* surface functions */
+static void 
+_e_comp_wl_surface_cb_pending_buffer_destroy(struct wl_listener *listener, 
void *data EINA_UNUSED)
+{
+   E_Wayland_Surface *ews = NULL;
+
+   /* try to get the surface from this listener */
+   if (!(ews = container_of(listener, E_Wayland_Surface, 
+                            pending.buffer_destroy)))
+     return;
+
+   /* set surface pending buffer to null */
+   ews->pending.buffer = NULL;
+}
+
+static void 
+_e_comp_wl_surface_cb_frame_destroy(struct wl_resource *resource)
+{
+   E_Wayland_Surface_Frame_Callback *cb = NULL;
+
+   /* try to cast the resource data to our surface frame callback structure */
+   if (!(cb = resource->data)) return;
+
+   wl_list_remove(&cb->wl.link);
+
+   /* free the allocated callback structure */
+   E_FREE(cb);
+}
+
+static void 
+_e_comp_wl_surface_buffer_reference(E_Wayland_Surface *ews, struct wl_buffer 
*buffer)
+{
+   /* check for valid surface */
+   if (!ews) return;
+
+   /* if the surface already has a buffer referenced and it is not the 
+    * same as the one passed in */
+   if ((ews->reference.buffer) && (buffer != ews->reference.buffer))
+     {
+        /* decrement the reference buffer busy count */
+        ews->reference.buffer->busy_count--;
+
+        /* if the compositor is finished with this referenced buffer, then 
+         * we need to release it */
+        if (ews->reference.buffer->busy_count == 0)
+          {
+             if (ews->reference.buffer->resource.client)
+               wl_resource_queue_event(&ews->reference.buffer->resource, 
+                                       WL_BUFFER_RELEASE);
+          }
+
+        /* remove the destroy link on the referenced buffer */
+        wl_list_remove(&ews->reference.buffer_destroy.link);
+     }
+
+   /* if we are passed in a buffer and it is not the one referenced */
+   if ((buffer) && (buffer != ews->reference.buffer))
+     {
+        /* increment busy count */
+        buffer->busy_count++;
+
+        /* setup destroy signal */
+        wl_signal_add(&buffer->resource.destroy_signal, 
+                      &ews->reference.buffer_destroy);
+     }
+
+   /* set buffer reference */
+   ews->reference.buffer = buffer;
+
+   /* setup destroy listener */
+   ews->reference.buffer_destroy.notify = 
+     _e_comp_wl_surface_buffer_reference_cb_destroy;
+}
+
+static void 
+_e_comp_wl_surface_buffer_reference_cb_destroy(struct wl_listener *listener, 
void *data EINA_UNUSED)
+{
+   E_Wayland_Surface *ews = NULL;
+
+   /* try to get the surface from this listener */
+   ews = container_of(listener, E_Wayland_Surface, reference.buffer_destroy);
+   if (!ews) return;
+
+   /* set referenced buffer to null */
+   ews->reference.buffer = NULL;
+}
+
+/* surface interface functionss */
+static void 
+_e_comp_wl_surface_cb_destroy(struct wl_client *client EINA_UNUSED, struct 
wl_resource *resource)
+{
+   wl_resource_destroy(resource);
+}
+
+static void 
+_e_comp_wl_surface_cb_attach(struct wl_client *client EINA_UNUSED, struct 
wl_resource *resource, struct wl_resource *buffer_resource, int x, int y)
+{
+
+}
+
+static void 
+_e_comp_wl_surface_cb_damage(struct wl_client *client EINA_UNUSED, struct 
wl_resource *resource, int x, int y, int w, int h)
+{
+   E_Wayland_Surface *ews = NULL;
+
+   /* try to cast the resource data to our surface structure */
+   if (!(ews = resource->data)) return;
+
+   /* tell pixman to add this damage to pending */
+   pixman_region32_union_rect(&ews->pending.damage, &ews->pending.damage, 
+                              x, y, w, h);
+}
+
+static void 
+_e_comp_wl_surface_cb_frame(struct wl_client *client, struct wl_resource 
*resource, unsigned int callback)
+{
+   E_Wayland_Surface *ews = NULL;
+   E_Wayland_Surface_Frame_Callback *cb = NULL;
+
+   /* try to cast the resource data to our surface structure */
+   if (!(ews = resource->data)) return;
+
+   /* try to allocate space for a new frame callback */
+   if (!(cb = E_NEW(E_Wayland_Surface_Frame_Callback, 1)))
+     {
+        wl_resource_post_no_memory(resource);
+        return;
+     }
+
+   /* set some properties on the callback */
+   cb->wl.resource.object.interface = &wl_callback_interface;
+   cb->wl.resource.object.id = callback;
+   cb->wl.resource.destroy = _e_comp_wl_surface_cb_frame_destroy;
+   cb->wl.resource.client = client;
+   cb->wl.resource.data = cb;
+
+   /* add frame callback to client */
+   wl_client_add_resource(client, &cb->wl.resource);
+
+   /* add this callback to the surface list of pending frames */
+   wl_list_insert(ews->pending.frames.prev, &cb->wl.link);
+}
+
+static void 
+_e_comp_wl_surface_cb_opaque_region_set(struct wl_client *client EINA_UNUSED, 
struct wl_resource *resource, struct wl_resource *region_resource)
+{
+   E_Wayland_Surface *ews = NULL;
+
+   /* try to cast the resource data to our surface structure */
+   if (!(ews = resource->data)) return;
+
+   if (region_resource)
+     {
+        E_Wayland_Region *ewr = NULL;
+
+        /* copy this region to the pending opaque region */
+        if ((ewr = region_resource->data))
+          pixman_region32_copy(&ews->pending.opaque, &ewr->region);
+     }
+   else
+     {
+        /* tell pixman we are finished with this region */
+        pixman_region32_fini(&ews->pending.opaque);
+
+        /* reinitalize the pending opaque region */
+        pixman_region32_init(&ews->pending.opaque);
+     }
+}
+
+static void 
+_e_comp_wl_surface_cb_input_region_set(struct wl_client *client EINA_UNUSED, 
struct wl_resource *resource, struct wl_resource *region_resource)
+{
+   E_Wayland_Surface *ews = NULL;
+
+   /* try to cast the resource data to our surface structure */
+   if (!(ews = resource->data)) return;
+
+   if (region_resource)
+     {
+        E_Wayland_Region *ewr = NULL;
+
+        /* copy this region to the pending input region */
+        if ((ewr = region_resource->data))
+          pixman_region32_copy(&ews->pending.input, &ewr->region);
+     }
+   else
+     {
+        /* tell pixman we are finished with this region */
+        pixman_region32_fini(&ews->pending.input);
+
+        /* reinitalize the pending input region */
+        pixman_region32_init_rect(&ews->pending.input, INT32_MIN, INT32_MIN, 
+                                  UINT32_MAX, UINT32_MAX);
+     }
+}
+
+static void 
+_e_comp_wl_surface_cb_commit(struct wl_client *client EINA_UNUSED, struct 
wl_resource *resource)
+{
+
+}

-- 

------------------------------------------------------------------------------
Precog is a next-generation analytics platform capable of advanced
analytics on semi-structured data. The platform includes APIs for building
apps and a phenomenal toolset for data science. Developers can use
our toolset for easy data analysis & visualization. Get a free account!
http://www2.precog.com/precogplatform/slashdotnewsletter

Reply via email to