[Mesa-dev] [PATCH 09/11 v3] test: test case drm-test-client in src/egl/wayland/wayland-drm

Zhao, Halley halley.zhao at linux.intel.com
Thu Jun 21 01:19:04 PDT 2012


small update following gbm change: gbm_bo_get_shared_handle()


>From fb0e0eec5064f8af3e126a457fc23173a8bb6d49 Mon Sep 17 00:00:00 2001
From: Zhao Halley <halley.zhao at intel.com>
Date: Tue, 5 Jun 2012 14:59:56 +0800
Subject: [PATCH 09/10] test: test case drm-test-client in
 src/egl/wayland/wayland-drm

 - it shows how wayland-drm protocol works between server and client
   buffer are shared basing on dri image
 - XRGB and YUYV format are supported,
   it can render to overlay plane potentially
---
 configure.ac                                  |    3 +-
 src/egl/wayland/wayland-drm/Makefile.am       |   15 +-
 src/egl/wayland/wayland-drm/drm-test-client.c |  456
+++++++++++++++++++++++++
 3 files changed, 472 insertions(+), 2 deletions(-)
 mode change 100644 => 100755 configure.ac
 create mode 100755 src/egl/wayland/wayland-drm/drm-test-client.c
 mode change 100644 => 100755 tests/Makefile.am

