Implement buffer_reference to fix client resizing issue
authorChris Michael <cp.michael@samsung.com>
Wed, 25 Feb 2015 18:14:30 +0000 (13:14 -0500)
committerChris Michael <cp.michael@samsung.com>
Thu, 26 Feb 2015 20:33:40 +0000 (15:33 -0500)
Signed-off-by: Chris Michael <cp.michael@samsung.com>
src/bin/e_comp_wl.c
src/bin/e_pixmap.c

index 9e22899c42027f1f3dba0c01aac0af360713f4a0..faf35542bbf27aa08aa193f9e9df55f5b64d6dd7 100644 (file)
@@ -634,7 +634,27 @@ _e_comp_wl_evas_cb_color_set(void *data, Evas_Object *obj, void *event EINA_UNUS
    ec->netwm.opacity_changed = EINA_TRUE;
 }
 
-static void
+static void 
+_e_comp_wl_buffer_reference_cb_destroy(struct wl_listener *listener, void *data)
+{
+   E_Comp_Wl_Buffer_Ref *ref;
+
+   ref = container_of(listener, E_Comp_Wl_Buffer_Ref, destroy_listener);
+   if ((E_Comp_Wl_Buffer *)data != ref->buffer) return;
+   ref->buffer = NULL;
+}
+
+static void 
+_e_comp_wl_buffer_cb_destroy(struct wl_listener *listener, void *data EINA_UNUSED)
+{
+   E_Comp_Wl_Buffer *buffer;
+
+   buffer = container_of(listener, E_Comp_Wl_Buffer, destroy_listener);
+   wl_signal_emit(&buffer->destroy_signal, buffer);
+   free(buffer);
+}
+
+static void 
 _e_comp_wl_client_evas_init(E_Client *ec)
 {
    if (ec->comp_data->evas_init) return;
@@ -868,102 +888,299 @@ _e_comp_wl_cb_input_event(void *data EINA_UNUSED, int type, void *ev)
    return ECORE_CALLBACK_RENEW;
 }
 
