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