diff --git a/configure.ac b/configure.ac
old mode 100644
new mode 100755
index 3bc59ca..044d19e
--- a/configure.ac
+++ b/configure.ac
@@ -2033,7 +2033,8 @@ AC_CONFIG_FILES([configs/autoconf
 		src/mesa/drivers/dri/radeon/Makefile
 		src/mesa/drivers/dri/swrast/Makefile
 		tests/Makefile
-		tests/glx/Makefile])
+		tests/glx/Makefile
+        ])
 
 dnl Replace the configs/current symlink
 AC_CONFIG_COMMANDS([configs],[
diff --git a/src/egl/wayland/wayland-drm/Makefile.am
b/src/egl/wayland/wayland-drm/Makefile.am
index cf15eda..dce9184 100644
--- a/src/egl/wayland/wayland-drm/Makefile.am
+++ b/src/egl/wayland/wayland-drm/Makefile.am
@@ -10,6 +10,19 @@ noinst_HEADERS = wayland-drm.h
 BUILT_SOURCES = wayland-drm-protocol.c \
 		wayland-drm-client-protocol.h \
 		wayland-drm-server-protocol.h
-CLEANFILES = $(BUILT_SOURCES)
+
+noinst_PROGRAMS = drm_test_client
+drm_test_client_CFLAGS = $(DEFINES) \
+			-I$(top_srcdir)/src/gbm/main \
+			$(WAYLAND_CFLAGS) \
+			$(LIBDRM_CFLAGS)
+
+drm_test_client_LDADD = $(WAYLAND_LIBS) $(LIBDRM_LIBS) 
+drm_test_client_LDADD += $(top_srcdir)/src/gbm/libgbm.la
+
+drm_test_client_SOURCES = drm-test-client.c wayland-drm-protocol.c \
+						  wayland-drm-client-protocol.h
+
+CLEANFILES = $(BUILT_SOURCES) $(drm_test_client_SOURCES)
 
 @wayland_scanner_rules@
diff --git a/src/egl/wayland/wayland-drm/drm-test-client.c
b/src/egl/wayland/wayland-drm/drm-test-client.c
new file mode 100755
index 0000000..d396aee
--- /dev/null
+++ b/src/egl/wayland/wayland-drm/drm-test-client.c
@@ -0,0 +1,456 @@
+/*
+ * 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 <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <assert.h>
+#include <xf86drm.h>
+#include "gbm.h"
+#include <wayland-client.h>
+#include <wayland-client-protocol.h>
+#include "wayland-drm-client-protocol.h"
+
+int win_width = 256, win_height = 256;
+int drm_fd = -1;
+int wayland_server_support_yuyv = 0;
+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 gbm_device *gbm;
+};
+
+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;
+    struct gbm_bo *gbm_bo;
+    unsigned int bo_pitch;
+};
+
+void fill_window_XRGB(struct window *win);
+void fill_window_YUYV(struct window *win);
+int wayland_drm_init(struct wl_display *wl_dpy);
+void wayland_drm_destroy(void);
+void redraw(void *data, struct wl_callback *callback, uint32_t time);
+
+void fill_window_XRGB(struct window *win)
+{
+    unsigned char *mem = malloc (win->bo_pitch * win_height);
+    static int color_index = 0;
+    static unsigned int color_arr[4] = {0xff000000, 0x00ff0000,
0x0000ff00, 0x000000ff};
+    unsigned int color; 
+    int i;
+    unsigned int *i_ptr;
+    unsigned char *c_ptr;
+
+    color = color_arr[color_index];
+    i_ptr = (unsigned int *)mem;
+    for (i=0; i<win_width/2; i++) {
+        *(i_ptr+i) = color;
+    }
+    color = color_arr[(color_index+1)%4];
+    for (i=win_width/2+1; i<win_width; i++) {
+        *(i_ptr+i) = color;
+    }
+
+    c_ptr = mem + win->bo_pitch;
+    for (i = 1; i<win_height/2; i++) {
+        memcpy (c_ptr, i_ptr, win_width*4);
+        c_ptr += win->bo_pitch;
+    }
+
+    color = color_arr[(color_index+2)%4];
+    i_ptr = (unsigned int *)c_ptr;
+    for (i=0; i<win_width/2; i++) {
+        *(i_ptr+i) = color;
+    }
+    color = color_arr[(color_index+3)%4];
+    for (i=win_width/2+1; i<win_width; i++) {
+        *(i_ptr+i) = color;
+    }
+
+    c_ptr += win->bo_pitch;
+    for (i = win_height/2+2; i<win_height; i++) {
+        memcpy (c_ptr, i_ptr, win_width*4);
+        c_ptr += win->bo_pitch;
+    }
+
+    gbm_bo_write(win->gbm_bo, mem, win->bo_pitch * win_height); 
+    free(mem);
+    color_index = (color_index+1) % 4;
+
+}
+
+void fill_window_YUYV(struct window *win)
+{
+    unsigned char *mem = malloc (win->bo_pitch * win_height);
+
+    static unsigned int color_arr[4] = {0x00ff00ff, 0x80ff00ff,
0x00ff80ff, 0x80ff80ff};
+    static int color_index = 0;
+    unsigned int color;
+    int i;
+    unsigned int *i_ptr;
+    unsigned char *c_ptr;
+
+    i_ptr = (unsigned int *)mem;
+    color = color_arr[color_index];
+    for (i=0; i<win_width/4; i++) {
+        *(i_ptr+i) = color;
+    }
+    color = color_arr[(color_index+1)%4];
+    for (i=win_width/4+1; i<win_width/2; i++) {
+        *(i_ptr+i) = color;
+    }
+
+    c_ptr = mem + win->bo_pitch;
+    for (i = 1; i<win_height/2; i++) {
+        memcpy (c_ptr, (unsigned char*)i_ptr, win_width*2);
+        c_ptr += win->bo_pitch;
+    }
+
+    i_ptr = (unsigned int *) c_ptr;
+    color = color_arr[(color_index+2)%4];
+    for (i=0; i<win_width/4; i++) {
+        *(i_ptr+i) = color;
+    }
+    color = color_arr[(color_index+3)%4];
+    for (i=win_width/4+1; i<win_width/2; i++) {
+        *(i_ptr+i) = color;
+    }
+
+	c_ptr += win->bo_pitch;
+    for (i = win_height/2+2; i<win_height; i++) {
+        memcpy (c_ptr, (unsigned char*)i_ptr, win_width*2);
+        c_ptr += win->bo_pitch;
+    }
+    
+    gbm_bo_write(win->gbm_bo, mem, win->bo_pitch * win_height); 
+    free(mem);
+
+    color_index = (color_index+1) % 4;
+}
+
+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)
+{
+    if (format == WL_DRM_FORMAT_YUYV) {
+        wayland_server_support_yuyv = 1;
+    }
+
+}
+
+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(void)
+{
+
+    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;
+
+void
+redraw(void *data, struct wl_callback *callback, uint32_t time)
+{
+	struct window *window = data;
+	if (callback)
+		wl_callback_destroy(callback);
+
+    if (window->format == WL_DRM_FORMAT_XRGB8888) {
+        fill_window_XRGB(window);
+    }
+    else {
+        fill_window_YUYV(window);
+    }
+
+    // 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)
+{
+
+    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;
+        }
+    }
+
+    win.geometry.width = win_width;
+    win.geometry.height = win_height;
+    
+    // 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);
+    if(!wayland_server_support_yuyv) {
+        win.format = WL_DRM_FORMAT_XRGB8888;
+    }
+
+    // create buffer object
+	dpy.gbm = gbm_create_device(drm_fd);
+    win.gbm_bo = gbm_bo_create(dpy.gbm, win_width, win_height,
win.format, GBM_BO_USE_RENDERING|GBM_BO_USE_WRITE);
+	win.bo_pitch = gbm_bo_get_pitch(win.gbm_bo);
+
+    unsigned int buf_name = gbm_bo_get_shared_handle(win.gbm_bo).u32;
+
+    // create wl_buffer
+    struct wl_buffer *buffer = wl_drm_create_buffer(wl_drm, buf_name,
win_width, win_height, win.bo_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();
+
+	gbm_bo_destroy(win.gbm_bo);
+
+    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);
+
+    return 0;
+}
+
diff --git a/tests/Makefile.am b/tests/Makefile.am
old mode 100644
new mode 100755
-- 
1.7.5.4


On Thu, 2012-06-14 at 18:32 +0800, Zhao Halley wrote:
> - it shows how wayland-drm protocol works between server and client
>    buffer are shared basing on dri image
>  - XRGB and YUYV format are supported,
>    it can render to overlay plane potentially
> ---
>  configure.ac                                  |    3 +-
>  src/egl/wayland/wayland-drm/Makefile.am       |   14 +-
>  src/egl/wayland/wayland-drm/drm-test-client.c |  456 +++++++++++++++++++++++++
>  3 files changed, 471 insertions(+), 2 deletions(-)
>  mode change 100644 => 100755 configure.ac
>  create mode 100755 src/egl/wayland/wayland-drm/drm-test-client.c
>  mode change 100644 => 100755 tests/Makefile.am
> 
> diff --git a/configure.ac b/configure.ac
> old mode 100644
> new mode 100755
> index 3bc59ca..044d19e
> --- a/configure.ac
> +++ b/configure.ac
> @@ -2033,7 +2033,8 @@ AC_CONFIG_FILES([configs/autoconf
>  		src/mesa/drivers/dri/radeon/Makefile
>  		src/mesa/drivers/dri/swrast/Makefile
>  		tests/Makefile
> -		tests/glx/Makefile])
> +		tests/glx/Makefile
> +        ])
>  
>  dnl Replace the configs/current symlink
>  AC_CONFIG_COMMANDS([configs],[
> diff --git a/src/egl/wayland/wayland-drm/Makefile.am b/src/egl/wayland/wayland-drm/Makefile.am
> index cf15eda..55ef063 100644
> --- a/src/egl/wayland/wayland-drm/Makefile.am
> +++ b/src/egl/wayland/wayland-drm/Makefile.am
> @@ -10,6 +10,18 @@ noinst_HEADERS = wayland-drm.h
>  BUILT_SOURCES = wayland-drm-protocol.c \
>  		wayland-drm-client-protocol.h \
>  		wayland-drm-server-protocol.h
> -CLEANFILES = $(BUILT_SOURCES)
> +
> +noinst_PROGRAMS = drm_test_client
> +drm_test_client_CFLAGS = $(DEFINES) \
> +		    $(WAYLAND_CFLAGS) \
> +		    $(LIBDRM_CFLAGS)
> +
> +drm_test_client_LDADD = $(WAYLAND_LIBS) $(LIBDRM_LIBS) 
> +drm_test_client_LDADD += $(top_srcdir)/src/gbm/libgbm.la
> +
> +drm_test_client_SOURCES = drm-test-client.c wayland-drm-protocol.c \
> +						  wayland-drm-client-protocol.h
> +
> +CLEANFILES = $(BUILT_SOURCES) $(drm_test_client_SOURCES)
>  
>  @wayland_scanner_rules@
> diff --git a/src/egl/wayland/wayland-drm/drm-test-client.c b/src/egl/wayland/wayland-drm/drm-test-client.c
> new file mode 100755
> index 0000000..05893ad
> --- /dev/null
> +++ b/src/egl/wayland/wayland-drm/drm-test-client.c
> @@ -0,0 +1,456 @@
> +/*
> + * 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 <stdio.h>
> +#include <unistd.h>
> +#include <errno.h>
> +#include <fcntl.h>
> +#include <sys/stat.h>
> +#include <string.h>
> +#include <assert.h>
> +#include <xf86drm.h>
> +#include <gbm.h>
> +#include <wayland-client.h>
> +#include <wayland-client-protocol.h>
> +#include "wayland-drm-client-protocol.h"
> +
> +int win_width = 256, win_height = 256;
> +int drm_fd = -1;
> +int wayland_server_support_yuyv = 0;
> +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 gbm_device *gbm;
> +};
> +
> +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;
> +    struct gbm_bo *gbm_bo;
> +    unsigned int bo_pitch;
> +};
> +
> +void fill_window_XRGB(struct window *win);
> +void fill_window_YUYV(struct window *win);
> +int wayland_drm_init(struct wl_display *wl_dpy);
> +void wayland_drm_destroy(void);
> +void redraw(void *data, struct wl_callback *callback, uint32_t time);
> +
> +void fill_window_XRGB(struct window *win)
> +{
> +    unsigned char *mem = malloc (win->bo_pitch * win_height);
> +    static int color_index = 0;
> +    static unsigned int color_arr[4] = {0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff};
> +    unsigned int color; 
> +    int i;
> +    unsigned int *i_ptr;
> +    unsigned char *c_ptr;
> +
> +    color = color_arr[color_index];
> +    i_ptr = (unsigned int *)mem;
> +    for (i=0; i<win_width/2; i++) {
> +        *(i_ptr+i) = color;
> +    }
> +    color = color_arr[(color_index+1)%4];
> +    for (i=win_width/2+1; i<win_width; i++) {
> +        *(i_ptr+i) = color;
> +    }
> +
> +    c_ptr = mem + win->bo_pitch;
> +    for (i = 1; i<win_height/2; i++) {
> +        memcpy (c_ptr, i_ptr, win_width*4);
> +        c_ptr += win->bo_pitch;
> +    }
> +
> +    color = color_arr[(color_index+2)%4];
> +    i_ptr = (unsigned int *)c_ptr;
> +    for (i=0; i<win_width/2; i++) {
> +        *(i_ptr+i) = color;
> +    }
> +    color = color_arr[(color_index+3)%4];
> +    for (i=win_width/2+1; i<win_width; i++) {
> +        *(i_ptr+i) = color;
> +    }
> +
> +    c_ptr += win->bo_pitch;
> +    for (i = win_height/2+2; i<win_height; i++) {
> +        memcpy (c_ptr, i_ptr, win_width*4);
> +        c_ptr += win->bo_pitch;
> +    }
> +
> +    gbm_bo_write(win->gbm_bo, mem, win->bo_pitch * win_height); 
> +    free(mem);
> +    color_index = (color_index+1) % 4;
> +
> +}
> +
> +void fill_window_YUYV(struct window *win)
> +{
> +    unsigned char *mem = malloc (win->bo_pitch * win_height);
> +
> +    static unsigned int color_arr[4] = {0x00ff00ff, 0x80ff00ff, 0x00ff80ff, 0x80ff80ff};
> +    static int color_index = 0;
> +    unsigned int color;
> +    int i;
> +    unsigned int *i_ptr;
> +    unsigned char *c_ptr;
> +
> +    i_ptr = (unsigned int *)mem;
> +    color = color_arr[color_index];
> +    for (i=0; i<win_width/4; i++) {
> +        *(i_ptr+i) = color;
> +    }
> +    color = color_arr[(color_index+1)%4];
> +    for (i=win_width/4+1; i<win_width/2; i++) {
> +        *(i_ptr+i) = color;
> +    }
> +
> +    c_ptr = mem + win->bo_pitch;
> +    for (i = 1; i<win_height/2; i++) {
> +        memcpy (c_ptr, (unsigned char*)i_ptr, win_width*2);
> +        c_ptr += win->bo_pitch;
> +    }
> +
> +    i_ptr = (unsigned int *) c_ptr;
> +    color = color_arr[(color_index+2)%4];
> +    for (i=0; i<win_width/4; i++) {
> +        *(i_ptr+i) = color;
> +    }
> +    color = color_arr[(color_index+3)%4];
> +    for (i=win_width/4+1; i<win_width/2; i++) {
> +        *(i_ptr+i) = color;
> +    }
> +
> +	c_ptr += win->bo_pitch;
> +    for (i = win_height/2+2; i<win_height; i++) {
> +        memcpy (c_ptr, (unsigned char*)i_ptr, win_width*2);
> +        c_ptr += win->bo_pitch;
> +    }
> +    
> +    gbm_bo_write(win->gbm_bo, mem, win->bo_pitch * win_height); 
> +    free(mem);
> +
> +    color_index = (color_index+1) % 4;
> +}
> +
> +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)
> +{
> +    if (format == WL_DRM_FORMAT_YUYV) {
> +        wayland_server_support_yuyv = 1;
> +    }
> +
> +}
> +
> +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(void)
> +{
> +
> +    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;
> +
> +void
> +redraw(void *data, struct wl_callback *callback, uint32_t time)
> +{
> +	struct window *window = data;
> +	if (callback)
> +		wl_callback_destroy(callback);
> +
> +    if (window->format == WL_DRM_FORMAT_XRGB8888) {
> +        fill_window_XRGB(window);
> +    }
> +    else {
> +        fill_window_YUYV(window);
> +    }
> +
> +    // 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)
> +{
> +
> +    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;
> +        }
> +    }
> +
> +    win.geometry.width = win_width;
> +    win.geometry.height = win_height;
> +    
> +    // 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);
> +    if(!wayland_server_support_yuyv) {
> +        win.format = WL_DRM_FORMAT_XRGB8888;
> +    }
> +
> +    // create buffer object
> +	dpy.gbm = gbm_create_device(drm_fd);
> +    win.gbm_bo = gbm_bo_create(dpy.gbm, win_width, win_height, win.format, GBM_BO_USE_RENDERING|GBM_BO_USE_WRITE);
> +	win.bo_pitch = gbm_bo_get_pitch(win.gbm_bo);
> +
> +    unsigned int buf_name = gbm_bo_get_handle2(win.gbm_bo).u32;
> +
> +    // create wl_buffer
> +    struct wl_buffer *buffer = wl_drm_create_buffer(wl_drm, buf_name, win_width, win_height, win.bo_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();
> +
> +	gbm_bo_destroy(win.gbm_bo);
> +
> +    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);
> +
> +    return 0;
> +}
> +
> diff --git a/tests/Makefile.am b/tests/Makefile.am
> old mode 100644
> new mode 100755




More information about the mesa-dev mailing list