[gtk+/wip/wayland-buffer: 2/2] buffer



commit c6007924c3eae1de2f59158e17646803f5a6ec18
Author: Jasper St. Pierre <jstpierre mecheye net>
Date:   Sun Feb 23 13:57:24 2014 -0500

    buffer

 gdk/wayland/gdkcursor-wayland.c  |   45 ++------
 gdk/wayland/gdkdisplay-wayland.c |  168 ++++++++++++++++++++++++++++++
 gdk/wayland/gdkprivate-wayland.h |   12 ++-
 gdk/wayland/gdkwindow-wayland.c  |  209 +++----------------------------------
 4 files changed, 204 insertions(+), 230 deletions(-)
---
diff --git a/gdk/wayland/gdkcursor-wayland.c b/gdk/wayland/gdkcursor-wayland.c
index e88fff5..677f500 100644
--- a/gdk/wayland/gdkcursor-wayland.c
+++ b/gdk/wayland/gdkcursor-wayland.c
@@ -56,7 +56,7 @@ struct _GdkWaylandCursor
   {
     int hotspot_x, hotspot_y;
     int width, height, scale;
-    struct wl_buffer *buffer;
+    cairo_surface_t *cairo_surface;
   } surface;
 
   struct wl_cursor *wl_cursor;
@@ -168,8 +168,8 @@ gdk_wayland_cursor_finalize (GObject *object)
   GdkWaylandCursor *cursor = GDK_WAYLAND_CURSOR (object);
 
   g_free (cursor->name);
-  if (cursor->surface.buffer)
-    wl_buffer_destroy (cursor->surface.buffer);
+  if (cursor->surface.cairo_surface)
+    cairo_surface_destroy (cursor->surface.cairo_surface);
 
   G_OBJECT_CLASS (_gdk_wayland_cursor_parent_class)->finalize (object);
 }
@@ -225,7 +225,10 @@ _gdk_wayland_cursor_get_buffer (GdkCursor *cursor,
       *h = wayland_cursor->surface.height / wayland_cursor->surface.scale;
       *scale = wayland_cursor->surface.scale;
 
-      return wayland_cursor->surface.buffer;
+      if (wayland_cursor->surface.cairo_surface)
+        return _gdk_wayland_shm_surface_get_wl_buffer (wayland_cursor->surface.cairo_surface);
+      else
+        return NULL;
     }
 }
 
