evas-wayland-shm: Fix redrawing issues that were causing 'flashing' in latest engine...
authorChris Michael <cp.michael@samsung.com>
Thu, 19 Mar 2015 20:15:11 +0000 (16:15 -0400)
committerChris Michael <cp.michael@samsung.com>
Thu, 19 Mar 2015 20:17:25 +0000 (16:17 -0400)
Summary: As reported by derek & zmike, the previous engine refactor
left some issues where the app would 'flash' during redraws due to
buffer handling. This commit fixes that issue along with flashing
during resize.

@fix

Signed-off-by: Chris Michael <cp.michael@samsung.com>
src/modules/evas/engines/wayland_shm/evas_engine.h
src/modules/evas/engines/wayland_shm/evas_outbuf.c
src/modules/evas/engines/wayland_shm/evas_shm.c

index 4a74f4f..3c4fcc2 100644 (file)
@@ -67,6 +67,7 @@ struct _Shm_Leaf
    Shm_Data *data;
    Shm_Pool *resize_pool;
    Eina_Bool valid : 1;
+   Eina_Bool reconfigure : 1;
 };
 
 typedef struct _Shm_Surface Shm_Surface;
@@ -79,6 +80,8 @@ struct _Shm_Surface
    int w, h;
    int dx, dy;
    int num_buff;
+   int last_buff;
+   int curr_buff;
 
    Shm_Leaf leaf[MAX_BUFFERS];
    Shm_Leaf *current;
@@ -116,9 +119,9 @@ struct _Outbuf
      } priv;
 };
 
-Shm_Surface *_evas_shm_surface_create(struct wl_shm *shm, struct wl_surface *surface, int w, int h, Eina_Bool alpha);
+Shm_Surface *_evas_shm_surface_create(struct wl_shm *shm, struct wl_surface *surface, int w, int h, int num_buff, Eina_Bool alpha);
 void _evas_shm_surface_destroy(Shm_Surface *surface);
-void _evas_shm_surface_prepare(Shm_Surface *surface, int dx, int dy, int w, int h, int num_buff, uint32_t flags);
+void _evas_shm_surface_reconfigure(Shm_Surface *surface, int dx, int dy, int w, int h, int num_buff, uint32_t flags);
 void _evas_shm_surface_swap(Shm_Surface *surface, Eina_Rectangle *rects, unsigned int count);
 void *_evas_shm_surface_data_get(Shm_Surface *surface, int *w, int *h);
 void _evas_shm_surface_redraw(Shm_Surface *surface);
index cedd2f1..ab12299 100644 (file)
@@ -5,9 +5,9 @@
 #endif
 #include "evas_engine.h"
 
-#define RED_MASK 0x00ff0000
-#define GREEN_MASK 0x0000ff00
-#define BLUE_MASK 0x000000ff
+#define RED_MASK 0xff0000
+#define GREEN_MASK 0x00ff00
+#define BLUE_MASK 0x0000ff
 
 Outbuf *
 _evas_outbuf_setup(int w, int h, int rot, Outbuf_Depth depth, Eina_Bool alpha, struct wl_shm *shm, struct wl_surface *surface)
@@ -43,13 +43,10 @@ _evas_outbuf_setup(int w, int h, int rot, Outbuf_Depth depth, Eina_Bool alpha, s
      }
 
    /* try to create the outbuf surface */
-   if (!(ob->surface = _evas_shm_surface_create(shm, surface, w, h, alpha)))
+   if (!(ob->surface = 
+         _evas_shm_surface_create(shm, surface, w, h, ob->num_buff, alpha)))
      goto surf_err;
 
-   /* call prepare function to setup first buffer */
-   _evas_shm_surface_prepare(ob->surface, 0, 0, w, h, 
-                             ob->num_buff, ob->surface->flags);
-
    eina_array_step_set(&ob->priv.onebuf_regions, sizeof(Eina_Array), 8);
 
    return ob;