-static void
-_e_comp_wl_surface_cb_destroy(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
+static void 
+_e_comp_wl_surface_state_size_update(E_Client *ec, E_Comp_Wl_Surface_State *state)
 {
-   E_Pixmap *ep;
+   int w = 0, h = 0;
+   double scale = 0.0;
 
-   DBG("Surface Cb Destroy: %d", wl_resource_get_id(resource));
+   if (!ec->comp_data->buffer_ref.buffer)
+     {
+        state->bw = 0;
+        state->bh = 0;
+        return;
+     }
 
-   /* unset the pixmap resource */
-   if ((ep = wl_resource_get_user_data(resource)))
-     e_pixmap_resource_set(ep, NULL);
+   scale = e_comp->wl_comp_data->output.scale;
+   switch (e_comp->wl_comp_data->output.transform)
+     {
+      case WL_OUTPUT_TRANSFORM_90:
+      case WL_OUTPUT_TRANSFORM_270:
+      case WL_OUTPUT_TRANSFORM_FLIPPED_90:
+      case WL_OUTPUT_TRANSFORM_FLIPPED_270:
+        w = ec->comp_data->buffer_ref.buffer->h / scale;
+        h = ec->comp_data->buffer_ref.buffer->w / scale;
+        break;
+      default:
+        w = ec->comp_data->buffer_ref.buffer->w / scale;
+        h = ec->comp_data->buffer_ref.buffer->h / scale;
+        break;
+     }
 
-   /* destroy this resource */
-   wl_resource_destroy(resource);
+   state->bw = w;
+   state->bh = h;
 }
 
-static void
-_e_comp_wl_surface_cb_attach(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, struct wl_resource *buffer_resource, int32_t sx, int32_t sy)
+static void 
+_e_comp_wl_surface_state_cb_buffer_destroy(struct wl_listener *listener, void *data EINA_UNUSED)
 {
-   E_Pixmap *ep;
-   E_Client *ec;
+   E_Comp_Wl_Surface_State *state;
 
-   /* get the e_pixmap reference */
-   if (!(ep = wl_resource_get_user_data(resource))) return;
+   state = 
+     container_of(listener, E_Comp_Wl_Surface_State, buffer_destroy_listener);
+   state->buffer = NULL;
+}
 
-   /* try to find the associated e_client */
-   if (!(ec = e_pixmap_client_get(ep)))
+static void 
+_e_comp_wl_surface_state_init(E_Comp_Wl_Surface_State *state, int w, int h)
+{
+   state->new_attach = EINA_FALSE;
+   state->buffer = NULL;
+   state->buffer_destroy_listener.notify = 
+     _e_comp_wl_surface_state_cb_buffer_destroy;
+   state->sx = state->sy = 0;
+
+   state->input = eina_tiler_new(w, h);
+   eina_tiler_tile_size_set(state->input, 1, 1);
+
+   state->opaque = eina_tiler_new(w, h);
+   eina_tiler_tile_size_set(state->opaque, 1, 1);
+}
+
+static void 
+_e_comp_wl_surface_state_finish(E_Comp_Wl_Surface_State *state)
+{
+   struct wl_resource *cb;
+   Eina_Rectangle *dmg;
+
+   EINA_LIST_FREE(state->frames, cb)
+     wl_resource_destroy(cb);
+
+   EINA_LIST_FREE(state->damages, dmg)
+     eina_rectangle_free(dmg);
+
+   if (state->opaque) eina_tiler_free(state->opaque);
+   state->opaque = NULL;
+
+   if (state->input) eina_tiler_free(state->input);
+   state->input = NULL;
+
+   if (state->buffer) wl_list_remove(&state->buffer_destroy_listener.link);
+   state->buffer = NULL;
+}
+
+static void 
+_e_comp_wl_surface_state_buffer_set(E_Comp_Wl_Surface_State *state, E_Comp_Wl_Buffer *buffer)
+{
+   if (state->buffer == buffer) return;
+   if (state->buffer) 
+     wl_list_remove(&state->buffer_destroy_listener.link);
+   state->buffer = buffer;
+   if (state->buffer) 
+     wl_signal_add(&state->buffer->destroy_signal, 
+                   &state->buffer_destroy_listener);
+}
+
+static void 
+_e_comp_wl_surface_state_commit(E_Client *ec, E_Comp_Wl_Surface_State *state)
+{
+   Eina_Bool first = EINA_FALSE;
+   Eina_Rectangle *dmg;
+   Eina_List *l;
+   struct wl_resource *cb;
+
+   first = !e_pixmap_usable_get(ec->pixmap);
+
+   if (state->new_attach)
+     e_comp_wl_surface_attach(ec, state->buffer);
+
+   _e_comp_wl_surface_state_buffer_set(state, NULL);
+
+   if (!e_pixmap_usable_get(ec->pixmap))
      {
-        ERR("\t\tCould not find client from pixmap %p", ep);
-        return;
+        if (ec->comp_data->mapped)
+          {
+             if ((ec->comp_data->shell.surface) && (ec->comp_data->shell.unmap))
+               ec->comp_data->shell.unmap(ec->comp_data->shell.surface);
+             else
+               {
+                  evas_object_hide(ec->frame);
+                  ec->comp_data->mapped = evas_object_visible_get(ec->frame);
+               }
+          }
+     }
+   else
+     {
+        if (!ec->comp_data->mapped)
+          {
+             if ((ec->comp_data->shell.surface) && (ec->comp_data->shell.map))
+               ec->comp_data->shell.map(ec->comp_data->shell.surface);
+             else
+               {
+                  evas_object_show(ec->frame);
+                  ec->comp_data->mapped = evas_object_visible_get(ec->frame);
+               }
+          }
      }
 
-   /* check if client is being deleted */
-   if (e_object_is_del(E_OBJECT(ec)))
+   if (state->new_attach)
      {
-        DBG("\tE_Client scheduled for deletion");
-        return;
+        Eina_Bool placed = EINA_TRUE;
+        int x = 0, y = 0;
+
+        _e_comp_wl_surface_state_size_update(ec, &ec->comp_data->pending);
+
+        if (ec->changes.pos)
+          e_comp_object_frame_xy_adjust(ec->frame, ec->x, ec->y, &x, &y);
+        else
+          x = ec->client.x, y = ec->client.y;
+
+        if (ec->new_client) placed = ec->placed;
+
+        if ((ec->comp_data->shell.surface) && (ec->comp_data->shell.configure))
+          ec->comp_data->shell.configure(ec->comp_data->shell.surface, 
+                                         x, y, state->bw, state->bh);
+        else
+          e_client_util_move_resize_without_frame(ec, x, y, state->bw, state->bh);
+
+        if (ec->new_client) 
+          ec->placed = placed;
+        else if ((first) && (ec->placed))
+          {
+             ec->x = ec->y = 0;
+             ec->placed = EINA_FALSE;
+             ec->new_client = EINA_TRUE;
+          }
      }
 
-   /* check for valid comp_data */
-   if (!ec->comp_data)
+   state->sx = 0;
+   state->sy = 0;
+   state->new_attach = EINA_FALSE;
+
+   if (!ec->comp_data->mapped) goto unmapped;
+
+   /* put state damages into surface */
+   if ((!ec->comp->nocomp) && (ec->frame))
      {
-        ERR("\tE_Client has no comp data");
-        return;
+        EINA_LIST_FREE(state->damages, dmg)
+          {
+             e_comp_object_damage(ec->frame, dmg->x, dmg->y, dmg->w, dmg->h);
+             eina_rectangle_free(dmg);
+          }
      }
 
-   /* DBG("Surface Attach: %d", wl_resource_get_id(resource)); */
+   /* put state opaque into surface */
+   if (state->opaque)
+     {
+        Eina_Rectangle *rect;
+        Eina_Iterator *itr;
 
-   /* reset client pending information */
-   ec->comp_data->pending.x = sx;
-   ec->comp_data->pending.y = sy;
-   ec->comp_data->pending.w = 0;
-   ec->comp_data->pending.h = 0;
-   ec->comp_data->pending.buffer = buffer_resource;
-   ec->comp_data->pending.new_attach = EINA_TRUE;
+        itr = eina_tiler_iterator_new(state->opaque);
+        EINA_ITERATOR_FOREACH(itr, rect)
+          {
+             e_pixmap_image_opaque_set(ec->pixmap, rect->x, rect->y, 
+                                       rect->w, rect->h);
+             break;
+          }
 
-   if (buffer_resource)
+        eina_iterator_free(itr);
+     }
+   else
+     e_pixmap_image_opaque_set(ec->pixmap, 0, 0, 0, 0);
+
+   /* put state input into surface */
+   if (state->input)
      {
-        struct wl_shm_buffer *shmb;
+        Eina_Tiler *src, *tmp;
 
-        /* check for this resource being a shm buffer */
-        if ((shmb = wl_shm_buffer_get(buffer_resource)))
+        tmp = eina_tiler_new(state->bw, state->bh);
+        eina_tiler_tile_size_set(tmp, 1, 1);
+        eina_tiler_rect_add(tmp, 
+                            &(Eina_Rectangle){0, 0, state->bw, state->bh});
+        if ((src = eina_tiler_intersection(state->input, tmp)))
           {
-             /* update pending size */
-             ec->comp_data->pending.w = wl_shm_buffer_get_width(shmb);
-             ec->comp_data->pending.h = wl_shm_buffer_get_height(shmb);
+             Eina_Rectangle *rect;
+             Eina_Iterator *itr;
+
+             itr = eina_tiler_iterator_new(src);
+             EINA_ITERATOR_FOREACH(itr, rect)
+               e_comp_object_input_area_set(ec->frame, rect->x, rect->y, 
+                                            rect->w, rect->h);
+
+             eina_iterator_free(itr);
+             eina_tiler_free(src);
           }
+        else
+          e_comp_object_input_area_set(ec->frame, 0, 0, ec->w, ec->h);
+
+        eina_tiler_free(tmp);
      }
+
+   /* insert state frame callbacks into comp_data->frames
+    * NB: This clears state->frames list */
+   EINA_LIST_FOREACH(state->frames, l, cb)
+     eina_list_move(&ec->comp_data->frames, &state->frames, cb);
+
+   return;
+
+unmapped:
+   /* clear pending damages */
+   EINA_LIST_FREE(state->damages, dmg)
+     eina_rectangle_free(dmg);
+
+   /* clear input tiler */
+   if (state->input)
+     eina_tiler_clear(state->input);
 }
 
-static void
-_e_comp_wl_surface_cb_damage(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, int32_t x, int32_t y, int32_t w, int32_t h)
+static void 
+_e_comp_wl_surface_cb_destroy(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
+{
+   DBG("Surface Cb Destroy: %d", wl_resource_get_id(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, int32_t sx, int32_t sy)
 {
    E_Pixmap *ep;
    E_Client *ec;
-   Eina_Rectangle *dmg = NULL;
+   E_Comp_Wl_Buffer *buffer = NULL;
 
-   /* get the e_pixmap reference */
    if (!(ep = wl_resource_get_user_data(resource))) return;
+   if (!(ec = e_pixmap_client_get(ep))) return;
+   if (e_object_is_del(E_OBJECT(ec))) return;
 
-   /* try to find the associated e_client */
-   if (!(ec = e_pixmap_client_get(ep)))
+   if (buffer_resource)
      {
-        ERR("\tCould not find client from pixmap %p", ep);
-        return;
+        if (!(buffer = e_comp_wl_buffer_get(buffer_resource)))
+          {
+             ERR("Could not get buffer from resource");
+             wl_client_post_no_memory(client);
+             return;
+          }
      }
 
-   if (e_object_is_del(E_OBJECT(ec))) return;
-   if (!ec->comp_data) return;
+   _e_comp_wl_surface_state_buffer_set(&ec->comp_data->pending, buffer);
 
-   /* DBG("Surface Cb Damage: %d", wl_resource_get_id(resource)); */
-   /* DBG("\tGeom: %d %d %d %d", x, y, w, h); */
+   ec->comp_data->pending.sx = sx;
+   ec->comp_data->pending.sy = sy;
+   ec->comp_data->pending.new_attach = EINA_TRUE;
+}
+
+static void 
+_e_comp_wl_surface_cb_damage(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, int32_t x, int32_t y, int32_t w, int32_t h)
+{
+   E_Pixmap *ep;
+   E_Client *ec;
+   Eina_Rectangle *dmg = NULL;
+
+   if (!(ep = wl_resource_get_user_data(resource))) return;
+   if (!(ec = e_pixmap_client_get(ep))) return;
+   if (e_object_is_del(E_OBJECT(ec))) return;
 
-   /* create new damage rectangle */
    if (!(dmg = eina_rectangle_new(x, y, w, h))) return;
 
-   /* add damage rectangle to list of pending damages */
    ec->comp_data->pending.damages =
      eina_list_append(ec->comp_data->pending.damages, dmg);
 }
@@ -974,11 +1191,10 @@ _e_comp_wl_frame_cb_destroy(struct wl_resource *resource)
    E_Client *ec;
 
    if (!(ec = wl_resource_get_user_data(resource))) return;
-
    if (e_object_is_del(E_OBJECT(ec))) return;
 
-   /* remove this frame callback */
-   ec->comp_data->frames = eina_list_remove(ec->comp_data->frames, resource);
+   ec->comp_data->frames = 
+     eina_list_remove(ec->comp_data->frames, resource);
 }
 
 static void
@@ -989,14 +1205,7 @@ _e_comp_wl_surface_cb_frame(struct wl_client *client, struct wl_resource *resour
    struct wl_resource *res;
 
    if (!(ep = wl_resource_get_user_data(resource))) return;
-
-   /* try to find the associated e_client */
-   if (!(ec = e_pixmap_client_get(ep)))
-     {
-        ERR("\tCould not find client from pixmap %p", ep);
-        return;
-     }
-
+   if (!(ec = e_pixmap_client_get(ep))) return;
    if (e_object_is_del(E_OBJECT(ec))) return;
 
    /* create frame callback */
@@ -1009,8 +1218,8 @@ _e_comp_wl_surface_cb_frame(struct wl_client *client, struct wl_resource *resour
 
    wl_resource_set_implementation(res, NULL, ec, _e_comp_wl_frame_cb_destroy);
 
-   /* append this frame callback to the client list */
-   ec->comp_data->frames = eina_list_append(ec->comp_data->frames, res);
+   ec->comp_data->pending.frames = 
+     eina_list_prepend(ec->comp_data->pending.frames, res);
 }
 
 static void
@@ -1019,40 +1228,27 @@ _e_comp_wl_surface_cb_opaque_region_set(struct wl_client *client EINA_UNUSED, st
    E_Pixmap *ep;
    E_Client *ec;
 
-   /* get the e_pixmap reference */
    if (!(ep = wl_resource_get_user_data(resource))) return;
-
-   /* try to find the associated e_client */
-   if (!(ec = e_pixmap_client_get(ep)))
-     {
-        ERR("\tCould not find client from pixmap %p", ep);
-        return;
-     }
-
-   /* trap for clients which are being deleted */
+   if (!(ec = e_pixmap_client_get(ep))) return;
    if (e_object_is_del(E_OBJECT(ec))) return;
 
    if (region_resource)
      {
         Eina_Tiler *tmp;
-        Eina_Iterator *it;
-        Eina_Rectangle *rect;
 
-        /* try to get the tiler from the region resource */
         if (!(tmp = wl_resource_get_user_data(region_resource)))
           return;
 
-        it = eina_tiler_iterator_new(tmp);
-        EINA_ITERATOR_FOREACH(it, rect)
+        eina_tiler_union(ec->comp_data->pending.opaque, tmp);
+     }
+   else
+     {
+        if (ec->comp_data->pending.opaque)
           {
-             e_pixmap_image_opaque_set(ec->pixmap, rect->x, rect->y, rect->w, rect->h);
-             break;
+             eina_tiler_clear(ec->comp_data->pending.opaque);
+             /* eina_tiler_free(ec->comp_data->pending.opaque); */
           }
-
-        eina_iterator_free(it);
      }
-   else
-     e_pixmap_image_opaque_set(ec->pixmap, 0, 0, 0, 0);
 }
 
 static void
@@ -1061,25 +1257,14 @@ _e_comp_wl_surface_cb_input_region_set(struct wl_client *client EINA_UNUSED, str
    E_Pixmap *ep;
    E_Client *ec;
 
-   /* get the e_pixmap reference */
    if (!(ep = wl_resource_get_user_data(resource))) return;
-
-   /* try to find the associated e_client */
-   if (!(ec = e_pixmap_client_get(ep)))
-     {
-        ERR("\tCould not find client from pixmap %p", ep);
-        return;
-     }
-
-   /* trap for clients which are being deleted */
+   if (!(ec = e_pixmap_client_get(ep))) return;
    if (e_object_is_del(E_OBJECT(ec))) return;
 
-   eina_tiler_clear(ec->comp_data->pending.input);
    if (region_resource)
      {
         Eina_Tiler *tmp;
 
-        /* try to get the tiler from the region resource */
         if (!(tmp = wl_resource_get_user_data(region_resource)))
           return;
 
@@ -1096,38 +1281,15 @@ static void
 _e_comp_wl_surface_cb_commit(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
 {
    E_Pixmap *ep;
-   E_Client *ec, *subc;
-   Eina_List *l;
+   E_Client *ec;
 
-   /* get the e_pixmap reference */
    if (!(ep = wl_resource_get_user_data(resource))) return;
-
-   /* try to find the associated e_client */
-   if (!(ec = e_pixmap_client_get(ep)))
-     {
-        ERR("\tCould not find client from pixmap %p", ep);
-        return;
-     }
-
-   /* trap for clients which are being deleted */
+   if (!(ec = e_pixmap_client_get(ep))) return;
    if (e_object_is_del(E_OBJECT(ec))) return;
 
-   /* DBG("Surface Commit: %d", wl_resource_get_id(resource)); */
+   e_comp_wl_surface_commit(ec);
 
-   /* call the subsurface commit function
-    *
-    * NB: Returns true on success */
-   if (e_comp_wl_subsurface_commit(ec)) return;
-
-   /* handle actual surface commit */
-   if (!e_comp_wl_surface_commit(ec))
-     ERR("Failed to commit surface: %d", wl_resource_get_id(resource));
-
-   EINA_LIST_FOREACH(ec->comp_data->sub.list, l, subc)
-     {
-        if (ec != subc)
-          _e_comp_wl_subsurface_parent_commit(subc, EINA_FALSE);
-     }
+   /* TODO: subsurface parent commit ? */
 }
 
 static void
@@ -1587,172 +1749,83 @@ _e_comp_wl_subsurface_commit_from_cache(E_Client *ec)
                        i++;
                     }
                }
+=======
+>>>>>>> start work on fixing resize issue
 
-             eina_iterator_free(itr);
-             eina_tiler_free(src);
-          }
+   wl_resource_set_implementation(res, &_e_comp_interface, comp, NULL);
+}
 
-        eina_tiler_free(tmp);
-        eina_tiler_clear(sdata->cached.input);
-     }
+static void 
+_e_comp_wl_compositor_cb_del(E_Comp *comp)
+{
+   E_Comp_Data *cdata;
 
-   return;
+   /* get existing compositor data */
+   if (!(cdata = comp->wl_comp_data)) return;
 
-unmap:
+   /* delete fd handler */
+   if (cdata->fd_hdlr) ecore_main_fd_handler_del(cdata->fd_hdlr);
 
-   /* surface is not visible, clear damages */
-   EINA_LIST_FREE(sdata->cached.damages, dmg)
-     eina_rectangle_free(dmg);
+   eina_list_free(cdata->output.resources);
 
-   /* clear pending input regions */
-   if (sdata->cached.input)
-     eina_tiler_clear(sdata->cached.input);
+   /* free allocated data structure */
+   free(cdata);
 }
 
-static void
-_e_comp_wl_subsurface_parent_commit(E_Client *ec, Eina_Bool parent_synchronized)
+static void 
+_e_comp_wl_subsurface_destroy(struct wl_resource *resource)
 {
-   E_Client *parent;
-   E_Comp_Wl_Subsurf_Data *sdata;
-
-   if (!(sdata = ec->comp_data->sub.data)) return;
-   if (!(parent = sdata->parent)) return;
+}
 
-   if (sdata->position.set)
-     {
-        evas_object_move(ec->frame, parent->x + sdata->position.x,
-                         parent->y + sdata->position.y);
-        sdata->position.set = EINA_FALSE;
-     }
+static Eina_Bool 
+_e_comp_wl_subsurface_synchronized_get(E_Comp_Wl_Subsurf_Data *sdata)
+{
+   return EINA_FALSE;
+}
 
-   if ((parent_synchronized) || (sdata->synchronized))
-     {
-        E_Client *subc;
-        Eina_List *l;
+static void 
+_e_comp_wl_subsurface_commit_to_cache(E_Client *ec)
+{
+}
 
-        if (sdata->cached.has_data)
-          _e_comp_wl_subsurface_commit_from_cache(ec);
+static void 
+_e_comp_wl_subsurface_commit_from_cache(E_Client *ec)
+{
+}
 
-        EINA_LIST_FOREACH(ec->comp_data->sub.list, l, subc)
-          {
-             if (ec != subc)
-               _e_comp_wl_subsurface_parent_commit(subc, EINA_TRUE);
-          }
-     }
+static void 
+_e_comp_wl_subsurface_parent_commit(E_Client *ec, Eina_Bool parent_synchronized)
+{
 }
 
 static void
 _e_comp_wl_subsurface_cb_destroy(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
 {
-   wl_resource_destroy(resource);
 }
 
 static void
 _e_comp_wl_subsurface_cb_position_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, int32_t x, int32_t y)
 {
-   E_Client *ec;
-   E_Comp_Wl_Subsurf_Data *sdata;
-
-   DBG("Subsurface Cb Position Set: %d", wl_resource_get_id(resource));
-
-   /* try to get the client from resource data */
-   if (!(ec = wl_resource_get_user_data(resource))) return;
-
-   if (!(sdata = ec->comp_data->sub.data)) return;
-
-   sdata->position.x = x;
-   sdata->position.y = y;
-   sdata->position.set = EINA_TRUE;
 }
 
 static void
 _e_comp_wl_subsurface_cb_place_above(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, struct wl_resource *sibling_resource)
 {
-   E_Client *ec, *ecs;
-   E_Client *parent;
-
-   DBG("Subsurface Cb Place Above: %d", wl_resource_get_id(resource));
-
-   /* try to get the client from resource data */
-   if (!(ec = wl_resource_get_user_data(resource))) return;
-
-   if (!ec->comp_data->sub.data) return;
-
-   /* try to get the client from the sibling resource */
-   if (!(ecs = wl_resource_get_user_data(sibling_resource))) return;
-
-   if (!ecs->comp_data->sub.data) return;
-
-   if (!(parent = ec->comp_data->sub.data->parent)) return;
-
-   parent->comp_data->sub.list =
-     eina_list_remove(parent->comp_data->sub.list, ec);
-
-   parent->comp_data->sub.list =
-     eina_list_append_relative(parent->comp_data->sub.list, ec, ecs);
-
-   parent->comp_data->sub.restack_target = parent;
 }
 
 static void
 _e_comp_wl_subsurface_cb_place_below(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, struct wl_resource *sibling_resource)
 {
-   E_Client *ec, *ecs;
-   E_Client *parent;
-
-   DBG("Subsurface Cb Place Below: %d", wl_resource_get_id(resource));
-
-   /* try to get the client from resource data */
-   if (!(ec = wl_resource_get_user_data(resource))) return;
-
-   if (!ec->comp_data->sub.data) return;
-
-   /* try to get the client from the sibling resource */
-   if (!(ecs = wl_resource_get_user_data(sibling_resource))) return;
-
-   if (!ecs->comp_data->sub.data) return;
-
-   if (!(parent = ec->comp_data->sub.data->parent)) return;
-
-   parent->comp_data->sub.list =
-     eina_list_remove(parent->comp_data->sub.list, ec);
-
-   parent->comp_data->sub.list =
-     eina_list_prepend_relative(parent->comp_data->sub.list, ec, ecs);
-
-   parent->comp_data->sub.restack_target = parent;
 }
 
 static void
 _e_comp_wl_subsurface_cb_sync_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
 {
-   E_Client *ec;
-   E_Comp_Wl_Subsurf_Data *sdata;
-
-   DBG("Subsurface Cb Sync Set: %d", wl_resource_get_id(resource));
-
-   /* try to get the client from resource data */
-   if (!(ec = wl_resource_get_user_data(resource))) return;
-
-   if (!(sdata = ec->comp_data->sub.data)) return;
-
-   sdata->synchronized = EINA_TRUE;
 }
 
 static void
 _e_comp_wl_subsurface_cb_desync_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
 {
-   E_Client *ec;
-   E_Comp_Wl_Subsurf_Data *sdata;
-
-   DBG("Subsurface Cb Desync Set: %d", wl_resource_get_id(resource));
-
-   /* try to get the client from resource data */
-   if (!(ec = wl_resource_get_user_data(resource))) return;
-
-   if (!(sdata = ec->comp_data->sub.data)) return;
-
-   sdata->synchronized = EINA_FALSE;
 }
 
 static const struct wl_subsurface_interface _e_subsurface_interface =
@@ -1768,165 +1841,16 @@ static const struct wl_subsurface_interface _e_subsurface_interface =
 static Eina_Bool
 _e_comp_wl_subsurface_create(E_Client *ec, E_Client *epc, uint32_t id, struct wl_resource *surface_resource)
 {
-   struct wl_client *client;
-   struct wl_resource *res;
-   E_Comp_Wl_Subsurf_Data *sdata;
-
-   /* try to get the wayland client from the surface resource */
-   if (!(client = wl_resource_get_client(surface_resource)))
-     {
-        ERR("Could not get client from resource %d",
-            wl_resource_get_id(surface_resource));
-        return EINA_FALSE;
-     }
-
-   /* try to allocate subsurface data */
-   if (!(sdata = E_NEW(E_Comp_Wl_Subsurf_Data, 1)))
-     {
-        ERR("Could not allocate space for subsurface data");
-        goto dat_err;
-     }
-
-   /* try to create the subsurface resource */
-   if (!(res = wl_resource_create(client, &wl_subsurface_interface, 1, id)))
-     {
-        ERR("Failed to create subsurface resource");
-        wl_resource_post_no_memory(surface_resource);
-        goto res_err;
-     }
-
-   /* set resource implementation */
-   wl_resource_set_implementation(res, &_e_subsurface_interface, ec,
-                                  _e_comp_wl_subsurface_destroy);
-
-   /* set subsurface data properties */
-   sdata->resource = res;
-   sdata->synchronized = EINA_TRUE;
-   sdata->parent = epc;
-
-   /* create subsurface tilers */
-   sdata->cached.input = eina_tiler_new(ec->w, ec->h);
-   eina_tiler_tile_size_set(sdata->cached.input, 1, 1);
-
-   /* set subsurface client properties */
-   ec->borderless = EINA_TRUE;
-   ec->argb = EINA_TRUE;
-   ec->lock_border = EINA_TRUE;
-   ec->lock_focus_in = ec->lock_focus_out = EINA_TRUE;
-   ec->netwm.state.skip_taskbar = EINA_TRUE;
-   ec->netwm.state.skip_pager = EINA_TRUE;
-
-   if (epc)
-     {
-        if (epc->comp_data)
-          {
-             /* append this client to the parents subsurface list */
-             epc->comp_data->sub.list =
-               eina_list_append(epc->comp_data->sub.list, ec);
-          }
-
-        /* TODO: add callbacks ?? */
-     }
-
-   ec->comp_data->surface = surface_resource;
-   ec->comp_data->sub.data = sdata;
-
-   return EINA_TRUE;
-
-res_err:
-   free(sdata);
-dat_err:
-   return EINA_FALSE;
 }
 
 static void
 _e_comp_wl_subcompositor_cb_destroy(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
 {
-   wl_resource_destroy(resource);
-
-   /* TODO: destroy iconify/uniconify handlers */
 }
 
 static void
 _e_comp_wl_subcompositor_cb_subsurface_get(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t id, struct wl_resource *surface_resource, struct wl_resource *parent_resource)
 {
-   E_Pixmap *ep, *epp;
-   E_Client *ec, *epc = NULL;
-   static const char where[] = "get_subsurface: wl_subsurface@";
-
-   DBG("Subcompositor Create Subsurface for Surface: %d",
-       wl_resource_get_id(surface_resource));
-
-   /* try to get the surface pixmap */
-   if (!(ep = wl_resource_get_user_data(surface_resource)))
-     {
-        wl_resource_post_error(resource, WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE,
-                               "%s%d: wl_surface@%d is invalid.", where, id,
-                               wl_resource_get_id(surface_resource));
-        return;
-     }
-
-   /* try to get the parent pixmap */
-   if (!(epp = wl_resource_get_user_data(parent_resource)))
-     {
-        wl_resource_post_error(resource, WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE,
-                               "%s%d: wl_surface@%d is invalid.", where, id,
-                               wl_resource_get_id(parent_resource));
-        return;
-     }
-
-   if (ep == epp)
-     {
-        wl_resource_post_error(resource, WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE,
-                               "%s%d: wl_surface@%d cannot be its own parent",
-                               where, id, wl_resource_get_id(surface_resource));
-        return;
-     }
-
-   /* try to find the associated e_client */
-   if (!(ec = e_pixmap_client_get(ep)))
-     ERR("\tCould not find client from pixmap %p", ep);
-
-   if (!ec)
-     {
-        /* no client exists for this pixmap yet */
-        if (!(ec = e_client_new(NULL, ep, 0, 0)))
-          {
-             ERR("Failed to create new client");
-             wl_resource_post_no_memory(resource);
-             return;
-          }
-
-        if (ec->comp_data)
-          ec->comp_data->surface = surface_resource;
-     }
-   else
-     {
-        /* trap for clients which are being deleted */
-        if (e_object_is_del(E_OBJECT(ec))) return;
-     }
-
-   /* try to find the parents associated e_client */
-   if (!(epc = e_pixmap_client_get(epp)))
-     ERR("\tCould not find client from pixmap %p", epp);
-
-   /* trap for clients which are being deleted */
-   if ((epc) && (e_object_is_del(E_OBJECT(epc)))) return;
-
-   /* check if this surface is already a sub-surface */
-   if ((ec->comp_data) && (ec->comp_data->sub.data))
-     {
-        wl_resource_post_error(resource,
-                               WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE,
-                               "%s%d: wl_surface@%d is already a sub-surface",
-                               where, id, wl_resource_get_id(surface_resource));
-        return;
-     }
-
-   /* try to create a new subsurface */
-   if (!_e_comp_wl_subsurface_create(ec, epc, id, surface_resource))
-     ERR("Failed to create subsurface for surface %d",
-         wl_resource_get_id(surface_resource));
 }
 
 static const struct wl_subcompositor_interface _e_subcomp_interface =
@@ -1982,9 +1906,9 @@ _e_comp_wl_client_cb_new(void *data EINA_UNUSED, E_Client *ec)
         return;
      }
 
-   /* create client tilers */
-   ec->comp_data->pending.input = eina_tiler_new(ec->w, ec->h);
-   eina_tiler_tile_size_set(ec->comp_data->pending.input, 1, 1);
+   wl_signal_init(&ec->comp_data->destroy_signal);
+
+   _e_comp_wl_surface_state_init(&ec->comp_data->pending, ec->w, ec->h);
 
    /* set initial client properties */
    ec->argb = EINA_TRUE;
@@ -2012,28 +1936,18 @@ _e_comp_wl_client_cb_new(void *data EINA_UNUSED, E_Client *ec)
 static void
 _e_comp_wl_client_cb_del(void *data EINA_UNUSED, E_Client *ec)
 {
-   /* uint64_t win; */
-   Eina_Rectangle *dmg;
+   /* Eina_Rectangle *dmg; */
+   struct wl_resource *cb;
 
    /* make sure this is a wayland client */
    E_COMP_WL_PIXMAP_CHECK;
 
-   /* get window id from pixmap */
-   /* win = e_pixmap_window_get(ec->pixmap); */
-   /* eina_hash_del_by_key(clients_win_hash, &win); */
-
    if ((!ec->already_unparented) && (ec->comp_data->reparented))
      _e_comp_wl_focus_down_set(ec);
 
    ec->already_unparented = EINA_TRUE;
    if (ec->comp_data->reparented)
      {
-        /* get the parent window */
-        /* win = e_client_util_pwin_get(ec); */
-
-        /* remove the parent from the hash */
-        /* eina_hash_del_by_key(clients_win_hash, &win); */
-
         /* reset pixmap parent window */
         e_pixmap_parent_window_set(ec->pixmap, 0);
      }
@@ -2044,16 +1958,23 @@ _e_comp_wl_client_cb_del(void *data EINA_UNUSED, E_Client *ec)
         ec->parent->modal = NULL;
      }
 
-   /* the client is getting deleted, which means the pixmap will be getting
-    * freed. We need to unset the surface user data */
-   if (ec->comp_data->surface)
-     wl_resource_set_user_data(ec->comp_data->surface, NULL);
+   wl_signal_emit(&ec->comp_data->destroy_signal, &ec->comp_data->surface);
 
-   EINA_LIST_FREE(ec->comp_data->pending.damages, dmg)
-     eina_rectangle_free(dmg);
+   _e_comp_wl_surface_state_finish(&ec->comp_data->pending);
+
+   e_comp_wl_buffer_reference(&ec->comp_data->buffer_ref, NULL);
+
+   /* EINA_LIST_FREE(ec->comp_data->damages, dmg) */
+   /*   eina_rectangle_free(dmg); */
+
+   /* if (ec->comp_data->opaque) eina_tiler_free(ec->comp_data->opaque); */
+   /* if (ec->comp_data->input) eina_tiler_free(ec->comp_data->input); */
 
-   if (ec->comp_data->pending.input)
-     eina_tiler_free(ec->comp_data->pending.input);
+   EINA_LIST_FREE(ec->comp_data->frames, cb)
+     wl_resource_destroy(cb);
+
+   if (ec->comp_data->surface)
+     wl_resource_set_user_data(ec->comp_data->surface, NULL);
 
    E_FREE(ec->comp_data);
 
@@ -2357,6 +2278,9 @@ _e_comp_wl_compositor_create(void)
    wl_signal_init(&cdata->signals.surface.activate);
    wl_signal_init(&cdata->signals.surface.kill);
 
+   cdata->output.transform = WL_OUTPUT_TRANSFORM_NORMAL;
+   cdata->output.scale = e_scale;
+
    /* try to add compositor to wayland globals */
    if (!wl_global_create(cdata->wl.disp, &wl_compositor_interface,
                          COMPOSITOR_VERSION, comp,
@@ -2559,9 +2483,6 @@ e_comp_wl_shutdown(void)
    /* free handlers */
    E_FREE_LIST(handlers, ecore_event_handler_del);
 
-   /* free the clients win hash */
-   /* E_FREE_FUNC(clients_win_hash, eina_hash_free); */
-
    /* shutdown ecore_wayland */
    ecore_wl_shutdown();
 }
@@ -2577,185 +2498,121 @@ e_comp_wl_surface_create(struct wl_client *client, int version, uint32_t id)
    return ret;
 }
 
-EINTERN Eina_Bool
-e_comp_wl_surface_commit(E_Client *ec)
+EINTERN void 
+e_comp_wl_surface_attach(E_Client *ec, E_Comp_Wl_Buffer *buffer)
 {
-   E_Pixmap *ep;
-   Eina_Rectangle *dmg;
-   Eina_Tiler *src, *tmp;
-   Eina_Bool first;
+   e_comp_wl_buffer_reference(&ec->comp_data->buffer_ref, buffer);
 
-   if (!(ep = ec->pixmap)) return EINA_FALSE;
-   _e_comp_wl_client_evas_init(ec);
-   if (ec->focused && ec->comp_data->focus_update)
-     _e_comp_wl_client_focus(ec);
+   /* set usable early because shell module checks this */
+   e_pixmap_usable_set(ec->pixmap, (buffer != NULL));
+   e_pixmap_resource_set(ec->pixmap, buffer);
+   e_pixmap_dirty(ec->pixmap);
 
-   first = !e_pixmap_usable_get(ep);
-   /* mark the pixmap as usable or not */
-   e_pixmap_usable_set(ep, (ec->comp_data->pending.buffer != NULL));
+   /* e_pixmap_image_clear(ec->pixmap, EINA_FALSE); */
 
-   /* mark the pixmap as dirty */
-   e_pixmap_dirty(ep);
+   _e_comp_wl_surface_state_size_update(ec, &ec->comp_data->pending);
+}
 
-   e_pixmap_image_clear(ep, EINA_FALSE);
-   e_pixmap_resource_set(ep, ec->comp_data->pending.buffer);
+EINTERN Eina_Bool 
+e_comp_wl_surface_commit(E_Client *ec)
+{
+   _e_comp_wl_surface_state_commit(ec, &ec->comp_data->pending);
 
-   /* refresh pixmap */
-   if (e_pixmap_refresh(ep))
+   /* TODO: commit_subsurface_order */
+
+   /* schedule repaint */
+   if (e_pixmap_refresh(ec->pixmap))
      {
         e_comp->post_updates = eina_list_append(e_comp->post_updates, ec);
         e_object_ref(E_OBJECT(ec));
      }
 
-   /* check if we need to map this surface */
-   if (ec->comp_data->pending.buffer)
+   if (!e_pixmap_usable_get(ec->pixmap))
      {
-        /* if this surface is not mapped yet, map it */
-        if (!ec->comp_data->mapped)
+        if (ec->comp_data->mapped)
           {
-             /* if the client has a shell map, call it */
-             if ((ec->comp_data->shell.surface) && (ec->comp_data->shell.map))
-               ec->comp_data->shell.map(ec->comp_data->shell.surface);
+             if ((ec->comp_data->shell.surface) && (ec->comp_data->shell.unmap))
+               ec->comp_data->shell.unmap(ec->comp_data->shell.surface);
              else
                {
-                  evas_object_show(ec->frame);
+                  evas_object_hide(ec->frame);
                   ec->comp_data->mapped = evas_object_visible_get(ec->frame);
                }
           }
      }
    else
      {
-        /* no pending buffer to attach. unmap the surface */
-        if (ec->comp_data->mapped)
+        if (!ec->comp_data->mapped)
           {
-             /* if the client has a shell map, call it */
-             if ((ec->comp_data->shell.surface) && (ec->comp_data->shell.unmap))
-               ec->comp_data->shell.unmap(ec->comp_data->shell.surface);
+             if ((ec->comp_data->shell.surface) && (ec->comp_data->shell.map))
+               ec->comp_data->shell.map(ec->comp_data->shell.surface);
              else
                {
-                  evas_object_hide(ec->frame);
+                  evas_object_show(ec->frame);
                   ec->comp_data->mapped = evas_object_visible_get(ec->frame);
                }
           }
      }
 
-   /* check for any pending attachments */
-   if (ec->comp_data->pending.new_attach)
-     {
-        int x, y, nw, nh;
-        Eina_Bool placed = EINA_TRUE;;
-
-        e_pixmap_size_get(ec->pixmap, &nw, &nh);
-        if (ec->changes.pos)
-          e_comp_object_frame_xy_adjust(ec->frame, ec->x, ec->y, &x, &y);
-        else
-          x = ec->client.x, y = ec->client.y;
-        if (ec->new_client)
-          placed = ec->placed;
-        /* if the client has a shell configure, call it */
-        if ((ec->comp_data->shell.surface) && (ec->comp_data->shell.configure))
-          ec->comp_data->shell.configure(ec->comp_data->shell.surface, x, y, nw, nh);
-        else
-          e_client_util_move_resize_without_frame(ec, x, y, nw, nh);
-        if (ec->new_client)
-          ec->placed = placed;
-        else if (first && ec->placed)
-          {
-             ec->x = ec->y = 0;
-             ec->placed = 0;
-             ec->new_client = 1;
-          }
-     }
+   return EINA_TRUE;
+}
 
-   if (!ec->comp_data->mapped)
-     {
-        DBG("\tSurface Not Mapped. Skip to Unmapped");
-        goto unmap;
-     }
+EINTERN Eina_Bool 
+e_comp_wl_subsurface_commit(E_Client *ec)
+{
+   return EINA_FALSE;
+}
 
-   /* commit any pending damages */
-   if ((!ec->comp->nocomp) && (ec->frame))
+EINTERN void 
+e_comp_wl_buffer_reference(E_Comp_Wl_Buffer_Ref *ref, E_Comp_Wl_Buffer *buffer)
+{
+   if ((ref->buffer) && (buffer != ref->buffer))
      {
-        EINA_LIST_FREE(ec->comp_data->pending.damages, dmg)
+        ref->buffer->busy--;
+        if (ref->buffer->busy == 0)
           {
-             e_comp_object_damage(ec->frame, dmg->x, dmg->y, dmg->w, dmg->h);
-             eina_rectangle_free(dmg);
+             if (!wl_resource_get_client(ref->buffer->resource)) return;
+             wl_resource_queue_event(ref->buffer->resource, WL_BUFFER_RELEASE);
           }
+        wl_list_remove(&ref->destroy_listener.link);
      }
 
-   /* handle pending input */
-   if (ec->comp_data->pending.input)
+   if ((buffer) && (buffer != ref->buffer))
      {
-        tmp = eina_tiler_new(ec->w, ec->h);
-        eina_tiler_tile_size_set(tmp, 1, 1);
-        eina_tiler_rect_add(tmp,
-                            &(Eina_Rectangle){0, 0, ec->client.w, ec->client.h});
-
-        if ((src = eina_tiler_intersection(ec->comp_data->pending.input, tmp)))
-          {
-             Eina_Rectangle *rect;
-             Eina_Iterator *itr;
-
-             itr = eina_tiler_iterator_new(src);
-             /* this should be exactly 1 rect */
-             EINA_ITERATOR_FOREACH(itr, rect)
-               e_comp_object_input_area_set(ec->frame, rect->x, rect->y, rect->w, rect->h);
-
-             eina_iterator_free(itr);
-             eina_tiler_free(src);
-          }
-        else
-          e_comp_object_input_area_set(ec->frame, 0, 0, ec->w, ec->h);
-
-        eina_tiler_free(tmp);
+        buffer->busy++;
+        wl_signal_add(&buffer->destroy_signal, &ref->destroy_listener);
      }
 
-   return EINA_TRUE;
-
-unmap:
-
-   /* surface is not visible, clear damages */
-   EINA_LIST_FREE(ec->comp_data->pending.damages, dmg)
-     eina_rectangle_free(dmg);
-
-   /* clear pending input regions */
-   if (ec->comp_data->pending.input)
-     eina_tiler_clear(ec->comp_data->pending.input);
-
-   return EINA_TRUE;
+   ref->buffer = buffer;
+   ref->destroy_listener.notify = _e_comp_wl_buffer_reference_cb_destroy;
 }
 
-EINTERN Eina_Bool
-e_comp_wl_subsurface_commit(E_Client *ec)
+EAPI E_Comp_Wl_Buffer *
+e_comp_wl_buffer_get(struct wl_resource *resource)
 {
-   E_Comp_Wl_Subsurf_Data *sdata;
+   E_Comp_Wl_Buffer *buffer;
+   struct wl_listener *listener;
+   struct wl_shm_buffer *shmbuff;
 
-   /* check for valid subcompositor data */
-   if (!(sdata = ec->comp_data->sub.data)) return EINA_FALSE;
+   listener = 
+     wl_resource_get_destroy_listener(resource, _e_comp_wl_buffer_cb_destroy);
+   if (listener)
+     return container_of(listener, E_Comp_Wl_Buffer, destroy_listener);
 
-   if (_e_comp_wl_subsurface_synchronized_get(sdata))
-     _e_comp_wl_subsurface_commit_to_cache(ec);
-   else
-     {
-        E_Client *subc;
-        Eina_List *l;
+   if (!(shmbuff = wl_shm_buffer_get(resource))) return NULL;
 
-        if (sdata->cached.has_data)
-          {
-             _e_comp_wl_subsurface_commit_to_cache(ec);
-             _e_comp_wl_subsurface_commit_from_cache(ec);
-          }
-        else
-          e_comp_wl_surface_commit(ec);
+   buffer = E_NEW(E_Comp_Wl_Buffer, 1);
+   if (!buffer) return NULL;
 
-        EINA_LIST_FOREACH(ec->comp_data->sub.list, l, subc)
-          {
-             if (ec != subc)
-               _e_comp_wl_subsurface_parent_commit(subc, EINA_FALSE);
-          }
-     }
+   buffer->w = wl_shm_buffer_get_width(shmbuff);
+   buffer->h = wl_shm_buffer_get_height(shmbuff);
 
-   return EINA_TRUE;
+   buffer->resource = resource;
+   wl_signal_init(&buffer->destroy_signal);
+   buffer->destroy_listener.notify = _e_comp_wl_buffer_cb_destroy;
+   wl_resource_add_destroy_listener(resource, &buffer->destroy_listener);
+
+   return buffer;
 }
 
 EAPI double
index 9a84e0b8ebebd2a28bcddfe79b2a92a72e8a5232..dbefc9971a6a26595eb1433e82552df0ccf28832 100644 (file)
@@ -32,8 +32,9 @@ struct _E_Pixmap
 #endif
 
 #if defined(HAVE_WAYLAND_CLIENTS) || defined(HAVE_WAYLAND_ONLY)
-   struct wl_resource *resource;
-   Eina_List *resource_cache;
+   E_Comp_Wl_Buffer_Ref buffer_ref;
+   struct wl_listener buffer_destroy_listener;
+   void *data;
    Eina_Rectangle opaque;
 #endif
 
@@ -44,9 +45,13 @@ struct _E_Pixmap
 
 #if defined(HAVE_WAYLAND_CLIENTS) || defined(HAVE_WAYLAND_ONLY)
 static void 
-_e_pixmap_resource_free(struct wl_resource *pixres)
+_e_pixmap_cb_buffer_destroy(struct wl_listener *listener, void *data EINA_UNUSED)
 {
-   if (pixres) wl_buffer_send_release(pixres);
+   E_Pixmap *cp;
+
+   cp = container_of(listener, E_Pixmap, buffer_destroy_listener);
+   cp->data = NULL;
+   cp->buffer_destroy_listener.notify = NULL;
 }
 #endif
 
@@ -70,13 +75,19 @@ _e_pixmap_clear(E_Pixmap *cp, Eina_Bool cache)
         break;
       case E_PIXMAP_TYPE_WL:
 #if defined(HAVE_WAYLAND_CLIENTS) || defined(HAVE_WAYLAND_ONLY)
-        if (cp->resource)
+        if (cp->buffer_destroy_listener.notify)
           {
-             e_pixmap_image_clear(cp, cache);
+             wl_list_remove(&cp->buffer_destroy_listener.link);
+             cp->buffer_destroy_listener.notify = NULL;
           }
+
+        e_comp_wl_buffer_reference(&cp->buffer_ref, NULL);
+
+        (void)cache;
 #endif
         break;
-      default: break;
+      default: 
+        break;
      }
 }
 
