diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index f8d5869aa..f208bd119 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -92,9 +92,6 @@ stages: .xorg_paths: &xorg_paths - hw/xfree86/**/* -.xwayland_paths: &xwayland_paths - - hw/xwayland/**/* - .all_ddx_paths: - hw/**/* @@ -178,12 +175,11 @@ meson: PIGLIT_DIR: /root/piglit LP_NUM_THREADS: 0 MESON_DDX_BUILD_ARGS: > - -Dxwayland=${BUILD_XWAYLAND} -Dxorg=${BUILD_XORG} -Dxephyr=${BUILD_XEPHYR} -Dxvfb=${BUILD_XVFB} -Dxnest=${BUILD_XNEST} + -Dxorg=${BUILD_XORG} -Dxephyr=${BUILD_XEPHYR} -Dxvfb=${BUILD_XVFB} -Dxnest=${BUILD_XNEST} BUILD_XEPHYR: true BUILD_XNEST: true BUILD_XORG: true BUILD_XVFB: true - BUILD_XWAYLAND: true MESON_EXTRA_ARGS: ${MESON_DDX_BUILD_ARGS} meson-noglamor: @@ -191,15 +187,6 @@ meson-noglamor: variables: MESON_EXTRA_ARGS: -Dglamor=false ${MESON_DDX_BUILD_ARGS} -xwayland-nolibdecor: - extends: meson - variables: - BUILD_XEPHYR: false - BUILD_XNEST: false - BUILD_XORG: false - BUILD_XVFB: false - MESON_EXTRA_ARGS: -Dlibdecor=false ${MESON_DDX_BUILD_ARGS} - mingw-cross-build: extends: .common-build-and-test script: @@ -374,7 +361,7 @@ xf86-driver-build-test: variables: GIT_DEPTH: 1 MESON_ARGS: -Dprefix=/usr/ - MESON_EXTRA_ARGS: -Dxwayland=false -Dxnest=false -Dxvfb=false -Dxquartz=false -Ddocs=false + MESON_EXTRA_ARGS: -Dxnest=false -Dxvfb=false -Dxquartz=false -Ddocs=false # # Verify that the merge request has the allow-collaboration checkbox ticked diff --git a/.gitlab-ci/check-ddx-build.sh b/.gitlab-ci/check-ddx-build.sh index df6f0c029..3b3a65f38 100755 --- a/.gitlab-ci/check-ddx-build.sh +++ b/.gitlab-ci/check-ddx-build.sh @@ -20,6 +20,5 @@ fi [[ "$BUILD_XNEST" == true ]] && check_executable "hw/xnest/Xnest" [[ "$BUILD_XORG" == true ]] && check_executable "hw/xfree86/Xorg" [[ "$BUILD_XVFB" == true ]] && check_executable "hw/vfb/Xvfb" -[[ "$BUILD_XWAYLAND" == true ]] && check_executable "hw/xwayland/Xwayland" exit 0 diff --git a/.gitlab-ci/check-piglit-results.sh b/.gitlab-ci/check-piglit-results.sh index 182579ed2..e8294b0ce 100755 --- a/.gitlab-ci/check-piglit-results.sh +++ b/.gitlab-ci/check-piglit-results.sh @@ -27,4 +27,3 @@ check_piglit_results () check_piglit_results xephyr-glamor hw/kdrive/ephyr/Xephyr.p/ephyr_glamor.c.o check_piglit_results xvfb hw/vfb/Xvfb -check_piglit_results xwayland hw/xwayland/Xwayland diff --git a/.gitlab-ci/debian-install.sh b/.gitlab-ci/debian-install.sh index 39cac8603..ff4f62eb2 100644 --- a/.gitlab-ci/debian-install.sh +++ b/.gitlab-ci/debian-install.sh @@ -49,7 +49,6 @@ apt-get install -y \ libglx-mesa0 \ libinput10 \ libinput-dev \ - libnvidia-egl-wayland-dev \ libpango1.0-0 \ libpango1.0-dev \ libpciaccess-dev \ @@ -60,7 +59,6 @@ apt-get install -y \ libtool \ libudev-dev \ libunwind-dev \ - libwayland-dev \ libx11-dev \ libx11-xcb-dev \ libxau-dev \ @@ -131,7 +129,7 @@ apt-get install -y \ cd /root -# Xwayland requires drm 2.4.116 for drmSyncobjEventfd +# drm 2.4.116 for drmSyncobjEventfd git clone https://gitlab.freedesktop.org/mesa/drm --depth 1 --branch=libdrm-2.4.121 cd drm meson _build @@ -147,7 +145,7 @@ ninja -C _build -j${FDO_CI_CONCURRENT:-4} install cd .. rm -rf libxcvt -# xserver requires xorgproto >= 2024.1 for XWAYLAND +# xserver requires xorgproto >= 2024.1 git clone https://gitlab.freedesktop.org/xorg/proto/xorgproto.git --depth 1 --branch=xorgproto-2024.1 pushd xorgproto ./autogen.sh @@ -155,38 +153,6 @@ make -j${FDO_CI_CONCURRENT:-4} install popd rm -rf xorgproto -# wayland-protocols requires wayland-scanner 1.20, but Debian bullseye has 1.18 only -git clone https://gitlab.freedesktop.org/wayland/wayland.git --depth 1 --branch=1.21.0 -cd wayland -meson -Dtests=false -Ddocumentation=false -Ddtd_validation=false _build -ninja -C _build -j${FDO_CI_CONCURRENT:-4} install -cd .. -rm -rf wayland - -# Xwayland requires wayland-protocols >= 1.38, but Debian bullseye has 1.20 only -git clone https://gitlab.freedesktop.org/wayland/wayland-protocols.git --depth 1 --branch=1.38 -cd wayland-protocols -meson _build -ninja -C _build -j${FDO_CI_CONCURRENT:-4} install -cd .. -rm -rf wayland-protocols - -# Install libdecor for Xwayland -git clone https://gitlab.freedesktop.org/libdecor/libdecor.git --depth 1 --branch=0.1.1 -cd libdecor -meson _build -D{demo,install_demo}=false -ninja -C _build -j${FDO_CI_CONCURRENT:-4} install -cd .. -rm -rf libdecor - -# Install libei for Xwayland -git clone https://gitlab.freedesktop.org/libinput/libei.git --depth 1 --branch=1.0.0 -cd libei -meson setup _build -Dtests=disabled -Ddocumentation=[] -Dliboeffis=enabled -ninja -C _build -j${FDO_CI_CONCURRENT:-4} install -cd .. -rm -rf libei - git clone https://gitlab.freedesktop.org/mesa/piglit.git cd piglit git checkout 265896c86f90cb72e8f218ba6a3617fca8b9a1e3 diff --git a/dix/extension.c b/dix/extension.c index 52bf19e64..3f5ed0cdf 100644 --- a/dix/extension.c +++ b/dix/extension.c @@ -106,7 +106,6 @@ static struct { const char *name; int id; } reservedExt[] = { { "XTEST", EXTENSION_MAJOR_XTEST }, { "XVideo", EXTENSION_MAJOR_XVIDEO }, { "XVideo-MotionCompensation", EXTENSION_MAJOR_XVMC }, - { "XWAYLAND", EXTENSION_MAJOR_XWAYLAND }, }; static int checkReserved(const char* name) diff --git a/dix/extension_priv.h b/dix/extension_priv.h index 71764ba0c..69396d2f0 100644 --- a/dix/extension_priv.h +++ b/dix/extension_priv.h @@ -43,7 +43,6 @@ #define EXTENSION_MAJOR_XTEST (EXTENSION_BASE + 33) #define EXTENSION_MAJOR_XVIDEO (EXTENSION_BASE + 34) #define EXTENSION_MAJOR_XVMC (EXTENSION_BASE + 35) -#define EXTENSION_MAJOR_XWAYLAND (EXTENSION_BASE + 36) #define RESERVED_EXTENSIONS 38 diff --git a/glamor/glamor_glx_provider.h b/glamor/glamor_glx_provider.h index b0db90e47..0d8737636 100644 --- a/glamor/glamor_glx_provider.h +++ b/glamor/glamor_glx_provider.h @@ -24,8 +24,8 @@ * Adam Jackson */ -#ifndef XWAYLAND_GLX_H -#define XWAYLAND_GLX_H +#ifndef GLAMOR_GLX_PROVIDER_H +#define GLAMOR_GLX_PROVIDER_H #include @@ -34,4 +34,4 @@ extern _X_EXPORT __GLXprovider glamor_provider; #endif -#endif /* XWAYLAND_GLX_H */ +#endif /* GLAMOR_GLX_PROVIDER_H */ diff --git a/hw/meson.build b/hw/meson.build index f9605a5b7..fb9e5d431 100644 --- a/hw/meson.build +++ b/hw/meson.build @@ -18,10 +18,6 @@ if build_xquartz subdir('xquartz') endif -if build_xwayland - subdir('xwayland') -endif - if build_xwin subdir('xwin') endif diff --git a/hw/xwayland/.gitignore b/hw/xwayland/.gitignore deleted file mode 100644 index 2fe460529..000000000 --- a/hw/xwayland/.gitignore +++ /dev/null @@ -1,17 +0,0 @@ -Xwayland -drm-client-protocol.h -drm-protocol.c -linux-dmabuf-unstable-v1-client-protocol.h -linux-dmabuf-unstable-v1-protocol.c -pointer-constraints-unstable-v1-client-protocol.h -pointer-constraints-unstable-v1-protocol.c -relative-pointer-unstable-v1-client-protocol.h -relative-pointer-unstable-v1-protocol.c -tablet-unstable-v2-client-protocol.h -tablet-unstable-v2-protocol.c -viewporter-client-protocol.h -viewporter-protocol.c -xdg-output-unstable-v1-client-protocol.h -xdg-output-unstable-v1-protocol.c -xwayland-keyboard-grab-unstable-v1-client-protocol.h -xwayland-keyboard-grab-unstable-v1-protocol.c diff --git a/hw/xwayland/desktop/org.freedesktop.Xwayland.desktop.in b/hw/xwayland/desktop/org.freedesktop.Xwayland.desktop.in deleted file mode 100644 index 106c8bc76..000000000 --- a/hw/xwayland/desktop/org.freedesktop.Xwayland.desktop.in +++ /dev/null @@ -1,8 +0,0 @@ -[Desktop Entry] -Name=Xwayland -Comment=A rootful instance of the Xwayland X11 server -Terminal=false -Type=Application -Categories=System; -Exec=@XWAYLAND@ @DECORATE@ -displayfd 1 -NoDisplay=true diff --git a/hw/xwayland/drm.xml b/hw/xwayland/drm.xml deleted file mode 100644 index 5e64622df..000000000 --- a/hw/xwayland/drm.xml +++ /dev/null @@ -1,185 +0,0 @@ - - - - - Copyright © 2008-2011 Kristian Høgsberg - Copyright © 2010-2011 Intel Corporation - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that\n the above copyright notice appear in - all copies and that both that copyright notice and this permission - notice appear in supporting documentation, and that the name of - the copyright holders not be used in advertising or publicity - pertaining to distribution of the software without specific, - written prior permission. The copyright holders make no - representations about the suitability of this software for any - purpose. It is provided "as is" without express or implied - warranty. - - THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS - SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY - SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, - ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF - THIS SOFTWARE. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Bitmask of capabilities. - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/hw/xwayland/man/Xwayland.man b/hw/xwayland/man/Xwayland.man deleted file mode 100644 index ea6d78eed..000000000 --- a/hw/xwayland/man/Xwayland.man +++ /dev/null @@ -1,183 +0,0 @@ -'\" t -.\" -.\" Copyright 1984 - 1991, 1993, 1994, 1998 The Open Group -.\" -.\" Permission to use, copy, modify, distribute, and sell this software and its -.\" documentation for any purpose is hereby granted without fee, provided that -.\" the above copyright notice appear in all copies and that both that -.\" copyright notice and this permission notice appear in supporting -.\" documentation. -.\" -.\" The above copyright notice and this permission notice shall be included -.\" in all copies or substantial portions of the Software. -.\" -.\" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -.\" OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -.\" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -.\" IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR -.\" OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -.\" ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -.\" OTHER DEALINGS IN THE SOFTWARE. -.\" -.\" Except as contained in this notice, the name of The Open Group shall -.\" not be used in advertising or otherwise to promote the sale, use or -.\" other dealings in this Software without prior written authorization -.\" from The Open Group. -.\" shorthand for double quote that works everywhere. -.ds q \N'34' -.TH XWAYLAND 1 @xorgversion@ -.SH NAME -Xwayland \- an X server for running X clients under Wayland. -.SH SYNOPSIS -.B Xwayland -[option ...] -.SH DESCRIPTION -.I Xwayland -is an X server and a Wayland client. It plays the role of a proxy between -legacy X clients which do not support the Wayland protocols and the Wayland -server. -.PP -Usually, \fIXwayland\fP is spawned automatically by the Wayland server -and runs rootless so that X clients integrate seamlessly with the rest -of the Wayland desktop. It is however possible for a user to launch Xwayland -non-rootless, mainly for testing purposes. -.PP -Like all of the X servers, \fIXwayland\fP accepts the command line options -described in the -.BR Xserver (@miscmansuffix@) -manual page. -The following additional arguments are supported as well. -.TP 8 -.B \-decorate -Add decorations to the Xwayland root window when running rootful. - -This option has no effect when \fIXwayland\fP is built without libdecor -support (optional). - -This option is not compatible with rootless mode (\fI-rootless\fP). -.TP 8 -.B \-enable-ei-portal -Enable support for the XDG portal for input emulation. - -A Wayland compositor running nested should not use that command line -option with Xwayland. - -This option has no effect if the compositor doesn't support the relevant -XDG portal or if Xwayland was not compiled with EI and OEFFIS support. -.TP 8 -.B \-fullscreen -Set the Xwayland window fullscreen when running rootful. - -This option is not compatible with rootless mode (\fI-rootless\fP). -.TP 8 -.B \-geometry \fIWxH\fP -Sets the geometry of the \fIXwayland\fP window to \fIWxH\fP when running rootful. - -This option is not compatible with rootless mode (\fI-rootless\fP). -.TP 8 -.B \-glamor " [\fIgl|es|off\fP]" -Use given rendering API for Glamor acceleration. Possible options are \fIgl\fP and \fIes\fP. -If \fIXwayland\fP was compiled with Glamor support, this option will instruct \fIXwayland\fP -to use only requested API for Glamor. If this set to \fIoff\fP, effect is equal to \fI-shm\fP option. -Without this option and without \fI-shm\fP option, \fIXwayland\fP tries the OpenGL rendering API first, -and fallback to GL ES if GL version is less than 2.1. - -This option is not compatible with \fI-shm\fP option. -.TP 8 -.B \-hidpi -Adjust to the scale of the outputs when running rootful in windowing mode. - -This option is not compatible with rootless mode (\fI-rootless\fP). -.TP 8 -.B \-host-grab -Disable host keyboard shorcuts and confine the pointer when running rootful. - -This feature relies on the protocol for inhibiting the compositor keyboard -shortcuts and on the protocol for pointer locking and confinement and may -have no effect if the Wayland compositor in use does not support these -protocols. - -Use the keys [CTRL]+[SHIFT] simultaneously to release the keyboard and -pointer devices. - -This option is not compatible with rootless mode (\fI-rootless\fP). -.TP 8 -.B \-initfd \fIfd\fP -Add the given \fIfd\fP as a listen socket for initialization of X clients. -This options is aimed at \fIWayland\fP servers which run \fIXwayland\fP -on-demand, to be able to spawn specific X clients which need to complete -before other regular X clients can connect to \fIXwayland\fP, like \fIxrdb\fP. -.TP 8 -.B \-listen \fIfd\fP -deprecated, use \fI\-listenfd\fP instead. -.TP 8 -.B \-listenfd \fIfd\\fP -Add given fd as a listen socket. This option is used by the \fIWayland\fP -server to pass \fIXwayland\fP the socket where X clients connect. -.TP 8 -.B \-noTouchPointerEmulation -Disable touch pointer emulation. This allows the Wayland compositor to -implement its own pointer emulation mechanism for X11 clients that don't -support touch input. -.TP 8 -.B \-force-xrandr-emulation -Force additional non-native modes to be exposed when viewporter is not -supported by the Wayland compositor. -.TP 8 -.B \-nokeymap -Instructs \fIXwayland\fP to ignore the keymap set by the Wayland compositor. - -By default, \fIXwayland\fP (as any Wayland client) uses the keymap set by the -Wayland compositor using the standard Wayland protocol. - -This option is meant for some specific use cases where it may be desirable to -let the X11 clients control the keymap used in Xwayland, ignoring the keymap -specified by the Wayland compositor. -.B \-output \fIname\fP -Specifies on which output \fIXwayland\fP fullscreen rootful should be placed. -The name must match the name of an existing Wayland output (output names can -be found using wayland-info). - -If no matching output can be found, the Wayland compositor will decide on which -output the fullscreen rootful \fIXwayland\fP window will be placed. - -This option has no effect if \fIXwayland\fP is not running fullscreen rootful. -.TP 8 -.B \-rootless -Run \fIXwayland\fP rootless, so that X clients integrate seamlessly with -Wayland clients in a Wayland desktop. That requires the Wayland server -to be an X window manager as well. -.TP 8 -.B \-shm -Force the shared memory backend instead of glamor (if available) for passing -buffers to the Wayland server. - -This option is not compatible with \fI-glamor\fP option. -.TP 8 -.BR \-verbose " [\fIn\fP]" -Sets the verbosity level for information printed on stderr. If the -.I n -value isn't supplied, each occurrence of this option increments the -verbosity level. When the -.I n -value is supplied, the verbosity level is set to that value. The default -verbosity level is 0. -.TP 8 -.B \-version -Show the server version and exit. -.TP 8 -.B \-wm \fIfd\fP -This option is used by the \fIWayland\fP server to pass \fIXwayland\fP -the socket where the X window manager client connects, when \fIXwayland\fP -is running with \fI-rootless\fP. -.SH ENVIRONMENT -.TP 8 -.B WAYLAND_DISPLAY -the name of the display of the Wayland server. -.TP 8 -.B XWAYLAND_NO_GLAMOR -disable glamor and DRI3 support in \fIXwayland\fP, for testing purposes. -.SH "SEE ALSO" -General information: -.BR X (@miscmansuffix@), -.BR wayland-info (@miscmansuffix@) diff --git a/hw/xwayland/meson.build b/hw/xwayland/meson.build deleted file mode 100644 index bee2eb324..000000000 --- a/hw/xwayland/meson.build +++ /dev/null @@ -1,220 +0,0 @@ -srcs = [ - 'xwayland.c', - 'xwayland-input.c', - 'xwayland-input.h', - 'xwayland-cursor.c', - 'xwayland-cursor.h', - 'xwayland-drm-lease.h', - 'xwayland-drm-lease.c', - 'xwayland-glamor.h', - 'xwayland-pixmap.c', - 'xwayland-pixmap.h', - 'xwayland-present.c', - 'xwayland-present.h', - 'xwayland-screen.c', - 'xwayland-screen.h', - 'xwayland-shm.c', - 'xwayland-shm.h', - 'xwayland-types.h', - 'xwayland-output.c', - 'xwayland-output.h', - 'xwayland-cvt.c', - 'xwayland-cvt.h', - 'xwayland-vidmode.c', - 'xwayland-vidmode.h', - 'xwayland-window.c', - 'xwayland-window.h', - 'xwayland-window-buffers.c', - 'xwayland-window-buffers.h', - '../../mi/miinitext.c', - '../../mi/miinitext.h', -] - -scanner_dep = dependency('wayland-scanner', native: true) -scanner = find_program(scanner_dep.get_variable(pkgconfig : 'wayland_scanner')) - -protocols_dep = dependency('wayland-protocols', version: wayland_protocols_req) -protodir = protocols_dep.get_variable(pkgconfig : 'pkgdatadir') - -pointer_xml = join_paths(protodir, 'unstable', 'pointer-constraints', 'pointer-constraints-unstable-v1.xml') -relative_xml = join_paths(protodir, 'unstable', 'relative-pointer', 'relative-pointer-unstable-v1.xml') -gestures_xml = join_paths(protodir, 'unstable', 'pointer-gestures', 'pointer-gestures-unstable-v1.xml') -tablet_xml = join_paths(protodir, 'unstable', 'tablet', 'tablet-unstable-v2.xml') -kbgrab_xml = join_paths(protodir, 'unstable', 'xwayland-keyboard-grab', 'xwayland-keyboard-grab-unstable-v1.xml') -xdg_output_xml = join_paths(protodir, 'unstable', 'xdg-output', 'xdg-output-unstable-v1.xml') -dmabuf_xml = join_paths(protodir, 'unstable', 'linux-dmabuf', 'linux-dmabuf-unstable-v1.xml') -viewporter_xml = join_paths(protodir, 'stable', 'viewporter', 'viewporter.xml') -xdg_shell_xml = join_paths(protodir, 'stable', 'xdg-shell', 'xdg-shell.xml') -drm_lease_xml = join_paths(protodir, 'staging', 'drm-lease', 'drm-lease-v1.xml') -shortcuts_inhibit_xml = join_paths(protodir, 'unstable', 'keyboard-shortcuts-inhibit', 'keyboard-shortcuts-inhibit-unstable-v1.xml') -xwayland_shell_xml = join_paths(protodir, 'staging', 'xwayland-shell', 'xwayland-shell-v1.xml') -tearing_xml = join_paths(protodir, 'staging', 'tearing-control', 'tearing-control-v1.xml') -fractional_scale_xml = join_paths(protodir, 'staging', 'fractional-scale', 'fractional-scale-v1.xml') -syncobj_xml = join_paths(protodir, 'staging', 'linux-drm-syncobj', 'linux-drm-syncobj-v1.xml') -system_bell_xml = join_paths(protodir, 'staging', 'xdg-system-bell', 'xdg-system-bell-v1.xml') - -proto_xml = [ - relative_xml, - pointer_xml, - gestures_xml, - tablet_xml, - kbgrab_xml, - xdg_output_xml, - dmabuf_xml, - viewporter_xml, - xdg_shell_xml, - drm_lease_xml, - shortcuts_inhibit_xml, - xwayland_shell_xml, - tearing_xml, - fractional_scale_xml, - syncobj_xml, - system_bell_xml, -] - -client_header = generator(scanner, - output : '@BASENAME@-client-protocol.h', - arguments : ['client-header', '@INPUT@', '@OUTPUT@'] -) - -if scanner_dep.version().version_compare('>= 1.14.91') - scanner_argument = 'private-code' -else - scanner_argument = 'code' -endif - -code = generator(scanner, - output : '@BASENAME@-protocol.c', - arguments : [scanner_argument, '@INPUT@', '@OUTPUT@'] -) - -foreach xml : proto_xml - srcs += client_header.process(xml) - srcs += code.process(xml) -endforeach - -if build_ei - xwayland_dep += libei_dep - srcs += [ 'xwayland-xtest.c', 'xwayland-xtest.h' ] - - if build_ei_portal - xwayland_dep += liboeffis_dep - endif -endif - -xwayland_glamor = [] -if build_xwayland_glamor - srcs += [ - 'xwayland-glamor.c', - 'xwayland-dmabuf.h', - 'xwayland-dmabuf.c', - 'xwayland-glamor-gbm.c', - 'xwayland-glamor-gbm.h' - ] - - if build_xv - srcs += 'xwayland-glamor-xv.c' - endif - - srcs += client_header.process('drm.xml') - srcs += code.process('drm.xml') - xwayland_dep += gbm_dep - xwayland_glamor += glamor -endif - -wayland_inc = [ inc, ] -if build_glx - wayland_inc += glx_inc -endif - -if libdrm_dep.found() - xwayland_dep += libdrm_dep -endif - -if have_libdecor - xwayland_dep += libdecor_dep -endif - -xwayland_server = executable( - 'Xwayland', - srcs, - include_directories: wayland_inc, - dependencies: [ - common_dep, - epoll_dep, - xwayland_dep, - xwaylandproto_dep, - ], - link_with: [ - libxserver_main, - xwayland_glamor, - libxserver_fb, - libxserver, - libxserver_xext_vidmode, - libxserver_xkb_stubs, - libxserver_xi_stubs, - libxserver_glx, - libglxvnd, - ], - install: true, - install_dir: xwayland_path -) - -xwayland_vars = [ - 'have_glamor=' + build_glamor.to_string(), - 'have_glamor_api=' + build_glamor.to_string(), - 'have_eglstream=false', - 'have_initfd=true', - 'have_listenfd=true', - 'have_verbose=true', - 'have_terminate_delay=true', - 'have_no_touch_pointer_emulation=true', - 'have_force_xrandr_emulation=true', - 'have_geometry=true', - 'have_fullscreen=true', - 'have_host_grab=true', - 'have_decorate=' + have_libdecor.to_string(), - 'have_enable_ei_portal=' + build_ei_portal.to_string(), - 'have_byteswappedclients=true', - 'have_hidpi=true', -] - -pkgconfig = import('pkgconfig') - -pkgconfig.generate( - filebase: 'xwayland', - name: 'Xwayland', - description: 'X Server for Wayland', - dataonly: true, - variables: [ - 'exec_prefix=${prefix}', - 'xwayland=' + xwayland_path / xwayland_server.name(), - ] + xwayland_vars, - url: 'https://gitlab.freedesktop.org/xorg/xserver/', -) - -xwayland_manpage = configure_file( - input: 'man/Xwayland.man', - output: 'Xwayland.1', - configuration: manpage_config, -) -install_man(xwayland_manpage) - -desktop_data = configuration_data() -desktop_data.set('XWAYLAND', xwayland_path / xwayland_server.name()) -desktop_data.set('DECORATE', have_libdecor ? '-decorate' : '') -desktop_file = configure_file( - input: 'desktop/org.freedesktop.Xwayland.desktop.in', - output: 'org.freedesktop.Xwayland.desktop', - configuration: desktop_data, -) -datadir = join_paths(get_option('prefix'), get_option('datadir')) -desktopdir = join_paths(datadir, 'applications') -install_data(desktop_file, install_dir : desktopdir) - -meson.override_find_program('Xwayland', xwayland_server) -meson.override_dependency('xwayland', declare_dependency( - variables: [ - 'xwayland=' + xwayland_server.full_path(), - ] + xwayland_vars, -)) diff --git a/hw/xwayland/xwayland-cursor.c b/hw/xwayland/xwayland-cursor.c deleted file mode 100644 index be78f97e3..000000000 --- a/hw/xwayland/xwayland-cursor.c +++ /dev/null @@ -1,440 +0,0 @@ -/* - * Copyright © 2014 Intel Corporation - * Copyright © 2011 Kristian Høgsberg - * - * Permission to use, copy, modify, distribute, and sell this software - * and its documentation for any purpose is hereby granted without - * fee, provided that the above copyright notice appear in all copies - * and that both that copyright notice and this permission notice - * appear in supporting documentation, and that the name of the - * copyright holders not be used in advertising or publicity - * pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied - * warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS - * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. - */ - -#include - -#include "mi/mipointer_priv.h" - -#include "scrnintstr.h" -#include "servermd.h" -#include "cursorstr.h" -#include "inputstr.h" -#include "mipointer.h" - -#include "xwayland-cursor.h" -#include "xwayland-input.h" -#include "xwayland-pixmap.h" -#include "xwayland-screen.h" -#include "xwayland-shm.h" -#include "xwayland-types.h" - -#include "tablet-unstable-v2-client-protocol.h" - -#define DELAYED_X_CURSOR_TIMEOUT 5 /* ms */ - -static void -expand_source_and_mask(CursorPtr cursor, CARD32 *data) -{ - CARD32 *p, d, fg, bg; - CursorBitsPtr bits = cursor->bits; - int x, y, stride, i, bit; - - p = data; - fg = ((cursor->foreRed & 0xff00) << 8) | - (cursor->foreGreen & 0xff00) | - (cursor->foreBlue >> 8); - bg = ((cursor->backRed & 0xff00) << 8) | - (cursor->backGreen & 0xff00) | - (cursor->backBlue >> 8); - stride = BitmapBytePad(bits->width); - for (y = 0; y < bits->height; y++) - for (x = 0; x < bits->width; x++) { - i = y * stride + x / 8; - bit = 1 << (x & 7); - if (bits->source[i] & bit) - d = fg; - else - d = bg; - if (bits->mask[i] & bit) - d |= 0xff000000; - else - d = 0x00000000; - - *p++ = d; - } -} - -static Bool -xwl_realize_cursor(DeviceIntPtr device, ScreenPtr screen, CursorPtr cursor) -{ - return TRUE; -} - -static Bool -xwl_unrealize_cursor(DeviceIntPtr device, ScreenPtr screen, CursorPtr cursor) -{ - struct xwl_screen *xwl_screen; - struct xwl_seat *xwl_seat; - - /* When called from FreeCursor(), device is always NULL */ - xwl_screen = xwl_screen_get(screen); - xorg_list_for_each_entry(xwl_seat, &xwl_screen->seat_list, link) { - if (cursor == xwl_seat->x_cursor) - xwl_seat->x_cursor = NULL; - } - - return TRUE; -} - -static void -frame_callback(void *data, - struct wl_callback *callback, - uint32_t time) -{ - struct xwl_cursor *xwl_cursor = data; - - xwl_cursor_clear_frame_cb(xwl_cursor); - if (xwl_cursor->needs_update) { - xwl_cursor->needs_update = FALSE; - xwl_cursor->update_proc(xwl_cursor); - } -} - -static const struct wl_callback_listener frame_listener = { - frame_callback -}; - -static void -xwl_cursor_buffer_release_callback(void *data) -{ - /* drop the reference we took in set_cursor */ - xwl_shm_destroy_pixmap(data); -} - -static void -xwl_cursor_copy_bits_to_pixmap(CursorPtr cursor, PixmapPtr pixmap) -{ - int stride; - - stride = cursor->bits->width * 4; - if (cursor->bits->argb) - memcpy(pixmap->devPrivate.ptr, - cursor->bits->argb, cursor->bits->height * stride); - else - expand_source_and_mask(cursor, pixmap->devPrivate.ptr); -} - -static void -xwl_cursor_attach_pixmap(struct xwl_seat *xwl_seat, - struct xwl_cursor *xwl_cursor, PixmapPtr pixmap) -{ - struct wl_buffer *buffer; - struct xwl_screen *xwl_screen = xwl_seat->xwl_screen; - - buffer = xwl_shm_pixmap_get_wl_buffer(pixmap); - if (!buffer) { - ErrorF("cursor: Error getting buffer\n"); - return; - } - - wl_surface_attach(xwl_cursor->surface, buffer, 0, 0); - wl_surface_set_buffer_scale(xwl_cursor->surface, xwl_screen->global_surface_scale); - xwl_surface_damage(xwl_screen, xwl_cursor->surface, 0, 0, - xwl_seat->x_cursor->bits->width, - xwl_seat->x_cursor->bits->height); - - xwl_cursor->frame_cb = wl_surface_frame(xwl_cursor->surface); - wl_callback_add_listener(xwl_cursor->frame_cb, &frame_listener, xwl_cursor); - - /* The pixmap will be destroyed in xwl_cursor_buffer_release_callback() - * once the compositor is done with it. - */ - xwl_pixmap_set_buffer_release_cb(pixmap, - xwl_cursor_buffer_release_callback, - pixmap); - - wl_surface_commit(xwl_cursor->surface); -} - -Bool -xwl_cursor_clear_frame_cb(struct xwl_cursor *xwl_cursor) -{ - if (xwl_cursor->frame_cb) { - wl_callback_destroy(xwl_cursor->frame_cb); - xwl_cursor->frame_cb = NULL; - return TRUE; - } - - return FALSE; -} - -void -xwl_seat_set_cursor(struct xwl_seat *xwl_seat) -{ - struct xwl_cursor *xwl_cursor = &xwl_seat->cursor; - struct xwl_screen *xwl_screen = xwl_seat->xwl_screen; - PixmapPtr pixmap; - CursorPtr cursor; - int xhot, yhot; - - if (!xwl_seat->wl_pointer) - return; - - if (!xwl_seat->x_cursor) { - wl_pointer_set_cursor(xwl_seat->wl_pointer, - xwl_seat->pointer_enter_serial, NULL, 0, 0); - xwl_cursor_clear_frame_cb(xwl_cursor); - xwl_cursor->needs_update = FALSE; - return; - } - - if (xwl_cursor->frame_cb) { - xwl_cursor->needs_update = TRUE; - return; - } - - cursor = xwl_seat->x_cursor; - pixmap = xwl_shm_create_pixmap(xwl_screen->screen, cursor->bits->width, - cursor->bits->height, 32, - CREATE_PIXMAP_USAGE_BACKING_PIXMAP); - if (!pixmap) - return; - - xwl_cursor_copy_bits_to_pixmap(cursor, pixmap); - - xhot = xwl_seat->x_cursor->bits->xhot / xwl_screen->global_surface_scale; - yhot = xwl_seat->x_cursor->bits->yhot / xwl_screen->global_surface_scale; - - wl_pointer_set_cursor(xwl_seat->wl_pointer, - xwl_seat->pointer_enter_serial, - xwl_cursor->surface, - xhot, - yhot); - - xwl_cursor_attach_pixmap(xwl_seat, xwl_cursor, pixmap); -} - -void -xwl_tablet_tool_set_cursor(struct xwl_tablet_tool *xwl_tablet_tool) -{ - struct xwl_seat *xwl_seat = xwl_tablet_tool->seat; - struct xwl_screen *xwl_screen = xwl_seat->xwl_screen; - struct xwl_cursor *xwl_cursor = &xwl_tablet_tool->cursor; - PixmapPtr pixmap; - CursorPtr cursor; - int xhot, yhot; - - if (!xwl_seat->x_cursor) { - zwp_tablet_tool_v2_set_cursor(xwl_tablet_tool->tool, - xwl_tablet_tool->proximity_in_serial, - NULL, 0, 0); - xwl_cursor_clear_frame_cb(xwl_cursor); - xwl_cursor->needs_update = FALSE; - return; - } - - if (xwl_cursor->frame_cb) { - xwl_cursor->needs_update = TRUE; - return; - } - - cursor = xwl_seat->x_cursor; - pixmap = xwl_shm_create_pixmap(xwl_screen->screen, cursor->bits->width, - cursor->bits->height, 32, - CREATE_PIXMAP_USAGE_BACKING_PIXMAP); - if (!pixmap) - return; - - xwl_cursor_copy_bits_to_pixmap(cursor, pixmap); - - xhot = xwl_seat->x_cursor->bits->xhot / xwl_screen->global_surface_scale; - yhot = xwl_seat->x_cursor->bits->yhot / xwl_screen->global_surface_scale; - - zwp_tablet_tool_v2_set_cursor(xwl_tablet_tool->tool, - xwl_tablet_tool->proximity_in_serial, - xwl_cursor->surface, - xhot, - yhot); - - xwl_cursor_attach_pixmap(xwl_seat, xwl_cursor, pixmap); -} - -void -xwl_cursor_release(struct xwl_cursor *xwl_cursor) -{ - wl_surface_destroy(xwl_cursor->surface); - xwl_cursor_clear_frame_cb(xwl_cursor); -} - -static void -xwl_seat_update_all_cursors(struct xwl_seat *xwl_seat) -{ - struct xwl_tablet_tool *xwl_tablet_tool; - - xwl_seat_set_cursor(xwl_seat); - - xorg_list_for_each_entry(xwl_tablet_tool, &xwl_seat->tablet_tools, link) { - if (xwl_tablet_tool->proximity_in_serial != 0) - xwl_tablet_tool_set_cursor(xwl_tablet_tool); - } - - /* Clear delayed cursor if any */ - xwl_seat->pending_x_cursor = NULL; -} - -static void -xwl_seat_update_cursor_visibility(struct xwl_seat *xwl_seat) -{ - xwl_seat->x_cursor = xwl_seat->pending_x_cursor; - xwl_seat_cursor_visibility_changed(xwl_seat); - xwl_seat_update_all_cursors(xwl_seat); -} - -static void -xwl_set_cursor_free_timer(struct xwl_seat *xwl_seat) -{ - if (xwl_seat->x_cursor_timer) { - TimerFree(xwl_seat->x_cursor_timer); - xwl_seat->x_cursor_timer = NULL; - } -} - -static CARD32 -xwl_set_cursor_timer_callback(OsTimerPtr timer, CARD32 time, void *arg) -{ - struct xwl_seat *xwl_seat = arg; - - xwl_set_cursor_free_timer(xwl_seat); - xwl_seat_update_cursor_visibility(xwl_seat); - - /* Don't re-arm the timer */ - return 0; -} - -static void -xwl_set_cursor_delayed(struct xwl_seat *xwl_seat, CursorPtr cursor) -{ - xwl_seat->pending_x_cursor = cursor; - - if (xwl_seat->x_cursor_timer == NULL) { - xwl_seat->x_cursor_timer = TimerSet(xwl_seat->x_cursor_timer, - 0, DELAYED_X_CURSOR_TIMEOUT, - &xwl_set_cursor_timer_callback, - xwl_seat); - } -} - -static void -xwl_set_cursor(DeviceIntPtr device, - ScreenPtr screen, CursorPtr cursor, int x, int y) -{ - struct xwl_seat *xwl_seat; - Bool cursor_visibility_changed; - - xwl_seat = device->public.devicePrivate; - if (xwl_seat == NULL) - return; - - cursor_visibility_changed = !!xwl_seat->x_cursor ^ !!cursor; - - if (!cursor_visibility_changed) { - /* Cursor remains shown or hidden, apply the change immediately */ - xwl_set_cursor_free_timer(xwl_seat); - xwl_seat->x_cursor = cursor; - xwl_seat_update_all_cursors(xwl_seat); - return; - } - - xwl_seat->pending_x_cursor = cursor; - if (cursor) { - /* Cursor is being shown, delay the change until moved or timed out */ - xwl_set_cursor_delayed(xwl_seat, cursor); - } else { - /* Cursor is being hidden, apply the change immediately */ - xwl_seat_update_cursor_visibility(xwl_seat); - } -} - -static void -xwl_move_cursor(DeviceIntPtr device, ScreenPtr screen, int x, int y) -{ - struct xwl_seat *xwl_seat; - - xwl_seat = device->public.devicePrivate; - if (xwl_seat == NULL) - return; - - xwl_set_cursor_free_timer(xwl_seat); - - if (xwl_seat->pending_x_cursor) - xwl_seat_update_cursor_visibility(xwl_seat); -} - -static Bool -xwl_device_cursor_initialize(DeviceIntPtr device, ScreenPtr screen) -{ - return TRUE; -} - -static void -xwl_device_cursor_cleanup(DeviceIntPtr device, ScreenPtr screen) -{ - struct xwl_seat *xwl_seat; - - xwl_seat = device->public.devicePrivate; - if (xwl_seat) - xwl_set_cursor_free_timer(xwl_seat); -} - -static miPointerSpriteFuncRec xwl_pointer_sprite_funcs = { - xwl_realize_cursor, - xwl_unrealize_cursor, - xwl_set_cursor, - xwl_move_cursor, - xwl_device_cursor_initialize, - xwl_device_cursor_cleanup -}; - -static Bool -xwl_cursor_off_screen(ScreenPtr *ppScreen, int *x, int *y) -{ - return FALSE; -} - -static void -xwl_cross_screen(ScreenPtr pScreen, Bool entering) -{ -} - -static void -xwl_pointer_warp_cursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) -{ - miPointerWarpCursor(pDev, pScreen, x, y); -} - -static miPointerScreenFuncRec xwl_pointer_screen_funcs = { - xwl_cursor_off_screen, - xwl_cross_screen, - xwl_pointer_warp_cursor -}; - -Bool -xwl_screen_init_cursor(struct xwl_screen *xwl_screen) -{ - return miPointerInitialize(xwl_screen->screen, - &xwl_pointer_sprite_funcs, - &xwl_pointer_screen_funcs, TRUE); -} diff --git a/hw/xwayland/xwayland-cursor.h b/hw/xwayland/xwayland-cursor.h deleted file mode 100644 index 76b5b49b6..000000000 --- a/hw/xwayland/xwayland-cursor.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright © 2014 Intel Corporation - * Copyright © 2011 Kristian Høgsberg - * - * Permission to use, copy, modify, distribute, and sell this software - * and its documentation for any purpose is hereby granted without - * fee, provided that the above copyright notice appear in all copies - * and that both that copyright notice and this permission notice - * appear in supporting documentation, and that the name of the - * copyright holders not be used in advertising or publicity - * pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied - * warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS - * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. - */ - -#ifndef XWAYLAND_CURSOR_H -#define XWAYLAND_CURSOR_H - -#include -#include -#include - -Bool xwl_cursor_clear_frame_cb(struct xwl_cursor *xwl_cursor); -void xwl_cursor_release(struct xwl_cursor *xwl_cursor); -void xwl_tablet_tool_set_cursor(struct xwl_tablet_tool *tool); -void xwl_seat_set_cursor(struct xwl_seat *xwl_seat); -Bool xwl_screen_init_cursor(struct xwl_screen *xwl_screen); - -#endif /* XWAYLAND_CURSOR_H */ diff --git a/hw/xwayland/xwayland-cvt.c b/hw/xwayland/xwayland-cvt.c deleted file mode 100644 index 4248d3869..000000000 --- a/hw/xwayland/xwayland-cvt.c +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2005-2006 Luc Verhaegen. - * Copyright © 2021 Red Hat, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -#include - -#include -#include -#include - -#include "xwayland-cvt.h" - -static void -xwayland_modeinfo_from_cvt(xRRModeInfo *modeinfo, - int hdisplay, int vdisplay, float vrefresh, - Bool reduced, Bool interlaced) -{ - struct libxcvt_mode_info *libxcvt_mode_info; - - libxcvt_mode_info = - libxcvt_gen_mode_info(hdisplay, vdisplay, vrefresh, reduced, interlaced); - - modeinfo->width = libxcvt_mode_info->hdisplay; - modeinfo->height = libxcvt_mode_info->vdisplay; - modeinfo->dotClock = libxcvt_mode_info->dot_clock * 1000.0; - modeinfo->hSyncStart = libxcvt_mode_info->hsync_start; - modeinfo->hSyncEnd = libxcvt_mode_info->hsync_end; - modeinfo->hTotal = libxcvt_mode_info->htotal; - modeinfo->vSyncStart = libxcvt_mode_info->vsync_start; - modeinfo->vSyncEnd = libxcvt_mode_info->vsync_end; - modeinfo->vTotal = libxcvt_mode_info->vtotal; - modeinfo->modeFlags = libxcvt_mode_info->mode_flags; - - free(libxcvt_mode_info); -} - -RRModePtr -xwayland_cvt(int hdisplay, int vdisplay, float vrefresh, Bool reduced, - Bool interlaced) -{ - char name[128]; - xRRModeInfo modeinfo = { 0, }; - - xwayland_modeinfo_from_cvt(&modeinfo, - hdisplay, vdisplay, vrefresh, reduced, interlaced); - - /* Horizontal granularity in libxcvt is 8, so if our horizontal size is not - * divisible by 8, libxcvt will round it up, and we will advertise a wrong - * size to our XRandR clients. - * Force the width/height (i.e. simply increase blanking which should not - * hurt anything), keeping the rest of the CVT mode timings unchanged. - */ - modeinfo.width = hdisplay; - modeinfo.height = vdisplay; - - snprintf(name, sizeof name, "%dx%d", - modeinfo.width, modeinfo.height); - modeinfo.nameLength = strlen(name); - - return RRModeGet(&modeinfo, name); -} diff --git a/hw/xwayland/xwayland-cvt.h b/hw/xwayland/xwayland-cvt.h deleted file mode 100644 index 64ff41e35..000000000 --- a/hw/xwayland/xwayland-cvt.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2005-2006 Luc Verhaegen. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifndef XWAYLAND_CVT_H -#define XWAYLAND_CVT_H - -#include - -#include -#include - -RRModePtr xwayland_cvt(int HDisplay, int VDisplay, - float VRefresh, Bool Reduced, Bool Interlaced); - -#endif /* XWAYLAND_CVT_H */ diff --git a/hw/xwayland/xwayland-dmabuf.c b/hw/xwayland/xwayland-dmabuf.c deleted file mode 100644 index d0ecd995a..000000000 --- a/hw/xwayland/xwayland-dmabuf.c +++ /dev/null @@ -1,797 +0,0 @@ -/* - * Copyright © 2011-2014 Intel Corporation - * - * Permission to use, copy, modify, distribute, and sell this software - * and its documentation for any purpose is hereby granted without - * fee, provided that the above copyright notice appear in all copies - * and that both that copyright notice and this permission notice - * appear in supporting documentation, and that the name of the - * copyright holders not be used in advertising or publicity - * pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied - * warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS - * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. - */ - -#include - -#include - -#include -#include - -#include "os/log_priv.h" - -#include "xwayland-dmabuf.h" -#include "xwayland-glamor-gbm.h" -#include "xwayland-screen.h" -#include "xwayland-types.h" -#include "xwayland-window-buffers.h" - -#include "drm-client-protocol.h" -#include "linux-dmabuf-unstable-v1-client-protocol.h" - -void -xwl_device_formats_destroy(struct xwl_device_formats *dev_formats) -{ - for (int j = 0; j < dev_formats->num_formats; j++) - free(dev_formats->formats[j].modifiers); - free(dev_formats->formats); - drmFreeDevice(&dev_formats->drm_dev); -} - -void -xwl_dmabuf_feedback_clear_dev_formats(struct xwl_dmabuf_feedback *xwl_feedback) -{ - if (xwl_feedback->dev_formats_len == 0) - return; - - for (int i = 0; i < xwl_feedback->dev_formats_len; i++) { - struct xwl_device_formats *dev_format = &xwl_feedback->dev_formats[i]; - xwl_device_formats_destroy(dev_format); - } - free(xwl_feedback->dev_formats); - xwl_feedback->dev_formats = NULL; - xwl_feedback->dev_formats_len = 0; -} - -void -xwl_dmabuf_feedback_destroy(struct xwl_dmabuf_feedback *xwl_feedback) -{ - munmap(xwl_feedback->format_table.entry, - xwl_feedback->format_table.len * sizeof(struct xwl_format_table_entry)); - xwl_dmabuf_feedback_clear_dev_formats(xwl_feedback); - - if (xwl_feedback->dmabuf_feedback) - zwp_linux_dmabuf_feedback_v1_destroy(xwl_feedback->dmabuf_feedback); - - xwl_feedback->dmabuf_feedback = NULL; - drmFreeDevice(&xwl_feedback->main_dev); -} - -static Bool -xwl_glamor_is_modifier_supported_in_formats(struct xwl_format *formats, int num_formats, - uint32_t format, uint64_t modifier) -{ - struct xwl_format *xwl_format = NULL; - int i; - - for (i = 0; i < num_formats; i++) { - if (formats[i].format == format) { - xwl_format = &formats[i]; - break; - } - } - - if (xwl_format) { - for (i = 0; i < xwl_format->num_modifiers; i++) { - if (xwl_format->modifiers[i] == modifier) { - return TRUE; - } - } - } - - return FALSE; -} - -static Bool -xwl_feedback_is_modifier_supported(struct xwl_dmabuf_feedback *xwl_feedback, - uint32_t format, uint64_t modifier, - int supports_scanout) -{ - for (int i = 0; i < xwl_feedback->dev_formats_len; i++) { - struct xwl_device_formats *dev_formats = &xwl_feedback->dev_formats[i]; - - if (supports_scanout && !dev_formats->supports_scanout) - continue; - - if (xwl_glamor_is_modifier_supported_in_formats(dev_formats->formats, - dev_formats->num_formats, - format, modifier)) - return TRUE; - } - - return FALSE; -} - -Bool -xwl_glamor_is_modifier_supported(struct xwl_screen *xwl_screen, - uint32_t format, uint64_t modifier) -{ - struct xwl_window *xwl_window; - - /* - * If we are using dmabuf v4, then we need to check in the main - * device and per-window format lists. For older protocol - * versions we can just check the list returned by the dmabuf.modifier - * events in xwl_screen - */ - if (xwl_screen->dmabuf_protocol_version < 4) { - return xwl_glamor_is_modifier_supported_in_formats(xwl_screen->formats, - xwl_screen->num_formats, - format, modifier); - } - - if (xwl_feedback_is_modifier_supported(&xwl_screen->default_feedback, format, modifier, FALSE)) - return TRUE; - - xorg_list_for_each_entry(xwl_window, &xwl_screen->window_list, link_window) { - if (xwl_feedback_is_modifier_supported(&xwl_window->feedback, format, modifier, FALSE)) - return TRUE; - } - - return FALSE; -} - -uint32_t -wl_drm_format_for_depth(int depth) -{ - switch (depth) { - case 15: - return WL_DRM_FORMAT_XRGB1555; - case 16: - return WL_DRM_FORMAT_RGB565; - case 24: - return WL_DRM_FORMAT_XRGB8888; - case 30: - return WL_DRM_FORMAT_ARGB2101010; - default: - ErrorF("unexpected depth: %d\n", depth); - case 32: - return WL_DRM_FORMAT_ARGB8888; - } -} - -static Bool -xwl_dmabuf_get_formats(struct xwl_format *format_array, int format_array_len, - CARD32 *num_formats, CARD32 **formats) -{ - *num_formats = 0; - *formats = NULL; - - if (format_array_len == 0) - return TRUE; - - *formats = calloc(format_array_len, sizeof(CARD32)); - if (*formats == NULL) - return FALSE; - - for (int i = 0; i < format_array_len; i++) - (*formats)[i] = format_array[i].format; - *num_formats = format_array_len; - - return TRUE; -} - -static Bool -xwl_dmabuf_get_formats_for_device(struct xwl_dmabuf_feedback *xwl_feedback, drmDevice *device, - CARD32 *num_formats, CARD32 **formats) -{ - CARD32 *ret = NULL; - uint32_t count = 0; - - /* go through all matching sets of tranches for the window's device */ - for (int i = 0; i < xwl_feedback->dev_formats_len; i++) { - if (drmDevicesEqual(xwl_feedback->dev_formats[i].drm_dev, device)) { - struct xwl_device_formats *dev_formats = &xwl_feedback->dev_formats[i]; - - /* Append the formats from this tranche to the list */ - ret = XNFreallocarray(ret, count + dev_formats->num_formats, sizeof(CARD32)); - - for (int j = 0; j < dev_formats->num_formats; j++) { - Bool found = FALSE; - - /* Check if this format is already present in the list */ - for (int k = 0; k < count; k++) { - if (ret[k] == dev_formats->formats[j].format) { - found = TRUE; - break; - } - } - - /* If this format has not yet been added, do so now */ - if (!found) - ret[count++] = dev_formats->formats[j].format; - } - } - } - - *num_formats = count; - *formats = ret; - - return TRUE; -} - -Bool -xwl_glamor_get_formats(ScreenPtr screen, - CARD32 *num_formats, CARD32 **formats) -{ - struct xwl_screen *xwl_screen = xwl_screen_get(screen); - - /* Explicitly zero the count as the caller may ignore the return value */ - *num_formats = 0; - - if (!xwl_screen->dmabuf) - return FALSE; - - if (xwl_screen->dmabuf_protocol_version >= 4) { - drmDevice *main_dev = xwl_gbm_get_main_device(xwl_screen); - - return xwl_dmabuf_get_formats_for_device(&xwl_screen->default_feedback, main_dev, - num_formats, formats); - } - - return xwl_dmabuf_get_formats(xwl_screen->formats, xwl_screen->num_formats, - num_formats, formats); -} - -static Bool -xwl_dmabuf_get_modifiers_for_format(struct xwl_format *format_array, int num_formats, - uint32_t format, uint32_t *num_modifiers, - uint64_t **modifiers) -{ - struct xwl_format *xwl_format = NULL; - int i; - - *num_modifiers = 0; - *modifiers = NULL; - - if (num_formats == 0) - return TRUE; - - for (i = 0; i < num_formats; i++) { - if (format_array[i].format == format) { - xwl_format = &format_array[i]; - break; - } - } - - if (!xwl_format || - (xwl_format->num_modifiers == 1 && - xwl_format->modifiers[0] == DRM_FORMAT_MOD_INVALID)) - return FALSE; - - *modifiers = calloc(xwl_format->num_modifiers, sizeof(uint64_t)); - if (*modifiers == NULL) - return FALSE; - - for (i = 0; i < xwl_format->num_modifiers; i++) - (*modifiers)[i] = xwl_format->modifiers[i]; - *num_modifiers = xwl_format->num_modifiers; - - return TRUE; -} - -static Bool -xwl_dmabuf_get_modifiers_for_device(struct xwl_dmabuf_feedback *feedback, - drmDevice *device, - uint32_t format, uint32_t *num_modifiers, - uint64_t **modifiers, - Bool *supports_scanout) -{ - /* Now try to find a matching set of tranches for the window's device */ - for (int i = 0; i < feedback->dev_formats_len; i++) { - struct xwl_device_formats *dev_formats = &feedback->dev_formats[i]; - - if (drmDevicesEqual(dev_formats->drm_dev, device) && - xwl_dmabuf_get_modifiers_for_format(dev_formats->formats, - dev_formats->num_formats, - format, num_modifiers, modifiers)) { - if (supports_scanout) - *supports_scanout = !!dev_formats->supports_scanout; - return TRUE; - } - } - - return FALSE; -} - -Bool -xwl_glamor_get_modifiers(ScreenPtr screen, uint32_t format, - uint32_t *num_modifiers, uint64_t **modifiers) -{ - struct xwl_screen *xwl_screen = xwl_screen_get(screen); - drmDevice *main_dev; - - /* Explicitly zero the count as the caller may ignore the return value */ - *num_modifiers = 0; - *modifiers = NULL; - - if (!xwl_screen->dmabuf) - return FALSE; - - if (xwl_screen->dmabuf_protocol_version >= 4) { - main_dev = xwl_gbm_get_main_device(xwl_screen); - - return xwl_dmabuf_get_modifiers_for_device(&xwl_screen->default_feedback, main_dev, - format, num_modifiers, modifiers, NULL); - } else { - return xwl_dmabuf_get_modifiers_for_format(xwl_screen->formats, xwl_screen->num_formats, - format, num_modifiers, modifiers); - } -} - -Bool -xwl_glamor_get_drawable_modifiers_and_scanout(DrawablePtr drawable, - uint32_t format, - uint32_t *num_modifiers, - uint64_t **modifiers, - Bool *supports_scanout) -{ - struct xwl_screen *xwl_screen = xwl_screen_get(drawable->pScreen); - struct xwl_window *xwl_window; - drmDevice *main_dev; - - *num_modifiers = 0; - *modifiers = NULL; - if (supports_scanout) - *supports_scanout = FALSE; - - /* We can only return per-drawable modifiers if the compositor supports feedback */ - if (xwl_screen->dmabuf_protocol_version < 4) - return TRUE; - - if (drawable->type != DRAWABLE_WINDOW || !xwl_screen->dmabuf) - return FALSE; - - xwl_window = xwl_window_from_window((WindowPtr)drawable); - - /* couldn't find drawable for window */ - if (!xwl_window) - return FALSE; - - main_dev = xwl_gbm_get_main_device(xwl_screen); - - return xwl_dmabuf_get_modifiers_for_device(&xwl_window->feedback, main_dev, - format, num_modifiers, modifiers, - supports_scanout); - -} - -Bool -xwl_glamor_get_drawable_modifiers(DrawablePtr drawable, uint32_t format, - uint32_t *num_modifiers, uint64_t **modifiers) -{ - return xwl_glamor_get_drawable_modifiers_and_scanout(drawable, - format, num_modifiers, - modifiers, NULL); - -} - -static void -xwl_dmabuf_handle_format(void *data, struct zwp_linux_dmabuf_v1 *dmabuf, - uint32_t format) -{ -} - -static void -xwl_add_format_and_mod_to_list(struct xwl_format **formats, - uint32_t *num_formats, - uint32_t format, - uint64_t modifier) -{ - struct xwl_format *xwl_format = NULL; - int i; - - for (i = 0; i < *num_formats; i++) { - if ((*formats)[i].format == format) { - xwl_format = &(*formats)[i]; - break; - } - } - - if (xwl_format == NULL) { - (*num_formats)++; - *formats = XNFrealloc(*formats, *num_formats * sizeof(*xwl_format)); - xwl_format = &(*formats)[*num_formats - 1]; - xwl_format->format = format; - xwl_format->num_modifiers = 0; - xwl_format->modifiers = NULL; - } - - for (i = 0; i < xwl_format->num_modifiers; i++) { - /* don't add it if the modifier already exists */ - if (xwl_format->modifiers[i] == modifier) - return; - } - - xwl_format->num_modifiers++; - xwl_format->modifiers = XNFrealloc(xwl_format->modifiers, - xwl_format->num_modifiers * sizeof(uint64_t)); - xwl_format->modifiers[xwl_format->num_modifiers - 1] = modifier; -} - -static void -xwl_dmabuf_handle_modifier(void *data, struct zwp_linux_dmabuf_v1 *dmabuf, - uint32_t format, uint32_t modifier_hi, - uint32_t modifier_lo) -{ - struct xwl_screen *xwl_screen = data; - - xwl_add_format_and_mod_to_list(&xwl_screen->formats, &xwl_screen->num_formats, - format, - ((uint64_t)modifier_hi << 32 | (uint64_t)modifier_lo)); -} - -static const struct zwp_linux_dmabuf_v1_listener xwl_dmabuf_listener = { - .format = xwl_dmabuf_handle_format, - .modifier = xwl_dmabuf_handle_modifier -}; - -/* - * We need to check if the compositor is resending all of the tranche - * information. Each tranche event will call this method to see - * if the existing format info should be cleared before refilling. - */ -static void -xwl_check_reset_tranche_info(struct xwl_dmabuf_feedback *xwl_feedback) -{ - if (!xwl_feedback->feedback_done) - return; - - xwl_feedback->feedback_done = FALSE; - - xwl_dmabuf_feedback_clear_dev_formats(xwl_feedback); -} - -static void -xwl_dmabuf_feedback_main_device(void *data, - struct zwp_linux_dmabuf_feedback_v1 *dmabuf_feedback, - struct wl_array *dev) -{ - struct xwl_dmabuf_feedback *xwl_feedback = data; - dev_t devid; - - xwl_check_reset_tranche_info(xwl_feedback); - - assert(dev->size == sizeof(dev_t)); - memcpy(&devid, dev->data, sizeof(dev_t)); - - drmFreeDevice(&xwl_feedback->main_dev); - - if (drmGetDeviceFromDevId(devid, 0, &xwl_feedback->main_dev) != 0) - ErrorF("linux_dmabuf_feedback.main_device: Failed to fetch DRM device\n"); -} - -static void -xwl_dmabuf_feedback_tranche_target_device(void *data, - struct zwp_linux_dmabuf_feedback_v1 *dmabuf_feedback, - struct wl_array *dev) -{ - struct xwl_dmabuf_feedback *xwl_feedback = data; - dev_t devid; - - xwl_check_reset_tranche_info(xwl_feedback); - - assert(dev->size == sizeof(dev_t)); - memcpy(&devid, dev->data, sizeof(dev_t)); - - if (drmGetDeviceFromDevId(devid, 0, &xwl_feedback->tmp_tranche.drm_dev) != 0) - ErrorF("linux_dmabuf_feedback.tranche_target_device: Failed to fetch DRM device\n"); -} - -static void -xwl_dmabuf_feedback_tranche_flags(void *data, - struct zwp_linux_dmabuf_feedback_v1 *dmabuf_feedback, - uint32_t flags) -{ - struct xwl_dmabuf_feedback *xwl_feedback = data; - - xwl_check_reset_tranche_info(xwl_feedback); - - if (flags & ZWP_LINUX_DMABUF_FEEDBACK_V1_TRANCHE_FLAGS_SCANOUT) - xwl_feedback->tmp_tranche.supports_scanout = TRUE; -} - -static void -xwl_dmabuf_feedback_tranche_formats(void *data, - struct zwp_linux_dmabuf_feedback_v1 *dmabuf_feedback, - struct wl_array *indices) -{ - struct xwl_dmabuf_feedback *xwl_feedback = data; - struct xwl_device_formats *tranche = &xwl_feedback->tmp_tranche; - uint16_t *index; - - xwl_check_reset_tranche_info(xwl_feedback); - - wl_array_for_each(index, indices) { - if (*index >= xwl_feedback->format_table.len) { - ErrorF("linux_dmabuf_feedback.tranche_formats: Index given to us by the compositor" - " is too large to fit in the format table\n"); - continue; - } - - /* Look up this format/mod in the format table */ - struct xwl_format_table_entry *entry = &xwl_feedback->format_table.entry[*index]; - - /* Add it to the in-progress tranche */ - xwl_add_format_and_mod_to_list(&tranche->formats, &tranche->num_formats, - entry->format, - entry->modifier); - } -} - -static void -xwl_append_to_tranche(struct xwl_device_formats *dst, struct xwl_device_formats *src) -{ - struct xwl_format *format; - - for (int i = 0; i < src->num_formats; i++) { - format = &src->formats[i]; - - for (int j = 0; j < format->num_modifiers; j++) - xwl_add_format_and_mod_to_list(&dst->formats, &dst->num_formats, - format->format, - format->modifiers[j]); - } -} - -static void -xwl_dmabuf_feedback_tranche_done(void *data, - struct zwp_linux_dmabuf_feedback_v1 *dmabuf_feedback) -{ - struct xwl_dmabuf_feedback *xwl_feedback = data; - struct xwl_device_formats *tranche; - int appended = FALSE; - - /* - * No need to call xwl_check_reset_tranche_info, the other events should have been - * triggered first - */ - - if (xwl_feedback->tmp_tranche.drm_dev == NULL) { - xwl_device_formats_destroy(&xwl_feedback->tmp_tranche); - goto out; - } - - /* - * First check if there is an existing tranche for this device+flags combo. We - * will combine it with this tranche, since we can only send one modifier list - * in DRI3 but the compositor may report multiple tranches per device (KDE - * does this) - */ - for (int i = 0; i < xwl_feedback->dev_formats_len; i++) { - tranche = &xwl_feedback->dev_formats[i]; - if (tranche->supports_scanout == xwl_feedback->tmp_tranche.supports_scanout && - drmDevicesEqual(tranche->drm_dev, xwl_feedback->tmp_tranche.drm_dev)) { - appended = TRUE; - - /* Add all format/mods to this tranche */ - xwl_append_to_tranche(tranche, &xwl_feedback->tmp_tranche); - - /* Now free our temp tranche's allocations */ - xwl_device_formats_destroy(&xwl_feedback->tmp_tranche); - - break; - } - } - - if (!appended) { - xwl_feedback->dev_formats_len++; - xwl_feedback->dev_formats = XNFrealloc(xwl_feedback->dev_formats, - sizeof(struct xwl_device_formats) * - xwl_feedback->dev_formats_len); - - /* copy the temporary tranche into the official array */ - memcpy(&xwl_feedback->dev_formats[xwl_feedback->dev_formats_len - 1], - &xwl_feedback->tmp_tranche, - sizeof(struct xwl_device_formats)); - } - -out: - /* reset the tranche */ - memset(&xwl_feedback->tmp_tranche, 0, sizeof(struct xwl_device_formats)); -} - -static void -xwl_dmabuf_feedback_done(void *data, struct zwp_linux_dmabuf_feedback_v1 *dmabuf_feedback) -{ - struct xwl_dmabuf_feedback *xwl_feedback = data; - - xwl_feedback->feedback_done = TRUE; - xwl_feedback->unprocessed_feedback_pending = TRUE; -} - -static void -xwl_dmabuf_feedback_format_table(void *data, - struct zwp_linux_dmabuf_feedback_v1 *zwp_linux_dmabuf_feedback_v1, - int32_t fd, uint32_t size) -{ - struct xwl_dmabuf_feedback *xwl_feedback = data; - /* Unmap the old table */ - if (xwl_feedback->format_table.entry) { - munmap(xwl_feedback->format_table.entry, - xwl_feedback->format_table.len * sizeof(struct xwl_format_table_entry)); - } - - assert(size % sizeof(struct xwl_format_table_entry) == 0); - xwl_feedback->format_table.len = size / sizeof(struct xwl_format_table_entry); - xwl_feedback->format_table.entry = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0); - close(fd); - - if (xwl_feedback->format_table.entry == MAP_FAILED) { - ErrorF("linux_dmabuf_feedback.format_table: Could not map the format" - " table: Compositor bug or out of resources\n"); - xwl_feedback->format_table.len = 0; - } -} - -static const struct zwp_linux_dmabuf_feedback_v1_listener xwl_dmabuf_feedback_listener = { - .done = xwl_dmabuf_feedback_done, - .format_table = xwl_dmabuf_feedback_format_table, - .main_device = xwl_dmabuf_feedback_main_device, - .tranche_done = xwl_dmabuf_feedback_tranche_done, - .tranche_target_device = xwl_dmabuf_feedback_tranche_target_device, - .tranche_formats = xwl_dmabuf_feedback_tranche_formats, - .tranche_flags = xwl_dmabuf_feedback_tranche_flags, -}; - -Bool -xwl_screen_set_dmabuf_interface(struct xwl_screen *xwl_screen, - uint32_t id, uint32_t version) -{ - /* We either support versions 3 or 4. 4 is needed for dmabuf feedback */ - int supported_version = version >= 4 ? 4 : 3; - - if (version < 3) - return FALSE; - - xwl_screen->dmabuf = - wl_registry_bind(xwl_screen->registry, id, &zwp_linux_dmabuf_v1_interface, supported_version); - xwl_screen->dmabuf_protocol_version = supported_version; - zwp_linux_dmabuf_v1_add_listener(xwl_screen->dmabuf, &xwl_dmabuf_listener, xwl_screen); - - /* If the compositor supports it, request the default feedback hints */ - if (version >= 4) { - xwl_screen->default_feedback.dmabuf_feedback = - zwp_linux_dmabuf_v1_get_default_feedback(xwl_screen->dmabuf); - if (!xwl_screen->default_feedback.dmabuf_feedback) - return FALSE; - - zwp_linux_dmabuf_feedback_v1_add_listener(xwl_screen->default_feedback.dmabuf_feedback, - &xwl_dmabuf_feedback_listener, - &xwl_screen->default_feedback); - } - - return TRUE; -} - -static void -xwl_window_dmabuf_feedback_main_device(void *data, - struct zwp_linux_dmabuf_feedback_v1 *dmabuf_feedback, - struct wl_array *dev) -{ - struct xwl_window *xwl_window = data; - - xwl_dmabuf_feedback_main_device(&xwl_window->feedback, dmabuf_feedback, dev); -} - -static void -xwl_window_dmabuf_feedback_tranche_target_device(void *data, - struct zwp_linux_dmabuf_feedback_v1 *dmabuf_feedback, - struct wl_array *dev) -{ - struct xwl_window *xwl_window = data; - - xwl_dmabuf_feedback_tranche_target_device(&xwl_window->feedback, dmabuf_feedback, dev); -} - -static void -xwl_window_dmabuf_feedback_tranche_flags(void *data, - struct zwp_linux_dmabuf_feedback_v1 *dmabuf_feedback, - uint32_t flags) -{ - struct xwl_window *xwl_window = data; - - xwl_dmabuf_feedback_tranche_flags(&xwl_window->feedback, dmabuf_feedback, flags); -} - -static void -xwl_window_dmabuf_feedback_tranche_formats(void *data, - struct zwp_linux_dmabuf_feedback_v1 *dmabuf_feedback, - struct wl_array *indices) -{ - struct xwl_window *xwl_window = data; - - xwl_dmabuf_feedback_tranche_formats(&xwl_window->feedback, dmabuf_feedback, indices); -} - -static void -xwl_window_dmabuf_feedback_tranche_done(void *data, - struct zwp_linux_dmabuf_feedback_v1 *dmabuf_feedback) -{ - struct xwl_window *xwl_window = data; - - xwl_dmabuf_feedback_tranche_done(&xwl_window->feedback, dmabuf_feedback); -} - -static void -xwl_window_dmabuf_feedback_done(void *data, - struct zwp_linux_dmabuf_feedback_v1 *dmabuf_feedback) -{ - struct xwl_window *xwl_window = data; - uint32_t format = wl_drm_format_for_depth(xwl_window->surface_window->drawable.depth); - - xwl_dmabuf_feedback_done(&xwl_window->feedback, dmabuf_feedback); - - xwl_window->has_implicit_scanout_support = - xwl_feedback_is_modifier_supported(&xwl_window->feedback, format, - DRM_FORMAT_MOD_INVALID, TRUE); - DebugF("XWAYLAND: Window 0x%x can%s get implicit scanout support\n", - xwl_window->surface_window->drawable.id, - xwl_window->has_implicit_scanout_support ? "" : "not"); - - /* If the linux-dmabuf v4 per-surface feedback changed, make sure the - * window buffers get re-created with appropriate parameters. - */ - xwl_window_buffers_dispose(xwl_window, FALSE); - xwl_window_realloc_pixmap(xwl_window); -} - -static void -xwl_window_dmabuf_feedback_format_table(void *data, - struct zwp_linux_dmabuf_feedback_v1 *dmabuf_feedback, - int32_t fd, uint32_t size) -{ - struct xwl_window *xwl_window = data; - - xwl_dmabuf_feedback_format_table(&xwl_window->feedback, dmabuf_feedback, fd, size); -} - -static const struct zwp_linux_dmabuf_feedback_v1_listener xwl_window_dmabuf_feedback_listener = { - .done = xwl_window_dmabuf_feedback_done, - .format_table = xwl_window_dmabuf_feedback_format_table, - .main_device = xwl_window_dmabuf_feedback_main_device, - .tranche_done = xwl_window_dmabuf_feedback_tranche_done, - .tranche_target_device = xwl_window_dmabuf_feedback_tranche_target_device, - .tranche_formats = xwl_window_dmabuf_feedback_tranche_formats, - .tranche_flags = xwl_window_dmabuf_feedback_tranche_flags, -}; - -Bool -xwl_dmabuf_setup_feedback_for_window(struct xwl_window *xwl_window) -{ - struct xwl_screen *xwl_screen = xwl_window->xwl_screen; - - xwl_window->feedback.dmabuf_feedback = - zwp_linux_dmabuf_v1_get_surface_feedback(xwl_screen->dmabuf, xwl_window->surface); - - if (!xwl_window->feedback.dmabuf_feedback) - return FALSE; - - zwp_linux_dmabuf_feedback_v1_add_listener(xwl_window->feedback.dmabuf_feedback, - &xwl_window_dmabuf_feedback_listener, - xwl_window); - - return TRUE; -} diff --git a/hw/xwayland/xwayland-dmabuf.h b/hw/xwayland/xwayland-dmabuf.h deleted file mode 100644 index ca0dcd706..000000000 --- a/hw/xwayland/xwayland-dmabuf.h +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright © 2011-2014 Intel Corporation - * - * Permission to use, copy, modify, distribute, and sell this software - * and its documentation for any purpose is hereby granted without - * fee, provided that the above copyright notice appear in all copies - * and that both that copyright notice and this permission notice - * appear in supporting documentation, and that the name of the - * copyright holders not be used in advertising or publicity - * pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied - * warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS - * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. - */ - -#ifndef XWAYLAND_DMABUF_H -#define XWAYLAND_DMABUF_H - -#include - -#include -#include -#include - -#include -#include -#include -#include - -#include "xwayland-types.h" - -struct xwl_format { - uint32_t format; - int num_modifiers; - uint64_t *modifiers; -}; - -struct xwl_format_table_entry { - uint32_t format; - uint32_t pad; - uint64_t modifier; -}; - -struct xwl_device_formats { - drmDevice *drm_dev; - uint32_t num_formats; - struct xwl_format *formats; - Bool supports_scanout; -}; - -struct xwl_format_table { - /* This is mmapped from the fd given to us by the compositor */ - int len; - struct xwl_format_table_entry *entry; -}; - -/* - * Helper struct for sharing dmabuf feedback logic between - * a screen and a window. The screen will get the default - * feedback, and a window will get a per-surface feedback. - */ -struct xwl_dmabuf_feedback { - struct zwp_linux_dmabuf_feedback_v1 *dmabuf_feedback; - struct xwl_format_table format_table; - drmDevice *main_dev; - /* - * This will be filled in during wl events and copied to - * dev_formats on dmabuf_feedback.tranche_done - */ - struct xwl_device_formats tmp_tranche; - int feedback_done; - int dev_formats_len; - struct xwl_device_formats *dev_formats; - /* - * This flag is used to identify if the feedback - * has been resent. If this is true, then the xwayland - * clients need to be sent PresentCompleteModeSuboptimalCopy - * to tell them to re-request modifiers. - */ - int unprocessed_feedback_pending; -}; - -void xwl_dmabuf_feedback_destroy(struct xwl_dmabuf_feedback *xwl_feedback); -void xwl_dmabuf_feedback_clear_dev_formats(struct xwl_dmabuf_feedback *xwl_feedback); -void xwl_device_formats_destroy(struct xwl_device_formats *dev_formats); - -Bool xwl_dmabuf_setup_feedback_for_window(struct xwl_window *xwl_window); -Bool xwl_screen_set_dmabuf_interface(struct xwl_screen *xwl_screen, - uint32_t id, uint32_t version); -Bool xwl_glamor_is_modifier_supported(struct xwl_screen *xwl_screen, - uint32_t format, uint64_t modifier); -uint32_t wl_drm_format_for_depth(int depth); -Bool xwl_glamor_get_formats(ScreenPtr screen, - CARD32 *num_formats, CARD32 **formats); -Bool xwl_glamor_get_modifiers(ScreenPtr screen, uint32_t format, - uint32_t *num_modifiers, uint64_t **modifiers); -Bool xwl_glamor_get_drawable_modifiers_and_scanout(DrawablePtr drawable, - uint32_t format, - uint32_t *num_modifiers, - uint64_t **modifiers, - Bool *supports_scanout); -Bool xwl_glamor_get_drawable_modifiers(DrawablePtr drawable, uint32_t format, - uint32_t *num_modifiers, uint64_t **modifiers); - -#endif /* XWAYLAND_DMABUF_H */ diff --git a/hw/xwayland/xwayland-drm-lease.c b/hw/xwayland/xwayland-drm-lease.c deleted file mode 100644 index 6c0683a61..000000000 --- a/hw/xwayland/xwayland-drm-lease.c +++ /dev/null @@ -1,487 +0,0 @@ -/* - * Copyright © 2020 Drew Devault - * Copyright © 2021 Xaver Hugl - * - * Permission to use, copy, modify, distribute, and sell this software - * and its documentation for any purpose is hereby granted without - * fee, provided that the above copyright notice appear in all copies - * and that both that copyright notice and this permission notice - * appear in supporting documentation, and that the name of the - * copyright holders not be used in advertising or publicity - * pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied - * warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS - * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. - */ - -#include - -#include "os/client_priv.h" -#include "randr/randrstr_priv.h" - -#ifdef WITH_LIBDRM -#include -#include -#endif - -#include "xwayland-drm-lease.h" -#include "xwayland-screen.h" -#include "xwayland-output.h" - -static void -xwl_randr_lease_cleanup_outputs(RRLeasePtr rrLease) -{ - struct xwl_output *output; - int i; - - for (i = 0; i < rrLease->numOutputs; ++i) { - output = rrLease->outputs[i]->devPrivate; - if (output) { - output->lease = NULL; - } - } -} - -static void -xwl_randr_lease_free_outputs(RRLeasePtr rrLease) -{ - struct xwl_output *xwl_output; - int i; - - for (i = 0; i < rrLease->numOutputs; ++i) { - xwl_output = rrLease->outputs[i]->devPrivate; - if (xwl_output && xwl_output->withdrawn_connector) { - rrLease->outputs[i]->devPrivate = NULL; - xwl_output_remove(xwl_output); - } - } -} - -static void -drm_lease_handle_lease_fd(void *data, - struct wp_drm_lease_v1 *wp_drm_lease_v1, - int32_t lease_fd) -{ - struct xwl_drm_lease *lease = (struct xwl_drm_lease *)data; - - lease->fd = lease_fd; - AttendClient(lease->client); -} - -static void -drm_lease_handle_finished(void *data, - struct wp_drm_lease_v1 *wp_drm_lease_v1) -{ - struct xwl_drm_lease *lease = (struct xwl_drm_lease *)data; - - if (lease->fd >= 0) { - RRTerminateLease(lease->rrLease); - } else { - AttendClient(lease->client); - xwl_randr_lease_cleanup_outputs(lease->rrLease); - } - - /* Free the xwl_outputs that have been withdrawn while lease-able */ - xwl_randr_lease_free_outputs(lease->rrLease); -} - -static struct wp_drm_lease_v1_listener drm_lease_listener = { - .lease_fd = drm_lease_handle_lease_fd, - .finished = drm_lease_handle_finished, -}; - -void -xwl_randr_get_lease(ClientPtr client, ScreenPtr screen, RRLeasePtr *rrLease, int *fd) -{ - struct xwl_screen *xwl_screen; - struct xwl_drm_lease *lease; - xwl_screen = xwl_screen_get(screen); - - xorg_list_for_each_entry(lease, &xwl_screen->drm_leases, link) { - if (lease->client == client) { - *rrLease = lease->rrLease; - *fd = lease->fd; - if (lease->fd < 0) - xorg_list_del(&lease->link); - return; - } - } - *rrLease = NULL; - *fd = -1; -} - -int -xwl_randr_request_lease(ClientPtr client, ScreenPtr screen, RRLeasePtr rrLease) -{ - struct xwl_screen *xwl_screen; - struct wp_drm_lease_request_v1 *req; - struct xwl_drm_lease *lease_private; - struct xwl_drm_lease_device *lease_device = NULL; - struct xwl_drm_lease_device *device_data; - struct xwl_output *output; - int i; - - xwl_screen = xwl_screen_get(screen); - - if (xorg_list_is_empty(&xwl_screen->drm_lease_devices)) { - ErrorF("Attempted to create DRM lease without wp_drm_lease_device_v1\n"); - return BadMatch; - } - - for (i = 0; i < rrLease->numOutputs; ++i) { - output = rrLease->outputs[i]->devPrivate; - if (!output || !output->lease_connector || output->lease) { - return BadValue; - } - } - - xorg_list_for_each_entry(device_data, &xwl_screen->drm_lease_devices, link) { - Bool connectors_of_device = FALSE; - for (i = 0; i < rrLease->numOutputs; ++i) { - output = rrLease->outputs[i]->devPrivate; - if (output->lease_device == device_data) { - connectors_of_device = TRUE; - break; - } - } - if (connectors_of_device) { - if (lease_device != NULL) { - ErrorF("Attempted to create DRM lease from multiple devices\n"); - return BadValue; - } - lease_device = device_data; - } - } - - req = wp_drm_lease_device_v1_create_lease_request( - lease_device->drm_lease_device); - if (!(lease_private = calloc(1, sizeof(struct xwl_drm_lease)))) - return BadAlloc; - for (i = 0; i < rrLease->numOutputs; ++i) { - output = rrLease->outputs[i]->devPrivate; - output->lease = lease_private; - wp_drm_lease_request_v1_request_connector(req, output->lease_connector); - } - lease_private->fd = -1; - lease_private->lease = wp_drm_lease_request_v1_submit(req); - lease_private->rrLease = rrLease; - lease_private->client = client; - rrLease->devPrivate = lease_private; - - wp_drm_lease_v1_add_listener(lease_private->lease, - &drm_lease_listener, lease_private); - xorg_list_add(&lease_private->link, &xwl_screen->drm_leases); - - ResetCurrentRequest(client); - client->sequence--; - IgnoreClient(client); - - return Success; -} - -void -xwl_randr_terminate_lease(ScreenPtr screen, RRLeasePtr lease) -{ - struct xwl_drm_lease *lease_private = lease->devPrivate; - - if (lease_private) { - xwl_randr_lease_cleanup_outputs(lease); - xorg_list_del(&lease_private->link); - if (lease_private->fd >= 0) - close(lease_private->fd); - wp_drm_lease_v1_destroy(lease_private->lease); - free(lease_private); - lease->devPrivate = NULL; - } - - RRLeaseTerminated(lease); -} - -static void -lease_connector_handle_name(void *data, - struct wp_drm_lease_connector_v1 *wp_drm_lease_connector_v1, - const char *name) -{ - struct xwl_output *xwl_output = data; - char rr_output_name[MAX_OUTPUT_NAME] = { 0 }; - - snprintf(rr_output_name, MAX_OUTPUT_NAME, "lease-%s", name); - xwl_output_set_name(xwl_output, rr_output_name); -} - -static void -lease_connector_handle_description(void *data, - struct wp_drm_lease_connector_v1 *wp_drm_lease_connector_v1, - const char *description) -{ - /* This space is deliberately left blank */ -} - -static RRModePtr * -xwl_get_rrmodes_from_connector_id(int drm, int32_t connector_id, int *nmode, int *npref) -{ -#ifdef WITH_LIBDRM - drmModeConnectorPtr conn; - drmModeModeInfoPtr kmode; - RRModePtr *rrmodes; - int pref, i; - - *nmode = *npref = 0; - - conn = drmModeGetConnectorCurrent(drm, connector_id); - if (!conn) { - ErrorF("drmModeGetConnector for connector %d failed\n", connector_id); - return NULL; - } - rrmodes = calloc(conn->count_modes, sizeof(RRModePtr)); - if (!rrmodes) { - ErrorF("Failed to allocate connector modes\n"); - drmModeFreeConnector(conn); - return NULL; - } - - /* This spaghetti brought to you courtesey of xf86RandrR12.c - * It adds preferred modes first, then non-preferred modes */ - for (pref = 1; pref >= 0; pref--) { - for (i = 0; i < conn->count_modes; ++i) { - kmode = &conn->modes[i]; - if ((pref != 0) == ((kmode->type & DRM_MODE_TYPE_PREFERRED) != 0)) { - xRRModeInfo modeInfo; - RRModePtr rrmode; - - modeInfo.nameLength = strlen(kmode->name); - - modeInfo.width = kmode->hdisplay; - modeInfo.dotClock = kmode->clock * 1000; - modeInfo.hSyncStart = kmode->hsync_start; - modeInfo.hSyncEnd = kmode->hsync_end; - modeInfo.hTotal = kmode->htotal; - modeInfo.hSkew = kmode->hskew; - - modeInfo.height = kmode->vdisplay; - modeInfo.vSyncStart = kmode->vsync_start; - modeInfo.vSyncEnd = kmode->vsync_end; - modeInfo.vTotal = kmode->vtotal; - modeInfo.modeFlags = kmode->flags; - - rrmode = RRModeGet(&modeInfo, kmode->name); - if (rrmode) { - rrmodes[*nmode] = rrmode; - *nmode = *nmode + 1; - *npref = *npref + pref; - } - } - } - } - /* workaround: there could be no preferred mode that got added */ - if (*nmode > 0 && *npref == 0) - *npref = 1; - - drmModeFreeConnector(conn); - return rrmodes; -#else - *nmode = *npref = 0; - return NULL; -#endif -} - -static void -lease_connector_handle_connector_id(void *data, - struct wp_drm_lease_connector_v1 *wp_drm_lease_connector_v1, - uint32_t connector_id) -{ - struct xwl_output *output; - Atom name; - INT32 value; - int err; - int nmode, npref; - RRModePtr *rrmodes; - - value = connector_id; - output = (struct xwl_output *)data; - name = MakeAtom("CONNECTOR_ID", 12, TRUE); - - if (name != BAD_RESOURCE) { - err = RRConfigureOutputProperty(output->randr_output, name, - FALSE, FALSE, TRUE, - 1, &value); - if (err != 0) { - ErrorF("RRConfigureOutputProperty error, %d\n", err); - return; - } - err = RRChangeOutputProperty(output->randr_output, name, - XA_INTEGER, 32, PropModeReplace, 1, - &value, FALSE, FALSE); - if (err != 0) { - ErrorF("RRChangeOutputProperty error, %d\n", err); - return; - } - } - rrmodes = xwl_get_rrmodes_from_connector_id(output->lease_device->drm_read_only_fd, - connector_id, &nmode, &npref); - - if (rrmodes != NULL) - RROutputSetModes(output->randr_output, rrmodes, nmode, npref); - - free(rrmodes); -} - -static void -lease_connector_handle_done(void *data, - struct wp_drm_lease_connector_v1 *wp_drm_lease_connector_v1) -{ - /* This space is deliberately left blank */ -} - -static void -lease_connector_handle_withdrawn(void *data, - struct wp_drm_lease_connector_v1 *wp_drm_lease_connector_v1) -{ - struct xwl_output *xwl_output = data; - - xwl_output->withdrawn_connector = TRUE; - - /* Not removing the xwl_output if currently leased with Wayland */ - if (xwl_output->lease) - return; - - xwl_output_remove(xwl_output); -} - -static const struct wp_drm_lease_connector_v1_listener lease_connector_listener = { - .name = lease_connector_handle_name, - .description = lease_connector_handle_description, - .connector_id = lease_connector_handle_connector_id, - .withdrawn = lease_connector_handle_withdrawn, - .done = lease_connector_handle_done, -}; - -static void -drm_lease_device_handle_drm_fd(void *data, - struct wp_drm_lease_device_v1 *wp_drm_lease_device_v1, - int fd) -{ - ((struct xwl_drm_lease_device *)data)->drm_read_only_fd = fd; -} - -static void -drm_lease_device_handle_connector(void *data, - struct wp_drm_lease_device_v1 *wp_drm_lease_device_v1, - struct wp_drm_lease_connector_v1 *connector) -{ - struct xwl_drm_lease_device *lease_device = data; - struct xwl_screen *xwl_screen = lease_device->xwl_screen; - struct xwl_output *xwl_output; - char name[MAX_OUTPUT_NAME] = { 0 }; - - xwl_output = calloc(1, sizeof *xwl_output); - if (xwl_output == NULL) { - ErrorF("%s ENOMEM\n", __func__); - return; - } - - xwl_output->lease_device = lease_device; - xwl_output->xwl_screen = xwl_screen; - xwl_output->lease_connector = connector; - xwl_output->randr_crtc = RRCrtcCreate(xwl_screen->screen, xwl_output); - if (!xwl_output->randr_crtc) { - ErrorF("Failed creating RandR CRTC\n"); - goto err; - } - RRCrtcSetRotations(xwl_output->randr_crtc, ALL_ROTATIONS); - xwl_output->randr_output = RROutputCreate(xwl_screen->screen, - name, MAX_OUTPUT_NAME, xwl_output); - snprintf(name, MAX_OUTPUT_NAME, "XWAYLAND%d", - xwl_screen_get_next_output_serial(xwl_screen)); - xwl_output_set_name(xwl_output, name); - - if (!xwl_output->randr_output) { - ErrorF("Failed creating RandR Output\n"); - goto err; - } - - RRCrtcGammaSetSize(xwl_output->randr_crtc, 256); - RROutputSetCrtcs(xwl_output->randr_output, &xwl_output->randr_crtc, 1); - RROutputSetConnection(xwl_output->randr_output, RR_Connected); - RROutputSetNonDesktop(xwl_output->randr_output, TRUE); - xwl_output->randr_output->devPrivate = xwl_output; - - wp_drm_lease_connector_v1_add_listener(connector, - &lease_connector_listener, - xwl_output); - - xorg_list_append(&xwl_output->link, &xwl_screen->output_list); - return; - -err: - if (xwl_output->randr_crtc) - RRCrtcDestroy(xwl_output->randr_crtc); - free(xwl_output); -} - -static void -drm_lease_device_handle_released(void *data, - struct wp_drm_lease_device_v1 *wp_drm_lease_device_v1) -{ - struct xwl_drm_lease_device *lease_device = data; - xwl_screen_destroy_drm_lease_device(lease_device->xwl_screen, wp_drm_lease_device_v1); -} - -static void -drm_lease_device_handle_done(void *data, - struct wp_drm_lease_device_v1 *wp_drm_lease_device_v1) -{ - /* This space is deliberately left blank */ -} - -static const struct wp_drm_lease_device_v1_listener drm_lease_device_listener = { - .drm_fd = drm_lease_device_handle_drm_fd, - .connector = drm_lease_device_handle_connector, - .released = drm_lease_device_handle_released, - .done = drm_lease_device_handle_done, -}; - -void -xwl_screen_add_drm_lease_device(struct xwl_screen *xwl_screen, uint32_t id) -{ - struct wp_drm_lease_device_v1 *lease_device = wl_registry_bind( - xwl_screen->registry, id, &wp_drm_lease_device_v1_interface, 1); - struct xwl_drm_lease_device *device_data = XNFcallocarray(1, sizeof(struct xwl_drm_lease_device)); - - device_data->drm_lease_device = lease_device; - device_data->xwl_screen = xwl_screen; - device_data->drm_read_only_fd = -1; - device_data->id = id; - xorg_list_add(&device_data->link, &xwl_screen->drm_lease_devices); - wp_drm_lease_device_v1_add_listener(lease_device, - &drm_lease_device_listener, - device_data); -} - -void -xwl_screen_destroy_drm_lease_device(struct xwl_screen *xwl_screen, - struct wp_drm_lease_device_v1 *wp_drm_lease_device_v1) -{ - struct xwl_drm_lease_device *device_data; - - xorg_list_for_each_entry(device_data, &xwl_screen->drm_lease_devices, link) { - if (device_data->drm_lease_device == wp_drm_lease_device_v1) { - wp_drm_lease_device_v1_destroy(wp_drm_lease_device_v1); - xorg_list_del(&device_data->link); - if (device_data->drm_read_only_fd >= 0) - close(device_data->drm_read_only_fd); - free(device_data); - return; - } - } -} diff --git a/hw/xwayland/xwayland-drm-lease.h b/hw/xwayland/xwayland-drm-lease.h deleted file mode 100644 index aa5aed63c..000000000 --- a/hw/xwayland/xwayland-drm-lease.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright © 2020 Drew Devault - * Copyright © 2021 Xaver Hugl - * - * Permission to use, copy, modify, distribute, and sell this software - * and its documentation for any purpose is hereby granted without - * fee, provided that the above copyright notice appear in all copies - * and that both that copyright notice and this permission notice - * appear in supporting documentation, and that the name of the - * copyright holders not be used in advertising or publicity - * pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied - * warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS - * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. - */ - -#ifndef XWAYLAND_DRM_LEASE_H -#define XWAYLAND_DRM_LEASE_H - -#include -#include - -#include "xwayland-types.h" -#include "list.h" - -#include "drm-lease-v1-client-protocol.h" - -struct xwl_drm_lease_device { - struct xorg_list link; - struct wp_drm_lease_device_v1 *drm_lease_device; - int drm_read_only_fd; - struct xwl_screen *xwl_screen; - uint32_t id; -}; - -struct xwl_queued_drm_lease_device { - struct xorg_list link; - uint32_t id; -}; - -struct xwl_drm_lease { - struct xorg_list link; - struct wp_drm_lease_v1 *lease; - RRLeasePtr rrLease; - ClientPtr client; - int fd; -}; - -int xwl_randr_request_lease(ClientPtr client, ScreenPtr screen, RRLeasePtr rrLease); -void xwl_randr_get_lease(ClientPtr client, ScreenPtr screen, RRLeasePtr *rrLease, int *fd); -void xwl_randr_terminate_lease(ScreenPtr screen, RRLeasePtr lease); - -void xwl_screen_add_drm_lease_device(struct xwl_screen *xwl_screen, uint32_t id); -void xwl_screen_destroy_drm_lease_device(struct xwl_screen *xwl_screen, - struct wp_drm_lease_device_v1 *wp_drm_lease_device_v1); - -#endif /* XWAYLAND_DRM_LEASE_H */ diff --git a/hw/xwayland/xwayland-glamor-gbm.c b/hw/xwayland/xwayland-glamor-gbm.c deleted file mode 100644 index 2512d7aa9..000000000 --- a/hw/xwayland/xwayland-glamor-gbm.c +++ /dev/null @@ -1,1881 +0,0 @@ -/* - * Copyright © 2011-2014 Intel Corporation - * Copyright © 2017 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including - * the next paragraph) shall be included in all copies or substantial - * portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Authors: - * Lyude Paul - * - */ - -#include - -#include -#include -#include -#ifdef DRI3 -#include -#endif /* DRI3 */ -#include -#include -#include -#if defined(__linux__) -#include -#include -#include -#endif - -#define MESA_EGL_NO_X11_HEADERS -#define EGL_NO_X11 -#include -#include - -#include -#include -#include -#include "drm-client-protocol.h" - -#include "dri3/dri3_priv.h" -#include "glamor/glamor_priv.h" - -#include "xwayland-glamor.h" -#include "xwayland-glamor-gbm.h" -#include "xwayland-pixmap.h" -#include "xwayland-screen.h" -#include "xwayland-window-buffers.h" - -#include "linux-dmabuf-unstable-v1-client-protocol.h" -#include "linux-drm-syncobj-v1-client-protocol.h" - -struct xwl_gbm_private { - drmDevice *device; - char *device_name; - struct gbm_device *gbm; - int drm_fd; - Bool fd_render_node; - Bool drm_authenticated; - Bool dmabuf_capable; - Bool glamor_gles; - Bool implicit_sync; - Bool supports_syncobjs; - - /* Set if wl_drm is available */ - struct wl_drm *drm; - uint32_t capabilities; -}; - -struct xwl_pixmap { - struct wl_buffer *buffer; - EGLImage image; - unsigned int texture; - struct gbm_bo *bo; - Bool implicit_modifier; -#ifdef DRI3 - struct dri3_syncobj *syncobj; - uint64_t timeline_point; - int efd; - struct xwl_window_buffer *xwl_window_buffer; -#endif /* DRI3 */ -}; - -static DevPrivateKeyRec xwl_gbm_private_key; -static DevPrivateKeyRec xwl_auth_state_private_key; - -static inline struct xwl_gbm_private * -xwl_gbm_get(struct xwl_screen *xwl_screen) -{ - return dixLookupPrivate(&xwl_screen->screen->devPrivates, - &xwl_gbm_private_key); -} - -Bool -xwl_glamor_has_wl_drm(struct xwl_screen *xwl_screen) -{ - struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen); - - return !!(xwl_gbm->drm != NULL); -} - -/* There is a workaround for Mesa behaviour, which will cause black windows - * when RGBX formats is using. Why exactly? There is an explanation: - * 1. We create GL_RGBA texture with GL_UNSIGNED_BYTE type, all allowed by ES. - * 2 .We export these texture to GBM bo with GBM_FORMAT_XRGB8888, and Mesa sets internal - * format of these textures as GL_RGB8 (mesa/mesa!5034 (merged)) - * 3. We import these BO at some point, and use glTexSubImage on it with GL_RGBA format - * and with GL_UNSIGNED_BYTE type, as we creates. Mesa checks its internalformat - * in glTexSubImage2D and fails due to GLES internal format limitation - * (see https://registry.khronos.org/OpenGL/specs/es/2.0/es_full_spec_2.0.pdf, section 3.7.1). - */ -static uint32_t -gbm_format_for_depth(int depth, int gles) -{ - switch (depth) { - case 15: - return GBM_FORMAT_ARGB1555; - case 16: - return GBM_FORMAT_RGB565; - case 24: - if (gles) - return GBM_FORMAT_ARGB8888; - return GBM_FORMAT_XRGB8888; - case 30: - return GBM_FORMAT_ARGB2101010; - default: - ErrorF("unexpected depth: %d\n", depth); - case 32: - return GBM_FORMAT_ARGB8888; - } -} - -static char -is_device_path_render_node (const char *device_path) -{ - char is_render_node; - int fd; - - fd = open(device_path, O_RDWR | O_CLOEXEC); - if (fd < 0) - return 0; - - is_render_node = (drmGetNodeTypeFromFd(fd) == DRM_NODE_RENDER); - close(fd); - - return is_render_node; -} - -static PixmapPtr -xwl_glamor_gbm_create_pixmap_for_bo(ScreenPtr screen, struct gbm_bo *bo, - int depth, - Bool implicit_modifier) -{ - PixmapPtr pixmap; - struct xwl_screen *xwl_screen = xwl_screen_get(screen); -#ifdef GBM_BO_FD_FOR_PLANE - struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen); - uint64_t modifier = gbm_bo_get_modifier(bo); - const int num_planes = gbm_bo_get_plane_count(bo); - int fds[GBM_MAX_PLANES]; - int plane; - int attr_num = 0; - EGLint img_attrs[64] = {0}; - enum PlaneAttrs { - PLANE_FD, - PLANE_OFFSET, - PLANE_PITCH, - PLANE_MODIFIER_LO, - PLANE_MODIFIER_HI, - NUM_PLANE_ATTRS - }; - static const EGLint planeAttrs[][NUM_PLANE_ATTRS] = { - { - EGL_DMA_BUF_PLANE0_FD_EXT, - EGL_DMA_BUF_PLANE0_OFFSET_EXT, - EGL_DMA_BUF_PLANE0_PITCH_EXT, - EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT, - EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT, - }, - { - EGL_DMA_BUF_PLANE1_FD_EXT, - EGL_DMA_BUF_PLANE1_OFFSET_EXT, - EGL_DMA_BUF_PLANE1_PITCH_EXT, - EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT, - EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT, - }, - { - EGL_DMA_BUF_PLANE2_FD_EXT, - EGL_DMA_BUF_PLANE2_OFFSET_EXT, - EGL_DMA_BUF_PLANE2_PITCH_EXT, - EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT, - EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT, - }, - { - EGL_DMA_BUF_PLANE3_FD_EXT, - EGL_DMA_BUF_PLANE3_OFFSET_EXT, - EGL_DMA_BUF_PLANE3_PITCH_EXT, - EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT, - EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT, - }, - }; - - for (plane = 0; plane < num_planes; plane++) fds[plane] = -1; -#endif - - struct xwl_pixmap *xwl_pixmap = calloc(1, sizeof(struct xwl_pixmap)); - if (xwl_pixmap == NULL) - return NULL; - - pixmap = glamor_create_pixmap(screen, - gbm_bo_get_width(bo), - gbm_bo_get_height(bo), - depth, - GLAMOR_CREATE_PIXMAP_NO_TEXTURE); - if (!pixmap) { - free(xwl_pixmap); - return NULL; - } - - xwl_glamor_egl_make_current(xwl_screen); - xwl_pixmap->bo = bo; - xwl_pixmap->buffer = NULL; - xwl_pixmap->implicit_modifier = implicit_modifier; -#if defined(XWL_HAS_GLAMOR) && defined(DRI3) - xwl_pixmap->efd = -1; -#endif /* defined(XWL_HAS_GLAMOR) && defined(DRI3) */ - -#ifdef GBM_BO_FD_FOR_PLANE - if (xwl_gbm->dmabuf_capable) { -#define ADD_ATTR(attrs, num, attr) \ - do { \ - assert(((num) + 1) < (sizeof(attrs) / sizeof((attrs)[0]))); \ - (attrs)[(num)++] = (attr); \ - } while (0) - ADD_ATTR(img_attrs, attr_num, EGL_WIDTH); - ADD_ATTR(img_attrs, attr_num, gbm_bo_get_width(bo)); - ADD_ATTR(img_attrs, attr_num, EGL_HEIGHT); - ADD_ATTR(img_attrs, attr_num, gbm_bo_get_height(bo)); - ADD_ATTR(img_attrs, attr_num, EGL_LINUX_DRM_FOURCC_EXT); - ADD_ATTR(img_attrs, attr_num, gbm_bo_get_format(bo)); - - for (plane = 0; plane < num_planes; plane++) { - fds[plane] = gbm_bo_get_fd_for_plane(bo, plane); - ADD_ATTR(img_attrs, attr_num, planeAttrs[plane][PLANE_FD]); - ADD_ATTR(img_attrs, attr_num, fds[plane]); - ADD_ATTR(img_attrs, attr_num, planeAttrs[plane][PLANE_OFFSET]); - ADD_ATTR(img_attrs, attr_num, gbm_bo_get_offset(bo, plane)); - ADD_ATTR(img_attrs, attr_num, planeAttrs[plane][PLANE_PITCH]); - ADD_ATTR(img_attrs, attr_num, gbm_bo_get_stride_for_plane(bo, plane)); - ADD_ATTR(img_attrs, attr_num, planeAttrs[plane][PLANE_MODIFIER_LO]); - ADD_ATTR(img_attrs, attr_num, (uint32_t)(modifier & 0xFFFFFFFFULL)); - ADD_ATTR(img_attrs, attr_num, planeAttrs[plane][PLANE_MODIFIER_HI]); - ADD_ATTR(img_attrs, attr_num, (uint32_t)(modifier >> 32ULL)); - } - ADD_ATTR(img_attrs, attr_num, EGL_NONE); -#undef ADD_ATTR - - xwl_pixmap->image = eglCreateImageKHR(xwl_screen->egl_display, - EGL_NO_CONTEXT, - EGL_LINUX_DMA_BUF_EXT, - NULL, - img_attrs); - - for (plane = 0; plane < num_planes; plane++) { - close(fds[plane]); - fds[plane] = -1; - } - } - else -#endif - { - xwl_pixmap->image = eglCreateImageKHR(xwl_screen->egl_display, - EGL_NO_CONTEXT, - EGL_NATIVE_PIXMAP_KHR, - xwl_pixmap->bo, NULL); - } - - if (xwl_pixmap->image == EGL_NO_IMAGE_KHR) - goto error; - - glGenTextures(1, &xwl_pixmap->texture); - glBindTexture(GL_TEXTURE_2D, xwl_pixmap->texture); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - - glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, xwl_pixmap->image); - if (eglGetError() != EGL_SUCCESS) - goto error; - - glBindTexture(GL_TEXTURE_2D, 0); - - if (!glamor_set_pixmap_texture(pixmap, xwl_pixmap->texture)) - goto error; - - glamor_set_pixmap_type(pixmap, GLAMOR_TEXTURE_DRM); - xwl_pixmap_set_private(pixmap, xwl_pixmap); - - return pixmap; - -error: - if (xwl_pixmap->image != EGL_NO_IMAGE_KHR) - eglDestroyImageKHR(xwl_screen->egl_display, xwl_pixmap->image); - if (pixmap) - glamor_destroy_pixmap(pixmap); - free(xwl_pixmap); - - return NULL; -} - -static PixmapPtr -xwl_glamor_gbm_create_pixmap_internal(struct xwl_screen *xwl_screen, - DrawablePtr drawable, - int width, int height, int depth, - unsigned int hint, - Bool implicit_scanout) -{ - struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen); - struct gbm_bo *bo = NULL; - PixmapPtr pixmap = NULL; - uint32_t num_modifiers = 0; - uint64_t *modifiers = NULL; - - if (width > 0 && height > 0 && depth >= 15 && - (hint == CREATE_PIXMAP_USAGE_BACKING_PIXMAP || - hint == CREATE_PIXMAP_USAGE_SHARED || - (xwl_screen->rootless && hint == 0))) { - uint32_t format = gbm_format_for_depth(depth, xwl_gbm->glamor_gles); - Bool implicit = FALSE; - -#ifdef GBM_BO_WITH_MODIFIERS - if (xwl_gbm->dmabuf_capable) { - Bool supports_scanout = FALSE; - - if (drawable) { - xwl_glamor_get_drawable_modifiers_and_scanout(drawable, - format, - &num_modifiers, - &modifiers, - &supports_scanout); - } - - if (num_modifiers == 0) { - xwl_glamor_get_modifiers(xwl_screen->screen, format, - &num_modifiers, &modifiers); - } - - if (num_modifiers > 0) { -#ifdef GBM_BO_WITH_MODIFIERS2 - uint32_t usage = GBM_BO_USE_RENDERING; - if (supports_scanout) - usage |= GBM_BO_USE_SCANOUT; - bo = gbm_bo_create_with_modifiers2(xwl_gbm->gbm, width, height, - format, modifiers, num_modifiers, - usage); -#else - bo = gbm_bo_create_with_modifiers(xwl_gbm->gbm, width, height, - format, modifiers, num_modifiers); -#endif - } - } -#endif - if (bo == NULL) { - uint32_t usage = GBM_BO_USE_RENDERING; - implicit = TRUE; - if (implicit_scanout) - usage |= GBM_BO_USE_SCANOUT; - - if (num_modifiers > 0) { - Bool has_mod_invalid = FALSE, has_mod_linear = FALSE; - int i; - - for (i = 0; i < num_modifiers; i++) { - if (modifiers[i] == DRM_FORMAT_MOD_INVALID) - has_mod_invalid = TRUE; - else if (modifiers[i] == DRM_FORMAT_MOD_LINEAR) - has_mod_linear = TRUE; - } - - if (!has_mod_invalid && has_mod_linear) - usage |= GBM_BO_USE_LINEAR; - } - - bo = gbm_bo_create(xwl_gbm->gbm, width, height, format, usage); - } - - if (bo) { - pixmap = xwl_glamor_gbm_create_pixmap_for_bo(xwl_screen->screen, bo, depth, implicit); - - if (!pixmap) { - gbm_bo_destroy(bo); - } - else if (xwl_screen->rootless && hint == CREATE_PIXMAP_USAGE_BACKING_PIXMAP) { - glamor_clear_pixmap(pixmap); - } - } - } - - if (!pixmap) - pixmap = glamor_create_pixmap(xwl_screen->screen, width, height, depth, hint); - - free(modifiers); - return pixmap; -} - -static PixmapPtr -xwl_glamor_gbm_create_pixmap(ScreenPtr screen, - int width, int height, int depth, - unsigned int hint) -{ - return xwl_glamor_gbm_create_pixmap_internal(xwl_screen_get(screen), NULL, - width, height, depth, hint, FALSE); -} - -PixmapPtr -xwl_glamor_create_pixmap_for_window(struct xwl_window *xwl_window) -{ - struct xwl_screen *xwl_screen = xwl_window->xwl_screen; - WindowPtr window = xwl_window->surface_window; - unsigned border_width = 2 * window->borderWidth; - - if (!xwl_screen->glamor) - return NullPixmap; - - return xwl_glamor_gbm_create_pixmap_internal(xwl_screen, - &window->drawable, - window->drawable.width + border_width, - window->drawable.height + border_width, - window->drawable.depth, - CREATE_PIXMAP_USAGE_BACKING_PIXMAP, - xwl_window->has_implicit_scanout_support); -} - -static Bool -xwl_glamor_gbm_destroy_pixmap(PixmapPtr pixmap) -{ - struct xwl_screen *xwl_screen = xwl_screen_get(pixmap->drawable.pScreen); - struct xwl_pixmap *xwl_pixmap = xwl_pixmap_get(pixmap); - - if (xwl_pixmap && pixmap->refcnt == 1) { - xwl_pixmap_del_buffer_release_cb(pixmap); - if (xwl_pixmap->buffer) - wl_buffer_destroy(xwl_pixmap->buffer); - - eglDestroyImageKHR(xwl_screen->egl_display, xwl_pixmap->image); - if (xwl_pixmap->bo) - gbm_bo_destroy(xwl_pixmap->bo); - xwl_glamor_gbm_dispose_syncpts(pixmap); - free(xwl_pixmap); - } - - return glamor_destroy_pixmap(pixmap); -} - -static const struct wl_buffer_listener xwl_glamor_gbm_buffer_listener = { - xwl_pixmap_buffer_release_cb, -}; - -#ifdef GBM_BO_WITH_MODIFIERS -static Bool -init_buffer_params_with_modifiers(struct xwl_pixmap *xwl_pixmap, - uint64_t *modifier, - int *num_planes, - int *prime_fds, - uint32_t *strides, - uint32_t *offsets) -{ -#ifndef GBM_BO_FD_FOR_PLANE - int32_t first_handle; -#endif - int i; - - *num_planes = gbm_bo_get_plane_count(xwl_pixmap->bo); - *modifier = gbm_bo_get_modifier(xwl_pixmap->bo); - - for (i = 0; i < *num_planes; i++) { -#ifdef GBM_BO_FD_FOR_PLANE - prime_fds[i] = gbm_bo_get_fd_for_plane(xwl_pixmap->bo, i); -#else - union gbm_bo_handle plane_handle; - - plane_handle = gbm_bo_get_handle_for_plane(xwl_pixmap->bo, i); - if (i == 0) - first_handle = plane_handle.s32; - - /* If all planes point to the same object as the first plane, i.e. they - * all have the same handle, we can fall back to the non-planar - * gbm_bo_get_fd without losing information. If they point to different - * objects we are out of luck and need to give up. - */ - if (first_handle == plane_handle.s32) - prime_fds[i] = gbm_bo_get_fd(xwl_pixmap->bo); - else - prime_fds[i] = -1; -#endif - if (prime_fds[i] == -1) { - while (--i >= 0) - close(prime_fds[i]); - return FALSE; - } - strides[i] = gbm_bo_get_stride_for_plane(xwl_pixmap->bo, i); - offsets[i] = gbm_bo_get_offset(xwl_pixmap->bo, i); - } - - return TRUE; -} -#endif - -static Bool -init_buffer_params_fallback(struct xwl_pixmap *xwl_pixmap, - uint64_t *modifier, - int *num_planes, - int *prime_fds, - uint32_t *strides, - uint32_t *offsets) -{ - *num_planes = 1; - *modifier = DRM_FORMAT_MOD_INVALID; - prime_fds[0] = gbm_bo_get_fd(xwl_pixmap->bo); - if (prime_fds[0] == -1) - return FALSE; - - strides[0] = gbm_bo_get_stride(xwl_pixmap->bo); - offsets[0] = 0; - - return TRUE; -} - -struct wl_buffer * -xwl_glamor_pixmap_get_wl_buffer(PixmapPtr pixmap) -{ - struct xwl_screen *xwl_screen = xwl_screen_get(pixmap->drawable.pScreen); - struct xwl_pixmap *xwl_pixmap = xwl_pixmap_get(pixmap); - struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen); - unsigned short width = pixmap->drawable.width; - unsigned short height = pixmap->drawable.height; - uint32_t format; - int num_planes; - int prime_fds[4]; - uint32_t strides[4]; - uint32_t offsets[4]; - uint64_t modifier; - int i; - - if (xwl_pixmap == NULL) - return NULL; - - if (xwl_pixmap->buffer) { - /* Buffer already exists. */ - return xwl_pixmap->buffer; - } - - if (!xwl_pixmap->bo) - return NULL; - - format = wl_drm_format_for_depth(pixmap->drawable.depth); - -#ifdef GBM_BO_WITH_MODIFIERS - if (!xwl_pixmap->implicit_modifier) { - if (!init_buffer_params_with_modifiers(xwl_pixmap, - &modifier, - &num_planes, - prime_fds, - strides, - offsets)) - return NULL; - } else -#endif - { - if (!init_buffer_params_fallback(xwl_pixmap, - &modifier, - &num_planes, - prime_fds, - strides, - offsets)) - return NULL; - } - - if (xwl_screen->dmabuf && - xwl_glamor_is_modifier_supported(xwl_screen, format, modifier)) { - struct zwp_linux_buffer_params_v1 *params; - - params = zwp_linux_dmabuf_v1_create_params(xwl_screen->dmabuf); - for (i = 0; i < num_planes; i++) { - zwp_linux_buffer_params_v1_add(params, prime_fds[i], i, - offsets[i], strides[i], - modifier >> 32, modifier & 0xffffffff); - } - - xwl_pixmap->buffer = - zwp_linux_buffer_params_v1_create_immed(params, width, height, - format, 0); - zwp_linux_buffer_params_v1_destroy(params); - } else if (num_planes == 1 && modifier == DRM_FORMAT_MOD_INVALID && - xwl_gbm->drm) { - xwl_pixmap->buffer = - wl_drm_create_prime_buffer(xwl_gbm->drm, prime_fds[0], width, height, - format, - 0, gbm_bo_get_stride(xwl_pixmap->bo), - 0, 0, - 0, 0); - } - - for (i = 0; i < num_planes; i++) - close(prime_fds[i]); - - /* Add our listener now */ - if (xwl_pixmap->buffer) - wl_buffer_add_listener(xwl_pixmap->buffer, - &xwl_glamor_gbm_buffer_listener, pixmap); - - return xwl_pixmap->buffer; -} - -static void -xwl_glamor_gbm_cleanup(struct xwl_screen *xwl_screen) -{ - struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen); - - if (!xwl_gbm) - return; - - /* Cannot use GBM after clean-up, disable GLAMOR support from now on */ - ErrorF("XWAYLAND: Disabling GLAMOR support\n"); - xwl_screen->glamor = XWL_GLAMOR_NONE; - - if (xwl_gbm->device_name) - free(xwl_gbm->device_name); - drmFreeDevice(&xwl_gbm->device); - if (xwl_gbm->drm_fd) - close(xwl_gbm->drm_fd); - if (xwl_gbm->drm) - wl_drm_destroy(xwl_gbm->drm); - if (xwl_gbm->gbm) - gbm_device_destroy(xwl_gbm->gbm); - if (xwl_screen->explicit_sync) - wp_linux_drm_syncobj_manager_v1_destroy(xwl_screen->explicit_sync); - - dixSetPrivate(&xwl_screen->screen->devPrivates, &xwl_gbm_private_key, - NULL); - free(xwl_gbm); -} - -struct xwl_auth_state { - int fd; - ClientPtr client; - struct wl_callback *callback; -}; - -static void -free_xwl_auth_state(ClientPtr pClient, struct xwl_auth_state *state) -{ - dixSetPrivate(&pClient->devPrivates, &xwl_auth_state_private_key, NULL); - if (state) { - wl_callback_destroy(state->callback); - free(state); - } -} - -static void -xwl_auth_state_client_callback(CallbackListPtr *pcbl, void *unused, void *data) -{ - NewClientInfoRec *clientinfo = (NewClientInfoRec *) data; - ClientPtr pClient = clientinfo->client; - struct xwl_auth_state *state; - - switch (pClient->clientState) { - case ClientStateGone: - case ClientStateRetained: - state = dixLookupPrivate(&pClient->devPrivates, - &xwl_auth_state_private_key); - free_xwl_auth_state(pClient, state); - break; - default: - break; - } -} - -#ifdef DRI3 -static void -sync_callback(void *data, struct wl_callback *callback, uint32_t serial) -{ - struct xwl_auth_state *state = data; - ClientPtr client = state->client; - - /* if the client is gone, the callback is cancelled so it's safe to - * assume the client is still in ClientStateRunning at this point... - */ - dri3_send_open_reply(client, state->fd); - AttendClient(client); - free_xwl_auth_state(client, state); -} - -static const struct wl_callback_listener sync_listener = { - sync_callback -}; - -static int -xwl_dri3_open_client(ClientPtr client, - ScreenPtr screen, - RRProviderPtr provider, - int *pfd) -{ - struct xwl_screen *xwl_screen = xwl_screen_get(screen); - struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen); - drm_magic_t magic; - int fd; - - fd = open(xwl_gbm->device_name, O_RDWR | O_CLOEXEC); - if (fd < 0) - return BadAlloc; - if (xwl_gbm->fd_render_node) { - *pfd = fd; - return Success; - } - - struct xwl_auth_state *state = calloc(1, sizeof(struct xwl_auth_state)); - if (state == NULL) { - close(fd); - return BadAlloc; - } - - state->client = client; - state->fd = fd; - - if (drmGetMagic(state->fd, &magic) < 0) { - close(state->fd); - free(state); - return BadMatch; - } - - wl_drm_authenticate(xwl_gbm->drm, magic); - state->callback = wl_display_sync(xwl_screen->display); - wl_callback_add_listener(state->callback, &sync_listener, state); - dixSetPrivate(&client->devPrivates, &xwl_auth_state_private_key, state); - - IgnoreClient(client); - - return Success; -} -#endif /* DRI3 */ - -PixmapPtr -glamor_pixmap_from_fds(ScreenPtr screen, CARD8 num_fds, const int *fds, - CARD16 width, CARD16 height, - const CARD32 *strides, const CARD32 *offsets, - CARD8 depth, CARD8 bpp, uint64_t modifier) -{ - struct xwl_screen *xwl_screen = xwl_screen_get(screen); - struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen); - struct gbm_bo *bo = NULL; - PixmapPtr pixmap; - int i; - Bool implicit = FALSE; - - if (width == 0 || height == 0 || num_fds == 0 || - depth < 15 || bpp != BitsPerPixel(depth) || - strides[0] < width * bpp / 8) - goto error; - - if (xwl_gbm->dmabuf_capable && modifier != DRM_FORMAT_MOD_INVALID) { -#ifdef GBM_BO_WITH_MODIFIERS - struct gbm_import_fd_modifier_data data; - - data.width = width; - data.height = height; - data.num_fds = num_fds; - data.format = gbm_format_for_depth(depth, xwl_gbm->glamor_gles); - data.modifier = modifier; - for (i = 0; i < num_fds; i++) { - data.fds[i] = fds[i]; - data.strides[i] = strides[i]; - data.offsets[i] = offsets[i]; - } - bo = gbm_bo_import(xwl_gbm->gbm, GBM_BO_IMPORT_FD_MODIFIER, &data, - GBM_BO_USE_RENDERING); -#endif - } else if (num_fds == 1) { - struct gbm_import_fd_data data; - - data.fd = fds[0]; - data.width = width; - data.height = height; - data.stride = strides[0]; - data.format = gbm_format_for_depth(depth, xwl_gbm->glamor_gles); - bo = gbm_bo_import(xwl_gbm->gbm, GBM_BO_IMPORT_FD, &data, - GBM_BO_USE_RENDERING); - implicit = TRUE; - } else { - goto error; - } - - if (bo == NULL) - goto error; - - pixmap = xwl_glamor_gbm_create_pixmap_for_bo(screen, bo, depth, implicit); - if (pixmap == NULL) { - gbm_bo_destroy(bo); - goto error; - } - - return pixmap; - -error: - return NULL; -} - -int -glamor_egl_fds_from_pixmap(ScreenPtr screen, PixmapPtr pixmap, int *fds, - uint32_t *strides, uint32_t *offsets, - uint64_t *modifier) -{ - struct xwl_pixmap *xwl_pixmap; -#ifdef GBM_BO_WITH_MODIFIERS -#ifndef GBM_BO_FD_FOR_PLANE - int32_t first_handle; -#endif - uint32_t num_fds; - int i; -#endif - - xwl_pixmap = xwl_pixmap_get(pixmap); - - if (xwl_pixmap == NULL) - return 0; - - if (!xwl_pixmap->bo) - return 0; - -#ifdef GBM_BO_WITH_MODIFIERS - num_fds = gbm_bo_get_plane_count(xwl_pixmap->bo); - *modifier = gbm_bo_get_modifier(xwl_pixmap->bo); - - for (i = 0; i < num_fds; i++) { -#ifdef GBM_BO_FD_FOR_PLANE - fds[i] = gbm_bo_get_fd_for_plane(xwl_pixmap->bo, i); -#else - union gbm_bo_handle plane_handle; - - plane_handle = gbm_bo_get_handle_for_plane(xwl_pixmap->bo, i); - if (i == 0) - first_handle = plane_handle.s32; - - /* If all planes point to the same object as the first plane, i.e. they - * all have the same handle, we can fall back to the non-planar - * gbm_bo_get_fd without losing information. If they point to different - * objects we are out of luck and need to give up. - */ - if (first_handle == plane_handle.s32) - fds[i] = gbm_bo_get_fd(xwl_pixmap->bo); - else - fds[i] = -1; -#endif - if (fds[i] == -1) { - while (--i >= 0) - close(fds[i]); - return 0; - } - strides[i] = gbm_bo_get_stride_for_plane(xwl_pixmap->bo, i); - offsets[i] = gbm_bo_get_offset(xwl_pixmap->bo, i); - } - - return num_fds; -#else - *modifier = DRM_FORMAT_MOD_INVALID; - fds[0] = gbm_bo_get_fd(xwl_pixmap->bo); - if (fds[0] == -1) - return 0; - strides[0] = gbm_bo_get_stride(xwl_pixmap->bo); - offsets[0] = 0; - return 1; -#endif -} - -/* Not actually used, just defined here so there's something for - * _glamor_egl_fds_from_pixmap() to link against - */ -int -glamor_egl_fd_from_pixmap(ScreenPtr screen, PixmapPtr pixmap, - CARD16 *stride, CARD32 *size) -{ - return -1; -} - -int -xwl_glamor_dmabuf_export_sync_file(PixmapPtr pixmap) -{ - struct xwl_screen *xwl_screen = xwl_screen_get(pixmap->drawable.pScreen); - struct xwl_pixmap *xwl_pixmap; - int num_planes; - int sync_file = -1; - int p; -#ifndef GBM_BO_FD_FOR_PLANE - int32_t first_handle; -#endif - - if (!xwl_screen->glamor) - return -1; - -#ifdef DMA_BUF_IOCTL_EXPORT_SYNC_FILE - xwl_pixmap = xwl_pixmap_get(pixmap); - num_planes = gbm_bo_get_plane_count(xwl_pixmap->bo); - - for (p = 0; p < num_planes; ++p) { - int plane_fd; -#ifdef GBM_BO_FD_FOR_PLANE - plane_fd = gbm_bo_get_fd_for_plane(xwl_pixmap->bo, p); -#else - union gbm_bo_handle plane_handle = - gbm_bo_get_handle_for_plane(xwl_pixmap->bo, p); - if (p == 0) - first_handle = plane_handle.s32; - - if (plane_handle.s32 == first_handle) - plane_fd = gbm_bo_get_fd(xwl_pixmap->bo); - else - continue; -#endif /* GBM_BO_FD_FOR_PLANE */ - struct dma_buf_export_sync_file export_args = { 0 }; - export_args.fd = -1; - export_args.flags = DMA_BUF_SYNC_READ; - drmIoctl(plane_fd, DMA_BUF_IOCTL_EXPORT_SYNC_FILE, &export_args); - close(plane_fd); - if (sync_file == -1) { - sync_file = export_args.fd; - } else { - struct sync_merge_data merge_args = { 0 }; - merge_args.fd2 = export_args.fd; - ioctl(sync_file, SYNC_IOC_MERGE, &merge_args); - close(export_args.fd); - close(sync_file); - sync_file = merge_args.fence; - } - } -#endif /* DMA_BUF_IOCTL_EXPORT_SYNC_FILE */ - return sync_file; -} - -void -xwl_glamor_dmabuf_import_sync_file(PixmapPtr pixmap, int sync_file) -{ - struct xwl_screen *xwl_screen = xwl_screen_get(pixmap->drawable.pScreen); - struct xwl_pixmap *xwl_pixmap; - int num_planes; - int p; -#ifndef GBM_BO_FD_FOR_PLANE - int32_t first_handle; -#endif - - if (!xwl_screen->glamor) - return; - -#ifdef DMA_BUF_IOCTL_IMPORT_SYNC_FILE - xwl_pixmap = xwl_pixmap_get(pixmap); - num_planes = gbm_bo_get_plane_count(xwl_pixmap->bo); - - for (p = 0; p < num_planes; ++p) { - int plane_fd; -#ifdef GBM_BO_FD_FOR_PLANE - plane_fd = gbm_bo_get_fd_for_plane(xwl_pixmap->bo, p); -#else - union gbm_bo_handle plane_handle = - gbm_bo_get_handle_for_plane(xwl_pixmap->bo, p); - if (p == 0) - first_handle = plane_handle.s32; - - if (plane_handle.s32 == first_handle) - plane_fd = gbm_bo_get_fd(xwl_pixmap->bo); - else - continue; -#endif /* GBM_BO_FD_FOR_PLANE */ - struct dma_buf_import_sync_file import_args = { 0 }; - import_args.fd = sync_file; - import_args.flags = DMA_BUF_SYNC_WRITE; - drmIoctl(plane_fd, DMA_BUF_IOCTL_IMPORT_SYNC_FILE, &import_args); - close(plane_fd); - } -#endif /* DMA_BUF_IOCTL_IMPORT_SYNC_FILE */ - close(sync_file); -} - -#ifdef DRI3 -struct xwl_dri3_syncobj -{ - struct dri3_syncobj base; - uint32_t handle; - struct wp_linux_drm_syncobj_timeline_v1 *timeline; -}; - -void -xwl_glamor_dri3_syncobj_passthrough(struct xwl_window *xwl_window, - struct dri3_syncobj *acquire_syncobj, - struct dri3_syncobj *release_syncobj, - uint64_t acquire_point, - uint64_t release_point) -{ - struct xwl_screen *xwl_screen = xwl_window->xwl_screen; - struct xwl_dri3_syncobj *xwl_acquire_syncobj = (struct xwl_dri3_syncobj *)acquire_syncobj; - struct xwl_dri3_syncobj *xwl_release_syncobj = (struct xwl_dri3_syncobj *)release_syncobj; - uint32_t acquire_hi = acquire_point >> 32; - uint32_t acquire_lo = acquire_point & 0xffffffff; - uint32_t release_hi = release_point >> 32; - uint32_t release_lo = release_point & 0xffffffff; - - if (!xwl_window->surface_sync) - xwl_window->surface_sync = - wp_linux_drm_syncobj_manager_v1_get_surface(xwl_screen->explicit_sync, - xwl_window->surface); - - wp_linux_drm_syncobj_surface_v1_set_acquire_point(xwl_window->surface_sync, - xwl_acquire_syncobj->timeline, - acquire_hi, acquire_lo); - wp_linux_drm_syncobj_surface_v1_set_release_point(xwl_window->surface_sync, - xwl_release_syncobj->timeline, - release_hi, release_lo); -} - -static Bool -xwl_dri3_check_syncobj(struct dri3_syncobj *syncobj, uint64_t point, Bool check_avail) -{ - struct xwl_dri3_syncobj *xwl_syncobj = (struct xwl_dri3_syncobj *)syncobj; - struct xwl_screen *xwl_screen = xwl_screen_get(syncobj->screen); - struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen); - - return !drmSyncobjTimelineWait(xwl_gbm->drm_fd, - &xwl_syncobj->handle, &point, 1, - 0 /* timeout */, - check_avail ? - DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE : - DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT, - NULL /* first_signaled */); -} - -static Bool -xwl_dri3_syncobj_has_fence(struct dri3_syncobj *syncobj, uint64_t point) -{ - return xwl_dri3_check_syncobj(syncobj, point, TRUE /* check_avail */); -} - -static Bool -xwl_dri3_syncobj_is_signaled(struct dri3_syncobj *syncobj, uint64_t point) -{ - return xwl_dri3_check_syncobj(syncobj, point, FALSE /* check_avail */); -} - -static int -xwl_dri3_syncobj_export_fence(struct dri3_syncobj *syncobj, uint64_t point) -{ - struct xwl_dri3_syncobj *xwl_syncobj = (struct xwl_dri3_syncobj *)syncobj; - struct xwl_screen *xwl_screen = xwl_screen_get(syncobj->screen); - struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen); - uint32_t temp_syncobj; - int fd = -1; - - drmSyncobjCreate(xwl_gbm->drm_fd, 0, &temp_syncobj); - drmSyncobjTransfer(xwl_gbm->drm_fd, temp_syncobj, 0, - xwl_syncobj->handle, point, 0); - drmSyncobjExportSyncFile(xwl_gbm->drm_fd, temp_syncobj, &fd); - drmSyncobjDestroy(xwl_gbm->drm_fd, temp_syncobj); - return fd; -} - -static void -xwl_dri3_syncobj_import_fence(struct dri3_syncobj *syncobj, - uint64_t point, int fd) -{ - struct xwl_dri3_syncobj *xwl_syncobj = (struct xwl_dri3_syncobj *)syncobj; - struct xwl_screen *xwl_screen = xwl_screen_get(syncobj->screen); - struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen); - uint32_t temp_syncobj; - - drmSyncobjCreate(xwl_gbm->drm_fd, 0, &temp_syncobj); - drmSyncobjImportSyncFile(xwl_gbm->drm_fd, temp_syncobj, fd); - drmSyncobjTransfer(xwl_gbm->drm_fd, xwl_syncobj->handle, point, - temp_syncobj, 0, 0); - drmSyncobjDestroy(xwl_gbm->drm_fd, temp_syncobj); - close(fd); -} - -static void -xwl_dri3_signal_syncobj(struct dri3_syncobj *syncobj, uint64_t point) -{ - struct xwl_dri3_syncobj *xwl_syncobj = (struct xwl_dri3_syncobj *)syncobj; - struct xwl_screen *xwl_screen = xwl_screen_get(syncobj->screen); - struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen); - - drmSyncobjTimelineSignal(xwl_gbm->drm_fd, &xwl_syncobj->handle, &point, 1); -} - -static void -xwl_dri3_free_syncobj(struct dri3_syncobj *syncobj) -{ - struct xwl_dri3_syncobj *xwl_syncobj = (struct xwl_dri3_syncobj *)syncobj; - struct xwl_screen *xwl_screen = xwl_screen_get(syncobj->screen); - struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen); - - if (xwl_syncobj->timeline) - wp_linux_drm_syncobj_timeline_v1_destroy(xwl_syncobj->timeline); - - if (xwl_syncobj->handle) - drmSyncobjDestroy(xwl_gbm->drm_fd, xwl_syncobj->handle); - - free(xwl_syncobj); -} - -static void -xwl_dri3_syncobj_eventfd(struct dri3_syncobj *syncobj, uint64_t point, - int efd, Bool wait_avail) -{ - struct xwl_dri3_syncobj *xwl_syncobj = (struct xwl_dri3_syncobj *)syncobj; - struct xwl_screen *xwl_screen = xwl_screen_get(syncobj->screen); - struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen); - - drmSyncobjEventfd(xwl_gbm->drm_fd, xwl_syncobj->handle, point, efd, - wait_avail ? DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE : 0); -} - -static void -xwl_dri3_syncobj_submitted_eventfd(struct dri3_syncobj *syncobj, - uint64_t point, int efd) -{ - xwl_dri3_syncobj_eventfd(syncobj, point, efd, TRUE /* wait_avail */); -} - -static void -xwl_dri3_syncobj_signaled_eventfd(struct dri3_syncobj *syncobj, - uint64_t point, int efd) -{ - xwl_dri3_syncobj_eventfd(syncobj, point, efd, FALSE /* wait_avail */); -} - -static struct dri3_syncobj * -xwl_dri3_create_syncobj(struct xwl_screen *xwl_screen, uint32_t handle) -{ - struct xwl_dri3_syncobj *syncobj = calloc(1, sizeof (*syncobj)); - struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen); - Bool create = !handle; - - if (!syncobj) - return NULL; - - if (create && drmSyncobjCreate(xwl_gbm->drm_fd, 0, &handle)) - goto fail; - - if (xwl_screen->explicit_sync) { - int syncobj_fd = -1; - if (drmSyncobjHandleToFD(xwl_gbm->drm_fd, handle, &syncobj_fd)) - goto fail; - - syncobj->timeline = - wp_linux_drm_syncobj_manager_v1_import_timeline(xwl_screen->explicit_sync, - syncobj_fd); - close(syncobj_fd); - if (!syncobj->timeline) - goto fail; - } - - syncobj->handle = handle; - syncobj->base.screen = xwl_screen->screen; - syncobj->base.refcount = 1; - - syncobj->base.free = xwl_dri3_free_syncobj; - syncobj->base.has_fence = xwl_dri3_syncobj_has_fence; - syncobj->base.is_signaled = xwl_dri3_syncobj_is_signaled; - syncobj->base.export_fence = xwl_dri3_syncobj_export_fence; - syncobj->base.import_fence = xwl_dri3_syncobj_import_fence; - syncobj->base.signal = xwl_dri3_signal_syncobj; - syncobj->base.signaled_eventfd = xwl_dri3_syncobj_signaled_eventfd; - syncobj->base.submitted_eventfd = xwl_dri3_syncobj_submitted_eventfd; - return &syncobj->base; - -fail: - if (create && handle) - drmSyncobjDestroy(xwl_gbm->drm_fd, handle); - free(syncobj); - return NULL; -} - -struct dri3_syncobj * -xwl_glamor_dri3_syncobj_create(struct xwl_screen *xwl_screen) -{ - return xwl_dri3_create_syncobj(xwl_screen, 0 /* allocate new handle */); -} - -static struct dri3_syncobj * -xwl_dri3_import_syncobj(ClientPtr client, ScreenPtr screen, XID id, int fd) -{ - struct xwl_screen *xwl_screen = xwl_screen_get(screen); - struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen); - struct xwl_dri3_syncobj *syncobj = NULL; - uint32_t handle; - - if (drmSyncobjFDToHandle(xwl_gbm->drm_fd, fd, &handle)) - return NULL; - - syncobj = (struct xwl_dri3_syncobj *)xwl_dri3_create_syncobj(xwl_screen, handle); - if (!syncobj) { - drmSyncobjDestroy(xwl_gbm->drm_fd, handle); - return NULL; - } - - syncobj->base.id = id; - - return &syncobj->base; -} - -static Bool -xwl_gbm_supports_syncobjs(struct xwl_screen *xwl_screen) -{ - struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen); - uint64_t syncobj_cap = 0; - - if (drmGetCap(xwl_gbm->drm_fd, DRM_CAP_SYNCOBJ_TIMELINE, - &syncobj_cap) || !syncobj_cap) - return FALSE; - - /* Check if syncobj eventfd is supported. */ - drmSyncobjEventfd(xwl_gbm->drm_fd, 0, 0, -1, 0); - if (errno != ENOENT) - return FALSE; - -#if !defined(DMA_BUF_IOCTL_EXPORT_SYNC_FILE) || \ - !defined(DMA_BUF_IOCTL_IMPORT_SYNC_FILE) - return FALSE; -#else - return TRUE; -#endif -} - -static dri3_screen_info_rec xwl_dri3_info = { - .version = 2, - .open = NULL, - .pixmap_from_fds = glamor_pixmap_from_fds, - .fds_from_pixmap = glamor_fds_from_pixmap, - .open_client = xwl_dri3_open_client, - .get_formats = xwl_glamor_get_formats, - .get_modifiers = xwl_glamor_get_modifiers, - .get_drawable_modifiers = xwl_glamor_get_drawable_modifiers, - .import_syncobj = NULL, /* need to check for kernel support */ -}; -#endif /* DRI3 */ - -static const char * -get_render_node_path_for_device(const drmDevicePtr drm_device, - const char *device_path) -{ - const char *render_node_path; - int i; - - if (!(drm_device->available_nodes & (1 << DRM_NODE_RENDER))) - return NULL; - render_node_path = drm_device->nodes[DRM_NODE_RENDER]; - - for (i = 0; i < DRM_NODE_MAX; i++) { - if (!(drm_device->available_nodes & (1 << i))) - continue; - if (strcmp(device_path, drm_device->nodes[i]) == 0) - return render_node_path; - } - - return NULL; -} - -static char * -get_render_node_path(const char *device_path) -{ - drmDevicePtr *devices = NULL; - char *render_node_path = NULL; - int i, n_devices, max_devices; - - max_devices = drmGetDevices2(0, NULL, 0); - if (max_devices <= 0) - goto out; - - devices = calloc(max_devices, sizeof(drmDevicePtr)); - if (!devices) - goto out; - - n_devices = drmGetDevices2(0, devices, max_devices); - if (n_devices < 0) - goto out; - - for (i = 0; i < n_devices; i++) { - const char *node_path = get_render_node_path_for_device(devices[i], - device_path); - if (node_path) { - render_node_path = strdup(node_path); - break; - } - } - -out: - free(devices); - return render_node_path; -} - -static void -xwl_drm_handle_device(void *data, struct wl_drm *drm, const char *device) -{ - struct xwl_screen *xwl_screen = data; - struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen); - drm_magic_t magic; - char *render_node_path = NULL; - - if (!is_device_path_render_node(device)) - render_node_path = get_render_node_path(device); - - if (render_node_path) - xwl_gbm->device_name = render_node_path; - else - xwl_gbm->device_name = strdup(device); - - if (!xwl_gbm->device_name) { - xwl_glamor_gbm_cleanup(xwl_screen); - xwl_screen->expecting_event--; - return; - } - - xwl_gbm->drm_fd = open(xwl_gbm->device_name, O_RDWR | O_CLOEXEC); - if (xwl_gbm->drm_fd == -1) { - ErrorF("wayland-egl: could not open %s (%s)\n", - xwl_gbm->device_name, strerror(errno)); - xwl_glamor_gbm_cleanup(xwl_screen); - xwl_screen->expecting_event--; - return; - } - - if (drmGetDevice2(xwl_gbm->drm_fd, 0, &xwl_gbm->device) != 0) { - ErrorF("wayland-egl: Could not fetch DRM device %s\n", - xwl_gbm->device_name); - xwl_screen->expecting_event--; - return; - } - - if (drmGetNodeTypeFromFd(xwl_gbm->drm_fd) == DRM_NODE_RENDER) { - xwl_gbm->fd_render_node = TRUE; - xwl_screen->expecting_event--; - } else { - drmGetMagic(xwl_gbm->drm_fd, &magic); - wl_drm_authenticate(xwl_gbm->drm, magic); - } -} - -static void -xwl_drm_handle_format(void *data, struct wl_drm *drm, uint32_t format) -{ -} - -static void -xwl_drm_handle_authenticated(void *data, struct wl_drm *drm) -{ - struct xwl_screen *xwl_screen = data; - struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen); - - xwl_gbm->drm_authenticated = TRUE; - xwl_screen->expecting_event--; -} - -static void -xwl_drm_handle_capabilities(void *data, struct wl_drm *drm, uint32_t value) -{ - xwl_gbm_get(data)->capabilities = value; -} - -static const struct wl_drm_listener xwl_drm_listener = { - xwl_drm_handle_device, - xwl_drm_handle_format, - xwl_drm_handle_authenticated, - xwl_drm_handle_capabilities -}; - -Bool -xwl_screen_set_drm_interface(struct xwl_screen *xwl_screen, - uint32_t id, uint32_t version) -{ - struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen); - - if (version < 2) - return FALSE; - - xwl_gbm->drm = - wl_registry_bind(xwl_screen->registry, id, &wl_drm_interface, 2); - wl_drm_add_listener(xwl_gbm->drm, &xwl_drm_listener, xwl_screen); - xwl_screen->expecting_event++; - - return TRUE; -} - -Bool -xwl_screen_set_syncobj_interface(struct xwl_screen *xwl_screen, - uint32_t id, uint32_t version) -{ - xwl_screen->explicit_sync = - wl_registry_bind(xwl_screen->registry, id, - &wp_linux_drm_syncobj_manager_v1_interface, - version); - return TRUE; -} - -static Bool -xwl_glamor_gbm_has_egl_extension(void) -{ - return (epoxy_has_egl_extension(NULL, "EGL_MESA_platform_gbm") || - epoxy_has_egl_extension(NULL, "EGL_KHR_platform_gbm")); -} - -#ifdef DRI3 -static void -xwl_glamor_gbm_release_fence_avail(int fd, int xevents, void *data) -{ - struct xwl_pixmap *xwl_pixmap = data; - struct xwl_window_buffer *xwl_window_buffer = xwl_pixmap->xwl_window_buffer; - - SetNotifyFd(fd, NULL, 0, NULL); - close(fd); - xwl_pixmap->efd = -1; - - xwl_window_buffer_release(xwl_window_buffer); -} -#endif /* DRI3 */ - -Bool -xwl_glamor_supports_implicit_sync(struct xwl_screen *xwl_screen) -{ - /* absent glamor, implicit sync is irrelevant so just return TRUE */ - return !xwl_screen->glamor || - xwl_gbm_get(xwl_screen)->implicit_sync; -} - -Bool -xwl_glamor_supports_syncobjs(struct xwl_screen *xwl_screen) -{ - return xwl_screen->glamor && - xwl_gbm_get(xwl_screen)->supports_syncobjs; -} - -Bool -xwl_glamor_gbm_set_syncpts(struct xwl_window *xwl_window, PixmapPtr pixmap) -{ -#ifdef DRI3 - struct xwl_screen *xwl_screen = xwl_window->xwl_screen; - struct xwl_pixmap *xwl_pixmap = xwl_pixmap_get(pixmap); - uint64_t acquire_point; - uint64_t release_point; - int fence_fd; - - if (!xwl_screen->glamor) - return FALSE; - - if (!xwl_pixmap) { - ErrorF("XWAYLAND: Failed to set synchronization point, no backing xwl_pixmap!\n"); - return FALSE; - } - - acquire_point = ++xwl_pixmap->timeline_point; - release_point = ++xwl_pixmap->timeline_point; - - if (!xwl_pixmap->syncobj) { - struct dri3_syncobj *syncobj = xwl_glamor_dri3_syncobj_create(xwl_screen); - if (!syncobj) - goto fail; - xwl_pixmap->syncobj = syncobj; - } - - fence_fd = xwl_glamor_get_fence(xwl_screen); - if (fence_fd >= 0) - xwl_pixmap->syncobj->import_fence(xwl_pixmap->syncobj, acquire_point, fence_fd); - else - goto fail; - - xwl_glamor_dri3_syncobj_passthrough(xwl_window, - xwl_pixmap->syncobj, - xwl_pixmap->syncobj, - acquire_point, - release_point); - return TRUE; - -fail: - /* can't use explicit sync, we will do a glFinish() before presenting */ - if (xwl_pixmap->syncobj) { - xwl_pixmap->syncobj->free(xwl_pixmap->syncobj); - xwl_pixmap->syncobj = NULL; - } -#endif /* DRI3 */ - return FALSE; -} - -void -xwl_glamor_gbm_dispose_syncpts(PixmapPtr pixmap) -{ -#ifdef DRI3 - struct xwl_pixmap *xwl_pixmap = xwl_pixmap_get(pixmap); - struct xwl_screen *xwl_screen = xwl_screen_get(pixmap->drawable.pScreen); - - if (!xwl_screen->glamor || !xwl_pixmap) - return; - - if (xwl_pixmap->syncobj) { - xwl_pixmap->syncobj->free(xwl_pixmap->syncobj); - xwl_pixmap->syncobj = NULL; - } - - if (xwl_pixmap->efd >= 0) { - SetNotifyFd(xwl_pixmap->efd, NULL, 0, NULL); - close(xwl_pixmap->efd); - } -#endif /* DRI3 */ -} - -void -xwl_glamor_gbm_wait_syncpts(PixmapPtr pixmap) -{ -#ifdef DRI3 - struct xwl_screen *xwl_screen = xwl_screen_get(pixmap->drawable.pScreen); - struct xwl_pixmap *xwl_pixmap = xwl_pixmap_get(pixmap); - - if (!xwl_screen->glamor || !xwl_pixmap) - return; - - if (xwl_pixmap->syncobj) { - int fence_fd = xwl_pixmap->syncobj->export_fence(xwl_pixmap->syncobj, - xwl_pixmap->timeline_point); - - xwl_glamor_wait_fence(xwl_screen, fence_fd); - } -#endif /* DRI3 */ -} - -void -xwl_glamor_gbm_wait_release_fence(struct xwl_window *xwl_window, - PixmapPtr pixmap, - struct xwl_window_buffer *xwl_window_buffer) -{ -#ifdef DRI3 - struct xwl_pixmap *xwl_pixmap = xwl_pixmap_get(pixmap); - struct xwl_screen *xwl_screen = xwl_screen_get(pixmap->drawable.pScreen); - - if (!xwl_screen->glamor || !xwl_pixmap || !xwl_window_buffer) - return; - - xwl_pixmap->xwl_window_buffer = xwl_window_buffer; - /* wait until the release fence is available before re-using this buffer */ - xwl_pixmap->efd = eventfd(0, EFD_CLOEXEC); - SetNotifyFd(xwl_pixmap->efd, xwl_glamor_gbm_release_fence_avail, X_NOTIFY_READ, - xwl_pixmap); - xwl_pixmap->syncobj->submitted_eventfd(xwl_pixmap->syncobj, - xwl_pixmap->timeline_point, - xwl_pixmap->efd); -#endif /* DRI3 */ -} - -static Bool -xwl_glamor_try_to_make_context_current(struct xwl_screen *xwl_screen) -{ - if (xwl_screen->egl_context == EGL_NO_CONTEXT) - return FALSE; - - return eglMakeCurrent(xwl_screen->egl_display, EGL_NO_SURFACE, - EGL_NO_SURFACE, xwl_screen->egl_context); -} - -static void -xwl_glamor_maybe_destroy_context(struct xwl_screen *xwl_screen) -{ - if (xwl_screen->egl_context == EGL_NO_CONTEXT) - return; - - eglMakeCurrent(xwl_screen->egl_display, EGL_NO_SURFACE, - EGL_NO_SURFACE, EGL_NO_CONTEXT); - eglDestroyContext(xwl_screen->egl_display, xwl_screen->egl_context); - xwl_screen->egl_context = EGL_NO_CONTEXT; -} - -static Bool -xwl_glamor_try_big_gl_api(struct xwl_screen *xwl_screen) -{ - static const EGLint config_attribs_core[] = { - EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR, - EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR, - EGL_CONTEXT_MAJOR_VERSION_KHR, - GLAMOR_GL_CORE_VER_MAJOR, - EGL_CONTEXT_MINOR_VERSION_KHR, - GLAMOR_GL_CORE_VER_MINOR, - EGL_NONE - }; - int gl_version; - - if (!(xwl_screen->glamor & XWL_GLAMOR_GL)) - return FALSE; - - eglBindAPI(EGL_OPENGL_API); - - xwl_screen->egl_context = - eglCreateContext(xwl_screen->egl_display, EGL_NO_CONFIG_KHR, - EGL_NO_CONTEXT, config_attribs_core); - - if (xwl_screen->egl_context == EGL_NO_CONTEXT) - xwl_screen->egl_context = - eglCreateContext(xwl_screen->egl_display, EGL_NO_CONFIG_KHR, - EGL_NO_CONTEXT, NULL); - - if (!xwl_glamor_try_to_make_context_current(xwl_screen)) { - ErrorF("Failed to make EGL context current with GL\n"); - xwl_glamor_maybe_destroy_context(xwl_screen); - return FALSE; - } - - /* glamor needs at least GL 2.1, if the GL version is less than 2.1, - * drop the context we created, it's useless. - */ - gl_version = epoxy_gl_version(); - if (gl_version < 21) { - ErrorF("Supported GL version is not sufficient (required 21, found %i)\n", - gl_version); - xwl_glamor_maybe_destroy_context(xwl_screen); - return FALSE; - } - - return TRUE; -} - -static Bool -xwl_glamor_try_gles_api(struct xwl_screen *xwl_screen) -{ - const EGLint gles_attribs[] = { - EGL_CONTEXT_CLIENT_VERSION, - 2, - EGL_NONE, - }; - - if (!(xwl_screen->glamor & XWL_GLAMOR_GLES)) - return FALSE; - - eglBindAPI(EGL_OPENGL_ES_API); - - xwl_screen->egl_context = eglCreateContext(xwl_screen->egl_display, - EGL_NO_CONFIG_KHR, - EGL_NO_CONTEXT, gles_attribs); - - if (!xwl_glamor_try_to_make_context_current(xwl_screen)) { - ErrorF("Failed to make EGL context current with GLES2\n"); - xwl_glamor_maybe_destroy_context(xwl_screen); - return FALSE; - } - - return TRUE; -} - -static Bool -xwl_glamor_gbm_init_main_dev(struct xwl_screen *xwl_screen) -{ - struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen); - drmDevice *main_dev; - - while (!xwl_screen->default_feedback.feedback_done) { - if (wl_display_dispatch(xwl_screen->display) < 0) { - ErrorF("Failed to dispatch Wayland display\n"); - return FALSE; - } - } - - main_dev = xwl_screen->default_feedback.main_dev; - if (!main_dev) { - ErrorF("No main linux-dmabuf device advertised by compositor\n"); - return FALSE; - } - - if (!(main_dev->available_nodes & (1 << DRM_NODE_RENDER))) { - ErrorF("Main linux-dmabuf device has no render node\n"); - return FALSE; - } - - xwl_gbm->device_name = strdup(main_dev->nodes[DRM_NODE_RENDER]); - if (!xwl_gbm->device_name) { - return FALSE; - } - - xwl_gbm->drm_fd = open(xwl_gbm->device_name, O_RDWR | O_CLOEXEC); - if (xwl_gbm->drm_fd < 0) { - ErrorF("wayland-egl: could not open %s (%s)\n", - xwl_gbm->device_name, strerror(errno)); - return FALSE; - } - - if (drmGetDevice2(xwl_gbm->drm_fd, 0, &xwl_gbm->device) != 0) { - ErrorF("wayland-egl: Could not fetch DRM device %s\n", - xwl_gbm->device_name); - return FALSE; - } - - xwl_gbm->fd_render_node = TRUE; - return TRUE; -} - -Bool -xwl_glamor_gbm_init_egl(struct xwl_screen *xwl_screen) -{ - struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen); - EGLint major, minor; - const GLubyte *renderer; - const char *gbm_backend_name, *egl_vendor; - - if (!xwl_gbm->drm && !xwl_glamor_gbm_init_main_dev(xwl_screen)) - return FALSE; - - if (!xwl_gbm->fd_render_node && !xwl_gbm->drm_authenticated) { - ErrorF("Failed to get wl_drm, disabling Glamor and DRI3\n"); - return FALSE; - } - - xwl_gbm->gbm = gbm_create_device(xwl_gbm->drm_fd); - if (!xwl_gbm->gbm) { - ErrorF("couldn't create gbm device\n"); - goto error; - } - - xwl_screen->egl_display = glamor_egl_get_display(EGL_PLATFORM_GBM_MESA, - xwl_gbm->gbm); - if (xwl_screen->egl_display == EGL_NO_DISPLAY) { - ErrorF("glamor_egl_get_display() failed\n"); - goto error; - } - - if (!eglInitialize(xwl_screen->egl_display, &major, &minor)) { - ErrorF("eglInitialize() failed\n"); - goto error; - } - - if (!xwl_glamor_try_big_gl_api(xwl_screen) && - !xwl_glamor_try_gles_api(xwl_screen)) { - ErrorF("Cannot use neither GL nor GLES2\n"); - goto error; - } - - renderer = glGetString(GL_RENDERER); - if (!renderer) { - ErrorF("glGetString() returned NULL, your GL is broken\n"); - goto error; - } - if (strstr((const char *)renderer, "softpipe")) { - ErrorF("Refusing to try glamor on softpipe\n"); - goto error; - } - if (!strncmp("llvmpipe", (const char *)renderer, strlen("llvmpipe"))) { - ErrorF("Refusing to try glamor on llvmpipe\n"); - goto error; - } - - if (!epoxy_has_gl_extension("GL_OES_EGL_image")) { - ErrorF("GL_OES_EGL_image not available\n"); - goto error; - } - - if (epoxy_has_egl_extension(xwl_screen->egl_display, - "EXT_image_dma_buf_import") && - epoxy_has_egl_extension(xwl_screen->egl_display, - "EXT_image_dma_buf_import_modifiers")) - xwl_gbm->dmabuf_capable = TRUE; - - gbm_backend_name = gbm_device_get_backend_name(xwl_gbm->gbm); - /* Mesa uses "drm" as backend name, in that case, just do nothing */ - if (gbm_backend_name && strcmp(gbm_backend_name, "drm") != 0) - xwl_screen->glvnd_vendor = gbm_backend_name; - xwl_gbm->glamor_gles = !epoxy_is_desktop_gl(); - - egl_vendor = eglQueryString(xwl_screen->egl_display, EGL_VENDOR); - if (!egl_vendor) { - ErrorF("Could not determine EGL vendor\n"); - goto error; - } - /* NVIDIA driver does not support implicit sync */ - xwl_gbm->implicit_sync = !strstr(egl_vendor, "NVIDIA"); -#ifdef DRI3 - if (xwl_gbm_supports_syncobjs(xwl_screen) && - epoxy_has_egl_extension(xwl_screen->egl_display, - "ANDROID_native_fence_sync")) - xwl_gbm->supports_syncobjs = TRUE; - - if (!xwl_gbm->supports_syncobjs && xwl_screen->explicit_sync) { - /* explicit sync requires syncobj support */ - wp_linux_drm_syncobj_manager_v1_destroy(xwl_screen->explicit_sync); - xwl_screen->explicit_sync = NULL; - } -#endif /* DRI3 */ - return TRUE; -error: - if (xwl_screen->egl_display != EGL_NO_DISPLAY) { - xwl_glamor_maybe_destroy_context(xwl_screen); - eglTerminate(xwl_screen->egl_display); - xwl_screen->egl_display = EGL_NO_DISPLAY; - } - - xwl_glamor_gbm_cleanup(xwl_screen); - return FALSE; -} - -Bool -xwl_glamor_gbm_init_screen(struct xwl_screen *xwl_screen) -{ - struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen); -#ifdef DRI3 - if (xwl_gbm->supports_syncobjs) { - xwl_dri3_info.version = 4; - xwl_dri3_info.import_syncobj = xwl_dri3_import_syncobj; - } - - if (!dri3_screen_init(xwl_screen->screen, &xwl_dri3_info)) { - ErrorF("Failed to initialize dri3\n"); - goto error; - } -#endif /* DRI3 */ - if (xwl_gbm->fd_render_node) - goto skip_drm_auth; - - if (!dixRegisterPrivateKey(&xwl_auth_state_private_key, PRIVATE_CLIENT, - 0)) { - ErrorF("Failed to register private key\n"); - goto error; - } - - if (!AddCallback(&ClientStateCallback, xwl_auth_state_client_callback, - NULL)) { - ErrorF("Failed to add client state callback\n"); - goto error; - } - -skip_drm_auth: - xwl_screen->screen->CreatePixmap = xwl_glamor_gbm_create_pixmap; - xwl_screen->screen->DestroyPixmap = xwl_glamor_gbm_destroy_pixmap; - - return TRUE; -error: - xwl_glamor_gbm_cleanup(xwl_screen); - return FALSE; -} - -drmDevice *xwl_gbm_get_main_device(struct xwl_screen *xwl_screen) -{ - struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen); - - return xwl_gbm->device; -} - -Bool -xwl_glamor_init_gbm(struct xwl_screen *xwl_screen) -{ - struct xwl_gbm_private *xwl_gbm; - - if (!xwl_glamor_gbm_has_egl_extension()) - return FALSE; - - if (!dixRegisterPrivateKey(&xwl_gbm_private_key, PRIVATE_SCREEN, 0)) - return FALSE; - - xwl_gbm = calloc(1, sizeof(*xwl_gbm)); - if (!xwl_gbm) { - ErrorF("glamor: Not enough memory to setup GBM, disabling\n"); - return FALSE; - } - - dixSetPrivate(&xwl_screen->screen->devPrivates, &xwl_gbm_private_key, - xwl_gbm); - - return TRUE; -} diff --git a/hw/xwayland/xwayland-glamor-gbm.h b/hw/xwayland/xwayland-glamor-gbm.h deleted file mode 100644 index b346a0ba6..000000000 --- a/hw/xwayland/xwayland-glamor-gbm.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright © 2011-2014 Intel Corporation - * Copyright © 2024 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including - * the next paragraph) shall be included in all copies or substantial - * portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - */ - -#ifndef XWAYLAND_GLAMOR_GBM_H -#define XWAYLAND_GLAMOR_GBM_H - -#include - -#include - -#include - -#include "xwayland-types.h" - -Bool xwl_glamor_init_gbm(struct xwl_screen *xwl_screen); -Bool xwl_glamor_has_wl_drm(struct xwl_screen *xwl_screen); -Bool xwl_glamor_gbm_init_egl(struct xwl_screen *xwl_screen); -Bool xwl_glamor_gbm_init_screen(struct xwl_screen *xwl_screen); -drmDevice *xwl_gbm_get_main_device(struct xwl_screen *xwl_screen); - -/* Explicit buffer synchronization points */ -Bool xwl_glamor_gbm_set_syncpts(struct xwl_window *xwl_window, PixmapPtr pixmap); -void xwl_glamor_gbm_dispose_syncpts(PixmapPtr pixmap); -void xwl_glamor_gbm_wait_syncpts(PixmapPtr pixmap); -void xwl_glamor_gbm_wait_release_fence(struct xwl_window *xwl_window, - PixmapPtr pixmap, - struct xwl_window_buffer *xwl_window_buffer); - -#endif /* XWAYLAND_GLAMOR_GBM_H */ diff --git a/hw/xwayland/xwayland-glamor-xv.c b/hw/xwayland/xwayland-glamor-xv.c deleted file mode 100644 index 6ecbe822f..000000000 --- a/hw/xwayland/xwayland-glamor-xv.c +++ /dev/null @@ -1,416 +0,0 @@ -/* - * Copyright (c) 1998-2003 by The XFree86 Project, Inc. - * Copyright © 2013 Red Hat - * Copyright © 2014 Intel Corporation - * Copyright © 2016 Red Hat - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - * - * Authors: - * Olivier Fourdan - * - * Derived from the glamor_xf86_xv, ephyr_glamor_xv and xf86xv - * implementations - */ - -#include - -#include - -#include "dix/screen_hooks_priv.h" -#include "Xext/xvdix_priv.h" - -#include "glamor_priv.h" -#include "xwayland-glamor.h" - -#define NUM_FORMATS 3 -#define NUM_PORTS 16 -#define ADAPTOR_NAME "glamor textured video" -#define ENCODER_NAME "XV_IMAGE" - -static DevPrivateKeyRec xwlXvScreenPrivateKeyRec; -#define xwlXvScreenPrivateKey (&xwlXvScreenPrivateKeyRec) - -typedef struct { - XvAdaptorPtr glxv_adaptor; /* We have only one adaptor, glamor Xv */ - glamor_port_private *port_privates; -} xwlXvScreenRec, *xwlXvScreenPtr; - -typedef struct { - char depth; - short class; -} xwlVideoFormatRec, *xwlVideoFormatPtr; - -static xwlVideoFormatRec Formats[NUM_FORMATS] = { - {15, TrueColor}, - {16, TrueColor}, - {24, TrueColor} -}; - -static int -xwl_glamor_xv_stop_video(XvPortPtr pPort, - DrawablePtr pDraw) -{ - glamor_port_private *gpp = (glamor_port_private *) (pPort->devPriv.ptr); - - if (pDraw->type != DRAWABLE_WINDOW) - return BadAlloc; - - glamor_xv_stop_video(gpp); - - return Success; -} - -static int -xwl_glamor_xv_set_port_attribute(XvPortPtr pPort, - Atom attribute, - INT32 value) -{ - glamor_port_private *gpp = (glamor_port_private *) (pPort->devPriv.ptr); - - return glamor_xv_set_port_attribute(gpp, attribute, value); -} - -static int -xwl_glamor_xv_get_port_attribute(XvPortPtr pPort, - Atom attribute, - INT32 *pValue) -{ - glamor_port_private *gpp = (glamor_port_private *) (pPort->devPriv.ptr); - - return glamor_xv_get_port_attribute(gpp, attribute, pValue); -} - -static int -xwl_glamor_xv_query_best_size(XvPortPtr pPort, - CARD8 motion, - CARD16 vid_w, - CARD16 vid_h, - CARD16 drw_w, - CARD16 drw_h, - unsigned int *p_w, - unsigned int *p_h) -{ - *p_w = drw_w; - *p_h = drw_h; - - return Success; -} - -static int -xwl_glamor_xv_query_image_attributes(XvPortPtr pPort, - XvImagePtr format, - CARD16 *width, - CARD16 *height, - int *pitches, - int *offsets) -{ - return glamor_xv_query_image_attributes(format->id, - width, - height, - pitches, - offsets); -} - -static int -xwl_glamor_xv_put_image(DrawablePtr pDrawable, - XvPortPtr pPort, - GCPtr pGC, - INT16 src_x, - INT16 src_y, - CARD16 src_w, - CARD16 src_h, - INT16 drw_x, - INT16 drw_y, - CARD16 drw_w, - CARD16 drw_h, - XvImagePtr format, - unsigned char *data, - Bool sync, - CARD16 width, - CARD16 height) -{ - glamor_port_private *gpp = (glamor_port_private *) (pPort->devPriv.ptr); - - RegionRec WinRegion; - RegionRec ClipRegion; - BoxRec WinBox; - int ret = Success; - - if (pDrawable->type != DRAWABLE_WINDOW) - return BadWindow; - - WinBox.x1 = pDrawable->x + drw_x; - WinBox.y1 = pDrawable->y + drw_y; - WinBox.x2 = WinBox.x1 + drw_w; - WinBox.y2 = WinBox.y1 + drw_h; - - RegionInit(&WinRegion, &WinBox, 1); - RegionInit(&ClipRegion, NullBox, 1); - RegionIntersect(&ClipRegion, &WinRegion, pGC->pCompositeClip); - - if (RegionNotEmpty(&ClipRegion)) - ret = glamor_xv_put_image(gpp, - pDrawable, - src_x, - src_y, - pDrawable->x + drw_x, - pDrawable->y + drw_y, - src_w, - src_h, - drw_w, - drw_h, - format->id, - data, - width, - height, - sync, - &ClipRegion); - - RegionUninit(&WinRegion); - RegionUninit(&ClipRegion); - - return ret; - -} - -static Bool -xwl_glamor_xv_add_formats(XvAdaptorPtr pa) -{ - ScreenPtr pScreen; - XvFormatPtr pFormat, pf; - VisualPtr pVisual; - int numFormat; - int totFormat; - int numVisuals; - int i; - - totFormat = NUM_FORMATS; - pFormat = XNFcallocarray(totFormat, sizeof(XvFormatRec)); - pScreen = pa->pScreen; - for (pf = pFormat, i = 0, numFormat = 0; i < NUM_FORMATS; i++) { - numVisuals = pScreen->numVisuals; - pVisual = pScreen->visuals; - - while (numVisuals--) { - if ((pVisual->class == Formats[i].class) && - (pVisual->nplanes == Formats[i].depth)) { - if (numFormat >= totFormat) { - void *moreSpace; - - totFormat *= 2; - moreSpace = XNFreallocarray(pFormat, totFormat, - sizeof(XvFormatRec)); - pFormat = moreSpace; - pf = pFormat + numFormat; - } - - pf->visual = pVisual->vid; - pf->depth = Formats[i].depth; - - pf++; - numFormat++; - } - pVisual++; - } - } - pa->nFormats = numFormat; - pa->pFormats = pFormat; - - return numFormat != 0; -} - -static Bool -xwl_glamor_xv_add_ports(XvAdaptorPtr pa) -{ - XvPortPtr pPorts, pp; - xwlXvScreenPtr xwlXvScreen; - unsigned long PortResource = 0; - int nPorts; - int i; - - pPorts = XNFcallocarray(NUM_PORTS, sizeof(XvPortRec)); - xwlXvScreen = dixLookupPrivate(&(pa->pScreen)->devPrivates, - xwlXvScreenPrivateKey); - xwlXvScreen->port_privates = XNFcallocarray(NUM_PORTS, - sizeof(glamor_port_private)); - - PortResource = XvGetRTPort(); - for (pp = pPorts, i = 0, nPorts = 0; i < NUM_PORTS; i++) { - if (!(pp->id = dixAllocServerXID())) - continue; - - pp->pAdaptor = pa; - - glamor_xv_init_port(&xwlXvScreen->port_privates[i]); - pp->devPriv.ptr = &xwlXvScreen->port_privates[i]; - - if (AddResource(pp->id, PortResource, pp)) { - pp++; - nPorts++; - } - } - - pa->base_id = pPorts->id; - pa->nPorts = nPorts; - pa->pPorts = pPorts; - - return nPorts != 0; -} - -static void -xwl_glamor_xv_add_attributes(XvAdaptorPtr pa) -{ - int i; - - pa->pAttributes = XNFcallocarray(glamor_xv_num_attributes, sizeof(XvAttributeRec)); - memcpy(pa->pAttributes, glamor_xv_attributes, - glamor_xv_num_attributes * sizeof(XvAttributeRec)); - - for (i = 0; i < glamor_xv_num_attributes; i++) - pa->pAttributes[i].name = strdup(glamor_xv_attributes[i].name); - - pa->nAttributes = glamor_xv_num_attributes; -} - -static void -xwl_glamor_xv_add_images(XvAdaptorPtr pa) -{ - pa->pImages = XNFcallocarray(glamor_xv_num_images, sizeof(XvImageRec)); - memcpy(pa->pImages, glamor_xv_images, glamor_xv_num_images * sizeof(XvImageRec)); - - pa->nImages = glamor_xv_num_images; -} - -static void -xwl_glamor_xv_add_encodings(XvAdaptorPtr pa) -{ - XvEncodingPtr pe; - GLint texsize; - - glGetIntegerv(GL_MAX_TEXTURE_SIZE, &texsize); - - pe = XNFcallocarray(1, sizeof(XvEncodingRec)); - pe->id = 0; - pe->pScreen = pa->pScreen; - pe->name = strdup(ENCODER_NAME); - pe->width = texsize; - pe->height = texsize; - pe->rate.numerator = 1; - pe->rate.denominator = 1; - - pa->pEncodings = pe; - pa->nEncodings = 1; -} - -static Bool -xwl_glamor_xv_add_adaptors(ScreenPtr pScreen) -{ - DevPrivateKey XvScreenKey; - XvScreenPtr XvScreen; - xwlXvScreenPtr xwlXvScreen; - XvAdaptorPtr pa; - - if (XvScreenInit(pScreen) != Success) - return FALSE; - - XvScreenKey = XvGetScreenKey(); - XvScreen = dixLookupPrivate(&(pScreen)->devPrivates, XvScreenKey); - - XvScreen->nAdaptors = 0; - XvScreen->pAdaptors = NULL; - - pa = XNFcallocarray(1, sizeof(XvAdaptorRec)); - pa->pScreen = pScreen; - pa->type = (unsigned char) (XvInputMask | XvImageMask); - pa->ddStopVideo = xwl_glamor_xv_stop_video; - pa->ddPutImage = xwl_glamor_xv_put_image; - pa->ddSetPortAttribute = xwl_glamor_xv_set_port_attribute; - pa->ddGetPortAttribute = xwl_glamor_xv_get_port_attribute; - pa->ddQueryBestSize = xwl_glamor_xv_query_best_size; - pa->ddQueryImageAttributes = xwl_glamor_xv_query_image_attributes; - pa->name = strdup(ADAPTOR_NAME); - - xwl_glamor_xv_add_encodings(pa); - xwl_glamor_xv_add_images(pa); - xwl_glamor_xv_add_attributes(pa); - if (!xwl_glamor_xv_add_formats(pa)) - goto failed; - if (!xwl_glamor_xv_add_ports(pa)) - goto failed; - - /* We're good now with out Xv adaptor */ - XvScreen->nAdaptors = 1; - XvScreen->pAdaptors = pa; - - xwlXvScreen = dixLookupPrivate(&(pa->pScreen)->devPrivates, - xwlXvScreenPrivateKey); - xwlXvScreen->glxv_adaptor = pa; - - return TRUE; - -failed: - XvFreeAdaptor(pa); - free(pa); - - return FALSE; -} - -static void xwl_glamor_xv_close_screen(CallbackListPtr *pcbl, - ScreenPtr pScreen, void *unused) -{ - dixScreenUnhookClose(pScreen, xwl_glamor_xv_close_screen); - - xwlXvScreenPtr xwlXvScreen; - xwlXvScreen = dixLookupPrivate(&(pScreen)->devPrivates, - xwlXvScreenPrivateKey); - - if (!xwlXvScreen) - return; - - if (xwlXvScreen->glxv_adaptor) { - XvFreeAdaptor(xwlXvScreen->glxv_adaptor); - free(xwlXvScreen->glxv_adaptor); - } - free(xwlXvScreen->port_privates); - dixSetPrivate(&(pScreen)->devPrivates, xwlXvScreenPrivateKey, NULL); -} - -Bool -xwl_glamor_xv_init(ScreenPtr pScreen) -{ - xwlXvScreenPtr xwlXvScreen; - - if (!dixRegisterPrivateKey(xwlXvScreenPrivateKey, PRIVATE_SCREEN, - sizeof(xwlXvScreenRec))) - return FALSE; - - xwlXvScreen = dixLookupPrivate(&(pScreen)->devPrivates, - xwlXvScreenPrivateKey); - - xwlXvScreen->port_privates = NULL; - xwlXvScreen->glxv_adaptor = NULL; - - dixScreenHookClose(pScreen, xwl_glamor_xv_close_screen); - - glamor_xv_core_init(pScreen); - - return xwl_glamor_xv_add_adaptors(pScreen); -} diff --git a/hw/xwayland/xwayland-glamor.c b/hw/xwayland/xwayland-glamor.c deleted file mode 100644 index a20aa78cf..000000000 --- a/hw/xwayland/xwayland-glamor.c +++ /dev/null @@ -1,267 +0,0 @@ -/* - * Copyright © 2011-2014 Intel Corporation - * - * Permission to use, copy, modify, distribute, and sell this software - * and its documentation for any purpose is hereby granted without - * fee, provided that the above copyright notice appear in all copies - * and that both that copyright notice and this permission notice - * appear in supporting documentation, and that the name of the - * copyright holders not be used in advertising or publicity - * pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied - * warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS - * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. - */ - -#include - -#include "glamor/glamor_priv.h" - -#define MESA_EGL_NO_X11_HEADERS -#define EGL_NO_X11 -#include - -#include -#include -#include -#ifdef GLXEXT -#include "glx_extinit.h" -#endif - -#include "drm-client-protocol.h" -#include "linux-dmabuf-unstable-v1-client-protocol.h" -#include "linux-drm-syncobj-v1-client-protocol.h" - -#include "mi/mi_priv.h" - -#include "xwayland-dmabuf.h" -#include "xwayland-glamor.h" -#include "xwayland-glamor-gbm.h" -#include "xwayland-present.h" -#include "xwayland-screen.h" -#include "xwayland-window.h" -#include "xwayland-window-buffers.h" - -#include - -static void -glamor_egl_make_current(struct glamor_context *glamor_ctx) -{ - eglMakeCurrent(glamor_ctx->display, EGL_NO_SURFACE, - EGL_NO_SURFACE, EGL_NO_CONTEXT); - if (!eglMakeCurrent(glamor_ctx->display, - EGL_NO_SURFACE, EGL_NO_SURFACE, - glamor_ctx->ctx)) - FatalError("Failed to make EGL context current\n"); -} - -void -xwl_glamor_egl_make_current(struct xwl_screen *xwl_screen) -{ - EGLContext ctx = xwl_screen->glamor_ctx->ctx; - - if (lastGLContext == ctx) - return; - - lastGLContext = ctx; - xwl_screen->glamor_ctx->make_current(xwl_screen->glamor_ctx); -} - -void -glamor_egl_screen_init(ScreenPtr screen, struct glamor_context *glamor_ctx) -{ - struct xwl_screen *xwl_screen = xwl_screen_get(screen); - - glamor_set_glvnd_vendor(screen, xwl_screen->glvnd_vendor); - glamor_enable_dri3(screen); - glamor_ctx->ctx = xwl_screen->egl_context; - glamor_ctx->display = xwl_screen->egl_display; - - glamor_ctx->make_current = glamor_egl_make_current; - - xwl_screen->glamor_ctx = glamor_ctx; -} - -Bool -xwl_glamor_check_flip(WindowPtr present_window, PixmapPtr pixmap) -{ - ScreenPtr screen = pixmap->drawable.pScreen; - PixmapPtr backing_pixmap = screen->GetWindowPixmap(present_window); - struct xwl_window *xwl_window = xwl_window_from_window(present_window); - WindowPtr surface_window = xwl_window->surface_window; - - if (pixmap->drawable.depth != backing_pixmap->drawable.depth) { - if (pixmap->drawable.depth == 32) - return FALSE; - - return xwl_present_maybe_redirect_window(present_window); - } - - if (surface_window->redirectDraw == RedirectDrawAutomatic && - surface_window->drawable.depth != 32 && - surface_window->parent->drawable.depth == 32) - xwl_present_maybe_redirect_window(surface_window); - - return TRUE; -} - -void -xwl_glamor_init_wl_registry(struct xwl_screen *xwl_screen, - struct wl_registry *registry, - uint32_t id, const char *interface, - uint32_t version) -{ - if (strcmp(interface, wl_drm_interface.name) == 0) - xwl_screen_set_drm_interface(xwl_screen, id, version); - else if (strcmp(interface, zwp_linux_dmabuf_v1_interface.name) == 0) - xwl_screen_set_dmabuf_interface(xwl_screen, id, version); - else if (strcmp(interface, wp_linux_drm_syncobj_manager_v1_interface.name) == 0) - xwl_screen_set_syncobj_interface(xwl_screen, id, version); -} - -static Bool -xwl_glamor_has_wl_interfaces(struct xwl_screen *xwl_screen) -{ - if (!xwl_glamor_has_wl_drm(xwl_screen) && - xwl_screen->dmabuf_protocol_version < 4) { - LogMessageVerb(X_INFO, 3, "glamor: 'wl_drm' not supported and linux-dmabuf v4 not supported\n"); - return FALSE; - } - - return TRUE; -} - -static Bool -xwl_glamor_create_screen_resources(ScreenPtr screen) -{ - struct xwl_screen *xwl_screen = xwl_screen_get(screen); - - if (!miCreateScreenResources(screen)) - return FALSE; - - if (xwl_screen->rootless) { - screen->devPrivate = - fbCreatePixmap(screen, 0, 0, screen->rootDepth, 0); - } - else { - screen->devPrivate = screen->CreatePixmap( - screen, screen->width, screen->height, screen->rootDepth, - CREATE_PIXMAP_USAGE_BACKING_PIXMAP); - } - - SetRootClip(screen, xwl_screen->root_clip_mode); - - return screen->devPrivate != NULL; -} - -int -glamor_egl_fd_name_from_pixmap(ScreenPtr screen, - PixmapPtr pixmap, - CARD16 *stride, CARD32 *size) -{ - return 0; -} - -int -xwl_glamor_get_fence(struct xwl_screen *xwl_screen) -{ - EGLint attribs[3]; - EGLSyncKHR sync; - int fence_fd = -1; - - if (!xwl_screen->glamor) - return -1; - - xwl_glamor_egl_make_current(xwl_screen); - - attribs[0] = EGL_SYNC_NATIVE_FENCE_FD_ANDROID; - attribs[1] = EGL_NO_NATIVE_FENCE_FD_ANDROID; - attribs[2] = EGL_NONE; - sync = eglCreateSyncKHR(xwl_screen->egl_display, EGL_SYNC_NATIVE_FENCE_ANDROID, attribs); - if (sync != EGL_NO_SYNC_KHR) { - fence_fd = eglDupNativeFenceFDANDROID(xwl_screen->egl_display, sync); - eglDestroySyncKHR(xwl_screen->egl_display, sync); - } - - return fence_fd; -} - -/* Takes ownership of fence_fd, specifically eglCreateSyncKHR does */ -void -xwl_glamor_wait_fence(struct xwl_screen *xwl_screen, int fence_fd) -{ - EGLint attribs[3]; - EGLSyncKHR sync; - - if (!xwl_screen->glamor) { - close(fence_fd); - return; - } - - xwl_glamor_egl_make_current(xwl_screen); - - attribs[0] = EGL_SYNC_NATIVE_FENCE_FD_ANDROID; - attribs[1] = fence_fd; - attribs[2] = EGL_NONE; - sync = eglCreateSyncKHR(xwl_screen->egl_display, EGL_SYNC_NATIVE_FENCE_ANDROID, attribs); - if (sync != EGL_NO_SYNC_KHR) { - eglWaitSyncKHR(xwl_screen->egl_display, sync, 0); - eglDestroySyncKHR(xwl_screen->egl_display, sync); - } -} - -Bool -xwl_glamor_init(struct xwl_screen *xwl_screen) -{ - ScreenPtr screen = xwl_screen->screen; - const char *no_glamor_env; - - no_glamor_env = getenv("XWAYLAND_NO_GLAMOR"); - if (no_glamor_env && *no_glamor_env != '0') { - ErrorF("Disabling glamor and dri3 support, XWAYLAND_NO_GLAMOR is set\n"); - return FALSE; - } - - if (!xwl_glamor_has_wl_interfaces(xwl_screen)) { - ErrorF("Xwayland glamor: GBM Wayland interfaces not available\n"); - return FALSE; - } - - if (!xwl_glamor_gbm_init_egl(xwl_screen)) { - ErrorF("EGL setup failed, disabling glamor\n"); - return FALSE; - } - - if (!glamor_init(xwl_screen->screen, GLAMOR_USE_EGL_SCREEN)) { - ErrorF("Failed to initialize glamor\n"); - return FALSE; - } - - if (!xwl_glamor_gbm_init_screen(xwl_screen)) { - ErrorF("EGL backend init_screen() failed, disabling glamor\n"); - return FALSE; - } - - screen->CreateScreenResources = xwl_glamor_create_screen_resources; - -#ifdef XV - if (!xwl_glamor_xv_init(screen)) - ErrorF("Failed to initialize glamor Xv extension\n"); -#endif - -#ifdef GLXEXT - GlxPushProvider(&glamor_provider); -#endif - - return TRUE; -} diff --git a/hw/xwayland/xwayland-glamor.h b/hw/xwayland/xwayland-glamor.h deleted file mode 100644 index ef312a857..000000000 --- a/hw/xwayland/xwayland-glamor.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright © 2011-2014 Intel Corporation - * - * Permission to use, copy, modify, distribute, and sell this software - * and its documentation for any purpose is hereby granted without - * fee, provided that the above copyright notice appear in all copies - * and that both that copyright notice and this permission notice - * appear in supporting documentation, and that the name of the - * copyright holders not be used in advertising or publicity - * pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied - * warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS - * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. - */ - -#ifndef XWAYLAND_GLAMOR_H -#define XWAYLAND_GLAMOR_H - -#include - -#include - -#include -#include - -#include "xwayland-types.h" -#include "xwayland-glamor-gbm.h" -#include "dri3.h" - -typedef enum _xwl_glamor_mode_flags{ - XWL_GLAMOR_NONE = 0, - XWL_GLAMOR_GL = (1 << 0), - XWL_GLAMOR_GLES = (1 << 1), - XWL_GLAMOR_DEFAULT = XWL_GLAMOR_GL | XWL_GLAMOR_GLES, -} xwl_glamor_mode_flags; - -#ifdef XWL_HAS_GLAMOR - -Bool xwl_glamor_init(struct xwl_screen *xwl_screen); - -Bool xwl_screen_set_drm_interface(struct xwl_screen *xwl_screen, - uint32_t id, uint32_t version); -Bool xwl_screen_set_syncobj_interface(struct xwl_screen *xwl_screen, - uint32_t id, uint32_t version); -struct wl_buffer *xwl_glamor_pixmap_get_wl_buffer(PixmapPtr pixmap); -void xwl_glamor_init_wl_registry(struct xwl_screen *xwl_screen, - struct wl_registry *registry, - uint32_t id, const char *interface, - uint32_t version); -void xwl_glamor_egl_make_current(struct xwl_screen *xwl_screen); -Bool xwl_glamor_check_flip(WindowPtr present_window, PixmapPtr pixmap); -PixmapPtr xwl_glamor_create_pixmap_for_window (struct xwl_window *xwl_window); -Bool xwl_glamor_supports_implicit_sync(struct xwl_screen *xwl_screen); -void xwl_glamor_dmabuf_import_sync_file(PixmapPtr pixmap, int sync_file); -int xwl_glamor_dmabuf_export_sync_file(PixmapPtr pixmap); -Bool xwl_glamor_supports_syncobjs(struct xwl_screen *xwl_screen); -int xwl_glamor_get_fence(struct xwl_screen *screen); -void xwl_glamor_wait_fence(struct xwl_screen *xwl_screen, int fence); -struct dri3_syncobj *xwl_glamor_dri3_syncobj_create(struct xwl_screen *xwl_screen); -void xwl_glamor_dri3_syncobj_passthrough(struct xwl_window *xwl_window, - struct dri3_syncobj *acquire_syncobj, - struct dri3_syncobj *release_syncobj, - uint64_t acquire_point, - uint64_t release_point); - -#ifdef XV -/* glamor Xv Adaptor */ -Bool xwl_glamor_xv_init(ScreenPtr pScreen); -#endif /* XV */ - -#endif /* XWL_HAS_GLAMOR */ - -#endif /* XWAYLAND_GLAMOR_H */ diff --git a/hw/xwayland/xwayland-input.c b/hw/xwayland/xwayland-input.c deleted file mode 100644 index c3e1ae760..000000000 --- a/hw/xwayland/xwayland-input.c +++ /dev/null @@ -1,3663 +0,0 @@ -/* - * Copyright © 2014 Intel Corporation - * Copyright © 2008 Kristian Høgsberg - * - * Permission to use, copy, modify, distribute, and sell this software - * and its documentation for any purpose is hereby granted without - * fee, provided that the above copyright notice appear in all copies - * and that both that copyright notice and this permission notice - * appear in supporting documentation, and that the name of the - * copyright holders not be used in advertising or publicity - * pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied - * warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS - * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. - */ - -#include - -#include -#include - -#include "dix/dix_priv.h" -#include "dix/exevents_priv.h" -#include "dix/input_priv.h" -#include "mi/mi_priv.h" -#include "mi/mipointer_priv.h" -#include "os/bug_priv.h" -#include "os/log_priv.h" -#include "xkb/xkbsrv_priv.h" - -#include -#include -#include -#include -#include -#include - -#include "xwayland-cursor.h" -#include "xwayland-input.h" -#include "xwayland-window.h" -#include "xwayland-screen.h" - -#ifdef XWL_HAS_EI -#include "xwayland-xtest.h" -#endif - -#include "pointer-constraints-unstable-v1-client-protocol.h" -#include "relative-pointer-unstable-v1-client-protocol.h" -#include "tablet-unstable-v2-client-protocol.h" -#include "pointer-gestures-unstable-v1-client-protocol.h" -#include "xwayland-keyboard-grab-unstable-v1-client-protocol.h" -#include "keyboard-shortcuts-inhibit-unstable-v1-client-protocol.h" -#include "xdg-system-bell-v1-client-protocol.h" - -#define SCROLL_AXIS_HORIZ 2 -#define SCROLL_AXIS_VERT 3 - -struct sync_pending { - struct xorg_list l; - DeviceIntPtr pending_dev; -}; - -static DevPrivateKeyRec xwl_tablet_private_key; - -static void -xwl_pointer_warp_emulator_handle_motion(struct xwl_pointer_warp_emulator *warp_emulator, - double dx, - double dy, - double dx_unaccel, - double dy_unaccel); -static void -xwl_pointer_warp_emulator_maybe_lock(struct xwl_pointer_warp_emulator *warp_emulator, - struct xwl_window *xwl_window, - SpritePtr sprite, - int x, int y); - -static Bool -xwl_seat_maybe_lock_on_hidden_cursor(struct xwl_seat *xwl_seat); - -static void -xwl_seat_destroy_confined_pointer(struct xwl_seat *xwl_seat); - -static void -init_tablet_manager_seat(struct xwl_screen *xwl_screen, - struct xwl_seat *xwl_seat); -static void -release_tablet_manager_seat(struct xwl_seat *xwl_seat); - -static void -xwl_pointer_control(DeviceIntPtr device, PtrCtrl *ctrl) -{ - /* Nothing to do, dix handles all settings */ -} - -static DeviceIntPtr -get_pointer_device(struct xwl_seat *xwl_seat) -{ - if (xwl_seat->relative_pointer) - return xwl_seat->relative_pointer; - else - return xwl_seat->pointer; -} - -static Bool -init_pointer_buttons(DeviceIntPtr device) -{ -#define NBUTTONS 10 - BYTE map[NBUTTONS + 1]; - int i = 0; - Atom btn_labels[NBUTTONS] = { 0 }; - - for (i = 1; i <= NBUTTONS; i++) - map[i] = i; - - btn_labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT); - btn_labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE); - btn_labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT); - btn_labels[3] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_UP); - btn_labels[4] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_DOWN); - btn_labels[5] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_LEFT); - btn_labels[6] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_RIGHT); - /* don't know about the rest */ - - if (!InitButtonClassDeviceStruct(device, NBUTTONS, btn_labels, map)) - return FALSE; - - return TRUE; -} - -static void -maybe_fake_grab_devices(struct xwl_seat *xwl_seat) -{ - struct xwl_screen *xwl_screen = xwl_seat->xwl_screen; - struct xwl_window *xwl_window; - - if (xwl_screen->rootless) - return; - - if (!xwl_screen->host_grab) - return; - - if (!xwl_screen->has_grab) - return; - - if (!xwl_screen->screen->root) - return; - - xwl_window = xwl_window_get(xwl_screen->screen->root); - if (!xwl_window) - return; - - xwl_seat_confine_pointer(xwl_seat, xwl_window); - - if (!xwl_screen->shortcuts_inhibit_manager) - return; - - if (xwl_screen->shortcuts_inhibit) - return; - - xwl_screen->shortcuts_inhibit = - zwp_keyboard_shortcuts_inhibit_manager_v1_inhibit_shortcuts ( - xwl_screen->shortcuts_inhibit_manager, - xwl_window->surface, - xwl_seat->seat); -} - -static void -maybe_fake_ungrab_devices(struct xwl_seat *xwl_seat) -{ - struct xwl_screen *xwl_screen = xwl_seat->xwl_screen; - - xwl_seat_unconfine_pointer(xwl_seat); - - if (!xwl_screen->shortcuts_inhibit) - return; - - zwp_keyboard_shortcuts_inhibitor_v1_destroy (xwl_screen->shortcuts_inhibit); - xwl_screen->shortcuts_inhibit = NULL; -} - -static int -xwl_pointer_proc(DeviceIntPtr device, int what) -{ -#define NAXES 4 - Atom axes_labels[NAXES] = { 0 }; - - switch (what) { - case DEVICE_INIT: - device->public.on = FALSE; - - if (!init_pointer_buttons(device)) - return BadValue; - - axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_X); - axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_Y); - axes_labels[SCROLL_AXIS_HORIZ] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_HWHEEL); - axes_labels[SCROLL_AXIS_VERT] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_WHEEL); - - if (!InitValuatorClassDeviceStruct(device, NAXES, axes_labels, - GetMotionHistorySize(), Absolute)) - return BadValue; - - /* Valuators */ - InitValuatorAxisStruct(device, 0, axes_labels[0], - 0, 0xFFFF, 10000, 0, 10000, Absolute); - InitValuatorAxisStruct(device, 1, axes_labels[1], - 0, 0xFFFF, 10000, 0, 10000, Absolute); - InitValuatorAxisStruct(device, SCROLL_AXIS_HORIZ, axes_labels[2], - NO_AXIS_LIMITS, NO_AXIS_LIMITS, 0, 0, 0, Relative); - InitValuatorAxisStruct(device, SCROLL_AXIS_VERT, axes_labels[3], - NO_AXIS_LIMITS, NO_AXIS_LIMITS, 0, 0, 0, Relative); - - SetScrollValuator(device, SCROLL_AXIS_HORIZ, SCROLL_TYPE_HORIZONTAL, 1.0, SCROLL_FLAG_NONE); - SetScrollValuator(device, SCROLL_AXIS_VERT, SCROLL_TYPE_VERTICAL, 1.0, SCROLL_FLAG_PREFERRED); - - if (!InitPtrFeedbackClassDeviceStruct(device, xwl_pointer_control)) - return BadValue; - - return Success; - - case DEVICE_ON: - device->public.on = TRUE; - return Success; - - case DEVICE_OFF: - case DEVICE_CLOSE: - device->public.on = FALSE; - return Success; - } - - return BadMatch; - -#undef NBUTTONS -#undef NAXES -} - -static int -xwl_pointer_proc_relative(DeviceIntPtr device, int what) -{ -#define NAXES 4 - Atom axes_labels[NAXES] = { 0 }; - - switch (what) { - case DEVICE_INIT: - device->public.on = FALSE; - - axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X); - axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y); - axes_labels[2] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_HWHEEL); - axes_labels[3] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_WHEEL); - - /* - * We'll never send buttons, but XGetPointerMapping might in certain - * situations make the client think we have no buttons. - */ - if (!init_pointer_buttons(device)) - return BadValue; - - if (!InitValuatorClassDeviceStruct(device, NAXES, axes_labels, - GetMotionHistorySize(), Relative)) - return BadValue; - - /* Valuators */ - InitValuatorAxisStruct(device, 0, axes_labels[0], - NO_AXIS_LIMITS, NO_AXIS_LIMITS, 0, 0, 0, Relative); - InitValuatorAxisStruct(device, 1, axes_labels[1], - NO_AXIS_LIMITS, NO_AXIS_LIMITS, 0, 0, 0, Relative); - InitValuatorAxisStruct(device, 2, axes_labels[2], - NO_AXIS_LIMITS, NO_AXIS_LIMITS, 0, 0, 0, Relative); - InitValuatorAxisStruct(device, 3, axes_labels[3], - NO_AXIS_LIMITS, NO_AXIS_LIMITS, 0, 0, 0, Relative); - - SetScrollValuator(device, 2, SCROLL_TYPE_HORIZONTAL, 1.0, SCROLL_FLAG_NONE); - SetScrollValuator(device, 3, SCROLL_TYPE_VERTICAL, 1.0, SCROLL_FLAG_PREFERRED); - - if (!InitPtrFeedbackClassDeviceStruct(device, xwl_pointer_control)) - return BadValue; - - return Success; - - case DEVICE_ON: - device->public.on = TRUE; - return Success; - - case DEVICE_OFF: - case DEVICE_CLOSE: - device->public.on = FALSE; - return Success; - } - - return BadMatch; - -#undef NAXES -} - -static int -xwl_pointer_proc_pointer_gestures(DeviceIntPtr device, int what) -{ -#define NTOUCHPOINTS 20 -#define NAXES 2 - Atom axes_labels[NAXES] = { 0 }; - - switch (what) { - case DEVICE_INIT: - device->public.on = FALSE; - - /* We need to setup a pointer device so that the device is attached to - master pointer device. - */ - axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X); - axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y); - - /* - * We'll never send buttons, but XGetPointerMapping might in certain - * situations make the client think we have no buttons. - */ - if (!init_pointer_buttons(device)) - return BadValue; - - if (!InitValuatorClassDeviceStruct(device, NAXES, axes_labels, - GetMotionHistorySize(), Relative)) - return BadValue; - - InitValuatorAxisStruct(device, 0, axes_labels[0], - NO_AXIS_LIMITS, NO_AXIS_LIMITS, 0, 0, 0, Relative); - InitValuatorAxisStruct(device, 1, axes_labels[1], - NO_AXIS_LIMITS, NO_AXIS_LIMITS, 0, 0, 0, Relative); - - InitGestureClassDeviceStruct(device, NTOUCHPOINTS); - return Success; - - case DEVICE_ON: - device->public.on = TRUE; - return Success; - - case DEVICE_OFF: - case DEVICE_CLOSE: - device->public.on = FALSE; - return Success; - } - - return BadMatch; - -#undef NTOUCHPOINTS -#undef NAXES -} - -static void -xwl_keyboard_control(DeviceIntPtr device, KeybdCtrl *ctrl) -{ -} - -static int -xwl_keyboard_proc(DeviceIntPtr device, int what) -{ - struct xwl_seat *xwl_seat = device->public.devicePrivate; - int len; - - switch (what) { - case DEVICE_INIT: - device->public.on = FALSE; - if (xwl_seat->keymap) - len = strnlen(xwl_seat->keymap, xwl_seat->keymap_size); - else - len = 0; - if (!InitKeyboardDeviceStructFromString(device, xwl_seat->keymap, - len, - NULL, xwl_keyboard_control)) - return BadValue; - - return Success; - case DEVICE_ON: - device->public.on = TRUE; - return Success; - - case DEVICE_OFF: - case DEVICE_CLOSE: - device->public.on = FALSE; - return Success; - } - - return BadMatch; -} - -static int -xwl_touch_proc(DeviceIntPtr device, int what) -{ -#define NTOUCHPOINTS 20 -#define NBUTTONS 1 -#define NAXES 2 - Atom btn_labels[NBUTTONS] = { 0 }; - Atom axes_labels[NAXES] = { 0 }; - BYTE map[NBUTTONS + 1] = { 0 }; - - switch (what) { - case DEVICE_INIT: - device->public.on = FALSE; - - axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_MT_POSITION_X); - axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_MT_POSITION_Y); - - if (!InitValuatorClassDeviceStruct(device, NAXES, axes_labels, - GetMotionHistorySize(), Absolute)) - return BadValue; - - if (!InitButtonClassDeviceStruct(device, NBUTTONS, btn_labels, map)) - return BadValue; - - if (!InitTouchClassDeviceStruct(device, NTOUCHPOINTS, - XIDirectTouch, NAXES)) - return BadValue; - - /* Valuators */ - InitValuatorAxisStruct(device, 0, axes_labels[0], - 0, 0xFFFF, 10000, 0, 10000, Absolute); - InitValuatorAxisStruct(device, 1, axes_labels[1], - 0, 0xFFFF, 10000, 0, 10000, Absolute); - - if (!InitPtrFeedbackClassDeviceStruct(device, xwl_pointer_control)) - return BadValue; - - return Success; - - case DEVICE_ON: - device->public.on = TRUE; - return Success; - - case DEVICE_OFF: - case DEVICE_CLOSE: - device->public.on = FALSE; - return Success; - } - - return BadMatch; -#undef NAXES -#undef NBUTTONS -#undef NTOUCHPOINTS -} - -static int -xwl_tablet_proc(DeviceIntPtr device, int what) -{ -#define NBUTTONS 9 -#define NAXES 6 - Atom btn_labels[NBUTTONS] = { 0 }; - Atom axes_labels[NAXES] = { 0 }; - BYTE map[NBUTTONS + 1] = { 0 }; - int i; - - switch (what) { - case DEVICE_INIT: - device->public.on = FALSE; - - for (i = 1; i <= NBUTTONS; i++) - map[i] = i; - - axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_X); - axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_Y); - axes_labels[2] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_PRESSURE); - axes_labels[3] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_TILT_X); - axes_labels[4] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_TILT_Y); - axes_labels[5] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_WHEEL); - - if (!InitValuatorClassDeviceStruct(device, NAXES, axes_labels, - GetMotionHistorySize(), Absolute)) - return BadValue; - - /* Valuators - match the xf86-input-wacom ranges */ - InitValuatorAxisStruct(device, 0, axes_labels[0], - 0, 262143, 10000, 0, 10000, Absolute); - InitValuatorAxisStruct(device, 1, axes_labels[1], - 0, 262143, 10000, 0, 10000, Absolute); - /* pressure */ - InitValuatorAxisStruct(device, 2, axes_labels[2], - 0, 65535, 1, 0, 1, Absolute); - /* tilt x */ - InitValuatorAxisStruct(device, 3, axes_labels[3], - -64, 63, 57, 0, 57, Absolute); - /* tilt y */ - InitValuatorAxisStruct(device, 4, axes_labels[4], - -64, 63, 57, 0, 57, Absolute); - /* abs wheel (airbrush) or rotation (artpen) */ - InitValuatorAxisStruct(device, 5, axes_labels[5], - -900, 899, 1, 0, 1, Absolute); - - if (!InitPtrFeedbackClassDeviceStruct(device, xwl_pointer_control)) - return BadValue; - - if (!InitButtonClassDeviceStruct(device, NBUTTONS, btn_labels, map)) - return BadValue; - - return Success; - - case DEVICE_ON: - device->public.on = TRUE; - return Success; - - case DEVICE_OFF: - case DEVICE_CLOSE: - device->public.on = FALSE; - return Success; - } - - return BadMatch; -#undef NAXES -#undef NBUTTONS -} - -static void -pointer_handle_enter(void *data, struct wl_pointer *pointer, - uint32_t serial, struct wl_surface *surface, - wl_fixed_t sx_w, wl_fixed_t sy_w) -{ - struct xwl_seat *xwl_seat = data; - struct xwl_screen *xwl_screen = xwl_seat->xwl_screen; - DeviceIntPtr dev = get_pointer_device(xwl_seat); - DeviceIntPtr master; - int i; - int sx, sy; - int dx, dy; - ScreenPtr pScreen = xwl_screen->screen; - ValuatorMask mask; - - /* There's a race here where if we create and then immediately - * destroy a surface, we might end up in a state where the Wayland - * compositor sends us an event for a surface that doesn't exist. - * - * Don't process enter events in this case. - */ - if (surface == NULL) - return; - - if (!is_surface_from_xwl_window(surface)) - return; - - sx = wl_fixed_to_int(sx_w) * xwl_screen->global_surface_scale; - sy = wl_fixed_to_int(sy_w) * xwl_screen->global_surface_scale; - - xwl_seat->xwl_screen->serial = serial; - xwl_seat->pointer_enter_serial = serial; - - xwl_seat->focus_window = wl_surface_get_user_data(surface); - dx = xwl_seat->focus_window->toplevel->drawable.x; - dy = xwl_seat->focus_window->toplevel->drawable.y; - - /* We just entered a new xwindow, forget about the old last xwindow */ - xwl_seat->last_focus_window = NULL; - - master = GetMaster(dev, POINTER_OR_FLOAT); - (*pScreen->SetCursorPosition) (dev, pScreen, dx + sx, dy + sy, TRUE); - - miPointerInvalidateSprite(master); - - CheckMotion(NULL, master); - - /* Ideally, X clients shouldn't see these button releases. When - * the pointer leaves a window with buttons down, it means that - * the wayland compositor has grabbed the pointer. The button - * release event is consumed by whatever grab in the compositor - * and won't be sent to clients (the X server is a client). - * However, we need to reset X's idea of which buttons are up and - * down, and they're all up (by definition) when the pointer - * enters a window. We should figure out a way to swallow these - * events, perhaps using an X grab whenever the pointer is not in - * any X window, but for now just send the events. */ - valuator_mask_zero(&mask); - for (i = 0; i < dev->button->numButtons; i++) - if (BitIsOn(dev->button->down, i)) - QueuePointerEvents(dev, ButtonRelease, i, 0, &mask); - - /* The last cursor frame we committed before the pointer left one - * of our surfaces might not have been shown. In that case we'll - * have a cursor surface frame callback pending which we need to - * clear so that we can continue submitting new cursor frames. */ - if (xwl_cursor_clear_frame_cb(&xwl_seat->cursor)) - xwl_seat_set_cursor(xwl_seat); - - if (xwl_seat->pointer_warp_emulator) { - xwl_pointer_warp_emulator_maybe_lock(xwl_seat->pointer_warp_emulator, - xwl_seat->focus_window, - NULL, 0, 0); - } - else { - xwl_seat_maybe_lock_on_hidden_cursor(xwl_seat); - } - - maybe_fake_grab_devices(xwl_seat); -} - -void -xwl_seat_leave_ptr(struct xwl_seat *xwl_seat, Bool focus_lost) -{ - DeviceIntPtr dev = get_pointer_device(xwl_seat); - - if (!dev) - return; - - if (focus_lost) - CheckMotion(NULL, GetMaster(dev, POINTER_OR_FLOAT)); - - maybe_fake_ungrab_devices(xwl_seat); -} - -static void -pointer_handle_leave(void *data, struct wl_pointer *pointer, - uint32_t serial, struct wl_surface *surface) -{ - struct xwl_seat *xwl_seat = data; - struct xwl_screen *xwl_screen = xwl_seat->xwl_screen; - - xwl_screen->serial = serial; - - if (xwl_screen->rootless) - xwl_seat_leave_ptr(xwl_seat, !!xwl_seat->focus_window); - - /* The pointer has left a known xwindow, save it for a possible match - * in sprite_check_lost_focus() - */ - if (xwl_seat->focus_window) { - xwl_seat->last_focus_window = xwl_seat->focus_window; - xwl_seat->focus_window = NULL; - } -} - -static void -dispatch_relative_motion_with_warp(struct xwl_seat *xwl_seat) -{ - struct xwl_screen *xwl_screen = xwl_seat->xwl_screen; - double dx, dx_unaccel; - double dy, dy_unaccel; - - dx = xwl_seat->pending_pointer_event.dx; - dy = xwl_seat->pending_pointer_event.dy; - dx_unaccel = xwl_seat->pending_pointer_event.dx_unaccel; - dy_unaccel = xwl_seat->pending_pointer_event.dy_unaccel; - - dx *= xwl_screen->global_surface_scale; - dy *= xwl_screen->global_surface_scale; - dx_unaccel *= xwl_screen->global_surface_scale; - dy_unaccel *= xwl_screen->global_surface_scale; - - dx *= xwl_seat->focus_window->viewport_scale_x; - dy *= xwl_seat->focus_window->viewport_scale_y; - dx_unaccel *= xwl_seat->focus_window->viewport_scale_x; - dy_unaccel *= xwl_seat->focus_window->viewport_scale_y; - - xwl_pointer_warp_emulator_handle_motion(xwl_seat->pointer_warp_emulator, - dx, dy, - dx_unaccel, dy_unaccel); -} - -static void -dispatch_absolute_motion(struct xwl_seat *xwl_seat) -{ - struct xwl_screen *xwl_screen = xwl_seat->xwl_screen; - ValuatorMask mask; - DeviceIntPtr device; - int flags; - int event_x = wl_fixed_to_int(xwl_seat->pending_pointer_event.x); - int event_y = wl_fixed_to_int(xwl_seat->pending_pointer_event.y); - int drawable_x = xwl_seat->focus_window->toplevel->drawable.x; - int drawable_y = xwl_seat->focus_window->toplevel->drawable.y; - int x; - int y; - - event_x *= xwl_screen->global_surface_scale; - event_y *= xwl_screen->global_surface_scale; - - event_x *= xwl_seat->focus_window->viewport_scale_x; - event_y *= xwl_seat->focus_window->viewport_scale_y; - - x = drawable_x + event_x; - y = drawable_y + event_y; - - valuator_mask_zero(&mask); - valuator_mask_set(&mask, 0, x); - valuator_mask_set(&mask, 1, y); - - if (xwl_seat->pending_pointer_event.has_relative) { - flags = POINTER_ABSOLUTE | POINTER_SCREEN | POINTER_NORAW; - device = xwl_seat->relative_pointer; - } else { - flags = POINTER_ABSOLUTE | POINTER_SCREEN; - device = xwl_seat->pointer; - } - - QueuePointerEvents(device, MotionNotify, 0, flags, &mask); -} - -static void -dispatch_relative_motion(struct xwl_seat *xwl_seat) -{ - struct xwl_screen *xwl_screen = xwl_seat->xwl_screen; - ValuatorMask mask; - double event_dx = xwl_seat->pending_pointer_event.dx; - double event_dy = xwl_seat->pending_pointer_event.dy; - double event_dx_unaccel = xwl_seat->pending_pointer_event.dx_unaccel; - double event_dy_unaccel = xwl_seat->pending_pointer_event.dy_unaccel; - - event_dx *= xwl_screen->global_surface_scale; - event_dy *= xwl_screen->global_surface_scale; - event_dx_unaccel *= xwl_screen->global_surface_scale; - event_dy_unaccel *= xwl_screen->global_surface_scale; - - event_dx *= xwl_seat->focus_window->viewport_scale_x; - event_dy *= xwl_seat->focus_window->viewport_scale_y; - event_dx_unaccel *= xwl_seat->focus_window->viewport_scale_x; - event_dy_unaccel *= xwl_seat->focus_window->viewport_scale_y; - - valuator_mask_zero(&mask); - valuator_mask_set_unaccelerated(&mask, 0, event_dx, event_dx_unaccel); - valuator_mask_set_unaccelerated(&mask, 1, event_dy, event_dy_unaccel); - - QueuePointerEvents(xwl_seat->relative_pointer, MotionNotify, 0, - POINTER_RAWONLY, &mask); -} - -static void -dispatch_scroll_motion(struct xwl_seat *xwl_seat) -{ - ValuatorMask mask; - const int divisor = 10; - wl_fixed_t dy = xwl_seat->pending_pointer_event.scroll_dy; - wl_fixed_t dx = xwl_seat->pending_pointer_event.scroll_dx; - int32_t dy_v120 = xwl_seat->pending_pointer_event.scroll_dy_v120; - int32_t dx_v120 = xwl_seat->pending_pointer_event.scroll_dx_v120; - - valuator_mask_zero(&mask); - if (xwl_seat->pending_pointer_event.has_vertical_scroll_v120) - valuator_mask_set_double(&mask, SCROLL_AXIS_VERT, dy_v120 / 120.0); - else if (xwl_seat->pending_pointer_event.has_vertical_scroll) - valuator_mask_set_double(&mask, - SCROLL_AXIS_VERT, - wl_fixed_to_double(dy) / divisor); - - if (xwl_seat->pending_pointer_event.has_horizontal_scroll_v120) - valuator_mask_set_double(&mask, SCROLL_AXIS_HORIZ, dx_v120 / 120.0); - else if (xwl_seat->pending_pointer_event.has_horizontal_scroll) - valuator_mask_set_double(&mask, - SCROLL_AXIS_HORIZ, - wl_fixed_to_double(dx) / divisor); - - QueuePointerEvents(get_pointer_device(xwl_seat), - MotionNotify, 0, POINTER_RELATIVE, &mask); -} - - -static void -dispatch_pointer_motion_event(struct xwl_seat *xwl_seat) -{ - Bool has_relative = xwl_seat->pending_pointer_event.has_relative; - Bool has_absolute = xwl_seat->pending_pointer_event.has_absolute; - - if (xwl_seat->pointer_warp_emulator && has_relative) { - dispatch_relative_motion_with_warp(xwl_seat); - } else { - if (has_relative) - dispatch_relative_motion(xwl_seat); - - if (has_absolute) - dispatch_absolute_motion(xwl_seat); - } - - if (xwl_seat->pending_pointer_event.has_vertical_scroll || - xwl_seat->pending_pointer_event.has_horizontal_scroll || - xwl_seat->pending_pointer_event.has_vertical_scroll_v120 || - xwl_seat->pending_pointer_event.has_horizontal_scroll_v120) - dispatch_scroll_motion(xwl_seat); - - xwl_seat->pending_pointer_event.has_absolute = FALSE; - xwl_seat->pending_pointer_event.has_relative = FALSE; - xwl_seat->pending_pointer_event.has_vertical_scroll = FALSE; - xwl_seat->pending_pointer_event.has_horizontal_scroll = FALSE; - xwl_seat->pending_pointer_event.has_vertical_scroll_v120 = FALSE; - xwl_seat->pending_pointer_event.has_horizontal_scroll_v120 = FALSE; -} - -static void -pointer_handle_motion(void *data, struct wl_pointer *pointer, - uint32_t time, wl_fixed_t sx_w, wl_fixed_t sy_w) -{ - struct xwl_seat *xwl_seat = data; - - if (!xwl_seat->focus_window) - return; - - xwl_seat->pending_pointer_event.has_absolute = TRUE; - xwl_seat->pending_pointer_event.x = sx_w; - xwl_seat->pending_pointer_event.y = sy_w; - - if (wl_proxy_get_version((struct wl_proxy *) xwl_seat->wl_pointer) < 5) - dispatch_pointer_motion_event(xwl_seat); -} - -static void -pointer_handle_button(void *data, struct wl_pointer *pointer, uint32_t serial, - uint32_t time, uint32_t button, uint32_t state) -{ - struct xwl_seat *xwl_seat = data; - int index; - ValuatorMask mask; - - xwl_seat->xwl_screen->serial = serial; - - switch (button) { - case BTN_LEFT: - index = 1; - break; - case BTN_MIDDLE: - index = 2; - break; - case BTN_RIGHT: - index = 3; - break; - default: - /* Skip indexes 4-7: they are used for vertical and horizontal scroll. - The rest of the buttons go in order: BTN_SIDE becomes 8, etc. */ - index = 8 + button - BTN_SIDE; - break; - } - - valuator_mask_zero(&mask); - QueuePointerEvents(get_pointer_device(xwl_seat), - state ? ButtonPress : ButtonRelease, index, 0, &mask); -} - -static void -pointer_handle_axis(void *data, struct wl_pointer *pointer, - uint32_t time, uint32_t axis, wl_fixed_t value) -{ - struct xwl_seat *xwl_seat = data; - - switch (axis) { - case WL_POINTER_AXIS_VERTICAL_SCROLL: - xwl_seat->pending_pointer_event.has_vertical_scroll = TRUE; - xwl_seat->pending_pointer_event.scroll_dy = value; - break; - case WL_POINTER_AXIS_HORIZONTAL_SCROLL: - xwl_seat->pending_pointer_event.has_horizontal_scroll = TRUE; - xwl_seat->pending_pointer_event.scroll_dx = value; - break; - } -} - -static void -pointer_handle_frame(void *data, struct wl_pointer *wl_pointer) -{ - struct xwl_seat *xwl_seat = data; - - if (!xwl_seat->focus_window) - return; - - dispatch_pointer_motion_event(xwl_seat); -} - -static void -pointer_handle_axis_source(void *data, struct wl_pointer *wl_pointer, uint32_t axis_source) -{ -} - -static void -pointer_handle_axis_stop(void *data, struct wl_pointer *wl_pointer, - uint32_t time, uint32_t axis) -{ - struct xwl_seat *xwl_seat = data; - - switch (axis) { - case WL_POINTER_AXIS_VERTICAL_SCROLL: - xwl_seat->pending_pointer_event.has_vertical_scroll = TRUE; - xwl_seat->pending_pointer_event.scroll_dy = 0; - break; - case WL_POINTER_AXIS_HORIZONTAL_SCROLL: - xwl_seat->pending_pointer_event.has_horizontal_scroll = TRUE; - xwl_seat->pending_pointer_event.scroll_dx = 0; - break; - } -} - -static void -pointer_handle_axis_discrete(void *data, struct wl_pointer *wl_pointer, - uint32_t axis, int32_t discrete) -{ - struct xwl_seat *xwl_seat = data; - - switch (axis) { - case WL_POINTER_AXIS_VERTICAL_SCROLL: - xwl_seat->pending_pointer_event.has_vertical_scroll_v120 = TRUE; - xwl_seat->pending_pointer_event.scroll_dy_v120 = 120 * discrete; - break; - case WL_POINTER_AXIS_HORIZONTAL_SCROLL: - xwl_seat->pending_pointer_event.has_horizontal_scroll_v120 = TRUE; - xwl_seat->pending_pointer_event.scroll_dx_v120 = 120 * discrete; - break; - } -} - -static void -pointer_handle_axis_v120(void *data, struct wl_pointer *pointer, - uint32_t axis, int32_t v120) -{ - struct xwl_seat *xwl_seat = data; - - switch (axis) { - case WL_POINTER_AXIS_VERTICAL_SCROLL: - xwl_seat->pending_pointer_event.has_vertical_scroll_v120 = TRUE; - xwl_seat->pending_pointer_event.scroll_dy_v120 = v120; - break; - case WL_POINTER_AXIS_HORIZONTAL_SCROLL: - xwl_seat->pending_pointer_event.has_horizontal_scroll_v120 = TRUE; - xwl_seat->pending_pointer_event.scroll_dx_v120 = v120; - break; - } -} - -static const struct wl_pointer_listener pointer_listener = { - pointer_handle_enter, - pointer_handle_leave, - pointer_handle_motion, - pointer_handle_button, - pointer_handle_axis, - pointer_handle_frame, - pointer_handle_axis_source, - pointer_handle_axis_stop, - pointer_handle_axis_discrete, - pointer_handle_axis_v120, -}; - -static void -relative_pointer_handle_relative_motion(void *data, - struct zwp_relative_pointer_v1 *zwp_relative_pointer_v1, - uint32_t utime_hi, - uint32_t utime_lo, - wl_fixed_t dxf, - wl_fixed_t dyf, - wl_fixed_t dx_unaccelf, - wl_fixed_t dy_unaccelf) -{ - struct xwl_seat *xwl_seat = data; - - xwl_seat->pending_pointer_event.has_relative = TRUE; - xwl_seat->pending_pointer_event.dx = wl_fixed_to_double(dxf); - xwl_seat->pending_pointer_event.dy = wl_fixed_to_double(dyf); - xwl_seat->pending_pointer_event.dx_unaccel = wl_fixed_to_double(dx_unaccelf); - xwl_seat->pending_pointer_event.dy_unaccel = wl_fixed_to_double(dy_unaccelf); - - if (!xwl_seat->focus_window) - return; - - if (wl_proxy_get_version((struct wl_proxy *) xwl_seat->wl_pointer) < 5) - dispatch_pointer_motion_event(xwl_seat); -} - -static const struct zwp_relative_pointer_v1_listener relative_pointer_listener = { - relative_pointer_handle_relative_motion, -}; - -static void -pointer_gesture_swipe_handle_begin(void *data, - struct zwp_pointer_gesture_swipe_v1 *swipe, - uint32_t serial, - uint32_t time, - struct wl_surface *surface, - uint32_t fingers) -{ - struct xwl_seat *xwl_seat = data; - - if (surface != NULL && !is_surface_from_xwl_window(surface)) - return; - - xwl_seat->pointer_gesture_swipe_fingers = fingers; - QueueGestureSwipeEvents(xwl_seat->pointer_gestures, - XI_GestureSwipeBegin, fingers, 0, 0.0, 0.0, 0.0, 0.0); -} - -static void -pointer_gesture_swipe_handle_update(void *data, - struct zwp_pointer_gesture_swipe_v1 *swipe, - uint32_t time, - wl_fixed_t dxf, - wl_fixed_t dyf) -{ - struct xwl_seat *xwl_seat = data; - double dx = wl_fixed_to_double(dxf); - double dy = wl_fixed_to_double(dyf); - - QueueGestureSwipeEvents(xwl_seat->pointer_gestures, - XI_GestureSwipeUpdate, - xwl_seat->pointer_gesture_swipe_fingers, - 0, - dx, dy, - dx, dy); -} - -static void -pointer_gesture_swipe_handle_end(void *data, - struct zwp_pointer_gesture_swipe_v1 *swipe, - uint32_t serial, - uint32_t time, - int32_t cancelled) -{ - struct xwl_seat *xwl_seat = data; - uint32_t flags = 0; - - if (cancelled) - flags |= XIGestureSwipeEventCancelled; - - QueueGestureSwipeEvents(xwl_seat->pointer_gestures, - XI_GestureSwipeEnd, - xwl_seat->pointer_gesture_swipe_fingers, - flags, 0.0, 0.0, 0.0, 0.0); -} - -static const struct zwp_pointer_gesture_swipe_v1_listener pointer_gesture_swipe_listener = { - pointer_gesture_swipe_handle_begin, - pointer_gesture_swipe_handle_update, - pointer_gesture_swipe_handle_end -}; - -static void -pointer_gesture_pinch_handle_begin(void *data, - struct zwp_pointer_gesture_pinch_v1 *pinch, - uint32_t serial, - uint32_t time, - struct wl_surface *surface, - uint32_t fingers) -{ - struct xwl_seat *xwl_seat = data; - - if (surface != NULL && !is_surface_from_xwl_window(surface)) - return; - - xwl_seat->pointer_gesture_pinch_fingers = fingers; - xwl_seat->pointer_gesture_pinch_last_scale = 1.0; - QueueGesturePinchEvents(xwl_seat->pointer_gestures, - XI_GesturePinchBegin, fingers, 0, 0.0, 0.0, 0.0, 0.0, - 1.0, 0.0); -} - -static void -pointer_gesture_pinch_handle_update(void *data, - struct zwp_pointer_gesture_pinch_v1 *pinch, - uint32_t time, - wl_fixed_t dxf, - wl_fixed_t dyf, - wl_fixed_t scalef, - wl_fixed_t rotation) -{ - struct xwl_seat *xwl_seat = data; - double dx = wl_fixed_to_double(dxf); - double dy = wl_fixed_to_double(dyf); - double scale = wl_fixed_to_double(scalef); - - xwl_seat->pointer_gesture_pinch_last_scale = scale; - QueueGesturePinchEvents(xwl_seat->pointer_gestures, - XI_GesturePinchUpdate, - xwl_seat->pointer_gesture_pinch_fingers, - 0, - dx, dy, - dx, dy, - scale, wl_fixed_to_double(rotation)); -} - -static void -pointer_gesture_pinch_handle_end(void *data, - struct zwp_pointer_gesture_pinch_v1 *pinch, - uint32_t serial, - uint32_t time, - int32_t cancelled) -{ - struct xwl_seat *xwl_seat = data; - uint32_t flags = 0; - - if (cancelled) - flags |= XIGesturePinchEventCancelled; - - QueueGesturePinchEvents(xwl_seat->pointer_gestures, - XI_GesturePinchEnd, - xwl_seat->pointer_gesture_pinch_fingers, - flags, 0.0, 0.0, 0.0, 0.0, - xwl_seat->pointer_gesture_pinch_last_scale, 0.0); -} - -static const struct zwp_pointer_gesture_pinch_v1_listener pointer_gesture_pinch_listener = { - pointer_gesture_pinch_handle_begin, - pointer_gesture_pinch_handle_update, - pointer_gesture_pinch_handle_end -}; - -static void -maybe_toggle_fake_grab(struct xwl_seat *xwl_seat, uint32_t key) -{ - struct xwl_screen *xwl_screen = xwl_seat->xwl_screen; - struct xwl_window *xwl_window; - XkbStateRec state_rec; - uint32_t xkb_state; - - if (xwl_screen->rootless) - return; - - if (!xwl_screen->host_grab) - return; - - state_rec = xwl_seat->keyboard->key->xkbInfo->state; - xkb_state = (XkbStateFieldFromRec(&state_rec) & 0xff); - - if (((key == KEY_LEFTSHIFT || key == KEY_RIGHTSHIFT) && (xkb_state & ControlMask)) || - ((key == KEY_LEFTCTRL || key == KEY_RIGHTCTRL) && (xkb_state & ShiftMask))) { - - xwl_screen->has_grab = !xwl_screen->has_grab; - - if (xwl_screen->has_grab) - maybe_fake_grab_devices(xwl_seat); - else - maybe_fake_ungrab_devices(xwl_seat); - - xwl_window = xwl_window_get(xwl_screen->screen->root); - if (xwl_window) - xwl_window_rootful_update_title(xwl_window); - } -} - -static void -keyboard_handle_key(void *data, struct wl_keyboard *keyboard, uint32_t serial, - uint32_t time, uint32_t key, uint32_t state) -{ - struct xwl_seat *xwl_seat = data; - uint32_t *k, *end; - - xwl_seat->xwl_screen->serial = serial; - - end = (uint32_t *) ((char *) xwl_seat->keys.data + xwl_seat->keys.size); - for (k = xwl_seat->keys.data; k < end; k++) { - if (*k == key) - *k = *--end; - } - xwl_seat->keys.size = (char *) end - (char *) xwl_seat->keys.data; - if (state) { - k = wl_array_add(&xwl_seat->keys, sizeof *k); - *k = key; - } - - QueueKeyboardEvents(xwl_seat->keyboard, - state ? KeyPress : KeyRelease, key + 8); - - if (!state) - maybe_toggle_fake_grab(xwl_seat, key); -} - -static void -keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard, - uint32_t format, int fd, uint32_t size) -{ - struct xwl_seat *xwl_seat = data; - struct xwl_screen *xwl_screen = xwl_seat->xwl_screen; - DeviceIntPtr master; - XkbDescPtr xkb; - XkbChangesRec changes = { 0 }; - - if (xwl_screen->nokeymap) - return; - - if (xwl_seat->keymap) - munmap(xwl_seat->keymap, xwl_seat->keymap_size); - - xwl_seat->keymap_size = size; - xwl_seat->keymap = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0); - if (xwl_seat->keymap == MAP_FAILED) { - xwl_seat->keymap_size = 0; - xwl_seat->keymap = NULL; - goto out; - } - - xkb = XkbCompileKeymapFromString(xwl_seat->keyboard, xwl_seat->keymap, - strnlen(xwl_seat->keymap, - xwl_seat->keymap_size)); - if (!xkb) - goto out; - - XkbUpdateDescActions(xkb, xkb->min_key_code, XkbNumKeys(xkb), &changes); - - memcpy( - xwl_seat->keyboard->kbdfeed->ctrl.autoRepeats, - xkb->ctrls->per_key_repeat, - XkbPerKeyBitArraySize - ); - if (xwl_seat->keyboard->key) { - /* Keep the current controls */ - XkbCopyControls(xkb, xwl_seat->keyboard->key->xkbInfo->desc); - memcpy( - xkb->ctrls->per_key_repeat, - xwl_seat->keyboard->kbdfeed->ctrl.autoRepeats, - XkbPerKeyBitArraySize - ); - } - - XkbDeviceApplyKeymap(xwl_seat->keyboard, xkb); - - master = GetMaster(xwl_seat->keyboard, MASTER_KEYBOARD); - if (master) - XkbDeviceApplyKeymap(master, xkb); - - XkbFreeKeyboard(xkb, XkbAllComponentsMask, TRUE); - - out: - close(fd); -} - -static void -keyboard_handle_enter(void *data, struct wl_keyboard *keyboard, - uint32_t serial, - struct wl_surface *surface, struct wl_array *keys) -{ - struct xwl_seat *xwl_seat = data; - uint32_t *k; - - if (surface != NULL && !is_surface_from_xwl_window(surface)) - return; - - xwl_seat->xwl_screen->serial = serial; - xwl_seat->keyboard_focus = surface; - - /* If `leave` wasn't sent (for a destroyed surface), release keys here. */ - wl_array_for_each(k, &xwl_seat->keys) - QueueKeyboardEvents(xwl_seat->keyboard, LeaveNotify, *k + 8); - - wl_array_copy(&xwl_seat->keys, keys); - wl_array_for_each(k, &xwl_seat->keys) - QueueKeyboardEvents(xwl_seat->keyboard, EnterNotify, *k + 8); - - maybe_fake_grab_devices(xwl_seat); -} - -void -xwl_seat_leave_kbd(struct xwl_seat *xwl_seat) -{ - uint32_t *k; - - wl_array_for_each(k, &xwl_seat->keys) - QueueKeyboardEvents(xwl_seat->keyboard, LeaveNotify, *k + 8); - xwl_seat->keys.size = 0; - - xwl_seat->keyboard_focus = NULL; - - maybe_fake_ungrab_devices(xwl_seat); -} - -static void -keyboard_handle_leave(void *data, struct wl_keyboard *keyboard, - uint32_t serial, struct wl_surface *surface) -{ - struct xwl_seat *xwl_seat = data; - struct xwl_screen *xwl_screen = xwl_seat->xwl_screen; - - xwl_screen->serial = serial; - - if (xwl_screen->rootless) - xwl_seat_leave_kbd(xwl_seat); -} - -static void -keyboard_handle_modifiers(void *data, struct wl_keyboard *keyboard, - uint32_t serial, uint32_t mods_depressed, - uint32_t mods_latched, uint32_t mods_locked, - uint32_t group) -{ - struct xwl_seat *xwl_seat = data; - DeviceIntPtr dev; - XkbStateRec old_state, *new_state; - xkbStateNotify sn; - CARD16 changed; - - mieqProcessInputEvents(); - - for (dev = inputInfo.devices; dev; dev = dev->next) { - if (dev != xwl_seat->keyboard && - dev != GetMaster(xwl_seat->keyboard, MASTER_KEYBOARD)) - continue; - - old_state = dev->key->xkbInfo->state; - new_state = &dev->key->xkbInfo->state; - - new_state->base_group = 0; - new_state->latched_group = 0; - new_state->locked_group = group & XkbAllGroupsMask; - new_state->base_mods = mods_depressed & XkbAllModifiersMask; - new_state->latched_mods = mods_latched & XkbAllModifiersMask; - new_state->locked_mods = mods_locked & XkbAllModifiersMask; - - XkbComputeDerivedState(dev->key->xkbInfo); - - changed = XkbStateChangedFlags(&old_state, new_state); - if (!changed) - continue; - - sn.keycode = 0; - sn.eventType = 0; - sn.requestMajor = XkbReqCode; - sn.requestMinor = X_kbLatchLockState; /* close enough */ - sn.changed = changed; - XkbSendStateNotify(dev, &sn); - } -} - -static void -remove_sync_pending(DeviceIntPtr dev) -{ - struct xwl_seat *xwl_seat = dev->public.devicePrivate; - struct sync_pending *p, *npd; - - if (!xwl_seat) - return; - - xorg_list_for_each_entry_safe(p, npd, &xwl_seat->sync_pending, l) { - if (p->pending_dev == dev) { - xorg_list_del(&xwl_seat->sync_pending); - free (p); - return; - } - } -} - -static void -sync_callback(void *data, struct wl_callback *callback, uint32_t serial) -{ - DeviceIntPtr dev = (DeviceIntPtr) data; - - remove_sync_pending(dev); - wl_callback_destroy(callback); -} - -static const struct wl_callback_listener sync_listener = { - sync_callback -}; - -static Bool -keyboard_check_repeat (DeviceIntPtr dev, XkbSrvInfoPtr xkbi, unsigned key) -{ - struct xwl_seat *xwl_seat = dev->public.devicePrivate; - struct xwl_screen *xwl_screen; - struct wl_callback *callback; - struct sync_pending *p; - - if (!xwl_seat) - return FALSE; - - /* Make sure we didn't miss a possible reply from the compositor */ - xwl_screen = xwl_seat->xwl_screen; - xwl_sync_events (xwl_screen); - - xorg_list_for_each_entry(p, &xwl_seat->sync_pending, l) { - if (p->pending_dev == dev) { - ErrorF("Key repeat discarded, Wayland compositor doesn't " - "seem to be processing events fast enough!\n"); - - return FALSE; - } - } - - p = XNFalloc(sizeof(struct sync_pending)); - p->pending_dev = dev; - callback = wl_display_sync (xwl_screen->display); - xorg_list_add(&p->l, &xwl_seat->sync_pending); - - wl_callback_add_listener(callback, &sync_listener, dev); - - return TRUE; -} - -static void -keyboard_handle_repeat_info (void *data, struct wl_keyboard *keyboard, - int32_t rate, int32_t delay) -{ - struct xwl_seat *xwl_seat = data; - DeviceIntPtr dev; - XkbControlsPtr ctrl; - - if (rate < 0 || delay < 0) { - ErrorF("Wrong rate/delay: %d, %d\n", rate, delay); - return; - } - - for (dev = inputInfo.devices; dev; dev = dev->next) { - if (dev != xwl_seat->keyboard && - dev != GetMaster(xwl_seat->keyboard, MASTER_KEYBOARD)) - continue; - - if (rate != 0) { - ctrl = dev->key->xkbInfo->desc->ctrls; - ctrl->repeat_delay = delay; - /* rate is number of keys per second */ - ctrl->repeat_interval = 1000 / rate; - - XkbSetRepeatKeys(dev, -1, AutoRepeatModeOn); - } else - XkbSetRepeatKeys(dev, -1, AutoRepeatModeOff); - } -} - -static const struct wl_keyboard_listener keyboard_listener = { - keyboard_handle_keymap, - keyboard_handle_enter, - keyboard_handle_leave, - keyboard_handle_key, - keyboard_handle_modifiers, - keyboard_handle_repeat_info, -}; - -static struct xwl_touch * -xwl_seat_lookup_touch(struct xwl_seat *xwl_seat, int32_t id) -{ - struct xwl_touch *xwl_touch, *next_xwl_touch; - - xorg_list_for_each_entry_safe(xwl_touch, next_xwl_touch, - &xwl_seat->touches, link_touch) { - if (xwl_touch->id == id) - return xwl_touch; - } - - return NULL; -} - -static void -xwl_touch_send_event(struct xwl_touch *xwl_touch, - struct xwl_seat *xwl_seat, int type) -{ - double dx, dy, x, y; - ValuatorMask mask; - - dx = xwl_touch->window->toplevel->drawable.x; - dy = xwl_touch->window->toplevel->drawable.y; - - x = (dx + xwl_touch->x) * 0xFFFF / xwl_screen_get_width(xwl_seat->xwl_screen); - y = (dy + xwl_touch->y) * 0xFFFF / xwl_screen_get_height(xwl_seat->xwl_screen); - - valuator_mask_zero(&mask); - valuator_mask_set_double(&mask, 0, x); - valuator_mask_set_double(&mask, 1, y); - QueueTouchEvents(xwl_seat->touch, type, xwl_touch->id, 0, &mask); -} - -static void -touch_handle_down(void *data, struct wl_touch *wl_touch, - uint32_t serial, uint32_t time, - struct wl_surface *surface, - int32_t id, wl_fixed_t sx_w, wl_fixed_t sy_w) -{ - struct xwl_seat *xwl_seat = data; - struct xwl_screen *xwl_screen = xwl_seat->xwl_screen; - struct xwl_touch *xwl_touch; - - if (surface == NULL) - return; - - if (!is_surface_from_xwl_window(surface)) - return; - - xwl_touch = calloc(1, sizeof *xwl_touch); - if (xwl_touch == NULL) { - ErrorF("%s: ENOMEM\n", __func__); - return; - } - - xwl_touch->window = wl_surface_get_user_data(surface); - xwl_touch->id = id; - xwl_touch->x = wl_fixed_to_int(sx_w); - xwl_touch->y = wl_fixed_to_int(sy_w); - xorg_list_add(&xwl_touch->link_touch, &xwl_seat->touches); - - xwl_touch->x *= xwl_screen->global_surface_scale; - xwl_touch->y *= xwl_screen->global_surface_scale; - - xwl_touch->x *= xwl_touch->window->viewport_scale_x; - xwl_touch->y *= xwl_touch->window->viewport_scale_y; - - xwl_touch_send_event(xwl_touch, xwl_seat, XI_TouchBegin); -} - -static void -touch_handle_up(void *data, struct wl_touch *wl_touch, - uint32_t serial, uint32_t time, int32_t id) -{ - struct xwl_touch *xwl_touch; - struct xwl_seat *xwl_seat = data; - - xwl_touch = xwl_seat_lookup_touch(xwl_seat, id); - - if (!xwl_touch) - return; - - xwl_touch_send_event(xwl_touch, xwl_seat, XI_TouchEnd); - xorg_list_del(&xwl_touch->link_touch); - free(xwl_touch); -} - -static void -touch_handle_motion(void *data, struct wl_touch *wl_touch, - uint32_t time, int32_t id, - wl_fixed_t sx_w, wl_fixed_t sy_w) -{ - struct xwl_seat *xwl_seat = data; - struct xwl_screen *xwl_screen = xwl_seat->xwl_screen; - struct xwl_touch *xwl_touch; - - xwl_touch = xwl_seat_lookup_touch(xwl_seat, id); - - if (!xwl_touch) - return; - - xwl_touch->x = wl_fixed_to_int(sx_w); - xwl_touch->y = wl_fixed_to_int(sy_w); - - xwl_touch->x *= xwl_screen->global_surface_scale; - xwl_touch->y *= xwl_screen->global_surface_scale; - - xwl_touch->x *= xwl_touch->window->viewport_scale_x; - xwl_touch->y *= xwl_touch->window->viewport_scale_y; - - xwl_touch_send_event(xwl_touch, xwl_seat, XI_TouchUpdate); -} - -static void -touch_handle_frame(void *data, struct wl_touch *wl_touch) -{ -} - -static void -touch_handle_cancel(void *data, struct wl_touch *wl_touch) -{ - struct xwl_seat *xwl_seat = data; - struct xwl_touch *xwl_touch, *next_xwl_touch; - - xorg_list_for_each_entry_safe(xwl_touch, next_xwl_touch, - &xwl_seat->touches, link_touch) { - /* We can't properly notify of cancellation to the X client - * once it thinks it has the ownership, send at least a - * TouchEnd event. - */ - xwl_touch_send_event(xwl_touch, xwl_seat, XI_TouchEnd); - xorg_list_del(&xwl_touch->link_touch); - free(xwl_touch); - } -} - -static const struct wl_touch_listener touch_listener = { - touch_handle_down, - touch_handle_up, - touch_handle_motion, - touch_handle_frame, - touch_handle_cancel -}; - -static struct xwl_seat * -find_matching_seat(DeviceIntPtr device) -{ - DeviceIntPtr dev; - - for (dev = inputInfo.devices; dev; dev = dev->next) - if (dev->deviceProc == xwl_keyboard_proc && - device == GetMaster(dev, MASTER_KEYBOARD)) - return (struct xwl_seat *) dev->public.devicePrivate; - - return NULL; -} - -static void -release_grab(struct xwl_seat *xwl_seat) -{ - if (xwl_seat->keyboard_grab) - zwp_xwayland_keyboard_grab_v1_destroy(xwl_seat->keyboard_grab); - xwl_seat->keyboard_grab = NULL; -} - -static void -set_grab(struct xwl_seat *xwl_seat, struct xwl_window *xwl_window) -{ - struct xwl_screen *xwl_screen; - - if (!xwl_window) - return; - - /* We already have a grab */ - if (xwl_seat->keyboard_grab) - release_grab (xwl_seat); - - xwl_screen = xwl_seat->xwl_screen; - xwl_seat->keyboard_grab = - zwp_xwayland_keyboard_grab_manager_v1_grab_keyboard(xwl_screen->wp_grab, - xwl_window->surface, - xwl_seat->seat); -} - -static void -find_toplevel_callback(void *resource, XID id, void *user_data) -{ - WindowPtr window = resource; - WindowPtr *toplevel = user_data; - - /* Pick the first realized toplevel we find */ - if (*toplevel == NullWindow && window->realized && xwl_window_is_toplevel(window)) - *toplevel = window; -} - -static WindowPtr -xwl_keyboard_search_window(ClientPtr client) -{ - WindowPtr window = NullWindow; - - FindClientResourcesByType(client, X11_RESTYPE_WINDOW, find_toplevel_callback, &window); - - return window; -} - -static void -xwl_keyboard_activate_grab(DeviceIntPtr device, GrabPtr grab, TimeStamp time, Bool passive) -{ - struct xwl_seat *xwl_seat = device->public.devicePrivate; - WindowPtr grab_window = grab->window; - - /* We are not interested in passive grabs */ - if (!passive) { - /* If the device is the MASTER_KEYBOARD, we don't have an xwl_seat */ - if (xwl_seat == NULL) - xwl_seat = find_matching_seat(device); - if (xwl_seat) { - if (grab_window == xwl_seat->xwl_screen->screen->root) - grab_window = xwl_keyboard_search_window(GetCurrentClient()); - if (grab_window) - set_grab(xwl_seat, xwl_window_from_window(grab_window)); - } - } - - ActivateKeyboardGrab(device, grab, time, passive); -} - -static void -xwl_keyboard_deactivate_grab(DeviceIntPtr device) -{ - struct xwl_seat *xwl_seat = device->public.devicePrivate; - - /* If the device is the MASTER_KEYBOARD, we don't have an xwl_seat */ - if (xwl_seat == NULL) - xwl_seat = find_matching_seat(device); - if (xwl_seat) - release_grab (xwl_seat); - - DeactivateKeyboardGrab(device); -} - -static void -setup_keyboard_grab_handler (DeviceIntPtr device) -{ - device->deviceGrab.ActivateGrab = xwl_keyboard_activate_grab; - device->deviceGrab.DeactivateGrab = xwl_keyboard_deactivate_grab; -} - -static DeviceIntPtr -add_device(struct xwl_seat *xwl_seat, - const char *driver, DeviceProc device_proc) -{ - DeviceIntPtr dev = NULL; - static Atom type_atom; - char name[32]; - - dev = AddInputDevice(serverClient, device_proc, TRUE); - if (dev == NULL) - return NULL; - - if (type_atom == None) - type_atom = MakeAtom(driver, strlen(driver), TRUE); - snprintf(name, sizeof name, "%s:%d", driver, xwl_seat->id); - AssignTypeAndName(dev, type_atom, name); - dev->public.devicePrivate = xwl_seat; - dev->type = SLAVE; - dev->spriteInfo->spriteOwner = FALSE; - dev->ignoreXkbActionsBehaviors = TRUE; - - return dev; -} - -static void -disable_device(DeviceIntPtr dev) -{ - DisableDevice(dev, TRUE); - dev->public.devicePrivate = NULL; -} - -static void -enable_device(struct xwl_seat *xwl_seat, DeviceIntPtr dev) -{ - dev->public.devicePrivate = xwl_seat; - EnableDevice(dev, TRUE); -} - - -static void -init_pointer(struct xwl_seat *xwl_seat) -{ - xwl_seat->wl_pointer = wl_seat_get_pointer(xwl_seat->seat); - wl_pointer_add_listener(xwl_seat->wl_pointer, - &pointer_listener, xwl_seat); - - if (xwl_seat->pointer == NULL) { - xwl_seat_set_cursor(xwl_seat); - xwl_seat->pointer = - add_device(xwl_seat, "xwayland-pointer", xwl_pointer_proc); - ActivateDevice(xwl_seat->pointer, TRUE); - } - enable_device(xwl_seat, xwl_seat->pointer); -} - -static void -release_pointer(struct xwl_seat *xwl_seat) -{ - wl_pointer_release(xwl_seat->wl_pointer); - xwl_seat->wl_pointer = NULL; - - if (xwl_seat->pointer) - disable_device(xwl_seat->pointer); -} - -static void -init_relative_pointer(struct xwl_seat *xwl_seat) -{ - if (xwl_seat->relative_pointer == NULL) { - xwl_seat->relative_pointer = - add_device(xwl_seat, "xwayland-relative-pointer", - xwl_pointer_proc_relative); - ActivateDevice(xwl_seat->relative_pointer, TRUE); - } - enable_device(xwl_seat, xwl_seat->relative_pointer); -} - -static void -init_relative_pointer_listener(struct xwl_seat *xwl_seat) -{ - struct zwp_relative_pointer_manager_v1 *relative_pointer_manager = - xwl_seat->xwl_screen->relative_pointer_manager; - - if (relative_pointer_manager) { - xwl_seat->wp_relative_pointer = - zwp_relative_pointer_manager_v1_get_relative_pointer( - relative_pointer_manager, xwl_seat->wl_pointer); - zwp_relative_pointer_v1_add_listener(xwl_seat->wp_relative_pointer, - &relative_pointer_listener, - xwl_seat); - } -} - -static void -release_relative_pointer(struct xwl_seat *xwl_seat) -{ - if (xwl_seat->wp_relative_pointer) { - zwp_relative_pointer_v1_destroy(xwl_seat->wp_relative_pointer); - xwl_seat->wp_relative_pointer = NULL; - } - - if (xwl_seat->relative_pointer) - disable_device(xwl_seat->relative_pointer); -} - -static void -init_pointer_gestures_device(struct xwl_seat *xwl_seat) -{ - if (xwl_seat->pointer_gestures == NULL) { - xwl_seat->pointer_gestures = - add_device(xwl_seat, "xwayland-pointer-gestures", - xwl_pointer_proc_pointer_gestures); - ActivateDevice(xwl_seat->pointer_gestures, TRUE); - } - enable_device(xwl_seat, xwl_seat->pointer_gestures); -} - -static void -init_pointer_gestures_listener(struct xwl_seat *xwl_seat) -{ - struct zwp_pointer_gestures_v1 *pointer_gestures = - xwl_seat->xwl_screen->pointer_gestures; - - if (pointer_gestures && !xwl_seat->wp_pointer_gesture_swipe) { - xwl_seat->wp_pointer_gesture_swipe = - zwp_pointer_gestures_v1_get_swipe_gesture(pointer_gestures, - xwl_seat->wl_pointer); - zwp_pointer_gesture_swipe_v1_set_user_data(xwl_seat->wp_pointer_gesture_swipe, - xwl_seat); - zwp_pointer_gesture_swipe_v1_add_listener(xwl_seat->wp_pointer_gesture_swipe, - &pointer_gesture_swipe_listener, - xwl_seat); - } - - if (pointer_gestures && !xwl_seat->wp_pointer_gesture_pinch) { - xwl_seat->wp_pointer_gesture_pinch = - zwp_pointer_gestures_v1_get_pinch_gesture(pointer_gestures, - xwl_seat->wl_pointer); - zwp_pointer_gesture_pinch_v1_set_user_data(xwl_seat->wp_pointer_gesture_pinch, - xwl_seat); - zwp_pointer_gesture_pinch_v1_add_listener(xwl_seat->wp_pointer_gesture_pinch, - &pointer_gesture_pinch_listener, - xwl_seat); - } -} - -static void -release_pointer_gestures_device(struct xwl_seat *xwl_seat) -{ - if (xwl_seat->wp_pointer_gesture_swipe) { - zwp_pointer_gesture_swipe_v1_destroy(xwl_seat->wp_pointer_gesture_swipe); - xwl_seat->wp_pointer_gesture_swipe = NULL; - } - - if (xwl_seat->wp_pointer_gesture_pinch) { - zwp_pointer_gesture_pinch_v1_destroy(xwl_seat->wp_pointer_gesture_pinch); - xwl_seat->wp_pointer_gesture_pinch = NULL; - } - - if (xwl_seat->pointer_gestures) - disable_device(xwl_seat->pointer_gestures); -} - -static void -init_keyboard(struct xwl_seat *xwl_seat) -{ - DeviceIntPtr master; - - xwl_seat->wl_keyboard = wl_seat_get_keyboard(xwl_seat->seat); - wl_keyboard_add_listener(xwl_seat->wl_keyboard, - &keyboard_listener, xwl_seat); - - if (xwl_seat->keyboard == NULL) { - xwl_seat->keyboard = - add_device(xwl_seat, "xwayland-keyboard", xwl_keyboard_proc); - ActivateDevice(xwl_seat->keyboard, TRUE); - } - enable_device(xwl_seat, xwl_seat->keyboard); - xwl_seat->keyboard->key->xkbInfo->checkRepeat = keyboard_check_repeat; - - if (xwl_seat->xwl_screen->wp_grab) { - /* We have Xwayland grab protocol supported by the compositor */ - master = GetMaster(xwl_seat->keyboard, MASTER_KEYBOARD); - if (master) - setup_keyboard_grab_handler(master); - } -} - -static void -release_keyboard(struct xwl_seat *xwl_seat) -{ - release_grab(xwl_seat); - wl_keyboard_release(xwl_seat->wl_keyboard); - xwl_seat->wl_keyboard = NULL; - - if (xwl_seat->keyboard) { - remove_sync_pending(xwl_seat->keyboard); - disable_device(xwl_seat->keyboard); - } -} - -static void -init_touch(struct xwl_seat *xwl_seat) -{ - xwl_seat->wl_touch = wl_seat_get_touch(xwl_seat->seat); - wl_touch_add_listener(xwl_seat->wl_touch, - &touch_listener, xwl_seat); - - if (xwl_seat->touch == NULL) { - xwl_seat->touch = - add_device(xwl_seat, "xwayland-touch", xwl_touch_proc); - ActivateDevice(xwl_seat->touch, TRUE); - } - enable_device(xwl_seat, xwl_seat->touch); -} - -static void -release_touch(struct xwl_seat *xwl_seat) -{ - wl_touch_release(xwl_seat->wl_touch); - xwl_seat->wl_touch = NULL; - - if (xwl_seat->touch) - disable_device(xwl_seat->touch); -} - -static void -seat_handle_capabilities(void *data, struct wl_seat *seat, - enum wl_seat_capability caps) -{ - struct xwl_seat *xwl_seat = data; - - if (caps & WL_SEAT_CAPABILITY_POINTER && xwl_seat->wl_pointer == NULL) { - init_pointer(xwl_seat); - init_relative_pointer(xwl_seat); - init_relative_pointer_listener(xwl_seat); - init_pointer_gestures_device(xwl_seat); - init_pointer_gestures_listener(xwl_seat); - } else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && xwl_seat->wl_pointer) { - release_pointer(xwl_seat); - release_relative_pointer(xwl_seat); - release_pointer_gestures_device(xwl_seat); - } - - if (caps & WL_SEAT_CAPABILITY_KEYBOARD && xwl_seat->wl_keyboard == NULL) { - init_keyboard(xwl_seat); - } else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && xwl_seat->wl_keyboard) { - release_keyboard(xwl_seat); - } - - if (caps & WL_SEAT_CAPABILITY_TOUCH && xwl_seat->wl_touch == NULL) { - init_touch(xwl_seat); - } else if (!(caps & WL_SEAT_CAPABILITY_TOUCH) && xwl_seat->wl_touch) { - release_touch(xwl_seat); - } - - xwl_seat->xwl_screen->expecting_event--; -} - -static void -seat_handle_name(void *data, struct wl_seat *seat, - const char *name) -{ - -} - -static const struct wl_seat_listener seat_listener = { - seat_handle_capabilities, - seat_handle_name -}; - -static void -xwl_cursor_init(struct xwl_cursor *xwl_cursor, struct xwl_screen *xwl_screen, - void (* update_proc)(struct xwl_cursor *)) -{ - xwl_cursor->surface = wl_compositor_create_surface(xwl_screen->compositor); - xwl_cursor->update_proc = update_proc; - xwl_cursor->frame_cb = NULL; - xwl_cursor->needs_update = FALSE; -} - -static void -xwl_seat_update_cursor(struct xwl_cursor *xwl_cursor) -{ - struct xwl_seat *xwl_seat = wl_container_of(xwl_cursor, xwl_seat, cursor); - xwl_seat_set_cursor(xwl_seat); -} - -static void -create_input_device(struct xwl_screen *xwl_screen, uint32_t id, uint32_t version) -{ - struct xwl_seat *xwl_seat; - int seat_version = 8; - - xwl_seat = calloc(1, sizeof *xwl_seat); - if (xwl_seat == NULL) { - ErrorF("%s: ENOMEM\n", __func__); - return; - } - - xwl_seat->xwl_screen = xwl_screen; - xorg_list_add(&xwl_seat->link, &xwl_screen->seat_list); - - xwl_seat->seat = - wl_registry_bind(xwl_screen->registry, id, - &wl_seat_interface, min(version, seat_version)); - xwl_seat->id = id; - - xwl_cursor_init(&xwl_seat->cursor, xwl_seat->xwl_screen, - xwl_seat_update_cursor); - wl_seat_add_listener(xwl_seat->seat, &seat_listener, xwl_seat); - - init_tablet_manager_seat(xwl_screen, xwl_seat); - - wl_array_init(&xwl_seat->keys); - - xorg_list_init(&xwl_seat->touches); - xorg_list_init(&xwl_seat->sync_pending); -} - -void -xwl_seat_destroy(struct xwl_seat *xwl_seat) -{ - struct xwl_touch *xwl_touch, *next_xwl_touch; - struct sync_pending *p, *npd; - - xorg_list_for_each_entry_safe(xwl_touch, next_xwl_touch, - &xwl_seat->touches, link_touch) { - xorg_list_del(&xwl_touch->link_touch); - free(xwl_touch); - } - - xorg_list_for_each_entry_safe(p, npd, &xwl_seat->sync_pending, l) { - xorg_list_del(&xwl_seat->sync_pending); - free (p); - } - - release_tablet_manager_seat(xwl_seat); - - release_grab(xwl_seat); - wl_seat_destroy(xwl_seat->seat); - xwl_cursor_release(&xwl_seat->cursor); - wl_array_release(&xwl_seat->keys); - free(xwl_seat); -} - -static void -tablet_handle_name(void *data, struct zwp_tablet_v2 *tablet, const char *name) -{ -} - -static void -tablet_handle_id(void *data, struct zwp_tablet_v2 *tablet, uint32_t vid, - uint32_t pid) -{ -} - -static void -tablet_handle_path(void *data, struct zwp_tablet_v2 *tablet, const char *path) -{ -} - -static void -tablet_handle_done(void *data, struct zwp_tablet_v2 *tablet) -{ - struct xwl_tablet *xwl_tablet = data; - struct xwl_seat *xwl_seat = xwl_tablet->seat; - - if (xwl_seat->stylus == NULL) { - xwl_seat->stylus = add_device(xwl_seat, "xwayland-tablet stylus", xwl_tablet_proc); - ActivateDevice(xwl_seat->stylus, TRUE); - } - enable_device(xwl_seat, xwl_seat->stylus); - - if (xwl_seat->eraser == NULL) { - xwl_seat->eraser = add_device(xwl_seat, "xwayland-tablet eraser", xwl_tablet_proc); - ActivateDevice(xwl_seat->eraser, TRUE); - } - enable_device(xwl_seat, xwl_seat->eraser); - - if (xwl_seat->puck == NULL) { - xwl_seat->puck = add_device(xwl_seat, "xwayland-tablet cursor", xwl_tablet_proc); - ActivateDevice(xwl_seat->puck, TRUE); - } - enable_device(xwl_seat, xwl_seat->puck); -} - -static void -tablet_handle_removed(void *data, struct zwp_tablet_v2 *tablet) -{ - struct xwl_tablet *xwl_tablet = data; - struct xwl_seat *xwl_seat = xwl_tablet->seat; - - xorg_list_del(&xwl_tablet->link); - - /* The tablet is merely disabled, not removed. The next tablet - will re-use the same X devices */ - if (xorg_list_is_empty(&xwl_seat->tablets)) { - if (xwl_seat->stylus) - disable_device(xwl_seat->stylus); - if (xwl_seat->eraser) - disable_device(xwl_seat->eraser); - if (xwl_seat->puck) - disable_device(xwl_seat->puck); - /* pads are removed separately */ - } - - zwp_tablet_v2_destroy(tablet); - free(xwl_tablet); -} - -static const struct zwp_tablet_v2_listener tablet_listener = { - tablet_handle_name, - tablet_handle_id, - tablet_handle_path, - tablet_handle_done, - tablet_handle_removed -}; - -static void -tablet_tool_receive_type(void *data, struct zwp_tablet_tool_v2 *tool, - uint32_t type) -{ - struct xwl_tablet_tool *xwl_tablet_tool = data; - struct xwl_seat *xwl_seat = xwl_tablet_tool->seat; - - switch (type) { - case ZWP_TABLET_TOOL_V2_TYPE_ERASER: - xwl_tablet_tool->xdevice = xwl_seat->eraser; - break; - case ZWP_TABLET_TOOL_V2_TYPE_MOUSE: - case ZWP_TABLET_TOOL_V2_TYPE_LENS: - xwl_tablet_tool->xdevice = xwl_seat->puck; - break; - default: - xwl_tablet_tool->xdevice = xwl_seat->stylus; - break; - } -} - -static void -tablet_tool_receive_hardware_serial(void *data, struct zwp_tablet_tool_v2 *tool, - uint32_t hi, uint32_t low) -{ -} - -static void -tablet_tool_receive_hardware_id_wacom(void *data, struct zwp_tablet_tool_v2 *tool, - uint32_t hi, uint32_t low) -{ -} - -static void -tablet_tool_receive_capability(void *data, struct zwp_tablet_tool_v2 *tool, - uint32_t capability) -{ -} - -static void -tablet_tool_receive_done(void *data, struct zwp_tablet_tool_v2 *tool) -{ -} - -static void -tablet_tool_receive_removed(void *data, struct zwp_tablet_tool_v2 *tool) -{ - struct xwl_tablet_tool *xwl_tablet_tool = data; - - xorg_list_del(&xwl_tablet_tool->link); - xwl_cursor_release(&xwl_tablet_tool->cursor); - zwp_tablet_tool_v2_destroy(tool); - free(xwl_tablet_tool); -} - -static void -tablet_tool_proximity_in(void *data, struct zwp_tablet_tool_v2 *tool, - uint32_t serial, struct zwp_tablet_v2 *tablet, - struct wl_surface *wl_surface) -{ - struct xwl_tablet_tool *xwl_tablet_tool = data; - struct xwl_seat *xwl_seat = xwl_tablet_tool->seat; - - /* There's a race here where if we create and then immediately - * destroy a surface, we might end up in a state where the Wayland - * compositor sends us an event for a surface that doesn't exist. - * - * Don't process enter events in this case. - * - * see pointer_handle_enter() - */ - if (wl_surface == NULL) - return; - - if (!is_surface_from_xwl_window(wl_surface)) - return; - - xwl_tablet_tool->proximity_in_serial = serial; - xwl_seat->tablet_focus_window = wl_surface_get_user_data(wl_surface); - - /* If there is a cursor surface frame callback pending, we need to clear it - * so that we can continue submitting new cursor frames. - */ - xwl_cursor_clear_frame_cb(&xwl_tablet_tool->cursor); - xwl_tablet_tool_set_cursor(xwl_tablet_tool); -} - -static void -tablet_tool_proximity_out(void *data, struct zwp_tablet_tool_v2 *tool) -{ - struct xwl_tablet_tool *xwl_tablet_tool = data; - struct xwl_seat *xwl_seat = xwl_tablet_tool->seat; - - xwl_tablet_tool->proximity_in_serial = 0; - xwl_seat->tablet_focus_window = NULL; - - xwl_tablet_tool->pressure = 0; - xwl_tablet_tool->tilt_x = 0; - xwl_tablet_tool->tilt_y = 0; - xwl_tablet_tool->rotation = 0; - xwl_tablet_tool->slider = 0; -} - -static void -tablet_tool_down(void *data, struct zwp_tablet_tool_v2 *tool, uint32_t serial) -{ - struct xwl_tablet_tool *xwl_tablet_tool = data; - struct xwl_seat *xwl_seat = xwl_tablet_tool->seat; - ValuatorMask mask; - - xwl_seat->xwl_screen->serial = serial; - - valuator_mask_zero(&mask); - QueuePointerEvents(xwl_tablet_tool->xdevice, ButtonPress, 1, 0, &mask); -} - -static void -tablet_tool_up(void *data, struct zwp_tablet_tool_v2 *tool) -{ - struct xwl_tablet_tool *xwl_tablet_tool = data; - ValuatorMask mask; - - valuator_mask_zero(&mask); - QueuePointerEvents(xwl_tablet_tool->xdevice, ButtonRelease, 1, 0, &mask); -} - -static void -tablet_tool_motion(void *data, struct zwp_tablet_tool_v2 *tool, - wl_fixed_t x, wl_fixed_t y) -{ - struct xwl_tablet_tool *xwl_tablet_tool = data; - struct xwl_seat *xwl_seat = xwl_tablet_tool->seat; - struct xwl_screen *xwl_screen = xwl_seat->xwl_screen; - int32_t dx, dy; - double sx = wl_fixed_to_double(x); - double sy = wl_fixed_to_double(y); - - if (!xwl_seat->tablet_focus_window) - return; - - sx *= xwl_screen->global_surface_scale; - sy *= xwl_screen->global_surface_scale; - - sx *= xwl_seat->tablet_focus_window->viewport_scale_x; - sy *= xwl_seat->tablet_focus_window->viewport_scale_y; - - dx = xwl_seat->tablet_focus_window->toplevel->drawable.x; - dy = xwl_seat->tablet_focus_window->toplevel->drawable.y; - - xwl_tablet_tool->x = (double) dx + sx; - xwl_tablet_tool->y = (double) dy + sy; -} - -static void -tablet_tool_pressure(void *data, struct zwp_tablet_tool_v2 *tool, - uint32_t pressure) -{ - struct xwl_tablet_tool *xwl_tablet_tool = data; - struct xwl_seat *xwl_seat = xwl_tablet_tool->seat; - - if (!xwl_seat->tablet_focus_window) - return; - - /* normalized to 65535 already */ - xwl_tablet_tool->pressure = pressure; -} - -static void -tablet_tool_distance(void *data, struct zwp_tablet_tool_v2 *tool, - uint32_t distance_raw) -{ -} - -static void -tablet_tool_tilt(void *data, struct zwp_tablet_tool_v2 *tool, - wl_fixed_t tilt_x, wl_fixed_t tilt_y) -{ - struct xwl_tablet_tool *xwl_tablet_tool = data; - struct xwl_seat *xwl_seat = xwl_tablet_tool->seat; - struct xwl_screen *xwl_screen = xwl_seat->xwl_screen; - - if (!xwl_seat->tablet_focus_window) - return; - - xwl_tablet_tool->tilt_x = wl_fixed_to_double(tilt_x); - xwl_tablet_tool->tilt_y = wl_fixed_to_double(tilt_y); - - xwl_tablet_tool->tilt_x *= xwl_screen->global_surface_scale; - xwl_tablet_tool->tilt_y *= xwl_screen->global_surface_scale; - - xwl_tablet_tool->tilt_x *= xwl_seat->tablet_focus_window->viewport_scale_x; - xwl_tablet_tool->tilt_y *= xwl_seat->tablet_focus_window->viewport_scale_y; -} - -static void -tablet_tool_rotation(void *data, struct zwp_tablet_tool_v2 *tool, - wl_fixed_t angle) -{ - struct xwl_tablet_tool *xwl_tablet_tool = data; - struct xwl_seat *xwl_seat = xwl_tablet_tool->seat; - double rotation = wl_fixed_to_double(angle); - - if (!xwl_seat->tablet_focus_window) - return; - - /* change origin (buttons facing right [libinput +90 degrees]) and - * scaling (5 points per degree) to match wacom driver behavior - */ - rotation = remainderf(rotation + 90.0f, 360.0f); - rotation *= 5.0f; - xwl_tablet_tool->rotation = rotation; -} - -static void -tablet_tool_slider(void *data, struct zwp_tablet_tool_v2 *tool, - int32_t position_raw) -{ - struct xwl_tablet_tool *xwl_tablet_tool = data; - struct xwl_seat *xwl_seat = xwl_tablet_tool->seat; - float position = position_raw / 65535.0; - - if (!xwl_seat->tablet_focus_window) - return; - - xwl_tablet_tool->slider = (position * 1799.0f) - 900.0f; -} - -static void -tablet_tool_wheel(void *data, struct zwp_tablet_tool_v2 *tool, - wl_fixed_t degrees, int32_t clicks) -{ - struct xwl_tablet_tool *xwl_tablet_tool = data; - struct xwl_seat *xwl_seat = xwl_tablet_tool->seat; - - if (!xwl_seat->tablet_focus_window) - return; - - xwl_tablet_tool->wheel_clicks = clicks; -} - -static void -tablet_tool_button_state(void *data, struct zwp_tablet_tool_v2 *tool, - uint32_t serial, uint32_t button, uint32_t state) -{ - struct xwl_tablet_tool *xwl_tablet_tool = data; - struct xwl_seat *xwl_seat = xwl_tablet_tool->seat; - uint32_t *mask = &xwl_tablet_tool->buttons_now; - int xbtn = 0; - - /* BTN_0 .. BTN_9 */ - if (button >= 0x100 && button <= 0x109) { - xbtn = button - 0x100 + 1; - } - /* BTN_A .. BTN_Z */ - else if (button >= 0x130 && button <= 0x135) { - xbtn = button - 0x130 + 10; - } - /* BTN_BASE .. BTN_BASE6 */ - else if (button >= 0x126 && button <= 0x12b) { - xbtn = button - 0x126 + 16; - } - else { - switch (button) { - case 0x110: /* BTN_LEFT */ - case 0x14a: /* BTN_TOUCH */ - xbtn = 1; - break; - - case 0x112: /* BTN_MIDDLE */ - case 0x14b: /* BTN_STYLUS */ - xbtn = 2; - break; - - case 0x111: /* BTN_RIGHT */ - case 0x14c: /* BTN_STYLUS2 */ - xbtn = 3; - break; - - case 0x113: /* BTN_SIDE */ - case 0x116: /* BTN_BACK */ - case 0x149: /* BTN_STYLUS3 */ - xbtn = 8; - break; - - case 0x114: /* BTN_EXTRA */ - case 0x115: /* BTN_FORWARD */ - xbtn = 9; - break; - } - } - - if (!xbtn) { - ErrorF("unknown tablet button number %d\n", button); - return; - } - - BUG_RETURN(xbtn >= 8 * sizeof(*mask)); - - if (state) - SetBit(mask, xbtn - 1); - else - ClearBit(mask, xbtn - 1); - - xwl_seat->xwl_screen->serial = serial; -} - -static void -tablet_tool_frame(void *data, struct zwp_tablet_tool_v2 *tool, uint32_t time) -{ - struct xwl_tablet_tool *xwl_tablet_tool = data; - ValuatorMask mask; - uint32_t released, pressed, diff; - int button; - - valuator_mask_zero(&mask); - valuator_mask_set_double(&mask, 0, xwl_tablet_tool->x); - valuator_mask_set_double(&mask, 1, xwl_tablet_tool->y); - valuator_mask_set(&mask, 2, xwl_tablet_tool->pressure); - valuator_mask_set_double(&mask, 3, xwl_tablet_tool->tilt_x); - valuator_mask_set_double(&mask, 4, xwl_tablet_tool->tilt_y); - valuator_mask_set_double(&mask, 5, xwl_tablet_tool->rotation + xwl_tablet_tool->slider); - - QueuePointerEvents(xwl_tablet_tool->xdevice, MotionNotify, 0, - POINTER_ABSOLUTE | POINTER_DESKTOP, &mask); - - valuator_mask_zero(&mask); - - diff = xwl_tablet_tool->buttons_prev ^ xwl_tablet_tool->buttons_now; - released = diff & ~xwl_tablet_tool->buttons_now; - pressed = diff & xwl_tablet_tool->buttons_now; - - button = 1; - while (released) { - if (released & 0x1) - QueuePointerEvents(xwl_tablet_tool->xdevice, - ButtonRelease, button, 0, &mask); - button++; - released >>= 1; - } - - button = 1; - while (pressed) { - if (pressed & 0x1) - QueuePointerEvents(xwl_tablet_tool->xdevice, - ButtonPress, button, 0, &mask); - button++; - pressed >>= 1; - } - - xwl_tablet_tool->buttons_prev = xwl_tablet_tool->buttons_now; - - while (xwl_tablet_tool->wheel_clicks) { - if (xwl_tablet_tool->wheel_clicks < 0) { - button = 4; - xwl_tablet_tool->wheel_clicks++; - } - else { - button = 5; - xwl_tablet_tool->wheel_clicks--; - } - - QueuePointerEvents(xwl_tablet_tool->xdevice, - ButtonPress, button, 0, &mask); - QueuePointerEvents(xwl_tablet_tool->xdevice, - ButtonRelease, button, 0, &mask); - - } -} - -static const struct zwp_tablet_tool_v2_listener tablet_tool_listener = { - tablet_tool_receive_type, - tablet_tool_receive_hardware_serial, - tablet_tool_receive_hardware_id_wacom, - tablet_tool_receive_capability, - tablet_tool_receive_done, - tablet_tool_receive_removed, - tablet_tool_proximity_in, - tablet_tool_proximity_out, - tablet_tool_down, - tablet_tool_up, - tablet_tool_motion, - tablet_tool_pressure, - tablet_tool_distance, - tablet_tool_tilt, - tablet_tool_rotation, - tablet_tool_slider, - tablet_tool_wheel, - tablet_tool_button_state, - tablet_tool_frame -}; - -static void -tablet_pad_ring_destroy(struct xwl_tablet_pad_ring *ring) -{ - zwp_tablet_pad_ring_v2_destroy(ring->ring); - xorg_list_del(&ring->link); - free(ring); -} - -static void -tablet_pad_ring_source(void *data, - struct zwp_tablet_pad_ring_v2 *zwp_tablet_pad_ring_v2, - uint32_t source) -{ -} - -static void -tablet_pad_ring_angle(void *data, - struct zwp_tablet_pad_ring_v2 *zwp_tablet_pad_ring_v2, - wl_fixed_t degrees) -{ - struct xwl_tablet_pad_ring *ring = data; - struct xwl_tablet_pad *pad = ring->group->pad; - double deg = wl_fixed_to_double(degrees); - ValuatorMask mask; - - valuator_mask_zero(&mask); - valuator_mask_set(&mask, 5 + ring->index, deg/360.0 * 71); - QueuePointerEvents(pad->xdevice, MotionNotify, 0, 0, &mask); -} - -static void -tablet_pad_ring_stop(void *data, - struct zwp_tablet_pad_ring_v2 *zwp_tablet_pad_ring_v2) -{ -} - -static void -tablet_pad_ring_frame(void *data, - struct zwp_tablet_pad_ring_v2 *zwp_tablet_pad_ring_v2, - uint32_t time) -{ -} - -static const struct zwp_tablet_pad_ring_v2_listener tablet_pad_ring_listener = { - tablet_pad_ring_source, - tablet_pad_ring_angle, - tablet_pad_ring_stop, - tablet_pad_ring_frame, -}; - - -static void -tablet_pad_strip_destroy(struct xwl_tablet_pad_strip *strip) -{ - zwp_tablet_pad_strip_v2_destroy(strip->strip); - xorg_list_del(&strip->link); - free(strip); -} - -static void -tablet_pad_strip_source(void *data, - struct zwp_tablet_pad_strip_v2 *zwp_tablet_pad_strip_v2, - uint32_t source) -{ -} - -static void -tablet_pad_strip_position(void *data, - struct zwp_tablet_pad_strip_v2 *zwp_tablet_pad_strip_v2, - uint32_t position) -{ - struct xwl_tablet_pad_strip *strip = data; - struct xwl_tablet_pad *pad = strip->group->pad; - ValuatorMask mask; - - valuator_mask_zero(&mask); - valuator_mask_set(&mask, 3 + strip->index, position/65535.0 * 2048); - QueuePointerEvents(pad->xdevice, MotionNotify, 0, 0, &mask); -} - -static void -tablet_pad_strip_stop(void *data, - struct zwp_tablet_pad_strip_v2 *zwp_tablet_pad_strip_v2) -{ -} - -static void -tablet_pad_strip_frame(void *data, - struct zwp_tablet_pad_strip_v2 *zwp_tablet_pad_strip_v2, - uint32_t time) -{ -} - -static const struct zwp_tablet_pad_strip_v2_listener tablet_pad_strip_listener = { - tablet_pad_strip_source, - tablet_pad_strip_position, - tablet_pad_strip_stop, - tablet_pad_strip_frame, -}; - -static void -tablet_pad_group_destroy(struct xwl_tablet_pad_group *group) -{ - struct xwl_tablet_pad_ring *r, *tr; - struct xwl_tablet_pad_strip *s, *ts; - - xorg_list_for_each_entry_safe(r, tr, - &group->pad_group_ring_list, - link) - tablet_pad_ring_destroy(r); - - xorg_list_for_each_entry_safe(s, ts, - &group->pad_group_strip_list, - link) - tablet_pad_strip_destroy(s); - - zwp_tablet_pad_group_v2_destroy(group->group); - xorg_list_del(&group->link); - free(group); -} - -static void -tablet_pad_group_buttons(void *data, - struct zwp_tablet_pad_group_v2 *zwp_tablet_pad_group_v2, - struct wl_array *buttons) -{ - -} - -static void -tablet_pad_group_ring(void *data, - struct zwp_tablet_pad_group_v2 *zwp_tablet_pad_group_v2, - struct zwp_tablet_pad_ring_v2 *wp_ring) -{ - static unsigned int ring_index = 0; - struct xwl_tablet_pad_group *group = data; - struct xwl_tablet_pad_ring *ring; - - ring = calloc(1, sizeof *ring); - if (ring == NULL) { - ErrorF("%s ENOMEM\n", __func__); - return; - } - - ring->index = ring_index++; - ring->group = group; - ring->ring = wp_ring; - - xorg_list_add(&ring->link, &group->pad_group_ring_list); - - zwp_tablet_pad_ring_v2_add_listener(wp_ring, &tablet_pad_ring_listener, - ring); -} - -static void -tablet_pad_group_strip(void *data, - struct zwp_tablet_pad_group_v2 *zwp_tablet_pad_group_v2, - struct zwp_tablet_pad_strip_v2 *wp_strip) -{ - static unsigned int strip_index = 0; - struct xwl_tablet_pad_group *group = data; - struct xwl_tablet_pad_strip *strip; - - strip = calloc(1, sizeof *strip); - if (strip == NULL) { - ErrorF("%s ENOMEM\n", __func__); - return; - } - - strip->index = strip_index++; - strip->group = group; - strip->strip = wp_strip; - - xorg_list_add(&strip->link, &group->pad_group_strip_list); - - zwp_tablet_pad_strip_v2_add_listener(wp_strip, &tablet_pad_strip_listener, - strip); -} - -static void -tablet_pad_group_modes(void *data, - struct zwp_tablet_pad_group_v2 *zwp_tablet_pad_group_v2, - uint32_t modes) -{ - -} - -static void -tablet_pad_group_done(void *data, - struct zwp_tablet_pad_group_v2 *zwp_tablet_pad_group_v2) -{ - -} - -static void -tablet_pad_group_mode_switch(void *data, - struct zwp_tablet_pad_group_v2 *zwp_tablet_pad_group_v2, - uint32_t time, - uint32_t serial, - uint32_t mode) -{ - -} - -static struct zwp_tablet_pad_group_v2_listener tablet_pad_group_listener = { - tablet_pad_group_buttons, - tablet_pad_group_ring, - tablet_pad_group_strip, - tablet_pad_group_modes, - tablet_pad_group_done, - tablet_pad_group_mode_switch, -}; - -static int -xwl_tablet_pad_proc(DeviceIntPtr device, int what) -{ - struct xwl_tablet_pad *pad = dixGetPrivate(&device->devPrivates, - &xwl_tablet_private_key); - /* Axis layout mirrors that of xf86-input-wacom to have better - compatibility with existing clients */ -#define NAXES 7 - Atom axes_labels[NAXES] = { 0 }; - BYTE map[MAX_BUTTONS + 1]; - int i = 0; - Atom btn_labels[MAX_BUTTONS] = { 0 }; /* btn labels are meaningless */ - int nbuttons; - - switch (what) { - case DEVICE_INIT: - device->public.on = FALSE; - - axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_X); - axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_Y); - /* The others have no good mapping */ - - if (!InitValuatorClassDeviceStruct(device, NAXES, axes_labels, - GetMotionHistorySize(), Absolute)) - return BadValue; - - for (i = 1; i <= MAX_BUTTONS; i++) - map[i] = i; - - /* We need at least 7 buttons to allow scrolling */ - nbuttons = min(max(pad->nbuttons + 4, 7), MAX_BUTTONS); - - if (!InitButtonClassDeviceStruct(device, nbuttons, - btn_labels, map)) - return BadValue; - - /* Valuators */ - InitValuatorAxisStruct(device, 0, axes_labels[0], - 0, 100, 1, 0, 1, Absolute); - InitValuatorAxisStruct(device, 1, axes_labels[1], - 0, 100, 1, 0, 1, Absolute); - /* Pressure - unused, for backwards compat only */ - InitValuatorAxisStruct(device, 2, axes_labels[2], - 0, 2048, 1, 0, 1, Absolute); - /* strip x */ - InitValuatorAxisStruct(device, 3, axes_labels[3], - 0, 2048, 1, 0, 1, Absolute); - /* strip y */ - InitValuatorAxisStruct(device, 4, axes_labels[4], - 0, 2048, 1, 0, 1, Absolute); - /* ring */ - InitValuatorAxisStruct(device, 5, axes_labels[5], - 0, 71, 1, 0, 1, Absolute); - /* ring2 */ - InitValuatorAxisStruct(device, 6, axes_labels[6], - 0, 71, 1, 0, 1, Absolute); - - if (!InitPtrFeedbackClassDeviceStruct(device, xwl_pointer_control)) - return BadValue; - - return Success; - - case DEVICE_ON: - device->public.on = TRUE; - return Success; - - case DEVICE_OFF: - case DEVICE_CLOSE: - device->public.on = FALSE; - return Success; - } - - return BadMatch; -#undef NAXES -} - -static void -tablet_pad_group(void *data, - struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2, - struct zwp_tablet_pad_group_v2 *pad_group) -{ - struct xwl_tablet_pad *pad = data; - struct xwl_tablet_pad_group *group; - - group = calloc(1, sizeof *group); - if (group == NULL) { - ErrorF("%s ENOMEM\n", __func__); - return; - } - - group->pad = pad; - group->group = pad_group; - xorg_list_init(&group->pad_group_ring_list); - xorg_list_init(&group->pad_group_strip_list); - - xorg_list_add(&group->link, &pad->pad_group_list); - - zwp_tablet_pad_group_v2_add_listener(pad_group, - &tablet_pad_group_listener, - group); -} - -static void -tablet_pad_path(void *data, - struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2, - const char *path) -{ - -} - -static void -tablet_pad_buttons(void *data, - struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2, - uint32_t buttons) -{ - struct xwl_tablet_pad *pad = data; - - pad->nbuttons = buttons; -} - -static void -tablet_pad_done(void *data, - struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2) -{ - struct xwl_tablet_pad *pad = data; - - pad->xdevice = add_device(pad->seat, "xwayland-tablet-pad", - xwl_tablet_pad_proc); - dixSetPrivate(&pad->xdevice->devPrivates, &xwl_tablet_private_key, pad); - ActivateDevice(pad->xdevice, TRUE); - EnableDevice(pad->xdevice, TRUE); -} - -static void -tablet_pad_button(void *data, - struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2, - uint32_t time, - uint32_t button, - uint32_t state) -{ - struct xwl_tablet_pad *pad = data; - ValuatorMask mask; - - button++; /* wayland index vs X's 1-offset */ - /* skip scroll wheel buttons 4-7 */ - button = button > 3 ? button + 4 : button; - - valuator_mask_zero(&mask); - QueuePointerEvents(pad->xdevice, - state ? ButtonPress : ButtonRelease, button, 0, &mask); -} - -static void -tablet_pad_enter(void *data, - struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2, - uint32_t serial, - struct zwp_tablet_v2 *tablet, - struct wl_surface *surface) -{ - /* pairs the pad with the tablet but also to set the focus. We - * don't care about the pairing and always use X's focus */ -} - -static void -tablet_pad_leave(void *data, - struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2, - uint32_t serial, - struct wl_surface *surface) -{ - /* pairs the pad with the tablet but also to set the focus. We - * don't care about the pairing and always use X's focus */ -} - -static void -tablet_pad_removed(void *data, - struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2) -{ - struct xwl_tablet_pad *pad = data; - struct xwl_tablet_pad_group *g, *tg; - - xorg_list_for_each_entry_safe(g, tg, &pad->pad_group_list, link) - tablet_pad_group_destroy(g); - - RemoveDevice(pad->xdevice, TRUE); - xorg_list_del(&pad->link); - zwp_tablet_pad_v2_destroy(pad->pad); - free(pad); -} - -static const struct zwp_tablet_pad_v2_listener tablet_pad_listener = { - tablet_pad_group, - tablet_pad_path, - tablet_pad_buttons, - tablet_pad_done, - tablet_pad_button, - tablet_pad_enter, - tablet_pad_leave, - tablet_pad_removed, -}; - -static void -tablet_seat_handle_add_tablet(void *data, struct zwp_tablet_seat_v2 *tablet_seat, - struct zwp_tablet_v2 *tablet) -{ - struct xwl_seat *xwl_seat = data; - struct xwl_tablet *xwl_tablet; - - xwl_tablet = calloc(1, sizeof *xwl_tablet); - if (xwl_tablet == NULL) { - ErrorF("%s ENOMEM\n", __func__); - return; - } - - xwl_tablet->tablet = tablet; - xwl_tablet->seat = xwl_seat; - - xorg_list_add(&xwl_tablet->link, &xwl_seat->tablets); - - zwp_tablet_v2_add_listener(tablet, &tablet_listener, xwl_tablet); -} - -static void -xwl_tablet_tool_update_cursor(struct xwl_cursor *xwl_cursor) -{ - struct xwl_tablet_tool *xwl_tablet_tool = wl_container_of(xwl_cursor, - xwl_tablet_tool, - cursor); - xwl_tablet_tool_set_cursor(xwl_tablet_tool); -} - -static void -tablet_seat_handle_add_tool(void *data, struct zwp_tablet_seat_v2 *tablet_seat, - struct zwp_tablet_tool_v2 *tool) -{ - struct xwl_seat *xwl_seat = data; - struct xwl_screen *xwl_screen = xwl_seat->xwl_screen; - struct xwl_tablet_tool *xwl_tablet_tool; - - xwl_tablet_tool = calloc(1, sizeof *xwl_tablet_tool); - if (xwl_tablet_tool == NULL) { - ErrorF("%s ENOMEM\n", __func__); - return; - } - - xwl_tablet_tool->tool = tool; - xwl_tablet_tool->seat = xwl_seat; - xwl_cursor_init(&xwl_tablet_tool->cursor, xwl_screen, - xwl_tablet_tool_update_cursor); - - xorg_list_add(&xwl_tablet_tool->link, &xwl_seat->tablet_tools); - - zwp_tablet_tool_v2_add_listener(tool, &tablet_tool_listener, xwl_tablet_tool); -} - -static void -tablet_seat_handle_add_pad(void *data, struct zwp_tablet_seat_v2 *tablet_seat, - struct zwp_tablet_pad_v2 *pad) -{ - struct xwl_seat *xwl_seat = data; - struct xwl_tablet_pad *xwl_tablet_pad; - - xwl_tablet_pad = calloc(1, sizeof *xwl_tablet_pad); - if (xwl_tablet_pad == NULL) { - ErrorF("%s ENOMEM\n", __func__); - return; - } - - xwl_tablet_pad->pad = pad; - xwl_tablet_pad->seat = xwl_seat; - xorg_list_init(&xwl_tablet_pad->pad_group_list); - - xorg_list_add(&xwl_tablet_pad->link, &xwl_seat->tablet_pads); - - zwp_tablet_pad_v2_add_listener(pad, &tablet_pad_listener, - xwl_tablet_pad); -} - -static const struct zwp_tablet_seat_v2_listener tablet_seat_listener = { - tablet_seat_handle_add_tablet, - tablet_seat_handle_add_tool, - tablet_seat_handle_add_pad -}; - -static void -init_tablet_manager_seat(struct xwl_screen *xwl_screen, - struct xwl_seat *xwl_seat) -{ - xorg_list_init(&xwl_seat->tablets); - xorg_list_init(&xwl_seat->tablet_tools); - xorg_list_init(&xwl_seat->tablet_pads); - - if (!xwl_screen->tablet_manager) - return; - - xwl_seat->tablet_seat = - zwp_tablet_manager_v2_get_tablet_seat(xwl_screen->tablet_manager, - xwl_seat->seat); - - zwp_tablet_seat_v2_add_listener(xwl_seat->tablet_seat, &tablet_seat_listener, xwl_seat); -} - -static void -release_tablet_manager_seat(struct xwl_seat *xwl_seat) -{ - struct xwl_tablet *xwl_tablet, *next_xwl_tablet; - struct xwl_tablet_tool *xwl_tablet_tool, *next_xwl_tablet_tool; - struct xwl_tablet_pad *xwl_tablet_pad, *next_xwl_tablet_pad; - - xorg_list_for_each_entry_safe(xwl_tablet_pad, next_xwl_tablet_pad, - &xwl_seat->tablet_pads, link) { - xorg_list_del(&xwl_tablet_pad->link); - zwp_tablet_pad_v2_destroy(xwl_tablet_pad->pad); - free(xwl_tablet_pad); - } - - xorg_list_for_each_entry_safe(xwl_tablet_tool, next_xwl_tablet_tool, - &xwl_seat->tablet_tools, link) { - xorg_list_del(&xwl_tablet_tool->link); - zwp_tablet_tool_v2_destroy(xwl_tablet_tool->tool); - free(xwl_tablet_tool); - } - - xorg_list_for_each_entry_safe(xwl_tablet, next_xwl_tablet, - &xwl_seat->tablets, link) { - xorg_list_del(&xwl_tablet->link); - zwp_tablet_v2_destroy(xwl_tablet->tablet); - free(xwl_tablet); - } - - if (xwl_seat->tablet_seat) { - zwp_tablet_seat_v2_destroy(xwl_seat->tablet_seat); - xwl_seat->tablet_seat = NULL; - } -} - -static void -init_tablet_manager(struct xwl_screen *xwl_screen, uint32_t id, uint32_t version) -{ - struct xwl_seat *xwl_seat; - - xwl_screen->tablet_manager = wl_registry_bind(xwl_screen->registry, - id, - &zwp_tablet_manager_v2_interface, - min(version,1)); - - xorg_list_for_each_entry(xwl_seat, &xwl_screen->seat_list, link) { - init_tablet_manager_seat(xwl_screen, xwl_seat); - } -} - -void -xwl_screen_release_tablet_manager(struct xwl_screen *xwl_screen) -{ - if (xwl_screen->tablet_manager) { - zwp_tablet_manager_v2_destroy(xwl_screen->tablet_manager); - xwl_screen->tablet_manager = NULL; - } -} - -static void -init_relative_pointer_manager(struct xwl_screen *xwl_screen, - uint32_t id, uint32_t version) -{ - xwl_screen->relative_pointer_manager = - wl_registry_bind(xwl_screen->registry, id, - &zwp_relative_pointer_manager_v1_interface, - 1); -} - -static void -init_pointer_constraints(struct xwl_screen *xwl_screen, - uint32_t id, uint32_t version) -{ - xwl_screen->pointer_constraints = - wl_registry_bind(xwl_screen->registry, id, - &zwp_pointer_constraints_v1_interface, - 1); -} - -static void -init_pointer_gestures(struct xwl_screen *xwl_screen, - uint32_t id, uint32_t version) -{ - xwl_screen->pointer_gestures = - wl_registry_bind(xwl_screen->registry, id, - &zwp_pointer_gestures_v1_interface, - 1); -} - -static void -init_keyboard_grab(struct xwl_screen *xwl_screen, - uint32_t id, uint32_t version) -{ - struct xwl_seat *xwl_seat; - DeviceIntPtr master; - - xwl_screen->wp_grab = - wl_registry_bind(xwl_screen->registry, id, - &zwp_xwayland_keyboard_grab_manager_v1_interface, - 1); - - xorg_list_for_each_entry(xwl_seat, &xwl_screen->seat_list, link) { - if (xwl_seat->keyboard) { - master = GetMaster(xwl_seat->keyboard, MASTER_KEYBOARD); - if (master) - setup_keyboard_grab_handler(master); - } - } -} - -static void -init_keyboard_shortcuts_inhibit(struct xwl_screen *xwl_screen, - uint32_t id, uint32_t version) -{ - xwl_screen->shortcuts_inhibit_manager = - wl_registry_bind(xwl_screen->registry, id, - &zwp_keyboard_shortcuts_inhibit_manager_v1_interface, - 1); -} - -static void -init_system_bell(struct xwl_screen *xwl_screen, uint32_t id, uint32_t version) -{ - xwl_screen->system_bell = - wl_registry_bind(xwl_screen->registry, id, - &xdg_system_bell_v1_interface, - 1); -} - -/* The compositor may send us wl_seat and its capabilities before sending e.g. - relative_pointer_manager or pointer_gesture interfaces. This would result in - devices being created in capabilities handler, but listeners not, because - the interfaces weren't available at the time. So we manually attempt to setup - listeners again. -*/ -static void -maybe_init_relative_pointer_listeners_after_capabilities(struct xwl_screen* xwl_screen) -{ - struct xwl_seat *xwl_seat; - xorg_list_for_each_entry(xwl_seat, &xwl_screen->seat_list, link) { - if (xwl_seat->wl_pointer) { - init_relative_pointer_listener(xwl_seat); - } - } -} - -static void -maybe_init_pointer_gesture_listeners_after_capabilities(struct xwl_screen* xwl_screen) -{ - struct xwl_seat *xwl_seat; - xorg_list_for_each_entry(xwl_seat, &xwl_screen->seat_list, link) { - if (xwl_seat->wl_pointer) { - init_pointer_gestures_listener(xwl_seat); - } - } -} - -static void -input_handler(void *data, struct wl_registry *registry, uint32_t id, - const char *interface, uint32_t version) -{ - struct xwl_screen *xwl_screen = data; - - if (strcmp(interface, wl_seat_interface.name) == 0 && version >= 3) { - create_input_device(xwl_screen, id, version); - xwl_screen->expecting_event++; - } else if (strcmp(interface, zwp_relative_pointer_manager_v1_interface.name) == 0) { - init_relative_pointer_manager(xwl_screen, id, version); - maybe_init_relative_pointer_listeners_after_capabilities(xwl_screen); - } else if (strcmp(interface, zwp_pointer_constraints_v1_interface.name) == 0) { - init_pointer_constraints(xwl_screen, id, version); - } else if (strcmp(interface, zwp_pointer_gestures_v1_interface.name) == 0) { - init_pointer_gestures(xwl_screen, id, version); - maybe_init_pointer_gesture_listeners_after_capabilities(xwl_screen); - } else if (strcmp(interface, zwp_tablet_manager_v2_interface.name) == 0) { - init_tablet_manager(xwl_screen, id, version); - } else if (strcmp(interface, zwp_xwayland_keyboard_grab_manager_v1_interface.name) == 0) { - init_keyboard_grab(xwl_screen, id, version); - } else if (strcmp(interface, zwp_keyboard_shortcuts_inhibit_manager_v1_interface.name) == 0) { - init_keyboard_shortcuts_inhibit(xwl_screen, id, version); - } else if (strcmp(interface, xdg_system_bell_v1_interface.name) == 0) { - init_system_bell(xwl_screen, id, version); - } -} - -static void -global_remove(void *data, struct wl_registry *registry, uint32_t name) -{ -} - -static const struct wl_registry_listener input_listener = { - input_handler, - global_remove, -}; - -void -ProcessInputEvents(void) -{ - mieqProcessInputEvents(); -} - -void -DDXRingBell(int volume, int pitch, int duration) -{ - ScreenPtr screen = screenInfo.screens[0]; - struct xwl_screen *xwl_screen; - struct xwl_seat *xwl_seat; - - xwl_screen = xwl_screen_get(screen); - if (!xwl_screen->system_bell) - return; - - xorg_list_for_each_entry(xwl_seat, &xwl_screen->seat_list, link) { - if (!xwl_seat->keyboard) - continue; - - if (!xwl_seat->keyboard->coreEvents) - continue; - - if (!xwl_seat->keyboard_focus) - continue; - - DebugF("XWAYLAND: Ringing the bell\n"); - xdg_system_bell_v1_ring (xwl_screen->system_bell, xwl_seat->keyboard_focus); - return; - } -} - -static Bool -sprite_check_lost_focus(SpritePtr sprite, WindowPtr window) -{ - DeviceIntPtr device, master; - struct xwl_seat *xwl_seat; - - for (device = inputInfo.devices; device; device = device->next) { - /* Ignore non-wayland devices */ - if (device->deviceProc == xwl_pointer_proc && - device->spriteInfo->sprite == sprite) - break; - } - - if (!device) - return FALSE; - - xwl_seat = device->public.devicePrivate; - if (!xwl_seat) - return FALSE; - - master = GetMaster(device, POINTER_OR_FLOAT); - if (!master || !master->lastSlave) - return FALSE; - - /* We do want the last active slave, we only check on slave xwayland - * devices so we can find out the xwl_seat, but those don't actually own - * their sprite, so the match doesn't mean a lot. - */ - if (master->lastSlave != get_pointer_device(xwl_seat)) - return FALSE; - - if (xwl_seat->focus_window != NULL && - xwl_seat->cursor_confinement_window != NULL && - xwl_seat->focus_window != xwl_seat->cursor_confinement_window) - return TRUE; - - if (xwl_seat->focus_window == NULL && - xwl_seat->last_focus_window != NULL && - (xwl_seat->last_focus_window->toplevel == window || - WindowIsParent(xwl_seat->last_focus_window->toplevel, window))) - return TRUE; - - return FALSE; -} - -static WindowPtr -xwl_xy_to_window(ScreenPtr screen, SpritePtr sprite, int x, int y) -{ - struct xwl_screen *xwl_screen; - WindowPtr ret; - - xwl_screen = xwl_screen_get(screen); - - screen->XYToWindow = xwl_screen->XYToWindow; - ret = screen->XYToWindow(screen, sprite, x, y); - xwl_screen->XYToWindow = screen->XYToWindow; - screen->XYToWindow = xwl_xy_to_window; - - /* If the device controlling the sprite has left the Wayland surface but - * the DIX still finds the pointer within the X11 window, it means that - * the pointer has crossed to another native Wayland window, in this - * case, pretend we entered the root window so that a LeaveNotify - * event is emitted. - */ - if (sprite_check_lost_focus(sprite, ret)) { - sprite->spriteTraceGood = 1; - return sprite->spriteTrace[0]; - } - - return ret; -} - -void -xwl_seat_clear_touch(struct xwl_seat *xwl_seat, struct xwl_window *xwl_window) -{ - struct xwl_touch *xwl_touch, *next_xwl_touch; - - xorg_list_for_each_entry_safe(xwl_touch, next_xwl_touch, - &xwl_seat->touches, link_touch) { - if (xwl_touch->window == xwl_window) { - xorg_list_del(&xwl_touch->link_touch); - free(xwl_touch); - } - } -} - -static void -xwl_pointer_warp_emulator_set_fake_pos(struct xwl_pointer_warp_emulator *warp_emulator, - int x, - int y) -{ - struct zwp_locked_pointer_v1 *locked_pointer = - warp_emulator->locked_pointer; - WindowPtr window; - int sx, sy; - - if (!warp_emulator->locked_pointer) - return; - - if (!warp_emulator->xwl_seat->focus_window) - return; - - window = warp_emulator->xwl_seat->focus_window->toplevel; - if (x >= window->drawable.x || - y >= window->drawable.y || - x < (window->drawable.x + window->drawable.width) || - y < (window->drawable.y + window->drawable.height)) { - sx = x - window->drawable.x; - sy = y - window->drawable.y; - zwp_locked_pointer_v1_set_cursor_position_hint(locked_pointer, - wl_fixed_from_int(sx), - wl_fixed_from_int(sy)); - wl_surface_commit(warp_emulator->xwl_seat->focus_window->surface); - } -} - -static Bool -xwl_pointer_warp_emulator_is_locked(struct xwl_pointer_warp_emulator *warp_emulator) -{ - if (warp_emulator->locked_pointer) - return TRUE; - else - return FALSE; -} - -static void -xwl_pointer_warp_emulator_lock(struct xwl_pointer_warp_emulator *warp_emulator) -{ - BUG_RETURN(!warp_emulator); - struct xwl_seat *xwl_seat = warp_emulator->xwl_seat; - struct xwl_screen *xwl_screen = xwl_seat->xwl_screen; - struct zwp_pointer_constraints_v1 *pointer_constraints = - xwl_screen->pointer_constraints; - struct xwl_window *lock_window = xwl_seat->focus_window; - - warp_emulator->locked_window = lock_window; - - warp_emulator->locked_pointer = - zwp_pointer_constraints_v1_lock_pointer(pointer_constraints, - lock_window->surface, - xwl_seat->wl_pointer, - NULL, - ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT); -} - -static void -xwl_pointer_warp_emulator_maybe_lock(struct xwl_pointer_warp_emulator *warp_emulator, - struct xwl_window *xwl_window, - SpritePtr sprite, - int x, int y) -{ - struct xwl_seat *xwl_seat = warp_emulator->xwl_seat; - GrabPtr pointer_grab = xwl_seat->pointer->deviceGrab.grab; - - if (warp_emulator->locked_pointer) - return; - - /* - * If there is no grab, and the window doesn't have pointer focus, ignore - * the warp, as under Wayland it won't receive input anyway. - */ - if (!pointer_grab && xwl_seat->focus_window != xwl_window) - return; - - /* - * If there is a grab, but it's not an ownerEvents grab and the destination - * is not the pointer focus, ignore it, as events wouldn't be delivered - * there anyway. - */ - if (pointer_grab && - !pointer_grab->ownerEvents && - sprite && - XYToWindow(sprite, x, y) != xwl_seat->focus_window->toplevel) - return; - - xwl_pointer_warp_emulator_lock(warp_emulator); -} - -static void -xwl_pointer_warp_emulator_warp(struct xwl_pointer_warp_emulator *warp_emulator, - struct xwl_window *xwl_window, - SpritePtr sprite, - int x, int y) -{ - xwl_pointer_warp_emulator_maybe_lock(warp_emulator, - xwl_window, - sprite, - x, y); - xwl_pointer_warp_emulator_set_fake_pos(warp_emulator, x, y); -} - -static void -xwl_pointer_warp_emulator_handle_motion(struct xwl_pointer_warp_emulator *warp_emulator, - double dx, - double dy, - double dx_unaccel, - double dy_unaccel) -{ - struct xwl_seat *xwl_seat = warp_emulator->xwl_seat; - ValuatorMask mask; - WindowPtr window; - int x, y; - - valuator_mask_zero(&mask); - valuator_mask_set_unaccelerated(&mask, 0, dx, dx_unaccel); - valuator_mask_set_unaccelerated(&mask, 1, dy, dy_unaccel); - - QueuePointerEvents(xwl_seat->relative_pointer, MotionNotify, 0, - POINTER_RELATIVE, &mask); - - window = xwl_seat->focus_window->toplevel; - miPointerGetPosition(xwl_seat->pointer, &x, &y); - - if (xwl_pointer_warp_emulator_is_locked(warp_emulator) && - xwl_seat->cursor_confinement_window != warp_emulator->locked_window && - (x < window->drawable.x || - y < window->drawable.y || - x >= (window->drawable.x + window->drawable.width) || - y >= (window->drawable.y + window->drawable.height))) - xwl_seat_destroy_pointer_warp_emulator(xwl_seat); - else - xwl_pointer_warp_emulator_set_fake_pos(warp_emulator, x, y); -} - -static struct xwl_pointer_warp_emulator * -xwl_pointer_warp_emulator_create(struct xwl_seat *xwl_seat) -{ - struct xwl_pointer_warp_emulator *warp_emulator; - - warp_emulator = calloc(1, sizeof *warp_emulator); - if (!warp_emulator) { - ErrorF("%s: ENOMEM\n", __func__); - return NULL; - } - - warp_emulator->xwl_seat = xwl_seat; - - return warp_emulator; -} - -static void -xwl_pointer_warp_emulator_destroy(struct xwl_pointer_warp_emulator *warp_emulator) -{ - if (warp_emulator->locked_pointer) - zwp_locked_pointer_v1_destroy(warp_emulator->locked_pointer); - free(warp_emulator); -} - -static void -xwl_seat_create_pointer_warp_emulator(struct xwl_seat *xwl_seat) -{ - if (xwl_seat->confined_pointer) - xwl_seat_destroy_confined_pointer(xwl_seat); - - xwl_seat->pointer_warp_emulator = - xwl_pointer_warp_emulator_create(xwl_seat); -} - -static Bool -xwl_seat_can_emulate_pointer_warp(struct xwl_seat *xwl_seat) -{ - struct xwl_screen *xwl_screen; - - if (!xwl_seat) - return FALSE; - - if (!xwl_seat->pointer) - return FALSE; - - xwl_screen = xwl_seat->xwl_screen; - - if (!xwl_screen->relative_pointer_manager) - return FALSE; - - if (!xwl_screen->pointer_constraints) - return FALSE; - - return TRUE; -} - -void -xwl_seat_emulate_pointer_warp(struct xwl_seat *xwl_seat, - struct xwl_window *xwl_window, - SpritePtr sprite, - int x, int y) -{ - if (!xwl_seat_can_emulate_pointer_warp(xwl_seat)) - return; - - if (xwl_seat->x_cursor != NULL) - return; - - if (!xwl_seat->pointer_warp_emulator) - xwl_seat_create_pointer_warp_emulator(xwl_seat); - - if (!xwl_seat->pointer_warp_emulator) - return; - - xwl_pointer_warp_emulator_warp(xwl_seat->pointer_warp_emulator, - xwl_window, - sprite, - x, y); -} - -static Bool -xwl_seat_maybe_lock_on_hidden_cursor(struct xwl_seat *xwl_seat) -{ - struct xwl_screen *xwl_screen = xwl_seat->xwl_screen; - - /* Some clients use hidden cursor+confineTo+relative motion - * to implement infinite panning (eg. 3D views), lock the - * pointer for so the relative pointer is used. - */ - if (xwl_seat->x_cursor) - return FALSE; - - if (!xwl_seat->focus_window) - return FALSE; - - if (!xwl_screen->rootless) - return FALSE; - - if (xwl_seat->cursor_confinement_window != xwl_seat->focus_window) - return FALSE; - - if (xwl_seat->confined_pointer) - xwl_seat_destroy_confined_pointer(xwl_seat); - - xwl_seat_create_pointer_warp_emulator(xwl_seat); - xwl_pointer_warp_emulator_lock(xwl_seat->pointer_warp_emulator); - return TRUE; -} - -void -xwl_seat_cursor_visibility_changed(struct xwl_seat *xwl_seat) -{ - if (xwl_seat->pointer_warp_emulator && xwl_seat->x_cursor != NULL) { - xwl_seat_destroy_pointer_warp_emulator(xwl_seat); - } else if (!xwl_seat->x_cursor && xwl_seat->cursor_confinement_window) { - /* If the cursor goes hidden as is confined, lock it for - * relative motion to work. */ - xwl_seat_maybe_lock_on_hidden_cursor(xwl_seat); - } -} - -void -xwl_seat_destroy_pointer_warp_emulator(struct xwl_seat *xwl_seat) -{ - if (!xwl_seat->pointer_warp_emulator) - return; - - xwl_pointer_warp_emulator_destroy(xwl_seat->pointer_warp_emulator); - xwl_seat->pointer_warp_emulator = NULL; - - if (xwl_seat->cursor_confinement_window) { - xwl_seat_confine_pointer(xwl_seat, - xwl_seat->cursor_confinement_window); - } -} - -void -xwl_seat_confine_pointer(struct xwl_seat *xwl_seat, - struct xwl_window *xwl_window) -{ - struct zwp_pointer_constraints_v1 *pointer_constraints = - xwl_seat->xwl_screen->pointer_constraints; - - if (!pointer_constraints) - return; - - if (!xwl_seat->wl_pointer) - return; - - if (xwl_seat->cursor_confinement_window == xwl_window && - xwl_seat->confined_pointer) - return; - - xwl_seat_unconfine_pointer(xwl_seat); - - xwl_seat->cursor_confinement_window = xwl_window; - - if (xwl_seat->pointer_warp_emulator) - return; - - if (xwl_seat_maybe_lock_on_hidden_cursor(xwl_seat)) - return; - - xwl_seat->confined_pointer = - zwp_pointer_constraints_v1_confine_pointer(pointer_constraints, - xwl_window->surface, - xwl_seat->wl_pointer, - NULL, - ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT); -} - -static void -xwl_seat_destroy_confined_pointer(struct xwl_seat *xwl_seat) -{ - zwp_confined_pointer_v1_destroy(xwl_seat->confined_pointer); - xwl_seat->confined_pointer = NULL; -} - -void -xwl_seat_unconfine_pointer(struct xwl_seat *xwl_seat) -{ - xwl_seat->cursor_confinement_window = NULL; - - if (xwl_seat->confined_pointer) - xwl_seat_destroy_confined_pointer(xwl_seat); -} - -void -InitInput(int argc, char *argv[]) -{ - ScreenPtr pScreen = screenInfo.screens[0]; - struct xwl_screen *xwl_screen = xwl_screen_get(pScreen); - - if (!dixRegisterPrivateKey(&xwl_tablet_private_key, PRIVATE_DEVICE, 0)) { - ErrorF("Failed to register private key\n"); - return; - } - - mieqInit(); - - inputInfo.keyboard->ignoreXkbActionsBehaviors = TRUE; - xwl_screen->input_registry = wl_display_get_registry(xwl_screen->display); - wl_registry_add_listener(xwl_screen->input_registry, &input_listener, - xwl_screen); - - xwl_screen->XYToWindow = pScreen->XYToWindow; - pScreen->XYToWindow = xwl_xy_to_window; - - xwl_screen_roundtrip(xwl_screen); -#ifdef XWL_HAS_EI - if (xwl_screen->rootless) - xwayland_override_xtest(); -#endif -} - -void -CloseInput(void) -{ -#ifdef XWL_HAS_EI - xwayland_restore_xtest(); -#endif - mieqFini(); -} diff --git a/hw/xwayland/xwayland-input.h b/hw/xwayland/xwayland-input.h deleted file mode 100644 index d40bca08a..000000000 --- a/hw/xwayland/xwayland-input.h +++ /dev/null @@ -1,215 +0,0 @@ -/* - * Copyright © 2014 Intel Corporation - * Copyright © 2008 Kristian Høgsberg - * - * Permission to use, copy, modify, distribute, and sell this software - * and its documentation for any purpose is hereby granted without - * fee, provided that the above copyright notice appear in all copies - * and that both that copyright notice and this permission notice - * appear in supporting documentation, and that the name of the - * copyright holders not be used in advertising or publicity - * pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied - * warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS - * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. - */ - -#ifndef XWAYLAND_INPUT_H -#define XWAYLAND_INPUT_H - -#include -#include - -#include -#include - -struct xwl_touch { - struct xwl_window *window; - int32_t id; - int x, y; - struct xorg_list link_touch; -}; - -struct xwl_pointer_warp_emulator { - struct xwl_seat *xwl_seat; - struct xwl_window *locked_window; - struct zwp_locked_pointer_v1 *locked_pointer; -}; - -struct xwl_cursor { - void (* update_proc) (struct xwl_cursor *); - struct wl_surface *surface; - struct wl_callback *frame_cb; - Bool needs_update; -}; - -struct xwl_seat { - DeviceIntPtr pointer; - DeviceIntPtr relative_pointer; - DeviceIntPtr pointer_gestures; - DeviceIntPtr keyboard; - DeviceIntPtr touch; - DeviceIntPtr stylus; - DeviceIntPtr eraser; - DeviceIntPtr puck; - struct xwl_screen *xwl_screen; - struct wl_seat *seat; - struct wl_pointer *wl_pointer; - struct zwp_relative_pointer_v1 *wp_relative_pointer; - struct zwp_pointer_gesture_swipe_v1 *wp_pointer_gesture_swipe; - struct zwp_pointer_gesture_pinch_v1 *wp_pointer_gesture_pinch; - struct wl_keyboard *wl_keyboard; - struct wl_touch *wl_touch; - struct zwp_tablet_seat_v2 *tablet_seat; - struct wl_array keys; - struct xwl_window *focus_window; - struct xwl_window *tablet_focus_window; - uint32_t id; - uint32_t pointer_enter_serial; - struct xorg_list link; - CursorPtr x_cursor; - OsTimerPtr x_cursor_timer; - CursorPtr pending_x_cursor; - struct xwl_cursor cursor; - struct xwl_window *last_focus_window; - - uint32_t pointer_gesture_swipe_fingers; - uint32_t pointer_gesture_pinch_fingers; - double pointer_gesture_pinch_last_scale; - - struct xorg_list touches; - - size_t keymap_size; - char *keymap; - struct wl_surface *keyboard_focus; - - struct xorg_list sync_pending; - - struct xwl_pointer_warp_emulator *pointer_warp_emulator; - - struct xwl_window *cursor_confinement_window; - struct zwp_confined_pointer_v1 *confined_pointer; - - struct { - Bool has_absolute; - wl_fixed_t x; - wl_fixed_t y; - - Bool has_relative; - double dx; - double dy; - double dx_unaccel; - double dy_unaccel; - - wl_fixed_t scroll_dy; - wl_fixed_t scroll_dx; - int32_t scroll_dy_v120; - int32_t scroll_dx_v120; - Bool has_vertical_scroll; - Bool has_horizontal_scroll; - Bool has_vertical_scroll_v120; - Bool has_horizontal_scroll_v120; - } pending_pointer_event; - - struct xorg_list tablets; - struct xorg_list tablet_tools; - struct xorg_list tablet_pads; - struct zwp_xwayland_keyboard_grab_v1 *keyboard_grab; -}; - -struct xwl_tablet { - struct xorg_list link; - struct zwp_tablet_v2 *tablet; - struct xwl_seat *seat; -}; - -struct xwl_tablet_tool { - struct xorg_list link; - struct zwp_tablet_tool_v2 *tool; - struct xwl_seat *seat; - - DeviceIntPtr xdevice; - uint32_t proximity_in_serial; - double x; - double y; - uint32_t pressure; - double tilt_x; - double tilt_y; - double rotation; - double slider; - - uint32_t buttons_now, - buttons_prev; - - int32_t wheel_clicks; - - struct xwl_cursor cursor; -}; - -struct xwl_tablet_pad_ring { - unsigned int index; - struct xorg_list link; - struct xwl_tablet_pad_group *group; - struct zwp_tablet_pad_ring_v2 *ring; -}; - -struct xwl_tablet_pad_strip { - unsigned int index; - struct xorg_list link; - struct xwl_tablet_pad_group *group; - struct zwp_tablet_pad_strip_v2 *strip; -}; - -struct xwl_tablet_pad_group { - struct xorg_list link; - struct xwl_tablet_pad *pad; - struct zwp_tablet_pad_group_v2 *group; - - struct xorg_list pad_group_ring_list; - struct xorg_list pad_group_strip_list; -}; - -struct xwl_tablet_pad { - struct xorg_list link; - struct zwp_tablet_pad_v2 *pad; - struct xwl_seat *seat; - - DeviceIntPtr xdevice; - - unsigned int nbuttons; - struct xorg_list pad_group_list; -}; - -void xwl_seat_leave_ptr(struct xwl_seat *xwl_seat, Bool focus_lost); -void xwl_seat_leave_kbd(struct xwl_seat *xwl_seat); - -void xwl_seat_destroy(struct xwl_seat *xwl_seat); - -void xwl_seat_clear_touch(struct xwl_seat *xwl_seat, struct xwl_window *xwl_window); - -void xwl_seat_emulate_pointer_warp(struct xwl_seat *xwl_seat, - struct xwl_window *xwl_window, - SpritePtr sprite, - int x, int y); - -void xwl_seat_destroy_pointer_warp_emulator(struct xwl_seat *xwl_seat); - -void xwl_seat_cursor_visibility_changed(struct xwl_seat *xwl_seat); - -void xwl_seat_confine_pointer(struct xwl_seat *xwl_seat, - struct xwl_window *xwl_window); -void xwl_seat_unconfine_pointer(struct xwl_seat *xwl_seat); - -void xwl_screen_release_tablet_manager(struct xwl_screen *xwl_screen); - -#endif /* XWAYLAND_INPUT_H */ diff --git a/hw/xwayland/xwayland-output.c b/hw/xwayland/xwayland-output.c deleted file mode 100644 index 9260180e8..000000000 --- a/hw/xwayland/xwayland-output.c +++ /dev/null @@ -1,1406 +0,0 @@ -/* - * Copyright © 2011-2014 Intel Corporation - * - * Permission to use, copy, modify, distribute, and sell this software - * and its documentation for any purpose is hereby granted without - * fee, provided that the above copyright notice appear in all copies - * and that both that copyright notice and this permission notice - * appear in supporting documentation, and that the name of the - * copyright holders not be used in advertising or publicity - * pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied - * warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS - * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. - */ - -#include - -#include - -#include - -#include "dix/dix_priv.h" -#include "dix/input_priv.h" -#include "dix/resource_priv.h" -#include "randr/randrstr_priv.h" -#include "os/log_priv.h" - -#include "xwayland-cvt.h" -#include "xwayland-output.h" -#include "xwayland-screen.h" -#include "xwayland-window.h" - -#include "xdg-output-unstable-v1-client-protocol.h" - -static void xwl_output_get_xdg_output(struct xwl_output *xwl_output); - -static Rotation -wl_transform_to_xrandr(enum wl_output_transform transform) -{ - switch (transform) { - default: - case WL_OUTPUT_TRANSFORM_NORMAL: - return RR_Rotate_0; - case WL_OUTPUT_TRANSFORM_90: - return RR_Rotate_90; - case WL_OUTPUT_TRANSFORM_180: - return RR_Rotate_180; - case WL_OUTPUT_TRANSFORM_270: - return RR_Rotate_270; - case WL_OUTPUT_TRANSFORM_FLIPPED: - return RR_Reflect_X | RR_Rotate_0; - case WL_OUTPUT_TRANSFORM_FLIPPED_90: - return RR_Reflect_X | RR_Rotate_90; - case WL_OUTPUT_TRANSFORM_FLIPPED_180: - return RR_Reflect_X | RR_Rotate_180; - case WL_OUTPUT_TRANSFORM_FLIPPED_270: - return RR_Reflect_X | RR_Rotate_270; - } -} - -static int -wl_subpixel_to_xrandr(int subpixel) -{ - switch (subpixel) { - default: - case WL_OUTPUT_SUBPIXEL_UNKNOWN: - return SubPixelUnknown; - case WL_OUTPUT_SUBPIXEL_NONE: - return SubPixelNone; - case WL_OUTPUT_SUBPIXEL_HORIZONTAL_RGB: - return SubPixelHorizontalRGB; - case WL_OUTPUT_SUBPIXEL_HORIZONTAL_BGR: - return SubPixelHorizontalBGR; - case WL_OUTPUT_SUBPIXEL_VERTICAL_RGB: - return SubPixelVerticalRGB; - case WL_OUTPUT_SUBPIXEL_VERTICAL_BGR: - return SubPixelVerticalBGR; - } -} - -static void -output_handle_geometry(void *data, struct wl_output *wl_output, int x, int y, - int physical_width, int physical_height, int subpixel, - const char *make, const char *model, int transform) -{ - struct xwl_output *xwl_output = data; - - if (xwl_output->randr_output) { - RROutputSetPhysicalSize(xwl_output->randr_output, - physical_width, physical_height); - RROutputSetSubpixelOrder(xwl_output->randr_output, - wl_subpixel_to_xrandr(subpixel)); - } - - /* Apply the change from wl_output only if xdg-output is not supported */ - if (!xwl_output->xdg_output) { - xwl_output->x = x; - xwl_output->y = y; - } - xwl_output->rotation = wl_transform_to_xrandr(transform); -} - -static void -output_handle_mode(void *data, struct wl_output *wl_output, uint32_t flags, - int width, int height, int refresh) -{ - struct xwl_output *xwl_output = data; - - if (!(flags & WL_OUTPUT_MODE_CURRENT)) - return; - - /* Apply the change from wl_output only if xdg-output is not supported */ - if (!xwl_output->xdg_output) { - xwl_output->width = width; - xwl_output->height = height; - } - xwl_output->refresh = refresh; -} - -/** - * Decides on the maximum expanse of an output in logical space (i.e. in the - * Wayland compositor plane) respective to some fix width and height values. The - * function sets the provided values to these maxima on return. - */ -static inline void -output_get_new_size(struct xwl_output *xwl_output, int *width, int *height) -{ - int output_width, output_height; - - /* When we have xdg-output support the stored size is already rotated. */ - if (xwl_output->xdg_output - || (xwl_output->rotation & (RR_Rotate_0 | RR_Rotate_180))) { - output_width = xwl_output->width; - output_height = xwl_output->height; - } else { - output_width = xwl_output->height; - output_height = xwl_output->width; - } - - if (*width < xwl_output->x + output_width) - *width = xwl_output->x + output_width; - - if (*height < xwl_output->y + output_height) - *height = xwl_output->y + output_height; -} - -static int -xwl_set_pixmap_visit_window(WindowPtr window, void *data) -{ - ScreenPtr screen = window->drawable.pScreen; - - if (screen->GetWindowPixmap(window) == data) { - screen->SetWindowPixmap(window, screen->GetScreenPixmap(screen)); - return WT_WALKCHILDREN; - } - - return WT_DONTWALKCHILDREN; -} - -static void -update_backing_pixmaps(struct xwl_screen *xwl_screen, int width, int height) -{ - ScreenPtr pScreen = xwl_screen->screen; - WindowPtr pRoot = pScreen->root; - PixmapPtr old_pixmap, new_pixmap; - - old_pixmap = pScreen->GetScreenPixmap(pScreen); - new_pixmap = pScreen->CreatePixmap(pScreen, width, height, - pScreen->rootDepth, - CREATE_PIXMAP_USAGE_BACKING_PIXMAP); - pScreen->SetScreenPixmap(new_pixmap); - - if (old_pixmap) { - TraverseTree(pRoot, xwl_set_pixmap_visit_window, old_pixmap); - dixDestroyPixmap(old_pixmap, 0); - } - - pScreen->ResizeWindow(pRoot, 0, 0, width, height, NULL); -} - -static void -update_screen_size(struct xwl_screen *xwl_screen, int width, int height) -{ - if (xwl_screen_get_width(xwl_screen) != width) - xwl_screen->width = width; - - if (xwl_screen_get_height(xwl_screen) != height) - xwl_screen->height = height; - - if (xwl_screen->root_clip_mode == ROOT_CLIP_FULL) - SetRootClip(xwl_screen->screen, ROOT_CLIP_NONE); - - if (!xwl_screen->rootless && xwl_screen->screen->root) - update_backing_pixmaps (xwl_screen, width, height); - - xwl_screen->screen->width = width; - xwl_screen->screen->height = height; - xwl_screen->screen->mmWidth = (width * 25.4) / monitorResolution; - xwl_screen->screen->mmHeight = (height * 25.4) / monitorResolution; - - SetRootClip(xwl_screen->screen, xwl_screen->root_clip_mode); - - if (xwl_screen->screen->root) { - BoxRec box = { 0, 0, width, height }; - - xwl_screen->screen->root->drawable.width = width; - xwl_screen->screen->root->drawable.height = height; - RegionReset(&xwl_screen->screen->root->winSize, &box); - RRScreenSizeNotify(xwl_screen->screen); - } - - update_desktop_dimensions(); - - RRTellChanged(xwl_screen->screen); -} - -struct xwl_emulated_mode * -xwl_output_get_emulated_mode_for_client(struct xwl_output *xwl_output, - ClientPtr client) -{ - struct xwl_client *xwl_client = xwl_client_get(client); - int i; - - if (!xwl_output) - return NULL; - - /* We don't do XRandr emulation when rootful or a fake lease display */ - if (!xwl_output->xwl_screen->rootless || !xwl_output->output) - return NULL; - - for (i = 0; i < XWL_CLIENT_MAX_EMULATED_MODES; i++) { - if (xwl_client->emulated_modes[i].server_output_id == - xwl_output->server_output_id) - return &xwl_client->emulated_modes[i]; - } - - return NULL; -} - -static void -xwl_output_add_emulated_mode_for_client(struct xwl_output *xwl_output, - ClientPtr client, - RRModePtr mode, - Bool from_vidmode) -{ - struct xwl_client *xwl_client = xwl_client_get(client); - struct xwl_emulated_mode *emulated_mode; - int i; - - emulated_mode = xwl_output_get_emulated_mode_for_client(xwl_output, client); - if (!emulated_mode) { - /* Find a free spot in the emulated modes array */ - for (i = 0; i < XWL_CLIENT_MAX_EMULATED_MODES; i++) { - if (xwl_client->emulated_modes[i].server_output_id == 0) { - emulated_mode = &xwl_client->emulated_modes[i]; - break; - } - } - } - if (!emulated_mode) { - static Bool warned; - - if (!warned) { - ErrorF("Ran out of space for emulated-modes, not adding mode"); - warned = TRUE; - } - - return; - } - - emulated_mode->server_output_id = xwl_output->server_output_id; - emulated_mode->width = mode->mode.width; - emulated_mode->height = mode->mode.height; - emulated_mode->id = mode->mode.id; - emulated_mode->from_vidmode = from_vidmode; -} - -static void -xwl_output_remove_emulated_mode_for_client(struct xwl_output *xwl_output, - ClientPtr client) -{ - struct xwl_emulated_mode *emulated_mode; - - emulated_mode = xwl_output_get_emulated_mode_for_client(xwl_output, client); - if (emulated_mode) { - DebugF("XWAYLAND: xwl_output_remove_emulated_mode: %dx%d\n", - emulated_mode->width, emulated_mode->height); - memset(emulated_mode, 0, sizeof(*emulated_mode)); - } -} - -/* From hw/xfree86/common/xf86DefModeSet.c with some obscure modes dropped */ -const int32_t xwl_output_fake_modes[][2] = { - /* 4:3 (1.33) */ - { 2048, 1536 }, - { 1920, 1440 }, - { 1600, 1200 }, - { 1440, 1080 }, - { 1400, 1050 }, - { 1280, 1024 }, /* 5:4 (1.25) */ - { 1280, 960 }, - { 1152, 864 }, - { 1024, 768 }, - { 800, 600 }, - { 640, 480 }, - { 320, 240 }, - /* 16:10 (1.6) */ - { 2560, 1600 }, - { 1920, 1200 }, - { 1680, 1050 }, - { 1440, 900 }, - { 1280, 800 }, - { 1152, 720 }, - { 960, 600 }, - { 928, 580 }, - { 800, 500 }, - { 768, 480 }, - { 720, 480 }, /* 3:2 (1.5) */ - { 640, 400 }, - { 320, 200 }, - /* 16:9 (1.77) */ - { 5120, 2880 }, - { 4096, 2304 }, - { 3840, 2160 }, - { 3200, 1800 }, - { 2880, 1620 }, - { 2560, 1440 }, - { 2048, 1152 }, - { 1920, 1080 }, - { 1600, 900 }, - { 1368, 768 }, - { 1280, 720 }, - { 1024, 576 }, - { 864, 486 }, - { 720, 400 }, - { 640, 350 }, -}; - -/* Build an array with RRModes the first mode is the actual output mode, the - * rest are fake modes from the xwl_output_fake_modes list. We do this for apps - * which want to change resolution when they go fullscreen. - * When an app requests a mode-change, we fake it using WPviewport. - */ -static RRModePtr * -output_get_rr_modes(struct xwl_output *xwl_output, - int32_t width, int32_t height, - int *count) -{ - struct xwl_screen *xwl_screen = xwl_output->xwl_screen; - RRModePtr *rr_modes; - int i; - - rr_modes = calloc(ARRAY_SIZE(xwl_output_fake_modes) + 1, - sizeof(RRModePtr)); - if (!rr_modes) - goto err; - - /* Add actual output mode */ - rr_modes[0] = xwayland_cvt(width, height, xwl_output->refresh / 1000.0, 0, 0); - if (!rr_modes[0]) - goto err; - - *count = 1; - - if (!xwl_screen_has_resolution_change_emulation(xwl_screen) && !xwl_screen->force_xrandr_emulation) - return rr_modes; - - /* Add fake modes */ - for (i = 0; i < ARRAY_SIZE(xwl_output_fake_modes); i++) { - /* Skip actual output mode, already added */ - if (xwl_output_fake_modes[i][0] == width && - xwl_output_fake_modes[i][1] == height) - continue; - - /* Skip modes which are too big, avoid downscaling */ - if (xwl_output_fake_modes[i][0] > width || - xwl_output_fake_modes[i][1] > height) - continue; - - rr_modes[*count] = xwayland_cvt(xwl_output_fake_modes[i][0], - xwl_output_fake_modes[i][1], - xwl_output->refresh / 1000.0, 0, 0); - if (!rr_modes[*count]) - goto err; - - (*count)++; - } - - return rr_modes; -err: - FatalError("Failed to allocate memory for list of RR modes"); -} - -RRModePtr -xwl_output_find_mode(struct xwl_output *xwl_output, - int32_t width, int32_t height) -{ - RROutputPtr output = xwl_output->randr_output; - int i; - - /* width & height -1 means we want the actual output mode */ - if (width == -1 && height == -1) { - if (xwl_output->mode_width > 0 && xwl_output->mode_height > 0) { - /* If running rootful, use the current mode size to search for the mode */ - width = xwl_output->mode_width; - height = xwl_output->mode_height; - } - else if (output->modes) { - /* else return the mode at first idx 0 */ - return output->modes[0]; - } - } - - for (i = 0; i < output->numModes; i++) { - if (output->modes[i]->mode.width == width && output->modes[i]->mode.height == height) - return output->modes[i]; - } - - ErrorF("XWAYLAND: mode %dx%d is not available\n", width, height); - return NULL; -} - -struct xwl_output_randr_emu_prop { - Atom atom; - uint32_t rects[XWL_CLIENT_MAX_EMULATED_MODES][4]; - int rect_count; -}; - -static void -xwl_output_randr_emu_prop(struct xwl_screen *xwl_screen, ClientPtr client, - struct xwl_output_randr_emu_prop *prop) -{ - static const char atom_name[] = "_XWAYLAND_RANDR_EMU_MONITOR_RECTS"; - struct xwl_emulated_mode *emulated_mode; - struct xwl_output *xwl_output; - int index = 0; - - prop->atom = MakeAtom(atom_name, strlen(atom_name), TRUE); - - xorg_list_for_each_entry(xwl_output, &xwl_screen->output_list, link) { - emulated_mode = xwl_output_get_emulated_mode_for_client(xwl_output, client); - if (!emulated_mode) - continue; - - prop->rects[index][0] = xwl_output->x; - prop->rects[index][1] = xwl_output->y; - prop->rects[index][2] = emulated_mode->width; - prop->rects[index][3] = emulated_mode->height; - index++; - } - - prop->rect_count = index; -} - -static void -xwl_output_set_randr_emu_prop(WindowPtr window, - struct xwl_output_randr_emu_prop *prop) -{ - if (prop->rect_count) { - dixChangeWindowProperty(serverClient, window, prop->atom, - XA_CARDINAL, 32, PropModeReplace, - prop->rect_count * 4, prop->rects, TRUE); - } else { - DeleteProperty(serverClient, window, prop->atom); - } -} - -static void -xwl_output_set_randr_emu_prop_callback(void *resource, XID id, void *user_data) -{ - if (xwl_window_is_toplevel(resource)) - xwl_output_set_randr_emu_prop(resource, user_data); -} - -static void -xwl_output_set_randr_emu_props(struct xwl_screen *xwl_screen, ClientPtr client) -{ - struct xwl_output_randr_emu_prop prop = {}; - - xwl_output_randr_emu_prop(xwl_screen, client, &prop); - FindClientResourcesByType(client, X11_RESTYPE_WINDOW, - xwl_output_set_randr_emu_prop_callback, &prop); -} - -static inline void -xwl_output_get_emulated_root_size(struct xwl_output *xwl_output, - ClientPtr client, - int *width, - int *height) -{ - struct xwl_screen *xwl_screen = xwl_output->xwl_screen; - struct xwl_emulated_mode *emulated_mode; - - emulated_mode = xwl_output_get_emulated_mode_for_client(xwl_output, client); - /* If not an emulated mode, just return the actual screen size */ - if (!emulated_mode) { - *width = xwl_screen_get_width(xwl_screen); - *height = xwl_screen_get_height(xwl_screen); - return; - } - - if (xwl_output->rotation & (RR_Rotate_0 | RR_Rotate_180)) { - *width = emulated_mode->width; - *height = emulated_mode->height; - } else { - *width = emulated_mode->height; - *height = emulated_mode->width; - } -} - -static int -xwl_output_get_rr_event_mask(WindowPtr pWin, ClientPtr client) -{ - RREventPtr pRREvent, *pHead; - - dixLookupResourceByType((void **) &pHead, pWin->drawable.id, - RREventType, client, DixReadAccess); - - pRREvent = NULL; - if (pHead) { - for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next) - if (pRREvent->client == client) - break; - } - - if (pRREvent) - return pRREvent->mask; - - return 0; -} - -static void -xwl_output_notify_emulated_root_size(struct xwl_output *xwl_output, - ClientPtr client, - int new_emulated_root_width, - int new_emulated_root_height) -{ - struct xwl_screen *xwl_screen = xwl_output->xwl_screen; - ScreenPtr pScreen = xwl_screen->screen; - WindowPtr pRoot = pScreen->root; - xEvent event = { - .u.configureNotify.event = pRoot->drawable.id, - .u.configureNotify.window = pRoot->drawable.id, - .u.configureNotify.aboveSibling = None, - .u.configureNotify.x = 0, - .u.configureNotify.y = 0, - .u.configureNotify.width = new_emulated_root_width, - .u.configureNotify.height = new_emulated_root_height, - .u.configureNotify.borderWidth = pRoot->borderWidth, - .u.configureNotify.override = pRoot->overrideRedirect - }; - event.u.u.type = ConfigureNotify; - - if (!client || client == serverClient || client->clientGone) - return; - - if (EventMaskForClient(pRoot, client) & StructureNotifyMask) - WriteEventsToClient(client, 1, &event); - - if (xwl_output_get_rr_event_mask(pRoot, client) & RRScreenChangeNotifyMask) - RRDeliverScreenEvent(client, pRoot, pScreen); -} - -void -xwl_output_set_window_randr_emu_props(struct xwl_screen *xwl_screen, - WindowPtr window) -{ - struct xwl_output_randr_emu_prop prop = {}; - - xwl_output_randr_emu_prop(xwl_screen, dixClientForWindow(window), &prop); - xwl_output_set_randr_emu_prop(window, &prop); -} - -void -xwl_output_set_emulated_mode(struct xwl_output *xwl_output, ClientPtr client, - RRModePtr mode, Bool from_vidmode) -{ - int old_emulated_width, old_emulated_height; - int new_emulated_width, new_emulated_height; - - DebugF("XWAYLAND: xwl_output_set_emulated_mode from %s: %dx%d\n", - from_vidmode ? "vidmode" : "randr", - mode->mode.width, mode->mode.height); - - xwl_output_get_emulated_root_size(xwl_output, client, - &old_emulated_width, &old_emulated_height); - - /* modes[0] is the actual (not-emulated) output mode */ - if (mode == xwl_output->randr_output->modes[0]) - xwl_output_remove_emulated_mode_for_client(xwl_output, client); - else - xwl_output_add_emulated_mode_for_client(xwl_output, client, mode, from_vidmode); - - xwl_screen_check_resolution_change_emulation(xwl_output->xwl_screen); - - xwl_output_set_randr_emu_props(xwl_output->xwl_screen, client); - - xwl_output_get_emulated_root_size(xwl_output, client, - &new_emulated_width, &new_emulated_height); - - if (new_emulated_width != old_emulated_width || - new_emulated_height != old_emulated_height) - xwl_output_notify_emulated_root_size(xwl_output, client, - new_emulated_width, - new_emulated_height); -} - -static void -maybe_update_fullscreen_state(struct xwl_output *xwl_output) -{ - struct xwl_screen *xwl_screen = xwl_output->xwl_screen; - struct xwl_window *xwl_window; - - if (xwl_screen->fullscreen) { - /* The root window may not yet be created */ - if (xwl_screen->screen->root) { - xwl_window = xwl_window_get(xwl_screen->screen->root); - xwl_window_rootful_update_fullscreen(xwl_window, xwl_output); - } - } -} - -static void -apply_output_change(struct xwl_output *xwl_output) -{ - struct xwl_screen *xwl_screen = xwl_output->xwl_screen; - struct xwl_output *it; - int mode_width, mode_height, count; - int width = 0, height = 0, has_this_output = 0; - RRModePtr *randr_modes; - - /* Clear out the "done" received flags */ - xwl_output->wl_output_done = FALSE; - xwl_output->xdg_output_done = FALSE; - - /* When we have received an xdg-output for the mode size we might need to - * rotate back the stored logical size it provided. - */ - if (xwl_output->xdg_output == NULL - || xwl_output->rotation & (RR_Rotate_0 | RR_Rotate_180)) { - mode_width = xwl_output->width; - mode_height = xwl_output->height; - } else { - mode_width = xwl_output->height; - mode_height = xwl_output->width; - } - if (xwl_output->randr_output) { - /* Build a fresh modes array using the current refresh rate */ - randr_modes = output_get_rr_modes(xwl_output, mode_width, mode_height, &count); - RROutputSetModes(xwl_output->randr_output, randr_modes, count, 1); - RRCrtcNotify(xwl_output->randr_crtc, randr_modes[0], - xwl_output->x, xwl_output->y, - xwl_output->rotation, NULL, 1, &xwl_output->randr_output); - /* RROutputSetModes takes ownership of the passed in modes, so we only - * have to free the pointer array. - */ - free(randr_modes); - } - - xorg_list_for_each_entry(it, &xwl_screen->output_list, link) { - /* output done event is sent even when some property - * of output is changed. That means that we may already - * have this output. If it is true, we must not add it - * into the output_list otherwise we'll corrupt it */ - if (it == xwl_output) - has_this_output = 1; - - output_get_new_size(it, &width, &height); - } - - if (!has_this_output) { - xorg_list_append(&xwl_output->link, &xwl_screen->output_list); - - /* we did not check this output for new screen size, do it now */ - output_get_new_size(xwl_output, &width, &height); - - --xwl_screen->expecting_event; - } - - if (xwl_screen->fixed_output == NULL) - update_screen_size(xwl_screen, width, height); - else - RRTellChanged(xwl_screen->screen); - - /* If running rootful and fullscreen, make sure to match the new setup */ - maybe_update_fullscreen_state(xwl_output); -} - -void -xwl_output_set_name(struct xwl_output *xwl_output, const char *name) -{ - struct xwl_screen *xwl_screen = xwl_output->xwl_screen; - rrScrPrivPtr pScrPriv; - RRLeasePtr lease; - int i; - - if (xwl_output->randr_output == NULL) - return; /* rootful */ - - /* Check whether the compositor is sending us something useful */ - if (!name || !strlen(name)) { - ErrorF("Not using the provided output name, invalid"); - return; - } - - /* Check for duplicate names to be safe */ - pScrPriv = rrGetScrPriv(xwl_screen->screen); - for (i = 0; i < pScrPriv->numOutputs; i++) { - if (!strcmp(name, pScrPriv->outputs[i]->name)) { - ErrorF("An output named '%s' already exists", name); - return; - } - } - /* And leases' names as well */ - xorg_list_for_each_entry(lease, &pScrPriv->leases, list) { - for (i = 0; i < lease->numOutputs; i++) { - if (!strcmp(name, pScrPriv->outputs[i]->name)) { - ErrorF("A lease output named '%s' already exists", name); - return; - } - } - } - - snprintf(xwl_output->randr_output->name, MAX_OUTPUT_NAME, "%s", name); - xwl_output->randr_output->nameLength = strlen(xwl_output->randr_output->name); - - if (xwl_screen->output_name && strcmp(name, xwl_screen->output_name) == 0) - maybe_update_fullscreen_state(xwl_output); -} - -static void -output_handle_done(void *data, struct wl_output *wl_output) -{ - struct xwl_output *xwl_output = data; - struct xwl_screen *xwl_screen = xwl_output->xwl_screen; - - xwl_output->wl_output_done = TRUE; - if (xwl_screen->fixed_output) - return; - - /* Apply the changes from wl_output only if both "done" events are received, - * if xdg-output is not supported or if xdg-output version is high enough. - */ - if (xwl_output->xdg_output_done || !xwl_output->xdg_output || - zxdg_output_v1_get_version(xwl_output->xdg_output) >= 3) - apply_output_change(xwl_output); -} - -static void -output_handle_scale(void *data, struct wl_output *wl_output, int32_t factor) -{ - struct xwl_output *xwl_output = data; - - xwl_output->scale = factor; -} - -static void -output_handle_name(void *data, struct wl_output *wl_output, - const char *name) -{ - struct xwl_output *xwl_output = data; - - xwl_output_set_name(xwl_output, name); -} - -static void -output_handle_description(void *data, struct wl_output *wl_output, - const char *description) -{ -} - -static const struct wl_output_listener output_listener = { - output_handle_geometry, - output_handle_mode, - output_handle_done, - output_handle_scale, - output_handle_name, - output_handle_description, -}; - -static void -xdg_output_handle_logical_position(void *data, struct zxdg_output_v1 *xdg_output, - int32_t x, int32_t y) -{ - struct xwl_output *xwl_output = data; - - xwl_output->x = x; - xwl_output->y = y; -} - -static void -xdg_output_handle_logical_size(void *data, struct zxdg_output_v1 *xdg_output, - int32_t width, int32_t height) -{ - struct xwl_output *xwl_output = data; - - xwl_output->width = width; - xwl_output->height = height; -} - -static void -xdg_output_handle_done(void *data, struct zxdg_output_v1 *xdg_output) -{ - struct xwl_output *xwl_output = data; - struct xwl_screen *xwl_screen = xwl_output->xwl_screen; - - xwl_output->xdg_output_done = TRUE; - - if (xwl_screen->fixed_output) - return; - - if (xwl_output->wl_output_done && - zxdg_output_v1_get_version(xdg_output) < 3) - apply_output_change(xwl_output); -} - -static void -xdg_output_handle_name(void *data, struct zxdg_output_v1 *xdg_output, - const char *name) -{ - struct xwl_output *xwl_output = data; - - if (wl_output_get_version(xwl_output->output) >= 4) - return; /* wl_output.name is preferred */ - - xwl_output_set_name(xwl_output, name); -} - -static void -xdg_output_handle_description(void *data, struct zxdg_output_v1 *xdg_output, - const char *description) -{ -} - -static const struct zxdg_output_v1_listener xdg_output_listener = { - xdg_output_handle_logical_position, - xdg_output_handle_logical_size, - xdg_output_handle_done, - xdg_output_handle_name, - xdg_output_handle_description, -}; - -#define XRANDR_EMULATION_PROP "RANDR Emulation" -static Atom -get_rand_emulation_property(void) -{ - const char *emulStr = XRANDR_EMULATION_PROP; - - return MakeAtom(emulStr, strlen(emulStr), TRUE); -} - -static void -xwl_output_set_emulated(struct xwl_output *xwl_output) -{ - int32_t val = TRUE; - - RRChangeOutputProperty(xwl_output->randr_output, - get_rand_emulation_property(), - XA_INTEGER, - 32, PropModeReplace, 1, - &val, FALSE, FALSE); -} - -struct xwl_output* -xwl_output_from_wl_output(struct xwl_screen *xwl_screen, - struct wl_output* wl_output) -{ - struct xwl_output *xwl_output; - - xorg_list_for_each_entry(xwl_output, &xwl_screen->output_list, link) { - if (xwl_output->output == wl_output) - return xwl_output; - } - - return NULL; -} - - -struct xwl_output * -xwl_output_get_output_from_name(struct xwl_screen *xwl_screen, const char *name) -{ - struct xwl_output *xwl_output; - - if (name == NULL) - return NULL; - - xorg_list_for_each_entry(xwl_output, &xwl_screen->output_list, link) { - if (xwl_output->randr_output == NULL) - continue; - - if (strcmp(xwl_output->randr_output->name, name) == 0) { - return xwl_output; - } - } - - return NULL; -} - -struct xwl_output * -xwl_output_create(struct xwl_screen *xwl_screen, uint32_t id, - Bool connected, uint32_t version) -{ - struct xwl_output *xwl_output; - char name[MAX_OUTPUT_NAME] = { 0 }; - - --xwl_screen->expecting_event; - - xwl_output = calloc(1, sizeof *xwl_output); - if (xwl_output == NULL) { - ErrorF("%s ENOMEM\n", __func__); - return NULL; - } - - xwl_output->output = wl_registry_bind(xwl_screen->registry, id, - &wl_output_interface, min(version, 4)); - if (!xwl_output->output) { - ErrorF("Failed binding wl_output\n"); - goto err; - } - - xwl_output->server_output_id = id; - wl_output_add_listener(xwl_output->output, &output_listener, xwl_output); - xwl_output->xscale = 1.0; - - xwl_output->xwl_screen = xwl_screen; - - xwl_output->randr_crtc = RRCrtcCreate(xwl_screen->screen, xwl_output); - if (!xwl_output->randr_crtc) { - ErrorF("Failed creating RandR CRTC\n"); - goto err; - } - RRCrtcSetRotations (xwl_output->randr_crtc, ALL_ROTATIONS); - - /* Allocate MAX_OUTPUT_NAME data for the output name, all filled with zeros */ - xwl_output->randr_output = RROutputCreate(xwl_screen->screen, name, - MAX_OUTPUT_NAME, xwl_output); - if (!xwl_output->randr_output) { - ErrorF("Failed creating RandR Output\n"); - goto err; - } - /* Set the default output name to a sensible value */ - snprintf(name, MAX_OUTPUT_NAME, "XWAYLAND%d", - xwl_screen_get_next_output_serial(xwl_screen)); - xwl_output_set_name(xwl_output, name); - xwl_output_set_emulated(xwl_output); - - RRCrtcGammaSetSize(xwl_output->randr_crtc, 256); - RROutputSetCrtcs(xwl_output->randr_output, &xwl_output->randr_crtc, 1); - RROutputSetConnection(xwl_output->randr_output, - connected ? RR_Connected : RR_Disconnected); - - /* We want the output to be in the list as soon as created so we can - * use it when binding to the xdg-output protocol... - */ - xorg_list_append(&xwl_output->link, &xwl_screen->output_list); - - if (xwl_screen->xdg_output_manager) - xwl_output_get_xdg_output(xwl_output); - - return xwl_output; - -err: - if (xwl_output->randr_crtc) - RRCrtcDestroy(xwl_output->randr_crtc); - if (xwl_output->output) - wl_output_destroy(xwl_output->output); - free(xwl_output); - return NULL; -} - -void -xwl_output_destroy(struct xwl_output *xwl_output) -{ - if (xwl_output->lease_connector) - wp_drm_lease_connector_v1_destroy(xwl_output->lease_connector); - if (xwl_output->transform) - free(xwl_output->transform); - if (xwl_output->xdg_output) - zxdg_output_v1_destroy(xwl_output->xdg_output); - if (xwl_output->output) - wl_output_destroy(xwl_output->output); - free(xwl_output); -} - -void -xwl_output_remove(struct xwl_output *xwl_output) -{ - struct xwl_output *it; - struct xwl_screen *xwl_screen = xwl_output->xwl_screen; - struct xwl_window *xwl_window; - int width = 0, height = 0; - - /* Not all compositors send a "leave" event on output removal */ - xorg_list_for_each_entry(xwl_window, &xwl_screen->window_list, link_window) - xwl_window_leave_output(xwl_window, xwl_output); - - xorg_list_del(&xwl_output->link); - - if (xwl_output->randr_output) - RROutputSetConnection(xwl_output->randr_output, RR_Disconnected); - - if (xwl_screen->fixed_output == NULL) { - xorg_list_for_each_entry(it, &xwl_screen->output_list, link) - output_get_new_size(it, &width, &height); - update_screen_size(xwl_screen, width, height); - } - - if (xwl_output->randr_crtc) - RRCrtcDestroy(xwl_output->randr_crtc); - if (xwl_output->randr_output) { - RROutputDestroy(xwl_output->randr_output); - RRTellChanged(xwl_screen->screen); - } - xwl_output_destroy(xwl_output); -} - -static Bool -xwl_randr_get_info(ScreenPtr pScreen, Rotation * rotations) -{ - *rotations = ALL_ROTATIONS; - - return TRUE; -} - -#ifdef RANDR_10_INTERFACE -static Bool -xwl_randr_set_config(ScreenPtr pScreen, - Rotation rotation, int rate, RRScreenSizePtr pSize) -{ - return FALSE; -} -#endif - -#if RANDR_12_INTERFACE -static Bool -xwl_randr_screen_set_size(ScreenPtr pScreen, - CARD16 width, - CARD16 height, - CARD32 mmWidth, CARD32 mmHeight) -{ - return TRUE; -} - -static Bool -xwl_randr_crtc_set(ScreenPtr pScreen, - RRCrtcPtr crtc, - RRModePtr new_mode, - int x, - int y, - Rotation rotation, - int numOutputs, RROutputPtr * outputs) -{ - struct xwl_output *xwl_output = crtc->devPrivate; - RRModePtr mode; - - if (new_mode) { - mode = xwl_output_find_mode(xwl_output, - new_mode->mode.width, - new_mode->mode.height); - } else { - mode = xwl_output_find_mode(xwl_output, -1, -1); - } - if (!mode) - return FALSE; - - xwl_output_set_emulated_mode(xwl_output, GetCurrentClient(), mode, FALSE); - - /* A real randr implementation would call: - * RRCrtcNotify(xwl_output->randr_crtc, mode, xwl_output->x, xwl_output->y, - * xwl_output->rotation, NULL, 1, &xwl_output->randr_output); - * here to update the mode reported to clients querying the randr settings - * but that influences *all* clients and we do randr mode change emulation - * on a per client basis. So we just return success here. - */ - - return TRUE; -} - -static void -xwl_randr_crtc_get(ScreenPtr pScreen, - RRCrtcPtr crtc, - xRRGetCrtcInfoReply *rep) -{ - struct xwl_output *xwl_output = crtc->devPrivate; - - struct xwl_emulated_mode *mode = xwl_output_get_emulated_mode_for_client( - xwl_output, GetCurrentClient()); - - if (mode) - rep->mode = mode->id; -} - -static Bool -xwl_randr_crtc_set_gamma(ScreenPtr pScreen, RRCrtcPtr crtc) -{ - return TRUE; -} - -static Bool -xwl_randr_crtc_get_gamma(ScreenPtr pScreen, RRCrtcPtr crtc) -{ - return TRUE; -} - -static Bool -xwl_randr_output_set_property(ScreenPtr pScreen, - RROutputPtr output, - Atom property, - RRPropertyValuePtr value) -{ - /* RANDR Emulation property is read-only. */ - if (get_rand_emulation_property() == property) - return FALSE; - - return TRUE; -} - -static Bool -xwl_output_validate_mode(ScreenPtr pScreen, - RROutputPtr output, - RRModePtr mode) -{ - return TRUE; -} - -static void -xwl_randr_mode_destroy(ScreenPtr pScreen, RRModePtr mode) -{ - return; -} -#endif - -Bool -xwl_screen_init_output(struct xwl_screen *xwl_screen) -{ - rrScrPrivPtr rp; - - if (!RRScreenInit(xwl_screen->screen)) - return FALSE; - - RRScreenSetSizeRange(xwl_screen->screen, 16, 16, 32767, 32767); - - rp = rrGetScrPriv(xwl_screen->screen); - rp->rrGetInfo = xwl_randr_get_info; - -#if RANDR_10_INTERFACE - rp->rrSetConfig = xwl_randr_set_config; -#endif - -#if RANDR_12_INTERFACE - rp->rrScreenSetSize = xwl_randr_screen_set_size; - rp->rrCrtcSet = xwl_randr_crtc_set; - rp->rrCrtcGet = xwl_randr_crtc_get; - rp->rrCrtcSetGamma = xwl_randr_crtc_set_gamma; - rp->rrCrtcGetGamma = xwl_randr_crtc_get_gamma; - rp->rrOutputSetProperty = xwl_randr_output_set_property; - rp->rrOutputValidateMode = xwl_output_validate_mode; - rp->rrModeDestroy = xwl_randr_mode_destroy; -#endif - - rp->rrRequestLease = xwl_randr_request_lease; - rp->rrGetLease = xwl_randr_get_lease; - rp->rrTerminateLease = xwl_randr_terminate_lease; - - return TRUE; -} - -static int -mode_sort(const void *left, const void *right) -{ - const RRModePtr *mode_a = left; - const RRModePtr *mode_b = right; - - if ((*mode_b)->mode.width == (*mode_a)->mode.width) - return (*mode_b)->mode.height - (*mode_a)->mode.height; - - return (*mode_b)->mode.width - (*mode_a)->mode.width; -} - -static void -xwl_output_set_transform(struct xwl_output *xwl_output) -{ - pixman_fixed_t transform_xscale; - RRModePtr mode; - - mode = xwl_output_find_mode(xwl_output, xwl_output->mode_width, xwl_output->mode_height); - if (!mode) { - ErrorF("XWAYLAND: Failed to find mode for %ix%i\n", - xwl_output->mode_width, xwl_output->mode_height); - return; - } - - if (xwl_output->transform == NULL) { - xwl_output->transform = XNFalloc(sizeof(RRTransformRec)); - RRTransformInit(xwl_output->transform); - } - - transform_xscale = pixman_double_to_fixed(xwl_output->xscale); - pixman_transform_init_scale(&xwl_output->transform->transform, - transform_xscale, transform_xscale); - pixman_f_transform_init_scale(&xwl_output->transform->f_transform, - xwl_output->xscale, xwl_output->xscale); - pixman_f_transform_invert(&xwl_output->transform->f_inverse, - &xwl_output->transform->f_transform); - - RRCrtcNotify(xwl_output->randr_crtc, mode, 0, 0, RR_Rotate_0, - xwl_output->transform, 1, &xwl_output->randr_output); -} - -void -xwl_output_set_xscale(struct xwl_output *xwl_output, double xscale) -{ - xwl_output->xscale = xscale; - xwl_output_set_transform(xwl_output); -} - -Bool -xwl_randr_add_modes_fixed(struct xwl_output *xwl_output, - int current_width, int current_height) -{ - RRModePtr *modes = NULL; - RRModePtr mode; - int i, nmodes, current; - - modes = calloc(ARRAY_SIZE(xwl_output_fake_modes) + 1, sizeof(RRModePtr)); - if (!modes) { - ErrorF("Failed to allocated RandR modes\n"); - return FALSE; - } - - xwl_output->mode_width = current_width; - xwl_output->mode_height = current_height; - - nmodes = 0; - current = 0; - - /* Add fake modes */ - for (i = 0; i < ARRAY_SIZE(xwl_output_fake_modes); i++) { - if (xwl_output_fake_modes[i][0] == current_width && - xwl_output_fake_modes[i][1] == current_height) - current = 1; - - mode = xwayland_cvt(xwl_output_fake_modes[i][0], - xwl_output_fake_modes[i][1], - 60, 0, 0); - - if (mode) - modes[nmodes++] = mode; - } - - if (!current) { - /* Add the current mode as it's not part of the fake modes. */ - mode = xwayland_cvt(current_width, current_height, 60, 0, 0); - - if (mode) - modes[nmodes++] = mode; - } - - qsort(modes, nmodes, sizeof(RRModePtr), mode_sort); - RROutputSetModes(xwl_output->randr_output, modes, nmodes, 1); - free(modes); - - return TRUE; -} - -void -xwl_output_set_mode_fixed(struct xwl_output *xwl_output, RRModePtr mode) -{ - struct xwl_screen *xwl_screen = xwl_output->xwl_screen; - - xwl_output->mode_width = mode->mode.width; - xwl_output->mode_height = mode->mode.height; - - update_screen_size(xwl_screen, - round((double) mode->mode.width * xwl_output->xscale), - round((double) mode->mode.height * xwl_output->xscale)); - - xwl_output_set_transform(xwl_output); -} - -static Bool -xwl_randr_set_config_fixed(ScreenPtr pScreen, - Rotation randr, int rate, RRScreenSizePtr pSize) -{ - struct xwl_screen *xwl_screen = xwl_screen_get(pScreen); - - update_screen_size(xwl_screen, pSize->width, pSize->height); - - return TRUE; -} - -/* Create a single RR output/mode used with a fixed geometry */ -Bool -xwl_screen_init_randr_fixed(struct xwl_screen *xwl_screen) -{ - struct xwl_output *xwl_output; - char name[MAX_OUTPUT_NAME] = { 0 }; - rrScrPrivPtr rp; - RRModePtr mode; - - xwl_output = calloc(1, sizeof *xwl_output); - if (xwl_output == NULL) { - ErrorF("%s ENOMEM\n", __func__); - return FALSE; - } - - if (!RRScreenInit(xwl_screen->screen)) - goto err; - - RRScreenSetSizeRange(xwl_screen->screen, 16, 16, 32767, 32767); - - rp = rrGetScrPriv(xwl_screen->screen); - rp->rrGetInfo = xwl_randr_get_info; - rp->rrSetConfig = xwl_randr_set_config_fixed; - - snprintf(name, MAX_OUTPUT_NAME, "XWAYLAND%d", - xwl_screen_get_next_output_serial(xwl_screen)); - xwl_output->randr_output = RROutputCreate(xwl_screen->screen, name, - strlen(name), NULL); - if (!xwl_output->randr_output) { - ErrorF("Failed to create RandR output\n"); - goto err; - } - - xwl_output->randr_crtc = RRCrtcCreate(xwl_screen->screen, xwl_output); - if (!xwl_output->randr_crtc) { - ErrorF("Failed to create RandR CRTC\n"); - goto err; - } - RRCrtcSetRotations (xwl_output->randr_crtc, RR_Rotate_0); - RRCrtcGammaSetSize(xwl_output->randr_crtc, 256); - RRCrtcSetTransformSupport(xwl_output->randr_crtc, TRUE); - RROutputSetCrtcs(xwl_output->randr_output, &xwl_output->randr_crtc, 1); - - xwl_randr_add_modes_fixed(xwl_output, - xwl_screen_get_width(xwl_screen), - xwl_screen_get_height(xwl_screen)); - /* Current mode */ - mode = xwl_output_find_mode(xwl_output, - xwl_screen_get_width(xwl_screen), - xwl_screen_get_height(xwl_screen)); - RRCrtcNotify(xwl_output->randr_crtc, mode, 0, 0, RR_Rotate_0, - NULL, 1, &xwl_output->randr_output); - - RROutputSetPhysicalSize(xwl_output->randr_output, - (xwl_screen->width * 25.4) / monitorResolution, - (xwl_screen->height * 25.4) / monitorResolution); - - RROutputSetConnection(xwl_output->randr_output, RR_Connected); - - xwl_output->xwl_screen = xwl_screen; - xwl_screen->fixed_output = xwl_output; - xwl_output->xscale = 1.0; - - return TRUE; - -err: - if (xwl_output->randr_crtc) - RRCrtcDestroy(xwl_output->randr_crtc); - if (xwl_output->randr_output) - RROutputDestroy(xwl_output->randr_output); - free(xwl_output); - - return FALSE; -} - -static void -xwl_output_get_xdg_output(struct xwl_output *xwl_output) -{ - struct xwl_screen *xwl_screen = xwl_output->xwl_screen; - - if (!xwl_output->output) { - /* This can happen when an output is created from a leasable DRM - * connector */ - return; - } - - xwl_output->xdg_output = - zxdg_output_manager_v1_get_xdg_output (xwl_screen->xdg_output_manager, - xwl_output->output); - - zxdg_output_v1_add_listener(xwl_output->xdg_output, - &xdg_output_listener, - xwl_output); -} - -void -xwl_screen_init_xdg_output(struct xwl_screen *xwl_screen) -{ - struct xwl_output *it; - - assert(xwl_screen->xdg_output_manager); - - xorg_list_for_each_entry(it, &xwl_screen->output_list, link) - xwl_output_get_xdg_output(it); -} diff --git a/hw/xwayland/xwayland-output.h b/hw/xwayland/xwayland-output.h deleted file mode 100644 index 0d36f459a..000000000 --- a/hw/xwayland/xwayland-output.h +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright © 2011-2014 Intel Corporation - * - * Permission to use, copy, modify, distribute, and sell this software - * and its documentation for any purpose is hereby granted without - * fee, provided that the above copyright notice appear in all copies - * and that both that copyright notice and this permission notice - * appear in supporting documentation, and that the name of the - * copyright holders not be used in advertising or publicity - * pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied - * warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS - * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. - */ - -#ifndef XWAYLAND_OUTPUT_H -#define XWAYLAND_OUTPUT_H - -#include -#include - -#include -#include -#include - -#include "xwayland-types.h" -#include "xwayland-drm-lease.h" - -#define ALL_ROTATIONS (RR_Rotate_0 | \ - RR_Rotate_90 | \ - RR_Rotate_180 | \ - RR_Rotate_270 | \ - RR_Reflect_X | \ - RR_Reflect_Y) - -#define MAX_OUTPUT_NAME 256 - -struct xwl_output { - struct xorg_list link; - struct xwl_screen *xwl_screen; - RROutputPtr randr_output; - RRCrtcPtr randr_crtc; - RRTransformPtr transform; - - /* only for regular outputs */ - struct wl_output *output; - struct zxdg_output_v1 *xdg_output; - uint32_t server_output_id; - int32_t x, y, width, height, refresh, scale; - int32_t mode_width, mode_height; - double xscale; /* Effective scale, can be fractional */ - Rotation rotation; - Bool wl_output_done; - Bool xdg_output_done; - - /* only for lease-able DRM connectors */ - struct wp_drm_lease_connector_v1 *lease_connector; - struct xwl_drm_lease *lease; - struct xwl_drm_lease_device *lease_device; - Bool withdrawn_connector; -}; - -/* Per client per output emulated randr/vidmode resolution info. */ -struct xwl_emulated_mode { - uint32_t server_output_id; - int32_t width; - int32_t height; - RRMode id; - Bool from_vidmode; -}; - -Bool xwl_screen_init_output(struct xwl_screen *xwl_screen); - -void xwl_output_set_name(struct xwl_output *xwl_output, const char *name); - -Bool xwl_screen_init_randr_fixed(struct xwl_screen *xwl_screen); - -void -xwl_output_set_xscale(struct xwl_output *xwl_output, double xscale); - -Bool -xwl_randr_add_modes_fixed(struct xwl_output *xwl_output, - int current_width, int current_height); - -void xwl_output_set_mode_fixed(struct xwl_output *xwl_output, - RRModePtr mode); - -struct xwl_output *xwl_output_from_wl_output(struct xwl_screen *xwl_screen, - struct wl_output* wl_output); -struct xwl_output *xwl_output_get_output_from_name(struct xwl_screen *xwl_screen, - const char *name); - -struct xwl_output *xwl_output_create(struct xwl_screen *xwl_screen, - uint32_t id, Bool connected, - uint32_t version); - -void xwl_output_destroy(struct xwl_output *xwl_output); - -void xwl_output_remove(struct xwl_output *xwl_output); - -struct xwl_emulated_mode *xwl_output_get_emulated_mode_for_client( - struct xwl_output *xwl_output, ClientPtr client); - -RRModePtr xwl_output_find_mode(struct xwl_output *xwl_output, - int32_t width, int32_t height); -void xwl_output_set_emulated_mode(struct xwl_output *xwl_output, - ClientPtr client, RRModePtr mode, - Bool from_vidmode); -void xwl_output_set_window_randr_emu_props(struct xwl_screen *xwl_screen, - WindowPtr window); - -void xwl_screen_init_xdg_output(struct xwl_screen *xwl_screen); - -#endif /* XWAYLAND_OUTPUT_H */ diff --git a/hw/xwayland/xwayland-pixmap.c b/hw/xwayland/xwayland-pixmap.c deleted file mode 100644 index 8e929f029..000000000 --- a/hw/xwayland/xwayland-pixmap.c +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright © 2014 Intel Corporation - * - * Permission to use, copy, modify, distribute, and sell this software - * and its documentation for any purpose is hereby granted without - * fee, provided that the above copyright notice appear in all copies - * and that both that copyright notice and this permission notice - * appear in supporting documentation, and that the name of the - * copyright holders not be used in advertising or publicity - * pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied - * warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS - * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. - */ - -#include - -#include - -#include "os.h" -#include "privates.h" -#include "dix.h" -#include "fb.h" -#include "pixmapstr.h" - -#ifdef XWL_HAS_GLAMOR -#include "xwayland-glamor.h" -#endif -#include "xwayland-types.h" -#include "xwayland-pixmap.h" -#include "xwayland-screen.h" -#include "xwayland-shm.h" -#include "xwayland-window-buffers.h" - -static DevPrivateKeyRec xwl_pixmap_private_key; -static DevPrivateKeyRec xwl_pixmap_cb_private_key; - -struct xwl_pixmap_buffer_release_callback { - xwl_buffer_release_cb callback; - void *data; -}; - -void -xwl_pixmap_set_private(PixmapPtr pixmap, struct xwl_pixmap *xwl_pixmap) -{ - dixSetPrivate(&pixmap->devPrivates, &xwl_pixmap_private_key, xwl_pixmap); -} - -struct xwl_pixmap * -xwl_pixmap_get(PixmapPtr pixmap) -{ - return dixLookupPrivate(&pixmap->devPrivates, &xwl_pixmap_private_key); -} - -struct wl_buffer * -xwl_pixmap_get_wl_buffer(PixmapPtr pixmap) -{ -#ifdef XWL_HAS_GLAMOR - struct xwl_screen *xwl_screen = xwl_screen_get(pixmap->drawable.pScreen); - - if (xwl_screen->glamor) - return xwl_glamor_pixmap_get_wl_buffer(pixmap); - else -#endif - return xwl_shm_pixmap_get_wl_buffer(pixmap); -} - -Bool -xwl_pixmap_set_buffer_release_cb(PixmapPtr pixmap, - xwl_buffer_release_cb func, void *data) -{ - struct xwl_pixmap_buffer_release_callback *xwl_pixmap_buffer_release_callback; - - xwl_pixmap_buffer_release_callback = dixLookupPrivate(&pixmap->devPrivates, - &xwl_pixmap_cb_private_key); - - if (xwl_pixmap_buffer_release_callback == NULL) { - xwl_pixmap_buffer_release_callback = - calloc(1, sizeof (struct xwl_pixmap_buffer_release_callback)); - - if (xwl_pixmap_buffer_release_callback == NULL) { - ErrorF("Failed to allocate pixmap callback data\n"); - return FALSE; - } - dixSetPrivate(&pixmap->devPrivates, &xwl_pixmap_cb_private_key, - xwl_pixmap_buffer_release_callback); - } - - xwl_pixmap_buffer_release_callback->callback = func; - xwl_pixmap_buffer_release_callback->data = data; - - return TRUE; -} - -void -xwl_pixmap_del_buffer_release_cb(PixmapPtr pixmap) -{ - struct xwl_pixmap_buffer_release_callback *xwl_pixmap_buffer_release_callback; - - xwl_pixmap_buffer_release_callback = dixLookupPrivate(&pixmap->devPrivates, - &xwl_pixmap_cb_private_key); - if (xwl_pixmap_buffer_release_callback) { - dixSetPrivate(&pixmap->devPrivates, &xwl_pixmap_cb_private_key, NULL); - free(xwl_pixmap_buffer_release_callback); - } -} - -void -xwl_pixmap_buffer_release_cb(void *data, struct wl_buffer *wl_buffer) -{ - PixmapPtr pixmap = data; - struct xwl_pixmap_buffer_release_callback *xwl_pixmap_buffer_release_callback; - - xwl_pixmap_buffer_release_callback = dixLookupPrivate(&pixmap->devPrivates, - &xwl_pixmap_cb_private_key); - if (xwl_pixmap_buffer_release_callback) - (*xwl_pixmap_buffer_release_callback->callback) - (xwl_pixmap_buffer_release_callback->data); -} - -Bool -xwl_pixmap_init(void) -{ - if (!dixRegisterPrivateKey(&xwl_pixmap_private_key, PRIVATE_PIXMAP, 0)) - return FALSE; - - if (!dixRegisterPrivateKey(&xwl_pixmap_cb_private_key, PRIVATE_PIXMAP, 0)) - return FALSE; - - return TRUE; -} diff --git a/hw/xwayland/xwayland-pixmap.h b/hw/xwayland/xwayland-pixmap.h deleted file mode 100644 index 8d9388766..000000000 --- a/hw/xwayland/xwayland-pixmap.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright © 2014 Intel Corporation - * - * Permission to use, copy, modify, distribute, and sell this software - * and its documentation for any purpose is hereby granted without - * fee, provided that the above copyright notice appear in all copies - * and that both that copyright notice and this permission notice - * appear in supporting documentation, and that the name of the - * copyright holders not be used in advertising or publicity - * pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied - * warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS - * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. - */ - -#ifndef XWAYLAND_PIXMAP_H -#define XWAYLAND_PIXMAP_H - -#include -#include - -#include "dix/resource_priv.h" - -#include "pixmapstr.h" - -/* This is an opaque structure implemented in the different backends */ -struct xwl_pixmap; - -typedef void (*xwl_buffer_release_cb) (void *data); - -void xwl_pixmap_set_private(PixmapPtr pixmap, struct xwl_pixmap *xwl_pixmap); -struct xwl_pixmap *xwl_pixmap_get(PixmapPtr pixmap); -struct wl_buffer *xwl_pixmap_get_wl_buffer(PixmapPtr pixmap); -Bool xwl_pixmap_set_buffer_release_cb(PixmapPtr pixmap, - xwl_buffer_release_cb func, void *data); -void xwl_pixmap_del_buffer_release_cb(PixmapPtr pixmap); -void xwl_pixmap_buffer_release_cb(void *data, struct wl_buffer *wl_buffer); -Bool xwl_pixmap_init(void); - -static inline Bool -xwl_is_client_pixmap(PixmapPtr pixmap) -{ - return (!dixResouceIsServerOwned(pixmap->drawable.id)); -} - -#endif /* XWAYLAND_PIXMAP_H */ diff --git a/hw/xwayland/xwayland-present.c b/hw/xwayland/xwayland-present.c deleted file mode 100644 index 693cadbda..000000000 --- a/hw/xwayland/xwayland-present.c +++ /dev/null @@ -1,1406 +0,0 @@ -/* - * Copyright © 2018 Roman Gilg - * - * Permission to use, copy, modify, distribute, and sell this software - * and its documentation for any purpose is hereby granted without - * fee, provided that the above copyright notice appear in all copies - * and that both that copyright notice and this permission notice - * appear in supporting documentation, and that the name of the - * copyright holders not be used in advertising or publicity - * pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied - * warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS - * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. - */ - -#include - -#include "os/bug_priv.h" - -#include -#ifdef XWL_HAS_GLAMOR -#include -#endif -#include -#include -#ifdef DRI3 -#include -#endif /* DRI3 */ - -#include "xwayland-present.h" -#include "xwayland-screen.h" -#include "xwayland-shm.h" -#include "xwayland-window.h" -#include "xwayland-window-buffers.h" -#include "xwayland-pixmap.h" - -#include "tearing-control-v1-client-protocol.h" -#include "linux-drm-syncobj-v1-client-protocol.h" - -#define XWL_PRESENT_CAPS PresentCapabilityAsync | PresentCapabilityAsyncMayTear - - -/* - * When not flipping let Present copy with 60fps. - * When flipping wait on frame_callback, otherwise - * the surface is not visible, in this case update - * with long interval. - */ -#define TIMER_LEN_COPY 17 // ~60fps -#define TIMER_LEN_FLIP 1000 // 1fps - -static DevPrivateKeyRec xwl_present_window_private_key; - -static struct xwl_present_window * -xwl_present_window_priv(WindowPtr window) -{ - return dixGetPrivate(&window->devPrivates, - &xwl_present_window_private_key); -} - -static struct xwl_present_window * -xwl_present_window_get_priv(WindowPtr window) -{ - struct xwl_present_window *xwl_present_window = xwl_present_window_priv(window); - - if (xwl_present_window == NULL) { - xwl_present_window = calloc (1, sizeof (struct xwl_present_window)); - if (!xwl_present_window) - return NULL; - - xwl_present_window->window = window; - xwl_present_window->msc = 1; - xwl_present_window->ust = GetTimeInMicros(); - - xorg_list_init(&xwl_present_window->frame_callback_list); - xorg_list_init(&xwl_present_window->wait_list); - xorg_list_init(&xwl_present_window->flip_queue); - xorg_list_init(&xwl_present_window->idle_queue); - xorg_list_init(&xwl_present_window->blocked_queue); - - dixSetPrivate(&window->devPrivates, - &xwl_present_window_private_key, - xwl_present_window); - } - - return xwl_present_window; -} - -static struct xwl_present_event * -xwl_present_event_from_id(WindowPtr present_window, uint64_t event_id) -{ - present_window_priv_ptr window_priv = present_get_window_priv(present_window, TRUE); - struct xwl_present_event *event; - - xorg_list_for_each_entry(event, &window_priv->vblank, vblank.window_list) { - if (event->vblank.event_id == event_id) - return event; - } - return NULL; -} - -static struct xwl_present_event * -xwl_present_event_from_vblank(present_vblank_ptr vblank) -{ - return container_of(vblank, struct xwl_present_event, vblank); -} - -static Bool entered_for_each_frame_callback; - -Bool -xwl_present_entered_for_each_frame_callback(void) -{ - return entered_for_each_frame_callback; -} - -void -xwl_present_for_each_frame_callback(struct xwl_window *xwl_window, - void iter_func(struct xwl_present_window *)) -{ - struct xwl_present_window *xwl_present_window, *tmp; - - if (entered_for_each_frame_callback) - FatalError("Nested xwl_present_for_each_frame_callback call"); - - entered_for_each_frame_callback = TRUE; - - xorg_list_for_each_entry_safe(xwl_present_window, tmp, - &xwl_window->frame_callback_list, - frame_callback_list) - iter_func(xwl_present_window); - - entered_for_each_frame_callback = FALSE; -} - -static void -xwl_present_free_timer(struct xwl_present_window *xwl_present_window) -{ - TimerFree(xwl_present_window->frame_timer); - xwl_present_window->frame_timer = NULL; - xwl_present_window->timer_armed = 0; -} - -static CARD32 -xwl_present_timer_callback(OsTimerPtr timer, - CARD32 time, - void *arg); - -static present_vblank_ptr -xwl_present_get_pending_flip(struct xwl_present_window *xwl_present_window) -{ - present_vblank_ptr flip_pending; - - if (xorg_list_is_empty(&xwl_present_window->flip_queue)) - return NULL; - - flip_pending = xorg_list_first_entry(&xwl_present_window->flip_queue, present_vblank_rec, - event_queue); - - if (flip_pending->queued) - return NULL; - - return flip_pending; -} - -static inline Bool -xwl_present_has_pending_events(struct xwl_present_window *xwl_present_window) -{ - present_vblank_ptr flip_pending = xwl_present_get_pending_flip(xwl_present_window); - - return (flip_pending && flip_pending->sync_flip) || - !xorg_list_is_empty(&xwl_present_window->wait_list) || - !xorg_list_is_empty(&xwl_present_window->blocked_queue); -} - -void -xwl_present_reset_timer(struct xwl_present_window *xwl_present_window) -{ - if (xwl_present_has_pending_events(xwl_present_window)) { - struct xwl_window *xwl_window = xwl_window_from_window(xwl_present_window->window); - CARD32 now = GetTimeInMillis(); - CARD32 timeout; - - if (xwl_window && xwl_window->frame_callback && - !xorg_list_is_empty(&xwl_present_window->frame_callback_list)) - timeout = TIMER_LEN_FLIP; - else - timeout = TIMER_LEN_COPY; - - /* Make sure the timer callback runs if at least a second has passed - * since we first armed the timer. This can happen e.g. if the Wayland - * compositor doesn't send a pending frame event, e.g. because the - * Wayland surface isn't visible anywhere. - */ - if (xwl_present_window->timer_armed) { - if ((int)(now - xwl_present_window->timer_armed) > 1000) { - xwl_present_timer_callback(xwl_present_window->frame_timer, now, - xwl_present_window); - return; - } - } else { - xwl_present_window->timer_armed = now; - } - - xwl_present_window->frame_timer = TimerSet(xwl_present_window->frame_timer, - 0, timeout, - &xwl_present_timer_callback, - xwl_present_window); - } else { - xwl_present_free_timer(xwl_present_window); - } -} - - -static void -xwl_present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc); - -static int -xwl_present_queue_vblank(ScreenPtr screen, - WindowPtr present_window, - RRCrtcPtr crtc, - uint64_t event_id, - uint64_t msc); - -static uint32_t -xwl_present_query_capabilities(present_screen_priv_ptr screen_priv) -{ - struct xwl_screen *xwl_screen = xwl_screen_get(screen_priv->pScreen); - return xwl_screen->present_capabilities; -} - -static int -xwl_present_get_ust_msc(ScreenPtr screen, - WindowPtr present_window, - uint64_t *ust, - uint64_t *msc) -{ - struct xwl_present_window *xwl_present_window = xwl_present_window_get_priv(present_window); - if (!xwl_present_window) - return BadAlloc; - - *ust = xwl_present_window->ust; - *msc = xwl_present_window->msc; - - return Success; -} - -static uint64_t -xwl_present_get_exec_msc(uint32_t options, uint64_t target_msc) -{ - /* Synchronous Xwayland presentations always complete (at least) one frame after they - * are executed - */ - if (options & PresentOptionAsyncMayTear) - return target_msc; - - return target_msc - 1; -} - -/* - * When the wait fence or previous flip is completed, it's time - * to re-try the request - */ -static void -xwl_present_re_execute(present_vblank_ptr vblank) -{ - struct xwl_present_event *event = xwl_present_event_from_vblank(vblank); - uint64_t ust = 0, crtc_msc = 0; - - (void) xwl_present_get_ust_msc(vblank->screen, vblank->window, &ust, &crtc_msc); - /* re-compute target / exec msc */ - vblank->target_msc = present_get_target_msc(0, crtc_msc, - event->divisor, - event->remainder, - event->options); - vblank->exec_msc = xwl_present_get_exec_msc(event->options, - vblank->target_msc); - - vblank->queued = TRUE; - if (msc_is_after(vblank->exec_msc, crtc_msc) && - xwl_present_queue_vblank(vblank->screen, vblank->window, - vblank->crtc, - vblank->event_id, - vblank->exec_msc) == Success) { - return; - } - - xwl_present_execute(vblank, ust, crtc_msc); -} - -static void -xwl_present_flip_try_ready(struct xwl_present_window *xwl_present_window) -{ - present_vblank_ptr vblank; - - xorg_list_for_each_entry(vblank, &xwl_present_window->flip_queue, event_queue) { - if (vblank->queued) { - xwl_present_re_execute(vblank); - return; - } - } -} - -static void -xwl_present_release_pixmap(struct xwl_present_event *event) -{ - if (!event->pixmap) - return; - - xwl_pixmap_del_buffer_release_cb(event->pixmap); - dixDestroyPixmap(event->pixmap, event->pixmap->drawable.id); - event->pixmap = NULL; -} - -static void -xwl_present_free_event(struct xwl_present_event *event) -{ - xwl_present_release_pixmap(event); - xorg_list_del(&event->vblank.event_queue); - present_vblank_destroy(&event->vblank); -} - -static void -xwl_present_free_idle_vblank(present_vblank_ptr vblank) -{ -#if defined(XWL_HAS_GLAMOR) && defined(DRI3) - if (vblank->release_syncobj) { - /* transfer implicit fence to release syncobj */ - int fence_fd = xwl_glamor_dmabuf_export_sync_file(vblank->pixmap); - vblank->release_syncobj->import_fence(vblank->release_syncobj, - vblank->release_point, - fence_fd); - } else -#endif /* defined(XWL_HAS_GLAMOR) && defined(DRI3) */ - present_pixmap_idle(vblank->pixmap, vblank->window, - vblank->serial, vblank->idle_fence); - xwl_present_free_event(xwl_present_event_from_vblank(vblank)); -} - -static WindowPtr -xwl_present_toplvl_pixmap_window(WindowPtr window) -{ - ScreenPtr screen = window->drawable.pScreen; - PixmapPtr pixmap = (*screen->GetWindowPixmap)(window); - WindowPtr w = window; - WindowPtr next_w; - - while(w->parent) { - next_w = w->parent; - if ( (*screen->GetWindowPixmap)(next_w) != pixmap) { - break; - } - w = next_w; - } - return w; -} - -static void -xwl_present_flips_stop(WindowPtr window) -{ - struct xwl_present_window *xwl_present_window = xwl_present_window_priv(window); - present_vblank_ptr vblank, tmp; - - /* Change back to the fast refresh rate */ - xwl_present_reset_timer(xwl_present_window); - - /* Free any left over idle vblanks */ - xorg_list_for_each_entry_safe(vblank, tmp, &xwl_present_window->idle_queue, event_queue) - xwl_present_free_idle_vblank(vblank); - - if (xwl_present_window->flip_active) { - struct xwl_present_event *event; - - vblank = xwl_present_window->flip_active; - event = xwl_present_event_from_vblank(vblank); - if (event->pixmap) - xwl_present_free_idle_vblank(vblank); - else - xwl_present_free_event(event); - - xwl_present_window->flip_active = NULL; - } - - xwl_present_flip_try_ready(xwl_present_window); -} - -static void -xwl_present_flip_notify_vblank(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc) -{ - WindowPtr window = vblank->window; -#ifdef DRI3 - struct xwl_screen *xwl_screen = xwl_screen_get(window->drawable.pScreen); -#endif /* DRI3 */ - struct xwl_present_window *xwl_present_window = xwl_present_window_priv(window); - uint8_t mode = PresentCompleteModeFlip; - - DebugPresent(("\tn %" PRIu64 " %p %" PRIu64 " %" PRIu64 ": %08" PRIx32 " -> %08" PRIx32 "\n", - vblank->event_id, vblank, vblank->exec_msc, vblank->target_msc, - vblank->pixmap ? vblank->pixmap->drawable.id : 0, - vblank->window ? vblank->window->drawable.id : 0)); - - assert (&vblank->event_queue == xwl_present_window->flip_queue.next); - - xorg_list_del(&vblank->event_queue); - - if (xwl_present_window->flip_active) { - struct xwl_present_event *event = - xwl_present_event_from_vblank(xwl_present_window->flip_active); - - if (!event->pixmap -#ifdef DRI3 - /* If this flip used explicit sync, we won't get a release event */ - || (xwl_screen->explicit_sync && vblank->release_syncobj) -#endif /* DRI3 */ - ) { - xwl_present_free_event(event); - } else - /* Put the previous flip in the idle_queue and wait for further notice from - * the Wayland compositor - */ - xorg_list_append(&xwl_present_window->flip_active->event_queue, &xwl_present_window->idle_queue); - } - - xwl_present_window->flip_active = vblank; - - if (vblank->reason == PRESENT_FLIP_REASON_BUFFER_FORMAT) - mode = PresentCompleteModeSuboptimalCopy; - - present_vblank_notify(vblank, PresentCompleteKindPixmap, mode, ust, crtc_msc); - - if (vblank->abort_flip) - xwl_present_flips_stop(window); - - xwl_present_flip_try_ready(xwl_present_window); -} - -static void -xwl_present_update_window_crtc(present_window_priv_ptr window_priv, RRCrtcPtr crtc, uint64_t new_msc) -{ - /* Crtc unchanged, no offset. */ - if (crtc == window_priv->crtc) - return; - - /* No crtc earlier to offset against, just set the crtc. */ - if (window_priv->crtc == PresentCrtcNeverSet) { - window_priv->msc_offset = 0; - window_priv->crtc = crtc; - return; - } - - /* In window-mode the last correct msc-offset is always kept - * in window-priv struct because msc is saved per window and - * not per crtc as in screen-mode. - */ - window_priv->msc_offset += new_msc - window_priv->msc; - window_priv->crtc = crtc; -} - - -void -xwl_present_cleanup(WindowPtr window) -{ - struct xwl_present_window *xwl_present_window = xwl_present_window_priv(window); - present_window_priv_ptr window_priv = present_window_priv(window); - struct xwl_present_event *event, *tmp; - - if (!xwl_present_window) - return; - - xorg_list_del(&xwl_present_window->frame_callback_list); - - if (xwl_present_window->sync_callback) { - wl_callback_destroy(xwl_present_window->sync_callback); - xwl_present_window->sync_callback = NULL; - } - - if (window_priv) { - /* Clear remaining events */ - xorg_list_for_each_entry_safe(event, tmp, &window_priv->vblank, vblank.window_list) - xwl_present_free_event(event); - } - - /* Clear timer */ - xwl_present_free_timer(xwl_present_window); - TimerFree(xwl_present_window->unredirect_timer); - - /* Remove from privates so we don't try to access it later */ - dixSetPrivate(&window->devPrivates, - &xwl_present_window_private_key, - NULL); - - free(xwl_present_window); -} - -static void -xwl_present_buffer_release(void *data) -{ - struct xwl_present_window *xwl_present_window; - struct xwl_present_event *event = data; - present_vblank_ptr vblank; - - if (!event) - return; - - vblank = &event->vblank; - -#if defined(XWL_HAS_GLAMOR) && defined(DRI3) - if (vblank->release_syncobj) { - /* transfer implicit fence to release syncobj */ - int fence_fd = xwl_glamor_dmabuf_export_sync_file(vblank->pixmap); - vblank->release_syncobj->import_fence(vblank->release_syncobj, - vblank->release_point, - fence_fd); - } else -#endif /* defined(XWL_HAS_GLAMOR) && defined(DRI3) */ - present_pixmap_idle(vblank->pixmap, vblank->window, vblank->serial, vblank->idle_fence); - - xwl_present_window = xwl_present_window_priv(vblank->window); - if (xwl_present_window->flip_active == vblank || - xwl_present_get_pending_flip(xwl_present_window) == vblank) - xwl_present_release_pixmap(event); - else - xwl_present_free_event(event); -} - -static void -xwl_present_msc_bump(struct xwl_present_window *xwl_present_window) -{ - present_vblank_ptr flip_pending = xwl_present_get_pending_flip(xwl_present_window); - uint64_t msc = ++xwl_present_window->msc; - present_vblank_ptr vblank, tmp; - - xwl_present_window->ust = GetTimeInMicros(); - - xwl_present_window->timer_armed = 0; - - if (flip_pending && flip_pending->sync_flip) - xwl_present_flip_notify_vblank(flip_pending, xwl_present_window->ust, msc); - - xorg_list_for_each_entry_safe(vblank, tmp, &xwl_present_window->wait_list, event_queue) { - if (vblank->exec_msc <= msc) { - DebugPresent(("\te %" PRIu64 " ust %" PRIu64 " msc %" PRIu64 "\n", - vblank->event_id, xwl_present_window->ust, msc)); - - xwl_present_execute(vblank, xwl_present_window->ust, msc); - } - } -} - -static CARD32 -xwl_present_timer_callback(OsTimerPtr timer, - CARD32 time, - void *arg) -{ - struct xwl_present_window *xwl_present_window = arg; - - /* If we were expecting a frame callback for this window, it didn't arrive - * in a second. Stop listening to it to avoid double-bumping the MSC - */ - xorg_list_del(&xwl_present_window->frame_callback_list); - - xwl_present_msc_bump(xwl_present_window); - xwl_present_reset_timer(xwl_present_window); - - return 0; -} - -void -xwl_present_frame_callback(struct xwl_present_window *xwl_present_window) -{ - xorg_list_del(&xwl_present_window->frame_callback_list); - - xwl_present_msc_bump(xwl_present_window); - - /* we do not need the timer anymore for this frame, - * reset it for potentially the next one - */ - xwl_present_reset_timer(xwl_present_window); -} - -static void -xwl_present_sync_callback(void *data, - struct wl_callback *callback, - uint32_t time) -{ - present_vblank_ptr vblank = data; - struct xwl_present_window *xwl_present_window = xwl_present_window_get_priv(vblank->window); - - wl_callback_destroy(xwl_present_window->sync_callback); - xwl_present_window->sync_callback = NULL; - - xwl_present_flip_notify_vblank(vblank, xwl_present_window->ust, xwl_present_window->msc); -} - -static const struct wl_callback_listener xwl_present_sync_listener = { - xwl_present_sync_callback -}; - -static RRCrtcPtr -xwl_present_get_crtc(present_screen_priv_ptr screen_priv, - WindowPtr present_window) -{ - struct xwl_present_window *xwl_present_window = xwl_present_window_get_priv(present_window); - rrScrPrivPtr rr_private; - - if (xwl_present_window == NULL) - return NULL; - - rr_private = rrGetScrPriv(present_window->drawable.pScreen); - - if (rr_private->numCrtcs == 0) - return NULL; - - return rr_private->crtcs[0]; -} - -/* - * Queue an event to report back to the Present extension when the specified - * MSC has passed - */ -static int -xwl_present_queue_vblank(ScreenPtr screen, - WindowPtr present_window, - RRCrtcPtr crtc, - uint64_t event_id, - uint64_t msc) -{ - struct xwl_present_window *xwl_present_window = xwl_present_window_get_priv(present_window); - struct xwl_window *xwl_window = xwl_window_from_window(present_window); - struct xwl_present_event *event = xwl_present_event_from_id(present_window, event_id); - - if (!event) { - ErrorF("present: Error getting event\n"); - return BadImplementation; - } - - BUG_RETURN_VAL(!xwl_present_window, BadImplementation); - - event->vblank.exec_msc = msc; - - xorg_list_del(&event->vblank.event_queue); - xorg_list_append(&event->vblank.event_queue, &xwl_present_window->wait_list); - - /* Hook up to frame callback */ - if (xwl_window && - xorg_list_is_empty(&xwl_present_window->frame_callback_list)) { - xorg_list_add(&xwl_present_window->frame_callback_list, - &xwl_window->frame_callback_list); - } - - if ((xwl_window && xwl_window->frame_callback) || - !xwl_present_window->frame_timer) - xwl_present_reset_timer(xwl_present_window); - - return Success; -} - -/* - * Remove a pending vblank event so that it is not reported - * to the extension - */ -static void -xwl_present_abort_vblank(ScreenPtr screen, - WindowPtr present_window, - RRCrtcPtr crtc, - uint64_t event_id, - uint64_t msc) -{ - static Bool called; - - if (called) - return; - - /* xwl_present_cleanup should have cleaned up everything, - * present_free_window_vblank shouldn't need to call this. - */ - ErrorF("Unexpected call to %s:\n", __func__); - xorg_backtrace(); -} - -static void -xwl_present_flush(WindowPtr window) -{ -#ifdef XWL_HAS_GLAMOR - ScreenPtr screen = window->drawable.pScreen; - struct xwl_screen *xwl_screen = xwl_screen_get(screen); - - if (xwl_screen->glamor) - glamor_block_handler(screen); -#endif -} - -static void -xwl_present_maybe_set_reason(struct xwl_window *xwl_window, PresentFlipReason *reason) -{ - struct xwl_screen *xwl_screen = xwl_window->xwl_screen; - - if (!reason || xwl_screen->dmabuf_protocol_version < 4) - return; - - if (xwl_window->feedback.unprocessed_feedback_pending) { - xwl_window->feedback.unprocessed_feedback_pending = 0; - - *reason = PRESENT_FLIP_REASON_BUFFER_FORMAT; - } - - if (xwl_screen->default_feedback.unprocessed_feedback_pending) { - xwl_screen->default_feedback.unprocessed_feedback_pending = 0; - - *reason = PRESENT_FLIP_REASON_BUFFER_FORMAT; - } -} - -static int -xwl_present_flush_fenced(WindowPtr window) -{ - int fence = -1; -#ifdef XWL_HAS_GLAMOR - struct xwl_screen *xwl_screen = xwl_screen_get(window->drawable.pScreen); - fence = xwl_glamor_get_fence(xwl_screen); -#endif /* XWL_HAS_GLAMOR */ - xwl_present_flush(window); - return fence; -} - -static Bool -xwl_present_check_flip(RRCrtcPtr crtc, - WindowPtr present_window, - PixmapPtr pixmap, - Bool sync_flip, - RegionPtr valid, - int16_t x_off, - int16_t y_off, - PresentFlipReason *reason) -{ - WindowPtr toplvl_window = xwl_present_toplvl_pixmap_window(present_window); - struct xwl_window *xwl_window = xwl_window_from_window(present_window); - ScreenPtr screen = pixmap->drawable.pScreen; - - if (reason) - *reason = PRESENT_FLIP_REASON_UNKNOWN; - - if (!xwl_window) - return FALSE; - - xwl_present_maybe_set_reason(xwl_window, reason); - - if (!crtc) - return FALSE; - - /* Source pixmap must align with window exactly */ - if (x_off || y_off) - return FALSE; - - /* Valid area must contain window (for simplicity for now just never flip when one is set). */ - if (valid) - return FALSE; - - /* Flip pixmap must have same dimensions as window */ - if (present_window->drawable.width != pixmap->drawable.width || - present_window->drawable.height != pixmap->drawable.height) - return FALSE; - - if (!xwl_pixmap_get_wl_buffer(pixmap)) - return FALSE; - - /* Window must be same region as toplevel window */ - if ( !RegionEqual(&present_window->winSize, &toplvl_window->winSize) ) - return FALSE; - - /* Can't flip if window clipped by children */ - if (!RegionEqual(&present_window->clipList, &present_window->winSize)) - return FALSE; - - /* Can't flip if the window pixmap doesn't match the xwl_window parent - * window's, e.g. because a client redirected this window or one of its - * parents. - */ - if (screen->GetWindowPixmap(xwl_window->surface_window) != screen->GetWindowPixmap(present_window)) - return FALSE; - - /* - * We currently only allow flips of windows, that have the same - * dimensions as their xwl_window parent window. For the case of - * different sizes subsurfaces are presumably the way forward. - */ - if (!RegionEqual(&xwl_window->toplevel->winSize, &present_window->winSize)) - return FALSE; - -#ifdef XWL_HAS_GLAMOR - if (!xwl_glamor_supports_implicit_sync(xwl_window->xwl_screen) && - !xwl_window->xwl_screen->explicit_sync) - return FALSE; - - if (xwl_window->xwl_screen->glamor && - !xwl_glamor_check_flip(present_window, pixmap)) - return FALSE; -#endif /* XWL_HAS_GLAMOR */ - - return TRUE; -} - -/* - * 'window' is being reconfigured. Check to see if it is involved - * in flipping and clean up as necessary. - */ -static void -xwl_present_check_flip_window (WindowPtr window) -{ - struct xwl_present_window *xwl_present_window = xwl_present_window_priv(window); - present_window_priv_ptr window_priv = present_window_priv(window); - present_vblank_ptr flip_pending; - present_vblank_ptr flip_active; - present_vblank_ptr vblank; - PresentFlipReason reason; - - /* If this window hasn't ever been used with Present, it can't be - * flipping - */ - if (!xwl_present_window || !window_priv) - return; - - flip_pending = xwl_present_get_pending_flip(xwl_present_window); - flip_active = xwl_present_window->flip_active; - - if (flip_pending) { - if (!xwl_present_check_flip(flip_pending->crtc, flip_pending->window, flip_pending->pixmap, - flip_pending->sync_flip, flip_pending->valid, 0, 0, NULL)) - flip_pending->abort_flip = TRUE; - } else if (flip_active) { - if (!xwl_present_check_flip(flip_active->crtc, flip_active->window, flip_active->pixmap, - flip_active->sync_flip, flip_active->valid, 0, 0, NULL)) - xwl_present_flips_stop(window); - } - - /* Now check any queued vblanks */ - xorg_list_for_each_entry(vblank, &window_priv->vblank, window_list) { - if (vblank->queued && vblank->flip && - !xwl_present_check_flip(vblank->crtc, window, vblank->pixmap, - vblank->sync_flip, vblank->valid, 0, 0, &reason)) { - vblank->flip = FALSE; - vblank->reason = reason; - } - } -} - -/* - * Clean up any pending or current flips for this window - */ -static void -xwl_present_clear_window_flip(WindowPtr window) -{ - /* xwl_present_cleanup cleaned up everything */ -} - -static Bool -xwl_present_flip(present_vblank_ptr vblank, RegionPtr damage) -{ - WindowPtr present_window = vblank->window; - PixmapPtr pixmap = vblank->pixmap; - struct xwl_window *xwl_window = xwl_window_from_window(present_window); - struct xwl_present_window *xwl_present_window = xwl_present_window_priv(present_window); - BoxPtr damage_box; - struct wl_buffer *buffer; - struct xwl_present_event *event = xwl_present_event_from_vblank(vblank); - Bool implicit_sync = TRUE; - - if (!xwl_window || !xwl_window->allow_commits) - return FALSE; - - buffer = xwl_pixmap_get_wl_buffer(pixmap); - if (!buffer) { - ErrorF("present: Error getting buffer\n"); - return FALSE; - } - - damage_box = RegionExtents(damage); - - pixmap->refcnt++; - - event->pixmap = pixmap; - -#if defined(XWL_HAS_GLAMOR) && defined(DRI3) - if (vblank->acquire_syncobj && vblank->release_syncobj) { - if (xwl_window->xwl_screen->explicit_sync) { - xwl_glamor_dri3_syncobj_passthrough(xwl_window, - vblank->acquire_syncobj, - vblank->release_syncobj, - vblank->acquire_point, - vblank->release_point); - implicit_sync = FALSE; - } else { - /* transfer from acquire syncobj to implicit fence */ - int fence_fd = - vblank->acquire_syncobj->export_fence(vblank->acquire_syncobj, - vblank->acquire_point); - xwl_glamor_dmabuf_import_sync_file(vblank->pixmap, fence_fd); - } - } -#endif /* defined(XWL_HAS_GLAMOR) && defined(DRI3) */ - - if (implicit_sync) { - xwl_pixmap_set_buffer_release_cb(pixmap, xwl_present_buffer_release, event); - - if (xwl_window->surface_sync) { - wp_linux_drm_syncobj_surface_v1_destroy(xwl_window->surface_sync); - xwl_window->surface_sync = NULL; - } - } - - /* We can flip directly to the main surface (full screen window without clips) */ - wl_surface_attach(xwl_window->surface, buffer, 0, 0); - - if (xorg_list_is_empty(&xwl_present_window->frame_callback_list)) { - xorg_list_add(&xwl_present_window->frame_callback_list, - &xwl_window->frame_callback_list); - } - - if (!xwl_window->frame_callback) - xwl_window_create_frame_callback(xwl_window); - - xwl_surface_damage(xwl_window->xwl_screen, xwl_window->surface, - damage_box->x1 - present_window->drawable.x, - damage_box->y1 - present_window->drawable.y, - damage_box->x2 - damage_box->x1, - damage_box->y2 - damage_box->y1); - - if (xwl_window->tearing_control) { - uint32_t hint; - if (event->options & PresentOptionAsyncMayTear) - hint = WP_TEARING_CONTROL_V1_PRESENTATION_HINT_ASYNC; - else - hint = WP_TEARING_CONTROL_V1_PRESENTATION_HINT_VSYNC; - - wp_tearing_control_v1_set_presentation_hint(xwl_window->tearing_control, hint); - } - - wl_surface_commit(xwl_window->surface); - - if (!vblank->sync_flip) { - xwl_present_window->sync_callback = - wl_display_sync(xwl_window->xwl_screen->display); - wl_callback_add_listener(xwl_present_window->sync_callback, - &xwl_present_sync_listener, - &event->vblank); - } - - wl_display_flush(xwl_window->xwl_screen->display); - return TRUE; -} - -#if defined(XWL_HAS_GLAMOR) && defined(DRI3) -static void -xwl_present_acquire_fence_avail(int fd, int xevents, void *data) -{ - present_vblank_ptr vblank = data; - - SetNotifyFd(fd, NULL, 0, NULL); - close(fd); - vblank->efd = -1; - - xwl_present_re_execute(vblank); -} -#endif /* defined(XWL_HAS_GLAMOR) && defined(DRI3) */ - -static Bool -xwl_present_wait_acquire_fence_avail(struct xwl_screen *xwl_screen, - present_vblank_ptr vblank) -{ -#if defined(XWL_HAS_GLAMOR) && defined(DRI3) - /* If the compositor does not support explicit sync we need to wait for the - * acquire fence to be submitted before flipping. */ - if (vblank->flip && !xwl_screen->explicit_sync && - vblank->pixmap && vblank->acquire_syncobj && - !vblank->acquire_syncobj->has_fence(vblank->acquire_syncobj, - vblank->acquire_point)) { - vblank->efd = eventfd(0, EFD_CLOEXEC); - SetNotifyFd(vblank->efd, xwl_present_acquire_fence_avail, X_NOTIFY_READ, vblank); - vblank->acquire_syncobj->submitted_eventfd(vblank->acquire_syncobj, - vblank->acquire_point, - vblank->efd); - return TRUE; - } -#endif /* defined(XWL_HAS_GLAMOR) && defined(DRI3) */ - return FALSE; -} - -static void -xwl_present_flush_blocked(struct xwl_present_window *xwl_present_window, - uint64_t crtc_msc) -{ - struct xwl_screen *xwl_screen = - xwl_screen_get(xwl_present_window->window->drawable.pScreen); - struct xwl_present_event *blocked_event, *tmp; - - if (!xwl_present_window->blocking_event) - return; - - xwl_present_window->blocking_event = 0; - - xorg_list_for_each_entry_safe(blocked_event, tmp, - &xwl_present_window->blocked_queue, - blocked) { - present_vblank_ptr blocked_vblank = &blocked_event->vblank; - xorg_list_del(&blocked_event->blocked); - if (present_execute_wait(blocked_vblank, crtc_msc) || - xwl_present_wait_acquire_fence_avail(xwl_screen, blocked_vblank)) { - xwl_present_window->blocking_event = blocked_vblank->event_id; - return; - } - - xwl_present_re_execute(blocked_vblank); - } -} - -/* - * Once the required MSC has been reached, execute the pending request. - * - * For requests to actually present something, either blt contents to - * the window pixmap or queue a window buffer swap on the backend. - * - * For requests to just get the current MSC/UST combo, skip that part and - * go straight to event delivery. - */ -static void -xwl_present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc) -{ - WindowPtr window = vblank->window; - struct xwl_present_window *xwl_present_window = xwl_present_window_get_priv(window); - present_vblank_ptr flip_pending = xwl_present_get_pending_flip(xwl_present_window); - struct xwl_present_event *event = xwl_present_event_from_vblank(vblank); - struct xwl_screen *xwl_screen = xwl_screen_get(window->drawable.pScreen); - Bool notify_only = !vblank->window || !vblank->pixmap; - - xorg_list_del(&vblank->event_queue); - - if (!notify_only && !event->copy_executed && - xwl_present_window->blocking_event && - xwl_present_window->blocking_event != event->vblank.event_id) { - /* an earlier request is blocking execution */ - xorg_list_append(&event->blocked, &xwl_present_window->blocked_queue); - return; - } - -retry: - if (present_execute_wait(vblank, crtc_msc) || - xwl_present_wait_acquire_fence_avail(xwl_screen, vblank)) { - if (!notify_only) - /* block execution of subsequent requests until this request is ready */ - xwl_present_window->blocking_event = event->vblank.event_id; - return; - } - - if (flip_pending && vblank->flip && !notify_only) { - present_vblank_ptr flip_queued_last; - - flip_queued_last = xorg_list_last_entry(&xwl_present_window->flip_queue, - present_vblank_rec, event_queue); - - /* Do mailbox handling for queued flips, to prevent the flip queue from - * growing unbounded. - */ - if (flip_queued_last != flip_pending && - (flip_queued_last->sync_flip -#ifdef DRI3 - || vblank->acquire_syncobj -#endif - )) { - xorg_list_del(&flip_queued_last->event_queue); - present_vblank_scrap(flip_queued_last); - xwl_present_re_execute(flip_queued_last); - } - - DebugPresent(("\tr %" PRIu64 " %p (pending %p)\n", - vblank->event_id, vblank, flip_pending)); - xorg_list_append(&vblank->event_queue, &xwl_present_window->flip_queue); - return; - } - - vblank->queued = FALSE; - - if (!notify_only && !event->copy_executed) { - ScreenPtr screen = window->drawable.pScreen; - int ret; - - if (vblank->flip) { - RegionPtr damage; - - DebugPresent(("\tf %" PRIu64 " %p %" PRIu64 ": %08" PRIx32 " -> %08" PRIx32 "\n", - vblank->event_id, vblank, crtc_msc, - vblank->pixmap->drawable.id, vblank->window->drawable.id)); - - /* Set update region as damaged */ - if (vblank->update) { - damage = RegionDuplicate(vblank->update); - /* Translate update region to screen space */ - assert(vblank->x_off == 0 && vblank->y_off == 0); - RegionTranslate(damage, window->drawable.x, window->drawable.y); - RegionIntersect(damage, damage, &window->clipList); - } else - damage = RegionDuplicate(&window->clipList); - - if (xwl_present_flip(vblank, damage)) { - WindowPtr toplvl_window = xwl_present_toplvl_pixmap_window(vblank->window); - struct xwl_window *xwl_window = xwl_window_from_window(window); - PixmapPtr old_pixmap = screen->GetWindowPixmap(window); - - /* Replace window pixmap with flip pixmap */ - vblank->pixmap->screen_x = old_pixmap->screen_x; - vblank->pixmap->screen_y = old_pixmap->screen_y; - present_set_tree_pixmap(toplvl_window, old_pixmap, vblank->pixmap); - - if (toplvl_window == screen->root && - screen->GetScreenPixmap(screen) == old_pixmap) - screen->SetScreenPixmap(vblank->pixmap); - - vblank->pixmap->refcnt++; - dixDestroyPixmap(old_pixmap, old_pixmap->drawable.id); - - /* Report damage, let damage_report ignore it though */ - xwl_screen->ignore_damage = TRUE; - DamageDamageRegion(&vblank->window->drawable, damage); - xwl_screen->ignore_damage = FALSE; - RegionDestroy(damage); - - /* Clear damage region, to ensure damage_report is called before - * any drawing to the window - */ - xwl_window_buffer_add_damage_region(xwl_window); - RegionEmpty(xwl_window_get_damage_region(xwl_window)); - xorg_list_del(&xwl_window->link_damage); - - /* Put pending flip at the flip queue head */ - xorg_list_add(&vblank->event_queue, &xwl_present_window->flip_queue); - - /* Realign timer */ - xwl_present_reset_timer(xwl_present_window); - - xwl_present_flush_blocked(xwl_present_window, crtc_msc); - return; - } - - vblank->flip = FALSE; - /* re-execute, falling through to copy */ - goto retry; - } - DebugPresent(("\tc %p %" PRIu64 ": %08" PRIx32 " -> %08" PRIx32 "\n", - vblank, crtc_msc, vblank->pixmap->drawable.id, vblank->window->drawable.id)); - - if (flip_pending) - flip_pending->abort_flip = TRUE; - else if (xwl_present_window->flip_active) - xwl_present_flips_stop(window); - - present_execute_copy(vblank, crtc_msc); - assert(!vblank->queued); - - /* Set the copy_executed field, so this will fall through to present_execute_post next time */ - event->copy_executed = TRUE; - - ret = xwl_present_queue_vblank(screen, window, vblank->crtc, - vblank->event_id, crtc_msc + 1); - - xwl_present_flush_blocked(xwl_present_window, crtc_msc); - - if (ret == Success) - return; - } - - present_execute_post(vblank, ust, crtc_msc); -} - -static int -xwl_present_pixmap(WindowPtr window, - PixmapPtr pixmap, - CARD32 serial, - RegionPtr valid, - RegionPtr update, - int16_t x_off, - int16_t y_off, - RRCrtcPtr target_crtc, - SyncFence *wait_fence, - SyncFence *idle_fence, -#ifdef DRI3 - struct dri3_syncobj *acquire_syncobj, - struct dri3_syncobj *release_syncobj, - uint64_t acquire_point, - uint64_t release_point, -#endif /* DRI3 */ - uint32_t options, - uint64_t target_window_msc, - uint64_t divisor, - uint64_t remainder, - present_notify_ptr notifies, - int num_notifies) -{ - static uint64_t xwl_present_event_id; - uint64_t ust = 0; - uint64_t target_msc; - uint64_t crtc_msc = 0; - int ret; - present_vblank_ptr vblank; - ScreenPtr screen = window->drawable.pScreen; - present_window_priv_ptr window_priv = present_get_window_priv(window, TRUE); - present_screen_priv_ptr screen_priv = present_screen_priv(screen); - struct xwl_screen *xwl_screen = xwl_screen_get(screen_priv->pScreen); - uint32_t caps = xwl_screen->present_capabilities; - struct xwl_present_event *event; - - if (!window_priv) - return BadAlloc; - -#ifdef DRI3 - if (!(caps & PresentCapabilitySyncobj) && - (acquire_syncobj || release_syncobj)) - return BadValue; -#endif /* DRI3 */ - - target_crtc = xwl_present_get_crtc(screen_priv, window); - - ret = xwl_present_get_ust_msc(screen, window, &ust, &crtc_msc); - - xwl_present_update_window_crtc(window_priv, target_crtc, crtc_msc); - - if (ret == Success) { - /* Stash the current MSC away in case we need it later - */ - window_priv->msc = crtc_msc; - } - - target_msc = present_get_target_msc(target_window_msc + window_priv->msc_offset, - crtc_msc, - divisor, - remainder, - options); - - event = calloc(1, sizeof(*event)); - if (!event) - return BadAlloc; - - vblank = &event->vblank; - if (!present_vblank_init(vblank, window, pixmap, serial, valid, update, x_off, y_off, - target_crtc, wait_fence, idle_fence, -#ifdef DRI3 - acquire_syncobj, release_syncobj, acquire_point, release_point, -#endif /* DRI3 */ - options, caps, notifies, num_notifies, target_msc, crtc_msc)) { - present_vblank_destroy(vblank); - return BadAlloc; - } - - vblank->event_id = ++xwl_present_event_id; - event->options = options; - event->divisor = divisor; - event->remainder = remainder; - vblank->exec_msc = xwl_present_get_exec_msc(options, vblank->target_msc); - - vblank->queued = TRUE; - if (crtc_msc < vblank->exec_msc) { - if (xwl_present_queue_vblank(screen, window, target_crtc, vblank->event_id, vblank->exec_msc) == Success) - return Success; - - DebugPresent(("present_queue_vblank failed\n")); - } - - xwl_present_execute(vblank, ust, crtc_msc); - return Success; -} - -void -xwl_present_unrealize_window(struct xwl_present_window *xwl_present_window) -{ - /* The pending frame callback may never be called, so drop it and shorten - * the frame timer interval. - */ - xorg_list_del(&xwl_present_window->frame_callback_list); - - /* Make sure the timer callback doesn't get called */ - xwl_present_window->timer_armed = 0; - xwl_present_reset_timer(xwl_present_window); -} - -Bool -xwl_present_maybe_redirect_window(WindowPtr window) -{ - struct xwl_present_window *xwl_present_window = xwl_present_window_get_priv(window); - struct xwl_window *xwl_window = xwl_window_from_window(window); - - if (xwl_present_window->redirect_failed) - return FALSE; - - if (compRedirectWindow(serverClient, window, CompositeRedirectManual) != Success) { - xwl_present_window->redirect_failed = TRUE; - return FALSE; - } - - xwl_present_window->redirected = TRUE; - - xwl_window_update_surface_window(xwl_window); - if (xwl_window->surface_window != window) { - compUnredirectWindow(serverClient, window, CompositeRedirectManual); - xwl_present_window->redirected = FALSE; - xwl_present_window->redirect_failed = TRUE; - xwl_window_update_surface_window(xwl_window); - return FALSE; - } - - if (!xwl_window->surface_window_damage) - xwl_window->surface_window_damage = RegionCreate(NullBox, 1); - - return TRUE; -} - -static CARD32 -unredirect_window(OsTimerPtr timer, CARD32 time, void *arg) -{ - WindowPtr window = arg; - struct xwl_present_window *xwl_present_window = xwl_present_window_get_priv(window); - - compUnredirectWindow(serverClient, window, CompositeRedirectManual); - xwl_present_window->redirected = FALSE; - - xwl_present_window->unredirect_timer = NULL; - return 0; -} - -Bool -xwl_present_maybe_unredirect_window(WindowPtr window) -{ - struct xwl_present_window *xwl_present_window = xwl_present_window_get_priv(window); - - if (!xwl_present_window || !xwl_present_window->redirected) - return FALSE; - - /* This function may get called from composite layer code, in which case - * calling compUnredirectWindow would blow up. To avoid this, set up a timer - * which will call it "as soon as possible". - */ - if (!xwl_present_window->unredirect_timer) { - xwl_present_window->unredirect_timer = - TimerSet(NULL, 0, 1, unredirect_window, window); - } - - return TRUE; -} - -Bool -xwl_present_window_redirected(WindowPtr window) -{ - struct xwl_present_window *xwl_present_window = xwl_present_window_get_priv(window); - - return xwl_present_window->redirected; -} - -Bool -xwl_present_init(ScreenPtr screen) -{ - struct xwl_screen *xwl_screen = xwl_screen_get(screen); - present_screen_priv_ptr screen_priv; - - if (!present_screen_register_priv_keys()) - return FALSE; - - if (present_screen_priv(screen)) - return TRUE; - - screen_priv = present_screen_priv_init(screen); - if (!screen_priv) - return FALSE; - - if (!dixRegisterPrivateKey(&xwl_present_window_private_key, PRIVATE_WINDOW, 0)) - return FALSE; - - xwl_screen->present_capabilities = XWL_PRESENT_CAPS; -#ifdef XWL_HAS_GLAMOR - if (xwl_glamor_supports_syncobjs(xwl_screen)) - xwl_screen->present_capabilities |= - PresentCapabilitySyncobj; -#endif /* XWL_HAS_GLAMOR */ - - screen_priv->query_capabilities = xwl_present_query_capabilities; - screen_priv->get_crtc = xwl_present_get_crtc; - - screen_priv->check_flip = xwl_present_check_flip; - screen_priv->check_flip_window = xwl_present_check_flip_window; - screen_priv->clear_window_flip = xwl_present_clear_window_flip; - - screen_priv->present_pixmap = xwl_present_pixmap; - screen_priv->queue_vblank = xwl_present_queue_vblank; - screen_priv->flush = xwl_present_flush; - screen_priv->flush_fenced = xwl_present_flush_fenced; - screen_priv->re_execute = xwl_present_re_execute; - - screen_priv->abort_vblank = xwl_present_abort_vblank; - - return TRUE; -} diff --git a/hw/xwayland/xwayland-present.h b/hw/xwayland/xwayland-present.h deleted file mode 100644 index 527233910..000000000 --- a/hw/xwayland/xwayland-present.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright © 2018 Roman Gilg - * - * Permission to use, copy, modify, distribute, and sell this software - * and its documentation for any purpose is hereby granted without - * fee, provided that the above copyright notice appear in all copies - * and that both that copyright notice and this permission notice - * appear in supporting documentation, and that the name of the - * copyright holders not be used in advertising or publicity - * pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied - * warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS - * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. - */ - -#ifndef XWAYLAND_PRESENT_H -#define XWAYLAND_PRESENT_H - -#include - -#include -#include - -#include "xwayland-types.h" - -struct xwl_present_window { - WindowPtr window; - - struct xorg_list frame_callback_list; - - uint64_t msc; - uint64_t ust; - - OsTimerPtr frame_timer; - /* Timestamp when the current timer was first armed */ - CARD32 timer_armed; - - struct wl_callback *sync_callback; - - struct xorg_list wait_list; - struct xorg_list flip_queue; - struct xorg_list idle_queue; - struct xorg_list blocked_queue; - - present_vblank_ptr flip_active; - uint64_t blocking_event; - - OsTimerPtr unredirect_timer; - Bool redirected; - Bool redirect_failed; -}; - -struct xwl_present_event { - present_vblank_rec vblank; - - PixmapPtr pixmap; - Bool copy_executed; - - uint32_t options; - uint64_t divisor; - uint64_t remainder; - - struct xorg_list blocked; -}; - -Bool xwl_present_entered_for_each_frame_callback(void); -void xwl_present_for_each_frame_callback(struct xwl_window *xwl_window, - void iter_func(struct xwl_present_window *)); -void xwl_present_reset_timer(struct xwl_present_window *xwl_present_window); -void xwl_present_frame_callback(struct xwl_present_window *xwl_present_window); -Bool xwl_present_init(ScreenPtr screen); -void xwl_present_cleanup(WindowPtr window); -void xwl_present_unrealize_window(struct xwl_present_window *xwl_present_window); -Bool xwl_present_maybe_redirect_window(WindowPtr window); -Bool xwl_present_maybe_unredirect_window(WindowPtr window); -Bool xwl_present_window_redirected(WindowPtr window); - -#endif /* XWAYLAND_PRESENT_H */ diff --git a/hw/xwayland/xwayland-screen.c b/hw/xwayland/xwayland-screen.c deleted file mode 100644 index 6dcd14748..000000000 --- a/hw/xwayland/xwayland-screen.c +++ /dev/null @@ -1,1180 +0,0 @@ -/* - * Copyright © 2011-2014 Intel Corporation - * - * Permission to use, copy, modify, distribute, and sell this software - * and its documentation for any purpose is hereby granted without - * fee, provided that the above copyright notice appear in all copies - * and that both that copyright notice and this permission notice - * appear in supporting documentation, and that the name of the - * copyright holders not be used in advertising or publicity - * pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied - * warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS - * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. - */ - -#include - -#include -#include -#include -#include - -#ifdef XWL_HAS_GLAMOR -#include -#endif - -#include -#include - -#include "dix/dix_priv.h" -#include "dix/input_priv.h" -#include "dix/property_priv.h" -#include "dix/screen_hooks_priv.h" -#include "miext/extinit_priv.h" -#include "os/client_priv.h" -#include "os/log_priv.h" -#include "os/osdep.h" -#include "os/xserver_poll.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "xwayland-cursor.h" -#include "xwayland-screen.h" -#include "xwayland-window.h" -#include "xwayland-input.h" -#include "xwayland-output.h" -#include "xwayland-pixmap.h" -#include "xwayland-present.h" -#include "xwayland-shm.h" -#ifdef XWL_HAS_EI -#include "xwayland-xtest.h" -#endif -#ifdef XWL_HAS_GLAMOR -#include "xwayland-glamor.h" -#endif - -#ifdef MITSHM -#include "shmint.h" -#endif - -#include "xdg-output-unstable-v1-client-protocol.h" -#include "viewporter-client-protocol.h" -#include "xdg-shell-client-protocol.h" -#include "xwayland-shell-v1-client-protocol.h" -#include "tearing-control-v1-client-protocol.h" -#include "fractional-scale-v1-client-protocol.h" - -static DevPrivateKeyRec xwl_screen_private_key; -static DevPrivateKeyRec xwl_client_private_key; - -#define DEFAULT_DPI 96 - -_X_NORETURN -static void _X_ATTRIBUTE_PRINTF(1, 2) -xwl_give_up(const char *f, ...) -{ - va_list args; - - va_start(args, f); - LogVMessageVerb(X_NONE, -1, f, args); - va_end(args); - - CloseWellKnownConnections(); - OsCleanup(TRUE); - fflush(stderr); - exit(1); -} - -struct xwl_client * -xwl_client_get(ClientPtr client) -{ - return dixLookupPrivate(&client->devPrivates, &xwl_client_private_key); -} - -struct xwl_screen * -xwl_screen_get(ScreenPtr screen) -{ - return dixLookupPrivate(&screen->devPrivates, &xwl_screen_private_key); -} - -Bool -xwl_screen_has_viewport_support(struct xwl_screen *xwl_screen) -{ - return wl_compositor_get_version(xwl_screen->compositor) >= - WL_SURFACE_DAMAGE_BUFFER_SINCE_VERSION && - xwl_screen->viewporter != NULL; -} - -Bool -xwl_screen_has_resolution_change_emulation(struct xwl_screen *xwl_screen) -{ - /* Resolution change emulation is only supported in rootless mode and - * it requires viewport support. - */ - return xwl_screen->rootless && xwl_screen_has_viewport_support(xwl_screen); -} - -/* Return the output @ 0x0, falling back to the first output in the list */ -struct xwl_output * -xwl_screen_get_first_output(struct xwl_screen *xwl_screen) -{ - struct xwl_output *xwl_output; - - xorg_list_for_each_entry(xwl_output, &xwl_screen->output_list, link) { - if (xwl_output->x == 0 && xwl_output->y == 0) - return xwl_output; - } - - if (xorg_list_is_empty(&xwl_screen->output_list)) - return NULL; - - return xorg_list_first_entry(&xwl_screen->output_list, struct xwl_output, link); -} - -struct xwl_output * -xwl_screen_get_fixed_or_first_output(struct xwl_screen *xwl_screen) -{ - if (xwl_screen->fixed_output) - return xwl_screen->fixed_output; - - return xwl_screen_get_first_output(xwl_screen); -} - -int -xwl_screen_get_width(struct xwl_screen *xwl_screen) -{ - return round(xwl_screen->width); -} - -int -xwl_screen_get_height(struct xwl_screen *xwl_screen) -{ - return round(xwl_screen->height); -} - -static void -xwl_property_callback(CallbackListPtr *pcbl, void *closure, - void *calldata) -{ - ScreenPtr screen = closure; - PropertyStateRec *rec = calldata; - struct xwl_screen *xwl_screen; - struct xwl_window *xwl_window; - - if (rec->win->drawable.pScreen != screen) - return; - - xwl_window = xwl_window_get(rec->win); - if (!xwl_window) - return; - - xwl_screen = xwl_screen_get(screen); - - if (rec->prop->propertyName == xwl_screen->allow_commits_prop) - xwl_window_update_property(xwl_window, rec); -} - -#define readOnlyPropertyAccessMask (DixReadAccess |\ - DixGetAttrAccess |\ - DixListPropAccess |\ - DixGetPropAccess) - -static void -xwl_access_property_callback(CallbackListPtr *pcbl, void *closure, - void *calldata) -{ - XacePropertyAccessRec *rec = calldata; - PropertyPtr prop = *rec->ppProp; - ClientPtr client = rec->client; - Mask access_mode = rec->access_mode; - ScreenPtr pScreen = closure; - struct xwl_screen *xwl_screen = xwl_screen_get(pScreen); - - if (prop->propertyName == xwl_screen->allow_commits_prop) { - /* Only the WM and the Xserver itself */ - if (client != serverClient && - client->index != xwl_screen->wm_client_id && - (access_mode & ~readOnlyPropertyAccessMask) != 0) - rec->status = BadAccess; - } -} - -#undef readOnlyPropertyAccessMask - -static void -xwl_root_window_finalized_callback(CallbackListPtr *pcbl, - void *closure, - void *calldata) -{ - ScreenPtr screen = closure; - struct xwl_screen *xwl_screen = xwl_screen_get(screen); - struct xwl_queued_drm_lease_device *queued_device, *next; - - xorg_list_for_each_entry_safe(queued_device, next, - &xwl_screen->queued_drm_lease_devices, link) { - xwl_screen_add_drm_lease_device(xwl_screen, queued_device->id); - xorg_list_del(&queued_device->link); - free(queued_device); - } - DeleteCallback(&RootWindowFinalizeCallback, xwl_root_window_finalized_callback, screen); -} - -static void xwl_close_screen(CallbackListPtr *pcbl, - ScreenPtr screen, void *unused) -{ - struct xwl_screen *xwl_screen = xwl_screen_get(screen); - struct xwl_output *xwl_output, *next_xwl_output; - struct xwl_seat *xwl_seat, *next_xwl_seat; - struct xwl_wl_surface *xwl_wl_surface, *xwl_wl_surface_next; -#ifdef XWL_HAS_GLAMOR - xwl_dmabuf_feedback_destroy(&xwl_screen->default_feedback); -#endif - dixScreenUnhookClose(screen, xwl_close_screen); - DeleteCallback(&PropertyStateCallback, xwl_property_callback, screen); - XaceDeleteCallback(XACE_PROPERTY_ACCESS, xwl_access_property_callback, screen); - - xorg_list_for_each_entry_safe(xwl_output, next_xwl_output, - &xwl_screen->output_list, link) - xwl_output_destroy(xwl_output); - - if (xwl_screen->fixed_output) - xwl_output_destroy(xwl_screen->fixed_output); - - xorg_list_for_each_entry_safe(xwl_seat, next_xwl_seat, - &xwl_screen->seat_list, link) - xwl_seat_destroy(xwl_seat); - - xwl_screen_release_tablet_manager(xwl_screen); - - struct xwl_drm_lease_device *device_data, *next; - xorg_list_for_each_entry_safe(device_data, next, - &xwl_screen->drm_lease_devices, link) - xwl_screen_destroy_drm_lease_device(xwl_screen, - device_data->drm_lease_device); - - xorg_list_for_each_entry_safe(xwl_wl_surface, xwl_wl_surface_next, - &xwl_screen->pending_wl_surface_destroy, link) - xwl_window_surface_do_destroy(xwl_wl_surface); - - RemoveNotifyFd(xwl_screen->wayland_fd); - - wl_display_disconnect(xwl_screen->display); - - free(xwl_screen); -} - -static struct xwl_seat * -xwl_screen_get_default_seat(struct xwl_screen *xwl_screen) -{ - if (xorg_list_is_empty(&xwl_screen->seat_list)) - return NULL; - - return container_of(xwl_screen->seat_list.prev, - struct xwl_seat, - link); -} - -static void -xwl_cursor_warped_to(DeviceIntPtr device, - ScreenPtr screen, - ClientPtr client, - WindowPtr window, - SpritePtr sprite, - int x, int y) -{ - struct xwl_screen *xwl_screen = xwl_screen_get(screen); - struct xwl_seat *xwl_seat = device->public.devicePrivate; - struct xwl_window *xwl_window; - WindowPtr focus; - - if (!xwl_seat) - xwl_seat = xwl_screen_get_default_seat(xwl_screen); - - if (!window) - window = XYToWindow(sprite, x, y); - - xwl_window = xwl_window_from_window(window); - - if (!xwl_window && xwl_seat && xwl_seat->focus_window) { - focus = xwl_seat->focus_window->toplevel; - - /* Warps on non wl_surface backed Windows are only allowed - * as long as the pointer stays within the focus window. - */ - if (x >= focus->drawable.x && - y >= focus->drawable.y && - x < focus->drawable.x + focus->drawable.width && - y < focus->drawable.y + focus->drawable.height) { - if (!window) { - DebugF("Warp relative to pointer, assuming pointer focus\n"); - xwl_window = xwl_seat->focus_window; - } else if (window == screen->root) { - DebugF("Warp on root window, assuming pointer focus\n"); - xwl_window = xwl_seat->focus_window; - } - } - } - if (!xwl_window) - return; - - xwl_seat_emulate_pointer_warp(xwl_seat, xwl_window, sprite, x, y); -} - -static void -xwl_set_shape(WindowPtr window, - int kind) -{ - ScreenPtr screen = window->drawable.pScreen; - struct xwl_screen *xwl_screen; - struct xwl_window *xwl_window; - - xwl_screen = xwl_screen_get(screen); - xwl_window = xwl_window_get(window); - - screen->SetShape = xwl_screen->SetShape; - (*screen->SetShape) (window, kind); - xwl_screen->SetShape = screen->SetShape; - screen->SetShape = xwl_set_shape; - - if (!xwl_window) - return; - - if (kind == ShapeInput) { - xwl_window_set_input_region(xwl_window, wInputShape(window)); - if (xwl_window->allow_commits) - wl_surface_commit(xwl_window->surface); - } -} - -static struct xwl_window * -find_matching_input_output_window(struct xwl_screen *xwl_screen, - WindowPtr window) -{ - struct xwl_window *xwl_window; - - xorg_list_for_each_entry(xwl_window, &xwl_screen->window_list, link_window) { - /* When confining happens on InputOnly windows, work out the InputOutput - * window that would be covered by its geometry. - */ - if (window->drawable.x < xwl_window->toplevel->drawable.x || - window->drawable.x + window->drawable.width > - xwl_window->toplevel->drawable.x + xwl_window->toplevel->drawable.width || - window->drawable.y < xwl_window->toplevel->drawable.y || - window->drawable.y + window->drawable.height > - xwl_window->toplevel->drawable.y + xwl_window->toplevel->drawable.height) - continue; - - if (xwl_window->toplevel->drawable.class == InputOnly) - continue; - - return xwl_window; - } - - return NULL; -} - -static void -xwl_cursor_confined_to(DeviceIntPtr device, - ScreenPtr screen, - WindowPtr window) -{ - struct xwl_screen *xwl_screen = xwl_screen_get(screen); - struct xwl_seat *xwl_seat = device->public.devicePrivate; - struct xwl_window *xwl_window; - - /* If running rootful with host grab requested, do not tamper with - * pointer confinement. - */ - if (!xwl_screen->rootless && xwl_screen->host_grab && xwl_screen->has_grab) - return; - - if (!xwl_seat) - xwl_seat = xwl_screen_get_default_seat(xwl_screen); - - /* xwl_seat hasn't been setup yet, don't do anything just yet */ - if (!xwl_seat) - return; - - if (window == screen->root) { - xwl_seat_unconfine_pointer(xwl_seat); - return; - } - - xwl_window = xwl_window_from_window(window); - if (!xwl_window && window->drawable.class == InputOnly) { - DebugF("Confine on InputOnly window, finding matching toplevel\n"); - xwl_window = find_matching_input_output_window(xwl_screen, window); - } - if (!xwl_window) - return; - - xwl_seat_confine_pointer(xwl_seat, xwl_window); -} - -void -xwl_screen_check_resolution_change_emulation(struct xwl_screen *xwl_screen) -{ - struct xwl_window *xwl_window; - - xorg_list_for_each_entry(xwl_window, &xwl_screen->window_list, link_window) - xwl_window_check_resolution_change_emulation(xwl_window); -} - -static void -xwl_screen_post_damage(struct xwl_screen *xwl_screen) -{ - struct xwl_window *xwl_window, *next_xwl_window; - struct xorg_list commit_window_list; - - xorg_list_init(&commit_window_list); - - xorg_list_for_each_entry_safe(xwl_window, next_xwl_window, - &xwl_screen->damage_window_list, link_damage) { - /* If we're waiting on a frame callback from the server, - * don't attach a new buffer. */ - if (xwl_window->frame_callback) - continue; - - if (!xwl_window->allow_commits) - continue; - - xwl_window_post_damage(xwl_window); - xorg_list_del(&xwl_window->link_damage); - xorg_list_append(&xwl_window->link_damage, &commit_window_list); - } - - if (xorg_list_is_empty(&commit_window_list)) - return; - -#ifdef XWL_HAS_GLAMOR - if (xwl_screen->glamor) - glamor_block_handler(xwl_screen->screen); -#endif - - xorg_list_for_each_entry_safe(xwl_window, next_xwl_window, - &commit_window_list, link_damage) { - wl_surface_commit(xwl_window->surface); - xorg_list_del(&xwl_window->link_damage); - } -} - -static void -xdg_wm_base_ping(void *data, struct xdg_wm_base *xdg_wm_base, - uint32_t serial) -{ - xdg_wm_base_pong(xdg_wm_base, serial); -} - -static const struct xdg_wm_base_listener xdg_wm_base_listener = { - xdg_wm_base_ping, -}; - -static void -registry_global(void *data, struct wl_registry *registry, uint32_t id, - const char *interface, uint32_t version) -{ - struct xwl_screen *xwl_screen = data; - - if (strcmp(interface, wl_compositor_interface.name) == 0) { - uint32_t request_version = 1; - - if (version >= WL_SURFACE_DAMAGE_BUFFER_SINCE_VERSION) - request_version = WL_SURFACE_DAMAGE_BUFFER_SINCE_VERSION; - - xwl_screen->compositor = - wl_registry_bind(registry, id, &wl_compositor_interface, request_version); - } - else if (strcmp(interface, wl_shm_interface.name) == 0) { - xwl_screen->shm = wl_registry_bind(registry, id, &wl_shm_interface, 1); - } - else if (strcmp(interface, xdg_wm_base_interface.name) == 0) { - xwl_screen->xdg_wm_base = - wl_registry_bind(registry, id, &xdg_wm_base_interface, 1); - xdg_wm_base_add_listener(xwl_screen->xdg_wm_base, - &xdg_wm_base_listener, - NULL); - } - else if (strcmp(interface, wl_output_interface.name) == 0 && version >= 2) { - if (xwl_output_create(xwl_screen, id, (xwl_screen->fixed_output == NULL), version)) - xwl_screen->expecting_event++; - } - else if (strcmp(interface, zxdg_output_manager_v1_interface.name) == 0) { - /* We support xdg-output from version 1 to version 3 */ - version = min(version, 3); - xwl_screen->xdg_output_manager = - wl_registry_bind(registry, id, &zxdg_output_manager_v1_interface, version); - xwl_screen_init_xdg_output(xwl_screen); - } - else if (strcmp(interface, wp_drm_lease_device_v1_interface.name) == 0) { - if (xwl_screen->screen->root == NULL) { - struct xwl_queued_drm_lease_device *queued = XNFcallocarray(1, sizeof(struct xwl_queued_drm_lease_device)); - queued->id = id; - xorg_list_append(&queued->link, &xwl_screen->queued_drm_lease_devices); - } else { - xwl_screen_add_drm_lease_device(xwl_screen, id); - } - } - else if (strcmp(interface, wp_viewporter_interface.name) == 0) { - xwl_screen->viewporter = wl_registry_bind(registry, id, &wp_viewporter_interface, 1); - } - else if (strcmp(interface, xwayland_shell_v1_interface.name) == 0 && xwl_screen->rootless) { - xwl_screen->xwayland_shell = - wl_registry_bind(registry, id, &xwayland_shell_v1_interface, 1); - } - else if (strcmp(interface, wp_tearing_control_manager_v1_interface.name) == 0) { - xwl_screen->tearing_control_manager = - wl_registry_bind(registry, id, &wp_tearing_control_manager_v1_interface, 1); - } - else if (strcmp(interface, wp_fractional_scale_manager_v1_interface.name) == 0) { - xwl_screen->fractional_scale_manager = - wl_registry_bind(registry, id, &wp_fractional_scale_manager_v1_interface, 1); - } -#ifdef XWL_HAS_GLAMOR - else if (xwl_screen->glamor) { - xwl_glamor_init_wl_registry(xwl_screen, registry, id, interface, - version); - } -#endif -} - -static void -global_remove(void *data, struct wl_registry *registry, uint32_t name) -{ - struct xwl_screen *xwl_screen = data; - struct xwl_output *xwl_output, *tmp_xwl_output; - struct xwl_drm_lease_device *lease_device, *tmp_lease_device; - - xorg_list_for_each_entry_safe(xwl_output, tmp_xwl_output, - &xwl_screen->output_list, link) { - if (xwl_output->server_output_id == name) { - xwl_output_remove(xwl_output); - break; - } - } - - xorg_list_for_each_entry_safe(lease_device, tmp_lease_device, - &xwl_screen->drm_lease_devices, link) { - if (lease_device->id == name) { - wp_drm_lease_device_v1_release(lease_device->drm_lease_device); - break; - } - } -} - -static const struct wl_registry_listener registry_listener = { - registry_global, - global_remove -}; - -static void -xwl_read_events (struct xwl_screen *xwl_screen) -{ - int ret; - - if (xwl_screen->wait_flush) - return; - - ret = wl_display_read_events(xwl_screen->display); - if (ret == -1) - xwl_give_up("failed to read Wayland events: %s\n", strerror(errno)); - - xwl_screen->prepare_read = 0; - - ret = wl_display_dispatch_pending(xwl_screen->display); - if (ret == -1) - xwl_give_up("failed to dispatch Wayland events: %s\n", strerror(errno)); -} - -static int -xwl_display_pollout (struct xwl_screen *xwl_screen, int timeout) -{ - struct pollfd poll_fd; - - poll_fd.fd = wl_display_get_fd(xwl_screen->display); - poll_fd.events = POLLOUT; - - return xserver_poll(&poll_fd, 1, timeout); -} - -#ifdef XWL_HAS_LIBDECOR -static void -xwl_dispatch_events_with_libdecor(struct xwl_screen *xwl_screen) -{ - int ret = 0; - - assert(!xwl_screen->rootless); - - ret = libdecor_dispatch(xwl_screen->libdecor_context, 0); - if (ret == -1) - xwl_give_up("failed to dispatch Wayland events with libdecor: %s\n", - strerror(errno)); -} - -static void -handle_libdecor_error(struct libdecor *context, - enum libdecor_error error, - const char *message) -{ - xwl_give_up("libdecor error (%d): %s\n", error, message); -} - -static struct libdecor_interface libdecor_iface = { - .error = handle_libdecor_error, -}; -#endif - -static void -xwl_dispatch_events (struct xwl_screen *xwl_screen) -{ - int ret = 0; - int ready; - - if (xwl_screen->wait_flush) - goto pollout; - - while (xwl_screen->prepare_read == 0 && - wl_display_prepare_read(xwl_screen->display) == -1) { - ret = wl_display_dispatch_pending(xwl_screen->display); - if (ret == -1) - xwl_give_up("failed to dispatch Wayland events: %s\n", - strerror(errno)); - } - - xwl_screen->prepare_read = 1; - -pollout: - ready = xwl_display_pollout(xwl_screen, 5); - if (ready == -1 && errno != EINTR) - xwl_give_up("error polling on Xwayland fd: %s\n", strerror(errno)); - - if (ready > 0) - ret = wl_display_flush(xwl_screen->display); - - if (ret == -1 && errno != EAGAIN) - xwl_give_up("failed to write to Xwayland fd: %s\n", strerror(errno)); - - xwl_screen->wait_flush = (ready == 0 || ready == -1 || ret == -1); -} - -static void -socket_handler(int fd, int ready, void *data) -{ - struct xwl_screen *xwl_screen = data; - -#ifdef XWL_HAS_LIBDECOR - if (xwl_screen->libdecor_context) { - xwl_dispatch_events_with_libdecor(xwl_screen); - return; - } -#endif - xwl_read_events (xwl_screen); -} - -static void -wakeup_handler(void *data, int err) -{ -} - -static void -block_handler(void *data, void *timeout) -{ - struct xwl_screen *xwl_screen = data; - - xwl_screen_post_damage(xwl_screen); -#ifdef XWL_HAS_LIBDECOR - if (xwl_screen->libdecor_context) { - xwl_dispatch_events_with_libdecor(xwl_screen); - return; - } -#endif - xwl_dispatch_events (xwl_screen); -} - -void -xwl_sync_events (struct xwl_screen *xwl_screen) -{ -#ifdef XWL_HAS_LIBDECOR - if (xwl_screen->libdecor_context) { - xwl_dispatch_events_with_libdecor(xwl_screen); - return; - } -#endif - xwl_dispatch_events (xwl_screen); - xwl_read_events (xwl_screen); -} - -void xwl_surface_damage(struct xwl_screen *xwl_screen, - struct wl_surface *surface, - int32_t x, int32_t y, int32_t width, int32_t height) -{ - if (wl_surface_get_version(surface) >= WL_SURFACE_DAMAGE_BUFFER_SINCE_VERSION) - wl_surface_damage_buffer(surface, x, y, width, height); - else - wl_surface_damage(surface, x, y, width, height); -} - -void -xwl_screen_roundtrip(struct xwl_screen *xwl_screen) -{ - int ret; - - do { - ret = wl_display_roundtrip(xwl_screen->display); - } while (ret >= 0 && xwl_screen->expecting_event); - - if (ret < 0) - xwl_give_up("could not connect to wayland server\n"); -} - -static int -xwl_server_grab(ClientPtr client) -{ - struct xwl_screen *xwl_screen; - - /* Allow GrabServer for the X11 window manager. - * Xwayland only has 1 screen (no Zaphod for Xwayland) so we check - * for the first and only screen here. - */ - xwl_screen = xwl_screen_get(screenInfo.screens[0]); - if (xwl_screen->wm_client_id == client->index) - return xwl_screen->GrabServer(client); - - /* For all other clients, just pretend it works for compatibility, - but do nothing */ - return Success; -} - -static int -xwl_server_ungrab(ClientPtr client) -{ - struct xwl_screen *xwl_screen; - - /* Same as above, allow UngrabServer for the X11 window manager only */ - xwl_screen = xwl_screen_get(screenInfo.screens[0]); - if (xwl_screen->wm_client_id == client->index) - return xwl_screen->UngrabServer(client); - - /* For all other clients, just pretend it works for compatibility, - but do nothing */ - return Success; -} - -static void -xwl_screen_setup_custom_vector(struct xwl_screen *xwl_screen) -{ - /* Rootfull Xwayland does not need a custom ProcVector (yet?) */ - if (!xwl_screen->rootless) - return; - - xwl_screen->GrabServer = ProcVector[X_GrabServer]; - xwl_screen->UngrabServer = ProcVector[X_UngrabServer]; - - ProcVector[X_GrabServer] = xwl_server_grab; - ProcVector[X_UngrabServer] = xwl_server_ungrab; -} - -int -xwl_screen_get_next_output_serial(struct xwl_screen *xwl_screen) -{ - return xwl_screen->output_name_serial++; -} - -void -xwl_screen_lost_focus(struct xwl_screen *xwl_screen) -{ - struct xwl_seat *xwl_seat; - - xorg_list_for_each_entry(xwl_seat, &xwl_screen->seat_list, link) { - xwl_seat_leave_ptr(xwl_seat, TRUE); - xwl_seat_leave_kbd(xwl_seat); - } -} - -Bool -xwl_screen_should_use_fractional_scale(struct xwl_screen *xwl_screen) -{ - /* Fullscreen uses a viewport already */ - if (xwl_screen->fullscreen) - return FALSE; - - if (xwl_screen->rootless) - return FALSE; - - /* We need both fractional scale and viewporter protocols */ - if (!xwl_screen->fractional_scale_manager) - return FALSE; - - if (!xwl_screen->viewporter) - return FALSE; - - return xwl_screen->hidpi; -} - -Bool -xwl_screen_update_global_surface_scale(struct xwl_screen *xwl_screen) -{ - ScreenPtr screen = xwl_screen->screen; - struct xwl_window *xwl_window; - int32_t old_scale; - - if (xwl_screen_should_use_fractional_scale(xwl_screen)) - return FALSE; - - if (xwl_screen->rootless) - return FALSE; - - if (xwl_screen->fullscreen) - return FALSE; - - if (!xwl_screen->hidpi) - return FALSE; - - if (screen->root == NullWindow) - return FALSE; - - xwl_window = xwl_window_get(screen->root); - if (!xwl_window) - return FALSE; - - old_scale = xwl_screen->global_surface_scale; - xwl_screen->global_surface_scale = xwl_window_get_max_output_scale(xwl_window); - - return (xwl_screen->global_surface_scale != old_scale); -} - -Bool -xwl_screen_init(ScreenPtr pScreen, int argc, char **argv) -{ - static const char allow_commits[] = "_XWAYLAND_ALLOW_COMMITS"; - struct xwl_screen *xwl_screen; - Pixel red_mask, blue_mask, green_mask; - int ret, bpc, green_bpc, i; - unsigned int xwl_width = 640; - unsigned int xwl_height = 480; - Bool use_fixed_size = FALSE; - - if (!dixRegisterPrivateKey(&xwl_screen_private_key, PRIVATE_SCREEN, 0)) - return FALSE; - if (!xwl_pixmap_init()) - return FALSE; - if (!xwl_window_init()) - return FALSE; - /* There are no easy to use new / delete client hooks, we could use a - * ClientStateCallback, but it is easier to let the dix code manage the - * memory for us. This will zero fill the initial xwl_client data. - */ - if (!dixRegisterPrivateKey(&xwl_client_private_key, PRIVATE_CLIENT, - sizeof(struct xwl_client))) - return FALSE; - - xwl_screen = calloc(1, sizeof *xwl_screen); - if (xwl_screen == NULL) - return FALSE; - - dixSetPrivate(&pScreen->devPrivates, &xwl_screen_private_key, xwl_screen); - xwl_screen->screen = pScreen; - -#ifdef XWL_HAS_EI - if (!xwayland_ei_init()) - return FALSE; -#endif - -#ifdef XWL_HAS_GLAMOR - xwl_screen->glamor = XWL_GLAMOR_DEFAULT; -#endif - - for (i = 1; i < argc; i++) { - if (strcmp(argv[i], "-rootless") == 0) { - xwl_screen->rootless = 1; - - /* Disable the XSS extension on Xwayland rootless. - * - * Xwayland is just a Wayland client, no X11 screensaver - * should be expected to work reliably on Xwayland rootless. - */ -#ifdef SCREENSAVER - noScreenSaverExtension = TRUE; -#endif - ScreenSaverTime = 0; - ScreenSaverInterval = 0; - defaultScreenSaverTime = 0; - defaultScreenSaverInterval = 0; - } - else if (strcmp(argv[i], "-shm") == 0) { - xwl_screen->glamor = XWL_GLAMOR_NONE; - } -#ifdef XWL_HAS_GLAMOR - else if (strcmp(argv[i], "-glamor") == 0) { - if (strncmp(argv[i + 1], "es", 2) == 0) - xwl_screen->glamor = XWL_GLAMOR_GLES; - else if (strncmp(argv[i + 1], "gl", 2) == 0) - xwl_screen->glamor = XWL_GLAMOR_GL; - else if (strncmp(argv[i + 1], "off", 3) == 0) - xwl_screen->glamor = XWL_GLAMOR_NONE; - else - ErrorF("Xwayland glamor: unknown rendering API selected\n"); - } -#endif - else if (strcmp(argv[i], "-force-xrandr-emulation") == 0) { - xwl_screen->force_xrandr_emulation = 1; - } - else if (strcmp(argv[i], "-geometry") == 0) { - sscanf(argv[i + 1], "%ix%i", &xwl_width, &xwl_height); - if (xwl_width == 0 || xwl_height == 0) { - ErrorF("invalid argument for -geometry %s\n", argv[i + 1]); - return FALSE; - } - use_fixed_size = 1; - } - else if (strcmp(argv[i], "-fullscreen") == 0) { - use_fixed_size = 1; - xwl_screen->fullscreen = 1; - } - else if (strcmp(argv[i], "-output") == 0) { - xwl_screen->output_name = argv[i + 1]; - } - else if (strcmp(argv[i], "-host-grab") == 0) { - xwl_screen->host_grab = 1; - xwl_screen->has_grab = 1; - } - else if (strcmp(argv[i], "-decorate") == 0) { -#ifdef XWL_HAS_LIBDECOR - xwl_screen->decorate = 1; - use_fixed_size = 1; -#else - ErrorF("This build does not have libdecor support\n"); -#endif - } - else if (strcmp(argv[i], "-enable-ei-portal") == 0) { -#ifdef XWL_HAS_EI_PORTAL - xwl_screen->enable_ei_portal = 1; -#else - ErrorF("This build does not have XDG portal support\n"); -#endif - } - else if (strcmp(argv[i], "-nokeymap") == 0) { - xwl_screen->nokeymap = 1; - } - else if (strcmp(argv[i], "-hidpi") == 0) { - xwl_screen->hidpi = 1; - } - } - - if (!xwl_screen->rootless) { - use_fixed_size = 1; - xwl_screen->width = xwl_width; - xwl_screen->height = xwl_height; - } else if (use_fixed_size) { - ErrorF("error, cannot set a geometry when running rootless\n"); - return FALSE; - } - - xwl_screen->display = wl_display_connect(NULL); - if (xwl_screen->display == NULL) { - ErrorF("could not connect to wayland server\n"); - return FALSE; - } - -#ifdef XWL_HAS_GLAMOR - if (xwl_screen->glamor && !xwl_glamor_init_gbm(xwl_screen)) { - ErrorF("xwayland glamor: failed to setup GBM backend, falling back to sw accel\n"); - xwl_screen->glamor = 0; - } -#endif - - /* In rootless mode, we don't have any screen storage, and the only - * rendering should be to redirected mode. */ - if (xwl_screen->rootless) - xwl_screen->root_clip_mode = ROOT_CLIP_INPUT_ONLY; - else - xwl_screen->root_clip_mode = ROOT_CLIP_FULL; - - xorg_list_init(&xwl_screen->output_list); - xorg_list_init(&xwl_screen->seat_list); - xorg_list_init(&xwl_screen->damage_window_list); - xorg_list_init(&xwl_screen->window_list); - xorg_list_init(&xwl_screen->drm_lease_devices); - xorg_list_init(&xwl_screen->queued_drm_lease_devices); - xorg_list_init(&xwl_screen->drm_leases); - xorg_list_init(&xwl_screen->pending_wl_surface_destroy); - xwl_screen->depth = 24; - xwl_screen->global_surface_scale = 1; - - if (!monitorResolution) - monitorResolution = DEFAULT_DPI; - - if (use_fixed_size) { - if (!xwl_screen_init_randr_fixed(xwl_screen)) - return FALSE; - } else { - if (!xwl_screen_init_output(xwl_screen)) - return FALSE; - } - - xwl_screen->expecting_event = 0; - xwl_screen->registry = wl_display_get_registry(xwl_screen->display); - wl_registry_add_listener(xwl_screen->registry, - ®istry_listener, xwl_screen); - xwl_screen_roundtrip(xwl_screen); - - - if (xwl_screen->fullscreen && xwl_screen->rootless) { - ErrorF("error, cannot set fullscreen when running rootless\n"); - return FALSE; - } - - if (xwl_screen->fullscreen && xwl_screen->decorate) { - ErrorF("error, cannot use the decorate option when running fullscreen\n"); - return FALSE; - } - - if (xwl_screen->fullscreen && !xwl_screen_has_viewport_support(xwl_screen)) { - ErrorF("missing viewport support in the compositor, ignoring fullscreen\n"); - xwl_screen->fullscreen = FALSE; - } - - if (xwl_screen->host_grab && xwl_screen->rootless) { - ErrorF("error, cannot use host grab when running rootless\n"); - return FALSE; - } - - if (!xwl_screen->rootless && !xwl_screen->xdg_wm_base) { - ErrorF("missing XDG-WM-Base protocol\n"); - return FALSE; - } - - bpc = xwl_screen->depth / 3; - green_bpc = xwl_screen->depth - 2 * bpc; - blue_mask = (1 << bpc) - 1; - green_mask = ((1 << green_bpc) - 1) << bpc; - red_mask = blue_mask << (green_bpc + bpc); - - miSetVisualTypesAndMasks(xwl_screen->depth, - ((1 << TrueColor) | (1 << DirectColor)), - green_bpc, TrueColor, - red_mask, green_mask, blue_mask); - - miSetPixmapDepths(); - - ret = fbScreenInit(pScreen, NULL, - xwl_screen_get_width(xwl_screen), - xwl_screen_get_height(xwl_screen), - monitorResolution, monitorResolution, 0, - BitsPerPixel(xwl_screen->depth)); - if (!ret) - return FALSE; - - fbPictureInit(pScreen, 0, 0); - -#ifdef MITSHM - ShmRegisterFbFuncs(pScreen); -#endif - -#ifdef HAVE_XSHMFENCE - if (!miSyncShmScreenInit(pScreen)) - return FALSE; -#endif - -#ifdef XWL_HAS_LIBDECOR - if (xwl_screen->decorate && !xwl_screen->rootless) { - xwl_screen->libdecor_context = libdecor_new(xwl_screen->display, &libdecor_iface); - xwl_screen->wayland_fd = libdecor_get_fd(xwl_screen->libdecor_context); - } - else -#endif - { - xwl_screen->wayland_fd = wl_display_get_fd(xwl_screen->display); - } - SetNotifyFd(xwl_screen->wayland_fd, socket_handler, X_NOTIFY_READ, xwl_screen); - RegisterBlockAndWakeupHandlers(block_handler, wakeup_handler, xwl_screen); - - pScreen->blackPixel = 0; - pScreen->whitePixel = 1; - - ret = fbCreateDefColormap(pScreen); - - if (!xwl_screen_init_cursor(xwl_screen)) - return FALSE; - -#ifdef XWL_HAS_GLAMOR - if (xwl_screen->glamor && !xwl_glamor_init(xwl_screen)) { - ErrorF("Failed to initialize glamor, falling back to sw\n"); - xwl_screen->glamor = XWL_GLAMOR_NONE; - } -#endif - - xwl_screen->present = xwl_present_init(pScreen); - - if (!xwl_screen->glamor) { - pScreen->CreateScreenResources = xwl_shm_create_screen_resources; - pScreen->CreatePixmap = xwl_shm_create_pixmap; - pScreen->DestroyPixmap = xwl_shm_destroy_pixmap; - } - - xwl_screen->RealizeWindow = pScreen->RealizeWindow; - pScreen->RealizeWindow = xwl_realize_window; - - xwl_screen->UnrealizeWindow = pScreen->UnrealizeWindow; - pScreen->UnrealizeWindow = xwl_unrealize_window; - - dixScreenHookWindowDestroy(pScreen, xwl_window_destroy); - dixScreenHookClose(pScreen, xwl_close_screen); - - xwl_screen->ChangeWindowAttributes = pScreen->ChangeWindowAttributes; - pScreen->ChangeWindowAttributes = xwl_change_window_attributes; - - xwl_screen->ClipNotify = pScreen->ClipNotify; - pScreen->ClipNotify = xwl_clip_notify; - - xwl_screen->ConfigNotify = pScreen->ConfigNotify; - pScreen->ConfigNotify = xwl_config_notify; - - xwl_screen->ResizeWindow = pScreen->ResizeWindow; - pScreen->ResizeWindow = xwl_resize_window; - - xwl_screen->MoveWindow = pScreen->MoveWindow; - pScreen->MoveWindow = xwl_move_window; - - xwl_screen->SetWindowPixmap = pScreen->SetWindowPixmap; - pScreen->SetWindowPixmap = xwl_window_set_window_pixmap; - - xwl_screen->SetShape = pScreen->SetShape; - pScreen->SetShape = xwl_set_shape; - - pScreen->CursorWarpedTo = xwl_cursor_warped_to; - pScreen->CursorConfinedTo = xwl_cursor_confined_to; - - xwl_screen->allow_commits_prop = MakeAtom(allow_commits, - strlen(allow_commits), - TRUE); - if (xwl_screen->allow_commits_prop == BAD_RESOURCE) - return FALSE; - - AddCallback(&PropertyStateCallback, xwl_property_callback, pScreen); - AddCallback(&RootWindowFinalizeCallback, xwl_root_window_finalized_callback, pScreen); - XaceRegisterCallback(XACE_PROPERTY_ACCESS, xwl_access_property_callback, pScreen); - - xwl_screen_setup_custom_vector(xwl_screen); - - xwl_screen_roundtrip(xwl_screen); - - return ret; -} diff --git a/hw/xwayland/xwayland-screen.h b/hw/xwayland/xwayland-screen.h deleted file mode 100644 index 6584c66e3..000000000 --- a/hw/xwayland/xwayland-screen.h +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Copyright © 2011-2014 Intel Corporation - * - * Permission to use, copy, modify, distribute, and sell this software - * and its documentation for any purpose is hereby granted without - * fee, provided that the above copyright notice appear in all copies - * and that both that copyright notice and this permission notice - * appear in supporting documentation, and that the name of the - * copyright holders not be used in advertising or publicity - * pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied - * warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS - * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. - */ - -#ifndef XWAYLAND_SCREEN_H -#define XWAYLAND_SCREEN_H - -#include - -#include -#include -#include -#include - -#include "xwayland-types.h" -#include "xwayland-window.h" -#include "xwayland-output.h" -#include "xwayland-glamor.h" -#include "xwayland-drm-lease.h" -#include "xwayland-dmabuf.h" - -#ifdef XWL_HAS_LIBDECOR -#include -#endif - -struct xwl_screen { - double width; - double height; - int depth; - int global_surface_scale; - int output_name_serial; - ScreenPtr screen; - int wm_client_id; - int expecting_event; - enum RootClipMode root_clip_mode; - - Bool active; - int rootless; - xwl_glamor_mode_flags glamor; - int present; - int force_xrandr_emulation; - int fullscreen; - int host_grab; - int has_grab; - int decorate; - int enable_ei_portal; - int nokeymap; - int hidpi; - - ClipNotifyProcPtr ClipNotify; - CloseScreenProcPtr CloseScreen; - ConfigNotifyProcPtr ConfigNotify; - RealizeWindowProcPtr RealizeWindow; - UnrealizeWindowProcPtr UnrealizeWindow; - XYToWindowProcPtr XYToWindow; - SetWindowPixmapProcPtr SetWindowPixmap; - ChangeWindowAttributesProcPtr ChangeWindowAttributes; - ResizeWindowProcPtr ResizeWindow; - MoveWindowProcPtr MoveWindow; - SourceValidateProcPtr SourceValidate; - SetShapeProcPtr SetShape; - - int (*GrabServer) (ClientPtr client); - int (*UngrabServer) (ClientPtr client); - - struct xorg_list output_list; - struct xorg_list seat_list; - struct xorg_list damage_window_list; - struct xorg_list window_list; - Bool ignore_damage; - - int need_source_validate; - - int wayland_fd; - struct wl_display *display; - struct wl_registry *registry; - struct wl_registry *input_registry; - struct wl_compositor *compositor; - struct zwp_tablet_manager_v2 *tablet_manager; - struct wl_shm *shm; - struct xdg_wm_base *xdg_wm_base; - struct zwp_relative_pointer_manager_v1 *relative_pointer_manager; - struct zwp_pointer_constraints_v1 *pointer_constraints; - struct zwp_pointer_gestures_v1 *pointer_gestures; - struct zwp_xwayland_keyboard_grab_manager_v1 *wp_grab; - struct zwp_keyboard_shortcuts_inhibit_manager_v1 *shortcuts_inhibit_manager; - struct zwp_keyboard_shortcuts_inhibitor_v1 *shortcuts_inhibit; - struct zwp_linux_dmabuf_v1 *dmabuf; - int dmabuf_protocol_version; - struct xwl_dmabuf_feedback default_feedback; - struct zxdg_output_manager_v1 *xdg_output_manager; - struct wp_viewporter *viewporter; - struct xwayland_shell_v1 *xwayland_shell; - struct wp_tearing_control_manager_v1 *tearing_control_manager; - struct wp_fractional_scale_manager_v1 *fractional_scale_manager; - struct wp_linux_drm_syncobj_manager_v1 *explicit_sync; - struct xdg_system_bell_v1 *system_bell; - struct xorg_list drm_lease_devices; - struct xorg_list queued_drm_lease_devices; - struct xorg_list drm_leases; - struct xwl_output *fixed_output; - struct xorg_list pending_wl_surface_destroy; - uint64_t surface_association_serial; - uint32_t serial; - -#define XWL_FORMAT_ARGB8888 (1 << 0) -#define XWL_FORMAT_XRGB8888 (1 << 1) -#define XWL_FORMAT_RGB565 (1 << 2) - - int prepare_read; - int wait_flush; - - uint32_t num_formats; - struct xwl_format *formats; - void *egl_display, *egl_context; - - struct glamor_context *glamor_ctx; - - Atom allow_commits_prop; - - /* The preferred GLVND vendor. If NULL, "mesa" is assumed. */ - const char *glvnd_vendor; -#ifdef XWL_HAS_LIBDECOR - int libdecor_fd; - struct libdecor *libdecor_context; -#endif - const char *output_name; - - uint32_t present_capabilities; -}; - -/* Apps which use randr/vidmode to change the mode when going fullscreen, - * usually change the mode of only a single monitor, so this should be plenty. - */ -#define XWL_CLIENT_MAX_EMULATED_MODES 16 - -struct xwl_client { - struct xwl_emulated_mode emulated_modes[XWL_CLIENT_MAX_EMULATED_MODES]; -}; - -struct xwl_client *xwl_client_get(ClientPtr client); -struct xwl_screen *xwl_screen_get(ScreenPtr screen); -Bool xwl_screen_has_viewport_support(struct xwl_screen *xwl_screen); -Bool xwl_screen_has_resolution_change_emulation(struct xwl_screen *xwl_screen); -void xwl_screen_check_resolution_change_emulation(struct xwl_screen *xwl_screen); -struct xwl_output *xwl_screen_get_first_output(struct xwl_screen *xwl_screen); -struct xwl_output *xwl_screen_get_fixed_or_first_output(struct xwl_screen *xwl_screen); -int xwl_screen_get_width(struct xwl_screen *xwl_screen); -int xwl_screen_get_height(struct xwl_screen *xwl_screen); - -Bool xwl_screen_init(ScreenPtr pScreen, int argc, char **argv); -void xwl_sync_events (struct xwl_screen *xwl_screen); -void xwl_screen_roundtrip (struct xwl_screen *xwl_screen); -void xwl_surface_damage(struct xwl_screen *xwl_screen, - struct wl_surface *surface, - int32_t x, int32_t y, int32_t width, int32_t height); -int xwl_screen_get_next_output_serial(struct xwl_screen * xwl_screen); -void xwl_screen_lost_focus(struct xwl_screen *xwl_screen); -Bool xwl_screen_update_global_surface_scale(struct xwl_screen *xwl_screen); -Bool xwl_screen_should_use_fractional_scale(struct xwl_screen *xwl_screen); - -#endif /* XWAYLAND_SCREEN_H */ diff --git a/hw/xwayland/xwayland-shm.c b/hw/xwayland/xwayland-shm.c deleted file mode 100644 index 77dc560f0..000000000 --- a/hw/xwayland/xwayland-shm.c +++ /dev/null @@ -1,370 +0,0 @@ -/* - * Copyright © 2014 Intel Corporation - * Copyright © 2012 Collabora, Ltd. - * - * Permission to use, copy, modify, distribute, and sell this software - * and its documentation for any purpose is hereby granted without - * fee, provided that the above copyright notice appear in all copies - * and that both that copyright notice and this permission notice - * appear in supporting documentation, and that the name of the - * copyright holders not be used in advertising or publicity - * pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied - * warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS - * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. - */ - -#include - -#include "os.h" - -#include -#include -#include -#include -#include -#include -#include - -#include "mi/mi_priv.h" -#include "os/osdep.h" - -#include "fb.h" -#include "pixmapstr.h" - -#include "xwayland-pixmap.h" -#include "xwayland-screen.h" -#include "xwayland-shm.h" - -struct xwl_pixmap { - struct wl_buffer *buffer; - void *data; - size_t size; -}; - -#ifndef HAVE_MKOSTEMP -static int -set_cloexec_or_close(int fd) -{ - long flags; - - if (fd == -1) - return -1; - - flags = fcntl(fd, F_GETFD); - if (flags == -1) - goto err; - - if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1) - goto err; - - return fd; - - err: - close(fd); - return -1; -} -#endif - -static int -create_tmpfile_cloexec(char *tmpname) -{ - int fd; - -#ifdef HAVE_MKOSTEMP - fd = mkostemp(tmpname, O_CLOEXEC); - if (fd >= 0) - unlink(tmpname); -#else - fd = mkstemp(tmpname); - if (fd >= 0) { - fd = set_cloexec_or_close(fd); - unlink(tmpname); - } -#endif - - return os_move_fd(fd); -} - -/* - * Create a new, unique, anonymous file of the given size, and - * return the file descriptor for it. The file descriptor is set - * CLOEXEC. The file is immediately suitable for mmap()'ing - * the given size at offset zero. - * - * The file should not have a permanent backing store like a disk, - * but may have if XDG_RUNTIME_DIR is not properly implemented in OS. - * - * The file name is deleted from the file system. - * - * The file is suitable for buffer sharing between processes by - * transmitting the file descriptor over Unix sockets using the - * SCM_RIGHTS methods. - * - * If the C library implements posix_fallocate(), it is used to - * guarantee that disk space is available for the file at the - * given size. If disk space is insufficient, errno is set to ENOSPC. - * If posix_fallocate() is not supported, program may receive - * SIGBUS on accessing mmap()'ed file contents instead. - * - * If the C library implements memfd_create(), it is used to create the - * file purely in memory, without any backing file name on the file - * system, and then sealing off the possibility of shrinking it. This - * can then be checked before accessing mmap()'ed file contents, to - * make sure SIGBUS can't happen. It also avoids requiring - * XDG_RUNTIME_DIR. - */ -static int -os_create_anonymous_file(off_t size) -{ - static const char template[] = "/xwayland-shared-XXXXXX"; - const char *path; - int fd; - int ret; - -#ifdef HAVE_MEMFD_CREATE - fd = memfd_create("xwayland-shared", MFD_CLOEXEC | MFD_ALLOW_SEALING); - if (fd >= 0) { - /* We can add this seal before calling posix_fallocate(), as - * the file is currently zero-sized anyway. - * - * There is also no need to check for the return value, we - * couldn't do anything with it anyway. - */ - fcntl(fd, F_ADD_SEALS, F_SEAL_SHRINK); - } else -#endif - { - path = getenv("XDG_RUNTIME_DIR"); - if (!path) { - errno = ENOENT; - return -1; - } - - char *name = calloc(1, strlen(path) + sizeof(template)); - if (!name) - return -1; - - strcpy(name, path); - strcat(name, template); - - fd = create_tmpfile_cloexec(name); - - free(name); - - if (fd < 0) - return -1; - } - -#ifdef HAVE_POSIX_FALLOCATE - /* - * posix_fallocate does an explicit rollback if it gets EINTR. - * Temporarily block signals to allow the call to succeed on - * slow systems where the smart scheduler's SIGALRM prevents - * large allocation attempts from ever succeeding. - */ - OsBlockSignals(); - do { - ret = posix_fallocate(fd, 0, size); - } while (ret == EINTR); - OsReleaseSignals(); - - if (ret != 0) { - close(fd); - errno = ret; - return -1; - } -#else - do { - ret = ftruncate(fd, size); - } while (ret == -1 && errno == EINTR); - - if (ret < 0) { - close(fd); - return -1; - } -#endif - - return fd; -} - -static uint32_t -shm_format_for_depth(int depth) -{ - switch (depth) { - case 32: - return WL_SHM_FORMAT_ARGB8888; - case 24: - default: - return WL_SHM_FORMAT_XRGB8888; -#ifdef WL_SHM_FORMAT_RGB565 - case 16: - /* XXX: Check run-time protocol version too */ - return WL_SHM_FORMAT_RGB565; -#endif - } -} - -static Bool -dimensions_match_toplevel_window(ScreenPtr screen, int width, int height) -{ - struct xwl_screen *xwl_screen = xwl_screen_get(screen); - WindowPtr toplevel; - - if (xwl_screen->rootless) - toplevel = screen->root->firstChild; - else - toplevel = screen->root; - - while (toplevel) { - if (width == toplevel->drawable.width && - height == toplevel->drawable.height) - return TRUE; - - toplevel = toplevel->nextSib; - } - - return FALSE; -} - -static const struct wl_buffer_listener xwl_shm_buffer_listener = { - xwl_pixmap_buffer_release_cb, -}; - -PixmapPtr -xwl_shm_create_pixmap(ScreenPtr screen, - int width, int height, int depth, unsigned int hint) -{ - struct xwl_screen *xwl_screen = xwl_screen_get(screen); - struct xwl_pixmap *xwl_pixmap; - struct wl_shm_pool *pool; - PixmapPtr pixmap; - size_t size, stride; - uint32_t format; - int fd; - - if (hint == CREATE_PIXMAP_USAGE_GLYPH_PICTURE || - (width == 0 && height == 0) || depth < 15 || - (hint != CREATE_PIXMAP_USAGE_BACKING_PIXMAP && - !dimensions_match_toplevel_window(screen, width, height))) - return fbCreatePixmap(screen, width, height, depth, hint); - - stride = PixmapBytePad(width, depth); - size = stride * height; - /* Size in the protocol is an integer, make sure we don't exceed - * INT32_MAX or else the Wayland compositor will raise an error and - * kill the Wayland connection! - */ - if (size > INT32_MAX) - return NULL; - - pixmap = fbCreatePixmap(screen, 0, 0, depth, hint); - if (!pixmap) - return NULL; - - xwl_pixmap = calloc(1, sizeof(*xwl_pixmap)); - if (xwl_pixmap == NULL) - goto err_destroy_pixmap; - - xwl_pixmap->buffer = NULL; - xwl_pixmap->size = size; - fd = os_create_anonymous_file(size); - if (fd < 0) - goto err_free_xwl_pixmap; - - xwl_pixmap->data = mmap(NULL, size, PROT_READ | PROT_WRITE, - MAP_SHARED, fd, 0); - if (xwl_pixmap->data == MAP_FAILED) - goto err_close_fd; - - if (!(*screen->ModifyPixmapHeader) (pixmap, width, height, depth, - BitsPerPixel(depth), - stride, xwl_pixmap->data)) - goto err_munmap; - - format = shm_format_for_depth(pixmap->drawable.depth); - pool = wl_shm_create_pool(xwl_screen->shm, fd, xwl_pixmap->size); - xwl_pixmap->buffer = wl_shm_pool_create_buffer(pool, 0, - pixmap->drawable.width, - pixmap->drawable.height, - pixmap->devKind, format); - wl_shm_pool_destroy(pool); - close(fd); - - wl_buffer_add_listener(xwl_pixmap->buffer, - &xwl_shm_buffer_listener, pixmap); - - xwl_pixmap_set_private(pixmap, xwl_pixmap); - - return pixmap; - - err_munmap: - munmap(xwl_pixmap->data, size); - err_close_fd: - close(fd); - err_free_xwl_pixmap: - free(xwl_pixmap); - err_destroy_pixmap: - fbDestroyPixmap(pixmap); - - return NULL; -} - -Bool -xwl_shm_destroy_pixmap(PixmapPtr pixmap) -{ - struct xwl_pixmap *xwl_pixmap = xwl_pixmap_get(pixmap); - - if (xwl_pixmap && pixmap->refcnt == 1) { - xwl_pixmap_del_buffer_release_cb(pixmap); - if (xwl_pixmap->buffer) - wl_buffer_destroy(xwl_pixmap->buffer); - munmap(xwl_pixmap->data, xwl_pixmap->size); - free(xwl_pixmap); - } - - return fbDestroyPixmap(pixmap); -} - -struct wl_buffer * -xwl_shm_pixmap_get_wl_buffer(PixmapPtr pixmap) -{ - struct xwl_pixmap *xwl_pixmap = xwl_pixmap_get(pixmap); - - if (!xwl_pixmap) - return NULL; - - return xwl_pixmap->buffer; -} - -Bool -xwl_shm_create_screen_resources(ScreenPtr screen) -{ - struct xwl_screen *xwl_screen = xwl_screen_get(screen); - - if (!miCreateScreenResources(screen)) - return FALSE; - - if (xwl_screen->rootless) - screen->devPrivate = - fbCreatePixmap(screen, 0, 0, screen->rootDepth, 0); - else - screen->devPrivate = - xwl_shm_create_pixmap(screen, screen->width, screen->height, - screen->rootDepth, - CREATE_PIXMAP_USAGE_BACKING_PIXMAP); - - SetRootClip(screen, xwl_screen->root_clip_mode); - - return screen->devPrivate != NULL; -} diff --git a/hw/xwayland/xwayland-shm.h b/hw/xwayland/xwayland-shm.h deleted file mode 100644 index 3c94000b6..000000000 --- a/hw/xwayland/xwayland-shm.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright © 2014 Intel Corporation - * Copyright © 2012 Collabora, Ltd. - * - * Permission to use, copy, modify, distribute, and sell this software - * and its documentation for any purpose is hereby granted without - * fee, provided that the above copyright notice appear in all copies - * and that both that copyright notice and this permission notice - * appear in supporting documentation, and that the name of the - * copyright holders not be used in advertising or publicity - * pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied - * warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS - * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. - */ - -#ifndef XWAYLAND_SHM_H -#define XWAYLAND_SHM_H - -#include - -#include "scrnintstr.h" -#include "pixmapstr.h" - -Bool xwl_shm_create_screen_resources(ScreenPtr screen); -PixmapPtr xwl_shm_create_pixmap(ScreenPtr screen, int width, int height, - int depth, unsigned int hint); -Bool xwl_shm_destroy_pixmap(PixmapPtr pixmap); -struct wl_buffer *xwl_shm_pixmap_get_wl_buffer(PixmapPtr pixmap); - -#endif /* XWAYLAND_SHM_H */ diff --git a/hw/xwayland/xwayland-types.h b/hw/xwayland/xwayland-types.h deleted file mode 100644 index d3fd2a0fc..000000000 --- a/hw/xwayland/xwayland-types.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright © 2014 Intel Corporation - * - * Permission to use, copy, modify, distribute, and sell this software - * and its documentation for any purpose is hereby granted without - * fee, provided that the above copyright notice appear in all copies - * and that both that copyright notice and this permission notice - * appear in supporting documentation, and that the name of the - * copyright holders not be used in advertising or publicity - * pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied - * warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS - * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. - */ - -#ifndef XWAYLAND_TYPES_H -#define XWAYLAND_TYPES_H - -struct xwl_pixmap; -struct xwl_window; -struct xwl_screen; -struct xwl_drm_lease; -struct xwl_output; -struct xwl_window_buffer; - -#endif /* XWAYLAND_TYPES_H */ diff --git a/hw/xwayland/xwayland-vidmode.c b/hw/xwayland/xwayland-vidmode.c deleted file mode 100644 index f6fe68942..000000000 --- a/hw/xwayland/xwayland-vidmode.c +++ /dev/null @@ -1,507 +0,0 @@ -/* - * Copyright (c) 1999-2003 by The XFree86 Project, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Except as contained in this notice, the name of the copyright holder(s) - * and author(s) shall not be used in advertising or otherwise to promote - * the sale, use or other dealings in this Software without prior written - * authorization from the copyright holder(s) and author(s). - */ - -#include - -#include - -#include "dix/dix_priv.h" - -#include "misc.h" -#include "os.h" - -#ifdef XF86VIDMODE - -#include "randrstr.h" -#include "vidmodestr.h" - -#include "xwayland-screen.h" -#include "xwayland-vidmode.h" - -static DevPrivateKeyRec xwlVidModePrivateKeyRec; -#define xwlVidModePrivateKey (&xwlVidModePrivateKeyRec) - -/* Taken from xrandr, h sync frequency in KHz */ -static double -mode_hsync(const xRRModeInfo *mode_info) -{ - double rate; - - if (mode_info->hTotal) - rate = (double) mode_info->dotClock / (double) mode_info->hTotal; - else - rate = 0.0; - - return rate / 1000.0; -} - -/* Taken from xrandr, v refresh frequency in Hz */ -static double -mode_refresh(const xRRModeInfo *mode_info) -{ - double rate; - double vTotal = mode_info->vTotal; - - if (mode_info->modeFlags & RR_DoubleScan) - vTotal *= 2.0; - - if (mode_info->modeFlags & RR_Interlace) - vTotal /= 2.0; - - if (mode_info->hTotal > 0.0 && vTotal > 0.0) - rate = ((double) mode_info->dotClock / - ((double) mode_info->hTotal * (double) vTotal)); - else - rate = 0.0; - - return rate; -} - -static void -xwlRRModeToDisplayMode(RRModePtr rrmode, DisplayModePtr mode) -{ - const xRRModeInfo *mode_info = &rrmode->mode; - - mode->next = mode; - mode->prev = mode; - mode->name = ""; - mode->VScan = 1; - mode->Private = NULL; - mode->HDisplay = mode_info->width; - mode->HSyncStart = mode_info->hSyncStart; - mode->HSyncEnd = mode_info->hSyncEnd; - mode->HTotal = mode_info->hTotal; - mode->HSkew = mode_info->hSkew; - mode->VDisplay = mode_info->height; - mode->VSyncStart = mode_info->vSyncStart; - mode->VSyncEnd = mode_info->vSyncEnd; - mode->VTotal = mode_info->vTotal; - mode->Flags = mode_info->modeFlags; - mode->Clock = mode_info->dotClock / 1000.0; - mode->VRefresh = mode_refresh(mode_info); /* Or RRVerticalRefresh() */ - mode->HSync = mode_hsync(mode_info); -} - -static RRModePtr -xwlVidModeGetRRMode(ScreenPtr pScreen, int32_t width, int32_t height) -{ - struct xwl_screen *xwl_screen = xwl_screen_get(pScreen); - struct xwl_output *xwl_output; - - xwl_output = xwl_screen_get_fixed_or_first_output(xwl_screen); - if (!xwl_output) - return NULL; - - return xwl_output_find_mode(xwl_output, width, height); -} - -static RRModePtr -xwlVidModeGetCurrentRRMode(ScreenPtr pScreen) -{ - struct xwl_screen *xwl_screen = xwl_screen_get(pScreen); - struct xwl_emulated_mode *emulated_mode; - struct xwl_output *xwl_output; - - xwl_output = xwl_screen_get_fixed_or_first_output(xwl_screen); - if (!xwl_output) - return NULL; - - emulated_mode = - xwl_output_get_emulated_mode_for_client(xwl_output, GetCurrentClient()); - - if (emulated_mode) { - return xwl_output_find_mode(xwl_output, - emulated_mode->width, - emulated_mode->height); - } else { - return xwl_output_find_mode(xwl_output, -1, -1); - } -} - -static Bool -xwlVidModeGetCurrentModeline(ScreenPtr pScreen, DisplayModePtr *mode, int *dotClock) -{ - DisplayModePtr pMod; - RRModePtr rrmode; - - pMod = dixLookupPrivate(&pScreen->devPrivates, xwlVidModePrivateKey); - if (pMod == NULL) - return FALSE; - - rrmode = xwlVidModeGetCurrentRRMode(pScreen); - if (rrmode == NULL) - return FALSE; - - xwlRRModeToDisplayMode(rrmode, pMod); - - *mode = pMod; - if (dotClock != NULL) - *dotClock = pMod->Clock; - - return TRUE; -} - -static vidMonitorValue -xwlVidModeGetMonitorValue(ScreenPtr pScreen, int valtyp, int indx) -{ - vidMonitorValue ret = { NULL, }; - RRModePtr rrmode; - - rrmode = xwlVidModeGetCurrentRRMode(pScreen); - if (rrmode == NULL) - return ret; - - switch (valtyp) { - case VIDMODE_MON_VENDOR: - ret.ptr = XVENDORNAME; - break; - case VIDMODE_MON_MODEL: - ret.ptr = "XWAYLAND"; - break; - case VIDMODE_MON_NHSYNC: - ret.i = 1; - break; - case VIDMODE_MON_NVREFRESH: - ret.i = 1; - break; - case VIDMODE_MON_HSYNC_LO: - case VIDMODE_MON_HSYNC_HI: - ret.f = mode_hsync(&rrmode->mode) * 100.0; - break; - case VIDMODE_MON_VREFRESH_LO: - case VIDMODE_MON_VREFRESH_HI: - ret.f = mode_refresh(&rrmode->mode) * 100.0; - break; - } - return ret; -} - -static int -xwlVidModeGetDotClock(ScreenPtr pScreen, int Clock) -{ - return Clock; -} - -static int -xwlVidModeGetNumOfClocks(ScreenPtr pScreen, Bool *progClock) -{ - /* We emulate a programmable clock, rather then a fixed set of clocks */ - *progClock = TRUE; - return 0; -} - -static Bool -xwlVidModeGetClocks(ScreenPtr pScreen, int *Clocks) -{ - return FALSE; /* Programmable clock, no clock list */ -} - -/* GetFirstModeline and GetNextModeline are used from Xext/vidmode.c like this: - * if (pVidMode->GetFirstModeline(pScreen, &mode, &dotClock)) { - * do { - * ... - * if (...) - * break; - * } while (pVidMode->GetNextModeline(pScreen, &mode, &dotClock)); - * } - * IOW our caller basically always loops over all the modes. There never is a - * return to the mainloop between GetFirstModeline and NextModeline calls where - * other parts of the server may change our state so we do not need to worry - * about xwl_output->randr_output->modes changing underneath us. - * Thus we can simply implement these two callbacks by storing the enumeration - * index in pVidMode->Next. - */ - -static Bool -xwlVidModeGetNextModeline(ScreenPtr pScreen, DisplayModePtr *mode, int *dotClock) -{ - struct xwl_screen *xwl_screen = xwl_screen_get(pScreen); - struct xwl_output *xwl_output; - VidModePtr pVidMode; - DisplayModePtr pMod; - intptr_t index; - - xwl_output = xwl_screen_get_fixed_or_first_output(xwl_screen); - if (xwl_output == NULL) - return FALSE; - - pMod = dixLookupPrivate(&pScreen->devPrivates, xwlVidModePrivateKey); - pVidMode = VidModeGetPtr(pScreen); - if (pMod == NULL || pVidMode == NULL) - return FALSE; - - index = (intptr_t)pVidMode->Next; - if (index >= xwl_output->randr_output->numModes) - return FALSE; - xwlRRModeToDisplayMode(xwl_output->randr_output->modes[index], pMod); - index++; - pVidMode->Next = (void *)index; - - *mode = pMod; - if (dotClock != NULL) - *dotClock = pMod->Clock; - - return TRUE; -} - -static Bool -xwlVidModeGetFirstModeline(ScreenPtr pScreen, DisplayModePtr *mode, int *dotClock) -{ - VidModePtr pVidMode; - intptr_t index = 0; - - pVidMode = VidModeGetPtr(pScreen); - if (pVidMode == NULL) - return FALSE; - - pVidMode->Next = (void *)index; /* 0 */ - return xwlVidModeGetNextModeline(pScreen, mode, dotClock); -} - -static Bool -xwlVidModeDeleteModeline(ScreenPtr pScreen, DisplayModePtr mode) -{ - /* Unsupported */ - return FALSE; -} - -static Bool -xwlVidModeZoomViewport(ScreenPtr pScreen, int zoom) -{ - /* Support only no zoom */ - return (zoom == 1); -} - -static Bool -xwlVidModeSetViewPort(ScreenPtr pScreen, int x, int y) -{ - struct xwl_screen *xwl_screen = xwl_screen_get(pScreen); - struct xwl_output *xwl_output; - - xwl_output = xwl_screen_get_fixed_or_first_output(xwl_screen); - if (xwl_output == NULL) - return FALSE; - - /* Support only default viewport */ - return (x == xwl_output->x && y == xwl_output->y); -} - -static Bool -xwlVidModeGetViewPort(ScreenPtr pScreen, int *x, int *y) -{ - struct xwl_screen *xwl_screen = xwl_screen_get(pScreen); - struct xwl_output *xwl_output; - - xwl_output = xwl_screen_get_fixed_or_first_output(xwl_screen); - if (xwl_output == NULL) - return FALSE; - - *x = xwl_output->x; - *y = xwl_output->y; - - return TRUE; -} - -static Bool -xwlVidModeSwitchMode(ScreenPtr pScreen, DisplayModePtr mode) -{ - struct xwl_screen *xwl_screen = xwl_screen_get(pScreen); - struct xwl_output *xwl_output; - RRModePtr rrmode; - - xwl_output = xwl_screen_get_fixed_or_first_output(xwl_screen); - if (xwl_output == NULL) - return FALSE; - - rrmode = xwl_output_find_mode(xwl_output, mode->HDisplay, mode->VDisplay); - if (rrmode == NULL) - return FALSE; - - if (xwl_screen->rootless) - xwl_output_set_emulated_mode(xwl_output, GetCurrentClient(), rrmode, TRUE); - else if (xwl_screen->fixed_output) - xwl_output_set_mode_fixed(xwl_screen->fixed_output, rrmode); - - return TRUE; -} - -static Bool -xwlVidModeLockZoom(ScreenPtr pScreen, Bool lock) -{ - /* Unsupported for now, but pretend it works */ - return TRUE; -} - -static ModeStatus -xwlVidModeCheckModeForMonitor(ScreenPtr pScreen, DisplayModePtr mode) -{ - RRModePtr rrmode; - - rrmode = xwlVidModeGetRRMode(pScreen, mode->HDisplay, mode->VDisplay); - if (rrmode == NULL) - return MODE_ERROR; - - /* Only support mode with the same HSync/VRefresh as we advertise */ - if (mode->HSync == mode_hsync(&rrmode->mode) && - mode->VRefresh == mode_refresh(&rrmode->mode)) - return MODE_OK; - - /* All the rest is unsupported - If we want to succeed, return MODE_OK instead */ - return MODE_ONE_SIZE; -} - -static ModeStatus -xwlVidModeCheckModeForDriver(ScreenPtr pScreen, DisplayModePtr mode) -{ - RRModePtr rrmode; - - rrmode = xwlVidModeGetRRMode(pScreen, mode->HDisplay, mode->VDisplay); - return rrmode ? MODE_OK : MODE_ERROR; -} - -static void -xwlVidModeSetCrtcForMode(ScreenPtr pScreen, DisplayModePtr mode) -{ - /* Unsupported */ - return; -} - -static Bool -xwlVidModeAddModeline(ScreenPtr pScreen, DisplayModePtr mode) -{ - /* Unsupported */ - return FALSE; -} - -static int -xwlVidModeGetNumOfModes(ScreenPtr pScreen) -{ - struct xwl_screen *xwl_screen = xwl_screen_get(pScreen); - struct xwl_output *xwl_output; - - xwl_output = xwl_screen_get_fixed_or_first_output(xwl_screen); - - return xwl_output ? xwl_output->randr_output->numModes : 0; -} - -static Bool -xwlVidModeSetGamma(ScreenPtr pScreen, float red, float green, float blue) -{ - /* Unsupported for now, but pretend it works */ - return TRUE; -} - -static Bool -xwlVidModeGetGamma(ScreenPtr pScreen, float *red, float *green, float *blue) -{ - /* Unsupported for now, but pretend it works */ - *red = *green = *blue = 1.0f; - return TRUE; -} - -static Bool -xwlVidModeSetGammaRamp(ScreenPtr pScreen, int size, CARD16 *r, CARD16 *g, CARD16 *b) -{ - /* Unsupported for now */ - return FALSE; -} - -static Bool -xwlVidModeGetGammaRamp(ScreenPtr pScreen, int size, CARD16 *r, CARD16 *g, CARD16 *b) -{ - /* Unsupported for now */ - return FALSE; -} - -static int -xwlVidModeGetGammaRampSize(ScreenPtr pScreen) -{ - /* Unsupported for now */ - return 0; -} - -static Bool -xwlVidModeInit(ScreenPtr pScreen) -{ - VidModePtr pVidMode = NULL; - - pVidMode = VidModeInit(pScreen); - if (!pVidMode) - return FALSE; - - pVidMode->Flags = 0; - pVidMode->Next = NULL; - - pVidMode->GetMonitorValue = xwlVidModeGetMonitorValue; - pVidMode->GetCurrentModeline = xwlVidModeGetCurrentModeline; - pVidMode->GetFirstModeline = xwlVidModeGetFirstModeline; - pVidMode->GetNextModeline = xwlVidModeGetNextModeline; - pVidMode->DeleteModeline = xwlVidModeDeleteModeline; - pVidMode->ZoomViewport = xwlVidModeZoomViewport; - pVidMode->GetViewPort = xwlVidModeGetViewPort; - pVidMode->SetViewPort = xwlVidModeSetViewPort; - pVidMode->SwitchMode = xwlVidModeSwitchMode; - pVidMode->LockZoom = xwlVidModeLockZoom; - pVidMode->GetNumOfClocks = xwlVidModeGetNumOfClocks; - pVidMode->GetClocks = xwlVidModeGetClocks; - pVidMode->CheckModeForMonitor = xwlVidModeCheckModeForMonitor; - pVidMode->CheckModeForDriver = xwlVidModeCheckModeForDriver; - pVidMode->SetCrtcForMode = xwlVidModeSetCrtcForMode; - pVidMode->AddModeline = xwlVidModeAddModeline; - pVidMode->GetDotClock = xwlVidModeGetDotClock; - pVidMode->GetNumOfModes = xwlVidModeGetNumOfModes; - pVidMode->SetGamma = xwlVidModeSetGamma; - pVidMode->GetGamma = xwlVidModeGetGamma; - pVidMode->SetGammaRamp = xwlVidModeSetGammaRamp; - pVidMode->GetGammaRamp = xwlVidModeGetGammaRamp; - pVidMode->GetGammaRampSize = xwlVidModeGetGammaRampSize; - - return TRUE; -} - -void -xwlVidModeExtensionInit(void) -{ - int i; - Bool enabled = FALSE; - - for (i = 0; i < screenInfo.numScreens; i++) { - if (xwlVidModeInit (screenInfo.screens[i])) - enabled = TRUE; - } - /* This means that the DDX doesn't want the vidmode extension enabled */ - if (!enabled) - return; - - if (!dixRegisterPrivateKey(xwlVidModePrivateKey, PRIVATE_SCREEN, - sizeof(DisplayModeRec))) - return; - - VidModeAddExtension(FALSE); -} - -#endif /* XF86VIDMODE */ diff --git a/hw/xwayland/xwayland-vidmode.h b/hw/xwayland/xwayland-vidmode.h deleted file mode 100644 index 4e3236eb1..000000000 --- a/hw/xwayland/xwayland-vidmode.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 1999-2003 by The XFree86 Project, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Except as contained in this notice, the name of the copyright holder(s) - * and author(s) shall not be used in advertising or otherwise to promote - * the sale, use or other dealings in this Software without prior written - * authorization from the copyright holder(s) and author(s). - */ - -#ifndef XWAYLAND_VIDMODE_H -#define XWAYLAND_VIDMODE_H - -#include - -#ifdef XF86VIDMODE -void xwlVidModeExtensionInit(void); -#endif - -#endif /* XWAYLAND_VIDMODE_H */ diff --git a/hw/xwayland/xwayland-window-buffers.c b/hw/xwayland/xwayland-window-buffers.c deleted file mode 100644 index a7a5e67a7..000000000 --- a/hw/xwayland/xwayland-window-buffers.c +++ /dev/null @@ -1,473 +0,0 @@ -/* - * Copyright © 2019 Red Hat, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Authors: - * Olivier Fourdan - */ - -#include - -#include "gcstruct.h" - -#include "xwayland-window.h" -#include "xwayland-pixmap.h" -#include "xwayland-screen.h" -#include "xwayland-glamor-gbm.h" -#include "xwayland-window-buffers.h" -#ifdef XWL_HAS_GLAMOR -#include "glamor.h" -#endif -#include "dri3.h" - -#include -#ifdef DRI3 -#include -#endif -#include "linux-drm-syncobj-v1-client-protocol.h" - -#define BUFFER_TIMEOUT 1 * 1000 /* ms */ - -struct xwl_window_buffer { - struct xwl_window *xwl_window; - PixmapPtr pixmap; - RegionPtr damage_region; - int refcnt; - uint32_t time; - struct xorg_list link_buffer; -}; - -static void -copy_pixmap_area(PixmapPtr src_pixmap, PixmapPtr dst_pixmap, - int x, int y, int width, int height) -{ - GCPtr pGC; - pGC = GetScratchGC(dst_pixmap->drawable.depth, - dst_pixmap->drawable.pScreen); - if (!pGC) - FatalError("GetScratchGC failed for depth %d", dst_pixmap->drawable.depth); - - ValidateGC(&dst_pixmap->drawable, pGC); - (void) (*pGC->ops->CopyArea) (&src_pixmap->drawable, - &dst_pixmap->drawable, - pGC, - x, y, - width, height, - x, y); - FreeScratchGC(pGC); -} - -static struct xwl_window_buffer * -xwl_window_buffer_new(struct xwl_window *xwl_window) -{ - struct xwl_window_buffer *xwl_window_buffer; - - xwl_window_buffer = calloc (1, sizeof(struct xwl_window_buffer)); - if (!xwl_window_buffer) - return NULL; - - xwl_window_buffer->xwl_window = xwl_window; - xwl_window_buffer->damage_region = RegionCreate(NullBox, 1); - xwl_window_buffer->pixmap = NullPixmap; - xwl_window_buffer->refcnt = 1; - - xorg_list_init(&xwl_window_buffer->link_buffer); - - return xwl_window_buffer; -} - -static void -xwl_window_buffer_destroy_pixmap(struct xwl_window_buffer *xwl_window_buffer) -{ - xwl_pixmap_del_buffer_release_cb(xwl_window_buffer->pixmap); - dixDestroyPixmap(xwl_window_buffer->pixmap, 0); - xwl_window_buffer->pixmap = NullPixmap; -} - -static void -xwl_window_buffer_dispose(struct xwl_window_buffer *xwl_window_buffer) -{ - RegionDestroy(xwl_window_buffer->damage_region); - - if (xwl_window_buffer->pixmap) { -#ifdef XWL_HAS_GLAMOR - xwl_glamor_gbm_dispose_syncpts(xwl_window_buffer->pixmap); -#endif /* XWL_HAS_GLAMOR */ - xwl_window_buffer_destroy_pixmap (xwl_window_buffer); - } - - xorg_list_del(&xwl_window_buffer->link_buffer); - free(xwl_window_buffer); -} - -static Bool -xwl_window_buffer_maybe_dispose(struct xwl_window_buffer *xwl_window_buffer) -{ - assert(xwl_window_buffer->refcnt > 0); - - if (--xwl_window_buffer->refcnt) - return FALSE; - - xwl_window_buffer_dispose(xwl_window_buffer); - - return TRUE; -} - -void -xwl_window_buffer_add_damage_region(struct xwl_window *xwl_window) -{ - RegionPtr region = xwl_window_get_damage_region(xwl_window); - struct xwl_window_buffer *xwl_window_buffer; - - /* Add damage region to all buffers */ - xorg_list_for_each_entry(xwl_window_buffer, - &xwl_window->window_buffers_available, - link_buffer) { - RegionUnion(xwl_window_buffer->damage_region, - xwl_window_buffer->damage_region, - region); - } - xorg_list_for_each_entry(xwl_window_buffer, - &xwl_window->window_buffers_unavailable, - link_buffer) { - RegionUnion(xwl_window_buffer->damage_region, - xwl_window_buffer->damage_region, - region); - } -} - -static struct xwl_window_buffer * -xwl_window_buffer_get_available(struct xwl_window *xwl_window) -{ - if (xorg_list_is_empty(&xwl_window->window_buffers_available)) - return NULL; - - return xorg_list_last_entry(&xwl_window->window_buffers_available, - struct xwl_window_buffer, - link_buffer); -} - -static CARD32 -xwl_window_buffer_timer_callback(OsTimerPtr timer, CARD32 time, void *arg) -{ - struct xwl_window *xwl_window = arg; - struct xwl_window_buffer *xwl_window_buffer, *tmp; - - /* Dispose older available buffers */ - xorg_list_for_each_entry_safe(xwl_window_buffer, tmp, - &xwl_window->window_buffers_available, - link_buffer) { - if ((int64_t)(time - xwl_window_buffer->time) >= BUFFER_TIMEOUT) - xwl_window_buffer_maybe_dispose(xwl_window_buffer); - } - - /* If there are still available buffers, re-arm the timer */ - if (!xorg_list_is_empty(&xwl_window->window_buffers_available)) { - struct xwl_window_buffer *oldest_available_buffer = - xorg_list_first_entry(&xwl_window->window_buffers_available, - struct xwl_window_buffer, - link_buffer); - - return oldest_available_buffer->time + BUFFER_TIMEOUT - time; - } - - /* Don't re-arm the timer */ - return 0; -} - -static void -xwl_window_buffer_release_callback(void *data) -{ - struct xwl_window_buffer *xwl_window_buffer = data; - struct xwl_window *xwl_window = xwl_window_buffer->xwl_window; - struct xwl_window_buffer *oldest_available_buffer; - - /* Drop the reference on the buffer we took in get_pixmap. If that - * frees the window buffer, we're done. - */ - if (xwl_window_buffer_maybe_dispose(xwl_window_buffer)) - return; - - /* We append the buffers to the end of the list, as we pick the last - * entry again when looking for new available buffers, that means the - * least used buffers will remain at the beginning of the list so that - * they can be garbage collected automatically after some time unused. - */ - - xorg_list_del(&xwl_window_buffer->link_buffer); - xorg_list_append(&xwl_window_buffer->link_buffer, - &xwl_window->window_buffers_available); - xwl_window_buffer->time = (uint32_t) GetTimeInMillis(); - - oldest_available_buffer = - xorg_list_first_entry(&xwl_window->window_buffers_available, - struct xwl_window_buffer, - link_buffer); - - /* Schedule next timer based on time of the oldest buffer */ - xwl_window->window_buffers_timer = - TimerSet(xwl_window->window_buffers_timer, - TimerAbsolute, - oldest_available_buffer->time + BUFFER_TIMEOUT, - &xwl_window_buffer_timer_callback, - xwl_window); -} - -void -xwl_window_buffer_release(struct xwl_window_buffer *xwl_window_buffer) -{ - xwl_window_buffer_release_callback(xwl_window_buffer); -} - -void -xwl_window_buffers_init(struct xwl_window *xwl_window) -{ - xorg_list_init(&xwl_window->window_buffers_available); - xorg_list_init(&xwl_window->window_buffers_unavailable); -} - -static void -xwl_window_buffer_disposal(struct xwl_window_buffer *xwl_window_buffer, Bool force) -{ - if (force) - xwl_window_buffer_dispose(xwl_window_buffer); - else - xwl_window_buffer_maybe_dispose(xwl_window_buffer); -} - -void -xwl_window_buffers_dispose(struct xwl_window *xwl_window, Bool force) -{ - struct xwl_window_buffer *xwl_window_buffer, *tmp; - - /* This is called prior to free the xwl_window, make sure to untie - * the buffers from the xwl_window so that we don't point at freed - * memory if we get a release buffer later. - */ - xorg_list_for_each_entry_safe(xwl_window_buffer, tmp, - &xwl_window->window_buffers_available, - link_buffer) { - xorg_list_del(&xwl_window_buffer->link_buffer); - xwl_window_buffer_disposal(xwl_window_buffer, force); - } - - xorg_list_for_each_entry_safe(xwl_window_buffer, tmp, - &xwl_window->window_buffers_unavailable, - link_buffer) { - xorg_list_del(&xwl_window_buffer->link_buffer); - xwl_window_buffer_disposal(xwl_window_buffer, force); - } - - if (xwl_window->window_buffers_timer) - TimerCancel(xwl_window->window_buffers_timer); -} - -struct pixmap_visit { - PixmapPtr old; - PixmapPtr new; -}; - -static int -xwl_set_pixmap_visit_window(WindowPtr window, void *data) -{ - ScreenPtr screen = window->drawable.pScreen; - struct pixmap_visit *visit = data; - - if (screen->GetWindowPixmap(window) == visit->old) { - screen->SetWindowPixmap(window, visit->new); - return WT_WALKCHILDREN; - } - - return WT_DONTWALKCHILDREN; -} - -static void -xwl_window_set_pixmap(WindowPtr window, PixmapPtr pixmap) -{ - ScreenPtr screen = window->drawable.pScreen; - struct pixmap_visit visit; - - visit.old = screen->GetWindowPixmap(window); - visit.new = pixmap; - - pixmap->screen_x = visit.old->screen_x; - pixmap->screen_y = visit.old->screen_y; - - TraverseTree(window, xwl_set_pixmap_visit_window, &visit); - - if (window == screen->root && - screen->GetScreenPixmap(screen) == visit.old) - screen->SetScreenPixmap(pixmap); -} - -static PixmapPtr -xwl_window_allocate_pixmap(struct xwl_window *xwl_window) -{ - ScreenPtr screen = xwl_window->xwl_screen->screen; - PixmapPtr window_pixmap; - -#ifdef XWL_HAS_GLAMOR - /* Try the xwayland/glamor direct hook first */ - window_pixmap = xwl_glamor_create_pixmap_for_window(xwl_window); - if (window_pixmap) - return window_pixmap; -#endif /* XWL_HAS_GLAMOR */ - - window_pixmap = screen->GetWindowPixmap(xwl_window->surface_window); - return screen->CreatePixmap(screen, - window_pixmap->drawable.width, - window_pixmap->drawable.height, - window_pixmap->drawable.depth, - CREATE_PIXMAP_USAGE_BACKING_PIXMAP); -} - -void -xwl_window_realloc_pixmap(struct xwl_window *xwl_window) -{ - PixmapPtr window_pixmap, new_window_pixmap; - WindowPtr window; - ScreenPtr screen; - - new_window_pixmap = xwl_window_allocate_pixmap(xwl_window); - if (!new_window_pixmap) - return; - - window = xwl_window->surface_window; - screen = window->drawable.pScreen; - window_pixmap = screen->GetWindowPixmap(window); - copy_pixmap_area(window_pixmap, - new_window_pixmap, - 0, 0, - window_pixmap->drawable.width, - window_pixmap->drawable.height); - xwl_window_set_pixmap(xwl_window->surface_window, new_window_pixmap); - dixDestroyPixmap(window_pixmap, 0); -} - -static Bool -xwl_window_handle_pixmap_sync(struct xwl_window *xwl_window, - PixmapPtr pixmap, - struct xwl_window_buffer *xwl_window_buffer) -{ - Bool implicit_sync = TRUE; -#ifdef XWL_HAS_GLAMOR - struct xwl_screen *xwl_screen = xwl_window->xwl_screen; - - if (!xwl_glamor_supports_implicit_sync(xwl_screen)) { - if (xwl_screen->explicit_sync && xwl_glamor_gbm_set_syncpts(xwl_window, pixmap)) { - implicit_sync = FALSE; - /* wait until the release fence is available before re-using this buffer */ - xwl_glamor_gbm_wait_release_fence(xwl_window, pixmap, xwl_window_buffer); - } else { - /* If glamor does not support implicit sync and we can't use - * explicit sync, wait for the GPU to be idle before presenting. - * Note that buffer re-use will still be unsynchronized :( - */ - glamor_finish(xwl_screen->screen); - } - } -#endif /* XWL_HAS_GLAMOR */ - return implicit_sync; -} - -PixmapPtr -xwl_window_swap_pixmap(struct xwl_window *xwl_window, Bool handle_sync) -{ - struct xwl_screen *xwl_screen = xwl_window->xwl_screen; - WindowPtr surface_window = xwl_window->surface_window; - struct xwl_window_buffer *xwl_window_buffer; - PixmapPtr window_pixmap; - - window_pixmap = (*xwl_screen->screen->GetWindowPixmap) (surface_window); - - xwl_window_buffer_add_damage_region(xwl_window); - - xwl_window_buffer = xwl_window_buffer_get_available(xwl_window); - if (xwl_window_buffer) { - RegionPtr full_damage = xwl_window_buffer->damage_region; - BoxPtr pBox = RegionRects(full_damage); - int nBox = RegionNumRects(full_damage); -#ifdef XWL_HAS_GLAMOR - xwl_glamor_gbm_wait_syncpts(xwl_window_buffer->pixmap); -#endif /* XWL_HAS_GLAMOR */ - while (nBox--) { - copy_pixmap_area(window_pixmap, - xwl_window_buffer->pixmap, - pBox->x1 + surface_window->borderWidth, - pBox->y1 + surface_window->borderWidth, - pBox->x2 - pBox->x1, - pBox->y2 - pBox->y1); - - pBox++; - } - - RegionEmpty(xwl_window_buffer->damage_region); - xorg_list_del(&xwl_window_buffer->link_buffer); - xwl_window_set_pixmap(surface_window, xwl_window_buffer->pixmap); - - /* Can't re-use client pixmap as a window buffer */ - if (xwl_is_client_pixmap(window_pixmap)) { - xwl_window_buffer->pixmap = NULL; - xwl_window_buffer_maybe_dispose(xwl_window_buffer); - if (handle_sync) - xwl_window_handle_pixmap_sync(xwl_window, window_pixmap, NULL); - return window_pixmap; - } - } else { - /* Can't re-use client pixmap as a window buffer */ - if (!xwl_is_client_pixmap(window_pixmap)) - xwl_window_buffer = xwl_window_buffer_new(xwl_window); - - window_pixmap->refcnt++; - xwl_window_realloc_pixmap(xwl_window); - - if (!xwl_window_buffer) { - if (handle_sync) - xwl_window_handle_pixmap_sync(xwl_window, window_pixmap, NULL); - return window_pixmap; - } - } - - xwl_window_buffer->pixmap = window_pixmap; - - /* Hold a reference on the buffer until it's released by the compositor */ - xwl_window_buffer->refcnt++; - - if (handle_sync && - xwl_window_handle_pixmap_sync(xwl_window, window_pixmap, xwl_window_buffer)) { - xwl_pixmap_set_buffer_release_cb(xwl_window_buffer->pixmap, - xwl_window_buffer_release_callback, - xwl_window_buffer); - - if (xwl_window->surface_sync) { - wp_linux_drm_syncobj_surface_v1_destroy(xwl_window->surface_sync); - xwl_window->surface_sync = NULL; - } - } - - xorg_list_append(&xwl_window_buffer->link_buffer, - &xwl_window->window_buffers_unavailable); - - if (xorg_list_is_empty(&xwl_window->window_buffers_available)) - TimerCancel(xwl_window->window_buffers_timer); - - return xwl_window_buffer->pixmap; -} diff --git a/hw/xwayland/xwayland-window-buffers.h b/hw/xwayland/xwayland-window-buffers.h deleted file mode 100644 index dabb343c1..000000000 --- a/hw/xwayland/xwayland-window-buffers.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright © 2019 Red Hat, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Authors: - * Olivier Fourdan - */ - -#ifndef XWAYLAND_WINDOW_BUFFERS_H -#define XWAYLAND_WINDOW_BUFFERS_H - -#include - -#include "xwayland-types.h" - -void xwl_window_buffer_add_damage_region(struct xwl_window *xwl_window); -void xwl_window_buffer_release(struct xwl_window_buffer *xwl_window_buffer); -void xwl_window_buffers_init(struct xwl_window *xwl_window); -void xwl_window_buffers_dispose(struct xwl_window *xwl_window, Bool force); -void xwl_window_realloc_pixmap(struct xwl_window *xwl_window); -PixmapPtr xwl_window_swap_pixmap(struct xwl_window *xwl_window, Bool handle_sync); - -#endif /* XWAYLAND_WINDOW_BUFFERS_H */ diff --git a/hw/xwayland/xwayland-window.c b/hw/xwayland/xwayland-window.c deleted file mode 100644 index 5a26cd00a..000000000 --- a/hw/xwayland/xwayland-window.c +++ /dev/null @@ -1,2050 +0,0 @@ -/* - * Copyright © 2011-2014 Intel Corporation - * - * Permission to use, copy, modify, distribute, and sell this software - * and its documentation for any purpose is hereby granted without - * fee, provided that the above copyright notice appear in all copies - * and that both that copyright notice and this permission notice - * appear in supporting documentation, and that the name of the - * copyright holders not be used in advertising or publicity - * pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied - * warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS - * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. - */ - -#include - -#include -#include -#include - -#include -#include - -#include "dix/dix_priv.h" -#include "dix/property_priv.h" -#include "dix/resource_priv.h" -#include "os/log_priv.h" - -#include "compositeext.h" -#include "compint.h" -#include "inputstr.h" -#include "propertyst.h" - -#include "xwayland-types.h" -#include "xwayland-input.h" -#include "xwayland-pixmap.h" -#include "xwayland-present.h" -#include "xwayland-screen.h" -#include "xwayland-window.h" -#include "xwayland-window-buffers.h" -#include "xwayland-shm.h" -#include "xwayland-dmabuf.h" - -#include "linux-dmabuf-unstable-v1-client-protocol.h" -#include "tearing-control-v1-client-protocol.h" -#include "viewporter-client-protocol.h" -#include "xdg-shell-client-protocol.h" -#include "xwayland-shell-v1-client-protocol.h" -#include "fractional-scale-v1-client-protocol.h" -#include "linux-drm-syncobj-v1-client-protocol.h" - -#define DELAYED_WL_SURFACE_DESTROY 1000 /* ms */ - -#define MAX_ROOTFUL_WIDTH 32767 -#define MAX_ROOTFUL_HEIGHT 32767 -#define MIN_ROOTFUL_WIDTH 320 -#define MIN_ROOTFUL_HEIGHT 200 - -#define FRACTIONAL_SCALE_DENOMINATOR 120 - -static DevPrivateKeyRec xwl_window_private_key; -static DevPrivateKeyRec xwl_damage_private_key; -static const char *xwl_surface_tag = "xwl-surface"; - -static Bool xwl_window_attach_buffer(struct xwl_window *); - -struct xwl_window * -xwl_window_get(WindowPtr window) -{ - return dixLookupPrivate(&window->devPrivates, &xwl_window_private_key); -} - -static DamagePtr -window_get_damage(WindowPtr window) -{ - return dixLookupPrivate(&window->devPrivates, &xwl_damage_private_key); -} - -RegionPtr -xwl_window_get_damage_region(struct xwl_window *xwl_window) -{ - return DamageRegion(window_get_damage(xwl_window->surface_window)); -} - -struct xwl_window * -xwl_window_from_window(WindowPtr window) -{ - struct xwl_window *xwl_window; - - while (window) { - xwl_window = xwl_window_get(window); - if (xwl_window) - return xwl_window; - - window = window->parent; - } - - return NULL; -} - -static void -xwl_window_set_xwayland_tag(struct xwl_window *xwl_window) -{ - wl_proxy_set_tag((struct wl_proxy *)xwl_window->surface, &xwl_surface_tag); -} - -static void -xwl_window_clear_xwayland_tag(struct xwl_window *xwl_window) -{ - wl_proxy_set_tag((struct wl_proxy *)xwl_window->surface, NULL); -} - -Bool -is_surface_from_xwl_window(struct wl_surface *surface) -{ - return wl_proxy_get_tag((struct wl_proxy *) surface) == &xwl_surface_tag; -} - -static void -xwl_window_set_allow_commits(struct xwl_window *xwl_window, Bool allow, - const char *debug_msg) -{ - struct xwl_screen *xwl_screen = xwl_window->xwl_screen; - DamagePtr damage; - - xwl_window->allow_commits = allow; - DebugF("XWAYLAND: win %d allow_commits = %d (%s)\n", - xwl_window->toplevel->drawable.id, allow, debug_msg); - - damage = window_get_damage(xwl_window->surface_window); - if (allow && - xorg_list_is_empty(&xwl_window->link_damage) && - damage && - RegionNotEmpty(DamageRegion(damage))) { - xorg_list_add(&xwl_window->link_damage, - &xwl_screen->damage_window_list); - } -} - -static void -xwl_window_set_allow_commits_from_property(struct xwl_window *xwl_window, - PropertyPtr prop) -{ - static Bool warned = FALSE; - CARD32 *propdata; - - if (prop->propertyName != xwl_window->xwl_screen->allow_commits_prop) - FatalError("Xwayland internal error: prop mismatch in %s.\n", __func__); - - if (prop->type != XA_CARDINAL || prop->format != 32 || prop->size != 1) { - /* Not properly set, so fall back to safe and glitchy */ - xwl_window_set_allow_commits(xwl_window, TRUE, "WM fault"); - - if (!warned) { - LogMessageVerb(X_WARNING, 0, "Window manager is misusing property %s.\n", - NameForAtom(prop->propertyName)); - warned = TRUE; - } - return; - } - - propdata = prop->data; - xwl_window_set_allow_commits(xwl_window, !!propdata[0], "from property"); -} - -void -xwl_window_update_property(struct xwl_window *xwl_window, - PropertyStateRec *propstate) -{ - switch (propstate->state) { - case PropertyNewValue: - xwl_window_set_allow_commits_from_property(xwl_window, propstate->prop); - break; - - case PropertyDelete: - xwl_window_set_allow_commits(xwl_window, TRUE, "property deleted"); - break; - - default: - break; - } -} - -static void -need_source_validate_dec(struct xwl_screen *xwl_screen) -{ - xwl_screen->need_source_validate--; - - if (!xwl_screen->need_source_validate) - xwl_screen->screen->SourceValidate = xwl_screen->SourceValidate; -} - -static void -xwl_source_validate(DrawablePtr drawable, int x, int y, int width, int height, - unsigned int sub_window_mode) -{ - struct xwl_window *xwl_window; - WindowPtr window, iterator; - RegionRec region; - BoxRec box; - - if (sub_window_mode != IncludeInferiors || - drawable->type != DRAWABLE_WINDOW) - return; - - window = (WindowPtr)drawable; - xwl_window = xwl_window_from_window(window); - if (!xwl_window || !xwl_window->surface_window_damage || - !RegionNotEmpty(xwl_window->surface_window_damage)) - return; - - for (iterator = xwl_window->toplevel; - ; - iterator = iterator->firstChild) { - if (iterator == xwl_window->surface_window) - return; - - if (iterator == window) - break; - } - - box.x1 = x; - box.y1 = y; - box.x2 = x + width; - box.y2 = y + height; - RegionInit(®ion, &box, 1); - RegionIntersect(®ion, ®ion, xwl_window->surface_window_damage); - - if (RegionNotEmpty(®ion)) { - ScreenPtr screen = drawable->pScreen; - PixmapPtr dst_pix, src_pix; - BoxPtr pbox; - GCPtr pGC; - int nbox; - - dst_pix = screen->GetWindowPixmap(window); - pGC = GetScratchGC(dst_pix->drawable.depth, screen); - if (!pGC) - FatalError("GetScratchGC failed for depth %d", dst_pix->drawable.depth); - ValidateGC(&dst_pix->drawable, pGC); - - src_pix = screen->GetWindowPixmap(xwl_window->surface_window); - - RegionSubtract(xwl_window->surface_window_damage, - xwl_window->surface_window_damage, - ®ion); - - if (!RegionNotEmpty(xwl_window->surface_window_damage)) - need_source_validate_dec(xwl_window->xwl_screen); - - if (dst_pix->screen_x || dst_pix->screen_y) - RegionTranslate(®ion, -dst_pix->screen_x, -dst_pix->screen_y); - - pbox = RegionRects(®ion); - nbox = RegionNumRects(®ion); - while (nbox--) { - (void) (*pGC->ops->CopyArea) (&src_pix->drawable, - &dst_pix->drawable, - pGC, - pbox->x1, pbox->y1, - pbox->x2 - pbox->x1, pbox->y2 - pbox->y1, - pbox->x1, pbox->y1); - pbox++; - } - FreeScratchGC(pGC); - } - - RegionUninit(®ion); -} - -static void -need_source_validate_inc(struct xwl_screen *xwl_screen) -{ - if (!xwl_screen->need_source_validate) { - ScreenPtr screen = xwl_screen->screen; - - xwl_screen->SourceValidate = screen->SourceValidate; - screen->SourceValidate = xwl_source_validate; - } - - xwl_screen->need_source_validate++; -} - -static void -damage_report(DamagePtr pDamage, RegionPtr pRegion, void *data) -{ - struct xwl_window *xwl_window = data; - struct xwl_screen *xwl_screen = xwl_window->xwl_screen; - PixmapPtr window_pixmap; - - if (xwl_window->surface_window_damage && - RegionNotEmpty(pRegion)) { - if (!RegionNotEmpty(xwl_window->surface_window_damage)) - need_source_validate_inc(xwl_screen); - - RegionUnion(xwl_window->surface_window_damage, - xwl_window->surface_window_damage, - DamageRegion(pDamage)); - } - - if (xwl_screen->ignore_damage) - return; - - if (xorg_list_is_empty(&xwl_window->link_damage)) - xorg_list_add(&xwl_window->link_damage, &xwl_screen->damage_window_list); - - window_pixmap = xwl_screen->screen->GetWindowPixmap(xwl_window->surface_window); - if (xwl_is_client_pixmap(window_pixmap)) - dixDestroyPixmap(xwl_window_swap_pixmap(xwl_window, FALSE), 0); -} - -static void -damage_destroy(DamagePtr pDamage, void *data) -{ -} - -static Bool -register_damage(struct xwl_window *xwl_window) -{ - WindowPtr surface_window = xwl_window->surface_window; - DamagePtr damage; - - damage = DamageCreate(damage_report, damage_destroy, DamageReportNonEmpty, - FALSE, surface_window->drawable.pScreen, xwl_window); - if (damage == NULL) { - ErrorF("Failed creating damage\n"); - return FALSE; - } - - DamageRegister(&surface_window->drawable, damage); - dixSetPrivate(&surface_window->devPrivates, &xwl_damage_private_key, damage); - - return TRUE; -} - -static void -unregister_damage(struct xwl_window *xwl_window) -{ - WindowPtr surface_window = xwl_window->surface_window; - DamagePtr damage; - - damage = dixLookupPrivate(&surface_window->devPrivates, &xwl_damage_private_key); - if (!damage) - return; - - DamageUnregister(damage); - DamageDestroy(damage); - - dixSetPrivate(&surface_window->devPrivates, &xwl_damage_private_key, NULL); -} - -static Bool -xwl_window_update_fractional_scale(struct xwl_window *xwl_window, - int fractional_scale_numerator) -{ - int old_scale_numerator = xwl_window->fractional_scale_numerator; - - xwl_window->fractional_scale_numerator = fractional_scale_numerator; - - return (old_scale_numerator != fractional_scale_numerator); -} - -static double -xwl_window_get_fractional_scale_factor(struct xwl_window *xwl_window) -{ - return (double) xwl_window->fractional_scale_numerator / - (double) FRACTIONAL_SCALE_DENOMINATOR; -} - -static Bool -xwl_window_has_viewport_enabled(struct xwl_window *xwl_window) -{ - return (xwl_window->viewport != NULL); -} - -static void -xwl_window_disable_viewport(struct xwl_window *xwl_window) -{ - assert (xwl_window->viewport); - - DebugF("XWAYLAND: disabling viewport\n"); - wp_viewport_destroy(xwl_window->viewport); - xwl_window->viewport = NULL; - xwl_window->viewport_scale_x = 1.0; - xwl_window->viewport_scale_y = 1.0; -} - -/* Enable the viewport for fractional scale support with Xwayland rootful. - * Fractional scale support is not used with Xwayland rootful fullscreen (which - * sets its own XRandR resolution) so we can use the viewport for either - * fullscreen mode or fractional scale. - */ -static void -xwl_window_enable_viewport_for_fractional_scale(struct xwl_window *xwl_window, - int width, int height) -{ - struct xwl_screen *xwl_screen = xwl_window->xwl_screen; - int buffer_width, buffer_height; - double scale; - - scale = xwl_window_get_fractional_scale_factor(xwl_window); - buffer_width = round((double) width / scale); - buffer_height = round((double) height / scale); - - if (!xwl_window_has_viewport_enabled(xwl_window)) - xwl_window->viewport = wp_viewporter_get_viewport(xwl_screen->viewporter, - xwl_window->surface); - - DebugF("XWAYLAND: enabling viewport for fractional scale %dx%d -> %dx%d\n", - width, height, buffer_width, buffer_height); - wp_viewport_set_source(xwl_window->viewport, - wl_fixed_from_int(0), - wl_fixed_from_int(0), - wl_fixed_from_int(width), - wl_fixed_from_int(height)); - wp_viewport_set_destination(xwl_window->viewport, - buffer_width, - buffer_height); - - xwl_window->viewport_scale_x = scale; - xwl_window->viewport_scale_y = scale; -} - -/* Enable the viewport for Xwayland rootful fullscreen, to match the XRandR - * resolution with the actual output size. - */ -static void -xwl_window_enable_viewport_for_output(struct xwl_window *xwl_window, - struct xwl_output *xwl_output, - struct xwl_emulated_mode *emulated_mode) -{ - struct xwl_screen *xwl_screen = xwl_window->xwl_screen; - int width, height; - - if (!xwl_window_has_viewport_enabled(xwl_window)) { - DebugF("XWAYLAND: enabling viewport %dx%d -> %dx%d\n", - emulated_mode->width, emulated_mode->height, - xwl_output->width, xwl_output->height); - xwl_window->viewport = wp_viewporter_get_viewport(xwl_window->xwl_screen->viewporter, - xwl_window->surface); - } - - width = emulated_mode->width / xwl_screen->global_surface_scale; - height = emulated_mode->height / xwl_screen->global_surface_scale; - - wp_viewport_set_source(xwl_window->viewport, - wl_fixed_from_int(0), - wl_fixed_from_int(0), - wl_fixed_from_int(width), - wl_fixed_from_int(height)); - wp_viewport_set_destination(xwl_window->viewport, - xwl_output->width, - xwl_output->height); - - xwl_window->viewport_scale_x = (float) width / xwl_output->width; - xwl_window->viewport_scale_y = (float) height / xwl_output->height; -} - -static Bool -window_is_wm_window(WindowPtr window) -{ - struct xwl_screen *xwl_screen = xwl_screen_get(window->drawable.pScreen); - - return dixClientIdForXID(window->drawable.id) == xwl_screen->wm_client_id; -} - -static WindowPtr -window_get_client_toplevel(WindowPtr window) -{ - assert(window); - - /* If the toplevel window is owned by the window-manager, then the - * actual client toplevel window has been reparented to some window-manager - * decoration/wrapper windows. In that case recurse by checking the client - * of the first *and only* child of the decoration/wrapper window. - */ - while (window_is_wm_window(window)) { - if (!window->firstChild || window->firstChild != window->lastChild) - return NULL; /* Should never happen, skip resolution emulation */ - - window = window->firstChild; - } - - return window; -} - -static Bool -is_output_suitable_for_fullscreen(struct xwl_output *xwl_output) -{ - if (xwl_output == NULL) - return FALSE; - - if (xwl_output->width == 0 || xwl_output->height == 0) - return FALSE; - - return TRUE; -} - -static struct xwl_output * -xwl_window_get_output(struct xwl_window *xwl_window) -{ - struct xwl_screen *xwl_screen = xwl_window->xwl_screen; - struct xwl_output *xwl_output; - - xwl_output = xwl_output_get_output_from_name(xwl_screen, xwl_screen->output_name); - if (is_output_suitable_for_fullscreen(xwl_output)) - return xwl_output; - - xwl_output = xwl_output_from_wl_output(xwl_screen, xwl_window->wl_output); - if (is_output_suitable_for_fullscreen(xwl_output)) - return xwl_output; - - return xwl_screen_get_first_output(xwl_screen); -} - -static Bool -xwl_window_should_enable_viewport_fullscreen(struct xwl_window *xwl_window, - struct xwl_output **xwl_output_ret, - struct xwl_emulated_mode *emulated_mode_ret) -{ - struct xwl_screen *xwl_screen = xwl_window->xwl_screen; - struct xwl_output *xwl_output; - - xwl_output = xwl_window_get_output(xwl_window); - if (!xwl_output) - return FALSE; - - *xwl_output_ret = xwl_output; - emulated_mode_ret->server_output_id = 0; - emulated_mode_ret->width = xwl_screen_get_width(xwl_screen); - emulated_mode_ret->height = xwl_screen_get_height(xwl_screen); - emulated_mode_ret->from_vidmode = FALSE; - - return TRUE; -} - -static Bool -xwl_window_should_enable_viewport(struct xwl_window *xwl_window, - struct xwl_output **xwl_output_ret, - struct xwl_emulated_mode *emulated_mode_ret) -{ - struct xwl_screen *xwl_screen = xwl_window->xwl_screen; - struct xwl_emulated_mode *emulated_mode; - struct xwl_output *xwl_output; - ClientPtr owner; - WindowPtr window; - DrawablePtr drawable; - - if (!xwl_screen_has_viewport_support(xwl_screen)) - return FALSE; - - if (xwl_screen->fullscreen) - return xwl_window_should_enable_viewport_fullscreen(xwl_window, - xwl_output_ret, - emulated_mode_ret); - - if (!xwl_screen->rootless) - return FALSE; - - window = window_get_client_toplevel(xwl_window->toplevel); - if (!window) - return FALSE; - - owner = dixClientForWindow(window); - drawable = &window->drawable; - - /* 1. Test if the window matches the emulated mode on one of the outputs - * This path gets hit by most games / libs (e.g. SDL, SFML, OGRE) - */ - xorg_list_for_each_entry(xwl_output, &xwl_screen->output_list, link) { - emulated_mode = xwl_output_get_emulated_mode_for_client(xwl_output, owner); - if (!emulated_mode) - continue; - - if (drawable->x == xwl_output->x && - drawable->y == xwl_output->y && - drawable->width == emulated_mode->width && - drawable->height == emulated_mode->height) { - - memcpy(emulated_mode_ret, emulated_mode, sizeof(struct xwl_emulated_mode)); - *xwl_output_ret = xwl_output; - return TRUE; - } - } - - /* 2. Test if the window uses override-redirect + vidmode - * and matches (fully covers) the entire screen. - * This path gets hit by: allegro4, ClanLib-1.0. - */ - xwl_output = xwl_screen_get_first_output(xwl_screen); - emulated_mode = xwl_output_get_emulated_mode_for_client(xwl_output, owner); - if (xwl_output && xwl_window->toplevel->overrideRedirect && - emulated_mode && emulated_mode->from_vidmode && - drawable->x == 0 && drawable->y == 0 && - drawable->width == xwl_screen_get_width(xwl_screen) && - drawable->height == xwl_screen_get_height(xwl_screen)) { - - memcpy(emulated_mode_ret, emulated_mode, sizeof(struct xwl_emulated_mode)); - *xwl_output_ret = xwl_output; - return TRUE; - } - - return FALSE; -} - -static Bool -xwl_window_should_enable_fractional_scale_viewport(struct xwl_window *xwl_window) -{ - struct xwl_screen *xwl_screen = xwl_window->xwl_screen; - double scale; - - if (!xwl_screen_should_use_fractional_scale(xwl_screen)) - return FALSE; - - scale = xwl_window_get_fractional_scale_factor(xwl_window); - - return fabs(scale - 1.00) > FLT_EPSILON; -} - -static void -xwl_window_check_fractional_scale_viewport(struct xwl_window *xwl_window, - int width, int height) -{ - struct xwl_screen *xwl_screen = xwl_window->xwl_screen; - - if (!xwl_screen_should_use_fractional_scale(xwl_screen)) - return; - - if (xwl_window_should_enable_fractional_scale_viewport(xwl_window)) - xwl_window_enable_viewport_for_fractional_scale(xwl_window, width, height); - else if (xwl_window_has_viewport_enabled(xwl_window)) - xwl_window_disable_viewport(xwl_window); -} - -void -xwl_window_check_resolution_change_emulation(struct xwl_window *xwl_window) -{ - struct xwl_emulated_mode emulated_mode; - struct xwl_output *xwl_output; - - if (xwl_window_should_enable_viewport(xwl_window, &xwl_output, &emulated_mode)) - xwl_window_enable_viewport_for_output(xwl_window, xwl_output, &emulated_mode); - else if (xwl_window_should_enable_fractional_scale_viewport(xwl_window)) - return; - else if (xwl_window_has_viewport_enabled(xwl_window)) - xwl_window_disable_viewport(xwl_window); -} - -/* This checks if the passed in Window is a toplevel client window, note this - * returns false for window-manager decoration windows and returns true for - * the actual client top-level window even if it has been reparented to - * a window-manager decoration window. - */ -Bool -xwl_window_is_toplevel(WindowPtr window) -{ - if (!window->parent || window_is_wm_window(window)) - return FALSE; - - /* CSD and override-redirect toplevel windows */ - if (!window->parent->parent) - return TRUE; - - /* Normal toplevel client windows, reparented to a window-manager window */ - return window_is_wm_window(window->parent); -} - -static void -xwl_window_init_allow_commits(struct xwl_window *xwl_window) -{ - PropertyPtr prop = NULL; - int ret; - - ret = dixLookupProperty(&prop, xwl_window->toplevel, - xwl_window->xwl_screen->allow_commits_prop, - serverClient, DixReadAccess); - if (ret == Success && prop) - xwl_window_set_allow_commits_from_property(xwl_window, prop); - else - xwl_window_set_allow_commits(xwl_window, TRUE, "no property"); -} - -static uint32_t -serial_lo(uint64_t value) -{ - return value & 0xFFFFFFFFu; -} - -static uint32_t -serial_hi(uint64_t value) -{ - return value >> 32u; -} - -static void -send_window_client_message(struct xwl_window *xwl_window, Atom type_atom, uint64_t value) -{ - DeviceIntPtr dev; - xEvent e; - - e.u.u.type = ClientMessage; - e.u.u.detail = 32; - e.u.clientMessage.window = xwl_window->toplevel->drawable.id; - e.u.clientMessage.u.l.type = type_atom; - e.u.clientMessage.u.l.longs0 = serial_lo(value); - e.u.clientMessage.u.l.longs1 = serial_hi(value); - e.u.clientMessage.u.l.longs2 = 0; - e.u.clientMessage.u.l.longs3 = 0; - e.u.clientMessage.u.l.longs4 = 0; - - dev = PickPointer(serverClient); - DeliverEventsToWindow(dev, xwl_window->xwl_screen->screen->root, - &e, 1, SubstructureRedirectMask, NullGrab); -} - -static void -send_surface_id_event_serial(struct xwl_window *xwl_window) -{ - static const char atom_name[] = "WL_SURFACE_SERIAL"; - static Atom type_atom; - uint64_t serial; - - if (type_atom == None) - type_atom = MakeAtom(atom_name, strlen(atom_name), TRUE); - - serial = ++xwl_window->xwl_screen->surface_association_serial; - - send_window_client_message(xwl_window, type_atom, serial); - xwayland_surface_v1_set_serial(xwl_window->xwayland_surface, - serial_lo(serial), serial_hi(serial)); - wl_surface_commit(xwl_window->surface); - - /* Flush wayland display *after* commit in the new path. */ - wl_display_flush(xwl_window->xwl_screen->display); -} - -static void -send_surface_id_event_legacy(struct xwl_window *xwl_window) -{ - static const char atom_name[] = "WL_SURFACE_ID"; - static Atom type_atom; - uint32_t surface_id; - - if (type_atom == None) - type_atom = MakeAtom(atom_name, strlen(atom_name), TRUE); - - surface_id = wl_proxy_get_id((struct wl_proxy *) xwl_window->surface); - - /* Flush wayland display *before* setting the atom in the legacy path */ - wl_display_flush(xwl_window->xwl_screen->display); - - send_window_client_message(xwl_window, type_atom, (uint64_t)surface_id); -} - -static void -send_surface_id_event(struct xwl_window *xwl_window) -{ - return xwl_window->xwayland_surface - ? send_surface_id_event_serial(xwl_window) - : send_surface_id_event_legacy(xwl_window); - -} - -static Bool -xwl_window_set_fullscreen(struct xwl_window *xwl_window) -{ - struct xwl_output *xwl_output; - struct wl_output *wl_output = NULL; - - if (!xwl_window->xdg_toplevel) - return FALSE; - - xwl_output = xwl_window_get_output(xwl_window); - if (xwl_output) - wl_output = xwl_output->output; - - if (wl_output && xwl_window->wl_output_fullscreen == wl_output) - return FALSE; - - xdg_toplevel_set_fullscreen(xwl_window->xdg_toplevel, wl_output); - xwl_window_check_resolution_change_emulation(xwl_window); - wl_surface_commit(xwl_window->surface); - - xwl_window->wl_output_fullscreen = wl_output; - - return TRUE; -} - -void -xwl_window_rootful_update_fullscreen(struct xwl_window *xwl_window, - struct xwl_output *xwl_output) -{ - struct xwl_screen *xwl_screen = xwl_window->xwl_screen; - - if (!xwl_screen->fullscreen) - return; - - if (xwl_window->toplevel != xwl_screen->screen->root) - return; - - if (xwl_window->wl_output_fullscreen != xwl_output->output) - return; - - /* The size and position of the output may have changed, clear our - * output to make sure the next call to xwl_window_set_fullscreen() - * recomputes the size and updates the viewport as needed. - */ - xwl_window->wl_output_fullscreen = NULL; - xwl_window_set_fullscreen(xwl_window); -} - -void -xwl_window_rootful_update_title(struct xwl_window *xwl_window) -{ - struct xwl_screen *xwl_screen = xwl_window->xwl_screen; - char title[128]; - const char *grab_message = ""; - - if (xwl_screen->host_grab) { - if (xwl_screen->has_grab) - grab_message = " - ([ctrl]+[shift] releases mouse and keyboard)"; - else - grab_message = " - ([ctrl]+[shift] grabs mouse and keyboard)"; - } - - snprintf(title, sizeof(title), "Xwayland on :%s%s", display, grab_message); - -#ifdef XWL_HAS_LIBDECOR - if (xwl_window->libdecor_frame) - libdecor_frame_set_title(xwl_window->libdecor_frame, title); - else -#endif - if (xwl_window->xdg_toplevel) - xdg_toplevel_set_title(xwl_window->xdg_toplevel, title); -} - -static void -xwl_window_rootful_set_app_id(struct xwl_window *xwl_window) -{ - const char *app_id = "org.freedesktop.Xwayland"; - -#ifdef XWL_HAS_LIBDECOR - if (xwl_window->libdecor_frame) - libdecor_frame_set_app_id(xwl_window->libdecor_frame, app_id); - else -#endif - if (xwl_window->xdg_toplevel) - xdg_toplevel_set_app_id(xwl_window->xdg_toplevel, app_id); -} - -static void -xwl_window_maybe_resize(struct xwl_window *xwl_window, double width, double height) -{ - struct xwl_screen *xwl_screen = xwl_window->xwl_screen; - struct xwl_output *xwl_output; - double scale; - RRModePtr mode; - - /* Clamp the size */ - width = min(max(width, MIN_ROOTFUL_WIDTH), MAX_ROOTFUL_WIDTH); - height = min(max(height, MIN_ROOTFUL_HEIGHT), MAX_ROOTFUL_HEIGHT); - - /* Make sure the size is a multiple of the scale, it's a protocol error otherwise. */ - scale = xwl_screen->global_surface_scale; - if (scale > 1.0) { - width = round(width / scale) * scale; - height = round(height / scale) * scale; - } - - if (width == xwl_screen->width && height == xwl_screen->height) - return; - - xwl_screen->width = width; - xwl_screen->height = height; - - /* When fractional scale is used, the global surface scale is 1, and vice - * versa, so we can multiply the two here, and have the resulting scale - * apply for both cases, the legacy wl_surface buffer scale and fractional - * scaling. - */ - scale *= xwl_window_get_fractional_scale_factor(xwl_window); - - xwl_output = xwl_screen_get_fixed_or_first_output(xwl_screen); - if (!xwl_randr_add_modes_fixed(xwl_output, round(width / scale), round(height / scale))) - return; - - mode = xwl_output_find_mode(xwl_output, round(width / scale), round(height / scale)); - xwl_output_set_mode_fixed(xwl_output, mode); - - xwl_window_attach_buffer(xwl_window); -} - -#ifdef XWL_HAS_LIBDECOR -static void -xwl_window_libdecor_set_size_limits(struct xwl_window *xwl_window) -{ - struct xwl_screen *xwl_screen = xwl_window->xwl_screen; - - libdecor_frame_set_min_content_size(xwl_window->libdecor_frame, - MIN_ROOTFUL_WIDTH / - xwl_screen->global_surface_scale, - MIN_ROOTFUL_HEIGHT / - xwl_screen->global_surface_scale); - libdecor_frame_set_max_content_size(xwl_window->libdecor_frame, - MAX_ROOTFUL_WIDTH / - xwl_screen->global_surface_scale, - MAX_ROOTFUL_HEIGHT / - xwl_screen->global_surface_scale); -} - -static void -xwl_window_update_libdecor_size(struct xwl_window *xwl_window, - struct libdecor_configuration *configuration /* nullable */, - int width, int height) -{ - struct libdecor_state *state; - double scale; - - if (xwl_window->libdecor_frame) { - scale = xwl_window_get_fractional_scale_factor(xwl_window); - state = libdecor_state_new(round((double) width / scale), - round((double) height / scale)); - libdecor_frame_commit(xwl_window->libdecor_frame, state, configuration); - libdecor_state_free(state); - } -} - -static void -handle_libdecor_configure(struct libdecor_frame *frame, - struct libdecor_configuration *configuration, - void *data) -{ - struct xwl_window *xwl_window = data; - struct xwl_screen *xwl_screen = xwl_window->xwl_screen; - int width, height; - double new_width, new_height; - double scale; - - if (libdecor_configuration_get_content_size(configuration, frame, &width, &height)) { - new_width = (double) width; - new_height = (double) height; - } - else { - new_width = xwl_screen->width / xwl_screen->global_surface_scale; - new_height = xwl_screen->height / xwl_screen->global_surface_scale; - } - - new_width *= xwl_screen->global_surface_scale; - new_height *= xwl_screen->global_surface_scale; - - scale = xwl_window_get_fractional_scale_factor(xwl_window); - new_width *= scale; - new_height *= scale; - - xwl_window_maybe_resize(xwl_window, new_width, new_height); - - new_width = xwl_screen->width / xwl_screen->global_surface_scale; - new_height = xwl_screen->height / xwl_screen->global_surface_scale; - - xwl_window_update_libdecor_size(xwl_window, configuration, - round(new_width), round(new_height)); - wl_surface_commit(xwl_window->surface); -} - -static void -handle_libdecor_close(struct libdecor_frame *frame, - void *data) -{ - DebugF("Terminating on compositor request"); - GiveUp(0); -} - -static void -handle_libdecor_commit(struct libdecor_frame *frame, - void *data) -{ - struct xwl_window *xwl_window = data; - wl_surface_commit(xwl_window->surface); -} - -static void -handle_libdecor_dismiss_popup(struct libdecor_frame *frame, - const char *seat_name, - void *data) -{ -} - -static struct libdecor_frame_interface libdecor_frame_iface = { - handle_libdecor_configure, - handle_libdecor_close, - handle_libdecor_commit, - handle_libdecor_dismiss_popup, -}; -#endif - -static void -xdg_surface_handle_configure(void *data, - struct xdg_surface *xdg_surface, - uint32_t serial) -{ - struct xwl_window *xwl_window = data; - struct xwl_screen *xwl_screen = xwl_window->xwl_screen; - - if (xwl_screen->fullscreen) - xwl_window_set_fullscreen(xwl_window); - - xdg_surface_ack_configure(xdg_surface, serial); - wl_surface_commit(xwl_window->surface); -} - -static const struct xdg_surface_listener xdg_surface_listener = { - xdg_surface_handle_configure, -}; - -static void -xwl_window_update_surface_scale(struct xwl_window *xwl_window) -{ - struct xwl_screen *xwl_screen = xwl_window->xwl_screen; - int previous_scale, new_scale; - double new_width, new_height; - - previous_scale = xwl_screen->global_surface_scale; - assert(previous_scale != 0); - xwl_window->surface_scale = xwl_window_get_max_output_scale(xwl_window); - - if (xwl_screen_update_global_surface_scale(xwl_screen)) { - new_scale = xwl_screen->global_surface_scale; - - DebugF("XWAYLAND: Global scale is now %i (was %i)\n", - new_scale, previous_scale); - - new_width = xwl_screen->width / previous_scale * new_scale; - new_height = xwl_screen->height / previous_scale * new_scale; - - wl_surface_set_buffer_scale(xwl_window->surface, xwl_screen->global_surface_scale); - /* Reflect the scale factor using XRandR transform */ - xwl_output_set_xscale(xwl_screen->fixed_output, new_scale); - xwl_window_maybe_resize(xwl_window, new_width, new_height); -#ifdef XWL_HAS_LIBDECOR - if (xwl_window->libdecor_frame) { - xwl_window_libdecor_set_size_limits(xwl_window); - xwl_window_update_libdecor_size(xwl_window, - NULL, - round(new_width / new_scale), - round(new_height / new_scale)); - } - else -#endif - wl_surface_commit(xwl_window->surface); - } -} - -static void -xwl_window_enter_output(struct xwl_window *xwl_window, struct xwl_output *xwl_output) -{ - struct xwl_window_output *window_output; - - window_output = XNFcallocarray(1, sizeof(struct xwl_window_output)); - window_output->xwl_output = xwl_output; - xorg_list_add(&window_output->link, &xwl_window->xwl_output_list); -} - -void -xwl_window_leave_output(struct xwl_window *xwl_window, struct xwl_output *xwl_output) -{ - struct xwl_window_output *window_output, *tmp; - - xorg_list_for_each_entry_safe(window_output, tmp, &xwl_window->xwl_output_list, link) { - if (window_output->xwl_output == xwl_output) { - xorg_list_del(&window_output->link); - free(window_output); - } - } -} - -static void -xwl_window_free_outputs(struct xwl_window *xwl_window) -{ - struct xwl_window_output *window_output, *tmp; - - xorg_list_for_each_entry_safe(window_output, tmp, &xwl_window->xwl_output_list, link) { - xorg_list_del(&window_output->link); - free(window_output); - } -} - -int -xwl_window_get_max_output_scale(struct xwl_window *xwl_window) -{ - struct xwl_window_output *window_output; - struct xwl_output *xwl_output; - int scale = 1; - - xorg_list_for_each_entry(window_output, &xwl_window->xwl_output_list, link) { - xwl_output = window_output->xwl_output; - if (xwl_output->scale > scale) - scale = xwl_output->scale; - } - - return scale; -} - -static void -xwl_window_surface_enter(void *data, - struct wl_surface *wl_surface, - struct wl_output *wl_output) -{ - struct xwl_window *xwl_window = data; - struct xwl_screen *xwl_screen = xwl_window->xwl_screen; - struct xwl_output *xwl_output = xwl_output_from_wl_output(xwl_screen, wl_output); - - if (xwl_output) { - xwl_window_enter_output(xwl_window, xwl_output); - xwl_window_update_surface_scale(xwl_window); - } - - if (xwl_window->wl_output != wl_output) { - xwl_window->wl_output = wl_output; - - if (xwl_screen->fullscreen) - xwl_window_set_fullscreen(xwl_window); - } -} - -static void -xwl_window_surface_leave(void *data, - struct wl_surface *wl_surface, - struct wl_output *wl_output) -{ - struct xwl_window *xwl_window = data; - struct xwl_screen *xwl_screen = xwl_window->xwl_screen; - struct xwl_output *xwl_output = xwl_output_from_wl_output(xwl_screen, wl_output); - - if (xwl_output) { - xwl_window_leave_output(xwl_window, xwl_output); - xwl_window_update_surface_scale(xwl_window); - } - - if (xwl_window->wl_output == wl_output) - xwl_window->wl_output = NULL; -} - -static const struct wl_surface_listener surface_listener = { - xwl_window_surface_enter, - xwl_window_surface_leave -}; - -static void -xdg_toplevel_handle_configure(void *data, - struct xdg_toplevel *xdg_toplevel, - int32_t width, - int32_t height, - struct wl_array *states) -{ - struct xwl_window *xwl_window = data; - struct xwl_screen *xwl_screen = xwl_window->xwl_screen; - uint32_t *p; - Bool old_active = xwl_screen->active; - double scale, new_width, new_height; - - /* Maintain our current size if no dimensions are requested */ - if (width == 0 && height == 0) - return; - - if (!xwl_screen->fullscreen) { - new_width = (double) (width * xwl_screen->global_surface_scale); - new_height = (double) (height * xwl_screen->global_surface_scale); - - scale = xwl_window_get_fractional_scale_factor(xwl_window); - new_width *= scale; - new_height *= scale; - - /* This will be committed by the xdg_surface.configure handler */ - xwl_window_maybe_resize(xwl_window, new_width, new_height); - } - - xwl_screen->active = FALSE; - wl_array_for_each (p, states) { - uint32_t state = *p; - if (state == XDG_TOPLEVEL_STATE_ACTIVATED) { - xwl_screen->active = TRUE; - break; - } - } - - if (old_active != xwl_screen->active) { - if (!xwl_screen->active) - xwl_screen_lost_focus(xwl_screen); - } -} - -static void -xdg_toplevel_handle_close(void *data, - struct xdg_toplevel *xdg_toplevel) -{ - DebugF("Terminating on compositor request"); - GiveUp(0); -} - -static const struct xdg_toplevel_listener xdg_toplevel_listener = { - xdg_toplevel_handle_configure, - xdg_toplevel_handle_close, -}; - -static void -xwl_window_update_rootful_scale(struct xwl_window *xwl_window, double previous_scale) -{ - struct xwl_screen *xwl_screen = xwl_window->xwl_screen; - double new_scale, new_width, new_height; - - new_scale = xwl_window_get_fractional_scale_factor(xwl_window); - new_width = xwl_screen->width / previous_scale * new_scale; - new_height = xwl_screen->height / previous_scale * new_scale; - - DebugF("XWAYLAND: Fractional scale is now %.2f (was %.2f)\n", - new_scale, previous_scale); - - xwl_output_set_xscale(xwl_screen->fixed_output, new_scale); - xwl_window_maybe_resize(xwl_window, new_width, new_height); - xwl_window_check_fractional_scale_viewport(xwl_window, - xwl_screen_get_width(xwl_screen), - xwl_screen_get_height(xwl_screen)); - -#ifdef XWL_HAS_LIBDECOR - if (xwl_window->libdecor_frame) { - xwl_window_libdecor_set_size_limits(xwl_window); - xwl_window_update_libdecor_size(xwl_window, - NULL, - xwl_screen_get_width(xwl_screen), - xwl_screen_get_height(xwl_screen)); - } - else -#endif - wl_surface_commit(xwl_window->surface); -} - -static void -wp_fractional_scale_preferred_scale(void *data, - struct wp_fractional_scale_v1 *fractional_scale, - uint32_t scale_numerator) -{ - struct xwl_window *xwl_window = data; - struct xwl_screen *xwl_screen = xwl_window->xwl_screen; - double previous_scale = xwl_window_get_fractional_scale_factor(xwl_window); - - if (xwl_window_update_fractional_scale(xwl_window, scale_numerator)) { - if (xwl_screen->fixed_output) { /* We're running rootful */ - xwl_window_update_rootful_scale(xwl_window, previous_scale); - } - } -} - -static const struct wp_fractional_scale_v1_listener fractional_scale_listener = { - wp_fractional_scale_preferred_scale, -}; - -static Bool -xwl_create_root_surface(struct xwl_window *xwl_window) -{ - struct xwl_screen *xwl_screen = xwl_window->xwl_screen; - WindowPtr window = xwl_window->toplevel; - struct wl_region *region; - - -#ifdef XWL_HAS_LIBDECOR - if (xwl_screen->decorate) { - xwl_window->libdecor_frame = - libdecor_decorate(xwl_screen->libdecor_context, - xwl_window->surface, - &libdecor_frame_iface, - xwl_window); - xwl_window_libdecor_set_size_limits(xwl_window); - libdecor_frame_map(xwl_window->libdecor_frame); - } - else -#endif - { - xwl_window->xdg_surface = - xdg_wm_base_get_xdg_surface(xwl_screen->xdg_wm_base, xwl_window->surface); - if (xwl_window->xdg_surface == NULL) { - ErrorF("Failed creating xdg_wm_base xdg_surface\n"); - goto err_surf; - } - - xwl_window->xdg_toplevel = - xdg_surface_get_toplevel(xwl_window->xdg_surface); - if (xwl_window->xdg_surface == NULL) { - ErrorF("Failed creating xdg_toplevel\n"); - goto err_surf; - } - - xdg_surface_add_listener(xwl_window->xdg_surface, - &xdg_surface_listener, xwl_window); - - xdg_toplevel_add_listener(xwl_window->xdg_toplevel, - &xdg_toplevel_listener, - xwl_window); - } - - wl_surface_add_listener(xwl_window->surface, - &surface_listener, xwl_window); - - if (xwl_screen_should_use_fractional_scale(xwl_screen)) { - xwl_window->fractional_scale = - wp_fractional_scale_manager_v1_get_fractional_scale(xwl_screen->fractional_scale_manager, - xwl_window->surface); - wp_fractional_scale_v1_add_listener(xwl_window->fractional_scale, - &fractional_scale_listener, xwl_window); - } - - xwl_window_rootful_update_title(xwl_window); - xwl_window_rootful_set_app_id(xwl_window); - wl_surface_commit(xwl_window->surface); - - region = wl_compositor_create_region(xwl_screen->compositor); - if (region == NULL) { - ErrorF("Failed creating region\n"); - goto err_surf; - } - - wl_region_add(region, 0, 0, - window->drawable.width, window->drawable.height); - wl_surface_set_opaque_region(xwl_window->surface, region); - wl_region_destroy(region); - - return TRUE; - -err_surf: - if (xwl_window->xdg_toplevel) - xdg_toplevel_destroy(xwl_window->xdg_toplevel); - if (xwl_window->xdg_surface) - xdg_surface_destroy(xwl_window->xdg_surface); - wl_surface_destroy(xwl_window->surface); - - return FALSE; -} - -void -xwl_window_update_surface_window(struct xwl_window *xwl_window) -{ - WindowPtr surface_window = xwl_window->toplevel; - ScreenPtr screen = surface_window->drawable.pScreen; - PixmapPtr surface_pixmap; - DamagePtr window_damage; - RegionRec damage_region; - WindowPtr window; - - surface_pixmap = screen->GetWindowPixmap(surface_window); - - for (window = surface_window->firstChild; window; window = window->firstChild) { - PixmapPtr window_pixmap; - - if (!RegionEqual(&window->winSize, &surface_window->winSize)) - break; - - if (!window->mapped) - break; - - /* The surface window must be top-level for its window pixmap */ - window_pixmap = screen->GetWindowPixmap(window); - if (window_pixmap == surface_pixmap) - continue; - - surface_pixmap = window_pixmap; - - /* A descendant with alpha channel cannot be the surface window, since - * any non-opaque areas need to take the contents of ancestors into - * account. - */ - if (window->drawable.depth == 32) - continue; - - if (window->redirectDraw == RedirectDrawManual && - !xwl_present_window_redirected(window)) - break; - - surface_window = window; - } - - if (xwl_window->surface_window == surface_window) - return; - - if (xwl_window->surface_window_damage) { - if (xwl_present_maybe_unredirect_window(xwl_window->surface_window) && - screen->SourceValidate == xwl_source_validate) { - WindowPtr toplevel = xwl_window->toplevel; - - xwl_source_validate(&toplevel->drawable, - toplevel->drawable.x, toplevel->drawable.y, - toplevel->drawable.width, - toplevel->drawable.height, - IncludeInferiors); - } - - if (RegionNotEmpty(xwl_window->surface_window_damage)) - need_source_validate_dec(xwl_window->xwl_screen); - - RegionDestroy(xwl_window->surface_window_damage); - xwl_window->surface_window_damage = NULL; - } - - window_damage = window_get_damage(xwl_window->surface_window); - if (window_damage) { - RegionInit(&damage_region, NullBox, 1); - RegionCopy(&damage_region, DamageRegion(window_damage)); - unregister_damage(xwl_window); - } - - if (surface_window->drawable.depth != xwl_window->surface_window->drawable.depth) - xwl_window_buffers_dispose(xwl_window, FALSE); - - xwl_window->surface_window = surface_window; - register_damage(xwl_window); - - if (window_damage) { - RegionPtr new_region = DamageRegion(window_get_damage(surface_window)); - - RegionUnion(new_region, new_region, &damage_region); - RegionUninit(&damage_region); - } -} - -static struct xwl_window * -ensure_surface_for_window(WindowPtr window) -{ - ScreenPtr screen = window->drawable.pScreen; - struct xwl_screen *xwl_screen; - struct xwl_window *xwl_window; - WindowPtr toplevel; - - xwl_window = xwl_window_from_window(window); - if (xwl_window) - return xwl_window; - - xwl_screen = xwl_screen_get(screen); - - if (xwl_screen->rootless) { - if (window->redirectDraw != RedirectDrawManual) - return NULL; - } - else { - if (window->parent) - return NULL; - } - - xwl_window = calloc(1, sizeof *xwl_window); - if (xwl_window == NULL) - return NULL; - - xwl_window->xwl_screen = xwl_screen; - xwl_window->toplevel = window; - xwl_window->surface_window = window; - xwl_window->fractional_scale_numerator = FRACTIONAL_SCALE_DENOMINATOR; - xwl_window->viewport_scale_x = 1.0; - xwl_window->viewport_scale_y = 1.0; - xwl_window->surface_scale = 1; - xorg_list_init(&xwl_window->xwl_output_list); - xwl_window->surface = wl_compositor_create_surface(xwl_screen->compositor); - if (xwl_window->surface == NULL) { - ErrorF("wl_display_create_surface failed\n"); - goto err; - } - - if (xwl_screen->xwayland_shell) { - xwl_window->xwayland_surface = xwayland_shell_v1_get_xwayland_surface( - xwl_screen->xwayland_shell, xwl_window->surface); - } - - if (!xwl_screen->rootless && !xwl_create_root_surface(xwl_window)) - goto err; - -#ifdef XWL_HAS_GLAMOR - if (xwl_screen->dmabuf_protocol_version >= 4) - xwl_dmabuf_setup_feedback_for_window(xwl_window); -#endif - - wl_display_flush(xwl_screen->display); - - send_surface_id_event(xwl_window); - - wl_surface_set_user_data(xwl_window->surface, xwl_window); - xwl_window_set_xwayland_tag(xwl_window); - - compRedirectWindow(serverClient, window, CompositeRedirectManual); - - dixSetPrivate(&window->devPrivates, &xwl_window_private_key, xwl_window); - xorg_list_init(&xwl_window->link_damage); - xorg_list_add(&xwl_window->link_window, &xwl_screen->window_list); - xorg_list_init(&xwl_window->frame_callback_list); - - xwl_window_buffers_init(xwl_window); - - xwl_window_update_surface_window(xwl_window); - - xwl_window_init_allow_commits(xwl_window); - - /* When a new window-manager window is realized, then the randr emulation - * props may have not been set on the managed client window yet. - */ - if (!xwl_screen->fullscreen && window_is_wm_window(window)) { - toplevel = window_get_client_toplevel(window); - if (toplevel) - xwl_output_set_window_randr_emu_props(xwl_screen, toplevel); - } else { - /* CSD or O-R toplevel window, check viewport on creation */ - xwl_window_check_resolution_change_emulation(xwl_window); - } - - if (xwl_screen->tearing_control_manager) { - xwl_window->tearing_control = wp_tearing_control_manager_v1_get_tearing_control( - xwl_screen->tearing_control_manager, xwl_window->surface); - } - - xwl_window_set_input_region(xwl_window, wInputShape(window)); - - return xwl_window; - -err: - free(xwl_window); - return NULL; -} - -Bool -xwl_realize_window(WindowPtr window) -{ - ScreenPtr screen = window->drawable.pScreen; - CompScreenPtr comp_screen = GetCompScreen(screen); - struct xwl_screen *xwl_screen; - struct xwl_window *xwl_window; - Bool ret; - - xwl_screen = xwl_screen_get(screen); - - screen->RealizeWindow = xwl_screen->RealizeWindow; - ret = (*screen->RealizeWindow) (window); - xwl_screen->RealizeWindow = screen->RealizeWindow; - screen->RealizeWindow = xwl_realize_window; - - if (!ret) - return FALSE; - - if (xwl_screen->rootless) { - /* We do not want the COW to be mapped when rootless in Xwayland */ - if (window == comp_screen->pOverlayWin) { - window->mapped = FALSE; - return TRUE; - } - - if (!window->parent) { - BoxRec box = { - 0, - 0, - xwl_screen_get_width(xwl_screen), - xwl_screen_get_height(xwl_screen) - }; - - RegionReset(&window->winSize, &box); - RegionNull(&window->clipList); - RegionNull(&window->borderClip); - } - } - - xwl_window = ensure_surface_for_window(window); - if (!xwl_window) - return FALSE; - - if (window == xwl_window->surface_window && - !window_get_damage(window)) - return register_damage(xwl_window); - - return TRUE; -} - -static void -xwl_surface_destroy_free_timer(struct xwl_wl_surface *xwl_wl_surface) -{ - if (xwl_wl_surface->wl_surface_destroy_timer) { - TimerFree(xwl_wl_surface->wl_surface_destroy_timer); - xwl_wl_surface->wl_surface_destroy_timer = NULL; - } -} - -void -xwl_window_surface_do_destroy(struct xwl_wl_surface *xwl_wl_surface) -{ - wl_surface_destroy(xwl_wl_surface->wl_surface); - xorg_list_del(&xwl_wl_surface->link); - xwl_surface_destroy_free_timer(xwl_wl_surface); - free(xwl_wl_surface); -} - -static CARD32 -xwl_surface_destroy_callback(OsTimerPtr timer, CARD32 now, void *arg) -{ - struct xwl_wl_surface *xwl_wl_surface = arg; - - xwl_window_surface_do_destroy(xwl_wl_surface); - - return 0; -} - -static void -release_wl_surface_for_window_legacy_delay(struct xwl_window *xwl_window) -{ - struct xwl_wl_surface *xwl_wl_surface; - - /* If the Xserver is terminating, destroy the surface immediately */ - if ((dispatchException & DE_TERMINATE) == DE_TERMINATE) { - wl_surface_destroy(xwl_window->surface); - return; - } - - /* Break the wl_surface / xwl_window relationship */ - wl_surface_set_user_data(xwl_window->surface, NULL); - xwl_window_clear_xwayland_tag(xwl_window); - - /* Schedule the destruction later, to mitigate the race between X11 - * and Wayland processing so that the compositor has the time to - * establish the association before the wl_surface is destroyed. - */ - xwl_wl_surface = XNFcallocarray(1, sizeof *xwl_wl_surface); - xwl_wl_surface->wl_surface = xwl_window->surface; - xorg_list_add(&xwl_wl_surface->link, - &xwl_window->xwl_screen->pending_wl_surface_destroy); - xwl_wl_surface->wl_surface_destroy_timer = - TimerSet(NULL, 0, DELAYED_WL_SURFACE_DESTROY, - xwl_surface_destroy_callback, xwl_wl_surface); -} - -static void -release_wl_surface_for_window_shell(struct xwl_window *xwl_window) -{ - xwayland_surface_v1_destroy(xwl_window->xwayland_surface); - wl_surface_destroy(xwl_window->surface); -} - -static void -release_wl_surface_for_window(struct xwl_window *xwl_window) -{ - if (xwl_window->xwayland_surface) - release_wl_surface_for_window_shell(xwl_window); - else - release_wl_surface_for_window_legacy_delay(xwl_window); -} - -static void -xwl_window_dispose(struct xwl_window *xwl_window) -{ - struct xwl_screen *xwl_screen = xwl_window->xwl_screen; - struct xwl_seat *xwl_seat; - WindowPtr window = xwl_window->toplevel; - ScreenPtr screen = xwl_screen->screen; - - compUnredirectWindow(serverClient, window, CompositeRedirectManual); - - xorg_list_for_each_entry(xwl_seat, &xwl_screen->seat_list, link) { - if (xwl_seat->focus_window == xwl_window) - xwl_seat->focus_window = NULL; - if (xwl_seat->tablet_focus_window == xwl_window) - xwl_seat->tablet_focus_window = NULL; - if (xwl_seat->last_focus_window == xwl_window) - xwl_seat->last_focus_window = NULL; - if (xwl_seat->cursor_confinement_window == xwl_window) - xwl_seat_unconfine_pointer(xwl_seat); - if (xwl_seat->pointer_warp_emulator && - xwl_seat->pointer_warp_emulator->locked_window == xwl_window) - xwl_seat_destroy_pointer_warp_emulator(xwl_seat); - xwl_seat_clear_touch(xwl_seat, xwl_window); - } - - if (xwl_window_has_viewport_enabled(xwl_window)) - xwl_window_disable_viewport(xwl_window); -#ifdef XWL_HAS_GLAMOR - xwl_dmabuf_feedback_destroy(&xwl_window->feedback); - -#ifdef GLAMOR_HAS_GBM - if (xwl_window->xwl_screen->present) - xwl_present_for_each_frame_callback(xwl_window, xwl_present_unrealize_window); -#endif /* GLAMOR_HAS_GBM */ -#endif /* XWL_HAS_GLAMOR */ - - if (xwl_window->tearing_control) - wp_tearing_control_v1_destroy(xwl_window->tearing_control); - - if (xwl_window->fractional_scale) - wp_fractional_scale_v1_destroy(xwl_window->fractional_scale); - - if (xwl_window->surface_sync) - wp_linux_drm_syncobj_surface_v1_destroy(xwl_window->surface_sync); - - release_wl_surface_for_window(xwl_window); - xorg_list_del(&xwl_window->link_damage); - xorg_list_del(&xwl_window->link_window); - - /* Special case for the root window in rootful mode */ - xwl_window_buffers_dispose(xwl_window, - (!xwl_screen->rootless && window == screen->root)); - - if (xwl_window->window_buffers_timer) - TimerFree(xwl_window->window_buffers_timer); - - if (xwl_window->frame_callback) - wl_callback_destroy(xwl_window->frame_callback); - - xwl_window_free_outputs(xwl_window); - - free(xwl_window); - dixSetPrivate(&window->devPrivates, &xwl_window_private_key, NULL); -} - -Bool -xwl_unrealize_window(WindowPtr window) -{ - ScreenPtr screen = window->drawable.pScreen; - struct xwl_screen *xwl_screen = xwl_screen_get(screen); - struct xwl_window *xwl_window = xwl_window_get(window); - Bool ret; - - if (xwl_window) { - unregister_damage(xwl_window); - xwl_window_dispose(xwl_window); - } - - screen->UnrealizeWindow = xwl_screen->UnrealizeWindow; - ret = (*screen->UnrealizeWindow) (window); - xwl_screen->UnrealizeWindow = screen->UnrealizeWindow; - screen->UnrealizeWindow = xwl_unrealize_window; - - return ret; -} - -void -xwl_window_set_window_pixmap(WindowPtr window, - PixmapPtr pixmap) -{ - ScreenPtr screen = window->drawable.pScreen; - struct xwl_screen *xwl_screen; - struct xwl_window *xwl_window; - PixmapPtr old_pixmap; - - old_pixmap = (*screen->GetWindowPixmap) (window); - xwl_screen = xwl_screen_get(screen); - - screen->SetWindowPixmap = xwl_screen->SetWindowPixmap; - (*screen->SetWindowPixmap) (window, pixmap); - xwl_screen->SetWindowPixmap = screen->SetWindowPixmap; - screen->SetWindowPixmap = xwl_window_set_window_pixmap; - - if (!RegionNotEmpty(&window->winSize)) - return; - - xwl_window = ensure_surface_for_window(window); - - if (!xwl_window || - (old_pixmap->drawable.width == pixmap->drawable.width && - old_pixmap->drawable.height == pixmap->drawable.height)) - return; - - xwl_window_buffers_dispose(xwl_window, FALSE); -} - -Bool -xwl_change_window_attributes(WindowPtr window, unsigned long mask) -{ - ScreenPtr screen = window->drawable.pScreen; - struct xwl_screen *xwl_screen = xwl_screen_get(screen); - OtherClients *others; - Bool ret; - - screen->ChangeWindowAttributes = xwl_screen->ChangeWindowAttributes; - ret = (*screen->ChangeWindowAttributes) (window, mask); - xwl_screen->ChangeWindowAttributes = screen->ChangeWindowAttributes; - screen->ChangeWindowAttributes = xwl_change_window_attributes; - - if (window != screen->root || !(mask & CWEventMask)) - return ret; - - for (others = wOtherClients(window); others; others = others->next) { - if (others->mask & (SubstructureRedirectMask | ResizeRedirectMask)) - xwl_screen->wm_client_id = dixClientIdForXID(others->resource); - } - - return ret; -} - -void -xwl_clip_notify(WindowPtr window, int dx, int dy) -{ - ScreenPtr screen = window->drawable.pScreen; - struct xwl_screen *xwl_screen = xwl_screen_get(screen); - struct xwl_window *xwl_window = xwl_window_from_window(window); - - screen->ClipNotify = xwl_screen->ClipNotify; - (*screen->ClipNotify) (window, dx, dy); - xwl_screen->ClipNotify = screen->ClipNotify; - screen->ClipNotify = xwl_clip_notify; - - if (xwl_window) - xwl_window_update_surface_window(xwl_window); -} - -int -xwl_config_notify(WindowPtr window, - int x, int y, - int width, int height, int bw, - WindowPtr sib) -{ - ScreenPtr screen = window->drawable.pScreen; - struct xwl_screen *xwl_screen; - struct xwl_window *xwl_window; - Bool size_changed; - int ret; - - xwl_screen = xwl_screen_get(screen); - xwl_window = xwl_window_from_window(window); - - size_changed = width != window->drawable.width || height != window->drawable.height; - if (size_changed && xwl_window && xwl_window->toplevel == window && - screen->SourceValidate == xwl_source_validate) { - xwl_source_validate(&window->drawable, window->drawable.x, window->drawable.y, - window->drawable.width, window->drawable.height, - IncludeInferiors); - } - - screen->ConfigNotify = xwl_screen->ConfigNotify; - ret = screen->ConfigNotify(window, x, y, width, height, bw, sib); - xwl_screen->ConfigNotify = screen->ConfigNotify; - screen->ConfigNotify = xwl_config_notify; - - return ret; -} - -void -xwl_resize_window(WindowPtr window, - int x, int y, - unsigned int width, unsigned int height, - WindowPtr sib) -{ - ScreenPtr screen = window->drawable.pScreen; - struct xwl_screen *xwl_screen; - struct xwl_window *xwl_window; - - xwl_screen = xwl_screen_get(screen); - xwl_window = xwl_window_from_window(window); - - screen->ResizeWindow = xwl_screen->ResizeWindow; - screen->ResizeWindow(window, x, y, width, height, sib); - xwl_screen->ResizeWindow = screen->ResizeWindow; - screen->ResizeWindow = xwl_resize_window; - - if (xwl_window) { - if (xwl_window_get(window) || xwl_window_is_toplevel(window)) - xwl_window_check_resolution_change_emulation(xwl_window); - if (window == screen->root) { -#ifdef XWL_HAS_LIBDECOR - unsigned int decor_width, decor_height; - - decor_width = width / xwl_screen->global_surface_scale; - decor_height = height / xwl_screen->global_surface_scale; - xwl_window_update_libdecor_size(xwl_window, NULL, - decor_width, decor_height); -#endif - xwl_window_check_fractional_scale_viewport(xwl_window, width, height); - } - } -} - -void -xwl_move_window(WindowPtr window, - int x, int y, - WindowPtr next_sib, - VTKind kind) -{ - ScreenPtr screen = window->drawable.pScreen; - struct xwl_screen *xwl_screen; - struct xwl_window *xwl_window; - - xwl_screen = xwl_screen_get(screen); - xwl_window = xwl_window_from_window(window); - - screen->MoveWindow = xwl_screen->MoveWindow; - (*screen->MoveWindow) (window, x, y, next_sib, kind); - xwl_screen->MoveWindow = screen->MoveWindow; - screen->MoveWindow = xwl_move_window; - - if (xwl_window && (xwl_window_get(window) || xwl_window_is_toplevel(window))) - xwl_window_check_resolution_change_emulation(xwl_window); -} - -static void -frame_callback(void *data, - struct wl_callback *callback, - uint32_t time) -{ - struct xwl_window *xwl_window = data; - - wl_callback_destroy (xwl_window->frame_callback); - xwl_window->frame_callback = NULL; - - if (xwl_window->xwl_screen->present) { - xwl_present_for_each_frame_callback(xwl_window, xwl_present_frame_callback); - - /* If xwl_window_create_frame_callback was called from - * xwl_present_frame_callback, need to make sure all fallback timers - * are adjusted correspondingly. - */ - if (xwl_window->frame_callback) - xwl_present_for_each_frame_callback(xwl_window, xwl_present_reset_timer); - } -} - -static const struct wl_callback_listener frame_listener = { - frame_callback -}; - -void -xwl_window_create_frame_callback(struct xwl_window *xwl_window) -{ - xwl_window->frame_callback = wl_surface_frame(xwl_window->surface); - wl_callback_add_listener(xwl_window->frame_callback, &frame_listener, - xwl_window); - - /* If we get called from frame_callback, it will take care of calling - * xwl_present_reset_timer. - */ - if (xwl_window->xwl_screen->present && - !xwl_present_entered_for_each_frame_callback()) - xwl_present_for_each_frame_callback(xwl_window, xwl_present_reset_timer); -} - -void -xwl_window_destroy(CallbackListPtr *pcbl, ScreenPtr pScreen, WindowPtr window) -{ - struct xwl_screen *xwl_screen = xwl_screen_get(pScreen); - struct xwl_window *xwl_window = xwl_window_get(window); - - if (xwl_screen->present) - xwl_present_cleanup(window); - - if (xwl_window) - xwl_window_dispose(xwl_window); -} - -static Bool -xwl_window_attach_buffer(struct xwl_window *xwl_window) -{ - struct xwl_screen *xwl_screen = xwl_window->xwl_screen; - WindowPtr surface_window = xwl_window->surface_window; - RegionPtr region; - BoxPtr box; - struct wl_buffer *buffer; - PixmapPtr pixmap; - int i; - - pixmap = xwl_window_swap_pixmap(xwl_window, TRUE); - buffer = xwl_pixmap_get_wl_buffer(pixmap); - - if (!buffer) { - ErrorF("Error getting buffer\n"); - return FALSE; - } - - wl_surface_attach(xwl_window->surface, buffer, 0, 0); - - /* Arbitrary limit to try to avoid flooding the Wayland - * connection. If we flood it too much anyway, this could - * abort in libwayland-client. - */ - region = xwl_window_get_damage_region(xwl_window); - if (RegionNumRects(region) > 256) { - box = RegionExtents(region); - xwl_surface_damage(xwl_screen, xwl_window->surface, - box->x1 + surface_window->borderWidth, - box->y1 + surface_window->borderWidth, - box->x2 - box->x1, box->y2 - box->y1); - } else { - box = RegionRects(region); - for (i = 0; i < RegionNumRects(region); i++, box++) { - xwl_surface_damage(xwl_screen, xwl_window->surface, - box->x1 + surface_window->borderWidth, - box->y1 + surface_window->borderWidth, - box->x2 - box->x1, box->y2 - box->y1); - } - } - - return TRUE; -} - -void -xwl_window_post_damage(struct xwl_window *xwl_window) -{ - assert(!xwl_window->frame_callback); - - if (!xwl_window_attach_buffer(xwl_window)) - return; - - xwl_window_create_frame_callback(xwl_window); - DamageEmpty(window_get_damage(xwl_window->surface_window)); -} - -void -xwl_window_set_input_region(struct xwl_window *xwl_window, - RegionPtr input_shape) -{ - struct wl_region *region; - BoxPtr box; - int i; - - if (!input_shape) { - wl_surface_set_input_region(xwl_window->surface, NULL); - return; - } - - region = wl_compositor_create_region(xwl_window->xwl_screen->compositor); - box = RegionRects(input_shape); - - for (i = 0; i < RegionNumRects(input_shape); ++i, ++box) { - wl_region_add(region, - box->x1, - box->y1, - box->x2 - box->x1, - box->y2 - box->y1); - } - - wl_surface_set_input_region(xwl_window->surface, region); - wl_region_destroy(region); -} - -Bool -xwl_window_init(void) -{ - if (!dixRegisterPrivateKey(&xwl_window_private_key, PRIVATE_WINDOW, 0)) - return FALSE; - - if (!dixRegisterPrivateKey(&xwl_damage_private_key, PRIVATE_WINDOW, 0)) - return FALSE; - - return TRUE; -} diff --git a/hw/xwayland/xwayland-window.h b/hw/xwayland/xwayland-window.h deleted file mode 100644 index 16f230982..000000000 --- a/hw/xwayland/xwayland-window.h +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright © 2011-2014 Intel Corporation - * - * Permission to use, copy, modify, distribute, and sell this software - * and its documentation for any purpose is hereby granted without - * fee, provided that the above copyright notice appear in all copies - * and that both that copyright notice and this permission notice - * appear in supporting documentation, and that the name of the - * copyright holders not be used in advertising or publicity - * pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied - * warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS - * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. - */ - -#ifndef XWAYLAND_WINDOW_H -#define XWAYLAND_WINDOW_H - -#include - -#include - -#include -#include - -#include - -#include "dix/property_priv.h" - -#include -#include -#include -#include -#include - -#include "xwayland-types.h" -#include "xwayland-dmabuf.h" - -struct xwl_wl_surface { - OsTimerPtr wl_surface_destroy_timer; - struct wl_surface *wl_surface; - struct xorg_list link; -}; - -struct xwl_window_output { - struct xorg_list link; - struct xwl_output *xwl_output; -}; - -struct xwl_window { - struct xwl_screen *xwl_screen; - struct wl_surface *surface; - struct wp_viewport *viewport; - float viewport_scale_x, viewport_scale_y; - int surface_scale; - struct xdg_surface *xdg_surface; - struct xdg_toplevel *xdg_toplevel; - - /* Top-level window for the Wayland surface: - * - With rootful, the root window itself - * - With rootless, a direct child of the root window - * Mainly useful when the top-level window is needed, can also be used for - * the X dimensions of the Wayland surface though. - */ - WindowPtr toplevel; - - /* The window associated with the Wayland surface: - * - If the top-level window has descendants which: - * - Cover it completely - * - Have no alpha channel - * - Use a different window pixmap than their parent for storage - * then the surface window is the lowest-level such descendant. - * - Otherwise it's the top-level window itself. - * Mainly useful for code dealing with (buffers for) the Wayland surface, - * can also be used for the X dimensions of the Wayland surface though. - */ - WindowPtr surface_window; - RegionPtr surface_window_damage; - - struct xorg_list link_damage; - struct xorg_list link_window; - struct wl_callback *frame_callback; - Bool allow_commits; - struct xorg_list window_buffers_available; - struct xorg_list window_buffers_unavailable; - OsTimerPtr window_buffers_timer; - struct wl_output *wl_output; - struct wl_output *wl_output_fullscreen; - struct xorg_list xwl_output_list; - struct xorg_list frame_callback_list; -#ifdef XWL_HAS_LIBDECOR - struct libdecor_frame *libdecor_frame; -#endif - struct xwayland_surface_v1 *xwayland_surface; - struct xwl_dmabuf_feedback feedback; - /* If TRUE, the window buffer format supports scanout with implicit modifier */ - Bool has_implicit_scanout_support; - struct wp_tearing_control_v1 *tearing_control; - struct wp_fractional_scale_v1 *fractional_scale; - int fractional_scale_numerator; - struct wp_linux_drm_syncobj_surface_v1 *surface_sync; -}; - -struct xwl_window *xwl_window_get(WindowPtr window); -RegionPtr xwl_window_get_damage_region(struct xwl_window *xwl_window); -struct xwl_window *xwl_window_from_window(WindowPtr window); - -Bool is_surface_from_xwl_window(struct wl_surface *surface); - -void xwl_window_update_property(struct xwl_window *xwl_window, - PropertyStateRec *propstate); -Bool xwl_window_is_toplevel(WindowPtr window); -void xwl_window_check_resolution_change_emulation(struct xwl_window *xwl_window); -void xwl_window_rootful_update_title(struct xwl_window *xwl_window); -void xwl_window_rootful_update_fullscreen(struct xwl_window *xwl_window, - struct xwl_output *xwl_output); -void xwl_window_set_window_pixmap(WindowPtr window, PixmapPtr pixmap); -void xwl_window_update_surface_window(struct xwl_window *xwl_window); - -void xwl_window_leave_output(struct xwl_window *xwl_window, - struct xwl_output *xwl_output); -int xwl_window_get_max_output_scale(struct xwl_window *xwl_window); -Bool xwl_realize_window(WindowPtr window); -Bool xwl_unrealize_window(WindowPtr window); -Bool xwl_change_window_attributes(WindowPtr window, unsigned long mask); -void xwl_clip_notify(WindowPtr window, int dx, int dy); -int xwl_config_notify(WindowPtr window, - int x, int y, - int width, int height, int bw, - WindowPtr sib); -void xwl_resize_window(WindowPtr window, - int x, int y, - unsigned int width, unsigned int height, - WindowPtr sib); -void xwl_move_window(WindowPtr window, - int x, int y, - WindowPtr next_sib, - VTKind kind); -void xwl_window_destroy(CallbackListPtr *pcbl, ScreenPtr pScreen, WindowPtr window); -void xwl_window_post_damage(struct xwl_window *xwl_window); -void xwl_window_create_frame_callback(struct xwl_window *xwl_window); -void xwl_window_surface_do_destroy(struct xwl_wl_surface *xwl_wl_surface); -void xwl_window_set_input_region(struct xwl_window *xwl_window, RegionPtr input_shape); - -Bool xwl_window_init(void); - -#endif /* XWAYLAND_WINDOW_H */ diff --git a/hw/xwayland/xwayland-xtest.c b/hw/xwayland/xwayland-xtest.c deleted file mode 100644 index 24cb13c3d..000000000 --- a/hw/xwayland/xwayland-xtest.c +++ /dev/null @@ -1,966 +0,0 @@ -/* - * Copyright © 2020 Red Hat - * - * Permission to use, copy, modify, distribute, and sell this software - * and its documentation for any purpose is hereby granted without - * fee, provided that the above copyright notice appear in all copies - * and that both that copyright notice and this permission notice - * appear in supporting documentation, and that the name of the - * copyright holders not be used in advertising or publicity - * pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied - * warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS - * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. - */ - -#include - -#include -#include -#include -#include - -#include "dix/dix_priv.h" -#include "dix/input_priv.h" -#include "os/client_priv.h" -#include "os/log_priv.h" - -#include -#include - -#ifdef XWL_HAS_EI_PORTAL -#include "liboeffis.h" -#endif - -#include "xwayland-screen.h" -#include "xwayland-xtest.h" - -#define debug_ei(...) DebugF("[xwayland ei] " __VA_ARGS__) -#define error_ei(...) ErrorF("[xwayland ei] " __VA_ARGS__) - -#define SCROLL_STEP 120 /* libei's definition of a logical scroll step */ - -static struct xorg_list clients_for_reuse; - -static DevPrivateKeyRec xwl_ei_private_key; -static DevPrivateKeyRec xwl_device_data_private_key; - -struct xwl_device_data { - DeviceSendEventsProc sendEventsProc; -}; - -struct xwl_emulated_event { - DeviceIntPtr dev; - int type; - int detail; - int flags; - ValuatorMask mask; - struct xorg_list link; -}; - -struct xwl_abs_device { - struct xorg_list link; - struct ei_device *device; -}; - -struct xwl_ei_client { - struct xorg_list link; /* in clients_for_reuse */ - ClientPtr client; /* can be NULL if the X11 client is gone */ - char *cmdline; - bool accept_pointer, accept_keyboard, accept_abs; - struct ei *ei; - int ei_fd; -#ifdef XWL_HAS_EI_PORTAL - struct oeffis *oeffis; - int oeffis_fd; -#endif - struct ei_seat *ei_seat; - struct ei_device *ei_pointer; - struct ei_device *ei_keyboard; - struct xorg_list abs_devices; - struct xorg_list pending_emulated_events; - - OsTimerPtr disconnect_timer; -}; - -static void xwl_handle_ei_event(int fd, int ready, void *data); -static bool xwl_dequeue_emulated_events(struct xwl_ei_client *xwl_ei_client); - -static struct xwl_device_data * -xwl_device_data_get(DeviceIntPtr dev) -{ - return dixLookupPrivate(&dev->devPrivates, &xwl_device_data_private_key); -} - -static struct xwl_ei_client * -get_xwl_ei_client(ClientPtr client) -{ - return dixLookupPrivate(&client->devPrivates, &xwl_ei_private_key); -} - -static void -xwl_queue_emulated_event(struct xwl_ei_client *xwl_ei_client, DeviceIntPtr dev, - int type, int detail, int flags, const ValuatorMask *mask) -{ - struct xwl_emulated_event *xwl_emulated_event; - - xwl_emulated_event = calloc(1, sizeof *xwl_emulated_event); - if (!xwl_emulated_event) { - error_ei("OOM, cannot queue event\n"); - return; - } - - xwl_emulated_event->dev = dev; - xwl_emulated_event->type = type; - xwl_emulated_event->detail = detail; - xwl_emulated_event->flags = flags; - valuator_mask_copy(&xwl_emulated_event->mask, mask); - - xorg_list_append(&xwl_emulated_event->link, - &xwl_ei_client->pending_emulated_events); -} - -static void -xwl_clear_emulated_events(struct xwl_ei_client *xwl_ei_client) -{ - struct xwl_emulated_event *xwl_emulated_event, *next_xwl_emulated_event; - - xorg_list_for_each_entry_safe(xwl_emulated_event, next_xwl_emulated_event, - &xwl_ei_client->pending_emulated_events, link) { - xorg_list_del(&xwl_emulated_event->link); - free(xwl_emulated_event); - } -} - -static void -add_ei_device(struct xwl_ei_client *xwl_ei_client, struct ei_device *device) -{ - bool used = true; - - /* Note: pointers in libei are split across four capabilities: - pointer/pointer-absolute/button/scroll. We expect any decent - compositor to give pointers the button + scroll interfaces too, - if that's not the case we can look into *why* and fix this as needed. - Meanwhile, we ignore any device that doesn't have button + scroll - in addition to pointer caps. - */ - - if (ei_device_has_capability(device, EI_DEVICE_CAP_POINTER) && - ei_device_has_capability(device, EI_DEVICE_CAP_BUTTON) && - ei_device_has_capability(device, EI_DEVICE_CAP_SCROLL) && - xwl_ei_client->ei_pointer == NULL) { - - xwl_ei_client->ei_pointer = ei_device_ref(device); - used = true; - } - - if (ei_device_has_capability(device, EI_DEVICE_CAP_KEYBOARD) && - xwl_ei_client->ei_keyboard == NULL) { - xwl_ei_client->ei_keyboard = ei_device_ref(device); - used = true; - } - - if (ei_device_has_capability(device, EI_DEVICE_CAP_POINTER_ABSOLUTE) && - ei_device_has_capability(device, EI_DEVICE_CAP_BUTTON) && - ei_device_has_capability(device, EI_DEVICE_CAP_SCROLL)) { - struct xwl_abs_device *abs = calloc(1, sizeof(*abs)); - - if (abs) { - xorg_list_add(&abs->link, &xwl_ei_client->abs_devices); - abs->device = ei_device_ref(device); - used = true; - } - } - - if (!used) - ei_device_close(device); -} - -static void -free_oeffis(struct xwl_ei_client *xwl_ei_client) -{ -#ifdef XWL_HAS_EI_PORTAL - if (xwl_ei_client->oeffis) { - debug_ei("Removing OEFFIS fd=%d\n", xwl_ei_client->oeffis_fd); - if (xwl_ei_client->oeffis_fd >= 0) - RemoveNotifyFd(xwl_ei_client->oeffis_fd); - xwl_ei_client->oeffis = oeffis_unref(xwl_ei_client->oeffis); - } -#endif -} - -static void -free_ei(struct xwl_ei_client *xwl_ei_client) -{ - struct ei *ei = xwl_ei_client->ei; - struct xwl_abs_device *abs, *tmp; - ClientPtr client = xwl_ei_client->client; - - TimerCancel(xwl_ei_client->disconnect_timer); - xorg_list_del(&xwl_ei_client->link); - - debug_ei("Removing EI fd=%d\n", xwl_ei_client->ei_fd); - if (xwl_ei_client->ei_fd >= 0) - RemoveNotifyFd(xwl_ei_client->ei_fd); - ei_device_unref(xwl_ei_client->ei_pointer); - ei_device_unref(xwl_ei_client->ei_keyboard); - xorg_list_for_each_entry_safe(abs, tmp, &xwl_ei_client->abs_devices, link) { - xorg_list_del(&abs->link); - ei_device_unref(abs->device); - free(abs); - } - - xwl_clear_emulated_events(xwl_ei_client); - if (client) - dixSetPrivate(&client->devPrivates, &xwl_ei_private_key, NULL); - - free_oeffis(xwl_ei_client); - - ei_seat_unref(xwl_ei_client->ei_seat); - ei_unref(ei); - - free(xwl_ei_client->cmdline); - free(xwl_ei_client); -} - -#ifdef XWL_HAS_EI_PORTAL -static void -setup_ei_from_oeffis(struct xwl_ei_client *xwl_ei_client) -{ - struct oeffis *oeffis = xwl_ei_client->oeffis; - - xwl_ei_client->ei_fd = oeffis_get_eis_fd(oeffis); - if (xwl_ei_client->ei_fd < 0) { - error_ei("Failed to setup EI file descriptor from oeffis\n"); - return; - } - ei_setup_backend_fd(xwl_ei_client->ei, xwl_ei_client->ei_fd); - SetNotifyFd(xwl_ei_client->ei_fd, xwl_handle_ei_event, - X_NOTIFY_READ, xwl_ei_client); -} - -static void -xwl_handle_oeffis_event(int fd, int ready, void *data) -{ - struct xwl_ei_client *xwl_ei_client = data; - struct oeffis *oeffis = xwl_ei_client->oeffis; - enum oeffis_event_type event_type; - bool done = false; - - oeffis_dispatch(oeffis); - - do { - event_type = oeffis_get_event(oeffis); - switch (event_type) { - case OEFFIS_EVENT_NONE: - debug_ei("OEFFIS event none\n"); - done = true; - break; - case OEFFIS_EVENT_CONNECTED_TO_EIS: - debug_ei("OEFFIS connected to EIS\n"); - setup_ei_from_oeffis(xwl_ei_client); - break; - case OEFFIS_EVENT_DISCONNECTED: - debug_ei("OEFFIS disconnected: %s\n", - oeffis_get_error_message(oeffis)); - xwl_dequeue_emulated_events(xwl_ei_client); - free_ei(xwl_ei_client); - done = true; - break; - case OEFFIS_EVENT_CLOSED: - debug_ei("OEFFIS closed\n"); - free_ei(xwl_ei_client); - done = true; - break; - } - } - while (!done); -} -#endif - -static bool -setup_oeffis(struct xwl_ei_client *xwl_ei_client) -{ -#ifdef XWL_HAS_EI_PORTAL - xwl_ei_client->oeffis_fd = -1; - xwl_ei_client->oeffis = oeffis_new(NULL); - if (!xwl_ei_client->oeffis) - return false; - - xwl_ei_client->oeffis_fd = oeffis_get_fd(xwl_ei_client->oeffis); - if (xwl_ei_client->oeffis_fd < 0) { - error_ei("Failed to setup OEFFIS file descriptor\n"); - return false; - } - - SetNotifyFd(xwl_ei_client->oeffis_fd, xwl_handle_oeffis_event, - X_NOTIFY_READ, xwl_ei_client); - - oeffis_create_session(xwl_ei_client->oeffis, - OEFFIS_DEVICE_KEYBOARD | OEFFIS_DEVICE_POINTER); - - return true; -#else - return false; -#endif -} - -static bool -setup_ei_from_socket(struct xwl_ei_client *xwl_ei_client) -{ - int rc; - - rc = ei_setup_backend_socket(xwl_ei_client->ei, NULL); - - if (rc != 0) { - error_ei("Setup failed: %s\n", strerror(-rc)); - return false; - } - - xwl_ei_client->ei_fd = ei_get_fd(xwl_ei_client->ei); - if (xwl_ei_client->ei_fd < 0) { - error_ei("Failed to setup EI file descriptor from socket\n"); - return false; - } - - SetNotifyFd(xwl_ei_client->ei_fd, xwl_handle_ei_event, - X_NOTIFY_READ, xwl_ei_client); - - return true; -} - -static struct xwl_ei_client * -setup_ei(ClientPtr client) -{ - ScreenPtr pScreen = screenInfo.screens[0]; - struct xwl_ei_client *xwl_ei_client = NULL; - struct xwl_screen *xwl_screen = xwl_screen_get(pScreen); - struct ei *ei = NULL; - char buffer[PATH_MAX]; - const char *cmdname; - char *client_name = NULL; - bool status = false; - - cmdname = GetClientCmdName(client); - if (cmdname) { - snprintf(buffer, sizeof(buffer) - 1, "%s", cmdname); - client_name = basename(buffer); - } - - if (!client_name) { - error_ei("Failed to retrieve the client command line name\n"); - goto out; - } - - xwl_ei_client = calloc(1, sizeof *xwl_ei_client); - if (!xwl_ei_client) { - error_ei("OOM, cannot setup EI\n"); - goto out; - } - - xwl_ei_client->cmdline = Xstrdup(cmdname); - xorg_list_init(&xwl_ei_client->link); - - ei = ei_new(NULL); - ei_configure_name(ei, basename(client_name)); - - /* We can't send events to EIS until we have a device and the device - * is resumed. - */ - xwl_ei_client->accept_pointer = false; - xwl_ei_client->accept_keyboard = false; - xwl_ei_client->accept_abs = false; - xwl_ei_client->ei = ei; - xwl_ei_client->ei_fd = -1; - xwl_ei_client->client = client; - xorg_list_init(&xwl_ei_client->pending_emulated_events); - xorg_list_init(&xwl_ei_client->abs_devices); - - if (xwl_screen->enable_ei_portal) - status = setup_oeffis(xwl_ei_client); - if (!status) - status = setup_ei_from_socket(xwl_ei_client); - - if (!status) { - free(xwl_ei_client); - xwl_ei_client = NULL; - ei_unref(ei); - error_ei("EI setup failed\n"); - /* We failed to setup EI using either backends, give up on EI. */ - xwayland_restore_xtest(); - } - - out: - return xwl_ei_client; -} - -static CARD32 -disconnect_timer_cb(OsTimerPtr timer, CARD32 time, void *arg) -{ - struct xwl_ei_client *xwl_ei_client = arg; - - free_ei(xwl_ei_client); - - return 0; -} - -static void -xwl_ei_start_emulating(struct xwl_ei_client *xwl_ei_client) -{ - static uint32_t sequence = 0; - struct xwl_abs_device *abs; - - sequence++; - if (xwl_ei_client->ei_pointer) - ei_device_start_emulating(xwl_ei_client->ei_pointer, sequence); - if (xwl_ei_client->ei_keyboard) - ei_device_start_emulating(xwl_ei_client->ei_keyboard, sequence); - xorg_list_for_each_entry(abs, &xwl_ei_client->abs_devices, link) { - ei_device_start_emulating(abs->device, sequence); - } -} - -static void -xwl_ei_stop_emulating(struct xwl_ei_client *xwl_ei_client) -{ - struct xwl_abs_device *abs; - - if (xwl_ei_client->ei_pointer) - ei_device_stop_emulating(xwl_ei_client->ei_pointer); - if (xwl_ei_client->ei_keyboard) - ei_device_stop_emulating(xwl_ei_client->ei_keyboard); - xorg_list_for_each_entry(abs, &xwl_ei_client->abs_devices, link) { - ei_device_stop_emulating(abs->device); - } -} - -static void -xwl_ei_handle_client_gone(struct xwl_ei_client *xwl_ei_client) -{ - ClientPtr client = xwl_ei_client->client; - - /* Make this EI client struct re-usable. xdotool only exists for a - * fraction of a second, so let's make it re-use the same client every - * time - this makes it easier to e.g. pause it */ - xorg_list_add(&xwl_ei_client->link, &clients_for_reuse); - - if (xorg_list_is_empty(&xwl_ei_client->pending_emulated_events)) - xwl_ei_stop_emulating(xwl_ei_client); - - debug_ei("Client %s is now reusable\n", xwl_ei_client->cmdline); - - /* Otherwise, we keep the EI part but break up with the X11 client */ - assert(client); - dixSetPrivate(&client->devPrivates, &xwl_ei_private_key, NULL); - xwl_ei_client->client = NULL; - - /* Set a timer for 10 minutes. If the same client doesn't reconnect, - * free it properly */ - xwl_ei_client->disconnect_timer = - TimerSet(xwl_ei_client->disconnect_timer, 0, - 10 * 60 * 1000, disconnect_timer_cb, xwl_ei_client); -} - -static void -xwl_ei_state_client_callback(CallbackListPtr *pcbl, void *unused, void *data) -{ - NewClientInfoRec *clientinfo = (NewClientInfoRec *) data; - ClientPtr client = clientinfo->client; - struct xwl_ei_client *xwl_ei_client = get_xwl_ei_client(client); - - switch (client->clientState) { - case ClientStateGone: - case ClientStateRetained: - if (xwl_ei_client) - xwl_ei_handle_client_gone(xwl_ei_client); - break; - default: - break; - } -} - -static inline unsigned int -buttonmap(unsigned int b) -{ - unsigned int button; - - switch (b) { - case 0: - button = 0; - break; - case 1: - button = 0x110; /* BTN_LEFT */ - break; - case 2: - button = 0x112; /* BTN_MIDDLE */ - break; - case 3: - button = 0x111; /* BTN_RIGHT */ - break; - default: - button = b - 8 + 0x113; /* BTN_SIDE */ - break; - } - - return button; -} - -static void -xwl_send_abs_event_to_ei(struct xwl_ei_client *xwl_ei_client, int sx, int sy) -{ - struct xwl_abs_device *abs; - struct ei *ei = xwl_ei_client->ei; - - xorg_list_for_each_entry(abs, &xwl_ei_client->abs_devices, link) { - struct ei_region *r; - size_t idx = 0; - - while ((r = ei_device_get_region(abs->device, idx++))) { - double x = sx, y = sy; - - if (ei_region_contains(r, x, y)) { - ei_device_pointer_motion_absolute(abs->device, sx, sy); - ei_device_frame(abs->device, ei_now(ei)); - return; - } - } - } -} - -static bool -xwl_send_event_to_ei(struct xwl_ei_client *xwl_ei_client, - int type, int detail, int flags, const ValuatorMask *mask) -{ - struct ei *ei = xwl_ei_client->ei; - struct ei_device *ei_device = NULL; - int x = 0, y = 0; - - debug_ei("Sending event type %d to EIS\n", type); - - switch (type) { - case MotionNotify: - valuator_mask_fetch(mask, 0, &x); - valuator_mask_fetch(mask, 1, &y); - - if (flags & POINTER_ABSOLUTE) { - if (!xwl_ei_client->accept_abs) - return false; - - xwl_send_abs_event_to_ei(xwl_ei_client, x, y); - } - else if (x || y) { - if (!xwl_ei_client->accept_pointer) - return false; - - ei_device = xwl_ei_client->ei_pointer; - ei_device_pointer_motion(ei_device, x, y); - ei_device_frame(ei_device, ei_now(ei)); - } - break; - case ButtonPress: - case ButtonRelease: - if (!xwl_ei_client->accept_pointer) - return false; - - ei_device = xwl_ei_client->ei_pointer; - if (detail < 4 || detail > 7) { - ei_device_button_button(ei_device, - buttonmap(detail), type == ButtonPress); - ei_device_frame(ei_device, ei_now(ei)); - /* Scroll only on release */ - } else if (type == ButtonRelease) { - if (detail == 4) { - ei_device_scroll_discrete(ei_device, 0, -SCROLL_STEP); - } else if (detail == 5) { - ei_device_scroll_discrete(ei_device, 0, SCROLL_STEP); - } else if (detail == 6) { - ei_device_scroll_discrete(ei_device, -SCROLL_STEP, 0); - } else if (detail == 7) { - ei_device_scroll_discrete(ei_device, SCROLL_STEP, 0); - } - ei_device_frame(ei_device, ei_now(ei)); - } - break; - case KeyPress: - case KeyRelease: - if (!xwl_ei_client->accept_keyboard) - return false; - - ei_device = xwl_ei_client->ei_keyboard; - ei_device_keyboard_key(ei_device, detail - 8, type == KeyPress); - ei_device_frame(ei_device, ei_now(ei)); - break; - default: - error_ei("XTEST event type %d is not implemented\n", type); - break; - } - - return true; -} - -static struct xwl_ei_client * -reuse_client(ClientPtr client) -{ - struct xwl_ei_client *xwl_ei_client = NULL; - const char *cmdname = GetClientCmdName(client); - - if (!cmdname) - return NULL; - - debug_ei("Client maybe up for re-use: %s\n", cmdname); - xorg_list_for_each_entry(xwl_ei_client, &clients_for_reuse, link) { - debug_ei("Checking if we can re-use %s\n", xwl_ei_client->cmdline); - if (xwl_ei_client->cmdline && - strcmp(xwl_ei_client->cmdline, cmdname) == 0) { - debug_ei("Re-using client for %s\n", cmdname); - xorg_list_del(&xwl_ei_client->link); - xorg_list_init(&xwl_ei_client->link); - TimerCancel(xwl_ei_client->disconnect_timer); - xwl_ei_start_emulating(xwl_ei_client); - return xwl_ei_client; - } - } - - return NULL; -} - -static void -xwayland_xtest_fallback(DeviceIntPtr dev, - int type, int detail, int flags, const ValuatorMask *mask) -{ - struct xwl_device_data *xwl_device_data = xwl_device_data_get(dev); - - if (xwl_device_data->sendEventsProc != NULL) { - debug_ei("EI failed, using XTEST as fallback for sending events\n"); - (xwl_device_data->sendEventsProc)(dev, type, detail, flags, mask); - } -} - - -static void -xwayland_xtest_send_events(DeviceIntPtr dev, - int type, int detail, int flags, const ValuatorMask *mask) -{ - ClientPtr client; - struct xwl_ei_client *xwl_ei_client; - bool accept = false; - - if (!IsXTestDevice(dev, NULL)) - return; - - client = GetCurrentClient(); - xwl_ei_client = get_xwl_ei_client(client); - if (!xwl_ei_client) { - xwl_ei_client = reuse_client(client); - if (xwl_ei_client) - xwl_ei_client->client = client; - } - - if (!xwl_ei_client) { - if (!(xwl_ei_client = setup_ei(client))) { - xwayland_xtest_fallback(dev, type, detail, flags, mask); - return; - } - } - dixSetPrivate(&client->devPrivates, &xwl_ei_private_key, xwl_ei_client); - - switch (type) { - case MotionNotify: - if (flags & POINTER_ABSOLUTE) - accept = xwl_ei_client->accept_abs; - else - accept = xwl_ei_client->accept_pointer; - break; - case ButtonPress: - case ButtonRelease: - accept = xwl_ei_client->accept_pointer; - break; - case KeyPress: - case KeyRelease: - accept = xwl_ei_client->accept_keyboard; - break; - default: - return; - } - - if (accept) { - xwl_send_event_to_ei(xwl_ei_client, type, detail, flags, mask); - } - else { - debug_ei("Not yet connected to EIS, queueing events\n"); - xwl_queue_emulated_event(xwl_ei_client, dev, type, detail, flags, mask); - } - -} - -static bool -xwl_dequeue_emulated_events(struct xwl_ei_client *xwl_ei_client) -{ - struct xwl_emulated_event *xwl_emulated_event, *next_xwl_emulated_event; - bool sent; - - xorg_list_for_each_entry_safe(xwl_emulated_event, next_xwl_emulated_event, - &xwl_ei_client->pending_emulated_events, link) { - sent = xwl_send_event_to_ei(xwl_ei_client, - xwl_emulated_event->type, - xwl_emulated_event->detail, - xwl_emulated_event->flags, - &xwl_emulated_event->mask); - if (!sent) - xwayland_xtest_fallback(xwl_emulated_event->dev, - xwl_emulated_event->type, - xwl_emulated_event->detail, - xwl_emulated_event->flags, - &xwl_emulated_event->mask); - - xorg_list_del(&xwl_emulated_event->link); - free(xwl_emulated_event); - } - return true; -} - -static void -xwl_ei_update_caps(struct xwl_ei_client *xwl_ei_client, - struct ei_device *ei_device) -{ - struct xwl_abs_device *abs; - - if (ei_device == xwl_ei_client->ei_pointer) - xwl_ei_client->accept_pointer = true; - - if (ei_device == xwl_ei_client->ei_keyboard) - xwl_ei_client->accept_keyboard = true; - - xorg_list_for_each_entry(abs, &xwl_ei_client->abs_devices, link) { - if (ei_device == abs->device) - xwl_ei_client->accept_abs = true; - } -} - -static bool -xwl_ei_devices_are_ready(struct xwl_ei_client *xwl_ei_client) -{ - if ((xwl_ei_client->accept_keyboard || - !ei_seat_has_capability(xwl_ei_client->ei_seat, EI_DEVICE_CAP_KEYBOARD)) && - (xwl_ei_client->accept_pointer || - !ei_seat_has_capability(xwl_ei_client->ei_seat, EI_DEVICE_CAP_POINTER)) && - (xwl_ei_client->accept_abs || - !ei_seat_has_capability(xwl_ei_client->ei_seat, EI_DEVICE_CAP_POINTER_ABSOLUTE))) - return true; - - return false; -} - -static void -xwl_handle_ei_event(int fd, int ready, void *data) -{ - struct xwl_ei_client *xwl_ei_client = data; - struct ei *ei; - bool done = false; - - ei = xwl_ei_client->ei; - - ei_dispatch(ei); - do { - enum ei_event_type type; - struct ei_event *e = ei_get_event(ei); - struct ei_device *ei_device; - - if (!e) - break; - - ei_device = ei_event_get_device(e); - type = ei_event_get_type(e); - switch (type) { - case EI_EVENT_CONNECT: - debug_ei("Connected\n"); - break; - case EI_EVENT_SEAT_ADDED: - /* We take the first seat that comes along and - * add our device there */ - if (!xwl_ei_client->ei_seat) { - struct ei_seat *seat = ei_event_get_seat(e); - - xwl_ei_client->ei_seat = ei_seat_ref(seat); - debug_ei("Using seat: %s (caps: %s%s%s%s%s)\n", - ei_seat_get_name(seat), ei_seat_has_capability(seat, - EI_DEVICE_CAP_KEYBOARD) ? "k" : "", - ei_seat_has_capability(seat, - EI_DEVICE_CAP_POINTER) ? "p" : "", - ei_seat_has_capability(seat, - EI_DEVICE_CAP_POINTER_ABSOLUTE) ? "a" : "", - ei_seat_has_capability(seat, - EI_DEVICE_CAP_BUTTON) ? "b" : "", - ei_seat_has_capability(seat, - EI_DEVICE_CAP_SCROLL) ? "s" : ""); - ei_seat_bind_capabilities(seat, - EI_DEVICE_CAP_POINTER, - EI_DEVICE_CAP_POINTER_ABSOLUTE, - EI_DEVICE_CAP_BUTTON, - EI_DEVICE_CAP_SCROLL, - EI_DEVICE_CAP_KEYBOARD, NULL); - } - break; - case EI_EVENT_SEAT_REMOVED: - if (ei_event_get_seat(e) == xwl_ei_client->ei_seat) { - debug_ei("Seat was removed\n"); - xwl_ei_client->ei_seat = - ei_seat_unref(xwl_ei_client->ei_seat); - } - break; - case EI_EVENT_DEVICE_ADDED: - debug_ei("New device: %s\n", ei_device_get_name(ei_device)); - add_ei_device(xwl_ei_client, ei_device); - break; - case EI_EVENT_DEVICE_REMOVED: - debug_ei("Device removed: %s\n", ei_device_get_name(ei_device)); - { - struct xwl_abs_device *abs, *tmp; - - xorg_list_for_each_entry_safe(abs, tmp, - &xwl_ei_client->abs_devices, link) { - if (abs->device != ei_device) - continue; - ei_device_unref(abs->device); - xorg_list_del(&abs->link); - free(abs); - } - } - if (xwl_ei_client->ei_pointer == ei_device) - xwl_ei_client->ei_pointer = - ei_device_unref(xwl_ei_client->ei_pointer); - if (xwl_ei_client->ei_keyboard == ei_device) - xwl_ei_client->ei_keyboard = - ei_device_unref(xwl_ei_client->ei_keyboard); - break; - case EI_EVENT_DISCONNECT: - debug_ei("Disconnected\n"); - free_ei(xwl_ei_client); - done = true; - break; - case EI_EVENT_DEVICE_PAUSED: - debug_ei("Device paused\n"); - if (ei_device == xwl_ei_client->ei_pointer) - xwl_ei_client->accept_pointer = false; - if (ei_device == xwl_ei_client->ei_keyboard) - xwl_ei_client->accept_keyboard = false; - { - struct xwl_abs_device *abs; - - xorg_list_for_each_entry(abs, &xwl_ei_client->abs_devices, - link) { - if (ei_device == abs->device) - xwl_ei_client->accept_abs = false; - } - } - break; - case EI_EVENT_DEVICE_RESUMED: - debug_ei("Device resumed\n"); - xwl_ei_update_caps(xwl_ei_client, ei_device); - /* Server has accepted our device (or resumed them), - * we can now start sending events */ - /* FIXME: Maybe add a timestamp and discard old events? */ - if (xwl_ei_devices_are_ready(xwl_ei_client)) { - xwl_ei_start_emulating(xwl_ei_client); - xwl_dequeue_emulated_events(xwl_ei_client); - } - if (!xwl_ei_client->client && - xorg_list_is_empty(&xwl_ei_client->pending_emulated_events)) - /* All events dequeued and client has disconnected in the meantime */ - xwl_ei_stop_emulating(xwl_ei_client); - break; - case EI_EVENT_KEYBOARD_MODIFIERS: - debug_ei("Ignored event %s (%d)\n", ei_event_type_to_string(type), type); - /* Don't care */ - break; - default: - error_ei("Unhandled event %s (%d)\n", ei_event_type_to_string(type), type); - break; - } - ei_event_unref(e); - } while (!done); -} - -Bool -xwayland_ei_init(void) -{ - xorg_list_init(&clients_for_reuse); - - if (!dixRegisterPrivateKey(&xwl_ei_private_key, PRIVATE_CLIENT, 0)) { - ErrorF("Failed to register EI private key\n"); - return FALSE; - } - - if (!AddCallback(&ClientStateCallback, xwl_ei_state_client_callback, NULL)) { - ErrorF("Failed to add client state callback\n"); - return FALSE; - } - - if (!dixRegisterPrivateKey(&xwl_device_data_private_key, PRIVATE_DEVICE, - sizeof(struct xwl_device_data))) { - ErrorF("Failed to register private key for XTEST override\n"); - return FALSE; - } - - return TRUE; -} - -static void -xwayland_override_events_proc(DeviceIntPtr dev) -{ - struct xwl_device_data *xwl_device_data = xwl_device_data_get(dev); - - if (xwl_device_data->sendEventsProc != NULL) - return; - - /* Save original sendEventsProc handler in case */ - xwl_device_data->sendEventsProc = dev->sendEventsProc; - - /* Set up our own sendEventsProc to forward events to EI */ - debug_ei("Overriding XTEST for %s\n", dev->name); - dev->sendEventsProc = xwayland_xtest_send_events; -} - -static void -xwayland_restore_events_proc(DeviceIntPtr dev) -{ - struct xwl_device_data *xwl_device_data = xwl_device_data_get(dev); - - if (xwl_device_data->sendEventsProc == NULL) - return; - - /* Restore original sendEventsProc handler */ - debug_ei("Restoring XTEST for %s\n", dev->name); - dev->sendEventsProc = xwl_device_data->sendEventsProc; - xwl_device_data->sendEventsProc = NULL; -} - -void -xwayland_override_xtest(void) -{ - DeviceIntPtr d; - - nt_list_for_each_entry(d, inputInfo.devices, next) { - xwayland_override_events_proc(d); - } -} - -void -xwayland_restore_xtest(void) -{ - DeviceIntPtr d; - - nt_list_for_each_entry(d, inputInfo.devices, next) { - xwayland_restore_events_proc(d); - } -} diff --git a/hw/xwayland/xwayland-xtest.h b/hw/xwayland/xwayland-xtest.h deleted file mode 100644 index 996fdcc27..000000000 --- a/hw/xwayland/xwayland-xtest.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright © 2020 Red Hat - * - * Permission to use, copy, modify, distribute, and sell this software - * and its documentation for any purpose is hereby granted without - * fee, provided that the above copyright notice appear in all copies - * and that both that copyright notice and this permission notice - * appear in supporting documentation, and that the name of the - * copyright holders not be used in advertising or publicity - * pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied - * warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS - * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. - */ - -#ifndef XWAYLAND_XTEST_H -#define XWAYLAND_XTEST_H - -#include - -Bool xwayland_ei_init(void); -void xwayland_override_xtest(void); -void xwayland_restore_xtest(void); - -#endif diff --git a/hw/xwayland/xwayland.c b/hw/xwayland/xwayland.c deleted file mode 100644 index 783dd6226..000000000 --- a/hw/xwayland/xwayland.c +++ /dev/null @@ -1,476 +0,0 @@ -/* - * Copyright © 2011-2014 Intel Corporation - * - * Permission to use, copy, modify, distribute, and sell this software - * and its documentation for any purpose is hereby granted without - * fee, provided that the above copyright notice appear in all copies - * and that both that copyright notice and this permission notice - * appear in supporting documentation, and that the name of the - * copyright holders not be used in advertising or publicity - * pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied - * warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS - * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. - */ - -#include - -#if !defined(WIN32) -#include -#endif - -#include -#include - -#include -#include - -#include "dix/dix_priv.h" -#include "dix/screenint_priv.h" -#include "dix/selection_priv.h" -#include "os/auth.h" -#include "os/cmdline.h" -#include "os/client_priv.h" -#include "os/ddx_priv.h" -#include "os/fmt.h" -#include "os/log_priv.h" -#include "os/osdep.h" -#include "os/xserver_poll.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "extinit.h" - -#include "xwayland-screen.h" -#include "xwayland-vidmode.h" - -#ifdef XF86VIDMODE -#include -Bool noXFree86VidModeExtension = FALSE; -#endif - -void -ddxGiveUp(enum ExitCode error) -{ -} - -void -OsVendorInit(void) -{ - if (serverGeneration == 1) - ForceClockId(CLOCK_MONOTONIC); -} - -void -OsVendorFatalError(const char *f, va_list args) -{ -} - -#if defined(DDXBEFORERESET) -void -ddxBeforeReset(void) -{ - return; -} -#endif - -#if INPUTTHREAD -/** This function is called in Xserver/os/inputthread.c when starting - the input thread. */ -void -ddxInputThreadInit(void) -{ -} -#endif - -void -ddxUseMsg(void) -{ - ErrorF("-rootless run rootless, requires wm support\n"); - ErrorF("-fullscreen run fullscreen when rootful\n"); - ErrorF("-geometry WxH set Xwayland window size when rootful\n"); - ErrorF("-hidpi adjust to output scale when rootful\n"); - ErrorF("-host-grab disable host keyboard shortcuts when rootful\n"); - ErrorF("-nokeymap ignore keymap from the Wayland compositor\n"); - ErrorF("-output specify which output to use for fullscreen when rootful\n"); - ErrorF("-wm fd create X client for wm on given fd\n"); - ErrorF("-initfd fd add given fd as a listen socket for initialization clients\n"); - ErrorF("-listenfd fd add given fd as a listen socket\n"); - ErrorF("-listen fd deprecated, use \"-listenfd\" instead\n"); - ErrorF("-shm use shared memory for passing buffers\n"); -#ifdef XWL_HAS_GLAMOR - ErrorF("-glamor [gl|es|off] use given API for Glamor acceleration. Incompatible with -shm option\n"); -#endif - ErrorF("-verbose [n] verbose startup messages\n"); - ErrorF("-version show the server version and exit\n"); - ErrorF("-noTouchPointerEmulation disable touch pointer emulation\n"); - ErrorF("-force-xrandr-emulation force non-native modes to be exposed when viewporter is not exposed by the compositor\n"); -#ifdef XWL_HAS_LIBDECOR - ErrorF("-decorate add decorations to Xwayland when rootful\n"); -#endif -#ifdef XWL_HAS_EI_PORTAL - ErrorF("-enable-ei-portal use the XDG portal for input emulation\n"); -#endif -} - -static int init_fd = -1; -static int wm_fd = -1; -static int listen_fds[5] = { -1, -1, -1, -1, -1 }; -static int listen_fd_count = 0; -static int verbosity = 0; - -static void -xwl_show_version(void) -{ - ErrorF("%s Xwayland %s (%d)\n", VENDOR_NAME, VENDOR_MAN_VERSION, VENDOR_RELEASE); - ErrorF("X Protocol Version %d, Revision %d\n", X_PROTOCOL, X_PROTOCOL_REVISION); -#if defined(BUILDERSTRING) - if (strlen(BUILDERSTRING)) - ErrorF("%s\n", BUILDERSTRING); -#endif -} - -static void -try_raising_nofile_limit(void) -{ -#ifdef RLIMIT_NOFILE - struct rlimit rlim; - - if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) { - ErrorF("Failed to get the current nofile limit: %s\n", strerror(errno)); - return; - } - - rlim.rlim_cur = rlim.rlim_max; - - if (setrlimit(RLIMIT_NOFILE, &rlim) < 0) { - ErrorF("Failed to set the current nofile limit: %s\n", strerror(errno)); - return; - } - - LogMessageVerb(X_INFO, 3, "Raising the file descriptors limit to %llu\n", - (long long unsigned int) rlim.rlim_max); -#endif /* RLIMIT_NOFILE */ -} - -static void -xwl_add_listen_fd(int argc, char *argv[], int i) -{ - NoListenAll = TRUE; - if (listen_fd_count == ARRAY_SIZE(listen_fds)) - FatalError("Too many -listen arguments given, max is %zu\n", - ARRAY_SIZE(listen_fds)); - - listen_fds[listen_fd_count++] = atoi(argv[i + 1]); -} - -int -ddxProcessArgument(int argc, char *argv[], int i) -{ - if (strcmp(argv[i], "-rootless") == 0) { - return 1; - } - else if (strcmp(argv[i], "-listen") == 0) { - CHECK_FOR_REQUIRED_ARGUMENTS(1); - - /* Not an FD */ - if (!isdigit(*argv[i + 1])) - return 0; - - LogMessageVerb(X_WARNING, 0, "Option \"-listen\" for file descriptors is deprecated\n" - "Please use \"-listenfd\" instead.\n"); - - xwl_add_listen_fd (argc, argv, i); - return 2; - } - else if (strcmp(argv[i], "-listenfd") == 0) { - CHECK_FOR_REQUIRED_ARGUMENTS(1); - - xwl_add_listen_fd (argc, argv, i); - return 2; - } - else if (strcmp(argv[i], "-wm") == 0) { - CHECK_FOR_REQUIRED_ARGUMENTS(1); - wm_fd = atoi(argv[i + 1]); - return 2; - } - else if (strcmp(argv[i], "-initfd") == 0) { - CHECK_FOR_REQUIRED_ARGUMENTS(1); - init_fd = atoi(argv[i + 1]); - return 2; - } - else if (strcmp(argv[i], "-shm") == 0) { - return 1; - } -#ifdef XWL_HAS_GLAMOR - else if (strcmp(argv[i], "-glamor") == 0) { - CHECK_FOR_REQUIRED_ARGUMENTS(1); - /* Only check here, actual work inside xwayland-screen.c */ - return 2; - } -#endif - else if (strcmp(argv[i], "-verbose") == 0) { - if (++i < argc && argv[i]) { - char *end; - long val; - - val = strtol(argv[i], &end, 0); - if (*end == '\0') { - verbosity = val; - xorgLogVerbosity = verbosity; - return 2; - } - } - xorgLogVerbosity = ++verbosity; - return 1; - } - else if (strcmp(argv[i], "-version") == 0) { - xwl_show_version(); - exit(0); - } - else if (strcmp(argv[i], "-noTouchPointerEmulation") == 0) { - touchEmulatePointer = FALSE; - return 1; - } - else if (strcmp(argv[i], "-force-xrandr-emulation") == 0) { - return 1; - } - else if (strcmp(argv[i], "-geometry") == 0) { - CHECK_FOR_REQUIRED_ARGUMENTS(1); - return 2; - } - else if (strcmp(argv[i], "-fullscreen") == 0) { - return 1; - } - else if (strcmp(argv[i], "-host-grab") == 0) { - return 1; - } - else if (strcmp(argv[i], "-decorate") == 0) { - return 1; - } - else if (strcmp(argv[i], "-enable-ei-portal") == 0) { - return 1; - } - else if (strcmp(argv[i], "-output") == 0) { - CHECK_FOR_REQUIRED_ARGUMENTS(1); - return 2; - } - else if (strcmp(argv[i], "-nokeymap") == 0) { - return 1; - } - else if (strcmp(argv[i], "-hidpi") == 0) { - return 1; - } - - return 0; -} - -static CARD32 -add_client_fd(OsTimerPtr timer, CARD32 time, void *arg) -{ - if (!AddClientOnOpenFD(wm_fd)) - FatalError("Failed to add wm client\n"); - - TimerFree(timer); - - return 0; -} - -static void -listen_on_fds(void) -{ - int i; - - for (i = 0; i < listen_fd_count; i++) - ListenOnOpenFD(listen_fds[i], FALSE); -} - -static void -wm_selection_callback(CallbackListPtr *p, void *data, void *arg) -{ - SelectionInfoRec *info = arg; - struct xwl_screen *xwl_screen = data; - static const char atom_name[] = "WM_S0"; - static Atom atom_wm_s0; - - if (atom_wm_s0 == None) - atom_wm_s0 = MakeAtom(atom_name, strlen(atom_name), TRUE); - if (info->selection->selection != atom_wm_s0 || - info->kind != SelectionSetOwner) - return; - - listen_on_fds(); - - DeleteCallback(&SelectionCallback, wm_selection_callback, xwl_screen); -} - -static void _X_ATTRIBUTE_PRINTF(1, 0) -xwl_log_handler(const char *format, va_list args) -{ - char msg[256]; - - vsnprintf(msg, sizeof msg, format, args); - ErrorF("XWAYLAND: %s", msg); -} - -#ifdef XWL_HAS_XWAYLAND_EXTENSION -#include - -Bool noXwaylandExtension = FALSE; - -static int -ProcXwlQueryVersion(ClientPtr client) -{ - xXwlQueryVersionReply reply; - int major, minor; - - REQUEST(xXwlQueryVersionReq); - REQUEST_SIZE_MATCH(xXwlQueryVersionReq); - - if (version_compare(stuff->majorVersion, stuff->minorVersion, - XWAYLAND_EXTENSION_MAJOR, - XWAYLAND_EXTENSION_MINOR) < 0) { - major = stuff->majorVersion; - minor = stuff->minorVersion; - } else { - major = XWAYLAND_EXTENSION_MAJOR; - minor = XWAYLAND_EXTENSION_MINOR; - } - - reply = (xXwlQueryVersionReply) { - .type = X_Reply, - .sequenceNumber = client->sequence, - .length = 0, - .majorVersion = major, - .minorVersion = minor, - }; - - if (client->swapped) { - swaps(&reply.sequenceNumber); - swapl(&reply.length); - swaps(&reply.majorVersion); - swaps(&reply.minorVersion); - } - - WriteToClient(client, sizeof(reply), &reply); - return Success; -} - -static int _X_COLD -SProcXwlQueryVersion(ClientPtr client) -{ - REQUEST(xXwlQueryVersionReq); - REQUEST_AT_LEAST_SIZE(xXwlQueryVersionReq); - swaps(&stuff->majorVersion); - swaps(&stuff->minorVersion); - - return ProcXwlQueryVersion(client); -} - -static int -ProcXwaylandDispatch(ClientPtr client) -{ - REQUEST(xReq); - - switch (stuff->data) { - case X_XwlQueryVersion: - return ProcXwlQueryVersion(client); - } - return BadRequest; -} - -static int -SProcXwaylandDispatch(ClientPtr client) -{ - REQUEST(xReq); - - switch (stuff->data) { - case X_XwlQueryVersion: - return SProcXwlQueryVersion(client); - } - return BadRequest; -} - -static void -xwlExtensionInit(void) -{ - AddExtension(XWAYLAND_EXTENSION_NAME, - XwlNumberEvents, XwlNumberErrors, - ProcXwaylandDispatch, SProcXwaylandDispatch, - NULL, StandardMinorOpcode); -} - -#endif - -static const ExtensionModule xwayland_extensions[] = { -#ifdef XF86VIDMODE - { xwlVidModeExtensionInit, XF86VIDMODENAME, &noXFree86VidModeExtension }, -#endif -#ifdef XWL_HAS_XWAYLAND_EXTENSION - { xwlExtensionInit, XWAYLAND_EXTENSION_NAME, &noXwaylandExtension }, -#endif -}; - -void -InitOutput(ScreenInfo * screen_info, int argc, char **argv) -{ - int depths[] = { 1, 4, 8, 15, 16, 24, 32 }; - int bpp[] = { 1, 8, 8, 16, 16, 32, 32 }; - int i; - - for (i = 0; i < ARRAY_SIZE(depths); i++) { - screen_info->formats[i].depth = depths[i]; - screen_info->formats[i].bitsPerPixel = bpp[i]; - screen_info->formats[i].scanlinePad = BITMAP_SCANLINE_PAD; - } - - screen_info->imageByteOrder = IMAGE_BYTE_ORDER; - screen_info->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT; - screen_info->bitmapScanlinePad = BITMAP_SCANLINE_PAD; - screen_info->bitmapBitOrder = BITMAP_BIT_ORDER; - screen_info->numPixmapFormats = ARRAY_SIZE(depths); - - if (serverGeneration == 1) { - try_raising_nofile_limit(); - LoadExtensionList(xwayland_extensions, - ARRAY_SIZE(xwayland_extensions), FALSE); - } - - wl_log_set_handler_client(xwl_log_handler); - - if (AddScreen(xwl_screen_init, argc, argv) == -1) { - FatalError("Couldn't add screen\n"); - } - - xorgGlxCreateVendor(); - - LocalAccessScopeUser(); - - if (wm_fd >= 0 || init_fd >= 0) { - if (wm_fd >= 0) - TimerSet(NULL, 0, 1, add_client_fd, NULL); - if (init_fd >= 0) - ListenOnOpenFD(init_fd, FALSE); - AddCallback(&SelectionCallback, wm_selection_callback, NULL); - } - else if (listen_fd_count > 0) { - listen_on_fds(); - } -} diff --git a/include/meson.build b/include/meson.build index 5ed4c1b24..8dda8c0fd 100644 --- a/include/meson.build +++ b/include/meson.build @@ -404,19 +404,6 @@ configure_file(output : 'xwin-config.h', input : 'xwin-config.h.meson.in', configuration : xwin_data) -build_xwayland_glamor = build_glamor and gbm_dep.found() - -xwayland_data = configuration_data() -xwayland_data.set('XWL_HAS_GLAMOR', build_xwayland_glamor ? '1' : false) -xwayland_data.set('XWL_HAS_LIBDECOR', have_libdecor ? '1' : false) -xwayland_data.set('XWL_HAS_XWAYLAND_EXTENSION', xwaylandproto_dep.found() ? '1' : false) -xwayland_data.set('XWL_HAS_EI', build_ei) -xwayland_data.set('XWL_HAS_EI_PORTAL', build_ei_portal) - -configure_file(output : 'xwayland-config.h', - input : 'xwayland-config.h.meson.in', - configuration : xwayland_data) - dtrace_hdr = [] dtrace_tmpl = files('Xserver.d') if with_dtrace diff --git a/include/xwayland-config.h.meson.in b/include/xwayland-config.h.meson.in deleted file mode 100644 index 17ca8fcb0..000000000 --- a/include/xwayland-config.h.meson.in +++ /dev/null @@ -1,20 +0,0 @@ -/* xwayland-config.h.meson.in: not at all generated */ - -#pragma once - -#include - -/* Build glamor support for Xwayland */ -#mesondefine XWL_HAS_GLAMOR - -/* Build Xwayland with libdecor support*/ -#mesondefine XWL_HAS_LIBDECOR - -/* Build Xwayland with XWAYLAND extension */ -#mesondefine XWL_HAS_XWAYLAND_EXTENSION - -/* Enable EI */ -#mesondefine XWL_HAS_EI - -/* Enable XDG portal integration */ -#mesondefine XWL_HAS_EI_PORTAL diff --git a/man/Xserver.man b/man/Xserver.man index d722f69a3..937eecf22 100644 --- a/man/Xserver.man +++ b/man/Xserver.man @@ -638,7 +638,6 @@ Controlling the server once started: .PP Server-specific man pages: .BR Xorg (1), -.BR Xwayland (1), .BR Xephyr (1), .BR Xnest (1), .BR Xvfb (1), diff --git a/meson.build b/meson.build index b94849ee6..faf153cfe 100644 --- a/meson.build +++ b/meson.build @@ -66,8 +66,6 @@ libdrm_req = '>= 2.4.116' libselinux_req = '>= 2.0.86' xext_req = '>= 1.0.99.4' xproto_req = '>= 7.0.31' -wayland_req = '>= 1.21.0' -wayland_protocols_req = '>= 1.38' gbm_req = '>= 10.2' xf86dgaproto_req = '>= 2.0.99.1' xshmfence_req = '>= 1.1' @@ -100,7 +98,6 @@ xf86bigfontproto_dep = dependency('xf86bigfontproto', version: '>= 1.2.0', fallb xf86vidmodeproto_dep = dependency('xf86vidmodeproto', version: '>= 2.2.99.1', fallback: ['xorgproto', 'ext_xorgproto']) applewmproto_dep = dependency('applewmproto', version: '>= 1.4', fallback: ['xorgproto', 'ext_xorgproto'], required: false) xshmfence_dep = dependency('xshmfence', version: xshmfence_req, required: false) -xwaylandproto_dep = dependency('xwaylandproto', version: '>= 1.0', fallback: ['xorgproto', 'ext_xorgproto'], required: false) dpmsproto_dep = dependency('dpmsproto', version: '>= 1.2', required: get_option('dpms')) pixman_dep = dependency('pixman-1') @@ -214,38 +211,6 @@ endif xorgsdkdir = join_paths(get_option('prefix'), get_option('includedir'), 'xorg') libxcvt_dep = dependency('libxcvt', fallback: ['libxcvt', 'libxcvt_dep'], required: build_xorg) -build_xwayland = false -if (host_machine.system() != 'darwin' and - host_machine.system() != 'windows' and - get_option('xwayland') != 'false') - xwayland_required = get_option('xwayland') == 'true' - build_glamor = glamor_option == 'true' or glamor_option == 'auto' - - xwayland_path = get_option('xwayland-path') - if (xwayland_path == '') - xwayland_path = join_paths(get_option('prefix'), get_option('bindir')) - endif - - xwayland_dep = [ - dependency('wayland-client', version: wayland_req, required: xwayland_required), - dependency('wayland-protocols', version: wayland_protocols_req, required: xwayland_required), - dependency('libxcvt', fallback: ['libxcvt', 'libxcvt_dep'], required: xwayland_required), - ] - if build_glamor - xwayland_dep += dependency('xshmfence', version: xshmfence_req, required: xwayland_required) - xwayland_dep += dependency('libdrm', version: libdrm_req, required: xwayland_required) - xwayland_dep += dependency('epoxy', required: xwayland_required) - endif - - build_xwayland = true - # check for all the deps being found, to handle 'auto' mode. - foreach d: xwayland_dep - if not d.found() - build_xwayland = false - endif - endforeach -endif - ## configure Xnest - nesting X server build_xnest = get_option('xnest') != 'false' @@ -277,7 +242,6 @@ build_xvfb = get_option('xvfb') summary({ 'Xorg': build_xorg, - 'Xwayland': build_xwayland, 'Xnest': build_xnest, 'Xvfb': build_xvfb, 'Xwin': build_xwin, @@ -350,7 +314,7 @@ endif module_dir = join_paths(get_option('libdir'), get_option('module_dir')) if glamor_option == 'auto' - build_glamor = build_xorg or build_xwayland + build_glamor = build_xorg else build_glamor = glamor_option == 'true' endif @@ -362,32 +326,6 @@ if build_glamor epoxy_dep = dependency('epoxy', required: false) endif -if build_xwayland - libdecor_dep = dependency('libdecor-0', required: false) - libdecor_option = get_option('libdecor') - if libdecor_option == 'auto' - have_libdecor = libdecor_dep.found() - else - have_libdecor = libdecor_option == 'true' - if have_libdecor and not libdecor_dep.found() - error('libdecor support requested but not found') - endif - endif -else - have_libdecor = false -endif - -if build_xwayland - libei_dep = dependency('libei-1.0', version: '>= 1.0.0', required: get_option('xwayland_ei') in ['portal', 'socket']) - liboeffis_dep = dependency('liboeffis-1.0', version: '>= 1.0.0', required: get_option('xwayland_ei') == 'portal') - - build_ei = libei_dep.found() and get_option('xwayland_ei') != 'false' - build_ei_portal = liboeffis_dep.found() and get_option('xwayland_ei') in ['portal', 'auto'] -else - build_ei = false - build_ei_portal = false -endif - # Lots of sha1 options, because Linux is about choice :) # The idea behind the ordering here is that we should first prefer system diff --git a/meson_options.txt b/meson_options.txt index 7c0e7f435..5760b38e9 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -2,12 +2,8 @@ option('xorg', type: 'combo', choices: ['true', 'false', 'auto'], value: 'auto', description: 'Enable Xorg X Server') option('xephyr', type: 'boolean', value: false, description: 'Enable Xephyr nested X server') -option('xwayland', type: 'combo', choices: ['true', 'false', 'auto'], value: 'false', - description: 'Enable Xwayland X server') option('glamor', type: 'combo', choices: ['true', 'false', 'auto'], value: 'auto', - description: 'Enable glamor (default yes for Xorg/Xwayland builds)') -option('xwayland_ei', type: 'combo', choices: ['socket', 'portal', 'false', 'auto'], - value: 'auto', description: 'Enable emulated input support on Xwayland') + description: 'Enable glamor (default yes for Xorg builds)') option('xnest', type: 'combo', choices: ['true', 'false', 'auto'], value: 'auto', description: 'Enable Xnest nested X server') option('xvfb', type: 'boolean', value: true, @@ -141,10 +137,6 @@ option('xpbproxy', type: 'boolean', value: false, option('libunwind', type: 'boolean', value: false, description: 'Use libunwind for backtrace reporting') -option('xwayland-path', type: 'string', description: 'Directory containing Xwayland executable') -option('libdecor', type: 'combo', choices: ['true', 'false', 'auto'], value: 'auto', - description: 'Whether Xwayland should use libdecor when running rootful.') - option('docs', type: 'combo', choices: ['true', 'false', 'auto'], value: 'auto', description: 'Build documentation') option('devel-docs', type: 'combo', choices: ['true', 'false', 'auto'], value: 'auto', diff --git a/miext/sync/meson.build b/miext/sync/meson.build index 0892fd807..78716e441 100644 --- a/miext/sync/meson.build +++ b/miext/sync/meson.build @@ -10,7 +10,7 @@ hdrs_miext_sync = [ 'misyncstr.h', ] -if build_dri3 or build_xwayland +if build_dri3 srcs_miext_sync += 'misyncshm.c' endif diff --git a/test/meson.build b/test/meson.build index 471032b64..2d71564e5 100644 --- a/test/meson.build +++ b/test/meson.build @@ -149,19 +149,6 @@ if get_option('xvfb') endif endif -if build_xwayland - xwayland_args = [ - xwayland_server.full_path(), - ] - - test('XTS', - find_program('scripts/xwayland-piglit.sh'), - env: piglit_env, - timeout: 1200, - suite: 'xwayland' - ) -endif - subdir('bigreq') subdir('damage') subdir('sync') diff --git a/test/scripts/xwayland-piglit.sh b/test/scripts/xwayland-piglit.sh deleted file mode 100755 index 9d6e54d01..000000000 --- a/test/scripts/xwayland-piglit.sh +++ /dev/null @@ -1,62 +0,0 @@ -#!/bin/bash -e - -if test "x$XTEST_DIR" = "x"; then - echo "XTEST_DIR must be set to the directory of the xtest repository." - # Exit as a "skip" so make check works even without xtest. - exit 77 -fi - -if test "x$PIGLIT_DIR" = "x"; then - echo "PIGLIT_DIR must be set to the directory of the piglit repository." - # Exit as a "skip" so make check works even without piglit. - exit 77 -fi - -# this times out on Travis, because the tests take too long. -if test "x$TRAVIS_BUILD_DIR" != "x"; then - exit 77 -fi - -# Weston requires XDG_RUNTIME_DIR -if test "x$XDG_RUNTIME_DIR" = "x"; then - export XDG_RUNTIME_DIR=$(mktemp -d) -fi - -# Skip if weston isn't available -weston --version >/dev/null || exit 77 - -weston --no-config --backend=headless-backend.so --socket=wayland-$$ & -WESTON_PID=$! -export WAYLAND_DISPLAY=wayland-$$ - -# Need to kill weston before exiting, or meson will time out waiting for it to terminate -# We rely on bash's behaviour, which executes the EXIT trap handler even if the shell is -# terminated due to receiving a signal -trap 'kill $WESTON_PID' EXIT - -# Wait for weston to initialize before starting Xwayland -if ! timeout 5s bash -c "while ! $XSERVER_BUILDDIR/hw/xwayland/Xwayland -pogo -displayfd 1 &>/dev/null; do sleep 1; done"; then - # Try running Xwayland one more time, so we can propagate its stdout/stderr - # output and exit status - $XSERVER_BUILDDIR/hw/xwayland/Xwayland -pogo -displayfd 1 -fi - -# Start an Xwayland server -export PIGLIT_RESULTS_DIR=$XSERVER_BUILDDIR/test/piglit-results/xwayland -export SERVER_COMMAND="$XSERVER_BUILDDIR/hw/xwayland/Xwayland -noreset" - -# Make sure glamor doesn't use HW acceleration -export GBM_ALWAYS_SOFTWARE=1 - -# Tests that currently fail on llvmpipe on CI -PIGLIT_ARGS="$PIGLIT_ARGS -x xcleararea@6" -PIGLIT_ARGS="$PIGLIT_ARGS -x xcleararea@7" -PIGLIT_ARGS="$PIGLIT_ARGS -x xclearwindow@4" -PIGLIT_ARGS="$PIGLIT_ARGS -x xclearwindow@5" -PIGLIT_ARGS="$PIGLIT_ARGS -x xcopyarea@1" -PIGLIT_ARGS="$PIGLIT_ARGS -x xsetfontpath@1" -PIGLIT_ARGS="$PIGLIT_ARGS -x xsetfontpath@2" - -export PIGLIT_ARGS - -$XSERVER_DIR/test/scripts/run-piglit.sh