Skip to contentSkip to conversation

userland: Add wayland support

RFC PATCH Superseded Khem Raj 1 participant 1 message Aug 10, 2015

v1 of 3 Superseded Latest is v3 →

lore
Share & tools
lore

Khem Raj

author
#0 lore raw

RFC PATCH 1/1 userland: Add wayland support

backport and fix needed patches for supporting wayland-egl

---
 ...-applications-to-set-next-resource-handle.patch |  210 +++
 ...ayland-Add-support-for-the-Wayland-winsys.patch | 1847 ++++++++++++++++++++
 .../0006-wayland-Add-Wayland-example.patch         |  864 +++++++++
 ...-wayland-egl-Add-bcm_host-to-dependencies.patch |   30 +
 recipes-graphics/userland/userland_git.bb          |    8 +-
 5 files changed, 2958 insertions(+), 1 deletion(-)
 create mode 100644 recipes-graphics/userland/userland/0004-Allow-applications-to-set-next-resource-handle.patch
 create mode 100644 recipes-graphics/userland/userland/0005-wayland-Add-support-for-the-Wayland-winsys.patch
 create mode 100644 recipes-graphics/userland/userland/0006-wayland-Add-Wayland-example.patch
 create mode 100644 recipes-graphics/userland/userland/0007-wayland-egl-Add-bcm_host-to-dependencies.patch