@@ -110,17 +121,6 @@ _e_pixmap_free(E_Pixmap *cp)
         break;
       case E_PIXMAP_TYPE_WL:
 #if defined(HAVE_WAYLAND_CLIENTS) || defined(HAVE_WAYLAND_ONLY)
-        if (!cp->resource_cache) break;
-        if (cp->client)
-          eina_list_free(cp->resource_cache);
-        else
-          {
-             void *i;
-
-             EINA_LIST_FREE(cp->resource_cache, i)
-               _e_pixmap_resource_free(i);
-          }
-        cp->resource_cache = NULL;
 #endif
         break;
       default:
@@ -173,52 +173,6 @@ _e_pixmap_find(E_Pixmap_Type type, va_list *l)
    return NULL;
 }
 
-#if defined(HAVE_WAYLAND_CLIENTS) || defined(HAVE_WAYLAND_ONLY)
-static void
-_e_pixmap_update_wl(E_Pixmap *cp)
-{
-   if (!cp) return;
-   cp->w = cp->h = 0;
-   if (cp->resource)
-     {
-        struct wl_shm_buffer *buffer;
-        uint32_t format;
-
-        if (!(buffer = wl_shm_buffer_get(cp->resource))) return;
-
-        format = wl_shm_buffer_get_format(buffer);
-        switch (format)
-          {
-             /* TOOD: add more cases */
-           case WL_SHM_FORMAT_ARGB8888:
-           case WL_SHM_FORMAT_ARGB4444:
-           case WL_SHM_FORMAT_ABGR4444:
-           case WL_SHM_FORMAT_RGBA4444:
-           case WL_SHM_FORMAT_BGRA4444:
-           case WL_SHM_FORMAT_ARGB1555:
-           case WL_SHM_FORMAT_ABGR1555:
-           case WL_SHM_FORMAT_RGBA5551:
-           case WL_SHM_FORMAT_BGRA5551:
-           case WL_SHM_FORMAT_ABGR8888:
-           case WL_SHM_FORMAT_RGBA8888:
-           case WL_SHM_FORMAT_BGRA8888:
-           case WL_SHM_FORMAT_ARGB2101010:
-           case WL_SHM_FORMAT_ABGR2101010:
-           case WL_SHM_FORMAT_RGBA1010102:
-           case WL_SHM_FORMAT_BGRA1010102:
-           case WL_SHM_FORMAT_AYUV:
-             cp->image_argb = EINA_TRUE;
-             break;
-           default:
-             cp->image_argb = EINA_FALSE;
-             break;
-          }
-        cp->w = wl_shm_buffer_get_width(buffer);
-        cp->h = wl_shm_buffer_get_height(buffer);
-     }
-}
-#endif
-
 EAPI int
 e_pixmap_free(E_Pixmap *cp)
 {
@@ -437,30 +391,7 @@ e_pixmap_refresh(E_Pixmap *cp)
         break;
       case E_PIXMAP_TYPE_WL:
 #if defined(HAVE_WAYLAND_CLIENTS) || defined(HAVE_WAYLAND_ONLY)
-          {
-             E_Comp_Wl_Client_Data *cd = NULL;
-             int pw = 0, ph = 0;
-
-             if (cp->client)
-               {
-                  cd = (E_Comp_Wl_Client_Data *)cp->client->comp_data;
-                  /* pw = cp->client->client.w; */
-                  /* ph = cp->client->client.h; */
-               }
-
-             success = !!cp->resource;
-             if (!success) break;
-
-             if ((cd) && (cd->pending.w) && (cd->pending.h))
-               {
-                  pw = cd->pending.w;
-                  ph = cd->pending.h;
-               }
-
-             success = ((pw > 0) && (ph > 0));
-             if (success)
-               _e_pixmap_update_wl(cp);
-          }
+        success = ((cp->w > 0) && (cp->h > 0));
 #endif
         break;
       default:
@@ -558,7 +489,7 @@ e_pixmap_resource_get(E_Pixmap *cp)
         return NULL;
      }
 #if defined(HAVE_WAYLAND_CLIENTS) || defined(HAVE_WAYLAND_ONLY)
