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