@@ -339,11 +342,6 @@ _gdk_wayland_display_get_cursor_for_surface (GdkDisplay *display,
 {
   GdkWaylandCursor *cursor;
   GdkWaylandDisplay *wayland_display = GDK_WAYLAND_DISPLAY (display);
-  int stride;
-  size_t size;
-  gpointer data;
-  struct wl_shm_pool *pool;
-  cairo_surface_t *buffer_surface;
   cairo_t *cr;
 
   cursor = g_object_new (GDK_TYPE_WAYLAND_CURSOR,
@@ -375,36 +373,17 @@ _gdk_wayland_display_get_cursor_for_surface (GdkDisplay *display,
       cursor->surface.height = 1;
     }
 
-  pool = _create_shm_pool (wayland_display->shm,
-                           cursor->surface.width,
-                           cursor->surface.height,
-                           &size,
-                           &data);
-
+  cursor->surface.cairo_surface = _gdk_wayland_display_create_shm_surface (wayland_display,
+                                                                           cursor->surface.width,
+                                                                           cursor->surface.height,
+                                                                           cursor->surface.scale);
   if (surface)
     {
-      buffer_surface = cairo_image_surface_create_for_data (data,
-                                                           CAIRO_FORMAT_ARGB32,
-                                                           cursor->surface.width,
-                                                           cursor->surface.height,
-                                                           cursor->surface.width * 4);
-      cr = cairo_create (buffer_surface);
+      cr = cairo_create (cursor->surface.cairo_surface);
       cairo_set_source_surface (cr, surface, 0, 0);
       cairo_paint (cr);
       cairo_destroy (cr);
-      cairo_surface_destroy (buffer_surface);
     }
-  else
-    memset (data, 0, 4);
-
-  stride = cursor->surface.width * 4;
-  cursor->surface.buffer = wl_shm_pool_create_buffer (pool, 0,
-                                                     cursor->surface.width,
-                                                     cursor->surface.height,
-                                                     stride,
-                                                     WL_SHM_FORMAT_ARGB8888);
-
-  wl_shm_pool_destroy (pool);
 
   return GDK_CURSOR (cursor);
 }
diff --git a/gdk/wayland/gdkdisplay-wayland.c b/gdk/wayland/gdkdisplay-wayland.c
index 3df219d..757fe8b 100644
--- a/gdk/wayland/gdkdisplay-wayland.c
+++ b/gdk/wayland/gdkdisplay-wayland.c
@@ -22,6 +22,7 @@
 #include <errno.h>
 #include <unistd.h>
 #include <fcntl.h>
+#include <sys/mman.h>
 
 #include <glib.h>
 #include "gdkwayland.h"
@@ -762,3 +763,170 @@ gdk_wayland_display_get_xdg_shell (GdkDisplay *display)
 
   return wayland_display->xdg_shell;
 }
+
+static const cairo_user_data_key_t gdk_wayland_cairo_key;
+
+typedef struct _GdkWaylandCairoSurfaceData {
+  gpointer buf;
+  size_t buf_length;
+  struct wl_shm_pool *pool;
+  struct wl_buffer *buffer;
+  GdkWaylandDisplay *display;
+  uint32_t scale;
+  gboolean busy;
+} GdkWaylandCairoSurfaceData;
+
+static void
+buffer_release_callback (void             *_data,
+                         struct wl_buffer *wl_buffer)
+{
+  cairo_surface_t *surface = _data;
+  GdkWaylandCairoSurfaceData *data = cairo_surface_get_user_data (surface, &gdk_wayland_cairo_key);
+
+  data->busy = FALSE;
+  cairo_surface_destroy (surface);
+}
+
+static const struct wl_buffer_listener buffer_listener = {
+  buffer_release_callback
+};
+
+struct wl_shm_pool *
+create_shm_pool (struct wl_shm  *shm,
+                 int             width,
+                 int             height,
+                 size_t         *buf_length,
+                 void          **data_out)
+{
+  char filename[] = "/tmp/wayland-shm-XXXXXX";
+  struct wl_shm_pool *pool;
+  int fd, size, stride;
+  void *data;
+
+  fd = mkstemp (filename);
+  if (fd < 0)
+    {
+      g_critical (G_STRLOC ": Unable to create temporary file (%s): %s",
+                  filename, g_strerror (errno));
+      return NULL;
+    }
+
+  stride = width * 4;
+  size = stride * height;
+  if (ftruncate (fd, size) < 0)
+    {
+      g_critical (G_STRLOC ": Truncating temporary file failed: %s",
+                  g_strerror (errno));
+      close (fd);
+      return NULL;
+    }
+
+  data = mmap (NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+  unlink (filename);
+
+  if (data == MAP_FAILED)
+    {
+      g_critical (G_STRLOC ": mmap'ping temporary file failed: %s",
+                  g_strerror (errno));
+      close (fd);
+      return NULL;
+    }
+
+  pool = wl_shm_create_pool(shm, fd, size);
+
+  close (fd);
+
+  *data_out = data;
+  *buf_length = size;
+
+  return pool;
+}
+
+static void
+gdk_wayland_cairo_surface_destroy (void *p)
+{
+  GdkWaylandCairoSurfaceData *data = p;
+
+  if (data->buffer)
+    wl_buffer_destroy (data->buffer);
+
+  if (data->pool)
+    wl_shm_pool_destroy (data->pool);
+
+  munmap (data->buf, data->buf_length);
+  g_free (data);
+}
+
+cairo_surface_t *
+_gdk_wayland_display_create_shm_surface (GdkWaylandDisplay *display,
+                                         int                width,
+                                         int                height,
+                                         guint              scale)
+{
+  GdkWaylandCairoSurfaceData *data;
+  cairo_surface_t *surface = NULL;
+  cairo_status_t status;
+  int stride;
+
+  data = g_new (GdkWaylandCairoSurfaceData, 1);
+  data->display = display;
+  data->buffer = NULL;
+  data->scale = scale;
+  data->busy = FALSE;
+
+  stride = width * 4;
+
+  data->pool = create_shm_pool (display->shm,
+                                width*scale, height*scale,
+                                &data->buf_length,
+                                &data->buf);
+
+  surface = cairo_image_surface_create_for_data (data->buf,
+                                                 CAIRO_FORMAT_ARGB32,
+                                                 width*scale,
+                                                 height*scale,
+                                                 stride*scale);
+
+  data->buffer = wl_shm_pool_create_buffer (data->pool, 0,
+                                            width*scale, height*scale,
+                                            stride*scale, WL_SHM_FORMAT_ARGB8888);
+  wl_buffer_add_listener (data->buffer, &buffer_listener, surface);
+
+  cairo_surface_set_user_data (surface, &gdk_wayland_cairo_key,
+                               data, gdk_wayland_cairo_surface_destroy);
+
+#ifdef HAVE_CAIRO_SURFACE_SET_DEVICE_SCALE
+  cairo_surface_set_device_scale (surface, scale, scale);
+#endif
+
+  status = cairo_surface_status (surface);
+  if (status != CAIRO_STATUS_SUCCESS)
+    {
+      g_critical (G_STRLOC ": Unable to create Cairo image surface: %s",
+                  cairo_status_to_string (status));
+    }
+
+  return surface;
+}
+
+struct wl_buffer *
+_gdk_wayland_shm_surface_get_wl_buffer (cairo_surface_t *surface)
+{
+  GdkWaylandCairoSurfaceData *data = cairo_surface_get_user_data (surface, &gdk_wayland_cairo_key);
+  return data->buffer;
+}
+
+void
+_gdk_wayland_shm_surface_set_busy (cairo_surface_t *surface)
+{
+  GdkWaylandCairoSurfaceData *data = cairo_surface_get_user_data (surface, &gdk_wayland_cairo_key);
+  data->busy = TRUE;
+  cairo_surface_reference (surface);
+}
+
+gboolean
+_gdk_wayland_shm_surface_get_busy (cairo_surface_t *surface)
+{
+  GdkWaylandCairoSurfaceData *data = cairo_surface_get_user_data (surface, &gdk_wayland_cairo_key);
+  return data->busy;
+}
diff --git a/gdk/wayland/gdkprivate-wayland.h b/gdk/wayland/gdkprivate-wayland.h
index 03016ca..d6d2375 100644
--- a/gdk/wayland/gdkprivate-wayland.h
+++ b/gdk/wayland/gdkprivate-wayland.h
@@ -178,10 +178,12 @@ void _gdk_wayland_window_set_device_grabbed (GdkWindow      *window,
 guint32 _gdk_wayland_display_get_serial (GdkWaylandDisplay *wayland_display);
 void _gdk_wayland_display_update_serial (GdkWaylandDisplay *wayland_display, guint32 serial);
 
-struct wl_shm_pool * _create_shm_pool (struct wl_shm *shm,
-                                      int             width,
-                                      int             height,
-                                      size_t         *buf_length,
-                                      void          **data_out);
+cairo_surface_t * _gdk_wayland_display_create_shm_surface (GdkWaylandDisplay *display,
+                                                           int                width,
+                                                           int                height,
+                                                           guint              scale);
+struct wl_buffer *_gdk_wayland_shm_surface_get_wl_buffer (cairo_surface_t *surface);
+void _gdk_wayland_shm_surface_set_busy (cairo_surface_t *surface);
+gboolean _gdk_wayland_shm_surface_get_busy (cairo_surface_t *surface);
 
 #endif /* __GDK_PRIVATE_WAYLAND_H__ */
diff --git a/gdk/wayland/gdkwindow-wayland.c b/gdk/wayland/gdkwindow-wayland.c
index 82dafb2..71710d3 100644
--- a/gdk/wayland/gdkwindow-wayland.c
+++ b/gdk/wayland/gdkwindow-wayland.c
@@ -34,7 +34,6 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
-#include <sys/mman.h>
 #include <errno.h>
 
 #define WL_SURFACE_HAS_BUFFER_SCALE 3
@@ -379,25 +378,11 @@ on_frame_clock_before_paint (GdkFrameClock *clock,
     }
 }
 
-static const cairo_user_data_key_t gdk_wayland_cairo_key;
-
-typedef struct _GdkWaylandCairoSurfaceData {
-  gpointer buf;
-  size_t buf_length;
-  struct wl_shm_pool *pool;
-  struct wl_buffer *buffer;
-  GdkWaylandDisplay *display;
-  int32_t width, height;
-  uint32_t scale;
-  gboolean busy;
-} GdkWaylandCairoSurfaceData;
-
 static void
 on_frame_clock_after_paint (GdkFrameClock *clock,
                             GdkWindow     *window)
 {
   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
-  GdkWaylandCairoSurfaceData *data;
   struct wl_callback *callback;
 
   if (!impl->pending_commit)
@@ -411,14 +396,7 @@ on_frame_clock_after_paint (GdkFrameClock *clock,
   _gdk_frame_clock_freeze (clock);
 
   wl_surface_commit (impl->surface);
-
-  data = cairo_surface_get_user_data (impl->cairo_surface,
-                                      &gdk_wayland_cairo_key);
-  if (!data->busy)
-    {
-      data->busy = TRUE;
-      cairo_surface_reference (impl->cairo_surface);
-    }
+  _gdk_wayland_shm_surface_set_busy (impl->cairo_surface);
 }
 
 static void
@@ -542,7 +520,6 @@ gdk_wayland_window_attach_image (GdkWindow *window)
 {
   GdkWaylandDisplay *display;
   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
-  GdkWaylandCairoSurfaceData *data;
   int32_t server_width, server_height, dx, dy;
 
   if (GDK_WINDOW_DESTROYED (window))
@@ -553,12 +530,9 @@ gdk_wayland_window_attach_image (GdkWindow *window)
    */
   if (impl->server_surface)
     {
-      data = cairo_surface_get_user_data (impl->server_surface,
-                                          &gdk_wayland_cairo_key);
-
       /* Save the old dimensions used for the surface */
-      server_width = data->width;
-      server_height = data->height;
+      server_width = cairo_image_surface_get_width (impl->server_surface);
+      server_height = cairo_image_surface_get_height (impl->server_surface);
 
       cairo_surface_destroy (impl->server_surface);
     }
@@ -571,181 +545,41 @@ gdk_wayland_window_attach_image (GdkWindow *window)
   /* Save the current "drawn to" surface for future calls into here */
   impl->server_surface = cairo_surface_reference (impl->cairo_surface);
 
-  /* Get a Wayland buffer from this new surface */
-  data = cairo_surface_get_user_data (impl->cairo_surface,
-                                      &gdk_wayland_cairo_key);
-
   if (impl->resize_edges & XDG_SURFACE_RESIZE_EDGE_LEFT)
-    dx = server_width - data->width;
+    dx = server_width - cairo_image_surface_get_width (impl->cairo_surface);
   else
     dx = 0;
 
   if (impl->resize_edges & XDG_SURFACE_RESIZE_EDGE_TOP)
-    dy = server_height - data->height;
+    dy = server_height - cairo_image_surface_get_height (impl->cairo_surface);
   else
     dy = 0;
 
   /* Attach this new buffer to the surface */
-  wl_surface_attach (impl->surface, data->buffer, dx, dy);
+  wl_surface_attach (impl->surface,
+                     _gdk_wayland_shm_surface_get_wl_buffer (impl->cairo_surface),
+                     dx, dy);
 
   /* Only set the buffer scale if supported by the compositor */
   display = GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
   if (display->compositor_version >= WL_SURFACE_HAS_BUFFER_SCALE)
-    wl_surface_set_buffer_scale (impl->surface, data->scale);
+    wl_surface_set_buffer_scale (impl->surface, impl->scale);
 
   impl->pending_commit = TRUE;
 }
 
 static void
-gdk_wayland_cairo_surface_destroy (void *p)
-{
-  GdkWaylandCairoSurfaceData *data = p;
-
-  if (data->buffer)
-    wl_buffer_destroy (data->buffer);
-
-  if (data->pool)
-    wl_shm_pool_destroy (data->pool);
-
-  munmap (data->buf, data->buf_length);
-  g_free (data);
-}
-
-struct wl_shm_pool *
-_create_shm_pool (struct wl_shm  *shm,
-                  int             width,
-                  int             height,
-                  size_t         *buf_length,
-                  void          **data_out)
-{
-  char filename[] = "/tmp/wayland-shm-XXXXXX";
-  struct wl_shm_pool *pool;
-  int fd, size, stride;
-  void *data;
-
-  fd = mkstemp (filename);
-  if (fd < 0)
-    {
-      g_critical (G_STRLOC ": Unable to create temporary file (%s): %s",
-                  filename, g_strerror (errno));
-      return NULL;
-    }
-
-  stride = width * 4;
-  size = stride * height;
-  if (ftruncate (fd, size) < 0)
-    {
-      g_critical (G_STRLOC ": Truncating temporary file failed: %s",
-                  g_strerror (errno));
-      close (fd);
-      return NULL;
-    }
-
-  data = mmap (NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
-  unlink (filename);
-
-  if (data == MAP_FAILED)
-    {
-      g_critical (G_STRLOC ": mmap'ping temporary file failed: %s",
-                  g_strerror (errno));
-      close (fd);
-      return NULL;
-    }
-
-  pool = wl_shm_create_pool(shm, fd, size);
-
-  close (fd);
-
-  *data_out = data;
-  *buf_length = size;
-
-  return pool;
-}
-
-
-static void
-buffer_release_callback (void             *_data,
-                         struct wl_buffer *wl_buffer)
-{
-  cairo_surface_t *surface = _data;
-  GdkWaylandCairoSurfaceData *data = cairo_surface_get_user_data (surface, &gdk_wayland_cairo_key);
-
-  data->busy = FALSE;
-  cairo_surface_destroy (surface);
-}
-
-static const struct wl_buffer_listener buffer_listener = {
-  buffer_release_callback
-};
-
-static cairo_surface_t *
-gdk_wayland_create_cairo_surface (GdkWaylandDisplay *display,
-                                  int                width,
-                                  int                height,
-                                  guint              scale)
-{
-  GdkWaylandCairoSurfaceData *data;
-  cairo_surface_t *surface = NULL;
-  cairo_status_t status;
-  int stride;
-
-  data = g_new (GdkWaylandCairoSurfaceData, 1);
-  data->display = display;
-  data->buffer = NULL;
-  data->width = width;
-  data->height = height;
-  data->scale = scale;
-  data->busy = FALSE;
-
-  stride = width * 4;
-
-  data->pool = _create_shm_pool (display->shm,
-                                 width*scale, height*scale,
-                                 &data->buf_length,
-                                 &data->buf);
-
-  surface = cairo_image_surface_create_for_data (data->buf,
-                                                 CAIRO_FORMAT_ARGB32,
-                                                 width*scale,
-                                                 height*scale,
-                                                 stride*scale);
-
-  data->buffer = wl_shm_pool_create_buffer (data->pool, 0,
-                                            width*scale, height*scale,
-                                            stride*scale, WL_SHM_FORMAT_ARGB8888);
-  wl_buffer_add_listener (data->buffer, &buffer_listener, surface);
-
-  cairo_surface_set_user_data (surface, &gdk_wayland_cairo_key,
-                               data, gdk_wayland_cairo_surface_destroy);
-
-#ifdef HAVE_CAIRO_SURFACE_SET_DEVICE_SCALE
-  cairo_surface_set_device_scale (surface, scale, scale);
-#endif
-
-  status = cairo_surface_status (surface);
-  if (status != CAIRO_STATUS_SUCCESS)
-    {
-      g_critical (G_STRLOC ": Unable to create Cairo image surface: %s",
-                  cairo_status_to_string (status));
-    }
-
-  return surface;
-}
-
-static void
 gdk_wayland_window_ensure_cairo_surface (GdkWindow *window)
 {
   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
   if (!impl->cairo_surface)
     {
-      GdkWaylandDisplay *display_wayland =
-        GDK_WAYLAND_DISPLAY (gdk_window_get_display (impl->wrapper));
-
-      impl->cairo_surface =
-        gdk_wayland_create_cairo_surface (display_wayland,
-                                          impl->wrapper->width,
-                                          impl->wrapper->height,
-                                          impl->scale);
+      GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (gdk_window_get_display (impl->wrapper));
+
+      impl->cairo_surface = _gdk_wayland_display_create_shm_surface (display_wayland,
+                                                                     impl->wrapper->width,
+                                                                     impl->wrapper->height,
+                                                                     impl->scale);
     }
 }
 
@@ -781,13 +615,8 @@ gdk_window_impl_wayland_begin_paint_region (GdkWindow            *window,
                                             const cairo_region_t *region)
 {
   GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
-  GdkWaylandCairoSurfaceData *data;
-
   gdk_wayland_window_ensure_cairo_surface (window);
-  data = cairo_surface_get_user_data (impl->cairo_surface,
-                                      &gdk_wayland_cairo_key);
-
-  return data->busy;
+  return _gdk_wayland_shm_surface_get_busy (impl->cairo_surface);
 }
 
 static void
@@ -1469,11 +1298,7 @@ gdk_wayland_window_destroy (GdkWindow *window,
   gdk_wayland_window_hide_surface (window, TRUE);
 
   if (impl->cairo_surface)
-    {
-      cairo_surface_finish (impl->cairo_surface);
-      cairo_surface_set_user_data (impl->cairo_surface, &gdk_wayland_cairo_key,
-                                   NULL, NULL);
-    }
+    cairo_surface_finish (impl->cairo_surface);
 }
 
 static void


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]