[PATCH 2/4 v2] Add support to render-nodes.

Axel Davy axel.davy at ens.fr
Thu Jan 16 13:29:36 PST 2014


And allows to create wl_buffers from fds instead of gem names.

Signed-off-by: Axel Davy <axel.davy at ens.fr>
---
v2: fix indentation
 hw/xfree86/xwayland/drm.xml            |  45 +++++++++++++-
 hw/xfree86/xwayland/xwayland-drm.c     | 108 +++++++++++++++++++++++++++++----
 hw/xfree86/xwayland/xwayland-private.h |   1 +
 hw/xfree86/xwayland/xwayland.h         |   7 +++
 4 files changed, 147 insertions(+), 14 deletions(-)

diff --git a/hw/xfree86/xwayland/drm.xml b/hw/xfree86/xwayland/drm.xml
index 89fd8f0..8a3ad69 100644
--- a/hw/xfree86/xwayland/drm.xml
+++ b/hw/xfree86/xwayland/drm.xml
@@ -29,7 +29,7 @@
 
   <!-- drm support. This object is created by the server and published
        using the display's global event. -->
-  <interface name="wl_drm" version="1">
+  <interface name="wl_drm" version="2">
     <enum name="error">
       <entry name="authenticate_fail" value="0"/>
       <entry name="invalid_format" value="1"/>
@@ -119,6 +119,38 @@
       <arg name="format" type="uint"/>
     </request>
 
+    <!-- Create a wayland buffer for the named DRM buffer.  The DRM
+         surface must have a name using the flink ioctl -->
+    <request name="create_planar_buffer">
+      <arg name="id" type="new_id" interface="wl_buffer"/>
+      <arg name="name" type="uint"/>
+      <arg name="width" type="int"/>
+      <arg name="height" type="int"/>
+      <arg name="format" type="uint"/>
+      <arg name="offset0" type="int"/>
+      <arg name="stride0" type="int"/>
+      <arg name="offset1" type="int"/>
+      <arg name="stride1" type="int"/>
+      <arg name="offset2" type="int"/>
+      <arg name="stride2" type="int"/>
+    </request>
+
+    <!-- Create a wayland buffer for the prime fd.  Use for regular and planar
+         buffers.  Pass 0 for offset and stride for unused planes. -->
+    <request name="create_prime_buffer" since="2">
+      <arg name="id" type="new_id" interface="wl_buffer"/>
+      <arg name="name" type="fd"/>
+      <arg name="width" type="int"/>
+      <arg name="height" type="int"/>
+      <arg name="format" type="uint"/>
+      <arg name="offset0" type="int"/>
+      <arg name="stride0" type="int"/>
+      <arg name="offset1" type="int"/>
+      <arg name="stride1" type="int"/>
+      <arg name="offset2" type="int"/>
+      <arg name="stride2" type="int"/>
+    </request>
+
     <!-- Notification of the path of the drm device which is used by
          the server.  The client should use this device for creating
          local buffers.  Only buffers created from this device should
@@ -134,6 +166,17 @@
 
     <!-- Raised if the authenticate request succeeded -->
     <event name="authenticated"/>
+
+    <enum name="capability" since="2">
+      <description summary="wl_drm capability bitmask">
+        Bitmask of capabilities.
+      </description>
+      <entry name="prime" value="1" summary="wl_drm prime available"/>
+    </enum>
+
+    <event name="capabilities">
+      <arg name="value" type="uint"/>
+    </event>
   </interface>
 
 </protocol>
diff --git a/hw/xfree86/xwayland/xwayland-drm.c b/hw/xfree86/xwayland/xwayland-drm.c
index 30ec176..076fb68 100644
--- a/hw/xfree86/xwayland/xwayland-drm.c
+++ b/hw/xfree86/xwayland/xwayland-drm.c
@@ -29,6 +29,7 @@
 
 #include <unistd.h>
 #include <fcntl.h>
+#include <sys/stat.h>
 
 #include <xf86drm.h>
 #include <wayland-util.h>
@@ -99,11 +100,20 @@ drm_handle_authenticated (void *data, struct wl_drm *drm)
     }
 }
 
+static void
+drm_handle_capabilities(void *data, struct wl_drm *drm, uint32_t value)
+{
+    struct xwl_screen *xwl_screen = data;
+
+    xwl_screen->drm_capabilities = value;
+}
+
 static const struct wl_drm_listener xwl_drm_listener =
 {
     drm_handle_device,
     drm_handle_format,
-    drm_handle_authenticated
+    drm_handle_authenticated,
+    drm_handle_capabilities
 };
 
 static void
@@ -114,7 +124,7 @@ drm_handler(void *data, struct wl_registry *registry, uint32_t id,
 
     if (strcmp (interface, "wl_drm") == 0) {
 	xwl_screen->drm = wl_registry_bind(xwl_screen->registry, id,
-                                           &wl_drm_interface, 1);
+                                           &wl_drm_interface, 2);
 	wl_drm_add_listener(xwl_screen->drm, &xwl_drm_listener, xwl_screen);
     }
 }
@@ -130,6 +140,22 @@ static const struct wl_registry_listener drm_listener = {
     global_remove
 };
 
