├── .github └── workflows │ ├── arch-build.yml │ ├── autoconf-build.yml │ ├── meson-build.yml │ └── meson-llvm-build.yml ├── .gitignore ├── COPYING ├── Makefile.am ├── README.md ├── autogen.sh ├── configure.ac ├── include ├── wayland-drm.h ├── wayland-egldevice.h ├── wayland-egldisplay.h ├── wayland-eglhandle.h ├── wayland-eglstream-server.h ├── wayland-eglstream.h ├── wayland-eglsurface-internal.h ├── wayland-eglsurface.h ├── wayland-eglswap.h ├── wayland-eglutils.h ├── wayland-external-exports.h └── wayland-thread.h ├── m4 ├── ax_check_compile_flag.m4 ├── ax_check_enable_debug.m4 ├── ax_check_link_flag.m4 └── ax_pthread.m4 ├── meson.build ├── src ├── 10_nvidia_wayland.json ├── meson.build ├── wayland-drm.c ├── wayland-egldevice.c ├── wayland-egldisplay.c ├── wayland-eglhandle.c ├── wayland-eglstream-server.c ├── wayland-eglstream.c ├── wayland-eglsurface.c ├── wayland-eglswap.c ├── wayland-eglutils.c ├── wayland-external-exports.c └── wayland-thread.c ├── wayland-drm ├── meson.build └── wayland-drm.xml ├── wayland-egl └── wayland-egl-ext.h ├── wayland-eglstream-protocols.pc.in ├── wayland-eglstream.pc.in └── wayland-eglstream ├── .gitignore ├── meson.build ├── wayland-eglstream-controller.xml └── wayland-eglstream.xml /.github/workflows/arch-build.yml: -------------------------------------------------------------------------------- 1 | name: Arch Build 2 | on: [push, pull_request] 3 | jobs: 4 | Meson-Build: 5 | runs-on: ubuntu-24.04 6 | container: 7 | image: archlinux:latest 8 | steps: 9 | - uses: actions/checkout@v4 10 | - run: pacman --noconfirm -Syy 11 | - run: pacman --noconfirm -S wayland-protocols libdrm libglvnd pkgconf 12 | - run: pacman --noconfirm -S wayland eglexternalplatform 13 | - run: pacman --noconfirm -S meson ninja gcc 14 | - run: meson build 15 | - run: ninja -C build 16 | - run: ninja -C build install 17 | -------------------------------------------------------------------------------- /.github/workflows/autoconf-build.yml: -------------------------------------------------------------------------------- 1 | name: Autotools GCC Build 2 | on: [push, pull_request] 3 | jobs: 4 | Meson-Build: 5 | runs-on: ubuntu-24.04 6 | steps: 7 | - uses: actions/checkout@v4 8 | - run: sudo apt update 9 | - run: sudo apt install -y wayland-protocols libdrm-dev libegl-dev 10 | - run: sudo apt install -y libwayland-dev libwayland-egl-backend-dev eglexternalplatform-dev 11 | - run: sudo apt install -y meson ninja-build gcc 12 | - run: ./autogen.sh 13 | - run: make 14 | - run: sudo make install 15 | -------------------------------------------------------------------------------- /.github/workflows/meson-build.yml: -------------------------------------------------------------------------------- 1 | name: Meson GCC Build 2 | on: [push, pull_request] 3 | jobs: 4 | Meson-Build: 5 | runs-on: ubuntu-24.04 6 | steps: 7 | - uses: actions/checkout@v4 8 | - run: sudo apt update 9 | - run: sudo apt install -y wayland-protocols libdrm-dev libegl-dev 10 | - run: sudo apt install -y libwayland-dev libwayland-egl-backend-dev eglexternalplatform-dev 11 | - run: sudo apt install -y meson ninja-build gcc 12 | - run: meson build 13 | - run: ninja -C build 14 | - run: sudo ninja -C build install 15 | -------------------------------------------------------------------------------- /.github/workflows/meson-llvm-build.yml: -------------------------------------------------------------------------------- 1 | name: Meson LLVM Build 2 | on: [push, pull_request] 3 | jobs: 4 | Meson-Build: 5 | runs-on: ubuntu-24.04 6 | steps: 7 | - uses: actions/checkout@v4 8 | - run: sudo apt update 9 | - run: sudo apt install -y wayland-protocols libdrm-dev libegl-dev 10 | - run: sudo apt install -y libwayland-dev libwayland-egl-backend-dev eglexternalplatform-dev 11 | - run: sudo apt install -y meson ninja-build clang 12 | - name: meson build 13 | run: meson build 14 | env: 15 | CC: clang 16 | - run: ninja -C build 17 | - run: sudo ninja -C build install 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Taken from https://github.com/github/gitignore 2 | 3 | # Build system ignores 4 | 5 | # http://www.gnu.org/software/automake 6 | 7 | Makefile.in 8 | /ar-lib 9 | /mdate-sh 10 | /test-driver 11 | /ylwrap 12 | 13 | # http://www.gnu.org/software/autoconf 14 | 15 | /autom4te.cache 16 | /autoscan.log 17 | /autoscan-*.log 18 | /aclocal.m4 19 | /compile 20 | /config.guess 21 | /config.h.in 22 | /config.sub 23 | /configure 24 | /configure.scan 25 | /depcomp 26 | /install-sh 27 | /missing 28 | /stamp-h1 29 | 30 | # other stuff generated by us 31 | /m4/* 32 | /build/* 33 | 34 | # C ignores 35 | 36 | # Object files 37 | *.o 38 | *.ko 39 | *.obj 40 | *.elf 41 | 42 | # Prerequisites 43 | *.d 44 | 45 | # Object files 46 | *.o 47 | *.ko 48 | *.obj 49 | *.elf 50 | 51 | # Linker output 52 | *.ilk 53 | *.map 54 | *.exp 55 | 56 | # Precompiled Headers 57 | *.gch 58 | *.pch 59 | 60 | # Libraries 61 | *.lib 62 | *.a 63 | *.la 64 | *.lo 65 | 66 | # Shared objects 67 | *.so 68 | *.so.* 69 | *.dylib 70 | 71 | # Executables 72 | *.out 73 | *.i*86 74 | *.x86_64 75 | *.hex 76 | 77 | # Debug files 78 | *.dSYM/ 79 | *.su 80 | *.idb 81 | *.pdb 82 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a 4 | copy of this software and associated documentation files (the "Software"), 5 | to deal in the Software without restriction, including without limitation 6 | the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | and/or sell copies of the Software, and to permit persons to whom the 8 | Software is furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | DEALINGS IN THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | 2 | # Install libraries 3 | lib_LTLIBRARIES = libnvidia-egl-wayland.la 4 | 5 | # Include paths 6 | libnvidia_egl_wayland_la_CFLAGS = \ 7 | -I$(top_srcdir)/wayland-egl \ 8 | -I$(top_srcdir)/include \ 9 | -I$(top_builddir)/wayland-eglstream \ 10 | -I$(top_builddir)/wayland-drm 11 | 12 | # Required library flags 13 | libnvidia_egl_wayland_la_CFLAGS += \ 14 | $(PTHREAD_CFLAGS) \ 15 | $(EGL_CFLAGS) \ 16 | $(EGL_EXTERNAL_PLATFORM_CFLAGS) \ 17 | $(WAYLAND_CFLAGS) \ 18 | $(LIBDRM_CFLAGS) \ 19 | $(COMPILER_FLAG_VISIBILITY_HIDDEN) 20 | 21 | # Make sure we don't use deprecated stuff 22 | libnvidia_egl_wayland_la_CFLAGS += \ 23 | -DWL_HIDE_DEPRECATED 24 | 25 | libnvidia_egl_wayland_la_LDFLAGS = \ 26 | -shared \ 27 | -Wl,-Bsymbolic \ 28 | -ldl \ 29 | $(WAYLAND_LIBS) \ 30 | $(LIBDRM_LIBS) \ 31 | -version-number $(WAYLAND_EXTERNAL_MAJOR_VERSION):$(WAYLAND_EXTERNAL_MINOR_VERSION):$(WAYLAND_EXTERNAL_MICRO_VERSION) \ 32 | $(LINKER_FLAG_NO_UNDEFINED) 33 | 34 | libnvidia_egl_wayland_la_SOURCES = \ 35 | src/wayland-thread.c \ 36 | src/wayland-egldevice.c \ 37 | src/wayland-egldisplay.c \ 38 | src/wayland-eglstream.c \ 39 | src/wayland-eglstream-server.c \ 40 | src/wayland-eglsurface.c \ 41 | src/wayland-eglswap.c \ 42 | src/wayland-eglutils.c \ 43 | src/wayland-eglhandle.c \ 44 | src/wayland-drm.c \ 45 | src/wayland-external-exports.c 46 | 47 | libnvidia_egl_wayland_la_SOURCES += \ 48 | include/wayland-drm.h \ 49 | include/wayland-egldevice.h \ 50 | include/wayland-egldisplay.h \ 51 | include/wayland-eglhandle.h \ 52 | include/wayland-eglstream.h \ 53 | include/wayland-eglstream-server.h \ 54 | include/wayland-eglsurface.h \ 55 | include/wayland-eglsurface-internal.h \ 56 | include/wayland-eglswap.h \ 57 | include/wayland-eglutils.h \ 58 | include/wayland-external-exports.h \ 59 | include/wayland-thread.h \ 60 | wayland-egl/wayland-egl-ext.h 61 | 62 | libnvidia_egl_wayland_la_built_public_protocols = \ 63 | wayland-eglstream/wayland-eglstream-controller-protocol.c \ 64 | wayland-drm/wayland-drm-protocol.c 65 | 66 | libnvidia_egl_wayland_la_built_private_protocols = \ 67 | wayland-eglstream/wayland-eglstream-protocol.c 68 | 69 | libnvidia_egl_wayland_la_built_client_headers = \ 70 | wayland-eglstream/wayland-eglstream-client-protocol.h \ 71 | wayland-eglstream/wayland-eglstream-controller-client-protocol.h \ 72 | wayland-drm/wayland-drm-client-protocol.h 73 | 74 | libnvidia_egl_wayland_la_built_server_headers = \ 75 | wayland-eglstream/wayland-eglstream-server-protocol.h \ 76 | wayland-drm/wayland-drm-server-protocol.h 77 | 78 | libnvidia_egl_wayland_la_dmabuf_built_client_headers = \ 79 | linux-dmabuf-unstable-v1-client-protocol.h 80 | 81 | libnvidia_egl_wayland_la_dmabuf_built_private_protocols = \ 82 | linux-dmabuf-unstable-v1-protocol.c 83 | 84 | libnvidia_egl_wayland_la_drm_syncobj_built_client_headers = \ 85 | linux-drm-syncobj-v1-client-protocol.h 86 | 87 | libnvidia_egl_wayland_la_drm_syncobj_built_private_protocols = \ 88 | linux-drm-syncobj-v1-protocol.c 89 | 90 | libnvidia_egl_wayland_la_presentation_time_built_client_headers = \ 91 | presentation-time-client-protocol.h 92 | 93 | libnvidia_egl_wayland_la_presentation_time_private_protocols = \ 94 | presentation-time-protocol.c 95 | 96 | libnvidia_egl_wayland_la_built_sources = \ 97 | $(libnvidia_egl_wayland_la_built_public_protocols) \ 98 | $(libnvidia_egl_wayland_la_built_private_protocols) \ 99 | $(libnvidia_egl_wayland_la_built_client_headers) \ 100 | $(libnvidia_egl_wayland_la_built_server_headers) \ 101 | $(libnvidia_egl_wayland_la_dmabuf_built_client_headers) \ 102 | $(libnvidia_egl_wayland_la_dmabuf_built_private_protocols) \ 103 | $(libnvidia_egl_wayland_la_drm_syncobj_built_client_headers) \ 104 | $(libnvidia_egl_wayland_la_drm_syncobj_built_private_protocols) \ 105 | $(libnvidia_egl_wayland_la_presentation_time_built_client_headers) \ 106 | $(libnvidia_egl_wayland_la_presentation_time_private_protocols) 107 | 108 | nodist_libnvidia_egl_wayland_la_SOURCES = $(libnvidia_egl_wayland_la_built_sources) 109 | 110 | dist_pkgdata_DATA = \ 111 | wayland-eglstream/wayland-eglstream.xml \ 112 | wayland-eglstream/wayland-eglstream-controller.xml \ 113 | wayland-drm/wayland-drm.xml 114 | 115 | wayland_eglstream_pkgconfig_files = \ 116 | wayland-eglstream.pc \ 117 | wayland-eglstream-protocols.pc 118 | 119 | noarch_pkgconfig_DATA = $(wayland_eglstream_pkgconfig_files) 120 | 121 | CLEANFILES = \ 122 | $(libnvidia_egl_wayland_la_built_sources) \ 123 | $(wayland_eglstream_pkgconfig_files) 124 | 125 | $(libnvidia_egl_wayland_la_SOURCES): $(libnvidia_egl_wayland_la_built_sources) 126 | 127 | if WAYLAND_SCANNER_HAS_PRIVATE_CODE 128 | WAYLAND_PUBLIC_CODEGEN = public-code 129 | WAYLAND_PRIVATE_CODEGEN = private-code 130 | else 131 | WAYLAND_PUBLIC_CODEGEN = code 132 | WAYLAND_PRIVATE_CODEGEN = code 133 | endif 134 | 135 | $(libnvidia_egl_wayland_la_dmabuf_built_private_protocols):%-protocol.c : $(WAYLAND_PROTOCOLS_DATADIR)/unstable/linux-dmabuf/%.xml 136 | $(AM_V_GEN)$(WAYLAND_SCANNER) $(WAYLAND_PRIVATE_CODEGEN) < $< > $@ 137 | 138 | $(libnvidia_egl_wayland_la_dmabuf_built_client_headers):%-client-protocol.h : $(WAYLAND_PROTOCOLS_DATADIR)/unstable/linux-dmabuf/%.xml 139 | $(AM_V_GEN)$(WAYLAND_SCANNER) client-header < $< > $@ 140 | 141 | $(libnvidia_egl_wayland_la_drm_syncobj_built_private_protocols):%-protocol.c : $(WAYLAND_PROTOCOLS_DATADIR)/staging/linux-drm-syncobj/%.xml 142 | $(AM_V_GEN)$(WAYLAND_SCANNER) $(WAYLAND_PRIVATE_CODEGEN) < $< > $@ 143 | 144 | $(libnvidia_egl_wayland_la_drm_syncobj_built_client_headers):%-client-protocol.h : $(WAYLAND_PROTOCOLS_DATADIR)/staging/linux-drm-syncobj/%.xml 145 | $(AM_V_GEN)$(WAYLAND_SCANNER) client-header < $< > $@ 146 | 147 | $(libnvidia_egl_wayland_la_presentation_time_private_protocols):%-protocol.c : $(WAYLAND_PROTOCOLS_DATADIR)/stable/presentation-time/%.xml 148 | $(AM_V_GEN)$(WAYLAND_SCANNER) $(WAYLAND_PRIVATE_CODEGEN) < $< > $@ 149 | 150 | $(libnvidia_egl_wayland_la_presentation_time_built_client_headers):%-client-protocol.h : $(WAYLAND_PROTOCOLS_DATADIR)/stable/presentation-time/%.xml 151 | $(AM_V_GEN)$(WAYLAND_SCANNER) client-header < $< > $@ 152 | 153 | $(libnvidia_egl_wayland_la_built_public_protocols):%-protocol.c : %.xml 154 | $(AM_V_GEN)$(WAYLAND_SCANNER) $(WAYLAND_PUBLIC_CODEGEN) < $< > $@ 155 | 156 | $(libnvidia_egl_wayland_la_built_private_protocols):%-protocol.c : %.xml 157 | $(AM_V_GEN)$(WAYLAND_SCANNER) $(WAYLAND_PRIVATE_CODEGEN) < $< > $@ 158 | 159 | $(libnvidia_egl_wayland_la_built_client_headers):%-client-protocol.h : %.xml 160 | $(AM_V_GEN)$(WAYLAND_SCANNER) client-header < $< > $@ 161 | 162 | $(libnvidia_egl_wayland_la_built_server_headers):%-server-protocol.h : %.xml 163 | $(AM_V_GEN)$(WAYLAND_SCANNER) server-header < $< > $@ 164 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Wayland EGL External Platform library 2 | ===================================== 3 | 4 | Overview 5 | -------- 6 | 7 | This is a work-in-progress implementation of a EGL External Platform library to 8 | add client-side Wayland support to EGL on top of EGLDevice and EGLStream 9 | families of extensions. 10 | 11 | This library implements an EGL External Platform interface to work along with 12 | EGL drivers that support the external platform mechanism. More information 13 | about EGL External platforms and the interface can be found at: 14 | 15 | https://github.com/NVIDIA/eglexternalplatform 16 | 17 | 18 | Building and Installing the library 19 | ----------------------------------- 20 | 21 | This library build-depends on: 22 | 23 | * EGL headers 24 | 25 | https://www.khronos.org/registry/EGL/ 26 | 27 | * Wayland libraries & protocols 28 | 29 | https://wayland.freedesktop.org/ 30 | 31 | * EGL External Platform interface 32 | 33 | https://github.com/NVIDIA/eglexternalplatform 34 | 35 | 36 | To build, run: 37 | 38 | ./autogen.sh 39 | make 40 | 41 | 42 | To install, run: 43 | 44 | make install 45 | 46 | 47 | You can also use meson build system to build and install: 48 | 49 | meson builddir 50 | cd builddir 51 | ninja 52 | ninja install 53 | 54 | 55 | *Notes*: 56 | 57 | The NVIDIA EGL driver uses a JSON-based loader to load all EGL External 58 | platforms available on the system. 59 | 60 | If this library is not installed as part of a NVIDIA driver installation, 61 | a JSON configuration file must be manually added in order to make the 62 | library work with the NVIDIA driver. 63 | 64 | The default EGL External platform JSON configuration directory is: 65 | 66 | `/usr/share/egl/egl_external_platform.d/` 67 | 68 | 69 | Acknowledgements 70 | ---------------- 71 | 72 | Thanks to James Jones for the original implementation of the Wayland EGL 73 | platform. 74 | 75 | 76 | ### Wayland EGL External platform library ### 77 | 78 | The Wayland EGL External platform library itself is licensed as follows: 79 | 80 | Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. 81 | 82 | Permission is hereby granted, free of charge, to any person obtaining a 83 | copy of this software and associated documentation files (the "Software"), 84 | to deal in the Software without restriction, including without limitation 85 | the rights to use, copy, modify, merge, publish, distribute, sublicense, 86 | and/or sell copies of the Software, and to permit persons to whom the 87 | Software is furnished to do so, subject to the following conditions: 88 | 89 | The above copyright notice and this permission notice shall be included in 90 | all copies or substantial portions of the Software. 91 | 92 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 93 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 94 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 95 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 96 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 97 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 98 | DEALINGS IN THE SOFTWARE. 99 | 100 | 101 | ### buildconf ### 102 | 103 | The Wayland EGL External platform library uses the buildconf autotools 104 | bootstrapping script 'autogen.sh': 105 | 106 | http://freecode.com/projects/buildconf 107 | 108 | This script carries the following copyright notice: 109 | 110 | Copyright (c) 2005-2009 United States Government as represented by 111 | the U.S. Army Research Laboratory. 112 | 113 | Redistribution and use in source and binary forms, with or without 114 | modification, are permitted provided that the following conditions 115 | are met: 116 | 117 | 1. Redistributions of source code must retain the above copyright 118 | notice, this list of conditions and the following disclaimer. 119 | 120 | 2. Redistributions in binary form must reproduce the above 121 | copyright notice, this list of conditions and the following 122 | disclaimer in the documentation and/or other materials provided 123 | with the distribution. 124 | 125 | 3. The name of the author may not be used to endorse or promote 126 | products derived from this software without specific prior written 127 | permission. 128 | 129 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 130 | OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 131 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 132 | ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 133 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 134 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 135 | GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 136 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 137 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 138 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 139 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 140 | -------------------------------------------------------------------------------- /autogen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | test -n "$srcdir" || srcdir=`dirname "$0"` 4 | test -n "$srcdir" || srcdir=. 5 | ( 6 | cd "$srcdir" && 7 | autoreconf --force -v --install 8 | ) || exit 9 | test -n "$NOCONFIGURE" || "$srcdir/configure" "$@" 10 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | AC_PREREQ([2.64]) 2 | 3 | m4_define([wayland_eglstream_major_version], [1]) 4 | m4_define([wayland_eglstream_minor_version], [1]) 5 | m4_define([wayland_eglstream_micro_version], [20]) 6 | m4_define([wayland_eglstream_version], 7 | [wayland_eglstream_major_version.wayland_eglstream_minor_version.wayland_eglstream_micro_version]) 8 | 9 | AC_INIT([wayland-eglstream], 10 | [wayland_eglstream_version], 11 | [mvicomoya@nvidia.com]) 12 | 13 | AC_CONFIG_MACRO_DIR([m4]) 14 | AC_CONFIG_AUX_DIR([build]) 15 | AC_CONFIG_SRCDIR([config.h.in]) 16 | AC_CONFIG_HEADERS([config.h]) 17 | 18 | AC_GNU_SOURCE 19 | 20 | AC_SUBST([WAYLAND_EXTERNAL_MAJOR_VERSION], [wayland_eglstream_major_version]) 21 | AC_SUBST([WAYLAND_EXTERNAL_MINOR_VERSION], [wayland_eglstream_minor_version]) 22 | AC_SUBST([WAYLAND_EXTERNAL_MICRO_VERSION], [wayland_eglstream_micro_version]) 23 | AC_SUBST([WAYLAND_EXTERNAL_VERSION], [wayland_eglstream_version]) 24 | 25 | AC_SUBST([EGL_EXTERNAL_PLATFORM_MIN_VERSION], [${WAYLAND_EXTERNAL_MAJOR_VERSION}.${WAYLAND_EXTERNAL_MINOR_VERSION}]) 26 | AC_SUBST([EGL_EXTERNAL_PLATFORM_MAX_VERSION], [$(($WAYLAND_EXTERNAL_MAJOR_VERSION + 1))]) 27 | 28 | # Add an --enable-debug option 29 | AX_CHECK_ENABLE_DEBUG(no, DEBUG) 30 | 31 | AC_USE_SYSTEM_EXTENSIONS 32 | 33 | AM_INIT_AUTOMAKE([1.11 foreign subdir-objects]) 34 | 35 | AM_SILENT_RULES([yes]) 36 | 37 | PKG_PROG_PKG_CONFIG() 38 | 39 | # Checks for programs. 40 | AC_PROG_CC 41 | AC_PROG_CXX 42 | AM_PROG_AS 43 | AC_PROG_LIBTOOL 44 | 45 | AC_ARG_VAR([WAYLAND_SCANNER], [The wayland-scanner executable]) 46 | AC_PATH_PROG([WAYLAND_SCANNER], [wayland-scanner]) 47 | 48 | # User didn't specify wayland-scanner location manually, so find it ourselves 49 | if test x$WAYLAND_SCANNER = x; then 50 | PKG_CHECK_MODULES(WAYLAND_SCANNER, [wayland-scanner]) 51 | WAYLAND_SCANNER=`$PKG_CONFIG --variable=wayland_scanner wayland-scanner` 52 | fi 53 | AM_CONDITIONAL([WAYLAND_SCANNER_HAS_PRIVATE_CODE], 54 | [test x$WAYLAND_SCANNER = x`$PKG_CONFIG --variable=wayland_scanner "wayland-scanner >= 1.14.91"`]) 55 | 56 | # Check for protocols. 57 | PKG_CHECK_MODULES(WAYLAND_PROTOCOLS, [wayland-protocols >= 1.8]) 58 | AC_SUBST(WAYLAND_PROTOCOLS_DATADIR, `$PKG_CONFIG --variable=pkgdatadir wayland-protocols`) 59 | 60 | # Initialize libtool 61 | LT_PREREQ([2.2]) 62 | LT_INIT 63 | 64 | # Checks for libraries. 65 | AX_PTHREAD() 66 | AC_CHECK_LIB([dl], [dlsym], 67 | [], 68 | [AC_MSG_ERROR("dlsym is needed to compile wayland-egldisplay")]) 69 | PKG_CHECK_MODULES([EGL_HEADERS], [egl >= 1.5 egl < 2]) 70 | PKG_CHECK_MODULES([EGL_EXTERNAL_PLATFORM], [eglexternalplatform >= ${EGL_EXTERNAL_PLATFORM_MIN_VERSION} eglexternalplatform < ${EGL_EXTERNAL_PLATFORM_MAX_VERSION}]) 71 | PKG_CHECK_MODULES([WAYLAND], [wayland-server wayland-client wayland-egl-backend >= 3]) 72 | PKG_CHECK_MODULES([LIBDRM], [libdrm]) 73 | 74 | # Checks for header files. 75 | AC_CHECK_HEADERS([arpa/inet.h stddef.h stdint.h stdlib.h string.h sys/socket.h unistd.h]) 76 | 77 | # Checks for typedefs, structures, and compiler characteristics. 78 | AC_C_INLINE 79 | AC_TYPE_INT32_T 80 | AC_TYPE_SIZE_T 81 | AC_TYPE_UINT32_T 82 | 83 | # Checks for library functions. 84 | AC_FUNC_MALLOC 85 | AC_CHECK_FUNCS([getpagesize inet_ntoa memset socket strcasecmp strstr]) 86 | 87 | # See if the compiler supports the -fvisibility=hidden flag. 88 | AX_CHECK_COMPILE_FLAG([-fvisibility=hidden], 89 | [COMPILER_FLAG_VISIBILITY_HIDDEN="-fvisibility=hidden"], 90 | [COMPILER_FLAG_VISIBILITY_HIDDEN=""]) 91 | AC_SUBST([COMPILER_FLAG_VISIBILITY_HIDDEN]) 92 | 93 | # See if the linker supports the --no-undefined flag. 94 | AX_CHECK_LINK_FLAG([-Xlinker --no-undefined], 95 | [LINKER_FLAG_NO_UNDEFINED="-Xlinker --no-undefined"], 96 | [LINKER_FLAG_NO_UNDEFINED=""]) 97 | AC_SUBST([LINKER_FLAG_NO_UNDEFINED]) 98 | 99 | # Default CFLAGS 100 | CFLAGS="$CFLAGS -Wall -Werror -include config.h" 101 | 102 | PKG_NOARCH_INSTALLDIR 103 | 104 | AC_CONFIG_FILES([ 105 | wayland-eglstream.pc 106 | wayland-eglstream-protocols.pc 107 | Makefile 108 | ]) 109 | AC_OUTPUT 110 | 111 | AC_MSG_RESULT([ 112 | Version ${WAYLAND_EXTERNAL_VERSION} 113 | Prefix ${prefix} 114 | ]) 115 | -------------------------------------------------------------------------------- /include/wayland-drm.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | #ifndef WAYLAND_DRM_H 24 | #define WAYLAND_DRM_H 25 | 26 | extern const char * 27 | wl_drm_get_dev_name(const WlEglPlatformData *data, 28 | EGLDisplay dpy); 29 | 30 | extern EGLBoolean 31 | wl_drm_display_bind(struct wl_display *display, 32 | struct wl_eglstream_display *wlStreamDpy, 33 | const char *dev_name); 34 | extern void 35 | wl_drm_display_unbind(struct wl_eglstream_display *wlStreamDpy); 36 | 37 | #endif /* WAYLAND_DRM_H */ 38 | -------------------------------------------------------------------------------- /include/wayland-egldevice.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2019, NVIDIA CORPORATION. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | #ifndef WAYLAND_EGLDEVICE_H 24 | #define WAYLAND_EGLDEVICE_H 25 | 26 | #include 27 | #include 28 | #include 29 | #include "wayland-external-exports.h" 30 | #include "wayland-eglhandle.h" 31 | 32 | #include 33 | 34 | #ifdef __cplusplus 35 | extern "C" { 36 | #endif 37 | 38 | /** 39 | * Keeps track of an internal display. 40 | * 41 | * Since the same internal display can be shared by multiple external displays, 42 | * the internal displays are always created with the EGL_TRACK_REFERENCES_KHR 43 | * flag set. If the driver doesn't support that extension, then we keep track 44 | * of an initialization count to produce the same behavior. 45 | */ 46 | typedef struct WlEglDeviceDpyRec { 47 | EGLDeviceEXT eglDevice; 48 | EGLDisplay eglDisplay; 49 | WlEglPlatformData *data; 50 | 51 | unsigned int initCount; 52 | EGLint major; 53 | EGLint minor; 54 | 55 | /* The EGL DRM device */ 56 | dev_t dev; 57 | /* The EGL DRM render node */ 58 | dev_t renderNode; 59 | 60 | struct { 61 | unsigned int stream : 1; 62 | unsigned int stream_attrib : 1; 63 | unsigned int stream_cross_process_fd : 1; 64 | unsigned int stream_remote : 1; 65 | unsigned int stream_producer_eglsurface : 1; 66 | unsigned int stream_fifo_synchronous : 1; 67 | unsigned int stream_sync : 1; 68 | unsigned int stream_flush : 1; 69 | unsigned int stream_consumer_eglimage : 1; 70 | unsigned int image_dma_buf_export : 1; 71 | } exts; 72 | 73 | struct wl_list link; 74 | } WlEglDeviceDpy; 75 | 76 | /** 77 | * Returns the WlEglDeviceDpy structure for a given device. 78 | * Note that the same device will always return the same WlEglDeviceDpy. 79 | */ 80 | WlEglDeviceDpy *wlGetInternalDisplay(WlEglPlatformData *data, EGLDeviceEXT device); 81 | 82 | /** 83 | * Frees all of the WlEglDeviceDpy structures. 84 | */ 85 | void wlFreeAllInternalDisplays(WlEglPlatformData *data); 86 | 87 | EGLBoolean wlInternalInitialize(WlEglDeviceDpy *devDpy); 88 | EGLBoolean wlInternalTerminate(WlEglDeviceDpy *devDpy); 89 | 90 | #ifdef __cplusplus 91 | } 92 | #endif 93 | 94 | #endif // WAYLAND_EGLDEVICE_H 95 | -------------------------------------------------------------------------------- /include/wayland-egldisplay.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2018, NVIDIA CORPORATION. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | #ifndef WAYLAND_EGLDISPLAY_H 24 | #define WAYLAND_EGLDISPLAY_H 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include "wayland-external-exports.h" 32 | #include "wayland-eglhandle.h" 33 | #include "wayland-egldevice.h" 34 | 35 | #ifdef __cplusplus 36 | extern "C" { 37 | #endif 38 | 39 | /* This define represents the version of the wl_eglstream_controller interface 40 | when the attach_eglstream_consumer_attrib() request was first available" */ 41 | #define WL_EGLSTREAM_CONTROLLER_ATTACH_EGLSTREAM_CONSUMER_ATTRIB_SINCE 2 42 | 43 | /* 44 | * Our representation of a dmabuf format. It has a drm_fourcc.h code 45 | * and a collection of modifiers that are supported. 46 | */ 47 | typedef struct WlEglDmaBufFormatRec { 48 | uint32_t format; 49 | uint32_t numModifiers; 50 | uint64_t *modifiers; 51 | } WlEglDmaBufFormat; 52 | 53 | /* 54 | * This is a helper struct for a collection of dmabuf formats. We have 55 | * a couple areas of the code that want to manage sets of formats and 56 | * this allows us to share code. 57 | */ 58 | typedef struct WlEglDmaBufFormatSetRec { 59 | uint32_t numFormats; 60 | WlEglDmaBufFormat *dmaBufFormats; 61 | } WlEglDmaBufFormatSet; 62 | 63 | /* 64 | * Container for all formats supported by a device. A "tranche" is 65 | * really just a set of formats and modifiers supported by a device 66 | * with a certain set of flags (really just a scanout flag). 67 | */ 68 | typedef struct WlEglDmaBufTrancheRec { 69 | dev_t drmDev; 70 | int supportsScanout; 71 | WlEglDmaBufFormatSet formatSet; 72 | } WlEglDmaBufTranche; 73 | 74 | /* 75 | * This is one item in the format table that the compositor sent 76 | * us. 77 | */ 78 | typedef struct WlEglDmaBufFormatTableEntryRec{ 79 | uint32_t format; 80 | uint32_t pad; 81 | uint64_t modifier; 82 | } WlEglDmaBufFormatTableEntry; 83 | 84 | /* 85 | * In linux_dmabuf_feedback.format_table the compositor will advertise all 86 | * (format, modifier) pairs that it supports importing buffers with. We 87 | * the client mmap this format table and refer to it during the tranche 88 | * events to construct WlEglDmaBufFormatSets that the compositor 89 | * supports. 90 | */ 91 | typedef struct WlEglDmaBufFormatTableRec { 92 | int len; 93 | /* This is mmapped from the fd given to us by the compositor */ 94 | WlEglDmaBufFormatTableEntry *entry; 95 | } WlEglDmaBufFormatTable; 96 | 97 | /* 98 | * A dmabuf feedback object. This will record all tranches sent by the 99 | * compositor. It can be used either for per-surface feedback or for 100 | * the default feedback for any surface. 101 | */ 102 | typedef struct WlEglDmaBufFeedbackRec { 103 | struct zwp_linux_dmabuf_feedback_v1 *wlDmaBufFeedback; 104 | int numTranches; 105 | WlEglDmaBufTranche *tranches; 106 | WlEglDmaBufFormatTable formatTable; 107 | dev_t mainDev; 108 | /* 109 | * This will be filled in during wl events and copied to 110 | * dev_formats on dmabuf_feedback.tranche_done 111 | */ 112 | WlEglDmaBufTranche tmpTranche; 113 | int feedbackDone; 114 | /* 115 | * This will be set to true if the compositor notified us of new 116 | * modifiers but we haven't reallocated our surface yet. 117 | */ 118 | int unprocessedFeedback; 119 | } WlEglDmaBufFeedback; 120 | 121 | typedef struct WlEglDisplayRec { 122 | WlEglDeviceDpy *devDpy; 123 | 124 | /* Supports EGL_ANDROID_native_fence_sync */ 125 | int supports_native_fence_sync; 126 | /* Underlying driver version is recent enough for explicit sync */ 127 | int supports_explicit_sync; 128 | 129 | EGLBoolean ownNativeDpy; 130 | struct wl_display *nativeDpy; 131 | 132 | struct wl_registry *wlRegistry; 133 | struct wl_eglstream_display *wlStreamDpy; 134 | struct wl_eglstream_controller *wlStreamCtl; 135 | struct zwp_linux_dmabuf_v1 *wlDmaBuf; 136 | struct wp_linux_drm_syncobj_manager_v1 *wlDrmSyncobj; 137 | unsigned int wlStreamCtlVer; 138 | struct wp_presentation *wpPresentation; 139 | struct wl_event_queue *wlEventQueue; 140 | struct { 141 | unsigned int stream_fd : 1; 142 | unsigned int stream_inet : 1; 143 | unsigned int stream_socket : 1; 144 | } caps; 145 | 146 | WlEglPlatformData *data; 147 | 148 | /* DRM device in use */ 149 | int drmFd; 150 | 151 | EGLBoolean useInitRefCount; 152 | EGLDeviceEXT requestedDevice; 153 | 154 | /** 155 | * The number of times that eglTerminate has to be called before the 156 | * display is termianted. 157 | * 158 | * If \c useInitRefCount is true, then this is incremented each time 159 | * eglInitialize is called, and decremented each time eglTerminate is 160 | * called. 161 | * 162 | * If \c useInitRefCount is false, then this value is capped at 1. 163 | * 164 | * In all cases, the display is initialized if (initCount > 0). 165 | */ 166 | unsigned int initCount; 167 | 168 | pthread_mutex_t mutex; 169 | 170 | int refCount; 171 | 172 | struct wl_list wlEglSurfaceList; 173 | 174 | struct wl_list link; 175 | 176 | /* The formats given to us by the linux_dmabuf.modifiers event */ 177 | WlEglDmaBufFormatSet formatSet; 178 | 179 | /* The linux_dmabuf protocol version in use. Will be >= 3 */ 180 | unsigned int dmaBufProtocolVersion; 181 | 182 | WlEglDmaBufFeedback defaultFeedback; 183 | 184 | EGLBoolean primeRenderOffload; 185 | 186 | char *extensionString; 187 | } WlEglDisplay; 188 | 189 | typedef struct WlEventQueueRec { 190 | WlEglDisplay *display; 191 | struct wl_event_queue *queue; 192 | int refCount; 193 | 194 | struct wl_list dpyLink; 195 | struct wl_list dangLink; 196 | struct wl_list threadLink; 197 | } WlEventQueue; 198 | 199 | int WlEglRegisterFeedback(WlEglDmaBufFeedback *feedback); 200 | void wlEglDestroyFeedback(WlEglDmaBufFeedback *feedback); 201 | EGLBoolean wlEglIsValidNativeDisplayExport(void *data, void *nativeDpy); 202 | EGLBoolean wlEglBindDisplaysHook(void *data, EGLDisplay dpy, void *nativeDpy); 203 | EGLBoolean wlEglUnbindDisplaysHook(EGLDisplay dpy, void *nativeDpy); 204 | EGLDisplay wlEglGetPlatformDisplayExport(void *data, 205 | EGLenum platform, 206 | void *nativeDpy, 207 | const EGLAttrib *attribs); 208 | EGLBoolean wlEglInitializeHook(EGLDisplay dpy, EGLint *major, EGLint *minor); 209 | EGLBoolean wlEglTerminateHook(EGLDisplay dpy); 210 | WlEglDisplay *wlEglAcquireDisplay(EGLDisplay dpy); 211 | void wlEglReleaseDisplay(WlEglDisplay *display); 212 | 213 | EGLBoolean wlEglChooseConfigHook(EGLDisplay dpy, 214 | EGLint const * attribs, 215 | EGLConfig * configs, 216 | EGLint configSize, 217 | EGLint * numConfig); 218 | EGLBoolean wlEglGetConfigAttribHook(EGLDisplay dpy, 219 | EGLConfig config, 220 | EGLint attribute, 221 | EGLint * value); 222 | 223 | EGLBoolean wlEglQueryDisplayAttribHook(EGLDisplay dpy, 224 | EGLint name, 225 | EGLAttrib *value); 226 | const char* wlEglQueryStringHook(EGLDisplay dpy, EGLint name); 227 | 228 | 229 | EGLBoolean wlEglIsWaylandDisplay(void *nativeDpy); 230 | EGLBoolean wlEglIsWlEglDisplay(WlEglDisplay *display); 231 | 232 | EGLBoolean wlEglDestroyAllDisplays(WlEglPlatformData *data); 233 | 234 | const char* wlEglQueryStringExport(void *data, 235 | EGLDisplay dpy, 236 | EGLExtPlatformString name); 237 | 238 | #ifdef __cplusplus 239 | } 240 | #endif 241 | 242 | #endif 243 | -------------------------------------------------------------------------------- /include/wayland-eglhandle.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2016, NVIDIA CORPORATION. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | #ifndef WAYLAND_EGLHANDLE_H 24 | #define WAYLAND_EGLHANDLE_H 25 | 26 | #include 27 | #include 28 | #include "wayland-external-exports.h" 29 | #include "wayland-egl-ext.h" 30 | #include 31 | 32 | #ifdef __cplusplus 33 | extern "C" { 34 | #endif 35 | 36 | /* 37 | * Define function pointers for EGL core functions 38 | */ 39 | typedef const char* (*PWLEGLFNQUERYSTRINGCOREPROC) (EGLDisplay dpy, EGLint name); 40 | typedef EGLContext (*PWLEGLFNGETCURRENTCONTEXTCOREPROC) (void); 41 | typedef EGLSurface (*PWLEGLFNGETCURRENTSURFACECOREPROC) (EGLint readdraw); 42 | typedef EGLBoolean (*PWLEGLFNRELEASETHREADCOREPROC) (void); 43 | typedef EGLint (*PWLEGLFNGETERRORCOREPROC) (void); 44 | typedef void* (*PWLEGLFNGETPROCADDRESSCOREPROC) (const char *name); 45 | typedef EGLBoolean (*PWLEGLFNINITIALIZECOREPROC) (EGLDisplay dpy, EGLint *major, EGLint *minor); 46 | typedef EGLBoolean (*PWLEGLFNTERMINATECOREPROC) (EGLDisplay dpy); 47 | typedef EGLBoolean (*PWLEGLFNCHOOSECONFIGCOREPROC) (EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config); 48 | typedef EGLBoolean (*PWLEGLFNGETCONFIGATTRIBCOREPROC) (EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value); 49 | typedef EGLSurface (*PWLEGLFNCREATEPBUFFERSURFACECOREPROC) (EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list); 50 | typedef EGLBoolean (*PWLEGLFNDESTROYSURFACECOREPROC) (EGLDisplay dpy, EGLSurface surface); 51 | typedef EGLBoolean (*PWLEGLFNMAKECURRENTCOREPROC) (EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx); 52 | typedef EGLBoolean (*PWLEGLFNSWAPBUFFERSCOREPROC) (EGLDisplay dpy, EGLSurface surface); 53 | typedef EGLBoolean (*PWLEGLFNSWAPBUFFERSWITHDAMAGEKHRPROC) (EGLDisplay dpy, EGLSurface surface, EGLint *rects, EGLint n_rects); 54 | typedef EGLBoolean (*PWLEGLFNSWAPINTERVALCOREPROC) (EGLDisplay dpy, EGLint interval); 55 | 56 | 57 | /* 58 | * WlEglPlatformData structure 59 | * 60 | * Keeps all EGL driver-specific methods provided by a specific EGL 61 | * implementation that are required by the Wayland external platform 62 | * implementation to manage resources associated with a specific backing 63 | * EGLDisplay. 64 | */ 65 | typedef struct WlEglPlatformDataRec { 66 | /* Application-facing callbacks fetched from the EGL driver */ 67 | struct { 68 | int major; 69 | int minor; 70 | 71 | PWLEGLFNQUERYSTRINGCOREPROC queryString; 72 | PFNEGLQUERYDEVICESEXTPROC queryDevices; 73 | 74 | PFNEGLGETPLATFORMDISPLAYEXTPROC getPlatformDisplay; 75 | PWLEGLFNINITIALIZECOREPROC initialize; 76 | PWLEGLFNTERMINATECOREPROC terminate; 77 | PWLEGLFNCHOOSECONFIGCOREPROC chooseConfig; 78 | PWLEGLFNGETCONFIGATTRIBCOREPROC getConfigAttrib; 79 | PFNEGLQUERYSURFACEPROC querySurface; 80 | 81 | PWLEGLFNGETCURRENTCONTEXTCOREPROC getCurrentContext; 82 | PWLEGLFNGETCURRENTSURFACECOREPROC getCurrentSurface; 83 | PWLEGLFNMAKECURRENTCOREPROC makeCurrent; 84 | 85 | PFNEGLCREATESTREAMKHRPROC createStream; 86 | PFNEGLCREATESTREAMFROMFILEDESCRIPTORKHRPROC createStreamFromFD; 87 | PFNEGLCREATESTREAMATTRIBNVPROC createStreamAttrib; 88 | PFNEGLGETSTREAMFILEDESCRIPTORKHRPROC getStreamFileDescriptor; 89 | PFNEGLCREATESTREAMPRODUCERSURFACEKHRPROC createStreamProducerSurface; 90 | PWLEGLFNCREATEPBUFFERSURFACECOREPROC createPbufferSurface; 91 | PFNEGLDESTROYSTREAMKHRPROC destroyStream; 92 | PWLEGLFNDESTROYSURFACECOREPROC destroySurface; 93 | 94 | PWLEGLFNSWAPBUFFERSCOREPROC swapBuffers; 95 | PWLEGLFNSWAPBUFFERSWITHDAMAGEKHRPROC swapBuffersWithDamage; 96 | PWLEGLFNSWAPINTERVALCOREPROC swapInterval; 97 | 98 | PWLEGLFNGETERRORCOREPROC getError; 99 | PWLEGLFNRELEASETHREADCOREPROC releaseThread; 100 | 101 | PFNEGLQUERYDISPLAYATTRIBEXTPROC queryDisplayAttrib; 102 | PFNEGLQUERYDEVICESTRINGEXTPROC queryDeviceString; 103 | 104 | /* Used for fifo_synchronous support */ 105 | PFNEGLQUERYSTREAMKHRPROC queryStream; 106 | PFNEGLQUERYSTREAMU64KHRPROC queryStreamu64; 107 | PFNEGLCREATESTREAMSYNCNVPROC createStreamSync; 108 | PFNEGLCLIENTWAITSYNCKHRPROC clientWaitSync; 109 | PFNEGLSIGNALSYNCKHRPROC signalSync; 110 | PFNEGLDESTROYSYNCKHRPROC destroySync; 111 | PFNEGLCREATESYNCKHRPROC createSync; 112 | PFNEGLSTREAMFLUSHNVPROC streamFlush; 113 | PFNEGLDUPNATIVEFENCEFDANDROIDPROC dupNativeFenceFD; 114 | 115 | /* Used for dma-buf surfaces */ 116 | PFNEGLSTREAMIMAGECONSUMERCONNECTNVPROC streamImageConsumerConnect; 117 | PFNEGLSTREAMACQUIREIMAGENVPROC streamAcquireImage; 118 | PFNEGLSTREAMRELEASEIMAGENVPROC streamReleaseImage; 119 | PFNEGLQUERYSTREAMCONSUMEREVENTNVPROC queryStreamConsumerEvent; 120 | PFNEGLEXPORTDMABUFIMAGEMESAPROC exportDMABUFImage; 121 | PFNEGLEXPORTDMABUFIMAGEQUERYMESAPROC exportDMABUFImageQuery; 122 | PFNEGLCREATEIMAGEKHRPROC createImage; 123 | PFNEGLDESTROYIMAGEKHRPROC destroyImage; 124 | } egl; 125 | 126 | /* Non-application-facing callbacks provided by the EGL driver */ 127 | struct { 128 | PEGLEXTFNSETERROR setError; 129 | PEGLEXTFNSTREAMSWAPINTERVAL streamSwapInterval; 130 | } callbacks; 131 | 132 | /* True if the driver supports the EGL_KHR_display_reference extension. */ 133 | EGLBoolean supportsDisplayReference; 134 | 135 | /* A linked list of WlEglDeviceDpy structs. */ 136 | struct wl_list deviceDpyList; 137 | 138 | /* pthread key for TLS */ 139 | pthread_key_t tlsKey; 140 | } WlEglPlatformData; 141 | 142 | 143 | /* 144 | * wlEglCreatePlatformData() 145 | * 146 | * Creates a new platform data structure and fills it out with all the required 147 | * application-facing EGL methods provided by . 148 | * 149 | * . correspond to the EGL External Platform interface 150 | * version supported by the driver. 151 | * 152 | * Returns a pointer to the newly created structure upon success; otherwise, 153 | * returns NULL. 154 | */ 155 | WlEglPlatformData* 156 | wlEglCreatePlatformData(int apiMajor, int apiMinor, const EGLExtDriver *driver); 157 | 158 | /* 159 | * wlEglDestroyPlatformData() 160 | * 161 | * Destroys the given platform data, previously created with 162 | * wlEglCreatePlatformData(). 163 | */ 164 | void wlEglDestroyPlatformData(WlEglPlatformData *data); 165 | 166 | void* wlEglGetInternalHandleExport(EGLDisplay dpy, EGLenum type, void *handle); 167 | 168 | #ifdef __cplusplus 169 | } 170 | #endif 171 | 172 | #endif 173 | -------------------------------------------------------------------------------- /include/wayland-eglstream-server.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2016, NVIDIA CORPORATION. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | #ifndef WAYLAND_EGLSTREAM_SERVER_H 24 | #define WAYLAND_EGLSTREAM_SERVER_H 25 | 26 | #include 27 | #include 28 | #include 29 | #include "wayland-eglhandle.h" 30 | 31 | #ifdef __cplusplus 32 | extern "C" { 33 | #endif 34 | 35 | /* 36 | * Forward declarations 37 | */ 38 | struct wl_eglstream_display; 39 | struct wl_eglstream; 40 | 41 | 42 | /* 43 | * wl_eglstream_display_bind() 44 | * 45 | * Creates and initializes a wl_eglstream_display connection associated to the 46 | * given wl_display and EGLDisplay. 47 | */ 48 | EGLBoolean 49 | wl_eglstream_display_bind(WlEglPlatformData *data, 50 | struct wl_display *wlDisplay, 51 | EGLDisplay eglDisplay, 52 | const char *exts, 53 | const char *dev_name); 54 | 55 | /* 56 | * wl_eglstream_display_unbind() 57 | * 58 | * Destroys the given wl_eglstream_display connection result of a previous 59 | * wl_eglstream_display_bind() call. 60 | */ 61 | void wl_eglstream_display_unbind(struct wl_eglstream_display *wlStreamDpy); 62 | 63 | /* 64 | * wl_eglstream_display_get() 65 | * 66 | * Given an EGL display, returns its associated wl_eglstream_display connection. 67 | */ 68 | struct wl_eglstream_display* wl_eglstream_display_get(EGLDisplay eglDisplay); 69 | 70 | /* 71 | * wl_eglstream_display_get_stream() 72 | * 73 | * Given a generic wl_resource, returns its associated wl_eglstream. 74 | */ 75 | struct wl_eglstream* 76 | wl_eglstream_display_get_stream(struct wl_eglstream_display *wlStreamDpy, 77 | struct wl_resource *resource); 78 | 79 | 80 | /* wl_eglstream_display definition */ 81 | struct wl_eglstream_display { 82 | WlEglPlatformData *data; 83 | 84 | struct wl_global *global; 85 | struct wl_display *wlDisplay; 86 | 87 | EGLDisplay eglDisplay; 88 | struct { 89 | int stream_attrib : 1; 90 | int stream_cross_process_fd : 1; 91 | int stream_remote : 1; 92 | int stream_socket : 1; 93 | int stream_socket_inet : 1; 94 | int stream_socket_unix : 1; 95 | int stream_origin : 1; 96 | } exts; 97 | 98 | struct { 99 | const char *device_name; 100 | struct wl_global *global; 101 | } *drm; 102 | 103 | int caps_override : 1; 104 | int supported_caps; 105 | 106 | struct wl_buffer_interface wl_eglstream_interface; 107 | 108 | struct wl_list link; 109 | }; 110 | 111 | /* wl_eglstream definition */ 112 | struct wl_eglstream { 113 | struct wl_resource *resource; 114 | struct wl_eglstream_display *wlStreamDpy; 115 | 116 | int width, height; 117 | 118 | EGLBoolean fromFd; 119 | EGLBoolean isInet; 120 | int handle; 121 | EGLStreamKHR eglStream; 122 | 123 | /* 124 | * The following attribute encodes the default value for a 125 | * stream's image inversion relative to wayland protocol 126 | * convention. Vulkan apps will be set to 'true', while 127 | * OpenGL apps will be set to 'false'. 128 | * NOTE: EGL_NV_stream_origin is the authorative source of 129 | * truth regarding a stream's frame orientation and should be 130 | * queried for an accurate value. The following attribute is a 131 | * 'best guess' fallback mechanism which should only be used 132 | * when a query to EGL_NV_stream_origin fails. 133 | */ 134 | EGLBoolean yInverted; 135 | }; 136 | 137 | #ifdef __cplusplus 138 | } 139 | #endif 140 | 141 | #endif 142 | -------------------------------------------------------------------------------- /include/wayland-eglstream.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | #ifndef WAYLAND_EGLSTREAM_H 24 | #define WAYLAND_EGLSTREAM_H 25 | 26 | #include 27 | #include 28 | 29 | #ifdef __cplusplus 30 | extern "C" { 31 | #endif 32 | 33 | /* wlEglCreateStreamAttribHook() 34 | * 35 | * Creates an EGLStream from the given external attribute list. If suceeded, 36 | * the new stream handle is returned; otherwise, EGL_NO_STREAM_KHR is returned 37 | * and the appropriate EGL error is generated. 38 | */ 39 | EGLStreamKHR wlEglCreateStreamAttribHook(EGLDisplay dpy, 40 | const EGLAttrib *attribs); 41 | 42 | #ifdef __cplusplus 43 | } 44 | #endif 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /include/wayland-eglsurface-internal.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2024, NVIDIA CORPORATION. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | #ifndef WAYLAND_EGLSURFACE_INTERNAL_H 24 | #define WAYLAND_EGLSURFACE_INTERNAL_H 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include "wayland-egldisplay.h" 31 | #include "wayland-eglutils.h" 32 | #include "wayland-eglsurface.h" 33 | 34 | #ifdef __cplusplus 35 | extern "C" { 36 | #endif 37 | 38 | typedef struct WlEglStreamImageRec { 39 | /* Pointer back to the parent surface for use in Wayland callbacks */ 40 | struct WlEglSurfaceRec *surface; 41 | 42 | EGLImageKHR eglImage; 43 | struct wl_buffer *buffer; 44 | EGLBoolean attached; 45 | struct wl_list acquiredLink; 46 | 47 | struct wp_linux_drm_syncobj_timeline_v1 *wlReleaseTimeline; 48 | uint32_t drmSyncobjHandle; 49 | int releasePending; 50 | /* Latest release point the compositor will signal with explicit sync */ 51 | uint64_t releasePoint; 52 | /* Cached acquire EGLSync from acquireImage */ 53 | EGLSyncKHR acquireSync; 54 | 55 | /* 56 | * Used for delaying the destruction of the image if we are waiting the 57 | * buffer release thread to use it later. 58 | */ 59 | EGLBoolean destructionPending; 60 | 61 | struct wl_list link; 62 | } WlEglStreamImage; 63 | 64 | typedef struct WlEglSurfaceCtxRec { 65 | EGLBoolean isOffscreen; 66 | EGLSurface eglSurface; 67 | EGLStreamKHR eglStream; 68 | void *wlStreamResource; 69 | EGLBoolean isAttached; 70 | 71 | int useDamageThread; 72 | pthread_t damageThreadId; 73 | EGLSyncKHR damageThreadSync; 74 | int damageThreadFlush; 75 | int damageThreadShutdown; 76 | EGLuint64KHR framesProduced; 77 | EGLuint64KHR framesFinished; 78 | EGLuint64KHR framesProcessed; 79 | 80 | /* 81 | * Use an individual mutex to guard access to streamImages. This helps us 82 | * to avoid sharing the surface lock between the app and buffer release 83 | * event threads, resulting in simplified lock management and smaller 84 | * critical sections. 85 | */ 86 | pthread_mutex_t streamImagesMutex; 87 | 88 | struct wl_list streamImages; 89 | struct wl_list acquiredImages; 90 | struct wl_buffer *currentBuffer; 91 | 92 | struct wl_list link; 93 | } WlEglSurfaceCtx; 94 | 95 | struct WlEglSurfaceRec { 96 | WlEglDisplay *wlEglDpy; 97 | EGLConfig eglConfig; 98 | EGLint *attribs; 99 | EGLBoolean pendingSwapIntervalUpdate; 100 | 101 | struct wl_egl_window *wlEglWin; 102 | long int wlEglWinVer; 103 | struct wl_surface *wlSurface; 104 | int width, height; 105 | int dx, dy; 106 | 107 | WlEglSurfaceCtx ctx; 108 | struct wl_list oldCtxList; 109 | 110 | EGLint swapInterval; 111 | EGLint fifoLength; 112 | 113 | int (*present_update_callback)(void*, uint64_t, int); 114 | struct wl_event_queue *presentFeedbackQueue; 115 | int inFlightPresentFeedbackCount; 116 | int landedPresentFeedbackCount; 117 | 118 | struct wl_callback *throttleCallback; 119 | struct wl_event_queue *wlEventQueue; 120 | 121 | /* Asynchronous wl_buffer.release event processing */ 122 | struct { 123 | struct wl_event_queue *wlBufferEventQueue; 124 | pthread_t bufferReleaseThreadId; 125 | int bufferReleaseThreadPipe[2]; 126 | }; 127 | 128 | struct wl_list link; 129 | 130 | EGLBoolean isSurfaceProducer; 131 | 132 | /* The refCount is initialized to 1 during EGLSurface creation, 133 | * gets incremented/decrementsd in wlEglSurfaceRef()/wlEglSurfaceUnref(), 134 | * when we enter/exit from eglSwapBuffers(). 135 | */ 136 | unsigned int refCount; 137 | /* 138 | * Set to EGL_TRUE before destroying the EGLSurface in eglDestroySurface(). 139 | */ 140 | EGLBoolean isDestroyed; 141 | 142 | /* The lock is used to serialize eglSwapBuffers()/eglDestroySurface(), 143 | * Using wlExternalApiLock() for this requires that we release lock 144 | * before dispatching frame sync events in wlEglWaitFrameSync(). 145 | */ 146 | pthread_mutex_t mutexLock; 147 | 148 | /* True when the EGL_PRESENT_OPAQUE_EXT surface attrib is set by the app */ 149 | EGLBoolean presentOpaque; 150 | 151 | /* This pair of mutex and conditional variable is used 152 | * for sychronization between eglSwapBuffers() and damage 153 | * thread on creating frame sync and waiting for it. 154 | */ 155 | pthread_mutex_t mutexFrameSync; 156 | pthread_cond_t condFrameSync; 157 | 158 | /* We want to delay the resizing of the window surface until the next 159 | * eglSwapBuffers(), so just set a resize flag. 160 | */ 161 | EGLBoolean isResized; 162 | 163 | WlEglDmaBufFeedback feedback; 164 | 165 | /* per-surface Explicit Sync objects */ 166 | struct wp_linux_drm_syncobj_surface_v1 *wlSyncobjSurf; 167 | struct wp_linux_drm_syncobj_timeline_v1 *wlAcquireTimeline; 168 | uint32_t drmSyncobjHandle; 169 | /* Last acquire point used. This starts at 1, zero means invalid. */ 170 | uint64_t syncPoint; 171 | }; 172 | 173 | void wlEglReallocSurface(WlEglDisplay *display, 174 | WlEglPlatformData *pData, 175 | WlEglSurface *surface); 176 | 177 | EGLSurface wlEglCreatePlatformWindowSurfaceHook(EGLDisplay dpy, 178 | EGLConfig config, 179 | void *nativeWin, 180 | const EGLAttrib *attribs); 181 | EGLSurface wlEglCreatePlatformPixmapSurfaceHook(EGLDisplay dpy, 182 | EGLConfig config, 183 | void *nativePixmap, 184 | const EGLAttrib *attribs); 185 | EGLSurface wlEglCreatePbufferSurfaceHook(EGLDisplay dpy, 186 | EGLConfig config, 187 | const EGLint *attribs); 188 | EGLSurface wlEglCreateStreamProducerSurfaceHook(EGLDisplay dpy, 189 | EGLConfig config, 190 | EGLStreamKHR stream, 191 | const EGLint *attribs); 192 | EGLBoolean wlEglDestroySurfaceHook(EGLDisplay dpy, EGLSurface eglSurface); 193 | EGLBoolean wlEglDestroyAllSurfaces(WlEglDisplay *display); 194 | 195 | EGLBoolean wlEglIsWaylandWindowValid(struct wl_egl_window *window); 196 | EGLBoolean wlEglIsWlEglSurfaceForDisplay(WlEglDisplay *display, WlEglSurface *wlEglSurface); 197 | 198 | EGLBoolean wlEglQuerySurfaceHook(EGLDisplay dpy, EGLSurface eglSurface, EGLint attribute, EGLint *value); 199 | 200 | EGLBoolean wlEglQueryNativeResourceHook(EGLDisplay dpy, 201 | void *nativeResource, 202 | EGLint attribute, 203 | int *value); 204 | 205 | EGLBoolean 206 | wlEglSurfaceCheckReleasePoints(WlEglDisplay *display, WlEglSurface *surface); 207 | 208 | EGLBoolean wlEglSendDamageEvent(WlEglSurface *surface, 209 | struct wl_event_queue *queue, 210 | EGLint *rects, 211 | EGLint n_rects); 212 | 213 | void wlEglCreateFrameSync(WlEglSurface *surface); 214 | EGLint wlEglWaitFrameSync(WlEglSurface *surface); 215 | 216 | EGLBoolean wlEglSurfaceRef(WlEglDisplay *display, WlEglSurface *surface); 217 | void wlEglSurfaceUnref(WlEglSurface *surface); 218 | 219 | EGLint wlEglHandleImageStreamEvents(WlEglSurface *surface); 220 | 221 | #ifdef __cplusplus 222 | } 223 | #endif 224 | 225 | #endif 226 | -------------------------------------------------------------------------------- /include/wayland-eglsurface.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2022, NVIDIA CORPORATION. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | #ifndef WAYLAND_EGLSURFACE_H 24 | #define WAYLAND_EGLSURFACE_H 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include "wayland-egldisplay.h" 31 | #include "wayland-eglutils.h" 32 | 33 | #ifdef __cplusplus 34 | extern "C" { 35 | #endif 36 | 37 | typedef struct WlEglSurfaceRec WlEglSurface; 38 | 39 | WL_EXPORT 40 | EGLStreamKHR wlEglGetSurfaceStreamExport(WlEglSurface *surface); 41 | 42 | WL_EXPORT 43 | WlEglSurface *wlEglCreateSurfaceExport(EGLDisplay dpy, 44 | int width, 45 | int height, 46 | struct wl_surface *native_surface, 47 | int fifo_length); 48 | 49 | WL_EXPORT 50 | WlEglSurface *wlEglCreateSurfaceExport2(EGLDisplay dpy, 51 | int width, 52 | int height, 53 | struct wl_surface *native_surface, 54 | int fifo_length, 55 | int (*present_update_callback)(void*, uint64_t, int), 56 | const EGLAttrib *attribs); 57 | 58 | WL_EXPORT 59 | int wlEglWaitAllPresentationFeedbacksExport(WlEglSurface *surface); 60 | 61 | WL_EXPORT 62 | int wlEglProcessPresentationFeedbacksExport(WlEglSurface *surface); 63 | 64 | #ifdef __cplusplus 65 | } 66 | #endif 67 | 68 | #endif 69 | -------------------------------------------------------------------------------- /include/wayland-eglswap.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2016, NVIDIA CORPORATION. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | #ifndef WAYLAND_EGLSWAP_H 24 | #define WAYLAND_EGLSWAP_H 25 | 26 | #include 27 | #include 28 | #include "wayland-eglhandle.h" 29 | #include "wayland-eglsurface.h" 30 | 31 | #ifdef __cplusplus 32 | extern "C" { 33 | #endif 34 | 35 | EGLBoolean wlEglSwapBuffersHook(EGLDisplay dpy, EGLSurface eglSurface); 36 | EGLBoolean wlEglSwapBuffersWithDamageHook(EGLDisplay eglDisplay, 37 | EGLSurface eglSurface, 38 | EGLint *rects, 39 | EGLint n_rects); 40 | EGLBoolean wlEglSwapIntervalHook(EGLDisplay eglDisplay, EGLint interval); 41 | 42 | EGLint wlEglStreamSwapIntervalCallback(WlEglPlatformData *data, 43 | EGLStreamKHR stream, 44 | EGLint *interval); 45 | 46 | WL_EXPORT 47 | EGLBoolean wlEglPrePresentExport(WlEglSurface *surface); 48 | 49 | WL_EXPORT 50 | EGLBoolean wlEglPostPresentExport(WlEglSurface *surface); 51 | 52 | WL_EXPORT 53 | EGLBoolean wlEglPostPresentExport2(WlEglSurface *surface, 54 | uint64_t presentId, 55 | void *presentInfo); 56 | 57 | #ifdef __cplusplus 58 | } 59 | #endif 60 | 61 | #endif 62 | -------------------------------------------------------------------------------- /include/wayland-eglutils.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2016, NVIDIA CORPORATION. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | #ifndef WAYLAND_EGLUTILS_H 24 | #define WAYLAND_EGLUTILS_H 25 | 26 | #include 27 | #include 28 | #include "wayland-external-exports.h" 29 | #include "wayland-eglhandle.h" 30 | 31 | #ifdef NDEBUG 32 | #define wlEglSetError(data, err) \ 33 | wlEglSetErrorCallback(data, err, 0, 0) 34 | #else 35 | #define wlEglSetError(data, err) \ 36 | wlEglSetErrorCallback(data, err, __FILE__, __LINE__) 37 | #endif 38 | 39 | #ifndef WL_LIST_INITIALIZER 40 | #define WL_LIST_INITIALIZER(head) { .prev = (head), .next = (head) } 41 | #endif 42 | 43 | #ifndef WL_LIST_INIT 44 | #define WL_LIST_INIT(head) \ 45 | do { (head)->prev = (head)->next = (head); } while (0); 46 | #endif 47 | 48 | #ifdef __cplusplus 49 | extern "C" { 50 | #endif 51 | 52 | EGLBoolean wlEglFindExtension(const char *extension, const char *extensions); 53 | EGLBoolean wlEglMemoryIsReadable(const void *p, size_t len); 54 | EGLBoolean wlEglCheckInterfaceType(struct wl_object *obj, const char *ifname); 55 | void wlEglSetErrorCallback(WlEglPlatformData *data, 56 | EGLint err, 57 | const char *file, 58 | int line); 59 | #ifdef __cplusplus 60 | } 61 | #endif 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /include/wayland-external-exports.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | #ifndef WAYLAND_EXTERNAL_EXPORTS_H 24 | #define WAYLAND_EXTERNAL_EXPORTS_H 25 | 26 | /* 27 | * .. 28 | * defines the EGL external Wayland 29 | * implementation version. 30 | * 31 | * The includer of this file can override either WAYLAND_EXTERNAL_VERSION_MAJOR 32 | * or WAYLAND_EXTERNAL_VERSION_MINOR in order to build against a certain EGL 33 | * external API version. 34 | * 35 | * 36 | * How to update this version numbers: 37 | * 38 | * - WAYLAND_EXTERNAL_VERSION_MAJOR must match the EGL external API major 39 | * number this platform implements 40 | * 41 | * - WAYLAND_EXTERNAL_VERSION_MINOR must match the EGL external API minor 42 | * number this platform implements 43 | * 44 | * - If the platform implementation is changed in any way, increase 45 | * WAYLAND_EXTERNAL_VERSION_MICRO by 1 46 | */ 47 | #if !defined(WAYLAND_EXTERNAL_VERSION_MAJOR) 48 | #define WAYLAND_EXTERNAL_VERSION_MAJOR 1 49 | #if !defined(WAYLAND_EXTERNAL_VERSION_MINOR) 50 | #define WAYLAND_EXTERNAL_VERSION_MINOR 1 51 | #endif 52 | #elif !defined(WAYLAND_EXTERNAL_VERSION_MINOR) 53 | #define WAYLAND_EXTERNAL_VERSION_MINOR 0 54 | #endif 55 | 56 | #define WAYLAND_EXTERNAL_VERSION_MICRO 20 57 | 58 | 59 | #define EGL_EXTERNAL_PLATFORM_VERSION_MAJOR WAYLAND_EXTERNAL_VERSION_MAJOR 60 | #define EGL_EXTERNAL_PLATFORM_VERSION_MINOR WAYLAND_EXTERNAL_VERSION_MINOR 61 | #include 62 | 63 | #include 64 | 65 | WL_EXPORT 66 | EGLBoolean loadEGLExternalPlatform(int major, int minor, 67 | const EGLExtDriver *driver, 68 | EGLExtPlatform *platform); 69 | 70 | #endif 71 | -------------------------------------------------------------------------------- /include/wayland-thread.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016-2019, NVIDIA CORPORATION. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | #ifndef WAYLAND_THREAD_H 24 | #define WAYLAND_THREAD_H 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | /* 31 | * wlExternalApiLock() 32 | * 33 | * Tries to acquire the external API lock. If the lock is already acquired by 34 | * another thread, it will block until the lock is released. 35 | * 36 | * Calling this function twice without calling wlExternalApiUnlock() in between 37 | * will fail. 38 | * 39 | * First call to wlExternalApiLock() will initialize the external API lock 40 | * resources. 41 | * 42 | * Returns 0 upon success; otherwise returns -1. 43 | */ 44 | int wlExternalApiLock(void); 45 | 46 | /* 47 | * wlExternalApiUnlock() 48 | * 49 | * Releases the external API lock. 50 | * 51 | * Calling this function without a previous call to wlExternalApiLock() will 52 | * fail. 53 | * 54 | * Returns 0 upon success; otherwise returns -1. 55 | */ 56 | int wlExternalApiUnlock(void); 57 | 58 | /* 59 | * wlExternalApiDestroyLock() 60 | * 61 | * Releases and frees the the external API lock resources. This call should only 62 | * be called as part of the global teardown. 63 | */ 64 | void wlExternalApiDestroyLock(void); 65 | 66 | /* 67 | * wlEglInitializeMutex(pthread_mutex_t *mutex) 68 | * 69 | * Initialises the pthread mutex referenced by mutex. 70 | */ 71 | bool wlEglInitializeMutex(pthread_mutex_t *mutex); 72 | 73 | /* 74 | * wlEglMutexDestroy(pthread_mutex_t *mutex) 75 | * 76 | * Destroys the pthread mutex referenced by mutex. 77 | */ 78 | void wlEglMutexDestroy(pthread_mutex_t *mutex); 79 | 80 | #endif 81 | -------------------------------------------------------------------------------- /m4/ax_check_compile_flag.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # https://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT]) 8 | # 9 | # DESCRIPTION 10 | # 11 | # Check whether the given FLAG works with the current language's compiler 12 | # or gives an error. (Warnings, however, are ignored) 13 | # 14 | # ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on 15 | # success/failure. 16 | # 17 | # If EXTRA-FLAGS is defined, it is added to the current language's default 18 | # flags (e.g. CFLAGS) when the check is done. The check is thus made with 19 | # the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to 20 | # force the compiler to issue an error when a bad flag is given. 21 | # 22 | # INPUT gives an alternative input source to AC_COMPILE_IFELSE. 23 | # 24 | # NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this 25 | # macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG. 26 | # 27 | # LICENSE 28 | # 29 | # Copyright (c) 2008 Guido U. Draheim 30 | # Copyright (c) 2011 Maarten Bosmans 31 | # 32 | # Copying and distribution of this file, with or without modification, are 33 | # permitted in any medium without royalty provided the copyright notice 34 | # and this notice are preserved. This file is offered as-is, without any 35 | # warranty. 36 | 37 | #serial 6 38 | 39 | AC_DEFUN([AX_CHECK_COMPILE_FLAG], 40 | [AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF 41 | AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl 42 | AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [ 43 | ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS 44 | _AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1" 45 | AC_COMPILE_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])], 46 | [AS_VAR_SET(CACHEVAR,[yes])], 47 | [AS_VAR_SET(CACHEVAR,[no])]) 48 | _AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags]) 49 | AS_VAR_IF(CACHEVAR,yes, 50 | [m4_default([$2], :)], 51 | [m4_default([$3], :)]) 52 | AS_VAR_POPDEF([CACHEVAR])dnl 53 | ])dnl AX_CHECK_COMPILE_FLAGS 54 | -------------------------------------------------------------------------------- /m4/ax_check_enable_debug.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # http://www.gnu.org/software/autoconf-archive/ax_check_enable_debug.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_CHECK_ENABLE_DEBUG([enable by default=yes/info/profile/no], [ENABLE DEBUG VARIABLES ...], [DISABLE DEBUG VARIABLES NDEBUG ...], [IS-RELEASE]) 8 | # 9 | # DESCRIPTION 10 | # 11 | # Check for the presence of an --enable-debug option to configure, with 12 | # the specified default value used when the option is not present. Return 13 | # the value in the variable $ax_enable_debug. 14 | # 15 | # Specifying 'yes' adds '-g -O0' to the compilation flags for all 16 | # languages. Specifying 'info' adds '-g' to the compilation flags. 17 | # Specifying 'profile' adds '-g -pg' to the compilation flags and '-pg' to 18 | # the linking flags. Otherwise, nothing is added. 19 | # 20 | # Define the variables listed in the second argument if debug is enabled, 21 | # defaulting to no variables. Defines the variables listed in the third 22 | # argument if debug is disabled, defaulting to NDEBUG. All lists of 23 | # variables should be space-separated. 24 | # 25 | # If debug is not enabled, ensure AC_PROG_* will not add debugging flags. 26 | # Should be invoked prior to any AC_PROG_* compiler checks. 27 | # 28 | # IS-RELEASE can be used to change the default to 'no' when making a 29 | # release. Set IS-RELEASE to 'yes' or 'no' as appropriate. By default, it 30 | # uses the value of $ax_is_release, so if you are using the AX_IS_RELEASE 31 | # macro, there is no need to pass this parameter. 32 | # 33 | # AX_IS_RELEASE([git-directory]) 34 | # AX_CHECK_ENABLE_DEBUG() 35 | # 36 | # LICENSE 37 | # 38 | # Copyright (c) 2011 Rhys Ulerich 39 | # Copyright (c) 2014, 2015 Philip Withnall 40 | # 41 | # Copying and distribution of this file, with or without modification, are 42 | # permitted in any medium without royalty provided the copyright notice 43 | # and this notice are preserved. 44 | 45 | #serial 5 46 | 47 | AC_DEFUN([AX_CHECK_ENABLE_DEBUG],[ 48 | AC_BEFORE([$0],[AC_PROG_CC])dnl 49 | AC_BEFORE([$0],[AC_PROG_CXX])dnl 50 | AC_BEFORE([$0],[AC_PROG_F77])dnl 51 | AC_BEFORE([$0],[AC_PROG_FC])dnl 52 | 53 | AC_MSG_CHECKING(whether to enable debugging) 54 | 55 | ax_enable_debug_default=m4_tolower(m4_normalize(ifelse([$1],,[no],[$1]))) 56 | ax_enable_debug_is_release=m4_tolower(m4_normalize(ifelse([$4],, 57 | [$ax_is_release], 58 | [$4]))) 59 | 60 | # If this is a release, override the default. 61 | AS_IF([test "$ax_enable_debug_is_release" = "yes"], 62 | [ax_enable_debug_default="no"]) 63 | 64 | m4_define(ax_enable_debug_vars,[m4_normalize(ifelse([$2],,,[$2]))]) 65 | m4_define(ax_disable_debug_vars,[m4_normalize(ifelse([$3],,[NDEBUG],[$3]))]) 66 | 67 | AC_ARG_ENABLE(debug, 68 | [AS_HELP_STRING([--enable-debug=]@<:@yes/info/profile/no@:>@,[compile with debugging])], 69 | [],enable_debug=$ax_enable_debug_default) 70 | 71 | # empty mean debug yes 72 | AS_IF([test "x$enable_debug" = "x"], 73 | [enable_debug="yes"]) 74 | 75 | # case of debug 76 | AS_CASE([$enable_debug], 77 | [yes],[ 78 | AC_MSG_RESULT(yes) 79 | CFLAGS="${CFLAGS} -g -O0" 80 | CXXFLAGS="${CXXFLAGS} -g -O0" 81 | FFLAGS="${FFLAGS} -g -O0" 82 | FCFLAGS="${FCFLAGS} -g -O0" 83 | OBJCFLAGS="${OBJCFLAGS} -g -O0" 84 | ], 85 | [info],[ 86 | AC_MSG_RESULT(info) 87 | CFLAGS="${CFLAGS} -g" 88 | CXXFLAGS="${CXXFLAGS} -g" 89 | FFLAGS="${FFLAGS} -g" 90 | FCFLAGS="${FCFLAGS} -g" 91 | OBJCFLAGS="${OBJCFLAGS} -g" 92 | ], 93 | [profile],[ 94 | AC_MSG_RESULT(profile) 95 | CFLAGS="${CFLAGS} -g -pg" 96 | CXXFLAGS="${CXXFLAGS} -g -pg" 97 | FFLAGS="${FFLAGS} -g -pg" 98 | FCFLAGS="${FCFLAGS} -g -pg" 99 | OBJCFLAGS="${OBJCFLAGS} -g -pg" 100 | LDFLAGS="${LDFLAGS} -pg" 101 | ], 102 | [ 103 | AC_MSG_RESULT(no) 104 | dnl Ensure AC_PROG_CC/CXX/F77/FC/OBJC will not enable debug flags 105 | dnl by setting any unset environment flag variables 106 | AS_IF([test "x${CFLAGS+set}" != "xset"], 107 | [CFLAGS=""]) 108 | AS_IF([test "x${CXXFLAGS+set}" != "xset"], 109 | [CXXFLAGS=""]) 110 | AS_IF([test "x${FFLAGS+set}" != "xset"], 111 | [FFLAGS=""]) 112 | AS_IF([test "x${FCFLAGS+set}" != "xset"], 113 | [FCFLAGS=""]) 114 | AS_IF([test "x${OBJCFLAGS+set}" != "xset"], 115 | [OBJCFLAGS=""]) 116 | ]) 117 | 118 | dnl Define various variables if debugging is disabled. 119 | dnl assert.h is a NOP if NDEBUG is defined, so define it by default. 120 | AS_IF([test "x$enable_debug" = "xyes"], 121 | [m4_map_args_w(ax_enable_debug_vars, [AC_DEFINE(], [,,[Define if debugging is enabled])])], 122 | [m4_map_args_w(ax_disable_debug_vars, [AC_DEFINE(], [,,[Define if debugging is disabled])])]) 123 | ax_enable_debug=$enable_debug 124 | ]) 125 | -------------------------------------------------------------------------------- /m4/ax_check_link_flag.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # http://www.gnu.org/software/autoconf-archive/ax_check_link_flag.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_CHECK_LINK_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS]) 8 | # 9 | # DESCRIPTION 10 | # 11 | # Check whether the given FLAG works with the linker or gives an error. 12 | # (Warnings, however, are ignored) 13 | # 14 | # ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on 15 | # success/failure. 16 | # 17 | # If EXTRA-FLAGS is defined, it is added to the linker's default flags 18 | # when the check is done. The check is thus made with the flags: "LDFLAGS 19 | # EXTRA-FLAGS FLAG". This can for example be used to force the linker to 20 | # issue an error when a bad flag is given. 21 | # 22 | # NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this 23 | # macro in sync with AX_CHECK_{PREPROC,COMPILE}_FLAG. 24 | # 25 | # LICENSE 26 | # 27 | # Copyright (c) 2008 Guido U. Draheim 28 | # Copyright (c) 2011 Maarten Bosmans 29 | # 30 | # This program is free software: you can redistribute it and/or modify it 31 | # under the terms of the GNU General Public License as published by the 32 | # Free Software Foundation, either version 3 of the License, or (at your 33 | # option) any later version. 34 | # 35 | # This program is distributed in the hope that it will be useful, but 36 | # WITHOUT ANY WARRANTY; without even the implied warranty of 37 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 38 | # Public License for more details. 39 | # 40 | # You should have received a copy of the GNU General Public License along 41 | # with this program. If not, see . 42 | # 43 | # As a special exception, the respective Autoconf Macro's copyright owner 44 | # gives unlimited permission to copy, distribute and modify the configure 45 | # scripts that are the output of Autoconf when processing the Macro. You 46 | # need not follow the terms of the GNU General Public License when using 47 | # or distributing such scripts, even though portions of the text of the 48 | # Macro appear in them. The GNU General Public License (GPL) does govern 49 | # all other use of the material that constitutes the Autoconf Macro. 50 | # 51 | # This special exception to the GPL applies to versions of the Autoconf 52 | # Macro released by the Autoconf Archive. When you make and distribute a 53 | # modified version of the Autoconf Macro, you may extend this special 54 | # exception to the GPL to apply to your modified version as well. 55 | 56 | #serial 2 57 | 58 | AC_DEFUN([AX_CHECK_LINK_FLAG], 59 | [AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_ldflags_$4_$1])dnl 60 | AC_CACHE_CHECK([whether the linker accepts $1], CACHEVAR, [ 61 | ax_check_save_flags=$LDFLAGS 62 | LDFLAGS="$LDFLAGS $4 $1" 63 | AC_LINK_IFELSE([AC_LANG_PROGRAM()], 64 | [AS_VAR_SET(CACHEVAR,[yes])], 65 | [AS_VAR_SET(CACHEVAR,[no])]) 66 | LDFLAGS=$ax_check_save_flags]) 67 | AS_IF([test x"AS_VAR_GET(CACHEVAR)" = xyes], 68 | [m4_default([$2], :)], 69 | [m4_default([$3], :)]) 70 | AS_VAR_POPDEF([CACHEVAR])dnl 71 | ])dnl AX_CHECK_LINK_FLAGS 72 | -------------------------------------------------------------------------------- /m4/ax_pthread.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # http://www.gnu.org/software/autoconf-archive/ax_pthread.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) 8 | # 9 | # DESCRIPTION 10 | # 11 | # This macro figures out how to build C programs using POSIX threads. It 12 | # sets the PTHREAD_LIBS output variable to the threads library and linker 13 | # flags, and the PTHREAD_CFLAGS output variable to any special C compiler 14 | # flags that are needed. (The user can also force certain compiler 15 | # flags/libs to be tested by setting these environment variables.) 16 | # 17 | # Also sets PTHREAD_CC to any special C compiler that is needed for 18 | # multi-threaded programs (defaults to the value of CC otherwise). (This 19 | # is necessary on AIX to use the special cc_r compiler alias.) 20 | # 21 | # NOTE: You are assumed to not only compile your program with these flags, 22 | # but also link it with them as well. e.g. you should link with 23 | # $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS 24 | # 25 | # If you are only building threads programs, you may wish to use these 26 | # variables in your default LIBS, CFLAGS, and CC: 27 | # 28 | # LIBS="$PTHREAD_LIBS $LIBS" 29 | # CFLAGS="$CFLAGS $PTHREAD_CFLAGS" 30 | # CC="$PTHREAD_CC" 31 | # 32 | # In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant 33 | # has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to that name 34 | # (e.g. PTHREAD_CREATE_UNDETACHED on AIX). 35 | # 36 | # Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the 37 | # PTHREAD_PRIO_INHERIT symbol is defined when compiling with 38 | # PTHREAD_CFLAGS. 39 | # 40 | # ACTION-IF-FOUND is a list of shell commands to run if a threads library 41 | # is found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it 42 | # is not found. If ACTION-IF-FOUND is not specified, the default action 43 | # will define HAVE_PTHREAD. 44 | # 45 | # Please let the authors know if this macro fails on any platform, or if 46 | # you have any other suggestions or comments. This macro was based on work 47 | # by SGJ on autoconf scripts for FFTW (http://www.fftw.org/) (with help 48 | # from M. Frigo), as well as ac_pthread and hb_pthread macros posted by 49 | # Alejandro Forero Cuervo to the autoconf macro repository. We are also 50 | # grateful for the helpful feedback of numerous users. 51 | # 52 | # Updated for Autoconf 2.68 by Daniel Richard G. 53 | # 54 | # LICENSE 55 | # 56 | # Copyright (c) 2008 Steven G. Johnson 57 | # Copyright (c) 2011 Daniel Richard G. 58 | # 59 | # This program is free software: you can redistribute it and/or modify it 60 | # under the terms of the GNU General Public License as published by the 61 | # Free Software Foundation, either version 3 of the License, or (at your 62 | # option) any later version. 63 | # 64 | # This program is distributed in the hope that it will be useful, but 65 | # WITHOUT ANY WARRANTY; without even the implied warranty of 66 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 67 | # Public License for more details. 68 | # 69 | # You should have received a copy of the GNU General Public License along 70 | # with this program. If not, see . 71 | # 72 | # As a special exception, the respective Autoconf Macro's copyright owner 73 | # gives unlimited permission to copy, distribute and modify the configure 74 | # scripts that are the output of Autoconf when processing the Macro. You 75 | # need not follow the terms of the GNU General Public License when using 76 | # or distributing such scripts, even though portions of the text of the 77 | # Macro appear in them. The GNU General Public License (GPL) does govern 78 | # all other use of the material that constitutes the Autoconf Macro. 79 | # 80 | # This special exception to the GPL applies to versions of the Autoconf 81 | # Macro released by the Autoconf Archive. When you make and distribute a 82 | # modified version of the Autoconf Macro, you may extend this special 83 | # exception to the GPL to apply to your modified version as well. 84 | 85 | #serial 20 86 | 87 | AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD]) 88 | AC_DEFUN([AX_PTHREAD], [ 89 | AC_REQUIRE([AC_CANONICAL_HOST]) 90 | AC_LANG_PUSH([C]) 91 | ax_pthread_ok=no 92 | 93 | # We used to check for pthread.h first, but this fails if pthread.h 94 | # requires special compiler flags (e.g. on True64 or Sequent). 95 | # It gets checked for in the link test anyway. 96 | 97 | # First of all, check if the user has set any of the PTHREAD_LIBS, 98 | # etcetera environment variables, and if threads linking works using 99 | # them: 100 | if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then 101 | save_CFLAGS="$CFLAGS" 102 | CFLAGS="$CFLAGS $PTHREAD_CFLAGS" 103 | save_LIBS="$LIBS" 104 | LIBS="$PTHREAD_LIBS $LIBS" 105 | AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS]) 106 | AC_TRY_LINK_FUNC(pthread_join, ax_pthread_ok=yes) 107 | AC_MSG_RESULT($ax_pthread_ok) 108 | if test x"$ax_pthread_ok" = xno; then 109 | PTHREAD_LIBS="" 110 | PTHREAD_CFLAGS="" 111 | fi 112 | LIBS="$save_LIBS" 113 | CFLAGS="$save_CFLAGS" 114 | fi 115 | 116 | # We must check for the threads library under a number of different 117 | # names; the ordering is very important because some systems 118 | # (e.g. DEC) have both -lpthread and -lpthreads, where one of the 119 | # libraries is broken (non-POSIX). 120 | 121 | # Create a list of thread flags to try. Items starting with a "-" are 122 | # C compiler flags, and other items are library names, except for "none" 123 | # which indicates that we try without any flags at all, and "pthread-config" 124 | # which is a program returning the flags for the Pth emulation library. 125 | 126 | ax_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" 127 | 128 | # The ordering *is* (sometimes) important. Some notes on the 129 | # individual items follow: 130 | 131 | # pthreads: AIX (must check this before -lpthread) 132 | # none: in case threads are in libc; should be tried before -Kthread and 133 | # other compiler flags to prevent continual compiler warnings 134 | # -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) 135 | # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) 136 | # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) 137 | # -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads) 138 | # -pthreads: Solaris/gcc 139 | # -mthreads: Mingw32/gcc, Lynx/gcc 140 | # -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it 141 | # doesn't hurt to check since this sometimes defines pthreads too; 142 | # also defines -D_REENTRANT) 143 | # ... -mt is also the pthreads flag for HP/aCC 144 | # pthread: Linux, etcetera 145 | # --thread-safe: KAI C++ 146 | # pthread-config: use pthread-config program (for GNU Pth library) 147 | 148 | case ${host_os} in 149 | solaris*) 150 | 151 | # On Solaris (at least, for some versions), libc contains stubbed 152 | # (non-functional) versions of the pthreads routines, so link-based 153 | # tests will erroneously succeed. (We need to link with -pthreads/-mt/ 154 | # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather 155 | # a function called by this macro, so we could check for that, but 156 | # who knows whether they'll stub that too in a future libc.) So, 157 | # we'll just look for -pthreads and -lpthread first: 158 | 159 | ax_pthread_flags="-pthreads pthread -mt -pthread $ax_pthread_flags" 160 | ;; 161 | 162 | darwin*) 163 | ax_pthread_flags="-pthread $ax_pthread_flags" 164 | ;; 165 | esac 166 | 167 | if test x"$ax_pthread_ok" = xno; then 168 | for flag in $ax_pthread_flags; do 169 | 170 | case $flag in 171 | none) 172 | AC_MSG_CHECKING([whether pthreads work without any flags]) 173 | ;; 174 | 175 | -*) 176 | AC_MSG_CHECKING([whether pthreads work with $flag]) 177 | PTHREAD_CFLAGS="$flag" 178 | ;; 179 | 180 | pthread-config) 181 | AC_CHECK_PROG(ax_pthread_config, pthread-config, yes, no) 182 | if test x"$ax_pthread_config" = xno; then continue; fi 183 | PTHREAD_CFLAGS="`pthread-config --cflags`" 184 | PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" 185 | ;; 186 | 187 | *) 188 | AC_MSG_CHECKING([for the pthreads library -l$flag]) 189 | PTHREAD_LIBS="-l$flag" 190 | ;; 191 | esac 192 | 193 | save_LIBS="$LIBS" 194 | save_CFLAGS="$CFLAGS" 195 | LIBS="$PTHREAD_LIBS $LIBS" 196 | CFLAGS="$CFLAGS $PTHREAD_CFLAGS" 197 | 198 | # Check for various functions. We must include pthread.h, 199 | # since some functions may be macros. (On the Sequent, we 200 | # need a special flag -Kthread to make this header compile.) 201 | # We check for pthread_join because it is in -lpthread on IRIX 202 | # while pthread_create is in libc. We check for pthread_attr_init 203 | # due to DEC craziness with -lpthreads. We check for 204 | # pthread_cleanup_push because it is one of the few pthread 205 | # functions on Solaris that doesn't have a non-functional libc stub. 206 | # We try pthread_create on general principles. 207 | AC_LINK_IFELSE([AC_LANG_PROGRAM([#include 208 | static void routine(void *a) { a = 0; } 209 | static void *start_routine(void *a) { return a; }], 210 | [pthread_t th; pthread_attr_t attr; 211 | pthread_create(&th, 0, start_routine, 0); 212 | pthread_join(th, 0); 213 | pthread_attr_init(&attr); 214 | pthread_cleanup_push(routine, 0); 215 | pthread_cleanup_pop(0) /* ; */])], 216 | [ax_pthread_ok=yes], 217 | []) 218 | 219 | LIBS="$save_LIBS" 220 | CFLAGS="$save_CFLAGS" 221 | 222 | AC_MSG_RESULT($ax_pthread_ok) 223 | if test "x$ax_pthread_ok" = xyes; then 224 | break; 225 | fi 226 | 227 | PTHREAD_LIBS="" 228 | PTHREAD_CFLAGS="" 229 | done 230 | fi 231 | 232 | # Various other checks: 233 | if test "x$ax_pthread_ok" = xyes; then 234 | save_LIBS="$LIBS" 235 | LIBS="$PTHREAD_LIBS $LIBS" 236 | save_CFLAGS="$CFLAGS" 237 | CFLAGS="$CFLAGS $PTHREAD_CFLAGS" 238 | 239 | # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. 240 | AC_MSG_CHECKING([for joinable pthread attribute]) 241 | attr_name=unknown 242 | for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do 243 | AC_LINK_IFELSE([AC_LANG_PROGRAM([#include ], 244 | [int attr = $attr; return attr /* ; */])], 245 | [attr_name=$attr; break], 246 | []) 247 | done 248 | AC_MSG_RESULT($attr_name) 249 | if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then 250 | AC_DEFINE_UNQUOTED(PTHREAD_CREATE_JOINABLE, $attr_name, 251 | [Define to necessary symbol if this constant 252 | uses a non-standard name on your system.]) 253 | fi 254 | 255 | AC_MSG_CHECKING([if more special flags are required for pthreads]) 256 | flag=no 257 | case ${host_os} in 258 | aix* | freebsd* | darwin*) flag="-D_THREAD_SAFE";; 259 | osf* | hpux*) flag="-D_REENTRANT";; 260 | solaris*) 261 | if test "$GCC" = "yes"; then 262 | flag="-D_REENTRANT" 263 | else 264 | flag="-mt -D_REENTRANT" 265 | fi 266 | ;; 267 | esac 268 | AC_MSG_RESULT(${flag}) 269 | if test "x$flag" != xno; then 270 | PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS" 271 | fi 272 | 273 | AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT], 274 | ax_cv_PTHREAD_PRIO_INHERIT, [ 275 | AC_LINK_IFELSE([ 276 | AC_LANG_PROGRAM([[#include ]], [[int i = PTHREAD_PRIO_INHERIT;]])], 277 | [ax_cv_PTHREAD_PRIO_INHERIT=yes], 278 | [ax_cv_PTHREAD_PRIO_INHERIT=no]) 279 | ]) 280 | AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes"], 281 | AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], 1, [Have PTHREAD_PRIO_INHERIT.])) 282 | 283 | LIBS="$save_LIBS" 284 | CFLAGS="$save_CFLAGS" 285 | 286 | # More AIX lossage: compile with *_r variant 287 | if test "x$GCC" != xyes; then 288 | case $host_os in 289 | aix*) 290 | AS_CASE(["x/$CC"], 291 | [x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6], 292 | [#handle absolute path differently from PATH based program lookup 293 | AS_CASE(["x$CC"], 294 | [x/*], 295 | [AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])], 296 | [AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])])]) 297 | ;; 298 | esac 299 | fi 300 | fi 301 | 302 | test -n "$PTHREAD_CC" || PTHREAD_CC="$CC" 303 | 304 | AC_SUBST(PTHREAD_LIBS) 305 | AC_SUBST(PTHREAD_CFLAGS) 306 | AC_SUBST(PTHREAD_CC) 307 | 308 | # Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: 309 | if test x"$ax_pthread_ok" = xyes; then 310 | ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1]) 311 | : 312 | else 313 | ax_pthread_ok=no 314 | $2 315 | fi 316 | AC_LANG_POP 317 | ])dnl AX_PTHREAD 318 | -------------------------------------------------------------------------------- /meson.build: -------------------------------------------------------------------------------- 1 | project('wayland-eglstream', 'c', 2 | version : '1.1.20', 3 | default_options : [ 4 | 'buildtype=debugoptimized', 5 | 'c_std=gnu99', 6 | 'warning_level=1', 7 | ], 8 | license : 'MIT', 9 | meson_version : '>= 0.50' 10 | ) 11 | 12 | cc = meson.get_compiler('c') 13 | 14 | wayland_eglstream_version = meson.project_version() 15 | ver_arr = wayland_eglstream_version.split('.') 16 | 17 | wayland_eglstream_major_version = ver_arr[0] 18 | wayland_eglstream_minor_version = ver_arr[1] 19 | wayland_eglstream_micro_version = ver_arr[2] 20 | 21 | egl = dependency('egl', version : ['>=1.5', '<2']) 22 | egl_headers = egl.partial_dependency(includes : true, compile_args : true) 23 | eglexternalplatform = dependency('eglexternalplatform', version : ['>=1.1', '<2']) 24 | wayland_server = dependency('wayland-server') 25 | wayland_client = dependency('wayland-client') 26 | wayland_egl_backend = dependency('wayland-egl-backend', version : ['>=3']) 27 | threads = dependency('threads') 28 | 29 | wl_scanner = dependency('wayland-scanner', native: true) 30 | prog_scanner = find_program(wl_scanner.get_pkgconfig_variable('wayland_scanner')) 31 | 32 | inc = include_directories( 33 | 'include', 34 | 'wayland-egl', 35 | ) 36 | 37 | pkgconf = configuration_data() 38 | pkgconf.set('prefix', get_option('prefix')) 39 | pkgconf.set('exec_prefix', '${prefix}') 40 | pkgconf.set('libdir', '${exec_prefix}/@0@'.format(get_option('libdir'))) 41 | pkgconf.set('includedir', '${prefix}/@0@'.format(get_option('includedir'))) 42 | pkgconf.set('datadir', '${datarootdir}') 43 | pkgconf.set('datarootdir', '${prefix}/@0@'.format(get_option('datadir'))) 44 | 45 | pkgconf.set('PACKAGE', meson.project_name()) 46 | pkgconf.set('WAYLAND_EXTERNAL_VERSION', meson.project_version()) 47 | pkgconf.set('EGL_EXTERNAL_PLATFORM_MIN_VERSION', '@0@.@1@'.format(wayland_eglstream_major_version, wayland_eglstream_minor_version)) 48 | pkgconf.set('EGL_EXTERNAL_PLATFORM_MAX_VERSION', wayland_eglstream_major_version.to_int() + 1) 49 | 50 | configure_file( 51 | input : 'wayland-eglstream.pc.in', 52 | output : '@BASENAME@', 53 | configuration : pkgconf, 54 | install : true, 55 | install_dir : join_paths(get_option('libdir'), 'pkgconfig') 56 | ) 57 | configure_file( 58 | input : 'wayland-eglstream-protocols.pc.in', 59 | output : '@BASENAME@', 60 | configuration : pkgconf, 61 | install : true, 62 | install_dir : join_paths(get_option('datadir'), 'pkgconfig') 63 | ) 64 | 65 | subdir('wayland-eglstream') 66 | subdir('wayland-drm') 67 | subdir('src') 68 | -------------------------------------------------------------------------------- /src/10_nvidia_wayland.json: -------------------------------------------------------------------------------- 1 | { 2 | "file_format_version" : "1.0.0", 3 | "ICD" : { 4 | "library_path" : "libnvidia-egl-wayland.so.1" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/meson.build: -------------------------------------------------------------------------------- 1 | if not cc.has_function('dlsym') 2 | libdl = cc.find_library('dl') 3 | else 4 | libdl = [] 5 | endif 6 | 7 | add_project_arguments('-Wall', language : 'c') 8 | add_project_arguments('-Werror', language : 'c') 9 | add_project_arguments('-fvisibility=hidden', language : 'c') 10 | add_project_arguments('-DWL_HIDE_DEPRECATED', language : 'c') 11 | add_project_arguments('-D_GNU_SOURCE', language : 'c') 12 | add_project_link_arguments('-Wl,-Bsymbolic', language : 'c') 13 | 14 | if cc.has_argument('-Wpedantic') 15 | add_project_arguments('-Wno-pedantic', language : 'c') 16 | endif 17 | 18 | wl_protos = dependency('wayland-protocols', version: '>= 1.8') 19 | libdrm = dependency('libdrm') 20 | wl_protos_dir = wl_protos.get_pkgconfig_variable('pkgdatadir') 21 | wl_dmabuf_xml = join_paths(wl_protos_dir, 'unstable', 'linux-dmabuf', 'linux-dmabuf-unstable-v1.xml') 22 | wp_presentation_time_xml = join_paths(wl_protos_dir, 'stable', 'presentation-time', 'presentation-time.xml') 23 | wl_drm_syncobj_xml = join_paths(wl_protos_dir, 'staging', 'linux-drm-syncobj', 'linux-drm-syncobj-v1.xml') 24 | 25 | client_header = generator(prog_scanner, 26 | output : '@BASENAME@-client-protocol.h', 27 | arguments : ['client-header', '@INPUT@', '@OUTPUT@'] 28 | ) 29 | 30 | if wl_scanner.version().version_compare('>= 1.14.91') 31 | code_arg = 'private-code' 32 | else 33 | code_arg = 'code' 34 | endif 35 | 36 | code = generator(prog_scanner, 37 | output : '@BASENAME@-protocol.c', 38 | arguments : [code_arg, '@INPUT@', '@OUTPUT@'] 39 | ) 40 | 41 | src = [ 42 | 'wayland-thread.c', 43 | 'wayland-egldevice.c', 44 | 'wayland-egldisplay.c', 45 | 'wayland-eglstream.c', 46 | 'wayland-eglstream-server.c', 47 | 'wayland-eglsurface.c', 48 | 'wayland-eglswap.c', 49 | 'wayland-eglutils.c', 50 | 'wayland-eglhandle.c', 51 | 'wayland-external-exports.c', 52 | 'wayland-drm.c', 53 | 54 | wayland_eglstream_protocol_c, 55 | wayland_eglstream_client_protocol_h, 56 | wayland_eglstream_server_protocol_h, 57 | wayland_eglstream_controller_protocol_c, 58 | wayland_eglstream_controller_client_protocol_h, 59 | wayland_drm_protocol_c, 60 | wayland_drm_client_protocol_h, 61 | wayland_drm_server_protocol_h, 62 | ] 63 | 64 | src += client_header.process(wl_dmabuf_xml) 65 | src += code.process(wl_dmabuf_xml) 66 | 67 | src += client_header.process(wp_presentation_time_xml) 68 | src += code.process(wp_presentation_time_xml) 69 | 70 | src += client_header.process(wl_drm_syncobj_xml) 71 | src += code.process(wl_drm_syncobj_xml) 72 | 73 | egl_wayland = library('nvidia-egl-wayland', 74 | src, 75 | dependencies : [ 76 | egl_headers, 77 | eglexternalplatform, 78 | wayland_server, 79 | wayland_client, 80 | wayland_egl_backend, 81 | threads, 82 | libdrm, 83 | libdl, 84 | ], 85 | include_directories : inc, 86 | version : meson.project_version(), 87 | install : true, 88 | ) 89 | 90 | install_data('10_nvidia_wayland.json', 91 | install_dir: '@0@/egl/egl_external_platform.d'.format(get_option('datadir'))) 92 | -------------------------------------------------------------------------------- /src/wayland-drm.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | #include 24 | #include 25 | 26 | #include 27 | #include "wayland-eglstream-server.h" 28 | #include "wayland-drm.h" 29 | #include "wayland-eglutils.h" 30 | #include "wayland-drm-server-protocol.h" 31 | 32 | static void 33 | authenticate(struct wl_client *client, 34 | struct wl_resource *resource, uint32_t id) 35 | { 36 | (void)client; 37 | (void)id; 38 | 39 | /* 40 | * This implementation will only ever report render node files, and 41 | * authentication is not supported nor required for render node devices. 42 | */ 43 | wl_resource_post_error(resource, 44 | WL_DRM_ERROR_AUTHENTICATE_FAIL, 45 | "authenticate failed"); 46 | } 47 | 48 | static void 49 | create_buffer(struct wl_client *client, struct wl_resource *resource, 50 | uint32_t id, uint32_t name, int32_t width, int32_t height, 51 | uint32_t stride, uint32_t format) 52 | { 53 | (void)client; 54 | (void)id; 55 | (void)name; 56 | (void)width; 57 | (void)height; 58 | (void)stride; 59 | (void)format; 60 | 61 | wl_resource_post_error(resource, 62 | WL_DRM_ERROR_INVALID_FORMAT, 63 | "invalid format"); 64 | } 65 | 66 | static void 67 | create_planar_buffer(struct wl_client *client, struct wl_resource *resource, 68 | uint32_t id, uint32_t name, int32_t width, int32_t height, 69 | uint32_t format, 70 | int32_t offset0, int32_t stride0, 71 | int32_t offset1, int32_t stride1, 72 | int32_t offset2, int32_t stride2) 73 | { 74 | (void)client; 75 | (void)id; 76 | (void)name; 77 | (void)width; 78 | (void)height; 79 | (void)format; 80 | (void)offset0; 81 | (void)stride0; 82 | (void)offset1; 83 | (void)stride1; 84 | (void)offset2; 85 | (void)stride2; 86 | 87 | wl_resource_post_error(resource, 88 | WL_DRM_ERROR_INVALID_FORMAT, 89 | "invalid format"); 90 | } 91 | 92 | static void 93 | create_prime_buffer(struct wl_client *client, struct wl_resource *resource, 94 | uint32_t id, int fd, int32_t width, int32_t height, 95 | uint32_t format, 96 | int32_t offset0, int32_t stride0, 97 | int32_t offset1, int32_t stride1, 98 | int32_t offset2, int32_t stride2) 99 | { 100 | (void)client; 101 | (void)id; 102 | (void)fd; 103 | (void)width; 104 | (void)height; 105 | (void)format; 106 | (void)offset0; 107 | (void)stride0; 108 | (void)offset1; 109 | (void)stride1; 110 | (void)offset2; 111 | (void)stride2; 112 | 113 | wl_resource_post_error(resource, 114 | WL_DRM_ERROR_INVALID_FORMAT, 115 | "invalid format"); 116 | close(fd); 117 | } 118 | 119 | static const struct wl_drm_interface interface = { 120 | authenticate, 121 | create_buffer, 122 | create_planar_buffer, 123 | create_prime_buffer, 124 | }; 125 | 126 | static void 127 | bind(struct wl_client *client, void *data, uint32_t version, uint32_t id) 128 | { 129 | struct wl_eglstream_display *wlStreamDpy = data; 130 | struct wl_resource *resource = wl_resource_create(client, &wl_drm_interface, 131 | version > 2 ? 2 : version, 132 | id); 133 | 134 | if (!resource) { 135 | wl_client_post_no_memory(client); 136 | return; 137 | } 138 | 139 | wl_resource_set_implementation(resource, &interface, data, NULL); 140 | wl_resource_post_event(resource, WL_DRM_DEVICE, wlStreamDpy->drm->device_name); 141 | 142 | /* 143 | * Don't send any format events. This implementation doesn't support 144 | * creating Wayland buffers of any format. 145 | */ 146 | 147 | /* 148 | * Don't report any capabilities beyond the baseline, as currently all 149 | * capabilities are only relevant when buffer creation is supported. 150 | */ 151 | if (version >= 2) 152 | wl_resource_post_event(resource, WL_DRM_CAPABILITIES, 0); 153 | } 154 | 155 | const char * 156 | wl_drm_get_dev_name(const WlEglPlatformData *data, 157 | EGLDisplay dpy) 158 | { 159 | EGLDeviceEXT egl_dev; 160 | const char *dev_exts; 161 | 162 | if (!data->egl.queryDisplayAttrib(dpy, EGL_DEVICE_EXT, 163 | (EGLAttribKHR*)&egl_dev)) { 164 | return NULL; 165 | } 166 | 167 | dev_exts = data->egl.queryDeviceString(egl_dev, EGL_EXTENSIONS); 168 | 169 | if (!dev_exts) { 170 | return NULL; 171 | } 172 | 173 | if (!wlEglFindExtension("EGL_EXT_device_drm_render_node", dev_exts)) { 174 | return NULL; 175 | } 176 | 177 | return data->egl.queryDeviceString(egl_dev, EGL_DRM_RENDER_NODE_FILE_EXT); 178 | } 179 | 180 | EGLBoolean 181 | wl_drm_display_bind(struct wl_display *display, 182 | struct wl_eglstream_display *wlStreamDpy, 183 | const char *dev_name) 184 | { 185 | if (!dev_name) { 186 | return EGL_FALSE; 187 | } 188 | 189 | wlStreamDpy->drm = calloc(1, sizeof *wlStreamDpy->drm); 190 | 191 | if (!wlStreamDpy->drm) { 192 | return EGL_FALSE; 193 | } 194 | 195 | wlStreamDpy->drm->device_name = dev_name; 196 | wlStreamDpy->drm->global = wl_global_create(display, &wl_drm_interface, 2, 197 | wlStreamDpy, bind); 198 | 199 | return EGL_TRUE; 200 | } 201 | 202 | void 203 | wl_drm_display_unbind(struct wl_eglstream_display *wlStreamDpy) 204 | { 205 | if (wlStreamDpy->drm) { 206 | wl_global_destroy(wlStreamDpy->drm->global); 207 | free(wlStreamDpy->drm); 208 | wlStreamDpy->drm = NULL; 209 | } 210 | } 211 | -------------------------------------------------------------------------------- /src/wayland-egldevice.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2019, NVIDIA CORPORATION. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | #include "wayland-egldevice.h" 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include "wayland-eglhandle.h" 33 | #include "wayland-eglutils.h" 34 | 35 | WlEglDeviceDpy *wlGetInternalDisplay(WlEglPlatformData *data, EGLDeviceEXT device) 36 | { 37 | static const EGLint TRACK_REFS_ATTRIBS[] = { 38 | EGL_TRACK_REFERENCES_KHR, 39 | EGL_TRUE, 40 | EGL_NONE 41 | }; 42 | 43 | WlEglDeviceDpy *devDpy = NULL; 44 | const EGLint *attribs = NULL; 45 | const char *drmName = NULL, *renderName = NULL; 46 | struct stat sb, render_sb; 47 | 48 | // First, see if we've already created an EGLDisplay for this device. 49 | wl_list_for_each(devDpy, &data->deviceDpyList, link) { 50 | if (devDpy->data == data && devDpy->eglDevice == device) { 51 | return devDpy; 52 | } 53 | } 54 | 55 | // We didn't find a matching display, so create one. 56 | if (data->supportsDisplayReference) { 57 | // Always use EGL_KHR_display_reference if the driver supports it. 58 | // We'll do our own refcounting so that we can work without it, but 59 | // setting EGL_TRACK_REFERENCES_KHR means that it's less likely that 60 | // something else might grab the same EGLDevice-based display and 61 | // call eglTerminate on it. 62 | attribs = TRACK_REFS_ATTRIBS; 63 | } 64 | 65 | devDpy = calloc(1, sizeof(WlEglDeviceDpy)); 66 | if (devDpy == NULL) { 67 | return NULL; 68 | } 69 | 70 | devDpy->eglDevice = device; 71 | devDpy->data = data; 72 | devDpy->eglDisplay = data->egl.getPlatformDisplay(EGL_PLATFORM_DEVICE_EXT, 73 | device, attribs); 74 | if (devDpy->eglDisplay == EGL_NO_DISPLAY) { 75 | goto fail; 76 | } 77 | 78 | /* Get the device in use, 79 | * calling eglQueryDeviceStringEXT(EGL_DRM_RENDER_NODE_FILE_EXT) to get drm fd. 80 | * We will be getting the dev_t for the render node and the normal node, since 81 | * we don't know for sure which one the compositor will happen to use. 82 | */ 83 | drmName = data->egl.queryDeviceString(devDpy->eglDevice, 84 | EGL_DRM_DEVICE_FILE_EXT); 85 | if (!drmName) { 86 | goto fail; 87 | } 88 | /* Then use stat to get the dev_t for this device */ 89 | if (stat(drmName, &sb) != 0) { 90 | goto fail; 91 | } 92 | 93 | renderName = data->egl.queryDeviceString(devDpy->eglDevice, 94 | EGL_DRM_RENDER_NODE_FILE_EXT); 95 | if (!renderName) { 96 | goto fail; 97 | } 98 | if (stat(renderName, &render_sb) != 0) { 99 | goto fail; 100 | } 101 | 102 | devDpy->dev = sb.st_rdev; 103 | devDpy->renderNode = render_sb.st_rdev; 104 | 105 | wl_list_insert(&data->deviceDpyList, &devDpy->link); 106 | return devDpy; 107 | 108 | fail: 109 | free(devDpy); 110 | return NULL; 111 | } 112 | 113 | static void wlFreeInternalDisplay(WlEglDeviceDpy *devDpy) 114 | { 115 | if (devDpy->initCount > 0) { 116 | devDpy->data->egl.terminate(devDpy->eglDisplay); 117 | } 118 | wl_list_remove(&devDpy->link); 119 | free(devDpy); 120 | } 121 | 122 | void wlFreeAllInternalDisplays(WlEglPlatformData *data) 123 | { 124 | WlEglDeviceDpy *devDpy, *devNext; 125 | wl_list_for_each_safe(devDpy, devNext, &data->deviceDpyList, link) { 126 | assert (devDpy->data == data); 127 | wlFreeInternalDisplay(devDpy); 128 | } 129 | } 130 | 131 | EGLBoolean wlInternalInitialize(WlEglDeviceDpy *devDpy) 132 | { 133 | if (devDpy->initCount == 0) { 134 | const char *exts; 135 | 136 | if (!devDpy->data->egl.initialize(devDpy->eglDisplay, &devDpy->major, &devDpy->minor)) { 137 | return EGL_FALSE; 138 | } 139 | 140 | exts = devDpy->data->egl.queryString(devDpy->eglDisplay, EGL_EXTENSIONS); 141 | #define CACHE_EXT(_PREFIX_, _NAME_) \ 142 | devDpy->exts._NAME_ = \ 143 | !!wlEglFindExtension("EGL_" #_PREFIX_ "_" #_NAME_, exts) 144 | 145 | CACHE_EXT(KHR, stream); 146 | CACHE_EXT(NV, stream_attrib); 147 | CACHE_EXT(KHR, stream_cross_process_fd); 148 | CACHE_EXT(NV, stream_remote); 149 | CACHE_EXT(KHR, stream_producer_eglsurface); 150 | CACHE_EXT(NV, stream_fifo_synchronous); 151 | CACHE_EXT(NV, stream_sync); 152 | CACHE_EXT(NV, stream_flush); 153 | CACHE_EXT(NV, stream_consumer_eglimage); 154 | CACHE_EXT(MESA, image_dma_buf_export); 155 | 156 | #undef CACHE_EXT 157 | } 158 | 159 | devDpy->initCount++; 160 | return EGL_TRUE; 161 | } 162 | 163 | EGLBoolean wlInternalTerminate(WlEglDeviceDpy *devDpy) 164 | { 165 | if (devDpy->initCount > 0) { 166 | if (devDpy->initCount == 1) { 167 | if (!devDpy->data->egl.terminate(devDpy->eglDisplay)) { 168 | return EGL_FALSE; 169 | } 170 | } 171 | devDpy->initCount--; 172 | } 173 | return EGL_TRUE; 174 | } 175 | -------------------------------------------------------------------------------- /src/wayland-eglhandle.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2022, NVIDIA CORPORATION. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | #include "wayland-eglhandle.h" 24 | #include "wayland-egldisplay.h" 25 | #include "wayland-eglsurface-internal.h" 26 | #include "wayland-thread.h" 27 | #include 28 | #include 29 | #include 30 | 31 | WlEglPlatformData* 32 | wlEglCreatePlatformData(int apiMajor, int apiMinor, const EGLExtDriver *driver) 33 | { 34 | const char *exts = NULL; 35 | WlEglPlatformData *res = NULL; 36 | 37 | assert((driver != NULL) && (driver->getProcAddress != NULL)); 38 | 39 | /* Allocate platform data and fetch EGL functions */ 40 | res = calloc(1, sizeof(WlEglPlatformData)); 41 | if (res == NULL) { 42 | return NULL; 43 | } 44 | 45 | wl_list_init(&res->deviceDpyList); 46 | 47 | /* Cache the EGL driver version */ 48 | #if EGL_EXTERNAL_PLATFORM_HAS(DRIVER_VERSION) 49 | if (EGL_EXTERNAL_PLATFORM_SUPPORTS(apiMajor, apiMinor, DRIVER_VERSION)) { 50 | res->egl.major = driver->major; 51 | res->egl.minor = driver->minor; 52 | } 53 | #endif 54 | 55 | /* Fetch all required driver functions */ 56 | #define GET_PROC(_FIELD_, _NAME_) \ 57 | do { \ 58 | res->egl._FIELD_ = driver->getProcAddress(#_NAME_); \ 59 | if (res->egl._FIELD_ == NULL) { \ 60 | goto fail; \ 61 | } \ 62 | } while (0) 63 | 64 | /* Core and basic stream functionality */ 65 | GET_PROC(queryString, eglQueryString); 66 | GET_PROC(queryDevices, eglQueryDevicesEXT); 67 | 68 | /* TODO: use eglGetPlatformDisplay instead of eglGetPlatformDisplayEXT 69 | if EGL 1.5 is available */ 70 | GET_PROC(getPlatformDisplay, eglGetPlatformDisplayEXT); 71 | GET_PROC(initialize, eglInitialize); 72 | GET_PROC(terminate, eglTerminate); 73 | GET_PROC(chooseConfig, eglChooseConfig); 74 | GET_PROC(getConfigAttrib, eglGetConfigAttrib); 75 | GET_PROC(querySurface, eglQuerySurface); 76 | 77 | GET_PROC(getCurrentContext, eglGetCurrentContext); 78 | GET_PROC(getCurrentSurface, eglGetCurrentSurface); 79 | GET_PROC(makeCurrent, eglMakeCurrent); 80 | 81 | GET_PROC(createStream, eglCreateStreamKHR); 82 | GET_PROC(createStreamFromFD, eglCreateStreamFromFileDescriptorKHR); 83 | GET_PROC(createStreamAttrib, eglCreateStreamAttribNV); 84 | GET_PROC(getStreamFileDescriptor, eglGetStreamFileDescriptorKHR); 85 | GET_PROC(createStreamProducerSurface, eglCreateStreamProducerSurfaceKHR); 86 | GET_PROC(createPbufferSurface, eglCreatePbufferSurface); 87 | GET_PROC(destroyStream, eglDestroyStreamKHR); 88 | GET_PROC(destroySurface, eglDestroySurface); 89 | 90 | GET_PROC(swapBuffers, eglSwapBuffers); 91 | GET_PROC(swapBuffersWithDamage, eglSwapBuffersWithDamageKHR); 92 | GET_PROC(swapInterval, eglSwapInterval); 93 | 94 | GET_PROC(getError, eglGetError); 95 | GET_PROC(releaseThread, eglReleaseThread); 96 | 97 | /* From EGL_EXT_device_query, used by the wayland-drm implementation */ 98 | GET_PROC(queryDisplayAttrib, eglQueryDisplayAttribEXT); 99 | GET_PROC(queryDeviceString, eglQueryDeviceStringEXT); 100 | 101 | #undef GET_PROC 102 | 103 | /* Fetch all optional driver functions */ 104 | #define GET_PROC(_FIELD_, _NAME_) \ 105 | res->egl._FIELD_ = driver->getProcAddress(#_NAME_) 106 | 107 | /* Used by damage thread */ 108 | GET_PROC(queryStream, eglQueryStreamKHR); 109 | GET_PROC(queryStreamu64, eglQueryStreamu64KHR); 110 | GET_PROC(createStreamSync, eglCreateStreamSyncNV); 111 | GET_PROC(clientWaitSync, eglClientWaitSyncKHR); 112 | GET_PROC(signalSync, eglSignalSyncKHR); 113 | GET_PROC(destroySync, eglDestroySyncKHR); 114 | GET_PROC(createSync, eglCreateSyncKHR); 115 | GET_PROC(dupNativeFenceFD, eglDupNativeFenceFDANDROID); 116 | 117 | /* Stream flush */ 118 | GET_PROC(streamFlush, eglStreamFlushNV); 119 | 120 | /* EGLImage Stream consumer and dependencies */ 121 | GET_PROC(streamImageConsumerConnect, eglStreamImageConsumerConnectNV); 122 | GET_PROC(streamAcquireImage, eglStreamAcquireImageNV); 123 | GET_PROC(streamReleaseImage, eglStreamReleaseImageNV); 124 | GET_PROC(queryStreamConsumerEvent, eglQueryStreamConsumerEventNV); 125 | GET_PROC(exportDMABUFImage, eglExportDMABUFImageMESA); 126 | GET_PROC(exportDMABUFImageQuery, eglExportDMABUFImageQueryMESA); 127 | GET_PROC(createImage, eglCreateImageKHR); 128 | GET_PROC(destroyImage, eglDestroyImageKHR); 129 | 130 | #undef GET_PROC 131 | 132 | /* Check for required EGL client extensions */ 133 | exts = res->egl.queryString(EGL_NO_DISPLAY, EGL_EXTENSIONS); 134 | if (exts == NULL) { 135 | goto fail; 136 | } 137 | 138 | /* 139 | * Note EGL_EXT_platform_device implies support for EGL_EXT_device_base, 140 | * which is equivalent to the combination of EGL_EXT_device_query and 141 | * EGL_EXT_device_enumeration. The wayland-drm implementation assumes 142 | * EGL_EXT_device_query is supported based on this check. 143 | */ 144 | if (!wlEglFindExtension("EGL_EXT_platform_base", exts) || 145 | !wlEglFindExtension("EGL_EXT_platform_device", exts)) { 146 | goto fail; 147 | } 148 | res->supportsDisplayReference = wlEglFindExtension("EGL_KHR_display_reference", exts); 149 | 150 | /* Cache driver imports */ 151 | res->callbacks.setError = driver->setError; 152 | res->callbacks.streamSwapInterval = driver->streamSwapInterval; 153 | 154 | return res; 155 | 156 | fail: 157 | free(res); 158 | return NULL; 159 | } 160 | 161 | void wlEglDestroyPlatformData(WlEglPlatformData *data) 162 | { 163 | free(data); 164 | } 165 | 166 | void* wlEglGetInternalHandleExport(EGLDisplay dpy, EGLenum type, void *handle) 167 | { 168 | WlEglDisplay *display; 169 | if (type == EGL_OBJECT_DISPLAY_KHR) { 170 | display = wlEglAcquireDisplay(handle); 171 | if (display) { 172 | handle = (void *)display->devDpy->eglDisplay; 173 | wlEglReleaseDisplay(display); 174 | } 175 | } else if (type == EGL_OBJECT_SURFACE_KHR) { 176 | display = wlEglAcquireDisplay(dpy); 177 | if (display) { 178 | pthread_mutex_lock(&display->mutex); 179 | if (wlEglIsWlEglSurfaceForDisplay(display, (WlEglSurface *)handle)) { 180 | handle = (void *)(((WlEglSurface *)handle)->ctx.eglSurface); 181 | } 182 | pthread_mutex_unlock(&display->mutex); 183 | wlEglReleaseDisplay(dpy); 184 | } 185 | } 186 | 187 | return handle; 188 | } 189 | -------------------------------------------------------------------------------- /src/wayland-eglstream-server.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2016, NVIDIA CORPORATION. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | #include 35 | #include 36 | #include 37 | 38 | #include "wayland-eglstream-server.h" 39 | #include "wayland-eglstream-server-protocol.h" 40 | #include "wayland-eglstream.h" 41 | #include "wayland-drm.h" 42 | #include "wayland-eglswap.h" 43 | #include "wayland-eglutils.h" 44 | #include "wayland-thread.h" 45 | 46 | #define MASK(_VAL_) (1 << (_VAL_)) 47 | 48 | static struct wl_list wlStreamDpyList = WL_LIST_INITIALIZER(&wlStreamDpyList); 49 | 50 | static void 51 | destroy_wl_eglstream_resource(struct wl_resource *resource) 52 | { 53 | struct wl_eglstream *wlStream = wl_resource_get_user_data(resource); 54 | 55 | if (wlStream->handle >= 0) { 56 | close(wlStream->handle); 57 | } 58 | 59 | free(wlStream); 60 | } 61 | 62 | static void 63 | destroy_wl_eglstream(struct wl_client *client, struct wl_resource *resource) 64 | { 65 | (void) client; 66 | wl_resource_destroy(resource); 67 | } 68 | 69 | static void 70 | handle_create_stream(struct wl_client *client, 71 | struct wl_resource *resource, uint32_t id, 72 | int32_t width, int32_t height, 73 | int handle, int handle_type, 74 | struct wl_array *attribs) 75 | { 76 | struct wl_eglstream_display *wlStreamDpy = 77 | wl_resource_get_user_data(resource); 78 | struct wl_eglstream *wlStream; 79 | struct sockaddr_in sockAddr; 80 | char sockAddrStr[NI_MAXHOST]; 81 | intptr_t *attr; 82 | int mask = 0; 83 | enum wl_eglstream_error err; 84 | 85 | wlStream = calloc(1, sizeof *wlStream); 86 | if (wlStream == NULL) { 87 | err = WL_EGLSTREAM_ERROR_BAD_ALLOC; 88 | goto error_create_stream; 89 | } 90 | 91 | wlStream->wlStreamDpy = wlStreamDpy; 92 | wlStream->eglStream = EGL_NO_STREAM_KHR; 93 | wlStream->width = width; 94 | wlStream->height = height; 95 | wlStream->handle = -1; 96 | wlStream->yInverted = EGL_FALSE; 97 | 98 | memset(&sockAddr, 0, sizeof(sockAddr)); 99 | 100 | switch (handle_type) { 101 | case WL_EGLSTREAM_HANDLE_TYPE_FD: 102 | wlStream->handle = handle; 103 | wlStream->fromFd = EGL_TRUE; 104 | break; 105 | 106 | case WL_EGLSTREAM_HANDLE_TYPE_INET: 107 | sockAddr.sin_family = AF_INET; 108 | wlStream->isInet = EGL_TRUE; 109 | /* Close the given dummy fd */ 110 | close(handle); 111 | break; 112 | 113 | case WL_EGLSTREAM_HANDLE_TYPE_SOCKET: 114 | wlStream->handle = handle; 115 | break; 116 | 117 | default: 118 | err = WL_EGLSTREAM_ERROR_BAD_HANDLE; 119 | goto error_create_stream; 120 | } 121 | 122 | wl_array_for_each(attr, attribs) { 123 | switch (attr[0]) { 124 | case WL_EGLSTREAM_ATTRIB_INET_ADDR: 125 | /* INET_ADDR should only be set once */ 126 | if (mask & MASK(WL_EGLSTREAM_ATTRIB_INET_ADDR)) { 127 | err = WL_EGLSTREAM_ERROR_BAD_ATTRIBS; 128 | goto error_create_stream; 129 | } 130 | sockAddr.sin_addr.s_addr = htonl((int)attr[1]); 131 | mask |= MASK(WL_EGLSTREAM_ATTRIB_INET_ADDR); 132 | break; 133 | 134 | case WL_EGLSTREAM_ATTRIB_INET_PORT: 135 | /* INET_PORT should only be set once */ 136 | if (mask & MASK(WL_EGLSTREAM_ATTRIB_INET_PORT)) { 137 | err = WL_EGLSTREAM_ERROR_BAD_ATTRIBS; 138 | goto error_create_stream; 139 | } 140 | sockAddr.sin_port = htons((int)attr[1]); 141 | mask |= MASK(WL_EGLSTREAM_ATTRIB_INET_PORT); 142 | break; 143 | 144 | case WL_EGLSTREAM_ATTRIB_Y_INVERTED: 145 | /* Y_INVERTED should only be set once */ 146 | if (mask & MASK(WL_EGLSTREAM_ATTRIB_Y_INVERTED)) { 147 | err = WL_EGLSTREAM_ERROR_BAD_ATTRIBS; 148 | goto error_create_stream; 149 | } 150 | wlStream->yInverted = (EGLBoolean)attr[1]; 151 | mask |= MASK(WL_EGLSTREAM_ATTRIB_Y_INVERTED); 152 | break; 153 | 154 | default: 155 | assert(!"Unknown attribute"); 156 | break; 157 | } 158 | 159 | /* Attribs processed in pairs */ 160 | attr++; 161 | } 162 | 163 | if (wlStream->isInet) { 164 | /* Both address and port should have been set */ 165 | if (mask != (MASK(WL_EGLSTREAM_ATTRIB_INET_ADDR) | 166 | MASK(WL_EGLSTREAM_ATTRIB_INET_PORT))) { 167 | err = WL_EGLSTREAM_ERROR_BAD_ATTRIBS; 168 | goto error_create_stream; 169 | } 170 | 171 | wlStream->handle = socket(AF_INET, SOCK_STREAM, 0); 172 | if (wlStream->handle == -1) { 173 | err = WL_EGLSTREAM_ERROR_BAD_ALLOC; 174 | goto error_create_stream; 175 | } 176 | 177 | if (connect(wlStream->handle, 178 | (struct sockaddr *)&sockAddr, 179 | sizeof(sockAddr)) < 0) { 180 | err = WL_EGLSTREAM_ERROR_BAD_ADDRESS; 181 | goto error_create_stream; 182 | } 183 | } 184 | 185 | wlStream->resource = 186 | wl_resource_create(client, &wl_buffer_interface, 1, id); 187 | if (!wlStream->resource) { 188 | err = WL_EGLSTREAM_ERROR_BAD_ALLOC; 189 | goto error_create_stream; 190 | } 191 | 192 | wl_resource_set_implementation( 193 | wlStream->resource, 194 | (void (**)(void))&wlStreamDpy->wl_eglstream_interface, 195 | wlStream, 196 | destroy_wl_eglstream_resource); 197 | return; 198 | 199 | error_create_stream: 200 | switch (err) { 201 | case WL_EGLSTREAM_ERROR_BAD_ALLOC: 202 | wl_resource_post_no_memory(resource); 203 | break; 204 | case WL_EGLSTREAM_ERROR_BAD_HANDLE: 205 | wl_resource_post_error(resource, err, "Invalid or unknown handle"); 206 | break; 207 | case WL_EGLSTREAM_ERROR_BAD_ATTRIBS: 208 | wl_resource_post_error(resource, err, "Malformed attributes list"); 209 | break; 210 | case WL_EGLSTREAM_ERROR_BAD_ADDRESS: 211 | wl_resource_post_error(resource, err, "Unable to connect to %s:%d.", 212 | (getnameinfo((struct sockaddr *)&sockAddr, 213 | sizeof(sockAddr), 214 | sockAddrStr, NI_MAXHOST, 215 | NULL, 0, 216 | NI_NUMERICHOST) ? 217 | "" : sockAddrStr), 218 | ntohs(sockAddr.sin_port)); 219 | break; 220 | default: 221 | assert(!"Unknown error code"); 222 | break; 223 | } 224 | 225 | if (wlStream) { 226 | if (wlStream->isInet && wlStream->handle >= 0) { 227 | close(wlStream->handle); 228 | } 229 | free(wlStream); 230 | } 231 | } 232 | 233 | static void 234 | handle_swap_interval(struct wl_client *client, 235 | struct wl_resource *displayResource, 236 | struct wl_resource *streamResource, 237 | int interval) 238 | { 239 | struct wl_eglstream_display *wlStreamDpy = 240 | wl_resource_get_user_data(displayResource); 241 | struct wl_eglstream *wlStream = 242 | wl_eglstream_display_get_stream(wlStreamDpy, streamResource); 243 | (void) client; 244 | 245 | if (wlEglStreamSwapIntervalCallback(wlStreamDpy->data, 246 | wlStream->eglStream, 247 | &interval) == EGL_BAD_MATCH) { 248 | wl_eglstream_display_send_swapinterval_override(displayResource, 249 | interval, 250 | streamResource); 251 | } 252 | } 253 | 254 | static const struct wl_eglstream_display_interface 255 | wl_eglstream_display_interface_impl = { 256 | handle_create_stream, 257 | handle_swap_interval, 258 | }; 259 | 260 | static void 261 | wl_eglstream_display_global_bind(struct wl_client *client, 262 | void *data, 263 | uint32_t version, 264 | uint32_t id) 265 | { 266 | struct wl_eglstream_display *wlStreamDpy = NULL; 267 | struct wl_resource *resource = NULL; 268 | 269 | wlStreamDpy = (struct wl_eglstream_display *)data; 270 | resource = wl_resource_create(client, 271 | &wl_eglstream_display_interface, 272 | version, 273 | id); 274 | if (!resource) { 275 | wl_client_post_no_memory(client); 276 | return; 277 | } 278 | 279 | wl_resource_set_implementation(resource, 280 | &wl_eglstream_display_interface_impl, 281 | data, 282 | NULL); 283 | 284 | 285 | wl_eglstream_display_send_caps(resource, wlStreamDpy->supported_caps); 286 | } 287 | 288 | EGLBoolean 289 | wl_eglstream_display_bind(WlEglPlatformData *data, 290 | struct wl_display *wlDisplay, 291 | EGLDisplay eglDisplay, 292 | const char *exts, 293 | const char *dev_name) 294 | { 295 | struct wl_eglstream_display *wlStreamDpy = NULL; 296 | char *env = NULL; 297 | 298 | /* Check whether there's an EGLDisplay already bound to the given 299 | * wl_display */ 300 | if (wl_eglstream_display_get(eglDisplay) != NULL) { 301 | return EGL_FALSE; 302 | } 303 | 304 | wlStreamDpy = calloc(1, sizeof(*wlStreamDpy)); 305 | if (!wlStreamDpy) { 306 | return EGL_FALSE; 307 | } 308 | 309 | wlStreamDpy->data = data; 310 | wlStreamDpy->wlDisplay = wlDisplay; 311 | wlStreamDpy->eglDisplay = eglDisplay; 312 | wlStreamDpy->caps_override = 0; 313 | 314 | #define CACHE_EXT(_PREFIX_, _NAME_) \ 315 | wlStreamDpy->exts._NAME_ = \ 316 | !!wlEglFindExtension("EGL_" #_PREFIX_ "_" #_NAME_, exts) 317 | 318 | CACHE_EXT(NV, stream_attrib); 319 | CACHE_EXT(KHR, stream_cross_process_fd); 320 | CACHE_EXT(NV, stream_remote); 321 | CACHE_EXT(NV, stream_socket); 322 | CACHE_EXT(NV, stream_socket_inet); 323 | CACHE_EXT(NV, stream_socket_unix); 324 | CACHE_EXT(NV, stream_origin); 325 | 326 | #undef CACHE_EXT 327 | 328 | /* Advertise server capabilities */ 329 | if (wlStreamDpy->exts.stream_cross_process_fd) { 330 | wlStreamDpy->supported_caps |= WL_EGLSTREAM_DISPLAY_CAP_STREAM_FD; 331 | } 332 | if (wlStreamDpy->exts.stream_attrib && 333 | wlStreamDpy->exts.stream_remote && 334 | wlStreamDpy->exts.stream_socket) { 335 | if (wlStreamDpy->exts.stream_socket_inet) { 336 | wlStreamDpy->supported_caps |= WL_EGLSTREAM_DISPLAY_CAP_STREAM_INET; 337 | } 338 | if (wlStreamDpy->exts.stream_socket_unix) { 339 | wlStreamDpy->supported_caps |= WL_EGLSTREAM_DISPLAY_CAP_STREAM_SOCKET; 340 | } 341 | } 342 | 343 | env = getenv("WL_EGLSTREAM_CAP_OVERRIDE"); 344 | if (env) { 345 | int serverCapOverride = atoi(env); 346 | wlStreamDpy->caps_override = (wlStreamDpy->supported_caps 347 | & serverCapOverride) != 348 | wlStreamDpy->supported_caps; 349 | wlStreamDpy->supported_caps &= serverCapOverride; 350 | } 351 | 352 | wlStreamDpy->wl_eglstream_interface.destroy = destroy_wl_eglstream; 353 | wlStreamDpy->global = wl_global_create(wlDisplay, 354 | &wl_eglstream_display_interface, 1, 355 | wlStreamDpy, 356 | wl_eglstream_display_global_bind); 357 | 358 | /* Failure is not fatal */ 359 | wl_drm_display_bind(wlDisplay, wlStreamDpy, dev_name); 360 | 361 | wl_list_insert(&wlStreamDpyList, &wlStreamDpy->link); 362 | 363 | return EGL_TRUE; 364 | } 365 | 366 | void 367 | wl_eglstream_display_unbind(struct wl_eglstream_display *wlStreamDpy) 368 | { 369 | wl_drm_display_unbind(wlStreamDpy); 370 | wl_global_destroy(wlStreamDpy->global); 371 | wl_list_remove(&wlStreamDpy->link); 372 | free(wlStreamDpy); 373 | } 374 | 375 | struct wl_eglstream_display* wl_eglstream_display_get(EGLDisplay eglDisplay) 376 | { 377 | struct wl_eglstream_display *wlDisplay; 378 | 379 | wl_list_for_each(wlDisplay, &wlStreamDpyList, link) { 380 | if (wlDisplay->eglDisplay == eglDisplay) { 381 | return wlDisplay; 382 | } 383 | } 384 | 385 | return NULL; 386 | } 387 | 388 | struct wl_eglstream* 389 | wl_eglstream_display_get_stream(struct wl_eglstream_display *wlStreamDpy, 390 | struct wl_resource *resource) 391 | { 392 | if (resource == NULL) { 393 | return NULL; 394 | } 395 | 396 | if (wl_resource_instance_of(resource, &wl_buffer_interface, 397 | &wlStreamDpy->wl_eglstream_interface)) { 398 | return wl_resource_get_user_data(resource); 399 | } else { 400 | return NULL; 401 | } 402 | } 403 | 404 | -------------------------------------------------------------------------------- /src/wayland-eglstream.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | #include "wayland-eglstream.h" 24 | #include "wayland-eglstream-server.h" 25 | #include "wayland-thread.h" 26 | #include "wayland-eglhandle.h" 27 | #include "wayland-egldisplay.h" 28 | #include "wayland-eglutils.h" 29 | #include "wayland-egl-ext.h" 30 | #include 31 | #include 32 | #include 33 | 34 | #define WL_EGL_CONN_WAIT_USECS 1e3 /* 1 msec */ 35 | #define WL_EGL_CONN_TIMEOUT_USECS 1e6 /* 1 sec */ 36 | 37 | EGLStreamKHR wlEglCreateStreamAttribHook(EGLDisplay dpy, 38 | const EGLAttrib *attribs) 39 | { 40 | WlEglPlatformData *data = NULL; 41 | EGLStreamKHR stream = EGL_NO_STREAM_KHR; 42 | struct wl_eglstream_display *wlStreamDpy = NULL; 43 | struct wl_resource *resource = NULL; 44 | struct wl_eglstream *wlStream = NULL; 45 | int nAttribs = 0; 46 | int idx = 0; 47 | int fd = -1; 48 | EGLint err = EGL_SUCCESS; 49 | 50 | /* Parse attribute list and count internal attributes */ 51 | if (attribs) { 52 | while (attribs[idx] != EGL_NONE) { 53 | if (attribs[idx] == EGL_WAYLAND_EGLSTREAM_WL) { 54 | if (resource != NULL) { 55 | err = EGL_BAD_MATCH; 56 | break; 57 | } 58 | 59 | resource = (struct wl_resource *)attribs[idx + 1]; 60 | if (resource == NULL) { 61 | err = EGL_BAD_ACCESS; 62 | break; 63 | } 64 | } else { 65 | /* Internal attribute */ 66 | nAttribs++; 67 | } 68 | idx += 2; 69 | } 70 | } 71 | 72 | if ((err == EGL_SUCCESS) && (resource == NULL)) { 73 | /* No EGL_WAYLAND_EGLSTREAM_WL attribute provided, which means dpy is 74 | * external. Forward this call to the underlying driver as there's 75 | * nothing to do here */ 76 | WlEglDisplay *display = (WlEglDisplay *)dpy; 77 | return display->data->egl.createStreamAttrib(display->devDpy->eglDisplay, 78 | attribs); 79 | } 80 | 81 | /* Otherwise, we must create a server-side stream */ 82 | wlExternalApiLock(); 83 | 84 | wlStreamDpy = wl_eglstream_display_get(dpy); 85 | if (wlStreamDpy == NULL) { 86 | err = EGL_BAD_ACCESS; 87 | } else { 88 | data = wlStreamDpy->data; 89 | } 90 | 91 | if (err != EGL_SUCCESS) { 92 | goto fail; 93 | } 94 | 95 | wlStream = wl_eglstream_display_get_stream(wlStreamDpy, resource); 96 | if (wlStream == NULL) { 97 | err = EGL_BAD_ACCESS; 98 | goto fail; 99 | } 100 | 101 | if (wlStream->eglStream != EGL_NO_STREAM_KHR || 102 | wlStream->handle == -1) { 103 | err = EGL_BAD_STREAM_KHR; 104 | goto fail; 105 | } 106 | 107 | if (wlStream->fromFd) { 108 | /* Check for EGL_KHR_stream_cross_process_fd support */ 109 | if (!wlStreamDpy->exts.stream_cross_process_fd) { 110 | err = EGL_BAD_ACCESS; 111 | goto fail; 112 | } 113 | 114 | /* eglCreateStreamFromFileDescriptorKHR from 115 | * EGL_KHR_stream_cross_process_fd does not take attributes. Thus, only 116 | * EGL_WAYLAND_EGLSTREAM_WL should have been specified and processed 117 | * above. caps_override is an exception to this, since the wayland 118 | * compositor calling into this function wouldn't be aware of an 119 | * override in place */ 120 | if (nAttribs != 0 && !wlStreamDpy->caps_override) { 121 | err = EGL_BAD_ATTRIBUTE; 122 | goto fail; 123 | } 124 | 125 | fd = wlStream->handle; 126 | stream = data->egl.createStreamFromFD(dpy, wlStream->handle); 127 | 128 | /* Clean up */ 129 | close(fd); 130 | wlStream->handle = -1; 131 | } 132 | #if defined(EGL_NV_stream_attrib) && \ 133 | defined(EGL_NV_stream_remote) && \ 134 | defined(EGL_NV_stream_socket) 135 | else { 136 | EGLAttrib *attribs2 = NULL; 137 | 138 | /* Check for required extensions support */ 139 | if (!wlStreamDpy->exts.stream_attrib || 140 | !wlStreamDpy->exts.stream_remote || 141 | !wlStreamDpy->exts.stream_socket || 142 | (!wlStreamDpy->exts.stream_socket_inet && 143 | !wlStreamDpy->exts.stream_socket_unix)) { 144 | err = EGL_BAD_ACCESS; 145 | goto fail; 146 | } 147 | 148 | /* If not inet connection supported, wlStream should not be inet */ 149 | if (!wlStreamDpy->exts.stream_socket_inet && 150 | wlStream->isInet) { 151 | err = EGL_BAD_ACCESS; 152 | goto fail; 153 | } 154 | 155 | /* Create attributes array to pass down to the actual EGL stream 156 | * creation function */ 157 | attribs2 = (EGLAttrib *)malloc((2*(nAttribs + 5) + 1)*sizeof(*attribs2)); 158 | 159 | nAttribs = 0; 160 | attribs2[nAttribs++] = EGL_STREAM_TYPE_NV; 161 | attribs2[nAttribs++] = EGL_STREAM_CROSS_PROCESS_NV; 162 | attribs2[nAttribs++] = EGL_STREAM_PROTOCOL_NV; 163 | attribs2[nAttribs++] = EGL_STREAM_PROTOCOL_SOCKET_NV; 164 | attribs2[nAttribs++] = EGL_STREAM_ENDPOINT_NV; 165 | attribs2[nAttribs++] = EGL_STREAM_CONSUMER_NV; 166 | attribs2[nAttribs++] = EGL_SOCKET_TYPE_NV; 167 | attribs2[nAttribs++] = (wlStream->isInet ? EGL_SOCKET_TYPE_INET_NV : 168 | EGL_SOCKET_TYPE_UNIX_NV); 169 | attribs2[nAttribs++] = EGL_SOCKET_HANDLE_NV; 170 | attribs2[nAttribs++] = (EGLAttrib)wlStream->handle; 171 | 172 | /* Include internal attributes given by the application */ 173 | while (attribs && attribs[0] != EGL_NONE) { 174 | switch (attribs[0]) { 175 | /* Filter out external attributes */ 176 | case EGL_WAYLAND_EGLSTREAM_WL: 177 | break; 178 | 179 | /* EGL_NV_stream_remote attributes shouldn't be set by the 180 | * application */ 181 | case EGL_STREAM_TYPE_NV: 182 | case EGL_STREAM_PROTOCOL_NV: 183 | case EGL_STREAM_ENDPOINT_NV: 184 | case EGL_SOCKET_TYPE_NV: 185 | case EGL_SOCKET_HANDLE_NV: 186 | free(attribs2); 187 | err = EGL_BAD_ATTRIBUTE; 188 | goto fail; 189 | 190 | /* Everything else is fine and will be handled by EGL */ 191 | default: 192 | attribs2[nAttribs++] = attribs[0]; 193 | attribs2[nAttribs++] = attribs[1]; 194 | } 195 | 196 | attribs += 2; 197 | } 198 | attribs2[nAttribs] = EGL_NONE; 199 | 200 | stream = data->egl.createStreamAttrib(dpy, attribs2); 201 | 202 | /* Clean up */ 203 | free(attribs2); 204 | 205 | if (stream != EGL_NO_STREAM_KHR) { 206 | /* Wait for the stream to establish connection with the producer's 207 | * side */ 208 | uint32_t timeout = WL_EGL_CONN_TIMEOUT_USECS; 209 | EGLint state = EGL_STREAM_STATE_INITIALIZING_NV; 210 | 211 | do { 212 | usleep(WL_EGL_CONN_WAIT_USECS); 213 | timeout -= WL_EGL_CONN_WAIT_USECS; 214 | 215 | if (!data->egl.queryStream(dpy, 216 | stream, 217 | EGL_STREAM_STATE_KHR, 218 | &state)) { 219 | break; 220 | } 221 | } while ((state == EGL_STREAM_STATE_INITIALIZING_NV) && 222 | (timeout > 0)); 223 | 224 | if (state == EGL_STREAM_STATE_INITIALIZING_NV) { 225 | data->egl.destroyStream(dpy, stream); 226 | stream = EGL_NO_STREAM_KHR; 227 | } 228 | } 229 | } 230 | #endif 231 | 232 | if (stream == EGL_NO_STREAM_KHR) { 233 | err = EGL_BAD_ACCESS; 234 | goto fail; 235 | } 236 | 237 | wlStream->eglStream = stream; 238 | wlStream->handle = -1; 239 | 240 | wlExternalApiUnlock(); 241 | 242 | return stream; 243 | 244 | fail: 245 | wlExternalApiUnlock(); 246 | wlEglSetError(data, err); 247 | return EGL_NO_STREAM_KHR; 248 | } 249 | 250 | -------------------------------------------------------------------------------- /src/wayland-eglswap.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2022, NVIDIA CORPORATION. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | #include "wayland-eglswap.h" 24 | #include "wayland-eglstream-client-protocol.h" 25 | #include "presentation-time-client-protocol.h" 26 | #include "wayland-thread.h" 27 | #include "wayland-egldisplay.h" 28 | #include "wayland-eglsurface-internal.h" 29 | #include "wayland-eglhandle.h" 30 | #include "wayland-eglutils.h" 31 | #include 32 | #include 33 | #include 34 | 35 | enum PresentationStatus { KICKED_OFF = 0, LANDED = 1 }; 36 | 37 | struct EventItem { 38 | uint64_t capturedId; 39 | void *presentInfo; 40 | WlEglSurface *surface; 41 | }; 42 | 43 | EGLBoolean wlEglSwapBuffersHook(EGLDisplay eglDisplay, EGLSurface eglSurface) 44 | { 45 | return wlEglSwapBuffersWithDamageHook(eglDisplay, eglSurface, NULL, 0); 46 | } 47 | 48 | EGLBoolean wlEglSwapBuffersWithDamageHook(EGLDisplay eglDisplay, EGLSurface eglSurface, EGLint *rects, EGLint n_rects) 49 | { 50 | WlEglDisplay *display = wlEglAcquireDisplay(eglDisplay); 51 | WlEglPlatformData *data = NULL; 52 | WlEglSurface *surface = NULL; 53 | EGLStreamKHR eglStream = EGL_NO_STREAM_KHR; 54 | EGLBoolean isOffscreen = EGL_FALSE; 55 | EGLBoolean res; 56 | EGLint err; 57 | 58 | if (!display) { 59 | return EGL_FALSE; 60 | } 61 | pthread_mutex_lock(&display->mutex); 62 | 63 | data = display->data; 64 | 65 | if (display->initCount == 0) { 66 | err = EGL_NOT_INITIALIZED; 67 | goto fail; 68 | } 69 | 70 | if (!wlEglSurfaceRef(display, eglSurface)) { 71 | err = EGL_BAD_SURFACE; 72 | goto fail; 73 | } 74 | 75 | surface = eglSurface; 76 | 77 | if (surface->pendingSwapIntervalUpdate == EGL_TRUE) { 78 | /* Send request from client to override swapinterval value based on 79 | * server's swapinterval for overlay compositing 80 | */ 81 | assert(surface->ctx.wlStreamResource); 82 | wl_eglstream_display_swap_interval(display->wlStreamDpy, 83 | surface->ctx.wlStreamResource, 84 | surface->swapInterval); 85 | /* For receiving any event in case of override */ 86 | if (wl_display_roundtrip_queue(display->nativeDpy, 87 | display->wlEventQueue) < 0) { 88 | err = EGL_BAD_ALLOC; 89 | goto fail; 90 | } 91 | surface->pendingSwapIntervalUpdate = EGL_FALSE; 92 | } 93 | 94 | pthread_mutex_unlock(&display->mutex); 95 | 96 | // Acquire wlEglSurface lock. 97 | pthread_mutex_lock(&surface->mutexLock); 98 | 99 | if (surface->isDestroyed) { 100 | err = EGL_BAD_SURFACE; 101 | goto fail_locked; 102 | } 103 | 104 | isOffscreen = surface->ctx.isOffscreen; 105 | if (!isOffscreen) { 106 | if (!wlEglIsWaylandWindowValid(surface->wlEglWin)) { 107 | err = EGL_BAD_NATIVE_WINDOW; 108 | goto fail_locked; 109 | } 110 | 111 | if (surface->ctx.useDamageThread) { 112 | pthread_mutex_lock(&surface->mutexFrameSync); 113 | // Wait for damage thread to submit the 114 | // previous frame and generate frame sync 115 | while (surface->ctx.framesProduced != surface->ctx.framesProcessed) { 116 | pthread_cond_wait(&surface->condFrameSync, &surface->mutexFrameSync); 117 | } 118 | pthread_mutex_unlock(&surface->mutexFrameSync); 119 | } 120 | 121 | wlEglWaitFrameSync(surface); 122 | } 123 | 124 | /* Save the internal EGLDisplay, EGLSurface and EGLStream handles, as 125 | * they are needed by the eglSwapBuffers() and streamFlush calls below */ 126 | eglDisplay = display->devDpy->eglDisplay; 127 | eglSurface = surface->ctx.eglSurface; 128 | eglStream = surface->ctx.eglStream; 129 | 130 | /* eglSwapBuffers() is a blocking call. We must release the lock so other 131 | * threads using the external platform are allowed to progress. 132 | */ 133 | if (rects) { 134 | res = data->egl.swapBuffersWithDamage(eglDisplay, eglSurface, rects, n_rects); 135 | } else { 136 | res = data->egl.swapBuffers(eglDisplay, eglSurface); 137 | } 138 | if (isOffscreen) { 139 | goto done; 140 | } 141 | if (display->devDpy->exts.stream_flush) { 142 | data->egl.streamFlush(eglDisplay, eglStream); 143 | } 144 | 145 | if (res) { 146 | if (surface->ctx.useDamageThread) { 147 | surface->ctx.framesProduced++; 148 | } else { 149 | wlEglCreateFrameSync(surface); 150 | res = wlEglSendDamageEvent(surface, surface->wlEventQueue, rects, n_rects); 151 | wlEglSurfaceCheckReleasePoints(display, surface); 152 | } 153 | } 154 | 155 | /* Resize stream if window geometry or available modifiers have changed */ 156 | if (surface->isResized || 157 | surface->feedback.unprocessedFeedback || 158 | display->defaultFeedback.unprocessedFeedback) { 159 | wlEglReallocSurface(display, data, surface); 160 | } 161 | 162 | done: 163 | // Release wlEglSurface lock. 164 | pthread_mutex_unlock(&surface->mutexLock); 165 | 166 | /* reacquire display lock */ 167 | pthread_mutex_lock(&display->mutex); 168 | wlEglSurfaceUnref(surface); 169 | pthread_mutex_unlock(&display->mutex); 170 | wlEglReleaseDisplay(display); 171 | 172 | return res; 173 | 174 | fail_locked: 175 | pthread_mutex_unlock(&surface->mutexLock); 176 | /* reacquire display lock */ 177 | pthread_mutex_lock(&display->mutex); 178 | fail: 179 | if (surface != NULL) { 180 | wlEglSurfaceUnref(surface); 181 | } 182 | pthread_mutex_unlock(&display->mutex); 183 | wlEglReleaseDisplay(display); 184 | 185 | wlEglSetError(data, err); 186 | return EGL_FALSE; 187 | } 188 | 189 | EGLBoolean wlEglSwapIntervalHook(EGLDisplay eglDisplay, EGLint interval) 190 | { 191 | WlEglDisplay *display = wlEglAcquireDisplay(eglDisplay); 192 | WlEglPlatformData *data = NULL; 193 | WlEglSurface *surface = NULL; 194 | EGLBoolean ret = EGL_TRUE; 195 | EGLint state; 196 | 197 | if (!display) { 198 | return EGL_FALSE; 199 | } 200 | pthread_mutex_lock(&display->mutex); 201 | 202 | data = display->data; 203 | 204 | if (display->initCount == 0) { 205 | wlEglSetError(data, EGL_NOT_INITIALIZED); 206 | ret = EGL_FALSE; 207 | goto done; 208 | } 209 | 210 | /* Save the internal EGLDisplay handle, as it's needed by the actual 211 | * eglSwapInterval() call */ 212 | eglDisplay = display->devDpy->eglDisplay; 213 | 214 | pthread_mutex_unlock(&display->mutex); 215 | 216 | if (!(data->egl.swapInterval(eglDisplay, interval))) { 217 | wlEglReleaseDisplay(display); 218 | return EGL_FALSE; 219 | } 220 | 221 | surface = (WlEglSurface *)data->egl.getCurrentSurface(EGL_DRAW); 222 | 223 | pthread_mutex_lock(&display->mutex); 224 | 225 | /* Check this is a valid wayland EGL surface */ 226 | if (display->initCount == 0 || 227 | !wlEglIsWlEglSurfaceForDisplay(display, surface) || 228 | (surface->swapInterval == interval) || 229 | (surface->ctx.eglStream == EGL_NO_STREAM_KHR)) { 230 | goto done; 231 | } 232 | 233 | /* Cache interval value so we can reset it upon surface reattach */ 234 | surface->swapInterval = interval; 235 | 236 | if (surface->ctx.wlStreamResource && 237 | data->egl.queryStream(display->devDpy->eglDisplay, 238 | surface->ctx.eglStream, 239 | EGL_STREAM_STATE_KHR, &state) && 240 | state != EGL_STREAM_STATE_DISCONNECTED_KHR) { 241 | /* Set client's pendingSwapIntervalUpdate for updating client's 242 | * swapinterval if the compositor supports wl_eglstream_display 243 | * and the surface has a valid server-side stream 244 | */ 245 | surface->pendingSwapIntervalUpdate = EGL_TRUE; 246 | } 247 | 248 | done: 249 | pthread_mutex_unlock(&display->mutex); 250 | wlEglReleaseDisplay(display); 251 | 252 | return ret; 253 | } 254 | 255 | WL_EXPORT 256 | EGLBoolean wlEglPrePresentExport(WlEglSurface *surface) { 257 | WlEglDisplay *display = wlEglAcquireDisplay((WlEglDisplay *)surface->wlEglDpy); 258 | if (!display) { 259 | return EGL_FALSE; 260 | } 261 | 262 | pthread_mutex_lock(&display->mutex); 263 | 264 | if (surface->pendingSwapIntervalUpdate == EGL_TRUE) { 265 | /* Send request from client to override swapinterval value based on 266 | * server's swapinterval for overlay compositing 267 | */ 268 | wl_eglstream_display_swap_interval(display->wlStreamDpy, 269 | surface->ctx.wlStreamResource, 270 | surface->swapInterval); 271 | /* For receiving any event in case of override */ 272 | if (wl_display_roundtrip_queue(display->nativeDpy, 273 | display->wlEventQueue) < 0) { 274 | pthread_mutex_unlock(&display->mutex); 275 | wlEglReleaseDisplay(display); 276 | return EGL_FALSE; 277 | } 278 | surface->pendingSwapIntervalUpdate = EGL_FALSE; 279 | } 280 | 281 | pthread_mutex_unlock(&display->mutex); 282 | 283 | // Acquire wlEglSurface lock. 284 | pthread_mutex_lock(&surface->mutexLock); 285 | 286 | if (surface->ctx.useDamageThread) { 287 | pthread_mutex_lock(&surface->mutexFrameSync); 288 | // Wait for damage thread to submit the 289 | // previous frame and generate frame sync 290 | while (surface->ctx.framesProduced != surface->ctx.framesProcessed) { 291 | pthread_cond_wait(&surface->condFrameSync, &surface->mutexFrameSync); 292 | } 293 | pthread_mutex_unlock(&surface->mutexFrameSync); 294 | } 295 | 296 | wlEglWaitFrameSync(surface); 297 | 298 | // Release wlEglSurface lock. 299 | pthread_mutex_unlock(&surface->mutexLock); 300 | wlEglReleaseDisplay(display); 301 | 302 | return EGL_TRUE; 303 | } 304 | 305 | WL_EXPORT 306 | EGLBoolean wlEglPostPresentExport(WlEglSurface *surface) { 307 | return wlEglPostPresentExport2(surface, 0, NULL); 308 | } 309 | 310 | static void present_feedback_sync_output(void *data, 311 | struct wp_presentation_feedback *feedback, 312 | struct wl_output *output) 313 | { 314 | // This function is intentionally left blank. sync_output events 315 | // precede the presented events when wl_output is bound. 316 | // 317 | // The information provided by this function is not needed at the 318 | // moment. 319 | 320 | (void) data; 321 | (void) feedback; 322 | (void) output; 323 | } 324 | 325 | static void present_feedback_discarded(void *data, 326 | struct wp_presentation_feedback *feedback) 327 | { 328 | struct EventItem *eventItem = data; 329 | WlEglSurface *surface = eventItem->surface; 330 | 331 | // If the following condition is not true, it means that this presentInfo 332 | // was overwritten. The presentInfo that it was pointing to when this 333 | // request was created is not the same as the one it is pointing to right 334 | // now. Status of the previous presentInfo is not relevant. 335 | if (surface->present_update_callback(eventItem->presentInfo, 336 | eventItem->capturedId, 337 | LANDED)) { 338 | surface->landedPresentFeedbackCount++; 339 | } 340 | 341 | surface->inFlightPresentFeedbackCount--; 342 | 343 | free(eventItem); 344 | (void) feedback; 345 | } 346 | 347 | static void present_feedback_presented(void *data, 348 | struct wp_presentation_feedback *feedback, 349 | uint32_t tv_sec_hi, 350 | uint32_t tv_sec_lo, 351 | uint32_t tv_nsec, 352 | uint32_t refresh, 353 | uint32_t seq_hi, 354 | uint32_t seq_lo, 355 | uint32_t flags) 356 | { 357 | // For now, whatever the outcome of the presentation is, the same 358 | // operations are performed as a result 359 | present_feedback_discarded(data, feedback); 360 | 361 | (void) tv_sec_hi; 362 | (void) tv_sec_lo; 363 | (void) tv_nsec; 364 | (void) refresh; 365 | (void) seq_hi; 366 | (void) seq_lo; 367 | (void) tv_sec_hi; 368 | (void) flags; 369 | } 370 | 371 | static const struct wp_presentation_feedback_listener present_feedback_listener = { 372 | present_feedback_sync_output, 373 | present_feedback_presented, 374 | present_feedback_discarded 375 | }; 376 | 377 | WL_EXPORT 378 | EGLBoolean wlEglPostPresentExport2(WlEglSurface *surface, 379 | uint64_t presentId, 380 | void *presentInfo) { 381 | WlEglDisplay *display = wlEglAcquireDisplay((WlEglDisplay *)surface->wlEglDpy); 382 | WlEglPlatformData *data = NULL; 383 | EGLBoolean res = EGL_TRUE; 384 | 385 | if (!display) { 386 | return EGL_FALSE; 387 | } 388 | 389 | data = display->data; 390 | 391 | // Acquire wlEglSurface lock. 392 | pthread_mutex_lock(&surface->mutexLock); 393 | 394 | if (display->devDpy->exts.stream_flush) { 395 | data->egl.streamFlush((EGLDisplay) display, surface->ctx.eglStream); 396 | } 397 | 398 | if (presentInfo) 399 | { 400 | assert(surface->present_update_callback != NULL); 401 | 402 | if (display->wpPresentation) 403 | { 404 | struct wp_presentation_feedback *presentationFeedback = NULL; 405 | struct wp_presentation *wrapper = wl_proxy_create_wrapper(display->wpPresentation); 406 | 407 | struct EventItem *eventItem = malloc(sizeof(struct EventItem)); 408 | eventItem->capturedId = presentId; 409 | eventItem->presentInfo = presentInfo; 410 | eventItem->surface = surface; 411 | 412 | wl_proxy_set_queue((struct wl_proxy *)wrapper, surface->presentFeedbackQueue); 413 | presentationFeedback = wp_presentation_feedback(wrapper, surface->wlSurface); 414 | wl_proxy_wrapper_destroy(wrapper); /* Done with wrapper */ 415 | if (wp_presentation_feedback_add_listener(presentationFeedback, 416 | &present_feedback_listener, 417 | eventItem) == -1) { 418 | pthread_mutex_unlock(&surface->mutexLock); 419 | wlEglReleaseDisplay(display); 420 | return EGL_FALSE; 421 | } 422 | 423 | surface->present_update_callback(presentInfo, presentId, KICKED_OFF); 424 | surface->inFlightPresentFeedbackCount++; 425 | } else { 426 | // If the presentation feedback protocol is not supported by the compositor, 427 | // there is not much we can do to get this information. 428 | surface->present_update_callback(presentInfo, presentId, LANDED); 429 | surface->landedPresentFeedbackCount++; 430 | } 431 | } 432 | 433 | if (surface->ctx.useDamageThread) { 434 | surface->ctx.framesProduced++; 435 | } else { 436 | wlEglCreateFrameSync(surface); 437 | res = wlEglSendDamageEvent(surface, surface->wlEventQueue, NULL, 0); 438 | } 439 | 440 | // Release wlEglSurface lock. 441 | pthread_mutex_unlock(&surface->mutexLock); 442 | wlEglReleaseDisplay(display); 443 | 444 | return res; 445 | } 446 | 447 | EGLint wlEglStreamSwapIntervalCallback(WlEglPlatformData *data, 448 | EGLStreamKHR stream, 449 | EGLint *interval) 450 | { 451 | EGLint res = EGL_SUCCESS; 452 | 453 | if (data->callbacks.streamSwapInterval) { 454 | res = data->callbacks.streamSwapInterval(stream, interval); 455 | } 456 | 457 | return res; 458 | } 459 | -------------------------------------------------------------------------------- /src/wayland-eglutils.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2016, NVIDIA CORPORATION. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | #ifndef _GNU_SOURCE 24 | #define _GNU_SOURCE 25 | #endif 26 | 27 | #include "wayland-eglutils.h" 28 | #include "wayland-thread.h" 29 | #include "wayland-eglhandle.h" 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | 38 | EGLBoolean wlEglFindExtension(const char *extension, const char *extensions) 39 | { 40 | const char *start; 41 | const char *where, *terminator; 42 | 43 | start = extensions; 44 | for (;;) { 45 | where = strstr(start, extension); 46 | if (!where) { 47 | break; 48 | } 49 | terminator = where + strlen(extension); 50 | if (where == start || *(where - 1) == ' ') { 51 | if (*terminator == ' ' || *terminator == '\0') { 52 | return EGL_TRUE; 53 | } 54 | } 55 | start = terminator; 56 | } 57 | 58 | return EGL_FALSE; 59 | } 60 | 61 | EGLBoolean wlEglMemoryIsReadable(const void *p, size_t len) 62 | { 63 | int fds[2], result = -1; 64 | if (pipe(fds) == -1) { 65 | return EGL_FALSE; 66 | } 67 | 68 | if (fcntl(fds[1], F_SETFL, O_NONBLOCK) == -1) { 69 | goto done; 70 | } 71 | 72 | /* write will fail with EFAULT if the provided buffer is outside 73 | * our accessible address space. */ 74 | result = write(fds[1], p, len); 75 | assert(result != -1 || errno == EFAULT); 76 | 77 | done: 78 | close(fds[0]); 79 | close(fds[1]); 80 | return result != -1; 81 | } 82 | 83 | EGLBoolean wlEglCheckInterfaceType(struct wl_object *obj, const char *ifname) 84 | { 85 | /* The first member of a wl_object is a pointer to its wl_interface, */ 86 | struct wl_interface *interface = *(void **)obj; 87 | 88 | /* Check if the memory for the wl_interface struct, and the 89 | * interface name, are safe to read. */ 90 | int len = strlen(ifname); 91 | if (!wlEglMemoryIsReadable(interface, sizeof (*interface)) || 92 | !wlEglMemoryIsReadable(interface->name, len + 1)) { 93 | return EGL_FALSE; 94 | } 95 | 96 | 97 | return !strcmp(interface->name, ifname); 98 | } 99 | 100 | void wlEglSetErrorCallback(WlEglPlatformData *data, 101 | EGLint error, 102 | const char *file, 103 | int line) 104 | { 105 | if (data && data->callbacks.setError) { 106 | const char *defaultMsg = "Wayland external platform error"; 107 | 108 | if (file != NULL) { 109 | char msg[256]; 110 | if (snprintf(msg, 256, "%s:%d: %s", file, line, defaultMsg) > 0) { 111 | data->callbacks.setError(error, EGL_DEBUG_MSG_ERROR_KHR, msg); 112 | return; 113 | } 114 | } 115 | data->callbacks.setError(error, EGL_DEBUG_MSG_ERROR_KHR, defaultMsg); 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /src/wayland-external-exports.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | #include 24 | #include "wayland-external-exports.h" 25 | #include "wayland-egldisplay.h" 26 | #include "wayland-eglstream.h" 27 | #include "wayland-eglsurface-internal.h" 28 | #include "wayland-eglswap.h" 29 | #include "wayland-eglutils.h" 30 | #include "wayland-eglhandle.h" 31 | #include 32 | #include 33 | 34 | typedef struct WlEglHookRec { 35 | const char *name; 36 | void *func; 37 | } WlEglHook; 38 | 39 | static const WlEglHook wlEglHooksMap[] = { 40 | /* Keep names in ascending order */ 41 | { "eglBindWaylandDisplayWL", wlEglBindDisplaysHook }, 42 | { "eglChooseConfig", wlEglChooseConfigHook }, 43 | { "eglCreatePbufferSurface", wlEglCreatePbufferSurfaceHook }, 44 | { "eglCreatePlatformPixmapSurface", wlEglCreatePlatformPixmapSurfaceHook }, 45 | { "eglCreatePlatformWindowSurface", wlEglCreatePlatformWindowSurfaceHook }, 46 | { "eglCreateStreamAttribNV", wlEglCreateStreamAttribHook }, 47 | { "eglCreateStreamProducerSurfaceKHR", wlEglCreateStreamProducerSurfaceHook }, 48 | { "eglDestroySurface", wlEglDestroySurfaceHook }, 49 | { "eglGetConfigAttrib", wlEglGetConfigAttribHook }, 50 | { "eglInitialize", wlEglInitializeHook }, 51 | { "eglQueryDisplayAttribEXT", wlEglQueryDisplayAttribHook }, 52 | { "eglQueryDisplayAttribKHR", wlEglQueryDisplayAttribHook }, 53 | { "eglQueryString", wlEglQueryStringHook }, 54 | { "eglQuerySurface", wlEglQuerySurfaceHook }, 55 | { "eglQueryWaylandBufferWL", wlEglQueryNativeResourceHook }, 56 | { "eglSwapBuffers", wlEglSwapBuffersHook }, 57 | { "eglSwapBuffersWithDamageKHR", wlEglSwapBuffersWithDamageHook }, 58 | { "eglSwapInterval", wlEglSwapIntervalHook }, 59 | { "eglTerminate", wlEglTerminateHook }, 60 | { "eglUnbindWaylandDisplayWL", wlEglUnbindDisplaysHook }, 61 | }; 62 | 63 | static int hookCmp(const void *elemA, const void *elemB) 64 | { 65 | const char *key = (const char *)elemA; 66 | const WlEglHook *hook = (const WlEglHook *)elemB; 67 | return strcmp(key, hook->name); 68 | } 69 | 70 | static void* wlEglGetHookAddressExport(void *data, const char *name) 71 | { 72 | WlEglHook *hook; 73 | (void) data; 74 | 75 | hook = (WlEglHook *)bsearch((const void *)name, 76 | (const void *)wlEglHooksMap, 77 | sizeof(wlEglHooksMap)/sizeof(WlEglHook), 78 | sizeof(WlEglHook), 79 | hookCmp); 80 | if (hook) { 81 | return hook->func; 82 | } 83 | return NULL; 84 | } 85 | 86 | static EGLBoolean wlEglUnloadPlatformExport(void *data) { 87 | EGLBoolean res; 88 | 89 | res = wlEglDestroyAllDisplays((WlEglPlatformData *)data); 90 | wlEglDestroyPlatformData((WlEglPlatformData *)data); 91 | 92 | return res; 93 | } 94 | 95 | EGLBoolean loadEGLExternalPlatform(int major, int minor, 96 | const EGLExtDriver *driver, 97 | EGLExtPlatform *platform) 98 | { 99 | if (!platform || 100 | !EGL_EXTERNAL_PLATFORM_VERSION_CMP(major, minor, 101 | WAYLAND_EXTERNAL_VERSION_MAJOR, WAYLAND_EXTERNAL_VERSION_MINOR)) { 102 | return EGL_FALSE; 103 | } 104 | 105 | platform->version.major = WAYLAND_EXTERNAL_VERSION_MAJOR; 106 | platform->version.minor = WAYLAND_EXTERNAL_VERSION_MINOR; 107 | platform->version.micro = WAYLAND_EXTERNAL_VERSION_MICRO; 108 | 109 | platform->platform = EGL_PLATFORM_WAYLAND_EXT; 110 | 111 | platform->data = (void *)wlEglCreatePlatformData(major, minor, driver); 112 | if (platform->data == NULL) { 113 | return EGL_FALSE; 114 | } 115 | 116 | platform->exports.unloadEGLExternalPlatform = wlEglUnloadPlatformExport; 117 | 118 | platform->exports.getHookAddress = wlEglGetHookAddressExport; 119 | platform->exports.isValidNativeDisplay = wlEglIsValidNativeDisplayExport; 120 | platform->exports.getPlatformDisplay = wlEglGetPlatformDisplayExport; 121 | platform->exports.queryString = wlEglQueryStringExport; 122 | platform->exports.getInternalHandle = wlEglGetInternalHandleExport; 123 | 124 | return EGL_TRUE; 125 | } 126 | -------------------------------------------------------------------------------- /src/wayland-thread.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016-2019, NVIDIA CORPORATION. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | /* To include PTHREAD_MUTEX_ERRORCHECK */ 24 | #ifndef _GNU_SOURCE 25 | #define _GNU_SOURCE 26 | #endif 27 | 28 | #include "wayland-thread.h" 29 | #include "wayland-egldisplay.h" 30 | #include 31 | #include 32 | 33 | #if defined(__QNX__) 34 | #define WL_EGL_ATTRIBUTE_DESTRUCTOR 35 | #define WL_EGL_ATEXIT(func) atexit(func) 36 | #else 37 | #define WL_EGL_ATTRIBUTE_DESTRUCTOR __attribute__((destructor)) 38 | #define WL_EGL_ATEXIT(func) 0 39 | #endif 40 | 41 | static pthread_mutex_t wlMutex; 42 | static pthread_once_t wlMutexOnceControl = PTHREAD_ONCE_INIT; 43 | static int wlMutexInitialized = 0; 44 | 45 | static void wlExternalApiInitializeLock(void) 46 | { 47 | pthread_mutexattr_t attr; 48 | 49 | if (pthread_mutexattr_init(&attr)) { 50 | assert(!"failed to initialize pthread attribute mutex"); 51 | return; 52 | } 53 | 54 | if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK)) { 55 | assert(!"failed to set pthread attribute mutex errorcheck"); 56 | goto fail; 57 | } 58 | 59 | if (pthread_mutex_init(&wlMutex, &attr)) { 60 | assert(!"failed to initialize pthread mutex"); 61 | goto fail; 62 | } 63 | 64 | wlMutexInitialized = 1; 65 | 66 | fail: 67 | if (pthread_mutexattr_destroy(&attr)) { 68 | assert(!"failed to destroy pthread attribute mutex"); 69 | } 70 | } 71 | 72 | void wlExternalApiDestroyLock(void) 73 | { 74 | if (!wlMutexInitialized || pthread_mutex_destroy(&wlMutex)) { 75 | assert(!"failed to destroy pthread mutex"); 76 | } 77 | } 78 | 79 | int wlExternalApiLock(void) 80 | { 81 | if (pthread_once(&wlMutexOnceControl, wlExternalApiInitializeLock)) { 82 | assert(!"pthread once failed"); 83 | return -1; 84 | } 85 | 86 | if (!wlMutexInitialized || pthread_mutex_lock(&wlMutex)) { 87 | assert(!"failed to lock pthread mutex"); 88 | return -1; 89 | } 90 | 91 | return 0; 92 | } 93 | 94 | int wlExternalApiUnlock(void) 95 | { 96 | if (!wlMutexInitialized || pthread_mutex_unlock(&wlMutex)) { 97 | assert(!"failed to unlock pthread mutex"); 98 | return -1; 99 | } 100 | 101 | return 0; 102 | } 103 | 104 | bool wlEglInitializeMutex(pthread_mutex_t *mutex) 105 | { 106 | pthread_mutexattr_t attr; 107 | bool ret = true; 108 | 109 | if (pthread_mutexattr_init(&attr)) { 110 | return false; 111 | } 112 | 113 | if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK)) { 114 | ret = false; 115 | goto done; 116 | } 117 | 118 | if (pthread_mutex_init(mutex, &attr)) { 119 | ret = false; 120 | goto done; 121 | } 122 | 123 | done: 124 | pthread_mutexattr_destroy(&attr); 125 | return ret; 126 | } 127 | 128 | void wlEglMutexDestroy(pthread_mutex_t *mutex) 129 | { 130 | pthread_mutex_destroy(mutex); 131 | } 132 | -------------------------------------------------------------------------------- /wayland-drm/meson.build: -------------------------------------------------------------------------------- 1 | foreach output_type: ['client-header', 'server-header', 'public-code'] 2 | if output_type == 'client-header' 3 | output_file = 'wayland-drm-client-protocol.h' 4 | elif output_type == 'server-header' 5 | output_file = 'wayland-drm-server-protocol.h' 6 | else 7 | output_file = 'wayland-drm-protocol.c' 8 | 9 | if wl_scanner.version().version_compare('< 1.14.91') 10 | output_type = 'code' 11 | elif generated_public_protocols.contains(proto) 12 | output_type = 'public-code' 13 | endif 14 | endif 15 | 16 | var_name = output_file.underscorify() 17 | target = custom_target( 18 | '@0@'.format(output_file), 19 | command: [prog_scanner, output_type, '@INPUT@', '@OUTPUT@'], 20 | input: 'wayland-drm.xml', 21 | output: output_file, 22 | ) 23 | 24 | set_variable(var_name, target) 25 | endforeach 26 | 27 | install_data( 28 | 'wayland-drm.xml', 29 | install_dir : join_paths(get_option('datadir'), meson.project_name()) 30 | ) 31 | -------------------------------------------------------------------------------- /wayland-drm/wayland-drm.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Copyright © 2008-2011 Kristian Høgsberg 6 | Copyright © 2010-2011 Intel Corporation 7 | 8 | Permission to use, copy, modify, distribute, and sell this 9 | software and its documentation for any purpose is hereby granted 10 | without fee, provided that\n the above copyright notice appear in 11 | all copies and that both that copyright notice and this permission 12 | notice appear in supporting documentation, and that the name of 13 | the copyright holders not be used in advertising or publicity 14 | pertaining to distribution of the software without specific, 15 | written prior permission. The copyright holders make no 16 | representations about the suitability of this software for any 17 | purpose. It is provided "as is" without express or implied 18 | warranty. 19 | 20 | THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS 21 | SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND 22 | FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY 23 | SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 24 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 25 | AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 26 | ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF 27 | THIS SOFTWARE. 28 | 29 | 30 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 111 | 112 | 113 | 114 | 115 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | Bitmask of capabilities. 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | -------------------------------------------------------------------------------- /wayland-egl/wayland-egl-ext.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | #ifndef WAYLAND_EGL_EXT_H 24 | #define WAYLAND_EGL_EXT_H 25 | 26 | #ifndef EGL_WL_bind_wayland_display 27 | #define EGL_WL_bind_wayland_display 1 28 | #define PFNEGLBINDWAYLANDDISPLAYWL PFNEGLBINDWAYLANDDISPLAYWLPROC 29 | #define PFNEGLUNBINDWAYLANDDISPLAYWL PFNEGLUNBINDWAYLANDDISPLAYWLPROC 30 | #define PFNEGLQUERYWAYLANDBUFFERWL PFNEGLQUERYWAYLANDBUFFERWLPROC 31 | struct wl_display; 32 | struct wl_resource; 33 | #define EGL_WAYLAND_BUFFER_WL 0x31D5 34 | #define EGL_WAYLAND_PLANE_WL 0x31D6 35 | #define EGL_TEXTURE_Y_U_V_WL 0x31D7 36 | #define EGL_TEXTURE_Y_UV_WL 0x31D8 37 | #define EGL_TEXTURE_Y_XUXV_WL 0x31D9 38 | #define EGL_TEXTURE_EXTERNAL_WL 0x31DA 39 | #define EGL_WAYLAND_Y_INVERTED_WL 0x31DB 40 | typedef EGLBoolean (EGLAPIENTRYP PFNEGLBINDWAYLANDDISPLAYWLPROC) (EGLDisplay dpy, struct wl_display *display); 41 | typedef EGLBoolean (EGLAPIENTRYP PFNEGLUNBINDWAYLANDDISPLAYWLPROC) (EGLDisplay dpy, struct wl_display *display); 42 | typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYWAYLANDBUFFERWLPROC) (EGLDisplay dpy, struct wl_resource *buffer, EGLint attribute, EGLint *value); 43 | #ifdef EGL_EGLEXT_PROTOTYPES 44 | EGLAPI EGLBoolean EGLAPIENTRY eglBindWaylandDisplayWL (EGLDisplay dpy, struct wl_display *display); 45 | EGLAPI EGLBoolean EGLAPIENTRY eglUnbindWaylandDisplayWL (EGLDisplay dpy, struct wl_display *display); 46 | EGLAPI EGLBoolean EGLAPIENTRY eglQueryWaylandBufferWL (EGLDisplay dpy, struct wl_resource *buffer, EGLint attribute, EGLint *value); 47 | #endif 48 | #endif /* EGL_WL_bind_wayland_display */ 49 | 50 | #ifndef EGL_WL_wayland_eglstream 51 | #define EGL_WL_wayland_eglstream 1 52 | #define EGL_WAYLAND_EGLSTREAM_WL 0x334B 53 | #endif /* EGL_WL_wayland_eglstream */ 54 | 55 | #ifndef EGL_NV_stream_fifo_synchronous 56 | #define EGL_NV_stream_fifo_synchronous 1 57 | #define EGL_STREAM_FIFO_SYNCHRONOUS_NV 0x3336 58 | #endif /* EGL_NV_stream_fifo_synchronous */ 59 | 60 | #ifndef EGL_NV_stream_flush 61 | #define EGL_NV_stream_flush 1 62 | typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMFLUSHNVPROC) (EGLDisplay dpy, EGLStreamKHR stream); 63 | #ifdef EGL_EGLEXT_PROTOTYPES 64 | EGLAPI EGLBoolean EGLAPIENTRY eglStreamFlushNV (EGLDisplay dpy, EGLStreamKHR stream); 65 | #endif 66 | #endif /*EGL_NV_stream_flush*/ 67 | 68 | /* Deprecated. Use EGL_KHR_stream_attrib */ 69 | #ifndef EGL_NV_stream_attrib 70 | #define EGL_NV_stream_attrib 1 71 | #ifdef EGL_EGLEXT_PROTOTYPES 72 | EGLAPI EGLStreamKHR EGLAPIENTRY eglCreateStreamAttribNV(EGLDisplay dpy, const EGLAttrib *attrib_list); 73 | #endif 74 | typedef EGLStreamKHR (EGLAPIENTRYP PFNEGLCREATESTREAMATTRIBNVPROC) (EGLDisplay dpy, const EGLAttrib *attrib_list); 75 | #endif /* EGL_NV_stream_attrib */ 76 | 77 | #ifndef EGL_KHR_display_reference 78 | #define EGL_KHR_display_reference 1 79 | #define EGL_TRACK_REFERENCES_KHR 0x3352 80 | typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDISPLAYATTRIBKHRPROC) (EGLDisplay dpy, EGLint name, EGLAttrib *value); 81 | #ifdef EGL_EGLEXT_PROTOTYPES 82 | EGLAPI EGLBoolean EGLAPIENTRY eglQueryDisplayAttribKHR (EGLDisplay dpy, EGLint name, EGLAttrib *value); 83 | #endif 84 | #endif /* EGL_KHR_display_reference */ 85 | 86 | #ifndef EGL_NV_stream_origin 87 | #define EGL_NV_stream_origin 1 88 | #define EGL_STREAM_FRAME_ORIGIN_X_NV 0x3366 89 | #define EGL_STREAM_FRAME_ORIGIN_Y_NV 0x3367 90 | #define EGL_STREAM_FRAME_MAJOR_AXIS_NV 0x3368 91 | #define EGL_CONSUMER_AUTO_ORIENTATION_NV 0x3369 92 | #define EGL_PRODUCER_AUTO_ORIENTATION_NV 0x336A 93 | #define EGL_LEFT_NV 0x336B 94 | #define EGL_RIGHT_NV 0x336C 95 | #define EGL_TOP_NV 0x336D 96 | #define EGL_BOTTOM_NV 0x336E 97 | #define EGL_X_AXIS_NV 0x336F 98 | #define EGL_Y_AXIS_NV 0x3370 99 | #endif /* EGL_NV_stream_origin */ 100 | 101 | #endif 102 | -------------------------------------------------------------------------------- /wayland-eglstream-protocols.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@prefix@ 2 | datarootdir=@datarootdir@ 3 | pkgdatadir=@datadir@/@PACKAGE@ 4 | 5 | Name: wayland-eglstream-protocols 6 | Description: Nvidia Wayland EGLStream XML protocol files 7 | Version: @WAYLAND_EXTERNAL_VERSION@ 8 | -------------------------------------------------------------------------------- /wayland-eglstream.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@prefix@ 2 | exec_prefix=@exec_prefix@ 3 | libdir=@libdir@ 4 | includedir=@includedir@ 5 | 6 | Name: wayland-eglstream 7 | Description: Nvidia Wayland EGLStream compositor helper libraries 8 | Version: @WAYLAND_EXTERNAL_VERSION@ 9 | Cflags: -I${includedir} 10 | Libs: -L${libdir} -lnvidia-egl-wayland 11 | Requires: eglexternalplatform >= @EGL_EXTERNAL_PLATFORM_MIN_VERSION@ eglexternalplatform < @EGL_EXTERNAL_PLATFORM_MAX_VERSION@ 12 | -------------------------------------------------------------------------------- /wayland-eglstream/.gitignore: -------------------------------------------------------------------------------- 1 | # All source files in this directory are autogenerated, ignore them 2 | *.c 3 | *.h 4 | -------------------------------------------------------------------------------- /wayland-eglstream/meson.build: -------------------------------------------------------------------------------- 1 | generated_private_protocols = [ 2 | 'wayland-eglstream', 3 | ] 4 | 5 | generated_public_protocols = [ 6 | 'wayland-eglstream-controller', 7 | ] 8 | 9 | foreach proto : generated_private_protocols + generated_public_protocols 10 | foreach output_type: ['client-header', 'server-header', 'private-code'] 11 | if output_type == 'client-header' 12 | output_file = '@0@-client-protocol.h'.format(proto) 13 | elif output_type == 'server-header' 14 | output_file = '@0@-server-protocol.h'.format(proto) 15 | else 16 | output_file = '@0@-protocol.c'.format(proto) 17 | if wl_scanner.version().version_compare('< 1.14.91') 18 | output_type = 'code' 19 | elif generated_public_protocols.contains(proto) 20 | output_type = 'public-code' 21 | endif 22 | endif 23 | 24 | var_name = output_file.underscorify() 25 | target = custom_target( 26 | '@0@'.format(output_file), 27 | command: [prog_scanner, output_type, '@INPUT@', '@OUTPUT@'], 28 | input: '@0@.xml'.format(proto), 29 | output: output_file, 30 | ) 31 | 32 | set_variable(var_name, target) 33 | endforeach 34 | endforeach 35 | 36 | install_data( 37 | 'wayland-eglstream.xml', 38 | 'wayland-eglstream-controller.xml', 39 | install_dir : join_paths(get_option('datadir'), meson.project_name()) 40 | ) 41 | -------------------------------------------------------------------------------- /wayland-eglstream/wayland-eglstream-controller.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Copyright (c) 2017-2018, NVIDIA CORPORATION. All rights reserved. 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a 7 | copy of this software and associated documentation files (the "Software"), 8 | to deal in the Software without restriction, including without limitation 9 | the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 | and/or sell copies of the Software, and to permit persons to whom the 11 | Software is furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22 | DEALINGS IN THE SOFTWARE. 23 | 24 | 25 | 27 | 28 | 29 | - dont_care: Using this enum will tell the server to make its own 30 | decisions regarding present mode. 31 | 32 | - fifo: Tells the server to use a fifo present mode. The decision to 33 | use fifo synchronous is left up to the server. 34 | 35 | - mailbox: Tells the server to use a mailbox present mode. 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | - present_mode: Must be one of wl_eglstream_controller_present_mode. Tells the 45 | server the desired present mode that should be used. 46 | 47 | - fifo_length: Only valid when the present_mode attrib is provided and its 48 | value is specified as fifo. Tells the server the desired fifo 49 | length to be used when the desired present_mode is fifo. 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | Creates the corresponding server side EGLStream from the given wl_buffer 58 | and attaches a consumer to it. 59 | 60 | 63 | 65 | 66 | 67 | 68 | 69 | Creates the corresponding server side EGLStream from the given wl_buffer 70 | and attaches a consumer to it using the given attributes. 71 | 72 | 75 | 77 | 79 | 80 | It contains key-value pairs compatible with intptr_t type. A key must 81 | be one of wl_eglstream_controller_attrib enumeration values. What a value 82 | represents is attribute-specific. 83 | 84 | 85 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /wayland-eglstream/wayland-eglstream.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Copyright (c) 2014-2019, NVIDIA CORPORATION. All rights reserved. 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a 8 | copy of this software and associated documentation files (the "Software"), 9 | to deal in the Software without restriction, including without limitation 10 | the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 | and/or sell copies of the Software, and to permit persons to whom the 12 | Software is furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in 15 | all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | DEALINGS IN THE SOFTWARE. 24 | 25 | 26 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 40 | 41 | 42 | - fd: The given handle represents a file descriptor, and the 43 | EGLStream connection must be done as described in 44 | EGL_KHR_stream_cross_process_fd 45 | 46 | - inet: The EGLStream connection must be done using an inet address 47 | and port as described in EGL_NV_stream_socket. The given 48 | handle can be ignored, but both inet address and port must 49 | be given as attributes. 50 | 51 | - socket: The given handle represents a unix socket, and the EGLStream 52 | connection must be done as described in EGL_NV_stream_socket. 53 | 54 | 55 | 56 | 57 | 58 | 59 | 61 | 62 | 63 | - inet_addr: The given attribute encodes an IPv4 address of a client 64 | socket. Both IPv4 address and port must be set at the same 65 | time. 66 | 67 | - inet_port: The given attribute encodes a port of a client socket. 68 | Both IPv4 address and port must be set at the same time. 69 | 70 | - y_inverted: The given attribute encodes the default value for a 71 | stream's image inversion relative to wayland protocol 72 | convention. Vulkan apps will be set to 'true', while 73 | OpenGL apps will be set to 'false'. 74 | NOTE: EGL_NV_stream_origin is the authorative source of 75 | truth regarding a stream's frame orientation and should be 76 | queried for an accurate value. The given attribute is a 77 | 'best guess' fallback mechanism which should only be used 78 | when a query to EGL_NV_stream_origin fails. 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 89 | 90 | 93 | 94 | 95 | This enum values should be used as bit masks. 96 | 97 | - stream_fd: The server supports EGLStream connections as described 98 | in EGL_KHR_stream_cross_process_fd 99 | 100 | - stream_inet: The server supports EGLStream inet connections as 101 | described in EGL_NV_stream_socket. 102 | 103 | - stream_socket: The server supports EGLStream unix socket connections 104 | as described in EGL_NV_stream_socket. 105 | 106 | 107 | 108 | 109 | 110 | 111 | 114 | 115 | 116 | The capabilities event is sent out at wl_eglstream_display binding 117 | time. It allows the server to advertise what features it supports so 118 | clients may know what is safe to be used. 119 | 120 | 121 | 122 | 123 | 124 | 125 | The swapinterval_override event is sent out whenever a client requests 126 | a swapinterval setting through swap_interval() and there is an override 127 | in place that will make such request to be ignored. 128 | The swapinterval_override event will provide the override value so 129 | that the client is made aware of it. 130 | 131 | 133 | 135 | 136 | 137 | 141 | 142 | 143 | Create a wl_buffer corresponding to given handle. The attributes list 144 | may be used to define additional EGLStream connection data (e.g inet 145 | address/port). The server can create its EGLStream handle using the 146 | information encoded in the wl_buffer. 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | It contains key-value pairs compatible with intptr_t type. A key must 156 | be one of wl_eglstream_display_attrib enumeration values. What a value 157 | represents is attribute-specific. 158 | 159 | 160 | 161 | 162 | 163 | 164 | Set the swap interval for the consumer of the given EGLStream. The swap 165 | interval is silently clamped to the valid range on the server side. 166 | 167 | 169 | 170 | 171 | 172 | 173 | --------------------------------------------------------------------------------