recipes-graphics/userland/userland/0004-Allow-applications-to-set-next-resource-handle.patch new file +210 -0
new file mode 100644
index 0000000..d5b43ca
@@ -0,0 +1,210 @@
+From 825c3236e5908ff003644abd870bfe98e82722b2 Mon Sep 17 00:00:00 2001
+From: Dom Cobley <[email protected]>
+Date: Tue, 9 Jul 2013 09:26:26 -0400
+Subject: [PATCH 1/3] 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.
+---
+Upstream-Status: Submitted
+
+ 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 418aa67..a7557a8 100644
+--- a/interface/khronos/common/khrn_client_rpc.h
++++ b/interface/khronos/common/khrn_client_rpc.h
+@@ -683,6 +683,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)
+@@ -700,6 +701,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 fd07eb6..e902d19 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?)
+@@ -643,7 +654,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)) {
+@@ -888,7 +900,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)) {
+@@ -1030,7 +1042,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)) {
+@@ -2302,6 +2314,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 cda5943..0be56c5 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.1.4
+
recipes-graphics/userland/userland/0005-wayland-Add-support-for-the-Wayland-winsys.patch new file +1847 -0

1,847 lines not on this page · raw message

recipes-graphics/userland/userland/0006-wayland-Add-Wayland-example.patch new file +57 -0

57 lines not on this page · raw message

$(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{s��x��w��fw�[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>MVv��w��l��r��cvz^qnXkbRdV\nay��cqxw��cp~z��v��{��}��fw�hw�dq�(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]>RYJYGW^=MTAQX?OVHX_AQXGW^/:BDOW6>H@IR-6<16=/6=45>/6??HQIU[GU[DRXBRTEQU=IM=JP=IN6BJ<KTp}eu�N]nQdw:JPWfiVf^M^Q`ndhts���ir�Wfobt|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����_otv��arzp��bs|ex~lz�brt2IX0ET6IX-<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]fZir���aqw������xz�{~����{��^mv���FVb���n~�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:FLAOVSagVbir��K^epy�ccstp~lhrvyx���cn~w��z��s��q�����goz~��?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_ASZEY9EK<HN2<C?IP.6=6;B06=4:A7;D;BILX^KX^EU[?SVARU6HJ?HS:EN7AIGPTCLOGSTTdQac7JRJ[bS_e[gjo{~������|��Xqvt��r}���l��m��Zovo|�/>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}t��x��_u{n~����r}�t��u��ct}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\ijJVXFRUix����i|�������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\�����̳����y��fm|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^PgFW^;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_LVgw��x��r��������2J]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:)[email protected]<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[\?KM8GJ4GNp��n��h�����������������������0HZ4JZ<Q2CP4DP4DQ1BO5DU5HU5HU3FU/?P'7H5EU:KX5DQ4DQ3CP6FS/?L4DQ9IV;KX/?L3@L/?MYiv6FV8HT5CN5AJ,6@+<J6FR6GP-<E%1;'4='/=19HPh(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��_v�hz�j�^z�]{�]u�\p�2M_+FV8M]/AN/AL4DO4ER:JW3ES3FS4GW0?Q*:L8HX:KX3BO/@M2BO7GT.?K0@L6GS;KX-=J8EP9IV���DSd7ES6CO5AJ/9B.?M6FR8IR/>G#/8&3<3:Gms�SbkAN[*: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[OcoPitBc�Ke�Tl�Pj�Gj~Lp�Li�Tj�4EP6EQ4DP/<J/<0AM8KW.DP2JV)?K9LX1BN(9F6GT7JW.AN/;J6CQ4DQ*9J1@P3AS0@Q1AR0CTMbq���B^g2LU/AL:AO03C.=H9KV7JR0?H)/='-="2C���MejH]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_JZPfN]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\[email protected];IBRc���OfkEYaEWb1AN5AO;GV<MY=NW;NV=PX?RZ>QY:MU>QY>QY>PX3SW9NVAMYAP^���TnwEYd!3;5AH;HP4AI7GP7CM4AK8BL8AK-AH1<D58C38B(6B���j~�?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^HWHXaHWHXaIYb4LX,BN8KZ/?O-=M4DT5GX5IZ~��Lbn?Q^6GT*;H6GT7JW1DQ1=K4AO1BO-=J,:K4CS/@O/?O*>P���{��8S]?U7IT4?K27G5CO6JQ7JR4BK09F5=KScsq��LglH_fCT_+;I1=L8FQ;LU:KT<PW9LT9LT>QY;NV>QY=PX=PX7RX<QY>MZ*:G���l��Ij>MZ1?H:IR8GP5@J8DN7CM;GRAIT0FJ:HN>GP<EO *���u��ASeAUY?PXBU[@PZDV]=PU@SVCVX=QVAUZ?OU=KQ>MS@LR=JPBJR=LN8HJ8CG4AD0;>+7:6?B=FJ6<ABGL/9<ENR=HL3=A?KO;FJ>JNAMQGVYFUWIW]JZHX^HX^P[cR]eS^fVahUhWbjYdkYdl:T5K[4JY1CT5GX<M8H[;Pa���H^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[>PX2AMFXh���y��CXgL[h6JP5FO9HQ;GQ8EO=GO>KS?KT6ML:LNBLTAOWJcn���i��DWnDU[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_hqir^gphqajsbjthr^gp0KWKdp1GV-AO1CT0AT1DZGZos��Rgr7KV6HS+=H1CN5IT/CN.:I5BP4DQ2BO1AO8HU3DQ3DQ1I��dž��Nfq=S^:LW.;H9DP,=F6HQ2IN7HQ?JV,8I���Ut�F]hG]hDXc9KW*;C3DM=NW6IQ8KS<OW;NV<OW;NV=PX<OW>QY8QW>PX>N\Ym|���t��H_oETdH\g1CO:HQ:EP>IQ>IQ<IR>KQ9PP;MOBMU=NYi�����q��@UnCV]BU]BS\FX^BT[CV]>PWI]cEV]HYIV^IV^ANVCPXGT]KXNZcVckUbjTbjWdlCPXLW_S_g\]fX^dPX_XbiS_eP^dP]cL\cQ]aUadTchYgmWejXhoXio\mt_jqksbmtcnualtbmtks^iq���3GS4ER1AQ4DU7H[3I[|�����Lbm>R]<NY4FQ3EP5IT4HS)5C1>L1AN2BO6FR>NZ6HS3EPOh����q��Net?S]BT_7GS8FR5HN4KQ2HN4GO7DQO^n���o��IaqAXgEXcDW_(9B5EN:MU;NV<OW=PX<OWAT\;NV<OW;NV?RZ7NS<OV>N[������m��Ogyt��_z�:NY:JW@KUALT?IR=LQ?OU?SUAQW<LR7JU������e��BVn>OY@R^EV_BT\FW]CPY-4IV=JRCPXERZFS[KXMZbR_gUbjScjRbiPagThUbjZgnZgoWdl\enYaj]enWaiZgoZfnWgnVfm\go\goXemYgn\gq\ks\ks]mubmwlv]irZeo]isalv][email protected]^��݆��Ndo=P[8JU5GR6HS7KV2FQ0<M5BP0AN3CP3CO=LY8KS8KS��싢�w��BYhK]jI[eCR_.>J:LR2IN.GM5GO)9Feu����e��]u�D[jGZeGZb/BH:MT6IQ9LT;NV=PX<OW=PX;NV<OW;NV>QY;PX=NZ(;G���~��m��Hav���p��>T_5ER>GQDMVBNSCQWFV\ARWERZCMW6JU��Α��r��BWm: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(9ANah���t��Ws�OhzNdsLlr�����������z��{�������·�Պ��k��[q�AXhF\fOgI[a@RX%7>&;B(9A)<C-@G5HO7JP?QX@RYBRZ<QX1@Ks����ǐ��k��Tl���ꑮ�5NZ<LX@ITAISALR>KR9LM@MVAITHQ^1CO��ݑ��}�BWj@QaNbmYjsYhm]gmbjr���41@gu|gt|cpxanvcpxamvZkqSdkZhpWfn[irZhq]ktXiqWhq[ltZlxYlvaq}p|^o{ao{_ny^lxem{fm{amxbl{_hv\huZeuR]nL_lL_lL_lL_lJ^kI\iG[hFYgOjp2IN;LU8FR6FS3HW/JZ���v��>V\8MU3HP7IT4ER1AN1AN18;MX]ozey�k��j}�h~�PfsE]iG\gJ[eO_l^n~�������������������і�ɓ�Ã��r��w��OfvI`pG^n{���������������������������������������Ұ�ߚ�Ѐ����Ur����v��Gam>LT?HPESXAQWHV[HSY[ggO^cZp{d~���ޘ��d�@Yi7R^FakXkrpyv��,1>kp~3YhpWgo\gr_ls]jqanu_ltbntWkyWkx[o{Xmx[ny^p{]oz\nz[nx^nzp|aq}dqdqer�er�crz^nz[jvVgsPcrLrKcsNfvOeqNepRerWguVfrUeqZgtWfoPjp;PV5HO;KW@P]2ET������Yqw:PU6KS4IQ:LW5FSN^kbr~t��\nyRdoLkMmK^k>T>T`4LX=S_\lyZkx>Raax����t��������������������w��w��h~�\s�Yq�~��������������\t���������������������š�Ʀ�Җ�Ə�†��t��y����ׁ��<VbCR^ET\K[d>SZFXcQ]jK\aNjXq���뜺ό��i��CZi=Vb9P[YmtkuYclXmt{�06Ebs�_o|_o{_o{nz^lxao{_lx[kxUfsTenTenSdmTfoTfoZirZjv]mxYiuScpScpYiuZhxVduTfpXhtUhuSfuSftRgxThyThzRhtPcpPdqSepXhuZjv\ktXgp\v|=T[3EP5DQ8HUL`l���p��G]b7LT5JR6GS9KV8IV8HU:IY7JT9KV>P[<P[ATb5HU9P[8OZ7M]9OZ���RboBVe9QaRl}���s��y����������������y��n��n��Wp�t��y����������9JWl����������ɒ�ă����Ț�ɕ�Ǐ�ň�����s�������˅��<Vd>MZ\myy�����������Ū�֥�ְ�虵΃��^t�DYh=T9MXWhqbnxCLWHS\DMZ%,;as�^o|]n{Zkx_p}YjwQboYjx]jq]jr^ksbowiv~dqybowhu|ev�jz�jz�fw�o�[m|TixPetPfuOfuQetNbsOctRduPbsM_qOcnPdoUfr_q}XiqRclRakQi^w�CYd/DN6HR8IV6GTl�H^j>QY9LT5IP6IT5FS8IU8HY:JZ7JT;MW8JU9LY6IV7JV7L[7L[4N]:Q���@SBUb=Ra7Qas��x��|��o�����x�����}��k��y��d}�h��[v�|��t��������DPAUf���������|����������ʔ�ˏ�Ɔ��{��z��������u��B\l?QPdu�����Ö�˗�lj����֫���ݚ��t��]q�GVg<P]GYdTcl\iqksLU8DNco|_itdoygr|hs}lt�eq~hu�iv�lu|nx~jt{ku}r}�v��r|�oyap�[jzSbrMoK_pKbrIbrHaqGbrF_oGaqKcsMasPctTduTdvPbmYkvfz�\mvPajL_fIZ`EU\VnzDZf=P]<MZ:LW4FQ>P[9KV7HQ6GP7GS2BN7HU7GW9IX5EU8JT:KX8IV3FS6IV;M]5JY4IX3K]E^n���Rhs7MY6K[<Sc<Scay�x��{��������{��p��f��~��a}�f��j��y��t�����m��Uaq2FXs��z�����w�������τ����˂��{��y�����������|��AXh:K])=N���}����ʗ�ˇ����և��v��l��Ul~MoK\iCVcDUc?NWeszgrzZem1=Gkx���{�x~�u{x��z��w~�ox�t~�s~�s}�o{�lw�it}anz[hsTctNqM^oI\mI_pIrGbrFpD_oIasJrOcuQds]m~aq~dt�\mvZjtVgqNgL_fIY`FV]BRX]t�@Wf8NY7JW9KV5ER7FO7FO<KS7EQ5FR7GU5EQ,<L2BR5EW5FS5FS3DQ3GS3FV5GV2HV5JY+DX=Ug���Pfv@Va6LX:LY7JZ8PcMex������y��z��k��q��o��i��]y�h��z��p����ہ��O_lAVf3I\^w�����Ђ�������Ɗ�����w����n����ܠ��k��AVgGVe8K]t��v����‹��y��p��GauB[n>VfCYhBTbFWaBWg>Q^>OXiv~v��}��$/7S_h������z��{��v}�w��x��x�n}�mz�iy�]lxWgsNoObpM^oNasJ_rI_qG_pG_sHbuJcwFbvPfxNdwShy[o~q~eu�Yiu]luK\eJ]dHZaEX_FV\AQWAPWBRXI`pNeu9N^=P]<NY?NW=JR<FN2@M1?K2@L0AN#2B#3C-=N4DU7HU6GT4ER6IX7JY3FU/DU/CT3Kb��̇��D_l=Ua5LX2ER;LY7N^7M]Ibr{��w��n��q��n��x��q��h��f}�y��o����ㆣ�Zr|>T?QbQ^u������~����„����}��x��x��}����ݍ��c{�IXgETd8KZUp~���e}�L^tCXjEYl=OaG[h@R]DUa=RZAV]8O8N[=QY[gox��jt|":CMclsgsxis{lw�iw�o{[kwZjvUhwQcrQftLcrG^pG_sGsG^uFpFaqHauIbvIcvKcyMe|Nf}Xi}[n~aq�ZkxXhu[luNgK[bL\cFV]M\dGV\CSYDTZ=PS;NQLctAXh=Ra9KXCT^DQYEQXIRZDO[6CO-:F,9G$+;-<M1@R5ER6FS3DQ2FU4GV1DS1DU*=N.E\��߁��Zu�<T`FYd9JU@O\0JV;S_=VgB]nw��s��p��u��y��l��d~�h��~�������ׁ��UtyLbm@N^NTiz����Æ����|�����}��y������Ɩ��~��Shw@OaBM[?P]*FQ2O]9Qa<K\AP>M^BM\ANZ<MU?RY=RZ<QW6Ra9R^@RYCRXq{tyqv|gkoVdoTdpTdoK]kMqJrI]sD\qIoFoE]nF^rEtD`y=]tFeDcuHcwJexKg{Tl�Um�Un�Vo�lw�]i}_nWguM^hEW^GW]DUWDS[HX_>NTCTYCSYASU;OR@SVf��D_h6P\6P\5O[>YgB]kHcqTjtATaq�����o~�y�����t��r�������������x����������ڥ����Vm|BXdATa?Rb8KZ>TXBZcF\i?ZjF`tk��p��m��w��s��j��g��}����—�ȉ�����7MY=P_.BSx�������������‚��y��{�������ǃ��d��FX^>QY@R]=OZ7HU=NZ9IY;K[;J[<MZ9JW:KX=N[<NY;MX<MX4IY3K[5M/J[Gcx>ZoA]rB^q9Xr>Yt>XqBZsF^tBZqC[qFsM_tK_tG_rB_tFcwFbzMgSi�Nk�Yt�Lg}^y�Wq�Wo~WlxLanHfkQjoEX_IY`IU]GW^ASZBT[=VV?TV>NTDOWEPXDOUCQT>OR_x�Piu7Q]4N\5O]:TbE^nOhx�����������������������ƀ������������������ə�ß�Օ�Ņ��Vm|F\gI[h@Rb;N]DXXCV[K^fNaoVi|F`pv��}��|��z��o��q��v����杻Ε��XpxC[g@Ud9M^t�����x�������Å�����{��d��Up�F]q?YjBT[BU]>P\:LW;LZ8JV:JZ9IZ4EQ6GT8IV<LZ8JU;MX=OZ:LW;LV<MU9LZ3HWJaqD[nC]mD]qA\qC^sD_tH_uBYpIbuJbuA]pKbzLe}Kf~Ml�Hg~Kk�Vp�]t�[w�x�Icwp�����j�KamNbnGfI`eFX_GW^CPXAQW@SY=PW=STAUY>NUBMUFPXAMS?NQ=OPl��Sm{6P^2K[5O^:ScC[mLdul��������v�����~��~��m��q��l��}��{����������������Ζ��v��k��?Sb@Ud@Ud=PbKZ^N]dTemZlvK^kYo{Umyw��~��z��{������ӟ�љ�Ʉ��_{�?Ye>Tc.EUw�����������`y�k��;Sf@Wg>Vf0EU<S^5HV<NY;MX<NY=OZ8HV:KX3DQ5FS:KX8IV9JW8IV9KV6HS;LX:LY@KN@NT>NT9KUThwLcuGbuKfzMgzLezHeyEauLh{Kf~Hg}Gf|If�Kl�No�Su�Kk�Po�Sp�Ok�j�����y��}��p��at�I]hN_kCV^CT^BQZ@OX?NW?NW>OX:MU9MS@QZ>NV@LVAMW=KQ?MP=OPz��Xq�5N^6N1I[;SeAYmHti��z�����Xs�u��g��Wu�q�����{��|��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{Mj�Jh�Pm�Pr�Xz�Vz�Tx�Jo�Vz�l��z���‡�ǎ�Ɏ�Ɩ�̕�Ĉ��{��]q�UgyPdsL]jHYf=OZBU`AR[DU^>LV?MVAPY?PZ;KU<MV>MVAQY;IU>IVBNXAOUBSV@RSr��_w�5M_/GY1I[7OcC[oNfzr��v��w��b�Ie~=\u6Tp=^{Xw�c��l��k��}������������֚��|��p��C]k;Uc:Sc<Ud>WkE]qC^r������}������������������ۨ�ܔ�ȑ��}��Vs�Bo<Vf6O_4L\AUg<K\6FX9LV<NY9KV;KW=MY8IQ6GO6HP@P^3CP4DQ(5,89IU7GS4DP6FS9IT8HT9IU8HU:KT;LU:KT7IQ=OW6JT5LZ]x����{��{�Ƀ�ʁ��}��~��{�ʂ�Ѓ�Β�܎�Г�Ԛ��j��}�h��c~�JduRetI\lHYfDTbCT`CUa?RZ>OX>OV>PX4GNASZ7JQ:LSASZ>QXCQY;GQ7FOBQZ@NX@PV?PS=OP���d}�>Wg0HZ2J\7OaBZoNfzn��u��m��Xs�9Ti5Qj$A]"@]">RJh}s��q��u��w����������։�����VpIcs<Vf6O4Pa9Yo@wIg�m��r�����{��x��y����’�Ǜ�Ω�ߑ�Œ��u��[t�@Zj6P`4N^3IX9KZ4DT:IZ9IT;KW:JV8HT7FR7GS7GS7GS5ER5EQp��+!1=7GS1AM1@M2BN9IU9IU:JW9JR;LU<MV<LU2IU7NY5KV2IX9Ti���t��r��t��y��z��y�Ɂ�ҍ�ە�ݕ�߈��Zz�Tp�LdzQiyF[kAWc=TaCTaCT`BT_?Q]?RY<OW>PY>PX:RW5MR5MQ6OS4JO;OT9LR;LR<HMBQT>MT9KS=OV<OTASU>OS|��k��D]m3L\4M]7OaBZlOgyn��x��s��\u�Ict-H\,Gb4S4GX,CS��ċ��z�����}�������Ո�����c~�Jdt;Ue6Sb3O`7Ug@_rIf|Lh����������v����������Ǐ�ǝ�Ӊ�����q��Wn�>Vh<Wf2L\2M[6LX8HU8HU7HU7IU:JW9JV4ER5FS6GT6GS7FV8GWJZgRbo1AM:JW=NV3EM;KW9IU;KW6GP=NW;KU8JQ7IP6IQ7KR9LS;NV-BQHdxIe�Dh�Dd�Gk�Cj�Bi�Fo�Fh�Hd�Ka~EpLdtNetPanJZhHXeDW_BU]?RZ>RY<OW>PX:OW8MU=SY9NTEdcDdc8WV+JI1MM2KK=OP:ILCQMDRP9KL@SV=QV>RV>NT=LO{��s��=We7O_6O_7PB[kPhzq��z��i��Xn}=Wd0IZ,G_8T7EO/AN{��������z����������א�ĉ��u��[y�9Vd7Tc2Pa;V`A[iLeuTm�������z��u��p�����|����ȏ�Ň�����y��h|�<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[bs��e��7Sd0JZ3L\6Pa@YmMh|x��}��}��\w�7Wj3Sf.F\'5O;R[7M_r�������������������ˌ��~��k��^y�<Wl5Sh3Rg3Wd<^mFbsQj~k��u��|��{��{��~������ҍ��x��s��x��e��=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{iP�pP�qN�mL�sU{p.A>{��ENQ0BA9SO4OKu��b��?Yj1JZ4M];SeB[pKg{}��t��n��h��4Ue3Sf+CY%3N5LU,BTr����������������ß�щ��q��h��Jcw?[o>Yn3Pe5Wf@]nHcwTk�d|�i��u��v��w��s������ɇ�����v��r��k��Ics: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|oCxiCxjEzlL�rc�|h���ƾ�Ž�ƿ���������p��e��>Xi5N^8Qa;SeB[oLeys��l��v��Uq�<^m0Qd.DZ 0G/FP2H[���������}��|�������ڍ��{��r��_x�D]r:Sh7Sd7Vi@^qGbwOf}Wo�t��t��t��y��w����������������w��r��Rl|:Sc6M]7K\2CT3EV5DV4HR2FQ1FQ4FQ3EP5HS9IU8GT;MT4FM3FM<LS<LS9IP9IP:FN7GN8IO:JQ<IQ;IO>MR>MSCNT;OS;NS7IP9KRL]fJZfO_kp|]mzTdq[kwUdpOalHYeGZb>RXBS=N[AR_;LY7HU9JW:KX4FS1AM6EP6>L!+2;EBNRFXWf|xTwJunN|rM}tExnG|rHqK�v?�pG�wC�ui��q��uºr���Ļ~��f��B\m?Xh7P`?WiHauIbvt��r��o��[u�8Zj5Sf)?V!.EE\f?Ug��΅�����~��q�������Љ��v��w�����Zq�>Wh4M]:UkC^sHcxNh}Xs�w��}��v�����~����������������~��r��Un~<Vf5N^/FV2EW3EV4GV6IV3FT4FQ5GR6HS3CO2BN:KS;NT;MT=MT<LS=NTANV>KS<IQ:GO>KS>KSANV:GPALT<GO>HP2EK9KR:MSFWNhRbnP`lO_kP]kKWfJ[fGWcBT^?S^DYc<Q[<MZ;LY7HU6GT6HU:LY2CP8IW1BM2@L<FP"(1;CJHQV(21&&*CA
)&?]Z`�}V~wS~wQ~wU�|J��D�xEvM��r��o��}��5�zu��m��BZl?XhCYi@VhMeyc|�v��s��~��\v�<Zk2Pa&>R$1IAXb8Na��׉��t����������Ɲ�Ԉ��}�����Wn~L`o<R^=S_8PhBYpIdyPm�^z�w��w��z��y��t����������ā����~��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�~r��Z��:�u^��o��M~zg��y��o��Nfx?VfAXhF\nf~����t��~��q��f��=\k/M^(=R!.E1HRAWi��݉��}���������ɜ�ӄ��������^s�3FS7IT3FM9RhE^rIdyPm�Zy�k��{��{�������������LJ�����{��~��|��f��?Yj2K[6M]3HW1FU4GS4ER6GT7IT6FR8IR1DK6FM;KR;KR=MT7HN?LT>KS<IQ=JS@KS?JR9FN9FN<IQ5AKCR[=LTCRZdt�]myu��Wfs^nzK[gAP]HXdGWcBQ]JZgAQ^:KX:KW8HX9IY:IY7FV8GW6EU2AQ5DT0?O0@P,7H%.='0;%,8>CEJM&)- #(-/527:48;7>A!!"1-&FAc��r��s�����s��u��^v�Riyj��p��y�����{��������x��:Zi0N_(=R!-C4>1GY���y��w��{�������ě�Ԉ�����n��ZlyJ\g:KT/AG5K_C[mFavKjSr�j��r��u��v����������ˍ�ą�������w��l��<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?q��o��j��u��w��ez�v��|��k��|�����m��:Zi6Rc&<N ,C3<EZm��Í��w����������ҟ�َ�Ñ��c{�Wiv?PX+=D*9?8M6PNk|Gh{Uu�q��y��{��s��z�������ρ��������������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,;=..7WLY���l��q��d}�r��q��u��w��|��z��g��j��G^m;P^1CP-@M0HX��Ν�ȁ�������������˛�������s��PetAR^:KS:JQ3DR4GVRg|Nfg�z��n��v��{������æ�ݑ��|�����v��q��e��>\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�~�r��j��r��n��w��m��~��v��|�����i��^x�Ohx@WgCWfMap�����Ɖ�������ʒ�Ǖ�ɛ�Е�ɂ��~��az�EZi6FSARZ8GP/BM/CRJ_u\t�y��s��u��w��~�������Ǧ�݈��~��~��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�����~�����{��z�����u��[v�r��Nhy@Xj��������������Ċ����Ȓ�ȗ�͘�Ό��������z��6JY9KU4EM5DL6GS,<L8Oa��������������{����Ǣ�٩�����x�����x�����a��: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Ž�����}����ɐ�ǔ�Ŗ�ǐ��v��g�����r�������͜�Ջ����ɕ�ʕ�˕�ɍ�Š� �Ԑ��t��VlwVhs7GS<JV2CL5FS3E��ˉ����������������Ӧ�ݟ�׏��{��|��w��~��a��Yw�6RcA[k9P_:Q`5KW5HO7HQ8GP7CM@LV:EO:FP:EP2<C:FP6BNlv����������WgqJ\cBT[HYb6GP?QY;KW;KW<KX9MT3EP>P[2DO6GT2CP6GT3EQ3CS3CS4DT7GW4DT5EU3CS->N2AQ.=M0?O.=M.;K+8H2?O#1A"0*& &6<=%%% ebdLNLAIB&!)"&��ȋ�р��v�������Ņ��{��m��s��Ws�s����̍��Ƃ���������ž�ٓ�˞�֍�ā���� �Ӎ��l��OdoDVa;KW8ER7FO/@N*>Qu�������������ȇ����ҟ�֡�؏�ņ����†�����m��Rq�@[l=Vh9Rb:Qa6M]:MS9JS5DM:FP:DM4@L3AM:JV?U\-AL��ו�����m��RhsLdkCT]HYb?PY>PX:JW<LX=MY9IU3EP9KV2DN.>L3DQ4ER4ER3CS3CS2BR3CS1AQ4DT6FV4DT/?O1@P2AQ.=M1>N0=M-;K2<M#,>(6"/#-$$)*  %!&XWY@ECCJE87.\RKgXRz��j��j��x�����t��l��t��{��f��o����Ă�����v��y����a�����}����Ǝ�ˍ�Ō�ő�ɕ�Ɍ��[t�Kak;MX9HT8ES4DJ2BO.CTBZq�����Ò�ʌ�Ō�Ĥ�۠�׏�Ǝ�Č��t��n��|��v��`~�B]n=Wh:Te9Qa1K[4HO6IQ6DM2=J,8D0>JDVa9KX���������Lguw��Nfr=Va<W^9IR@QZ7HP?O[7GS8HT8HT3CP3EP1CN5FS1BO.?L3DP3CS1AQ5EU3CS3CS1AQ3CS4DT3CS/?O2AQ1AQ0=M/<L0=M/9J+5F$.@!,:&4$. %!!&'  
  475GHF>3/ub]B)%b��h��q��v��q��v�����v��m��p�����������}��~��{����Ń��v����Ƅ��}����̀����ǎ��|��j��E\d@RZ:JW6BS9FL/?L/AS0H^��Ɇ����˒�ʏ�Ǐ�ƣ����������z��s��{��w��g��<Xh=Yj;Uf8Rc2L^7NU4IQ+<D8COAO[;JWx��������Rm|l��F]mYn}7JW9KV=QX>NX:KT9JS7GS2BN:JU6FS9HV2EO.?L5FS1BO0AM1AQ1AQ1AQ2BR2BR2BR2BR1AQ3CS4DT3CS2AQ0=M0=M/<L0:K1;L)3D(2C#.<)6$."'$), ! !#()
++!" &'%&$$ /(%$OD=k��y�ċ�Ӏ�‰�’�Ƒ����Ë�‚����ȏ�ʍ�͍��{����Dž��{��r��o����ń��g��|����������w��E\dCV]7FT>K[9FM3CP*<M$<R��̀����Ƌ�ň����������À��{��|��s��r��m��k��>Ym=Yj:Te8Rc6Pb1KQ/FO9IR>KX������}��^x�[v�f}�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
+Index: git/host_applications/linux/apps/hello_pi/hello_wayland/Makefile

+===================================================================
+--- /dev/null

++++ git/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
+Index: git/host_applications/linux/apps/hello_pi/hello_wayland/cube_texture_and_coords.h

+===================================================================
+--- /dev/null

++++ git/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,
++};
++
+Index: git/host_applications/linux/apps/hello_pi/hello_wayland/triangle.c
+===================================================================
+--- /dev/null

