window: Use window surfaces for windows
This commit is contained in:
+2
-2
@@ -110,7 +110,7 @@ item_create(struct display *display, int x, int y, int seed)
|
|||||||
|
|
||||||
rect.width = item_width;
|
rect.width = item_width;
|
||||||
rect.height = item_height;
|
rect.height = item_height;
|
||||||
item->surface = display_create_surface(display, &rect);
|
item->surface = display_create_surface(display, NULL, &rect);
|
||||||
|
|
||||||
item->x = x;
|
item->x = x;
|
||||||
item->y = y;
|
item->y = y;
|
||||||
@@ -527,7 +527,7 @@ create_drag_cursor(struct dnd_drag *dnd_drag,
|
|||||||
|
|
||||||
rectangle.width = item_width + 2 * pointer_width;
|
rectangle.width = item_width + 2 * pointer_width;
|
||||||
rectangle.height = item_height + 2 * pointer_height;
|
rectangle.height = item_height + 2 * pointer_height;
|
||||||
surface = display_create_surface(dnd->display, &rectangle);
|
surface = display_create_surface(dnd->display, NULL, &rectangle);
|
||||||
|
|
||||||
cr = cairo_create(surface);
|
cr = cairo_create(surface);
|
||||||
cairo_translate(cr, pointer_width, pointer_height);
|
cairo_translate(cr, pointer_width, pointer_height);
|
||||||
|
|||||||
@@ -359,6 +359,7 @@ gears_create(struct display *display)
|
|||||||
gears->d = display;
|
gears->d = display;
|
||||||
gears->window = window_create(display, width, height);
|
gears->window = window_create(display, width, height);
|
||||||
window_set_title(gears->window, "Wayland Gears");
|
window_set_title(gears->window, "Wayland Gears");
|
||||||
|
window_set_buffer_type(gears->window, WINDOW_BUFFER_TYPE_EGL_IMAGE);
|
||||||
|
|
||||||
gears->display = display_get_egl_display(gears->d);
|
gears->display = display_get_egl_display(gears->d);
|
||||||
if (gears->display == NULL)
|
if (gears->display == NULL)
|
||||||
|
|||||||
+147
-18
@@ -66,6 +66,7 @@ struct display {
|
|||||||
struct rectangle screen_allocation;
|
struct rectangle screen_allocation;
|
||||||
int authenticated;
|
int authenticated;
|
||||||
EGLDisplay dpy;
|
EGLDisplay dpy;
|
||||||
|
EGLConfig conf;
|
||||||
EGLContext ctx;
|
EGLContext ctx;
|
||||||
cairo_device_t *device;
|
cairo_device_t *device;
|
||||||
int fd;
|
int fd;
|
||||||
@@ -188,6 +189,64 @@ struct surface_data {
|
|||||||
|
|
||||||
#ifdef HAVE_CAIRO_EGL
|
#ifdef HAVE_CAIRO_EGL
|
||||||
|
|
||||||
|
struct egl_window_surface_data {
|
||||||
|
struct display *display;
|
||||||
|
struct wl_surface *surface;
|
||||||
|
struct wl_egl_window *window;
|
||||||
|
EGLSurface surf;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
egl_window_surface_data_destroy(void *p)
|
||||||
|
{
|
||||||
|
struct egl_window_surface_data *data = p;
|
||||||
|
struct display *d = data->display;
|
||||||
|
|
||||||
|
eglDestroySurface(d->dpy, data->surf);
|
||||||
|
wl_egl_window_destroy(data->window);
|
||||||
|
data->surface = NULL;
|
||||||
|
|
||||||
|
free(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
static cairo_surface_t *
|
||||||
|
display_create_egl_window_surface(struct display *display,
|
||||||
|
struct wl_surface *surface,
|
||||||
|
struct rectangle *rectangle)
|
||||||
|
{
|
||||||
|
cairo_surface_t *cairo_surface;
|
||||||
|
struct egl_window_surface_data *data;
|
||||||
|
struct wl_visual *visual;
|
||||||
|
|
||||||
|
data = malloc(sizeof *data);
|
||||||
|
if (data == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
data->display = display;
|
||||||
|
data->surface = surface;
|
||||||
|
|
||||||
|
visual = wl_display_get_premultiplied_argb_visual(display->display);
|
||||||
|
|
||||||
|
data->window = wl_egl_window_create(display->native_dpy,
|
||||||
|
surface,
|
||||||
|
rectangle->width,
|
||||||
|
rectangle->height,
|
||||||
|
visual);
|
||||||
|
|
||||||
|
data->surf = eglCreateWindowSurface(display->dpy, display->conf,
|
||||||
|
data->window, NULL);
|
||||||
|
|
||||||
|
cairo_surface = cairo_gl_surface_create_for_egl(display->device,
|
||||||
|
data->surf,
|
||||||
|
rectangle->width,
|
||||||
|
rectangle->height);
|
||||||
|
|
||||||
|
cairo_surface_set_user_data(cairo_surface, &surface_data_key,
|
||||||
|
data, egl_window_surface_data_destroy);
|
||||||
|
|
||||||
|
return cairo_surface;
|
||||||
|
}
|
||||||
|
|
||||||
struct egl_image_surface_data {
|
struct egl_image_surface_data {
|
||||||
struct surface_data data;
|
struct surface_data data;
|
||||||
EGLImageKHR image;
|
EGLImageKHR image;
|
||||||
@@ -499,13 +558,20 @@ check_size(struct rectangle *rect)
|
|||||||
|
|
||||||
cairo_surface_t *
|
cairo_surface_t *
|
||||||
display_create_surface(struct display *display,
|
display_create_surface(struct display *display,
|
||||||
|
struct wl_surface *surface,
|
||||||
struct rectangle *rectangle)
|
struct rectangle *rectangle)
|
||||||
{
|
{
|
||||||
if (check_size(rectangle) < 0)
|
if (check_size(rectangle) < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
#ifdef HAVE_CAIRO_EGL
|
#ifdef HAVE_CAIRO_EGL
|
||||||
if (display->dpy) {
|
if (display->dpy) {
|
||||||
return display_create_egl_image_surface(display, rectangle);
|
if (surface)
|
||||||
|
return display_create_egl_window_surface(display,
|
||||||
|
surface,
|
||||||
|
rectangle);
|
||||||
|
else
|
||||||
|
return display_create_egl_image_surface(display,
|
||||||
|
rectangle);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return display_create_shm_surface(display, rectangle);
|
return display_create_shm_surface(display, rectangle);
|
||||||
@@ -607,32 +673,52 @@ window_attach_surface(struct window *window)
|
|||||||
{
|
{
|
||||||
struct display *display = window->display;
|
struct display *display = window->display;
|
||||||
struct wl_buffer *buffer;
|
struct wl_buffer *buffer;
|
||||||
|
struct egl_window_surface_data *data;
|
||||||
int32_t x, y;
|
int32_t x, y;
|
||||||
|
int width = window->allocation.width;
|
||||||
|
int height = window->allocation.height;
|
||||||
|
|
||||||
|
if (window->resize_edges & WINDOW_RESIZING_LEFT)
|
||||||
|
x = window->server_allocation.width - width;
|
||||||
|
else
|
||||||
|
x = 0;
|
||||||
|
|
||||||
|
if (window->resize_edges & WINDOW_RESIZING_TOP)
|
||||||
|
y = window->server_allocation.height - height;
|
||||||
|
else
|
||||||
|
y = 0;
|
||||||
|
|
||||||
|
window->resize_edges = 0;
|
||||||
|
|
||||||
|
switch (window->buffer_type) {
|
||||||
|
case WINDOW_BUFFER_TYPE_EGL_WINDOW:
|
||||||
|
data = cairo_surface_get_user_data(window->cairo_surface,
|
||||||
|
&surface_data_key);
|
||||||
|
|
||||||
|
wl_egl_window_resize(data->window, width, height, x, y);
|
||||||
|
cairo_gl_surface_swapbuffers(window->cairo_surface);
|
||||||
|
wl_egl_window_get_attached_size(data->window,
|
||||||
|
&window->server_allocation.width,
|
||||||
|
&window->server_allocation.height);
|
||||||
|
break;
|
||||||
|
case WINDOW_BUFFER_TYPE_EGL_IMAGE:
|
||||||
|
case WINDOW_BUFFER_TYPE_SHM:
|
||||||
if (window->pending_surface != NULL)
|
if (window->pending_surface != NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
window->pending_surface = window->cairo_surface;
|
window->pending_surface = window->cairo_surface;
|
||||||
window->cairo_surface = NULL;
|
window->cairo_surface = NULL;
|
||||||
|
|
||||||
buffer = display_get_buffer_for_surface(display,
|
buffer =
|
||||||
|
display_get_buffer_for_surface(display,
|
||||||
window->pending_surface);
|
window->pending_surface);
|
||||||
if (window->resize_edges & WINDOW_RESIZING_LEFT)
|
|
||||||
x = window->server_allocation.width -
|
|
||||||
window->allocation.width;
|
|
||||||
else
|
|
||||||
x = 0;
|
|
||||||
|
|
||||||
if (window->resize_edges & WINDOW_RESIZING_TOP)
|
|
||||||
y = window->server_allocation.height -
|
|
||||||
window->allocation.height;
|
|
||||||
else
|
|
||||||
y = 0;
|
|
||||||
|
|
||||||
window->server_allocation = window->allocation;
|
|
||||||
window->resize_edges = 0;
|
|
||||||
wl_surface_attach(window->surface, buffer, x, y);
|
wl_surface_attach(window->surface, buffer, x, y);
|
||||||
wl_display_sync_callback(display->display, free_surface, window);
|
window->server_allocation = window->allocation;
|
||||||
|
wl_display_sync_callback(display->display, free_surface,
|
||||||
|
window);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (window->fullscreen)
|
if (window->fullscreen)
|
||||||
wl_surface_map_fullscreen(window->surface);
|
wl_surface_map_fullscreen(window->surface);
|
||||||
@@ -666,6 +752,22 @@ window_set_surface(struct window *window, cairo_surface_t *surface)
|
|||||||
window->cairo_surface = surface;
|
window->cairo_surface = surface;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
window_resize_cairo_window_surface(struct window *window)
|
||||||
|
{
|
||||||
|
struct egl_window_surface_data *data;
|
||||||
|
|
||||||
|
data = cairo_surface_get_user_data(window->cairo_surface,
|
||||||
|
&surface_data_key);
|
||||||
|
|
||||||
|
wl_egl_window_resize(data->window,
|
||||||
|
window->allocation.width,
|
||||||
|
window->allocation.height, 0, 0);
|
||||||
|
cairo_gl_surface_set_size(window->cairo_surface,
|
||||||
|
window->allocation.width,
|
||||||
|
window->allocation.height);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
window_create_surface(struct window *window)
|
window_create_surface(struct window *window)
|
||||||
{
|
{
|
||||||
@@ -673,8 +775,18 @@ window_create_surface(struct window *window)
|
|||||||
|
|
||||||
switch (window->buffer_type) {
|
switch (window->buffer_type) {
|
||||||
#ifdef HAVE_CAIRO_EGL
|
#ifdef HAVE_CAIRO_EGL
|
||||||
|
case WINDOW_BUFFER_TYPE_EGL_WINDOW:
|
||||||
|
if (window->cairo_surface) {
|
||||||
|
window_resize_cairo_window_surface(window);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
surface = display_create_surface(window->display,
|
||||||
|
window->surface,
|
||||||
|
&window->allocation);
|
||||||
|
break;
|
||||||
case WINDOW_BUFFER_TYPE_EGL_IMAGE:
|
case WINDOW_BUFFER_TYPE_EGL_IMAGE:
|
||||||
surface = display_create_surface(window->display,
|
surface = display_create_surface(window->display,
|
||||||
|
NULL,
|
||||||
&window->allocation);
|
&window->allocation);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
@@ -1325,7 +1437,8 @@ window_create_internal(struct display *display, struct window *parent,
|
|||||||
window->decoration = 1;
|
window->decoration = 1;
|
||||||
|
|
||||||
if (display->dpy)
|
if (display->dpy)
|
||||||
window->buffer_type = WINDOW_BUFFER_TYPE_EGL_IMAGE;
|
/* FIXME: make TYPE_EGL_IMAGE choosable for testing */
|
||||||
|
window->buffer_type = WINDOW_BUFFER_TYPE_EGL_WINDOW;
|
||||||
else
|
else
|
||||||
window->buffer_type = WINDOW_BUFFER_TYPE_SHM;
|
window->buffer_type = WINDOW_BUFFER_TYPE_SHM;
|
||||||
|
|
||||||
@@ -1595,6 +1708,17 @@ static int
|
|||||||
init_egl(struct display *d)
|
init_egl(struct display *d)
|
||||||
{
|
{
|
||||||
EGLint major, minor;
|
EGLint major, minor;
|
||||||
|
EGLint n;
|
||||||
|
static const EGLint cfg_attribs[] = {
|
||||||
|
EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PIXMAP_BIT,
|
||||||
|
EGL_RED_SIZE, 1,
|
||||||
|
EGL_GREEN_SIZE, 1,
|
||||||
|
EGL_BLUE_SIZE, 1,
|
||||||
|
EGL_ALPHA_SIZE, 1,
|
||||||
|
EGL_DEPTH_SIZE, 1,
|
||||||
|
EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
|
||||||
|
EGL_NONE
|
||||||
|
};
|
||||||
|
|
||||||
d->dpy = eglGetDisplay(d->native_dpy);
|
d->dpy = eglGetDisplay(d->native_dpy);
|
||||||
if (!eglInitialize(d->dpy, &major, &minor)) {
|
if (!eglInitialize(d->dpy, &major, &minor)) {
|
||||||
@@ -1607,7 +1731,12 @@ init_egl(struct display *d)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
d->ctx = eglCreateContext(d->dpy, NULL, EGL_NO_CONTEXT, NULL);
|
if (!eglChooseConfig(d->dpy, cfg_attribs, &d->conf, 1, &n) || n != 1) {
|
||||||
|
fprintf(stderr, "failed to choose config\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
d->ctx = eglCreateContext(d->dpy, d->conf, EGL_NO_CONTEXT, NULL);
|
||||||
if (d->ctx == NULL) {
|
if (d->ctx == NULL) {
|
||||||
fprintf(stderr, "failed to create context\n");
|
fprintf(stderr, "failed to create context\n");
|
||||||
return -1;
|
return -1;
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ display_get_image_for_egl_image_surface(struct display *display,
|
|||||||
|
|
||||||
cairo_surface_t *
|
cairo_surface_t *
|
||||||
display_create_surface(struct display *display,
|
display_create_surface(struct display *display,
|
||||||
|
struct wl_surface *surface,
|
||||||
struct rectangle *rectangle);
|
struct rectangle *rectangle);
|
||||||
|
|
||||||
struct wl_buffer *
|
struct wl_buffer *
|
||||||
@@ -167,6 +168,7 @@ void
|
|||||||
window_create_surface(struct window *window);
|
window_create_surface(struct window *window);
|
||||||
|
|
||||||
enum window_buffer_type {
|
enum window_buffer_type {
|
||||||
|
WINDOW_BUFFER_TYPE_EGL_WINDOW,
|
||||||
WINDOW_BUFFER_TYPE_EGL_IMAGE,
|
WINDOW_BUFFER_TYPE_EGL_IMAGE,
|
||||||
WINDOW_BUFFER_TYPE_SHM,
|
WINDOW_BUFFER_TYPE_SHM,
|
||||||
};
|
};
|
||||||
|
|||||||
+1
-1
@@ -54,7 +54,7 @@ if test x$enable_wayland_compositor == xyes; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
PKG_CHECK_MODULES(CAIRO_EGL, [cairo-egl],
|
PKG_CHECK_MODULES(CAIRO_EGL, [cairo-egl >= 1.11.3],
|
||||||
[have_cairo_egl=yes], [have_cairo_egl=no])
|
[have_cairo_egl=yes], [have_cairo_egl=no])
|
||||||
AS_IF([test "x$have_cairo_egl" = "xyes"],
|
AS_IF([test "x$have_cairo_egl" = "xyes"],
|
||||||
[AC_DEFINE([HAVE_CAIRO_EGL], [1], [Have cairo-egl])])
|
[AC_DEFINE([HAVE_CAIRO_EGL], [1], [Have cairo-egl])])
|
||||||
|
|||||||
Reference in New Issue
Block a user