1From 3c1566e9c3b356cfcd8327fed0e537ed978c8e78 Mon Sep 17 00:00:00 2001
2From: Tomeu Vizoso <tomeu.vizoso@collabora.com>
3Date: Tue, 1 Oct 2013 13:19:20 +0200
4Subject: [PATCH] wayland: Add support for the Wayland winsys
5
6* Adds EGL_WL_bind_wayland_display extension
7* Adds wayland-egl library
8* Adds wl_dispmanx_buffer protocol extension
9
10TODO: Check that platform_get_dimensions() returning swapchain_count == 1 is correct
11
12TODO: Remove the requirement of passing a valid DispmanX element handle to
13the SwapBuffers and CreateSurface RPC calls. This will remove the need to open
14a DispmanX display from the clients.
15
16TODO: wl_dispmanx_server_buffer should probably be defined in a
17private header that can be included from EGL and vc_* instead of in
18vc_vchi_dispmanx.h
19
20Signed-off-by: Khem Raj <raj.khem@gmail.com>
21---
22Upstream-Status: Pending
23
24 .gitignore                                    |   1 +
25 CMakeLists.txt                                |  11 +
26 README.md                                     |   4 +
27 buildme                                       |  10 +-
28 .../linux/apps/raspicam/CMakeLists.txt        |   2 +-
29 interface/khronos/CMakeLists.txt              |  54 +++-
30 interface/khronos/common/khrn_client.c        |  15 ++
31 interface/khronos/common/khrn_client.h        |  10 +
32 interface/khronos/common/khrn_client_mangle.h |   3 +
33 .../khronos/common/khrn_client_platform.h     |   8 +
34 .../khronos/common/khrn_client_unmangle.h     |   3 +
35 .../common/linux/khrn_client_platform_linux.c | 115 +++++++-
36 interface/khronos/common/linux/khrn_wayland.c | 215 +++++++++++++++
37 .../common/linux/khrn_wayland.h}              |  46 +---
38 interface/khronos/egl/egl_client.c            |  92 +++++--
39 interface/khronos/egl/egl_client_get_proc.c   |  11 +
40 interface/khronos/egl/egl_client_surface.c    |  42 ++-
41 interface/khronos/egl/egl_client_surface.h    |  38 ++-
42 interface/khronos/egl/egl_int_impl.h          |   2 +-
43 interface/khronos/ext/egl_wayland.c           | 246 ++++++++++++++++++
44 interface/khronos/include/EGL/eglext.h        |  23 ++
45 .../khronos/wayland-egl/wayland-egl-priv.h    |  53 ++++
46 interface/khronos/wayland-egl/wayland-egl.c   |  59 +++++
47 .../khronos/wayland-egl/wayland-egl.pc.in     |  10 +
48 interface/vmcs_host/CMakeLists.txt            |  13 +-
49 interface/vmcs_host/vc_dispmanx.h             |  10 +
50 interface/vmcs_host/vc_vchi_dispmanx.c        |  42 +++
51 interface/vmcs_host/vc_vchi_dispmanx.h        |  15 ++
52 interface/wayland/dispmanx.xml                | 123 +++++++++
53 makefiles/cmake/Wayland.cmake                 |  72 +++++
54 30 files changed, 1253 insertions(+), 95 deletions(-)
55 create mode 100644 interface/khronos/common/linux/khrn_wayland.c
56 copy interface/{vmcs_host/vc_vchi_dispmanx.h => khronos/common/linux/khrn_wayland.h} (56%)
57 create mode 100644 interface/khronos/ext/egl_wayland.c
58 create mode 100644 interface/khronos/wayland-egl/wayland-egl-priv.h
59 create mode 100644 interface/khronos/wayland-egl/wayland-egl.c
60 create mode 100644 interface/khronos/wayland-egl/wayland-egl.pc.in
61 create mode 100644 interface/wayland/dispmanx.xml
62 create mode 100644 makefiles/cmake/Wayland.cmake
63
64diff --git a/.gitignore b/.gitignore
65index 63570f1..1459436 100644
66--- a/.gitignore
67+++ b/.gitignore
68@@ -30,3 +30,4 @@ build/
69 *.pts
70 *.ppm
71 *.mkv
72+*~
73diff --git a/CMakeLists.txt b/CMakeLists.txt
74index fe67fc8..80337b2 100644
75--- a/CMakeLists.txt
76+++ b/CMakeLists.txt
77@@ -24,6 +24,17 @@ include(makefiles/cmake/global_settings.cmake)
78 include(makefiles/cmake/arm-linux.cmake)
79 include(makefiles/cmake/vmcs.cmake)
80
81+if (BUILD_WAYLAND)
82+   include(makefiles/cmake/Wayland.cmake)
83+
84+   # Find Wayland libraries
85+   find_package(PkgConfig)
86+   pkg_check_modules(WAYLAND_CLIENT wayland-client REQUIRED)
87+   pkg_check_modules(WAYLAND_SERVER wayland-server REQUIRED)
88+
89+   set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DBUILD_WAYLAND")
90+endif()
91+
92 enable_language(ASM)
93
94 # Global include paths
95diff --git a/README.md b/README.md
96index 404e4d4..97a6b8f 100644
97--- a/README.md
98+++ b/README.md
99@@ -8,3 +8,7 @@ https://github.com/raspberrypi/tools/tree/master/arm-bcm2708/gcc-linaro-arm-linu
100 Whilst 64-bit userspace is not officially supported, some of the libraries will work for it. To cross compile, install gcc-aarch64-linux-gnu and g++-aarch64-linux-gnu first. For both native and cross compiles, add the option ```--aarch64``` to the buildme command.
101
102 Note that this repository does not contain the source for the edidparser and vcdbg binaries due to licensing restrictions.
103+
104+To build support for the Wayland winsys in EGL, execute the buildme script like this:
105+
106+$ BUILD_WAYLAND=1 ./buildme.
107diff --git a/buildme b/buildme
108index 9e2d405..7b8c0d6 100755
109--- a/buildme
110+++ b/buildme
111@@ -17,6 +17,10 @@ fi
112
113 BUILDSUBDIR=`echo $BUILDTYPE | tr '[A-Z]' '[a-z]'`;
114
115+if [ -n "$BUILD_WAYLAND" ]; then
116+       WAYLAND_VARS="-DBUILD_WAYLAND=TRUE"
117+fi
118+
119 if [ $ARCH = "armv6l" ] || [ $ARCH = "armv7l" ] || [ $ARCH = "aarch64" ]; then
120 	# Native compile on the Raspberry Pi
121 	mkdir -p build/raspberry/$BUILDSUBDIR
122@@ -41,9 +45,13 @@ elif [ "$1" = "--native" ]; then
123 	make -j `nproc` $*
124 else
125 	# Cross compile on a more capable machine
126+	if [ -n "$BUILD_WAYLAND" ]; then
127+		# Use wayland-scanner from the build platform
128+		WAYLAND_VARS+=" -DWAYLAND_SCANNER_EXECUTABLE:FILEPATH=/usr/bin/wayland-scanner"
129+	fi
130 	mkdir -p build/arm-linux/$BUILDSUBDIR
131 	pushd build/arm-linux/$BUILDSUBDIR
132-	cmake -DCMAKE_TOOLCHAIN_FILE=$CMAKE_TOOLCHAIN_FILE -DCMAKE_BUILD_TYPE=$BUILDTYPE -DARM64=$ARM64 ../../..
133+	cmake -DCMAKE_TOOLCHAIN_FILE=$CMAKE_TOOLCHAIN_FILE -DCMAKE_BUILD_TYPE=$BUILDTYPE -DARM64=$ARM64 $WAYLAND_VARS ../../..
134 	make -j `nproc`
135
136 	if [ "$1" != "" ]; then
137diff --git a/host_applications/linux/apps/raspicam/CMakeLists.txt b/host_applications/linux/apps/raspicam/CMakeLists.txt
138index eb1ef7c..5aeeb2e 100644
139--- a/host_applications/linux/apps/raspicam/CMakeLists.txt
140+++ b/host_applications/linux/apps/raspicam/CMakeLists.txt
141@@ -61,7 +61,7 @@ add_executable(raspivid   ${COMMON_SOURCES} RaspiVid.c)
142 add_executable(raspividyuv  ${COMMON_SOURCES} RaspiVidYUV.c)
143
144 set (MMAL_LIBS mmal_core mmal_util mmal_vc_client)
145-target_link_libraries(raspistill ${MMAL_LIBS} vcos bcm_host ${EGL_LIBS} m dl)
146+target_link_libraries(raspistill ${MMAL_LIBS} vcos bcm_host ${EGL_LIBS} m dl ${WAYLAND_SERVER_LIBRARIES} ${WAYLAND_CLIENT_LIBRARIES})
147 target_link_libraries(raspiyuv   ${MMAL_LIBS} vcos bcm_host m)
148 target_link_libraries(raspivid   ${MMAL_LIBS} vcos bcm_host m)
149 target_link_libraries(raspividyuv   ${MMAL_LIBS} vcos bcm_host m)
150diff --git a/interface/khronos/CMakeLists.txt b/interface/khronos/CMakeLists.txt
151index 9ad615b..95c0e11 100644
152--- a/interface/khronos/CMakeLists.txt
153+++ b/interface/khronos/CMakeLists.txt
154@@ -6,6 +6,12 @@
155 # have quite a few circular dependencies, and so the only way
156 # to make it work seems to be to have everything static.
157
158+if (BUILD_WAYLAND)
159+include_directories(
160+   ${WAYLAND_SERVER_INCLUDE_DIRS}
161+)
162+endif ()
163+
164 set(EGL_SOURCE
165    egl/egl_client_config.c
166    egl/egl_client_context.c
167@@ -55,12 +61,55 @@ set(CLIENT_SOURCE
168    common/khrn_int_hash_asm.s
169    common/khrn_client_cache.c)
170
171+set(EGL_LIBS
172+   khrn_client
173+   vchiq_arm
174+   vcos
175+   bcm_host)
176+
177+if (BUILD_WAYLAND)
178+   set(EGL_SOURCE
179+      ${EGL_SOURCE}
180+      ext/egl_wayland.c
181+      common/linux/khrn_wayland.c)
182+
183+   set(EGL_LIBS
184+      ${EGL_LIBS}
185+      wayland-client
186+      wayland-server)
187+
188+   set(WAYLAND_EGL_SOURCE
189+      wayland-egl/wayland-egl.c)
190+
191+   wayland_add_protocol_server(
192+       EGL_SOURCE
193+       ../../interface/wayland/dispmanx.xml
194+       dispmanx
195+   )
196+
197+   wayland_add_protocol_client(
198+       EGL_SOURCE
199+       ../../interface/wayland/dispmanx.xml
200+       dispmanx
201+   )
202+
203+   add_library(wayland-egl ${SHARED} ${WAYLAND_EGL_SOURCE})
204+   install(TARGETS wayland-egl DESTINATION lib)
205+
206+   configure_file ("wayland-egl/wayland-egl.pc.in" "wayland-egl/wayland-egl.pc" @ONLY)
207+   install (FILES "${CMAKE_CURRENT_BINARY_DIR}/wayland-egl/wayland-egl.pc"
208+            DESTINATION lib/pkgconfig)
209+endif ()
210+
211 add_library(EGL ${SHARED} ${EGL_SOURCE})
212 add_library(GLESv2 ${SHARED} ${GLES_SOURCE})
213 add_library(OpenVG ${SHARED} ${VG_SOURCE})
214 add_library(WFC ${SHARED} ${WFC_SOURCE})
215 add_library(khrn_client ${CLIENT_SOURCE})
216
217+set_target_properties(EGL PROPERTIES SOVERSION 1 VERSION 1.0.0)
218+set_target_properties(GLESv2 PROPERTIES SOVERSION 2 VERSION 2.0.0)
219+
220 # TODO do we need EGL_static and GLESv2_static now that khrn_static exists?
221 add_library(EGL_static STATIC ${EGL_SOURCE})
222 add_library(GLESv2_static STATIC ${GLES_SOURCE})
223@@ -72,8 +121,7 @@ include_directories (../../host_applications/linux/libs/sm )
224 set(VCSM_LIBS vcsm)
225 add_definitions(-DKHRONOS_HAVE_VCSM)
226 endif()
227-
228-target_link_libraries(EGL khrn_client vchiq_arm vcos bcm_host ${VCSM_LIBS} -lm)
229+target_link_libraries(EGL ${EGL_LIBS} ${VCSM_LIBS} -lm)
230 target_link_libraries(GLESv2 EGL khrn_client vcos)
231 target_link_libraries(WFC EGL)
232 target_link_libraries(OpenVG EGL)
233@@ -87,7 +135,7 @@ add_library(brcmGLESv2 ${SHARED} ${GLES_SOURCE})
234 add_library(brcmOpenVG ${SHARED} ${VG_SOURCE})
235 add_library(brcmWFC ${SHARED} ${WFC_SOURCE})
236
237-target_link_libraries(brcmEGL khrn_client vchiq_arm vcos bcm_host ${VCSM_LIBS} -lm)
238+target_link_libraries(brcmEGL ${EGL_LIBS} ${VCSM_LIBS} -lm)
239 target_link_libraries(brcmGLESv2 brcmEGL khrn_client vcos)
240 target_link_libraries(brcmWFC brcmEGL)
241 target_link_libraries(brcmOpenVG brcmEGL)
242diff --git a/interface/khronos/common/khrn_client.c b/interface/khronos/common/khrn_client.c
243index ef4babd..d7e798e 100644
244--- a/interface/khronos/common/khrn_client.c
245+++ b/interface/khronos/common/khrn_client.c
246@@ -54,6 +54,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
247 #include "applications/vmcs/khronos/khronos_server.h"
248 #endif
249
250+#ifdef BUILD_WAYLAND
251+#include "interface/khronos/common/linux/khrn_wayland.h"
252+#endif
253+
254 VCOS_LOG_CAT_T khrn_client_log = VCOS_LOG_INIT("khrn_client", VCOS_LOG_WARN);
255
256 /*
257@@ -142,6 +146,10 @@ void client_try_unload_server(CLIENT_PROCESS_STATE_T *process)
258 bool client_process_state_init(CLIENT_PROCESS_STATE_T *process)
259 {
260    if (!process->inited) {
261+#ifdef BUILD_WAYLAND
262+      process->wl_global = NULL;
263+#endif
264+
265       if (!khrn_pointer_map_init(&process->contexts, 64))
266          return false;
267
268@@ -194,6 +202,13 @@ bool client_process_state_init(CLIENT_PROCESS_STATE_T *process)
269       }
270 #endif
271
272+#ifdef BUILD_WAYLAND
273+      struct wl_display *wl_display = khrn_platform_get_wl_display();
274+      if (wl_display)
275+         if (!init_process_wayland(process))
276+            return false;
277+#endif
278+
279       process->inited = true;
280    }
281
282diff --git a/interface/khronos/common/khrn_client.h b/interface/khronos/common/khrn_client.h
283index 804039b..615f7b4 100644
284--- a/interface/khronos/common/khrn_client.h
285+++ b/interface/khronos/common/khrn_client.h
286@@ -310,6 +310,16 @@ struct CLIENT_PROCESS_STATE {
287 #ifdef RPC_LIBRARY
288    KHRONOS_SERVER_CONNECTION_T khrn_connection;
289 #endif
290+
291+#ifdef BUILD_WAYLAND
292+   /* Client-side Wayland state */
293+   struct wl_registry *wl_registry;
294+   struct wl_dispmanx *wl_dispmanx;
295+   struct wl_event_queue *wl_queue;
296+
297+   /* Compositor-side Wayland state */
298+   struct wl_global *wl_global;
299+#endif
300 };
301
302 extern bool client_process_state_init(CLIENT_PROCESS_STATE_T *process);
303diff --git a/interface/khronos/common/khrn_client_mangle.h b/interface/khronos/common/khrn_client_mangle.h
304index b3c04f4..b7b21c5 100644
305--- a/interface/khronos/common/khrn_client_mangle.h
306+++ b/interface/khronos/common/khrn_client_mangle.h
307@@ -83,6 +83,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
308 #define eglReleaseGlobalImageBRCM mangled_eglReleaseGlobalImageBRCM
309 #define eglInitGlobalImageBRCM mangled_eglInitGlobalImageBRCM
310 #define eglTermGlobalImageBRCM mangled_eglTermGlobalImageBRCM
311+#define eglBindWaylandDisplayWL mangled_eglBindWaylandDisplayWL
312+#define eglUnbindWaylandDisplayWL mangled_eglUnbindWaylandDisplayWL
313+#define eglQueryWaylandBufferWL mangled_eglQueryWaylandBufferWL
314
315 /* OpenGL ES 1.1 and 2.0 functions */
316
317diff --git a/interface/khronos/common/khrn_client_platform.h b/interface/khronos/common/khrn_client_platform.h
318index 1c9da3a..715c67e 100644
319--- a/interface/khronos/common/khrn_client_platform.h
320+++ b/interface/khronos/common/khrn_client_platform.h
321@@ -48,6 +48,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
322 #include "interface/khronos/common/vcos/khrn_client_platform_filler_vcos.h"
323 #endif
324
325+#ifdef BUILD_WAYLAND
326+#include <wayland-client.h>
327+#endif
328+
329 #ifdef __cplusplus
330 extern "C" {
331 #endif
332@@ -328,4 +332,8 @@ typedef struct
333
334 void *platform_wfc_bounce_thread(void *param);
335
336+#ifdef BUILD_WAYLAND
337+struct wl_display *khrn_platform_get_wl_display();
338+#endif
339+
340 #endif // KHRN_CLIENT_PLATFORM_H
341diff --git a/interface/khronos/common/khrn_client_unmangle.h b/interface/khronos/common/khrn_client_unmangle.h
342index 4f3ce49..84f6ec0 100644
343--- a/interface/khronos/common/khrn_client_unmangle.h
344+++ b/interface/khronos/common/khrn_client_unmangle.h
345@@ -83,6 +83,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
346 #undef eglReleaseGlobalImageBRCM
347 #undef eglInitGlobalImageBRCM
348 #undef eglTermGlobalImageBRCM
349+#undef eglBindWaylandDisplayWL
350+#undef eglUnbindWaylandDisplayWL
351+#undef eglQueryWaylandBufferWL
352
353 /* OpenGL ES 1.1 and 2.0 functions */
354
355diff --git a/interface/khronos/common/linux/khrn_client_platform_linux.c b/interface/khronos/common/linux/khrn_client_platform_linux.c
356index 710d20f..50d60a6 100644
357--- a/interface/khronos/common/linux/khrn_client_platform_linux.c
358+++ b/interface/khronos/common/linux/khrn_client_platform_linux.c
359@@ -37,6 +37,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
360 #include "X11/Xlib.h"
361 #endif
362
363+#ifdef BUILD_WAYLAND
364+#include <wayland-client.h>
365+#include "interface/khronos/wayland-egl/wayland-egl-priv.h"
366+#endif
367+
368 extern VCOS_LOG_CAT_T khrn_client_log;
369
370 extern void vc_vchi_khronos_init();
371@@ -464,13 +469,36 @@ EGLDisplay khrn_platform_set_display_id(EGLNativeDisplayType display_id)
372 	   return EGL_NO_DISPLAY;
373 }
374 #else
375+
376+#ifdef BUILD_WAYLAND
377+static struct wl_display *hacky_display = NULL;
378+#endif
379+
380 EGLDisplay khrn_platform_set_display_id(EGLNativeDisplayType display_id)
381 {
382    if (display_id == EGL_DEFAULT_DISPLAY)
383       return (EGLDisplay)1;
384-   else
385-      return EGL_NO_DISPLAY;
386+   else {
387+#ifdef BUILD_WAYLAND
388+      void *first_pointer = *(void **) display_id;
389+
390+      /* wl_display is a wl_proxy, which is a wl_object.
391+       * wl_object's first element points to the interfacetype. */
392+      if (first_pointer == &wl_display_interface) {
393+         hacky_display = (struct wl_display*)display_id;
394+         return (EGLDisplay)1;
395+      } else
396+#endif
397+         return EGL_NO_DISPLAY;
398+   }
399 }
400+
401+#ifdef BUILD_WAYLAND
402+struct wl_display *khrn_platform_get_wl_display()
403+{
404+   return hacky_display;
405+}
406+#endif
407 #endif
408
409 #ifdef WANT_X
410@@ -805,22 +833,81 @@ static EGL_DISPMANX_WINDOW_T *check_default(EGLNativeWindowType win)
411 void platform_get_dimensions(EGLDisplay dpy, EGLNativeWindowType win,
412       uint32_t *width, uint32_t *height, uint32_t *swapchain_count)
413 {
414-   EGL_DISPMANX_WINDOW_T *dwin = check_default(win);
415-   vcos_assert(dwin);
416-   vcos_assert(dwin->width < 1<<16); // sanity check
417-   vcos_assert(dwin->height < 1<<16); // sanity check
418-   *width = dwin->width;
419-   *height = dwin->height;
420-   *swapchain_count = 0;
421+#ifdef BUILD_WAYLAND
422+   if(khrn_platform_get_wl_display()) {
423+      struct wl_egl_window *wl_egl_window = (struct wl_egl_window*)win;
424+      *width = wl_egl_window->width;
425+      *height = wl_egl_window->height;
426+      /* This seems to be used for sync'ing with the VC on buffer creation, but
427+         we are managing them on the CPU side */
428+      *swapchain_count = 1;
429+   } else {
430+#endif
431+      EGL_DISPMANX_WINDOW_T *dwin = check_default(win);
432+      vcos_assert(dwin);
433+      vcos_assert(dwin->width < 1<<16); // sanity check
434+      vcos_assert(dwin->height < 1<<16); // sanity check
435+      *width = dwin->width;
436+      *height = dwin->height;
437+      *swapchain_count = 0;
438+#ifdef BUILD_WAYLAND
439+   }
440+#endif
441 }
442
443+#ifdef BUILD_WAYLAND
444+static DISPMANX_ELEMENT_HANDLE_T create_dummy_element()
445+{
446+   DISPMANX_DISPLAY_HANDLE_T display = vc_dispmanx_display_open(0);
447+   DISPMANX_UPDATE_HANDLE_T update = vc_dispmanx_update_start(0);
448+   DISPMANX_ELEMENT_HANDLE_T element;
449+   VC_DISPMANX_ALPHA_T alpha = {DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS, 255, 0};
450+   VC_RECT_T src_rect;
451+   VC_RECT_T dst_rect;
452+
453+   src_rect.x = 0;
454+   src_rect.y = 0;
455+   src_rect.width = 1 << 16;
456+   src_rect.height = 1 << 16;
457+
458+   dst_rect.x = 0;
459+   dst_rect.y = 0;
460+   dst_rect.width = 1;
461+   dst_rect.height = 1;
462+
463+   element = vc_dispmanx_element_add(update, display, 0/*layer*/, &dst_rect,
464+                                     0/*src*/, &src_rect,
465+                                     DISPMANX_PROTECTION_NONE, &alpha,
466+                                     0/*clamp*/, 0/*transform*/);
467+
468+   vc_dispmanx_update_submit_sync(update);
469+
470+   vc_dispmanx_display_close(display);
471+
472+   return element;
473+}
474+#endif
475+
476 uint32_t platform_get_handle(EGLDisplay dpy, EGLNativeWindowType win)
477 {
478-   EGL_DISPMANX_WINDOW_T *dwin = check_default(win);
479-   vcos_assert(dwin);
480-   vcos_assert(dwin->width < 1<<16); // sanity check
481-   vcos_assert(dwin->height < 1<<16); // sanity check
482-   return dwin->element;
483+#ifdef BUILD_WAYLAND
484+   if(khrn_platform_get_wl_display()) {
485+      struct wl_egl_window *wl_egl_window = (struct wl_egl_window*)win;
486+
487+      if (wl_egl_window->dummy_element == PLATFORM_WIN_NONE)
488+         wl_egl_window->dummy_element = create_dummy_element();
489+
490+      return wl_egl_window->dummy_element;
491+   } else {
492+#endif
493+      EGL_DISPMANX_WINDOW_T *dwin = check_default(win);
494+      vcos_assert(dwin);
495+      vcos_assert(dwin->width < 1<<16); // sanity check
496+      vcos_assert(dwin->height < 1<<16); // sanity check
497+      return dwin->element;
498+#ifdef BUILD_WAYLAND
499+   }
500+#endif
501 }
502
503 #endif
504diff --git a/interface/khronos/common/linux/khrn_wayland.c b/interface/khronos/common/linux/khrn_wayland.c
505new file mode 100644
506index 0000000..0e1b9e7
507--- /dev/null
508+++ b/interface/khronos/common/linux/khrn_wayland.c
509@@ -0,0 +1,215 @@
510+/*
511+Copyright (c) 2013, Raspberry Pi Foundation
512+All rights reserved.
513+
514+Redistribution and use in source and binary forms, with or without
515+modification, are permitted provided that the following conditions are met:
516+    * Redistributions of source code must retain the above copyright
517+      notice, this list of conditions and the following disclaimer.
518+    * Redistributions in binary form must reproduce the above copyright
519+      notice, this list of conditions and the following disclaimer in the
520+      documentation and/or other materials provided with the distribution.
521+    * Neither the name of the copyright holder nor the
522+      names of its contributors may be used to endorse or promote products
523+      derived from this software without specific prior written permission.
524+
525+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
526+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
527+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
528+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
529+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
530+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
531+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
532+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
533+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
534+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
535+*/
536+
537+#define VCOS_LOG_CATEGORY (&khrn_client_log)
538+
539+#include "interface/khronos/common/linux/khrn_wayland.h"
540+#include "interface/khronos/wayland-dispmanx-client-protocol.h"
541+#include "interface/khronos/wayland-egl/wayland-egl-priv.h"
542+
543+extern VCOS_LOG_CAT_T khrn_client_log;
544+
545+static void handle_dispmanx_format(void *data, struct wl_dispmanx *dispmanx,
546+                                   uint32_t format)
547+{
548+}
549+
550+static void handle_dispmanx_allocated(void *data, struct wl_dispmanx *dispmanx,
551+                                      struct wl_buffer *wl_buffer,
552+                                      uint32_t resource_handle)
553+{
554+    struct wl_dispmanx_client_buffer *buffer = wl_buffer_get_user_data(wl_buffer);
555+
556+    buffer->pending_allocation = 0;
557+    buffer->resource = resource_handle;
558+}
559+
560+static const struct wl_dispmanx_listener dispmanx_listener = {
561+    handle_dispmanx_format,
562+    handle_dispmanx_allocated,
563+};
564+
565+static void
566+sync_callback(void *data, struct wl_callback *callback, uint32_t serial)
567+{
568+   int *done = data;
569+
570+   *done = 1;
571+
572+   wl_callback_destroy(callback);
573+}
574+
575+static const struct wl_callback_listener sync_listener = {
576+   sync_callback
577+};
578+
579+static int
580+roundtrip(CLIENT_PROCESS_STATE_T *process)
581+{
582+   struct wl_display *wl_display = khrn_platform_get_wl_display();
583+   struct wl_callback *callback;
584+   int done = 0, ret = 0;
585+
586+   callback = wl_display_sync(wl_display);
587+   wl_callback_add_listener(callback, &sync_listener, &done);
588+   wl_proxy_set_queue((struct wl_proxy *) callback, process->wl_queue);
589+   while (ret != -1 && !done)
590+      ret = wl_display_dispatch_queue(wl_display, process->wl_queue);
591+
592+   if (!done)
593+      wl_callback_destroy(callback);
594+
595+   return ret;
596+}
597+
598+int do_wl_roundtrip()
599+{
600+   CLIENT_PROCESS_STATE_T *process = CLIENT_GET_PROCESS_STATE();
601+   return roundtrip(process);
602+}
603+
604+static void
605+registry_handle_global(void *data, struct wl_registry *registry,
606+                       uint32_t name, const char *interface, uint32_t version)
607+{
608+   struct wl_display *wl_display = khrn_platform_get_wl_display();
609+   CLIENT_PROCESS_STATE_T *process = (CLIENT_PROCESS_STATE_T *)data;
610+
611+   if (strcmp(interface, "wl_dispmanx") == 0) {
612+      process->wl_dispmanx = wl_registry_bind(registry, name,
613+	       &wl_dispmanx_interface, 1);
614+
615+      wl_proxy_set_queue((struct wl_proxy *) process->wl_dispmanx,
616+                         process->wl_queue);
617+      wl_dispmanx_add_listener(process->wl_dispmanx, &dispmanx_listener, wl_display);
618+      roundtrip(process);
619+   }
620+}
621+
622+static void
623+registry_handle_global_remove(void *data, struct wl_registry *registry,
624+                              uint32_t name)
625+{
626+}
627+
628+static const struct wl_registry_listener registry_listener = {
629+	registry_handle_global,
630+	registry_handle_global_remove
631+};
632+
633+int
634+init_process_wayland(CLIENT_PROCESS_STATE_T *process)
635+{
636+    struct wl_display *wl_display = khrn_platform_get_wl_display();
637+
638+    process->wl_queue = wl_display_create_queue(wl_display);
639+    if (!process->wl_queue) {
640+        vcos_log_error("wl_display_create_queue failed\n");
641+        return false;
642+    }
643+    wl_display_dispatch_pending(wl_display);
644+
645+    process->wl_registry = wl_display_get_registry(wl_display);
646+    if (!process->wl_registry) {
647+        vcos_log_error("wl_display_get_registry failed\n");
648+        return false;
649+    }
650+
651+    wl_proxy_set_queue((struct wl_proxy *) process->wl_registry,
652+    process->wl_queue);
653+
654+    wl_registry_add_listener(process->wl_registry, &registry_listener, process);
655+
656+    if (roundtrip(process) < 0 || process->wl_dispmanx == NULL) {
657+        vcos_log_error("failed to get wl_dispmanx\n");
658+        return false;
659+    }
660+
661+    return true;
662+}
663+
664+#ifndef ALIGN_UP
665+#define ALIGN_UP(x,y)  ((x + (y)-1) & ~((y)-1))
666+#endif
667+
668+static void handle_buffer_release(void *data, struct wl_buffer *buffer_wl)
669+{
670+   struct wl_dispmanx_client_buffer *wl_dispmanx_client_buffer = data;
671+   wl_dispmanx_client_buffer->in_use = 0;
672+}
673+
674+static const struct wl_buffer_listener buffer_listener = {
675+   handle_buffer_release
676+};
677+
678+struct wl_dispmanx_client_buffer *
679+allocate_wl_buffer(struct wl_egl_window *window, KHRN_IMAGE_FORMAT_T color)
680+{
681+   CLIENT_PROCESS_STATE_T *process = CLIENT_GET_PROCESS_STATE();
682+   struct wl_dispmanx_client_buffer *wl_dispmanx_client_buffer;
683+   struct wl_buffer *wl_buffer;
684+   uint32_t stride = ALIGN_UP(window->width * 4, 16);
685+   uint32_t buffer_height = ALIGN_UP(window->height, 16);
686+   enum wl_dispmanx_format color_format;
687+   int ret = 0;
688+
689+   switch (color) {
690+   case ABGR_8888:
691+      color_format = WL_DISPMANX_FORMAT_ABGR8888;
692+      break;
693+   case XBGR_8888:
694+      color_format = WL_DISPMANX_FORMAT_XBGR8888;
695+      break;
696+   case RGB_565:
697+      color_format = WL_DISPMANX_FORMAT_RGB565;
698+      break;
699+   default:
700+      vcos_log_error("unknown KHRN_IMAGE_FORMAT_T 0x%x\n", color);
701+      return NULL;
702+   }
703+
704+   wl_buffer = wl_dispmanx_create_buffer(process->wl_dispmanx, window->width,
705+                                         window->height, stride, buffer_height,
706+                                         color_format);
707+   if (wl_buffer == NULL)
708+      return NULL;
709+
710+   wl_dispmanx_client_buffer = calloc(1, sizeof(struct wl_dispmanx_client_buffer));
711+   wl_dispmanx_client_buffer->wl_buffer = wl_buffer;
712+   wl_dispmanx_client_buffer->in_use = 0;
713+   wl_dispmanx_client_buffer->pending_allocation = 1;
714+   wl_dispmanx_client_buffer->width = window->width;
715+   wl_dispmanx_client_buffer->height = window->height;
716+
717+   wl_proxy_set_queue((struct wl_proxy *) wl_buffer, process->wl_queue);
718+   wl_buffer_add_listener(wl_buffer, &buffer_listener, wl_dispmanx_client_buffer);
719+
720+   while (ret != -1 && wl_dispmanx_client_buffer->pending_allocation)
721+      ret = do_wl_roundtrip();
722+
723+   return wl_dispmanx_client_buffer;
724+}
725diff --git a/interface/vmcs_host/vc_vchi_dispmanx.h b/interface/khronos/common/linux/khrn_wayland.h
726similarity index 56%
727copy from interface/vmcs_host/vc_vchi_dispmanx.h
728copy to interface/khronos/common/linux/khrn_wayland.h
729index b723b76..b9bf08c 100644
730--- a/interface/vmcs_host/vc_vchi_dispmanx.h
731+++ b/interface/khronos/common/linux/khrn_wayland.h
732@@ -1,5 +1,5 @@
733 /*
734-Copyright (c) 2012, Broadcom Europe Ltd
735+Copyright (c) 2013, Raspberry Pi Foundation
736 All rights reserved.
737
738 Redistribution and use in source and binary forms, with or without
739@@ -25,45 +25,9 @@ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
740 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
741 */
742
743-#ifndef VC_VCHI_DISPMANX_H
744-#define VC_VCHI_DISPMANX_H
745+#include "interface/khronos/common/khrn_client.h"
746
747-#include "interface/peer/vc_vchi_dispmanx_common.h"
748+int init_process_wayland(CLIENT_PROCESS_STATE_T *process);
749+int do_wl_roundtrip();
750
751-#define VC_NUM_HOST_RESOURCES 64
752-#define DISPMANX_MSGFIFO_SIZE 1024
753-#define DISPMANX_CLIENT_NAME MAKE_FOURCC("DISP")
754-#define DISPMANX_NOTIFY_NAME MAKE_FOURCC("UPDH")
755-
756-//Or with command to indicate we don't need a response
757-#define DISPMANX_NO_REPLY_MASK (1<<31)
758-
759-typedef struct {
760-   char     description[32];
761-   uint32_t width;
762-   uint32_t height;
763-   uint32_t aspect_pixwidth;
764-   uint32_t aspect_pixheight;
765-   uint32_t fieldrate_num;
766-   uint32_t fieldrate_denom;
767-   uint32_t fields_per_frame;
768-   uint32_t transform;
769-} GET_MODES_DATA_T;
770-
771-typedef struct {
772-   int32_t  response;
773-   uint32_t width;
774-   uint32_t height;
775-   uint32_t transform;
776-   uint32_t input_format;
777-} GET_INFO_DATA_T;
778-
779-//Attributes changes flag mask
780-#define ELEMENT_CHANGE_LAYER          (1<<0)
781-#define ELEMENT_CHANGE_OPACITY        (1<<1)
782-#define ELEMENT_CHANGE_DEST_RECT      (1<<2)
783-#define ELEMENT_CHANGE_SRC_RECT       (1<<3)
784-#define ELEMENT_CHANGE_MASK_RESOURCE  (1<<4)
785-#define ELEMENT_CHANGE_TRANSFORM      (1<<5)
786-
787-#endif
788+struct wl_dispmanx_client_buffer *allocate_wl_buffer(struct wl_egl_window *window, KHRN_IMAGE_FORMAT_T color);
789diff --git a/interface/khronos/egl/egl_client.c b/interface/khronos/egl/egl_client.c
790index b8bb374..03fe67b 100644
791--- a/interface/khronos/egl/egl_client.c
792+++ b/interface/khronos/egl/egl_client.c
793@@ -153,6 +153,10 @@ by an attribute value"
794 #include <stdlib.h>
795 #include <string.h>
796
797+#ifdef BUILD_WAYLAND
798+#include "interface/khronos/wayland-egl/wayland-egl-priv.h"
799+#include "interface/khronos/common/linux/khrn_wayland.h"
800+#endif
801
802 #include "interface/khronos/egl/egl_client_cr.c"
803
804@@ -162,17 +166,6 @@ static void egl_current_release(CLIENT_PROCESS_STATE_T *process, EGL_CURRENT_T *
805 void egl_gl_flush_callback(bool wait);
806 void egl_vg_flush_callback(bool wait);
807
808-#include "interface/vmcs_host/vc_dispmanx_types.h"
809-/**HACKHACK - give us the ability to inject a DispmanX
810- * resource handle into the CreateWindowSurface and
811- * SwapBuffers calls */
812-static DISPMANX_RESOURCE_HANDLE_T next_resource_handle;
813-
814-EGLAPI EGLBoolean EGLAPIENTRY eglSetNextResourceHandle(DISPMANX_RESOURCE_HANDLE_T handle)
815-{
816-   next_resource_handle = handle;
817-}
818-
819 /*
820 TODO: do an RPC call to make sure the Khronos vll is loaded (and that it stays loaded until eglTerminate)
821 Also affects global image (and possibly others?)
822@@ -450,6 +443,9 @@ EGLAPI const char EGLAPIENTRY * eglQueryString(EGLDisplay dpy, EGLint name)
823 #ifdef EGL_KHR_fence_sync
824             "EGL_KHR_fence_sync "
825 #endif
826+#endif
827+#if EGL_WL_bind_wayland_display
828+            "EGL_WL_bind_wayland_display "
829 #endif
830             ;
831          break;
832@@ -655,8 +651,7 @@ EGLAPI EGLSurface EGLAPIENTRY eglCreateWindowSurface(EGLDisplay dpy, EGLConfig c
833                                 false,
834                                 EGL_NO_TEXTURE,
835                                 EGL_NO_TEXTURE,
836-                                0, 0,
837-                                next_resource_handle);
838+                                0, 0);
839
840                if (surface) {
841                   if (khrn_pointer_map_insert(&process->surfaces, process->next_surface, surface)) {
842@@ -901,7 +896,7 @@ EGLAPI EGLSurface EGLAPIENTRY eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig
843                              mipmap_texture,
844                              texture_format,
845                              texture_target,
846-                             0, 0, 0);
847+                             0, 0);
848
849             if (surface) {
850                if (khrn_pointer_map_insert(&process->surfaces, process->next_surface, surface)) {
851@@ -1043,7 +1038,7 @@ EGLAPI EGLSurface EGLAPIENTRY eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig c
852                                    false,
853                                    EGL_NO_TEXTURE,
854                                    EGL_NO_TEXTURE,
855-                                   pixmap, ((server_handle[0] == 0) && (server_handle[1] == (uint32_t)(-1))) ? NULL : server_handle, 0);
856+                                   pixmap, ((server_handle[0] == 0) && (server_handle[1] == (uint32_t)(-1))) ? NULL : server_handle);
857
858                      if (surface) {
859                         if (khrn_pointer_map_insert(&process->surfaces, process->next_surface, surface)) {
860@@ -2245,6 +2240,9 @@ EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffers(EGLDisplay dpy, EGLSurface surf)
861    CLIENT_THREAD_STATE_T *thread;
862    CLIENT_PROCESS_STATE_T *process;
863    EGLBoolean result;
864+#ifdef BUILD_WAYLAND
865+   struct wl_display *wl_display = khrn_platform_get_wl_display();
866+#endif
867
868    vcos_log_trace("eglSwapBuffers start. dpy=%d. surf=%d.", (int)dpy, (int)surf);
869
870@@ -2315,18 +2313,58 @@ EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffers(EGLDisplay dpy, EGLSurface surf)
871
872                vcos_log_trace("eglSwapBuffers server call");
873
874-               if (next_resource_handle)
875-               RPC_CALL7(eglIntSwapBuffers_impl,
876-                     thread,
877-                     EGLINTSWAPBUFFERS_ID_V2,
878-                     RPC_UINT(surface->serverbuffer),
879-                     RPC_UINT(surface->width),
880-                     RPC_UINT(surface->height),
881-                     RPC_UINT(surface->internal_handle),
882-                     RPC_UINT(surface->swap_behavior == EGL_BUFFER_PRESERVED ? 1 : 0),
883-                     RPC_UINT(khrn_platform_get_window_position(surface->win)),
884-                     RPC_INT(next_resource_handle));
885-               else
886+#ifdef BUILD_WAYLAND
887+               if (wl_display) {
888+                  struct wl_egl_window *wl_egl_window = surface->wl_egl_window;
889+                  struct wl_dispmanx_client_buffer *buffer_temp;
890+                  uint32_t configid;
891+                  KHRN_IMAGE_FORMAT_T color;
892+                  int ret = 0;
893+
894+                  buffer_temp = surface->front_wl_buffer;
895+                  surface->front_wl_buffer = surface->back_wl_buffer;
896+                  surface->back_wl_buffer = buffer_temp;
897+
898+                  configid = egl_config_to_id(surface->config);
899+                  color = egl_config_get_color_format(configid);
900+
901+                  if (surface->back_wl_buffer == NULL)
902+                     surface->back_wl_buffer = allocate_wl_buffer(wl_egl_window, color);
903+                  else if (surface->back_wl_buffer->width != width ||
904+                           surface->back_wl_buffer->height != height) {
905+
906+                     struct wl_dispmanx_client_buffer *buffer;
907+
908+                     wl_buffer_destroy(surface->back_wl_buffer->wl_buffer);
909+                     free(surface->back_wl_buffer);
910+
911+                     buffer = allocate_wl_buffer(wl_egl_window, color);
912+                     surface->back_wl_buffer = buffer;
913+                  }
914+
915+                  RPC_CALL7(eglIntSwapBuffers_impl,
916+                        thread,
917+                        EGLINTSWAPBUFFERS_ID_V2,
918+                        RPC_UINT(surface->serverbuffer),
919+                        RPC_UINT(surface->width),
920+                        RPC_UINT(surface->height),
921+                        RPC_UINT(surface->internal_handle),
922+                        RPC_UINT(surface->swap_behavior == EGL_BUFFER_PRESERVED ? 1 : 0),
923+                        RPC_UINT(khrn_platform_get_window_position(surface->win)),
924+                        RPC_INT(surface->back_wl_buffer->resource));
925+
926+                  surface->front_wl_buffer->in_use = 1;
927+                  wl_surface_attach(wl_egl_window->wl_surface,
928+                                    surface->front_wl_buffer->wl_buffer,
929+                                    0, 0);
930+                  wl_surface_damage(wl_egl_window->wl_surface, 0, 0,
931+                                    surface->width, surface->height);
932+                  wl_surface_commit(wl_egl_window->wl_surface);
933+
934+                  while(ret != -1 && surface->back_wl_buffer->in_use)
935+                     ret = wl_display_dispatch_queue(wl_display, process->wl_queue);
936+               } else
937+#endif
938                RPC_CALL6(eglIntSwapBuffers_impl,
939                      thread,
940                      EGLINTSWAPBUFFERS_ID,
941diff --git a/interface/khronos/egl/egl_client_get_proc.c b/interface/khronos/egl/egl_client_get_proc.c
942index 4cfa9ff..6a715af 100644
943--- a/interface/khronos/egl/egl_client_get_proc.c
944+++ b/interface/khronos/egl/egl_client_get_proc.c
945@@ -254,6 +254,17 @@ EGLAPI void EGLAPIENTRY (* eglGetProcAddress(const char *procname))(void)
946       return (void(*)(void))eglQueryGlobalImageBRCM;
947 #endif
948
949+#ifdef BUILD_WAYLAND
950+#if EGL_WL_bind_wayland_display
951+   if (!strcmp(procname, "eglBindWaylandDisplayWL"))
952+      return (void(*)(void))eglBindWaylandDisplayWL;
953+   if (!strcmp(procname, "eglUnbindWaylandDisplayWL"))
954+      return (void(*)(void))eglUnbindWaylandDisplayWL;
955+   if (!strcmp(procname, "eglQueryWaylandBufferWL"))
956+      return (void(*)(void))eglQueryWaylandBufferWL;
957+#endif
958+#endif
959+
960    return (void(*)(void)) NULL;
961 }
962
963diff --git a/interface/khronos/egl/egl_client_surface.c b/interface/khronos/egl/egl_client_surface.c
964index 128325e..42350bf 100644
965--- a/interface/khronos/egl/egl_client_surface.c
966+++ b/interface/khronos/egl/egl_client_surface.c
967@@ -46,6 +46,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
968 #include "interface/khronos/egl/egl_int_impl.h"
969 #endif
970
971+#ifdef BUILD_WAYLAND
972+#include "interface/khronos/wayland-egl/wayland-egl-priv.h"
973+#include "interface/khronos/common/linux/khrn_wayland.h"
974+#endif
975+
976 #include <stdlib.h>
977
978
979@@ -314,8 +319,7 @@ EGL_SURFACE_T *egl_surface_create(
980    EGLenum texture_format,
981    EGLenum texture_target,
982    EGLNativePixmapType pixmap,
983-   const uint32_t *pixmap_server_handle,
984-   DISPMANX_RESOURCE_HANDLE_T next_resource_handle)
985+   const uint32_t *pixmap_server_handle)
986 {
987    KHRN_IMAGE_FORMAT_T color;
988    KHRN_IMAGE_FORMAT_T depth;
989@@ -326,6 +330,10 @@ EGL_SURFACE_T *egl_surface_create(
990    EGLint   config_depth_bits;
991    EGLint   config_stencil_bits;
992    CLIENT_THREAD_STATE_T *thread = CLIENT_GET_THREAD_STATE();
993+#ifdef BUILD_WAYLAND
994+   struct wl_display *wl_display = khrn_platform_get_wl_display();
995+   DISPMANX_RESOURCE_HANDLE_T resource;
996+#endif
997
998    EGL_SURFACE_T *surface = egl_surface_pool_alloc();
999
1000@@ -390,6 +398,18 @@ EGL_SURFACE_T *egl_surface_create(
1001
1002    vcos_assert(color != IMAGE_FORMAT_INVALID);
1003
1004+#ifdef BUILD_WAYLAND
1005+   if (type == WINDOW && wl_display) {
1006+      surface->wl_egl_window = (struct wl_egl_window*)win;
1007+      surface->back_wl_buffer = allocate_wl_buffer(
1008+            surface->wl_egl_window, color);
1009+      resource = surface->back_wl_buffer->resource;
1010+   } else {
1011+      surface->wl_egl_window = NULL;
1012+      resource = DISPMANX_NO_HANDLE;
1013+   }
1014+#endif
1015+
1016 #ifdef KHRONOS_EGL_PLATFORM_OPENWFC
1017    // Create stream for this window
1018    if(type != PBUFFER)
1019@@ -474,7 +494,8 @@ EGL_SURFACE_T *egl_surface_create(
1020 #endif
1021          uint32_t results[3];
1022
1023-         if (next_resource_handle)
1024+#ifdef BUILD_WAYLAND
1025+         if (resource != DISPMANX_NO_HANDLE)
1026          RPC_CALL16_OUT_CTRL(eglIntCreateSurface_impl,
1027                              thread,
1028                              EGLINTCREATESURFACE_ID_V2,
1029@@ -492,9 +513,10 @@ EGL_SURFACE_T *egl_surface_create(
1030                              RPC_UINT(config_stencil_bits),
1031                              RPC_UINT(sem_name),
1032                              RPC_UINT(type),
1033-                             RPC_INT(next_resource_handle),
1034+                             RPC_INT(resource),
1035                              results);
1036          else
1037+#endif
1038          RPC_CALL15_OUT_CTRL(eglIntCreateSurface_impl,
1039                              thread,
1040                              EGLINTCREATESURFACE_ID,
1041@@ -663,6 +685,18 @@ void egl_surface_free(EGL_SURFACE_T *surface)
1042    if( surface->type == WINDOW ) {
1043       vcos_log_trace("egl_surface_free: calling platform_destroy_winhandle...");
1044       platform_destroy_winhandle( surface->win, surface->internal_handle );
1045+
1046+#ifdef BUILD_WAYLAND
1047+      if (surface->back_wl_buffer) {
1048+         wl_buffer_destroy(surface->back_wl_buffer->wl_buffer);
1049+         free(surface->back_wl_buffer);
1050+      }
1051+
1052+      if (surface->front_wl_buffer) {
1053+         wl_buffer_destroy(surface->front_wl_buffer->wl_buffer);
1054+         free(surface->front_wl_buffer);
1055+      }
1056+#endif
1057    }
1058    /* return value ignored -- read performed to ensure blocking. we want this to
1059     * block so clients can safely destroy the surface's window as soon as the
1060diff --git a/interface/khronos/egl/egl_client_surface.h b/interface/khronos/egl/egl_client_surface.h
1061index b5bf70a..e328b77 100644
1062--- a/interface/khronos/egl/egl_client_surface.h
1063+++ b/interface/khronos/egl/egl_client_surface.h
1064@@ -288,6 +288,41 @@ typedef struct {
1065       type == PIXMAP
1066    */
1067    bool server_owned;
1068+
1069+#ifdef BUILD_WAYLAND
1070+   /*
1071+      wl_egl_window
1072+
1073+      Validity:
1074+      type == WINDOW
1075+
1076+      Invariant:
1077+      wayland EGL window
1078+   */
1079+   struct wl_egl_window *wl_egl_window;
1080+
1081+   /*
1082+      front_wl_buffer
1083+
1084+      Validity:
1085+      type == WINDOW
1086+
1087+      Invariant:
1088+      client-side information about the wl_buffer in the front
1089+   */
1090+   struct wl_dispmanx_client_buffer *front_wl_buffer;
1091+
1092+   /*
1093+      back_wl_buffer
1094+
1095+      Validity:
1096+      type == WINDOW
1097+
1098+      Invariant:
1099+      client-side information about the wl_buffer in the back
1100+   */
1101+   struct wl_dispmanx_client_buffer *back_wl_buffer;
1102+#endif
1103 } EGL_SURFACE_T;
1104
1105 extern bool egl_surface_check_attribs(
1106@@ -322,8 +357,7 @@ extern EGL_SURFACE_T *egl_surface_create(
1107    EGLenum texture_format,
1108    EGLenum texture_target,
1109    EGLNativePixmapType pixmap,
1110-   const uint32_t *pixmap_server_handle,
1111-   DISPMANX_RESOURCE_HANDLE_T next_resource_handle);
1112+   const uint32_t *pixmap_server_handle);
1113 extern EGL_SURFACE_T *egl_surface_from_vg_image(
1114    VGImage vg_handle,
1115    EGLSurface name,
1116diff --git a/interface/khronos/egl/egl_int_impl.h b/interface/khronos/egl/egl_int_impl.h
1117index 51b3580..6863a3b 100644
1118--- a/interface/khronos/egl/egl_int_impl.h
1119+++ b/interface/khronos/egl/egl_int_impl.h
1120@@ -57,7 +57,7 @@ FN(int, eglIntCreateSurface_impl, (
1121    uint32_t sem,
1122    uint32_t type,
1123    uint32_t *results,
1124-   DISPMANX_RESOURCE_HANDLE_T next_resource_handle))
1125+   DISPMANX_RESOURCE_HANDLE_T resource_handle))
1126
1127 FN(int, eglIntCreatePbufferFromVGImage_impl, (
1128    VGImage vg_handle,
1129diff --git a/interface/khronos/ext/egl_wayland.c b/interface/khronos/ext/egl_wayland.c
1130new file mode 100644
1131index 0000000..5730743
1132--- /dev/null
1133+++ b/interface/khronos/ext/egl_wayland.c
1134@@ -0,0 +1,246 @@
1135+/*
1136+Copyright (c) 2013, Raspberry Pi Foundation
1137+All rights reserved.
1138+
1139+Redistribution and use in source and binary forms, with or without
1140+modification, are permitted provided that the following conditions are met:
1141+    * Redistributions of source code must retain the above copyright
1142+      notice, this list of conditions and the following disclaimer.
1143+    * Redistributions in binary form must reproduce the above copyright
1144+      notice, this list of conditions and the following disclaimer in the
1145+      documentation and/or other materials provided with the distribution.
1146+    * Neither the name of the copyright holder nor the
1147+      names of its contributors may be used to endorse or promote products
1148+      derived from this software without specific prior written permission.
1149+
1150+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
1151+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
1152+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
1153+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
1154+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
1155+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
1156+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
1157+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1158+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
1159+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1160+*/
1161+
1162+#include "interface/khronos/common/khrn_client_mangle.h"
1163+#include "interface/khronos/common/khrn_client_rpc.h"
1164+
1165+#include "interface/khronos/ext/egl_khr_sync_client.h"
1166+#include "interface/khronos/include/EGL/egl.h"
1167+#include "interface/khronos/include/EGL/eglext.h"
1168+
1169+#include "interface/vmcs_host/vc_vchi_dispmanx.h"
1170+
1171+#include <wayland-server.h>
1172+#include "interface/khronos/wayland-dispmanx-server-protocol.h"
1173+
1174+static void
1175+destroy_buffer(struct wl_resource *resource)
1176+{
1177+   struct wl_dispmanx_server_buffer *buffer = wl_resource_get_user_data(resource);
1178+
1179+   if(!buffer->in_use)
1180+      vc_dispmanx_resource_delete(buffer->handle);
1181+
1182+   free(buffer);
1183+}
1184+
1185+static void
1186+buffer_destroy(struct wl_client *client, struct wl_resource *resource)
1187+{
1188+   wl_resource_destroy(resource);
1189+}
1190+
1191+static const struct wl_buffer_interface dispmanx_buffer_interface = {
1192+   buffer_destroy
1193+};
1194+
1195+static VC_IMAGE_TYPE_T
1196+get_vc_format(enum wl_dispmanx_format format)
1197+{
1198+	/* XXX: The app is likely to have been premultiplying in its shaders,
1199+	 * but the VC scanout hardware on the RPi cannot mix premultiplied alpha
1200+	 * channel with the element's alpha.
1201+	 */
1202+	switch (format) {
1203+	case WL_DISPMANX_FORMAT_ABGR8888:
1204+		return VC_IMAGE_RGBA32;
1205+	case WL_DISPMANX_FORMAT_XBGR8888:
1206+		return VC_IMAGE_BGRX8888;
1207+	case WL_DISPMANX_FORMAT_RGB565:
1208+		return VC_IMAGE_RGB565;
1209+	default:
1210+		/* invalid format */
1211+		return VC_IMAGE_MIN;
1212+	}
1213+}
1214+
1215+static void
1216+dispmanx_create_buffer(struct wl_client *client, struct wl_resource *resource,
1217+                       uint32_t id, int32_t width, int32_t height,
1218+                       uint32_t stride, uint32_t buffer_height, uint32_t format)
1219+{
1220+   struct wl_dispmanx_server_buffer *buffer;
1221+   VC_IMAGE_TYPE_T vc_format = get_vc_format(format);
1222+   uint32_t dummy;
1223+
1224+   if(vc_format == VC_IMAGE_MIN) {
1225+      wl_resource_post_error(resource,
1226+                             WL_DISPMANX_ERROR_INVALID_FORMAT,
1227+                             "invalid format");
1228+      return;
1229+   }
1230+
1231+   buffer = calloc(1, sizeof *buffer);
1232+   if (buffer == NULL) {
1233+      wl_resource_post_no_memory(resource);
1234+      return;
1235+   }
1236+
1237+   buffer->handle = vc_dispmanx_resource_create(vc_format,
1238+                                                width | (stride << 16),
1239+                                                height | (buffer_height << 16),
1240+                                                &dummy);
1241+   if(buffer->handle == DISPMANX_NO_HANDLE) {
1242+      wl_resource_post_error(resource,
1243+                             WL_DISPMANX_ERROR_ALLOC_FAILED,
1244+                             "allocation failed");
1245+      free(buffer);
1246+      return;
1247+   }
1248+
1249+   buffer->width = width;
1250+   buffer->height = height;
1251+   buffer->format = format;
1252+
1253+   buffer->resource = wl_resource_create(resource->client, &wl_buffer_interface,
1254+                                         1, id);
1255+   if (!buffer->resource) {
1256+      wl_resource_post_no_memory(resource);
1257+      vc_dispmanx_resource_delete(buffer->handle);
1258+      free(buffer);
1259+      return;
1260+   }
1261+
1262+   wl_resource_set_implementation(buffer->resource,
1263+				       (void (**)(void)) &dispmanx_buffer_interface,
1264+				       buffer, destroy_buffer);
1265+
1266+   wl_dispmanx_send_buffer_allocated(resource, buffer->resource,
1267+                                     buffer->handle);
1268+}
1269+
1270+static const struct wl_dispmanx_interface dispmanx_interface = {
1271+   dispmanx_create_buffer,
1272+};
1273+
1274+static void
1275+bind_dispmanx(struct wl_client *client, void *data, uint32_t version, uint32_t id)
1276+{
1277+   struct wl_resource *resource;
1278+
1279+   resource = wl_resource_create(client, &wl_dispmanx_interface, 1, id);
1280+   wl_resource_set_implementation(resource, &dispmanx_interface, NULL, NULL);
1281+
1282+   wl_resource_post_event(resource, WL_DISPMANX_FORMAT,
1283+                          WL_DISPMANX_FORMAT_ARGB8888);
1284+
1285+   wl_resource_post_event(resource, WL_DISPMANX_FORMAT,
1286+                          WL_DISPMANX_FORMAT_XRGB8888);
1287+
1288+   wl_resource_post_event(resource, WL_DISPMANX_FORMAT,
1289+                          WL_DISPMANX_FORMAT_ABGR8888);
1290+
1291+   wl_resource_post_event(resource, WL_DISPMANX_FORMAT,
1292+                          WL_DISPMANX_FORMAT_XBGR8888);
1293+
1294+   wl_resource_post_event(resource, WL_DISPMANX_FORMAT,
1295+                          WL_DISPMANX_FORMAT_RGB565);
1296+}
1297+
1298+EGLBoolean EGLAPIENTRY
1299+eglBindWaylandDisplayWL(EGLDisplay dpy, struct wl_display *display)
1300+{
1301+   CLIENT_THREAD_STATE_T *thread;
1302+   CLIENT_PROCESS_STATE_T *process;
1303+
1304+   if (!CLIENT_LOCK_AND_GET_STATES(dpy, &thread, &process))
1305+      return EGL_FALSE;
1306+
1307+   if (process->wl_global != NULL)
1308+      goto error;
1309+
1310+   process->wl_global = wl_global_create(display, &wl_dispmanx_interface, 1,
1311+                                         NULL, bind_dispmanx);
1312+   if (process->wl_global == NULL)
1313+      goto error;
1314+
1315+   return EGL_TRUE;
1316+
1317+error:
1318+   CLIENT_UNLOCK();
1319+   return EGL_FALSE;
1320+}
1321+
1322+EGLBoolean EGLAPIENTRY
1323+eglUnbindWaylandDisplayWL(EGLDisplay dpy, struct wl_display *display)
1324+{
1325+   CLIENT_THREAD_STATE_T *thread;
1326+   CLIENT_PROCESS_STATE_T *process;
1327+
1328+   if (!CLIENT_LOCK_AND_GET_STATES(dpy, &thread, &process))
1329+      return EGL_FALSE;
1330+
1331+   wl_global_destroy(process->wl_global);
1332+   process->wl_global = NULL;
1333+
1334+   CLIENT_UNLOCK();
1335+
1336+   return EGL_TRUE;
1337+}
1338+
1339+static int
1340+get_egl_format(enum wl_dispmanx_format format)
1341+{
1342+	switch (format) {
1343+	case WL_DISPMANX_FORMAT_ABGR8888:
1344+		return EGL_TEXTURE_RGBA;
1345+	case WL_DISPMANX_FORMAT_XBGR8888:
1346+		return EGL_TEXTURE_RGB;
1347+	case WL_DISPMANX_FORMAT_RGB565:
1348+		return EGL_TEXTURE_RGB;
1349+	default:
1350+		/* invalid format */
1351+		return EGL_NO_TEXTURE;
1352+	}
1353+}
1354+
1355+EGLBoolean EGLAPIENTRY
1356+eglQueryWaylandBufferWL(EGLDisplay dpy, struct wl_resource *_buffer,
1357+         EGLint attribute, EGLint *value)
1358+{
1359+   struct wl_dispmanx_server_buffer *buffer = wl_resource_get_user_data(_buffer);
1360+
1361+   if (wl_resource_instance_of(_buffer, &wl_dispmanx_interface,
1362+                               &dispmanx_buffer_interface))
1363+      return EGL_FALSE;
1364+
1365+   switch (attribute) {
1366+   case EGL_TEXTURE_FORMAT:
1367+      *value = get_egl_format(buffer->format);
1368+      if (*value == EGL_NO_TEXTURE)
1369+         return EGL_FALSE;
1370+      return EGL_TRUE;
1371+   case EGL_WIDTH:
1372+      *value = buffer->width;
1373+      return EGL_TRUE;
1374+   case EGL_HEIGHT:
1375+      *value = buffer->height;
1376+      return EGL_TRUE;
1377+   }
1378+
1379+   return EGL_FALSE;
1380+}
1381diff --git a/interface/khronos/include/EGL/eglext.h b/interface/khronos/include/EGL/eglext.h
1382index 89a3369..d7e5ba7 100755
1383--- a/interface/khronos/include/EGL/eglext.h
1384+++ b/interface/khronos/include/EGL/eglext.h
1385@@ -191,6 +191,29 @@ typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETSYNCATTRIBKHRPROC) (EGLDisplay dpy, EG
1386 #endif
1387
1388
1389+#ifndef EGL_WL_bind_wayland_display
1390+#define EGL_WL_bind_wayland_display 1
1391+
1392+#define EGL_WAYLAND_BUFFER_WL		0x31D5 /* eglCreateImageKHR target */
1393+#define EGL_WAYLAND_PLANE_WL		0x31D6 /* eglCreateImageKHR target */
1394+#define EGL_TEXTURE_Y_U_V_WL            0x31D7
1395+#define EGL_TEXTURE_Y_UV_WL             0x31D8
1396+#define EGL_TEXTURE_Y_XUXV_WL           0x31D9
1397+
1398+struct wl_display;
1399+struct wl_resource;
1400+#ifdef EGL_EGLEXT_PROTOTYPES
1401+EGLAPI EGLBoolean EGLAPIENTRY eglBindWaylandDisplayWL(EGLDisplay dpy, struct wl_display *display);
1402+EGLAPI EGLBoolean EGLAPIENTRY eglUnbindWaylandDisplayWL(EGLDisplay dpy, struct wl_display *display);
1403+EGLAPI EGLBoolean EGLAPIENTRY eglQueryWaylandBufferWL(EGLDisplay dpy, struct wl_resource *buffer, EGLint attribute, EGLint *value);
1404+#endif
1405+typedef EGLBoolean (EGLAPIENTRYP PFNEGLBINDWAYLANDDISPLAYWL) (EGLDisplay dpy, struct wl_display *display);
1406+typedef EGLBoolean (EGLAPIENTRYP PFNEGLUNBINDWAYLANDDISPLAYWL) (EGLDisplay dpy, struct wl_display *display);
1407+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYWAYLANDBUFFERWL) (EGLDisplay dpy, struct wl_resource *buffer, EGLint attribute, EGLint *value);
1408+
1409+#endif
1410+
1411+
1412 #ifdef __cplusplus
1413 }
1414 #endif
1415diff --git a/interface/khronos/wayland-egl/wayland-egl-priv.h b/interface/khronos/wayland-egl/wayland-egl-priv.h
1416new file mode 100644
1417index 0000000..8e38d36
1418--- /dev/null
1419+++ b/interface/khronos/wayland-egl/wayland-egl-priv.h
1420@@ -0,0 +1,53 @@
1421+/* Copied from Mesa */
1422+
1423+#ifndef _WAYLAND_EGL_PRIV_H
1424+#define _WAYLAND_EGL_PRIV_H
1425+
1426+#ifdef  __cplusplus
1427+extern "C" {
1428+#endif
1429+
1430+/* GCC visibility */
1431+#if defined(__GNUC__) && __GNUC__ >= 4
1432+#define WL_EGL_EXPORT __attribute__ ((visibility("default")))
1433+#else
1434+#define WL_EGL_EXPORT
1435+#endif
1436+
1437+#include "interface/vmcs_host/vc_dispmanx.h"
1438+#include "interface/khronos/egl/egl_client_surface.h"
1439+
1440+#include <wayland-client.h>
1441+
1442+struct wl_dispmanx_client_buffer {
1443+	struct wl_buffer *wl_buffer;
1444+	DISPMANX_RESOURCE_HANDLE_T resource;
1445+
1446+	int pending_allocation;
1447+	int in_use;
1448+	int width;
1449+	int height;
1450+};
1451+
1452+struct wl_egl_window {
1453+	struct wl_surface *wl_surface;
1454+
1455+	int width;
1456+	int height;
1457+	int dx;
1458+	int dy;
1459+
1460+	int attached_width;
1461+	int attached_height;
1462+
1463+	/* XXX: The VC side seems to expect a valid element handle to be
1464+	   passed to eglIntCreateSurface_impl and/or eglIntSwapBuffers_impl,
1465+	   even for host-managed surfaces. */
1466+	DISPMANX_ELEMENT_HANDLE_T dummy_element;
1467+};
1468+
1469+#ifdef  __cplusplus
1470+}
1471+#endif
1472+
1473+#endif
1474diff --git a/interface/khronos/wayland-egl/wayland-egl.c b/interface/khronos/wayland-egl/wayland-egl.c
1475new file mode 100644
1476index 0000000..b8f050b
1477--- /dev/null
1478+++ b/interface/khronos/wayland-egl/wayland-egl.c
1479@@ -0,0 +1,59 @@
1480+/* Copied from Mesa */
1481+
1482+#include <stdlib.h>
1483+
1484+#include <wayland-client.h>
1485+#include <wayland-egl.h>
1486+#include "wayland-egl-priv.h"
1487+
1488+WL_EGL_EXPORT void
1489+wl_egl_window_resize(struct wl_egl_window *egl_window,
1490+		     int width, int height,
1491+		     int dx, int dy)
1492+{
1493+        if (egl_window->width == width &&
1494+	    egl_window->height == height &&
1495+	    egl_window->dx == dx &&
1496+	    egl_window->dy == dy)
1497+		return;
1498+
1499+	egl_window->width = width;
1500+	egl_window->height = height;
1501+	egl_window->dx = dx;
1502+	egl_window->dy = dy;
1503+}
1504+
1505+WL_EGL_EXPORT struct wl_egl_window *
1506+wl_egl_window_create(struct wl_surface *surface,
1507+		     int width, int height)
1508+{
1509+	struct wl_egl_window *egl_window;
1510+
1511+	egl_window = calloc(1, sizeof *egl_window);
1512+	if (!egl_window)
1513+		return NULL;
1514+
1515+	egl_window->wl_surface = surface;
1516+	wl_egl_window_resize(egl_window, width, height, 0, 0);
1517+	egl_window->attached_width  = 0;
1518+	egl_window->attached_height = 0;
1519+	egl_window->dummy_element = PLATFORM_WIN_NONE;
1520+
1521+	return egl_window;
1522+}
1523+
1524+WL_EGL_EXPORT void
1525+wl_egl_window_destroy(struct wl_egl_window *egl_window)
1526+{
1527+	free(egl_window);
1528+}
1529+
1530+WL_EGL_EXPORT void
1531+wl_egl_window_get_attached_size(struct wl_egl_window *egl_window,
1532+				int *width, int *height)
1533+{
1534+	if (width)
1535+		*width = egl_window->attached_width;
1536+	if (height)
1537+		*height = egl_window->attached_height;
1538+}
1539diff --git a/interface/khronos/wayland-egl/wayland-egl.pc.in b/interface/khronos/wayland-egl/wayland-egl.pc.in
1540new file mode 100644
1541index 0000000..8bafc15
1542--- /dev/null
1543+++ b/interface/khronos/wayland-egl/wayland-egl.pc.in
1544@@ -0,0 +1,10 @@
1545+prefix=@CMAKE_INSTALL_PREFIX@
1546+exec_prefix=${prefix}
1547+libdir=${exec_prefix}/lib
1548+includedir=${prefix}/include
1549+
1550+Name: wayland-egl
1551+Description: VideoCore wayland-egl library
1552+Version: @PROJECT_APIVER@
1553+Libs: -L${libdir} -lwayland-egl
1554+Cflags: -I${includedir}
1555diff --git a/interface/vmcs_host/CMakeLists.txt b/interface/vmcs_host/CMakeLists.txt
1556index cbef80c..552312a 100755
1557--- a/interface/vmcs_host/CMakeLists.txt
1558+++ b/interface/vmcs_host/CMakeLists.txt
1559@@ -7,13 +7,24 @@
1560 # vc_vchi_gencmd.c has a type-punning problem in vc_gencmd_read_response
1561 add_definitions(-fno-strict-aliasing)
1562
1563-add_library(vchostif
1564+set(VCHOSTIF_SOURCE
1565             ${VMCS_TARGET}/vcmisc.c
1566             vc_vchi_gencmd.c vc_vchi_gpuserv.c
1567             vc_vchi_tvservice.c vc_vchi_cecservice.c
1568             vc_vchi_dispmanx.c vc_service_common.c)
1569 #            ${VMCS_TARGET}/vmcs_main.c
1570 #  vc_vchi_haud.c
1571+
1572+if (BUILD_WAYLAND)
1573+wayland_add_protocol_server(
1574+    VCHOSTIF_SOURCE
1575+    ../../interface/wayland/dispmanx.xml
1576+    dispmanx
1577+)
1578+endif ()
1579+
1580+add_library(vchostif ${VCHOSTIF_SOURCE})
1581+
1582 #add_library(bufman            vc_vchi_bufman.c            )
1583 set(INSTALL_TARGETS vchostif)
1584
1585diff --git a/interface/vmcs_host/vc_dispmanx.h b/interface/vmcs_host/vc_dispmanx.h
1586index 37fdae1..fe3619a 100755
1587--- a/interface/vmcs_host/vc_dispmanx.h
1588+++ b/interface/vmcs_host/vc_dispmanx.h
1589@@ -39,6 +39,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1590 #ifdef __cplusplus
1591 extern "C" {
1592 #endif
1593+
1594+#ifdef BUILD_WAYLAND
1595+struct wl_resource;
1596+#endif
1597+
1598 // Same function as above, to aid migration of code.
1599 VCHPRE_ int VCHPOST_ vc_dispman_init( void );
1600 // Stop the service from being used
1601@@ -135,6 +140,11 @@ VCHPRE_ int VCHPOST_ vc_dispmanx_resource_set_palette( DISPMANX_RESOURCE_HANDLE_
1602 // Start triggering callbacks synced to vsync
1603 VCHPRE_ int VCHPOST_ vc_dispmanx_vsync_callback( DISPMANX_DISPLAY_HANDLE_T display, DISPMANX_CALLBACK_FUNC_T cb_func, void *cb_arg );
1604
1605+#ifdef BUILD_WAYLAND
1606+VCHPRE_ DISPMANX_RESOURCE_HANDLE_T VCHPOST_ vc_dispmanx_get_handle_from_wl_buffer( struct wl_resource *_buffer );
1607+
1608+VCHPRE_ void VCHPOST_ vc_dispmanx_set_wl_buffer_in_use( struct wl_resource *_buffer, int in_use );
1609+#endif
1610 #ifdef __cplusplus
1611 }
1612 #endif
1613diff --git a/interface/vmcs_host/vc_vchi_dispmanx.c b/interface/vmcs_host/vc_vchi_dispmanx.c
1614index 7a6cdcd..eab146e 100755
1615--- a/interface/vmcs_host/vc_vchi_dispmanx.c
1616+++ b/interface/vmcs_host/vc_vchi_dispmanx.c
1617@@ -1319,3 +1319,45 @@ static void *dispmanx_notify_func( void *arg ) {
1618    }
1619    return 0;
1620 }
1621+
1622+
1623+#ifdef BUILD_WAYLAND
1624+/***********************************************************
1625+ * Name: vc_dispmanx_get_handle_from_wl_buffer
1626+ *
1627+ * Arguments:
1628+ *       struct wl_resource *_buffer
1629+ *
1630+ * Description: Return the handle of the resource associated to this Wayland buffer
1631+ *
1632+ * Returns: A resource handle
1633+ *
1634+ ***********************************************************/
1635+VCHPRE_ DISPMANX_RESOURCE_HANDLE_T VCHPOST_ vc_dispmanx_get_handle_from_wl_buffer( struct wl_resource *_buffer )
1636+{
1637+	struct wl_dispmanx_server_buffer *buffer = (struct wl_dispmanx_server_buffer*)_buffer->data;
1638+	if (!buffer)
1639+		return DISPMANX_NO_HANDLE;
1640+
1641+	return buffer->handle;
1642+}
1643+
1644+/***********************************************************
1645+ * Name: vc_dispmanx_set_wl_buffer_in_use
1646+ *
1647+ * Arguments:
1648+ *       struct wl_resource *_buffer
1649+ *       int in_use
1650+ *
1651+ * Description: Mark this Wayland buffer as being in use by the compositor
1652+ *
1653+ ***********************************************************/
1654+VCHPRE_ void VCHPOST_ vc_dispmanx_set_wl_buffer_in_use( struct wl_resource *_buffer, int in_use )
1655+{
1656+	struct wl_dispmanx_server_buffer *buffer = (struct wl_dispmanx_server_buffer*)_buffer->data;
1657+	if (!buffer)
1658+		return;
1659+
1660+	buffer->in_use = in_use;
1661+}
1662+#endif
1663diff --git a/interface/vmcs_host/vc_vchi_dispmanx.h b/interface/vmcs_host/vc_vchi_dispmanx.h
1664index b723b76..f0bae30 100644
1665--- a/interface/vmcs_host/vc_vchi_dispmanx.h
1666+++ b/interface/vmcs_host/vc_vchi_dispmanx.h
1667@@ -66,4 +66,19 @@ typedef struct {
1668 #define ELEMENT_CHANGE_MASK_RESOURCE  (1<<4)
1669 #define ELEMENT_CHANGE_TRANSFORM      (1<<5)
1670
1671+#ifdef BUILD_WAYLAND
1672+/* XXX: This should be in a private header that can be included from EGL and vc_* */
1673+#include <wayland-server.h>
1674+#include "interface/vmcs_host/wayland-dispmanx-server-protocol.h"
1675+struct wl_dispmanx_server_buffer {
1676+	struct wl_resource *resource;
1677+	struct wl_dispmanx *dispmanx;
1678+	enum wl_dispmanx_format format;
1679+	DISPMANX_RESOURCE_HANDLE_T handle;
1680+	int32_t width;
1681+	int32_t height;
1682+	int in_use;
1683+};
1684+#endif
1685+
1686 #endif
1687diff --git a/interface/wayland/dispmanx.xml b/interface/wayland/dispmanx.xml
1688new file mode 100644
1689index 0000000..c18626d
1690--- /dev/null
1691+++ b/interface/wayland/dispmanx.xml
1692@@ -0,0 +1,123 @@
1693+<?xml version="1.0" encoding="UTF-8"?>
1694+<protocol name="dispmanx">
1695+
1696+  <copyright>
1697+    Copyright © 2008-2011 Kristian Høgsberg
1698+    Copyright © 2010-2011 Intel Corporation
1699+    Copyright © 2013 Raspberry Pi Foundation
1700+
1701+    Permission to use, copy, modify, distribute, and sell this
1702+    software and its documentation for any purpose is hereby granted
1703+    without fee, provided that\n the above copyright notice appear in
1704+    all copies and that both that copyright notice and this permission
1705+    notice appear in supporting documentation, and that the name of
1706+    the copyright holders not be used in advertising or publicity
1707+    pertaining to distribution of the software without specific,
1708+    written prior permission.  The copyright holders make no
1709+    representations about the suitability of this software for any
1710+    purpose.  It is provided "as is" without express or implied
1711+    warranty.
1712+
1713+    THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
1714+    SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
1715+    FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
1716+    SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1717+    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
1718+    AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
1719+    ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
1720+    THIS SOFTWARE.
1721+  </copyright>
1722+
1723+  <!-- DispManX support. This object is created by the server and published
1724+       using the display's global event. -->
1725+  <interface name="wl_dispmanx" version="1">
1726+    <enum name="error">
1727+      <entry name="alloc_failed" value="0"/>
1728+      <entry name="invalid_format" value="1"/>
1729+    </enum>
1730+
1731+    <enum name="format">
1732+      <!-- The pixel format codes match the #defines in drm_fourcc.h.
1733+           The formats actually supported by the compositor will be
1734+           reported by the format event. -->
1735+      <entry name="c8" value="0x20203843"/>
1736+      <entry name="rgb332" value="0x38424752"/>
1737+      <entry name="bgr233" value="0x38524742"/>
1738+      <entry name="xrgb4444" value="0x32315258"/>
1739+      <entry name="xbgr4444" value="0x32314258"/>
1740+      <entry name="rgbx4444" value="0x32315852"/>
1741+      <entry name="bgrx4444" value="0x32315842"/>
1742+      <entry name="argb4444" value="0x32315241"/>
1743+      <entry name="abgr4444" value="0x32314241"/>
1744+      <entry name="rgba4444" value="0x32314152"/>
1745+      <entry name="bgra4444" value="0x32314142"/>
1746+      <entry name="xrgb1555" value="0x35315258"/>
1747+      <entry name="xbgr1555" value="0x35314258"/>
1748+      <entry name="rgbx5551" value="0x35315852"/>
1749+      <entry name="bgrx5551" value="0x35315842"/>
1750+      <entry name="argb1555" value="0x35315241"/>
1751+      <entry name="abgr1555" value="0x35314241"/>
1752+      <entry name="rgba5551" value="0x35314152"/>
1753+      <entry name="bgra5551" value="0x35314142"/>
1754+      <entry name="rgb565" value="0x36314752"/>
1755+      <entry name="bgr565" value="0x36314742"/>
1756+      <entry name="rgb888" value="0x34324752"/>
1757+      <entry name="bgr888" value="0x34324742"/>
1758+      <entry name="xrgb8888" value="0x34325258"/>
1759+      <entry name="xbgr8888" value="0x34324258"/>
1760+      <entry name="rgbx8888" value="0x34325852"/>
1761+      <entry name="bgrx8888" value="0x34325842"/>
1762+      <entry name="argb8888" value="0x34325241"/>
1763+      <entry name="abgr8888" value="0x34324241"/>
1764+      <entry name="rgba8888" value="0x34324152"/>
1765+      <entry name="bgra8888" value="0x34324142"/>
1766+      <entry name="xrgb2101010" value="0x30335258"/>
1767+      <entry name="xbgr2101010" value="0x30334258"/>
1768+      <entry name="rgbx1010102" value="0x30335852"/>
1769+      <entry name="bgrx1010102" value="0x30335842"/>
1770+      <entry name="argb2101010" value="0x30335241"/>
1771+      <entry name="abgr2101010" value="0x30334241"/>
1772+      <entry name="rgba1010102" value="0x30334152"/>
1773+      <entry name="bgra1010102" value="0x30334142"/>
1774+      <entry name="yuyv" value="0x56595559"/>
1775+      <entry name="yvyu" value="0x55595659"/>
1776+      <entry name="uyvy" value="0x59565955"/>
1777+      <entry name="vyuy" value="0x59555956"/>
1778+      <entry name="ayuv" value="0x56555941"/>
1779+      <entry name="nv12" value="0x3231564e"/>
1780+      <entry name="nv21" value="0x3132564e"/>
1781+      <entry name="nv16" value="0x3631564e"/>
1782+      <entry name="nv61" value="0x3136564e"/>
1783+      <entry name="yuv410" value="0x39565559"/>
1784+      <entry name="yvu410" value="0x39555659"/>
1785+      <entry name="yuv411" value="0x31315559"/>
1786+      <entry name="yvu411" value="0x31315659"/>
1787+      <entry name="yuv420" value="0x32315559"/>
1788+      <entry name="yvu420" value="0x32315659"/>
1789+      <entry name="yuv422" value="0x36315559"/>
1790+      <entry name="yvu422" value="0x36315659"/>
1791+      <entry name="yuv444" value="0x34325559"/>
1792+      <entry name="yvu444" value="0x34325659"/>
1793+    </enum>
1794+
1795+    <event name="format">
1796+      <arg name="format" type="uint"/>
1797+    </event>
1798+
1799+    <!-- Create a wayland buffer for the DispManX resource. -->
1800+    <request name="create_buffer">
1801+      <arg name="id" type="new_id" interface="wl_buffer"/>
1802+      <arg name="width" type="int"/>
1803+      <arg name="height" type="int"/>
1804+      <arg name="stride" type="uint"/>
1805+      <arg name="buffer_height" type="uint"/>
1806+      <arg name="format" type="uint"/>
1807+    </request>
1808+
1809+    <event name="buffer_allocated">
1810+      <arg name="buffer" type="object" interface="wl_buffer"/>
1811+      <arg name="handle" type="uint"/>
1812+    </event>
1813+  </interface>
1814+
1815+</protocol>
1816diff --git a/makefiles/cmake/Wayland.cmake b/makefiles/cmake/Wayland.cmake
1817new file mode 100644
1818index 0000000..ad90d30
1819--- /dev/null
1820+++ b/makefiles/cmake/Wayland.cmake
1821@@ -0,0 +1,72 @@
1822+#=============================================================================
1823+# Copyright (C) 2012-2013 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
1824+# All rights reserved.
1825+#
1826+# Redistribution and use in source and binary forms, with or without
1827+# modification, are permitted provided that the following conditions
1828+# are met:
1829+#
1830+# * Redistributions of source code must retain the above copyright
1831+#   notice, this list of conditions and the following disclaimer.
1832+#
1833+# * Redistributions in binary form must reproduce the above copyright
1834+#   notice, this list of conditions and the following disclaimer in the
1835+#   documentation and/or other materials provided with the distribution.
1836+#
1837+# * Neither the name of Pier Luigi Fiorini nor the names of his
1838+#   contributors may be used to endorse or promote products derived
1839+#   from this software without specific prior written permission.
1840+#
1841+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1842+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1843+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1844+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
1845+# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
1846+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
1847+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
1848+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
1849+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1850+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
1851+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1852+#=============================================================================
1853+
1854+find_program(WAYLAND_SCANNER_EXECUTABLE NAMES wayland-scanner)
1855+
1856+# wayland_add_protocol_client(outfiles inputfile basename)
1857+function(WAYLAND_ADD_PROTOCOL_CLIENT _sources _protocol _basename)
1858+    if(NOT WAYLAND_SCANNER_EXECUTABLE)
1859+        message(FATAL "The wayland-scanner executable has nto been found on your system. You must install it.")
1860+    endif()
1861+
1862+    get_filename_component(_infile ${_protocol} ABSOLUTE)
1863+    set(_client_header "${CMAKE_CURRENT_BINARY_DIR}/wayland-${_basename}-client-protocol.h")
1864+    set(_code "${CMAKE_CURRENT_BINARY_DIR}/wayland-${_basename}-protocol.c")
1865+
1866+    add_custom_command(OUTPUT "${_client_header}"
1867+        COMMAND ${WAYLAND_SCANNER_EXECUTABLE} client-header < ${_infile} > ${_client_header}
1868+        DEPENDS ${_infile} VERBATIM)
1869+
1870+    add_custom_command(OUTPUT "${_code}"
1871+        COMMAND ${WAYLAND_SCANNER_EXECUTABLE} code < ${_infile} > ${_code}
1872+        DEPENDS ${_infile} VERBATIM)
1873+
1874+    list(APPEND ${_sources} "${_client_header}" "${_code}")
1875+    set(${_sources} ${${_sources}} PARENT_SCOPE)
1876+endfunction()
1877+
1878+# wayland_add_protocol_server(outfiles inputfile basename)
1879+function(WAYLAND_ADD_PROTOCOL_SERVER _sources _protocol _basename)
1880+    if(NOT WAYLAND_SCANNER_EXECUTABLE)
1881+        message(FATAL "The wayland-scanner executable has nto been found on your system. You must install it.")
1882+    endif()
1883+
1884+    get_filename_component(_infile ${_protocol} ABSOLUTE)
1885+    set(_server_header "${CMAKE_CURRENT_BINARY_DIR}/wayland-${_basename}-server-protocol.h")
1886+
1887+    add_custom_command(OUTPUT "${_server_header}"
1888+        COMMAND ${WAYLAND_SCANNER_EXECUTABLE} server-header < ${_infile} > ${_server_header}
1889+        DEPENDS ${_infile} VERBATIM)
1890+
1891+    list(APPEND ${_sources} "${_server_header}")
1892+    set(${_sources} ${${_sources}} PARENT_SCOPE)
1893+endfunction()
1894