[PATCH 1/4] Move the wl_buffer from xwl_window to xwl_pixmap

Axel Davy axel.davy at ens.fr
Wed Jan 15 11:46:50 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>
---
 hw/xfree86/xwayland/xwayland-drm.c     | 10 +++-
 hw/xfree86/xwayland/xwayland-private.h | 10 +++-
 hw/xfree86/xwayland/xwayland-window.c  | 87 ++++++++++++++++++++++++++++------
 hw/xfree86/xwayland/xwayland.c         | 38 ++++++++++-----
 4 files changed, 115 insertions(+), 30 deletions(-)

diff --git a/hw/xfree86/xwayland/xwayland-drm.c b/hw/xfree86/xwayland/xwayland-drm.c
index 5250857..a52449d 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..cd237ab 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,39 @@ 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;
-
-    /* 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_window->buffer) {
-        ErrorF("failed to create buffer\n");
-	return;
+    struct xwl_pixmap *xwl_pixmap =
+	    dixLookupPrivate(&pixmap->devPrivates, &xwl_pixmap_private_key);
+
+    if (!xwl_pixmap) {
+        xwl_screen->driver->create_window_buffer(xwl_window, pixmap);
+        xwl_pixmap =
+	    dixLookupPrivate(&pixmap->devPrivates, &xwl_pixmap_private_key);
+
+        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 +105,22 @@ 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);
+            destroy_buffer_listener(xwl_pixmap);
+            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..3d08f82 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 wl_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