- 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 | 4 +- tests/Makefile.am | 2 +- tests/wayland-drm/Makefile.am | 12 + tests/wayland-drm/wayland-drm-test.c | 456 ++++++++++++++++++++++++++++++++++ 4 files changed, 472 insertions(+), 2 deletions(-) mode change 100644 => 100755 configure.ac mode change 100644 => 100755 tests/Makefile.am create mode 100755 tests/wayland-drm/Makefile.am create mode 100755 tests/wayland-drm/wayland-drm-test.c
diff --git a/configure.ac b/configure.ac old mode 100644 new mode 100755 index 3bc59ca..58c05bc --- a/configure.ac +++ b/configure.ac @@ -2033,7 +2033,9 @@ 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 + tests/wayland-drm/Makefile + ]) dnl Replace the configs/current symlink AC_CONFIG_COMMANDS([configs],[ diff --git a/tests/Makefile.am b/tests/Makefile.am old mode 100644 new mode 100755 index 4079bb9..f6125f1 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1 +1 @@ -SUBDIRS=glx +SUBDIRS=glx wayland-drm diff --git a/tests/wayland-drm/Makefile.am b/tests/wayland-drm/Makefile.am new file mode 100755 index 0000000..7673368 --- /dev/null +++ b/tests/wayland-drm/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) +wayland_drm_test_LDADD += $(top_srcdir)/src/egl/main/libEGL.la $(top_srcdir)/src/gbm/libgbm.la + +wayland_drm_test_SOURCES = wayland-drm-test.c \ + $(top_srcdir)/src/egl/wayland/wayland-drm//wayland-drm-client-protocol.h diff --git a/tests/wayland-drm/wayland-drm-test.c b/tests/wayland-drm/wayland-drm-test.c new file mode 100755 index 0000000..aa6f001 --- /dev/null +++ b/tests/wayland-drm/wayland-drm-test.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.z...@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 "../../src/gbm/main/gbm.h" +#include <wayland-client.h> +#include <wayland-client-protocol.h> +#include "../../src/egl/wayland/wayland-drm/wayland-drm-client-protocol.h" + +int win_width = 1024, win_height = 512; +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 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() +{ + + 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_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); + +} + -- 1.7.5.4 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev