From patchwork Tue Jan 7 17:41:44 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Benjamin Gaignard X-Patchwork-Id: 22920 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-pa0-f69.google.com (mail-pa0-f69.google.com [209.85.220.69]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id C1DA6216D9 for ; Tue, 7 Jan 2014 17:42:26 +0000 (UTC) Received: by mail-pa0-f69.google.com with SMTP id hz1sf1765437pad.8 for ; Tue, 07 Jan 2014 09:42:26 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:delivered-to:from:to:date:message-id:in-reply-to :references:mime-version:subject:precedence:list-id:list-unsubscribe :list-archive:list-post:list-help:list-subscribe:errors-to:sender :x-original-sender:x-original-authentication-results:mailing-list :content-type:content-transfer-encoding; bh=ejhiyTb/ttGGHYx5XFGuF1cXgM06eKPfT6NLteUbf9A=; b=Q9fC4ev4AV3r5JRamG/fJLIN78Dr9rhlra3o4aVrZX3ouZyS9RGEFczJI0DoGvLT6K pFdPQvbwhh9VKIMe+EQCTJ64GjyxiMZj9Zc+JOceyNZbLcNhMR+7BZY4kuX84PM7S7i3 QRRnWTAjEwKKGOpt7b7Q5/TF1VJ5VAin2naq/NgRK3gePEgUpyG64OujYh31Btw3FdZR aXLu9L568VWDTCRqT7ps5c4CsJalztSLsdn8H7jn7tc2tMJ6qMd4HSDBBOQn5wjrC6Lb Bmy75Rq9sgUyUkAmpXOnydxrUb71bk/loqxFWaf+FXUp73MFIQnJqs21huZIh3EGeXu7 JEgQ== X-Gm-Message-State: ALoCoQmmCHb0OJBKrsr4JUI3EtiVljrD/zmTWg5pHQRU0fbKJppqdgDp697Nh0Fka7JR1e4mHKCM X-Received: by 10.66.102.36 with SMTP id fl4mr2528092pab.20.1389116545976; Tue, 07 Jan 2014 09:42:25 -0800 (PST) X-BeenThere: patchwork-forward@linaro.org Received: by 10.49.105.193 with SMTP id go1ls181900qeb.97.gmail; Tue, 07 Jan 2014 09:42:25 -0800 (PST) X-Received: by 10.58.201.169 with SMTP id kb9mr4082362vec.42.1389116545789; Tue, 07 Jan 2014 09:42:25 -0800 (PST) Received: from mail-vb0-f43.google.com (mail-vb0-f43.google.com [209.85.212.43]) by mx.google.com with ESMTPS id c14si17540566veu.28.2014.01.07.09.42.25 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Tue, 07 Jan 2014 09:42:25 -0800 (PST) Received-SPF: neutral (google.com: 209.85.212.43 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) client-ip=209.85.212.43; Received: by mail-vb0-f43.google.com with SMTP id p6so343698vbe.16 for ; Tue, 07 Jan 2014 09:42:25 -0800 (PST) X-Received: by 10.58.146.5 with SMTP id sy5mr4148188veb.43.1389116545275; Tue, 07 Jan 2014 09:42:25 -0800 (PST) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patches@linaro.org Received: by 10.59.13.131 with SMTP id ey3csp174193ved; Tue, 7 Jan 2014 09:42:24 -0800 (PST) X-Received: by 10.14.48.74 with SMTP id u50mr2934838eeb.107.1389116543628; Tue, 07 Jan 2014 09:42:23 -0800 (PST) Received: from ip-10-141-164-156.ec2.internal (lists.linaro.org. [54.225.227.206]) by mx.google.com with ESMTPS id l44si89775184eem.229.2014.01.07.09.42.22 for (version=TLSv1 cipher=RC4-SHA bits=128/128); Tue, 07 Jan 2014 09:42:23 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linaro-mm-sig-bounces@lists.linaro.org designates 54.225.227.206 as permitted sender) client-ip=54.225.227.206; Received: from localhost ([127.0.0.1] helo=ip-10-141-164-156.ec2.internal) by ip-10-141-164-156.ec2.internal with esmtp (Exim 4.76) (envelope-from ) id 1W0afE-0006Ga-Ra; Tue, 07 Jan 2014 17:42:04 +0000 Received: from mail-we0-f180.google.com ([74.125.82.180]) by ip-10-141-164-156.ec2.internal with esmtp (Exim 4.76) (envelope-from ) id 1W0aey-0006DB-Rh for linaro-mm-sig@lists.linaro.org; Tue, 07 Jan 2014 17:41:49 +0000 Received: by mail-we0-f180.google.com with SMTP id t61so450980wes.39 for ; Tue, 07 Jan 2014 09:41:56 -0800 (PST) X-Received: by 10.180.38.8 with SMTP id c8mr17979160wik.48.1389116515974; Tue, 07 Jan 2014 09:41:55 -0800 (PST) Received: from lmenx321.lme.st.com (lya72-2-88-175-155-153.fbx.proxad.net. [88.175.155.153]) by mx.google.com with ESMTPSA id f7sm45992553wjb.7.2014.01.07.09.41.54 for (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Tue, 07 Jan 2014 09:41:55 -0800 (PST) From: benjamin.gaignard@linaro.org To: wayland-devel@lists.freedesktop.org, linaro-mm-sig@lists.linaro.org Date: Tue, 7 Jan 2014 18:41:44 +0100 Message-Id: <1389116504-3923-4-git-send-email-benjamin.gaignard@linaro.org> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1389116504-3923-1-git-send-email-benjamin.gaignard@linaro.org> References: <1389116504-3923-1-git-send-email-benjamin.gaignard@linaro.org> MIME-Version: 1.0 Subject: [Linaro-mm-sig] =?utf-8?q?=5BPATCH_v4_3/3=5D_add_simple-dmabuf_cl?= =?utf-8?q?ient?= X-BeenThere: linaro-mm-sig@lists.linaro.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: , List-Help: , List-Subscribe: , Errors-To: linaro-mm-sig-bounces@lists.linaro.org Sender: linaro-mm-sig-bounces@lists.linaro.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: benjamin.gaignard@linaro.org X-Original-Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.212.43 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 From: Benjamin Gaignard It is a simple example of how use wl_dmabuf protocol with weston Signed-off-by: Benjamin Gaignard --- clients/Makefile.am | 11 ++ clients/simple-dmabuf.c | 469 +++++++++++++++++++++++++++++++++++++++++++++++ configure.ac | 5 + 3 files changed, 485 insertions(+) create mode 100644 clients/simple-dmabuf.c diff --git a/clients/Makefile.am b/clients/Makefile.am index 032d900..3840079 100644 --- a/clients/Makefile.am +++ b/clients/Makefile.am @@ -52,6 +52,17 @@ weston_multi_resource_SOURCES = multi-resource.c \ ../shared/os-compatibility.h weston_multi_resource_CPPFLAGS = $(SIMPLE_CLIENT_CFLAGS) weston_multi_resource_LDADD = $(SIMPLE_CLIENT_LIBS) -lm + +if BUILD_SIMPLE_CLIENT_DMABUF +simple_clients_programs += \ + weston-simple-dmabuf + +weston_simple_dmabuf_SOURCES = simple-dmabuf.c \ + ../shared/os-compatibility.c \ + ../shared/os-compatibility.h +weston_simple_dmabuf_CPPFLAGS = $(SIMPLE_CLIENT_CFLAGS) $(SIMPLE_CLIENT_DMABUF_CFLAGS) +weston_simple_dmabuf_LDADD = $(SIMPLE_CLIENT_LIBS) $(SIMPLE_CLIENT_DMABUF_LIBS) +endif endif if BUILD_SIMPLE_EGL_CLIENTS diff --git a/clients/simple-dmabuf.c b/clients/simple-dmabuf.c new file mode 100644 index 0000000..7f381ae --- /dev/null +++ b/clients/simple-dmabuf.c @@ -0,0 +1,469 @@ +/* + * Copyright 2014 Benjamin Gaignard for Linaro + * Copyright © 2011 Benjamin Franzke + * Copyright © 2010 Intel Corporation + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "../shared/os-compatibility.h" + +struct display { + struct wl_display *display; + struct wl_registry *registry; + struct wl_compositor *compositor; + struct wl_shell *shell; + struct wl_dmabuf *dmabuf; + uint32_t format; + int drm_fd; +}; + +struct buffer { + struct wl_buffer *buffer; + int fd; + int busy; + uint32_t size; + struct display *display; + void *dmabuf_data; +}; + +struct window { + struct display *display; + int width, height; + struct wl_surface *surface; + struct wl_shell_surface *shell_surface; + struct buffer buffers[2]; + struct buffer *prev_buffer; + struct wl_callback *callback; +}; + +static void +buffer_release(void *data, struct wl_buffer *buffer) +{ + struct buffer *mybuf = data; + + mybuf->busy = 0; +} + +static const struct wl_buffer_listener buffer_listener = { + buffer_release +}; + +static int +create_dmabuf_buffer(struct display *display, struct buffer *buffer, + int width, int height, uint32_t format) +{ + struct drm_mode_create_dumb create_arg; + int ret; + int prime_fd; + uint32_t stride; + + memset (&create_arg, 0, sizeof (create_arg)); + create_arg.bpp = 32; + create_arg.width = width; + create_arg.height = height; + + ret = drmIoctl (display->drm_fd, DRM_IOCTL_MODE_CREATE_DUMB, &create_arg); + if (ret) + return ret; + + stride = create_arg.pitch; + + ret = drmPrimeHandleToFD (display->drm_fd, create_arg.handle, DRM_CLOEXEC, &prime_fd); + if (ret) + return ret; + + buffer->buffer = wl_dmabuf_create_prime_buffer (display->dmabuf, prime_fd, + width, height, format, stride); + + wl_buffer_add_listener(buffer->buffer, &buffer_listener, buffer); + + buffer->fd = prime_fd; + buffer->display = display; + + buffer->size = width * height * 4; + + buffer->dmabuf_data = mmap (0, buffer->size, PROT_READ | PROT_WRITE, MAP_SHARED, buffer->fd, 0); + + return 0; +} + +static void +destroy_dmabuf_buffer(struct buffer *buffer) +{ + struct display *display = buffer->display; + struct drm_mode_destroy_dumb destroy_arg; + + munmap (buffer->dmabuf_data, buffer->size); + + memset (&destroy_arg, 0, sizeof destroy_arg); + drmPrimeFDToHandle (display->drm_fd, buffer->fd, &destroy_arg.handle); + drmIoctl (display->drm_fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_arg); + close (buffer->fd); +} + +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) +{ +} + +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 struct window * +create_window(struct display *display, int width, int height) +{ + struct window *window; + + window = calloc(1, sizeof *window); + if (!window) + return NULL; + + window->callback = NULL; + window->display = display; + window->width = width; + window->height = height; + window->surface = wl_compositor_create_surface(display->compositor); + window->shell_surface = wl_shell_get_shell_surface(display->shell, + window->surface); + + if (window->shell_surface) + wl_shell_surface_add_listener(window->shell_surface, + &shell_surface_listener, window); + + wl_shell_surface_set_title(window->shell_surface, "simple-dmabuf"); + + wl_shell_surface_set_toplevel(window->shell_surface); + + return window; +} + +static void +destroy_window(struct window *window) +{ + if (window->callback) + wl_callback_destroy(window->callback); + + if (window->buffers[0].buffer) + wl_buffer_destroy(window->buffers[0].buffer); + if (window->buffers[1].buffer) + wl_buffer_destroy(window->buffers[1].buffer); + + destroy_dmabuf_buffer(&window->buffers[0]); + destroy_dmabuf_buffer(&window->buffers[1]); + + wl_shell_surface_destroy(window->shell_surface); + wl_surface_destroy(window->surface); + free(window); +} + +static struct buffer * +window_next_buffer(struct window *window) +{ + struct buffer *buffer; + int ret = 0; + + if (!window->buffers[0].busy) + buffer = &window->buffers[0]; + else if (!window->buffers[1].busy) + buffer = &window->buffers[1]; + else + return NULL; + + if (!buffer->buffer) { + ret = create_dmabuf_buffer(window->display, buffer, + window->width, window->height, + WL_DMABUF_FORMAT_XRGB8888); + + if (ret) + return NULL; + + /* paint the padding */ + memset(buffer->dmabuf_data, 0xff, window->width * window->height * 4); + } + + return buffer; +} + +static void +paint_pixels(void *image, int padding, int width, int height, uint32_t time) +{ + const int halfh = padding + (height - padding * 2) / 2; + const int halfw = padding + (width - padding * 2) / 2; + int ir, or; + uint32_t *pixel = image; + int y; + + /* squared radii thresholds */ + or = (halfw < halfh ? halfw : halfh) - 8; + ir = or - 32; + or *= or; + ir *= ir; + + pixel += padding * width; + for (y = padding; y < height - padding; y++) { + int x; + int y2 = (y - halfh) * (y - halfh); + + pixel += padding; + for (x = padding; x < width - padding; x++) { + uint32_t v; + + /* squared distance from center */ + int r2 = (x - halfw) * (x - halfw) + y2; + + if (r2 < ir) + v = (r2 / 32 + time / 64) * 0x0080401; + else if (r2 < or) + v = (y + time / 32) * 0x0080401; + else + v = (x + time / 16) * 0x0080401; + v &= 0x00ffffff; + + /* cross if compositor uses X from XRGB as alpha */ + if (abs(x - y) > 6 && abs(x + y - height) > 6) + v |= 0xff000000; + + *pixel++ = v; + } + + pixel += padding; + } +} + +static const struct wl_callback_listener frame_listener; + +static void +redraw(void *data, struct wl_callback *callback, uint32_t time) +{ + struct window *window = data; + struct buffer *buffer; + + buffer = window_next_buffer(window); + if (!buffer) { + fprintf(stderr, + !callback ? "Failed to create the first buffer.\n" : + "Both buffers busy at redraw(). Server bug?\n"); + abort(); + } + + paint_pixels(buffer->dmabuf_data, 20, window->width, window->height, time); + + wl_surface_attach(window->surface, buffer->buffer, 0, 0); + wl_surface_damage(window->surface, + 20, 20, window->width - 40, window->height - 40); + + if (callback) + wl_callback_destroy(callback); + + window->callback = wl_surface_frame(window->surface); + wl_callback_add_listener(window->callback, &frame_listener, window); + wl_surface_commit(window->surface); + buffer->busy = 1; +} + +static const struct wl_callback_listener frame_listener = { + redraw +}; + +static void +dmabuf_handle_format(void *data, struct wl_dmabuf *wl_dmabuf, uint32_t format) +{ + struct display *d = data; + + fprintf(stderr, "server supported format %.4s\n", (char *) &format); + + if (format == WL_DMABUF_FORMAT_XRGB8888) + d->format = format; +} + +static void +dmabuf_handle_device (void *data, struct wl_dmabuf *wl_dmabuf, char *name) +{ + struct display *d = data; + + fprintf(stderr, "server %s\n", name); + d->drm_fd = open (name, O_RDWR, 0); +} + +struct wl_dmabuf_listener dmabuf_listener = { + dmabuf_handle_format, + dmabuf_handle_device +}; + +static void +registry_handle_global(void *data, struct wl_registry *registry, + uint32_t id, const char *interface, uint32_t version) +{ + struct display *d = data; + + if (strcmp(interface, "wl_compositor") == 0) { + d->compositor = + wl_registry_bind(registry, + id, &wl_compositor_interface, 1); + } else if (strcmp(interface, "wl_shell") == 0) { + d->shell = wl_registry_bind(registry, + id, &wl_shell_interface, 1); + } else if (strcmp(interface, "wl_dmabuf") == 0) { + d->dmabuf = wl_registry_bind(registry, + id, &wl_dmabuf_interface, 1); + wl_dmabuf_add_listener(d->dmabuf, &dmabuf_listener, d); + } +} + +static void +registry_handle_global_remove(void *data, struct wl_registry *registry, + uint32_t name) +{ +} + +static const struct wl_registry_listener registry_listener = { + registry_handle_global, + registry_handle_global_remove +}; + +static struct display * +create_display(void) +{ + struct display *display; + + display = malloc(sizeof *display); + if (display == NULL) { + fprintf(stderr, "out of memory\n"); + exit(1); + } + display->display = wl_display_connect(NULL); + assert(display->display); + + display->format = 0; + display->drm_fd = -1; + display->registry = wl_display_get_registry(display->display); + wl_registry_add_listener(display->registry, + ®istry_listener, display); + wl_display_roundtrip(display->display); + if (display->dmabuf == NULL) { + fprintf(stderr, "No wl_dmabuf global\n"); + exit(1); + } + + wl_display_roundtrip(display->display); + + if (display->format != WL_DMABUF_FORMAT_XRGB8888) { + fprintf(stderr, "WL_DMABUF_FORMAT_XRGB8888 not available\n"); + exit(1); + } + + wl_display_get_fd(display->display); + + return display; +} + +static void +destroy_display(struct display *display) +{ + if (display->dmabuf) + wl_dmabuf_destroy(display->dmabuf); + + if (display->shell) + wl_shell_destroy(display->shell); + + if (display->compositor) + wl_compositor_destroy(display->compositor); + + wl_registry_destroy(display->registry); + wl_display_flush(display->display); + wl_display_disconnect(display->display); + close(display->drm_fd); + free(display); +} + +static int running = 1; + +static void +signal_int(int signum) +{ + running = 0; +} + +int +main(int argc, char **argv) +{ + struct sigaction sigint; + struct display *display; + struct window *window; + int ret = 0; + + display = create_display(); + window = create_window(display, 250, 250); + if (!window) + return 1; + + sigint.sa_handler = signal_int; + sigemptyset(&sigint.sa_mask); + sigint.sa_flags = SA_RESETHAND; + sigaction(SIGINT, &sigint, NULL); + + /* Initialise damage to full surface, so the padding gets painted */ + wl_surface_damage(window->surface, 0, 0, + window->width, window->height); + + redraw(window, NULL, 0); + + while (running && ret != -1) + ret = wl_display_dispatch(display->display); + + fprintf(stderr, "simple-dmabuf exiting\n"); + destroy_window(window); + destroy_display(display); + + return 0; +} diff --git a/configure.ac b/configure.ac index 50bce23..da445f3 100644 --- a/configure.ac +++ b/configure.ac @@ -271,6 +271,11 @@ AC_ARG_ENABLE(simple-clients, AM_CONDITIONAL(BUILD_SIMPLE_CLIENTS, test "x$enable_simple_clients" = "xyes") if test x$enable_simple_clients = xyes; then PKG_CHECK_MODULES(SIMPLE_CLIENT, [wayland-client]) + AC_CHECK_HEADER([wayland-dmabuf.h], + [ PKG_CHECK_MODULES(SIMPLE_CLIENT_DMABUF, [libdrm libkms] , + [have_dmabuf=yes], [have_dmabuf=no])], + [have_dmabuf=no]) + AM_CONDITIONAL(BUILD_SIMPLE_CLIENT_DMABUF, test "x$have_dmabuf" = "xyes") fi AC_ARG_ENABLE(simple-egl-clients,