[gtk+] wayland: Add support for rendering into an SHM buffer with Cairo image backend
- From: Rob Bradford <rbradford src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+] wayland: Add support for rendering into an SHM buffer with Cairo image backend
- Date: Mon, 16 Apr 2012 14:27:32 +0000 (UTC)
commit cdf5c2af628a1ca202cd8c6a8d3529b46718183b
Author: Rob Bradford <rob linux intel com>
Date: Wed Apr 4 17:20:13 2012 +0100
wayland: Add support for rendering into an SHM buffer with Cairo image backend
The first version of this change included a bug that meant that if you don't
compile for any other backend then it wouldn't search for cairo. Credit for
identifying the bug goes to darxus chaosreigns com
Fixes: https://bugzilla.gnome.org/show_bug.cgi?id=672361
configure.ac | 9 ++-
gdk/wayland/gdkdisplay-wayland.c | 11 ++++
gdk/wayland/gdkdisplay-wayland.h | 10 +++
gdk/wayland/gdkwindow-wayland.c | 121 +++++++++++++++++++++++++++++++++++++-
4 files changed, 145 insertions(+), 6 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 93cf281..8e1d691 100644
--- a/configure.ac
+++ b/configure.ac
@@ -379,13 +379,16 @@ else
fi
if test "x$enable_wayland_backend" == "xyes"; then
- # Wayland uses cairo-gl
- cairo_backends="$cairo_backends cairo-gl"
+ # For the cairo image backend
+ cairo_backends="$cairo_backends cairo"
GDK_BACKENDS="$GDK_BACKENDS wayland"
have_gio_unix=yes
GDK_WINDOWING="$GDK_WINDOWING
#define GDK_WINDOWING_WAYLAND"
- WAYLAND_PACKAGES="wayland-client xkbcommon wayland-egl egl"
+ WAYLAND_PACKAGES="wayland-client xkbcommon "
+ if test "x$enable_wayland_cairo_gl" == "xyes"; then
+ WAYLAND_PACKAGES="$WAYLAND_PACKAGES wayland-egl egl"
+ fi
AM_CONDITIONAL(USE_WAYLAND, true)
else
AM_CONDITIONAL(USE_WAYLAND, false)
diff --git a/gdk/wayland/gdkdisplay-wayland.c b/gdk/wayland/gdkdisplay-wayland.c
index 6367bb0..1d81395 100644
--- a/gdk/wayland/gdkdisplay-wayland.c
+++ b/gdk/wayland/gdkdisplay-wayland.c
@@ -17,7 +17,9 @@
#include "config.h"
+#ifdef GDK_WAYLAND_USE_EGL
#include <wayland-egl.h>
+#endif
#include <stdlib.h>
#include <string.h>
@@ -145,6 +147,7 @@ gdk_display_handle_global(struct wl_display *display, uint32_t id,
}
}
+#ifdef GDK_WAYLAND_USE_EGL
static gboolean
gdk_display_init_egl(GdkDisplay *display)
{
@@ -200,6 +203,7 @@ gdk_display_init_egl(GdkDisplay *display)
return TRUE;
}
+#endif
GdkDisplay *
_gdk_wayland_display_open (const gchar *display_name)
@@ -225,7 +229,12 @@ _gdk_wayland_display_open (const gchar *display_name)
wl_display_add_global_listener(display_wayland->wl_display,
gdk_display_handle_global, display_wayland);
+#ifdef GDK_WAYLAND_USE_EGL
gdk_display_init_egl(display);
+#else
+ wl_display_iterate(wl_display, WL_DISPLAY_READABLE);
+ wl_display_roundtrip(wl_display);
+#endif
display_wayland->event_source =
_gdk_wayland_display_event_source_new (display);
@@ -257,7 +266,9 @@ gdk_wayland_display_dispose (GObject *object)
display_wayland->event_source = NULL;
}
+#ifdef GDK_WAYLAND_USE_EGL
eglTerminate(display_wayland->egl_display);
+#endif
G_OBJECT_CLASS (_gdk_display_wayland_parent_class)->dispose (object);
}
diff --git a/gdk/wayland/gdkdisplay-wayland.h b/gdk/wayland/gdkdisplay-wayland.h
index a248125..ae456bc 100644
--- a/gdk/wayland/gdkdisplay-wayland.h
+++ b/gdk/wayland/gdkdisplay-wayland.h
@@ -22,14 +22,19 @@
#ifndef __GDK_DISPLAY_WAYLAND__
#define __GDK_DISPLAY_WAYLAND__
+#include <config.h>
#include <stdint.h>
#include <wayland-client.h>
+
+#ifdef GDK_WAYLAND_USE_EGL
#include <wayland-egl.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <GL/gl.h>
#include <GL/glext.h>
#include <cairo-gl.h>
+#endif
+
#include <glib.h>
#include <gdk/gdkkeys.h>
#include <gdk/gdkwindow.h>
@@ -76,15 +81,20 @@ struct _GdkDisplayWayland
struct wl_input_device *input_device;
struct wl_data_device_manager *data_device_manager;
GSource *event_source;
+
+#ifdef GDK_WAYLAND_USE_EGL
EGLDisplay egl_display;
EGLContext egl_context;
cairo_device_t *cairo_device;
+#endif
GdkCursor **cursors;
+#ifdef GDK_WAYLAND_USE_EGL
PFNGLEGLIMAGETARGETTEXTURE2DOESPROC image_target_texture_2d;
PFNEGLCREATEIMAGEKHRPROC create_image;
PFNEGLDESTROYIMAGEKHRPROC destroy_image;
+#endif
};
struct _GdkDisplayWaylandClass
diff --git a/gdk/wayland/gdkwindow-wayland.c b/gdk/wayland/gdkwindow-wayland.c
index 80ed791..d2adc36 100644
--- a/gdk/wayland/gdkwindow-wayland.c
+++ b/gdk/wayland/gdkwindow-wayland.c
@@ -33,6 +33,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
+#include <sys/mman.h>
#include <wayland-egl.h>
@@ -300,9 +301,14 @@ _gdk_wayland_display_create_window_impl (GdkDisplay *display,
static const cairo_user_data_key_t gdk_wayland_cairo_key;
typedef struct _GdkWaylandCairoSurfaceData {
+#ifdef GDK_WAYLAND_USE_EGL
EGLImageKHR image;
GLuint texture;
struct wl_egl_pixmap *pixmap;
+#else
+ gpointer buf;
+ size_t buf_length;
+#endif
struct wl_buffer *buffer;
GdkDisplayWayland *display;
int32_t width, height;
@@ -366,6 +372,7 @@ gdk_wayland_window_attach_image (GdkWindow *window)
wl_surface_attach (impl->surface, data->buffer, dx, dy);
}
+#ifdef GDK_WAYLAND_USE_EGL
static void
gdk_wayland_cairo_surface_destroy (void *p)
{
@@ -419,6 +426,100 @@ gdk_wayland_create_cairo_surface (GdkDisplayWayland *display,
return surface;
}
+#else
+static struct wl_buffer *
+create_shm_buffer (struct wl_shm *shm,
+ int width,
+ int height,
+ uint32_t format,
+ size_t *buf_length,
+ void **data_out)
+{
+ char filename[] = "/tmp/wayland-shm-XXXXXX";
+ struct wl_buffer *buffer;
+ int fd, size, stride;
+ void *data;
+
+ fd = mkstemp(filename);
+ if (fd < 0) {
+ fprintf(stderr, "open %s failed: %m\n", filename);
+ return NULL;
+ }
+ stride = width * 4;
+ size = stride * height;
+ if (ftruncate(fd, size) < 0) {
+ fprintf(stderr, "ftruncate failed: %m\n");
+ close(fd);
+ return NULL;
+ }
+
+ data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ unlink(filename);
+
+ if (data == MAP_FAILED) {
+ fprintf(stderr, "mmap failed: %m\n");
+ close(fd);
+ return NULL;
+ }
+
+ buffer = wl_shm_create_buffer(shm, fd,
+ width, height,
+ stride, format);
+
+ close(fd);
+
+ *data_out = data;
+ *buf_length = size;
+ return buffer;
+}
+
+static void
+gdk_wayland_cairo_surface_destroy (void *p)
+{
+ GdkWaylandCairoSurfaceData *data = p;
+
+ if (data->buffer)
+ wl_buffer_destroy(data->buffer);
+
+ munmap(data->buf, data->buf_length);
+ g_free(data);
+}
+
+static cairo_surface_t *
+gdk_wayland_create_cairo_surface (GdkDisplayWayland *display,
+ int width, int height)
+{
+ GdkWaylandCairoSurfaceData *data;
+ cairo_surface_t *surface;
+
+ data = g_new (GdkWaylandCairoSurfaceData, 1);
+ data->display = display;
+ data->buffer = NULL;
+ data->width = width;
+ data->height = height;
+
+ data->buffer = create_shm_buffer (display->shm,
+ width,
+ height,
+ WL_SHM_FORMAT_XRGB8888,
+ &data->buf_length,
+ &data->buf);
+
+ surface = cairo_image_surface_create_for_data (data->buf,
+ CAIRO_FORMAT_RGB24,
+ width,
+ height,
+ width * 4);
+
+ cairo_surface_set_user_data (surface, &gdk_wayland_cairo_key,
+ data, gdk_wayland_cairo_surface_destroy);
+
+ if (cairo_surface_status (surface) != CAIRO_STATUS_SUCCESS)
+ fprintf (stderr, "create image surface failed\n");
+
+ return surface;
+}
+#endif
/* On this first call this creates a double reference - the first reference
* is held by the GdkWindowImplWayland struct - since unlike other backends
@@ -1360,10 +1461,13 @@ gdk_wayland_window_destroy_notify (GdkWindow *window)
}
static void
-gdk_wayland_window_process_updates_recurse (GdkWindow *window,
- cairo_region_t *region)
+gdk_wayland_window_process_updates_recurse (GdkWindow *window,
+ cairo_region_t *region)
{
GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
+#ifndef GDK_WAYLAND_USE_EGL
+ GdkWaylandCairoSurfaceData *data = NULL;
+#endif
cairo_rectangle_int_t rect;
int i, n;
@@ -1372,12 +1476,23 @@ gdk_wayland_window_process_updates_recurse (GdkWindow *window,
if (impl->cairo_surface)
gdk_wayland_window_attach_image (window);
+#ifndef GDK_WAYLAND_USE_EGL
+ if (impl->server_surface)
+ data = cairo_surface_get_user_data (impl->server_surface,
+ &gdk_wayland_cairo_key);
+#endif
+
n = cairo_region_num_rectangles(region);
for (i = 0; i < n; i++)
{
cairo_region_get_rectangle (region, i, &rect);
+#ifndef GDK_WAYLAND_USE_EGL
+ if (data && data->buffer)
+ wl_buffer_damage (data->buffer,
+ rect.x, rect.y, rect.width, rect.height);
+#endif
wl_surface_damage (impl->surface,
- rect.x, rect.y, rect.width, rect.height);
+ rect.x, rect.y, rect.width, rect.height);
}
_gdk_window_process_updates_recurse (window, region);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]