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