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