summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJasper St. Pierre <jstpierre@mecheye.net>2014-02-23 13:57:24 -0500
committerJasper St. Pierre <jstpierre@mecheye.net>2014-02-24 20:39:30 -0500
commitc6007924c3eae1de2f59158e17646803f5a6ec18 (patch)
treed7daab1475160cbdb9438ff94b7db78f7c9c555b
parent6b921142ab44b2b36f5b190527a454059e8bc1ea (diff)
downloadgtk+-wip/wayland-buffer.tar.gz
-rw-r--r--gdk/wayland/gdkcursor-wayland.c45
-rw-r--r--gdk/wayland/gdkdisplay-wayland.c168
-rw-r--r--gdk/wayland/gdkprivate-wayland.h12
-rw-r--r--gdk/wayland/gdkwindow-wayland.c209
4 files changed, 204 insertions, 230 deletions
diff --git a/gdk/wayland/gdkcursor-wayland.c b/gdk/wayland/gdkcursor-wayland.c
index e88fff5f89..677f500bc2 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 3df219dc02..757fe8bb25 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 03016ca7a6..d6d2375429 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 82dafb21ff..71710d3510 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