-   return cp->resource;
+   return cp->buffer_ref.buffer;
 #endif
    return NULL;
 }
@@ -568,9 +499,54 @@ e_pixmap_resource_set(E_Pixmap *cp, void *resource)
 {
    if ((!cp) || (cp->type != E_PIXMAP_TYPE_WL)) return;
 #if defined(HAVE_WAYLAND_CLIENTS) || defined(HAVE_WAYLAND_ONLY)
-   cp->resource = resource;
+     {
+        E_Comp_Wl_Buffer *buffer;
+        struct wl_shm_buffer *shm_buffer;
+
+        buffer = (E_Comp_Wl_Buffer *)resource;
+        e_comp_wl_buffer_reference(&cp->buffer_ref, buffer);
+
+        if (cp->buffer_destroy_listener.notify)
+          {
+             wl_list_remove(&cp->buffer_destroy_listener.link);
+             cp->buffer_destroy_listener.notify = NULL;
+          }
+
+        cp->w = cp->h = 0;
+        cp->image_argb = EINA_FALSE;
+
+        if (!buffer) return;
+
+        if (!(shm_buffer = wl_shm_buffer_get(buffer->resource)))
+          {
+             WRN("Cannot get shm buffer from buffer resource");
+             e_comp_wl_buffer_reference(&cp->buffer_ref, NULL);
+             return;
+          }
+
+        buffer->shm_buffer = shm_buffer;
+        cp->w = buffer->w;
+        cp->h = buffer->h;
+        /* buffer->w = cp->w = wl_shm_buffer_get_width(shm_buffer); */
+        /* buffer->h = cp->h = wl_shm_buffer_get_height(shm_buffer); */
+
+        switch (wl_shm_buffer_get_format(shm_buffer))
+          {
+           case WL_SHM_FORMAT_ARGB8888:
+             cp->image_argb = EINA_TRUE;
+             break;
+           default:
+             cp->image_argb = EINA_FALSE;
+             break;
+          }
+
+        cp->data = wl_shm_buffer_get_data(shm_buffer);
+
+        cp->buffer_destroy_listener.notify = _e_pixmap_cb_buffer_destroy;
+        wl_signal_add(&buffer->destroy_signal, &cp->buffer_destroy_listener);
+     }
 #else
-   (void) resource;
+   (void)resource;
 #endif
 }
 