++++ git/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;
++}
++
+Index: git/host_applications/linux/apps/hello_pi/rebuild.sh

+===================================================================
+--- git.orig/host_applications/linux/apps/hello_pi/rebuild.sh

++++ git/host_applications/linux/apps/hello_pi/rebuild.sh +@@ -13,6 +13,7 @@ make -C hello_jpeg clean
+ make -C hello_videocube clean
+ make -C hello_teapot clean
+ make -C hello_fft clean
++make -C hello_wayland clean
+
+ make -C libs/ilclient
+ make -C libs/vgfont
+@@ -29,4 +30,4 @@ make -C hello_jpeg
+ make -C hello_videocube
+ make -C hello_teapot
+ make -C hello_fft
+-
++make -C hello_wayland

recipes-graphics/userland/userland/0007-wayland-egl-Add-bcm_host-to-dependencies.patch new file +30 -0
new file mode 100644
index 0000000..011f255
@@ -0,0 +1,30 @@
+From de087d5081c45384c40f62de70267581476edba3 Mon Sep 17 00:00:00 2001
+From: Khem Raj <[email protected]>
+Date: Mon, 10 Aug 2015 02:38:27 -0700
+Subject: [PATCH] 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 <[email protected]>
+---
+Upstream-Status: Submitted
+
+ 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.1.4
+
recipes-graphics/userland/userland_git.bb +7 -1
index 35e5672..e2170a2 100644
@@ -19,12 +19,18 @@ SRC_URI = "git://github.com/${SRCFORK}/userland.git;protocol=git;branch=${SRCBRA
            file://0001-Use-newer-POSIX-macro.patch \
            file://0002-set-VMCS_INSTALL_PREFIX-to-usr.patch \
            file://0003-cmake-generate-and-install-pkgconfig-files.patch \
+           file://0004-Allow-applications-to-set-next-resource-handle.patch \
+           file://0005-wayland-Add-support-for-the-Wayland-winsys.patch \
+           file://0006-wayland-Add-Wayland-example.patch \
+           file://0007-wayland-egl-Add-bcm_host-to-dependencies.patch \
           "
 S = "${WORKDIR}/git"
 
 inherit cmake pkgconfig
 
-EXTRA_OECMAKE = "-DCMAKE_BUILD_TYPE=Release -DCMAKE_EXE_LINKER_FLAGS='-Wl,--no-as-needed'"
+EXTRA_OECMAKE = "-DCMAKE_BUILD_TYPE=Release -DCMAKE_EXE_LINKER_FLAGS='-Wl,--no-as-needed' \
+                 ${@bb.utils.contains('DISTRO_FEATURES', 'wayland', '-DBUILD_WAYLAND=TRUE', '', d)} \
+                "
 CFLAGS_append = " -fPIC"
 
 # Shared libs from userland package  build aren't versioned, so we need
Signature · 1 line
2.1.4