summaryrefslogtreecommitdiffstats
path: root/meta-raspberrypi/recipes-graphics
diff options
context:
space:
mode:
authorDave Cobbley <david.j.cobbley@linux.intel.com>2018-08-14 10:05:37 -0700
committerBrad Bishop <bradleyb@fuzziesquirrel.com>2018-08-22 21:26:31 -0400
commiteb8dc40360f0cfef56fb6947cc817a547d6d9bc6 (patch)
treede291a73dc37168da6370e2cf16c347d1eba9df8 /meta-raspberrypi/recipes-graphics
parent9c3cf826d853102535ead04cebc2d6023eff3032 (diff)
downloadtalos-openbmc-eb8dc40360f0cfef56fb6947cc817a547d6d9bc6.zip
talos-openbmc-eb8dc40360f0cfef56fb6947cc817a547d6d9bc6.tar.gz
[Subtree] Removing import-layers directory
As part of the move to subtrees, need to bring all the import layers content to the top level. Change-Id: I4a163d10898cbc6e11c27f776f60e1a470049d8f Signed-off-by: Dave Cobbley <david.j.cobbley@linux.intel.com> Signed-off-by: Brad Bishop <bradleyb@fuzziesquirrel.com>
Diffstat (limited to 'meta-raspberrypi/recipes-graphics')
-rw-r--r--meta-raspberrypi/recipes-graphics/eglinfo/eglinfo-fb_%.bbappend2
-rw-r--r--meta-raspberrypi/recipes-graphics/eglinfo/eglinfo-x11_%.bbappend2
-rw-r--r--meta-raspberrypi/recipes-graphics/mesa/mesa-gl_%.bbappend1
-rw-r--r--meta-raspberrypi/recipes-graphics/mesa/mesa_%.bbappend7
-rw-r--r--meta-raspberrypi/recipes-graphics/userland/userland/0001-Allow-applications-to-set-next-resource-handle.patch208
-rw-r--r--meta-raspberrypi/recipes-graphics/userland/userland/0002-wayland-Add-support-for-the-Wayland-winsys.patch1861
-rw-r--r--meta-raspberrypi/recipes-graphics/userland/userland/0003-wayland-Add-Wayland-example.patch866
-rw-r--r--meta-raspberrypi/recipes-graphics/userland/userland/0004-wayland-egl-Add-bcm_host-to-dependencies.patch28
-rw-r--r--meta-raspberrypi/recipes-graphics/userland/userland/0005-interface-remove-faulty-assert-to-make-weston-happy-.patch29
-rw-r--r--meta-raspberrypi/recipes-graphics/userland/userland/0006-zero-out-wl-buffers-in-egl_surface_free.patch33
-rw-r--r--meta-raspberrypi/recipes-graphics/userland/userland/0007-initialize-front-back-wayland-buffers.patch34
-rw-r--r--meta-raspberrypi/recipes-graphics/userland/userland/0008-Remove-RPC_FLUSH.patch27
-rw-r--r--meta-raspberrypi/recipes-graphics/userland/userland/0009-fix-cmake-dependency-race.patch78
-rw-r--r--meta-raspberrypi/recipes-graphics/userland/userland/0010-Fix-for-framerate-with-nested-composition.patch60
-rw-r--r--meta-raspberrypi/recipes-graphics/userland/userland/0011-build-shared-library-for-vchostif.patch28
-rw-r--r--meta-raspberrypi/recipes-graphics/userland/userland/0012-implement-buffer-wrapping-interface-for-dispmanx.patch92
-rw-r--r--meta-raspberrypi/recipes-graphics/userland/userland/0013-Implement-triple-buffering-for-wayland.patch90
-rw-r--r--meta-raspberrypi/recipes-graphics/userland/userland/0014-GLES2-gl2ext.h-Define-GL_R8_EXT-and-GL_RG8_EXT.patch30
-rw-r--r--meta-raspberrypi/recipes-graphics/userland/userland/0015-EGL-glplatform.h-define-EGL_CAST.patch32
-rw-r--r--meta-raspberrypi/recipes-graphics/userland/userland/0016-Allow-multiple-wayland-compositor-state-data-per-pro.patch145
-rw-r--r--meta-raspberrypi/recipes-graphics/userland/userland_git.bb85
-rw-r--r--meta-raspberrypi/recipes-graphics/vc-graphics/files/egl.pc10
-rw-r--r--meta-raspberrypi/recipes-graphics/vc-graphics/files/vchiq.sh24
-rw-r--r--meta-raspberrypi/recipes-graphics/vc-graphics/vc-graphics-hardfp.bb6
-rw-r--r--meta-raspberrypi/recipes-graphics/vc-graphics/vc-graphics.bb6
-rw-r--r--meta-raspberrypi/recipes-graphics/vc-graphics/vc-graphics.inc58
-rw-r--r--meta-raspberrypi/recipes-graphics/wayland/weston_%.bbappend10
-rw-r--r--meta-raspberrypi/recipes-graphics/xorg-xserver/xserver-xf86-config/rpi/xorg.conf6
-rw-r--r--meta-raspberrypi/recipes-graphics/xorg-xserver/xserver-xf86-config/rpi/xorg.conf.d/10-noglamor.conf6
-rw-r--r--meta-raspberrypi/recipes-graphics/xorg-xserver/xserver-xf86-config/rpi/xorg.conf.d/98-pitft.conf5
-rw-r--r--meta-raspberrypi/recipes-graphics/xorg-xserver/xserver-xf86-config/rpi/xorg.conf.d/99-calibration.conf6
-rw-r--r--meta-raspberrypi/recipes-graphics/xorg-xserver/xserver-xf86-config_0.1.bbappend21
-rw-r--r--meta-raspberrypi/recipes-graphics/xorg-xserver/xserver-xorg_%.bbappend9
33 files changed, 3905 insertions, 0 deletions
diff --git a/meta-raspberrypi/recipes-graphics/eglinfo/eglinfo-fb_%.bbappend b/meta-raspberrypi/recipes-graphics/eglinfo/eglinfo-fb_%.bbappend
new file mode 100644
index 0000000..7692133
--- /dev/null
+++ b/meta-raspberrypi/recipes-graphics/eglinfo/eglinfo-fb_%.bbappend
@@ -0,0 +1,2 @@
+EGLINFO_DEVICE_rpi = "raspberrypi"
+COMPATIBLE_HOST_rpi = "${@bb.utils.contains('MACHINE_FEATURES', 'vc4graphics', 'null', '"(.*)"', d)}"
diff --git a/meta-raspberrypi/recipes-graphics/eglinfo/eglinfo-x11_%.bbappend b/meta-raspberrypi/recipes-graphics/eglinfo/eglinfo-x11_%.bbappend
new file mode 100644
index 0000000..2d720ba
--- /dev/null
+++ b/meta-raspberrypi/recipes-graphics/eglinfo/eglinfo-x11_%.bbappend
@@ -0,0 +1,2 @@
+EGLINFO_DEVICE_rpi = "${@bb.utils.contains('MACHINE_FEATURES', 'vc4graphics', 'generic', 'raspberrypi', d)}"
+ASNEEDED = ""
diff --git a/meta-raspberrypi/recipes-graphics/mesa/mesa-gl_%.bbappend b/meta-raspberrypi/recipes-graphics/mesa/mesa-gl_%.bbappend
new file mode 100644
index 0000000..7897125
--- /dev/null
+++ b/meta-raspberrypi/recipes-graphics/mesa/mesa-gl_%.bbappend
@@ -0,0 +1 @@
+PACKAGECONFIG_append_rpi = " gbm"
diff --git a/meta-raspberrypi/recipes-graphics/mesa/mesa_%.bbappend b/meta-raspberrypi/recipes-graphics/mesa/mesa_%.bbappend
new file mode 100644
index 0000000..52fe757
--- /dev/null
+++ b/meta-raspberrypi/recipes-graphics/mesa/mesa_%.bbappend
@@ -0,0 +1,7 @@
+# DRI3 note:
+# With oe-core commit 8509e2e1a87578882b71948ccef3b50ccf1228b3 dri3 is set
+# as default. To state out clearly that Raspi needs dri3 and to avoid surprises
+# in case oe-core changes this default, we set dri3 explicitly.
+PACKAGECONFIG_append_rpi = " gallium ${@bb.utils.contains('DISTRO_FEATURES', 'x11 opengl', 'x11 dri3', '', d)}"
+GALLIUMDRIVERS_rpi = "vc4"
+DRIDRIVERS_rpi = ""
diff --git a/meta-raspberrypi/recipes-graphics/userland/userland/0001-Allow-applications-to-set-next-resource-handle.patch b/meta-raspberrypi/recipes-graphics/userland/userland/0001-Allow-applications-to-set-next-resource-handle.patch
new file mode 100644
index 0000000..933f279
--- /dev/null
+++ b/meta-raspberrypi/recipes-graphics/userland/userland/0001-Allow-applications-to-set-next-resource-handle.patch
@@ -0,0 +1,208 @@
+From 0a64dc61d3d7db69389157ae757203b4b3afdbfa Mon Sep 17 00:00:00 2001
+From: Dom Cobley <dc4@broadcom.com>
+Date: Tue, 9 Jul 2013 09:26:26 -0400
+Subject: [PATCH 01/16] Allow applications to set next resource handle
+
+This patch adds provisions in userland to
+let apps callers set the next rendereing dispmanx resource.
+It's useful for implementing, say, a buffer carousel.
+---
+ interface/khronos/common/khrn_client_rpc.h | 2 ++
+ interface/khronos/common/khrn_int_ids.h | 2 ++
+ interface/khronos/egl/egl_client.c | 30 +++++++++++++++++++++++++++---
+ interface/khronos/egl/egl_client_surface.c | 24 +++++++++++++++++++++++-
+ interface/khronos/egl/egl_client_surface.h | 3 ++-
+ interface/khronos/egl/egl_int_impl.h | 5 +++--
+ 6 files changed, 59 insertions(+), 7 deletions(-)
+
+diff --git a/interface/khronos/common/khrn_client_rpc.h b/interface/khronos/common/khrn_client_rpc.h
+index dc4351d..10ea060 100644
+--- a/interface/khronos/common/khrn_client_rpc.h
++++ b/interface/khronos/common/khrn_client_rpc.h
+@@ -685,6 +685,7 @@ static INLINE void rpc_call12_out_ctrl(CLIENT_THREAD_STATE_T *thread,uint32_t id
+ static INLINE void rpc_call13_out_ctrl(CLIENT_THREAD_STATE_T *thread,uint32_t id, uint32_t p0, uint32_t p1, uint32_t p2, uint32_t p3, uint32_t p4, uint32_t p5, uint32_t p6, uint32_t p7, uint32_t p8, uint32_t p9, uint32_t p10, uint32_t p11, void *out) { rpc_begin(thread); RPC_CALL(thread, id, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11); rpc_recv(thread, out, NULL, (RPC_RECV_FLAG_T)(RPC_RECV_FLAG_CTRL | RPC_RECV_FLAG_LEN)); rpc_end(thread); }
+ static INLINE void rpc_call14_out_ctrl(CLIENT_THREAD_STATE_T *thread,uint32_t id, uint32_t p0, uint32_t p1, uint32_t p2, uint32_t p3, uint32_t p4, uint32_t p5, uint32_t p6, uint32_t p7, uint32_t p8, uint32_t p9, uint32_t p10, uint32_t p11, uint32_t p12, void *out) { rpc_begin(thread); RPC_CALL(thread, id, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12); rpc_recv(thread, out, NULL, (RPC_RECV_FLAG_T)(RPC_RECV_FLAG_CTRL | RPC_RECV_FLAG_LEN)); rpc_end(thread); }
+ static INLINE void rpc_call15_out_ctrl(CLIENT_THREAD_STATE_T *thread,uint32_t id, uint32_t p0, uint32_t p1, uint32_t p2, uint32_t p3, uint32_t p4, uint32_t p5, uint32_t p6, uint32_t p7, uint32_t p8, uint32_t p9, uint32_t p10, uint32_t p11, uint32_t p12, uint32_t p13, void *out) { rpc_begin(thread); RPC_CALL(thread, id, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13); rpc_recv(thread, out, NULL, (RPC_RECV_FLAG_T)(RPC_RECV_FLAG_CTRL | RPC_RECV_FLAG_LEN)); rpc_end(thread); }
++static INLINE void rpc_call16_out_ctrl(CLIENT_THREAD_STATE_T *thread,uint32_t id, uint32_t p0, uint32_t p1, uint32_t p2, uint32_t p3, uint32_t p4, uint32_t p5, uint32_t p6, uint32_t p7, uint32_t p8, uint32_t p9, uint32_t p10, uint32_t p11, uint32_t p12, uint32_t p13, uint32_t p14, void *out) { rpc_begin(thread); RPC_CALL(thread, id, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14); rpc_recv(thread, out, NULL, (RPC_RECV_FLAG_T)(RPC_RECV_FLAG_CTRL | RPC_RECV_FLAG_LEN)); rpc_end(thread); }
+ #endif
+
+ #define RPC_CALL1_OUT_CTRL(fn, thread, id, out) rpc_call1_out_ctrl(thread, id, out)
+@@ -702,6 +703,7 @@ static INLINE void rpc_call15_out_ctrl(CLIENT_THREAD_STATE_T *thread,uint32_t id
+ #define RPC_CALL13_OUT_CTRL(fn, thread, id, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, out) rpc_call13_out_ctrl(thread, id, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, out)
+ #define RPC_CALL14_OUT_CTRL(fn, thread, id, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, out) rpc_call14_out_ctrl(thread, id, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, out)
+ #define RPC_CALL15_OUT_CTRL(fn, thread, id, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, out) rpc_call15_out_ctrl(thread, id, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, out)
++#define RPC_CALL16_OUT_CTRL(fn, thread, id, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, out) rpc_call16_out_ctrl(thread, id, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, out)
+
+ # if !defined(__SYMBIAN32__) //use functions defined in khrpc.cpp
+ static INLINE uint32_t rpc_call1_out_ctrl_res(CLIENT_THREAD_STATE_T *thread,uint32_t id, void *out) { uint32_t res; rpc_begin(thread); RPC_CALL(thread, id); res = rpc_recv(thread, out, NULL, (RPC_RECV_FLAG_T)(RPC_RECV_FLAG_RES | RPC_RECV_FLAG_CTRL | RPC_RECV_FLAG_LEN)); rpc_end(thread); return res; }
+diff --git a/interface/khronos/common/khrn_int_ids.h b/interface/khronos/common/khrn_int_ids.h
+index 8378f4a..ec961e0 100644
+--- a/interface/khronos/common/khrn_int_ids.h
++++ b/interface/khronos/common/khrn_int_ids.h
+@@ -367,6 +367,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+ #define EGLINTCREATESURFACE_ID 0x4000
++#define EGLINTCREATESURFACE_ID_V2 0x4100
+ #define EGLINTCREATEGLES11_ID 0x4001
+ #define EGLINTCREATEGLES20_ID 0x4002
+ #define EGLINTCREATEVG_ID 0x4003
+@@ -377,6 +378,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ #define EGLINTMAKECURRENT_ID 0x4008
+ #define EGLINTFLUSHANDWAIT_ID 0x4009
+ #define EGLINTSWAPBUFFERS_ID 0x400a
++#define EGLINTSWAPBUFFERS_ID_V2 0x410a
+ #define EGLINTSELECTMIPMAP_ID 0x400b
+ #define EGLINTFLUSH_ID 0x400c
+ #define EGLINTGETCOLORDATA_ID 0x400d
+diff --git a/interface/khronos/egl/egl_client.c b/interface/khronos/egl/egl_client.c
+index 9d617c8..b8bb374 100644
+--- a/interface/khronos/egl/egl_client.c
++++ b/interface/khronos/egl/egl_client.c
+@@ -162,6 +162,17 @@ static void egl_current_release(CLIENT_PROCESS_STATE_T *process, EGL_CURRENT_T *
+ void egl_gl_flush_callback(bool wait);
+ void egl_vg_flush_callback(bool wait);
+
++#include "interface/vmcs_host/vc_dispmanx_types.h"
++/**HACKHACK - give us the ability to inject a DispmanX
++ * resource handle into the CreateWindowSurface and
++ * SwapBuffers calls */
++static DISPMANX_RESOURCE_HANDLE_T next_resource_handle;
++
++EGLAPI EGLBoolean EGLAPIENTRY eglSetNextResourceHandle(DISPMANX_RESOURCE_HANDLE_T handle)
++{
++ next_resource_handle = handle;
++}
++
+ /*
+ TODO: do an RPC call to make sure the Khronos vll is loaded (and that it stays loaded until eglTerminate)
+ Also affects global image (and possibly others?)
+@@ -644,7 +655,8 @@ EGLAPI EGLSurface EGLAPIENTRY eglCreateWindowSurface(EGLDisplay dpy, EGLConfig c
+ false,
+ EGL_NO_TEXTURE,
+ EGL_NO_TEXTURE,
+- 0, 0);
++ 0, 0,
++ next_resource_handle);
+
+ if (surface) {
+ if (khrn_pointer_map_insert(&process->surfaces, process->next_surface, surface)) {
+@@ -889,7 +901,7 @@ EGLAPI EGLSurface EGLAPIENTRY eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig
+ mipmap_texture,
+ texture_format,
+ texture_target,
+- 0, 0);
++ 0, 0, 0);
+
+ if (surface) {
+ if (khrn_pointer_map_insert(&process->surfaces, process->next_surface, surface)) {
+@@ -1031,7 +1043,7 @@ EGLAPI EGLSurface EGLAPIENTRY eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig c
+ false,
+ EGL_NO_TEXTURE,
+ EGL_NO_TEXTURE,
+- pixmap, ((server_handle[0] == 0) && (server_handle[1] == (uint32_t)(-1))) ? NULL : server_handle);
++ pixmap, ((server_handle[0] == 0) && (server_handle[1] == (uint32_t)(-1))) ? NULL : server_handle, 0);
+
+ if (surface) {
+ if (khrn_pointer_map_insert(&process->surfaces, process->next_surface, surface)) {
+@@ -2303,6 +2315,18 @@ EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffers(EGLDisplay dpy, EGLSurface surf)
+
+ vcos_log_trace("eglSwapBuffers server call");
+
++ if (next_resource_handle)
++ RPC_CALL7(eglIntSwapBuffers_impl,
++ thread,
++ EGLINTSWAPBUFFERS_ID_V2,
++ RPC_UINT(surface->serverbuffer),
++ RPC_UINT(surface->width),
++ RPC_UINT(surface->height),
++ RPC_UINT(surface->internal_handle),
++ RPC_UINT(surface->swap_behavior == EGL_BUFFER_PRESERVED ? 1 : 0),
++ RPC_UINT(khrn_platform_get_window_position(surface->win)),
++ RPC_INT(next_resource_handle));
++ else
+ RPC_CALL6(eglIntSwapBuffers_impl,
+ thread,
+ EGLINTSWAPBUFFERS_ID,
+diff --git a/interface/khronos/egl/egl_client_surface.c b/interface/khronos/egl/egl_client_surface.c
+index 6846dfa..128325e 100644
+--- a/interface/khronos/egl/egl_client_surface.c
++++ b/interface/khronos/egl/egl_client_surface.c
+@@ -314,7 +314,8 @@ EGL_SURFACE_T *egl_surface_create(
+ EGLenum texture_format,
+ EGLenum texture_target,
+ EGLNativePixmapType pixmap,
+- const uint32_t *pixmap_server_handle)
++ const uint32_t *pixmap_server_handle,
++ DISPMANX_RESOURCE_HANDLE_T next_resource_handle)
+ {
+ KHRN_IMAGE_FORMAT_T color;
+ KHRN_IMAGE_FORMAT_T depth;
+@@ -473,6 +474,27 @@ EGL_SURFACE_T *egl_surface_create(
+ #endif
+ uint32_t results[3];
+
++ if (next_resource_handle)
++ RPC_CALL16_OUT_CTRL(eglIntCreateSurface_impl,
++ thread,
++ EGLINTCREATESURFACE_ID_V2,
++ RPC_UINT(serverwin),
++ RPC_UINT(buffers),
++ RPC_UINT(width),
++ RPC_UINT(height),
++ RPC_UINT(color),
++ RPC_UINT(depth),
++ RPC_UINT(mask),
++ RPC_UINT(multi),
++ RPC_UINT(largest_pbuffer),
++ RPC_UINT(mipmap_texture),
++ RPC_UINT(config_depth_bits),
++ RPC_UINT(config_stencil_bits),
++ RPC_UINT(sem_name),
++ RPC_UINT(type),
++ RPC_INT(next_resource_handle),
++ results);
++ else
+ RPC_CALL15_OUT_CTRL(eglIntCreateSurface_impl,
+ thread,
+ EGLINTCREATESURFACE_ID,
+diff --git a/interface/khronos/egl/egl_client_surface.h b/interface/khronos/egl/egl_client_surface.h
+index c99d44c..b5bf70a 100644
+--- a/interface/khronos/egl/egl_client_surface.h
++++ b/interface/khronos/egl/egl_client_surface.h
+@@ -322,7 +322,8 @@ extern EGL_SURFACE_T *egl_surface_create(
+ EGLenum texture_format,
+ EGLenum texture_target,
+ EGLNativePixmapType pixmap,
+- const uint32_t *pixmap_server_handle);
++ const uint32_t *pixmap_server_handle,
++ DISPMANX_RESOURCE_HANDLE_T next_resource_handle);
+ extern EGL_SURFACE_T *egl_surface_from_vg_image(
+ VGImage vg_handle,
+ EGLSurface name,
+diff --git a/interface/khronos/egl/egl_int_impl.h b/interface/khronos/egl/egl_int_impl.h
+index 8a5734c..51b3580 100644
+--- a/interface/khronos/egl/egl_int_impl.h
++++ b/interface/khronos/egl/egl_int_impl.h
+@@ -56,7 +56,8 @@ FN(int, eglIntCreateSurface_impl, (
+ uint32_t config_stencil_bits,
+ uint32_t sem,
+ uint32_t type,
+- uint32_t *results))
++ uint32_t *results,
++ DISPMANX_RESOURCE_HANDLE_T next_resource_handle))
+
+ FN(int, eglIntCreatePbufferFromVGImage_impl, (
+ VGImage vg_handle,
+@@ -110,7 +111,7 @@ FN(void, eglIntMakeCurrent_impl, (uint32_t pid_0, uint32_t pid_1, uint32_t glver
+ FN(int, eglIntFlushAndWait_impl, (uint32_t flushgl, uint32_t flushvg))
+ FN(void, eglIntFlush_impl, (uint32_t flushgl, uint32_t flushvg))
+
+-FN(void, eglIntSwapBuffers_impl, (EGL_SURFACE_ID_T s, uint32_t width, uint32_t height, uint32_t handle, uint32_t preserve, uint32_t position))
++FN(void, eglIntSwapBuffers_impl, (EGL_SURFACE_ID_T s, uint32_t width, uint32_t height, uint32_t handle, uint32_t preserve, uint32_t position, DISPMANX_RESOURCE_HANDLE_T new_back_buffer))
+ FN(void, eglIntSelectMipmap_impl, (EGL_SURFACE_ID_T s, int level))
+
+ FN(void, eglIntGetColorData_impl, (EGL_SURFACE_ID_T s, KHRN_IMAGE_FORMAT_T format, uint32_t width, uint32_t height, int32_t stride, uint32_t y_offset, void *data))
+--
+2.16.1
+
diff --git a/meta-raspberrypi/recipes-graphics/userland/userland/0002-wayland-Add-support-for-the-Wayland-winsys.patch b/meta-raspberrypi/recipes-graphics/userland/userland/0002-wayland-Add-support-for-the-Wayland-winsys.patch
new file mode 100644
index 0000000..4613504
--- /dev/null
+++ b/meta-raspberrypi/recipes-graphics/userland/userland/0002-wayland-Add-support-for-the-Wayland-winsys.patch
@@ -0,0 +1,1861 @@
+From 5608ec8002be8370e78c9dbb1e07cee4cfb18b58 Mon Sep 17 00:00:00 2001
+From: Tomeu Vizoso <tomeu.vizoso@collabora.com>
+Date: Tue, 1 Oct 2013 13:19:20 +0200
+Subject: [PATCH 02/16] wayland: Add support for the Wayland winsys
+
+* Adds EGL_WL_bind_wayland_display extension
+* Adds wayland-egl library
+* Adds wl_dispmanx_buffer protocol extension
+
+TODO: Check that platform_get_dimensions() returning swapchain_count == 1 is correct
+
+TODO: Remove the requirement of passing a valid DispmanX element handle to
+the SwapBuffers and CreateSurface RPC calls. This will remove the need to open
+a DispmanX display from the clients.
+
+TODO: wl_dispmanx_server_buffer should probably be defined in a
+private header that can be included from EGL and vc_* instead of in
+vc_vchi_dispmanx.h
+---
+ .gitignore | 1 +
+ CMakeLists.txt | 11 +
+ README.md | 4 +
+ buildme | 10 +-
+ .../linux/apps/raspicam/CMakeLists.txt | 2 +-
+ interface/khronos/CMakeLists.txt | 53 ++++-
+ interface/khronos/common/khrn_client.c | 15 ++
+ interface/khronos/common/khrn_client.h | 10 +
+ interface/khronos/common/khrn_client_mangle.h | 3 +
+ interface/khronos/common/khrn_client_platform.h | 8 +
+ interface/khronos/common/khrn_client_unmangle.h | 3 +
+ .../common/linux/khrn_client_platform_linux.c | 115 ++++++++--
+ interface/khronos/common/linux/khrn_wayland.c | 215 ++++++++++++++++++
+ .../common/linux/khrn_wayland.h} | 46 +---
+ interface/khronos/egl/egl_client.c | 92 +++++---
+ interface/khronos/egl/egl_client_get_proc.c | 11 +
+ interface/khronos/egl/egl_client_surface.c | 42 +++-
+ interface/khronos/egl/egl_client_surface.h | 38 +++-
+ interface/khronos/egl/egl_int_impl.h | 2 +-
+ interface/khronos/ext/egl_wayland.c | 246 +++++++++++++++++++++
+ interface/khronos/include/EGL/eglext.h | 23 ++
+ interface/khronos/wayland-egl/wayland-egl-priv.h | 53 +++++
+ interface/khronos/wayland-egl/wayland-egl.c | 59 +++++
+ interface/khronos/wayland-egl/wayland-egl.pc.in | 10 +
+ interface/vmcs_host/CMakeLists.txt | 21 +-
+ interface/vmcs_host/vc_dispmanx.h | 10 +
+ interface/vmcs_host/vc_vchi_dispmanx.c | 42 ++++
+ interface/vmcs_host/vc_vchi_dispmanx.h | 15 ++
+ interface/wayland/dispmanx.xml | 123 +++++++++++
+ makefiles/cmake/Wayland.cmake | 72 ++++++
+ 30 files changed, 1257 insertions(+), 98 deletions(-)
+ create mode 100644 interface/khronos/common/linux/khrn_wayland.c
+ copy interface/{vmcs_host/vc_vchi_dispmanx.h => khronos/common/linux/khrn_wayland.h} (56%)
+ create mode 100644 interface/khronos/ext/egl_wayland.c
+ create mode 100644 interface/khronos/wayland-egl/wayland-egl-priv.h
+ create mode 100644 interface/khronos/wayland-egl/wayland-egl.c
+ create mode 100644 interface/khronos/wayland-egl/wayland-egl.pc.in
+ create mode 100644 interface/wayland/dispmanx.xml
+ create mode 100644 makefiles/cmake/Wayland.cmake
+
+Index: git/.gitignore
+===================================================================
+--- git.orig/.gitignore
++++ git/.gitignore
+@@ -30,3 +30,4 @@ build/
+ *.pts
+ *.ppm
+ *.mkv
++*~
+Index: git/CMakeLists.txt
+===================================================================
+--- git.orig/CMakeLists.txt
++++ git/CMakeLists.txt
+@@ -24,6 +24,17 @@ include(makefiles/cmake/global_settings.
+ include(makefiles/cmake/arm-linux.cmake)
+ include(makefiles/cmake/vmcs.cmake)
+
++if (BUILD_WAYLAND)
++ include(makefiles/cmake/Wayland.cmake)
++
++ # Find Wayland libraries
++ find_package(PkgConfig)
++ pkg_check_modules(WAYLAND_CLIENT wayland-client REQUIRED)
++ pkg_check_modules(WAYLAND_SERVER wayland-server REQUIRED)
++
++ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DBUILD_WAYLAND")
++endif()
++
+ enable_language(ASM)
+
+ # Global include paths
+Index: git/README.md
+===================================================================
+--- git.orig/README.md
++++ git/README.md
+@@ -6,3 +6,7 @@ Use buildme to build. It requires cmake
+ https://github.com/raspberrypi/tools/tree/master/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian
+
+ Note that this repository does not contain the source for the edid_parser and vcdbg binaries due to licensing restrictions.
++
++To build support for the Wayland winsys in EGL, execute the buildme script like this:
++
++$ BUILD_WAYLAND=1 ./buildme.
+Index: git/buildme
+===================================================================
+--- git.orig/buildme
++++ git/buildme
+@@ -8,6 +8,10 @@ fi
+
+ BUILDSUBDIR=`echo $BUILDTYPE | tr '[A-Z]' '[a-z]'`;
+
++if [ -n "$BUILD_WAYLAND" ]; then
++ WAYLAND_VARS="-DBUILD_WAYLAND=TRUE"
++fi
++
+ if [ "armv6l" = `arch` ] || [ "armv7l" = `arch` ]; then
+ # Native compile on the Raspberry Pi
+ mkdir -p build/raspberry/$BUILDSUBDIR
+@@ -32,9 +36,13 @@ elif [ "$1" = "--native" ]; then
+ make -j `nproc` $*
+ else
+ # Cross compile on a more capable machine
++ if [ -n "$BUILD_WAYLAND" ]; then
++ # Use wayland-scanner from the build platform
++ WAYLAND_VARS+=" -DWAYLAND_SCANNER_EXECUTABLE:FILEPATH=/usr/bin/wayland-scanner"
++ fi
+ mkdir -p build/arm-linux/$BUILDSUBDIR
+ pushd build/arm-linux/$BUILDSUBDIR
+- cmake -DCMAKE_TOOLCHAIN_FILE=../../../makefiles/cmake/toolchains/arm-linux-gnueabihf.cmake -DCMAKE_BUILD_TYPE=$BUILDTYPE ../../..
++ cmake -DCMAKE_TOOLCHAIN_FILE=../../../makefiles/cmake/toolchains/arm-linux-gnueabihf.cmake -DCMAKE_BUILD_TYPE=$BUILDTYPE $WAYLAND_VARS ../../..
+ make -j `nproc`
+
+ if [ "$1" != "" ]; then
+Index: git/host_applications/linux/apps/raspicam/CMakeLists.txt
+===================================================================
+--- git.orig/host_applications/linux/apps/raspicam/CMakeLists.txt
++++ git/host_applications/linux/apps/raspicam/CMakeLists.txt
+@@ -28,7 +28,7 @@ add_executable(raspividyuv ${COMMON_SOU
+
+ set (MMAL_LIBS mmal_core mmal_util mmal_vc_client)
+
+-target_link_libraries(raspistill ${MMAL_LIBS} vcos bcm_host brcmGLESv2 brcmEGL m)
++target_link_libraries(raspistill ${MMAL_LIBS} vcos bcm_host brcmGLESv2 brcmEGL m ${WAYLAND_SERVER_LIBRARIES} ${WAYLAND_CLIENT_LIBRARIES})
+ target_link_libraries(raspiyuv ${MMAL_LIBS} vcos bcm_host)
+ target_link_libraries(raspivid ${MMAL_LIBS} vcos bcm_host)
+ target_link_libraries(raspividyuv ${MMAL_LIBS} vcos bcm_host)
+Index: git/interface/khronos/CMakeLists.txt
+===================================================================
+--- git.orig/interface/khronos/CMakeLists.txt
++++ git/interface/khronos/CMakeLists.txt
+@@ -6,6 +6,12 @@
+ # have quite a few circular dependencies, and so the only way
+ # to make it work seems to be to have everything static.
+
++if (BUILD_WAYLAND)
++include_directories(
++ ${WAYLAND_SERVER_INCLUDE_DIRS}
++)
++endif ()
++
+ set(EGL_SOURCE
+ egl/egl_client_config.c
+ egl/egl_client_context.c
+@@ -55,12 +61,55 @@ set(CLIENT_SOURCE
+ common/khrn_int_hash_asm.s
+ common/khrn_client_cache.c)
+
++set(EGL_LIBS
++ khrn_client
++ vchiq_arm
++ vcos
++ bcm_host)
++
++if (BUILD_WAYLAND)
++ set(EGL_SOURCE
++ ${EGL_SOURCE}
++ ext/egl_wayland.c
++ common/linux/khrn_wayland.c)
++
++ set(EGL_LIBS
++ ${EGL_LIBS}
++ wayland-client
++ wayland-server)
++
++ set(WAYLAND_EGL_SOURCE
++ wayland-egl/wayland-egl.c)
++
++ wayland_add_protocol_server(
++ EGL_SOURCE
++ ../../interface/wayland/dispmanx.xml
++ dispmanx
++ )
++
++ wayland_add_protocol_client(
++ EGL_SOURCE
++ ../../interface/wayland/dispmanx.xml
++ dispmanx
++ )
++
++ add_library(wayland-egl ${SHARED} ${WAYLAND_EGL_SOURCE})
++ install(TARGETS wayland-egl DESTINATION lib)
++
++ configure_file ("wayland-egl/wayland-egl.pc.in" "wayland-egl/wayland-egl.pc" @ONLY)
++ install (FILES "${CMAKE_CURRENT_BINARY_DIR}/wayland-egl/wayland-egl.pc"
++ DESTINATION lib/pkgconfig)
++endif ()
++
+ add_library(EGL ${SHARED} ${EGL_SOURCE})
+ add_library(GLESv2 ${SHARED} ${GLES_SOURCE})
+ add_library(OpenVG ${SHARED} ${VG_SOURCE})
+ add_library(WFC ${SHARED} ${WFC_SOURCE})
+ add_library(khrn_client ${CLIENT_SOURCE})
+
++set_target_properties(EGL PROPERTIES SOVERSION 1 VERSION 1.0.0)
++set_target_properties(GLESv2 PROPERTIES SOVERSION 2 VERSION 2.0.0)
++
+ # TODO do we need EGL_static and GLESv2_static now that khrn_static exists?
+ add_library(EGL_static STATIC ${EGL_SOURCE})
+ add_library(GLESv2_static STATIC ${GLES_SOURCE})
+@@ -72,8 +121,7 @@ include_directories (../../host_applicat
+ set(VCSM_LIBS vcsm)
+ add_definitions(-DKHRONOS_HAVE_VCSM)
+ endif()
+-
+-target_link_libraries(EGL khrn_client vchiq_arm vcos bcm_host ${VCSM_LIBS} -lm)
++target_link_libraries(EGL ${EGL_LIBS} ${VCSM_LIBS} -lm)
+ target_link_libraries(GLESv2 EGL khrn_client vcos)
+ target_link_libraries(WFC EGL)
+ target_link_libraries(OpenVG EGL)
+@@ -87,7 +135,7 @@ add_library(brcmGLESv2 ${SHARED} ${GLES_
+ add_library(brcmOpenVG ${SHARED} ${VG_SOURCE})
+ add_library(brcmWFC ${SHARED} ${WFC_SOURCE})
+
+-target_link_libraries(brcmEGL khrn_client vchiq_arm vcos bcm_host ${VCSM_LIBS} -lm)
++target_link_libraries(brcmEGL ${EGL_LIBS} ${VCSM_LIBS} -lm)
+ target_link_libraries(brcmGLESv2 brcmEGL khrn_client vcos)
+ target_link_libraries(brcmWFC brcmEGL)
+ target_link_libraries(brcmOpenVG brcmEGL)
+Index: git/interface/khronos/common/khrn_client.c
+===================================================================
+--- git.orig/interface/khronos/common/khrn_client.c
++++ git/interface/khronos/common/khrn_client.c
+@@ -54,6 +54,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBI
+ #include "applications/vmcs/khronos/khronos_server.h"
+ #endif
+
++#ifdef BUILD_WAYLAND
++#include "interface/khronos/common/linux/khrn_wayland.h"
++#endif
++
+ VCOS_LOG_CAT_T khrn_client_log = VCOS_LOG_INIT("khrn_client", VCOS_LOG_WARN);
+
+ /*
+@@ -142,6 +146,10 @@ void client_try_unload_server(CLIENT_PRO
+ bool client_process_state_init(CLIENT_PROCESS_STATE_T *process)
+ {
+ if (!process->inited) {
++#ifdef BUILD_WAYLAND
++ process->wl_global = NULL;
++#endif
++
+ if (!khrn_pointer_map_init(&process->contexts, 64))
+ return false;
+
+@@ -194,6 +202,13 @@ bool client_process_state_init(CLIENT_PR
+ }
+ #endif
+
++#ifdef BUILD_WAYLAND
++ struct wl_display *wl_display = khrn_platform_get_wl_display();
++ if (wl_display)
++ if (!init_process_wayland(process))
++ return false;
++#endif
++
+ process->inited = true;
+ }
+
+Index: git/interface/khronos/common/khrn_client.h
+===================================================================
+--- git.orig/interface/khronos/common/khrn_client.h
++++ git/interface/khronos/common/khrn_client.h
+@@ -310,6 +310,16 @@ struct CLIENT_PROCESS_STATE {
+ #ifdef RPC_LIBRARY
+ KHRONOS_SERVER_CONNECTION_T khrn_connection;
+ #endif
++
++#ifdef BUILD_WAYLAND
++ /* Client-side Wayland state */
++ struct wl_registry *wl_registry;
++ struct wl_dispmanx *wl_dispmanx;
++ struct wl_event_queue *wl_queue;
++
++ /* Compositor-side Wayland state */
++ struct wl_global *wl_global;
++#endif
+ };
+
+ extern bool client_process_state_init(CLIENT_PROCESS_STATE_T *process);
+Index: git/interface/khronos/common/khrn_client_mangle.h
+===================================================================
+--- git.orig/interface/khronos/common/khrn_client_mangle.h
++++ git/interface/khronos/common/khrn_client_mangle.h
+@@ -83,6 +83,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBI
+ #define eglReleaseGlobalImageBRCM mangled_eglReleaseGlobalImageBRCM
+ #define eglInitGlobalImageBRCM mangled_eglInitGlobalImageBRCM
+ #define eglTermGlobalImageBRCM mangled_eglTermGlobalImageBRCM
++#define eglBindWaylandDisplayWL mangled_eglBindWaylandDisplayWL
++#define eglUnbindWaylandDisplayWL mangled_eglUnbindWaylandDisplayWL
++#define eglQueryWaylandBufferWL mangled_eglQueryWaylandBufferWL
+
+ /* OpenGL ES 1.1 and 2.0 functions */
+
+Index: git/interface/khronos/common/khrn_client_platform.h
+===================================================================
+--- git.orig/interface/khronos/common/khrn_client_platform.h
++++ git/interface/khronos/common/khrn_client_platform.h
+@@ -48,6 +48,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBI
+ #include "interface/khronos/common/vcos/khrn_client_platform_filler_vcos.h"
+ #endif
+
++#ifdef BUILD_WAYLAND
++#include <wayland-client.h>
++#endif
++
+ #ifdef __cplusplus
+ extern "C" {
+ #endif
+@@ -328,4 +332,8 @@ typedef struct
+
+ void *platform_wfc_bounce_thread(void *param);
+
++#ifdef BUILD_WAYLAND
++struct wl_display *khrn_platform_get_wl_display();
++#endif
++
+ #endif // KHRN_CLIENT_PLATFORM_H
+Index: git/interface/khronos/common/khrn_client_unmangle.h
+===================================================================
+--- git.orig/interface/khronos/common/khrn_client_unmangle.h
++++ git/interface/khronos/common/khrn_client_unmangle.h
+@@ -83,6 +83,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBI
+ #undef eglReleaseGlobalImageBRCM
+ #undef eglInitGlobalImageBRCM
+ #undef eglTermGlobalImageBRCM
++#undef eglBindWaylandDisplayWL
++#undef eglUnbindWaylandDisplayWL
++#undef eglQueryWaylandBufferWL
+
+ /* OpenGL ES 1.1 and 2.0 functions */
+
+Index: git/interface/khronos/common/linux/khrn_client_platform_linux.c
+===================================================================
+--- git.orig/interface/khronos/common/linux/khrn_client_platform_linux.c
++++ git/interface/khronos/common/linux/khrn_client_platform_linux.c
+@@ -37,6 +37,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBI
+ #include "X11/Xlib.h"
+ #endif
+
++#ifdef BUILD_WAYLAND
++#include <wayland-client.h>
++#include "interface/khronos/wayland-egl/wayland-egl-priv.h"
++#endif
++
+ extern VCOS_LOG_CAT_T khrn_client_log;
+
+ extern void vc_vchi_khronos_init();
+@@ -464,14 +469,37 @@ EGLDisplay khrn_platform_set_display_id(
+ return EGL_NO_DISPLAY;
+ }
+ #else
++
++#ifdef BUILD_WAYLAND
++static struct wl_display *hacky_display = NULL;
++#endif
++
+ EGLDisplay khrn_platform_set_display_id(EGLNativeDisplayType display_id)
+ {
+ if (display_id == EGL_DEFAULT_DISPLAY)
+ return (EGLDisplay)1;
+- else
+- return EGL_NO_DISPLAY;
++ else {
++#ifdef BUILD_WAYLAND
++ void *first_pointer = *(void **) display_id;
++
++ /* wl_display is a wl_proxy, which is a wl_object.
++ * wl_object's first element points to the interfacetype. */
++ if (first_pointer == &wl_display_interface) {
++ hacky_display = (struct wl_display*)display_id;
++ return (EGLDisplay)1;
++ } else
++#endif
++ return EGL_NO_DISPLAY;
++ }
++}
++
++#ifdef BUILD_WAYLAND
++struct wl_display *khrn_platform_get_wl_display()
++{
++ return hacky_display;
+ }
+ #endif
++#endif
+
+ #ifdef WANT_X
+ static void dump_hierarchy(Window w, Window thisw, Window look, int level)
+@@ -805,22 +833,81 @@ static EGL_DISPMANX_WINDOW_T *check_defa
+ void platform_get_dimensions(EGLDisplay dpy, EGLNativeWindowType win,
+ uint32_t *width, uint32_t *height, uint32_t *swapchain_count)
+ {
+- EGL_DISPMANX_WINDOW_T *dwin = check_default(win);
+- vcos_assert(dwin);
+- vcos_assert(dwin->width < 1<<16); // sanity check
+- vcos_assert(dwin->height < 1<<16); // sanity check
+- *width = dwin->width;
+- *height = dwin->height;
+- *swapchain_count = 0;
++#ifdef BUILD_WAYLAND
++ if(khrn_platform_get_wl_display()) {
++ struct wl_egl_window *wl_egl_window = (struct wl_egl_window*)win;
++ *width = wl_egl_window->width;
++ *height = wl_egl_window->height;
++ /* This seems to be used for sync'ing with the VC on buffer creation, but
++ we are managing them on the CPU side */
++ *swapchain_count = 1;
++ } else {
++#endif
++ EGL_DISPMANX_WINDOW_T *dwin = check_default(win);
++ vcos_assert(dwin);
++ vcos_assert(dwin->width < 1<<16); // sanity check
++ vcos_assert(dwin->height < 1<<16); // sanity check
++ *width = dwin->width;
++ *height = dwin->height;
++ *swapchain_count = 0;
++#ifdef BUILD_WAYLAND
++ }
++#endif
++}
++
++#ifdef BUILD_WAYLAND
++static DISPMANX_ELEMENT_HANDLE_T create_dummy_element()
++{
++ DISPMANX_DISPLAY_HANDLE_T display = vc_dispmanx_display_open(0);
++ DISPMANX_UPDATE_HANDLE_T update = vc_dispmanx_update_start(0);
++ DISPMANX_ELEMENT_HANDLE_T element;
++ VC_DISPMANX_ALPHA_T alpha = {DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS, 255, 0};
++ VC_RECT_T src_rect;
++ VC_RECT_T dst_rect;
++
++ src_rect.x = 0;
++ src_rect.y = 0;
++ src_rect.width = 1 << 16;
++ src_rect.height = 1 << 16;
++
++ dst_rect.x = 0;
++ dst_rect.y = 0;
++ dst_rect.width = 1;
++ dst_rect.height = 1;
++
++ element = vc_dispmanx_element_add(update, display, 0/*layer*/, &dst_rect,
++ 0/*src*/, &src_rect,
++ DISPMANX_PROTECTION_NONE, &alpha,
++ 0/*clamp*/, 0/*transform*/);
++
++ vc_dispmanx_update_submit_sync(update);
++
++ vc_dispmanx_display_close(display);
++
++ return element;
+ }
++#endif
+
+ uint32_t platform_get_handle(EGLDisplay dpy, EGLNativeWindowType win)
+ {
+- EGL_DISPMANX_WINDOW_T *dwin = check_default(win);
+- vcos_assert(dwin);
+- vcos_assert(dwin->width < 1<<16); // sanity check
+- vcos_assert(dwin->height < 1<<16); // sanity check
+- return dwin->element;
++#ifdef BUILD_WAYLAND
++ if(khrn_platform_get_wl_display()) {
++ struct wl_egl_window *wl_egl_window = (struct wl_egl_window*)win;
++
++ if (wl_egl_window->dummy_element == PLATFORM_WIN_NONE)
++ wl_egl_window->dummy_element = create_dummy_element();
++
++ return wl_egl_window->dummy_element;
++ } else {
++#endif
++ EGL_DISPMANX_WINDOW_T *dwin = check_default(win);
++ vcos_assert(dwin);
++ vcos_assert(dwin->width < 1<<16); // sanity check
++ vcos_assert(dwin->height < 1<<16); // sanity check
++ return dwin->element;
++#ifdef BUILD_WAYLAND
++ }
++#endif
+ }
+
+ #endif
+Index: git/interface/khronos/common/linux/khrn_wayland.c
+===================================================================
+--- /dev/null
++++ git/interface/khronos/common/linux/khrn_wayland.c
+@@ -0,0 +1,215 @@
++/*
++Copyright (c) 2013, Raspberry Pi Foundation
++All rights reserved.
++
++Redistribution and use in source and binary forms, with or without
++modification, are permitted provided that the following conditions are met:
++ * Redistributions of source code must retain the above copyright
++ notice, this list of conditions and the following disclaimer.
++ * Redistributions in binary form must reproduce the above copyright
++ notice, this list of conditions and the following disclaimer in the
++ documentation and/or other materials provided with the distribution.
++ * Neither the name of the copyright holder nor the
++ names of its contributors may be used to endorse or promote products
++ derived from this software without specific prior written permission.
++
++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
++DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
++ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
++SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++*/
++
++#define VCOS_LOG_CATEGORY (&khrn_client_log)
++
++#include "interface/khronos/common/linux/khrn_wayland.h"
++#include "interface/khronos/wayland-dispmanx-client-protocol.h"
++#include "interface/khronos/wayland-egl/wayland-egl-priv.h"
++
++extern VCOS_LOG_CAT_T khrn_client_log;
++
++static void handle_dispmanx_format(void *data, struct wl_dispmanx *dispmanx,
++ uint32_t format)
++{
++}
++
++static void handle_dispmanx_allocated(void *data, struct wl_dispmanx *dispmanx,
++ struct wl_buffer *wl_buffer,
++ uint32_t resource_handle)
++{
++ struct wl_dispmanx_client_buffer *buffer = wl_buffer_get_user_data(wl_buffer);
++
++ buffer->pending_allocation = 0;
++ buffer->resource = resource_handle;
++}
++
++static const struct wl_dispmanx_listener dispmanx_listener = {
++ handle_dispmanx_format,
++ handle_dispmanx_allocated,
++};
++
++static void
++sync_callback(void *data, struct wl_callback *callback, uint32_t serial)
++{
++ int *done = data;
++
++ *done = 1;
++
++ wl_callback_destroy(callback);
++}
++
++static const struct wl_callback_listener sync_listener = {
++ sync_callback
++};
++
++static int
++roundtrip(CLIENT_PROCESS_STATE_T *process)
++{
++ struct wl_display *wl_display = khrn_platform_get_wl_display();
++ struct wl_callback *callback;
++ int done = 0, ret = 0;
++
++ callback = wl_display_sync(wl_display);
++ wl_callback_add_listener(callback, &sync_listener, &done);
++ wl_proxy_set_queue((struct wl_proxy *) callback, process->wl_queue);
++ while (ret != -1 && !done)
++ ret = wl_display_dispatch_queue(wl_display, process->wl_queue);
++
++ if (!done)
++ wl_callback_destroy(callback);
++
++ return ret;
++}
++
++int do_wl_roundtrip()
++{
++ CLIENT_PROCESS_STATE_T *process = CLIENT_GET_PROCESS_STATE();
++ return roundtrip(process);
++}
++
++static void
++registry_handle_global(void *data, struct wl_registry *registry,
++ uint32_t name, const char *interface, uint32_t version)
++{
++ struct wl_display *wl_display = khrn_platform_get_wl_display();
++ CLIENT_PROCESS_STATE_T *process = (CLIENT_PROCESS_STATE_T *)data;
++
++ if (strcmp(interface, "wl_dispmanx") == 0) {
++ process->wl_dispmanx = wl_registry_bind(registry, name,
++ &wl_dispmanx_interface, 1);
++
++ wl_proxy_set_queue((struct wl_proxy *) process->wl_dispmanx,
++ process->wl_queue);
++ wl_dispmanx_add_listener(process->wl_dispmanx, &dispmanx_listener, wl_display);
++ roundtrip(process);
++ }
++}
++
++static void
++registry_handle_global_remove(void *data, struct wl_registry *registry,
++ uint32_t name)
++{
++}
++
++static const struct wl_registry_listener registry_listener = {
++ registry_handle_global,
++ registry_handle_global_remove
++};
++
++int
++init_process_wayland(CLIENT_PROCESS_STATE_T *process)
++{
++ struct wl_display *wl_display = khrn_platform_get_wl_display();
++
++ process->wl_queue = wl_display_create_queue(wl_display);
++ if (!process->wl_queue) {
++ vcos_log_error("wl_display_create_queue failed\n");
++ return false;
++ }
++ wl_display_dispatch_pending(wl_display);
++
++ process->wl_registry = wl_display_get_registry(wl_display);
++ if (!process->wl_registry) {
++ vcos_log_error("wl_display_get_registry failed\n");
++ return false;
++ }
++
++ wl_proxy_set_queue((struct wl_proxy *) process->wl_registry,
++ process->wl_queue);
++
++ wl_registry_add_listener(process->wl_registry, &registry_listener, process);
++
++ if (roundtrip(process) < 0 || process->wl_dispmanx == NULL) {
++ vcos_log_error("failed to get wl_dispmanx\n");
++ return false;
++ }
++
++ return true;
++}
++
++#ifndef ALIGN_UP
++#define ALIGN_UP(x,y) ((x + (y)-1) & ~((y)-1))
++#endif
++
++static void handle_buffer_release(void *data, struct wl_buffer *buffer_wl)
++{
++ struct wl_dispmanx_client_buffer *wl_dispmanx_client_buffer = data;
++ wl_dispmanx_client_buffer->in_use = 0;
++}
++
++static const struct wl_buffer_listener buffer_listener = {
++ handle_buffer_release
++};
++
++struct wl_dispmanx_client_buffer *
++allocate_wl_buffer(struct wl_egl_window *window, KHRN_IMAGE_FORMAT_T color)
++{
++ CLIENT_PROCESS_STATE_T *process = CLIENT_GET_PROCESS_STATE();
++ struct wl_dispmanx_client_buffer *wl_dispmanx_client_buffer;
++ struct wl_buffer *wl_buffer;
++ uint32_t stride = ALIGN_UP(window->width * 4, 16);
++ uint32_t buffer_height = ALIGN_UP(window->height, 16);
++ enum wl_dispmanx_format color_format;
++ int ret = 0;
++
++ switch (color) {
++ case ABGR_8888:
++ color_format = WL_DISPMANX_FORMAT_ABGR8888;
++ break;
++ case XBGR_8888:
++ color_format = WL_DISPMANX_FORMAT_XBGR8888;
++ break;
++ case RGB_565:
++ color_format = WL_DISPMANX_FORMAT_RGB565;
++ break;
++ default:
++ vcos_log_error("unknown KHRN_IMAGE_FORMAT_T 0x%x\n", color);
++ return NULL;
++ }
++
++ wl_buffer = wl_dispmanx_create_buffer(process->wl_dispmanx, window->width,
++ window->height, stride, buffer_height,
++ color_format);
++ if (wl_buffer == NULL)
++ return NULL;
++
++ wl_dispmanx_client_buffer = calloc(1, sizeof(struct wl_dispmanx_client_buffer));
++ wl_dispmanx_client_buffer->wl_buffer = wl_buffer;
++ wl_dispmanx_client_buffer->in_use = 0;
++ wl_dispmanx_client_buffer->pending_allocation = 1;
++ wl_dispmanx_client_buffer->width = window->width;
++ wl_dispmanx_client_buffer->height = window->height;
++
++ wl_proxy_set_queue((struct wl_proxy *) wl_buffer, process->wl_queue);
++ wl_buffer_add_listener(wl_buffer, &buffer_listener, wl_dispmanx_client_buffer);
++
++ while (ret != -1 && wl_dispmanx_client_buffer->pending_allocation)
++ ret = do_wl_roundtrip();
++
++ return wl_dispmanx_client_buffer;
++}
+Index: git/interface/vmcs_host/vc_vchi_dispmanx.h
+===================================================================
+--- git.orig/interface/vmcs_host/vc_vchi_dispmanx.h
++++ git/interface/vmcs_host/vc_vchi_dispmanx.h
+@@ -66,4 +66,19 @@ typedef struct {
+ #define ELEMENT_CHANGE_MASK_RESOURCE (1<<4)
+ #define ELEMENT_CHANGE_TRANSFORM (1<<5)
+
++#ifdef BUILD_WAYLAND
++/* XXX: This should be in a private header that can be included from EGL and vc_* */
++#include <wayland-server.h>
++#include "interface/vmcs_host/wayland-dispmanx-server-protocol.h"
++struct wl_dispmanx_server_buffer {
++ struct wl_resource *resource;
++ struct wl_dispmanx *dispmanx;
++ enum wl_dispmanx_format format;
++ DISPMANX_RESOURCE_HANDLE_T handle;
++ int32_t width;
++ int32_t height;
++ int in_use;
++};
++#endif
++
+ #endif
+Index: git/interface/khronos/common/linux/khrn_wayland.h
+===================================================================
+--- /dev/null
++++ git/interface/khronos/common/linux/khrn_wayland.h
+@@ -0,0 +1,33 @@
++/*
++Copyright (c) 2013, Raspberry Pi Foundation
++All rights reserved.
++
++Redistribution and use in source and binary forms, with or without
++modification, are permitted provided that the following conditions are met:
++ * Redistributions of source code must retain the above copyright
++ notice, this list of conditions and the following disclaimer.
++ * Redistributions in binary form must reproduce the above copyright
++ notice, this list of conditions and the following disclaimer in the
++ documentation and/or other materials provided with the distribution.
++ * Neither the name of the copyright holder nor the
++ names of its contributors may be used to endorse or promote products
++ derived from this software without specific prior written permission.
++
++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
++DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
++ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
++SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++*/
++
++#include "interface/khronos/common/khrn_client.h"
++
++int init_process_wayland(CLIENT_PROCESS_STATE_T *process);
++int do_wl_roundtrip();
++
++struct wl_dispmanx_client_buffer *allocate_wl_buffer(struct wl_egl_window *window, KHRN_IMAGE_FORMAT_T color);
+Index: git/interface/khronos/egl/egl_client.c
+===================================================================
+--- git.orig/interface/khronos/egl/egl_client.c
++++ git/interface/khronos/egl/egl_client.c
+@@ -153,6 +153,10 @@ by an attribute value"
+ #include <stdlib.h>
+ #include <string.h>
+
++#ifdef BUILD_WAYLAND
++#include "interface/khronos/wayland-egl/wayland-egl-priv.h"
++#include "interface/khronos/common/linux/khrn_wayland.h"
++#endif
+
+ #include "interface/khronos/egl/egl_client_cr.c"
+
+@@ -162,17 +166,6 @@ static void egl_current_release(CLIENT_P
+ void egl_gl_flush_callback(bool wait);
+ void egl_vg_flush_callback(bool wait);
+
+-#include "interface/vmcs_host/vc_dispmanx_types.h"
+-/**HACKHACK - give us the ability to inject a DispmanX
+- * resource handle into the CreateWindowSurface and
+- * SwapBuffers calls */
+-static DISPMANX_RESOURCE_HANDLE_T next_resource_handle;
+-
+-EGLAPI EGLBoolean EGLAPIENTRY eglSetNextResourceHandle(DISPMANX_RESOURCE_HANDLE_T handle)
+-{
+- next_resource_handle = handle;
+-}
+-
+ /*
+ TODO: do an RPC call to make sure the Khronos vll is loaded (and that it stays loaded until eglTerminate)
+ Also affects global image (and possibly others?)
+@@ -451,6 +444,9 @@ EGLAPI const char EGLAPIENTRY * eglQuery
+ "EGL_KHR_fence_sync "
+ #endif
+ #endif
++#if EGL_WL_bind_wayland_display
++ "EGL_WL_bind_wayland_display "
++#endif
+ ;
+ break;
+ case EGL_VENDOR:
+@@ -655,8 +651,7 @@ EGLAPI EGLSurface EGLAPIENTRY eglCreateW
+ false,
+ EGL_NO_TEXTURE,
+ EGL_NO_TEXTURE,
+- 0, 0,
+- next_resource_handle);
++ 0, 0);
+
+ if (surface) {
+ if (khrn_pointer_map_insert(&process->surfaces, process->next_surface, surface)) {
+@@ -901,7 +896,7 @@ EGLAPI EGLSurface EGLAPIENTRY eglCreateP
+ mipmap_texture,
+ texture_format,
+ texture_target,
+- 0, 0, 0);
++ 0, 0);
+
+ if (surface) {
+ if (khrn_pointer_map_insert(&process->surfaces, process->next_surface, surface)) {
+@@ -1043,7 +1038,7 @@ EGLAPI EGLSurface EGLAPIENTRY eglCreateP
+ false,
+ EGL_NO_TEXTURE,
+ EGL_NO_TEXTURE,
+- pixmap, ((server_handle[0] == 0) && (server_handle[1] == (uint32_t)(-1))) ? NULL : server_handle, 0);
++ pixmap, ((server_handle[0] == 0) && (server_handle[1] == (uint32_t)(-1))) ? NULL : server_handle);
+
+ if (surface) {
+ if (khrn_pointer_map_insert(&process->surfaces, process->next_surface, surface)) {
+@@ -2245,6 +2240,9 @@ EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuf
+ CLIENT_THREAD_STATE_T *thread;
+ CLIENT_PROCESS_STATE_T *process;
+ EGLBoolean result;
++#ifdef BUILD_WAYLAND
++ struct wl_display *wl_display = khrn_platform_get_wl_display();
++#endif
+
+ vcos_log_trace("eglSwapBuffers start. dpy=%d. surf=%d.", (int)dpy, (int)surf);
+
+@@ -2315,18 +2313,58 @@ EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuf
+
+ vcos_log_trace("eglSwapBuffers server call");
+
+- if (next_resource_handle)
+- RPC_CALL7(eglIntSwapBuffers_impl,
+- thread,
+- EGLINTSWAPBUFFERS_ID_V2,
+- RPC_UINT(surface->serverbuffer),
+- RPC_UINT(surface->width),
+- RPC_UINT(surface->height),
+- RPC_UINT(surface->internal_handle),
+- RPC_UINT(surface->swap_behavior == EGL_BUFFER_PRESERVED ? 1 : 0),
+- RPC_UINT(khrn_platform_get_window_position(surface->win)),
+- RPC_INT(next_resource_handle));
+- else
++#ifdef BUILD_WAYLAND
++ if (wl_display) {
++ struct wl_egl_window *wl_egl_window = surface->wl_egl_window;
++ struct wl_dispmanx_client_buffer *buffer_temp;
++ uint32_t configid;
++ KHRN_IMAGE_FORMAT_T color;
++ int ret = 0;
++
++ buffer_temp = surface->front_wl_buffer;
++ surface->front_wl_buffer = surface->back_wl_buffer;
++ surface->back_wl_buffer = buffer_temp;
++
++ configid = egl_config_to_id(surface->config);
++ color = egl_config_get_color_format(configid);
++
++ if (surface->back_wl_buffer == NULL)
++ surface->back_wl_buffer = allocate_wl_buffer(wl_egl_window, color);
++ else if (surface->back_wl_buffer->width != width ||
++ surface->back_wl_buffer->height != height) {
++
++ struct wl_dispmanx_client_buffer *buffer;
++
++ wl_buffer_destroy(surface->back_wl_buffer->wl_buffer);
++ free(surface->back_wl_buffer);
++
++ buffer = allocate_wl_buffer(wl_egl_window, color);
++ surface->back_wl_buffer = buffer;
++ }
++
++ RPC_CALL7(eglIntSwapBuffers_impl,
++ thread,
++ EGLINTSWAPBUFFERS_ID_V2,
++ RPC_UINT(surface->serverbuffer),
++ RPC_UINT(surface->width),
++ RPC_UINT(surface->height),
++ RPC_UINT(surface->internal_handle),
++ RPC_UINT(surface->swap_behavior == EGL_BUFFER_PRESERVED ? 1 : 0),
++ RPC_UINT(khrn_platform_get_window_position(surface->win)),
++ RPC_INT(surface->back_wl_buffer->resource));
++
++ surface->front_wl_buffer->in_use = 1;
++ wl_surface_attach(wl_egl_window->wl_surface,
++ surface->front_wl_buffer->wl_buffer,
++ 0, 0);
++ wl_surface_damage(wl_egl_window->wl_surface, 0, 0,
++ surface->width, surface->height);
++ wl_surface_commit(wl_egl_window->wl_surface);
++
++ while(ret != -1 && surface->back_wl_buffer->in_use)
++ ret = wl_display_dispatch_queue(wl_display, process->wl_queue);
++ } else
++#endif
+ RPC_CALL6(eglIntSwapBuffers_impl,
+ thread,
+ EGLINTSWAPBUFFERS_ID,
+Index: git/interface/khronos/egl/egl_client_get_proc.c
+===================================================================
+--- git.orig/interface/khronos/egl/egl_client_get_proc.c
++++ git/interface/khronos/egl/egl_client_get_proc.c
+@@ -254,6 +254,17 @@ EGLAPI void EGLAPIENTRY (* eglGetProcAdd
+ return (void(*)(void))eglQueryGlobalImageBRCM;
+ #endif
+
++#ifdef BUILD_WAYLAND
++#if EGL_WL_bind_wayland_display
++ if (!strcmp(procname, "eglBindWaylandDisplayWL"))
++ return (void(*)(void))eglBindWaylandDisplayWL;
++ if (!strcmp(procname, "eglUnbindWaylandDisplayWL"))
++ return (void(*)(void))eglUnbindWaylandDisplayWL;
++ if (!strcmp(procname, "eglQueryWaylandBufferWL"))
++ return (void(*)(void))eglQueryWaylandBufferWL;
++#endif
++#endif
++
+ return (void(*)(void)) NULL;
+ }
+
+Index: git/interface/khronos/egl/egl_client_surface.c
+===================================================================
+--- git.orig/interface/khronos/egl/egl_client_surface.c
++++ git/interface/khronos/egl/egl_client_surface.c
+@@ -46,6 +46,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBI
+ #include "interface/khronos/egl/egl_int_impl.h"
+ #endif
+
++#ifdef BUILD_WAYLAND
++#include "interface/khronos/wayland-egl/wayland-egl-priv.h"
++#include "interface/khronos/common/linux/khrn_wayland.h"
++#endif
++
+ #include <stdlib.h>
+
+
+@@ -314,8 +319,7 @@ EGL_SURFACE_T *egl_surface_create(
+ EGLenum texture_format,
+ EGLenum texture_target,
+ EGLNativePixmapType pixmap,
+- const uint32_t *pixmap_server_handle,
+- DISPMANX_RESOURCE_HANDLE_T next_resource_handle)
++ const uint32_t *pixmap_server_handle)
+ {
+ KHRN_IMAGE_FORMAT_T color;
+ KHRN_IMAGE_FORMAT_T depth;
+@@ -326,6 +330,10 @@ EGL_SURFACE_T *egl_surface_create(
+ EGLint config_depth_bits;
+ EGLint config_stencil_bits;
+ CLIENT_THREAD_STATE_T *thread = CLIENT_GET_THREAD_STATE();
++#ifdef BUILD_WAYLAND
++ struct wl_display *wl_display = khrn_platform_get_wl_display();
++ DISPMANX_RESOURCE_HANDLE_T resource;
++#endif
+
+ EGL_SURFACE_T *surface = egl_surface_pool_alloc();
+
+@@ -390,6 +398,18 @@ EGL_SURFACE_T *egl_surface_create(
+
+ vcos_assert(color != IMAGE_FORMAT_INVALID);
+
++#ifdef BUILD_WAYLAND
++ if (type == WINDOW && wl_display) {
++ surface->wl_egl_window = (struct wl_egl_window*)win;
++ surface->back_wl_buffer = allocate_wl_buffer(
++ surface->wl_egl_window, color);
++ resource = surface->back_wl_buffer->resource;
++ } else {
++ surface->wl_egl_window = NULL;
++ resource = DISPMANX_NO_HANDLE;
++ }
++#endif
++
+ #ifdef KHRONOS_EGL_PLATFORM_OPENWFC
+ // Create stream for this window
+ if(type != PBUFFER)
+@@ -474,7 +494,8 @@ EGL_SURFACE_T *egl_surface_create(
+ #endif
+ uint32_t results[3];
+
+- if (next_resource_handle)
++#ifdef BUILD_WAYLAND
++ if (resource != DISPMANX_NO_HANDLE)
+ RPC_CALL16_OUT_CTRL(eglIntCreateSurface_impl,
+ thread,
+ EGLINTCREATESURFACE_ID_V2,
+@@ -492,9 +513,10 @@ EGL_SURFACE_T *egl_surface_create(
+ RPC_UINT(config_stencil_bits),
+ RPC_UINT(sem_name),
+ RPC_UINT(type),
+- RPC_INT(next_resource_handle),
++ RPC_INT(resource),
+ results);
+ else
++#endif
+ RPC_CALL15_OUT_CTRL(eglIntCreateSurface_impl,
+ thread,
+ EGLINTCREATESURFACE_ID,
+@@ -663,6 +685,18 @@ void egl_surface_free(EGL_SURFACE_T *sur
+ if( surface->type == WINDOW ) {
+ vcos_log_trace("egl_surface_free: calling platform_destroy_winhandle...");
+ platform_destroy_winhandle( surface->win, surface->internal_handle );
++
++#ifdef BUILD_WAYLAND
++ if (surface->back_wl_buffer) {
++ wl_buffer_destroy(surface->back_wl_buffer->wl_buffer);
++ free(surface->back_wl_buffer);
++ }
++
++ if (surface->front_wl_buffer) {
++ wl_buffer_destroy(surface->front_wl_buffer->wl_buffer);
++ free(surface->front_wl_buffer);
++ }
++#endif
+ }
+ /* return value ignored -- read performed to ensure blocking. we want this to
+ * block so clients can safely destroy the surface's window as soon as the
+Index: git/interface/khronos/egl/egl_client_surface.h
+===================================================================
+--- git.orig/interface/khronos/egl/egl_client_surface.h
++++ git/interface/khronos/egl/egl_client_surface.h
+@@ -288,6 +288,41 @@ typedef struct {
+ type == PIXMAP
+ */
+ bool server_owned;
++
++#ifdef BUILD_WAYLAND
++ /*
++ wl_egl_window
++
++ Validity:
++ type == WINDOW
++
++ Invariant:
++ wayland EGL window
++ */
++ struct wl_egl_window *wl_egl_window;
++
++ /*
++ front_wl_buffer
++
++ Validity:
++ type == WINDOW
++
++ Invariant:
++ client-side information about the wl_buffer in the front
++ */
++ struct wl_dispmanx_client_buffer *front_wl_buffer;
++
++ /*
++ back_wl_buffer
++
++ Validity:
++ type == WINDOW
++
++ Invariant:
++ client-side information about the wl_buffer in the back
++ */
++ struct wl_dispmanx_client_buffer *back_wl_buffer;
++#endif
+ } EGL_SURFACE_T;
+
+ extern bool egl_surface_check_attribs(
+@@ -322,8 +357,7 @@ extern EGL_SURFACE_T *egl_surface_create
+ EGLenum texture_format,
+ EGLenum texture_target,
+ EGLNativePixmapType pixmap,
+- const uint32_t *pixmap_server_handle,
+- DISPMANX_RESOURCE_HANDLE_T next_resource_handle);
++ const uint32_t *pixmap_server_handle);
+ extern EGL_SURFACE_T *egl_surface_from_vg_image(
+ VGImage vg_handle,
+ EGLSurface name,
+Index: git/interface/khronos/egl/egl_int_impl.h
+===================================================================
+--- git.orig/interface/khronos/egl/egl_int_impl.h
++++ git/interface/khronos/egl/egl_int_impl.h
+@@ -57,7 +57,7 @@ FN(int, eglIntCreateSurface_impl, (
+ uint32_t sem,
+ uint32_t type,
+ uint32_t *results,
+- DISPMANX_RESOURCE_HANDLE_T next_resource_handle))
++ DISPMANX_RESOURCE_HANDLE_T resource_handle))
+
+ FN(int, eglIntCreatePbufferFromVGImage_impl, (
+ VGImage vg_handle,
+Index: git/interface/khronos/ext/egl_wayland.c
+===================================================================
+--- /dev/null
++++ git/interface/khronos/ext/egl_wayland.c
+@@ -0,0 +1,246 @@
++/*
++Copyright (c) 2013, Raspberry Pi Foundation
++All rights reserved.
++
++Redistribution and use in source and binary forms, with or without
++modification, are permitted provided that the following conditions are met:
++ * Redistributions of source code must retain the above copyright
++ notice, this list of conditions and the following disclaimer.
++ * Redistributions in binary form must reproduce the above copyright
++ notice, this list of conditions and the following disclaimer in the
++ documentation and/or other materials provided with the distribution.
++ * Neither the name of the copyright holder nor the
++ names of its contributors may be used to endorse or promote products
++ derived from this software without specific prior written permission.
++
++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
++DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
++ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
++SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++*/
++
++#include "interface/khronos/common/khrn_client_mangle.h"
++#include "interface/khronos/common/khrn_client_rpc.h"
++
++#include "interface/khronos/ext/egl_khr_sync_client.h"
++#include "interface/khronos/include/EGL/egl.h"
++#include "interface/khronos/include/EGL/eglext.h"
++
++#include "interface/vmcs_host/vc_vchi_dispmanx.h"
++
++#include <wayland-server.h>
++#include "interface/khronos/wayland-dispmanx-server-protocol.h"
++
++static void
++destroy_buffer(struct wl_resource *resource)
++{
++ struct wl_dispmanx_server_buffer *buffer = wl_resource_get_user_data(resource);
++
++ if(!buffer->in_use)
++ vc_dispmanx_resource_delete(buffer->handle);
++
++ free(buffer);
++}
++
++static void
++buffer_destroy(struct wl_client *client, struct wl_resource *resource)
++{
++ wl_resource_destroy(resource);
++}
++
++static const struct wl_buffer_interface dispmanx_buffer_interface = {
++ buffer_destroy
++};
++
++static VC_IMAGE_TYPE_T
++get_vc_format(enum wl_dispmanx_format format)
++{
++ /* XXX: The app is likely to have been premultiplying in its shaders,
++ * but the VC scanout hardware on the RPi cannot mix premultiplied alpha
++ * channel with the element's alpha.
++ */
++ switch (format) {
++ case WL_DISPMANX_FORMAT_ABGR8888:
++ return VC_IMAGE_RGBA32;
++ case WL_DISPMANX_FORMAT_XBGR8888:
++ return VC_IMAGE_BGRX8888;
++ case WL_DISPMANX_FORMAT_RGB565:
++ return VC_IMAGE_RGB565;
++ default:
++ /* invalid format */
++ return VC_IMAGE_MIN;
++ }
++}
++
++static void
++dispmanx_create_buffer(struct wl_client *client, struct wl_resource *resource,
++ uint32_t id, int32_t width, int32_t height,
++ uint32_t stride, uint32_t buffer_height, uint32_t format)
++{
++ struct wl_dispmanx_server_buffer *buffer;
++ VC_IMAGE_TYPE_T vc_format = get_vc_format(format);
++ uint32_t dummy;
++
++ if(vc_format == VC_IMAGE_MIN) {
++ wl_resource_post_error(resource,
++ WL_DISPMANX_ERROR_INVALID_FORMAT,
++ "invalid format");
++ return;
++ }
++
++ buffer = calloc(1, sizeof *buffer);
++ if (buffer == NULL) {
++ wl_resource_post_no_memory(resource);
++ return;
++ }
++
++ buffer->handle = vc_dispmanx_resource_create(vc_format,
++ width | (stride << 16),
++ height | (buffer_height << 16),
++ &dummy);
++ if(buffer->handle == DISPMANX_NO_HANDLE) {
++ wl_resource_post_error(resource,
++ WL_DISPMANX_ERROR_ALLOC_FAILED,
++ "allocation failed");
++ free(buffer);
++ return;
++ }
++
++ buffer->width = width;
++ buffer->height = height;
++ buffer->format = format;
++
++ buffer->resource = wl_resource_create(resource->client, &wl_buffer_interface,
++ 1, id);
++ if (!buffer->resource) {
++ wl_resource_post_no_memory(resource);
++ vc_dispmanx_resource_delete(buffer->handle);
++ free(buffer);
++ return;
++ }
++
++ wl_resource_set_implementation(buffer->resource,
++ (void (**)(void)) &dispmanx_buffer_interface,
++ buffer, destroy_buffer);
++
++ wl_dispmanx_send_buffer_allocated(resource, buffer->resource,
++ buffer->handle);
++}
++
++static const struct wl_dispmanx_interface dispmanx_interface = {
++ dispmanx_create_buffer,
++};
++
++static void
++bind_dispmanx(struct wl_client *client, void *data, uint32_t version, uint32_t id)
++{
++ struct wl_resource *resource;
++
++ resource = wl_resource_create(client, &wl_dispmanx_interface, 1, id);
++ wl_resource_set_implementation(resource, &dispmanx_interface, NULL, NULL);
++
++ wl_resource_post_event(resource, WL_DISPMANX_FORMAT,
++ WL_DISPMANX_FORMAT_ARGB8888);
++
++ wl_resource_post_event(resource, WL_DISPMANX_FORMAT,
++ WL_DISPMANX_FORMAT_XRGB8888);
++
++ wl_resource_post_event(resource, WL_DISPMANX_FORMAT,
++ WL_DISPMANX_FORMAT_ABGR8888);
++
++ wl_resource_post_event(resource, WL_DISPMANX_FORMAT,
++ WL_DISPMANX_FORMAT_XBGR8888);
++
++ wl_resource_post_event(resource, WL_DISPMANX_FORMAT,
++ WL_DISPMANX_FORMAT_RGB565);
++}
++
++EGLBoolean EGLAPIENTRY
++eglBindWaylandDisplayWL(EGLDisplay dpy, struct wl_display *display)
++{
++ CLIENT_THREAD_STATE_T *thread;
++ CLIENT_PROCESS_STATE_T *process;
++
++ if (!CLIENT_LOCK_AND_GET_STATES(dpy, &thread, &process))
++ return EGL_FALSE;
++
++ if (process->wl_global != NULL)
++ goto error;
++
++ process->wl_global = wl_global_create(display, &wl_dispmanx_interface, 1,
++ NULL, bind_dispmanx);
++ if (process->wl_global == NULL)
++ goto error;
++
++ return EGL_TRUE;
++
++error:
++ CLIENT_UNLOCK();
++ return EGL_FALSE;
++}
++
++EGLBoolean EGLAPIENTRY
++eglUnbindWaylandDisplayWL(EGLDisplay dpy, struct wl_display *display)
++{
++ CLIENT_THREAD_STATE_T *thread;
++ CLIENT_PROCESS_STATE_T *process;
++
++ if (!CLIENT_LOCK_AND_GET_STATES(dpy, &thread, &process))
++ return EGL_FALSE;
++
++ wl_global_destroy(process->wl_global);
++ process->wl_global = NULL;
++
++ CLIENT_UNLOCK();
++
++ return EGL_TRUE;
++}
++
++static int
++get_egl_format(enum wl_dispmanx_format format)
++{
++ switch (format) {
++ case WL_DISPMANX_FORMAT_ABGR8888:
++ return EGL_TEXTURE_RGBA;
++ case WL_DISPMANX_FORMAT_XBGR8888:
++ return EGL_TEXTURE_RGB;
++ case WL_DISPMANX_FORMAT_RGB565:
++ return EGL_TEXTURE_RGB;
++ default:
++ /* invalid format */
++ return EGL_NO_TEXTURE;
++ }
++}
++
++EGLBoolean EGLAPIENTRY
++eglQueryWaylandBufferWL(EGLDisplay dpy, struct wl_resource *_buffer,
++ EGLint attribute, EGLint *value)
++{
++ struct wl_dispmanx_server_buffer *buffer = wl_resource_get_user_data(_buffer);
++
++ if (wl_resource_instance_of(_buffer, &wl_dispmanx_interface,
++ &dispmanx_buffer_interface))
++ return EGL_FALSE;
++
++ switch (attribute) {
++ case EGL_TEXTURE_FORMAT:
++ *value = get_egl_format(buffer->format);
++ if (*value == EGL_NO_TEXTURE)
++ return EGL_FALSE;
++ return EGL_TRUE;
++ case EGL_WIDTH:
++ *value = buffer->width;
++ return EGL_TRUE;
++ case EGL_HEIGHT:
++ *value = buffer->height;
++ return EGL_TRUE;
++ }
++
++ return EGL_FALSE;
++}
+Index: git/interface/khronos/include/EGL/eglext.h
+===================================================================
+--- git.orig/interface/khronos/include/EGL/eglext.h
++++ git/interface/khronos/include/EGL/eglext.h
+@@ -191,6 +191,29 @@ typedef EGLBoolean (EGLAPIENTRYP PFNEGLG
+ #endif
+
+
++#ifndef EGL_WL_bind_wayland_display
++#define EGL_WL_bind_wayland_display 1
++
++#define EGL_WAYLAND_BUFFER_WL 0x31D5 /* eglCreateImageKHR target */
++#define EGL_WAYLAND_PLANE_WL 0x31D6 /* eglCreateImageKHR target */
++#define EGL_TEXTURE_Y_U_V_WL 0x31D7
++#define EGL_TEXTURE_Y_UV_WL 0x31D8
++#define EGL_TEXTURE_Y_XUXV_WL 0x31D9
++
++struct wl_display;
++struct wl_resource;
++#ifdef EGL_EGLEXT_PROTOTYPES
++EGLAPI EGLBoolean EGLAPIENTRY eglBindWaylandDisplayWL(EGLDisplay dpy, struct wl_display *display);
++EGLAPI EGLBoolean EGLAPIENTRY eglUnbindWaylandDisplayWL(EGLDisplay dpy, struct wl_display *display);
++EGLAPI EGLBoolean EGLAPIENTRY eglQueryWaylandBufferWL(EGLDisplay dpy, struct wl_resource *buffer, EGLint attribute, EGLint *value);
++#endif
++typedef EGLBoolean (EGLAPIENTRYP PFNEGLBINDWAYLANDDISPLAYWL) (EGLDisplay dpy, struct wl_display *display);
++typedef EGLBoolean (EGLAPIENTRYP PFNEGLUNBINDWAYLANDDISPLAYWL) (EGLDisplay dpy, struct wl_display *display);
++typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYWAYLANDBUFFERWL) (EGLDisplay dpy, struct wl_resource *buffer, EGLint attribute, EGLint *value);
++
++#endif
++
++
+ #ifdef __cplusplus
+ }
+ #endif
+Index: git/interface/khronos/wayland-egl/wayland-egl-priv.h
+===================================================================
+--- /dev/null
++++ git/interface/khronos/wayland-egl/wayland-egl-priv.h
+@@ -0,0 +1,53 @@
++/* Copied from Mesa */
++
++#ifndef _WAYLAND_EGL_PRIV_H
++#define _WAYLAND_EGL_PRIV_H
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++/* GCC visibility */
++#if defined(__GNUC__) && __GNUC__ >= 4
++#define WL_EGL_EXPORT __attribute__ ((visibility("default")))
++#else
++#define WL_EGL_EXPORT
++#endif
++
++#include "interface/vmcs_host/vc_dispmanx.h"
++#include "interface/khronos/egl/egl_client_surface.h"
++
++#include <wayland-client.h>
++
++struct wl_dispmanx_client_buffer {
++ struct wl_buffer *wl_buffer;
++ DISPMANX_RESOURCE_HANDLE_T resource;
++
++ int pending_allocation;
++ int in_use;
++ int width;
++ int height;
++};
++
++struct wl_egl_window {
++ struct wl_surface *wl_surface;
++
++ int width;
++ int height;
++ int dx;
++ int dy;
++
++ int attached_width;
++ int attached_height;
++
++ /* XXX: The VC side seems to expect a valid element handle to be
++ passed to eglIntCreateSurface_impl and/or eglIntSwapBuffers_impl,
++ even for host-managed surfaces. */
++ DISPMANX_ELEMENT_HANDLE_T dummy_element;
++};
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif
+Index: git/interface/khronos/wayland-egl/wayland-egl.c
+===================================================================
+--- /dev/null
++++ git/interface/khronos/wayland-egl/wayland-egl.c
+@@ -0,0 +1,59 @@
++/* Copied from Mesa */
++
++#include <stdlib.h>
++
++#include <wayland-client.h>
++#include <wayland-egl.h>
++#include "wayland-egl-priv.h"
++
++WL_EGL_EXPORT void
++wl_egl_window_resize(struct wl_egl_window *egl_window,
++ int width, int height,
++ int dx, int dy)
++{
++ if (egl_window->width == width &&
++ egl_window->height == height &&
++ egl_window->dx == dx &&
++ egl_window->dy == dy)
++ return;
++
++ egl_window->width = width;
++ egl_window->height = height;
++ egl_window->dx = dx;
++ egl_window->dy = dy;
++}
++
++WL_EGL_EXPORT struct wl_egl_window *
++wl_egl_window_create(struct wl_surface *surface,
++ int width, int height)
++{
++ struct wl_egl_window *egl_window;
++
++ egl_window = calloc(1, sizeof *egl_window);
++ if (!egl_window)
++ return NULL;
++
++ egl_window->wl_surface = surface;
++ wl_egl_window_resize(egl_window, width, height, 0, 0);
++ egl_window->attached_width = 0;
++ egl_window->attached_height = 0;
++ egl_window->dummy_element = PLATFORM_WIN_NONE;
++
++ return egl_window;
++}
++
++WL_EGL_EXPORT void
++wl_egl_window_destroy(struct wl_egl_window *egl_window)
++{
++ free(egl_window);
++}
++
++WL_EGL_EXPORT void
++wl_egl_window_get_attached_size(struct wl_egl_window *egl_window,
++ int *width, int *height)
++{
++ if (width)
++ *width = egl_window->attached_width;
++ if (height)
++ *height = egl_window->attached_height;
++}
+Index: git/interface/khronos/wayland-egl/wayland-egl.pc.in
+===================================================================
+--- /dev/null
++++ git/interface/khronos/wayland-egl/wayland-egl.pc.in
+@@ -0,0 +1,10 @@
++prefix=@CMAKE_INSTALL_PREFIX@
++exec_prefix=${prefix}
++libdir=${exec_prefix}/lib
++includedir=${prefix}/include
++
++Name: wayland-egl
++Description: VideoCore wayland-egl library
++Version: @PROJECT_APIVER@
++Libs: -L${libdir} -lwayland-egl
++Cflags: -I${includedir}
+Index: git/interface/vmcs_host/CMakeLists.txt
+===================================================================
+--- git.orig/interface/vmcs_host/CMakeLists.txt
++++ git/interface/vmcs_host/CMakeLists.txt
+@@ -9,13 +9,24 @@ add_definitions(-fno-strict-aliasing)
+
+ include_directories(${VMCS_TARGET}/vcfiled)
+
+-add_library(vchostif
+- ${VMCS_TARGET}/vcfilesys.c ${VMCS_TARGET}/vcmisc.c
+- vc_vchi_gencmd.c vc_vchi_filesys.c vc_vchi_gpuserv.c
+- vc_vchi_tvservice.c vc_vchi_cecservice.c
+- vc_vchi_dispmanx.c vc_service_common.c)
++set(VCHOSTIF_SOURCE
++ ${VMCS_TARGET}/vcfilesys.c ${VMCS_TARGET}/vcmisc.c
++ vc_vchi_gencmd.c vc_vchi_filesys.c vc_vchi_gpuserv.c
++ vc_vchi_tvservice.c vc_vchi_cecservice.c
++ vc_vchi_dispmanx.c vc_service_common.c)
+ # ${VMCS_TARGET}/vmcs_main.c
+ # vc_vchi_haud.c
++
++if (BUILD_WAYLAND)
++wayland_add_protocol_server(
++ VCHOSTIF_SOURCE
++ ../../interface/wayland/dispmanx.xml
++ dispmanx
++)
++endif ()
++
++add_library(vchostif ${VCHOSTIF_SOURCE})
++
+ #add_library(bufman vc_vchi_bufman.c )
+
+ # OpenMAX/IL component service
+Index: git/interface/vmcs_host/vc_dispmanx.h
+===================================================================
+--- git.orig/interface/vmcs_host/vc_dispmanx.h
++++ git/interface/vmcs_host/vc_dispmanx.h
+@@ -39,6 +39,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBI
+ #ifdef __cplusplus
+ extern "C" {
+ #endif
++
++#ifdef BUILD_WAYLAND
++struct wl_resource;
++#endif
++
+ // Same function as above, to aid migration of code.
+ VCHPRE_ int VCHPOST_ vc_dispman_init( void );
+ // Stop the service from being used
+@@ -135,6 +140,11 @@ VCHPRE_ int VCHPOST_ vc_dispmanx_resourc
+ // Start triggering callbacks synced to vsync
+ VCHPRE_ int VCHPOST_ vc_dispmanx_vsync_callback( DISPMANX_DISPLAY_HANDLE_T display, DISPMANX_CALLBACK_FUNC_T cb_func, void *cb_arg );
+
++#ifdef BUILD_WAYLAND
++VCHPRE_ DISPMANX_RESOURCE_HANDLE_T VCHPOST_ vc_dispmanx_get_handle_from_wl_buffer( struct wl_resource *_buffer );
++
++VCHPRE_ void VCHPOST_ vc_dispmanx_set_wl_buffer_in_use( struct wl_resource *_buffer, int in_use );
++#endif
+ #ifdef __cplusplus
+ }
+ #endif
+Index: git/interface/vmcs_host/vc_vchi_dispmanx.c
+===================================================================
+--- git.orig/interface/vmcs_host/vc_vchi_dispmanx.c
++++ git/interface/vmcs_host/vc_vchi_dispmanx.c
+@@ -1319,3 +1319,45 @@ static void *dispmanx_notify_func( void
+ }
+ return 0;
+ }
++
++
++#ifdef BUILD_WAYLAND
++/***********************************************************
++ * Name: vc_dispmanx_get_handle_from_wl_buffer
++ *
++ * Arguments:
++ * struct wl_resource *_buffer
++ *
++ * Description: Return the handle of the resource associated to this Wayland buffer
++ *
++ * Returns: A resource handle
++ *
++ ***********************************************************/
++VCHPRE_ DISPMANX_RESOURCE_HANDLE_T VCHPOST_ vc_dispmanx_get_handle_from_wl_buffer( struct wl_resource *_buffer )
++{
++ struct wl_dispmanx_server_buffer *buffer = (struct wl_dispmanx_server_buffer*)_buffer->data;
++ if (!buffer)
++ return DISPMANX_NO_HANDLE;
++
++ return buffer->handle;
++}
++
++/***********************************************************
++ * Name: vc_dispmanx_set_wl_buffer_in_use
++ *
++ * Arguments:
++ * struct wl_resource *_buffer
++ * int in_use
++ *
++ * Description: Mark this Wayland buffer as being in use by the compositor
++ *
++ ***********************************************************/
++VCHPRE_ void VCHPOST_ vc_dispmanx_set_wl_buffer_in_use( struct wl_resource *_buffer, int in_use )
++{
++ struct wl_dispmanx_server_buffer *buffer = (struct wl_dispmanx_server_buffer*)_buffer->data;
++ if (!buffer)
++ return;
++
++ buffer->in_use = in_use;
++}
++#endif
+Index: git/interface/wayland/dispmanx.xml
+===================================================================
+--- /dev/null
++++ git/interface/wayland/dispmanx.xml
+@@ -0,0 +1,123 @@
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="dispmanx">
++
++ <copyright>
++ Copyright © 2008-2011 Kristian Høgsberg
++ Copyright © 2010-2011 Intel Corporation
++ Copyright © 2013 Raspberry Pi Foundation
++
++ Permission to use, copy, modify, distribute, and sell this
++ software and its documentation for any purpose is hereby granted
++ without fee, provided that\n the above copyright notice appear in
++ all copies and that both that copyright notice and this permission
++ notice appear in supporting documentation, and that the name of
++ the copyright holders not be used in advertising or publicity
++ pertaining to distribution of the software without specific,
++ written prior permission. The copyright holders make no
++ representations about the suitability of this software for any
++ purpose. It is provided "as is" without express or implied
++ warranty.
++
++ THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
++ SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
++ FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
++ SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
++ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
++ AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
++ ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
++ THIS SOFTWARE.
++ </copyright>
++
++ <!-- DispManX support. This object is created by the server and published
++ using the display's global event. -->
++ <interface name="wl_dispmanx" version="1">
++ <enum name="error">
++ <entry name="alloc_failed" value="0"/>
++ <entry name="invalid_format" value="1"/>
++ </enum>
++
++ <enum name="format">
++ <!-- The pixel format codes match the #defines in drm_fourcc.h.
++ The formats actually supported by the compositor will be
++ reported by the format event. -->
++ <entry name="c8" value="0x20203843"/>
++ <entry name="rgb332" value="0x38424752"/>
++ <entry name="bgr233" value="0x38524742"/>
++ <entry name="xrgb4444" value="0x32315258"/>
++ <entry name="xbgr4444" value="0x32314258"/>
++ <entry name="rgbx4444" value="0x32315852"/>
++ <entry name="bgrx4444" value="0x32315842"/>
++ <entry name="argb4444" value="0x32315241"/>
++ <entry name="abgr4444" value="0x32314241"/>
++ <entry name="rgba4444" value="0x32314152"/>
++ <entry name="bgra4444" value="0x32314142"/>
++ <entry name="xrgb1555" value="0x35315258"/>
++ <entry name="xbgr1555" value="0x35314258"/>
++ <entry name="rgbx5551" value="0x35315852"/>
++ <entry name="bgrx5551" value="0x35315842"/>
++ <entry name="argb1555" value="0x35315241"/>
++ <entry name="abgr1555" value="0x35314241"/>
++ <entry name="rgba5551" value="0x35314152"/>
++ <entry name="bgra5551" value="0x35314142"/>
++ <entry name="rgb565" value="0x36314752"/>
++ <entry name="bgr565" value="0x36314742"/>
++ <entry name="rgb888" value="0x34324752"/>
++ <entry name="bgr888" value="0x34324742"/>
++ <entry name="xrgb8888" value="0x34325258"/>
++ <entry name="xbgr8888" value="0x34324258"/>
++ <entry name="rgbx8888" value="0x34325852"/>
++ <entry name="bgrx8888" value="0x34325842"/>
++ <entry name="argb8888" value="0x34325241"/>
++ <entry name="abgr8888" value="0x34324241"/>
++ <entry name="rgba8888" value="0x34324152"/>
++ <entry name="bgra8888" value="0x34324142"/>
++ <entry name="xrgb2101010" value="0x30335258"/>
++ <entry name="xbgr2101010" value="0x30334258"/>
++ <entry name="rgbx1010102" value="0x30335852"/>
++ <entry name="bgrx1010102" value="0x30335842"/>
++ <entry name="argb2101010" value="0x30335241"/>
++ <entry name="abgr2101010" value="0x30334241"/>
++ <entry name="rgba1010102" value="0x30334152"/>
++ <entry name="bgra1010102" value="0x30334142"/>
++ <entry name="yuyv" value="0x56595559"/>
++ <entry name="yvyu" value="0x55595659"/>
++ <entry name="uyvy" value="0x59565955"/>
++ <entry name="vyuy" value="0x59555956"/>
++ <entry name="ayuv" value="0x56555941"/>
++ <entry name="nv12" value="0x3231564e"/>
++ <entry name="nv21" value="0x3132564e"/>
++ <entry name="nv16" value="0x3631564e"/>
++ <entry name="nv61" value="0x3136564e"/>
++ <entry name="yuv410" value="0x39565559"/>
++ <entry name="yvu410" value="0x39555659"/>
++ <entry name="yuv411" value="0x31315559"/>
++ <entry name="yvu411" value="0x31315659"/>
++ <entry name="yuv420" value="0x32315559"/>
++ <entry name="yvu420" value="0x32315659"/>
++ <entry name="yuv422" value="0x36315559"/>
++ <entry name="yvu422" value="0x36315659"/>
++ <entry name="yuv444" value="0x34325559"/>
++ <entry name="yvu444" value="0x34325659"/>
++ </enum>
++
++ <event name="format">
++ <arg name="format" type="uint"/>
++ </event>
++
++ <!-- Create a wayland buffer for the DispManX resource. -->
++ <request name="create_buffer">
++ <arg name="id" type="new_id" interface="wl_buffer"/>
++ <arg name="width" type="int"/>
++ <arg name="height" type="int"/>
++ <arg name="stride" type="uint"/>
++ <arg name="buffer_height" type="uint"/>
++ <arg name="format" type="uint"/>
++ </request>
++
++ <event name="buffer_allocated">
++ <arg name="buffer" type="object" interface="wl_buffer"/>
++ <arg name="handle" type="uint"/>
++ </event>
++ </interface>
++
++</protocol>
+Index: git/makefiles/cmake/Wayland.cmake
+===================================================================
+--- /dev/null
++++ git/makefiles/cmake/Wayland.cmake
+@@ -0,0 +1,72 @@
++#=============================================================================
++# Copyright (C) 2012-2013 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
++# All rights reserved.
++#
++# Redistribution and use in source and binary forms, with or without
++# modification, are permitted provided that the following conditions
++# are met:
++#
++# * Redistributions of source code must retain the above copyright
++# notice, this list of conditions and the following disclaimer.
++#
++# * Redistributions in binary form must reproduce the above copyright
++# notice, this list of conditions and the following disclaimer in the
++# documentation and/or other materials provided with the distribution.
++#
++# * Neither the name of Pier Luigi Fiorini nor the names of his
++# contributors may be used to endorse or promote products derived
++# from this software without specific prior written permission.
++#
++# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++#=============================================================================
++
++find_program(WAYLAND_SCANNER_EXECUTABLE NAMES wayland-scanner)
++
++# wayland_add_protocol_client(outfiles inputfile basename)
++function(WAYLAND_ADD_PROTOCOL_CLIENT _sources _protocol _basename)
++ if(NOT WAYLAND_SCANNER_EXECUTABLE)
++ message(FATAL "The wayland-scanner executable has nto been found on your system. You must install it.")
++ endif()
++
++ get_filename_component(_infile ${_protocol} ABSOLUTE)
++ set(_client_header "${CMAKE_CURRENT_BINARY_DIR}/wayland-${_basename}-client-protocol.h")
++ set(_code "${CMAKE_CURRENT_BINARY_DIR}/wayland-${_basename}-protocol.c")
++
++ add_custom_command(OUTPUT "${_client_header}"
++ COMMAND ${WAYLAND_SCANNER_EXECUTABLE} client-header < ${_infile} > ${_client_header}
++ DEPENDS ${_infile} VERBATIM)
++
++ add_custom_command(OUTPUT "${_code}"
++ COMMAND ${WAYLAND_SCANNER_EXECUTABLE} code < ${_infile} > ${_code}
++ DEPENDS ${_infile} VERBATIM)
++
++ list(APPEND ${_sources} "${_client_header}" "${_code}")
++ set(${_sources} ${${_sources}} PARENT_SCOPE)
++endfunction()
++
++# wayland_add_protocol_server(outfiles inputfile basename)
++function(WAYLAND_ADD_PROTOCOL_SERVER _sources _protocol _basename)
++ if(NOT WAYLAND_SCANNER_EXECUTABLE)
++ message(FATAL "The wayland-scanner executable has nto been found on your system. You must install it.")
++ endif()
++
++ get_filename_component(_infile ${_protocol} ABSOLUTE)
++ set(_server_header "${CMAKE_CURRENT_BINARY_DIR}/wayland-${_basename}-server-protocol.h")
++
++ add_custom_command(OUTPUT "${_server_header}"
++ COMMAND ${WAYLAND_SCANNER_EXECUTABLE} server-header < ${_infile} > ${_server_header}
++ DEPENDS ${_infile} VERBATIM)
++
++ list(APPEND ${_sources} "${_server_header}")
++ set(${_sources} ${${_sources}} PARENT_SCOPE)
++endfunction()
diff --git a/meta-raspberrypi/recipes-graphics/userland/userland/0003-wayland-Add-Wayland-example.patch b/meta-raspberrypi/recipes-graphics/userland/userland/0003-wayland-Add-Wayland-example.patch
new file mode 100644
index 0000000..e3a0cf2
--- /dev/null
+++ b/meta-raspberrypi/recipes-graphics/userland/userland/0003-wayland-Add-Wayland-example.patch
@@ -0,0 +1,866 @@
+From 20ac7c6af4e826b5c536b6a7c8b2d1d266ced81e Mon Sep 17 00:00:00 2001
+From: Tomeu Vizoso <tomeu.vizoso@collabora.com>
+Date: Tue, 1 Oct 2013 13:19:20 +0200
+Subject: [PATCH 03/16] wayland: Add Wayland example
+
+---
+ .../linux/apps/hello_pi/CMakeLists.txt | 1 +
+ .../apps/hello_pi/hello_wayland/CMakeLists.txt | 8 +
+ .../apps/hello_pi/hello_wayland/Djenne_128_128.raw | 3 +
+ .../linux/apps/hello_pi/hello_wayland/Makefile | 5 +
+ .../hello_wayland/cube_texture_and_coords.h | 100 ++++
+ .../linux/apps/hello_pi/hello_wayland/triangle.c | 666 +++++++++++++++++++++
+ host_applications/linux/apps/hello_pi/rebuild.sh | 3 +-
+ 7 files changed, 785 insertions(+), 1 deletion(-)
+ create mode 100644 host_applications/linux/apps/hello_pi/hello_wayland/CMakeLists.txt
+ create mode 100644 host_applications/linux/apps/hello_pi/hello_wayland/Djenne_128_128.raw
+ create mode 100644 host_applications/linux/apps/hello_pi/hello_wayland/Makefile
+ create mode 100644 host_applications/linux/apps/hello_pi/hello_wayland/cube_texture_and_coords.h
+ create mode 100644 host_applications/linux/apps/hello_pi/hello_wayland/triangle.c
+
+diff --git a/host_applications/linux/apps/hello_pi/CMakeLists.txt b/host_applications/linux/apps/hello_pi/CMakeLists.txt
+index f2c6aef..0df78f7 100644
+--- a/host_applications/linux/apps/hello_pi/CMakeLists.txt
++++ b/host_applications/linux/apps/hello_pi/CMakeLists.txt
+@@ -21,6 +21,7 @@ add_subdirectory(hello_encode)
+ add_subdirectory(hello_jpeg)
+ add_subdirectory(hello_videocube)
+ add_subdirectory(hello_teapot)
++add_subdirectory(hello_wayland)
+
+ if(BUILD_FONT)
+ set(VGFONT_SRCS libs/vgfont/font.c libs/vgfont/vgft.c libs/vgfont/graphics.c)
+diff --git a/host_applications/linux/apps/hello_pi/hello_wayland/CMakeLists.txt b/host_applications/linux/apps/hello_pi/hello_wayland/CMakeLists.txt
+new file mode 100644
+index 0000000..9a2f75c
+--- /dev/null
++++ b/host_applications/linux/apps/hello_pi/hello_wayland/CMakeLists.txt
+@@ -0,0 +1,8 @@
++set(EXEC hello_wayland.bin)
++set(SRCS triangle.c)
++
++add_executable(${EXEC} ${SRCS})
++target_link_libraries(${EXEC} ${HELLO_PI_LIBS} -lwayland-client -lwayland-egl)
++
++install(TARGETS ${EXEC}
++ RUNTIME DESTINATION bin)
+diff --git a/host_applications/linux/apps/hello_pi/hello_wayland/Djenne_128_128.raw b/host_applications/linux/apps/hello_pi/hello_wayland/Djenne_128_128.raw
+new file mode 100644
+index 0000000..de9173c
+--- /dev/null
++++ b/host_applications/linux/apps/hello_pi/hello_wayland/Djenne_128_128.raw
+@@ -0,0 +1,3 @@
++ֿֿվֿվվվվվվվվվվԽԽվվվվӼԽԽӼһһһһккккккккиѹииζϷϷѹ͵ϷϷ͵ζ͵͵͵͵͵̴̴̴˳˳˳˱˱˱˱˱˱˱ʰʰʰɯɯȮǭǭǭƬƬƬūūūƬƬéĪĪéééé¨ֿֿֿֿֿֿֿվվվվվӽӽӽӽҼҼҼҼӺӻӻӻѹҺҺҺиѹѹииииϷиϷϷϷϷζζζδδδδδδͳͳͳ̲̲̲˱ʰʰʰɯɯɯȮɯȮȮǭǭȮȮǭƬƬūūֿֿֿֿֿֿվվվվվӽӽӽӽҼҼҼҼӺӻӻҺҺҺҺҺѹѹѹѹѹѹиииииϷϷϷζζδδδδδδͳͳͳ̲̲̲˱˱ʰʰʰɯɯɯʰɯȮǭǭǭǭƬǭƬƬƬֿֿվվվվվӽӽӽӽҼҼҼҼӺӻӻҺӻӻҺҺѹиѹҺѹѹииѹиииϷϷϷζϵϵϵϵδδͳͳͳ̲̲̲˱˱˱ʰʰʰɯɯɯɯɯɯȮɯɯȮǭǭƬƬ׿ս׿ֿֿֿվվԾԼԼս־ѹԼսսӻӻӻӻҺҺҺҺѹѹѹѹѹѹѹѹѹѹѹѹииϷϷжϵϵϵδδͳͳ̲̲̲̲̲̲˱˱˱˱˱ʰʰɯɯɯʰɯɯɯǭǭǭƬ׿ֿտ־־׿׿ԼսսԼսսսսԼԼԼԼӻӻӻӻӻӻӻӻѹѹѹѹѹииижжжϵжжϵϵδδδδͳ̲̲̲̲̲˱˱˱ʰʰʰʰʰɯɯɯɯɯȮ׿׿׿׿׿־սսսսսսԼԼԼԼԼԼԼԼӻӻӻӻӻӻӻӻҺҺѹѹҸѷѷѷжжϵϵжϵϵϵδδͳͳͳͳͳ̲̲̲˱˱˱˱˱ʰʰʰɯȮ׿־־׿־־־־սսսսսսսսԼԼԼԼԼԼԼԼӻӻҺҺӹҸҸҸѷѷѷжжжϵδϵϵδδδδδͳͳͳͳ̲̲̲̲˱˱̲˱ʰٿٿٿٿٿٿٿؾֿֿֿֿ־սսսսսսսԼսԼӻӻӻӻҺѹҺѹиѹииииϷϷϷииииϷϷϷζζζ͵͵ͳͳͳ̲̲̲˱˱׿׿־־־־ս־սԼ־սսԼԼԼӻҺӻӻҺҺҺѹѹѹϷϷϷϷϷϷζζϷζζζϵϵϵδδδͳͳؿؿؿؿ׿׿־־־־սսսսԼӻӻӻӻӻҺҺѹѹииииииϷϷииϷϷϵϵϵδδδͳͳ׿׿׿׿׿׿־սսսԼԼԼӻӻӻҺҺҺҺҺҺѹѹѹѹииѷжжжϵϵϵδؿؿؿؿ׾׾׾ֽ־սսսԼԼԼԼӺӺӺӺӺӺҹҹииϷϷϷϷϷζ׿־־־սսսԼռռռռԻԻԻӺҺѹѹѹииϷϷ׿׿׿׿־־׾׾׾ֽֽֽռռӻӻҺҺѹѹѹиؿؿؿ׾ֽֽֽռռԻԻԻӺӺӺӺҹؿؿؿ׾ֽ׾ֽռռռռԻԻԻӺӺؿؿ׾׾ֽֽֽռռռԻԻԻԻؿ׾׾׾׾ֽֽֽռռռԻnhc׾׾ؿ׾׾ֽֽֽֽռռ]egؿؿ׾׾ֽֽռռռռӬUdlYheؿ׾׾׾׾ֽֽռЁ@Vg:PMؿؿؿ׾ؿ׾ֽlyzB[n>VWIJؿؿ׾׾׾׾A;=?LWI]`AU[ֿGV`=QV@TY.23D2+ð_pzGV]@T\MRShwv͐\m|M[d:T\LSVڦViuˢ /5G\nJS_<ZgFOW↛K`tSS_v1EYPVd;ZiGQYogc|?RePUbŒ||@ZnKM\=_nJU`C<;ӳ9=APbTYfjWiw]v`bsChx[ir纲b;JXZbnCHVڼծԌćk;W^Nir/GQࡹjUT_MZ[xJM[˘}yzx\mx<R^8M]K\iJVaV[^onjm"?PSXiN^`F]YNQ_Դv{{s~]R_q>M_BSg=L`KXhFO]OU]ΰsKRhL]h#>:JM[Ӡv}yx|s^^gv@Q]>N^<L^<M]TaoMZḓmgn`w.OJ,/=ztnZҪq^wm^sCXkCZj|Obf<MVBV\BU\@TZGXaCW]rm:ZtMfs.QRQIN̺?BPؘYxy%*=Q\-?M<N_yYj{CTfTglATZAT[AT[@RY!59@PUuܮPpK`k*PS|}MJ@DGUݍuϜĩ϶j~JapeoVlxF\cGW`2@J6CK-6A $ìаʯȐxwyRhlCkmO\]Z`\ĺGIWѿٟmz~7R_3T[6]]<RiAYjBTe>N\<GS">BPEJ]ঠySuqm|]pt:dfNU`^mvZcdûտ?TX˽Zp~Xdrn{usxne|7N]>R^=Q_8MR@U\@V]@S[9MU/6;MV<NWw{]j~CTdYhwSak<NXSkd^fuU`kBTZJSW܇PdlEU^Ƽ\\cwk|f}Thw>U`@Vc:P\AT[@SZ@RZEX`?OYGXaBS\DT^9WRHX[ԓoh|DTdfvDU^9ITIa[HQbF>H¼fpz9JX<FMupppz~>T\@S[}U\iZ]h鲶І}ouxu|aue|8KV@S_F[bFV_>OXIZcFW`GU^GV_ET]ES\7Y^G[c@FJǕ~{Ldt=P]_q|?RY;NWCZYWar_^lͧUbl4DTGQ[IHM`ruBZbAT\]addpxKXeZcglzO[kѧXjvAS\ߟ^o 1C!<K[n-=;O`6KZ*<I@T_>SZ1FN-:)5=JW!.;1?LJUaFR^NXd:XbBUaBDMЕƝ̌Lcr9P[OdoI\c<OX.-'2IQ`]¹LRe˼QapRYZн.?%347?φSls:RX<LVFFNِTdl>KZCU^ۏTjx>R__eg~D`lA^eglf獗kzxTj|yBWfG^i?R]@U\9NV0?L7GS0>J#1=6DP#/%1"-9"6F2<K74?䣱~wc}H`l?UaAW^BR[>PWDWX;F\)8;GRg詭Ug{T]],9G!,:7=H #,/.3a|Jbh?UZ>MTEDSjHV^;IU:P`mtsrUnt4OYGVXgz~>[e9TZ7EIx8I8I}vzczqQit<R]@Va6NU<KW<LX3CO1AM/<H:HT;IU(6B(:G*2A'%0F85ѿ׾uxcyUny=VbCVbG[b?NWDPYHZZEPe@QSPhbP_tZbj{Uk\hn?KT.:F0:H1;JCMW?JQ>LPCRP8KY:NR>RR=PW?M\BIVeIRULU_/J]WaexI_c@[h8LXqxwqLdtIZ`2LTHQ`Nj{.?Pet^|rnxo`{8P\=Ua<V`AQ^?P^9JW6GT7GT6FS8HV8HU7LW8DQ;=EѹRp/@*<K2@;KWdw&9D9OZ@V]-7%2:AKTL\[CLaGXZF`[FVmIPX=TlWclvxu@JR?IS/:I%3C(8J&9G-BI7OU;FU@MR;IJ5HO1JZ2L[-CEL`O/TdMRSKPY4OeGRVOmgz}:TfCWjPXbl}G[nCQV1N[CPasslz]{tnoQk|4O]:U`9T`<O\;O\1ER*:G=N[<MZ?O\BQ_5SW-@G9CGеozwNW\FVd5GQVkuAU`GZa8GP5?G?FQ*75ILeK\^Hc\@PgAIQЕE_xWbj9JP4BH1<C/8A-5>'%,;1;J6FN2DN3FR2ES1DP8IS7HR1?L?P];P_5KX@P\>P^J`rqftBX`9MW=P]7K[Zr|Kbk4MT7PZ.KVwnkhfua}B]jXsd{@Tc?P`=P_8CQ*7+<I@Sa8LY2BO(6"+:ALS6=G7:>ܣyvssi}^sas;N\I[f@QZ;NU6JP;M\@RV>HQ,3@-7@CEJݥաϒ͆l4DK)9BEOY2;D4=G"0)2?1=I6EN:IQ5EQ7GT8IV9IU5CL(.?L5ER6GT<MZ7GT3CP@P];KX4JQ3GS=P]>Qa:M\H[h6JU6KR2IQ2JV`wd}d|za|qh<SbAYh;O^AVe/DS=P_=P`<IU5EQ2DO9NY8JU-<I+9EEP\:KW)8D(2y}ꢰtmkh{BUbEWbCT]BT[<NUI]dK\cLY^9DLLU_/38悄wg~ua}Seo]bd-=J+9E#/)2?-6@2=F0:D2=G3?I<GT6DP/@M5ER1?K9DQ#/9'7E4DQ;KX9IV@L[9FT)+8F4JQ4HS8KX8K[3FU8KX1EP8MU<QY6IU!4A)<K^rgz{v9IUK\iAQ^FZf?R_?Q^;N[<S_BS[5FO:MU;NU9MT:KT7FO=HQ4IW8IV1CQet^luN^[󑤦n~|xh|s_rDWdEWbK\eM_fGY`HYc@NTfqt^gn=GQEKOۈt~~h|Wn~HZdfoputk)9F)72=K*3@%/9=GQ0>E6CK8BL6BN4AP5AO5BP:GUDP\8BK1BO5ER8ES8ES2?M8BP)7.8F0EP6HR;KYCS`%6C$5B2BM5EQ7JR=MV&6C+;F/<]lyM^k9IV-8C<GS@NZ (3EP8LW8LW<S^CS\:KT?OY@QZFXaFU^?NW<GQ;LX8HU7IVN_lSgw?Sce{F_d\dlVns$2-?P3>MnThy0?9LYEWb$4=)0&8?*9B2=C*.sJW^CKP|Khj\mw`t[n{@R\OY^_^[3BS3@P5?M.7D/8F7AJ6BL(9?-6D)5A3@N1=N2>O#0>'/7E7HU8HU6BQ7DRAN\5?M9DR>HV.?L2BP3FP:LW0?L)9E-:H/<J5GO8GP".8&0&/,%1,:"+.7AFQ[:IQ5FNAT[?U\6OV&6?(1,>G #$-(1(1-=F9AGO\`?KSAPY7ITBUbXpTk|1N^@MZqgj{7DP\qsK_q,@R`r9LYEWb:KT8JPCV\BP]?JR4?C +.1@G2<?ґu|oWfoLX]DGF3DQ6GS2@N1<J2;H5BN-9E%2+7(63@N/>O7FV)6C0:H?LW;KX:JW3DQ1AN0<J&4 &.;I3CT4ER1CNCS\>MU1?L1;I,6H4GS;IU5?H'0:#'3 )3#0<,:&31>J:ERDQ^DS`@R^?S^9MY1DK6GP+9B +5&2<&1;0@H)207=$(.$17'-:MT?R_J_n,L[CS_z~g{by|[nM`o7KX?Q\>OX<NU:MS@M\BNYEPSARX:MU:GNw|O_kSblVcgAHG3EP6FS2@L.:F.:H6AO0>L%2@%3?.:I1AQ/?O1AQ/>N0<J8GS7HU5FS5FS4ER2CO,9?P\=MZ5EU0BN4CO3DM%.%108F29J8IZ8HU&.;%*5(.9'1:,4B"/= /:3AM:HT?O[:MX@R]=OZ<Q[6GS0@L9GT%)1>0=I8FS$0&.=.6C;GQ:KQ;MT3FM<MXAS`-IZBM\~YzuXey[r|ThzOcu{DWdI[fEV_ASY@SX;I]?MYBSYDW[=S[<PXⶼYlpvzhUbnSclP\cOZZEJF4HO1BK7FR*7C-8G09K-:J-8K.=H+<I/?O';J*>M.>N,<I4BN5IV3FS4HU4ER/@M(9F)9E5FR.>O2DP3CO2@H)4=8DO5=K4;M(<M)7H -',6-0:).9/8F1>O&7C->K8HU8IV>O\GWe;LY6FT3CQ8HU+4C#18@O?FUCQ_%3'0G6DX6GS1AN<PW;MX7KX>Qa3P^@JUEKX6Qb'J_dt &2Pcu/A1@AUbEWb>OX'9@L^c?NdGXf@PWDX^8P]H]fS\`Ζ^fm]{fw}eU^jNYdAPVWehU]X0=I0>J(13<F.8A2>J0=K1>M*8D,=I'8E+>M.BN2DN3EM3CI1@M/?K1AN4DQ6EV,;K+9L/<O/@J0AO,@P0CU+>P/?Q)9I*7E-<M);G!3@#1?#.="2>*8D+<G*;H-?L2CP5IV2ER9Q\:Q]8Q],CM 7B"7B:MX9JV6GS&2,8.EN5HR=MY>KW4?K4?KCP\<IU;JW8ETAMY:CO2<IDTbudy9IT0AM1CM2DOCVa*;D<LV$.")'4<E*4<DPWKW_YfoGY`@UewPaoQbrtK^o<K\LdiEX_HX^@EK=<>,<I+7-9E-9C*6.9G*7G-;M3AM0=K-=J.>N0AN5EQ3BK1BH3CP4DP->I7GT6FS2AR1@P0@P0@L0@L1BO7FW6EV+:K+8F*6B,>K/?L'4B#.<)1>#/;'3?)7C/;J0@M1AN4ER6JW;N[.EQ/EQ/EP-@K+@K8JU<LX5EQ1?K9GS8NY2EO%1)58DP3?K/=I-:F,<I5APBNZ'4=)5 #%5F(9M0@L5ER3BO:JVFVc!2;6GP=OX"*3DLU9EL>HP)15BJ,4<MRjzDXeatzViwCUfi{xH[bNahFU[V_cLQRȊ2BR3CP1=L)7C-;I-:J-;N/>Q4@K7BP0<M-<L3BS7DR9EN8CN8GP1@I2@L9GS1?K1?J.;I,9G5DL/>G->J3CP:JW2?K-8B09C0AN2>L)4B(0?)1>%-;)1?*6B/9H0=K2?M3CP:JW=N[8HV7JX7KV5JU7HS7IT:JV1AM6DP;IU5GR4DQ3AM=IU8DP.:FFT`6GR3BS3@N@LX"+5.8B'09*6B0;F2?M0=L2AL8EQES`7FOCR[APY<FNFQY<GOGQY&4<:GOGT\EQYWiq6GOI[fSdpzlli}I]aIYa4@EALT>BF妪XW]5GX-=M9IV)6E*7E*9I)9J(;-"0.;K2?N3@P-:H!.$-7".8%0:$09*6@=IR.9F%1=5AM8EL0<F1?L7DPDR^2=G3=E,6=.;J4?M,5C%-:)/<'0=-6?/9C1:H4?M9DR;HV?KY<LY<MZ7HU;MW9JU5HS<KX8HT3DP9FR:HT3DM1CL9HQ?JT'0/:D2BJ%7?'7H7DR@KW:DM7?H*5;8?F3;@4=L@HV3;H9EQFR^NYcJV`DOZHV]DQYES[AOWCPXFS[IV^@MUDTZBQXEV_br~xtfxH]pIV\R`fLX^JS[U_bowz[]i(:K.>N/?L&3A,9G2BR-=N!3F08F0:K9GV5@S.;J/<J'3?7AJ*6(4%1=*6?-8B+4$.)3%()55DP&2;)0)0"*-$/>7?L)1>',9#)6 &0)2<+3=-6E.7E'2@*4B<IW8HU:JW@P]<LX5EQ9IU9IU9IU7DP6DP@NZ<KS>MV>IT@IS1>H7BL6EN2CL=IX8ES&5@&1>2=D$+2"'4;<(/?$409F7@M?LX7CM&1<&6?1BI8IOMYaGT\VckN[cMZb;IQFQW;JOHU]CS[DR^4DRgx6GYJT\R^dCOU>JPEOWIS[blt<Y_}OQ^.>N;KX<IW+:F1>L7DT+9K)8K,7E.7I/:M0?Q/=P6CS/;F/;G+8F&3A,:F)7C/=I,:F+;C$3< ,6(4@&5A-:F*6$+$$(+8)5A)'5*#"-)3%+9)7"08DR;LY:KX6GT!1=&2/;(4)7C*9E.<H$1>&6>/;E.8B5?I+4>9EO.=F3DM:HT3@N0=L.<H-9C"*4(*/67&-=")8)2?;CPCO[AQY7GO;IR*9@/>E,2/5(5=,9A2?G9FNIS\?JRGRZ;FM0:D7AK%/9\foEPWQ\dGSZ>IMYdh+6:ISZhoyOin\`n"2?!.:'3*6@*6B9DR4AQ-;M.;K2?O1?Q1AR4DU4DS/<J0>J.=N)9I+:J%6B*;H0@L&6C*:G.8G&3A*6D'8E/=I'2=(-"-0&4A+7C/7D(1%.#-".5$.6"-<%0>$2@,8F1BN9JW:KX:KX*7C1>J0=I,9E1?K-;G9JV%6B/:E(2<+5@(2<(1;9EO.@I6HQ5AJ0<H5AP.?L(4C'3=&/9(06,2C)3@)1>4@LAO\AR[<LV;OW1CJ=OV8JQ<KR?PWJW_<IQ'4<6@J09CCLU3:C:@F29@;=EHJR@KUV^hNY\GTU1=?HUVMY\SYbCVSR[hgj{0<H*7B7BK'1(2.:F4AO1>N,9J)8H*:K*=N-?P2BR,=J0?K-;O+8K(7G)8I5EQ2CP%5A*:F&3A.;K&6F0?O1AN(7?!.6%16+<H-;G0<H )3'1(2&19%3:"/?%2A)5D,<J.?M;LY7KX2ER7CO1>K6DP4BN3AM3@L2BN3CP7BI7@H;EMELU6AH3@G+?E3GM19C1>J5AP,<M(8I%2B(3<,5=,6E.6E,8D/=IANZ>OX7KS<OW=PW@SZ<OVEV\DU\>KS<JRBPW@HW?HRDIU@EN9;D*(/<=@HDF>JTV^h?IM9EGQZY6>APY]KSYR`VJR]EJ[^fd$@Q$<M+?N&7D)6E2>J7?L/;D,=H/@M3CT0=T-<O5DT3>J7AI+:B/=H,8F,9I1>O3?M.<H+:B-:I+<I)8I0AQ,;K.:I*7$-7(9K6FS+9E#.5+2*2%08$0;$4<&5=':B,=E*=H6HS8MW<O\7LV8MX0EP5GR2DO0CN3CO4DP3MT/HP8NV?T\"1: *&0!(2'4)50=I%.7)2<%.8-2>29B'-63;E2>J-;G@P\<LY7EO0AH9@IGNX5@G(2;KV\JT[MT[DHO>IQ>KP>IO:EL3<C5<@:@F=DIAIOMW^NZ`HTXNZ_HTYBOPIPT3GGL\YFPKQUO+BR*@O4DT)6D+6D.9G+7C,7C5EQ'9E.>O-:Q0?R5DT3AM/<D1AJ3AN5AP.;K6CS4AO0>J-<D/:G(5D(9F/>N3DP(6B(1;!-4*:L.?K'5A!,3)1!,4%08'3=%0;,8B%4=1>K5ER6HS5ES8KX3EP8JU+=H0CM9IU.>J7GS3CO2IP5HP6IQAR\0@H,8B*4>6?I.=I'3?2>J(2<%/9 )"..6>#,!++7C3@L<MYEVb(7@"39(1;",61=G8EM&.#+"(*28ALTCPV?IPDLS5=D>DI.49?BG<DKISZHTZAMQJVZT`dIVXFNRN][HUUNVSab^0BM1AL7ER)4B.9G-7H(5E.-8-=,<M,;N*9M,;K*6$.'0 ,-%2B5BR)6D!/;.6+3=!.:&5@5BP7EQ+7A$,5'18*;L6FS-;G!,3)1!,4(3;$0:-6@'0: ,9#/+8D7HU1AN9JW2AM(8D/?K(9E1>J>LX1?K@NZ5CL;JS=MUEPZ?KU/;E1:D9BL/>J,7C6BO+5>%/9"+5(-9+2;*1:(1;(4@0>J:JV:KW>MV5EL:FR8DP8FS<KT5DM@LWAMT,4>,8@&07)3:,4;"*2-380386:?DLSHRYAMT6BF.:>+7;5BC=FIANNX``LQQPQM5DM6AM=FS,5C/7E-7I/:L"0C&2@,<L*;L*:K+;L3AQ-9/>F(7@-9-9H'3D.;K&2@"/;%.&-!+5&2>3?J ,!+"+$*(9J*;G%1 *2$, '/$0;"'5&/<'3%2A:FT7GT'7C!-%5A#/-9#1=$0*6B!- +5 * *#-+5.:D,9C5AK4CO)5A6BN4=G&0:$-7(.9*1:.4=*3=(4@0>J5EQ@P\@OX=NT:GV@NZ;KW9IU9IV>NWFR\8CM:CL;EL4?F8@G-2:3:?8<A<?D<DKISZMZ`HTXEQUEQU>KMBKN@GJ?DEHMLTXW2>H'2>&/<+4B2;I6@Q.<O*:K,:J.;K-;M-=N,<L4DT-=J-:F,=F-=I*;H(7G5DT6FS'7C&8A*5<&/9#/;/;G.:F)3<$-")/&7I*;G!/;&-!)&.(3;,6"*8(1>'0<)3B%3@7DR<LX4CT.>J0@L2?K-;G0?K2>J1=I6BN4@J.:D7BM8DN6BL($.1=G&5A)4@6BN7@J%/9#,6-3>+2;-4=/7A(4@/=I7HT?O\IXaCTZ?KZAR^<KWAT_8GTFU^COZ>HS;CM<GN>EL=FM06><?D7;@CEJ9AHKU\MY_NZ^LX\MY]KWYHQTUZ]PUVKPOOTR"0< .9.9F*5C!,:+9I/>O.>N3<N1>N.>M-=M+;K2CO+;H.>K4EM.>K3CP,;L2AQ9IV*:F,=F4=G*7C&4@4AO7EQ-8B#+4",3+<M)9F(6B *2!,4)1(3;$0:,4A)1>%0?+8F,8F5FR<K\8HX7GS7GS4DP5FR7EQ6DP7DP<IV8GO:IR9HQ?IT9EO*4",6+4>!-$0+7C"+ *4&0)/:+2;.5>.7@(4@-;G:KWDTa(7@"28)5+77GTEV_+=F+:C:GO)4<'0:)18.6=.4;#*126:,/41389AHCMT:FL0<@-9=.:>3@B*46;>B:?@=ACIRQק3CS+;K/?O&3A/<J2?M1AL/AL3=O3?Q1@P-=M/@L4ER,=J2BN0AJ-=I1AN*9I4CS:KW.>J->F/:G.;J'8E0?P8IU+9E%.8)1+<M/?L5CO*1 +3)1$/7#/:'3?)4C'4B)5C&7C2BS9IY1ET7IS;MX8JU4FQ8HT8HT6FR>NZ1GN;MU8LS=NX;JS0;F&/9;EN)7D&2>:GS0:C%/(!&2(/8(.71:D/;G*8D>NZBR_?MV<MTBLW;KSAPYGZa8IO5AJ>JP7BH8?H:BI:BI8>E(+326;/271386>EHRYKW]JVZ@LPAMRJVX>HKIKOHLM?IINYWþ׻¼ܬ2EW4EW8GX&6C)5D.=H0AM,>F37M4=P1@P/AM0AM8IV,=J.=N,>F.>K.>K(7H6FV5FS-=J&8@+8G):G$3D/@Q6EV+8F'4@'2*<M1AN3AN)0'/)1%08'4>#1A$1@$6C'8E):K1AR3GV5GW9NY:OZ6KV:MX5HS5HS1AM:JW5OV3LT4JR7KS;JT1=G%0:4=G6ER*5B6BN2<F)3(2(-9$+4%$-7+7C*8D:JVBR_HV_DT[GS[FRZ?PW@PW>NTBPVKV\?IO;AK;CJ7<C@FM.1:15:58=79>4<CBLSERXHTXHTXFRVJVXFOSNSULSV=GGANLwz̓yoxt~ĽȾvvdx|*KS2QY0GR-?J.<H.:F7?L3;H1AI6FN7GT3BS/?Q3BR4@Q1>L-<D/>F4BN)6D0<J;IT1@H,:C4?I/;E+9E4BM8FR2>G+6=&06,9F7DQ:DK$.4#*1%,3*3<)2<06>/8@-7@*6?.<H2BM8IV8LY<JRAOX>LU=GR<GQ@KU@LVCLVEOWDMU:DK:DL2=D.4=04=?>H5BL%2;5AK5?I&/8"+4&-5%,5$-6,5?,4A-9E@MYBR^EV_9MTBRYGW^=MTAQX>NU>OVEV]:LS5?F=GN3<CGLT,3758=26;:=A6;BHOWJUXHTXJVZFTUDPR/=>=@E9@B;CGFQRizwaupn~b{rl^uid}|[rp[ljcqk}}m|cvw^uvtw|.JT1JT2FQ/?K1@K4@L -8*"+,9/?L,<L4DT7FV&3C)7.7!09#1=,:9FT4BN'6>-6"-&0%4@5CN'5A)"*!(#4B0>J#,6'0%+$.%.7#,6'2(0:*3&3$2>6FR3DQ)=K,4!* /8$-!,6*5)3'1%/",&0$/+7B%/#03> )&02>H*3>'/$-6%+4&,5"+4(1;*3@/;G3AM@Q]CT]6JQ&6=-4,<CHX_2BI-=D3CJ1BI'1)3:%-419A!&*.3$(-,059?FGOV2;C+7;/;?/;@;GI9FHJPT?DI>IMIVXCQSbwt\sp_tsUthp`|rczucvt[libpn}yz{n4JV8KX<LY1>L+6D5?M(4C!-<,<D*:F2CP/>N-<M1AQ"3?"/=,4$1'5@$1?1>L,;F(5$3<(3=-;H"0<.?L1>J*5?(/ &&7E-;G%/"+ $(1&0)*4=&.<"-,9E:JV2CP(8F$5==NW$5>3AJ/>G.>G2=G'2<3CL-<E2CL3DM9HP/;E#,6;?J$4A#,/<E(2$.$(1"(1$!*4(1>'3?1?K=MZ8HQ(;B7FM?OVGW^BRYBRY=MT/?F0AH4=F@IR5=D@HO(-5.59,/41498=DFNUFPX?KN>NPAMQBNR<IJBJQ<FM<GM;IOy~|x]tpv^wlUja\nfdvr_jnt`m{sxwfw[j~m}^l.>K.>K5BP/9G/:H0=K.?L(9E.;H1AM3DP,@O+>M7GW/?L+9D1@H)7C+7F"/=1=K7DR2@L-<D,8A+9E"3@2BO9IV1?K(1;(/,=K9FR7CM)1 *$-(1;!,5(1?*2@(5@)8C,=H3CO:KX9JW2EL5EN6GP5FP5CLN\eKZcN]f?PY7JR7IQ7JR7HR0?H&2<5?I4BO"/+7C;GQ!+#.!*3&/#,5'0:*3@&2>2@LAQ^EV_BU\BRY@PW?OVAQX@PWAQXCSZCT[2>EAJS+5>DLS05<+1947<48<1:@@JQEQWESZFVXBRUAMQ<GK?IPAMR1>F>MVvwlrcvz^qnXkbRdV\naycqxwcp~zv{}fwhwdq(7D*71>K1<J"/=3@N4DQ,=J2BN3BP1@Q+>M(;J7GT8HT)9F.>J-=I.>K&5E4CS7GT3DO,<I0>K/=I(8E4DP8HU8FR(4>(0(:G3DQ7CL&18"+ )1%0:'0>'2@+6D*8F0<J,=J<KY:LW>P[8KS8KS9LT9LT6GP5FO:KT>LU5IQ9LT8NU9NV7KR5FO+53<E5CO!/;+:F8DQ",!+6"+5$-7'08&/9'0=(4@-;G?O[CT]>RYJY`GW^=MTAQX?OVHX_AQXGW^/:BDOW6>H@IR-6<16=/6=45>/6??HQIU[GU[DRXBRTEQU=IM=JP=IN6BJ<KT`p}euN]nQdw:JPWfiVf^M^Q`ndhtsirWfobt|Xht\mzOancrJYbJW_-@O1@P5DT-<L.;K1@Q1AR-AP0@M3EQ*=L)<K)<K4GT9KV,=F3CP4DQ4DQ)8H7EV8HT2BO.>J3@L->K$4A-=M<MY7EQ*6@!,3,=N4DQ6DP%/9'.",6)3<*2?)7H+8I,9F->K0@M9IV<NY;MX;QX6LT:MU=OW:NU;LU=NW<MV;MY<MY;OZ<Q\:LW4EQ*6/7E/@M!.:+9E7CO(5",6!,6"+5)2;&/9&/<'3?*8DAQ^BS\-AH$4;(/ 07AQX<LS&6=(8?$5<+4?BLV2;CBLT28B-5<06=4:A39B>GPLV_ESXCTZCQWCQX?JN=JP9EK6CK;FP;IVUfs[kxSbtcv}kz}bnn{qw_otvarzpbs|ex~lzbrt2IX0ET6IX-<M,;K1AQ3CS+>M.>K8HX2ET+>M)<K2ER9KV+<E3CO6FS6EU)8H3BR8GW3CP2BN6DP1BO)8I2BR6EU6BP-9B"+5/@Q4DQ9GS)2<$.#-7'0>'4?)9I+:J,;K/?K,<I4DQ7JU:LW5JR9NV<QY9OW<NVAT\EX`?RZ;JW9KV9KV;MX9LW8FR!.94<I1BO$5B/<H7EQ(5!+4#-7",6)1:&/8%.;%1<.<HCS_AQZ&9@5EL:JQ?OVBRYEU\<LS@PWCTZ3<FEOY1;EDNW07@18A39?27>1:C=FOHU]BSZFV\CSYESY@LR>GOBKS3?ELW_ERZ>ITM]fZiraqwxz{~{^mvFVbn~x{DPV0M[0LZ7M]1EU0AQ2BR4DT.AO0?L4CT2ET*>P+AP4HT;OU,=E3CO3CP5CT+:J2AQ:IY2CO/?K8FR3CP(8I1AQ9IY7HT2>J)3/@Q1AN:HT(4>$.%.8(0>(5@(5J+9L-<L0?O6FR9IV5DP;LX5MU9MU:PX:OW@V^AS[AT\?RYBQ^=LY:LX<NY9HU6DQ"*82:G3DQ&7D.:I2AM"/;"+9#-7 *5(19*3<*3A%2>(7C?O\HYb:NUBRYEU\CRY;KRFV]IX_:JQGW^1=H>HR.8CAIS09C.5>04>49@/8A>IQER[FW^DTZBRXDRX?JQ@KN=HK<FM7CI:FLAOVSagVbirK^epyccstp~lhrvyxcn~wzsqgoz~?O\?NZ7FR1?K1>K2AQ/?P.?S/CO.AN3FU.>O*:K5EU9JX0@M2BO4DQ4DQ-=J2BO8IU5ER0@N4BN0@M"2?1AR8HT6DP.:C",6+<I:JV4EM(7@%/%2<'/=.6E*:A+9E,<I/>N.=N:JW8KV9MT7JR;NV<OWCU]>QYBU]<OWAT\=QXBU];NU;NV=QX3BJ(2/8A.<I+9E0<H8DN&0:$/8&/9&.7$0;)2<+5?.8A+4>=LUDU^>RZ>PWDV]CV]@RYEX_FX_ASZEY`9EK<HN2<C?IP.6=6;B06=4:A7;D;BILX^KX^EU[?SVARU6HJ?HS:EN7AIGPTCLOGSTT`dQac7JRJ[bS_e[gjo{~|Xqvtr}lmZovo|/>O8IV<LY0>J8ES4CS/?P.?R3FR2ER6IX0@Q,<M4DT8IV-=J2BO3CP4DQ-=J0@M5ER0@M.>K/=I2BO 0=1AR?O\7DP0<E"+5+<J9IU3EM+:C%/#/9&.<,5C,<D,:F*:G,:K/>N9IU;MX>RY:MU9LT8KS7JR@S[@S[>QYCV^=PX>QY=PX:MU:MU2AJ ,61;D;JV*8D6BN8DN*4>",6%.8&/8%1;)2<+5?,6@7@JAPYGXa-@H7GM2AH+;B1AHCSZ#3:$4;%5<)/4AG09@@KQ08?.7>27>39@9>G:BIIU[ESYCSZCSVBSV9JM<IQ;GM:EI?HL:ED?HKNZ\OZ^5HO8FM[gk_kmZeikv}tx_u{n~r}tuct}x':H%5E$1!2=$1,;K1AR0AU1DQ3FS4GV.>O.>O7GW9KW.>K4DQ6FS7GT0@M/?L9IV6FS-=J1?K-=J#3@/?P7GT8FR0;E!+50AN9IU5FO0?H&0!.7&/<,5C+;C,:F):G-;L,;K3CP7IT:MU8KS9LT=PX?RZ9LT=PX@S[CV^AT\?RZ=PX8KS<PX4CL$0:09C4CO-;G/;G:FP,6@!+5%.8$-6%1<)3=*4>,6@3<F>NW>OX!5=)9@%5<-=DAQXAQX4DK>NU?OV9DJBNT2?DBLS29@/8?27>5;B3:D6=DHTZESY@QW@QTCQT6EHETZ<HL6CEAIIbjj^gfV\_NVY?MTT`d\ijJVXFRUixi|U\i}o~u_o|PZd,?Q*=K5FS,<I-=J.>J3CS3EV3FS6IV3FU.>O,<M5EU9JW.=J1AN4DQ6FS.>K4DQ8HU4DQ/?L2@L3CQ%5B1ARIYf/=I3>H!*42CP6FR0AJ-<E)3#/9&/<.6E'7?*8D*:G0?O2AQ5ER:LW:MT<OW;NV@S[=PX9LT@S[EX`?RZ>QYBU]=PX?RZ:NU4CL&2<1;D4BO/=I2=J7DM/8B$.8)2<$-6*6@+5?-7A-7A5>H<LUCT];OWAQX<LSAQX:JQGW^AQXEU\DT[6DJ<JP2>DBKR+5<19@*3:4:A29B0:AFRX@NTFSZDTVBRT8CGFVXBMR2?A=FEMQRBGG:AD9>CCOSP\^forIUWKV\̳yfm|t|t{lz\er4K[1FT:NZ.?L.>K3CO1AQ4CU/BO3FS6IX/?P*:K4DT6HT1AN1AN3CP7GT0@M0@M8HU7GT/?L2@L4ER3CP+;L3CP4BN3?I)3=->K<LX7HP,;D ,6+5)2?.6E-=E-:G+<H,;K0?O8HT9KV<OV9LT<OW<OWBU]<OW?RZ;NVBU];NVAT\<OW;NV>QY4CL*6@09C6EQ3BN+7C<HR3=G#-7)1<&/8#/:-7A.8B-7A09D<LTGXaAU]DU[DT[@QX<MSBRYFW^P`gFW^;IO1@F3>DFRX-8?,3:.6=-6<3:C.8?EQV@OU>MSCNRFRV6@E@PSIVX0<>>FECLKGMP',1/7>?JNEQRNWZ?KM>KR\mx]t[t_t@O_LVgwxr2J]4L\>P`/@M5EQ5ER2BS5EU2ER3FS1DS-=N)9J5EU7IU2AN3CP2BO4DQ.>K3CP9IV7GT.>K=KW.?L"2?3CS1AN1?K3?H,5?,=K9IU6GP-<E'1!-73;I(1?"2:9FS*:G,;K.=M5ER:LW<OV8KS<OW>QY?RZ=PX=PX<OWDW_?RZ>QY:MU?RZ:MU6EN-9C,6?4CO2@L*6B?KU7AK!+5*3=)1:)5@.8B-7A.8B3<F7FOEV_=QYKW_ANV4AI#081>F>KS(0 )&4:0>D7EK:FL/9@&18+3:/7>18A.8?COU>JP>MS@LP>JN4<@AMQIUY1>?:BF<EH>ILhtzx>IPDPTN[\?KM8GJ4GNpnh0HZ4JZ<Q`2CP4DP4DQ1BO5DU5HU5HU3FU/?P'7H5EU:KX5DQ4DQ3CP6FS/?L4DQ9IV;KX/?L3@L/?MYiv6FV8HT5CN5AJ,6@+<J6FR6GP-<E%1;'4='/=19HP`h(6B0AN1@P.=N6FS=P[<OW8KS:MU<OW=PX8KS=PX>QY>QY:MU<OW=PX>QY>RY6DM0<F09C6DQ5CO)4A<HR8AK!+5&/9&/8(4>-7A,6@-7A/8B4CL;LUBV^$19$19.;C1>F8EM@MU5BJ;HP8IO:HN.<B<HN4AG-7>*5<+3:07@,6=BNT?KQDPVALP:BF5>A;HMGQY1<@=HL;GKCOWGXa2DP9IPCQXIUY=JLFUX;LS|}r_vhzj^z]{]u\p2M_+FV8M]/AN/AL4DO4ER:JW3ES3FS4GW0?Q*:L8HX:KX3BO/@M2BO7GT.?K0@L6GS;KX-=J8EP9IVDSd7ES6CO5AJ/9B.?M6FR8IR/>G#/8&3<3:GmsSbkAN[*:H0?O-<M3CP:MX5HP>QY9LT>QY?RZ=PX<OW>QY=PXARZ;NV:NU:NV:NU:GP5?J-5?4BO7ER)5B:FO>GQ*4>&/9)1:%1</9C-9B+7@/8B.<E<MV=RZCNX<HQDQYAMU:GN8EM&3<=ISCRX>NU7EK;FL;GM;EL:DK6>D6<F+4<?KQ=IPCPW?KO4>A9?C>GQ?IPHRYMV]KY_<PV@S_(AN4FP<MTHSZS^bFUWBU[OcoPitBcKeTlPjGj~LpLiTj4EP6EQ4DP/<J/<0AM8KW.DP2JV)?K9LX1BN(9F6GT7JW.AN/;J6CQ4DQ*9J1@P3AS0@Q1AR0CTMbqB^g2LU/AL:AO03C.=H9KV7JR0?H)/='-="2CMejH]e/AL.<M1>N7DR>LX?PY9MU>QY?RZ>QY:MU?RZ?RZ>PX3SW>RZBN[BNZ7IWs*AH"1:6BJ;HP.;C7GP5FN2>H1;E.7B$5>,5>43B12A0<H$6A/ALHSa=TT>RW>PWAS\*:C(6<>HMJWT>RW9MR6FL5FL8GM:GL?IP=GN9HK7FI;GK>IM@HLINS:@E=?D4AG?KQANTFPXCMT=GNBIP@FM7BH?JPGV\FTZJV_HX_JZ`P`fN]hO^jM\hO^jM\hL[gM\hN^j*<I 3@%6C.>K.>J3CS6JX=Ra*BNG]i5HU<LY):G6GT5IV.AN0<J4AO2BO+:K0?O1>Q8IZ2AS/CUt;V`9R\4EP6BN07F0?K8JV7JR2@I.4B2;IBRcOfkEYaEWb1AN5AO;GV<MY=NW;NV=PX?RZ>QY:MU>QY>QY>PX3SW9NVAMYAP^TnwEYd!3;5AH;HP4AI7GP7CM4AK8BL8AK-AH1<D58C38B(6Bj~?N\>RW:OSASZ?PY?MW@PV:LOERT@TY<OT9IO9JP<JP=IO>HO=FN<KN8HK:FK:EI9DH9CF39>;@E@LP=IMDOS>IMBMQ>JM<GK7BF:FJ;GKCQWGU\JX^GW\EU\GW^EU^FV_EU^HW`HXaHW`HXaIYb4LX,BN8KZ/?O-=M4DT5GX5IZ~Lbn?Q^6GT*;H6GT7JW1DQ1=K4AO1BO-=J,:K4CS/@O/?O*>P{8S]?U`7IT4?K27G5CO6JQ7JR4BK09F5=KScsqLglH_fCT_+;I1=L8FQ;LU:KT<PW9LT9LT>QY;NV>QY=PX=PX7RX<QY>MZ*:GlI`j>MZ1?H:IR8GP5@J8DN7CM;GRAIT0FJ:HN>GP<EO *uASeAUY?PXBU[@PZDV]=PU@SVCVX=QVAUZ?OU=KQ>MS@LR=JPBJR=LN8HJ8CG4AD0;>+7:6?B=FJ6<ABGL/9<ENR=HL3=A?KO;FJ>JNAMQGVYFUWIW]JZ`HX^HX^P[cR]eS^fVahU`hWbjYdkYdl:T`5K[4JY1CT5GX<M`8H[;PaH^j>Q^/@M%6D3DQ6IV2ER1=K3@N1AN-=J.>K9IV7GW/?P,AWЈTlx<R\:LW5CO8@M4FN5IP4IR1BK;BO7AO}WpyI_jEYd>MY(8D4CP;LU;LU;NV<OW=PX;NV=PX=PX;NV<OW9U[>PX2AMFXhyCXgL[h6JP5FO9HQ;GQ8EO=GO>KS?KT6ML:LNBLTAOWJcniDWnDU[ASZ?QW>QX@SZ@TY?TY@UZHX^EU[?PUGU[APU@LQ7CI7CI?MS=KQ?NS@KQ:FL.:@8AI#.58<@>BF9>CAJMDOS;GJ@OR@OQFRVEPUJY[JY\HV\BRXIY^Ufl_hq`ir^gp`hqajsbjt`hr^gp0KWKdp1GV-AO1CT0AT1DZGZosRgr7KV6HS+=H1CN5IT/CN.:I5BP4DQ2BO1AO8HU3DQ3DQ1I`džNfq=S^:LW.;H9DP,=F6HQ2IN7HQ?JV,8IUtF]hG]hDXc9KW*;C3DM=NW6IQ8KS<OW;NV<OW;NV=PX<OW>QY8QW>PX>N\Ym|tH_oETdH\g1CO:HQ:EP>IQ>IQ<IR>KQ9PP;MOBMU=NYiq@UnCV]BU]BS\FX^BT[CV]>PWI]cEV]HY`IV^IV^ANVCPXGT]KX`NZcVckUbjTbjWdlCPXLW_S_g\]fX^dPX_XbiS_eP^dP]cL\cQ]aUadTchYgmWejXhoXio\mt_jq`ksbmtcnualtbmt`ks^iq3GS4ER1AQ4DU7H[3I[|Lbm>R]<NY4FQ3EP5IT4HS)5C1>L1AN2BO6FR>NZ6HS3EPOhqNet?S]BT_7GS8FR5HN4KQ2HN4GO7DQO^noIaqAXgEXcDW_(9B5EN:MU;NV<OW=PX<OWAT\;NV<OW;NV?RZ7NS<OV>N[mOgyt_z:NY:JW@KUALT?IR=LQ?OU?SUAQW<LR7JUeBVn>OY@R^EV_BT\FW]CPY-4IV`=JRCPXERZFS[KX`MZbR_gUbjScjRbiPagT`hUbjZgnZgoWdl\enYaj]enWaiZgoZfnWgnVfm\go\goXemYgn\gq\ks\ks]mubmw`lv]irZeo]isalv]hrVak_qx0?HDR_8IV0@P.BS6L^݆Ndo=P[8JU5GR6HS7KV2FQ0<M5BP0AN3CP3CO=LY8KS8KS싢wBYhK]jI[eCR_.>J:LR2IN.GM5GO)9Feue]uD[jGZeGZb/BH:MT6IQ9LT;NV=PX<OW=PX;NV<OW;NV>QY;PX=NZ(;G~mHavp>T_5ER>GQDMVBNSCQWFV\ARWERZCMW6JUΑrBWm:MZ?Q\8IRARXHUZXaj
++bepSaiYfnYfn[hpWdlZgo\iq]iqYhrWfoYhq[ktUdm[jsZir[js[jr]ktZjrZirZir[js[js]lu\fo^hr]ir_kw^jv\kv\iwYftWgsQamO_kRbnM]iM]iM]iN^jgsy=IQDOY:HT6FS4IX/HX̅BWc6JU8JU:LW7IT6KV4IS0<M8DR0@M7FS8HT(9ANahtWsOhzNdsL`lrz{·Պk[qAXhF\fO`gI[a@RX%7>&;B(9A)<C-@G5HO7JP?QX@RYBRZ<QX1@KsǐkTlꑮ5NZ<LX@ITAISALR>KR9LM@MVAITHQ^1COݑ`}BWj@QaNbmYjsYhm]gmbjr41@gu|gt|cpxanvcpxamvZkqSdkZhpWfn[irZhq]ktXiqWhq[ltZlxYlvaq}`p|^o{ao{_ny^lxem{fm{amxbl{_hv\huZeuR]nL_lL_lL_lL_lJ^kI\iG[hFYgOjp2IN;LU8FR6FS3HW/JZv>V\8MU3HP7IT4ER1AN1AN18;MX]ozeykj}h~PfsE]iG\gJ[eO_l^n~іɓÃrwOfvI`pG^n{ҰߚЀUrvGam>LT?HPESXAQWHV[HSY[ggO^cZp{d~ޘd@Yi7R^FakXkr`pyv,1>kp~3YhpWgo\gr_ls]jqanu_ltbntWkyWkx[o{Xmx[ny^p{]oz\nz[nx^nz`p|aq}dqdqerercrz^nz[jvVgsPcrL`rKcsNfvOeqNepRerWguVfrUeqZgtWfoPjp;PV5HO;KW@P]2ETYqw:PU6KS4IQ:LW5FSN^kbr~t\nyRdoL`kM`mK^k>T`>T`4LX=S_\lyZkx>Raaxtwwh~\sYq~\tšƦҖƏ†tyׁ<VbCR^ET\K[d>SZFXcQ]jK\aN`jXq뜺όiCZi=Vb9P[Ymt`kuYclX`mt{06Ebs_o|_o{_o{`nz^lxao{_lx[kxUfsTenTenSdmTfoTfoZirZjv]mxYiuScpScpYiuZhxVduTfpXhtUhuSfuSftRgxThyThzRhtPcpPdqSepXhuZjv\ktXgp\v|=T[3EP5DQ8HUL`lpG]b7LT5JR6GS9KV8IV8HU:IY7JT9KV>P[<P[ATb5HU9P[8OZ7M]9OZRboBVe9QaRl}syynnWpty9JWlɒăȚɕǏňs˅<Vd>MZ\myyŪְ֥虵΃^tDYh=T`9MXWhqbnxCLWHS\DMZ%,;as^o|]n{Zkx_p}YjwQboYjx]jq]jr^ksbowiv~dqybowhu|evjzjzfw`o[m|TixPetPfuOfuQetNbsOctRduPbsM_qOcnPdoUfr_q}XiqRclRakQ`i^wCYd/DN6HR8IV6GTlH^j>QY9LT5IP6IT5FS8IU8HY:JZ7JT;MW8JU9LY6IV7JV7L[7L[4N]:Q`@S`BUb=Ra7Qasx|ox}kyd}h[v|tDP`AUf|ʔˏƆ{zuB\l?Q`PduÖ˗lj֫ݚt]qGVg<P]GYdTcl\iq`ksLU`8DNco|_itdoygr|hs}lteq~huivlu|nx~jt{ku}r}vr|oyap[jzSbrM`oK_pKbrIbrHaqGbrF_oGaqKcsMasPctTduTdvPbmYkvfz\mvPajL_fIZ`EU\VnzDZf=P]<MZ:LW4FQ>P[9KV7HQ6GP7GS2BN7HU7GW9IX5EU8JT:KX8IV3FS6IV;M]5JY4IX3K]E^nRhs7MY6K[<Sc<Scayx{{pf~a}fjytmUaq2FXszwτ˂{y|AXh:K])=N}ʗˇևvlUl~M`oK\iCVcDUc?NWeszgrzZem1=Gkx{x~u{xzw~oxt~s~s}o{lwit}anz[hsTctN`qM^oI\mI_pI`rGbrF`pD_oIasJ`rOcuQds]m~aq~dt\mvZjtVgqN`gL_fIY`FV]BRX]t@Wf8NY7JW9KV5ER7FO7FO<KS7EQ5FR7GU5EQ,<L2BR5EW5FS5FS3DQ3GS3FV5GV2HV5JY+DX=UgPfv@Va6LX:LY7JZ8PcMexyzkqoi]yhzpہO_lAVf3I\^wЂƊwnܠkAVgGVe8K]tv‹ypGauB[n>VfCYhBTbFWaBWg>Q^>OXiv~v}$/7S_hz{v}wxxn}mziy]lxWgsN`oObpM^oNasJ_rI_qG_pG_sHbuJcwFbvPfxNdwShy[o~`q~euYiu]luK\eJ]dHZaEX_FV\AQWAPWBRXI`pNeu9N^=P]<NY?NW=JR<FN2@M1?K2@L0AN#2B#3C-=N4DU7HU6GT4ER6IX7JY3FU/DU/CT3KḃD_l=Ua5LX2ER;LY7N^7M]Ibr{wnqnxqhf}yoㆣZr|>T`?QbQ^u~„}xx}ݍc{IXgETd8KZUp~e}L^tCXjEYl=OaG[h@R]DUa=RZAV]8O`8N[=QY[goxjt|":CMclsgsxis{lwiw`o{[kwZjvUhwQcrQftLcrG^pG_sG`sG^uF`pFaqHauIbvIcvKcyMe|Nf}Xi}[n~aqZkxXhu[luN`gK[bL\cFV]M\dGV\CSYDTZ=PS;NQLctAXh=Ra9KXCT^DQYEQXIRZDO[6CO-:F,9G$+;-<M1@R5ER6FS3DQ2FU4GV1DS1DU*=N.E\߁Zu<T`FYd9JU@O\0JV;S_=VgB]nwspuyld~h~ׁUtyLbm@N^NTizÆ|}yƖ~Shw@OaBM[?P]*FQ2O]9Qa<K\AP`>M^BM\ANZ<MU?RY=RZ<QW6Ra9R^@RYCRXq{tyqv|gkoVdoTdpTdoK]kM`qJ`rI]sD\qI`oF`oE]nF^rE`tD`y=]tFeDcuHcwJexKg{TlUmUnVolw]i}_nWguM^hEW^GW]DUWDS[HX_>NTCTYCSYASU;OR@SVfD_h6P\6P\5O[>YgB]kHcqTjtATaqo~ytrxڥVm|BXdATa?Rb8KZ>TXBZcF\i?ZjF`tkpmwsjg}—ȉ7MY=P_.BSx‚y{ǃdFX^>QY@R]=OZ7HU=NZ9IY;K[;J[<MZ9JW:KX=N[<NY;MX<MX4IY3K[5M`/J[Gcx>ZoA]rB^q9Xr>Yt>XqBZsF^tBZqC[qF`sM_tK_tG_rB_tFcwFbzMgSiNkYtLg}^yWqWo~WlxLanHfkQjoEX_IY`IU]GW^ASZBT[=VV?TV>NTDOWEPXDOUCQT>OR_xPiu7Q]4N\5O]:TbE^nOhxƀəßՕŅVm|F\gI[h@Rb;N]DXXCV[K^fNaoVi|F`pv}|zoqv杻ΕXpxC[g@Ud9M^txÅ{dUpF]q?YjBT[BU]>P\:LW;LZ8JV:JZ9IZ4EQ6GT8IV<LZ8JU;MX=OZ:LW;LV<MU9LZ3HWJaqD[nC]mD]qA\qC^sD_tH_uBYpIbuJbuA]pKbzLe}Kf~MlHg~KkVp]t[w`xIcwpjKamNbnG`fI`eFX_GW^CPXAQW@SY=PW=STAUY>NUBMUFPXAMS?NQ=OPlSm{6P^2K[5O^:ScC[mLdulv~~mql}{Ζvk?Sb@Ud@Ud=PbKZ^N]dTemZlvK^kYo{Umyw~z{ӟљɄ_{?Ye>Tc.EUw`yk;Sf@Wg>Vf0EU<S^5HV<NY;MX<NY=OZ8HV:KX3DQ5FS:KX8IV9JW8IV9KV6HS;LX:LY@KN@NT>NT9KUThwLcuGbuKfzMgzLezHeyEauLh{Kf~Hg}Gf|IfKlNoSuKkPoSpOkjy}patI]hN_kCV^CT^BQZ@OX?NW?NW>OX:MU9MS@QZ>NV@LVAMW=KQ?MP=OPzXq5N^6N`1I[;SeAYmH`tizXsugWuq{|r}¥ڛΑn<RaE[j=Tc@WhL_hSeqXm{`sư塽җʀc>Xf5Q^9Rb>Uem?TfBUl:P^>Td?R_BVc9KU>P[5GR:IV<NY7IT4FQ+=H$28IV1BO8IV7IV5FS9JW6HS9KV9KW>QY8LT?MN@OU;MS7JUE^mJg{MjJhPmPrXzVzTxJoVzlz‡ǎɎƖ̕Ĉ{]qUgyPdsL]jHYf=OZBU`AR[DU^>LV?MVAPY?PZ;KU<MV>MVAQY;IU>IVBNXAOUBSV@RSr_w5M_/GY1I[7OcC[oNfzrvwbIe~=\u6Tp=^{Xwclk}֚|pC]k;Uc:Sc<Ud>WkE]qC^r}ۨܔȑ}VsB`o<Vf6O_4L\AUg<K\6FX9LV<NY9KV;KW=MY8IQ6GO6HP@P^3CP4DQ(5,89IU7GS4DP6FS9IT8HT9IU8HU:KT;LU:KT7IQ=OW6JT5LZ]x{{Ƀʁ}~{ʂЃΒ܎ГԚj`}hc~JduRetI\lHYfDTbCT`CUa?RZ>OX>OV>PX4GNASZ7JQ:LSASZ>QXCQY;GQ7FOBQZ@NX@PV?PS=OPd}>Wg0HZ2J\7OaBZoNfznumXs9Ti5Qj$A]"@]">RJh}squw։VpIcs<Vf6O`4Pa9Yo@`wIgmr{xy’ǛΩߑŒu[t@Zj6P`4N^3IX9KZ4DT:IZ9IT;KW:JV8HT7FR7GS7GS7GS5ER5EQp+!1=7GS1AM1@M2BN9IU9IU:JW9JR;LU<MV<LU2IU7NY5KV2IX9TitrtyzyɁҍەݕ߈ZzTpLdzQiyF[kAWc=TaCTaCT`BT_?Q]?RY<OW>PY>PX:RW5MR5MQ6OS4JO;OT9LR;LR<HMBQT>MT9KS=OV<OTASU>OS|kD]m3L\4M]7OaBZlOgynxs\uIct-H\,Gb4S4GX,CSċz}Ոc~Jdt;Ue6Sb3O`7Ug@_rIf|LhvǏǝӉqWn>Vh<Wf2L\2M[6LX8HU8HU7HU7IU:JW9JV4ER5FS6GT6GS7FV8GWJZgRbo1AM:JW=NV3EM;KW9IU;KW6GP=NW;KU8JQ7IP6IQ7KR9LS;NV-BQHdxIeDhDdGkCjBiFoFhHdKa~E`pLdtNetPanJZhHXeDW_BU]?RZ>RY<OW>PX:OW8MU=SY9NTEdcDdc8WV+JI1MM2KK=OP:ILCQMDRP9KL@SV=QV>RV>NT=LO{s=We7O_6O_7P`B[kPhzqziXn}=Wd0IZ,G_8T7EO/AN{zאĉu[y9Vd7Tc2Pa;V`A[iLeuTmzup|ȏŇyh|<Qc=Wf4O_0KY1GS9KU<KW<MZ4CT3GV2ET4GW2FU3EW4GY2AR8GX0@M5ER5EQ8HU6GP3DM6ER4CP9HU<MV:JT8IS7JQ6IQ>PP:IK=KHBNO=MR6J[2Kd3Qq8Sx8Vw4Uu2Vo9\uMj[p]l~QhtJ\gQ_kJV_T\fO\cDSZ=OU=PX:MU2IP;QX7NT7MT9MT#5>UuuCgfMqpRrsPmnF[].15>CMXPLYUburF[\DY^ATZ?NUN[bse7Sd0JZ3L\6Pa@YmMh|x}}\w7Wj3Sf.F\'5O;R[7M_rˌ~k^y<Wl5Sh3Rg3Wd<^mFbsQj~ku|{{~ҍxsxe=Wg<Ue6M]1EV3DV5EV7EZ3HR5JT5JT4GU5FS6GT/@M5FT6GO6GP6GP4EN:IR>MV6EN8GP7KS5HO9LS5IM6JO9JL<MP<JM:KN<MO=MS;LS4CKES_M[gKVd<P]CVcOcnWht_pxUfoYioRbhK]iGYdGYdGYdDWb>P[?Q\9KV4HO-;G7CO4@L2BIAWZ40SyqDyk?uf:oaH|jF{iPpPqNmLsU{p.A>{ENQ0BA9SO4OKub?Yj1JZ4M];SeB[pKg{}tnh4Ue3Sf+CY%3N5LU,BTrßщqhJcw?[o>Yn3Pe5Wf@]nHcwTkd|iuvwsɇvrkIcs:Sc5L\8L]1CT6EV5DV3HR3GR3GR2ES2CP0AN2CP4DR3DM4EN8IR9KT>MV;JS:IR:HR6IP6HO9LS9IP<LR=MTAPS@OR:KM;JQ9HN9IP5DM?MYM[gFR`M_lZkyVhsSfpCR_UfnIYcXhqGYdDVa?Q[?Q\>PZ<NY9KV;MX1EL,:F5BN;CQUaj[mqXsq[{tI|oDvj;pcG|oCxiCxjEzlLrc|hƾŽƿpe>Xi5N^8Qa;SeB[oLeyslvUq<^m0Qd.DZ 0G/FP2H[}|ڍ{r_xD]r:Sh7Sd7Vi@^qGbwOf}WotttywwrRl|:Sc6M]7K\2CT3EV5DV4HR2FQ1FQ4FQ3EP5HS9IU8GT;MT4FM3FM<LS<LS9IP9IP:FN7GN8IO:JQ<IQ;IO>MR>MSCNT;OS;NS7IP9KRL]fJZfO_k`p|]mzTdq[kwUdpOalHYeGZb>RXBS`=N[AR_;LY7HU9JW:KX4FS1AM6EP6>L!+2;EBNRFXWf|xTwJunN|rM}tExnG|rHqKv?pGwCuiquºrĻ~fB\m?Xh7P`?WiHauIbvtro[u8Zj5Sf)?V!.EE\f?Ug΅~qЉvwZq>Wh4M]:UkC^sHcxNh}Xsw}v~~rUn~<Vf5N^/FV2EW3EV4GV6IV3FT4FQ5GR6HS3CO2BN:KS;NT;MT=MT<LS=NTANV>KS<IQ:GO>KS>KSANV:GPALT<GO>HP2EK9KR:MSFW`N`hRbnP`lO_kP]kKWfJ[fGWcBT^?S^DYc<Q[<MZ;LY7HU6GT6HU:LY2CP8IW1BM2@L<FP"(1;CJHQV(21&&*CA )&?]Z`}V~wS~wQ~wU|JDxEvMro}5zumBZl?XhCYi@VhMeyc|vs~\v<Zk2Pa&>R$1IAXb8Na׉tƝԈ}Wn~L`o<R^=S_8PhBYpIdyPm^zwwzytā~v\x;Uf6O^1HX3HW4GV2FU6FS6GT6HS6HT5FO5FO3EN4EO;KQAQX:JQ<LSBNV?LT9FN:HP<GO<GOAKS?LT<IP5AI/<D>KR;LUEV_^ow[ltO_kTdpQamO`lKXdIWbBR_@P]?O\>Q^:NZ;N[;KX7GT3DP1AN7GS9IV3CP5FR0=K.:F1;E")35;@JOR"'*"''46-/ $"!=:Xurs~rZ:u^oM~zgyoNfx?VfAXhF\nf~t~qf=\k/M^(=R!.E1HRAWi݉}ɜӄ^s3FS7IT3FM9RhE^rIdyPmZyk{{LJ{~|f?Yj2K[6M]3HW1FU4GS4ER6GT7IT6FR8IR1DK6FM;KR;KR=MT7HN?LT>KS<IQ=JS@KS?JR9FN9FN<IQ5AKCR[=LTCRZdt]myuWfs^nzK[gAP]HXdGWcBQ]JZgAQ^:KX:KW8HX9IY:IY7FV8GW6EU2AQ5DT0?O0@P,7H%.='0;%,8>CEJM&)- #(-/527:48;7>A!!"1-&FAcrssu^vRiyjpy{x:Zi0N_(=R!-C4>1GYyw{ěԈnZlyJ\g:KT/AG5K_C[mFavKjSrjruvˍąwl<Xi4N]4M^1GV/EP.EQ9IV7HU<LW8GT5FO>NU9IN=MS<LR<LR9JP@NT=KQ>MS>JP:FL6CL8DM7HO<LSGU_7HQVfr[jwGZdj|CU`PbmDVaAS^GYdAS^7IT7IT9JW4ER6FR6EV9HX8GW5DT7FV3BR8GW5DT5DT2AQ0@P-5F$+:"+5%-+2527:69= #$(-25-25!$) "###$ )>;;<DG"47%9?qojuwezv|k|m:Zi6Rc&<N ,C3<EZmÍwҟَÑc{Wiv?PX+=D*9?8M`6P`Nk|Gh{Uuqy{szρs=Yj1K[8Qa5L[4JU0GS8HU2BO9HU5FO&7A<LSBRX4DJ:IO;KQ=KQ>LR9GM9EJ/;A5AG7EJ=MT?OUAR[WgpZlwM_jXjuQaoM]kJ\gFXcAS^>P[:LW<MX;PZ6JU<P]2CO6EU8GW<GY4?Q5DT3BR6EU4CS2AQ2AQ1@P,=L+0D!'7(2$';EH!$$ #+-(*  %&/12!%53,;=..7WLYlqd}rquw|zgjG^m;P^1CP-@M0HXΝȁ˛sPetAR^:KS:JQ3DR4GVRg|Nfgznv{æݑ|vqe>\o=Wf7Q_;Q]6JU7HS1FQ4HT6KS9KS7IP6FM;IO>IO:PR7LM:MU3EM1AN%7@=KU;KQ?QX:LSWip[msQbkRclVgpPajCV^J]e@S[<OV=OZ@R]7IS:KW4DT;K[:JZ7GW5EU9IY8HX3CS4DT2BR1AQ9HX1@P.=M.>N.;K$/='4#,!&!%/45#"#(' .,,&!"+"O93D($gRQqgj~rjrnwm~v|i^xOhx@WgCWfMapƉʒǕɛЕɂ~azEZi6FSARZ8GP/BM/CRJ_u\tysuw~Ǧ݈~~r{:Xk5N^9Tb:O[9MW3GR4FQ7IT9LT9MU6IO9IP<JO;GM9IK<JP1>F:FP1>J@LX?KULWbSfm\nuQcjQcjL]fHYbK\eFW`GZb>QY:MT>P[7IT:LW6GT7HT6FV9IY8HX6FV7GW8HX7GW7GW3CS3CS1AQ3BR/>N,<L3@P,9I$/=%3!*#!"022###  $3';.(60-#'&|z~{zu[vrNhy@XjĊȒȗ͘Όz6JY9KU4EM5DL6GS,<L8Oa{Ǣ٩xxa:Xk=Wg:Sc;Qa4JU6HV3EP6IP7HQ8GP9HQ:GN;IQ<GO<FM6?H5>G19FAJWZbp\fpfnyNahFX_GY_@QZHYbEV_;LTFUbDW_:MT;MX5GR:LV3CQ3DQ4FR3CT5EU4DT3CS6FV6FV5EU4DT1BR/?O/>N.=M-<L0=M0=M*7H&1?$1%!&) &((!##% "LFHQMI]]T$) #.'CSL)%̆ĉDŽ}ɐǔŖǐvgr͜Ջɕʕ˕ɍŠ ԐtVlwVhs7GS<JV2CL5FS3EˉӦݟ׏{|w~aYw6RcA[k9P_:Q`5KW5HO7HQ8GP7CM@LV:EO:FP:EP2<C:FP6BNlvWgqJ\cBT[HYb6GP?QY;KW;KW<KX9MT3EP>P[2DO6GT2CP6GT3EQ3CS3CS4DT7GW4DT5EU3CS->N2AQ.=M0?O.=M.;K+8H2?O#1A"0*& &6<=%%% ebdLNLAIB&!)"&ȋрvŅ{msWss̍Ƃžٓ˞֍ā ӍlOdoDVa;KW8ER7FO/@N*>Quȇҟ֡؏ņ†mRq@[l=Vh9Rb:Qa6M]:MS9JS5DM:FP:DM4@L3AM:JV?U\-ALוmRhsLdkCT]HYb?PY>PX:JW<LX=MY9IU3EP9KV2DN.>L3DQ4ER4ER3CS3CS2BR3CS1AQ4DT6FV4DT/?O1@P2AQ.=M1>N0=M-;K2<M#,>(6"/#-$$)*  %!&XWY@ECCJE87.\RKgXRzjjxtlt{foĂvya}ƎˍŌőɕɌ[tKak;MX9HT8ES4DJ2BO.CTBZqÒʌŌĤ۠׏ƎČtn|v`~B]n=Wh:Te9Qa1K[4HO6IQ6DM2=J,8D0>JDVa9KXLguwNfr=Va<W^9IR@QZ7HP?O[7GS8HT8HT3CP3EP1CN5FS1BO.?L3DP3CS1AQ5EU3CS3CS1AQ3CS4DT3CS/?O2AQ1AQ0=M/<L0=M/9J+5F$.@!,:&4$. %!!&'     475GHF>3/ub]B)%bhqvqvvmp}~{ŃvƄ}̀ǎ|jE\d@RZ:JW6BS9FL/?L/AS0H^Ɇ˒ʏǏƣzs{wg<Xh=Yj;Uf8Rc2L^7NU4IQ+<D8COAO[;JWxRm|lF]mYn}7JW9KV=QX>NX:KT9JS7GS2BN:JU6FS9HV2EO.?L5FS1BO0AM1AQ1AQ1AQ2BR2BR2BR2BR1AQ3CS4DT3CS2AQ0=M0=M/<L0:K1;L)3D(2C#.<)6$."'$), ! !#()
++!" &'%&$$ /(%$OD=kyċӀ‰’Ƒ˂ȏʍ͍{Dž{rońg|wE\dCV]7FT>K[9FM3CP*<M$<R̀ƋňÀ{|srmk>Ym=Yj:Te8Rc6Pb1KQ/FO9IR>KX}^x[vf}Oct:L]BQbAN\;GSDMW;MV5GO1AM5EQ5EQ5ER9IV3BO1BO/@M3DQ/@L3CS/?O0@P2BR0@P0@P2BR3CS0@P1AQ1AQ1AQ,9I0=M1>N'4D+5F1;L'1B'1C"-;!*7$.$*&+/&*+"'((,-".+%-,#"%$#!!,+'/+*=98%-&
+\ No newline at end of file
+diff --git a/host_applications/linux/apps/hello_pi/hello_wayland/Makefile b/host_applications/linux/apps/hello_pi/hello_wayland/Makefile
+new file mode 100644
+index 0000000..c9ddf23
+--- /dev/null
++++ b/host_applications/linux/apps/hello_pi/hello_wayland/Makefile
+@@ -0,0 +1,5 @@
++OBJS=triangle.o
++BIN=hello_wayland.bin
++LDFLAGS+=-lwayland-client -lwayland-egl
++
++include ../Makefile.include
+diff --git a/host_applications/linux/apps/hello_pi/hello_wayland/cube_texture_and_coords.h b/host_applications/linux/apps/hello_pi/hello_wayland/cube_texture_and_coords.h
+new file mode 100644
+index 0000000..663e23b
+--- /dev/null
++++ b/host_applications/linux/apps/hello_pi/hello_wayland/cube_texture_and_coords.h
+@@ -0,0 +1,100 @@
++/*
++Copyright (c) 2012, Broadcom Europe Ltd
++All rights reserved.
++
++Redistribution and use in source and binary forms, with or without
++modification, are permitted provided that the following conditions are met:
++ * Redistributions of source code must retain the above copyright
++ notice, this list of conditions and the following disclaimer.
++ * Redistributions in binary form must reproduce the above copyright
++ notice, this list of conditions and the following disclaimer in the
++ documentation and/or other materials provided with the distribution.
++ * Neither the name of the copyright holder nor the
++ names of its contributors may be used to endorse or promote products
++ derived from this software without specific prior written permission.
++
++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
++DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
++ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
++SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++*/
++
++// Spatial coordinates for the cube
++
++static const GLbyte quadx[6*4*3] = {
++ /* FRONT */
++ -10, -10, 10,
++ 10, -10, 10,
++ -10, 10, 10,
++ 10, 10, 10,
++
++ /* BACK */
++ -10, -10, -10,
++ -10, 10, -10,
++ 10, -10, -10,
++ 10, 10, -10,
++
++ /* LEFT */
++ -10, -10, 10,
++ -10, 10, 10,
++ -10, -10, -10,
++ -10, 10, -10,
++
++ /* RIGHT */
++ 10, -10, -10,
++ 10, 10, -10,
++ 10, -10, 10,
++ 10, 10, 10,
++
++ /* TOP */
++ -10, 10, 10,
++ 10, 10, 10,
++ -10, 10, -10,
++ 10, 10, -10,
++
++ /* BOTTOM */
++ -10, -10, 10,
++ -10, -10, -10,
++ 10, -10, 10,
++ 10, -10, -10,
++};
++
++/** Texture coordinates for the quad. */
++static const GLfloat texCoords[6 * 4 * 2] = {
++ 0.f, 0.f,
++ 1.f, 0.f,
++ 0.f, 1.f,
++ 1.f, 1.f,
++
++ 0.f, 0.f,
++ 1.f, 0.f,
++ 0.f, 1.f,
++ 1.f, 1.f,
++
++ 0.f, 0.f,
++ 1.f, 0.f,
++ 0.f, 1.f,
++ 1.f, 1.f,
++
++ 0.f, 0.f,
++ 1.f, 0.f,
++ 0.f, 1.f,
++ 1.f, 1.f,
++
++ 0.f, 0.f,
++ 1.f, 0.f,
++ 0.f, 1.f,
++ 1.f, 1.f,
++
++ 0.f, 0.f,
++ 1.f, 0.f,
++ 0.f, 1.f,
++ 1.f, 1.f,
++};
++
+diff --git a/host_applications/linux/apps/hello_pi/hello_wayland/triangle.c b/host_applications/linux/apps/hello_pi/hello_wayland/triangle.c
+new file mode 100644
+index 0000000..1a7bfc4
+--- /dev/null
++++ b/host_applications/linux/apps/hello_pi/hello_wayland/triangle.c
+@@ -0,0 +1,666 @@
++/*
++Copyright (c) 2012, Broadcom Europe Ltd
++All rights reserved.
++
++Redistribution and use in source and binary forms, with or without
++modification, are permitted provided that the following conditions are met:
++ * Redistributions of source code must retain the above copyright
++ notice, this list of conditions and the following disclaimer.
++ * Redistributions in binary form must reproduce the above copyright
++ notice, this list of conditions and the following disclaimer in the
++ documentation and/or other materials provided with the distribution.
++ * Neither the name of the copyright holder nor the
++ names of its contributors may be used to endorse or promote products
++ derived from this software without specific prior written permission.
++
++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
++ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
++DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
++ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
++SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++*/
++
++// A rotating cube rendered with OpenGL|ES. Three images used as textures on the cube faces.
++
++#define _GNU_SOURCE
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <math.h>
++#include <assert.h>
++#include <unistd.h>
++#include <sys/socket.h>
++#include <sys/un.h>
++
++#include <wayland-egl.h>
++#include <wayland-client.h>
++
++#include "GLES/gl.h"
++#include "EGL/egl.h"
++#include "EGL/eglext.h"
++
++#include "cube_texture_and_coords.h"
++
++#define PATH "./"
++
++#define IMAGE_SIZE 128
++
++#ifndef M_PI
++ #define M_PI 3.141592654
++#endif
++
++
++typedef struct
++{
++ uint32_t screen_width;
++ uint32_t screen_height;
++// OpenGL|ES objects
++ EGLDisplay display;
++ EGLSurface surface;
++ EGLContext context;
++ GLuint tex[6];
++// model rotation vector and direction
++ GLfloat rot_angle_x_inc;
++ GLfloat rot_angle_y_inc;
++ GLfloat rot_angle_z_inc;
++// current model rotation angles
++ GLfloat rot_angle_x;
++ GLfloat rot_angle_y;
++ GLfloat rot_angle_z;
++// current distance from camera
++ GLfloat distance;
++ GLfloat distance_inc;
++// pointers to texture buffers
++ char *tex_buf1;
++ char *tex_buf2;
++ char *tex_buf3;
++ struct wl_display *wl_display;
++ struct wl_registry *wl_registry;
++ struct wl_shell *wl_shell;
++ struct wl_shell_surface *wl_shell_surface;
++ struct wl_compositor *wl_compositor;
++ struct wl_surface *wl_surface;
++ struct wl_callback *wl_callback;
++ struct wl_egl_window *wl_egl_window;
++ int needs_update;
++ int ellapsed_frames;
++ int kill_compositor;
++ int single_frame;
++ int terminate_abruptly;
++} CUBE_STATE_T;
++
++static void init_ogl(CUBE_STATE_T *state);
++static void init_model_proj(CUBE_STATE_T *state);
++static void reset_model(CUBE_STATE_T *state);
++static GLfloat inc_and_wrap_angle(GLfloat angle, GLfloat angle_inc);
++static GLfloat inc_and_clip_distance(GLfloat distance, GLfloat distance_inc);
++static void redraw_scene(CUBE_STATE_T *state);
++static void update_model(CUBE_STATE_T *state);
++static void init_textures(CUBE_STATE_T *state);
++static void load_tex_images(CUBE_STATE_T *state);
++static void exit_func(CUBE_STATE_T *state);
++
++static void
++registry_handle_global(void *data, struct wl_registry *registry,
++ uint32_t name, const char *interface, uint32_t version)
++{
++ CUBE_STATE_T *state = data;
++
++ if (strcmp(interface, "wl_compositor") == 0) {
++ state->wl_compositor =
++ wl_registry_bind(registry, name,
++ &wl_compositor_interface, 1);
++ } else if (strcmp(interface, "wl_shell") == 0) {
++ state->wl_shell = wl_registry_bind(registry, name,
++ &wl_shell_interface, 1);
++ }
++}
++
++static void
++registry_handle_global_remove(void *data, struct wl_registry *registry,
++ uint32_t name)
++{
++}
++
++static const struct wl_registry_listener registry_listener = {
++ registry_handle_global,
++ registry_handle_global_remove
++};
++
++/***********************************************************
++ * Name: init_ogl
++ *
++ * Arguments:
++ * CUBE_STATE_T *state - holds OGLES model info
++ *
++ * Description: Sets the display, OpenGL|ES context and screen stuff
++ *
++ * Returns: void
++ *
++ ***********************************************************/
++static void init_ogl(CUBE_STATE_T *state)
++{
++ EGLBoolean result;
++ EGLint num_config;
++
++ static const EGLint attribute_list[] =
++ {
++ EGL_RED_SIZE, 8,
++ EGL_GREEN_SIZE, 8,
++ EGL_BLUE_SIZE, 8,
++ EGL_ALPHA_SIZE, 8,
++ EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
++ EGL_NONE
++ };
++
++ EGLConfig config;
++
++ state->wl_display = wl_display_connect(NULL);
++
++ state->wl_registry = wl_display_get_registry(state->wl_display);
++ wl_registry_add_listener(state->wl_registry, &registry_listener, state);
++
++ wl_display_dispatch(state->wl_display);
++
++ // get an EGL display connection
++ state->display = eglGetDisplay(state->wl_display);
++ assert(state->display!=EGL_NO_DISPLAY);
++
++ // initialize the EGL display connection
++ result = eglInitialize(state->display, NULL, NULL);
++ assert(EGL_FALSE != result);
++
++ // get an appropriate EGL frame buffer configuration
++ result = eglChooseConfig(state->display, attribute_list, &config, 1, &num_config);
++ assert(EGL_FALSE != result);
++
++ // create an EGL rendering context
++ state->context = eglCreateContext(state->display, config, EGL_NO_CONTEXT, NULL);
++ assert(state->context!=EGL_NO_CONTEXT);
++
++ // create an EGL window surface
++ state->screen_width = 1024;
++ state->screen_height = 860;
++
++ state->wl_surface = wl_compositor_create_surface(state->wl_compositor);
++ state->wl_shell_surface = wl_shell_get_shell_surface(state->wl_shell, state->wl_surface);
++
++ wl_shell_surface_set_toplevel(state->wl_shell_surface);
++ wl_shell_surface_set_title(state->wl_shell_surface, "triangle.c");
++
++ state->wl_egl_window = wl_egl_window_create(state->wl_surface, state->screen_width, state->screen_height);
++
++ state->surface = eglCreateWindowSurface( state->display, config, state->wl_egl_window, NULL );
++ assert(state->surface != EGL_NO_SURFACE);
++
++ // connect the context to the surface
++ result = eglMakeCurrent(state->display, state->surface, state->surface, state->context);
++ assert(EGL_FALSE != result);
++
++ // Set background color and clear buffers
++ glClearColor(0.15f, 0.25f, 0.35f, 1.0f);
++
++ // Enable back face culling.
++ glEnable(GL_CULL_FACE);
++
++ glMatrixMode(GL_MODELVIEW);
++}
++
++/***********************************************************
++ * Name: init_model_proj
++ *
++ * Arguments:
++ * CUBE_STATE_T *state - holds OGLES model info
++ *
++ * Description: Sets the OpenGL|ES model to default values
++ *
++ * Returns: void
++ *
++ ***********************************************************/
++static void init_model_proj(CUBE_STATE_T *state)
++{
++ float nearp = 1.0f;
++ float farp = 500.0f;
++ float hht;
++ float hwd;
++
++ glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );
++
++ glViewport(0, 0, (GLsizei)state->screen_width, (GLsizei)state->screen_height);
++
++ glMatrixMode(GL_PROJECTION);
++ glLoadIdentity();
++
++ hht = nearp * (float)tan(45.0 / 2.0 / 180.0 * M_PI);
++ hwd = hht * (float)state->screen_width / (float)state->screen_height;
++
++ glFrustumf(-hwd, hwd, -hht, hht, nearp, farp);
++
++ glEnableClientState( GL_VERTEX_ARRAY );
++ glVertexPointer( 3, GL_BYTE, 0, quadx );
++
++ reset_model(state);
++}
++
++/***********************************************************
++ * Name: reset_model
++ *
++ * Arguments:
++ * CUBE_STATE_T *state - holds OGLES model info
++ *
++ * Description: Resets the Model projection and rotation direction
++ *
++ * Returns: void
++ *
++ ***********************************************************/
++static void reset_model(CUBE_STATE_T *state)
++{
++ // reset model position
++ glMatrixMode(GL_MODELVIEW);
++ glLoadIdentity();
++ glTranslatef(0.f, 0.f, -50.f);
++
++ // reset model rotation
++ state->rot_angle_x = 45.f; state->rot_angle_y = 30.f; state->rot_angle_z = 0.f;
++ state->rot_angle_x_inc = 0.5f; state->rot_angle_y_inc = 0.5f; state->rot_angle_z_inc = 0.f;
++ state->distance = 40.f;
++}
++
++/***********************************************************
++ * Name: update_model
++ *
++ * Arguments:
++ * CUBE_STATE_T *state - holds OGLES model info
++ *
++ * Description: Updates model projection to current position/rotation
++ *
++ * Returns: void
++ *
++ ***********************************************************/
++static void update_model(CUBE_STATE_T *state)
++{
++ // update position
++ state->rot_angle_x = inc_and_wrap_angle(state->rot_angle_x, state->rot_angle_x_inc);
++ state->rot_angle_y = inc_and_wrap_angle(state->rot_angle_y, state->rot_angle_y_inc);
++ state->rot_angle_z = inc_and_wrap_angle(state->rot_angle_z, state->rot_angle_z_inc);
++ state->distance = inc_and_clip_distance(state->distance, state->distance_inc);
++
++ glLoadIdentity();
++ // move camera back to see the cube
++ glTranslatef(0.f, 0.f, -state->distance);
++
++ // Rotate model to new position
++ glRotatef(state->rot_angle_x, 1.f, 0.f, 0.f);
++ glRotatef(state->rot_angle_y, 0.f, 1.f, 0.f);
++ glRotatef(state->rot_angle_z, 0.f, 0.f, 1.f);
++}
++
++/***********************************************************
++ * Name: inc_and_wrap_angle
++ *
++ * Arguments:
++ * GLfloat angle current angle
++ * GLfloat angle_inc angle increment
++ *
++ * Description: Increments or decrements angle by angle_inc degrees
++ * Wraps to 0 at 360 deg.
++ *
++ * Returns: new value of angle
++ *
++ ***********************************************************/
++static GLfloat inc_and_wrap_angle(GLfloat angle, GLfloat angle_inc)
++{
++ angle += angle_inc;
++
++ if (angle >= 360.0)
++ angle -= 360.f;
++ else if (angle <=0)
++ angle += 360.f;
++
++ return angle;
++}
++
++/***********************************************************
++ * Name: inc_and_clip_distance
++ *
++ * Arguments:
++ * GLfloat distance current distance
++ * GLfloat distance_inc distance increment
++ *
++ * Description: Increments or decrements distance by distance_inc units
++ * Clips to range
++ *
++ * Returns: new value of angle
++ *
++ ***********************************************************/
++static GLfloat inc_and_clip_distance(GLfloat distance, GLfloat distance_inc)
++{
++ distance += distance_inc;
++
++ if (distance >= 120.0f)
++ distance = 120.f;
++ else if (distance <= 40.0f)
++ distance = 40.0f;
++
++ return distance;
++}
++
++static pid_t get_server_pid(CUBE_STATE_T *state)
++{
++ struct ucred ucred;
++ socklen_t len;
++ int fd;
++
++ fd = wl_display_get_fd(state->wl_display);
++ len = sizeof ucred;
++ getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &len);
++
++ return ucred.pid;
++}
++
++static void
++frame(void *data, struct wl_callback *callback, uint32_t time)
++{
++ CUBE_STATE_T *state = (CUBE_STATE_T *) data;
++
++ state->needs_update = 1;
++}
++
++static const struct wl_callback_listener frame_listener = {
++ frame
++};
++
++static void
++update(CUBE_STATE_T *state)
++{
++ if (!state->single_frame || state->ellapsed_frames == 0) {
++ update_model(state);
++ redraw_scene(state);
++ }
++
++ state->wl_callback = wl_surface_frame(state->wl_surface);
++ wl_callback_add_listener(state->wl_callback, &frame_listener, state);
++
++ if (state->ellapsed_frames == 100) {
++ if (state->kill_compositor) {
++ fprintf(stderr, "reached frame 100, killing compositor\n");
++ pid_t pid = get_server_pid(state);
++ kill(pid, SIGTERM);
++ } else if (state->terminate_abruptly) {
++ fprintf(stderr, "reached frame 100, terminating right away\n");
++ exit_func(state);
++ exit(0);
++ }
++ }
++
++ if (!state->single_frame || state->ellapsed_frames == 0)
++ eglSwapBuffers(state->display, state->surface);
++ else {
++ wl_surface_damage(state->wl_surface, 0, 0, state->screen_width,
++ state->screen_height);
++ wl_surface_commit(state->wl_surface);
++ }
++
++ state->ellapsed_frames++;
++}
++
++/***********************************************************
++ * Name: redraw_scene
++ *
++ * Arguments:
++ * CUBE_STATE_T *state - holds OGLES model info
++ *
++ * Description: Draws the model and calls eglSwapBuffers
++ * to render to screen
++ *
++ * Returns: void
++ *
++ ***********************************************************/
++static void redraw_scene(CUBE_STATE_T *state)
++{
++ // Start with a clear screen
++ glClear( GL_COLOR_BUFFER_BIT );
++
++ // Draw first (front) face:
++ // Bind texture surface to current vertices
++ glBindTexture(GL_TEXTURE_2D, state->tex[0]);
++
++ // Need to rotate textures - do this by rotating each cube face
++ glRotatef(270.f, 0.f, 0.f, 1.f ); // front face normal along z axis
++
++ // draw first 4 vertices
++ glDrawArrays( GL_TRIANGLE_STRIP, 0, 4);
++
++ // same pattern for other 5 faces - rotation chosen to make image orientation 'nice'
++ glBindTexture(GL_TEXTURE_2D, state->tex[1]);
++ glRotatef(90.f, 0.f, 0.f, 1.f ); // back face normal along z axis
++ glDrawArrays( GL_TRIANGLE_STRIP, 4, 4);
++
++ glBindTexture(GL_TEXTURE_2D, state->tex[2]);
++ glRotatef(90.f, 1.f, 0.f, 0.f ); // left face normal along x axis
++ glDrawArrays( GL_TRIANGLE_STRIP, 8, 4);
++
++ glBindTexture(GL_TEXTURE_2D, state->tex[3]);
++ glRotatef(90.f, 1.f, 0.f, 0.f ); // right face normal along x axis
++ glDrawArrays( GL_TRIANGLE_STRIP, 12, 4);
++
++ glBindTexture(GL_TEXTURE_2D, state->tex[4]);
++ glRotatef(270.f, 0.f, 1.f, 0.f ); // top face normal along y axis
++ glDrawArrays( GL_TRIANGLE_STRIP, 16, 4);
++
++ glBindTexture(GL_TEXTURE_2D, state->tex[5]);
++ glRotatef(90.f, 0.f, 1.f, 0.f ); // bottom face normal along y axis
++ glDrawArrays( GL_TRIANGLE_STRIP, 20, 4);
++}
++
++/***********************************************************
++ * Name: init_textures
++ *
++ * Arguments:
++ * CUBE_STATE_T *state - holds OGLES model info
++ *
++ * Description: Initialise OGL|ES texture surfaces to use image
++ * buffers
++ *
++ * Returns: void
++ *
++ ***********************************************************/
++static void init_textures(CUBE_STATE_T *state)
++{
++ // load three texture buffers but use them on six OGL|ES texture surfaces
++ load_tex_images(state);
++ glGenTextures(6, &state->tex[0]);
++
++ // setup first texture
++ glBindTexture(GL_TEXTURE_2D, state->tex[0]);
++ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, IMAGE_SIZE, IMAGE_SIZE, 0,
++ GL_RGB, GL_UNSIGNED_BYTE, state->tex_buf1);
++ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (GLfloat)GL_NEAREST);
++ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (GLfloat)GL_NEAREST);
++
++ // setup second texture - reuse first image
++ glBindTexture(GL_TEXTURE_2D, state->tex[1]);
++ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, IMAGE_SIZE, IMAGE_SIZE, 0,
++ GL_RGB, GL_UNSIGNED_BYTE, state->tex_buf1);
++ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (GLfloat)GL_NEAREST);
++ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (GLfloat)GL_NEAREST);
++
++ // third texture
++ glBindTexture(GL_TEXTURE_2D, state->tex[2]);
++ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, IMAGE_SIZE, IMAGE_SIZE, 0,
++ GL_RGB, GL_UNSIGNED_BYTE, state->tex_buf2);
++ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (GLfloat)GL_NEAREST);
++ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (GLfloat)GL_NEAREST);
++
++ // fourth texture - reuse second image
++ glBindTexture(GL_TEXTURE_2D, state->tex[3]);
++ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, IMAGE_SIZE, IMAGE_SIZE, 0,
++ GL_RGB, GL_UNSIGNED_BYTE, state->tex_buf2);
++ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (GLfloat)GL_NEAREST);
++ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (GLfloat)GL_NEAREST);
++
++ //fifth texture
++ glBindTexture(GL_TEXTURE_2D, state->tex[4]);
++ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, IMAGE_SIZE, IMAGE_SIZE, 0,
++ GL_RGB, GL_UNSIGNED_BYTE, state->tex_buf3);
++ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (GLfloat)GL_NEAREST);
++ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (GLfloat)GL_NEAREST);
++
++ // sixth texture - reuse third image
++ glBindTexture(GL_TEXTURE_2D, state->tex[5]);
++ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, IMAGE_SIZE, IMAGE_SIZE, 0,
++ GL_RGB, GL_UNSIGNED_BYTE, state->tex_buf3);
++ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (GLfloat)GL_NEAREST);
++ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (GLfloat)GL_NEAREST);
++
++ // setup overall texture environment
++ glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
++ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
++
++ glEnable(GL_TEXTURE_2D);
++}
++
++/***********************************************************
++ * Name: load_tex_images
++ *
++ * Arguments:
++ * void
++ *
++ * Description: Loads three raw images to use as textures on faces
++ *
++ * Returns: void
++ *
++ ***********************************************************/
++static void load_tex_images(CUBE_STATE_T *state)
++{
++ FILE *tex_file1 = NULL, *tex_file2=NULL, *tex_file3 = NULL;
++ int bytes_read, image_sz = IMAGE_SIZE*IMAGE_SIZE*3;
++
++ state->tex_buf1 = malloc(image_sz);
++ state->tex_buf2 = malloc(image_sz);
++ state->tex_buf3 = malloc(image_sz);
++
++ tex_file1 = fopen(PATH "Lucca_128_128.raw", "rb");
++ if (tex_file1 && state->tex_buf1)
++ {
++ bytes_read=fread(state->tex_buf1, 1, image_sz, tex_file1);
++ assert(bytes_read == image_sz); // some problem with file?
++ fclose(tex_file1);
++ }
++
++ tex_file2 = fopen(PATH "Djenne_128_128.raw", "rb");
++ if (tex_file2 && state->tex_buf2)
++ {
++ bytes_read=fread(state->tex_buf2, 1, image_sz, tex_file2);
++ assert(bytes_read == image_sz); // some problem with file?
++ fclose(tex_file2);
++ }
++
++ tex_file3 = fopen(PATH "Gaudi_128_128.raw", "rb");
++ if (tex_file3 && state->tex_buf3)
++ {
++ bytes_read=fread(state->tex_buf3, 1, image_sz, tex_file3);
++ assert(bytes_read == image_sz); // some problem with file?
++ fclose(tex_file3);
++ }
++}
++
++//------------------------------------------------------------------------------
++
++static void exit_func(CUBE_STATE_T *state)
++{
++ // clear screen
++ glClear( GL_COLOR_BUFFER_BIT );
++ eglSwapBuffers(state->display, state->surface);
++
++ // Release OpenGL resources
++ eglMakeCurrent( state->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT );
++
++ wl_egl_window_destroy(state->wl_egl_window);
++ wl_shell_surface_destroy(state->wl_shell_surface);
++ wl_surface_destroy(state->wl_surface);
++
++ eglDestroySurface( state->display, state->surface );
++ eglDestroyContext( state->display, state->context );
++ eglTerminate( state->display );
++
++ wl_display_flush(state->wl_display);
++
++ // release texture buffers
++ free(state->tex_buf1);
++ free(state->tex_buf2);
++ free(state->tex_buf3);
++
++ printf("\ncube closed\n");
++} // exit_func()
++
++static int running = 1;
++
++static void
++signal_int(int signum)
++{
++ running = 0;
++}
++
++//==============================================================================
++
++int main (int argc, char *argv[])
++{
++ struct sigaction sigint;
++ CUBE_STATE_T state = {0,};
++ int ret = 0;
++ int i;
++
++ for (i = 0; i < argc; i++) {
++ if (strcmp(argv[i], "--kill-compositor") == 0)
++ state.kill_compositor = 1;
++ if (strcmp(argv[i], "--single-frame") == 0)
++ state.single_frame = 1;
++ if (strcmp(argv[i], "--terminate-abruptly") == 0)
++ state.terminate_abruptly = 1;
++ else if (strcmp(argv[i], "--help") == 0 ||
++ strcmp(argv[i], "-h") == 0) {
++ printf("Usage: hello_wayland.bin [OPTION]\n\n");
++ printf("\t--kill-compositor\tkill the Wayland compositor after 100 frames\n");
++ printf("\t-h, --help\t\tshow this text\n");
++ printf("\t--single-frame\t\tupdate the display only once\n");
++ printf("\t--terminate-abruptly\texit right after rendering the 100th frame\n");
++ return 0;
++ }
++ }
++
++ // Start OGLES
++ init_ogl(&state);
++
++ // Setup the model world
++ init_model_proj(&state);
++
++ // initialise the OGLES texture(s)
++ init_textures(&state);
++
++ sigint.sa_handler = signal_int;
++ sigemptyset(&sigint.sa_mask);
++ sigint.sa_flags = SA_RESETHAND;
++ sigaction(SIGINT, &sigint, NULL);
++
++ state.needs_update = 1;
++ while (running && ret != -1) {
++ if (state.needs_update) {
++ update(&state);
++ state.needs_update = 0;
++ }
++
++ ret = wl_display_dispatch(state.wl_display);
++ }
++
++ exit_func(&state);
++
++ return 0;
++}
++
+diff --git a/host_applications/linux/apps/hello_pi/rebuild.sh b/host_applications/linux/apps/hello_pi/rebuild.sh
+index 8225dd5..0be6ce7 100755
+--- a/host_applications/linux/apps/hello_pi/rebuild.sh
++++ b/host_applications/linux/apps/hello_pi/rebuild.sh
+@@ -14,6 +14,7 @@ make -C hello_videocube clean
+ make -C hello_teapot clean
+ make -C hello_fft clean
+ make -C hello_mmal_encode clean
++make -C hello_wayland clean
+
+ make -C libs/ilclient
+ make -C libs/vgfont
+@@ -31,4 +32,4 @@ make -C hello_videocube
+ make -C hello_teapot
+ make -C hello_fft
+ make -C hello_mmal_encode
+-
++make -C hello_wayland
+--
+2.16.1
+
diff --git a/meta-raspberrypi/recipes-graphics/userland/userland/0004-wayland-egl-Add-bcm_host-to-dependencies.patch b/meta-raspberrypi/recipes-graphics/userland/userland/0004-wayland-egl-Add-bcm_host-to-dependencies.patch
new file mode 100644
index 0000000..713fc3e
--- /dev/null
+++ b/meta-raspberrypi/recipes-graphics/userland/userland/0004-wayland-egl-Add-bcm_host-to-dependencies.patch
@@ -0,0 +1,28 @@
+From f17879b691984b5c4950e4b94ebf102c78797ede Mon Sep 17 00:00:00 2001
+From: Khem Raj <raj.khem@gmail.com>
+Date: Mon, 10 Aug 2015 02:38:27 -0700
+Subject: [PATCH 04/16] wayland-egl: Add bcm_host to dependencies
+
+It uses headers like vcos_platform_types.h but does not
+depend on module which should add the required include paths
+lets add the dependency on bcm_host module which should do it
+
+Signed-off-by: Khem Raj <raj.khem@gmail.com>
+---
+ interface/khronos/wayland-egl/wayland-egl.pc.in | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/interface/khronos/wayland-egl/wayland-egl.pc.in b/interface/khronos/wayland-egl/wayland-egl.pc.in
+index 8bafc15..fd259c9 100644
+--- a/interface/khronos/wayland-egl/wayland-egl.pc.in
++++ b/interface/khronos/wayland-egl/wayland-egl.pc.in
+@@ -6,5 +6,6 @@ includedir=${prefix}/include
+ Name: wayland-egl
+ Description: VideoCore wayland-egl library
+ Version: @PROJECT_APIVER@
++Requires: bcm_host
+ Libs: -L${libdir} -lwayland-egl
+ Cflags: -I${includedir}
+--
+2.16.1
+
diff --git a/meta-raspberrypi/recipes-graphics/userland/userland/0005-interface-remove-faulty-assert-to-make-weston-happy-.patch b/meta-raspberrypi/recipes-graphics/userland/userland/0005-interface-remove-faulty-assert-to-make-weston-happy-.patch
new file mode 100644
index 0000000..8d78333
--- /dev/null
+++ b/meta-raspberrypi/recipes-graphics/userland/userland/0005-interface-remove-faulty-assert-to-make-weston-happy-.patch
@@ -0,0 +1,29 @@
+From 0273b7b9d7a27d8fe7d3ad8680b799f997e75dca Mon Sep 17 00:00:00 2001
+From: "Yann E. MORIN" <yann.morin.1998@free.fr>
+Date: Sat, 24 Jan 2015 22:07:19 +0100
+Subject: [PATCH 05/16] interface: remove faulty assert() to make weston happy
+ at runtime
+
+This was removed after a discussion on IRC with the weston guys
+('daniels' on irc.freenode.net/#wayland).
+
+Signed-off-by: "Yann E. MORIN" <yann.morin.1998@free.fr>
+---
+ interface/vmcs_host/vc_vchi_dispmanx.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/interface/vmcs_host/vc_vchi_dispmanx.c b/interface/vmcs_host/vc_vchi_dispmanx.c
+index eab146e..29e0dee 100755
+--- a/interface/vmcs_host/vc_vchi_dispmanx.c
++++ b/interface/vmcs_host/vc_vchi_dispmanx.c
+@@ -1306,7 +1306,6 @@ static void *dispmanx_notify_func( void *arg ) {
+ // Decrement the use count - the corresponding "use" is in vc_dispmanx_update_submit.
+ vchi_service_release(dispmanx_client.notify_handle[0]);
+ if (dispmanx_client.update_callback ) {
+- vcos_assert( dispmanx_client.pending_update_handle == handle);
+ dispmanx_client.update_callback(handle, dispmanx_client.update_callback_param);
+ }
+ } else {
+--
+2.16.1
+
diff --git a/meta-raspberrypi/recipes-graphics/userland/userland/0006-zero-out-wl-buffers-in-egl_surface_free.patch b/meta-raspberrypi/recipes-graphics/userland/userland/0006-zero-out-wl-buffers-in-egl_surface_free.patch
new file mode 100644
index 0000000..43eb7f0
--- /dev/null
+++ b/meta-raspberrypi/recipes-graphics/userland/userland/0006-zero-out-wl-buffers-in-egl_surface_free.patch
@@ -0,0 +1,33 @@
+From 0d678cd2042551cc4e26ec42fa3aba7c72d033b4 Mon Sep 17 00:00:00 2001
+From: Khem Raj <raj.khem@gmail.com>
+Date: Sat, 6 Feb 2016 11:10:47 -0800
+Subject: [PATCH 06/16] zero-out wl buffers in egl_surface_free
+
+origins from buildroot
+
+Signed-off-by: Khem Raj <raj.khem@gmail.com>
+---
+ interface/khronos/egl/egl_client_surface.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/interface/khronos/egl/egl_client_surface.c b/interface/khronos/egl/egl_client_surface.c
+index 42350bf..1f923d9 100644
+--- a/interface/khronos/egl/egl_client_surface.c
++++ b/interface/khronos/egl/egl_client_surface.c
+@@ -690,11 +690,13 @@ void egl_surface_free(EGL_SURFACE_T *surface)
+ if (surface->back_wl_buffer) {
+ wl_buffer_destroy(surface->back_wl_buffer->wl_buffer);
+ free(surface->back_wl_buffer);
++ surface->back_wl_buffer = 0;
+ }
+
+ if (surface->front_wl_buffer) {
+ wl_buffer_destroy(surface->front_wl_buffer->wl_buffer);
+ free(surface->front_wl_buffer);
++ surface->front_wl_buffer = 0;
+ }
+ #endif
+ }
+--
+2.16.1
+
diff --git a/meta-raspberrypi/recipes-graphics/userland/userland/0007-initialize-front-back-wayland-buffers.patch b/meta-raspberrypi/recipes-graphics/userland/userland/0007-initialize-front-back-wayland-buffers.patch
new file mode 100644
index 0000000..987740b
--- /dev/null
+++ b/meta-raspberrypi/recipes-graphics/userland/userland/0007-initialize-front-back-wayland-buffers.patch
@@ -0,0 +1,34 @@
+From ec2e00989bf614b259bc9a47b5035f8586e8a214 Mon Sep 17 00:00:00 2001
+From: Khem Raj <raj.khem@gmail.com>
+Date: Sat, 6 Feb 2016 11:11:41 -0800
+Subject: [PATCH 07/16] initialize front back wayland buffers
+
+origins from metrological wayland support
+
+Signed-off-by: Khem Raj <raj.khem@gmail.com>
+---
+ interface/khronos/egl/egl_client_surface.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/interface/khronos/egl/egl_client_surface.c b/interface/khronos/egl/egl_client_surface.c
+index 1f923d9..9a9582c 100644
+--- a/interface/khronos/egl/egl_client_surface.c
++++ b/interface/khronos/egl/egl_client_surface.c
+@@ -401,11 +401,14 @@ EGL_SURFACE_T *egl_surface_create(
+ #ifdef BUILD_WAYLAND
+ if (type == WINDOW && wl_display) {
+ surface->wl_egl_window = (struct wl_egl_window*)win;
++ surface->front_wl_buffer = NULL;
+ surface->back_wl_buffer = allocate_wl_buffer(
+ surface->wl_egl_window, color);
+ resource = surface->back_wl_buffer->resource;
+ } else {
+ surface->wl_egl_window = NULL;
++ surface->front_wl_buffer = NULL;
++ surface->back_wl_buffer = NULL;
+ resource = DISPMANX_NO_HANDLE;
+ }
+ #endif
+--
+2.16.1
+
diff --git a/meta-raspberrypi/recipes-graphics/userland/userland/0008-Remove-RPC_FLUSH.patch b/meta-raspberrypi/recipes-graphics/userland/userland/0008-Remove-RPC_FLUSH.patch
new file mode 100644
index 0000000..4bf05c1
--- /dev/null
+++ b/meta-raspberrypi/recipes-graphics/userland/userland/0008-Remove-RPC_FLUSH.patch
@@ -0,0 +1,27 @@
+From 59ba66c2ea17f7a57124b9fd6c9bdff4325ff5c9 Mon Sep 17 00:00:00 2001
+From: Khem Raj <raj.khem@gmail.com>
+Date: Sat, 6 Feb 2016 11:09:18 -0800
+Subject: [PATCH 08/16] Remove RPC_FLUSH
+
+Origins from buildroot
+
+Signed-off-by: Khem Raj <raj.khem@gmail.com>
+---
+ interface/khronos/ext/gl_oes_egl_image_client.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/interface/khronos/ext/gl_oes_egl_image_client.c b/interface/khronos/ext/gl_oes_egl_image_client.c
+index f9b7287..b04ffef 100644
+--- a/interface/khronos/ext/gl_oes_egl_image_client.c
++++ b/interface/khronos/ext/gl_oes_egl_image_client.c
+@@ -107,7 +107,6 @@ GL_API void GL_APIENTRY glEGLImageTargetTexture2DOES (GLenum target, GLeglImageO
+ GLEGLIMAGETARGETTEXTURE2DOES_ID,
+ RPC_ENUM(target),
+ RPC_EGLID(image));
+- RPC_FLUSH(thread);
+ #if EGL_BRCM_global_image
+ }
+ #endif
+--
+2.16.1
+
diff --git a/meta-raspberrypi/recipes-graphics/userland/userland/0009-fix-cmake-dependency-race.patch b/meta-raspberrypi/recipes-graphics/userland/userland/0009-fix-cmake-dependency-race.patch
new file mode 100644
index 0000000..a2c1df5
--- /dev/null
+++ b/meta-raspberrypi/recipes-graphics/userland/userland/0009-fix-cmake-dependency-race.patch
@@ -0,0 +1,78 @@
+From 264d82387ea1e607b2e5c899ff6bd46807c7b185 Mon Sep 17 00:00:00 2001
+From: Khem Raj <raj.khem@gmail.com>
+Date: Sat, 6 Feb 2016 13:12:47 -0800
+Subject: [PATCH 09/16] fix cmake dependency race
+
+Fixes errors like
+
+/a/builder/mnt/build-oe/tmp-glibc/work/raspberrypi2-oe-linux-gnueabi/userland/git-r5/git/interface/vmcs_host/vc_vchi_dispmanx.h:72:66:
+fatal error: interface/vmcs_host/wayland-dispmanx-server-protocol.h: No
+such file or directory
+compilation terminated.
+interface/khronos/CMakeFiles/EGL_static.dir/build.make:773: recipe for
+target 'interface/khronos/CMakeFiles/EGL_static.dir/ext/egl_wayland.c.o'
+failed
+make[2]: ***
+[interface/khronos/CMakeFiles/EGL_static.dir/ext/egl_wayland.c.o] Error 1
+
+Signed-off-by: Khem Raj <raj.khem@gmail.com>
+---
+ interface/vcos/pthreads/CMakeLists.txt | 8 ++++++++
+ interface/vmcs_host/CMakeLists.txt | 8 --------
+ interface/vmcs_host/vc_vchi_dispmanx.h | 2 +-
+ 3 files changed, 9 insertions(+), 9 deletions(-)
+
+diff --git a/interface/vcos/pthreads/CMakeLists.txt b/interface/vcos/pthreads/CMakeLists.txt
+index 1d81ca3..d6cd415 100644
+--- a/interface/vcos/pthreads/CMakeLists.txt
++++ b/interface/vcos/pthreads/CMakeLists.txt
+@@ -33,6 +33,14 @@ set (SOURCES
+ ../generic/vcos_generic_blockpool.c
+ )
+
++if (BUILD_WAYLAND)
++wayland_add_protocol_server(
++ SOURCES
++ ../../../interface/wayland/dispmanx.xml
++ dispmanx
++)
++endif ()
++
+ if (VCOS_PTHREADS_BUILD_SHARED)
+ add_library (vcos SHARED ${SOURCES})
+ target_link_libraries (vcos pthread dl rt)
+diff --git a/interface/vmcs_host/CMakeLists.txt b/interface/vmcs_host/CMakeLists.txt
+index 6718215..c415176 100755
+--- a/interface/vmcs_host/CMakeLists.txt
++++ b/interface/vmcs_host/CMakeLists.txt
+@@ -17,14 +17,6 @@ set(VCHOSTIF_SOURCE
+ # ${VMCS_TARGET}/vmcs_main.c
+ # vc_vchi_haud.c
+
+-if (BUILD_WAYLAND)
+-wayland_add_protocol_server(
+- VCHOSTIF_SOURCE
+- ../../interface/wayland/dispmanx.xml
+- dispmanx
+-)
+-endif ()
+-
+ add_library(vchostif ${VCHOSTIF_SOURCE})
+
+ #add_library(bufman vc_vchi_bufman.c )
+diff --git a/interface/vmcs_host/vc_vchi_dispmanx.h b/interface/vmcs_host/vc_vchi_dispmanx.h
+index f0bae30..8c44c58 100644
+--- a/interface/vmcs_host/vc_vchi_dispmanx.h
++++ b/interface/vmcs_host/vc_vchi_dispmanx.h
+@@ -69,7 +69,7 @@ typedef struct {
+ #ifdef BUILD_WAYLAND
+ /* XXX: This should be in a private header that can be included from EGL and vc_* */
+ #include <wayland-server.h>
+-#include "interface/vmcs_host/wayland-dispmanx-server-protocol.h"
++#include "interface/vcos/pthreads/wayland-dispmanx-server-protocol.h"
+ struct wl_dispmanx_server_buffer {
+ struct wl_resource *resource;
+ struct wl_dispmanx *dispmanx;
+--
+2.16.1
+
diff --git a/meta-raspberrypi/recipes-graphics/userland/userland/0010-Fix-for-framerate-with-nested-composition.patch b/meta-raspberrypi/recipes-graphics/userland/userland/0010-Fix-for-framerate-with-nested-composition.patch
new file mode 100644
index 0000000..a6c9a59
--- /dev/null
+++ b/meta-raspberrypi/recipes-graphics/userland/userland/0010-Fix-for-framerate-with-nested-composition.patch
@@ -0,0 +1,60 @@
+From 7c51c2d37bfadaabbbf205237d932b685b09d34f Mon Sep 17 00:00:00 2001
+From: Khem Raj <raj.khem@gmail.com>
+Date: Tue, 29 Mar 2016 20:38:30 -0700
+Subject: [PATCH 10/16] Fix for framerate with nested composition
+
+frame rate appears irregular and lower than expected when using nested composition.
+
+Signed-off-by: Khem Raj <raj.khem@gmail.com>
+---
+ interface/khronos/egl/egl_client.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/interface/khronos/egl/egl_client.c b/interface/khronos/egl/egl_client.c
+index 03fe67b..13a110c 100644
+--- a/interface/khronos/egl/egl_client.c
++++ b/interface/khronos/egl/egl_client.c
+@@ -2342,6 +2342,9 @@ EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffers(EGLDisplay dpy, EGLSurface surf)
+ surface->back_wl_buffer = buffer;
+ }
+
++ glFlush();
++ glFinish();
++
+ RPC_CALL7(eglIntSwapBuffers_impl,
+ thread,
+ EGLINTSWAPBUFFERS_ID_V2,
+@@ -2353,6 +2356,8 @@ EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffers(EGLDisplay dpy, EGLSurface surf)
+ RPC_UINT(khrn_platform_get_window_position(surface->win)),
+ RPC_INT(surface->back_wl_buffer->resource));
+
++ RPC_FLUSH(thread);
++
+ surface->front_wl_buffer->in_use = 1;
+ wl_surface_attach(wl_egl_window->wl_surface,
+ surface->front_wl_buffer->wl_buffer,
+@@ -2360,11 +2365,13 @@ EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffers(EGLDisplay dpy, EGLSurface surf)
+ wl_surface_damage(wl_egl_window->wl_surface, 0, 0,
+ surface->width, surface->height);
+ wl_surface_commit(wl_egl_window->wl_surface);
++ wl_display_flush(wl_display);
+
+ while(ret != -1 && surface->back_wl_buffer->in_use)
+ ret = wl_display_dispatch_queue(wl_display, process->wl_queue);
+ } else
+ #endif
++ {
+ RPC_CALL6(eglIntSwapBuffers_impl,
+ thread,
+ EGLINTSWAPBUFFERS_ID,
+@@ -2376,6 +2383,7 @@ EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffers(EGLDisplay dpy, EGLSurface surf)
+ RPC_UINT(khrn_platform_get_window_position(surface->win)));
+
+ RPC_FLUSH(thread);
++ }
+
+ #ifdef ANDROID
+ CLIENT_UNLOCK();
+--
+2.16.1
+
diff --git a/meta-raspberrypi/recipes-graphics/userland/userland/0011-build-shared-library-for-vchostif.patch b/meta-raspberrypi/recipes-graphics/userland/userland/0011-build-shared-library-for-vchostif.patch
new file mode 100644
index 0000000..55a5be8
--- /dev/null
+++ b/meta-raspberrypi/recipes-graphics/userland/userland/0011-build-shared-library-for-vchostif.patch
@@ -0,0 +1,28 @@
+From fb3002f77a175633af31019c513754d2ef5f3ac0 Mon Sep 17 00:00:00 2001
+From: Khem Raj <raj.khem@gmail.com>
+Date: Sat, 2 Apr 2016 10:37:24 -0700
+Subject: [PATCH 11/16] build shared library for vchostif
+
+Fixes #149
+
+Signed-off-by: Khem Raj <raj.khem@gmail.com>
+---
+ interface/vmcs_host/CMakeLists.txt | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/interface/vmcs_host/CMakeLists.txt b/interface/vmcs_host/CMakeLists.txt
+index c415176..d0cca1a 100755
+--- a/interface/vmcs_host/CMakeLists.txt
++++ b/interface/vmcs_host/CMakeLists.txt
+@@ -17,7 +17,7 @@ set(VCHOSTIF_SOURCE
+ # ${VMCS_TARGET}/vmcs_main.c
+ # vc_vchi_haud.c
+
+-add_library(vchostif ${VCHOSTIF_SOURCE})
++add_library(vchostif SHARED ${VCHOSTIF_SOURCE})
+
+ #add_library(bufman vc_vchi_bufman.c )
+
+--
+2.16.1
+
diff --git a/meta-raspberrypi/recipes-graphics/userland/userland/0012-implement-buffer-wrapping-interface-for-dispmanx.patch b/meta-raspberrypi/recipes-graphics/userland/userland/0012-implement-buffer-wrapping-interface-for-dispmanx.patch
new file mode 100644
index 0000000..28a5fc6
--- /dev/null
+++ b/meta-raspberrypi/recipes-graphics/userland/userland/0012-implement-buffer-wrapping-interface-for-dispmanx.patch
@@ -0,0 +1,92 @@
+From df8b9633a45069bdd1bf256d974636ef11aa39cb Mon Sep 17 00:00:00 2001
+From: Khem Raj <raj.khem@gmail.com>
+Date: Sat, 2 Apr 2016 10:54:59 -0700
+Subject: [PATCH 12/16] implement buffer wrapping interface for dispmanx
+
+Courtesy: Zan Dobersek
+
+Signed-off-by: Khem Raj <raj.khem@gmail.com>
+---
+ interface/khronos/ext/egl_wayland.c | 42 +++++++++++++++++++++++++++++++++++++
+ interface/wayland/dispmanx.xml | 10 +++++++++
+ 2 files changed, 52 insertions(+)
+
+diff --git a/interface/khronos/ext/egl_wayland.c b/interface/khronos/ext/egl_wayland.c
+index 5730743..9ef89cd 100644
+--- a/interface/khronos/ext/egl_wayland.c
++++ b/interface/khronos/ext/egl_wayland.c
+@@ -133,8 +133,50 @@ dispmanx_create_buffer(struct wl_client *client, struct wl_resource *resource,
+ buffer->handle);
+ }
+
++static void
++dispmanx_wrap_buffer(struct wl_client *client, struct wl_resource *resource,
++ uint32_t id, uint32_t handle, int32_t width, int32_t height,
++ uint32_t stride, uint32_t buffer_height, uint32_t format)
++{
++ struct wl_dispmanx_server_buffer *buffer;
++ VC_IMAGE_TYPE_T vc_format = get_vc_format(format);
++ uint32_t dummy;
++
++ if(vc_format == VC_IMAGE_MIN) {
++ wl_resource_post_error(resource,
++ WL_DISPMANX_ERROR_INVALID_FORMAT,
++ "invalid format");
++ return;
++ }
++
++ buffer = calloc(1, sizeof *buffer);
++ if (buffer == NULL) {
++ wl_resource_post_no_memory(resource);
++ return;
++ }
++
++ buffer->handle = handle;
++ buffer->width = width;
++ buffer->height = height;
++ buffer->format = format;
++
++ buffer->resource = wl_resource_create(resource->client, &wl_buffer_interface,
++ 1, id);
++ if (!buffer->resource) {
++ wl_resource_post_no_memory(resource);
++ vc_dispmanx_resource_delete(buffer->handle);
++ free(buffer);
++ return;
++ }
++
++ wl_resource_set_implementation(buffer->resource,
++ (void (**)(void)) &dispmanx_buffer_interface,
++ buffer, destroy_buffer);
++}
++
+ static const struct wl_dispmanx_interface dispmanx_interface = {
+ dispmanx_create_buffer,
++ dispmanx_wrap_buffer,
+ };
+
+ static void
+diff --git a/interface/wayland/dispmanx.xml b/interface/wayland/dispmanx.xml
+index c18626d..11ed1ef 100644
+--- a/interface/wayland/dispmanx.xml
++++ b/interface/wayland/dispmanx.xml
+@@ -118,6 +118,16 @@
+ <arg name="buffer" type="object" interface="wl_buffer"/>
+ <arg name="handle" type="uint"/>
+ </event>
++
++ <request name="wrap_buffer">
++ <arg name="id" type="new_id" interface="wl_buffer"/>
++ <arg name="handle" type="uint"/>
++ <arg name="width" type="int"/>
++ <arg name="height" type="int"/>
++ <arg name="stride" type="uint"/>
++ <arg name="buffer_height" type="uint"/>
++ <arg name="format" type="uint"/>
++ </request>
+ </interface>
+
+ </protocol>
+--
+2.16.1
+
diff --git a/meta-raspberrypi/recipes-graphics/userland/userland/0013-Implement-triple-buffering-for-wayland.patch b/meta-raspberrypi/recipes-graphics/userland/userland/0013-Implement-triple-buffering-for-wayland.patch
new file mode 100644
index 0000000..ebff314
--- /dev/null
+++ b/meta-raspberrypi/recipes-graphics/userland/userland/0013-Implement-triple-buffering-for-wayland.patch
@@ -0,0 +1,90 @@
+From 2e0e331da8556fecd841349cfae294baf0f14485 Mon Sep 17 00:00:00 2001
+From: Jeff Wannamaker <jeff_wannamaker@cable.comcast.com>
+Date: Thu, 19 Jan 2017 18:56:07 +0000
+Subject: [PATCH 13/16] Implement triple buffering for wayland
+
+Change from double to triple buffering for wayland.
+This enables higher frame rates without tearing artifacts
+by allowing both the glFinish and the buffer release
+interlock to operate without pushing the frame period
+to two vertical intervals
+
+Signed-off-by: Jeff Wannamaker <jeff_wannamaker@cable.comcast.com>
+Signed-off-by: Khem Raj <raj.khem@gmail.com>
+---
+ interface/khronos/egl/egl_client.c | 3 ++-
+ interface/khronos/egl/egl_client_surface.c | 8 ++++++++
+ interface/khronos/egl/egl_client_surface.h | 11 +++++++++++
+ 3 files changed, 21 insertions(+), 1 deletion(-)
+
+diff --git a/interface/khronos/egl/egl_client.c b/interface/khronos/egl/egl_client.c
+index 13a110c..0380274 100644
+--- a/interface/khronos/egl/egl_client.c
++++ b/interface/khronos/egl/egl_client.c
+@@ -2323,7 +2323,8 @@ EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffers(EGLDisplay dpy, EGLSurface surf)
+
+ buffer_temp = surface->front_wl_buffer;
+ surface->front_wl_buffer = surface->back_wl_buffer;
+- surface->back_wl_buffer = buffer_temp;
++ surface->back_wl_buffer = surface->middle_wl_buffer;
++ surface->middle_wl_buffer = buffer_temp;
+
+ configid = egl_config_to_id(surface->config);
+ color = egl_config_get_color_format(configid);
+diff --git a/interface/khronos/egl/egl_client_surface.c b/interface/khronos/egl/egl_client_surface.c
+index 9a9582c..10b3b04 100644
+--- a/interface/khronos/egl/egl_client_surface.c
++++ b/interface/khronos/egl/egl_client_surface.c
+@@ -402,12 +402,14 @@ EGL_SURFACE_T *egl_surface_create(
+ if (type == WINDOW && wl_display) {
+ surface->wl_egl_window = (struct wl_egl_window*)win;
+ surface->front_wl_buffer = NULL;
++ surface->middle_wl_buffer = NULL;
+ surface->back_wl_buffer = allocate_wl_buffer(
+ surface->wl_egl_window, color);
+ resource = surface->back_wl_buffer->resource;
+ } else {
+ surface->wl_egl_window = NULL;
+ surface->front_wl_buffer = NULL;
++ surface->middle_wl_buffer = NULL;
+ surface->back_wl_buffer = NULL;
+ resource = DISPMANX_NO_HANDLE;
+ }
+@@ -696,6 +698,12 @@ void egl_surface_free(EGL_SURFACE_T *surface)
+ surface->back_wl_buffer = 0;
+ }
+
++ if (surface->middle_wl_buffer) {
++ wl_buffer_destroy(surface->middle_wl_buffer->wl_buffer);
++ free(surface->middle_wl_buffer);
++ surface->middle_wl_buffer = 0;
++ }
++
+ if (surface->front_wl_buffer) {
+ wl_buffer_destroy(surface->front_wl_buffer->wl_buffer);
+ free(surface->front_wl_buffer);
+diff --git a/interface/khronos/egl/egl_client_surface.h b/interface/khronos/egl/egl_client_surface.h
+index e328b77..58a3184 100644
+--- a/interface/khronos/egl/egl_client_surface.h
++++ b/interface/khronos/egl/egl_client_surface.h
+@@ -312,6 +312,17 @@ typedef struct {
+ */
+ struct wl_dispmanx_client_buffer *front_wl_buffer;
+
++ /*
++ middle_wl_buffer
++
++ Validity:
++ type == WINDOW
++
++ Invariant:
++ client-side information about the wl_buffer in the middle
++ */
++ struct wl_dispmanx_client_buffer *middle_wl_buffer;
++
+ /*
+ back_wl_buffer
+
+--
+2.16.1
+
diff --git a/meta-raspberrypi/recipes-graphics/userland/userland/0014-GLES2-gl2ext.h-Define-GL_R8_EXT-and-GL_RG8_EXT.patch b/meta-raspberrypi/recipes-graphics/userland/userland/0014-GLES2-gl2ext.h-Define-GL_R8_EXT-and-GL_RG8_EXT.patch
new file mode 100644
index 0000000..025b6bc
--- /dev/null
+++ b/meta-raspberrypi/recipes-graphics/userland/userland/0014-GLES2-gl2ext.h-Define-GL_R8_EXT-and-GL_RG8_EXT.patch
@@ -0,0 +1,30 @@
+From 8d9299d219a2a4f76f8278973584e1a9f7116c78 Mon Sep 17 00:00:00 2001
+From: Khem Raj <raj.khem@gmail.com>
+Date: Wed, 10 May 2017 06:39:34 +0000
+Subject: [PATCH 14/16] GLES2/gl2ext.h: Define GL_R8_EXT and GL_RG8_EXT
+
+weston code uses these defines
+Upstream-Status: Pending
+
+Signed-off-by: Khem Raj <raj.khem@gmail.com>
+---
+ interface/khronos/include/GLES2/gl2ext.h | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/interface/khronos/include/GLES2/gl2ext.h b/interface/khronos/include/GLES2/gl2ext.h
+index 4eacf7f..283e3e1 100644
+--- a/interface/khronos/include/GLES2/gl2ext.h
++++ b/interface/khronos/include/GLES2/gl2ext.h
+@@ -327,6 +327,9 @@ typedef void* GLeglImageOES;
+ #define GL_RGBX_BRCM 0x80EE
+ #endif
+
++#define GL_R8_EXT 0x8229
++#define GL_RG8_EXT 0x822B
++
+ /* GL_EXT_texture_type_2_10_10_10_REV */
+ #ifndef GL_EXT_texture_type_2_10_10_10_REV
+ #define GL_UNSIGNED_INT_2_10_10_10_REV_EXT 0x8368
+--
+2.16.1
+
diff --git a/meta-raspberrypi/recipes-graphics/userland/userland/0015-EGL-glplatform.h-define-EGL_CAST.patch b/meta-raspberrypi/recipes-graphics/userland/userland/0015-EGL-glplatform.h-define-EGL_CAST.patch
new file mode 100644
index 0000000..605d0c0
--- /dev/null
+++ b/meta-raspberrypi/recipes-graphics/userland/userland/0015-EGL-glplatform.h-define-EGL_CAST.patch
@@ -0,0 +1,32 @@
+From a2182e5437a6664cdb0f3330f6cbee873b6f975a Mon Sep 17 00:00:00 2001
+From: Andrea Galbusera <gizero@gmail.com>
+Date: Fri, 14 Jul 2017 09:52:54 +0200
+Subject: [PATCH 15/16] EGL/glplatform.h: define EGL_CAST
+
+C++ / C typecast macros for special EGL handle values: used by libepoxy code
+The definition comes from the updated version of this header in mesa.
+
+Upstream-Status: Pending
+---
+ interface/khronos/include/EGL/eglplatform.h | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/interface/khronos/include/EGL/eglplatform.h b/interface/khronos/include/EGL/eglplatform.h
+index 1f7c930..c39d425 100644
+--- a/interface/khronos/include/EGL/eglplatform.h
++++ b/interface/khronos/include/EGL/eglplatform.h
+@@ -202,4 +202,11 @@ EGLAPI void EGLAPIENTRY BEGL_GetDefaultDriverInterfaces(BEGL_DriverInterfaces *i
+ #include "interface/khronos/common/khrn_client_mangle.h"
+ #endif
+
++/* C++ / C typecast macros for special EGL handle values */
++#if defined(__cplusplus)
++#define EGL_CAST(type, value) (static_cast<type>(value))
++#else
++#define EGL_CAST(type, value) ((type) (value))
++#endif
++
+ #endif /* __eglplatform_h */
+--
+2.16.1
+
diff --git a/meta-raspberrypi/recipes-graphics/userland/userland/0016-Allow-multiple-wayland-compositor-state-data-per-pro.patch b/meta-raspberrypi/recipes-graphics/userland/userland/0016-Allow-multiple-wayland-compositor-state-data-per-pro.patch
new file mode 100644
index 0000000..d20ec82
--- /dev/null
+++ b/meta-raspberrypi/recipes-graphics/userland/userland/0016-Allow-multiple-wayland-compositor-state-data-per-pro.patch
@@ -0,0 +1,145 @@
+From 6b4c4d469d435bfcfb464356b6ccc9421c6b8fd5 Mon Sep 17 00:00:00 2001
+From: Jeff Wannamaker <jeff_wannamaker@cable.comcast.com>
+Date: Sat, 27 Jan 2018 12:28:31 -0500
+Subject: [PATCH 16/16] Allow multiple wayland compositor state data per
+ process
+
+When eglBindWaylandDisplayWL is called store the wl_global
+created in a list associated with the wayland display.
+This allows multiple wayland compositor instances to be
+created and used per process. This scenario is common for
+applications integrating externl process UI elements
+via embedded composition e.g. westeros
+
+Signed-off-by: Jeff Wannamaker <jeff_wannamaker@cable.comcast.com>
+Signed-off-by: Khem Raj <raj.khem@gmail.com>
+---
+ interface/khronos/common/khrn_client.c | 2 +-
+ interface/khronos/common/khrn_client.h | 11 +++++++-
+ interface/khronos/ext/egl_wayland.c | 50 ++++++++++++++++++++++++++++++----
+ 3 files changed, 55 insertions(+), 8 deletions(-)
+
+diff --git a/interface/khronos/common/khrn_client.c b/interface/khronos/common/khrn_client.c
+index d7e798e..60bdb63 100644
+--- a/interface/khronos/common/khrn_client.c
++++ b/interface/khronos/common/khrn_client.c
+@@ -147,7 +147,7 @@ bool client_process_state_init(CLIENT_PROCESS_STATE_T *process)
+ {
+ if (!process->inited) {
+ #ifdef BUILD_WAYLAND
+- process->wl_global = NULL;
++ process->wlStateMap = NULL;
+ #endif
+
+ if (!khrn_pointer_map_init(&process->contexts, 64))
+diff --git a/interface/khronos/common/khrn_client.h b/interface/khronos/common/khrn_client.h
+index 615f7b4..4fa86f7 100644
+--- a/interface/khronos/common/khrn_client.h
++++ b/interface/khronos/common/khrn_client.h
+@@ -170,6 +170,15 @@ static INLINE CLIENT_THREAD_STATE_T *CLIENT_GET_CHECK_THREAD_STATE(void)
+ return (CLIENT_THREAD_STATE_T *)platform_tls_get_check(client_tls);
+ }
+
++#ifdef BUILD_WAYLAND
++typedef struct WAYLAND_STATE
++{
++ struct WAYLAND_STATE *next;
++ struct wl_display *display;
++ struct wl_global *wl_global;
++} WAYLAND_STATE_T;
++#endif
++
+ /*
+ per-process state
+
+@@ -318,7 +327,7 @@ struct CLIENT_PROCESS_STATE {
+ struct wl_event_queue *wl_queue;
+
+ /* Compositor-side Wayland state */
+- struct wl_global *wl_global;
++ WAYLAND_STATE_T *wlStateMap;
+ #endif
+ };
+
+diff --git a/interface/khronos/ext/egl_wayland.c b/interface/khronos/ext/egl_wayland.c
+index 9ef89cd..abd5ab3 100644
+--- a/interface/khronos/ext/egl_wayland.c
++++ b/interface/khronos/ext/egl_wayland.c
+@@ -208,17 +208,38 @@ eglBindWaylandDisplayWL(EGLDisplay dpy, struct wl_display *display)
+ {
+ CLIENT_THREAD_STATE_T *thread;
+ CLIENT_PROCESS_STATE_T *process;
++ WAYLAND_STATE_T *stateIter;
++ WAYLAND_STATE_T *stateNew;
++ struct wl_global *wl_global;
+
+ if (!CLIENT_LOCK_AND_GET_STATES(dpy, &thread, &process))
+ return EGL_FALSE;
+
+- if (process->wl_global != NULL)
++ stateIter= process->wlStateMap;
++ while( stateIter )
++ {
++ if ( stateIter->display == display )
++ goto error;
++ stateIter= stateIter->next;
++ }
++
++ wl_global = wl_global_create(display, &wl_dispmanx_interface, 1,
++ NULL, bind_dispmanx);
++ if (wl_global == NULL)
+ goto error;
+
+- process->wl_global = wl_global_create(display, &wl_dispmanx_interface, 1,
+- NULL, bind_dispmanx);
+- if (process->wl_global == NULL)
++ stateNew= (WAYLAND_STATE_T*)calloc( 1, sizeof(WAYLAND_STATE_T));
++ if (stateNew == NULL )
++ {
++ wl_global_destroy(wl_global);
+ goto error;
++ }
++
++ stateNew->next= process->wlStateMap;
++ stateNew->display= display;
++ stateNew->wl_global= wl_global;
++ process->wlStateMap= stateNew;
++ CLIENT_UNLOCK();
+
+ return EGL_TRUE;
+
+@@ -232,12 +253,29 @@ eglUnbindWaylandDisplayWL(EGLDisplay dpy, struct wl_display *display)
+ {
+ CLIENT_THREAD_STATE_T *thread;
+ CLIENT_PROCESS_STATE_T *process;
++ WAYLAND_STATE_T *stateIter;
++ WAYLAND_STATE_T *statePrev;
+
+ if (!CLIENT_LOCK_AND_GET_STATES(dpy, &thread, &process))
+ return EGL_FALSE;
+
+- wl_global_destroy(process->wl_global);
+- process->wl_global = NULL;
++ statePrev= NULL;
++ stateIter= process->wlStateMap;
++ while( stateIter )
++ {
++ if ( stateIter->display == display )
++ {
++ wl_global_destroy(stateIter->wl_global);
++ if ( statePrev )
++ statePrev->next= stateIter->next;
++ else
++ process->wlStateMap= stateIter->next;
++ free( stateIter );
++ break;
++ }
++ statePrev= stateIter;
++ stateIter= stateIter->next;
++ }
+
+ CLIENT_UNLOCK();
+
+--
+2.16.1
+
diff --git a/meta-raspberrypi/recipes-graphics/userland/userland_git.bb b/meta-raspberrypi/recipes-graphics/userland/userland_git.bb
new file mode 100644
index 0000000..7f2dca6
--- /dev/null
+++ b/meta-raspberrypi/recipes-graphics/userland/userland_git.bb
@@ -0,0 +1,85 @@
+DESCRIPTION = "This repository contains the source code for the ARM side \
+libraries used on Raspberry Pi. These typically are installed in /opt/vc/lib \
+and includes source for the ARM side code to interface to: EGL, mmal, GLESv2,\
+vcos, openmaxil, vchiq_arm, bcm_host, WFC, OpenVG."
+LICENSE = "BSD-3-Clause"
+LIC_FILES_CHKSUM = "file://LICENCE;md5=0448d6488ef8cc380632b1569ee6d196"
+
+PROVIDES = "virtual/libgles2 \
+ virtual/egl"
+
+RPROVIDES_${PN} += "libgles2 egl libegl"
+
+COMPATIBLE_MACHINE = "^rpi$"
+
+SRCBRANCH = "master"
+SRCFORK = "raspberrypi"
+SRCREV = "11389772c79685442e0ab8aa9be8ad0e32703f68"
+
+# Use the date of the above commit as the package version. Update this when
+# SRCREV is changed.
+PV = "20180219"
+
+SRC_URI = "\
+ git://github.com/${SRCFORK}/userland.git;protocol=git;branch=${SRCBRANCH} \
+ file://0001-Allow-applications-to-set-next-resource-handle.patch \
+ file://0002-wayland-Add-support-for-the-Wayland-winsys.patch \
+ file://0003-wayland-Add-Wayland-example.patch \
+ file://0004-wayland-egl-Add-bcm_host-to-dependencies.patch \
+ file://0005-interface-remove-faulty-assert-to-make-weston-happy-.patch \
+ file://0006-zero-out-wl-buffers-in-egl_surface_free.patch \
+ file://0007-initialize-front-back-wayland-buffers.patch \
+ file://0008-Remove-RPC_FLUSH.patch \
+ file://0009-fix-cmake-dependency-race.patch \
+ file://0010-Fix-for-framerate-with-nested-composition.patch \
+ file://0011-build-shared-library-for-vchostif.patch \
+ file://0012-implement-buffer-wrapping-interface-for-dispmanx.patch \
+ file://0013-Implement-triple-buffering-for-wayland.patch \
+ file://0014-GLES2-gl2ext.h-Define-GL_R8_EXT-and-GL_RG8_EXT.patch \
+ file://0015-EGL-glplatform.h-define-EGL_CAST.patch \
+ file://0016-Allow-multiple-wayland-compositor-state-data-per-pro.patch \
+"
+S = "${WORKDIR}/git"
+
+inherit cmake pkgconfig
+
+ASNEEDED = ""
+
+EXTRA_OECMAKE = "-DCMAKE_BUILD_TYPE=Release -DCMAKE_EXE_LINKER_FLAGS='-Wl,--no-as-needed' \
+ -DVMCS_INSTALL_PREFIX=${exec_prefix} \
+"
+
+EXTRA_OECMAKE_append_aarch64 = " -DARM64=ON "
+
+
+PACKAGECONFIG ?= "${@bb.utils.contains('DISTRO_FEATURES', 'wayland', 'wayland', '', d)}"
+
+PACKAGECONFIG[wayland] = "-DBUILD_WAYLAND=TRUE -DWAYLAND_SCANNER_EXECUTABLE:FILEPATH=${STAGING_BINDIR_NATIVE}/wayland-scanner,,wayland-native wayland"
+
+CFLAGS_append = " -fPIC"
+
+do_install_append () {
+ for f in `find ${D}${includedir}/interface/vcos/ -name "*.h"`; do
+ sed -i 's/include "vcos_platform.h"/include "pthreads\/vcos_platform.h"/g' ${f}
+ sed -i 's/include "vcos_futex_mutex.h"/include "pthreads\/vcos_futex_mutex.h"/g' ${f}
+ sed -i 's/include "vcos_platform_types.h"/include "pthreads\/vcos_platform_types.h"/g' ${f}
+ done
+}
+
+# Shared libs from userland package build aren't versioned, so we need
+# to force the .so files into the runtime package (and keep them
+# out of -dev package).
+FILES_SOLIBSDEV = ""
+INSANE_SKIP_${PN} += "dev-so"
+
+FILES_${PN} += " \
+ ${libdir}/*.so \
+ ${libdir}/plugins"
+FILES_${PN}-dev += "${includedir} \
+ ${prefix}/src"
+FILES_${PN}-doc += "${datadir}/install"
+FILES_${PN}-dbg += "${libdir}/plugins/.debug"
+
+PACKAGE_ARCH = "${MACHINE_ARCH}"
+
+RDEPENDS_${PN} += "bash"
diff --git a/meta-raspberrypi/recipes-graphics/vc-graphics/files/egl.pc b/meta-raspberrypi/recipes-graphics/vc-graphics/files/egl.pc
new file mode 100644
index 0000000..c314202
--- /dev/null
+++ b/meta-raspberrypi/recipes-graphics/vc-graphics/files/egl.pc
@@ -0,0 +1,10 @@
+prefix=/usr
+exec_prefix=${prefix}
+libdir=${exec_prefix}/lib
+includedir=${prefix}/include
+
+Name: egl
+Description: egl for RaspberryPI
+Version: 0.0
+Libs: -L${libdir} -lEGL -lGLESv2
+Cflags: -I${includedir}/vc -I${includedir}/interface -I${includedir}/interface/vcos -I${includedir}/interface/vcos/pthreads
diff --git a/meta-raspberrypi/recipes-graphics/vc-graphics/files/vchiq.sh b/meta-raspberrypi/recipes-graphics/vc-graphics/files/vchiq.sh
new file mode 100644
index 0000000..c73e3a9
--- /dev/null
+++ b/meta-raspberrypi/recipes-graphics/vc-graphics/files/vchiq.sh
@@ -0,0 +1,24 @@
+#!/bin/sh
+### BEGIN INIT INFO
+# Provides: vchiq.sh
+# Required-Start: $remote_fs rmnologin
+# Required-Stop:
+# Default-Start: S
+# Default-Stop:
+# Short-Description: Create /dev/vchiq.
+# Description: Get the major number from /proc/devices and use it
+# ti create /dev/vchiq
+### END INIT INFO
+
+rm -f /dev/vchiq
+
+#Get the major number
+major=$(awk "\$2==\"vchiq\" {print \$1}" /proc/devices)
+
+if [ -z "$major" ]; then
+ echo "Error: Cannot find vchiq in /proc/devices"
+ exit 2
+else
+ mknod /dev/vchiq c "$major" 0
+ chmod a+w /dev/vchiq
+fi
diff --git a/meta-raspberrypi/recipes-graphics/vc-graphics/vc-graphics-hardfp.bb b/meta-raspberrypi/recipes-graphics/vc-graphics/vc-graphics-hardfp.bb
new file mode 100644
index 0000000..0db71fd
--- /dev/null
+++ b/meta-raspberrypi/recipes-graphics/vc-graphics/vc-graphics-hardfp.bb
@@ -0,0 +1,6 @@
+CONFLICTS = "vc-graphics"
+
+VCDIR = "hardfp/opt/vc"
+require vc-graphics.inc
+
+PR = "${INCPR}.0"
diff --git a/meta-raspberrypi/recipes-graphics/vc-graphics/vc-graphics.bb b/meta-raspberrypi/recipes-graphics/vc-graphics/vc-graphics.bb
new file mode 100644
index 0000000..a1bce56
--- /dev/null
+++ b/meta-raspberrypi/recipes-graphics/vc-graphics/vc-graphics.bb
@@ -0,0 +1,6 @@
+CONFLICTS = "vc-graphics-hardfp"
+
+VCDIR = "opt/vc"
+require vc-graphics.inc
+
+PR = "${INCPR}.0"
diff --git a/meta-raspberrypi/recipes-graphics/vc-graphics/vc-graphics.inc b/meta-raspberrypi/recipes-graphics/vc-graphics/vc-graphics.inc
new file mode 100644
index 0000000..cd0d57b
--- /dev/null
+++ b/meta-raspberrypi/recipes-graphics/vc-graphics/vc-graphics.inc
@@ -0,0 +1,58 @@
+DESCRIPTION = "Graphics libraries for BCM2835."
+LICENSE = "Proprietary"
+
+LIC_FILES_CHKSUM = "file://LICENCE;md5=86e53f5f5909ee66900418028de11780"
+
+PROVIDES = "virtual/libgles2 virtual/egl"
+COMPATIBLE_MACHINE = "^rpi$"
+
+INHIBIT_DEFAULT_DEPS = "1"
+
+include recipes-bsp/common/firmware.inc
+
+SRC_URI += " \
+ file://egl.pc \
+ file://vchiq.sh \
+"
+
+S = "${RPIFW_S}/${VCDIR}"
+
+INCPR = "r1"
+
+inherit pkgconfig update-rc.d
+
+do_install () {
+ install -d ${D}${bindir}
+ cp -R bin/* ${D}${bindir}
+
+ install -d ${D}${sbindir}
+ cp -R sbin/* ${D}${sbindir}
+
+ install -d ${D}${libdir}
+ # note: -H option to deref symlinked .so
+ cp -R -H lib/* ${D}${libdir}
+
+ install -d ${D}${includedir}
+ cp -R include/* ${D}${includedir}
+
+ install -d ${D}${libdir}/pkgconfig
+ install -m 0644 ${WORKDIR}/egl.pc ${D}${libdir}/pkgconfig/
+
+ install -d ${D}/${sysconfdir}/init.d
+ install -m 0755 ${WORKDIR}/vchiq.sh ${D}${sysconfdir}/init.d/
+}
+
+# These are proprietary binaries generated elsewhere so don't check ldflags
+INSANE_SKIP_${PN} = "ldflags"
+
+INITSCRIPT_NAME = "vchiq.sh"
+INITSCRIPT_PARAMS = "start 03 S ."
+
+FILES_${PN} = "${bindir}/* \
+ ${sbindir}/* \
+ ${libdir}/lib*.so \
+ ${sysconfdir}/init.d \
+ ${libdir}/plugins"
+FILES_${PN}-dev = "${libdir}/pkgconfig \
+ ${includedir}"
+FILES_${PN}-dbg += "${libdir}/plugins/.debug"
diff --git a/meta-raspberrypi/recipes-graphics/wayland/weston_%.bbappend b/meta-raspberrypi/recipes-graphics/wayland/weston_%.bbappend
new file mode 100644
index 0000000..55cf700
--- /dev/null
+++ b/meta-raspberrypi/recipes-graphics/wayland/weston_%.bbappend
@@ -0,0 +1,10 @@
+PACKAGECONFIG_remove_rpi = "${@bb.utils.contains('MACHINE_FEATURES', 'vc4graphics', 'fbdev', '', d)}"
+
+EXTRA_OECONF_append_rpi = " \
+ --disable-xwayland-test \
+ --disable-simple-egl-clients \
+ ${@bb.utils.contains('MACHINE_FEATURES', 'vc4graphics', '', ' \
+ --disable-resize-optimization \
+ --disable-setuid-install \
+ ', d)} \
+"
diff --git a/meta-raspberrypi/recipes-graphics/xorg-xserver/xserver-xf86-config/rpi/xorg.conf b/meta-raspberrypi/recipes-graphics/xorg-xserver/xserver-xf86-config/rpi/xorg.conf
new file mode 100644
index 0000000..6fd5298
--- /dev/null
+++ b/meta-raspberrypi/recipes-graphics/xorg-xserver/xserver-xf86-config/rpi/xorg.conf
@@ -0,0 +1,6 @@
+# Initial xorg.conf for the RaspberryPi
+# Most things are setup automatically by magic pixies in the system.
+#
+# It is suggested this file is not used any more and configuration
+# snippets are placed in xorg.conf.d instead.
+#
diff --git a/meta-raspberrypi/recipes-graphics/xorg-xserver/xserver-xf86-config/rpi/xorg.conf.d/10-noglamor.conf b/meta-raspberrypi/recipes-graphics/xorg-xserver/xserver-xf86-config/rpi/xorg.conf.d/10-noglamor.conf
new file mode 100644
index 0000000..1a562ea
--- /dev/null
+++ b/meta-raspberrypi/recipes-graphics/xorg-xserver/xserver-xf86-config/rpi/xorg.conf.d/10-noglamor.conf
@@ -0,0 +1,6 @@
+#
+Section "Device"
+ Identifier "modeset"
+ Driver "modesetting"
+ Option "AccelMethod" "None"
+EndSection
diff --git a/meta-raspberrypi/recipes-graphics/xorg-xserver/xserver-xf86-config/rpi/xorg.conf.d/98-pitft.conf b/meta-raspberrypi/recipes-graphics/xorg-xserver/xserver-xf86-config/rpi/xorg.conf.d/98-pitft.conf
new file mode 100644
index 0000000..0d2b36b
--- /dev/null
+++ b/meta-raspberrypi/recipes-graphics/xorg-xserver/xserver-xf86-config/rpi/xorg.conf.d/98-pitft.conf
@@ -0,0 +1,5 @@
+Section "Device"
+ Identifier "Adafruit PiTFT"
+ Driver "fbdev"
+ Option "fbdev" "/dev/fb1"
+EndSection
diff --git a/meta-raspberrypi/recipes-graphics/xorg-xserver/xserver-xf86-config/rpi/xorg.conf.d/99-calibration.conf b/meta-raspberrypi/recipes-graphics/xorg-xserver/xserver-xf86-config/rpi/xorg.conf.d/99-calibration.conf
new file mode 100644
index 0000000..f8b578c
--- /dev/null
+++ b/meta-raspberrypi/recipes-graphics/xorg-xserver/xserver-xf86-config/rpi/xorg.conf.d/99-calibration.conf
@@ -0,0 +1,6 @@
+Section "InputClass"
+ Identifier "calibration"
+ MatchProduct "stmpe-ts"
+ Option "Calibration" "3800 200 200 3800"
+ Option "SwapAxes" "1"
+EndSection
diff --git a/meta-raspberrypi/recipes-graphics/xorg-xserver/xserver-xf86-config_0.1.bbappend b/meta-raspberrypi/recipes-graphics/xorg-xserver/xserver-xf86-config_0.1.bbappend
new file mode 100644
index 0000000..919e95e
--- /dev/null
+++ b/meta-raspberrypi/recipes-graphics/xorg-xserver/xserver-xf86-config_0.1.bbappend
@@ -0,0 +1,21 @@
+FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:"
+
+SRC_URI_append_rpi = " \
+ file://xorg.conf.d/98-pitft.conf \
+ file://xorg.conf.d/99-calibration.conf \
+ file://xorg.conf.d/10-noglamor.conf \
+"
+do_install_append_rpi () {
+ PITFT="${@bb.utils.contains("MACHINE_FEATURES", "pitft", "1", "0", d)}"
+ VC4="${@bb.utils.contains("MACHINE_FEATURES", "vc4graphics", "1", "0", d)}"
+ if [ "${PITFT}" = "1" ]; then
+ install -d ${D}/${sysconfdir}/X11/xorg.conf.d/
+ install -m 0644 ${WORKDIR}/xorg.conf.d/98-pitft.conf ${D}/${sysconfdir}/X11/xorg.conf.d/
+ install -m 0644 ${WORKDIR}/xorg.conf.d/99-calibration.conf ${D}/${sysconfdir}/X11/xorg.conf.d/
+ fi
+ if [ "${VC4}" = "1" ]; then
+ install -Dm 0644 ${WORKDIR}/xorg.conf.d/10-noglamor.conf ${D}/${sysconfdir}/X11/xorg.conf.d/10-noglamor.conf
+ fi
+}
+
+FILES_${PN}_rpi += "${sysconfdir}/X11/xorg.conf ${sysconfdir}/X11/xorg.conf.d/*"
diff --git a/meta-raspberrypi/recipes-graphics/xorg-xserver/xserver-xorg_%.bbappend b/meta-raspberrypi/recipes-graphics/xorg-xserver/xserver-xorg_%.bbappend
new file mode 100644
index 0000000..a5a6af3
--- /dev/null
+++ b/meta-raspberrypi/recipes-graphics/xorg-xserver/xserver-xorg_%.bbappend
@@ -0,0 +1,9 @@
+OPENGL_PKGCFG = "${@bb.utils.contains('MACHINE_FEATURES', 'vc4graphics', 'dri3 xshmfence glamor', '', d)}"
+
+# slightly modified to oe-core's default: add ${OPENGL_PKGCFG}
+PACKAGECONFIG_rpi ?= " \
+ dri2 udev ${XORG_CRYPTO} \
+ ${@bb.utils.contains('DISTRO_FEATURES', 'opengl', 'dri glx ${OPENGL_PKGCFG}', '', d)} \
+ ${@bb.utils.contains("DISTRO_FEATURES", "wayland", "xwayland", "", d)} \
+ ${@bb.utils.contains("DISTRO_FEATURES", "systemd", "systemd", "", d)} \
+"
OpenPOWER on IntegriCloud