@@ -631,7 +607,7 @@ e_pixmap_image_clear(E_Pixmap *cp, Eina_Bool cache)
         if (!cp->image) return;
 #endif
 #if defined(HAVE_WAYLAND_CLIENTS) || defined(HAVE_WAYLAND_ONLY)
-        if (!cp->resource) return;
+        if (!cp->buffer_ref.buffer) return;
 #endif
      }
 
@@ -658,19 +634,15 @@ e_pixmap_image_clear(E_Pixmap *cp, Eina_Bool cache)
 #if defined(HAVE_WAYLAND_CLIENTS) || defined(HAVE_WAYLAND_ONLY)
         if (cache)
           {
-             void *i;
+             E_Comp_Wl_Client_Data *cd;
+             struct wl_resource *cb;
 
-             EINA_LIST_FREE(cp->resource_cache, i)
-               _e_pixmap_resource_free(i);
-          }
-        else
-          {
-             if (eina_list_data_find(cp->resource_cache, cp->resource) != 
-                 cp->resource)
+             if ((!cp->client) || (!cp->client->comp_data)) return;
+             cd = (E_Comp_Wl_Client_Data *)cp->client->comp_data;
+             EINA_LIST_FREE(cd->frames, cb)
                {
-                  cp->resource_cache = 
-                    eina_list_append(cp->resource_cache, cp->resource);
-                  cp->resource = NULL;
+                  wl_callback_send_done(cb, ecore_time_unix_get());
+                  wl_resource_destroy(cb);
                }
           }
 #endif
