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