[Mesa-dev] [PATCH] add test for wayland drm, XRGB/YUYV is supported

Zhao halley halley.zhao at intel.com
Mon Jun 4 10:26:14 CEST 2012


when I sent patches for YUYV support of dri image, a test case is
required to make sure the patches can work well. so it is created.

it also shows how wayland-drm protocol works between wayland client 
and server -- they communicate data in buffer/drm level.

---
 configure.ac                                       |    1 +
 src/egl/wayland/Makefile.am                        |    2 +-
 src/egl/wayland/wayland-drm/Makefile.am            |    1 +
 src/egl/wayland/wayland-drm/tests/Makefile.am      |   12 +
 .../wayland/wayland-drm/tests/wayland-drm-test.c   |  463 ++++++++++++++++++++
 5 files changed, 478 insertions(+), 1 deletions(-)
 create mode 100644 src/egl/wayland/wayland-drm/tests/Makefile.am
 create mode 100644 src/egl/wayland/wayland-drm/tests/wayland-drm-test.c

diff --git a/configure.ac b/configure.ac
index 3bc59ca..83bf637 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2019,6 +2019,7 @@ AC_CONFIG_FILES([configs/autoconf
 		src/egl/wayland/wayland-egl/Makefile
 		src/egl/wayland/wayland-egl/wayland-egl.pc
 		src/egl/wayland/wayland-drm/Makefile
+		src/egl/wayland/wayland-drm/tests/Makefile
 		src/glsl/tests/Makefile
 		src/glx/Makefile
 		src/mapi/shared-glapi/Makefile
diff --git a/src/egl/wayland/Makefile.am b/src/egl/wayland/Makefile.am
index ca7207c..526d64f 100644
--- a/src/egl/wayland/Makefile.am
+++ b/src/egl/wayland/Makefile.am
@@ -1 +1 @@
-SUBDIRS = wayland-drm wayland-egl
+SUBDIRS = wayland-drm wayland-egl 
diff --git a/src/egl/wayland/wayland-drm/Makefile.am b/src/egl/wayland/wayland-drm/Makefile.am
index cf15eda..4a7c6eb 100644
--- a/src/egl/wayland/wayland-drm/Makefile.am
+++ b/src/egl/wayland/wayland-drm/Makefile.am
@@ -1,3 +1,4 @@
+SUBDIRS = tests
 AM_CFLAGS = -I$(top_srcdir)/src/egl/main \
 	    -I$(top_srcdir)/include \
 	    $(DEFINES) \
diff --git a/src/egl/wayland/wayland-drm/tests/Makefile.am b/src/egl/wayland/wayland-drm/tests/Makefile.am
new file mode 100644
index 0000000..d489c74
--- /dev/null
+++ b/src/egl/wayland/wayland-drm/tests/Makefile.am
@@ -0,0 +1,12 @@
+bin_PROGRAMS = wayland_drm_test
+wayland_drm_test_CFLAGS = -I$(top_srcdir)/src/egl/main \
+	    -I$(top_srcdir)/include \
+	    $(DEFINES) \
+	    $(WAYLAND_CFLAGS) \
+	    $(LIBDRM_CFLAGS)
+
+wayland_drm_test_LDADD = $(WAYLAND_LIBS) $(LIBDRM_LIBS) -ldrm_intel
+wayland_drm_test_LDADD += $(top_srcdir)/src/egl/main/libEGL.la
+
+wayland_drm_test_SOURCES = wayland-drm-test.c \
+						../wayland-drm-client-protocol.h
diff --git a/src/egl/wayland/wayland-drm/tests/wayland-drm-test.c b/src/egl/wayland/wayland-drm/tests/wayland-drm-test.c
new file mode 100644
index 0000000..04c23d4
--- /dev/null
+++ b/src/egl/wayland/wayland-drm/tests/wayland-drm-test.c
@@ -0,0 +1,463 @@
+/*
+ * Copyright © 2012 Halley Zhao
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Halley Zhao <halley.zhao at intel.com>
+ */
+
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <assert.h>
+#include <xf86drm.h>
+#include <i915_drm.h>
+#include "libdrm/intel_bufmgr.h"
+#include <drm.h>
+#include "gbm.h"
+#include <wayland-client.h>
+#include <wayland-client-protocol.h>
+#include "../wayland-drm-client-protocol.h"
+
+void fill_bo_XRGB(dri_bo *bo, int width, int height, int pitch);
+void fill_bo_YUYV(dri_bo *bo, int width, int height, int pitch);
+int wayland_drm_init(struct wl_display *wl_dpy);
+
+int win_width = 1024, win_height = 512;
+int drm_fd = -1;
+struct wl_drm *wl_drm;
+
+struct display {
+	struct wl_display *display;
+	struct wl_compositor *compositor;
+	struct wl_shell *shell;
+	struct wl_input_device *input;
+	uint32_t mask;
+};
+
+struct window {
+	struct display *display;
+	struct wl_surface *surface;
+	struct wl_shell_surface *shell_surface;
+	struct wl_callback *callback;
+	struct {
+		int width, height;
+	} geometry;
+    unsigned int format;
+    struct wl_buffer *buffer;
+    dri_bo *bo;
+    unsigned int bo_pitch;
+};
+
+void fill_bo_XRGB(dri_bo *bo, int width, int height, int pitch)
+{
+    unsigned int tiling, swizzle;
+    dri_bo_get_tiling(bo, &tiling, &swizzle);
+
+    if (tiling != I915_TILING_NONE)
+        drm_intel_gem_bo_map_gtt(bo);
+    else
+        dri_bo_map(bo, 1);
+
+    static int color_index = 0;
+    unsigned int color = 0; 
+    int i;
+    switch (color_index) {
+    case 0:
+        color = 0xff000000;
+        break;
+    case 1:
+        color = 0x00ff0000;
+        break;
+    case 2:
+        color = 0x0000ff00;
+        break;
+    case 3:
+        color = 0x000000ff;
+        break;
+    default:
+        break;
+    }
+    color_index = (color_index+1) % 4;
+
+    unsigned int *i_ptr = bo->virtual;
+    for (i=0; i<width; i++) {
+        *i_ptr++ = color;
+    }
+
+    unsigned char *c_ptr = bo->virtual + pitch;
+    for (i = 1; i<height; i++) {
+        memcpy (c_ptr, bo->virtual, width*4);
+        c_ptr += pitch;
+    }
+
+    if (tiling != I915_TILING_NONE)
+        drm_intel_gem_bo_unmap_gtt(bo);
+    else
+        dri_bo_unmap(bo);
+}
+
+void fill_bo_YUYV(dri_bo *bo, int width, int height, int pitch)
+{
+    unsigned int tiling, swizzle;
+    dri_bo_get_tiling(bo, &tiling, &swizzle);
+
+    if (tiling != I915_TILING_NONE)
+        drm_intel_gem_bo_map_gtt(bo);
+    else
+        dri_bo_map(bo, 1);
+
+    static int color_index = 0;
+    unsigned int color = 0;
+    int i;
+    switch (color_index) {
+    case 0:
+        color = 0x00ff00ff;
+        break;
+    case 1:
+        color = 0x80ff00ff;
+        break;
+    case 2:
+        color = 0x00ff80ff;
+        break;
+    case 3:
+        color = 0x80ff80ff;
+        break;
+    default:
+        break;
+    }
+    color_index = (color_index+1) % 4;
+
+    unsigned int *i_ptr = bo->virtual;
+    for (i=0; i<width/2; i++) {
+        *i_ptr++ = color;
+    }
+
+    unsigned char *c_ptr = bo->virtual + pitch;
+    for (i = 1; i<height; i++) {
+        memcpy (c_ptr, bo->virtual, width*2);
+        c_ptr += pitch;
+    }
+
+    if (tiling != I915_TILING_NONE)
+        drm_intel_gem_bo_unmap_gtt(bo);
+    else
+        dri_bo_unmap(bo);
+}
+
+
+static void
+drm_handle_device(void *data, struct wl_drm *drm, const char *device)
+{
+    drm_magic_t magic;
+    struct stat st;
+
+    if (stat(device, &st) < 0) {
+        printf("failed to identify %s (errno %d)",
+                         device, errno);
+        return;
+    }
+
+    if (!S_ISCHR(st.st_mode)) {
+        printf("%s is not a device", device);
+        return;
+    }
+    drm_fd = open(device, O_RDWR);
+    if (drm_fd < 0) {
+        printf("failed to open %s (errno %d)",
+                         device, errno);
+        return;
+    }
+
+    drmGetMagic(drm_fd, &magic);
+    wl_drm_authenticate(wl_drm, magic);
+}
+
+static void
+drm_handle_format(void *data, struct wl_drm *drm, uint32_t format)
+{
+
+}
+
+static void
+drm_handle_authenticated(void *data, struct wl_drm *drm)
+{
+
+}
+
+static const struct wl_drm_listener drm_listener = {
+    drm_handle_device,
+    drm_handle_format,
+    drm_handle_authenticated
+};
+
+
+
+static void
+wayland_drm_finalize()
+{
+
+    if (wl_drm) {
+        wl_drm_destroy(wl_drm);
+        wl_drm = NULL;
+    }
+
+    if (drm_fd >= 0) {
+        close(drm_fd);
+        drm_fd = -1;
+    }
+}
+
+int 
+wayland_drm_init(struct wl_display *wl_dpy)
+{
+    uint32_t id;
+
+    assert(wl_dpy);
+
+    id = wl_display_get_global(wl_dpy, "wl_drm", 1);
+    if (!id) {
+        wl_display_roundtrip(wl_dpy);
+        id = wl_display_get_global(wl_dpy, "wl_drm", 1);
+        if (!id)
+            return -1;
+    }
+
+    wl_drm = wl_display_bind(wl_dpy, id, &wl_drm_interface);
+    if (!wl_drm)
+        return -1;
+
+    wl_drm_add_listener(wl_drm, &drm_listener, NULL);
+    wl_display_roundtrip(wl_dpy);
+    if (drm_fd < 0)
+        return -1;
+
+    wl_display_roundtrip(wl_dpy);
+
+    return 0;
+}
+
+static const struct wl_callback_listener frame_listener;
+
+static void
+redraw(void *data, struct wl_callback *callback, int time)
+{
+	struct window *window = data;
+	if (callback)
+		wl_callback_destroy(callback);
+
+    if (window->format == WL_DRM_FORMAT_XRGB8888) {
+        fill_bo_XRGB(window->bo, win_width, win_height, window->bo_pitch);
+    }
+    else {
+        fill_bo_YUYV(window->bo, win_width, win_height, window->bo_pitch);
+    }
+
+    // update
+    wl_surface_attach(
+        window->surface,
+        window->buffer,
+        0, 0
+    );
+    wl_surface_damage(
+        window->surface,
+        0, 0, win_width, win_height
+    );
+    
+	window->callback = wl_surface_frame(window->surface);
+	wl_callback_add_listener(window->callback, &frame_listener, window);
+    sleep(1);
+}
+
+static const struct wl_callback_listener frame_listener = {
+	redraw
+};
+
+static void
+display_handle_global(struct wl_display *display, uint32_t id,
+		      const char *interface, uint32_t version, void *data)
+{
+	struct display *d = data;
+
+	if (strcmp(interface, "wl_compositor") == 0) {
+		d->compositor =
+			wl_display_bind(display, id, &wl_compositor_interface);
+	} else if (strcmp(interface, "wl_shell") == 0) {
+		d->shell = wl_display_bind(display, id, &wl_shell_interface);
+	} else if (strcmp(interface, "wl_input_device") == 0) {
+		d->input = wl_display_bind(display, id, &wl_input_device_interface);
+		// wl_input_device_add_listener(d->input, &input_listener, d);
+	}
+}
+
+static void
+handle_ping(void *data, struct wl_shell_surface *shell_surface,
+	    uint32_t serial)
+{
+	wl_shell_surface_pong(shell_surface, serial);
+}
+
+static void
+handle_configure(void *data, struct wl_shell_surface *shell_surface,
+		 uint32_t edges, int32_t width, int32_t height)
+{
+	struct window *window = data;
+
+	window->geometry.width = width;
+	window->geometry.height = height;
+}
+
+static void
+handle_popup_done(void *data, struct wl_shell_surface *shell_surface)
+{
+}
+
+static const struct wl_shell_surface_listener shell_surface_listener = {
+	handle_ping,
+	handle_configure,
+	handle_popup_done
+};
+
+static int
+event_mask_update(uint32_t mask, void *data)
+{
+	struct display *d = data;
+
+	d->mask = mask;
+
+	return 0;
+}
+int main(int argc, char **argv)
+{
+
+PRINT_MARK;
+    struct display dpy;
+    struct window win;
+    int running = 1;
+    win.format = WL_DRM_FORMAT_XRGB8888;
+    char c=0;
+
+    while ((c =getopt(argc,argv,"c:w:h:?") ) != EOF) {
+        switch (c) {
+            case '?':
+                printf("./wayland_drm_test -c (XRGB/YUYV) -w window_width -h window_height\n");
+                exit(0);
+                break;
+            case 'c':
+                if (!strcmp(optarg, "YUYV")) {
+                    win.format = WL_DRM_FORMAT_YUYV;
+                }
+                break;
+            case 'w':
+                win_width = atoi(optarg);
+                break;
+            case 'h':
+                win_height = atoi(optarg);
+                break;
+            default:
+                printf("./wayland_drm_test -c (XRGB/YUYV) -w window_width -h window_height\n");
+                exit(0);
+                break;
+        }
+    }
+
+
+    // wl_display connection
+	dpy.display = wl_display_connect(NULL);
+	assert(dpy.display);
+    
+	wl_display_add_global_listener(dpy.display,
+				       display_handle_global, &dpy);
+
+	wl_display_get_fd(dpy.display, event_mask_update, &dpy);
+	wl_display_iterate(dpy.display, WL_DISPLAY_READABLE);
+
+    // create wl_surface
+	win.surface = wl_compositor_create_surface(dpy.compositor);
+	win.shell_surface = wl_shell_get_shell_surface(dpy.shell,
+							   win.surface);
+
+	wl_shell_surface_add_listener(win.shell_surface, &shell_surface_listener, &win);
+
+	wl_shell_surface_set_toplevel(win.shell_surface);
+
+    // wayland drm initialization
+    wayland_drm_init(dpy.display);
+
+    // gem buf mgr
+    drm_intel_bufmgr *gem_bufmgr;
+    gem_bufmgr = drm_intel_bufmgr_gem_init(drm_fd, 16 * 4096);
+    drm_intel_bufmgr_gem_enable_reuse(gem_bufmgr);
+    drm_intel_bufmgr_gem_enable_fenced_relocs(gem_bufmgr);
+
+    // create drm bo
+    dri_bo *bo;
+    int cpp = (win.format == WL_DRM_FORMAT_XRGB8888 ? 4:2); 
+    uint32_t tiling_mode = I915_TILING_X;
+    unsigned long alloc_pitch;
+
+    bo = drm_intel_bo_alloc_tiled(gem_bufmgr,
+                     "sprite buffer",
+                     win_width, win_height,
+                     cpp,
+                     &tiling_mode, &alloc_pitch,
+                     BO_ALLOC_FOR_RENDER);
+    win.bo = bo;
+    win.bo_pitch = alloc_pitch;
+
+    unsigned int buf_name;
+    dri_bo_flink(bo, &buf_name);
+
+    // create wl_buffer
+    struct wl_buffer *buffer = wl_drm_create_buffer(wl_drm, buf_name, win_width, win_height, alloc_pitch, win.format);
+    win.buffer = buffer;
+
+    redraw (&win, NULL, 0);
+    
+    while (running) {
+        wl_display_iterate(dpy.display, dpy.mask);
+        sleep(0.3);
+    }    
+
+    wayland_drm_finalize();
+
+    wl_shell_surface_destroy(win.shell_surface);
+    wl_surface_destroy(win.surface);
+
+    if (win.callback)
+        wl_callback_destroy(win.callback);
+
+    if (dpy.shell)
+        wl_shell_destroy(dpy.shell);
+
+    if (dpy.compositor)
+        wl_compositor_destroy(dpy.compositor);
+
+    wl_display_flush(dpy.display);
+    wl_display_disconnect(dpy.display);
+
+}
+
-- 
1.7.5.4



More information about the mesa-dev mailing list