@@ -709,8 +681,8 @@ e_pixmap_image_refresh(E_Pixmap *cp)
         break;
       case E_PIXMAP_TYPE_WL:
 #if defined(HAVE_WAYLAND_CLIENTS) || defined(HAVE_WAYLAND_ONLY)
-        _e_pixmap_update_wl(cp);
-        return ((cp->w > 0) && (cp->h > 0));
+        /* FIXME */
+        return EINA_TRUE;
 #endif
         break;
       default:
@@ -730,7 +702,7 @@ e_pixmap_image_exists(const E_Pixmap *cp)
      return !!cp->image;
 #endif
 #if defined(HAVE_WAYLAND_CLIENTS) || defined(HAVE_WAYLAND_ONLY)
-   return (cp->resource != NULL);
+   return (cp->buffer_ref.buffer != NULL);
 #endif
 
    return EINA_FALSE;
@@ -749,7 +721,7 @@ e_pixmap_image_is_argb(const E_Pixmap *cp)
 #endif
       case E_PIXMAP_TYPE_WL:
 #if defined(HAVE_WAYLAND_CLIENTS) || defined(HAVE_WAYLAND_ONLY)
-        return ((cp->resource != NULL) && (cp->image_argb));
+        return ((cp->buffer_ref.buffer != NULL) && (cp->image_argb));
 #endif
         default: break;
      }
