[PATCH 1/4 v2] Move the wl_buffer from xwl_window to xwl_pixmap
Axel Davy
axel.davy at ens.fr
Thu Jan 16 13:29:35 PST 2014
This change enables to change the window pixmap, and have
xwayland send the correct buffer to the Wayland compositor.
Signed-off-by: Axel Davy <axel.davy at ens.fr>
---
v2: fix indentation and remove a call that had to be in patch 4
hw/xfree86/xwayland/xwayland-drm.c | 10 +++-
hw/xfree86/xwayland/xwayland-private.h | 10 +++-
hw/xfree86/xwayland/xwayland-window.c | 83 +++++++++++++++++++++++++++++-----
hw/xfree86/xwayland/xwayland.c | 38 ++++++++++------
4 files changed, 113 insertions(+), 28 deletions(-)
diff --git a/hw/xfree86/xwayland/xwayland-drm.c b/hw/xfree86/xwayland/xwayland-drm.c
index 5250857..30ec176 100644
--- a/hw/xfree86/xwayland/xwayland-drm.c
+++ b/hw/xfree86/xwayland/xwayland-drm.c
@@ -217,6 +217,7 @@ xwl_create_window_buffer_drm(struct xwl_window *xwl_window,
VisualID visual;
WindowPtr window = xwl_window->window;
ScreenPtr screen = window->drawable.pScreen;
+ struct wl_buffer *buffer;
uint32_t format;
int i;
@@ -238,7 +239,7 @@ xwl_create_window_buffer_drm(struct xwl_window *xwl_window,
break;
}
- xwl_window->buffer =
+ buffer =
wl_drm_create_buffer(xwl_window->xwl_screen->drm,
name,
pixmap->drawable.width,
@@ -246,5 +247,10 @@ xwl_create_window_buffer_drm(struct xwl_window *xwl_window,
pixmap->devKind,
format);
- return xwl_window->buffer ? Success : BadDrawable;
+ if (!buffer)
+ return BadDrawable;
+
+ xwl_pixmap_attach_buffer(pixmap, buffer);
+
+ return Success;
}
diff --git a/hw/xfree86/xwayland/xwayland-private.h b/hw/xfree86/xwayland/xwayland-private.h
index bdecf8a..853ab3b 100644
--- a/hw/xfree86/xwayland/xwayland-private.h
+++ b/hw/xfree86/xwayland/xwayland-private.h
@@ -29,13 +29,16 @@
struct xwl_window {
struct xwl_screen *xwl_screen;
struct wl_surface *surface;
- struct wl_buffer *buffer;
WindowPtr window;
DamagePtr damage;
struct xorg_list link;
struct xorg_list link_damage;
};
+struct xwl_pixmap {
+ struct wl_buffer *buffer;
+};
+
struct xwl_output;
struct xwl_screen {
@@ -72,6 +75,7 @@ struct xwl_screen {
RealizeWindowProcPtr RealizeWindow;
UnrealizeWindowProcPtr UnrealizeWindow;
SetWindowPixmapProcPtr SetWindowPixmap;
+ DestroyPixmapProcPtr DestroyPixmap;
MoveWindowProcPtr MoveWindow;
miPointerSpriteFuncPtr sprite_funcs;
};
@@ -135,6 +139,10 @@ void xwl_seat_set_cursor(struct xwl_seat *xwl_seat);
void xwl_output_remove(struct xwl_output *output);
+void xwl_pixmap_attach_buffer(PixmapPtr pixmap, struct wl_buffer *buffer);
+struct xwl_pixmap *xwl_window_get_buffer(struct xwl_window *xwl_window);
+struct xwl_window *get_xwl_window(WindowPtr window);
+
extern const struct xserver_listener xwl_server_listener;
#endif /* _XWAYLAND_PRIVATE_H_ */
diff --git a/hw/xfree86/xwayland/xwayland-window.c b/hw/xfree86/xwayland/xwayland-window.c
index a2a8206..1e6c09b 100644
--- a/hw/xfree86/xwayland/xwayland-window.c
+++ b/hw/xfree86/xwayland/xwayland-window.c
@@ -41,6 +41,13 @@
#include "xserver-client-protocol.h"
static DevPrivateKeyRec xwl_window_private_key;
+static DevPrivateKeyRec xwl_pixmap_private_key;
+
+struct xwl_window *
+get_xwl_window(WindowPtr window)
+{
+ return dixLookupPrivate(&window->devPrivates, &xwl_window_private_key);
+}
static void
free_pixmap(void *data, struct wl_callback *callback, uint32_t time)
@@ -56,25 +63,38 @@ static const struct wl_callback_listener free_pixmap_listener = {
free_pixmap,
};
+void
+xwl_pixmap_attach_buffer(PixmapPtr pixmap, struct wl_buffer *buffer)
+{
+ struct xwl_pixmap *xwl_pixmap = calloc(sizeof *xwl_pixmap, 1);
+ if (!xwl_pixmap) {
+ wl_buffer_destroy(buffer);
+ return;
+ }
+ xwl_pixmap->buffer = buffer;
+ dixSetPrivate(&pixmap->devPrivates, &xwl_pixmap_private_key, xwl_pixmap);
+}
+
static void
xwl_window_attach(struct xwl_window *xwl_window, PixmapPtr pixmap)
{
struct xwl_screen *xwl_screen = xwl_window->xwl_screen;
struct wl_callback *callback;
+ struct xwl_pixmap *xwl_pixmap =
+ dixLookupPrivate(&pixmap->devPrivates, &xwl_pixmap_private_key);
- /* We can safely destroy the buffer because we only use one buffer
- * per surface in xwayland model */
- if (xwl_window->buffer)
- wl_buffer_destroy(xwl_window->buffer);
-
- xwl_screen->driver->create_window_buffer(xwl_window, pixmap);
+ if (!xwl_pixmap) {
+ xwl_screen->driver->create_window_buffer(xwl_window, pixmap);
+ xwl_pixmap =
+ dixLookupPrivate(&pixmap->devPrivates, &xwl_pixmap_private_key);
- if (!xwl_window->buffer) {
- ErrorF("failed to create buffer\n");
- return;
+ if (!xwl_pixmap) {
+ ErrorF("failed to create buffer\n");
+ return;
+ }
}
- wl_surface_attach(xwl_window->surface, xwl_window->buffer, 0, 0);
+ wl_surface_attach(xwl_window->surface, xwl_pixmap->buffer, 0, 0);
wl_surface_damage(xwl_window->surface, 0, 0,
pixmap->drawable.width,
pixmap->drawable.height);
@@ -84,6 +104,23 @@ xwl_window_attach(struct xwl_window *xwl_window, PixmapPtr pixmap)
pixmap->refcnt++;
}
+struct xwl_pixmap *
+xwl_window_get_buffer(struct xwl_window *xwl_window)
+{
+ PixmapPtr pixmap = (*xwl_window->xwl_screen->screen->GetWindowPixmap)
+ (xwl_window->window);
+ struct xwl_pixmap *xwl_pixmap =
+ dixLookupPrivate(&pixmap->devPrivates, &xwl_pixmap_private_key);
+
+ if (!xwl_pixmap) {
+ xwl_window_attach(xwl_window, pixmap);
+ return dixLookupPrivate(&pixmap->devPrivates,
+ &xwl_pixmap_private_key);
+ } else {
+ return xwl_pixmap;
+ }
+}
+
static void
damage_report(DamagePtr pDamage, RegionPtr pRegion, void *data)
{
@@ -184,8 +221,6 @@ xwl_unrealize_window(WindowPtr window)
if (!xwl_window)
return ret;
- if (xwl_window->buffer)
- wl_buffer_destroy(xwl_window->buffer);
wl_surface_destroy(xwl_window->surface);
xorg_list_del(&xwl_window->link);
if (RegionNotEmpty(DamageRegion(xwl_window->damage)))
@@ -218,6 +253,24 @@ xwl_set_window_pixmap(WindowPtr window, PixmapPtr pixmap)
xwl_window_attach(xwl_window, pixmap);
}
+static Bool
+xwl_destroy_pixmap(PixmapPtr pixmap)
+{
+ ScreenPtr screen = pixmap->drawable.pScreen;
+ struct xwl_screen *xwl_screen = xwl_screen_get(screen);
+ if (pixmap->refcnt == 1) {
+ struct xwl_pixmap *xwl_pixmap =
+ dixLookupPrivate(&pixmap->devPrivates, &xwl_pixmap_private_key);
+ if (xwl_pixmap) {
+ wl_buffer_destroy(xwl_pixmap->buffer);
+ dixSetPrivate(&pixmap->devPrivates, &xwl_pixmap_private_key,
+ NULL);
+ free(xwl_pixmap);
+ }
+ }
+ return xwl_screen->DestroyPixmap(pixmap);
+}
+
static void
xwl_move_window(WindowPtr window, int x, int y,
WindowPtr sibling, VTKind kind)
@@ -245,6 +298,9 @@ xwl_screen_init_window(struct xwl_screen *xwl_screen, ScreenPtr screen)
if (!dixRegisterPrivateKey(&xwl_window_private_key, PRIVATE_WINDOW, 0))
return BadAlloc;
+ if (!dixRegisterPrivateKey(&xwl_pixmap_private_key, PRIVATE_PIXMAP, 0))
+ return BadAlloc;
+
xwl_screen->RealizeWindow = screen->RealizeWindow;
screen->RealizeWindow = xwl_realize_window;
@@ -254,6 +310,9 @@ xwl_screen_init_window(struct xwl_screen *xwl_screen, ScreenPtr screen)
xwl_screen->SetWindowPixmap = screen->SetWindowPixmap;
screen->SetWindowPixmap = xwl_set_window_pixmap;
+ xwl_screen->DestroyPixmap = screen->DestroyPixmap;
+ screen->DestroyPixmap = xwl_destroy_pixmap;
+
xwl_screen->MoveWindow = screen->MoveWindow;
screen->MoveWindow = xwl_move_window;
diff --git a/hw/xfree86/xwayland/xwayland.c b/hw/xfree86/xwayland/xwayland.c
index c70a52d..15308b0 100644
--- a/hw/xfree86/xwayland/xwayland.c
+++ b/hw/xfree86/xwayland/xwayland.c
@@ -247,6 +247,7 @@ xwl_create_window_buffer_shm(struct xwl_window *xwl_window,
WindowPtr window = xwl_window->window;
ScreenPtr screen = window->drawable.pScreen;
VisualID visual = wVisual(window);
+ struct wl_buffer *buffer;
uint32_t format;
int size, stride, bpp, i;
@@ -277,13 +278,18 @@ xwl_create_window_buffer_shm(struct xwl_window *xwl_window,
size = stride * pixmap->drawable.height;
pool = wl_shm_create_pool(xwl_window->xwl_screen->shm, fd, size);
- xwl_window->buffer = wl_shm_pool_create_buffer(pool, 0,
+ buffer = wl_shm_pool_create_buffer(pool, 0,
pixmap->drawable.width,
pixmap->drawable.height,
stride, format);
wl_shm_pool_destroy(pool);
- return xwl_window->buffer ? Success : BadDrawable;
+ if (!buffer)
+ return BadDrawable;
+
+ xwl_pixmap_attach_buffer(pixmap, buffer);
+
+ return Success;
}
void xwl_screen_close(struct xwl_screen *xwl_screen)
@@ -302,7 +308,6 @@ void xwl_screen_close(struct xwl_screen *xwl_screen)
}
xorg_list_for_each_entry_safe(xwl_window, wtmp,
&xwl_screen->window_list, link) {
- wl_buffer_destroy(xwl_window->buffer);
wl_surface_destroy(xwl_window->surface);
free(xwl_window);
}
@@ -334,22 +339,29 @@ void xwl_screen_post_damage(struct xwl_screen *xwl_screen)
RegionPtr region;
BoxPtr box;
int count, i;
+ struct xwl_pixmap *xwl_pixmap;
xorg_list_for_each_entry(xwl_window, &xwl_screen->damage_window_list,
link_damage) {
region = DamageRegion(xwl_window->damage);
count = RegionNumRects(region);
- for (i = 0; i < count; i++) {
- box = &RegionRects(region)[i];
- wl_surface_damage(xwl_window->surface,
- box->x1, box->y1,
- box->x2 - box->x1,
- box->y2 - box->y1);
+ xwl_pixmap = xwl_window_get_buffer(xwl_window);
+ /* in the case we have no xwl_buffer associated to a xwl_window,
+ * because of incompatible pixmap, or memory shortage, we are
+ * going to retry later to create the buffer */
+ if (xwl_pixmap) {
+ for (i = 0; i < count; i++) {
+ box = &RegionRects(region)[i];
+ wl_surface_damage(xwl_window->surface,
+ box->x1, box->y1,
+ box->x2 - box->x1,
+ box->y2 - box->y1);
+ }
+ wl_surface_attach(xwl_window->surface,
+ xwl_pixmap->buffer,
+ 0, 0);
+ wl_surface_commit(xwl_window->surface);
}
- wl_surface_attach(xwl_window->surface,
- xwl_window->buffer,
- 0, 0);
- wl_surface_commit(xwl_window->surface);
DamageEmpty(xwl_window->damage);
}
--
1.8.3.2
More information about the wayland-devel
mailing list