simple-dmabuf is an example client which shows how to write wayland
clients that use render-nodes for hardware-accelerated rendering and pass
the buffer via dmabuf to the compositor. No mesa/EGL extensions are
needed! Instead we pass dmabufs as wl_shm buffers to the compositors. This
allows us to use hardware-accelerated rendering even with fbdev or other
backends. Hurray!

This still contains some hacks and is more a proof-of-concept than
something useful. However, it shows what render-nodes allow us to do
without modifying the compositor at all.

This example requires a 3.12-rc kernel with drm.rnodes=1 on the kernel
command line (must be set during boot!). Furthermore, this currently only
works with drivers that implement dmabuf-mmap (which is rcar-du, shmob,
omapdrm and others). I have some hacks which implement it for i915 (but
flushing seems to not work..).

I haven't succeeded in making rendering work with i915. I currently have
no access to other drivers so any further testing/debugging welcome. We
either still miss some render-nodes ioctls that are needed by mesa (but I
didn't get any mesa errors..) or my i915-dmabuf-mmap is just wrong.
If someone gets this working on a specific card (working means non-black
window), please let me know.
---
 clients/.gitignore      |   1 +
 clients/Makefile.am     |   7 +-
 clients/simple-dmabuf.c | 675 ++++++++++++++++++++++++++++++++++++++++++++++++
 configure.ac            |   2 +-
 4 files changed, 683 insertions(+), 2 deletions(-)
 create mode 100644 clients/simple-dmabuf.c

diff --git a/clients/.gitignore b/clients/.gitignore
index 23959cc..b77b537 100644
--- a/clients/.gitignore
+++ b/clients/.gitignore
@@ -11,6 +11,7 @@ weston-image
 weston-nested
 weston-nested-client
 weston-resizor
+weston-simple-dmabuf
 weston-simple-egl
 weston-simple-shm
 weston-simple-touch
diff --git a/clients/Makefile.am b/clients/Makefile.am
index 4f9dc48..39dca7f 100644
--- a/clients/Makefile.am
+++ b/clients/Makefile.am
@@ -56,11 +56,16 @@ endif
 
 if BUILD_SIMPLE_EGL_CLIENTS
 simple_egl_clients_programs =                  \
-       weston-simple-egl
+       weston-simple-egl \
+       weston-simple-dmabuf
 
 weston_simple_egl_SOURCES = simple-egl.c
 weston_simple_egl_CPPFLAGS = $(SIMPLE_EGL_CLIENT_CFLAGS)
 weston_simple_egl_LDADD = $(SIMPLE_EGL_CLIENT_LIBS) -lm
+
+weston_simple_dmabuf_SOURCES = simple-dmabuf.c
+weston_simple_dmabuf_CPPFLAGS = $(SIMPLE_EGL_CLIENT_CFLAGS)
+weston_simple_dmabuf_LDADD = $(SIMPLE_EGL_CLIENT_LIBS) -lm
 endif
 
 if BUILD_CLIENTS
diff --git a/clients/simple-dmabuf.c b/clients/simple-dmabuf.c
new file mode 100644
index 0000000..570c929
--- /dev/null
+++ b/clients/simple-dmabuf.c
@@ -0,0 +1,675 @@
+/*
+ * Copyright © 2012-2013 David Herrmann <dh.herrm...@gmail.com>
+ *
+ * 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.
+ */
+
+/*
+ * Simple dmabuf/render-nodes Client
+ * This is a simple example client which uses dmabuf to pass buffers via wl_shm
+ * (instead of wl_drm or other EGL extensions) to the compositor. To render the
+ * images, we use DRM render-nodes or software-rendering as fallback.
+ *
+ * Note that this is a very basic example how to use wl_shm to share buffers
+ * which were rendered using a dedicated GPU. No mesa/EGL internal extensions
+ * are required.
+ * However, this is *not* the recommended way to do it! The mesa/EGL extensions
+ * allow much better integration and control. This client serves as a
+ * proof-of-concept and generic HOWTO.
+ */
+
+#define EGL_EGLEXT_PROTOTYPES
+#define GL_GLEXT_PROTOTYPES
+
+#include <config.h>
+
+#include <assert.h>
+#include <dirent.h>
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <errno.h>
+#include <error.h>
+#include <fcntl.h>
+#include <gbm.h>
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <wayland-client.h>
+#include <xf86drm.h>
+
+/* buffer objects */
+
+struct buffer {
+       struct window *window;
+       struct wl_buffer *buffer;
+       void *shm_data;
+
+       struct rnode_buffer *rnode;
+};
+
+struct rnode_buffer {
+       struct gbm_bo *gbm_bo;
+       int fd;
+       struct buffer buf;
+};
+
+/* window objects */
+
+struct rnode_window {
+       struct gbm_surface *gbm_surface;
+       EGLSurface egl_surface;
+};
+
+struct window {
+       struct display *display;
+       int width, height;
+       struct wl_surface *surface;
+       struct wl_shell_surface *shell_surface;
+       struct wl_callback *callback;
+
+       struct rnode_window rnode;
+};
+
+/* display objects */
+
+struct rnode_display {
+       int fd;
+       struct gbm_device *gbm_dev;
+       EGLDisplay egl_display;
+       EGLConfig egl_conf;
+       EGLContext egl_ctx;
+};
+
+struct display {
+       struct wl_display *display;
+       struct wl_registry *registry;
+       struct wl_compositor *compositor;
+       struct wl_shell *shell;
+       struct wl_shm *shm;
+       uint32_t formats;
+
+       struct rnode_display rnode;
+};
+
+/* forward declarations */
+
+static void buffer_init(struct buffer *buf, struct window *w,
+                       struct rnode_buffer *b);
+static void buffer_destroy(struct buffer *buf);
+
+/*
+ * Render Nodes
+ */
+
+/* rnode_open() tries to find a render-node, open it and return an FD. This
+ * should really be done via udev_enumerate_*() APIs, but to avoid a udev
+ * dependency here, we just hack it up via a /dev/dri/ iterator.
+ * DON'T COPY THAT! It's an ugly hack! */
+static int rnode_open(void)
+{
+       DIR *dir;
+       struct dirent *e;
+       int r, fd;
+       char *p;
+
+       dir = opendir("/dev/dri/");
+       if (!dir)
+               error(1, errno, "cannot open /dev/dri/");
+
+       fd = -1;
+       while ((e = readdir(dir))) {
+               if (e->d_type != DT_CHR)
+                       continue;
+               if (strncmp(e->d_name, "renderD", 7))
+                       continue;
+
+               r = asprintf(&p, "/dev/dri/%s", e->d_name);
+               if (r < 0)
+                       error(1, errno, "cannot allocate pathname");
+
+               r = open(p, O_RDWR | O_CLOEXEC | O_NOCTTY | O_NONBLOCK);
+               if (r < 0) {
+                       free(p);
+                       error(0, errno, "cannot open %s", p);
+                       continue;
+               }
+
+               fd = r;
+               fprintf(stderr, "using render node %s\n", p);
+               free(p);
+               break;
+       }
+
+       if (fd < 0)
+               error(1, 0, "cannot open any render-node in /dev/dri/");
+
+       return fd;
+}
+
+static void rnode_init(struct display *d)
+{
+       static const EGLint conf_att[] = {
+               EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+               EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+               EGL_RED_SIZE, 1,
+               EGL_GREEN_SIZE, 1,
+               EGL_BLUE_SIZE, 1,
+               EGL_ALPHA_SIZE, 0,
+               EGL_NONE,
+       };
+       static const EGLint ctx_att[] = {
+               EGL_CONTEXT_CLIENT_VERSION, 2,
+               EGL_NONE
+       };
+       EGLBoolean b;
+       EGLenum api;
+       EGLint major, minor, n;
+
+       d->rnode.fd = rnode_open();
+       d->rnode.gbm_dev = gbm_create_device(d->rnode.fd);
+       if (!d->rnode.gbm_dev)
+               error(1, errno, "cannot create gbm device");
+
+       d->rnode.egl_display = 
eglGetDisplay((EGLNativeDisplayType)d->rnode.gbm_dev);
+       if (!d->rnode.egl_display)
+               error(1, errno, "cannot create EGL display");
+
+       b = eglInitialize(d->rnode.egl_display, &major, &minor);
+       if (!b)
+               error(1, errno, "cannot initialize EGL");
+
+       fprintf(stderr, "EGL major/minor: %d.%d\n", major, minor);
+       fprintf(stderr, "EGL version: %s\n",
+               eglQueryString(d->rnode.egl_display, EGL_VERSION));
+       fprintf(stderr, "EGL vendor: %s\n",
+               eglQueryString(d->rnode.egl_display, EGL_VENDOR));
+       fprintf(stderr, "EGL extensions: %s\n",
+               eglQueryString(d->rnode.egl_display, EGL_EXTENSIONS));
+
+       api = EGL_OPENGL_ES_API;
+       b = eglBindAPI(api);
+       if (!b)
+               error(1, errno, "cannot bind OpenGLES API");
+
+       b = eglChooseConfig(d->rnode.egl_display, conf_att, &d->rnode.egl_conf,
+                           1, &n);
+       if (!b || n != 1)
+               error(1, errno, "cannot find suitable EGL config");
+
+       d->rnode.egl_ctx = eglCreateContext(d->rnode.egl_display,
+                                           d->rnode.egl_conf,
+                                           EGL_NO_CONTEXT,
+                                           ctx_att);
+       if (!d->rnode.egl_ctx)
+               error(1, errno, "cannot create EGL context");
+}
+
+static void rnode_destroy(struct display *d)
+{
+       eglMakeCurrent(d->rnode.egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE,
+                      EGL_NO_CONTEXT);
+       eglDestroyContext(d->rnode.egl_display, d->rnode.egl_ctx);
+       eglTerminate(d->rnode.egl_display);
+       gbm_device_destroy(d->rnode.gbm_dev);
+       close(d->rnode.fd);
+}
+
+static void rnode_buffer_destroy_cb(struct gbm_bo *bo, void *data)
+{
+       struct rnode_buffer *b = data;
+
+       if (!b)
+               return;
+
+       buffer_destroy(&b->buf);
+       close(b->fd);
+       free(b);
+}
+
+static struct rnode_buffer *rnode_bo_to_buffer(struct window *w,
+                                              struct gbm_bo *bo)
+{
+       struct display *d = w->display;
+       struct rnode_buffer *b;
+       int r;
+
+       b = gbm_bo_get_user_data(bo);
+       if (b)
+               return b;
+
+       b = calloc(1, sizeof(*b));
+       if (!b)
+               error(1, errno, "cannot allocate buffer object");
+
+       b->gbm_bo = bo;
+
+       r = drmPrimeHandleToFD(d->rnode.fd, gbm_bo_get_handle(bo).u32,
+                              0, &b->fd);
+       if (r < 0)
+               error(1, errno, "cannot get prime-fd for buffer handle");
+
+       buffer_init(&b->buf, w, b);
+       gbm_bo_set_user_data(bo, b, rnode_buffer_destroy_cb);
+       return b;
+}
+
+static void rnode_window_create(struct window *w)
+{
+       struct display *d = w->display;
+       EGLBoolean b;
+
+       w->rnode.gbm_surface = gbm_surface_create(d->rnode.gbm_dev,
+                                                 w->width, w->height,
+                                                 GBM_FORMAT_XRGB8888,
+                                                 GBM_BO_USE_RENDERING);
+       if (!w->rnode.gbm_surface)
+               error(1, errno, "cannot create gbm surface");
+
+       w->rnode.egl_surface = eglCreateWindowSurface(d->rnode.egl_display,
+                                                     d->rnode.egl_conf,
+                                                     
(EGLNativeWindowType)w->rnode.gbm_surface,
+                                                     NULL);
+       if (!w->rnode.egl_surface)
+               error(1, errno, "cannot create EGL surface");
+
+       b = eglMakeCurrent(d->rnode.egl_display,
+                          w->rnode.egl_surface,
+                          w->rnode.egl_surface,
+                          d->rnode.egl_ctx);
+       if (!b)
+               error(1, errno, "cannot activate EGL context");
+
+       glClearColor(0, 0, 0, 1);
+       glClear(GL_COLOR_BUFFER_BIT);
+}
+
+static void rnode_window_destroy(struct window *w)
+{
+       struct display *d = w->display;
+
+       eglMakeCurrent(d->rnode.egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE,
+                      d->rnode.egl_ctx);
+       eglDestroySurface(d->rnode.egl_display, w->rnode.egl_surface);
+       gbm_surface_destroy(w->rnode.gbm_surface);
+}
+
+static struct buffer *rnode_window_swap(struct window *w)
+{
+       int r;
+       EGLBoolean eb;
+       struct display *d = w->display;
+       struct gbm_bo *bo;
+       struct rnode_buffer *b;
+
+       r = gbm_surface_has_free_buffers(w->rnode.gbm_surface);
+       if (!r)
+               error(1, errno, "gbm surface has no free buffers left");
+
+       glFinish();
+       eb = eglSwapBuffers(d->rnode.egl_display, w->rnode.egl_surface);
+       if (!eb)
+               error(1, errno, "cannot swap buffers");
+
+       bo = gbm_surface_lock_front_buffer(w->rnode.gbm_surface);
+       if (!bo)
+               error(1, errno, "cannot lock front buffer");
+
+       b = rnode_bo_to_buffer(w, bo);
+       return &b->buf;
+}
+
+static void rnode_buffer_release(struct buffer *buf)
+{
+       struct rnode_buffer *b = buf->rnode;
+       struct window *w = buf->window;
+
+       gbm_surface_release_buffer(w->rnode.gbm_surface, b->gbm_bo);
+}
+
+/*
+ * Buffer Handling
+ */
+
+static void
+buffer_release(void *data, struct wl_buffer *buffer)
+{
+       struct buffer *buf = data;
+
+       rnode_buffer_release(buf);
+}
+
+static const struct wl_buffer_listener buffer_listener = {
+       buffer_release,
+};
+
+static void buffer_init(struct buffer *buf, struct window *w,
+                       struct rnode_buffer *b)
+{
+       struct wl_shm_pool *pool;
+       struct display *d = w->display;
+       unsigned int size, stride;
+
+       buf->window = w;
+       buf->rnode = b;
+
+       stride = w->width * 4;
+       size = stride * w->height;
+
+       /* mmap() not needed, but could be used as software fallback */
+       buf->shm_data = mmap(NULL, size, PROT_READ, MAP_SHARED,
+                            b->fd, 0);
+       if (buf->shm_data == MAP_FAILED)
+               error(1, errno, "cannot mmap buffer");
+
+       pool = wl_shm_create_pool(d->shm, b->fd, size);
+       if (!pool)
+               error(1, errno, "cannot create wl_shm pool");
+
+       buf->buffer = wl_shm_pool_create_buffer(pool, 0, w->width, w->height,
+                                               stride,
+                                               WL_SHM_FORMAT_XRGB8888);
+       if (!buf->buffer)
+               error(1, errno, "cannot create wl_shm buffer");
+
+       wl_buffer_add_listener(buf->buffer, &buffer_listener, buf);
+
+       wl_shm_pool_destroy(pool);
+}
+
+static void buffer_destroy(struct buffer *buf)
+{
+       struct window *w = buf->window;
+
+       munmap(buf->shm_data, w->width * w->height * 4);
+       wl_buffer_destroy(buf->buffer);
+}
+
+/*
+ * Window Handling
+ */
+
+static void
+window_handle_ping(void *data, struct wl_shell_surface *shell_surface,
+                  uint32_t serial)
+{
+       wl_shell_surface_pong(shell_surface, serial);
+}
+
+static void
+window_handle_configure(void *data, struct wl_shell_surface *shell_surface,
+                       uint32_t edges, int32_t width, int32_t height)
+{
+}
+
+static void
+window_handle_popup_done(void *data, struct wl_shell_surface *shell_surface)
+{
+}
+
+static const struct wl_shell_surface_listener window_shell_surface_listener = {
+       window_handle_ping,
+       window_handle_configure,
+       window_handle_popup_done,
+};
+
+static struct window *window_create(struct display *display)
+{
+       struct window *window;
+
+       window = calloc(1, sizeof *window);
+       if (!window)
+               error(1, errno, "cannot allocate window object");
+
+       window->callback = NULL;
+       window->display = display;
+       window->width = 250;
+       window->height = 250;
+
+       window->surface = wl_compositor_create_surface(display->compositor);
+       if (!window->surface)
+               error(1, errno, "cannot create window surface");
+
+       window->shell_surface = wl_shell_get_shell_surface(display->shell,
+                                                          window->surface);
+       if (!window->shell_surface)
+               error(1, errno, "cannot create window shell surface");
+
+       wl_shell_surface_add_listener(window->shell_surface,
+                                     &window_shell_surface_listener, window);
+       wl_shell_surface_set_title(window->shell_surface, "simple-dmabuf");
+       wl_shell_surface_set_toplevel(window->shell_surface);
+
+       rnode_window_create(window);
+
+       return window;
+}
+
+static void window_destroy(struct window *window)
+{
+       if (window->callback)
+               wl_callback_destroy(window->callback);
+
+       rnode_window_destroy(window);
+
+       wl_shell_surface_destroy(window->shell_surface);
+       wl_surface_destroy(window->surface);
+
+       free(window);
+}
+
+static void paint(int padding, int width, int height, uint32_t time)
+{
+       glClearColor(1, 0, 0, 1);
+       glClear(GL_COLOR_BUFFER_BIT);
+}
+
+static void
+window_redraw(void *data, struct wl_callback *callback, uint32_t time);
+
+static const struct wl_callback_listener window_frame_listener = {
+       window_redraw,
+};
+
+static void
+window_redraw(void *data, struct wl_callback *callback, uint32_t time)
+{
+       struct window *w = data;
+       struct buffer *buf;
+
+       paint(20, w->width, w->height, time);
+
+       buf = rnode_window_swap(w);
+
+       wl_surface_attach(w->surface, buf->buffer, 0, 0);
+       wl_surface_damage(w->surface, 20, 20,
+                         w->width - 40, w->height - 40);
+
+       if (callback)
+               wl_callback_destroy(callback);
+
+       w->callback = wl_surface_frame(w->surface);
+       if (!w->callback)
+               error(1, errno, "cannot create wayland frame callback");
+
+       wl_callback_add_listener(w->callback, &window_frame_listener, w);
+       wl_surface_commit(w->surface);
+}
+
+/*
+ * Display Handling
+ */
+
+static void
+display_shm_format(void *data, struct wl_shm *wl_shm, uint32_t format)
+{
+       struct display *d = data;
+
+       d->formats |= (1 << format);
+}
+
+struct wl_shm_listener display_shm_listener = {
+       display_shm_format,
+};
+
+static void
+display_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")) {
+               d->compositor = wl_registry_bind(registry, id,
+                                                &wl_compositor_interface, 1);
+       } else if (!strcmp(interface, "wl_shell")) {
+               d->shell = wl_registry_bind(registry, id,
+                                           &wl_shell_interface, 1);
+       } else if (!strcmp(interface, "wl_shm")) {
+               d->shm = wl_registry_bind(registry, id, &wl_shm_interface, 1);
+               if (d->shm)
+                       wl_shm_add_listener(d->shm, &display_shm_listener, d);
+       }
+}
+
+static void
+display_registry_handle_global_remove(void *data, struct wl_registry *registry,
+                                     uint32_t name)
+{
+}
+
+static const struct wl_registry_listener display_registry_listener = {
+       display_registry_handle_global,
+       display_registry_handle_global_remove,
+};
+
+static struct display *display_create(void)
+{
+       struct display *display;
+
+       display = calloc(1, sizeof(*display));
+       if (!display)
+               error(1, ENOMEM, "cannot allocate display");
+
+       display->display = wl_display_connect(NULL);
+       if (!display->display)
+               error(1, errno, "cannot connect to wayland server");
+
+       display->registry = wl_display_get_registry(display->display);
+       if (!display->registry)
+               error(1, errno, "cannot allocate wayland registry");
+
+       wl_registry_add_listener(display->registry,
+                                &display_registry_listener,
+                                display);
+
+       /* wait for globals */
+       wl_display_roundtrip(display->display);
+       if (!display->shm || !display->shell || !display->compositor)
+               error(1, 0, "wayland server does not support 
wl_shm/wl_shell/wl_compositor");
+
+       /* wait for wl_shm formats */
+       wl_display_roundtrip(display->display);
+       if (!(display->formats & (1 << WL_SHM_FORMAT_XRGB8888)))
+               error(1, 0, "wayland server does not support xrgb32");
+
+       rnode_init(display);
+
+       return display;
+}
+
+static void display_destroy(struct display *display)
+{
+       rnode_destroy(display);
+
+       wl_shm_destroy(display->shm);
+       wl_shell_destroy(display->shell);
+       wl_compositor_destroy(display->compositor);
+       wl_registry_destroy(display->registry);
+
+       wl_display_flush(display->display);
+       wl_display_disconnect(display->display);
+
+       free(display);
+}
+
+/*
+ * Main
+ */
+
+static int running = 1;
+
+static void
+signal_int(int signum)
+{
+       running = 0;
+}
+
+static void
+signal_setup(void)
+{
+       struct sigaction sigint;
+
+       sigint.sa_handler = signal_int;
+       sigemptyset(&sigint.sa_mask);
+       sigint.sa_flags = SA_RESETHAND;
+       sigaction(SIGINT, &sigint, NULL);
+       sigaction(SIGTERM, &sigint, NULL);
+       sigaction(SIGPIPE, &sigint, NULL);
+       sigaction(SIGHUP, &sigint, NULL);
+}
+
+int
+main(int argc, char **argv)
+{
+       struct display *display;
+       struct window *window;
+       int r;
+
+       fprintf(stderr, "initialize..\n");
+
+       signal_setup();
+       display = display_create();
+       window = window_create(display);
+
+       fprintf(stderr, "run..\n");
+
+       /* Initialise damage to full surface, so the padding gets painted */
+       wl_surface_damage(window->surface, 0, 0,
+                         window->width, window->height);
+
+       window_redraw(window, NULL, 0);
+
+       do {
+               r = wl_display_dispatch(display->display);
+       } while (running && r >= 0);
+
+       fprintf(stderr, "exit..\n");
+
+       window_destroy(window);
+       display_destroy(display);
+
+       return 0;
+}
diff --git a/configure.ac b/configure.ac
index 950086d..3d7b9f5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -282,7 +282,7 @@ AC_ARG_ENABLE(simple-egl-clients,
 AM_CONDITIONAL(BUILD_SIMPLE_EGL_CLIENTS, test "x$enable_simple_egl_clients" = 
"xyes")
 if test x$enable_simple_egl_clients = xyes; then
   PKG_CHECK_MODULES(SIMPLE_EGL_CLIENT,
-                    [egl >= 7.10 glesv2 wayland-client wayland-egl 
wayland-cursor])
+                    [egl >= 7.10 gbm libdrm glesv2 wayland-client wayland-egl 
wayland-cursor])
 fi
 
 AC_ARG_ENABLE(clients, [  --enable-clients],, enable_clients=yes)
-- 
1.8.4.1

_______________________________________________
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to