@@ -771,20 +743,7 @@ e_pixmap_image_data_get(E_Pixmap *cp)
         break;
       case E_PIXMAP_TYPE_WL:
 #if defined(HAVE_WAYLAND_CLIENTS) || defined(HAVE_WAYLAND_ONLY)
-        if (cp->resource)
-          {
-             struct wl_shm_buffer *buffer;
-             void *data = NULL;
-
-             if (!(buffer = wl_shm_buffer_get(cp->resource)))
-               return NULL;
-
-             wl_shm_buffer_begin_access(buffer);
-             data = wl_shm_buffer_get_data(buffer);
-             wl_shm_buffer_end_access(buffer);
-
-             return data;
-          }
+        return cp->data;
 #endif
         break;
       default:
@@ -814,18 +773,17 @@ e_pixmap_image_data_argb_convert(E_Pixmap *cp, void *pix, void *ipix, Eina_Recta
       case E_PIXMAP_TYPE_WL:
         if (cp->image_argb) return EINA_TRUE;
 #if defined(HAVE_WAYLAND_CLIENTS) || defined(HAVE_WAYLAND_ONLY)
-        if (cp->resource)
+        if (cp->buffer_ref.buffer)
           {
-             /* TOOD: add more cases */
-             struct wl_shm_buffer *buffer;
+             struct wl_shm_buffer *shm_buffer;
              uint32_t format;
              int i, x, y;
              unsigned int *src, *dst;
 
-             if (!(buffer = wl_shm_buffer_get(cp->resource)))
-               return EINA_FALSE;
+             shm_buffer = wl_shm_buffer_get(cp->buffer_ref.buffer->resource);
+             if (!shm_buffer) return EINA_FALSE;
 
-             format = wl_shm_buffer_get_format(buffer);
+             format = wl_shm_buffer_get_format(shm_buffer);
              if (format == WL_SHM_FORMAT_XRGB8888)
                {
                   dst = (unsigned int *)pix;
@@ -839,9 +797,9 @@ e_pixmap_image_data_argb_convert(E_Pixmap *cp, void *pix, void *ipix, Eina_Recta
                     }
                   pix = (void *)dst;
                }
-          }
 
-        return EINA_TRUE;
+             return EINA_TRUE;
+          }
 #endif
         break;
       default:
