forked from AuroraMiddleware/gtk
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
This commit is contained in:
parent
6977ea0bd1
commit
cdf5c2af62
@ -379,13 +379,16 @@ else
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if test "x$enable_wayland_backend" == "xyes"; then
|
if test "x$enable_wayland_backend" == "xyes"; then
|
||||||
# Wayland uses cairo-gl
|
# For the cairo image backend
|
||||||
cairo_backends="$cairo_backends cairo-gl"
|
cairo_backends="$cairo_backends cairo"
|
||||||
GDK_BACKENDS="$GDK_BACKENDS wayland"
|
GDK_BACKENDS="$GDK_BACKENDS wayland"
|
||||||
have_gio_unix=yes
|
have_gio_unix=yes
|
||||||
GDK_WINDOWING="$GDK_WINDOWING
|
GDK_WINDOWING="$GDK_WINDOWING
|
||||||
#define GDK_WINDOWING_WAYLAND"
|
#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)
|
AM_CONDITIONAL(USE_WAYLAND, true)
|
||||||
else
|
else
|
||||||
AM_CONDITIONAL(USE_WAYLAND, false)
|
AM_CONDITIONAL(USE_WAYLAND, false)
|
||||||
|
@ -17,7 +17,9 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
|
#ifdef GDK_WAYLAND_USE_EGL
|
||||||
#include <wayland-egl.h>
|
#include <wayland-egl.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.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
|
static gboolean
|
||||||
gdk_display_init_egl(GdkDisplay *display)
|
gdk_display_init_egl(GdkDisplay *display)
|
||||||
{
|
{
|
||||||
@ -200,6 +203,7 @@ gdk_display_init_egl(GdkDisplay *display)
|
|||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
GdkDisplay *
|
GdkDisplay *
|
||||||
_gdk_wayland_display_open (const gchar *display_name)
|
_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,
|
wl_display_add_global_listener(display_wayland->wl_display,
|
||||||
gdk_display_handle_global, display_wayland);
|
gdk_display_handle_global, display_wayland);
|
||||||
|
|
||||||
|
#ifdef GDK_WAYLAND_USE_EGL
|
||||||
gdk_display_init_egl(display);
|
gdk_display_init_egl(display);
|
||||||
|
#else
|
||||||
|
wl_display_iterate(wl_display, WL_DISPLAY_READABLE);
|
||||||
|
wl_display_roundtrip(wl_display);
|
||||||
|
#endif
|
||||||
|
|
||||||
display_wayland->event_source =
|
display_wayland->event_source =
|
||||||
_gdk_wayland_display_event_source_new (display);
|
_gdk_wayland_display_event_source_new (display);
|
||||||
@ -257,7 +266,9 @@ gdk_wayland_display_dispose (GObject *object)
|
|||||||
display_wayland->event_source = NULL;
|
display_wayland->event_source = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef GDK_WAYLAND_USE_EGL
|
||||||
eglTerminate(display_wayland->egl_display);
|
eglTerminate(display_wayland->egl_display);
|
||||||
|
#endif
|
||||||
|
|
||||||
G_OBJECT_CLASS (_gdk_display_wayland_parent_class)->dispose (object);
|
G_OBJECT_CLASS (_gdk_display_wayland_parent_class)->dispose (object);
|
||||||
}
|
}
|
||||||
|
@ -22,14 +22,19 @@
|
|||||||
#ifndef __GDK_DISPLAY_WAYLAND__
|
#ifndef __GDK_DISPLAY_WAYLAND__
|
||||||
#define __GDK_DISPLAY_WAYLAND__
|
#define __GDK_DISPLAY_WAYLAND__
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <wayland-client.h>
|
#include <wayland-client.h>
|
||||||
|
|
||||||
|
#ifdef GDK_WAYLAND_USE_EGL
|
||||||
#include <wayland-egl.h>
|
#include <wayland-egl.h>
|
||||||
#include <EGL/egl.h>
|
#include <EGL/egl.h>
|
||||||
#include <EGL/eglext.h>
|
#include <EGL/eglext.h>
|
||||||
#include <GL/gl.h>
|
#include <GL/gl.h>
|
||||||
#include <GL/glext.h>
|
#include <GL/glext.h>
|
||||||
#include <cairo-gl.h>
|
#include <cairo-gl.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
#include <gdk/gdkkeys.h>
|
#include <gdk/gdkkeys.h>
|
||||||
#include <gdk/gdkwindow.h>
|
#include <gdk/gdkwindow.h>
|
||||||
@ -76,15 +81,20 @@ struct _GdkDisplayWayland
|
|||||||
struct wl_input_device *input_device;
|
struct wl_input_device *input_device;
|
||||||
struct wl_data_device_manager *data_device_manager;
|
struct wl_data_device_manager *data_device_manager;
|
||||||
GSource *event_source;
|
GSource *event_source;
|
||||||
|
|
||||||
|
#ifdef GDK_WAYLAND_USE_EGL
|
||||||
EGLDisplay egl_display;
|
EGLDisplay egl_display;
|
||||||
EGLContext egl_context;
|
EGLContext egl_context;
|
||||||
cairo_device_t *cairo_device;
|
cairo_device_t *cairo_device;
|
||||||
|
#endif
|
||||||
|
|
||||||
GdkCursor **cursors;
|
GdkCursor **cursors;
|
||||||
|
|
||||||
|
#ifdef GDK_WAYLAND_USE_EGL
|
||||||
PFNGLEGLIMAGETARGETTEXTURE2DOESPROC image_target_texture_2d;
|
PFNGLEGLIMAGETARGETTEXTURE2DOESPROC image_target_texture_2d;
|
||||||
PFNEGLCREATEIMAGEKHRPROC create_image;
|
PFNEGLCREATEIMAGEKHRPROC create_image;
|
||||||
PFNEGLDESTROYIMAGEKHRPROC destroy_image;
|
PFNEGLDESTROYIMAGEKHRPROC destroy_image;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GdkDisplayWaylandClass
|
struct _GdkDisplayWaylandClass
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
|
||||||
#include <wayland-egl.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;
|
static const cairo_user_data_key_t gdk_wayland_cairo_key;
|
||||||
|
|
||||||
typedef struct _GdkWaylandCairoSurfaceData {
|
typedef struct _GdkWaylandCairoSurfaceData {
|
||||||
|
#ifdef GDK_WAYLAND_USE_EGL
|
||||||
EGLImageKHR image;
|
EGLImageKHR image;
|
||||||
GLuint texture;
|
GLuint texture;
|
||||||
struct wl_egl_pixmap *pixmap;
|
struct wl_egl_pixmap *pixmap;
|
||||||
|
#else
|
||||||
|
gpointer buf;
|
||||||
|
size_t buf_length;
|
||||||
|
#endif
|
||||||
struct wl_buffer *buffer;
|
struct wl_buffer *buffer;
|
||||||
GdkDisplayWayland *display;
|
GdkDisplayWayland *display;
|
||||||
int32_t width, height;
|
int32_t width, height;
|
||||||
@ -366,6 +372,7 @@ gdk_wayland_window_attach_image (GdkWindow *window)
|
|||||||
wl_surface_attach (impl->surface, data->buffer, dx, dy);
|
wl_surface_attach (impl->surface, data->buffer, dx, dy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef GDK_WAYLAND_USE_EGL
|
||||||
static void
|
static void
|
||||||
gdk_wayland_cairo_surface_destroy (void *p)
|
gdk_wayland_cairo_surface_destroy (void *p)
|
||||||
{
|
{
|
||||||
@ -419,6 +426,100 @@ gdk_wayland_create_cairo_surface (GdkDisplayWayland *display,
|
|||||||
|
|
||||||
return surface;
|
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
|
/* On this first call this creates a double reference - the first reference
|
||||||
* is held by the GdkWindowImplWayland struct - since unlike other backends
|
* is held by the GdkWindowImplWayland struct - since unlike other backends
|
||||||
@ -1360,10 +1461,13 @@ gdk_wayland_window_destroy_notify (GdkWindow *window)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gdk_wayland_window_process_updates_recurse (GdkWindow *window,
|
gdk_wayland_window_process_updates_recurse (GdkWindow *window,
|
||||||
cairo_region_t *region)
|
cairo_region_t *region)
|
||||||
{
|
{
|
||||||
GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
|
GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
|
||||||
|
#ifndef GDK_WAYLAND_USE_EGL
|
||||||
|
GdkWaylandCairoSurfaceData *data = NULL;
|
||||||
|
#endif
|
||||||
cairo_rectangle_int_t rect;
|
cairo_rectangle_int_t rect;
|
||||||
int i, n;
|
int i, n;
|
||||||
|
|
||||||
@ -1372,12 +1476,23 @@ gdk_wayland_window_process_updates_recurse (GdkWindow *window,
|
|||||||
if (impl->cairo_surface)
|
if (impl->cairo_surface)
|
||||||
gdk_wayland_window_attach_image (window);
|
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);
|
n = cairo_region_num_rectangles(region);
|
||||||
for (i = 0; i < n; i++)
|
for (i = 0; i < n; i++)
|
||||||
{
|
{
|
||||||
cairo_region_get_rectangle (region, i, &rect);
|
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,
|
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);
|
_gdk_window_process_updates_recurse (window, region);
|
||||||
|
Loading…
Reference in New Issue
Block a user