diff options
author | Khem Raj <raj.khem@gmail.com> | 2015-08-10 02:52:39 -0700 |
---|---|---|
committer | Andrei Gherzan <andrei@gherzan.ro> | 2016-03-10 14:49:21 +0100 |
commit | bfbe0ce3b443ae8b6eff3e76a9ed38f0f13c23a3 (patch) | |
tree | 954eab04257d7637f9ac8afc8eea302b9fa64f65 | |
parent | 4db634bcda93fd0d891cb4c91f9c956537fb7c7a (diff) | |
download | meta-raspberrypi-bfbe0ce3b443ae8b6eff3e76a9ed38f0f13c23a3.tar.gz |
userland: Add wayland support
backport and fix needed patches for supporting wayland-egl
use PACKAGECONFIG for wayland so we can add proper DEPENDS on wayland
Fix QA warnings about dev-so
Signed-off-by: Khem Raj <raj.khem@gmail.com>
8 files changed, 3093 insertions, 1 deletions
diff --git a/recipes-graphics/userland/userland/0008-Allow-applications-to-set-next-resource-handle.patch b/recipes-graphics/userland/userland/0008-Allow-applications-to-set-next-resource-handle.patch new file mode 100644 index 0000000..bf6511d --- /dev/null +++ b/recipes-graphics/userland/userland/0008-Allow-applications-to-set-next-resource-handle.patch | |||
@@ -0,0 +1,208 @@ | |||
1 | From b5295cb247dfb062843f4a4c9996186e865d0cc2 Mon Sep 17 00:00:00 2001 | ||
2 | From: Dom Cobley <dc4@broadcom.com> | ||
3 | Date: Tue, 9 Jul 2013 09:26:26 -0400 | ||
4 | Subject: [PATCH 08/16] Allow applications to set next resource handle | ||
5 | |||
6 | This patch adds provisions in userland to | ||
7 | let apps callers set the next rendereing dispmanx resource. | ||
8 | It's useful for implementing, say, a buffer carousel. | ||
9 | --- | ||
10 | interface/khronos/common/khrn_client_rpc.h | 2 ++ | ||
11 | interface/khronos/common/khrn_int_ids.h | 2 ++ | ||
12 | interface/khronos/egl/egl_client.c | 30 +++++++++++++++++++++++++++--- | ||
13 | interface/khronos/egl/egl_client_surface.c | 24 +++++++++++++++++++++++- | ||
14 | interface/khronos/egl/egl_client_surface.h | 3 ++- | ||
15 | interface/khronos/egl/egl_int_impl.h | 5 +++-- | ||
16 | 6 files changed, 59 insertions(+), 7 deletions(-) | ||
17 | |||
18 | diff --git a/interface/khronos/common/khrn_client_rpc.h b/interface/khronos/common/khrn_client_rpc.h | ||
19 | index 418aa67..a7557a8 100644 | ||
20 | --- a/interface/khronos/common/khrn_client_rpc.h | ||
21 | +++ b/interface/khronos/common/khrn_client_rpc.h | ||
22 | @@ -683,6 +683,7 @@ static INLINE void rpc_call12_out_ctrl(CLIENT_THREAD_STATE_T *thread,uint32_t id | ||
23 | 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); } | ||
24 | 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); } | ||
25 | 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); } | ||
26 | +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); } | ||
27 | #endif | ||
28 | |||
29 | #define RPC_CALL1_OUT_CTRL(fn, thread, id, out) rpc_call1_out_ctrl(thread, id, out) | ||
30 | @@ -700,6 +701,7 @@ static INLINE void rpc_call15_out_ctrl(CLIENT_THREAD_STATE_T *thread,uint32_t id | ||
31 | #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) | ||
32 | #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) | ||
33 | #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) | ||
34 | +#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) | ||
35 | |||
36 | # if !defined(__SYMBIAN32__) //use functions defined in khrpc.cpp | ||
37 | 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; } | ||
38 | diff --git a/interface/khronos/common/khrn_int_ids.h b/interface/khronos/common/khrn_int_ids.h | ||
39 | index 8378f4a..ec961e0 100644 | ||
40 | --- a/interface/khronos/common/khrn_int_ids.h | ||
41 | +++ b/interface/khronos/common/khrn_int_ids.h | ||
42 | @@ -367,6 +367,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
43 | */ | ||
44 | |||
45 | #define EGLINTCREATESURFACE_ID 0x4000 | ||
46 | +#define EGLINTCREATESURFACE_ID_V2 0x4100 | ||
47 | #define EGLINTCREATEGLES11_ID 0x4001 | ||
48 | #define EGLINTCREATEGLES20_ID 0x4002 | ||
49 | #define EGLINTCREATEVG_ID 0x4003 | ||
50 | @@ -377,6 +378,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
51 | #define EGLINTMAKECURRENT_ID 0x4008 | ||
52 | #define EGLINTFLUSHANDWAIT_ID 0x4009 | ||
53 | #define EGLINTSWAPBUFFERS_ID 0x400a | ||
54 | +#define EGLINTSWAPBUFFERS_ID_V2 0x410a | ||
55 | #define EGLINTSELECTMIPMAP_ID 0x400b | ||
56 | #define EGLINTFLUSH_ID 0x400c | ||
57 | #define EGLINTGETCOLORDATA_ID 0x400d | ||
58 | diff --git a/interface/khronos/egl/egl_client.c b/interface/khronos/egl/egl_client.c | ||
59 | index 472ef0c..234da65 100644 | ||
60 | --- a/interface/khronos/egl/egl_client.c | ||
61 | +++ b/interface/khronos/egl/egl_client.c | ||
62 | @@ -162,6 +162,17 @@ static void egl_current_release(CLIENT_PROCESS_STATE_T *process, EGL_CURRENT_T * | ||
63 | void egl_gl_flush_callback(bool wait); | ||
64 | void egl_vg_flush_callback(bool wait); | ||
65 | |||
66 | +#include "interface/vmcs_host/vc_dispmanx_types.h" | ||
67 | +/**HACKHACK - give us the ability to inject a DispmanX | ||
68 | + * resource handle into the CreateWindowSurface and | ||
69 | + * SwapBuffers calls */ | ||
70 | +static DISPMANX_RESOURCE_HANDLE_T next_resource_handle; | ||
71 | + | ||
72 | +EGLAPI EGLBoolean EGLAPIENTRY eglSetNextResourceHandle(DISPMANX_RESOURCE_HANDLE_T handle) | ||
73 | +{ | ||
74 | + next_resource_handle = handle; | ||
75 | +} | ||
76 | + | ||
77 | /* | ||
78 | TODO: do an RPC call to make sure the Khronos vll is loaded (and that it stays loaded until eglTerminate) | ||
79 | Also affects global image (and possibly others?) | ||
80 | @@ -644,7 +655,8 @@ EGLAPI EGLSurface EGLAPIENTRY eglCreateWindowSurface(EGLDisplay dpy, EGLConfig c | ||
81 | false, | ||
82 | EGL_NO_TEXTURE, | ||
83 | EGL_NO_TEXTURE, | ||
84 | - 0, 0); | ||
85 | + 0, 0, | ||
86 | + next_resource_handle); | ||
87 | |||
88 | if (surface) { | ||
89 | if (khrn_pointer_map_insert(&process->surfaces, process->next_surface, surface)) { | ||
90 | @@ -889,7 +901,7 @@ EGLAPI EGLSurface EGLAPIENTRY eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig | ||
91 | mipmap_texture, | ||
92 | texture_format, | ||
93 | texture_target, | ||
94 | - 0, 0); | ||
95 | + 0, 0, 0); | ||
96 | |||
97 | if (surface) { | ||
98 | if (khrn_pointer_map_insert(&process->surfaces, process->next_surface, surface)) { | ||
99 | @@ -1031,7 +1043,7 @@ EGLAPI EGLSurface EGLAPIENTRY eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig c | ||
100 | false, | ||
101 | EGL_NO_TEXTURE, | ||
102 | EGL_NO_TEXTURE, | ||
103 | - pixmap, ((server_handle[0] == 0) && (server_handle[1] == (uint32_t)(-1))) ? NULL : server_handle); | ||
104 | + pixmap, ((server_handle[0] == 0) && (server_handle[1] == (uint32_t)(-1))) ? NULL : server_handle, 0); | ||
105 | |||
106 | if (surface) { | ||
107 | if (khrn_pointer_map_insert(&process->surfaces, process->next_surface, surface)) { | ||
108 | @@ -2303,6 +2315,18 @@ EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffers(EGLDisplay dpy, EGLSurface surf) | ||
109 | |||
110 | vcos_log_trace("eglSwapBuffers server call"); | ||
111 | |||
112 | + if (next_resource_handle) | ||
113 | + RPC_CALL7(eglIntSwapBuffers_impl, | ||
114 | + thread, | ||
115 | + EGLINTSWAPBUFFERS_ID_V2, | ||
116 | + RPC_UINT(surface->serverbuffer), | ||
117 | + RPC_UINT(surface->width), | ||
118 | + RPC_UINT(surface->height), | ||
119 | + RPC_UINT(surface->internal_handle), | ||
120 | + RPC_UINT(surface->swap_behavior == EGL_BUFFER_PRESERVED ? 1 : 0), | ||
121 | + RPC_UINT(khrn_platform_get_window_position(surface->win)), | ||
122 | + RPC_INT(next_resource_handle)); | ||
123 | + else | ||
124 | RPC_CALL6(eglIntSwapBuffers_impl, | ||
125 | thread, | ||
126 | EGLINTSWAPBUFFERS_ID, | ||
127 | diff --git a/interface/khronos/egl/egl_client_surface.c b/interface/khronos/egl/egl_client_surface.c | ||
128 | index 0fa1fd1..0dc10e2 100644 | ||
129 | --- a/interface/khronos/egl/egl_client_surface.c | ||
130 | +++ b/interface/khronos/egl/egl_client_surface.c | ||
131 | @@ -314,7 +314,8 @@ EGL_SURFACE_T *egl_surface_create( | ||
132 | EGLenum texture_format, | ||
133 | EGLenum texture_target, | ||
134 | EGLNativePixmapType pixmap, | ||
135 | - const uint32_t *pixmap_server_handle) | ||
136 | + const uint32_t *pixmap_server_handle, | ||
137 | + DISPMANX_RESOURCE_HANDLE_T next_resource_handle) | ||
138 | { | ||
139 | KHRN_IMAGE_FORMAT_T color; | ||
140 | KHRN_IMAGE_FORMAT_T depth; | ||
141 | @@ -473,6 +474,27 @@ EGL_SURFACE_T *egl_surface_create( | ||
142 | #endif | ||
143 | uint32_t results[3]; | ||
144 | |||
145 | + if (next_resource_handle) | ||
146 | + RPC_CALL16_OUT_CTRL(eglIntCreateSurface_impl, | ||
147 | + thread, | ||
148 | + EGLINTCREATESURFACE_ID_V2, | ||
149 | + RPC_UINT(serverwin), | ||
150 | + RPC_UINT(buffers), | ||
151 | + RPC_UINT(width), | ||
152 | + RPC_UINT(height), | ||
153 | + RPC_UINT(color), | ||
154 | + RPC_UINT(depth), | ||
155 | + RPC_UINT(mask), | ||
156 | + RPC_UINT(multi), | ||
157 | + RPC_UINT(largest_pbuffer), | ||
158 | + RPC_UINT(mipmap_texture), | ||
159 | + RPC_UINT(config_depth_bits), | ||
160 | + RPC_UINT(config_stencil_bits), | ||
161 | + RPC_UINT(sem_name), | ||
162 | + RPC_UINT(type), | ||
163 | + RPC_INT(next_resource_handle), | ||
164 | + results); | ||
165 | + else | ||
166 | RPC_CALL15_OUT_CTRL(eglIntCreateSurface_impl, | ||
167 | thread, | ||
168 | EGLINTCREATESURFACE_ID, | ||
169 | diff --git a/interface/khronos/egl/egl_client_surface.h b/interface/khronos/egl/egl_client_surface.h | ||
170 | index c99d44c..b5bf70a 100644 | ||
171 | --- a/interface/khronos/egl/egl_client_surface.h | ||
172 | +++ b/interface/khronos/egl/egl_client_surface.h | ||
173 | @@ -322,7 +322,8 @@ extern EGL_SURFACE_T *egl_surface_create( | ||
174 | EGLenum texture_format, | ||
175 | EGLenum texture_target, | ||
176 | EGLNativePixmapType pixmap, | ||
177 | - const uint32_t *pixmap_server_handle); | ||
178 | + const uint32_t *pixmap_server_handle, | ||
179 | + DISPMANX_RESOURCE_HANDLE_T next_resource_handle); | ||
180 | extern EGL_SURFACE_T *egl_surface_from_vg_image( | ||
181 | VGImage vg_handle, | ||
182 | EGLSurface name, | ||
183 | diff --git a/interface/khronos/egl/egl_int_impl.h b/interface/khronos/egl/egl_int_impl.h | ||
184 | index 8a5734c..51b3580 100644 | ||
185 | --- a/interface/khronos/egl/egl_int_impl.h | ||
186 | +++ b/interface/khronos/egl/egl_int_impl.h | ||
187 | @@ -56,7 +56,8 @@ FN(int, eglIntCreateSurface_impl, ( | ||
188 | uint32_t config_stencil_bits, | ||
189 | uint32_t sem, | ||
190 | uint32_t type, | ||
191 | - uint32_t *results)) | ||
192 | + uint32_t *results, | ||
193 | + DISPMANX_RESOURCE_HANDLE_T next_resource_handle)) | ||
194 | |||
195 | FN(int, eglIntCreatePbufferFromVGImage_impl, ( | ||
196 | VGImage vg_handle, | ||
197 | @@ -110,7 +111,7 @@ FN(void, eglIntMakeCurrent_impl, (uint32_t pid_0, uint32_t pid_1, uint32_t glver | ||
198 | FN(int, eglIntFlushAndWait_impl, (uint32_t flushgl, uint32_t flushvg)) | ||
199 | FN(void, eglIntFlush_impl, (uint32_t flushgl, uint32_t flushvg)) | ||
200 | |||
201 | -FN(void, eglIntSwapBuffers_impl, (EGL_SURFACE_ID_T s, uint32_t width, uint32_t height, uint32_t handle, uint32_t preserve, uint32_t position)) | ||
202 | +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)) | ||
203 | FN(void, eglIntSelectMipmap_impl, (EGL_SURFACE_ID_T s, int level)) | ||
204 | |||
205 | 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)) | ||
206 | -- | ||
207 | 2.7.0 | ||
208 | |||
diff --git a/recipes-graphics/userland/userland/0009-wayland-Add-support-for-the-Wayland-winsys.patch b/recipes-graphics/userland/userland/0009-wayland-Add-support-for-the-Wayland-winsys.patch new file mode 100644 index 0000000..c6e175e --- /dev/null +++ b/recipes-graphics/userland/userland/0009-wayland-Add-support-for-the-Wayland-winsys.patch | |||
@@ -0,0 +1,1880 @@ | |||
1 | From dba72dbc97a07509befc3072cc4dc5184913b5a7 Mon Sep 17 00:00:00 2001 | ||
2 | From: Tomeu Vizoso <tomeu.vizoso@collabora.com> | ||
3 | Date: Tue, 1 Oct 2013 13:19:20 +0200 | ||
4 | Subject: [PATCH 09/16] wayland: Add support for the Wayland winsys | ||
5 | |||
6 | * Adds EGL_WL_bind_wayland_display extension | ||
7 | * Adds wayland-egl library | ||
8 | * Adds wl_dispmanx_buffer protocol extension | ||
9 | |||
10 | TODO: Check that platform_get_dimensions() returning swapchain_count == 1 is correct | ||
11 | |||
12 | TODO: Remove the requirement of passing a valid DispmanX element handle to | ||
13 | the SwapBuffers and CreateSurface RPC calls. This will remove the need to open | ||
14 | a DispmanX display from the clients. | ||
15 | |||
16 | TODO: wl_dispmanx_server_buffer should probably be defined in a | ||
17 | private header that can be included from EGL and vc_* instead of in | ||
18 | vc_vchi_dispmanx.h | ||
19 | --- | ||
20 | .gitignore | 2 + | ||
21 | CMakeLists.txt | 11 + | ||
22 | README.md | 4 + | ||
23 | buildme | 14 +- | ||
24 | interface/khronos/CMakeLists.txt | 52 ++++- | ||
25 | interface/khronos/common/khrn_client.c | 15 ++ | ||
26 | interface/khronos/common/khrn_client.h | 10 + | ||
27 | interface/khronos/common/khrn_client_mangle.h | 3 + | ||
28 | interface/khronos/common/khrn_client_platform.h | 8 + | ||
29 | interface/khronos/common/khrn_client_unmangle.h | 3 + | ||
30 | .../common/linux/khrn_client_platform_linux.c | 115 ++++++++-- | ||
31 | interface/khronos/common/linux/khrn_wayland.c | 215 ++++++++++++++++++ | ||
32 | .../common/linux/khrn_wayland.h} | 46 +--- | ||
33 | interface/khronos/egl/egl_client.c | 92 +++++--- | ||
34 | interface/khronos/egl/egl_client_get_proc.c | 11 + | ||
35 | interface/khronos/egl/egl_client_surface.c | 42 +++- | ||
36 | interface/khronos/egl/egl_client_surface.h | 38 +++- | ||
37 | interface/khronos/egl/egl_int_impl.h | 2 +- | ||
38 | interface/khronos/ext/egl_wayland.c | 246 +++++++++++++++++++++ | ||
39 | interface/khronos/include/EGL/eglext.h | 23 ++ | ||
40 | interface/khronos/wayland-egl/wayland-egl-priv.h | 53 +++++ | ||
41 | interface/khronos/wayland-egl/wayland-egl.c | 59 +++++ | ||
42 | interface/khronos/wayland-egl/wayland-egl.pc.in | 10 + | ||
43 | interface/vmcs_host/CMakeLists.txt | 21 +- | ||
44 | interface/vmcs_host/vc_dispmanx.h | 10 + | ||
45 | interface/vmcs_host/vc_vchi_dispmanx.c | 42 ++++ | ||
46 | interface/vmcs_host/vc_vchi_dispmanx.h | 15 ++ | ||
47 | interface/wayland/dispmanx.xml | 123 +++++++++++ | ||
48 | makefiles/cmake/Wayland.cmake | 72 ++++++ | ||
49 | 29 files changed, 1260 insertions(+), 97 deletions(-) | ||
50 | create mode 100644 interface/khronos/common/linux/khrn_wayland.c | ||
51 | copy interface/{vmcs_host/vc_vchi_dispmanx.h => khronos/common/linux/khrn_wayland.h} (56%) | ||
52 | create mode 100644 interface/khronos/ext/egl_wayland.c | ||
53 | create mode 100644 interface/khronos/wayland-egl/wayland-egl-priv.h | ||
54 | create mode 100644 interface/khronos/wayland-egl/wayland-egl.c | ||
55 | create mode 100644 interface/khronos/wayland-egl/wayland-egl.pc.in | ||
56 | create mode 100644 interface/wayland/dispmanx.xml | ||
57 | create mode 100644 makefiles/cmake/Wayland.cmake | ||
58 | |||
59 | diff --git a/.gitignore b/.gitignore | ||
60 | index 8df9393..d0d1387 100644 | ||
61 | --- a/.gitignore | ||
62 | +++ b/.gitignore | ||
63 | @@ -10,3 +10,5 @@ | ||
64 | *.lai | ||
65 | *.la | ||
66 | *.a | ||
67 | + | ||
68 | +*~ | ||
69 | diff --git a/CMakeLists.txt b/CMakeLists.txt | ||
70 | index f15dc2b..b240ef6 100644 | ||
71 | --- a/CMakeLists.txt | ||
72 | +++ b/CMakeLists.txt | ||
73 | @@ -13,6 +13,17 @@ include(makefiles/cmake/global_settings.cmake) | ||
74 | include(makefiles/cmake/arm-linux.cmake) | ||
75 | include(makefiles/cmake/vmcs.cmake) | ||
76 | |||
77 | +if (BUILD_WAYLAND) | ||
78 | + include(makefiles/cmake/Wayland.cmake) | ||
79 | + | ||
80 | + # Find Wayland libraries | ||
81 | + find_package(PkgConfig) | ||
82 | + pkg_check_modules(WAYLAND_CLIENT wayland-client REQUIRED) | ||
83 | + pkg_check_modules(WAYLAND_SERVER wayland-server REQUIRED) | ||
84 | + | ||
85 | + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DBUILD_WAYLAND") | ||
86 | +endif() | ||
87 | + | ||
88 | enable_language(ASM) | ||
89 | |||
90 | # Global include paths | ||
91 | diff --git a/README.md b/README.md | ||
92 | index 358d2b4..4da4448 100644 | ||
93 | --- a/README.md | ||
94 | +++ b/README.md | ||
95 | @@ -4,3 +4,7 @@ EGL, mmal, GLESv2, vcos, openmaxil, vchiq_arm, bcm_host, WFC, OpenVG. | ||
96 | |||
97 | Use buildme to build. It requires cmake to be installed and an arm cross compiler. It is set up to use this one: | ||
98 | https://github.com/raspberrypi/tools/tree/master/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian | ||
99 | + | ||
100 | +To build support for the Wayland winsys in EGL, execute the buildme script like this: | ||
101 | + | ||
102 | +$ BUILD_WAYLAND=1 ./buildme. | ||
103 | diff --git a/buildme b/buildme | ||
104 | index d5d3de9..c46f214 100755 | ||
105 | --- a/buildme | ||
106 | +++ b/buildme | ||
107 | @@ -1,10 +1,14 @@ | ||
108 | #!/bin/bash | ||
109 | |||
110 | +if [ -n "$BUILD_WAYLAND" ]; then | ||
111 | + WAYLAND_VARS="-DBUILD_WAYLAND=TRUE" | ||
112 | +fi | ||
113 | + | ||
114 | if [ "armv6l" = `arch` ] || [ "armv7l" = `arch` ]; then | ||
115 | # Native compile on the Raspberry Pi | ||
116 | mkdir -p build/raspberry/release | ||
117 | pushd build/raspberry/release | ||
118 | - cmake -DCMAKE_BUILD_TYPE=Release ../../.. | ||
119 | + cmake -DCMAKE_BUILD_TYPE=Release $WAYLAND_VARS ../../.. | ||
120 | if [ "armv6l" = `arch` ]; then | ||
121 | make | ||
122 | else | ||
123 | @@ -17,9 +21,15 @@ if [ "armv6l" = `arch` ] || [ "armv7l" = `arch` ]; then | ||
124 | fi | ||
125 | else | ||
126 | # Cross compile on a more capable machine | ||
127 | + | ||
128 | + if [ -n "$BUILD_WAYLAND" ]; then | ||
129 | + # Use wayland-scanner from the build platform | ||
130 | + WAYLAND_VARS+=" -DWAYLAND_SCANNER_EXECUTABLE:FILEPATH=/usr/bin/wayland-scanner" | ||
131 | + fi | ||
132 | + | ||
133 | mkdir -p build/arm-linux/release/ | ||
134 | pushd build/arm-linux/release/ | ||
135 | - cmake -DCMAKE_TOOLCHAIN_FILE=../../../makefiles/cmake/toolchains/arm-linux-gnueabihf.cmake -DCMAKE_BUILD_TYPE=Release ../../.. | ||
136 | + cmake -DCMAKE_TOOLCHAIN_FILE=../../../makefiles/cmake/toolchains/arm-linux-gnueabihf.cmake -DCMAKE_BUILD_TYPE=Release $WAYLAND_VARS ../../.. | ||
137 | make -j 6 | ||
138 | |||
139 | if [ "$1" != "" ]; then | ||
140 | diff --git a/interface/khronos/CMakeLists.txt b/interface/khronos/CMakeLists.txt | ||
141 | index c437291..6778e10 100644 | ||
142 | --- a/interface/khronos/CMakeLists.txt | ||
143 | +++ b/interface/khronos/CMakeLists.txt | ||
144 | @@ -6,6 +6,12 @@ | ||
145 | # have quite a few circular dependencies, and so the only way | ||
146 | # to make it work seems to be to have everything static. | ||
147 | |||
148 | +if (BUILD_WAYLAND) | ||
149 | +include_directories( | ||
150 | + ${WAYLAND_SERVER_INCLUDE_DIRS} | ||
151 | +) | ||
152 | +endif () | ||
153 | + | ||
154 | set(EGL_SOURCE | ||
155 | egl/egl_client_config.c | ||
156 | egl/egl_client_context.c | ||
157 | @@ -55,19 +61,63 @@ set(CLIENT_SOURCE | ||
158 | common/khrn_int_hash_asm.s | ||
159 | common/khrn_client_cache.c) | ||
160 | |||
161 | +set(EGL_LIBS | ||
162 | + khrn_client | ||
163 | + vchiq_arm | ||
164 | + vcos | ||
165 | + bcm_host | ||
166 | + -lm) | ||
167 | + | ||
168 | +if (BUILD_WAYLAND) | ||
169 | + set(EGL_SOURCE | ||
170 | + ${EGL_SOURCE} | ||
171 | + ext/egl_wayland.c | ||
172 | + common/linux/khrn_wayland.c) | ||
173 | + | ||
174 | + set(EGL_LIBS | ||
175 | + ${EGL_LIBS} | ||
176 | + wayland-client | ||
177 | + wayland-server) | ||
178 | + | ||
179 | + set(WAYLAND_EGL_SOURCE | ||
180 | + wayland-egl/wayland-egl.c) | ||
181 | + | ||
182 | + wayland_add_protocol_server( | ||
183 | + EGL_SOURCE | ||
184 | + ../../interface/wayland/dispmanx.xml | ||
185 | + dispmanx | ||
186 | + ) | ||
187 | + | ||
188 | + wayland_add_protocol_client( | ||
189 | + EGL_SOURCE | ||
190 | + ../../interface/wayland/dispmanx.xml | ||
191 | + dispmanx | ||
192 | + ) | ||
193 | + | ||
194 | + add_library(wayland-egl ${SHARED} ${WAYLAND_EGL_SOURCE}) | ||
195 | + install(TARGETS wayland-egl DESTINATION lib) | ||
196 | + | ||
197 | + configure_file ("wayland-egl/wayland-egl.pc.in" "wayland-egl/wayland-egl.pc" @ONLY) | ||
198 | + install (FILES "${CMAKE_CURRENT_BINARY_DIR}/wayland-egl/wayland-egl.pc" | ||
199 | + DESTINATION lib/pkgconfig) | ||
200 | +endif () | ||
201 | + | ||
202 | add_library(EGL ${SHARED} ${EGL_SOURCE}) | ||
203 | add_library(GLESv2 ${SHARED} ${GLES_SOURCE}) | ||
204 | add_library(OpenVG ${SHARED} ${VG_SOURCE}) | ||
205 | add_library(WFC ${SHARED} ${WFC_SOURCE}) | ||
206 | add_library(khrn_client ${CLIENT_SOURCE}) | ||
207 | |||
208 | +set_target_properties(EGL PROPERTIES SOVERSION 1 VERSION 1.0.0) | ||
209 | +set_target_properties(GLESv2 PROPERTIES SOVERSION 2 VERSION 2.0.0) | ||
210 | + | ||
211 | # TODO do we need EGL_static and GLESv2_static now that khrn_static exists? | ||
212 | add_library(EGL_static STATIC ${EGL_SOURCE}) | ||
213 | add_library(GLESv2_static STATIC ${GLES_SOURCE}) | ||
214 | add_library(khrn_static STATIC | ||
215 | ${EGL_SOURCE} ${GLES_SOURCE} ${VG_SOURCE} ${WFC_SOURCE} ${CLIENT_SOURCE}) | ||
216 | |||
217 | -target_link_libraries(EGL khrn_client vchiq_arm vcos bcm_host -lm) | ||
218 | +target_link_libraries(EGL ${EGL_LIBS}) | ||
219 | target_link_libraries(GLESv2 EGL khrn_client vcos) | ||
220 | target_link_libraries(WFC EGL) | ||
221 | target_link_libraries(OpenVG EGL) | ||
222 | diff --git a/interface/khronos/common/khrn_client.c b/interface/khronos/common/khrn_client.c | ||
223 | index e38a85f..783a68e 100644 | ||
224 | --- a/interface/khronos/common/khrn_client.c | ||
225 | +++ b/interface/khronos/common/khrn_client.c | ||
226 | @@ -54,6 +54,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
227 | #include "applications/vmcs/khronos/khronos_server.h" | ||
228 | #endif | ||
229 | |||
230 | +#ifdef BUILD_WAYLAND | ||
231 | +#include "interface/khronos/common/linux/khrn_wayland.h" | ||
232 | +#endif | ||
233 | + | ||
234 | VCOS_LOG_CAT_T khrn_client_log = VCOS_LOG_INIT("khrn_client", VCOS_LOG_WARN); | ||
235 | |||
236 | /* | ||
237 | @@ -142,6 +146,10 @@ void client_try_unload_server(CLIENT_PROCESS_STATE_T *process) | ||
238 | bool client_process_state_init(CLIENT_PROCESS_STATE_T *process) | ||
239 | { | ||
240 | if (!process->inited) { | ||
241 | +#ifdef BUILD_WAYLAND | ||
242 | + process->wl_global = NULL; | ||
243 | +#endif | ||
244 | + | ||
245 | if (!khrn_pointer_map_init(&process->contexts, 64)) | ||
246 | return false; | ||
247 | |||
248 | @@ -194,6 +202,13 @@ bool client_process_state_init(CLIENT_PROCESS_STATE_T *process) | ||
249 | } | ||
250 | #endif | ||
251 | |||
252 | +#ifdef BUILD_WAYLAND | ||
253 | + struct wl_display *wl_display = khrn_platform_get_wl_display(); | ||
254 | + if (wl_display) | ||
255 | + if (!init_process_wayland(process)) | ||
256 | + return false; | ||
257 | +#endif | ||
258 | + | ||
259 | process->inited = true; | ||
260 | } | ||
261 | |||
262 | diff --git a/interface/khronos/common/khrn_client.h b/interface/khronos/common/khrn_client.h | ||
263 | index 804039b..615f7b4 100644 | ||
264 | --- a/interface/khronos/common/khrn_client.h | ||
265 | +++ b/interface/khronos/common/khrn_client.h | ||
266 | @@ -310,6 +310,16 @@ struct CLIENT_PROCESS_STATE { | ||
267 | #ifdef RPC_LIBRARY | ||
268 | KHRONOS_SERVER_CONNECTION_T khrn_connection; | ||
269 | #endif | ||
270 | + | ||
271 | +#ifdef BUILD_WAYLAND | ||
272 | + /* Client-side Wayland state */ | ||
273 | + struct wl_registry *wl_registry; | ||
274 | + struct wl_dispmanx *wl_dispmanx; | ||
275 | + struct wl_event_queue *wl_queue; | ||
276 | + | ||
277 | + /* Compositor-side Wayland state */ | ||
278 | + struct wl_global *wl_global; | ||
279 | +#endif | ||
280 | }; | ||
281 | |||
282 | extern bool client_process_state_init(CLIENT_PROCESS_STATE_T *process); | ||
283 | diff --git a/interface/khronos/common/khrn_client_mangle.h b/interface/khronos/common/khrn_client_mangle.h | ||
284 | index b3c04f4..b7b21c5 100644 | ||
285 | --- a/interface/khronos/common/khrn_client_mangle.h | ||
286 | +++ b/interface/khronos/common/khrn_client_mangle.h | ||
287 | @@ -83,6 +83,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
288 | #define eglReleaseGlobalImageBRCM mangled_eglReleaseGlobalImageBRCM | ||
289 | #define eglInitGlobalImageBRCM mangled_eglInitGlobalImageBRCM | ||
290 | #define eglTermGlobalImageBRCM mangled_eglTermGlobalImageBRCM | ||
291 | +#define eglBindWaylandDisplayWL mangled_eglBindWaylandDisplayWL | ||
292 | +#define eglUnbindWaylandDisplayWL mangled_eglUnbindWaylandDisplayWL | ||
293 | +#define eglQueryWaylandBufferWL mangled_eglQueryWaylandBufferWL | ||
294 | |||
295 | /* OpenGL ES 1.1 and 2.0 functions */ | ||
296 | |||
297 | diff --git a/interface/khronos/common/khrn_client_platform.h b/interface/khronos/common/khrn_client_platform.h | ||
298 | index 1c9da3a..715c67e 100644 | ||
299 | --- a/interface/khronos/common/khrn_client_platform.h | ||
300 | +++ b/interface/khronos/common/khrn_client_platform.h | ||
301 | @@ -48,6 +48,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
302 | #include "interface/khronos/common/vcos/khrn_client_platform_filler_vcos.h" | ||
303 | #endif | ||
304 | |||
305 | +#ifdef BUILD_WAYLAND | ||
306 | +#include <wayland-client.h> | ||
307 | +#endif | ||
308 | + | ||
309 | #ifdef __cplusplus | ||
310 | extern "C" { | ||
311 | #endif | ||
312 | @@ -328,4 +332,8 @@ typedef struct | ||
313 | |||
314 | void *platform_wfc_bounce_thread(void *param); | ||
315 | |||
316 | +#ifdef BUILD_WAYLAND | ||
317 | +struct wl_display *khrn_platform_get_wl_display(); | ||
318 | +#endif | ||
319 | + | ||
320 | #endif // KHRN_CLIENT_PLATFORM_H | ||
321 | diff --git a/interface/khronos/common/khrn_client_unmangle.h b/interface/khronos/common/khrn_client_unmangle.h | ||
322 | index 4f3ce49..84f6ec0 100644 | ||
323 | --- a/interface/khronos/common/khrn_client_unmangle.h | ||
324 | +++ b/interface/khronos/common/khrn_client_unmangle.h | ||
325 | @@ -83,6 +83,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
326 | #undef eglReleaseGlobalImageBRCM | ||
327 | #undef eglInitGlobalImageBRCM | ||
328 | #undef eglTermGlobalImageBRCM | ||
329 | +#undef eglBindWaylandDisplayWL | ||
330 | +#undef eglUnbindWaylandDisplayWL | ||
331 | +#undef eglQueryWaylandBufferWL | ||
332 | |||
333 | /* OpenGL ES 1.1 and 2.0 functions */ | ||
334 | |||
335 | diff --git a/interface/khronos/common/linux/khrn_client_platform_linux.c b/interface/khronos/common/linux/khrn_client_platform_linux.c | ||
336 | index a060f26..13c8c25 100644 | ||
337 | --- a/interface/khronos/common/linux/khrn_client_platform_linux.c | ||
338 | +++ b/interface/khronos/common/linux/khrn_client_platform_linux.c | ||
339 | @@ -37,6 +37,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
340 | #include "X11/Xlib.h" | ||
341 | #endif | ||
342 | |||
343 | +#ifdef BUILD_WAYLAND | ||
344 | +#include <wayland-client.h> | ||
345 | +#include "interface/khronos/wayland-egl/wayland-egl-priv.h" | ||
346 | +#endif | ||
347 | + | ||
348 | extern VCOS_LOG_CAT_T khrn_client_log; | ||
349 | |||
350 | extern void vc_vchi_khronos_init(); | ||
351 | @@ -460,13 +465,36 @@ EGLDisplay khrn_platform_set_display_id(EGLNativeDisplayType display_id) | ||
352 | return EGL_NO_DISPLAY; | ||
353 | } | ||
354 | #else | ||
355 | + | ||
356 | +#ifdef BUILD_WAYLAND | ||
357 | +static struct wl_display *hacky_display = NULL; | ||
358 | +#endif | ||
359 | + | ||
360 | EGLDisplay khrn_platform_set_display_id(EGLNativeDisplayType display_id) | ||
361 | { | ||
362 | if (display_id == EGL_DEFAULT_DISPLAY) | ||
363 | return (EGLDisplay)1; | ||
364 | - else | ||
365 | - return EGL_NO_DISPLAY; | ||
366 | + else { | ||
367 | +#ifdef BUILD_WAYLAND | ||
368 | + void *first_pointer = *(void **) display_id; | ||
369 | + | ||
370 | + /* wl_display is a wl_proxy, which is a wl_object. | ||
371 | + * wl_object's first element points to the interfacetype. */ | ||
372 | + if (first_pointer == &wl_display_interface) { | ||
373 | + hacky_display = (struct wl_display*)display_id; | ||
374 | + return (EGLDisplay)1; | ||
375 | + } else | ||
376 | +#endif | ||
377 | + return EGL_NO_DISPLAY; | ||
378 | + } | ||
379 | } | ||
380 | + | ||
381 | +#ifdef BUILD_WAYLAND | ||
382 | +struct wl_display *khrn_platform_get_wl_display() | ||
383 | +{ | ||
384 | + return hacky_display; | ||
385 | +} | ||
386 | +#endif | ||
387 | #endif | ||
388 | |||
389 | #ifdef WANT_X | ||
390 | @@ -801,22 +829,81 @@ static EGL_DISPMANX_WINDOW_T *check_default(EGLNativeWindowType win) | ||
391 | void platform_get_dimensions(EGLDisplay dpy, EGLNativeWindowType win, | ||
392 | uint32_t *width, uint32_t *height, uint32_t *swapchain_count) | ||
393 | { | ||
394 | - EGL_DISPMANX_WINDOW_T *dwin = check_default(win); | ||
395 | - vcos_assert(dwin); | ||
396 | - vcos_assert(dwin->width < 1<<16); // sanity check | ||
397 | - vcos_assert(dwin->height < 1<<16); // sanity check | ||
398 | - *width = dwin->width; | ||
399 | - *height = dwin->height; | ||
400 | - *swapchain_count = 0; | ||
401 | +#ifdef BUILD_WAYLAND | ||
402 | + if(khrn_platform_get_wl_display()) { | ||
403 | + struct wl_egl_window *wl_egl_window = (struct wl_egl_window*)win; | ||
404 | + *width = wl_egl_window->width; | ||
405 | + *height = wl_egl_window->height; | ||
406 | + /* This seems to be used for sync'ing with the VC on buffer creation, but | ||
407 | + we are managing them on the CPU side */ | ||
408 | + *swapchain_count = 1; | ||
409 | + } else { | ||
410 | +#endif | ||
411 | + EGL_DISPMANX_WINDOW_T *dwin = check_default(win); | ||
412 | + vcos_assert(dwin); | ||
413 | + vcos_assert(dwin->width < 1<<16); // sanity check | ||
414 | + vcos_assert(dwin->height < 1<<16); // sanity check | ||
415 | + *width = dwin->width; | ||
416 | + *height = dwin->height; | ||
417 | + *swapchain_count = 0; | ||
418 | +#ifdef BUILD_WAYLAND | ||
419 | + } | ||
420 | +#endif | ||
421 | } | ||
422 | |||
423 | +#ifdef BUILD_WAYLAND | ||
424 | +static DISPMANX_ELEMENT_HANDLE_T create_dummy_element() | ||
425 | +{ | ||
426 | + DISPMANX_DISPLAY_HANDLE_T display = vc_dispmanx_display_open(0); | ||
427 | + DISPMANX_UPDATE_HANDLE_T update = vc_dispmanx_update_start(0); | ||
428 | + DISPMANX_ELEMENT_HANDLE_T element; | ||
429 | + VC_DISPMANX_ALPHA_T alpha = {DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS, 255, 0}; | ||
430 | + VC_RECT_T src_rect; | ||
431 | + VC_RECT_T dst_rect; | ||
432 | + | ||
433 | + src_rect.x = 0; | ||
434 | + src_rect.y = 0; | ||
435 | + src_rect.width = 1 << 16; | ||
436 | + src_rect.height = 1 << 16; | ||
437 | + | ||
438 | + dst_rect.x = 0; | ||
439 | + dst_rect.y = 0; | ||
440 | + dst_rect.width = 1; | ||
441 | + dst_rect.height = 1; | ||
442 | + | ||
443 | + element = vc_dispmanx_element_add(update, display, 0/*layer*/, &dst_rect, | ||
444 | + 0/*src*/, &src_rect, | ||
445 | + DISPMANX_PROTECTION_NONE, &alpha, | ||
446 | + 0/*clamp*/, 0/*transform*/); | ||
447 | + | ||
448 | + vc_dispmanx_update_submit_sync(update); | ||
449 | + | ||
450 | + vc_dispmanx_display_close(display); | ||
451 | + | ||
452 | + return element; | ||
453 | +} | ||
454 | +#endif | ||
455 | + | ||
456 | uint32_t platform_get_handle(EGLDisplay dpy, EGLNativeWindowType win) | ||
457 | { | ||
458 | - EGL_DISPMANX_WINDOW_T *dwin = check_default(win); | ||
459 | - vcos_assert(dwin); | ||
460 | - vcos_assert(dwin->width < 1<<16); // sanity check | ||
461 | - vcos_assert(dwin->height < 1<<16); // sanity check | ||
462 | - return dwin->element; | ||
463 | +#ifdef BUILD_WAYLAND | ||
464 | + if(khrn_platform_get_wl_display()) { | ||
465 | + struct wl_egl_window *wl_egl_window = (struct wl_egl_window*)win; | ||
466 | + | ||
467 | + if (wl_egl_window->dummy_element == PLATFORM_WIN_NONE) | ||
468 | + wl_egl_window->dummy_element = create_dummy_element(); | ||
469 | + | ||
470 | + return wl_egl_window->dummy_element; | ||
471 | + } else { | ||
472 | +#endif | ||
473 | + EGL_DISPMANX_WINDOW_T *dwin = check_default(win); | ||
474 | + vcos_assert(dwin); | ||
475 | + vcos_assert(dwin->width < 1<<16); // sanity check | ||
476 | + vcos_assert(dwin->height < 1<<16); // sanity check | ||
477 | + return dwin->element; | ||
478 | +#ifdef BUILD_WAYLAND | ||
479 | + } | ||
480 | +#endif | ||
481 | } | ||
482 | |||
483 | #endif | ||
484 | diff --git a/interface/khronos/common/linux/khrn_wayland.c b/interface/khronos/common/linux/khrn_wayland.c | ||
485 | new file mode 100644 | ||
486 | index 0000000..0e1b9e7 | ||
487 | --- /dev/null | ||
488 | +++ b/interface/khronos/common/linux/khrn_wayland.c | ||
489 | @@ -0,0 +1,215 @@ | ||
490 | +/* | ||
491 | +Copyright (c) 2013, Raspberry Pi Foundation | ||
492 | +All rights reserved. | ||
493 | + | ||
494 | +Redistribution and use in source and binary forms, with or without | ||
495 | +modification, are permitted provided that the following conditions are met: | ||
496 | + * Redistributions of source code must retain the above copyright | ||
497 | + notice, this list of conditions and the following disclaimer. | ||
498 | + * Redistributions in binary form must reproduce the above copyright | ||
499 | + notice, this list of conditions and the following disclaimer in the | ||
500 | + documentation and/or other materials provided with the distribution. | ||
501 | + * Neither the name of the copyright holder nor the | ||
502 | + names of its contributors may be used to endorse or promote products | ||
503 | + derived from this software without specific prior written permission. | ||
504 | + | ||
505 | +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | ||
506 | +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
507 | +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
508 | +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY | ||
509 | +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
510 | +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
511 | +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
512 | +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
513 | +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
514 | +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
515 | +*/ | ||
516 | + | ||
517 | +#define VCOS_LOG_CATEGORY (&khrn_client_log) | ||
518 | + | ||
519 | +#include "interface/khronos/common/linux/khrn_wayland.h" | ||
520 | +#include "interface/khronos/wayland-dispmanx-client-protocol.h" | ||
521 | +#include "interface/khronos/wayland-egl/wayland-egl-priv.h" | ||
522 | + | ||
523 | +extern VCOS_LOG_CAT_T khrn_client_log; | ||
524 | + | ||
525 | +static void handle_dispmanx_format(void *data, struct wl_dispmanx *dispmanx, | ||
526 | + uint32_t format) | ||
527 | +{ | ||
528 | +} | ||
529 | + | ||
530 | +static void handle_dispmanx_allocated(void *data, struct wl_dispmanx *dispmanx, | ||
531 | + struct wl_buffer *wl_buffer, | ||
532 | + uint32_t resource_handle) | ||
533 | +{ | ||
534 | + struct wl_dispmanx_client_buffer *buffer = wl_buffer_get_user_data(wl_buffer); | ||
535 | + | ||
536 | + buffer->pending_allocation = 0; | ||
537 | + buffer->resource = resource_handle; | ||
538 | +} | ||
539 | + | ||
540 | +static const struct wl_dispmanx_listener dispmanx_listener = { | ||
541 | + handle_dispmanx_format, | ||
542 | + handle_dispmanx_allocated, | ||
543 | +}; | ||
544 | + | ||
545 | +static void | ||
546 | +sync_callback(void *data, struct wl_callback *callback, uint32_t serial) | ||
547 | +{ | ||
548 | + int *done = data; | ||
549 | + | ||
550 | + *done = 1; | ||
551 | + | ||
552 | + wl_callback_destroy(callback); | ||
553 | +} | ||
554 | + | ||
555 | +static const struct wl_callback_listener sync_listener = { | ||
556 | + sync_callback | ||
557 | +}; | ||
558 | + | ||
559 | +static int | ||
560 | +roundtrip(CLIENT_PROCESS_STATE_T *process) | ||
561 | +{ | ||
562 | + struct wl_display *wl_display = khrn_platform_get_wl_display(); | ||
563 | + struct wl_callback *callback; | ||
564 | + int done = 0, ret = 0; | ||
565 | + | ||
566 | + callback = wl_display_sync(wl_display); | ||
567 | + wl_callback_add_listener(callback, &sync_listener, &done); | ||
568 | + wl_proxy_set_queue((struct wl_proxy *) callback, process->wl_queue); | ||
569 | + while (ret != -1 && !done) | ||
570 | + ret = wl_display_dispatch_queue(wl_display, process->wl_queue); | ||
571 | + | ||
572 | + if (!done) | ||
573 | + wl_callback_destroy(callback); | ||
574 | + | ||
575 | + return ret; | ||
576 | +} | ||
577 | + | ||
578 | +int do_wl_roundtrip() | ||
579 | +{ | ||
580 | + CLIENT_PROCESS_STATE_T *process = CLIENT_GET_PROCESS_STATE(); | ||
581 | + return roundtrip(process); | ||
582 | +} | ||
583 | + | ||
584 | +static void | ||
585 | +registry_handle_global(void *data, struct wl_registry *registry, | ||
586 | + uint32_t name, const char *interface, uint32_t version) | ||
587 | +{ | ||
588 | + struct wl_display *wl_display = khrn_platform_get_wl_display(); | ||
589 | + CLIENT_PROCESS_STATE_T *process = (CLIENT_PROCESS_STATE_T *)data; | ||
590 | + | ||
591 | + if (strcmp(interface, "wl_dispmanx") == 0) { | ||
592 | + process->wl_dispmanx = wl_registry_bind(registry, name, | ||
593 | + &wl_dispmanx_interface, 1); | ||
594 | + | ||
595 | + wl_proxy_set_queue((struct wl_proxy *) process->wl_dispmanx, | ||
596 | + process->wl_queue); | ||
597 | + wl_dispmanx_add_listener(process->wl_dispmanx, &dispmanx_listener, wl_display); | ||
598 | + roundtrip(process); | ||
599 | + } | ||
600 | +} | ||
601 | + | ||
602 | +static void | ||
603 | +registry_handle_global_remove(void *data, struct wl_registry *registry, | ||
604 | + uint32_t name) | ||
605 | +{ | ||
606 | +} | ||
607 | + | ||
608 | +static const struct wl_registry_listener registry_listener = { | ||
609 | + registry_handle_global, | ||
610 | + registry_handle_global_remove | ||
611 | +}; | ||
612 | + | ||
613 | +int | ||
614 | +init_process_wayland(CLIENT_PROCESS_STATE_T *process) | ||
615 | +{ | ||
616 | + struct wl_display *wl_display = khrn_platform_get_wl_display(); | ||
617 | + | ||
618 | + process->wl_queue = wl_display_create_queue(wl_display); | ||
619 | + if (!process->wl_queue) { | ||
620 | + vcos_log_error("wl_display_create_queue failed\n"); | ||
621 | + return false; | ||
622 | + } | ||
623 | + wl_display_dispatch_pending(wl_display); | ||
624 | + | ||
625 | + process->wl_registry = wl_display_get_registry(wl_display); | ||
626 | + if (!process->wl_registry) { | ||
627 | + vcos_log_error("wl_display_get_registry failed\n"); | ||
628 | + return false; | ||
629 | + } | ||
630 | + | ||
631 | + wl_proxy_set_queue((struct wl_proxy *) process->wl_registry, | ||
632 | + process->wl_queue); | ||
633 | + | ||
634 | + wl_registry_add_listener(process->wl_registry, ®istry_listener, process); | ||
635 | + | ||
636 | + if (roundtrip(process) < 0 || process->wl_dispmanx == NULL) { | ||
637 | + vcos_log_error("failed to get wl_dispmanx\n"); | ||
638 | + return false; | ||
639 | + } | ||
640 | + | ||
641 | + return true; | ||
642 | +} | ||
643 | + | ||
644 | +#ifndef ALIGN_UP | ||
645 | +#define ALIGN_UP(x,y) ((x + (y)-1) & ~((y)-1)) | ||
646 | +#endif | ||
647 | + | ||
648 | +static void handle_buffer_release(void *data, struct wl_buffer *buffer_wl) | ||
649 | +{ | ||
650 | + struct wl_dispmanx_client_buffer *wl_dispmanx_client_buffer = data; | ||
651 | + wl_dispmanx_client_buffer->in_use = 0; | ||
652 | +} | ||
653 | + | ||
654 | +static const struct wl_buffer_listener buffer_listener = { | ||
655 | + handle_buffer_release | ||
656 | +}; | ||
657 | + | ||
658 | +struct wl_dispmanx_client_buffer * | ||
659 | +allocate_wl_buffer(struct wl_egl_window *window, KHRN_IMAGE_FORMAT_T color) | ||
660 | +{ | ||
661 | + CLIENT_PROCESS_STATE_T *process = CLIENT_GET_PROCESS_STATE(); | ||
662 | + struct wl_dispmanx_client_buffer *wl_dispmanx_client_buffer; | ||
663 | + struct wl_buffer *wl_buffer; | ||
664 | + uint32_t stride = ALIGN_UP(window->width * 4, 16); | ||
665 | + uint32_t buffer_height = ALIGN_UP(window->height, 16); | ||
666 | + enum wl_dispmanx_format color_format; | ||
667 | + int ret = 0; | ||
668 | + | ||
669 | + switch (color) { | ||
670 | + case ABGR_8888: | ||
671 | + color_format = WL_DISPMANX_FORMAT_ABGR8888; | ||
672 | + break; | ||
673 | + case XBGR_8888: | ||
674 | + color_format = WL_DISPMANX_FORMAT_XBGR8888; | ||
675 | + break; | ||
676 | + case RGB_565: | ||
677 | + color_format = WL_DISPMANX_FORMAT_RGB565; | ||
678 | + break; | ||
679 | + default: | ||
680 | + vcos_log_error("unknown KHRN_IMAGE_FORMAT_T 0x%x\n", color); | ||
681 | + return NULL; | ||
682 | + } | ||
683 | + | ||
684 | + wl_buffer = wl_dispmanx_create_buffer(process->wl_dispmanx, window->width, | ||
685 | + window->height, stride, buffer_height, | ||
686 | + color_format); | ||
687 | + if (wl_buffer == NULL) | ||
688 | + return NULL; | ||
689 | + | ||
690 | + wl_dispmanx_client_buffer = calloc(1, sizeof(struct wl_dispmanx_client_buffer)); | ||
691 | + wl_dispmanx_client_buffer->wl_buffer = wl_buffer; | ||
692 | + wl_dispmanx_client_buffer->in_use = 0; | ||
693 | + wl_dispmanx_client_buffer->pending_allocation = 1; | ||
694 | + wl_dispmanx_client_buffer->width = window->width; | ||
695 | + wl_dispmanx_client_buffer->height = window->height; | ||
696 | + | ||
697 | + wl_proxy_set_queue((struct wl_proxy *) wl_buffer, process->wl_queue); | ||
698 | + wl_buffer_add_listener(wl_buffer, &buffer_listener, wl_dispmanx_client_buffer); | ||
699 | + | ||
700 | + while (ret != -1 && wl_dispmanx_client_buffer->pending_allocation) | ||
701 | + ret = do_wl_roundtrip(); | ||
702 | + | ||
703 | + return wl_dispmanx_client_buffer; | ||
704 | +} | ||
705 | diff --git a/interface/vmcs_host/vc_vchi_dispmanx.h b/interface/khronos/common/linux/khrn_wayland.h | ||
706 | similarity index 56% | ||
707 | copy from interface/vmcs_host/vc_vchi_dispmanx.h | ||
708 | copy to interface/khronos/common/linux/khrn_wayland.h | ||
709 | index b723b76..b9bf08c 100644 | ||
710 | --- a/interface/vmcs_host/vc_vchi_dispmanx.h | ||
711 | +++ b/interface/khronos/common/linux/khrn_wayland.h | ||
712 | @@ -1,5 +1,5 @@ | ||
713 | /* | ||
714 | -Copyright (c) 2012, Broadcom Europe Ltd | ||
715 | +Copyright (c) 2013, Raspberry Pi Foundation | ||
716 | All rights reserved. | ||
717 | |||
718 | Redistribution and use in source and binary forms, with or without | ||
719 | @@ -25,45 +25,9 @@ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
720 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
721 | */ | ||
722 | |||
723 | -#ifndef VC_VCHI_DISPMANX_H | ||
724 | -#define VC_VCHI_DISPMANX_H | ||
725 | +#include "interface/khronos/common/khrn_client.h" | ||
726 | |||
727 | -#include "interface/peer/vc_vchi_dispmanx_common.h" | ||
728 | +int init_process_wayland(CLIENT_PROCESS_STATE_T *process); | ||
729 | +int do_wl_roundtrip(); | ||
730 | |||
731 | -#define VC_NUM_HOST_RESOURCES 64 | ||
732 | -#define DISPMANX_MSGFIFO_SIZE 1024 | ||
733 | -#define DISPMANX_CLIENT_NAME MAKE_FOURCC("DISP") | ||
734 | -#define DISPMANX_NOTIFY_NAME MAKE_FOURCC("UPDH") | ||
735 | - | ||
736 | -//Or with command to indicate we don't need a response | ||
737 | -#define DISPMANX_NO_REPLY_MASK (1<<31) | ||
738 | - | ||
739 | -typedef struct { | ||
740 | - char description[32]; | ||
741 | - uint32_t width; | ||
742 | - uint32_t height; | ||
743 | - uint32_t aspect_pixwidth; | ||
744 | - uint32_t aspect_pixheight; | ||
745 | - uint32_t fieldrate_num; | ||
746 | - uint32_t fieldrate_denom; | ||
747 | - uint32_t fields_per_frame; | ||
748 | - uint32_t transform; | ||
749 | -} GET_MODES_DATA_T; | ||
750 | - | ||
751 | -typedef struct { | ||
752 | - int32_t response; | ||
753 | - uint32_t width; | ||
754 | - uint32_t height; | ||
755 | - uint32_t transform; | ||
756 | - uint32_t input_format; | ||
757 | -} GET_INFO_DATA_T; | ||
758 | - | ||
759 | -//Attributes changes flag mask | ||
760 | -#define ELEMENT_CHANGE_LAYER (1<<0) | ||
761 | -#define ELEMENT_CHANGE_OPACITY (1<<1) | ||
762 | -#define ELEMENT_CHANGE_DEST_RECT (1<<2) | ||
763 | -#define ELEMENT_CHANGE_SRC_RECT (1<<3) | ||
764 | -#define ELEMENT_CHANGE_MASK_RESOURCE (1<<4) | ||
765 | -#define ELEMENT_CHANGE_TRANSFORM (1<<5) | ||
766 | - | ||
767 | -#endif | ||
768 | +struct wl_dispmanx_client_buffer *allocate_wl_buffer(struct wl_egl_window *window, KHRN_IMAGE_FORMAT_T color); | ||
769 | diff --git a/interface/khronos/egl/egl_client.c b/interface/khronos/egl/egl_client.c | ||
770 | index 234da65..024f3ed 100644 | ||
771 | --- a/interface/khronos/egl/egl_client.c | ||
772 | +++ b/interface/khronos/egl/egl_client.c | ||
773 | @@ -153,6 +153,10 @@ by an attribute value" | ||
774 | #include <stdlib.h> | ||
775 | #include <string.h> | ||
776 | |||
777 | +#ifdef BUILD_WAYLAND | ||
778 | +#include "interface/khronos/wayland-egl/wayland-egl-priv.h" | ||
779 | +#include "interface/khronos/common/linux/khrn_wayland.h" | ||
780 | +#endif | ||
781 | |||
782 | #include "interface/khronos/egl/egl_client_cr.c" | ||
783 | |||
784 | @@ -162,17 +166,6 @@ static void egl_current_release(CLIENT_PROCESS_STATE_T *process, EGL_CURRENT_T * | ||
785 | void egl_gl_flush_callback(bool wait); | ||
786 | void egl_vg_flush_callback(bool wait); | ||
787 | |||
788 | -#include "interface/vmcs_host/vc_dispmanx_types.h" | ||
789 | -/**HACKHACK - give us the ability to inject a DispmanX | ||
790 | - * resource handle into the CreateWindowSurface and | ||
791 | - * SwapBuffers calls */ | ||
792 | -static DISPMANX_RESOURCE_HANDLE_T next_resource_handle; | ||
793 | - | ||
794 | -EGLAPI EGLBoolean EGLAPIENTRY eglSetNextResourceHandle(DISPMANX_RESOURCE_HANDLE_T handle) | ||
795 | -{ | ||
796 | - next_resource_handle = handle; | ||
797 | -} | ||
798 | - | ||
799 | /* | ||
800 | TODO: do an RPC call to make sure the Khronos vll is loaded (and that it stays loaded until eglTerminate) | ||
801 | Also affects global image (and possibly others?) | ||
802 | @@ -451,6 +444,9 @@ EGLAPI const char EGLAPIENTRY * eglQueryString(EGLDisplay dpy, EGLint name) | ||
803 | "EGL_KHR_fence_sync " | ||
804 | #endif | ||
805 | #endif | ||
806 | +#if EGL_WL_bind_wayland_display | ||
807 | + "EGL_WL_bind_wayland_display " | ||
808 | +#endif | ||
809 | ; | ||
810 | break; | ||
811 | case EGL_VENDOR: | ||
812 | @@ -655,8 +651,7 @@ EGLAPI EGLSurface EGLAPIENTRY eglCreateWindowSurface(EGLDisplay dpy, EGLConfig c | ||
813 | false, | ||
814 | EGL_NO_TEXTURE, | ||
815 | EGL_NO_TEXTURE, | ||
816 | - 0, 0, | ||
817 | - next_resource_handle); | ||
818 | + 0, 0); | ||
819 | |||
820 | if (surface) { | ||
821 | if (khrn_pointer_map_insert(&process->surfaces, process->next_surface, surface)) { | ||
822 | @@ -901,7 +896,7 @@ EGLAPI EGLSurface EGLAPIENTRY eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig | ||
823 | mipmap_texture, | ||
824 | texture_format, | ||
825 | texture_target, | ||
826 | - 0, 0, 0); | ||
827 | + 0, 0); | ||
828 | |||
829 | if (surface) { | ||
830 | if (khrn_pointer_map_insert(&process->surfaces, process->next_surface, surface)) { | ||
831 | @@ -1043,7 +1038,7 @@ EGLAPI EGLSurface EGLAPIENTRY eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig c | ||
832 | false, | ||
833 | EGL_NO_TEXTURE, | ||
834 | EGL_NO_TEXTURE, | ||
835 | - pixmap, ((server_handle[0] == 0) && (server_handle[1] == (uint32_t)(-1))) ? NULL : server_handle, 0); | ||
836 | + pixmap, ((server_handle[0] == 0) && (server_handle[1] == (uint32_t)(-1))) ? NULL : server_handle); | ||
837 | |||
838 | if (surface) { | ||
839 | if (khrn_pointer_map_insert(&process->surfaces, process->next_surface, surface)) { | ||
840 | @@ -2245,6 +2240,9 @@ EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffers(EGLDisplay dpy, EGLSurface surf) | ||
841 | CLIENT_THREAD_STATE_T *thread; | ||
842 | CLIENT_PROCESS_STATE_T *process; | ||
843 | EGLBoolean result; | ||
844 | +#ifdef BUILD_WAYLAND | ||
845 | + struct wl_display *wl_display = khrn_platform_get_wl_display(); | ||
846 | +#endif | ||
847 | |||
848 | vcos_log_trace("eglSwapBuffers start. dpy=%d. surf=%d.", (int)dpy, (int)surf); | ||
849 | |||
850 | @@ -2315,18 +2313,58 @@ EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffers(EGLDisplay dpy, EGLSurface surf) | ||
851 | |||
852 | vcos_log_trace("eglSwapBuffers server call"); | ||
853 | |||
854 | - if (next_resource_handle) | ||
855 | - RPC_CALL7(eglIntSwapBuffers_impl, | ||
856 | - thread, | ||
857 | - EGLINTSWAPBUFFERS_ID_V2, | ||
858 | - RPC_UINT(surface->serverbuffer), | ||
859 | - RPC_UINT(surface->width), | ||
860 | - RPC_UINT(surface->height), | ||
861 | - RPC_UINT(surface->internal_handle), | ||
862 | - RPC_UINT(surface->swap_behavior == EGL_BUFFER_PRESERVED ? 1 : 0), | ||
863 | - RPC_UINT(khrn_platform_get_window_position(surface->win)), | ||
864 | - RPC_INT(next_resource_handle)); | ||
865 | - else | ||
866 | +#ifdef BUILD_WAYLAND | ||
867 | + if (wl_display) { | ||
868 | + struct wl_egl_window *wl_egl_window = surface->wl_egl_window; | ||
869 | + struct wl_dispmanx_client_buffer *buffer_temp; | ||
870 | + uint32_t configid; | ||
871 | + KHRN_IMAGE_FORMAT_T color; | ||
872 | + int ret = 0; | ||
873 | + | ||
874 | + buffer_temp = surface->front_wl_buffer; | ||
875 | + surface->front_wl_buffer = surface->back_wl_buffer; | ||
876 | + surface->back_wl_buffer = buffer_temp; | ||
877 | + | ||
878 | + configid = egl_config_to_id(surface->config); | ||
879 | + color = egl_config_get_color_format(configid); | ||
880 | + | ||
881 | + if (surface->back_wl_buffer == NULL) | ||
882 | + surface->back_wl_buffer = allocate_wl_buffer(wl_egl_window, color); | ||
883 | + else if (surface->back_wl_buffer->width != width || | ||
884 | + surface->back_wl_buffer->height != height) { | ||
885 | + | ||
886 | + struct wl_dispmanx_client_buffer *buffer; | ||
887 | + | ||
888 | + wl_buffer_destroy(surface->back_wl_buffer->wl_buffer); | ||
889 | + free(surface->back_wl_buffer); | ||
890 | + | ||
891 | + buffer = allocate_wl_buffer(wl_egl_window, color); | ||
892 | + surface->back_wl_buffer = buffer; | ||
893 | + } | ||
894 | + | ||
895 | + RPC_CALL7(eglIntSwapBuffers_impl, | ||
896 | + thread, | ||
897 | + EGLINTSWAPBUFFERS_ID_V2, | ||
898 | + RPC_UINT(surface->serverbuffer), | ||
899 | + RPC_UINT(surface->width), | ||
900 | + RPC_UINT(surface->height), | ||
901 | + RPC_UINT(surface->internal_handle), | ||
902 | + RPC_UINT(surface->swap_behavior == EGL_BUFFER_PRESERVED ? 1 : 0), | ||
903 | + RPC_UINT(khrn_platform_get_window_position(surface->win)), | ||
904 | + RPC_INT(surface->back_wl_buffer->resource)); | ||
905 | + | ||
906 | + surface->front_wl_buffer->in_use = 1; | ||
907 | + wl_surface_attach(wl_egl_window->wl_surface, | ||
908 | + surface->front_wl_buffer->wl_buffer, | ||
909 | + 0, 0); | ||
910 | + wl_surface_damage(wl_egl_window->wl_surface, 0, 0, | ||
911 | + surface->width, surface->height); | ||
912 | + wl_surface_commit(wl_egl_window->wl_surface); | ||
913 | + | ||
914 | + while(ret != -1 && surface->back_wl_buffer->in_use) | ||
915 | + ret = wl_display_dispatch_queue(wl_display, process->wl_queue); | ||
916 | + } else | ||
917 | +#endif | ||
918 | RPC_CALL6(eglIntSwapBuffers_impl, | ||
919 | thread, | ||
920 | EGLINTSWAPBUFFERS_ID, | ||
921 | diff --git a/interface/khronos/egl/egl_client_get_proc.c b/interface/khronos/egl/egl_client_get_proc.c | ||
922 | index 4cfa9ff..6a715af 100644 | ||
923 | --- a/interface/khronos/egl/egl_client_get_proc.c | ||
924 | +++ b/interface/khronos/egl/egl_client_get_proc.c | ||
925 | @@ -254,6 +254,17 @@ EGLAPI void EGLAPIENTRY (* eglGetProcAddress(const char *procname))(void) | ||
926 | return (void(*)(void))eglQueryGlobalImageBRCM; | ||
927 | #endif | ||
928 | |||
929 | +#ifdef BUILD_WAYLAND | ||
930 | +#if EGL_WL_bind_wayland_display | ||
931 | + if (!strcmp(procname, "eglBindWaylandDisplayWL")) | ||
932 | + return (void(*)(void))eglBindWaylandDisplayWL; | ||
933 | + if (!strcmp(procname, "eglUnbindWaylandDisplayWL")) | ||
934 | + return (void(*)(void))eglUnbindWaylandDisplayWL; | ||
935 | + if (!strcmp(procname, "eglQueryWaylandBufferWL")) | ||
936 | + return (void(*)(void))eglQueryWaylandBufferWL; | ||
937 | +#endif | ||
938 | +#endif | ||
939 | + | ||
940 | return (void(*)(void)) NULL; | ||
941 | } | ||
942 | |||
943 | diff --git a/interface/khronos/egl/egl_client_surface.c b/interface/khronos/egl/egl_client_surface.c | ||
944 | index 0dc10e2..49cf7e5 100644 | ||
945 | --- a/interface/khronos/egl/egl_client_surface.c | ||
946 | +++ b/interface/khronos/egl/egl_client_surface.c | ||
947 | @@ -46,6 +46,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
948 | #include "interface/khronos/egl/egl_int_impl.h" | ||
949 | #endif | ||
950 | |||
951 | +#ifdef BUILD_WAYLAND | ||
952 | +#include "interface/khronos/wayland-egl/wayland-egl-priv.h" | ||
953 | +#include "interface/khronos/common/linux/khrn_wayland.h" | ||
954 | +#endif | ||
955 | + | ||
956 | #include <stdlib.h> | ||
957 | |||
958 | |||
959 | @@ -314,8 +319,7 @@ EGL_SURFACE_T *egl_surface_create( | ||
960 | EGLenum texture_format, | ||
961 | EGLenum texture_target, | ||
962 | EGLNativePixmapType pixmap, | ||
963 | - const uint32_t *pixmap_server_handle, | ||
964 | - DISPMANX_RESOURCE_HANDLE_T next_resource_handle) | ||
965 | + const uint32_t *pixmap_server_handle) | ||
966 | { | ||
967 | KHRN_IMAGE_FORMAT_T color; | ||
968 | KHRN_IMAGE_FORMAT_T depth; | ||
969 | @@ -326,6 +330,10 @@ EGL_SURFACE_T *egl_surface_create( | ||
970 | EGLint config_depth_bits; | ||
971 | EGLint config_stencil_bits; | ||
972 | CLIENT_THREAD_STATE_T *thread = CLIENT_GET_THREAD_STATE(); | ||
973 | +#ifdef BUILD_WAYLAND | ||
974 | + struct wl_display *wl_display = khrn_platform_get_wl_display(); | ||
975 | + DISPMANX_RESOURCE_HANDLE_T resource; | ||
976 | +#endif | ||
977 | |||
978 | EGL_SURFACE_T *surface = egl_surface_pool_alloc(); | ||
979 | |||
980 | @@ -390,6 +398,18 @@ EGL_SURFACE_T *egl_surface_create( | ||
981 | |||
982 | vcos_assert(color != IMAGE_FORMAT_INVALID); | ||
983 | |||
984 | +#ifdef BUILD_WAYLAND | ||
985 | + if (type == WINDOW && wl_display) { | ||
986 | + surface->wl_egl_window = (struct wl_egl_window*)win; | ||
987 | + surface->back_wl_buffer = allocate_wl_buffer( | ||
988 | + surface->wl_egl_window, color); | ||
989 | + resource = surface->back_wl_buffer->resource; | ||
990 | + } else { | ||
991 | + surface->wl_egl_window = NULL; | ||
992 | + resource = DISPMANX_NO_HANDLE; | ||
993 | + } | ||
994 | +#endif | ||
995 | + | ||
996 | #ifdef KHRONOS_EGL_PLATFORM_OPENWFC | ||
997 | // Create stream for this window | ||
998 | if(type != PBUFFER) | ||
999 | @@ -474,7 +494,8 @@ EGL_SURFACE_T *egl_surface_create( | ||
1000 | #endif | ||
1001 | uint32_t results[3]; | ||
1002 | |||
1003 | - if (next_resource_handle) | ||
1004 | +#ifdef BUILD_WAYLAND | ||
1005 | + if (resource != DISPMANX_NO_HANDLE) | ||
1006 | RPC_CALL16_OUT_CTRL(eglIntCreateSurface_impl, | ||
1007 | thread, | ||
1008 | EGLINTCREATESURFACE_ID_V2, | ||
1009 | @@ -492,9 +513,10 @@ EGL_SURFACE_T *egl_surface_create( | ||
1010 | RPC_UINT(config_stencil_bits), | ||
1011 | RPC_UINT(sem_name), | ||
1012 | RPC_UINT(type), | ||
1013 | - RPC_INT(next_resource_handle), | ||
1014 | + RPC_INT(resource), | ||
1015 | results); | ||
1016 | else | ||
1017 | +#endif | ||
1018 | RPC_CALL15_OUT_CTRL(eglIntCreateSurface_impl, | ||
1019 | thread, | ||
1020 | EGLINTCREATESURFACE_ID, | ||
1021 | @@ -663,6 +685,18 @@ void egl_surface_free(EGL_SURFACE_T *surface) | ||
1022 | if( surface->type == WINDOW ) { | ||
1023 | vcos_log_trace("egl_surface_free: calling platform_destroy_winhandle..."); | ||
1024 | platform_destroy_winhandle( surface->win, surface->internal_handle ); | ||
1025 | + | ||
1026 | +#ifdef BUILD_WAYLAND | ||
1027 | + if (surface->back_wl_buffer) { | ||
1028 | + wl_buffer_destroy(surface->back_wl_buffer->wl_buffer); | ||
1029 | + free(surface->back_wl_buffer); | ||
1030 | + } | ||
1031 | + | ||
1032 | + if (surface->front_wl_buffer) { | ||
1033 | + wl_buffer_destroy(surface->front_wl_buffer->wl_buffer); | ||
1034 | + free(surface->front_wl_buffer); | ||
1035 | + } | ||
1036 | +#endif | ||
1037 | } | ||
1038 | /* return value ignored -- read performed to ensure blocking. we want this to | ||
1039 | * block so clients can safely destroy the surface's window as soon as the | ||
1040 | diff --git a/interface/khronos/egl/egl_client_surface.h b/interface/khronos/egl/egl_client_surface.h | ||
1041 | index b5bf70a..e328b77 100644 | ||
1042 | --- a/interface/khronos/egl/egl_client_surface.h | ||
1043 | +++ b/interface/khronos/egl/egl_client_surface.h | ||
1044 | @@ -288,6 +288,41 @@ typedef struct { | ||
1045 | type == PIXMAP | ||
1046 | */ | ||
1047 | bool server_owned; | ||
1048 | + | ||
1049 | +#ifdef BUILD_WAYLAND | ||
1050 | + /* | ||
1051 | + wl_egl_window | ||
1052 | + | ||
1053 | + Validity: | ||
1054 | + type == WINDOW | ||
1055 | + | ||
1056 | + Invariant: | ||
1057 | + wayland EGL window | ||
1058 | + */ | ||
1059 | + struct wl_egl_window *wl_egl_window; | ||
1060 | + | ||
1061 | + /* | ||
1062 | + front_wl_buffer | ||
1063 | + | ||
1064 | + Validity: | ||
1065 | + type == WINDOW | ||
1066 | + | ||
1067 | + Invariant: | ||
1068 | + client-side information about the wl_buffer in the front | ||
1069 | + */ | ||
1070 | + struct wl_dispmanx_client_buffer *front_wl_buffer; | ||
1071 | + | ||
1072 | + /* | ||
1073 | + back_wl_buffer | ||
1074 | + | ||
1075 | + Validity: | ||
1076 | + type == WINDOW | ||
1077 | + | ||
1078 | + Invariant: | ||
1079 | + client-side information about the wl_buffer in the back | ||
1080 | + */ | ||
1081 | + struct wl_dispmanx_client_buffer *back_wl_buffer; | ||
1082 | +#endif | ||
1083 | } EGL_SURFACE_T; | ||
1084 | |||
1085 | extern bool egl_surface_check_attribs( | ||
1086 | @@ -322,8 +357,7 @@ extern EGL_SURFACE_T *egl_surface_create( | ||
1087 | EGLenum texture_format, | ||
1088 | EGLenum texture_target, | ||
1089 | EGLNativePixmapType pixmap, | ||
1090 | - const uint32_t *pixmap_server_handle, | ||
1091 | - DISPMANX_RESOURCE_HANDLE_T next_resource_handle); | ||
1092 | + const uint32_t *pixmap_server_handle); | ||
1093 | extern EGL_SURFACE_T *egl_surface_from_vg_image( | ||
1094 | VGImage vg_handle, | ||
1095 | EGLSurface name, | ||
1096 | diff --git a/interface/khronos/egl/egl_int_impl.h b/interface/khronos/egl/egl_int_impl.h | ||
1097 | index 51b3580..6863a3b 100644 | ||
1098 | --- a/interface/khronos/egl/egl_int_impl.h | ||
1099 | +++ b/interface/khronos/egl/egl_int_impl.h | ||
1100 | @@ -57,7 +57,7 @@ FN(int, eglIntCreateSurface_impl, ( | ||
1101 | uint32_t sem, | ||
1102 | uint32_t type, | ||
1103 | uint32_t *results, | ||
1104 | - DISPMANX_RESOURCE_HANDLE_T next_resource_handle)) | ||
1105 | + DISPMANX_RESOURCE_HANDLE_T resource_handle)) | ||
1106 | |||
1107 | FN(int, eglIntCreatePbufferFromVGImage_impl, ( | ||
1108 | VGImage vg_handle, | ||
1109 | diff --git a/interface/khronos/ext/egl_wayland.c b/interface/khronos/ext/egl_wayland.c | ||
1110 | new file mode 100644 | ||
1111 | index 0000000..5730743 | ||
1112 | --- /dev/null | ||
1113 | +++ b/interface/khronos/ext/egl_wayland.c | ||
1114 | @@ -0,0 +1,246 @@ | ||
1115 | +/* | ||
1116 | +Copyright (c) 2013, Raspberry Pi Foundation | ||
1117 | +All rights reserved. | ||
1118 | + | ||
1119 | +Redistribution and use in source and binary forms, with or without | ||
1120 | +modification, are permitted provided that the following conditions are met: | ||
1121 | + * Redistributions of source code must retain the above copyright | ||
1122 | + notice, this list of conditions and the following disclaimer. | ||
1123 | + * Redistributions in binary form must reproduce the above copyright | ||
1124 | + notice, this list of conditions and the following disclaimer in the | ||
1125 | + documentation and/or other materials provided with the distribution. | ||
1126 | + * Neither the name of the copyright holder nor the | ||
1127 | + names of its contributors may be used to endorse or promote products | ||
1128 | + derived from this software without specific prior written permission. | ||
1129 | + | ||
1130 | +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | ||
1131 | +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
1132 | +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
1133 | +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY | ||
1134 | +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
1135 | +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
1136 | +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
1137 | +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
1138 | +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
1139 | +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
1140 | +*/ | ||
1141 | + | ||
1142 | +#include "interface/khronos/common/khrn_client_mangle.h" | ||
1143 | +#include "interface/khronos/common/khrn_client_rpc.h" | ||
1144 | + | ||
1145 | +#include "interface/khronos/ext/egl_khr_sync_client.h" | ||
1146 | +#include "interface/khronos/include/EGL/egl.h" | ||
1147 | +#include "interface/khronos/include/EGL/eglext.h" | ||
1148 | + | ||
1149 | +#include "interface/vmcs_host/vc_vchi_dispmanx.h" | ||
1150 | + | ||
1151 | +#include <wayland-server.h> | ||
1152 | +#include "interface/khronos/wayland-dispmanx-server-protocol.h" | ||
1153 | + | ||
1154 | +static void | ||
1155 | +destroy_buffer(struct wl_resource *resource) | ||
1156 | +{ | ||
1157 | + struct wl_dispmanx_server_buffer *buffer = wl_resource_get_user_data(resource); | ||
1158 | + | ||
1159 | + if(!buffer->in_use) | ||
1160 | + vc_dispmanx_resource_delete(buffer->handle); | ||
1161 | + | ||
1162 | + free(buffer); | ||
1163 | +} | ||
1164 | + | ||
1165 | +static void | ||
1166 | +buffer_destroy(struct wl_client *client, struct wl_resource *resource) | ||
1167 | +{ | ||
1168 | + wl_resource_destroy(resource); | ||
1169 | +} | ||
1170 | + | ||
1171 | +static const struct wl_buffer_interface dispmanx_buffer_interface = { | ||
1172 | + buffer_destroy | ||
1173 | +}; | ||
1174 | + | ||
1175 | +static VC_IMAGE_TYPE_T | ||
1176 | +get_vc_format(enum wl_dispmanx_format format) | ||
1177 | +{ | ||
1178 | + /* XXX: The app is likely to have been premultiplying in its shaders, | ||
1179 | + * but the VC scanout hardware on the RPi cannot mix premultiplied alpha | ||
1180 | + * channel with the element's alpha. | ||
1181 | + */ | ||
1182 | + switch (format) { | ||
1183 | + case WL_DISPMANX_FORMAT_ABGR8888: | ||
1184 | + return VC_IMAGE_RGBA32; | ||
1185 | + case WL_DISPMANX_FORMAT_XBGR8888: | ||
1186 | + return VC_IMAGE_BGRX8888; | ||
1187 | + case WL_DISPMANX_FORMAT_RGB565: | ||
1188 | + return VC_IMAGE_RGB565; | ||
1189 | + default: | ||
1190 | + /* invalid format */ | ||
1191 | + return VC_IMAGE_MIN; | ||
1192 | + } | ||
1193 | +} | ||
1194 | + | ||
1195 | +static void | ||
1196 | +dispmanx_create_buffer(struct wl_client *client, struct wl_resource *resource, | ||
1197 | + uint32_t id, int32_t width, int32_t height, | ||
1198 | + uint32_t stride, uint32_t buffer_height, uint32_t format) | ||
1199 | +{ | ||
1200 | + struct wl_dispmanx_server_buffer *buffer; | ||
1201 | + VC_IMAGE_TYPE_T vc_format = get_vc_format(format); | ||
1202 | + uint32_t dummy; | ||
1203 | + | ||
1204 | + if(vc_format == VC_IMAGE_MIN) { | ||
1205 | + wl_resource_post_error(resource, | ||
1206 | + WL_DISPMANX_ERROR_INVALID_FORMAT, | ||
1207 | + "invalid format"); | ||
1208 | + return; | ||
1209 | + } | ||
1210 | + | ||
1211 | + buffer = calloc(1, sizeof *buffer); | ||
1212 | + if (buffer == NULL) { | ||
1213 | + wl_resource_post_no_memory(resource); | ||
1214 | + return; | ||
1215 | + } | ||
1216 | + | ||
1217 | + buffer->handle = vc_dispmanx_resource_create(vc_format, | ||
1218 | + width | (stride << 16), | ||
1219 | + height | (buffer_height << 16), | ||
1220 | + &dummy); | ||
1221 | + if(buffer->handle == DISPMANX_NO_HANDLE) { | ||
1222 | + wl_resource_post_error(resource, | ||
1223 | + WL_DISPMANX_ERROR_ALLOC_FAILED, | ||
1224 | + "allocation failed"); | ||
1225 | + free(buffer); | ||
1226 | + return; | ||
1227 | + } | ||
1228 | + | ||
1229 | + buffer->width = width; | ||
1230 | + buffer->height = height; | ||
1231 | + buffer->format = format; | ||
1232 | + | ||
1233 | + buffer->resource = wl_resource_create(resource->client, &wl_buffer_interface, | ||
1234 | + 1, id); | ||
1235 | + if (!buffer->resource) { | ||
1236 | + wl_resource_post_no_memory(resource); | ||
1237 | + vc_dispmanx_resource_delete(buffer->handle); | ||
1238 | + free(buffer); | ||
1239 | + return; | ||
1240 | + } | ||
1241 | + | ||
1242 | + wl_resource_set_implementation(buffer->resource, | ||
1243 | + (void (**)(void)) &dispmanx_buffer_interface, | ||
1244 | + buffer, destroy_buffer); | ||
1245 | + | ||
1246 | + wl_dispmanx_send_buffer_allocated(resource, buffer->resource, | ||
1247 | + buffer->handle); | ||
1248 | +} | ||
1249 | + | ||
1250 | +static const struct wl_dispmanx_interface dispmanx_interface = { | ||
1251 | + dispmanx_create_buffer, | ||
1252 | +}; | ||
1253 | + | ||
1254 | +static void | ||
1255 | +bind_dispmanx(struct wl_client *client, void *data, uint32_t version, uint32_t id) | ||
1256 | +{ | ||
1257 | + struct wl_resource *resource; | ||
1258 | + | ||
1259 | + resource = wl_resource_create(client, &wl_dispmanx_interface, 1, id); | ||
1260 | + wl_resource_set_implementation(resource, &dispmanx_interface, NULL, NULL); | ||
1261 | + | ||
1262 | + wl_resource_post_event(resource, WL_DISPMANX_FORMAT, | ||
1263 | + WL_DISPMANX_FORMAT_ARGB8888); | ||
1264 | + | ||
1265 | + wl_resource_post_event(resource, WL_DISPMANX_FORMAT, | ||
1266 | + WL_DISPMANX_FORMAT_XRGB8888); | ||
1267 | + | ||
1268 | + wl_resource_post_event(resource, WL_DISPMANX_FORMAT, | ||
1269 | + WL_DISPMANX_FORMAT_ABGR8888); | ||
1270 | + | ||
1271 | + wl_resource_post_event(resource, WL_DISPMANX_FORMAT, | ||
1272 | + WL_DISPMANX_FORMAT_XBGR8888); | ||
1273 | + | ||
1274 | + wl_resource_post_event(resource, WL_DISPMANX_FORMAT, | ||
1275 | + WL_DISPMANX_FORMAT_RGB565); | ||
1276 | +} | ||
1277 | + | ||
1278 | +EGLBoolean EGLAPIENTRY | ||
1279 | +eglBindWaylandDisplayWL(EGLDisplay dpy, struct wl_display *display) | ||
1280 | +{ | ||
1281 | + CLIENT_THREAD_STATE_T *thread; | ||
1282 | + CLIENT_PROCESS_STATE_T *process; | ||
1283 | + | ||
1284 | + if (!CLIENT_LOCK_AND_GET_STATES(dpy, &thread, &process)) | ||
1285 | + return EGL_FALSE; | ||
1286 | + | ||
1287 | + if (process->wl_global != NULL) | ||
1288 | + goto error; | ||
1289 | + | ||
1290 | + process->wl_global = wl_global_create(display, &wl_dispmanx_interface, 1, | ||
1291 | + NULL, bind_dispmanx); | ||
1292 | + if (process->wl_global == NULL) | ||
1293 | + goto error; | ||
1294 | + | ||
1295 | + return EGL_TRUE; | ||
1296 | + | ||
1297 | +error: | ||
1298 | + CLIENT_UNLOCK(); | ||
1299 | + return EGL_FALSE; | ||
1300 | +} | ||
1301 | + | ||
1302 | +EGLBoolean EGLAPIENTRY | ||
1303 | +eglUnbindWaylandDisplayWL(EGLDisplay dpy, struct wl_display *display) | ||
1304 | +{ | ||
1305 | + CLIENT_THREAD_STATE_T *thread; | ||
1306 | + CLIENT_PROCESS_STATE_T *process; | ||
1307 | + | ||
1308 | + if (!CLIENT_LOCK_AND_GET_STATES(dpy, &thread, &process)) | ||
1309 | + return EGL_FALSE; | ||
1310 | + | ||
1311 | + wl_global_destroy(process->wl_global); | ||
1312 | + process->wl_global = NULL; | ||
1313 | + | ||
1314 | + CLIENT_UNLOCK(); | ||
1315 | + | ||
1316 | + return EGL_TRUE; | ||
1317 | +} | ||
1318 | + | ||
1319 | +static int | ||
1320 | +get_egl_format(enum wl_dispmanx_format format) | ||
1321 | +{ | ||
1322 | + switch (format) { | ||
1323 | + case WL_DISPMANX_FORMAT_ABGR8888: | ||
1324 | + return EGL_TEXTURE_RGBA; | ||
1325 | + case WL_DISPMANX_FORMAT_XBGR8888: | ||
1326 | + return EGL_TEXTURE_RGB; | ||
1327 | + case WL_DISPMANX_FORMAT_RGB565: | ||
1328 | + return EGL_TEXTURE_RGB; | ||
1329 | + default: | ||
1330 | + /* invalid format */ | ||
1331 | + return EGL_NO_TEXTURE; | ||
1332 | + } | ||
1333 | +} | ||
1334 | + | ||
1335 | +EGLBoolean EGLAPIENTRY | ||
1336 | +eglQueryWaylandBufferWL(EGLDisplay dpy, struct wl_resource *_buffer, | ||
1337 | + EGLint attribute, EGLint *value) | ||
1338 | +{ | ||
1339 | + struct wl_dispmanx_server_buffer *buffer = wl_resource_get_user_data(_buffer); | ||
1340 | + | ||
1341 | + if (wl_resource_instance_of(_buffer, &wl_dispmanx_interface, | ||
1342 | + &dispmanx_buffer_interface)) | ||
1343 | + return EGL_FALSE; | ||
1344 | + | ||
1345 | + switch (attribute) { | ||
1346 | + case EGL_TEXTURE_FORMAT: | ||
1347 | + *value = get_egl_format(buffer->format); | ||
1348 | + if (*value == EGL_NO_TEXTURE) | ||
1349 | + return EGL_FALSE; | ||
1350 | + return EGL_TRUE; | ||
1351 | + case EGL_WIDTH: | ||
1352 | + *value = buffer->width; | ||
1353 | + return EGL_TRUE; | ||
1354 | + case EGL_HEIGHT: | ||
1355 | + *value = buffer->height; | ||
1356 | + return EGL_TRUE; | ||
1357 | + } | ||
1358 | + | ||
1359 | + return EGL_FALSE; | ||
1360 | +} | ||
1361 | diff --git a/interface/khronos/include/EGL/eglext.h b/interface/khronos/include/EGL/eglext.h | ||
1362 | index 89a3369..d7e5ba7 100755 | ||
1363 | --- a/interface/khronos/include/EGL/eglext.h | ||
1364 | +++ b/interface/khronos/include/EGL/eglext.h | ||
1365 | @@ -191,6 +191,29 @@ typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETSYNCATTRIBKHRPROC) (EGLDisplay dpy, EG | ||
1366 | #endif | ||
1367 | |||
1368 | |||
1369 | +#ifndef EGL_WL_bind_wayland_display | ||
1370 | +#define EGL_WL_bind_wayland_display 1 | ||
1371 | + | ||
1372 | +#define EGL_WAYLAND_BUFFER_WL 0x31D5 /* eglCreateImageKHR target */ | ||
1373 | +#define EGL_WAYLAND_PLANE_WL 0x31D6 /* eglCreateImageKHR target */ | ||
1374 | +#define EGL_TEXTURE_Y_U_V_WL 0x31D7 | ||
1375 | +#define EGL_TEXTURE_Y_UV_WL 0x31D8 | ||
1376 | +#define EGL_TEXTURE_Y_XUXV_WL 0x31D9 | ||
1377 | + | ||
1378 | +struct wl_display; | ||
1379 | +struct wl_resource; | ||
1380 | +#ifdef EGL_EGLEXT_PROTOTYPES | ||
1381 | +EGLAPI EGLBoolean EGLAPIENTRY eglBindWaylandDisplayWL(EGLDisplay dpy, struct wl_display *display); | ||
1382 | +EGLAPI EGLBoolean EGLAPIENTRY eglUnbindWaylandDisplayWL(EGLDisplay dpy, struct wl_display *display); | ||
1383 | +EGLAPI EGLBoolean EGLAPIENTRY eglQueryWaylandBufferWL(EGLDisplay dpy, struct wl_resource *buffer, EGLint attribute, EGLint *value); | ||
1384 | +#endif | ||
1385 | +typedef EGLBoolean (EGLAPIENTRYP PFNEGLBINDWAYLANDDISPLAYWL) (EGLDisplay dpy, struct wl_display *display); | ||
1386 | +typedef EGLBoolean (EGLAPIENTRYP PFNEGLUNBINDWAYLANDDISPLAYWL) (EGLDisplay dpy, struct wl_display *display); | ||
1387 | +typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYWAYLANDBUFFERWL) (EGLDisplay dpy, struct wl_resource *buffer, EGLint attribute, EGLint *value); | ||
1388 | + | ||
1389 | +#endif | ||
1390 | + | ||
1391 | + | ||
1392 | #ifdef __cplusplus | ||
1393 | } | ||
1394 | #endif | ||
1395 | diff --git a/interface/khronos/wayland-egl/wayland-egl-priv.h b/interface/khronos/wayland-egl/wayland-egl-priv.h | ||
1396 | new file mode 100644 | ||
1397 | index 0000000..8e38d36 | ||
1398 | --- /dev/null | ||
1399 | +++ b/interface/khronos/wayland-egl/wayland-egl-priv.h | ||
1400 | @@ -0,0 +1,53 @@ | ||
1401 | +/* Copied from Mesa */ | ||
1402 | + | ||
1403 | +#ifndef _WAYLAND_EGL_PRIV_H | ||
1404 | +#define _WAYLAND_EGL_PRIV_H | ||
1405 | + | ||
1406 | +#ifdef __cplusplus | ||
1407 | +extern "C" { | ||
1408 | +#endif | ||
1409 | + | ||
1410 | +/* GCC visibility */ | ||
1411 | +#if defined(__GNUC__) && __GNUC__ >= 4 | ||
1412 | +#define WL_EGL_EXPORT __attribute__ ((visibility("default"))) | ||
1413 | +#else | ||
1414 | +#define WL_EGL_EXPORT | ||
1415 | +#endif | ||
1416 | + | ||
1417 | +#include "interface/vmcs_host/vc_dispmanx.h" | ||
1418 | +#include "interface/khronos/egl/egl_client_surface.h" | ||
1419 | + | ||
1420 | +#include <wayland-client.h> | ||
1421 | + | ||
1422 | +struct wl_dispmanx_client_buffer { | ||
1423 | + struct wl_buffer *wl_buffer; | ||
1424 | + DISPMANX_RESOURCE_HANDLE_T resource; | ||
1425 | + | ||
1426 | + int pending_allocation; | ||
1427 | + int in_use; | ||
1428 | + int width; | ||
1429 | + int height; | ||
1430 | +}; | ||
1431 | + | ||
1432 | +struct wl_egl_window { | ||
1433 | + struct wl_surface *wl_surface; | ||
1434 | + | ||
1435 | + int width; | ||
1436 | + int height; | ||
1437 | + int dx; | ||
1438 | + int dy; | ||
1439 | + | ||
1440 | + int attached_width; | ||
1441 | + int attached_height; | ||
1442 | + | ||
1443 | + /* XXX: The VC side seems to expect a valid element handle to be | ||
1444 | + passed to eglIntCreateSurface_impl and/or eglIntSwapBuffers_impl, | ||
1445 | + even for host-managed surfaces. */ | ||
1446 | + DISPMANX_ELEMENT_HANDLE_T dummy_element; | ||
1447 | +}; | ||
1448 | + | ||
1449 | +#ifdef __cplusplus | ||
1450 | +} | ||
1451 | +#endif | ||
1452 | + | ||
1453 | +#endif | ||
1454 | diff --git a/interface/khronos/wayland-egl/wayland-egl.c b/interface/khronos/wayland-egl/wayland-egl.c | ||
1455 | new file mode 100644 | ||
1456 | index 0000000..b8f050b | ||
1457 | --- /dev/null | ||
1458 | +++ b/interface/khronos/wayland-egl/wayland-egl.c | ||
1459 | @@ -0,0 +1,59 @@ | ||
1460 | +/* Copied from Mesa */ | ||
1461 | + | ||
1462 | +#include <stdlib.h> | ||
1463 | + | ||
1464 | +#include <wayland-client.h> | ||
1465 | +#include <wayland-egl.h> | ||
1466 | +#include "wayland-egl-priv.h" | ||
1467 | + | ||
1468 | +WL_EGL_EXPORT void | ||
1469 | +wl_egl_window_resize(struct wl_egl_window *egl_window, | ||
1470 | + int width, int height, | ||
1471 | + int dx, int dy) | ||
1472 | +{ | ||
1473 | + if (egl_window->width == width && | ||
1474 | + egl_window->height == height && | ||
1475 | + egl_window->dx == dx && | ||
1476 | + egl_window->dy == dy) | ||
1477 | + return; | ||
1478 | + | ||
1479 | + egl_window->width = width; | ||
1480 | + egl_window->height = height; | ||
1481 | + egl_window->dx = dx; | ||
1482 | + egl_window->dy = dy; | ||
1483 | +} | ||
1484 | + | ||
1485 | +WL_EGL_EXPORT struct wl_egl_window * | ||
1486 | +wl_egl_window_create(struct wl_surface *surface, | ||
1487 | + int width, int height) | ||
1488 | +{ | ||
1489 | + struct wl_egl_window *egl_window; | ||
1490 | + | ||
1491 | + egl_window = calloc(1, sizeof *egl_window); | ||
1492 | + if (!egl_window) | ||
1493 | + return NULL; | ||
1494 | + | ||
1495 | + egl_window->wl_surface = surface; | ||
1496 | + wl_egl_window_resize(egl_window, width, height, 0, 0); | ||
1497 | + egl_window->attached_width = 0; | ||
1498 | + egl_window->attached_height = 0; | ||
1499 | + egl_window->dummy_element = PLATFORM_WIN_NONE; | ||
1500 | + | ||
1501 | + return egl_window; | ||
1502 | +} | ||
1503 | + | ||
1504 | +WL_EGL_EXPORT void | ||
1505 | +wl_egl_window_destroy(struct wl_egl_window *egl_window) | ||
1506 | +{ | ||
1507 | + free(egl_window); | ||
1508 | +} | ||
1509 | + | ||
1510 | +WL_EGL_EXPORT void | ||
1511 | +wl_egl_window_get_attached_size(struct wl_egl_window *egl_window, | ||
1512 | + int *width, int *height) | ||
1513 | +{ | ||
1514 | + if (width) | ||
1515 | + *width = egl_window->attached_width; | ||
1516 | + if (height) | ||
1517 | + *height = egl_window->attached_height; | ||
1518 | +} | ||
1519 | diff --git a/interface/khronos/wayland-egl/wayland-egl.pc.in b/interface/khronos/wayland-egl/wayland-egl.pc.in | ||
1520 | new file mode 100644 | ||
1521 | index 0000000..8bafc15 | ||
1522 | --- /dev/null | ||
1523 | +++ b/interface/khronos/wayland-egl/wayland-egl.pc.in | ||
1524 | @@ -0,0 +1,10 @@ | ||
1525 | +prefix=@CMAKE_INSTALL_PREFIX@ | ||
1526 | +exec_prefix=${prefix} | ||
1527 | +libdir=${exec_prefix}/lib | ||
1528 | +includedir=${prefix}/include | ||
1529 | + | ||
1530 | +Name: wayland-egl | ||
1531 | +Description: VideoCore wayland-egl library | ||
1532 | +Version: @PROJECT_APIVER@ | ||
1533 | +Libs: -L${libdir} -lwayland-egl | ||
1534 | +Cflags: -I${includedir} | ||
1535 | diff --git a/interface/vmcs_host/CMakeLists.txt b/interface/vmcs_host/CMakeLists.txt | ||
1536 | index e0c6e13..35150ed 100755 | ||
1537 | --- a/interface/vmcs_host/CMakeLists.txt | ||
1538 | +++ b/interface/vmcs_host/CMakeLists.txt | ||
1539 | @@ -9,13 +9,24 @@ add_definitions(-fno-strict-aliasing) | ||
1540 | |||
1541 | include_directories(${VMCS_TARGET}/vcfiled) | ||
1542 | |||
1543 | -add_library(vchostif | ||
1544 | - ${VMCS_TARGET}/vcfilesys.c ${VMCS_TARGET}/vcmisc.c | ||
1545 | - vc_vchi_gencmd.c vc_vchi_filesys.c | ||
1546 | - vc_vchi_tvservice.c vc_vchi_cecservice.c | ||
1547 | - vc_vchi_dispmanx.c vc_service_common.c) | ||
1548 | +set(VCHOSTIF_SOURCE | ||
1549 | + ${VMCS_TARGET}/vcfilesys.c ${VMCS_TARGET}/vcmisc.c | ||
1550 | + vc_vchi_gencmd.c vc_vchi_filesys.c | ||
1551 | + vc_vchi_tvservice.c vc_vchi_cecservice.c | ||
1552 | + vc_vchi_dispmanx.c vc_service_common.c) | ||
1553 | # ${VMCS_TARGET}/vmcs_main.c | ||
1554 | # vc_vchi_haud.c | ||
1555 | + | ||
1556 | +if (BUILD_WAYLAND) | ||
1557 | +wayland_add_protocol_server( | ||
1558 | + VCHOSTIF_SOURCE | ||
1559 | + ../../interface/wayland/dispmanx.xml | ||
1560 | + dispmanx | ||
1561 | +) | ||
1562 | +endif () | ||
1563 | + | ||
1564 | +add_library(vchostif ${VCHOSTIF_SOURCE}) | ||
1565 | + | ||
1566 | #add_library(bufman vc_vchi_bufman.c ) | ||
1567 | |||
1568 | # OpenMAX/IL component service | ||
1569 | diff --git a/interface/vmcs_host/vc_dispmanx.h b/interface/vmcs_host/vc_dispmanx.h | ||
1570 | index 37fdae1..fe3619a 100755 | ||
1571 | --- a/interface/vmcs_host/vc_dispmanx.h | ||
1572 | +++ b/interface/vmcs_host/vc_dispmanx.h | ||
1573 | @@ -39,6 +39,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
1574 | #ifdef __cplusplus | ||
1575 | extern "C" { | ||
1576 | #endif | ||
1577 | + | ||
1578 | +#ifdef BUILD_WAYLAND | ||
1579 | +struct wl_resource; | ||
1580 | +#endif | ||
1581 | + | ||
1582 | // Same function as above, to aid migration of code. | ||
1583 | VCHPRE_ int VCHPOST_ vc_dispman_init( void ); | ||
1584 | // Stop the service from being used | ||
1585 | @@ -135,6 +140,11 @@ VCHPRE_ int VCHPOST_ vc_dispmanx_resource_set_palette( DISPMANX_RESOURCE_HANDLE_ | ||
1586 | // Start triggering callbacks synced to vsync | ||
1587 | VCHPRE_ int VCHPOST_ vc_dispmanx_vsync_callback( DISPMANX_DISPLAY_HANDLE_T display, DISPMANX_CALLBACK_FUNC_T cb_func, void *cb_arg ); | ||
1588 | |||
1589 | +#ifdef BUILD_WAYLAND | ||
1590 | +VCHPRE_ DISPMANX_RESOURCE_HANDLE_T VCHPOST_ vc_dispmanx_get_handle_from_wl_buffer( struct wl_resource *_buffer ); | ||
1591 | + | ||
1592 | +VCHPRE_ void VCHPOST_ vc_dispmanx_set_wl_buffer_in_use( struct wl_resource *_buffer, int in_use ); | ||
1593 | +#endif | ||
1594 | #ifdef __cplusplus | ||
1595 | } | ||
1596 | #endif | ||
1597 | diff --git a/interface/vmcs_host/vc_vchi_dispmanx.c b/interface/vmcs_host/vc_vchi_dispmanx.c | ||
1598 | index 3c91e07..1d24b6e 100755 | ||
1599 | --- a/interface/vmcs_host/vc_vchi_dispmanx.c | ||
1600 | +++ b/interface/vmcs_host/vc_vchi_dispmanx.c | ||
1601 | @@ -1316,3 +1316,45 @@ static void *dispmanx_notify_func( void *arg ) { | ||
1602 | } | ||
1603 | return 0; | ||
1604 | } | ||
1605 | + | ||
1606 | + | ||
1607 | +#ifdef BUILD_WAYLAND | ||
1608 | +/*********************************************************** | ||
1609 | + * Name: vc_dispmanx_get_handle_from_wl_buffer | ||
1610 | + * | ||
1611 | + * Arguments: | ||
1612 | + * struct wl_resource *_buffer | ||
1613 | + * | ||
1614 | + * Description: Return the handle of the resource associated to this Wayland buffer | ||
1615 | + * | ||
1616 | + * Returns: A resource handle | ||
1617 | + * | ||
1618 | + ***********************************************************/ | ||
1619 | +VCHPRE_ DISPMANX_RESOURCE_HANDLE_T VCHPOST_ vc_dispmanx_get_handle_from_wl_buffer( struct wl_resource *_buffer ) | ||
1620 | +{ | ||
1621 | + struct wl_dispmanx_server_buffer *buffer = (struct wl_dispmanx_server_buffer*)_buffer->data; | ||
1622 | + if (!buffer) | ||
1623 | + return DISPMANX_NO_HANDLE; | ||
1624 | + | ||
1625 | + return buffer->handle; | ||
1626 | +} | ||
1627 | + | ||
1628 | +/*********************************************************** | ||
1629 | + * Name: vc_dispmanx_set_wl_buffer_in_use | ||
1630 | + * | ||
1631 | + * Arguments: | ||
1632 | + * struct wl_resource *_buffer | ||
1633 | + * int in_use | ||
1634 | + * | ||
1635 | + * Description: Mark this Wayland buffer as being in use by the compositor | ||
1636 | + * | ||
1637 | + ***********************************************************/ | ||
1638 | +VCHPRE_ void VCHPOST_ vc_dispmanx_set_wl_buffer_in_use( struct wl_resource *_buffer, int in_use ) | ||
1639 | +{ | ||
1640 | + struct wl_dispmanx_server_buffer *buffer = (struct wl_dispmanx_server_buffer*)_buffer->data; | ||
1641 | + if (!buffer) | ||
1642 | + return; | ||
1643 | + | ||
1644 | + buffer->in_use = in_use; | ||
1645 | +} | ||
1646 | +#endif | ||
1647 | diff --git a/interface/vmcs_host/vc_vchi_dispmanx.h b/interface/vmcs_host/vc_vchi_dispmanx.h | ||
1648 | index b723b76..f0bae30 100644 | ||
1649 | --- a/interface/vmcs_host/vc_vchi_dispmanx.h | ||
1650 | +++ b/interface/vmcs_host/vc_vchi_dispmanx.h | ||
1651 | @@ -66,4 +66,19 @@ typedef struct { | ||
1652 | #define ELEMENT_CHANGE_MASK_RESOURCE (1<<4) | ||
1653 | #define ELEMENT_CHANGE_TRANSFORM (1<<5) | ||
1654 | |||
1655 | +#ifdef BUILD_WAYLAND | ||
1656 | +/* XXX: This should be in a private header that can be included from EGL and vc_* */ | ||
1657 | +#include <wayland-server.h> | ||
1658 | +#include "interface/vmcs_host/wayland-dispmanx-server-protocol.h" | ||
1659 | +struct wl_dispmanx_server_buffer { | ||
1660 | + struct wl_resource *resource; | ||
1661 | + struct wl_dispmanx *dispmanx; | ||
1662 | + enum wl_dispmanx_format format; | ||
1663 | + DISPMANX_RESOURCE_HANDLE_T handle; | ||
1664 | + int32_t width; | ||
1665 | + int32_t height; | ||
1666 | + int in_use; | ||
1667 | +}; | ||
1668 | +#endif | ||
1669 | + | ||
1670 | #endif | ||
1671 | diff --git a/interface/wayland/dispmanx.xml b/interface/wayland/dispmanx.xml | ||
1672 | new file mode 100644 | ||
1673 | index 0000000..c18626d | ||
1674 | --- /dev/null | ||
1675 | +++ b/interface/wayland/dispmanx.xml | ||
1676 | @@ -0,0 +1,123 @@ | ||
1677 | +<?xml version="1.0" encoding="UTF-8"?> | ||
1678 | +<protocol name="dispmanx"> | ||
1679 | + | ||
1680 | + <copyright> | ||
1681 | + Copyright © 2008-2011 Kristian Høgsberg | ||
1682 | + Copyright © 2010-2011 Intel Corporation | ||
1683 | + Copyright © 2013 Raspberry Pi Foundation | ||
1684 | + | ||
1685 | + Permission to use, copy, modify, distribute, and sell this | ||
1686 | + software and its documentation for any purpose is hereby granted | ||
1687 | + without fee, provided that\n the above copyright notice appear in | ||
1688 | + all copies and that both that copyright notice and this permission | ||
1689 | + notice appear in supporting documentation, and that the name of | ||
1690 | + the copyright holders not be used in advertising or publicity | ||
1691 | + pertaining to distribution of the software without specific, | ||
1692 | + written prior permission. The copyright holders make no | ||
1693 | + representations about the suitability of this software for any | ||
1694 | + purpose. It is provided "as is" without express or implied | ||
1695 | + warranty. | ||
1696 | + | ||
1697 | + THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS | ||
1698 | + SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND | ||
1699 | + FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY | ||
1700 | + SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
1701 | + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN | ||
1702 | + AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, | ||
1703 | + ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF | ||
1704 | + THIS SOFTWARE. | ||
1705 | + </copyright> | ||
1706 | + | ||
1707 | + <!-- DispManX support. This object is created by the server and published | ||
1708 | + using the display's global event. --> | ||
1709 | + <interface name="wl_dispmanx" version="1"> | ||
1710 | + <enum name="error"> | ||
1711 | + <entry name="alloc_failed" value="0"/> | ||
1712 | + <entry name="invalid_format" value="1"/> | ||
1713 | + </enum> | ||
1714 | + | ||
1715 | + <enum name="format"> | ||
1716 | + <!-- The pixel format codes match the #defines in drm_fourcc.h. | ||
1717 | + The formats actually supported by the compositor will be | ||
1718 | + reported by the format event. --> | ||
1719 | + <entry name="c8" value="0x20203843"/> | ||
1720 | + <entry name="rgb332" value="0x38424752"/> | ||
1721 | + <entry name="bgr233" value="0x38524742"/> | ||
1722 | + <entry name="xrgb4444" value="0x32315258"/> | ||
1723 | + <entry name="xbgr4444" value="0x32314258"/> | ||
1724 | + <entry name="rgbx4444" value="0x32315852"/> | ||
1725 | + <entry name="bgrx4444" value="0x32315842"/> | ||
1726 | + <entry name="argb4444" value="0x32315241"/> | ||
1727 | + <entry name="abgr4444" value="0x32314241"/> | ||
1728 | + <entry name="rgba4444" value="0x32314152"/> | ||
1729 | + <entry name="bgra4444" value="0x32314142"/> | ||
1730 | + <entry name="xrgb1555" value="0x35315258"/> | ||
1731 | + <entry name="xbgr1555" value="0x35314258"/> | ||
1732 | + <entry name="rgbx5551" value="0x35315852"/> | ||
1733 | + <entry name="bgrx5551" value="0x35315842"/> | ||
1734 | + <entry name="argb1555" value="0x35315241"/> | ||
1735 | + <entry name="abgr1555" value="0x35314241"/> | ||
1736 | + <entry name="rgba5551" value="0x35314152"/> | ||
1737 | + <entry name="bgra5551" value="0x35314142"/> | ||
1738 | + <entry name="rgb565" value="0x36314752"/> | ||
1739 | + <entry name="bgr565" value="0x36314742"/> | ||
1740 | + <entry name="rgb888" value="0x34324752"/> | ||
1741 | + <entry name="bgr888" value="0x34324742"/> | ||
1742 | + <entry name="xrgb8888" value="0x34325258"/> | ||
1743 | + <entry name="xbgr8888" value="0x34324258"/> | ||
1744 | + <entry name="rgbx8888" value="0x34325852"/> | ||
1745 | + <entry name="bgrx8888" value="0x34325842"/> | ||
1746 | + <entry name="argb8888" value="0x34325241"/> | ||
1747 | + <entry name="abgr8888" value="0x34324241"/> | ||
1748 | + <entry name="rgba8888" value="0x34324152"/> | ||
1749 | + <entry name="bgra8888" value="0x34324142"/> | ||
1750 | + <entry name="xrgb2101010" value="0x30335258"/> | ||
1751 | + <entry name="xbgr2101010" value="0x30334258"/> | ||
1752 | + <entry name="rgbx1010102" value="0x30335852"/> | ||
1753 | + <entry name="bgrx1010102" value="0x30335842"/> | ||
1754 | + <entry name="argb2101010" value="0x30335241"/> | ||
1755 | + <entry name="abgr2101010" value="0x30334241"/> | ||
1756 | + <entry name="rgba1010102" value="0x30334152"/> | ||
1757 | + <entry name="bgra1010102" value="0x30334142"/> | ||
1758 | + <entry name="yuyv" value="0x56595559"/> | ||
1759 | + <entry name="yvyu" value="0x55595659"/> | ||
1760 | + <entry name="uyvy" value="0x59565955"/> | ||
1761 | + <entry name="vyuy" value="0x59555956"/> | ||
1762 | + <entry name="ayuv" value="0x56555941"/> | ||
1763 | + <entry name="nv12" value="0x3231564e"/> | ||
1764 | + <entry name="nv21" value="0x3132564e"/> | ||
1765 | + <entry name="nv16" value="0x3631564e"/> | ||
1766 | + <entry name="nv61" value="0x3136564e"/> | ||
1767 | + <entry name="yuv410" value="0x39565559"/> | ||
1768 | + <entry name="yvu410" value="0x39555659"/> | ||
1769 | + <entry name="yuv411" value="0x31315559"/> | ||
1770 | + <entry name="yvu411" value="0x31315659"/> | ||
1771 | + <entry name="yuv420" value="0x32315559"/> | ||
1772 | + <entry name="yvu420" value="0x32315659"/> | ||
1773 | + <entry name="yuv422" value="0x36315559"/> | ||
1774 | + <entry name="yvu422" value="0x36315659"/> | ||
1775 | + <entry name="yuv444" value="0x34325559"/> | ||
1776 | + <entry name="yvu444" value="0x34325659"/> | ||
1777 | + </enum> | ||
1778 | + | ||
1779 | + <event name="format"> | ||
1780 | + <arg name="format" type="uint"/> | ||
1781 | + </event> | ||
1782 | + | ||
1783 | + <!-- Create a wayland buffer for the DispManX resource. --> | ||
1784 | + <request name="create_buffer"> | ||
1785 | + <arg name="id" type="new_id" interface="wl_buffer"/> | ||
1786 | + <arg name="width" type="int"/> | ||
1787 | + <arg name="height" type="int"/> | ||
1788 | + <arg name="stride" type="uint"/> | ||
1789 | + <arg name="buffer_height" type="uint"/> | ||
1790 | + <arg name="format" type="uint"/> | ||
1791 | + </request> | ||
1792 | + | ||
1793 | + <event name="buffer_allocated"> | ||
1794 | + <arg name="buffer" type="object" interface="wl_buffer"/> | ||
1795 | + <arg name="handle" type="uint"/> | ||
1796 | + </event> | ||
1797 | + </interface> | ||
1798 | + | ||
1799 | +</protocol> | ||
1800 | diff --git a/makefiles/cmake/Wayland.cmake b/makefiles/cmake/Wayland.cmake | ||
1801 | new file mode 100644 | ||
1802 | index 0000000..ad90d30 | ||
1803 | --- /dev/null | ||
1804 | +++ b/makefiles/cmake/Wayland.cmake | ||
1805 | @@ -0,0 +1,72 @@ | ||
1806 | +#============================================================================= | ||
1807 | +# Copyright (C) 2012-2013 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com> | ||
1808 | +# All rights reserved. | ||
1809 | +# | ||
1810 | +# Redistribution and use in source and binary forms, with or without | ||
1811 | +# modification, are permitted provided that the following conditions | ||
1812 | +# are met: | ||
1813 | +# | ||
1814 | +# * Redistributions of source code must retain the above copyright | ||
1815 | +# notice, this list of conditions and the following disclaimer. | ||
1816 | +# | ||
1817 | +# * Redistributions in binary form must reproduce the above copyright | ||
1818 | +# notice, this list of conditions and the following disclaimer in the | ||
1819 | +# documentation and/or other materials provided with the distribution. | ||
1820 | +# | ||
1821 | +# * Neither the name of Pier Luigi Fiorini nor the names of his | ||
1822 | +# contributors may be used to endorse or promote products derived | ||
1823 | +# from this software without specific prior written permission. | ||
1824 | +# | ||
1825 | +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
1826 | +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
1827 | +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
1828 | +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
1829 | +# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
1830 | +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
1831 | +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
1832 | +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
1833 | +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
1834 | +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
1835 | +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
1836 | +#============================================================================= | ||
1837 | + | ||
1838 | +find_program(WAYLAND_SCANNER_EXECUTABLE NAMES wayland-scanner) | ||
1839 | + | ||
1840 | +# wayland_add_protocol_client(outfiles inputfile basename) | ||
1841 | +function(WAYLAND_ADD_PROTOCOL_CLIENT _sources _protocol _basename) | ||
1842 | + if(NOT WAYLAND_SCANNER_EXECUTABLE) | ||
1843 | + message(FATAL "The wayland-scanner executable has nto been found on your system. You must install it.") | ||
1844 | + endif() | ||
1845 | + | ||
1846 | + get_filename_component(_infile ${_protocol} ABSOLUTE) | ||
1847 | + set(_client_header "${CMAKE_CURRENT_BINARY_DIR}/wayland-${_basename}-client-protocol.h") | ||
1848 | + set(_code "${CMAKE_CURRENT_BINARY_DIR}/wayland-${_basename}-protocol.c") | ||
1849 | + | ||
1850 | + add_custom_command(OUTPUT "${_client_header}" | ||
1851 | + COMMAND ${WAYLAND_SCANNER_EXECUTABLE} client-header < ${_infile} > ${_client_header} | ||
1852 | + DEPENDS ${_infile} VERBATIM) | ||
1853 | + | ||
1854 | + add_custom_command(OUTPUT "${_code}" | ||
1855 | + COMMAND ${WAYLAND_SCANNER_EXECUTABLE} code < ${_infile} > ${_code} | ||
1856 | + DEPENDS ${_infile} VERBATIM) | ||
1857 | + | ||
1858 | + list(APPEND ${_sources} "${_client_header}" "${_code}") | ||
1859 | + set(${_sources} ${${_sources}} PARENT_SCOPE) | ||
1860 | +endfunction() | ||
1861 | + | ||
1862 | +# wayland_add_protocol_server(outfiles inputfile basename) | ||
1863 | +function(WAYLAND_ADD_PROTOCOL_SERVER _sources _protocol _basename) | ||
1864 | + if(NOT WAYLAND_SCANNER_EXECUTABLE) | ||
1865 | + message(FATAL "The wayland-scanner executable has nto been found on your system. You must install it.") | ||
1866 | + endif() | ||
1867 | + | ||
1868 | + get_filename_component(_infile ${_protocol} ABSOLUTE) | ||
1869 | + set(_server_header "${CMAKE_CURRENT_BINARY_DIR}/wayland-${_basename}-server-protocol.h") | ||
1870 | + | ||
1871 | + add_custom_command(OUTPUT "${_server_header}" | ||
1872 | + COMMAND ${WAYLAND_SCANNER_EXECUTABLE} server-header < ${_infile} > ${_server_header} | ||
1873 | + DEPENDS ${_infile} VERBATIM) | ||
1874 | + | ||
1875 | + list(APPEND ${_sources} "${_server_header}") | ||
1876 | + set(${_sources} ${${_sources}} PARENT_SCOPE) | ||
1877 | +endfunction() | ||
1878 | -- | ||
1879 | 2.7.0 | ||
1880 | |||
diff --git a/recipes-graphics/userland/userland/0010-wayland-Add-Wayland-example.patch b/recipes-graphics/userland/userland/0010-wayland-Add-Wayland-example.patch new file mode 100644 index 0000000..f468ef3 --- /dev/null +++ b/recipes-graphics/userland/userland/0010-wayland-Add-Wayland-example.patch | |||
@@ -0,0 +1,866 @@ | |||
1 | From b853c05f425775a65cfc5a2d64b3491ab3673e36 Mon Sep 17 00:00:00 2001 | ||
2 | From: Tomeu Vizoso <tomeu.vizoso@collabora.com> | ||
3 | Date: Tue, 1 Oct 2013 13:19:20 +0200 | ||
4 | Subject: [PATCH 10/16] wayland: Add Wayland example | ||
5 | |||
6 | --- | ||
7 | .../linux/apps/hello_pi/CMakeLists.txt | 1 + | ||
8 | .../apps/hello_pi/hello_wayland/CMakeLists.txt | 8 + | ||
9 | .../apps/hello_pi/hello_wayland/Djenne_128_128.raw | 3 + | ||
10 | .../linux/apps/hello_pi/hello_wayland/Makefile | 5 + | ||
11 | .../hello_wayland/cube_texture_and_coords.h | 100 ++++ | ||
12 | .../linux/apps/hello_pi/hello_wayland/triangle.c | 666 +++++++++++++++++++++ | ||
13 | host_applications/linux/apps/hello_pi/rebuild.sh | 3 +- | ||
14 | 7 files changed, 785 insertions(+), 1 deletion(-) | ||
15 | create mode 100644 host_applications/linux/apps/hello_pi/hello_wayland/CMakeLists.txt | ||
16 | create mode 100644 host_applications/linux/apps/hello_pi/hello_wayland/Djenne_128_128.raw | ||
17 | create mode 100644 host_applications/linux/apps/hello_pi/hello_wayland/Makefile | ||
18 | create mode 100644 host_applications/linux/apps/hello_pi/hello_wayland/cube_texture_and_coords.h | ||
19 | create mode 100644 host_applications/linux/apps/hello_pi/hello_wayland/triangle.c | ||
20 | |||
21 | diff --git a/host_applications/linux/apps/hello_pi/CMakeLists.txt b/host_applications/linux/apps/hello_pi/CMakeLists.txt | ||
22 | index f2c6aef..0df78f7 100644 | ||
23 | --- a/host_applications/linux/apps/hello_pi/CMakeLists.txt | ||
24 | +++ b/host_applications/linux/apps/hello_pi/CMakeLists.txt | ||
25 | @@ -21,6 +21,7 @@ add_subdirectory(hello_encode) | ||
26 | add_subdirectory(hello_jpeg) | ||
27 | add_subdirectory(hello_videocube) | ||
28 | add_subdirectory(hello_teapot) | ||
29 | +add_subdirectory(hello_wayland) | ||
30 | |||
31 | if(BUILD_FONT) | ||
32 | set(VGFONT_SRCS libs/vgfont/font.c libs/vgfont/vgft.c libs/vgfont/graphics.c) | ||
33 | diff --git a/host_applications/linux/apps/hello_pi/hello_wayland/CMakeLists.txt b/host_applications/linux/apps/hello_pi/hello_wayland/CMakeLists.txt | ||
34 | new file mode 100644 | ||
35 | index 0000000..9a2f75c | ||
36 | --- /dev/null | ||
37 | +++ b/host_applications/linux/apps/hello_pi/hello_wayland/CMakeLists.txt | ||
38 | @@ -0,0 +1,8 @@ | ||
39 | +set(EXEC hello_wayland.bin) | ||
40 | +set(SRCS triangle.c) | ||
41 | + | ||
42 | +add_executable(${EXEC} ${SRCS}) | ||
43 | +target_link_libraries(${EXEC} ${HELLO_PI_LIBS} -lwayland-client -lwayland-egl) | ||
44 | + | ||
45 | +install(TARGETS ${EXEC} | ||
46 | + RUNTIME DESTINATION bin) | ||
47 | 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 | ||
48 | new file mode 100644 | ||
49 | index 0000000..de9173c | ||
50 | --- /dev/null | ||
51 | +++ b/host_applications/linux/apps/hello_pi/hello_wayland/Djenne_128_128.raw | ||
52 | @@ -0,0 +1,3 @@ | ||
53 | +öÖ¿÷×À÷×ÀøØÁúÚÃúÚÃúÚÃúÚÃùÙÂùÙÂùÙÂùÙÂùÙÂùÙÂùÙÂùÙÂûÙÂûÙÂûÙÂûÙÂúØÁúØÁúØÁúØÁøÖ¿ù×Àù×ÀúØÁúØÁúØÁúØÁúØÁù×Àù×Àù×Àù×À÷Õ¾øÖ¿ù×Àù×À÷Õ¾÷Õ¾÷Õ¾÷Õ¾÷Õ¾÷Õ¾÷Õ¾÷Õ¾÷Õ¾÷Õ¾öÔ½öÔ½÷Õ¾÷Õ¾÷Õ¾÷Õ¾õÓ¼öÔ½öÔ½õÓ¼ôÒ»ôÒ»ôÒ»ôÒ»õкõкõкõкõкõкõкõкôиõѹôиôиòζóÏ·óÏ·õѹñ͵óÏ·óÏ·ñ͵òζñ͵ñ͵ñ͵ñ͵ñ͵ðÌ´ðÌ´ðÌ´ï˳ï˳ï˳î˱î˱î˱î˱î˱î˱î˱íʰïʰïʰîɯîɯíÈ®ìÇìÇìÇëÆ¬ëÆ¬ëÆ¬êÅ«êÅ«êÅ«ëÆ¬ëÆ¬èééĪéĪèéèéèéèéç¨ùÙÂúÚÃúÚÃûÛÄüÜÅüÜÅüÜÅüÜÅûÛÄûÛÄûÛÄûÛÄûÛÄûÛÄûÛÄûÛÄýÛÄýÛÄýÛÄýÛÄýÛÄýÛÄýÛÄýÛÄüÚÃüÚÃüÚÃüÚÃüÚÃüÚÃüÚÃüÚÃüÚÃüÚÃüÚÃüÚÃûÙÂûÙÂûÙÂûÙÂúØÁúØÁúØÁúØÁù×Àù×Àù×Àù×ÀúØÁù×Àù×Àù×ÀøÖ¿øÖ¿øÖ¿øÖ¿øÖ¿øÖ¿øÖ¿÷Õ¾÷Õ¾÷Õ¾÷Õ¾÷Õ¾øÓ½øÓ½øÓ½øÓ½÷Ò¼÷Ò¼÷Ò¼÷Ò¼öÓº÷Ó»÷Ó»÷Ó»õѹöÒºöÒºöÒºôиõѹõѹôиôиôиôиóÏ·ôиóÏ·óÏ·óÏ·óÏ·òζòζòζñδñδñδñδñδñδðͳðͳòͳñ̲ñ̲ñ̲ð˱ïʰïʰïʰîɯîɯîɯíÈ®îɯíÈ®íÈ®ìÇìÇíÈ®íÈ®ìÇëÆ¬ëÆ¬êÅ«êÅ«ûÛÄûÛÄûÛÄûÛÄüÜÅüÜÅüÜÅüÜÅüÜÅüÜÅüÜÅüÜÅüÜÅüÜÅüÜÅüÜÅüÜÅüÜÅüÜÅüÜÅûÛÄûÛÄûÛÄûÛÄýÛÄýÛÄüÚÃüÚÃüÚÃüÚÃüÚÃüÚÃüÚÃüÚÃüÚÃüÚÃüÚÃüÚÃûÙÂúØÁûÙÂûÙÂûÙÂûÙÂúØÁúØÁúØÁúØÁúØÁúØÁù×Àù×ÀøÖ¿øÖ¿øÖ¿øÖ¿øÖ¿ù×ÀøÖ¿÷Õ¾÷Õ¾÷Õ¾÷Õ¾÷Õ¾øÓ½øÓ½øÓ½øÓ½÷Ò¼÷Ò¼÷Ò¼÷Ò¼öÓº÷Ó»÷Ó»öÒºöÒºöÒºöÒºöÒºõѹõѹõѹõѹõѹõѹôиôиôиôиôиóÏ·óÏ·óÏ·òζòζñδñδñδñδñδñδðͳðͳòͳñ̲ñ̲ñ̲ð˱ð˱ïʰïʰïʰîɯîɯîɯïʰîɯíÈ®ìÇìÇìÇìÇëÆ¬ìÇëÆ¬ëÆ¬ëÆ¬üÜÅüÜÅüÜÅüÜÅýÝÆýÝÆýÝÆýÝÆüÜÅüÜÅüÜÅüÜÅüÜÅüÜÅüÜÅüÜÅüÜÅüÜÅüÜÅüÜÅûÛÄûÛÄûÛÄûÛÄüÚÃýÛÄýÛÄýÛÄüÚÃüÚÃüÚÃüÚÃüÚÃüÚÃüÚÃüÚÃûÙÂûÙÂûÙÂûÙÂûÙÂûÙÂûÙÂûÙÂúØÁúØÁúØÁúØÁúØÁúØÁù×Àù×Àù×Àù×Àù×Àù×ÀøÖ¿ù×ÀøÖ¿÷Õ¾÷Õ¾÷Õ¾÷Õ¾÷Õ¾øÓ½øÓ½øÓ½øÓ½÷Ò¼÷Ò¼÷Ò¼÷Ò¼öÓº÷Ó»÷Ó»öÒº÷Ó»÷Ó»öÒºöÒºõѹôиõѹöÒºõѹõѹôиôиõѹôиôиôиóÏ·óÏ·óÏ·òζòϵòϵòϵòϵñδñδðͳðͳòͳñ̲ñ̲ñ̲ð˱ð˱ð˱ïʰïʰïʰîɯîɯîɯîɯîɯîɯíÈ®îɯîɯíÈ®ìÇìÇëÆ¬ëÆ¬ûÜÅüÝÆýÞÇüÝÆüÝÆüÝÆüÝÆüÝÆûÜÅûÜÅûÜÅûÜÅûÜÅûÜÅûÜÅûÜÅûÛÄûÛÄûÛÄûÛÄüÜÅüÜÅüÜÅüÜÅûÛÄûÛÄûÛÄûÛÄúÚÃûÛÄûÛÄûÛÄýÛÃýÛÃýÛÃýÛÃüÚÂüÚÂüÚÂüÚÂüÚÃüÚÃüÚÃüÚÃûÙÂûÙÂûÙÂûÙÂúØÀúØÀúØÀù׿÷Õ½úØÀúØÀù׿øÖ¿øÖ¿øÖ¿÷Õ¾÷Õ¾ù×Àù×ÀöÔ¾øÔ¼øÔ¼ùÕ½úÖ¾õѹøÔ¼ùÕ½ùÕ½÷Ó»÷Ó»÷Ó»÷Ó»öÒºöÒºöÒºöÒºõѹõѹõѹõѹõѹõѹõѹõѹõѹõѹõѹõѹôиôиóÏ·óÏ·óжòϵòϵòϵñδñδðͳðͳñ̲ñ̲ñ̲ñ̲ñ̲ñ̲ð˱ð˱ð˱ð˱ð˱ïʰïʰîɯîɯîɯïʰîɯîɯîɯìÇìÇìÇëÆ¬ûÜÅüÝÆýÞÇýÞÇüÝÆüÝÆüÝÆüÝÆûÜÅûÜÅûÜÅûÜÅûÜÅûÜÅûÜÅûÜÅüÜÅüÜÅüÜÅüÜÅüÜÅüÜÅüÜÅüÜÅüÜÅüÜÅüÜÅüÜÅûÛÄûÛÄüÜÅûÛÄýÛÃýÛÃýÛÃýÛÃýÛÃýÛÃýÛÃýÛÃýÛÄýÛÄýÛÄýÛÄüÚÃüÚÃüÚÃüÚÃüÚÂüÚÂüÚÂûÙÁúØÀúØÀúØÀù׿ù×Àù×Àù×ÀøÖ¿ù×Àù×Àù×À÷Õ¿úÖ¾úÖ¾û׿û׿øÔ¼ùÕ½ùÕ½øÔ¼ùÕ½ùÕ½ùÕ½ùÕ½øÔ¼øÔ¼øÔ¼øÔ¼÷Ó»÷Ó»÷Ó»÷Ó»÷Ó»÷Ó»÷Ó»÷Ó»õѹõѹõѹõѹõѹôиôиôиóжóжóжòϵóжóжòϵòϵóδóδóδóδòͳñ̲ñ̲ñ̲ñ̲ñ̲ð˱ð˱ð˱ïʰïʰïʰïʰïʰîɯîɯîɯîɯîɯíÈ®üÝÆýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇüÝÆüÝÆüÝÆüÝÆüÝÆüÝÆüÝÆüÝÆüÝÆüÝÆüÝÆüÝÆûÜÅûÜÅûÜÅûÜÅýÝÆýÝÆýÝÆýÝÆûÛÄüÜÅüÜÅüÜÅþÜÄþÜÄþÜÄþÜÄýÛÃýÛÃýÛÃýÛÃýÛÄýÛÄýÛÄýÛÄýÛÄýÛÄýÛÄýÛÄüÚÂüÚÂüÚÂûÙÁüÚÂûÙÁûÙÁúØÀûÙÂûÙÂúØÁúØÁúØÁúØÁù×Àù×Àû׿û׿û׿û׿û׿úÖ¾ùÕ½ùÕ½ùÕ½ùÕ½ùÕ½ùÕ½øÔ¼øÔ¼øÔ¼øÔ¼øÔ¼øÔ¼øÔ¼øÔ¼÷Ó»÷Ó»÷Ó»÷Ó»÷Ó»÷Ó»÷Ó»÷Ó»öÒºöÒºõѹõѹõÒ¸ôÑ·ôÑ·ôÑ·óжóжòϵòϵõжôϵôϵôϵóδóδòͳòͳòͳòͳòͳñ̲ñ̲ñ̲ð˱ð˱ð˱ð˱ð˱ïʰïʰïʰîɯíÈ®üÝÆýÞÇþßÈýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇüÝÆüÝÆüÝÆüÝÆüÝÆüÝÆüÝÆüÝÆýÝÆýÝÆýÝÆýÝÆüÜÅýÝÆýÝÆüÜÅÿÝÅÿÝÅÿÝÅÿÝÅþÜÄþÜÄþÜÄþÜÄþÜÅþÜÅþÜÅþÜÅýÛÄýÛÄýÛÄýÛÄþÜÄýÛÃýÛÃýÛÃüÚÂûÙÁûÙÁýÛÃüÚÃüÚÃüÚÃûÙÂüÚÃûÙÂúØÁûÙÂýÙÀüØÀüØÀû׿üØÀúÖ¾úÖ¾û׿úÖ¾úÖ¾úÖ¾úÖ¾ùÕ½ùÕ½ùÕ½ùÕ½ùÕ½ùÕ½ùÕ½ùÕ½øÔ¼øÔ¼øÔ¼øÔ¼øÔ¼øÔ¼øÔ¼øÔ¼÷Ó»÷Ó»öÒºöÒºöÓ¹õÒ¸õÒ¸õÒ¸ôÑ·ôÑ·ôÑ·óжõжõжôϵóδôϵôϵóδóδóδóδóδòͳòͳòͳòͳñ̲ñ̲ñ̲ñ̲ð˱ð˱ñ̲ð˱ïʰýÞÇýÞÇýÞÇýÞÇüÝÆüÝÆüÝÆüÝÆýÞÇýÞÇýÞÇýÞÇüÝÆýÞÇýÞÇýÞÇþÞÇþÞÇþÞÇþÞÇþÞÇþÞÇþÞÇþÞÇýÞÇýÞÇýÞÇýÞÇüÝÆüÝÆüÝÆüÝÆýÝÆýÝÆýÝÆýÝÆüÜÅüÜÅüÜÅüÜÅûÜÂüÝÄüÝÄûÜÃûÜÃûÜÃûÜÃûÜÃýÜÂýÜÂýÜÂýÜÂýÜÂýÜÂýÜÂýÜÂüÚÂüÚÂüÚÂüÚÂüÚÂüÚÂüÚÂüÚÂúÙ¿úÙ¿úÙ¿úÙ¿úÙ¿úÙ¿úÙ¿ùؾúØÁúØÁúØÁúØÁøÖ¿øÖ¿øÖ¿øÖ¿øÖ¾÷Õ½÷Õ½÷Õ½÷Õ½÷Õ½÷Õ½÷Õ½öÔ¼÷Õ½öÔ¼õÓ»õÓ»õÓ»õÓ»ôÒºóѹôÒºóѹòиóѹòиòиòиôиóÏ·óÏ·óÏ·ôиôиôиôиñÏ·ñÏ·ñÏ·ðζðζðζï͵ï͵ðͳðͳðͳï̲ï̲ï̲î˱î˱þßÈþßÈþßÈþßÈþßÈþßÈþßÈþßÈþßÈþßÈþßÈþßÈýÞÇýÞÇþßÈýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇýÝÆýÝÆýÝÆýÝÆüÜÅüÜÅüÜÅüÜÅûÜÃüÝÄüÝÄüÝÄüÝÄüÝÄüÝÄüÝÄþÝÃþÝÃþÝÃþÝÃýÜÂýÜÂýÜÂýÜÂýÛÃýÛÃýÛÃýÛÃýÛÃýÛÃýÛÃýÛÃüÛÁüÛÁüÛÁüÛÁýÜÂýÜÂüÛÁüÜÁúØÁúØÁúØÁúØÁúØÁúØÁúØÁúØÁúØÀúØÀù׿ù׿øÖ¾øÖ¾øÖ¾øÖ¾÷Õ½øÖ¾÷Õ½öÔ¼øÖ¾÷Õ½÷Õ½öÔ¼öÔ¼öÔ¼õÓ»ôÒºõÓ»õÓ»ôÒºôÒºöÒºõѹõѹõѹóÏ·óÏ·óÏ·óÏ·ñÏ·ñÏ·ðζðζñÏ·ðζðζðζòϵòϵòϵñδñδñδðͳðͳþßÈþßÈþßÈþßÈþßÈþßÈþßÈþßÈþßÈþßÈþßÈþßÈþßÈþßÈÿàÉþßÈýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇüÝÆüÝÆüÝÆüÝÆþÞÇþÞÇþÞÇþÞÇýÝÆýÝÆýÝÆýÝÆüÝÄýÞÅýÞÅüÝÄýÞÅýÞÅýÞÅýÞÅýÞÅýÞÅýÞÅýÞÅüÝÄüÝÄüÝÄüÝÄûÜÃûÜÃûÜÃûÜÃûÜÃûÜÃûÜÃûÜÃûÜÃûÜÃûÜÃûÜÃûÜÃûÜÃûÜÃûÜÃúÚÃúÚÃúÚÃúÚÃùÙÂùÙÂùÙÂùÙÂøÚÀøÙÀøÙÀøÙÀ÷Ø¿÷Ø¿÷Ø¿÷Ø¿ù׿ù׿øÖ¾øÖ¾øÖ¾øÖ¾÷Õ½÷Õ½÷Õ½÷Õ½öÔ¼õÓ»õÓ»õÓ»õÓ»õÓ»öÒºöÒºõѹõѹôиôиôиôиòиòиñÏ·ñÏ·òиòиñÏ·ñÏ·òϵòϵòϵñδñδñδðͳðͳüàÈüàÈüàÈüàÈýáÉýáÉýáÉýáÉüàÈüàÈüàÈüàÈüàÈýáÉýáÉýáÉþßÈþßÈþßÈþßÈþßÈþßÈþßÈþßÈþßÈþßÈþßÈþßÈýÞÇýÞÇýÞÇýÞÇÿßÈÿßÈÿßÈÿßÈþÞÇþÞÇþÞÇþÞÇýÞÅýÞÅþ߯ýÞÅýÞÅýÞÅýÞÅýÞÅýÞÅýÞÅýÞÅýÞÅýÞÅýÞÅýÞÅýÞÅüÝÄüÝÄüÝÄüÝÄüÝÄüÝÄüÝÄüÝÄüÝÄüÝÄüÝÄüÝÄûÜÃûÜÃüÝÄüÝÄûÛÄûÛÄûÛÄûÛÄúÚÃúÚÃúÚÃúÚÃúÛÂúÛÂúÛÂùÚÁùÚÁùÚÁùÚÁùÚÁúØÀúØÀúØÀù׿úØÀù׿ù׿ù׿ù׿ù׿øÖ¾÷Õ½÷Õ½÷Õ½öÔ¼öÔ¼öÔ¼õÓ»õÓ»õÓ»ôÒºôÒºôÒºôÒºôÒºôÒºóѹóѹóѹóѹòиòиòÑ·ñжñжñжðϵðϵðϵïδüàÈüàÈýáÉýáÉýáÉýáÉýáÉýáÉýáÉýáÉýáÉýáÉýáÉýáÉýáÉýáÉÿàÉÿàÉÿàÉÿàÉÿàÉÿàÉÿàÉÿàÉþßÈþßÈþßÈþßÈþßÈþßÈþßÈþßÈýÞÇþßÈþßÈýÞÇýÞÇýÞÇýÞÇýÞÇüÝÆüÝÆüÝÆüÝÆüÝÆüÝÆüÝÆüÝÆýÞÅýÞÅýÞÅýÞÅýÞÅýÞÅýÞÅýÞÅýÞÅýÞÅýÞÅýÞÅüÝÄüÝÄüÝÄüÝÄüÝÄüÝÄüÝÄüÝÄüÝÄüÝÄýÞÅýÞÅüÜÅüÜÅüÜÅüÜÅüÜÅüÜÅüÜÅýÜÆùÚÁùÚÁùÚÁùÚÁùÚÁùÚÁùÚÁùÚÁùÙÂùÙÂùÙÂùÙÂùÙÂùÙÂùÙÂùÙÂ÷Ø¿÷Ø¿÷Ø¿÷Ø¿ö×¾ö×¾ö×¾õÖ½øÖ¾÷Õ½÷Õ½÷Õ½öÔ¼öÔ¼öÔ¼÷Ô¼òÓºòÓºòÓºòÓºòÓºòÓºñÒ¹ñÒ¹òиòиñÏ·ñÏ·ñÏ·ñÏ·ñÏ·ðζüàÈýáÉýáÉýáÉýáÉýáÉýáÉýáÉýáÉýáÉýáÉýáÉýáÉýáÉýáÉýáÉýáÉýáÉýáÉýáÉýáÉýáÉýáÉýáÉþßÈþßÈþßÈþßÈþßÈþßÈþßÈþßÈýÞÇþßÈþßÈýÞÇþßÈþßÈþßÈþßÈÿàÉÿàÉÿàÉÿàÉýÞÇýÞÇýÞÇýÞÇýÞÅýÞÅýÞÅýÞÅýÞÅýÞÅýÞÅýÞÅýÞÅýÞÅýÞÅýÞÅýÞÅýÞÅýÞÅýÞÅýÞÅýÞÅýÞÅýÞÅüÝÄýÞÅýÞÅýÞÅüÜÅüÜÅüÜÅüÜÅüÜÅüÜÅüÜÅüÜÅüÝÄüÝÄüÝÄüÝÄûÜÃûÜÃûÜÃûÜÃûÛÄûÛÄûÛÄûÛÄúÚÃúÚÃúÚÃúÚÃùÚÁùÚÁøÙÀøÙÀùÚÁøÙÀøÙÀøÙÀù׿øÖ¾øÖ¾øÖ¾÷Õ½÷Õ½÷Õ½öÔ¼ôÕ¼ôÕ¼ôÕ¼ôÕ¼óÔ»óÔ»óÔ»òÓºôÒºóѹóѹóѹòиòиñÏ·ñÏ·ûáÉûáÉûáÉüâÊûáÉûáÉûáÉûáÉûáÉûáÉûáÉûáÉûáÉûáÉûáÉûáÉýáÉýáÉýáÉýáÉýáÉýáÉýáÉýáÉÿàÉÿàÉÿàÉÿàÉÿàÉÿàÉÿàÉÿàÉýÞÇþßÈþßÈþßÈþßÈþßÈþßÈþßÈþßÈþßÈþßÈþßÈýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇý߯ý߯ý߯ý߯üÞÅüÞÅüÞÅüÞÅüÝÆüÝÆüÝÆüÝÆüÝÆüÝÆüÝÆüÝÆûÜÅûÜÅûÜÅûÜÅûÜÅûÜÅûÜÅûÜÅûÝÄûÝÄûÝÄûÝÄûÝÄûÝÄûÝÄûÝÄüÜÅüÜÅüÜÅüÜÅûÛÄûÛÄûÛÄûÛÄûÜÃúÛÂúÛÂúÛÂùÚÁùÚÁøÙÀøÙÀúØÀúØÀù׿ù׿ù׿ù׿øÖ¾øÖ¾ö×¾ö×¾ö×¾õÖ½õÖ½õÖ½ôÕ¼ôÕ¼õÓ»õÓ»ôÒºôÒºóѹóѹóѹòиûáÉûáÉüâÊüâÊüâÊüâÊüâÊüâÊüâÊüâÊüâÊüâÊüâÊüâÊüâÊüâÊþâÊþâÊþâÊþâÊþâÊþâÊþâÊþâÊÿàÉÿàÉÿàÉÿàÉÿàÉÿàÉÿàÉÿàÉþßÈÿàÉÿàÉþßÈþßÈþßÈþßÈþßÈþßÈþßÈþßÈþßÈþßÈþßÈþßÈþßÈþßÈþßÈþßÈþßÈþßÈþßÈþßÈþßÈý߯ý߯ý߯ý߯üÞÅüÞÅüÞÅüÞÅüÝÆüÝÆüÝÆüÝÆýÞÇýÞÇüÝÆüÝÆüÝÆüÝÆüÝÆüÝÆüÝÆüÝÆüÝÆüÝÆûÝÄûÝÄûÝÄûÝÄûÝÄûÝÄûÝÄûÝÄüÜÅüÜÅüÜÅüÜÅüÜÅüÜÅüÜÅüÜÅûÜÃúÛÂúÛÂúÛÂûÜÃúÛÂúÛÂúÛÂúÛÂùÚÁùÚÁùÚÁøÙÀøÙÀøÙÀ÷Ø¿÷Ø¿÷Ø¿ö×¾õÖ½õÖ½õÖ½ôÕ¼ôÕ¼óÔ»óÔ»óÔ»òÓºòÓºòÓºòÓºñÒ¹ùâÈùâÈùáÉùáÉüáÌüáÌüáÍüáÍûáÉûáÉûáÉûáÉüâÊüâÊüâÊüâÊüâÊüâÊüâÊþâÊýáÉýáÉýáÉÿàÉýãÈýâÈýâÈýâÈýâÈýâÈýâÈýâÈÿáÈÿáÈÿáÈÿáÈÿáÈÿáÈÿáÈÿáÈþáÀúàÆøÞÊþÞÇÿãÄÿâÃûÝÃöÚÆúÞÅÿãÈúÝÂ÷äÊùÝÎÿÛÎÿÞÈñåÃÿÞÉÿßÈÿßÈÿßÈþÞÇþÞÇþÞÇþÞÇþÞÇþÞÇþÞÇþÞÇþÞÇþÞÇþÞÇþÞÇþÞÇþÞÇþÞÇþÞÇýÝÆýÝÆýÝÆýÝÆüÝÆüÝÆüÝÆüÝÆüÝÆüÝÆüÝÆüÝÆûÜÅûÜÅûÜÅûÜÅúÛÄúÛÄúÛÄúÛÄúÛÄúÛÄúÛÄúÛÄúÛÄúÛÄúÛÄúÛÄúÛÄúÛÄúÛÄúÛÅøÙÂ÷ØÁ÷ØÁ÷ØÁ÷Ø¿÷Ø¿÷Ø¿ö×¾õÖ½ö×¾õÖ½ôÕ¼ôÕ¼ôÕ¼ôÕ¼óÔ»óÔ»óÔ»òÓºòÓºùãÊúâÊúâÊúâÌüáÌüáÌüáÍüáÍüâÊüâÊüâÊüâÊüâÊüâÊüâÊüâÊüâÊüâÊüâÊüâÊýáÉýáÉýáÉýáÉýáÉýáÉýáÉýáÉýáÉýáÉýáÉýáÉÿàÉÿàÉÿàÉÿàÉÿàÉÿàÉÿàÉÿàÉÿâÄýâÈûàÌÿàÉÿÞÅÿæÈúÜÃöàÍþéÖÿãÉûÝÁùæÊúßËÿÛÎÿÞÈõäÃÿÞÉþßÈþßÈþßÈþßÈþßÈþßÈþßÈþßÈþßÈþßÈþßÈýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇüÝÆüÝÆüÝÆüÝÆüÝÆüÝÆüÝÆüÝÆüÝÆüÝÆüÝÆüÝÆûÜÅûÜÅûÜÅûÜÅüÝÆüÝÆüÝÆüÝÆûÜÅûÜÅûÜÅûÜÅúÛÄúÛÄúÛÄúÛÄúÛÄúÛÄúÛÄúÛÄøÙÂøÙÂ÷ØÁ÷ØÁøÙÀøÙÀ÷Ø¿÷Ø¿ö×¾ö×¾õÖ½õÖ½õÖ½ôÕ¼ôÕ¼ôÕ¼óÔ»óÔ»óÔ»óÔ»úäËúäËûãÍûãÍûãÍýâÍýâÎýâÎýãËýãËýãËýãËüâÊüâÊüâÊüâÊüâÊüâÊüâÊüâÊþâÊþâÊþâÊþâÊþâÊþâÊþâÊþâÊþâÊþâÊþâÊþâÊÿàÉÿàÉÿàÉÿàÉÿàÉÿàÉÿàÉÿàÉþâÃùàÈúßÊþßÈþàÆÿãÇ÷ßÌìÜÑóãÒÿãÏÿáÅøâÈûàÍÿÞÌÿàÉöäÇÿàÉÿàÉÿàÉÿàÉþßÈþßÈþßÈþßÈÿàÉÿàÉÿàÉÿàÉýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇüÝÆüÝÆüÝÆüÝÆýÞÇýÞÇýÞÇýÞÇüÝÆüÝÆüÝÆüÝÆûÜÅûÜÅûÜÅûÜÅúÛÄúÛÄúÛÄúÛÄùÚÃùÚÃøÙÂøÙÂùÚÁøÙÀøÙÀøÙÀ÷Ø¿ö×¾ö×¾ö×¾ö×¾õÖ½õÖ½õÖ½ôÕ¼ôÕ¼ôÕ¼óÔ»úãÍúãÍúãÍûãÍüäÎüäÎþãÏþãÏûãÍûãÍûãÍûãÍûãÍûãÍûãÍûãÍûãÍûãÍýâÍýâÍüáÌþáÌþáÌþáÌþâÊþâÊþâÊþâÊþâÊþâÊþâÊþâÊþâÊþâÊþâÊþâÊþâÊþâÊþâÊþâÊýâÇûáÉûàÌÿàÉÿåÉøÝÅúíÞnhcòëÞøÜËÿäÊøàÅúßËÿÞÌÿßËøäÆÿàÉÿàÉÿàÉÿàÉþßÈþßÈþßÈþßÈþßÈþßÈþßÈþßÈþßÈþßÈþßÈþßÈþßÈþßÈþßÈþßÈýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇüÝÆüÝÆüÝÆüÝÆûÜÅûÜÅûÜÅûÜÅûÜÅûÜÅûÜÅûÜÅúÛÄùÚÃùÚÃùÚÃùÚÁùÚÁùÚÁøÙÀøÙÀö×¾ö×¾÷Ø¿ö×¾ö×¾õÖ½õÖ½õÖ½õÖ½ôÕ¼ôÕ¼úâÎúâÎúâÎúâÎúáÍüãÏüäÎûãÍüäÎüäÎüäÎüäÎûãÍûãÍûãÍûãÍûãÍûãÍûãÍýâÍýâÍýâÍýâÍÿâÍüâÊüâÊüâÊüâÊûáÉüâÊýãËûâÊýáÉýáÉþâÊÿãËþâÊþâÊþâÊþâÊþâÊüáÍüáÌÿãÉýàÄñÝÇÚÖÌ]eg•˜ŽòÛÌÿÜÄÿæÊøáÉÿàËÿßËúâÈÿàÉÿàÉÿàÉÿàÉÿàÉÿàÉÿàÉÿàÉþßÈþßÈþßÈþßÈýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇþßÈþßÈþßÈþßÈýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇþßÈþßÈýÞÇýÞÇýÞÇýÞÇüÝÆüÝÆüÝÆüÝÆûÜÅûÜÅûÜÅûÜÅúÛÄúÛÄúÛÄúÛÄúÛÄúÛÄúÛÄúÛÄúÛÄúÛÄùÚÃùÚÃùÚÁùÚÁøÙÀøÙÀøÙÀøÙÀ÷Ø¿÷Ø¿ö×¾ö×¾õÖ½õÖ½ôÕ¼ôÕ¼ôÕ¼ôÕ¼üæÔûåÓüäÐúâÎûãÏüãÏýåÏüäÎüäÎüäÎüäÎüäÎûãÍûãÍûãÍûãÍûãÍûãÍûãÍûãÍýâÍýâÍýâÍýâÍýâÍýâÍýâÍýâÍýâÍþãÎþãÎýâÍþáÌþáÌþáÌþáÌþáÌþáÌþáÌþáÌûáÌüáÌüáÌÿâÉùàÅôæÓ¬«UdlYheÿìáÿäÐþáÅùäÉþáÍÿàÌþâÊýáÉýáÉýáÉýáÉýáÉýáÉýáÉýáÉþâÊþâÊþâÊþâÊýáÉýáÉýáÉýáÉüàÈüàÈüàÈüàÈüàÈüàÈüàÈûàÈþßÈþßÈþßÈþßÈþßÈþßÈýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇüÝÆüÝÆüÝÆüÝÆüÝÆüÝÆüÝÆüÝÆüÝÆüÝÆüÝÆüÝÆúÛÄúÛÄúÛÄúÛÄúÛÄúÛÄúÛÄùÚÃúÛÂúÛÂúÛÂùÚÁøÙÀøÙÀøÙÀøÙÀ÷Ø¿ö×¾ö×¾ö×¾ö×¾õÖ½õÖ½ôÕ¼ùãÑùãÑùãÑûãÏûãÏûãÏûãÍûãÍüãÏüãÏüãÏüãÏüãÏüãÏüãÏüãÏûãÏûãÏüãÏüãÏüãÏþãÏþãÏþãÏýâÍýâÍýâÍýâÍýâÍýâÍýâÍýâÍýâÍýâÍüáÌüáÌüáÌüáÌüáÌüáÌüáÌüáÌüâÊþãÉÿèÍîâЊŠ@Vg:PMÿõîÿÞÉÿäÆùåÈüáÍÿáÌÿáÍýáÉýáÉýáÉýáÉýáÉýáÉýáÉýáÉýáÉýáÉýáÉýáÉüàÈüàÈüàÈüàÈýáÉýáÉýáÉýáÉýáÉýáÉýáÉýáÉÿàÉÿàÉÿàÉÿàÉÿàÉþßÈýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇüÝÆüÝÆüÝÆüÝÆûÜÅûÜÅûÜÅûÜÅûÜÅûÜÅûÜÅûÜÅûÜÅúÛÄúÛÄúÛÄûÜÃûÜÃúÛÂúÛÂùÚÁùÚÁùÚÁøÙÀ÷Ø¿÷Ø¿÷Ø¿ö×¾øÙÀ÷Ø¿ö×¾õÖ½þç×þç×þèÖÿçÖÿçÓýåÑûäÎýåÏüäÐüäÐüäÐüäÐûãÏûãÏûãÏûãÏûãÏûãÏüãÏüãÏüãÏþãÏþãÏþãÏýâÍýâÍýâÍýâÍþãÎýâÍýâÍþãÎüáÌýâÍýâÍýâÍýâÍýâÍýâÍýâÍýâÎýâÎýãËÿäÉøàÆäÚÉlyzB[n>VWIJ¬ÿÞÉÿ寸äÈùâÊÿßÎÿáÌþâÊþâÊþâÊþâÊþâÊþâÊþâÊþâÊýáÉýáÉýáÉýáÉýáÉýáÉýáÉýáÉýáÉýáÉýáÉýáÉþáÉýáÉýáÉýáÉþßÈþßÈþßÈþßÈþßÈþßÈÿàÉÿàÉþßÈþßÈþßÈþßÈýÞÇýÞÇýÞÇýÞÇüÝÆüÝÆüÝÆüÝÆüÝÆüÝÆüÝÆüÝÆûÜÅûÜÅûÜÅûÜÅûÜÅûÜÅúÛÄúÛÄúÛÂúÛÂúÛÂúÛÂúÛÂúÛÂùÚÁùÚÁøÙÀøÙÀ÷Ø¿÷Ø¿ö×¾ö×¾ö×¾ö×¾úêÒýëÚþëÜùçÖõåÎøçÏûåÓüá×øãÎùäÏùåÐùåÏüäÐüäÐüäÐüäÐüäÎüäÎýåÏýåÏüäÎüäÎüäÎüäÎüãÏüãÏüãÏüãÏüãÏüãÏüãÏüãÏüåÎüäÎüäÎüäÎûãÍûãÍûãÍúãÍÿáÈõâÎöâÍÿåÃÿèÏA;=?LWI]`AU[Ž’“ôãÛúÝÍÿãÈüãÉûâÉþßÎýãÇýâÈýâÈýâÈýãÈþãÉÿäÊÿäÊþãÉþãÉþãÉþãÉýâÈýâÈýâÈýâÇøßËïæÉÿàÂÿäËÙáÈøãÒÿØÉðèÈýàÈüàÈüàÈüàÈüàÈüàÈüàÈüàÈûßÇûßÇûßÇûßÇûßÇûßÇûßÇúßÇýÞÇýÞÇýÞÇýÞÇûÜÅüÝÆýÞÇýÞÇüÝÆüÝÆûÜÅûÜÅûÜÅûÜÅûÜÅûÜÅúÛÄúÛÄùÚÃùÚÃùÚÃùÚÃùÚÃøÙÂùÙÂøØÁøØÁøØÁ÷×À÷×À÷×ÀöÖ¿ùéÙ÷ç×ö娸è×øêÔûêÕýéØýçÛÿñÛÿîÙÿëÖýèÓûãÏûãÏûãÏûãÏüäÎüäÎüäÎüäÎüäÎüäÎüäÎüäÎýäÐýäÐýäÐýäÐüãÏüãÏüãÏüãÏüäÎüäÎüäÎüäÎûãÍûãÍûãÍûãÍÿäÈ÷ãÏ÷ãÍÿæÆüåÏÉÇÅGV`=QV@TY.23D2+óØÆÿãËüãÉüâÊþßÎÿãËÿãËÿãËÿãËÿãËÿãËþâÊþâÊþâÊþâÊþâÊþâÊþâÊþâÊþâÊþâÊþßÈõçËþÛÄüâÑÝç×îÚÏÿßÌõåÄüßÈüàÈüàÈüàÈüàÈüàÈüàÈüàÈüàÈüàÈüàÈüàÈûßÇûßÇûßÇûßÇýÞÇýÞÇýÞÇýÞÇýÞÇüÝÆüÝÆüÝÆüÝÆüÝÆûÜÅûÜÅûÜÅûÜÅûÜÅûÜÅúÛÄúÛÄúÛÄùÚÃúÛÄùÚÃùÚÃùÚÃøÙÂøÙÂ÷ØÁ÷ØÁ÷ØÁ÷ØÁö×Àö×Àúîâùîâùíß÷ëÙøêØúêÙùéÚøèÛúåÏùäÏùäÏúåÐüäÐüäÐüäÐüäÐýåÏýåÏüäÎüäÎüäÎüäÎüäÎüäÎüãÏüãÏüãÏüãÏüãÏüãÏüãÏüãÏüäÎüäÎüäÎüäÎüäÎüäÎüäÎüäÎÿäÈúâÑúâÎÿäÈÃ°š¶¸»_pzGV]@T\MRS¡“Š÷ÞËýâÊüäÉüáÍüáÎüâÉüâÊüâÊûâÊýãËýãËüâÊûáÉþâÊþâÊþâÊþâÊþâÊþâÊþâÊþâÊÿáÅùáÈýâÒêÝÙhwvñäàÿÝÌùãÁýáÊýáÉýáÉýáÉýáÉýáÉýáÉýáÉüàÈüàÈüàÈüàÈûßÇûßÇûßÇûßÇýÞÇýÞÇýÞÇýÞÇýÞÇýÞÇüÝÆüÝÆýÞÇüÝÆüÝÆüÝÆûÜÅûÜÅûÜÅûÜÅûÜÅúÛÄúÛÄúÛÄúÛÄúÛÄùÚÃùÚÃùÚÃùÚÃøÙÂøÙÂøÙÂ÷ØÁ÷ØÁ÷ØÁõíéùðæúòáýñßÿðàþîáûëßùêÚüçÒúåÐùäÏûæÑÿèÔÿèÔÿèÔÿèÔÿçÑÿçÑþæÐýåÏýåÏýåÏýåÏýåÏüãÏüãÏüãÏüãÏýäÐýäÐýäÐýäÐüäÎüäÎüäÎüäÎüäÎüäÎüäÎüäÎÿåÈùâÑûáÑÿåÉìßÍ›\m|M[d:T\LSVÿñëöÝÍüäÊûãËûãÍýâÎýãËýãËýãËýãËüâÊüâÊýãËýãËþâÊþâÊþâÊþâÊþâÊþâÊþâÊþâËÿãÅÿàÊöâÚ¦¯³Viu¯©¯ýÞÐþå¿ýáÊýáÉýáÉýáÉýáÉýáÉýáÉýáÉüàÈüàÈüàÈüàÈüàÈüàÈüàÈüàÈüàÈüàÈüàÈüàÈúßÇûßÇûßÇûßÇûßÇûßÇúÞÆúÞÆúÞÆúÞÆúÞÆúÞÆùÝÅùÝÅøÜÄøÜÄøÜÄøÜÄøÜÄ÷ÛÃúÛÄùÚÃùÚÃùÚÃøÙÂøÙÂøÙÂ÷ØÁõìïôìåøñÞùîÚøéÙúèÞùêÝøê×þèÓÿëÖÿì×þéÔýäÐýåÑýåÑýåÑûãÐüäÐüäÐüäÐüäÐüäÐüäÐüäÐýäÐýäÐýäÐýäÐüãÏüãÏüãÏüãÏüãÏüãÏüãÏüãÏüãÏüãÏüãÏüãÐõâÄûäÓþãÕþáË¢šŒ /5G\nJS_<ZgFOWËÁ½º¤”ÿîØûæÌüäÎúâÎýãËýãËýãËýãËýãËýãËýãËýãËüâÊüâÊüâÊüâÊüâÊüâÊüâÊüâËýãÂûÙÅóæâ†›¥K`tSS_üêàÿåÅúáÉûáÉûáÉûáÉûáÉûáÉûáÉûáÉúáÉüâÊûáÉùßÇúàÈúàÈúàÈúàÈûßÇûßÇûßÇûßÇûßÇûßÇûßÇûßÇúÞÆúÞÆúÞÆúÞÆùÝÅùÝÅùÝÅùÝÅùÝÅùÝÅùÝÅùÝÅøÜÄøÜÄøÜÄøÜÄúÛÄúÛÄúÛÄúÛÄùÚÃùÚÃøÙÂøÙÂÑÆÑöìåøí×ùëÔüæ×úãÜ÷äÕõèÐúåÐûæÑûæÑúåÐýåÑýåÑýåÑýåÑüäÐüäÐüäÐüäÐüäÐüäÐüäÐüäÐýäÐýäÐýäÐýäÐýäÐýäÐýäÐýäÐýäÐýäÐýäÐýäÐüãÏüãÏüãÏüãÐùåÇøàÏÿáÕõçÑÓÎÁv–1EYPVd;ZiGQYogcÿîáùàÌûåËûäÎüãÏûãÍûãÍûãÍûãÍûãÍûãÍûãÍûãÎýâÍýâÍýâÍýâÍüáÌüáÌüáÌýáÎõãÅÿÚÍßÖÓ|ž¥?RePUbâáØúàÇûáÉûáÉûáÉûáÉûáÉûáÉûáÉûáÉûáÉûáÉûáÉúàÈúàÈúàÈúàÈúàÈüàÈüàÈüàÈüàÈûßÇûßÇûßÇûßÇúÞÆúÞÆúÞÆúÞÆúÞÆúÞÆúÞÆúÞÆùÝÅùÝÅùÝÅùÝÅøÜÄøÜÄøÜÄøÜÄøÜÄøÜÄøÜÄøÜÄ÷ÛÃ÷ÛÃ÷ÛÃöÚÂŒ|‹éÝ×óèÌýìÐþãÖýàÚúãÒùéËûæÑûæÑüçÒûæÑýåÑýåÑýåÑýåÑýåÑýåÑýåÑýåÑýåÑýåÑýåÑýåÑþåÑþåÑþåÑþåÑýäÐýäÐýäÐýäÐýäÐýäÐýäÐýäÐüãÏüãÏüãÏýãÐøéÇþåÕ÷ÕÉÿíÞÌÍÃ|˜Ÿ@ZnKM\=_nJU`C<;ÿÿòùäÎøäÎüäÎüãÏüäÎüäÎüäÎüäÎüäÎüäÎüäÎüäÎýâÍýâÍýâÍýâÍüáÌüáÌüáÌþáÌéàÊÿßÓ³§9=APbTYf–£œêÔÃýâÊüâÊüâÊüâÊûáÉûáÉûáÉûáÉüâÊûáÉûáÉûáÉûáÉûáÉûáÉûáÉúàÈúàÈúàÈúàÈùßÇùßÇùßÇùßÇùßÇùßÇùßÇùßÇøÞÆøÞÆøÞÆøÞÆ÷ÝÅ÷ÝÅ÷ÝÅ÷ÝÅ÷ÝÅ÷ÝÅ÷ÝÅ÷ÝÅøÜÄøÜÄøÜÄøÜÄøÜÄøÜÄ÷ÛÃ÷ÛÃjWiïàÚøêÍÿîÑÿäÕÿâÜÿæ×üêÊûæÒûæÑûæÑûæÑýåÑýåÑýåÑýåÑýåÑýåÑýåÑýåÑýåÑýåÑýåÑýåÑþåÑþåÑþåÑþåÑýäÐýäÐýäÐýäÐýäÐýäÐýäÐýäÐýäÐýäÐýäÐþäÐ÷êÆþãÕþØÐÿçÕÏÑÆw˜¡]v‰`bsChx[irކ„úæÚûåÍúäÎúåÏýäÑüäÎüäÎüäÎüäÎüäÎüäÎüäÎüäÎýâÍýâÍýâÍýâÍýâÍýâÍýâÍÿâÍêèÒ纲¾¹³bŒŽ;JXZbn°Á»îßÏýâÉüâÊüâÊüâÊüâÊüâÊüâÊüâÊýâÊûáÉûáÉüâÊûáÉûáÉûáÉûáÉúàÈúàÈúàÈúàÈúàÈúàÈúàÈúàÈùßÇùßÇùßÇùßÇøÞÆøÞÆøÞÆøÞÆøÞÆøÞÆøÞÆøÞÆ÷ÝÅ÷ÝÅ÷ÝÅ÷ÝÅùÝÅùÝÅùÝÅùÝÅùÝÅøÜÄøÜÄøÜÄCHVèÚÔÿæÔ÷ãÓöåÔýçÎýçÍôä×öæÑöæÑöæÑùæÑ÷åÐøæÑûæÑüçÒýåÑýåÑýåÑýåÑýåÑýåÑýåÑýåÑýæÐýæÐýæÐýæÐüåÏýæÐýæÐÿçÑòêÌþêÈûçÎóäÚøáÒÿäÆüàËóèãÐãÚÌßÚ¼ÕÕ®ËÔŒª¼˜±Ä‡žµ–³k…†;W^Nir/GQ¤¶»ÒÙÖîíßçßÍùåÊûåÌûåËûäÎûãÏüãÏüãÏüáÓüéÅüåËúæËûãÐùâÎûâÎûãÍþãÊóáÊïçࡹÃjˆ™UT_MZ[x†ôÜÜúãÌúâÌùáÎüáÍüáÍüáÎúâÌúâÍøãÊùãÊúâÊúâÊûáÉûáÉþáÉþáÉùáÌùáËùáËùáÌøàÊøàÊøàÊøàË÷àÆ÷àÆ÷àÆ÷àÆõßÅ÷àÆ÷àÆøáÇößÅößÅößÅößÅößÅößÅößÅößÅ÷ÞÄ÷ÞÄ÷ÞÄ÷ÞÄõÜÂ÷ÞÄöÝÃõÜÂJM[÷éãýåÑ÷ãÒ÷åÔýæÐýçÎõåÕúæÑúæÑùæÑùæÑýçÒüçÒûæÑûæÑûæÑûæÑûæÑûæÑûæÑûæÑûæÑûæÑûæÐûæÐûæÐûæÐüçÑüçÑúæÐûæÐöæÔÿæÍÿåÒöäØúæÕúãÉäÛ˘¥¦”¤±‘£°¢´}˜©‰¥¶y˜©z˜©x™§\mx<R^8M]K\iJVaV[^onjîéåþèÌúæÍýåÐüåÏüäÐýäÐýäÐýãÓüåÊüäÌûäÎüãÏýäÐýäÑÿåÌÿäÍÿèËüçÞmƒˆ"?PSXiN^`F]YåÎÌúäÉûãÎþâÍþãÍüáÌüáÌúâÌúâÌùãÊùãÊúâÊúâÊûáÉûáÉûáÉþáÉùáËùáËùáËùáËøàÊøàÊøàÊøàÊøàÈøàÈøàÈøàÈ÷ßÈ÷ßÇ÷ßÇ÷ßÇ÷ßÇ÷ßÇ÷ßÇ÷ßÇöÞÆöÞÆöÞÆöÞÆ÷ÝÅ÷ÝÅ÷ÝÅ÷ÝÅ÷ÝÅ÷ÝÆ÷ÝÅ÷ÝÅNQ_öéãþéÕüè×øæÕþçÑþèÏöæÖúçÒúçÒüçÒüçÒýèÓþæÒþæÒýåÑüçÒüçÒüçÒüçÒüçÒüçÒüçÒüçÒüçÒüçÒüçÒüçÒýèÓüçÒüçÒûæÑöáÝÿäÓÿäÑûäÖôãÒöêÔ´¾´v—¥‰¿‚˜·{•°{›µs’¨¡°~¡]„ŠR_q>M_BSg=L`KXhFO]OU]»ÁÉþåÌúåÏùåÏüåÏüäÐüäÐýäÐýäÐûäÎûäÎýãÏüãÏþãÏþãÎÿäÌÿåËþéÄΰŸª½Ãs‘§KRhL]h#>:ÿôôûçÌûåÌüäËÿãÏüáÌýáÌúâÌùáÎùãÊùãÊúâÊúâÊùâÊüâÊüâÊüâÊùáËùáËùáËùáËùáËùáËùáËùáÌøàÈøàÈøàÈøàÈøàÈøàÈ÷ßÇöÞÆöÞÆöÞÆöÞÆöÞÆ÷ßÇ÷ßÇ÷ßÇ÷ßÇ÷ÝÅ÷ÝÅ÷ÝÅ÷ÝÅ÷ÝÅöÜÄöÜÄ÷ÜÄJM[çÙÓÿñÝøäÓøæÕþçÑþèÏöæÖýæÔýæÔüæÔüæÔþæÔþæÔþæÔÿçÖüçÒüçÒüçÒüçÒüçÒüçÒüçÒüçÒüçÒüçÒüçÒüçÒüçÒüçÒüçÒþèÓôäÝÿæÑÿèÎÿæÒþêÕøêÓ ¨¥v–«}™µy•¯x“®|˜°s¥ƒ¡²…£^‡^gv@Q]>N^<L^<M]TaoMZdƒ’þäËúåÐúåÐùåÐüäÐüäÐüäÐüäÐúäÓùäÒüäÒýäÐÿäÐÿäÏÿäÐÿäÍÿóÌýÛ̼ÄmФgnˆ`w„.OJðæåôâÌõäÌúãÎýãÊýãÊýâÍûãÍúâÎûãÍûãÍûãÍûãÍúâÌúâÌúâÌúâÌúâÌúâÌúâÌúâÌùáËùáËùáËùáËøàÈøàÈøàÈøàÈ÷ßÇøàÈøàÈùáÉ÷ßÇ÷ßÇ÷ßÇ÷ßÇ÷ßÇ÷ßÇ÷ßÇ÷ßÇöÞÆöÞÆöÞÆöÞÆöÞÆôÝÅõÞÆ÷ßÇ,/=ˆztnZþíÜøæÕþçÑþèÏöæÖöâÐôàÎÿìÚýèÖüæÔþæÔþæÔþæÔüçÒüçÒüçÒüçÒüçÒüçÒüçÒüçÒüçÒüçÒüçÒüçÒüçÒüçÒüçÒýçÒéåÔÿìÑÿèËÿçÒúãÌþèÒª§¤q‡œ†¦®§µ^w†m„–^s…CXkCZj|“£Obf<MVBV\BU\@TZGXaCW]r†ÿçÒ÷äÒ÷ãÍýèÓúæÑþåÑýåÑþåÑ÷äÒüæÔþæÔýäÐýâÎùàÌûåÑüèÔÿåÇóßÕm‚:Zt‰©Mfs.QRQINÓ̺ßÔÃòãÍ÷àÊþãËþâÍúãÍ÷ãÎûãÍûãÍûãÍûãÍúãÍúãÍùâÌùâÌùâÌùâÌùâÌùâÌøáËøáËøáËøáËøâÉøâÉøâÉøãÉöàÇöàÇöàÇöàÇ÷áÈ÷áÈ÷áÈ÷áÈöàÇöàÇ÷áÈ÷âÈ÷ßÇ÷ßÇöÞÆöÞÆõÝÅõÝÅöÞÆöÞÆ?BPùëåûàÌïÚÉøæÕþçÑþèÏöæÖöåÒÿðÝñÝËþé×úæÔüæÔüæÔüæÔúçÒúçÒúçÒúçÒúçÒúçÒúçÒúçÒúæÕúæÔúæÔúæÔúæÔúæÔúæÔúæÔïéÔúéÍÿëÏøç×ôßÑùéØ˜––…—°Yxy%*=Q\-?M<N_yŠ›Yj{CTfTglATZAT[AT[@RY!59@PUu‰ÿèÓýíÚôßÍýêÙüçÑúæÑýåÑþåÑøåÓûåÓýåÐþåÑüäÏùåÓ÷è×íàÑðéÜ®¦¨ªÈÖPp…£§ÀK`k*PS|}ƒ¢¤›MJ@ýðáúèÒûãÎûãÊüãÍúâÏûãÍûãÍûãÍúäÍùâÌûãÍøãÍòÞÈùâÌùâÌùâÌùâÌøáËøáËøáËøáËøáËøáËøáËøáË÷àË÷àË÷àË÷àË÷àÊ÷àÊ÷àÊ÷àÊößÊößÊ÷àÊ÷àÊ÷ßÊ÷ßÉ÷ßÉöÞÉöÞÈöÞÈöÞÈöÞÈDGUóåßüãÏþêÙøæÕþçÑþèÏöæÖùë×ôåÒ÷èÕìÛÈ÷æÓ÷çÔúæÔúæÔúçÒúçÒúçÒúçÒúçÒúçÒúçÒúçÒúæÔúæÔúæÔúæÔúæÔúæÔúæÔúæÔûêÔÿéÏôâÓëáàïìëäáÝœ u˜²…Ÿ¬¦¾Ïœ²Ä©½Ï¶ÅÙj~Jape€‹o‰“VlxF\cGW`2@J6CK-6A$ì—ôßÏÿîÝ÷ãÑûåÔûæÑúæÑþåÑùçÑûæÑýæÐýåÑýçÕðàÐòêÞåÝаÅʯ¸È³Çx™¬wy‹RhlCkm˜œ¨O\]Z`\ÈĺñâÑüäÎüäÌüäÎûäÎüãÏüãÏüãÏûãÐûâÏûæÒöàÌñÜÇúãÍùâÌùâÌùâÌùâÌùâÌùâÌùâÌøáËøáËøáËøáËøáËøáËøáËøáËøáËøáËøáËøáË÷àÊ÷àÊ÷àÊ÷àÊøàÊ÷ßÉ÷ßÉ÷ßÉ÷ßÉöÞÈöÞÈõÝÇGIWóãÝþåÐÿìÛùçÖÿèÒÿéÐ÷ç×÷é×÷èÕÑ¿ÿóà÷çÖøæÕ÷æÖ÷æÕúçÓûçÑüèÑúçÒúçÓúçÒúçÒúçÒûæÕûæÔûæÔúæÔúæÕúæÔúæÔúæÕÿäÕÿâÒûèãÒÐÙŸ¥°žž‚¡«m¢¼z’°„›º€•±~‘¬‚—7R_3T[6]]<RiAYjBTe>N\<GS">BPEJ]ÿÿÿóßÍýéØùåÒüæÔüçÒüçÒüçÒûçÒûæÏýæÐÿèÑôåÑöéÚðëঠ“‰¨¼Œ¤¹y¢ºSu…qm|]pt:dfNU`^mvZcdÅûæÙÉúåÎþåËýäÌúäÎüãÏüãÏüãÏûâÏûçÒñÜÇüèÒéÕ¿ýäÍûãÍúãÍúãÍùâÌùâÌùâÌùâÌùâÌùâÌùâÌúâÌøáËøáËøáËøàËøáËøáËøáËøáËøáËøàÊ÷àÊ÷àÊ÷àÊ÷àÊößÉößÉößÉößÉõÞÈôÝÇ?TXÃÎÍçåÝùë×ÿèÑüèÓõç×ñè×çÞ˽ÇÄZp~XdrîßÞþàÑÿßËÿíÝúë¼êãâäâí÷èÔÿæÇüàÒúäÚýìËîêÍêè×ïêÖÿíÏýçÈùèÓùêÑûéÁûæÉÿéØèçänŽ•{¢µˆœ¶œ¶—ªuŒ¡sŠŸxŒ¡n„•e|Œ7N]>R^=Q_8MR@U\@V]@S[9MU/6;MV<NWw–ØãåïæåûãÙÿæÑÿçÎÿæÒÿã×èäÝôåÖ÷äÖöä×þçÐÿëÊïèÞ{”¬…¨Á¬Á˜®Â]j~CTdYhwSak<NXSkd^fuµº´áåÐÒÎÚåÚÚòçÅÿäÒöãÑöãÒøäÏýäÌþåÉõæÑàÞÚU`kÙÞØäàÏûæÐýäËûáÍ÷áÐ÷âÎ÷åÈõãÌõãÌõãÌõäÌóâËõãÌõãÌöåÎõàÊöáË÷âÌ÷âÌöáËöáËöáËöáË÷àÊ÷àÊ÷àÊ÷àÊößÉøàÊ÷àÊöÞÈBTZJSWöóëôãÓÿçÓÿèÒùèÓöèÖóê܇Œ‹PdlEU^ïêéÿîÝüéÔöêÓó鯼º¸\\cöìÞýèÎüâÓ÷åØýîÒÚÙÍÛØÖìãÚüãÏþëÕîâÕêâÖüðÞÿòÕíÚÊåãàŒ¦°…¨¹‹žµ„”©š¬wŒ¡k€•|’£f}Thw>U`@Vc:P\AT[@SZ@RZEX`?OYGXaBS\DT^9WRHX[”‘’ÿñéýçÑÿèÎùçÒõæ×òæÖûçÑýçÑøæÖùãÍÿéËâàÔ“§¸…©½oŒ¢—°Åh|DTdfv‚DU^9ITIa[HQb¢¨£ÚàÑF>HôéèöêÊÿäÔøäÒøäÒ÷åÐüæÍüèËõåÐÆÂ¼fpz¼À·ïéÛìÚÅþäËûâÎøâÐõãÎøäËöäÍöäÍöäÍöäÍõãÌõãÌõãÌõãÌ÷âÌ÷âÌöáËöáËöáËöáËöáËöáËõàÊõàÊõàÊõàÊõàÊõáËöáËõàÊ9JX<FMuppíßÓýçÕÿèÒþèÒùéÑåãÜpz~>T\@S[ƒˆ†åßÒïêÖèæÍæéÔ}ƒ‡U\i‰‰‚òçÑøäÓöåÙíçÓƒŒZ]höïñüåÕüæ×îéé²¶¹ÓÕÖñäÍöêßÍÎІ¤«ˆ¦¹}‘¦o”uŽŸx£uŒ| au„e|‡8KV@S_F[bFV_>OXIZcFW`GU^GV_ET]ES\7Y^G[c@FJÿüõõçÕõêÎõèÒïèÖøæÐÿçÌþçÍôäÔöéÖõåÑÐÎÇ•¨¸~ž´{šž¸ÉLdt=P]_q|?RY;NWCZYWarœšÒÝÏ_^lÏËÍõêÐýäÕ÷äÒøäÒ÷åÐüæÌþéÏîáͧ¨¦Ubl•š–ûöêýíØüèÒúáÍöâÐöãÎøäÊöãÎöãÎöãÎöãÎöãÎöãÎõâÍõâÍøãÍ÷âÌ÷áËöáËöáËöáËöáËöáËöáËöáËöáËöáËõàÊôßÉôßÉõàÊ4DTGQ[IHMòçä÷æÙûçÕûèÓúéÒÂÌÎ`ruBZbAT\]adîåÝðâÑöëÔÀÔËdpxKXeZcgöñæùåÓñå×ÑÒÄlz‹O[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äåç—¡“¯¾ ²’¥·kz‹x”¡Tj|y‘ ‚•¦BWfG^i?R]@U\9NV0?L7GS0>J#1=6DP#/%1"-9"6F2<K74?ÿúûøè×öæÎýì×øåÔñåÙûèÐòåÒÜã䣱¾¦²½‰š§~šµw‘ † °c}‹H`l?UaAW^BR[>PWDWX;F\)8;¨½·GRgŒ—íèÒüäÖùäÏ÷ãÒôäÏøæÏöåÌÿöè©°Ug{T]]ÛÚÔíßËþèÒ÷äÏõäÑõäÑøäÏóãÎôäÏôãÎôãÎóâÍóâÍóâÍóâÍõâÍõâÍõâÍõâÍôáÌõâÍõâÍóàËöáÌöáÌöáÌöáÌõàËõàËõàËõàË,9G!,:7=H #,/.3›šš¹»²ÀÁ¸a|ˆJbh?UZ>MTEDS¬ ªýæäüáÒj™HV^;IU:P`mtsúçÔïâ×r‡ŒUnt4OYGVXááÕÓØÌgz~>[e9TZ7EIÝäîxƒ’8I8IŽ¢}Œv“¡ˆ µz’¤cz‰qˆ—Qit<R]@Va6NU<KW<LX3CO1AM/<H:HT;IU(6B(:G*2A'%0F85áÑ¿ÿóÛúäÏþèØìæÛüèÓòê×¾ËÐu‘¨…Ÿ²—©†¡¼xŽœcy‰Uny=VbCVbG[b?NWDPYHZZEPe@QSPhbP_tZbjóî×üàÔûæÏùæÐöåÑöæÎ÷éÑðèÜ{ƒ†Uk€\hnÛÜ×èßÎôäÌõäÏóäÑòãÒõäÑôãÐõäÑõäÒôãÐôãÐôãÐôãÐôãÑõâÍõâÍõâÍõâÍôáÌõâÍõâÍôáÌôáÌôáÌôáÌôáÌôáÌôáÌôáÌôáÌ?KT.:F0:H1;JCMW?JQ>LPCRP8KY:NR>RR=PW?M\BIVôôöøóèe™IRULU_/J]WaeÿîÚìàÓx“£I_c@[h8LXqxw¦®®q„‘LdtIZ`2LTHQ`’¡²‘¯ÀNj{.?Pet„^|†rŠ n‡œx¢oˆ˜`{‰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/TdMRSKPY4OeGRVÿ÷áéÛÐOm‚gz}:TfCWjPXb‹“l}“G[nCQV1N[CPaŒ›s‘¢s¡ lz‰]{„t¦n…œ€™®o‰šQk|4O]:U`9T`<O\;O\1ER*:G=N[<MZ?O\BQ_5SW-@G9CGáâÛùòßëàÉûîÚøèß÷çÔÿèÅþïеÂÀo‹žz’¢w„ŠNW\FVd5GQVkuAU`GZa8GP5?G?FQ*75ILeK\^Hc\@PgAIQÿûàþâÔýæÏùåÐ÷æÐùæÏúèÑäÞЕ¤E_xWbj¨«ªïæÔôåÍóæÎòäÒóãÒõâÓõäÑöåÒõäÑõäÑõãÐõäÑõãÐõãÑôãÎôãÎôãÎôãÎôãÎòáÌóâÍôãÎõâÍõâÍõâÍõâÍôáÌôáÌôáÌôáÌ9JP4BH1<C/8A-5>'%,;1;J6FN2DN3FR2ES1DP8IS7HR1?L?P];P_5KX@P\>P^J`rq…•ft€BX`9MW=P]7K[Ž¢²Zr|Kbk4MT7PZ.KV…¡²w¤n‰Ÿkˆžh…™f‚”ua}ŠB]jXs€d{Š@Tc?P`=P_8CQ*7+<I@Sa8LY2BO(6"+:ALS6=G7:>’“îçäøîà÷èÐÿëÌêëÙõäÕòäÜ£«©yŒ›v†¢s†¥s”¯i}^s…asƒ;N\I[f@QZ;NU6JP;M\@RV>HQ,3@-7@CEJ¶±¬ùéÔÞáÖüêØöß×ÎÑÝ¥ÄÕ¡ÄÏ’®½“«Í†¢´lŒ·¿ÄçâÛòâÔóåÎóåÎñåÎóäÑóäÑóäÑóäÑñâÏñâÏòãÐòãÐñâÐñâÐñâÐñâÐðâÏñâÏñâÏïáÎóâÍóâÍóâÍóâÍòáÌòáÌòáÌòáÌ4DK)9BEOY2;D4=G"0)2?1=I6EN:IQ5EQ7GT8IV9IU5CL(.?L5ER6GT<MZ7GT3CP@P];KX4JQ3GS=P]>Qa:M\H[h6JU6KR2IQ2JV`wˆd}d|z“§a|ŒqŒhŽ<SbAYh;O^AVe/DS=P_=P`<IU5EQ2DO9NY8JU-<I+9EEP\:KW)8D(2y}‡¸»ÀÛÙÕåäÚëèÙÍÑÅøìâüòꢰ¯t‹›Ž¦ˆ—®m‰˜k‚–§h{ŠBUbEWbCT]BT[<NUI]dK\cLY^9DLLU_/38ëåÜúêÖïæÕúæÎÿòæ‚„w£‚Ÿ©g~ŒuŒ¨a}‹Seo]bd¾¸²ñäÔôåÓôæÐóæÐóäÑóäÑóäÑóäÑôåÒóäÑóäÑóäÑòãÐòãÐòãÐòãÐòãÐñâÏñâÏñâÏóâÍóâÍóâÍóâÍòáÌòáÌòáÌòáÌ-=J+9E#/)2?-6@2=F0:D2=G3?I<GT6DP/@M5ER1?K9DQ#/9'7E4DQ;KX9IV@L[9FT)+8F4JQ4HS8KX8K[3FU8KX1EP8MU<QY6IU!4A)<K^rƒgz‹{Ž vŽ9IUK\iAQ^FZf?R_?Q^;N[<S_BS[5FO:MU;NU9MT:KT7FO=HQ4IW8IV1CQŠœ©et^luëøÿ ¬²N^[ÈÄÄõö󑤦–¯¿n~’|Œœx™h|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?Sc¦¼Ìe{F_d\dlñõúVns$2-?P3>Mn‚”Thy0?9LYEWb$4=)0&8?*9B2=C*.sƒJW^CKPòñéõçÙþëÎúæÌçàÙ|¦Kh‰j‚•\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\`?KSAPY7ITBUbXp€Tk|1N^@MZ²ºÄq‹•g†•j{7DP\qsK_q,@R`r9LYEWb:KT8JPCV\BP]?JR4?C +.1@G2<?®¯ªÚÑÅüéÒúì×ÒÖÒ‘«Á†¤ÆuŠœž©|•£o€ŽWfoLX]DGFÙØÎêáÔóçÕöçÔóåÓóåÓóåÓóåÓñãÑòäÒòäÒòäÒñãÑñãÑñãÑñãÑñãÑñãÑñãÑñãÑðâÏðâÏðâÏðâÏðâÏðâÏðâÏðâÏ3DQ6GS2@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|[n“§¸M`o7KX?Q\>OX<NU:MS@M\BNYEPSARX:MU:GNàãâóîåëâÙÒÊÀˆ““ƒŸ¸w°‰–©‰˜¤|˜ªO_kSblVcgAHGããÞãÞÔóæÖóãÒóåÓóåÓóåÓóåÓóåÓòäÒñãÑñãÑòãÑòãÑòãÑòãÑòãÑòãÑòãÑòãÒñãÐñãÐñãÐñãÐðâÏðâÏðâÏðâÏ3EP6FS2@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\~‰”š§Yz‘uŠ Xey[r|ThzOcu{ŽDWdI[fEV_ASY@SX;I]?MYBSYDW[=S[<PXª³³íéãÙÙâ¶¼ºYlpv“§z‘ˆ‘¢„ h‹¢UbnSclP\cOZZEJFêæÛíãÖõåÓñäÔñäÔñäÔñäÔòåÕñäÔðãÓïâÒðäÒðäÒðäÒðäÒðäÒðäÒðäÒðäÒïäÐïäÐïäÐïäÐîäÏîäÏîäÏîäÏ4HO1BK7FR*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“}€šªeŽ©U^jNYdAPVWehU]XöõìîäÖúéØñãÕñäÓòåÓóäÓòãÓòäÓñäÔñäÕðäÒðäÒðäÒðäÒðäÒðäÒðäÒñäÒðãÒðãÒðãÒðãÒïãÑïãÑïãÑïãÑ0=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<IDTbuˆždy’9IT0AM1CM2DOCVa*;D<LV$.")'4<E*4<DPWKW_YfoGY`€–¥@Uew‰šPaoQbrt‡˜K^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<MRjzˆDXeat€zViwCUfi{Œx‰œH[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[fSdpzœl€‘l’i}’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~x‰–t‡–fx‰H]pIV\R`fLX^JS[U_b†Œowz¥¨¬Œ¤¦•ž[]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^4DRgx„6GYJT\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``LQQPQMÏÑÇààÖèåÛáßÑÝâÖÝâÖÝâÖÝâÖàâÖàâÖßâÖàâÖÜà×ÞàØßàØßà×ÝßÕÝßÕàßÕáà×5DM6AM=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?DEHMLTXWããÝáÞÖæäÛääØàâÖàâÖàâÖàâÖàâÖßâÖàâÖßâÕÜßÚßàØÞà×ßà×ááÕÞßÓáàÒâáÓ2>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=GGANLw‡‚z‰…ž§¡¼À»´¾¹ÇÑÌ“——¥Ÿy†€o€xt…~¯Ä½ÈÉȾÂÀÅÊÉÑÚÚv‚‚v…‡‡š›dx|*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^ui‡d}|[rp[ljcqk}Š}m|cvw^uv”«°t‹‘Š¡§wŽ’|•.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}Їy…Ž‹›¡˜«¶„—¤Šªzš{˜n€‹4JV8KX<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{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]>RYJY`GW^=MTAQX?OVHX_AQXGW^/:BDOW6>H@IR-6<16=/6=45>/6??HQIU[GU[DRXBRTEQU=IM=JP=IN6BJ<KT`p}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_ASZEY`9EK<HN2<C?IP.6=6;B06=4:A7;D;BILX^KX^EU[?SVARU6HJ?HS:EN7AIGPTCLOGSTT`dQac7JRJ[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^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_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:)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[\?KM8GJ4GNp‡–n‰šh€”ƒ“¦Ž ”£´“ªºŽ§¶“§¹‰–¬0HZ4JZ<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ަ_vŒhzj‘^zŠ]{Ž]uŠ\p‰2M_+FV8M]/AN/AL4DO4ER:JW3ES3FS4GW0?Q*:L8HX:KX3BO/@M2BO7GT.?K0@L6GS;KX-=J8EP9IV¯¾ËDSd7ES6CO5AJ/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[OcoPitBcKe‚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_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;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^HW`HXaHW`HXaIYb4LX,BN8KZ/?O-=M4DT5GX5IZ~—¢Lbn?Q^6GT*;H6GT7JW1DQ1=K4AO1BO-=J,:K4CS/@O/?O*>P§¾Í{–¤8S]?U`7IT4?K27G5CO6JQ7JR4BK09F5=KScsqŒœLglH_fCT_+;I1=L8FQ;LU:KT<PW9LT9LT>QY;NV>QY=PX=PX7RX<QY>MZ*:G¨ÁÌl‡“I`j>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]JZ`HX^HX^P[cR]eS^fVahU`hWbjYdkYdl:T`5K[4JY1CT5GX<M`8H[;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_hq`ir^gp`hqajsbjt`hr^gp0KWKdp1GV-AO1CT0AT1DZGZosŒ•Rgr7KV6HS+=H1CN5IT/CN.:I5BP4DQ2BO1AO8HU3DQ3DQ1I`›³Ç†Ÿ¯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]HY`IV^IV^ANVCPXGT]KX`NZcVckUbjTbjWdlCPXLW_S_g\]fX^dPX_XbiS_eP^dP]cL\cQ]aUadTchYgmWejXhoXio\mt_jq`ksbmtcnualtbmt`ks^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[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·Óì‹¢¸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 | ||
54 | +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‰OhzNdsL`lrƒŒ†– “£¬Œœ¡z”{“—“¦ª·Â·ÅÕŠ¥µk‘¦[q„AXhF\fO`gI[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^FakXkr`pyvŠ,1>kp~3YhpWgo\gr_ls]jqanu_ltbntWkyWkx[o{Xmx[ny^p{]oz\nz[nx^nz`p|aq}dqdqer€er€crz^nz[jvVgsPcrL`rKcsNfvOeqNepRerWguVfrUeqZgtWfoPjp;PV5HO;KW@P]2ET˜±ÁœºÉYqw:PU6KS4IQ:LW5FSN^kbr~t‡’\nyRdoL`kM`mK^k>T`>T`4LX=S_\lyZkx>Raaxˆ‚ž³t“©ƒ¡±Ž¬Àˆ¦¹®Áˆ§º…Ÿ´w’¦w’§h~Œ\s‚Yqƒ~–§ƒ›‚’«»«¹\t€€˜¤Œ¢²¨º™°Á“½“¬½•³Âš¸Æ¦ÁÒ–´Æ®Â†¥¼t”«y–ª§Áצ²<VbCR^ET\K[d>SZFXcQ]jK\aN`jXq€¼×뜺ό¨¼i“CZi=Vb9P[Ymt`kuYclX`mt{Š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=T`9MXWhqbnxCLWHS\DMZ%,;as€^o|]n{Zkx_p}YjwQboYjx]jq]jr^ksbowiv~dqybowhu|ev‚jz‡jz‡fwƒ`o€[m|TixPetPfuOfuQetNbsOctRduPbsM_qOcnPdoUfr_q}XiqRclRakQ`i^wCYd/DN6HR8IV6GTlH^j>QY9LT5IP6IT5FS8IU8HY:JZ7JT;MW8JU9LY6IV7JV7L[7L[4N]:Q`®ÂÒ@S`BUb=Ra7Qasžx¦|˜oŠŸ… ´x“§‚ž®}œk‰šy’£d}‘h„™[v‹|–«t’§Š¨»Œ«¼DP`AUf‚Ÿ°„¦º¤»|³†Ÿ·”ªÀ˜¶Ê”´ËƆ¤À{™µz˜±Š§¾‹¤½u–£B\l?Q`Pdu–°Á’±Ã–²Ë—¬Ç‰¬¿ž¾Ö«Ìã¦ÆÝš¸Ít¡]q‚GVg<P]GYdTcl\iq`ksLU`8DNco|_itdoygr|hs}lt‚eq~huivƒlu|nx~jt{ku}r}…v‰r|„oyap€[jzSbrM`oK_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~M`oK\iCVcDUc?NWeszgrzZem1=Gkxƒ‚‡{„x~ƒu{x€‡z‚ˆw~‡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=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„]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/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]8O`8N[=QY[gox„Šjt|":CMclsgsxis{lw€iw‚`o{[kwZjvUhwQcrQftLcrG^pG_sG`sG^uF`pFaqHauIbvIcvKcyMe|Nf}Xi}[n~aq‚ZkxXhu[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]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]kM`qJ`rI]sD\qI`oF`oE]nF^rE`tD`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[qF`sM_tK_tG_rB_tFcwFbzMgSiƒNk„Yt‰Lg}^yŠWqWo~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ŽKamNbnG`fI`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|IfKl†NoˆSuKk‚Po‡Sp…Ok€jƒ—Œ ¶y¡}‘£p†–atI]hN_kCV^CT^BQZ@OX?NW?NW>OX:MU9MS@QZ>NV@LVAMW=KQ?MP=OPz’£Xq5N^6N`1I[;SeAYmH`ti†ž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=^{Xwc‚›l‹¥kŠ£}ž´ˆ§¾žµ‰¤¼ž¿Öš¹Î|˜¨pŠšC]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Š¢`}“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<Vf6O`4Pa9Yo@`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‰GkCjŒBi‹Fo‹Fh‚Hd€Ka~E`pLdtNetPanJZhHXeDW_BU]?RZ>RY<OW>PX:OW8MU=SY9NTEdcDdc8WV+JI1MM2KK=OP:ILCQMDRP9KL@SV=QV>RV>NT=LO{•¢sš=We7O_6O_7P`B[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{iPpPqN€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_k`p|]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:MSFW`N`hRbnP`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‚^zw”¨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Š¡{–®{—¯¡µ‡¦¾ƒ¡º®Ç‡¥¾Š©À{š¯~ž±|–«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?8M`6P`Nk|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\ty•¯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)%‹°Ì†§Ä‰«Ç„¥¿…£¾}šµ’°É®Ç”±Å–³ÇÂ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‘®¹”®¹›©LguwNfr=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$."'$), ! !#() | ||
55 | +!" &'%&$$/(%$OD=k•ºy¡Ä‹±Ó€¤Â‰§Â’®Æ‘«À•¬Ã‹©Â‚ ¹È°Ê¯Í²Î{¡¿ƒ©Ç…¤È{›¾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%-& | ||
56 | \ No newline at end of file | ||
57 | diff --git a/host_applications/linux/apps/hello_pi/hello_wayland/Makefile b/host_applications/linux/apps/hello_pi/hello_wayland/Makefile | ||
58 | new file mode 100644 | ||
59 | index 0000000..c9ddf23 | ||
60 | --- /dev/null | ||
61 | +++ b/host_applications/linux/apps/hello_pi/hello_wayland/Makefile | ||
62 | @@ -0,0 +1,5 @@ | ||
63 | +OBJS=triangle.o | ||
64 | +BIN=hello_wayland.bin | ||
65 | +LDFLAGS+=-lwayland-client -lwayland-egl | ||
66 | + | ||
67 | +include ../Makefile.include | ||
68 | 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 | ||
69 | new file mode 100644 | ||
70 | index 0000000..663e23b | ||
71 | --- /dev/null | ||
72 | +++ b/host_applications/linux/apps/hello_pi/hello_wayland/cube_texture_and_coords.h | ||
73 | @@ -0,0 +1,100 @@ | ||
74 | +/* | ||
75 | +Copyright (c) 2012, Broadcom Europe Ltd | ||
76 | +All rights reserved. | ||
77 | + | ||
78 | +Redistribution and use in source and binary forms, with or without | ||
79 | +modification, are permitted provided that the following conditions are met: | ||
80 | + * Redistributions of source code must retain the above copyright | ||
81 | + notice, this list of conditions and the following disclaimer. | ||
82 | + * Redistributions in binary form must reproduce the above copyright | ||
83 | + notice, this list of conditions and the following disclaimer in the | ||
84 | + documentation and/or other materials provided with the distribution. | ||
85 | + * Neither the name of the copyright holder nor the | ||
86 | + names of its contributors may be used to endorse or promote products | ||
87 | + derived from this software without specific prior written permission. | ||
88 | + | ||
89 | +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | ||
90 | +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
91 | +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
92 | +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY | ||
93 | +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
94 | +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
95 | +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
96 | +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
97 | +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
98 | +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
99 | +*/ | ||
100 | + | ||
101 | +// Spatial coordinates for the cube | ||
102 | + | ||
103 | +static const GLbyte quadx[6*4*3] = { | ||
104 | + /* FRONT */ | ||
105 | + -10, -10, 10, | ||
106 | + 10, -10, 10, | ||
107 | + -10, 10, 10, | ||
108 | + 10, 10, 10, | ||
109 | + | ||
110 | + /* BACK */ | ||
111 | + -10, -10, -10, | ||
112 | + -10, 10, -10, | ||
113 | + 10, -10, -10, | ||
114 | + 10, 10, -10, | ||
115 | + | ||
116 | + /* LEFT */ | ||
117 | + -10, -10, 10, | ||
118 | + -10, 10, 10, | ||
119 | + -10, -10, -10, | ||
120 | + -10, 10, -10, | ||
121 | + | ||
122 | + /* RIGHT */ | ||
123 | + 10, -10, -10, | ||
124 | + 10, 10, -10, | ||
125 | + 10, -10, 10, | ||
126 | + 10, 10, 10, | ||
127 | + | ||
128 | + /* TOP */ | ||
129 | + -10, 10, 10, | ||
130 | + 10, 10, 10, | ||
131 | + -10, 10, -10, | ||
132 | + 10, 10, -10, | ||
133 | + | ||
134 | + /* BOTTOM */ | ||
135 | + -10, -10, 10, | ||
136 | + -10, -10, -10, | ||
137 | + 10, -10, 10, | ||
138 | + 10, -10, -10, | ||
139 | +}; | ||
140 | + | ||
141 | +/** Texture coordinates for the quad. */ | ||
142 | +static const GLfloat texCoords[6 * 4 * 2] = { | ||
143 | + 0.f, 0.f, | ||
144 | + 1.f, 0.f, | ||
145 | + 0.f, 1.f, | ||
146 | + 1.f, 1.f, | ||
147 | + | ||
148 | + 0.f, 0.f, | ||
149 | + 1.f, 0.f, | ||
150 | + 0.f, 1.f, | ||
151 | + 1.f, 1.f, | ||
152 | + | ||
153 | + 0.f, 0.f, | ||
154 | + 1.f, 0.f, | ||
155 | + 0.f, 1.f, | ||
156 | + 1.f, 1.f, | ||
157 | + | ||
158 | + 0.f, 0.f, | ||
159 | + 1.f, 0.f, | ||
160 | + 0.f, 1.f, | ||
161 | + 1.f, 1.f, | ||
162 | + | ||
163 | + 0.f, 0.f, | ||
164 | + 1.f, 0.f, | ||
165 | + 0.f, 1.f, | ||
166 | + 1.f, 1.f, | ||
167 | + | ||
168 | + 0.f, 0.f, | ||
169 | + 1.f, 0.f, | ||
170 | + 0.f, 1.f, | ||
171 | + 1.f, 1.f, | ||
172 | +}; | ||
173 | + | ||
174 | diff --git a/host_applications/linux/apps/hello_pi/hello_wayland/triangle.c b/host_applications/linux/apps/hello_pi/hello_wayland/triangle.c | ||
175 | new file mode 100644 | ||
176 | index 0000000..1a7bfc4 | ||
177 | --- /dev/null | ||
178 | +++ b/host_applications/linux/apps/hello_pi/hello_wayland/triangle.c | ||
179 | @@ -0,0 +1,666 @@ | ||
180 | +/* | ||
181 | +Copyright (c) 2012, Broadcom Europe Ltd | ||
182 | +All rights reserved. | ||
183 | + | ||
184 | +Redistribution and use in source and binary forms, with or without | ||
185 | +modification, are permitted provided that the following conditions are met: | ||
186 | + * Redistributions of source code must retain the above copyright | ||
187 | + notice, this list of conditions and the following disclaimer. | ||
188 | + * Redistributions in binary form must reproduce the above copyright | ||
189 | + notice, this list of conditions and the following disclaimer in the | ||
190 | + documentation and/or other materials provided with the distribution. | ||
191 | + * Neither the name of the copyright holder nor the | ||
192 | + names of its contributors may be used to endorse or promote products | ||
193 | + derived from this software without specific prior written permission. | ||
194 | + | ||
195 | +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | ||
196 | +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
197 | +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
198 | +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY | ||
199 | +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
200 | +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
201 | +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
202 | +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
203 | +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
204 | +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
205 | +*/ | ||
206 | + | ||
207 | +// A rotating cube rendered with OpenGL|ES. Three images used as textures on the cube faces. | ||
208 | + | ||
209 | +#define _GNU_SOURCE | ||
210 | + | ||
211 | +#include <stdio.h> | ||
212 | +#include <stdlib.h> | ||
213 | +#include <string.h> | ||
214 | +#include <math.h> | ||
215 | +#include <assert.h> | ||
216 | +#include <unistd.h> | ||
217 | +#include <sys/socket.h> | ||
218 | +#include <sys/un.h> | ||
219 | + | ||
220 | +#include <wayland-egl.h> | ||
221 | +#include <wayland-client.h> | ||
222 | + | ||
223 | +#include "GLES/gl.h" | ||
224 | +#include "EGL/egl.h" | ||
225 | +#include "EGL/eglext.h" | ||
226 | + | ||
227 | +#include "cube_texture_and_coords.h" | ||
228 | + | ||
229 | +#define PATH "./" | ||
230 | + | ||
231 | +#define IMAGE_SIZE 128 | ||
232 | + | ||
233 | +#ifndef M_PI | ||
234 | + #define M_PI 3.141592654 | ||
235 | +#endif | ||
236 | + | ||
237 | + | ||
238 | +typedef struct | ||
239 | +{ | ||
240 | + uint32_t screen_width; | ||
241 | + uint32_t screen_height; | ||
242 | +// OpenGL|ES objects | ||
243 | + EGLDisplay display; | ||
244 | + EGLSurface surface; | ||
245 | + EGLContext context; | ||
246 | + GLuint tex[6]; | ||
247 | +// model rotation vector and direction | ||
248 | + GLfloat rot_angle_x_inc; | ||
249 | + GLfloat rot_angle_y_inc; | ||
250 | + GLfloat rot_angle_z_inc; | ||
251 | +// current model rotation angles | ||
252 | + GLfloat rot_angle_x; | ||
253 | + GLfloat rot_angle_y; | ||
254 | + GLfloat rot_angle_z; | ||
255 | +// current distance from camera | ||
256 | + GLfloat distance; | ||
257 | + GLfloat distance_inc; | ||
258 | +// pointers to texture buffers | ||
259 | + char *tex_buf1; | ||
260 | + char *tex_buf2; | ||
261 | + char *tex_buf3; | ||
262 | + struct wl_display *wl_display; | ||
263 | + struct wl_registry *wl_registry; | ||
264 | + struct wl_shell *wl_shell; | ||
265 | + struct wl_shell_surface *wl_shell_surface; | ||
266 | + struct wl_compositor *wl_compositor; | ||
267 | + struct wl_surface *wl_surface; | ||
268 | + struct wl_callback *wl_callback; | ||
269 | + struct wl_egl_window *wl_egl_window; | ||
270 | + int needs_update; | ||
271 | + int ellapsed_frames; | ||
272 | + int kill_compositor; | ||
273 | + int single_frame; | ||
274 | + int terminate_abruptly; | ||
275 | +} CUBE_STATE_T; | ||
276 | + | ||
277 | +static void init_ogl(CUBE_STATE_T *state); | ||
278 | +static void init_model_proj(CUBE_STATE_T *state); | ||
279 | +static void reset_model(CUBE_STATE_T *state); | ||
280 | +static GLfloat inc_and_wrap_angle(GLfloat angle, GLfloat angle_inc); | ||
281 | +static GLfloat inc_and_clip_distance(GLfloat distance, GLfloat distance_inc); | ||
282 | +static void redraw_scene(CUBE_STATE_T *state); | ||
283 | +static void update_model(CUBE_STATE_T *state); | ||
284 | +static void init_textures(CUBE_STATE_T *state); | ||
285 | +static void load_tex_images(CUBE_STATE_T *state); | ||
286 | +static void exit_func(CUBE_STATE_T *state); | ||
287 | + | ||
288 | +static void | ||
289 | +registry_handle_global(void *data, struct wl_registry *registry, | ||
290 | + uint32_t name, const char *interface, uint32_t version) | ||
291 | +{ | ||
292 | + CUBE_STATE_T *state = data; | ||
293 | + | ||
294 | + if (strcmp(interface, "wl_compositor") == 0) { | ||
295 | + state->wl_compositor = | ||
296 | + wl_registry_bind(registry, name, | ||
297 | + &wl_compositor_interface, 1); | ||
298 | + } else if (strcmp(interface, "wl_shell") == 0) { | ||
299 | + state->wl_shell = wl_registry_bind(registry, name, | ||
300 | + &wl_shell_interface, 1); | ||
301 | + } | ||
302 | +} | ||
303 | + | ||
304 | +static void | ||
305 | +registry_handle_global_remove(void *data, struct wl_registry *registry, | ||
306 | + uint32_t name) | ||
307 | +{ | ||
308 | +} | ||
309 | + | ||
310 | +static const struct wl_registry_listener registry_listener = { | ||
311 | + registry_handle_global, | ||
312 | + registry_handle_global_remove | ||
313 | +}; | ||
314 | + | ||
315 | +/*********************************************************** | ||
316 | + * Name: init_ogl | ||
317 | + * | ||
318 | + * Arguments: | ||
319 | + * CUBE_STATE_T *state - holds OGLES model info | ||
320 | + * | ||
321 | + * Description: Sets the display, OpenGL|ES context and screen stuff | ||
322 | + * | ||
323 | + * Returns: void | ||
324 | + * | ||
325 | + ***********************************************************/ | ||
326 | +static void init_ogl(CUBE_STATE_T *state) | ||
327 | +{ | ||
328 | + EGLBoolean result; | ||
329 | + EGLint num_config; | ||
330 | + | ||
331 | + static const EGLint attribute_list[] = | ||
332 | + { | ||
333 | + EGL_RED_SIZE, 8, | ||
334 | + EGL_GREEN_SIZE, 8, | ||
335 | + EGL_BLUE_SIZE, 8, | ||
336 | + EGL_ALPHA_SIZE, 8, | ||
337 | + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, | ||
338 | + EGL_NONE | ||
339 | + }; | ||
340 | + | ||
341 | + EGLConfig config; | ||
342 | + | ||
343 | + state->wl_display = wl_display_connect(NULL); | ||
344 | + | ||
345 | + state->wl_registry = wl_display_get_registry(state->wl_display); | ||
346 | + wl_registry_add_listener(state->wl_registry, ®istry_listener, state); | ||
347 | + | ||
348 | + wl_display_dispatch(state->wl_display); | ||
349 | + | ||
350 | + // get an EGL display connection | ||
351 | + state->display = eglGetDisplay(state->wl_display); | ||
352 | + assert(state->display!=EGL_NO_DISPLAY); | ||
353 | + | ||
354 | + // initialize the EGL display connection | ||
355 | + result = eglInitialize(state->display, NULL, NULL); | ||
356 | + assert(EGL_FALSE != result); | ||
357 | + | ||
358 | + // get an appropriate EGL frame buffer configuration | ||
359 | + result = eglChooseConfig(state->display, attribute_list, &config, 1, &num_config); | ||
360 | + assert(EGL_FALSE != result); | ||
361 | + | ||
362 | + // create an EGL rendering context | ||
363 | + state->context = eglCreateContext(state->display, config, EGL_NO_CONTEXT, NULL); | ||
364 | + assert(state->context!=EGL_NO_CONTEXT); | ||
365 | + | ||
366 | + // create an EGL window surface | ||
367 | + state->screen_width = 1024; | ||
368 | + state->screen_height = 860; | ||
369 | + | ||
370 | + state->wl_surface = wl_compositor_create_surface(state->wl_compositor); | ||
371 | + state->wl_shell_surface = wl_shell_get_shell_surface(state->wl_shell, state->wl_surface); | ||
372 | + | ||
373 | + wl_shell_surface_set_toplevel(state->wl_shell_surface); | ||
374 | + wl_shell_surface_set_title(state->wl_shell_surface, "triangle.c"); | ||
375 | + | ||
376 | + state->wl_egl_window = wl_egl_window_create(state->wl_surface, state->screen_width, state->screen_height); | ||
377 | + | ||
378 | + state->surface = eglCreateWindowSurface( state->display, config, state->wl_egl_window, NULL ); | ||
379 | + assert(state->surface != EGL_NO_SURFACE); | ||
380 | + | ||
381 | + // connect the context to the surface | ||
382 | + result = eglMakeCurrent(state->display, state->surface, state->surface, state->context); | ||
383 | + assert(EGL_FALSE != result); | ||
384 | + | ||
385 | + // Set background color and clear buffers | ||
386 | + glClearColor(0.15f, 0.25f, 0.35f, 1.0f); | ||
387 | + | ||
388 | + // Enable back face culling. | ||
389 | + glEnable(GL_CULL_FACE); | ||
390 | + | ||
391 | + glMatrixMode(GL_MODELVIEW); | ||
392 | +} | ||
393 | + | ||
394 | +/*********************************************************** | ||
395 | + * Name: init_model_proj | ||
396 | + * | ||
397 | + * Arguments: | ||
398 | + * CUBE_STATE_T *state - holds OGLES model info | ||
399 | + * | ||
400 | + * Description: Sets the OpenGL|ES model to default values | ||
401 | + * | ||
402 | + * Returns: void | ||
403 | + * | ||
404 | + ***********************************************************/ | ||
405 | +static void init_model_proj(CUBE_STATE_T *state) | ||
406 | +{ | ||
407 | + float nearp = 1.0f; | ||
408 | + float farp = 500.0f; | ||
409 | + float hht; | ||
410 | + float hwd; | ||
411 | + | ||
412 | + glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST ); | ||
413 | + | ||
414 | + glViewport(0, 0, (GLsizei)state->screen_width, (GLsizei)state->screen_height); | ||
415 | + | ||
416 | + glMatrixMode(GL_PROJECTION); | ||
417 | + glLoadIdentity(); | ||
418 | + | ||
419 | + hht = nearp * (float)tan(45.0 / 2.0 / 180.0 * M_PI); | ||
420 | + hwd = hht * (float)state->screen_width / (float)state->screen_height; | ||
421 | + | ||
422 | + glFrustumf(-hwd, hwd, -hht, hht, nearp, farp); | ||
423 | + | ||
424 | + glEnableClientState( GL_VERTEX_ARRAY ); | ||
425 | + glVertexPointer( 3, GL_BYTE, 0, quadx ); | ||
426 | + | ||
427 | + reset_model(state); | ||
428 | +} | ||
429 | + | ||
430 | +/*********************************************************** | ||
431 | + * Name: reset_model | ||
432 | + * | ||
433 | + * Arguments: | ||
434 | + * CUBE_STATE_T *state - holds OGLES model info | ||
435 | + * | ||
436 | + * Description: Resets the Model projection and rotation direction | ||
437 | + * | ||
438 | + * Returns: void | ||
439 | + * | ||
440 | + ***********************************************************/ | ||
441 | +static void reset_model(CUBE_STATE_T *state) | ||
442 | +{ | ||
443 | + // reset model position | ||
444 | + glMatrixMode(GL_MODELVIEW); | ||
445 | + glLoadIdentity(); | ||
446 | + glTranslatef(0.f, 0.f, -50.f); | ||
447 | + | ||
448 | + // reset model rotation | ||
449 | + state->rot_angle_x = 45.f; state->rot_angle_y = 30.f; state->rot_angle_z = 0.f; | ||
450 | + state->rot_angle_x_inc = 0.5f; state->rot_angle_y_inc = 0.5f; state->rot_angle_z_inc = 0.f; | ||
451 | + state->distance = 40.f; | ||
452 | +} | ||
453 | + | ||
454 | +/*********************************************************** | ||
455 | + * Name: update_model | ||
456 | + * | ||
457 | + * Arguments: | ||
458 | + * CUBE_STATE_T *state - holds OGLES model info | ||
459 | + * | ||
460 | + * Description: Updates model projection to current position/rotation | ||
461 | + * | ||
462 | + * Returns: void | ||
463 | + * | ||
464 | + ***********************************************************/ | ||
465 | +static void update_model(CUBE_STATE_T *state) | ||
466 | +{ | ||
467 | + // update position | ||
468 | + state->rot_angle_x = inc_and_wrap_angle(state->rot_angle_x, state->rot_angle_x_inc); | ||
469 | + state->rot_angle_y = inc_and_wrap_angle(state->rot_angle_y, state->rot_angle_y_inc); | ||
470 | + state->rot_angle_z = inc_and_wrap_angle(state->rot_angle_z, state->rot_angle_z_inc); | ||
471 | + state->distance = inc_and_clip_distance(state->distance, state->distance_inc); | ||
472 | + | ||
473 | + glLoadIdentity(); | ||
474 | + // move camera back to see the cube | ||
475 | + glTranslatef(0.f, 0.f, -state->distance); | ||
476 | + | ||
477 | + // Rotate model to new position | ||
478 | + glRotatef(state->rot_angle_x, 1.f, 0.f, 0.f); | ||
479 | + glRotatef(state->rot_angle_y, 0.f, 1.f, 0.f); | ||
480 | + glRotatef(state->rot_angle_z, 0.f, 0.f, 1.f); | ||
481 | +} | ||
482 | + | ||
483 | +/*********************************************************** | ||
484 | + * Name: inc_and_wrap_angle | ||
485 | + * | ||
486 | + * Arguments: | ||
487 | + * GLfloat angle current angle | ||
488 | + * GLfloat angle_inc angle increment | ||
489 | + * | ||
490 | + * Description: Increments or decrements angle by angle_inc degrees | ||
491 | + * Wraps to 0 at 360 deg. | ||
492 | + * | ||
493 | + * Returns: new value of angle | ||
494 | + * | ||
495 | + ***********************************************************/ | ||
496 | +static GLfloat inc_and_wrap_angle(GLfloat angle, GLfloat angle_inc) | ||
497 | +{ | ||
498 | + angle += angle_inc; | ||
499 | + | ||
500 | + if (angle >= 360.0) | ||
501 | + angle -= 360.f; | ||
502 | + else if (angle <=0) | ||
503 | + angle += 360.f; | ||
504 | + | ||
505 | + return angle; | ||
506 | +} | ||
507 | + | ||
508 | +/*********************************************************** | ||
509 | + * Name: inc_and_clip_distance | ||
510 | + * | ||
511 | + * Arguments: | ||
512 | + * GLfloat distance current distance | ||
513 | + * GLfloat distance_inc distance increment | ||
514 | + * | ||
515 | + * Description: Increments or decrements distance by distance_inc units | ||
516 | + * Clips to range | ||
517 | + * | ||
518 | + * Returns: new value of angle | ||
519 | + * | ||
520 | + ***********************************************************/ | ||
521 | +static GLfloat inc_and_clip_distance(GLfloat distance, GLfloat distance_inc) | ||
522 | +{ | ||
523 | + distance += distance_inc; | ||
524 | + | ||
525 | + if (distance >= 120.0f) | ||
526 | + distance = 120.f; | ||
527 | + else if (distance <= 40.0f) | ||
528 | + distance = 40.0f; | ||
529 | + | ||
530 | + return distance; | ||
531 | +} | ||
532 | + | ||
533 | +static pid_t get_server_pid(CUBE_STATE_T *state) | ||
534 | +{ | ||
535 | + struct ucred ucred; | ||
536 | + socklen_t len; | ||
537 | + int fd; | ||
538 | + | ||
539 | + fd = wl_display_get_fd(state->wl_display); | ||
540 | + len = sizeof ucred; | ||
541 | + getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &len); | ||
542 | + | ||
543 | + return ucred.pid; | ||
544 | +} | ||
545 | + | ||
546 | +static void | ||
547 | +frame(void *data, struct wl_callback *callback, uint32_t time) | ||
548 | +{ | ||
549 | + CUBE_STATE_T *state = (CUBE_STATE_T *) data; | ||
550 | + | ||
551 | + state->needs_update = 1; | ||
552 | +} | ||
553 | + | ||
554 | +static const struct wl_callback_listener frame_listener = { | ||
555 | + frame | ||
556 | +}; | ||
557 | + | ||
558 | +static void | ||
559 | +update(CUBE_STATE_T *state) | ||
560 | +{ | ||
561 | + if (!state->single_frame || state->ellapsed_frames == 0) { | ||
562 | + update_model(state); | ||
563 | + redraw_scene(state); | ||
564 | + } | ||
565 | + | ||
566 | + state->wl_callback = wl_surface_frame(state->wl_surface); | ||
567 | + wl_callback_add_listener(state->wl_callback, &frame_listener, state); | ||
568 | + | ||
569 | + if (state->ellapsed_frames == 100) { | ||
570 | + if (state->kill_compositor) { | ||
571 | + fprintf(stderr, "reached frame 100, killing compositor\n"); | ||
572 | + pid_t pid = get_server_pid(state); | ||
573 | + kill(pid, SIGTERM); | ||
574 | + } else if (state->terminate_abruptly) { | ||
575 | + fprintf(stderr, "reached frame 100, terminating right away\n"); | ||
576 | + exit_func(state); | ||
577 | + exit(0); | ||
578 | + } | ||
579 | + } | ||
580 | + | ||
581 | + if (!state->single_frame || state->ellapsed_frames == 0) | ||
582 | + eglSwapBuffers(state->display, state->surface); | ||
583 | + else { | ||
584 | + wl_surface_damage(state->wl_surface, 0, 0, state->screen_width, | ||
585 | + state->screen_height); | ||
586 | + wl_surface_commit(state->wl_surface); | ||
587 | + } | ||
588 | + | ||
589 | + state->ellapsed_frames++; | ||
590 | +} | ||
591 | + | ||
592 | +/*********************************************************** | ||
593 | + * Name: redraw_scene | ||
594 | + * | ||
595 | + * Arguments: | ||
596 | + * CUBE_STATE_T *state - holds OGLES model info | ||
597 | + * | ||
598 | + * Description: Draws the model and calls eglSwapBuffers | ||
599 | + * to render to screen | ||
600 | + * | ||
601 | + * Returns: void | ||
602 | + * | ||
603 | + ***********************************************************/ | ||
604 | +static void redraw_scene(CUBE_STATE_T *state) | ||
605 | +{ | ||
606 | + // Start with a clear screen | ||
607 | + glClear( GL_COLOR_BUFFER_BIT ); | ||
608 | + | ||
609 | + // Draw first (front) face: | ||
610 | + // Bind texture surface to current vertices | ||
611 | + glBindTexture(GL_TEXTURE_2D, state->tex[0]); | ||
612 | + | ||
613 | + // Need to rotate textures - do this by rotating each cube face | ||
614 | + glRotatef(270.f, 0.f, 0.f, 1.f ); // front face normal along z axis | ||
615 | + | ||
616 | + // draw first 4 vertices | ||
617 | + glDrawArrays( GL_TRIANGLE_STRIP, 0, 4); | ||
618 | + | ||
619 | + // same pattern for other 5 faces - rotation chosen to make image orientation 'nice' | ||
620 | + glBindTexture(GL_TEXTURE_2D, state->tex[1]); | ||
621 | + glRotatef(90.f, 0.f, 0.f, 1.f ); // back face normal along z axis | ||
622 | + glDrawArrays( GL_TRIANGLE_STRIP, 4, 4); | ||
623 | + | ||
624 | + glBindTexture(GL_TEXTURE_2D, state->tex[2]); | ||
625 | + glRotatef(90.f, 1.f, 0.f, 0.f ); // left face normal along x axis | ||
626 | + glDrawArrays( GL_TRIANGLE_STRIP, 8, 4); | ||
627 | + | ||
628 | + glBindTexture(GL_TEXTURE_2D, state->tex[3]); | ||
629 | + glRotatef(90.f, 1.f, 0.f, 0.f ); // right face normal along x axis | ||
630 | + glDrawArrays( GL_TRIANGLE_STRIP, 12, 4); | ||
631 | + | ||
632 | + glBindTexture(GL_TEXTURE_2D, state->tex[4]); | ||
633 | + glRotatef(270.f, 0.f, 1.f, 0.f ); // top face normal along y axis | ||
634 | + glDrawArrays( GL_TRIANGLE_STRIP, 16, 4); | ||
635 | + | ||
636 | + glBindTexture(GL_TEXTURE_2D, state->tex[5]); | ||
637 | + glRotatef(90.f, 0.f, 1.f, 0.f ); // bottom face normal along y axis | ||
638 | + glDrawArrays( GL_TRIANGLE_STRIP, 20, 4); | ||
639 | +} | ||
640 | + | ||
641 | +/*********************************************************** | ||
642 | + * Name: init_textures | ||
643 | + * | ||
644 | + * Arguments: | ||
645 | + * CUBE_STATE_T *state - holds OGLES model info | ||
646 | + * | ||
647 | + * Description: Initialise OGL|ES texture surfaces to use image | ||
648 | + * buffers | ||
649 | + * | ||
650 | + * Returns: void | ||
651 | + * | ||
652 | + ***********************************************************/ | ||
653 | +static void init_textures(CUBE_STATE_T *state) | ||
654 | +{ | ||
655 | + // load three texture buffers but use them on six OGL|ES texture surfaces | ||
656 | + load_tex_images(state); | ||
657 | + glGenTextures(6, &state->tex[0]); | ||
658 | + | ||
659 | + // setup first texture | ||
660 | + glBindTexture(GL_TEXTURE_2D, state->tex[0]); | ||
661 | + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, IMAGE_SIZE, IMAGE_SIZE, 0, | ||
662 | + GL_RGB, GL_UNSIGNED_BYTE, state->tex_buf1); | ||
663 | + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (GLfloat)GL_NEAREST); | ||
664 | + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (GLfloat)GL_NEAREST); | ||
665 | + | ||
666 | + // setup second texture - reuse first image | ||
667 | + glBindTexture(GL_TEXTURE_2D, state->tex[1]); | ||
668 | + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, IMAGE_SIZE, IMAGE_SIZE, 0, | ||
669 | + GL_RGB, GL_UNSIGNED_BYTE, state->tex_buf1); | ||
670 | + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (GLfloat)GL_NEAREST); | ||
671 | + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (GLfloat)GL_NEAREST); | ||
672 | + | ||
673 | + // third texture | ||
674 | + glBindTexture(GL_TEXTURE_2D, state->tex[2]); | ||
675 | + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, IMAGE_SIZE, IMAGE_SIZE, 0, | ||
676 | + GL_RGB, GL_UNSIGNED_BYTE, state->tex_buf2); | ||
677 | + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (GLfloat)GL_NEAREST); | ||
678 | + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (GLfloat)GL_NEAREST); | ||
679 | + | ||
680 | + // fourth texture - reuse second image | ||
681 | + glBindTexture(GL_TEXTURE_2D, state->tex[3]); | ||
682 | + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, IMAGE_SIZE, IMAGE_SIZE, 0, | ||
683 | + GL_RGB, GL_UNSIGNED_BYTE, state->tex_buf2); | ||
684 | + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (GLfloat)GL_NEAREST); | ||
685 | + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (GLfloat)GL_NEAREST); | ||
686 | + | ||
687 | + //fifth texture | ||
688 | + glBindTexture(GL_TEXTURE_2D, state->tex[4]); | ||
689 | + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, IMAGE_SIZE, IMAGE_SIZE, 0, | ||
690 | + GL_RGB, GL_UNSIGNED_BYTE, state->tex_buf3); | ||
691 | + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (GLfloat)GL_NEAREST); | ||
692 | + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (GLfloat)GL_NEAREST); | ||
693 | + | ||
694 | + // sixth texture - reuse third image | ||
695 | + glBindTexture(GL_TEXTURE_2D, state->tex[5]); | ||
696 | + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, IMAGE_SIZE, IMAGE_SIZE, 0, | ||
697 | + GL_RGB, GL_UNSIGNED_BYTE, state->tex_buf3); | ||
698 | + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (GLfloat)GL_NEAREST); | ||
699 | + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (GLfloat)GL_NEAREST); | ||
700 | + | ||
701 | + // setup overall texture environment | ||
702 | + glTexCoordPointer(2, GL_FLOAT, 0, texCoords); | ||
703 | + glEnableClientState(GL_TEXTURE_COORD_ARRAY); | ||
704 | + | ||
705 | + glEnable(GL_TEXTURE_2D); | ||
706 | +} | ||
707 | + | ||
708 | +/*********************************************************** | ||
709 | + * Name: load_tex_images | ||
710 | + * | ||
711 | + * Arguments: | ||
712 | + * void | ||
713 | + * | ||
714 | + * Description: Loads three raw images to use as textures on faces | ||
715 | + * | ||
716 | + * Returns: void | ||
717 | + * | ||
718 | + ***********************************************************/ | ||
719 | +static void load_tex_images(CUBE_STATE_T *state) | ||
720 | +{ | ||
721 | + FILE *tex_file1 = NULL, *tex_file2=NULL, *tex_file3 = NULL; | ||
722 | + int bytes_read, image_sz = IMAGE_SIZE*IMAGE_SIZE*3; | ||
723 | + | ||
724 | + state->tex_buf1 = malloc(image_sz); | ||
725 | + state->tex_buf2 = malloc(image_sz); | ||
726 | + state->tex_buf3 = malloc(image_sz); | ||
727 | + | ||
728 | + tex_file1 = fopen(PATH "Lucca_128_128.raw", "rb"); | ||
729 | + if (tex_file1 && state->tex_buf1) | ||
730 | + { | ||
731 | + bytes_read=fread(state->tex_buf1, 1, image_sz, tex_file1); | ||
732 | + assert(bytes_read == image_sz); // some problem with file? | ||
733 | + fclose(tex_file1); | ||
734 | + } | ||
735 | + | ||
736 | + tex_file2 = fopen(PATH "Djenne_128_128.raw", "rb"); | ||
737 | + if (tex_file2 && state->tex_buf2) | ||
738 | + { | ||
739 | + bytes_read=fread(state->tex_buf2, 1, image_sz, tex_file2); | ||
740 | + assert(bytes_read == image_sz); // some problem with file? | ||
741 | + fclose(tex_file2); | ||
742 | + } | ||
743 | + | ||
744 | + tex_file3 = fopen(PATH "Gaudi_128_128.raw", "rb"); | ||
745 | + if (tex_file3 && state->tex_buf3) | ||
746 | + { | ||
747 | + bytes_read=fread(state->tex_buf3, 1, image_sz, tex_file3); | ||
748 | + assert(bytes_read == image_sz); // some problem with file? | ||
749 | + fclose(tex_file3); | ||
750 | + } | ||
751 | +} | ||
752 | + | ||
753 | +//------------------------------------------------------------------------------ | ||
754 | + | ||
755 | +static void exit_func(CUBE_STATE_T *state) | ||
756 | +{ | ||
757 | + // clear screen | ||
758 | + glClear( GL_COLOR_BUFFER_BIT ); | ||
759 | + eglSwapBuffers(state->display, state->surface); | ||
760 | + | ||
761 | + // Release OpenGL resources | ||
762 | + eglMakeCurrent( state->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT ); | ||
763 | + | ||
764 | + wl_egl_window_destroy(state->wl_egl_window); | ||
765 | + wl_shell_surface_destroy(state->wl_shell_surface); | ||
766 | + wl_surface_destroy(state->wl_surface); | ||
767 | + | ||
768 | + eglDestroySurface( state->display, state->surface ); | ||
769 | + eglDestroyContext( state->display, state->context ); | ||
770 | + eglTerminate( state->display ); | ||
771 | + | ||
772 | + wl_display_flush(state->wl_display); | ||
773 | + | ||
774 | + // release texture buffers | ||
775 | + free(state->tex_buf1); | ||
776 | + free(state->tex_buf2); | ||
777 | + free(state->tex_buf3); | ||
778 | + | ||
779 | + printf("\ncube closed\n"); | ||
780 | +} // exit_func() | ||
781 | + | ||
782 | +static int running = 1; | ||
783 | + | ||
784 | +static void | ||
785 | +signal_int(int signum) | ||
786 | +{ | ||
787 | + running = 0; | ||
788 | +} | ||
789 | + | ||
790 | +//============================================================================== | ||
791 | + | ||
792 | +int main (int argc, char *argv[]) | ||
793 | +{ | ||
794 | + struct sigaction sigint; | ||
795 | + CUBE_STATE_T state = {0,}; | ||
796 | + int ret = 0; | ||
797 | + int i; | ||
798 | + | ||
799 | + for (i = 0; i < argc; i++) { | ||
800 | + if (strcmp(argv[i], "--kill-compositor") == 0) | ||
801 | + state.kill_compositor = 1; | ||
802 | + if (strcmp(argv[i], "--single-frame") == 0) | ||
803 | + state.single_frame = 1; | ||
804 | + if (strcmp(argv[i], "--terminate-abruptly") == 0) | ||
805 | + state.terminate_abruptly = 1; | ||
806 | + else if (strcmp(argv[i], "--help") == 0 || | ||
807 | + strcmp(argv[i], "-h") == 0) { | ||
808 | + printf("Usage: hello_wayland.bin [OPTION]\n\n"); | ||
809 | + printf("\t--kill-compositor\tkill the Wayland compositor after 100 frames\n"); | ||
810 | + printf("\t-h, --help\t\tshow this text\n"); | ||
811 | + printf("\t--single-frame\t\tupdate the display only once\n"); | ||
812 | + printf("\t--terminate-abruptly\texit right after rendering the 100th frame\n"); | ||
813 | + return 0; | ||
814 | + } | ||
815 | + } | ||
816 | + | ||
817 | + // Start OGLES | ||
818 | + init_ogl(&state); | ||
819 | + | ||
820 | + // Setup the model world | ||
821 | + init_model_proj(&state); | ||
822 | + | ||
823 | + // initialise the OGLES texture(s) | ||
824 | + init_textures(&state); | ||
825 | + | ||
826 | + sigint.sa_handler = signal_int; | ||
827 | + sigemptyset(&sigint.sa_mask); | ||
828 | + sigint.sa_flags = SA_RESETHAND; | ||
829 | + sigaction(SIGINT, &sigint, NULL); | ||
830 | + | ||
831 | + state.needs_update = 1; | ||
832 | + while (running && ret != -1) { | ||
833 | + if (state.needs_update) { | ||
834 | + update(&state); | ||
835 | + state.needs_update = 0; | ||
836 | + } | ||
837 | + | ||
838 | + ret = wl_display_dispatch(state.wl_display); | ||
839 | + } | ||
840 | + | ||
841 | + exit_func(&state); | ||
842 | + | ||
843 | + return 0; | ||
844 | +} | ||
845 | + | ||
846 | diff --git a/host_applications/linux/apps/hello_pi/rebuild.sh b/host_applications/linux/apps/hello_pi/rebuild.sh | ||
847 | index fa4539e..37120ac 100755 | ||
848 | --- a/host_applications/linux/apps/hello_pi/rebuild.sh | ||
849 | +++ b/host_applications/linux/apps/hello_pi/rebuild.sh | ||
850 | @@ -13,6 +13,7 @@ make -C hello_jpeg clean | ||
851 | make -C hello_videocube clean | ||
852 | make -C hello_teapot clean | ||
853 | make -C hello_fft clean | ||
854 | +make -C hello_wayland clean | ||
855 | |||
856 | make -C libs/ilclient | ||
857 | make -C libs/vgfont | ||
858 | @@ -29,4 +30,4 @@ make -C hello_jpeg | ||
859 | make -C hello_videocube | ||
860 | make -C hello_teapot | ||
861 | make -C hello_fft | ||
862 | - | ||
863 | +make -C hello_wayland | ||
864 | -- | ||
865 | 2.7.0 | ||
866 | |||
diff --git a/recipes-graphics/userland/userland/0011-wayland-egl-Add-bcm_host-to-dependencies.patch b/recipes-graphics/userland/userland/0011-wayland-egl-Add-bcm_host-to-dependencies.patch new file mode 100644 index 0000000..386ddf3 --- /dev/null +++ b/recipes-graphics/userland/userland/0011-wayland-egl-Add-bcm_host-to-dependencies.patch | |||
@@ -0,0 +1,28 @@ | |||
1 | From 071771f1c2eb73c1f9083abb3a9f3a7712e20cdf Mon Sep 17 00:00:00 2001 | ||
2 | From: Khem Raj <raj.khem@gmail.com> | ||
3 | Date: Mon, 10 Aug 2015 02:38:27 -0700 | ||
4 | Subject: [PATCH 11/16] wayland-egl: Add bcm_host to dependencies | ||
5 | |||
6 | It uses headers like vcos_platform_types.h but does not | ||
7 | depend on module which should add the required include paths | ||
8 | lets add the dependency on bcm_host module which should do it | ||
9 | |||
10 | Signed-off-by: Khem Raj <raj.khem@gmail.com> | ||
11 | --- | ||
12 | interface/khronos/wayland-egl/wayland-egl.pc.in | 1 + | ||
13 | 1 file changed, 1 insertion(+) | ||
14 | |||
15 | diff --git a/interface/khronos/wayland-egl/wayland-egl.pc.in b/interface/khronos/wayland-egl/wayland-egl.pc.in | ||
16 | index 8bafc15..fd259c9 100644 | ||
17 | --- a/interface/khronos/wayland-egl/wayland-egl.pc.in | ||
18 | +++ b/interface/khronos/wayland-egl/wayland-egl.pc.in | ||
19 | @@ -6,5 +6,6 @@ includedir=${prefix}/include | ||
20 | Name: wayland-egl | ||
21 | Description: VideoCore wayland-egl library | ||
22 | Version: @PROJECT_APIVER@ | ||
23 | +Requires: bcm_host | ||
24 | Libs: -L${libdir} -lwayland-egl | ||
25 | Cflags: -I${includedir} | ||
26 | -- | ||
27 | 2.7.0 | ||
28 | |||
diff --git a/recipes-graphics/userland/userland/0012-interface-remove-faulty-assert-to-make-weston-happy-.patch b/recipes-graphics/userland/userland/0012-interface-remove-faulty-assert-to-make-weston-happy-.patch new file mode 100644 index 0000000..74374fc --- /dev/null +++ b/recipes-graphics/userland/userland/0012-interface-remove-faulty-assert-to-make-weston-happy-.patch | |||
@@ -0,0 +1,29 @@ | |||
1 | From fb577f53f9a91745557194b0422504e2cc93a637 Mon Sep 17 00:00:00 2001 | ||
2 | From: "Yann E. MORIN" <yann.morin.1998@free.fr> | ||
3 | Date: Sat, 24 Jan 2015 22:07:19 +0100 | ||
4 | Subject: [PATCH 12/16] interface: remove faulty assert() to make weston happy | ||
5 | at runtime | ||
6 | |||
7 | This was removed after a discussion on IRC with the weston guys | ||
8 | ('daniels' on irc.freenode.net/#wayland). | ||
9 | |||
10 | Signed-off-by: "Yann E. MORIN" <yann.morin.1998@free.fr> | ||
11 | --- | ||
12 | interface/vmcs_host/vc_vchi_dispmanx.c | 1 - | ||
13 | 1 file changed, 1 deletion(-) | ||
14 | |||
15 | diff --git a/interface/vmcs_host/vc_vchi_dispmanx.c b/interface/vmcs_host/vc_vchi_dispmanx.c | ||
16 | index 1d24b6e..e2e7ccc 100755 | ||
17 | --- a/interface/vmcs_host/vc_vchi_dispmanx.c | ||
18 | +++ b/interface/vmcs_host/vc_vchi_dispmanx.c | ||
19 | @@ -1304,7 +1304,6 @@ static void *dispmanx_notify_func( void *arg ) { | ||
20 | // Decrement the use count - the corresponding "use" is in vc_dispmanx_update_submit. | ||
21 | vchi_service_release(dispmanx_client.notify_handle[0]); | ||
22 | if (dispmanx_client.update_callback ) { | ||
23 | - vcos_assert( dispmanx_client.pending_update_handle == handle); | ||
24 | dispmanx_client.update_callback(handle, dispmanx_client.update_callback_param); | ||
25 | } | ||
26 | } else { | ||
27 | -- | ||
28 | 2.7.0 | ||
29 | |||
diff --git a/recipes-graphics/userland/userland/0013-zero-out-wl-buffers-in-egl_surface_free.patch b/recipes-graphics/userland/userland/0013-zero-out-wl-buffers-in-egl_surface_free.patch new file mode 100644 index 0000000..af291dc --- /dev/null +++ b/recipes-graphics/userland/userland/0013-zero-out-wl-buffers-in-egl_surface_free.patch | |||
@@ -0,0 +1,33 @@ | |||
1 | From 2d91c1fded75b3207743e058b0d5ca9eb98dce58 Mon Sep 17 00:00:00 2001 | ||
2 | From: Khem Raj <raj.khem@gmail.com> | ||
3 | Date: Sat, 6 Feb 2016 11:10:47 -0800 | ||
4 | Subject: [PATCH 13/16] zero-out wl buffers in egl_surface_free | ||
5 | |||
6 | origins from buildroot | ||
7 | |||
8 | Signed-off-by: Khem Raj <raj.khem@gmail.com> | ||
9 | --- | ||
10 | interface/khronos/egl/egl_client_surface.c | 2 ++ | ||
11 | 1 file changed, 2 insertions(+) | ||
12 | |||
13 | diff --git a/interface/khronos/egl/egl_client_surface.c b/interface/khronos/egl/egl_client_surface.c | ||
14 | index 49cf7e5..512c83b 100644 | ||
15 | --- a/interface/khronos/egl/egl_client_surface.c | ||
16 | +++ b/interface/khronos/egl/egl_client_surface.c | ||
17 | @@ -690,11 +690,13 @@ void egl_surface_free(EGL_SURFACE_T *surface) | ||
18 | if (surface->back_wl_buffer) { | ||
19 | wl_buffer_destroy(surface->back_wl_buffer->wl_buffer); | ||
20 | free(surface->back_wl_buffer); | ||
21 | + surface->back_wl_buffer = 0; | ||
22 | } | ||
23 | |||
24 | if (surface->front_wl_buffer) { | ||
25 | wl_buffer_destroy(surface->front_wl_buffer->wl_buffer); | ||
26 | free(surface->front_wl_buffer); | ||
27 | + surface->front_wl_buffer = 0; | ||
28 | } | ||
29 | #endif | ||
30 | } | ||
31 | -- | ||
32 | 2.7.0 | ||
33 | |||
diff --git a/recipes-graphics/userland/userland/0014-initialize-front-back-wayland-buffers.patch b/recipes-graphics/userland/userland/0014-initialize-front-back-wayland-buffers.patch new file mode 100644 index 0000000..26cae0a --- /dev/null +++ b/recipes-graphics/userland/userland/0014-initialize-front-back-wayland-buffers.patch | |||
@@ -0,0 +1,34 @@ | |||
1 | From 2c1574b2e867bb5dad028784642a9ad88df6b16c Mon Sep 17 00:00:00 2001 | ||
2 | From: Khem Raj <raj.khem@gmail.com> | ||
3 | Date: Sat, 6 Feb 2016 11:11:41 -0800 | ||
4 | Subject: [PATCH 14/16] initialize front back wayland buffers | ||
5 | |||
6 | origins from metrological wayland support | ||
7 | |||
8 | Signed-off-by: Khem Raj <raj.khem@gmail.com> | ||
9 | --- | ||
10 | interface/khronos/egl/egl_client_surface.c | 3 +++ | ||
11 | 1 file changed, 3 insertions(+) | ||
12 | |||
13 | diff --git a/interface/khronos/egl/egl_client_surface.c b/interface/khronos/egl/egl_client_surface.c | ||
14 | index 512c83b..a429724 100644 | ||
15 | --- a/interface/khronos/egl/egl_client_surface.c | ||
16 | +++ b/interface/khronos/egl/egl_client_surface.c | ||
17 | @@ -401,11 +401,14 @@ EGL_SURFACE_T *egl_surface_create( | ||
18 | #ifdef BUILD_WAYLAND | ||
19 | if (type == WINDOW && wl_display) { | ||
20 | surface->wl_egl_window = (struct wl_egl_window*)win; | ||
21 | + surface->front_wl_buffer = NULL; | ||
22 | surface->back_wl_buffer = allocate_wl_buffer( | ||
23 | surface->wl_egl_window, color); | ||
24 | resource = surface->back_wl_buffer->resource; | ||
25 | } else { | ||
26 | surface->wl_egl_window = NULL; | ||
27 | + surface->front_wl_buffer = NULL; | ||
28 | + surface->back_wl_buffer = NULL; | ||
29 | resource = DISPMANX_NO_HANDLE; | ||
30 | } | ||
31 | #endif | ||
32 | -- | ||
33 | 2.7.0 | ||
34 | |||
diff --git a/recipes-graphics/userland/userland_git.bb b/recipes-graphics/userland/userland_git.bb index bbba080..75e437f 100644 --- a/recipes-graphics/userland/userland_git.bb +++ b/recipes-graphics/userland/userland_git.bb | |||
@@ -25,12 +25,25 @@ SRC_URI = "\ | |||
25 | file://0005-user-vcsm-Fix-build-with-clang.patch \ | 25 | file://0005-user-vcsm-Fix-build-with-clang.patch \ |
26 | file://0006-Fix-enum-type-conversion-warnings.patch \ | 26 | file://0006-Fix-enum-type-conversion-warnings.patch \ |
27 | file://0007-vcos_platform_types-Dont-use-extern-inline-with-clan.patch \ | 27 | file://0007-vcos_platform_types-Dont-use-extern-inline-with-clan.patch \ |
28 | file://0008-Allow-applications-to-set-next-resource-handle.patch \ | ||
29 | file://0009-wayland-Add-support-for-the-Wayland-winsys.patch \ | ||
30 | file://0010-wayland-Add-Wayland-example.patch \ | ||
31 | file://0011-wayland-egl-Add-bcm_host-to-dependencies.patch \ | ||
32 | file://0012-interface-remove-faulty-assert-to-make-weston-happy-.patch \ | ||
33 | file://0013-zero-out-wl-buffers-in-egl_surface_free.patch \ | ||
34 | file://0014-initialize-front-back-wayland-buffers.patch \ | ||
28 | " | 35 | " |
29 | S = "${WORKDIR}/git" | 36 | S = "${WORKDIR}/git" |
30 | 37 | ||
31 | inherit cmake pkgconfig | 38 | inherit cmake pkgconfig |
32 | 39 | ||
33 | EXTRA_OECMAKE = "-DCMAKE_BUILD_TYPE=Release -DCMAKE_EXE_LINKER_FLAGS='-Wl,--no-as-needed'" | 40 | EXTRA_OECMAKE = "-DCMAKE_BUILD_TYPE=Release -DCMAKE_EXE_LINKER_FLAGS='-Wl,--no-as-needed' \ |
41 | " | ||
42 | |||
43 | PACKAGECONFIG ?= "${@bb.utils.contains('DISTRO_FEATURES', 'wayland', 'wayland', '', d)}" | ||
44 | |||
45 | PACKAGECONFIG[wayland] = "-DBUILD_WAYLAND=TRUE,,wayland," | ||
46 | |||
34 | CFLAGS_append = " -fPIC" | 47 | CFLAGS_append = " -fPIC" |
35 | 48 | ||
36 | do_install_append () { | 49 | do_install_append () { |
@@ -45,6 +58,7 @@ do_install_append () { | |||
45 | # to force the .so files into the runtime package (and keep them | 58 | # to force the .so files into the runtime package (and keep them |
46 | # out of -dev package). | 59 | # out of -dev package). |
47 | FILES_SOLIBSDEV = "" | 60 | FILES_SOLIBSDEV = "" |
61 | INSANE_SKIP_${PN} += "dev-so" | ||
48 | 62 | ||
49 | FILES_${PN} += " \ | 63 | FILES_${PN} += " \ |
50 | ${libdir}/*.so \ | 64 | ${libdir}/*.so \ |