@@ -865,20 +823,6 @@ e_pixmap_image_draw(E_Pixmap *cp, const Eina_Rectangle *r)
         break;
       case E_PIXMAP_TYPE_WL:
 #if defined(HAVE_WAYLAND_CLIENTS) || defined(HAVE_WAYLAND_ONLY)
-          {
-             E_Comp_Wl_Client_Data *cd;
-             struct wl_resource *cb;
-
-             if ((!cp->client) || (!cp->client->comp_data)) 
-               return EINA_FALSE;
-
-             cd = (E_Comp_Wl_Client_Data*)cp->client->comp_data;
-             EINA_LIST_FREE(cd->frames, cb)
-               {
-                  wl_callback_send_done(cb, ecore_time_unix_get());
-                  wl_resource_destroy(cb);
-               }
-          }
 #endif
         (void) r;
         return EINA_TRUE;
@@ -888,6 +832,21 @@ e_pixmap_image_draw(E_Pixmap *cp, const Eina_Rectangle *r)
    return EINA_FALSE;
 }
 
+EAPI void 
+e_pixmap_image_draw_done(E_Pixmap *cp)
+{
+   EINA_SAFETY_ON_NULL_RETURN(cp);
+
+#if defined(HAVE_WAYLAND_CLIENTS) || defined(HAVE_WAYLAND_ONLY)
+   struct wl_shm_buffer *shm_buffer;
+
+   shm_buffer = wl_shm_buffer_get(cp->buffer_ref.buffer->resource);
+   if (!shm_buffer) return;
+
+   wl_shm_buffer_end_access(shm_buffer);
+#endif
+}
+
 EAPI void
 e_pixmap_image_opaque_set(E_Pixmap *cp, int x, int y, int w, int h)
 {