@@ -64,6 +61,27 @@ _evas_outbuf_free(Outbuf *ob)
 {
    LOGFN(__FILE__, __LINE__, __FUNCTION__);
 
+   while (ob->priv.pending_writes)
+     {
+        RGBA_Image *img;
+        Eina_Rectangle *rect;
+
+        img = ob->priv.pending_writes->data;
+        ob->priv.pending_writes = 
+          eina_list_remove_list(ob->priv.pending_writes, ob->priv.pending_writes);
+
+        rect = img->extended_info;
+
+#ifdef EVAS_CSERVE2
+        if (evas_cserve2_use_get())
+          evas_cache2_image_close(&img->cache_entry);
+        else
+#endif
+          evas_cache_image_drop(&img->cache_entry);
+
+        eina_rectangle_free(rect);
+     }
+
    _evas_outbuf_flush(ob, NULL, MODE_FULL);
    _evas_outbuf_idle_flush(ob);
 
@@ -77,7 +95,43 @@ _evas_outbuf_free(Outbuf *ob)
 void 
 _evas_outbuf_idle_flush(Outbuf *ob)
 {
-   _evas_shm_surface_redraw(ob->surface);
+   RGBA_Image *img;
+   Eina_Rectangle *rect;
+
+   if (ob->priv.onebuf)
+     {
+        img = ob->priv.onebuf;
+        ob->priv.onebuf = NULL;
+
+        rect = img->extended_info;
+        eina_rectangle_free(rect);
+
+#ifdef EVAS_CSERVE2
+        if (evas_cserve2_use_get())
+          evas_cache2_image_close(&img->cache_entry);
+        else
+#endif
+          evas_cache_image_drop(&img->cache_entry);
+     }
+   else
+     {
+        while (ob->priv.prev_pending_writes)
+          {
+             img = ob->priv.prev_pending_writes->data;
+             ob->priv.prev_pending_writes = 
+               eina_list_remove_list(ob->priv.prev_pending_writes, 
+                                     ob->priv.prev_pending_writes);
+             rect = img->extended_info;
+#ifdef EVAS_CSERVE2
+             if (evas_cserve2_use_get())
+               evas_cache2_image_close(&img->cache_entry);
+             else
+#endif
+               evas_cache_image_drop(&img->cache_entry);
+
+             eina_rectangle_free(rect);
+          }
+     }
 }
 
 void 
@@ -91,12 +145,6 @@ _evas_outbuf_flush(Outbuf *ob, Tilebuf_Rect *rects EINA_UNUSED, Evas_Render_Mode
 
    if (render_mode == EVAS_RENDER_MODE_ASYNC_INIT) return;
 
-   if (!ob->surface->current)
-     {
-        WRN("Cannot Flush. No Current Leaf !!");
-        return;
-     }
-
    /* check for pending writes */
    if (!ob->priv.pending_writes)
      {
@@ -114,6 +162,8 @@ _evas_outbuf_flush(Outbuf *ob, Tilebuf_Rect *rects EINA_UNUSED, Evas_Render_Mode
         EINA_ARRAY_ITER_NEXT(&ob->priv.onebuf_regions, i, rect, it)
           result[i] = *rect;
 
+        _evas_shm_surface_redraw(ob->surface);
+
         /* force a buffer swap */
         _evas_shm_surface_swap(ob->surface, result, n);
 
@@ -197,27 +247,25 @@ _evas_outbuf_flush(Outbuf *ob, Tilebuf_Rect *rects EINA_UNUSED, Evas_Render_Mode
              i++;
           }
 
+        _evas_shm_surface_redraw(ob->surface);
+
         /* force a buffer swap */
         _evas_shm_surface_swap(ob->surface, result, n);
      }
-
-   _evas_shm_surface_redraw(ob->surface);
 }
 
 Render_Engine_Swap_Mode 
 _evas_outbuf_swapmode_get(Outbuf *ob)
 {
-   int i = 0, count = 0;
+   int i = 0;
 
    LOGFN(__FILE__, __LINE__, __FUNCTION__);
 
-   for (; i < ob->num_buff; i++)
-     {
-        if (ob->surface->leaf[i].busy)
-          count++;
-     }
+   i = (ob->surface->last_buff - ob->surface->curr_buff + 
+        (ob->surface->last_buff > ob->surface->last_buff ? 
+            0 : ob->surface->num_buff)) % ob->surface->num_buff;
 
-   switch (count)
+   switch (i)
      {
       case 0:
         return MODE_COPY;
@@ -263,8 +311,10 @@ _evas_outbuf_reconfigure(Outbuf *ob, int x, int y, int w, int h, int rot, Outbuf
    else
      ob->surface->flags = 0;
 
-   _evas_shm_surface_prepare(ob->surface, x, y, w, h, 
-                             ob->num_buff, ob->surface->flags);
+   _evas_shm_surface_reconfigure(ob->surface, x, y, w, h, 
+                                 ob->num_buff, ob->surface->flags);
+
+   _evas_outbuf_idle_flush(ob);
 }
 
 void *
@@ -287,7 +337,7 @@ _evas_outbuf_update_region_new(Outbuf *ob, int x, int y, int w, int h, int *cx,
 
              if (!(data = _evas_shm_surface_data_get(ob->surface, &bw, &bh)))
                {
-                  ERR("Could not get surface data");
+                  /* ERR("Could not get surface data"); */
                   return NULL;
                }
 
@@ -360,6 +410,8 @@ _evas_outbuf_update_region_new(Outbuf *ob, int x, int y, int w, int h, int *cx,
              return NULL;
           }
 
+        img->cache_entry.w = w;
+        img->cache_entry.h = h;
         img->cache_entry.flags.alpha |= ob->priv.destination_alpha ? 1 : 0;
 
 #ifdef EVAS_CSERVE2
@@ -462,7 +514,11 @@ _evas_outbuf_update_region_push(Outbuf *ob, RGBA_Image *update, int x, int y, in
    if (bpp <= 0) return;
 
    /* check for valid desination data */
-   if (!(dst = _evas_shm_surface_data_get(ob->surface, &ww, &hh))) return;
+   if (!(dst = _evas_shm_surface_data_get(ob->surface, &ww, &hh)))
+     {
+        /* ERR("Could not get surface data"); */
+        return;
+     }
 
    bpl = (ww * sizeof(int));
 
index 16c7d27..b9c0a6a 100644 (file)
@@ -1,30 +1,10 @@
 #include "evas_common_private.h"
 #include "evas_private.h"
-#ifdef EVAS_CSERVE2
-# include "evas_cs2_private.h"
-#endif
 #include "evas_engine.h"
 #include <sys/mman.h>
 
-static void 
-_evas_shm_surface_cb_frame(void *data, struct wl_callback *callback, uint32_t timestamp EINA_UNUSED)
-{
-   Shm_Surface *surf;
-
-   LOGFN(__FILE__, __LINE__, __FUNCTION__);
-
-   if (!(surf = data)) return;
-   if (callback != surf->frame_cb) return;
-
-   wl_callback_destroy(callback);
-   surf->frame_cb = NULL;
-   surf->redraw = EINA_FALSE;
-}
-
-static const struct wl_callback_listener _frame_listener = 
-{
-   _evas_shm_surface_cb_frame
-};
+static Eina_Bool _shm_leaf_create(Shm_Surface *surface, Shm_Leaf *leaf, int w, int h);
+static void _shm_leaf_release(Shm_Leaf *leaf);
 
 static struct wl_shm_pool *
 _shm_pool_make(struct wl_shm *shm, int size, void **data)
@@ -132,7 +112,10 @@ _shm_pool_allocate(Shm_Pool *pool, size_t size, int *offset)
    LOGFN(__FILE__, __LINE__, __FUNCTION__);
 
    if ((pool->used + size) > pool->size)
-     return NULL;
+     {
+        WRN("Shm Pool Too Small");
+        return NULL;
+     }
 
    *offset = pool->used;
    pool->used += size;
@@ -148,6 +131,26 @@ _shm_pool_reset(Shm_Pool *pool)
    pool->used = 0;
 }
 
+static void 
+_shm_frame_release(void *data, struct wl_callback *callback, uint32_t timestamp EINA_UNUSED)
+{
+   Shm_Surface *surf;
+
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+
+   if (!(surf = data)) return;
+   if (callback != surf->frame_cb) return;
+
+   wl_callback_destroy(surf->frame_cb);
+   surf->frame_cb = NULL;
+   surf->redraw = EINA_FALSE;
+}
+
+static const struct wl_callback_listener _shm_frame_listener = 
+{
+   _shm_frame_release
+};
+
 static Shm_Data *
 _shm_data_create_from_pool(Shm_Pool *pool, int w, int h, Eina_Bool alpha)
 {
@@ -170,8 +173,7 @@ _shm_data_create_from_pool(Shm_Pool *pool, int w, int h, Eina_Bool alpha)
    if (!(data->map = _shm_pool_allocate(pool, len, &offset)))
      {
         ERR("Could not map leaf data");
-        free(data);
-        return NULL;
+        goto err;
      }
 
    if (alpha) 
@@ -183,14 +185,17 @@ _shm_data_create_from_pool(Shm_Pool *pool, int w, int h, Eina_Bool alpha)
    if (!data->buffer)
      {
         ERR("Could not create buffer from pool: %m");
-        free(data);
-        return NULL;
+        goto err;
      }
 
    return data;
+
+err:
+   free(data);
+   return NULL;
 }
 
-static void
+static void 
 _shm_data_create(Shm_Pool *alt_pool, Shm_Data **ret, Shm_Surface *surface, int w, int h)
 {
    Shm_Pool *pool;
@@ -198,6 +203,8 @@ _shm_data_create(Shm_Pool *alt_pool, Shm_Data **ret, Shm_Surface *surface, int w
 
    LOGFN(__FILE__, __LINE__, __FUNCTION__);
 
+   if (ret) *ret = NULL;
+
    if (alt_pool)
      {
         _shm_pool_reset(alt_pool);
@@ -208,23 +215,20 @@ _shm_data_create(Shm_Pool *alt_pool, Shm_Data **ret, Shm_Surface *surface, int w
    if (!(pool = _shm_pool_create(surface->shm, ((w * sizeof(int)) * h))))
      {
         ERR("Could not create shm pool");
-        goto err;
+        return;
      }
 
    if (!(data = _shm_data_create_from_pool(pool, w, h, surface->alpha)))
      {
         ERR("Could not create data from pool");
         _shm_pool_destroy(pool);
-        goto err;
+        return;
      }
 
    data->pool = pool;
 
 out:
    if (ret) *ret = data;
-   return;
-err:
-   if (ret) *ret = NULL;
 }
 
 static void 
@@ -238,16 +242,6 @@ _shm_data_destroy(Shm_Data *data)
 }
 
 static void 
-_shm_leaf_release(Shm_Leaf *leaf)
-{
-   LOGFN(__FILE__, __LINE__, __FUNCTION__);
-
-   if (leaf->data) _shm_data_destroy(leaf->data);
-   if (leaf->resize_pool) _shm_pool_destroy(leaf->resize_pool);
-   memset(leaf, 0, sizeof(*leaf));
-}
-
-static void 
 _shm_buffer_release(void *data, struct wl_buffer *buffer)
 {
    Shm_Surface *surf;
@@ -257,13 +251,20 @@ _shm_buffer_release(void *data, struct wl_buffer *buffer)
    LOGFN(__FILE__, __LINE__, __FUNCTION__);
 
    surf = data;
-
    for (; i < surf->num_buff; i++)
      {
         leaf = &surf->leaf[i];
         if ((leaf->data) && (leaf->data->buffer == buffer))
           {
+//             DBG("Buffer Released: %d", (int)(leaf - &surf->leaf[0]));
              leaf->busy = 0;
+
+             if (leaf->reconfigure)
+               {
+                  _shm_leaf_release(leaf);
+                  _shm_leaf_create(surf, leaf, surf->w, surf->h);
+               }
+
              break;
           }
      }
@@ -274,10 +275,43 @@ static const struct wl_buffer_listener _shm_buffer_listener =
    _shm_buffer_release
 };
 
+static Eina_Bool 
+_shm_leaf_create(Shm_Surface *surface, Shm_Leaf *leaf, int w, int h)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+
+   _shm_data_create(leaf->resize_pool, &leaf->data, surface, w, h);
+   if (!leaf->data)
+     {
+        CRI("Failed to create leaf data");
+        abort();
+     }
+
+   leaf->w = w;
+   leaf->h = h;
+   leaf->valid = EINA_TRUE;
+
+   wl_buffer_add_listener(leaf->data->buffer, &_shm_buffer_listener, surface);
+
+   return EINA_TRUE;
+}
+
+static void 
+_shm_leaf_release(Shm_Leaf *leaf)
+{
+   LOGFN(__FILE__, __LINE__, __FUNCTION__);
+
+   if (leaf->data) _shm_data_destroy(leaf->data);
+   if (leaf->resize_pool) _shm_pool_destroy(leaf->resize_pool);
+   memset(leaf, 0, sizeof(*leaf));
+   leaf->valid = EINA_FALSE;
+}
+
 Shm_Surface *
-_evas_shm_surface_create(struct wl_shm *shm, struct wl_surface *surface, int w, int h, Eina_Bool alpha)
+_evas_shm_surface_create(struct wl_shm *shm, struct wl_surface *surface, int w, int h, int num_buff, Eina_Bool alpha)
 {
    Shm_Surface *surf;
+   int i = 0;
 
    LOGFN(__FILE__, __LINE__, __FUNCTION__);
 
@@ -289,10 +323,25 @@ _evas_shm_surface_create(struct wl_shm *shm, struct wl_surface *surface, int w,
    surf->h = h;
    surf->shm = shm;
    surf->surface = surface;
+   surf->num_buff = num_buff;
    surf->alpha = alpha;
    surf->flags = 0;
 
+   /* create surface buffers */
+   for (; i < surf->num_buff; i++)
+     {
+        if (!_shm_leaf_create(surf, &(surf->leaf[i]), w, h))
+          {
+             ERR("Could not create surface leaf");
+             goto err;
+          }
+     }
+
    return surf;
+
+err:
+   _evas_shm_surface_destroy(surf);
+   return NULL;
 }
 
 void 
@@ -309,152 +358,133 @@ _evas_shm_surface_destroy(Shm_Surface *surface)
 }
 
 void 
-_evas_shm_surface_prepare(Shm_Surface *surface, int dx, int dy, int w, int h, int num_buff, uint32_t flags)
+_evas_shm_surface_reconfigure(Shm_Surface *surface, int dx, int dy, int w, int h, int num_buff, uint32_t flags)
 {
-   Shm_Leaf *leaf = NULL;
    int i = 0, resize = 0;
 
    LOGFN(__FILE__, __LINE__, __FUNCTION__);
 
    resize = !!(flags & SURFACE_HINT_RESIZING);
 
-   /* update surface properties */
+   for (; i < surface->num_buff; i++)
+     {
+        /* don't resize any busy leafs */
+        if (surface->leaf[i].busy)
+          {
+             surface->leaf[i].reconfigure = EINA_TRUE;
+             continue;
+          }
+
+        /* clear this leaf */
+        _shm_leaf_release(&surface->leaf[i]);
+     }
+
    surface->w = w;
    surface->h = h;
    surface->dx = dx;
    surface->dy = dy;
+   surface->flags = flags;
    surface->num_buff = num_buff;
 
-   for (; i < num_buff; i++)
+   for (i = 0; i < surface->num_buff; i++)
      {
         if (surface->leaf[i].busy) continue;
-        if ((!leaf) || (leaf->valid))
+
+        if ((resize) && (!surface->leaf[i].resize_pool))
           {
-             leaf = &surface->leaf[i];
-             break;
+             surface->leaf[i].resize_pool = 
+               _shm_pool_create(surface->shm, 10 * 1024 * 1024);
           }
-     }
 
-   if (!leaf)
-     {
-        CRI("All buffers held by server");
-        return;
-     }
-
-   if ((!resize) && (leaf->resize_pool))
-     {
-        _shm_data_destroy(leaf->data);
-        leaf->data = NULL;
-
-        _shm_pool_destroy(leaf->resize_pool);
-        leaf->resize_pool = NULL;
-     }
-
-   if (leaf->valid)
-     {
-        if ((leaf->w == w) && (leaf->h == h)) goto out;
-     }
-
-   if (leaf->data) _shm_data_destroy(leaf->data);
-   leaf->data = NULL;
-
-   if ((resize) && (!leaf->resize_pool))
-     {
-        leaf->resize_pool = 
-          _shm_pool_create(surface->shm, 6 * 1024 * 1024);
-     }
-
-   _shm_data_create(leaf->resize_pool, &leaf->data, surface, w, h);
-   if (!leaf->data)
-     {
-        CRI("Failed to create leaf data");
-        abort();
+        if (!_shm_leaf_create(surface, &surface->leaf[i], w, h))
+          {
+             CRI("Failed to create leaf data");
+             abort();
+          }
      }
-
-   leaf->w = w;
-   leaf->h = h;
-   leaf->valid = EINA_TRUE;
-
-   wl_buffer_add_listener(leaf->data->buffer, &_shm_buffer_listener, surface);
-
-out:
-   surface->current = leaf;
 }
 
 void 
 _evas_shm_surface_swap(Shm_Surface *surface, Eina_Rectangle *rects, unsigned int count)
 {
-   Shm_Leaf *leaf;
-   Eina_Rectangle *rect;
+   Shm_Leaf *leaf = NULL;
+   int i = 0;
 
    LOGFN(__FILE__, __LINE__, __FUNCTION__);
 
-   if (!(leaf = surface->current))
+   for (; i < surface->num_buff; i++)
      {
-        ERR("No Current Leaf");
-        return;
+        if (surface->leaf[i].busy) continue;
+        if ((!leaf) || (leaf->valid))
+          {
+             leaf = &surface->leaf[i];
+             break;
+          }
      }
 
-   if (!leaf->valid)
+   if (!leaf)
      {
-        ERR("Leaf Not Valid");
+        /* WRN("All buffers held by server"); */
         return;
      }
 
-   rect = eina_rectangle_new(0, 0, 0, 0);
+   /* DBG("Current Leaf %d", (int)(leaf - &surface->leaf[0])); */
+
+   wl_surface_attach(surface->surface, leaf->data->buffer, 0, 0);
+
    if ((rects) && (count > 0))
      {
         unsigned int i = 0;
 
         for (; i < count; i++)
-          eina_rectangle_union(rect, &rects[i]);
+          wl_surface_damage(surface->surface, 
+                            rects[i].x, rects[i].y, 
+                            rects[i].w, rects[i].h);
      }
    else
-     {
-        Eina_Rectangle r;
-
-        r.x = 0; r.y = 0;
-        r.w = leaf->w; r.h = leaf->h;
+     wl_surface_damage(surface->surface, 0, 0, leaf->w, leaf->h);
 
-        eina_rectangle_union(rect, &r);
-     }
-
-   wl_surface_attach(surface->surface, leaf->data->buffer, 0, 0);
-   wl_surface_damage(surface->surface, rect->x, rect->y, rect->w, rect->h);
    wl_surface_commit(surface->surface);
 
-   eina_rectangle_free(rect);
-
    leaf->busy = 1;
    surface->dx = 0;
    surface->dy = 0;
    surface->redraw = EINA_TRUE;
+   surface->last_buff = surface->curr_buff;
+   surface->curr_buff = (int)(leaf - &surface->leaf[0]);
 }
 
 void *
-_evas_shm_surface_data_get(Shm_Surface *surface, int *bw, int *bh)
+_evas_shm_surface_data_get(Shm_Surface *surface, int *w, int *h)
 {
-   Shm_Leaf *leaf;
+   Shm_Leaf *leaf = NULL;
+   int i = 0;
 
    LOGFN(__FILE__, __LINE__, __FUNCTION__);
 
-   if (bw) *bw = 0;
-   if (bh) *bh = 0;
+   if (w) *w = 0;
+   if (h) *h = 0;
 
-   if (!(leaf = surface->current))
+   for (; i < surface->num_buff; i++)
      {
-        _evas_shm_surface_prepare(surface, 0, 0, surface->w, surface->h, 
-                                  surface->num_buff, surface->flags);
-
-        if (!(leaf = surface->current))
+        if (surface->leaf[i].busy) continue;
+        if ((!leaf) || (leaf->valid))
           {
-             CRI("NO Current Surface");
-             return NULL;
+             leaf = &surface->leaf[i];
+             break;
           }
      }
 
-   if (bw) *bw = leaf->w;
-   if (bh) *bh = leaf->h;
+   if (!leaf)
+     {
+        /* WRN("All buffers held by server"); */
+        return NULL;
+     }
+
+   /* DBG("Leaf Data Get %d", (int)(leaf - &surface->leaf[0])); */
+
+   if (w) *w = leaf->w;
+   if (h) *h = leaf->h;
 
    return leaf->data->map;
 }
@@ -473,5 +503,5 @@ _evas_shm_surface_redraw(Shm_Surface *surface)
    if (!surface->surface) return;
 
    surface->frame_cb = wl_surface_frame(surface->surface);
-   wl_callback_add_listener(surface->frame_cb, &_frame_listener, surface);
+   wl_callback_add_listener(surface->frame_cb, &_shm_frame_listener, surface);
 }