+static char
+is_fd_render_node(int fd)
+{
+    struct stat render;
+
+    if (fstat(fd, &render))
+	return 0;
+
+    if (!S_ISCHR(render.st_mode))
+	return 0;
+
+    if (render.st_rdev & 0x80)
+	return 1;
+    return 0;
+}
+
 int
 xwl_drm_pre_init(struct xwl_screen *xwl_screen)
 {
@@ -137,7 +163,7 @@ xwl_drm_pre_init(struct xwl_screen *xwl_screen)
 
     xwl_screen->drm_registry = wl_display_get_registry(xwl_screen->display);
     wl_registry_add_listener(xwl_screen->drm_registry, &drm_listener,
-                             xwl_screen);
+			     xwl_screen);
 
     /* Ensure drm_handler has seen all the interfaces */
     wl_display_roundtrip(xwl_screen->display);
@@ -153,20 +179,25 @@ xwl_drm_pre_init(struct xwl_screen *xwl_screen)
 	return BadAccess;
     }
 
-    if (drmGetMagic(xwl_screen->drm_fd, &magic)) {
-	ErrorF("failed to get drm magic");
-	return BadAccess;
-    }
+    if (!is_fd_render_node(xwl_screen->drm_fd)) {
 
-    wl_drm_authenticate(xwl_screen->drm, magic);
+	if (drmGetMagic(xwl_screen->drm_fd, &magic)) {
+	    ErrorF("failed to get drm magic");
+	    return BadAccess;
+	}
 
-    wl_display_roundtrip(xwl_screen->display);
+	wl_drm_authenticate(xwl_screen->drm, magic);
 
-    ErrorF("opened drm fd: %d\n", xwl_screen->drm_fd);
+	wl_display_roundtrip(xwl_screen->display);
 
-    if (!xwl_screen->authenticated) {
-	ErrorF("Failed to auth drm fd\n");
-	return BadAccess;
+	ErrorF("opened drm fd: %d\n", xwl_screen->drm_fd);
+
+	if (!xwl_screen->authenticated) {
+	    ErrorF("Failed to auth drm fd\n");
+	    return BadAccess;
+	}
+    } else {
+	xwl_screen->authenticated = 1;
     }
 
     return Success;
@@ -177,6 +208,11 @@ Bool xwl_drm_initialised(struct xwl_screen *xwl_screen)
     return xwl_screen->authenticated;
 }
 
+Bool xwl_drm_prime_able(struct xwl_screen *xwl_screen)
+{
+    return xwl_screen->drm_capabilities & WL_DRM_CAPABILITY_PRIME;
+}
+
 int xwl_screen_get_drm_fd(struct xwl_screen *xwl_screen)
 {
     return xwl_screen->drm_fd;
@@ -254,3 +290,49 @@ xwl_create_window_buffer_drm(struct xwl_window *xwl_window,
 
     return Success;
 }
+
+int
+xwl_create_window_buffer_drm_from_fd(struct xwl_window *xwl_window,
+				     PixmapPtr pixmap, int fd)
+{
+    VisualID visual;
+    WindowPtr window = xwl_window->window;
+    ScreenPtr screen = window->drawable.pScreen;
+    struct wl_buffer *buffer;
+    uint32_t format;
+    int i;
+
+    visual = wVisual(window);
+    for (i = 0; i < screen->numVisuals; i++)
+	if (screen->visuals[i].vid == visual)
+	    break;
+
+    switch (screen->visuals[i].nplanes) {
+    case 32:
+	format = WL_DRM_FORMAT_ARGB8888;
+	break;
+    case 24:
+    default:
+	format = WL_DRM_FORMAT_XRGB8888;
+	break;
+    case 16:
+	format = WL_DRM_FORMAT_RGB565;
+	break;
+    }
+
+    buffer =
+	wl_drm_create_prime_buffer(xwl_window->xwl_screen->drm,
+				   fd,
+				   pixmap->drawable.width,
+				   pixmap->drawable.height,
+				   format, 0,
+				   pixmap->devKind,
+				   0, 0, 0, 0);
+
+    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 853ab3b..3131dac 100644
--- a/hw/xfree86/xwayland/xwayland-private.h
+++ b/hw/xfree86/xwayland/xwayland-private.h
@@ -46,6 +46,7 @@ struct xwl_screen {
     ScreenPtr			 screen;
     ScrnInfoPtr			 scrninfo;
     int				 drm_fd;
+    uint32_t			 drm_capabilities;
     int				 wayland_fd;
     struct wl_display		*display;
     struct wl_registry          *registry;
diff --git a/hw/xfree86/xwayland/xwayland.h b/hw/xfree86/xwayland/xwayland.h
index f268366..8e484a1 100644
--- a/hw/xfree86/xwayland/xwayland.h
+++ b/hw/xfree86/xwayland/xwayland.h
@@ -68,6 +68,9 @@ xwl_screen_destroy(struct xwl_screen *xwl_screen);
 extern _X_EXPORT void
 xwl_screen_post_damage(struct xwl_screen *xwl_screen);
 
+extern _X_EXPORT Bool
+xwl_drm_prime_able(struct xwl_screen *xwl_screen);
+
 extern _X_EXPORT int
 xwl_drm_authenticate(ClientPtr client, struct xwl_screen *xwl_screen,
 		     uint32_t magic);
@@ -77,6 +80,10 @@ xwl_create_window_buffer_drm(struct xwl_window *xwl_window,
 			     PixmapPtr pixmap, uint32_t name);
 
 extern _X_EXPORT int
+xwl_create_window_buffer_drm_from_fd(struct xwl_window *xwl_window,
+				     PixmapPtr pixmap, int fd);
+
+extern _X_EXPORT int
 xwl_create_window_buffer_shm(struct xwl_window *xwl_window,
 			     PixmapPtr pixmap, int fd);
 
-- 
1.8.3.2



More information about the wayland-devel mailing list