Drop XWayland DDX
This commit is contained in:
parent
72c5d153c9
commit
4ee66f574a
|
@ -180,7 +180,6 @@ EXTRA_DIST += \
|
|||
hw/xfree86/xkb/meson.build \
|
||||
hw/xnest/meson.build \
|
||||
hw/xquartz/meson.build \
|
||||
hw/xwayland/meson.build \
|
||||
hw/xwin/dri/meson.build \
|
||||
hw/xwin/glx/meson.build \
|
||||
hw/xwin/meson.build \
|
||||
|
|
98
configure.ac
98
configure.ac
|
@ -67,8 +67,6 @@ dnl xkb-config.h covers XKB for the Xorg and Xnest DDXs.
|
|||
AC_CONFIG_HEADERS(include/xkb-config.h)
|
||||
dnl xwin-config.h covers the XWin DDX.
|
||||
AC_CONFIG_HEADERS(include/xwin-config.h)
|
||||
dnl xwayland-config.h covers Xwayland.
|
||||
AC_CONFIG_HEADERS(include/xwayland-config.h)
|
||||
dnl version-config.h covers the version numbers so they can be bumped without
|
||||
dnl forcing an entire recompile.x
|
||||
AC_CONFIG_HEADERS(include/version-config.h)
|
||||
|
@ -575,10 +573,6 @@ AC_ARG_ENABLE(xorg, AS_HELP_STRING([--enable-xorg], [Build Xorg server
|
|||
AC_ARG_ENABLE(xvfb, AS_HELP_STRING([--enable-xvfb], [Build Xvfb server (default: yes)]), [XVFB=$enableval], [XVFB=yes])
|
||||
AC_ARG_ENABLE(xnest, AS_HELP_STRING([--enable-xnest], [Build Xnest server (default: auto)]), [XNEST=$enableval], [XNEST=auto])
|
||||
AC_ARG_ENABLE(xquartz, AS_HELP_STRING([--enable-xquartz], [Build Xquartz server for OS-X (default: auto)]), [XQUARTZ=$enableval], [XQUARTZ=auto])
|
||||
AC_ARG_ENABLE(xwayland, AS_HELP_STRING([--enable-xwayland], [Build Xwayland server (default: auto)]), [XWAYLAND=$enableval], [XWAYLAND=auto])
|
||||
AC_ARG_ENABLE(xwayland-eglstream, AS_HELP_STRING([--enable-xwayland-eglstream], [Build Xwayland eglstream support (default: no)]), [XWAYLAND_EGLSTREAM=$enableval], [XWAYLAND_EGLSTREAM=no])
|
||||
AC_ARG_WITH(xwayland-path, AS_HELP_STRING([--with-xwayland-path=PATH], [Directory containing Xwayland executable (default: ${bindir})]),
|
||||
[ xwayland_path="$withval" ], [ xwayland_path="$bindir" ])
|
||||
AC_ARG_ENABLE(standalone-xpbproxy, AS_HELP_STRING([--enable-standalone-xpbproxy], [Build a standalone xpbproxy (in addition to the one integrated into Xquartz as a separate thread) (default: no)]), [STANDALONE_XPBPROXY=$enableval], [STANDALONE_XPBPROXY=no])
|
||||
AC_ARG_ENABLE(xwin, AS_HELP_STRING([--enable-xwin], [Build XWin server (default: auto)]), [XWIN=$enableval], [XWIN=auto])
|
||||
AC_ARG_ENABLE(glamor, AS_HELP_STRING([--enable-glamor], [Build glamor dix module (default: auto)]), [GLAMOR=$enableval], [GLAMOR=auto])
|
||||
|
@ -685,7 +679,6 @@ case $host_os in
|
|||
XQUARTZ=yes
|
||||
XVFB=no
|
||||
XNEST=no
|
||||
XWAYLAND=no
|
||||
|
||||
COMPOSITE=no
|
||||
DGA=no
|
||||
|
@ -2019,7 +2012,7 @@ AM_CONDITIONAL([XORG_DRIVER_INPUT_INPUTTEST], [test "x$XORG_DRIVER_INPUT_INPUTTE
|
|||
|
||||
dnl glamor
|
||||
if test "x$GLAMOR" = xauto; then
|
||||
if echo "$XORG" "$XEPHYR" "$XWAYLAND" | grep -q yes ; then
|
||||
if echo "$XORG" "$XEPHYR" | grep -q yes ; then
|
||||
GLAMOR=yes
|
||||
fi
|
||||
fi
|
||||
|
@ -2234,92 +2227,6 @@ AC_SUBST([KDRIVE_LOCAL_LIBS])
|
|||
AC_SUBST([KDRIVE_LIBS])
|
||||
AM_CONDITIONAL(XEPHYR, [test "x$KDRIVE" = xyes && test "x$XEPHYR" = xyes])
|
||||
|
||||
dnl Xwayland DDX
|
||||
|
||||
XWAYLANDMODULES="wayland-client >= 1.5.0 wayland-protocols >= 1.18"
|
||||
if test "x$XF86VIDMODE" = xyes; then
|
||||
XWAYLANDMODULES="$XWAYLANDMODULES $VIDMODEPROTO"
|
||||
fi
|
||||
if test "x$DRM" = xyes; then
|
||||
XWAYLANDMODULES="$XWAYLANDMODULES $LIBDRM"
|
||||
fi
|
||||
if test "x$GLAMOR" = xyes; then
|
||||
XWAYLANDMODULES="$XWAYLANDMODULES epoxy"
|
||||
fi
|
||||
PKG_CHECK_MODULES(XWAYLANDMODULES, [$XWAYLANDMODULES], [have_xwayland=yes], [have_xwayland=no])
|
||||
AC_MSG_CHECKING([whether to build Xwayland DDX])
|
||||
if test "x$XWAYLAND" = xauto; then
|
||||
XWAYLAND="$have_xwayland"
|
||||
fi
|
||||
AC_MSG_RESULT([$XWAYLAND])
|
||||
AM_CONDITIONAL(XWAYLAND, [test "x$XWAYLAND" = xyes])
|
||||
|
||||
if test "x$XWAYLAND" = xyes; then
|
||||
if test "x$have_xwayland" = xno; then
|
||||
AC_MSG_ERROR([Xwayland build explicitly requested, but required modules not found.])
|
||||
fi
|
||||
|
||||
if test "x$GLAMOR" = xyes && test "x$GBM" = xyes; then
|
||||
AC_DEFINE(XWL_HAS_GLAMOR, 1,
|
||||
[Build xwayland with glamor support])
|
||||
AC_SUBST(have_glamor, "true")
|
||||
else
|
||||
AC_SUBST(have_glamor, "false")
|
||||
fi
|
||||
|
||||
PKG_CHECK_MODULES(WAYLAND_EGLSTREAM, [wayland-eglstream-protocols >= 1.0.2], [have_wl_eglstream=yes], [have_wl_eglstream=no])
|
||||
|
||||
if test "x$XWAYLAND_EGLSTREAM" = xauto; then
|
||||
if test "x$have_wl_eglstream" = xyes && test "x$GLAMOR" = xyes; then
|
||||
XWAYLAND_EGLSTREAM=yes
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "x$XWAYLAND_EGLSTREAM" = xyes; then
|
||||
if test "x$GLAMOR" != xyes; then
|
||||
AC_MSG_ERROR([Xwayland eglstream support explicitly requested, but required modules not found.])
|
||||
fi
|
||||
|
||||
if test "x$have_wl_eglstream" = xno; then
|
||||
AC_MSG_ERROR([Xwayland eglstream support requires wayland-eglstream-protocols >= 1.0.2])
|
||||
fi
|
||||
|
||||
AC_SUBST(WAYLAND_EGLSTREAM_DATADIR, `$PKG_CONFIG --variable=pkgdatadir wayland-eglstream-protocols`)
|
||||
AC_DEFINE(XWL_HAS_EGLSTREAM, 1,
|
||||
[Build xwayland with eglstream support])
|
||||
AC_SUBST(have_eglstream, "true")
|
||||
else
|
||||
AC_SUBST(have_eglstream, "false")
|
||||
fi
|
||||
|
||||
PKG_CHECK_MODULES([LIBXCVT], $LIBXCVT)
|
||||
|
||||
XWAYLAND_LIBS="$FB_LIB $FIXES_LIB $MI_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $DRI3_LIB $PRESENT_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $MAIN_LIB $DIX_LIB $OS_LIB"
|
||||
XWAYLAND_SYS_LIBS="$XWAYLANDMODULES_LIBS $GLX_SYS_LIBS $LIBXCVT_LIBS"
|
||||
AC_SUBST([XWAYLAND_LIBS])
|
||||
AC_SUBST([XWAYLAND_SYS_LIBS])
|
||||
|
||||
if test "x$MONOTONIC_CLOCK" != xyes; then
|
||||
AC_MSG_ERROR([Xwayland requires CLOCK_MONOTONIC support.])
|
||||
fi
|
||||
|
||||
AC_PATH_PROG([WAYLAND_SCANNER], [wayland-scanner])
|
||||
if test "x$WAYLAND_SCANNER" = x; then
|
||||
PKG_CHECK_MODULES(WAYLAND_SCANNER, [wayland-scanner])
|
||||
AC_SUBST(WAYLAND_SCANNER, `$PKG_CONFIG --variable=wayland_scanner wayland-scanner`)
|
||||
fi
|
||||
|
||||
PKG_CHECK_MODULES(WAYLAND_SCANNER, [wayland-scanner >= 1.14.91],
|
||||
AC_SUBST(SCANNER_ARG, 'private-code'),
|
||||
AC_SUBST(SCANNER_ARG, 'code'))
|
||||
|
||||
AC_SUBST(WAYLAND_PROTOCOLS_DATADIR, `$PKG_CONFIG --variable=pkgdatadir wayland-protocols`)
|
||||
|
||||
AC_SUBST(xwayland_path)
|
||||
|
||||
fi
|
||||
AM_CONDITIONAL(XWAYLAND_EGLSTREAM, [test "x$XWAYLAND_EGLSTREAM" = "xyes"])
|
||||
|
||||
|
||||
dnl and the rest of these are generic, so they're in config.h
|
||||
dnl
|
||||
|
@ -2450,9 +2357,6 @@ hw/kdrive/Makefile
|
|||
hw/kdrive/ephyr/Makefile
|
||||
hw/kdrive/ephyr/man/Makefile
|
||||
hw/kdrive/src/Makefile
|
||||
hw/xwayland/Makefile
|
||||
hw/xwayland/man/Makefile
|
||||
hw/xwayland/xwayland.pc
|
||||
test/Makefile
|
||||
xserver.ent
|
||||
xorg-server.pc
|
||||
|
|
|
@ -22,20 +22,15 @@ if XQUARTZ
|
|||
XQUARTZ_SUBDIRS = xquartz
|
||||
endif
|
||||
|
||||
if XWAYLAND
|
||||
XWAYLAND_SUBDIRS = xwayland
|
||||
endif
|
||||
|
||||
SUBDIRS = \
|
||||
$(XORG_SUBDIRS) \
|
||||
$(XWIN_SUBDIRS) \
|
||||
$(XVFB_SUBDIRS) \
|
||||
$(XNEST_SUBDIRS) \
|
||||
$(KDRIVE_SUBDIRS) \
|
||||
$(XQUARTZ_SUBDIRS) \
|
||||
$(XWAYLAND_SUBDIRS)
|
||||
$(XQUARTZ_SUBDIRS)
|
||||
|
||||
DIST_SUBDIRS = xfree86 vfb xnest xwin xquartz kdrive xwayland
|
||||
DIST_SUBDIRS = xfree86 vfb xnest xwin xquartz kdrive
|
||||
|
||||
relink:
|
||||
$(AM_V_at)for i in $(SUBDIRS) ; do $(MAKE) -C $$i relink || exit 1 ; done
|
||||
|
|
|
@ -18,10 +18,6 @@ if build_xquartz
|
|||
subdir('xquartz')
|
||||
endif
|
||||
|
||||
if build_xwayland
|
||||
subdir('xwayland')
|
||||
endif
|
||||
|
||||
if build_xwin
|
||||
subdir('xwin')
|
||||
endif
|
||||
|
|
|
@ -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
|
|
@ -1,189 +0,0 @@
|
|||
SUBDIRS = man
|
||||
|
||||
DIST_SUBDIRS = man
|
||||
|
||||
bindir = @xwayland_path@
|
||||
bin_PROGRAMS = Xwayland
|
||||
|
||||
Xwayland_CFLAGS = \
|
||||
-I$(top_srcdir)/glamor \
|
||||
-I$(top_srcdir)/dri3 \
|
||||
-DHAVE_DIX_CONFIG_H \
|
||||
$(XWAYLANDMODULES_CFLAGS) \
|
||||
$(DIX_CFLAGS) \
|
||||
$(GLAMOR_CFLAGS) \
|
||||
$(GBM_CFLAGS) \
|
||||
$(LIBXCVT_CFLAGS)
|
||||
|
||||
Xwayland_SOURCES = \
|
||||
xwayland.c \
|
||||
xwayland-input.c \
|
||||
xwayland-input.h \
|
||||
xwayland-cursor.c \
|
||||
xwayland-cursor.h \
|
||||
xwayland-glamor.h \
|
||||
xwayland-glx.h \
|
||||
xwayland-pixmap.c \
|
||||
xwayland-pixmap.h \
|
||||
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 \
|
||||
$(top_srcdir)/Xi/stubs.c \
|
||||
$(top_srcdir)/mi/miinitext.c \
|
||||
$(top_srcdir)/mi/miinitext.h
|
||||
|
||||
if GLAMOR
|
||||
if GLX
|
||||
Xwayland_SOURCES += \
|
||||
xwayland-glx.c
|
||||
Xwayland_CFLAGS += \
|
||||
-I$(top_srcdir)/glx
|
||||
GLXVND_LIB = $(top_builddir)/glx/libglxvnd.la
|
||||
endif #GLX
|
||||
endif # GLAMOR
|
||||
|
||||
Xwayland_LDADD = \
|
||||
$(glamor_lib) \
|
||||
$(XWAYLAND_LIBS) \
|
||||
$(GLXVND_LIB) \
|
||||
$(XWAYLAND_SYS_LIBS) \
|
||||
$(top_builddir)/Xext/libXvidmode.la \
|
||||
$(XSERVER_SYS_LIBS) \
|
||||
$(LIBXCVT_LIBS)
|
||||
Xwayland_LDFLAGS = $(LD_EXPORT_SYMBOLS_FLAG)
|
||||
|
||||
Xwayland_built_sources =
|
||||
|
||||
if GLAMOR_EGL
|
||||
Xwayland_SOURCES += \
|
||||
xwayland-glamor.c \
|
||||
xwayland-glamor-gbm.c \
|
||||
xwayland-present.c
|
||||
if XV
|
||||
Xwayland_SOURCES += \
|
||||
xwayland-glamor-xv.c
|
||||
endif
|
||||
|
||||
if XWAYLAND_EGLSTREAM
|
||||
Xwayland_SOURCES += \
|
||||
xwayland-glamor-eglstream.c
|
||||
endif
|
||||
|
||||
glamor_built_sources = \
|
||||
drm-client-protocol.h \
|
||||
drm-protocol.c
|
||||
|
||||
Xwayland_built_sources += $(glamor_built_sources)
|
||||
|
||||
glamor_lib = $(top_builddir)/glamor/libglamor.la
|
||||
|
||||
Xwayland_LDADD += $(GLAMOR_LIBS) $(GBM_LIBS) -lEGL -lGL
|
||||
Xwayland_DEPENDENCIES = $(glamor_lib) $(XWAYLAND_LIBS)
|
||||
endif
|
||||
|
||||
Xwayland_built_sources += \
|
||||
relative-pointer-unstable-v1-client-protocol.h \
|
||||
relative-pointer-unstable-v1-protocol.c \
|
||||
pointer-constraints-unstable-v1-client-protocol.h \
|
||||
pointer-constraints-unstable-v1-protocol.c \
|
||||
tablet-unstable-v2-client-protocol.h \
|
||||
tablet-unstable-v2-protocol.c \
|
||||
xwayland-keyboard-grab-unstable-v1-protocol.c \
|
||||
xwayland-keyboard-grab-unstable-v1-client-protocol.h \
|
||||
xdg-output-unstable-v1-protocol.c \
|
||||
xdg-output-unstable-v1-client-protocol.h \
|
||||
linux-dmabuf-unstable-v1-client-protocol.h \
|
||||
linux-dmabuf-unstable-v1-protocol.c \
|
||||
viewporter-client-protocol.h \
|
||||
viewporter-protocol.c\
|
||||
xdg-shell-client-protocol.h\
|
||||
xdg-shell-protocol.c
|
||||
|
||||
if XWAYLAND_EGLSTREAM
|
||||
Xwayland_built_sources += \
|
||||
wayland-eglstream-client-protocol.h \
|
||||
wayland-eglstream-protocol.c \
|
||||
wayland-eglstream-controller-client-protocol.h \
|
||||
wayland-eglstream-controller-protocol.c
|
||||
endif
|
||||
|
||||
nodist_Xwayland_SOURCES = $(Xwayland_built_sources)
|
||||
CLEANFILES = $(Xwayland_built_sources)
|
||||
|
||||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
pkgconfig_DATA = xwayland.pc
|
||||
|
||||
EXTRA_DIST = xwayland.pc.in drm.xml
|
||||
|
||||
$(Xwayland_SOURCES): $(Xwayland_built_sources)
|
||||
|
||||
relink:
|
||||
$(AM_V_at)rm -f Xwayland$(EXEEXT) && $(MAKE) Xwayland$(EXEEXT)
|
||||
|
||||
relative-pointer-unstable-v1-protocol.c : $(WAYLAND_PROTOCOLS_DATADIR)/unstable/relative-pointer/relative-pointer-unstable-v1.xml
|
||||
$(AM_V_GEN)$(WAYLAND_SCANNER) @SCANNER_ARG@ < $< > $@
|
||||
relative-pointer-unstable-v1-client-protocol.h : $(WAYLAND_PROTOCOLS_DATADIR)/unstable/relative-pointer/relative-pointer-unstable-v1.xml
|
||||
$(AM_V_GEN)$(WAYLAND_SCANNER) client-header < $< > $@
|
||||
|
||||
pointer-constraints-unstable-v1-protocol.c : $(WAYLAND_PROTOCOLS_DATADIR)/unstable/pointer-constraints/pointer-constraints-unstable-v1.xml
|
||||
$(AM_V_GEN)$(WAYLAND_SCANNER) @SCANNER_ARG@ < $< > $@
|
||||
pointer-constraints-unstable-v1-client-protocol.h : $(WAYLAND_PROTOCOLS_DATADIR)/unstable/pointer-constraints/pointer-constraints-unstable-v1.xml
|
||||
$(AM_V_GEN)$(WAYLAND_SCANNER) client-header < $< > $@
|
||||
|
||||
tablet-unstable-v2-protocol.c: $(WAYLAND_PROTOCOLS_DATADIR)/unstable/tablet/tablet-unstable-v2.xml
|
||||
$(AM_V_GEN)$(WAYLAND_SCANNER) @SCANNER_ARG@ < $< > $@
|
||||
tablet-unstable-v2-client-protocol.h: $(WAYLAND_PROTOCOLS_DATADIR)/unstable/tablet/tablet-unstable-v2.xml
|
||||
$(AM_V_GEN)$(WAYLAND_SCANNER) client-header < $< > $@
|
||||
|
||||
xwayland-keyboard-grab-unstable-v1-protocol.c : $(WAYLAND_PROTOCOLS_DATADIR)/unstable/xwayland-keyboard-grab/xwayland-keyboard-grab-unstable-v1.xml
|
||||
$(AM_V_GEN)$(WAYLAND_SCANNER) @SCANNER_ARG@ < $< > $@
|
||||
xwayland-keyboard-grab-unstable-v1-client-protocol.h : $(WAYLAND_PROTOCOLS_DATADIR)/unstable/xwayland-keyboard-grab/xwayland-keyboard-grab-unstable-v1.xml
|
||||
$(AM_V_GEN)$(WAYLAND_SCANNER) client-header < $< > $@
|
||||
xdg-output-unstable-v1-protocol.c : $(WAYLAND_PROTOCOLS_DATADIR)/unstable/xdg-output/xdg-output-unstable-v1.xml
|
||||
$(AM_V_GEN)$(WAYLAND_SCANNER) @SCANNER_ARG@ < $< > $@
|
||||
xdg-output-unstable-v1-client-protocol.h : $(WAYLAND_PROTOCOLS_DATADIR)/unstable/xdg-output/xdg-output-unstable-v1.xml
|
||||
$(AM_V_GEN)$(WAYLAND_SCANNER) client-header < $< > $@
|
||||
|
||||
linux-dmabuf-unstable-v1-protocol.c : $(WAYLAND_PROTOCOLS_DATADIR)/unstable/linux-dmabuf/linux-dmabuf-unstable-v1.xml
|
||||
$(AM_V_GEN)$(WAYLAND_SCANNER) @SCANNER_ARG@ < $< > $@
|
||||
linux-dmabuf-unstable-v1-client-protocol.h : $(WAYLAND_PROTOCOLS_DATADIR)/unstable/linux-dmabuf/linux-dmabuf-unstable-v1.xml
|
||||
$(AM_V_GEN)$(WAYLAND_SCANNER) client-header < $< > $@
|
||||
|
||||
viewporter-protocol.c: $(WAYLAND_PROTOCOLS_DATADIR)/stable/viewporter/viewporter.xml
|
||||
$(AM_V_GEN)$(WAYLAND_SCANNER) @SCANNER_ARG@ < $< > $@
|
||||
viewporter-client-protocol.h: $(WAYLAND_PROTOCOLS_DATADIR)/stable/viewporter/viewporter.xml
|
||||
$(AM_V_GEN)$(WAYLAND_SCANNER) client-header < $< > $@
|
||||
|
||||
xdg-shell-protocol.c: $(WAYLAND_PROTOCOLS_DATADIR)/stable/xdg-shell/xdg-shell.xml
|
||||
$(AM_V_GEN)$(WAYLAND_SCANNER) @SCANNER_ARG@ < $< > $@
|
||||
xdg-shell-client-protocol.h: $(WAYLAND_PROTOCOLS_DATADIR)/stable/xdg-shell/xdg-shell.xml
|
||||
$(AM_V_GEN)$(WAYLAND_SCANNER) client-header < $< > $@
|
||||
|
||||
wayland-eglstream-client-protocol.h : $(WAYLAND_EGLSTREAM_DATADIR)/wayland-eglstream.xml
|
||||
$(AM_V_GEN)$(WAYLAND_SCANNER) client-header < $< > $@
|
||||
wayland-eglstream-controller-client-protocol.h : $(WAYLAND_EGLSTREAM_DATADIR)/wayland-eglstream-controller.xml
|
||||
$(AM_V_GEN)$(WAYLAND_SCANNER) client-header < $< > $@
|
||||
|
||||
wayland-eglstream-protocol.c : $(WAYLAND_EGLSTREAM_DATADIR)/wayland-eglstream.xml
|
||||
$(AM_V_GEN)$(WAYLAND_SCANNER) code < $< > $@
|
||||
wayland-eglstream-controller-protocol.c : $(WAYLAND_EGLSTREAM_DATADIR)/wayland-eglstream-controller.xml
|
||||
$(AM_V_GEN)$(WAYLAND_SCANNER) code < $< > $@
|
||||
|
||||
%-protocol.c : %.xml
|
||||
$(AM_V_GEN)$(WAYLAND_SCANNER) @SCANNER_ARG@ < $< > $@
|
||||
|
||||
%-client-protocol.h : %.xml
|
||||
$(AM_V_GEN)$(WAYLAND_SCANNER) client-header < $< > $@
|
|
@ -1,185 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<protocol name="drm">
|
||||
|
||||
<copyright>
|
||||
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.
|
||||
</copyright>
|
||||
|
||||
<!-- drm support. This object is created by the server and published
|
||||
using the display's global event. -->
|
||||
<interface name="wl_drm" version="2">
|
||||
<enum name="error">
|
||||
<entry name="authenticate_fail" value="0"/>
|
||||
<entry name="invalid_format" value="1"/>
|
||||
<entry name="invalid_name" value="2"/>
|
||||
</enum>
|
||||
|
||||
<enum name="format">
|
||||
<!-- The drm format codes match the #defines in drm_fourcc.h.
|
||||
The formats actually supported by the compositor will be
|
||||
reported by the format event. -->
|
||||
<entry name="c8" value="0x20203843"/>
|
||||
<entry name="rgb332" value="0x38424752"/>
|
||||
<entry name="bgr233" value="0x38524742"/>
|
||||
<entry name="xrgb4444" value="0x32315258"/>
|
||||
<entry name="xbgr4444" value="0x32314258"/>
|
||||
<entry name="rgbx4444" value="0x32315852"/>
|
||||
<entry name="bgrx4444" value="0x32315842"/>
|
||||
<entry name="argb4444" value="0x32315241"/>
|
||||
<entry name="abgr4444" value="0x32314241"/>
|
||||
<entry name="rgba4444" value="0x32314152"/>
|
||||
<entry name="bgra4444" value="0x32314142"/>
|
||||
<entry name="xrgb1555" value="0x35315258"/>
|
||||
<entry name="xbgr1555" value="0x35314258"/>
|
||||
<entry name="rgbx5551" value="0x35315852"/>
|
||||
<entry name="bgrx5551" value="0x35315842"/>
|
||||
<entry name="argb1555" value="0x35315241"/>
|
||||
<entry name="abgr1555" value="0x35314241"/>
|
||||
<entry name="rgba5551" value="0x35314152"/>
|
||||
<entry name="bgra5551" value="0x35314142"/>
|
||||
<entry name="rgb565" value="0x36314752"/>
|
||||
<entry name="bgr565" value="0x36314742"/>
|
||||
<entry name="rgb888" value="0x34324752"/>
|
||||
<entry name="bgr888" value="0x34324742"/>
|
||||
<entry name="xrgb8888" value="0x34325258"/>
|
||||
<entry name="xbgr8888" value="0x34324258"/>
|
||||
<entry name="rgbx8888" value="0x34325852"/>
|
||||
<entry name="bgrx8888" value="0x34325842"/>
|
||||
<entry name="argb8888" value="0x34325241"/>
|
||||
<entry name="abgr8888" value="0x34324241"/>
|
||||
<entry name="rgba8888" value="0x34324152"/>
|
||||
<entry name="bgra8888" value="0x34324142"/>
|
||||
<entry name="xrgb2101010" value="0x30335258"/>
|
||||
<entry name="xbgr2101010" value="0x30334258"/>
|
||||
<entry name="rgbx1010102" value="0x30335852"/>
|
||||
<entry name="bgrx1010102" value="0x30335842"/>
|
||||
<entry name="argb2101010" value="0x30335241"/>
|
||||
<entry name="abgr2101010" value="0x30334241"/>
|
||||
<entry name="rgba1010102" value="0x30334152"/>
|
||||
<entry name="bgra1010102" value="0x30334142"/>
|
||||
<entry name="yuyv" value="0x56595559"/>
|
||||
<entry name="yvyu" value="0x55595659"/>
|
||||
<entry name="uyvy" value="0x59565955"/>
|
||||
<entry name="vyuy" value="0x59555956"/>
|
||||
<entry name="ayuv" value="0x56555941"/>
|
||||
<entry name="nv12" value="0x3231564e"/>
|
||||
<entry name="nv21" value="0x3132564e"/>
|
||||
<entry name="nv16" value="0x3631564e"/>
|
||||
<entry name="nv61" value="0x3136564e"/>
|
||||
<entry name="yuv410" value="0x39565559"/>
|
||||
<entry name="yvu410" value="0x39555659"/>
|
||||
<entry name="yuv411" value="0x31315559"/>
|
||||
<entry name="yvu411" value="0x31315659"/>
|
||||
<entry name="yuv420" value="0x32315559"/>
|
||||
<entry name="yvu420" value="0x32315659"/>
|
||||
<entry name="yuv422" value="0x36315559"/>
|
||||
<entry name="yvu422" value="0x36315659"/>
|
||||
<entry name="yuv444" value="0x34325559"/>
|
||||
<entry name="yvu444" value="0x34325659"/>
|
||||
</enum>
|
||||
|
||||
<!-- Call this request with the magic received from drmGetMagic().
|
||||
It will be passed on to the drmAuthMagic() or
|
||||
DRIAuthConnection() call. This authentication must be
|
||||
completed before create_buffer could be used. -->
|
||||
<request name="authenticate">
|
||||
<arg name="id" type="uint"/>
|
||||
</request>
|
||||
|
||||
<!-- Create a wayland buffer for the named DRM buffer. The DRM
|
||||
surface must have a name using the flink ioctl -->
|
||||
<request name="create_buffer">
|
||||
<arg name="id" type="new_id" interface="wl_buffer"/>
|
||||
<arg name="name" type="uint"/>
|
||||
<arg name="width" type="int"/>
|
||||
<arg name="height" type="int"/>
|
||||
<arg name="stride" type="uint"/>
|
||||
<arg name="format" type="uint"/>
|
||||
</request>
|
||||
|
||||
<!-- Create a wayland buffer for the named DRM buffer. The DRM
|
||||
surface must have a name using the flink ioctl -->
|
||||
<request name="create_planar_buffer">
|
||||
<arg name="id" type="new_id" interface="wl_buffer"/>
|
||||
<arg name="name" type="uint"/>
|
||||
<arg name="width" type="int"/>
|
||||
<arg name="height" type="int"/>
|
||||
<arg name="format" type="uint"/>
|
||||
<arg name="offset0" type="int"/>
|
||||
<arg name="stride0" type="int"/>
|
||||
<arg name="offset1" type="int"/>
|
||||
<arg name="stride1" type="int"/>
|
||||
<arg name="offset2" type="int"/>
|
||||
<arg name="stride2" type="int"/>
|
||||
</request>
|
||||
|
||||
<!-- Notification of the path of the drm device which is used by
|
||||
the server. The client should use this device for creating
|
||||
local buffers. Only buffers created from this device should
|
||||
be be passed to the server using this drm object's
|
||||
create_buffer request. -->
|
||||
<event name="device">
|
||||
<arg name="name" type="string"/>
|
||||
</event>
|
||||
|
||||
<event name="format">
|
||||
<arg name="format" type="uint"/>
|
||||
</event>
|
||||
|
||||
<!-- Raised if the authenticate request succeeded -->
|
||||
<event name="authenticated"/>
|
||||
|
||||
<enum name="capability" since="2">
|
||||
<description summary="wl_drm capability bitmask">
|
||||
Bitmask of capabilities.
|
||||
</description>
|
||||
<entry name="prime" value="1" summary="wl_drm prime available"/>
|
||||
</enum>
|
||||
|
||||
<event name="capabilities">
|
||||
<arg name="value" type="uint"/>
|
||||
</event>
|
||||
|
||||
<!-- Version 2 additions -->
|
||||
|
||||
<!-- Create a wayland buffer for the prime fd. Use for regular and planar
|
||||
buffers. Pass 0 for offset and stride for unused planes. -->
|
||||
<request name="create_prime_buffer" since="2">
|
||||
<arg name="id" type="new_id" interface="wl_buffer"/>
|
||||
<arg name="name" type="fd"/>
|
||||
<arg name="width" type="int"/>
|
||||
<arg name="height" type="int"/>
|
||||
<arg name="format" type="uint"/>
|
||||
<arg name="offset0" type="int"/>
|
||||
<arg name="stride0" type="int"/>
|
||||
<arg name="offset1" type="int"/>
|
||||
<arg name="stride1" type="int"/>
|
||||
<arg name="offset2" type="int"/>
|
||||
<arg name="stride2" type="int"/>
|
||||
</request>
|
||||
|
||||
</interface>
|
||||
|
||||
</protocol>
|
|
@ -1,2 +0,0 @@
|
|||
include $(top_srcdir)/manpages.am
|
||||
appman_PRE = Xwayland.man
|
|
@ -1,107 +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 \fIXserver\fP(@miscmansuffix@) manual page.
|
||||
The following additional arguments are supported as well.
|
||||
.TP 8
|
||||
.B \-eglstream
|
||||
Use EGLStream backend for NVidia GPUs. If \fIXwayland\fP was compiled with
|
||||
EGLStream support, this option will instruct \fIXwayland\fP to try that
|
||||
backend first, then fallback to the GBM backend if EGLStream is not supported
|
||||
by the Wayland server. Without this option, \fIXwayland\fP tries the GBM
|
||||
backend first, and fallback to EGLStream if GBM is not usable.
|
||||
.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 \-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
|
||||
.BI \-shm
|
||||
Force the shared memory backend instead of glamor (if available) for passing
|
||||
buffers to the Wayland server.
|
||||
.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
|
||||
.BI \-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: \fIX\fP(@miscmansuffix@)
|
|
@ -1,160 +0,0 @@
|
|||
srcs = [
|
||||
'xwayland.c',
|
||||
'xwayland-input.c',
|
||||
'xwayland-input.h',
|
||||
'xwayland-cursor.c',
|
||||
'xwayland-cursor.h',
|
||||
'xwayland-glamor.h',
|
||||
'xwayland-glx.h',
|
||||
'xwayland-pixmap.c',
|
||||
'xwayland-pixmap.h',
|
||||
'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_pkgconfig_variable('wayland_scanner'))
|
||||
|
||||
protocols_dep = dependency('wayland-protocols', version: wayland_protocols_req)
|
||||
protodir = protocols_dep.get_pkgconfig_variable('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')
|
||||
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')
|
||||
|
||||
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@']
|
||||
)
|
||||
srcs += client_header.process(relative_xml)
|
||||
srcs += client_header.process(pointer_xml)
|
||||
srcs += client_header.process(tablet_xml)
|
||||
srcs += client_header.process(kbgrab_xml)
|
||||
srcs += client_header.process(xdg_output_xml)
|
||||
srcs += client_header.process(dmabuf_xml)
|
||||
srcs += client_header.process(viewporter_xml)
|
||||
srcs += client_header.process(xdg_shell_xml)
|
||||
srcs += code.process(relative_xml)
|
||||
srcs += code.process(pointer_xml)
|
||||
srcs += code.process(tablet_xml)
|
||||
srcs += code.process(kbgrab_xml)
|
||||
srcs += code.process(xdg_output_xml)
|
||||
srcs += code.process(dmabuf_xml)
|
||||
srcs += code.process(viewporter_xml)
|
||||
srcs += code.process(xdg_shell_xml)
|
||||
|
||||
xwayland_glamor = []
|
||||
eglstream_srcs = []
|
||||
if build_glamor
|
||||
srcs += 'xwayland-glamor.c'
|
||||
if build_glx
|
||||
srcs += 'xwayland-glx.c'
|
||||
endif
|
||||
if gbm_dep.found()
|
||||
srcs += 'xwayland-glamor-gbm.c'
|
||||
endif
|
||||
if build_eglstream
|
||||
eglstream_protodir = eglstream_dep.get_pkgconfig_variable('pkgdatadir')
|
||||
eglstream_xml = join_paths(eglstream_protodir, 'wayland-eglstream.xml')
|
||||
eglstream_controller_xml = join_paths(eglstream_protodir, 'wayland-eglstream-controller.xml')
|
||||
|
||||
srcs += client_header.process(eglstream_xml)
|
||||
srcs += client_header.process(eglstream_controller_xml)
|
||||
srcs += code.process(eglstream_xml)
|
||||
srcs += code.process(eglstream_controller_xml)
|
||||
|
||||
srcs += 'xwayland-glamor-eglstream.c'
|
||||
endif
|
||||
srcs += 'xwayland-present.c'
|
||||
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
|
||||
|
||||
xwayland_server = executable(
|
||||
'Xwayland',
|
||||
srcs,
|
||||
include_directories: wayland_inc,
|
||||
dependencies: [
|
||||
common_dep,
|
||||
xwayland_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_data = configuration_data()
|
||||
xwayland_data.set('prefix', get_option('prefix'))
|
||||
xwayland_data.set('exec_prefix', '${prefix}')
|
||||
xwayland_data.set('PACKAGE_VERSION', meson.project_version())
|
||||
xwayland_data.set('xwayland_path', xwayland_path)
|
||||
xwayland_data.set('have_glamor', build_glamor ? 'true' : 'false')
|
||||
xwayland_data.set('have_eglstream', build_eglstream ? 'true' : 'false')
|
||||
configure_file(
|
||||
input: 'xwayland.pc.in',
|
||||
output: 'xwayland.pc',
|
||||
configuration: xwayland_data,
|
||||
install_dir: join_paths(get_option('prefix'),
|
||||
get_option('libdir'),
|
||||
'pkgconfig'),
|
||||
)
|
||||
|
||||
xwayland_manpage = configure_file(
|
||||
input: 'man/Xwayland.man',
|
||||
output: 'Xwayland.1',
|
||||
configuration: manpage_config,
|
||||
)
|
||||
install_man(xwayland_manpage)
|
|
@ -1,428 +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 <xwayland-config.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 DevPrivateKeyRec xwl_cursor_private_key;
|
||||
|
||||
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->foreGreen >> 8);
|
||||
bg = ((cursor->backRed & 0xff00) << 8) |
|
||||
(cursor->backGreen & 0xff00) | (cursor->backGreen >> 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)
|
||||
{
|
||||
PixmapPtr pixmap;
|
||||
|
||||
pixmap = xwl_shm_create_pixmap(screen, cursor->bits->width,
|
||||
cursor->bits->height, 32,
|
||||
CREATE_PIXMAP_USAGE_BACKING_PIXMAP);
|
||||
dixSetPrivate(&cursor->devPrivates, &xwl_cursor_private_key, pixmap);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static Bool
|
||||
xwl_unrealize_cursor(DeviceIntPtr device, ScreenPtr screen, CursorPtr cursor)
|
||||
{
|
||||
PixmapPtr pixmap;
|
||||
struct xwl_screen *xwl_screen;
|
||||
struct xwl_seat *xwl_seat;
|
||||
|
||||
pixmap = dixGetPrivate(&cursor->devPrivates, &xwl_cursor_private_key);
|
||||
if (!pixmap)
|
||||
return TRUE;
|
||||
|
||||
dixSetPrivate(&cursor->devPrivates, &xwl_cursor_private_key, NULL);
|
||||
|
||||
/* 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 xwl_shm_destroy_pixmap(pixmap);
|
||||
}
|
||||
|
||||
static void
|
||||
clear_cursor_frame_callback(struct xwl_cursor *xwl_cursor)
|
||||
{
|
||||
if (xwl_cursor->frame_cb) {
|
||||
wl_callback_destroy (xwl_cursor->frame_cb);
|
||||
xwl_cursor->frame_cb = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
frame_callback(void *data,
|
||||
struct wl_callback *callback,
|
||||
uint32_t time)
|
||||
{
|
||||
struct xwl_cursor *xwl_cursor = data;
|
||||
|
||||
clear_cursor_frame_callback(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;
|
||||
|
||||
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);
|
||||
xwl_surface_damage(xwl_seat->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);
|
||||
|
||||
/* Hold a reference on the pixmap until it's released by the compositor */
|
||||
pixmap->refcnt++;
|
||||
xwl_pixmap_set_buffer_release_cb(pixmap,
|
||||
xwl_cursor_buffer_release_callback,
|
||||
pixmap);
|
||||
|
||||
wl_surface_commit(xwl_cursor->surface);
|
||||
}
|
||||
|
||||
void
|
||||
xwl_seat_set_cursor(struct xwl_seat *xwl_seat)
|
||||
{
|
||||
struct xwl_cursor *xwl_cursor = &xwl_seat->cursor;
|
||||
PixmapPtr pixmap;
|
||||
CursorPtr cursor;
|
||||
|
||||
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);
|
||||
clear_cursor_frame_callback(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 = dixGetPrivate(&cursor->devPrivates, &xwl_cursor_private_key);
|
||||
if (!pixmap)
|
||||
return;
|
||||
|
||||
xwl_cursor_copy_bits_to_pixmap(cursor, pixmap);
|
||||
|
||||
wl_pointer_set_cursor(xwl_seat->wl_pointer,
|
||||
xwl_seat->pointer_enter_serial,
|
||||
xwl_cursor->surface,
|
||||
xwl_seat->x_cursor->bits->xhot,
|
||||
xwl_seat->x_cursor->bits->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_cursor *xwl_cursor = &xwl_tablet_tool->cursor;
|
||||
PixmapPtr pixmap;
|
||||
CursorPtr cursor;
|
||||
|
||||
if (!xwl_seat->x_cursor) {
|
||||
zwp_tablet_tool_v2_set_cursor(xwl_tablet_tool->tool,
|
||||
xwl_tablet_tool->proximity_in_serial,
|
||||
NULL, 0, 0);
|
||||
clear_cursor_frame_callback(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 = dixGetPrivate(&cursor->devPrivates, &xwl_cursor_private_key);
|
||||
if (!pixmap)
|
||||
return;
|
||||
|
||||
xwl_cursor_copy_bits_to_pixmap(cursor, pixmap);
|
||||
|
||||
zwp_tablet_tool_v2_set_cursor(xwl_tablet_tool->tool,
|
||||
xwl_tablet_tool->proximity_in_serial,
|
||||
xwl_cursor->surface,
|
||||
xwl_seat->x_cursor->bits->xhot,
|
||||
xwl_seat->x_cursor->bits->yhot);
|
||||
|
||||
xwl_cursor_attach_pixmap(xwl_seat, xwl_cursor, pixmap);
|
||||
}
|
||||
|
||||
static void
|
||||
xwl_seat_update_cursor(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_cursor(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_cursor(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)
|
||||
{
|
||||
if (!dixRegisterPrivateKey(&xwl_cursor_private_key, PRIVATE_CURSOR_BITS, 0))
|
||||
return FALSE;
|
||||
|
||||
return miPointerInitialize(xwl_screen->screen,
|
||||
&xwl_pointer_sprite_funcs,
|
||||
&xwl_pointer_screen_funcs, TRUE);
|
||||
}
|
|
@ -1,38 +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 <xwayland-config.h>
|
||||
#include <xwayland-types.h>
|
||||
#include <xwayland-input.h>
|
||||
|
||||
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 */
|
|
@ -1,62 +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 <xwayland-config.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <randrstr.h>
|
||||
#include <libxcvt/libxcvt.h>
|
||||
|
||||
#include "xwayland-cvt.h"
|
||||
|
||||
RRModePtr
|
||||
xwayland_cvt(int hdisplay, int vdisplay, float vrefresh, Bool reduced,
|
||||
Bool interlaced)
|
||||
{
|
||||
struct libxcvt_mode_info *libxcvt_mode_info;
|
||||
char name[128];
|
||||
xRRModeInfo modeinfo;
|
||||
|
||||
libxcvt_mode_info =
|
||||
libxcvt_gen_mode_info(hdisplay, vdisplay, vrefresh, reduced, interlaced);
|
||||
|
||||
memset(&modeinfo, 0, sizeof modeinfo);
|
||||
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);
|
||||
|
||||
snprintf(name, sizeof name, "%dx%d",
|
||||
modeinfo.width, modeinfo.height);
|
||||
modeinfo.nameLength = strlen(name);
|
||||
|
||||
return RRModeGet(&modeinfo, name);
|
||||
}
|
|
@ -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 <xwayland-config.h>
|
||||
|
||||
#include <dix.h>
|
||||
#include <randrstr.h>
|
||||
|
||||
RRModePtr xwayland_cvt(int HDisplay, int VDisplay,
|
||||
float VRefresh, Bool Reduced, Bool Interlaced);
|
||||
|
||||
#endif /* XWAYLAND_CVT_H */
|
File diff suppressed because it is too large
Load Diff
|
@ -1,974 +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 <lyude@redhat.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <xwayland-config.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <sys/stat.h>
|
||||
#include <xf86drm.h>
|
||||
#include <drm_fourcc.h>
|
||||
|
||||
#define MESA_EGL_NO_X11_HEADERS
|
||||
#define EGL_NO_X11
|
||||
#include <gbm.h>
|
||||
#include <glamor_egl.h>
|
||||
|
||||
#include <glamor.h>
|
||||
#include <glamor_context.h>
|
||||
#include <dri3.h>
|
||||
#include "drm-client-protocol.h"
|
||||
|
||||
#include "xwayland-glamor.h"
|
||||
#include "xwayland-pixmap.h"
|
||||
#include "xwayland-screen.h"
|
||||
|
||||
#include "linux-dmabuf-unstable-v1-client-protocol.h"
|
||||
|
||||
struct xwl_gbm_private {
|
||||
char *device_name;
|
||||
struct gbm_device *gbm;
|
||||
struct wl_drm *drm;
|
||||
int drm_fd;
|
||||
int fd_render_node;
|
||||
Bool drm_authenticated;
|
||||
uint32_t capabilities;
|
||||
int dmabuf_capable;
|
||||
};
|
||||
|
||||
struct xwl_pixmap {
|
||||
struct wl_buffer *buffer;
|
||||
EGLImage image;
|
||||
unsigned int texture;
|
||||
struct gbm_bo *bo;
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
gbm_format_for_depth(int depth)
|
||||
{
|
||||
switch (depth) {
|
||||
case 16:
|
||||
return GBM_FORMAT_RGB565;
|
||||
case 24:
|
||||
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)
|
||||
{
|
||||
PixmapPtr pixmap;
|
||||
struct xwl_pixmap *xwl_pixmap;
|
||||
struct xwl_screen *xwl_screen = xwl_screen_get(screen);
|
||||
|
||||
xwl_pixmap = calloc(1, sizeof(*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->image = eglCreateImageKHR(xwl_screen->egl_display,
|
||||
xwl_screen->egl_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(ScreenPtr screen,
|
||||
int width, int height, int depth,
|
||||
unsigned int hint)
|
||||
{
|
||||
struct xwl_screen *xwl_screen = xwl_screen_get(screen);
|
||||
struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen);
|
||||
struct gbm_bo *bo;
|
||||
PixmapPtr pixmap = 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);
|
||||
|
||||
#ifdef GBM_BO_WITH_MODIFIERS
|
||||
if (xwl_gbm->dmabuf_capable) {
|
||||
uint32_t num_modifiers;
|
||||
uint64_t *modifiers = NULL;
|
||||
|
||||
xwl_glamor_get_modifiers(screen, format, &num_modifiers, &modifiers);
|
||||
bo = gbm_bo_create_with_modifiers(xwl_gbm->gbm, width, height,
|
||||
format, modifiers, num_modifiers);
|
||||
free(modifiers);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
bo = gbm_bo_create(xwl_gbm->gbm, width, height, format,
|
||||
GBM_BO_USE_RENDERING);
|
||||
}
|
||||
|
||||
if (bo) {
|
||||
pixmap = xwl_glamor_gbm_create_pixmap_for_bo(screen, bo, depth);
|
||||
|
||||
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(screen, width, height, depth, hint);
|
||||
|
||||
return pixmap;
|
||||
}
|
||||
|
||||
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);
|
||||
free(xwl_pixmap);
|
||||
}
|
||||
|
||||
return glamor_destroy_pixmap(pixmap);
|
||||
}
|
||||
|
||||
static const struct wl_buffer_listener xwl_glamor_gbm_buffer_listener = {
|
||||
xwl_pixmap_buffer_release_cb,
|
||||
};
|
||||
|
||||
static struct wl_buffer *
|
||||
xwl_glamor_gbm_get_wl_buffer_for_pixmap(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 prime_fd;
|
||||
int num_planes;
|
||||
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);
|
||||
|
||||
prime_fd = gbm_bo_get_fd(xwl_pixmap->bo);
|
||||
if (prime_fd == -1)
|
||||
return NULL;
|
||||
|
||||
#ifdef GBM_BO_WITH_MODIFIERS
|
||||
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++) {
|
||||
strides[i] = gbm_bo_get_stride_for_plane(xwl_pixmap->bo, i);
|
||||
offsets[i] = gbm_bo_get_offset(xwl_pixmap->bo, i);
|
||||
}
|
||||
#else
|
||||
num_planes = 1;
|
||||
modifier = DRM_FORMAT_MOD_INVALID;
|
||||
strides[0] = gbm_bo_get_stride(xwl_pixmap->bo);
|
||||
offsets[0] = 0;
|
||||
#endif
|
||||
|
||||
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_fd, 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) {
|
||||
xwl_pixmap->buffer =
|
||||
wl_drm_create_prime_buffer(xwl_gbm->drm, prime_fd, width, height,
|
||||
format,
|
||||
0, gbm_bo_get_stride(xwl_pixmap->bo),
|
||||
0, 0,
|
||||
0, 0);
|
||||
}
|
||||
|
||||
close(prime_fd);
|
||||
|
||||
/* Add our listener now */
|
||||
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->device_name)
|
||||
free(xwl_gbm->device_name);
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
struct xwl_auth_state *state;
|
||||
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;
|
||||
}
|
||||
|
||||
state = malloc(sizeof *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;
|
||||
}
|
||||
|
||||
_X_EXPORT 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;
|
||||
|
||||
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);
|
||||
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);
|
||||
bo = gbm_bo_import(xwl_gbm->gbm, GBM_BO_IMPORT_FD, &data,
|
||||
GBM_BO_USE_RENDERING);
|
||||
} else {
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (bo == NULL)
|
||||
goto error;
|
||||
|
||||
pixmap = xwl_glamor_gbm_create_pixmap_for_bo(screen, bo, depth);
|
||||
if (pixmap == NULL) {
|
||||
gbm_bo_destroy(bo);
|
||||
goto error;
|
||||
}
|
||||
|
||||
return pixmap;
|
||||
|
||||
error:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
_X_EXPORT 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
|
||||
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++) {
|
||||
fds[i] = gbm_bo_get_fd(xwl_pixmap->bo);
|
||||
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);
|
||||
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
|
||||
*/
|
||||
_X_EXPORT int
|
||||
glamor_egl_fd_from_pixmap(ScreenPtr screen, PixmapPtr pixmap,
|
||||
CARD16 *stride, CARD32 *size)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
static const 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 = glamor_get_drawable_modifiers,
|
||||
};
|
||||
|
||||
static const char *
|
||||
get_render_node_path_for_device(const drmDevicePtr drm_device,
|
||||
const char *device_path)
|
||||
{
|
||||
char *render_node_path = NULL;
|
||||
char device_found = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < DRM_NODE_MAX; i++) {
|
||||
if ((drm_device->available_nodes & (1 << i)) == 0)
|
||||
continue;
|
||||
|
||||
if (!strcmp (device_path, drm_device->nodes[i]))
|
||||
device_found = 1;
|
||||
|
||||
if (is_device_path_render_node(drm_device->nodes[i]))
|
||||
render_node_path = drm_device->nodes[i];
|
||||
|
||||
if (device_found && render_node_path)
|
||||
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);
|
||||
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);
|
||||
return;
|
||||
}
|
||||
|
||||
if (drmGetNodeTypeFromFd(xwl_gbm->drm_fd) == DRM_NODE_RENDER) {
|
||||
xwl_gbm->fd_render_node = 1;
|
||||
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;
|
||||
}
|
||||
|
||||
static Bool
|
||||
xwl_glamor_gbm_init_wl_registry(struct xwl_screen *xwl_screen,
|
||||
struct wl_registry *wl_registry,
|
||||
uint32_t id, const char *name,
|
||||
uint32_t version)
|
||||
{
|
||||
if (strcmp(name, "wl_drm") == 0) {
|
||||
xwl_screen_set_drm_interface(xwl_screen, id, version);
|
||||
return TRUE;
|
||||
} else if (strcmp(name, "zwp_linux_dmabuf_v1") == 0) {
|
||||
xwl_screen_set_dmabuf_interface(xwl_screen, id, version);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* no match */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
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"));
|
||||
}
|
||||
|
||||
static Bool
|
||||
xwl_glamor_gbm_has_wl_interfaces(struct xwl_screen *xwl_screen)
|
||||
{
|
||||
struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen);
|
||||
|
||||
if (xwl_gbm->drm == NULL) {
|
||||
ErrorF("glamor: 'wl_drm' not supported\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
eglBindAPI(EGL_OPENGL_API);
|
||||
|
||||
xwl_screen->egl_context =
|
||||
eglCreateContext(xwl_screen->egl_display, NULL,
|
||||
EGL_NO_CONTEXT, config_attribs_core);
|
||||
|
||||
if (xwl_screen->egl_context == EGL_NO_CONTEXT)
|
||||
xwl_screen->egl_context =
|
||||
eglCreateContext(xwl_screen->egl_display, NULL,
|
||||
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,
|
||||
};
|
||||
|
||||
eglBindAPI(EGL_OPENGL_ES_API);
|
||||
|
||||
xwl_screen->egl_context = eglCreateContext(xwl_screen->egl_display, NULL,
|
||||
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_egl(struct xwl_screen *xwl_screen)
|
||||
{
|
||||
struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen);
|
||||
EGLint major, minor;
|
||||
const GLubyte *renderer;
|
||||
|
||||
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, "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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static Bool
|
||||
xwl_glamor_gbm_init_screen(struct xwl_screen *xwl_screen)
|
||||
{
|
||||
struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen);
|
||||
|
||||
if (!dri3_screen_init(xwl_screen->screen, &xwl_dri3_info)) {
|
||||
ErrorF("Failed to initialize dri3\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void
|
||||
xwl_glamor_init_gbm(struct xwl_screen *xwl_screen)
|
||||
{
|
||||
struct xwl_gbm_private *xwl_gbm;
|
||||
|
||||
xwl_screen->gbm_backend.is_available = FALSE;
|
||||
|
||||
if (!xwl_glamor_gbm_has_egl_extension())
|
||||
return;
|
||||
|
||||
if (!dixRegisterPrivateKey(&xwl_gbm_private_key, PRIVATE_SCREEN, 0))
|
||||
return;
|
||||
|
||||
xwl_gbm = calloc(sizeof(*xwl_gbm), 1);
|
||||
if (!xwl_gbm) {
|
||||
ErrorF("glamor: Not enough memory to setup GBM, disabling\n");
|
||||
return;
|
||||
}
|
||||
|
||||
dixSetPrivate(&xwl_screen->screen->devPrivates, &xwl_gbm_private_key,
|
||||
xwl_gbm);
|
||||
|
||||
xwl_screen->gbm_backend.init_wl_registry = xwl_glamor_gbm_init_wl_registry;
|
||||
xwl_screen->gbm_backend.has_wl_interfaces = xwl_glamor_gbm_has_wl_interfaces;
|
||||
xwl_screen->gbm_backend.init_egl = xwl_glamor_gbm_init_egl;
|
||||
xwl_screen->gbm_backend.init_screen = xwl_glamor_gbm_init_screen;
|
||||
xwl_screen->gbm_backend.get_wl_buffer_for_pixmap = xwl_glamor_gbm_get_wl_buffer_for_pixmap;
|
||||
xwl_screen->gbm_backend.check_flip = NULL;
|
||||
xwl_screen->gbm_backend.is_available = TRUE;
|
||||
xwl_screen->gbm_backend.backend_flags = XWL_EGL_BACKEND_NEEDS_BUFFER_FLUSH |
|
||||
XWL_EGL_BACKEND_NEEDS_N_BUFFERING;
|
||||
}
|
|
@ -1,415 +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 <ofourdan@redhat.com>
|
||||
*
|
||||
* Derived from the glamor_xf86_xv, ephyr_glamor_xv and xf86xv
|
||||
* implementations
|
||||
*/
|
||||
|
||||
#include <xwayland-config.h>
|
||||
|
||||
#include "glamor_priv.h"
|
||||
|
||||
#include <X11/extensions/Xv.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;
|
||||
|
||||
CloseScreenProcPtr CloseScreen;
|
||||
} 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 = xnfcalloc(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 = xnfcalloc(NUM_PORTS, sizeof(XvPortRec));
|
||||
xwlXvScreen = dixLookupPrivate(&(pa->pScreen)->devPrivates,
|
||||
xwlXvScreenPrivateKey);
|
||||
xwlXvScreen->port_privates = xnfcalloc(NUM_PORTS,
|
||||
sizeof(glamor_port_private));
|
||||
|
||||
PortResource = XvGetRTPort();
|
||||
for (pp = pPorts, i = 0, nPorts = 0; i < NUM_PORTS; i++) {
|
||||
if (!(pp->id = FakeClientID(0)))
|
||||
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 = xnfcalloc(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 = xnfcalloc(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 = xnfcalloc(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 = xnfcalloc(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 Bool
|
||||
xwl_glamor_xv_close_screen(ScreenPtr pScreen)
|
||||
{
|
||||
xwlXvScreenPtr xwlXvScreen;
|
||||
|
||||
xwlXvScreen = dixLookupPrivate(&(pScreen)->devPrivates,
|
||||
xwlXvScreenPrivateKey);
|
||||
|
||||
if (xwlXvScreen->glxv_adaptor) {
|
||||
XvFreeAdaptor(xwlXvScreen->glxv_adaptor);
|
||||
free(xwlXvScreen->glxv_adaptor);
|
||||
}
|
||||
free(xwlXvScreen->port_privates);
|
||||
|
||||
pScreen->CloseScreen = xwlXvScreen->CloseScreen;
|
||||
|
||||
return pScreen->CloseScreen(pScreen);
|
||||
}
|
||||
|
||||
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;
|
||||
xwlXvScreen->CloseScreen = pScreen->CloseScreen;
|
||||
pScreen->CloseScreen = xwl_glamor_xv_close_screen;
|
||||
|
||||
glamor_xv_core_init(pScreen);
|
||||
|
||||
return xwl_glamor_xv_add_adaptors(pScreen);
|
||||
}
|
|
@ -1,491 +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 <xwayland-config.h>
|
||||
|
||||
#define MESA_EGL_NO_X11_HEADERS
|
||||
#define EGL_NO_X11
|
||||
#include <glamor_egl.h>
|
||||
|
||||
#include <glamor.h>
|
||||
#include <glamor_context.h>
|
||||
#ifdef GLXEXT
|
||||
#include "glx_extinit.h"
|
||||
#endif
|
||||
|
||||
#include "linux-dmabuf-unstable-v1-client-protocol.h"
|
||||
#include "drm-client-protocol.h"
|
||||
#include <drm_fourcc.h>
|
||||
|
||||
#include "xwayland-glamor.h"
|
||||
#include "xwayland-glx.h"
|
||||
#include "xwayland-screen.h"
|
||||
#include "xwayland-window.h"
|
||||
|
||||
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)
|
||||
{
|
||||
if (lastGLContext == xwl_screen->glamor_ctx)
|
||||
return;
|
||||
|
||||
lastGLContext = xwl_screen->glamor_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_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(PixmapPtr pixmap)
|
||||
{
|
||||
struct xwl_screen *xwl_screen = xwl_screen_get(pixmap->drawable.pScreen);
|
||||
|
||||
if (!xwl_glamor_pixmap_get_wl_buffer(pixmap))
|
||||
return FALSE;
|
||||
|
||||
if (xwl_screen->egl_backend->check_flip)
|
||||
return xwl_screen->egl_backend->check_flip(pixmap);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
Bool
|
||||
xwl_glamor_is_modifier_supported(struct xwl_screen *xwl_screen,
|
||||
uint32_t format, uint64_t modifier)
|
||||
{
|
||||
struct xwl_format *xwl_format = NULL;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < xwl_screen->num_formats; i++) {
|
||||
if (xwl_screen->formats[i].format == format) {
|
||||
xwl_format = &xwl_screen->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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
Bool
|
||||
xwl_glamor_get_formats(ScreenPtr screen,
|
||||
CARD32 *num_formats, CARD32 **formats)
|
||||
{
|
||||
struct xwl_screen *xwl_screen = xwl_screen_get(screen);
|
||||
int i;
|
||||
|
||||
/* Explicitly zero the count as the caller may ignore the return value */
|
||||
*num_formats = 0;
|
||||
|
||||
if (!xwl_screen->dmabuf)
|
||||
return FALSE;
|
||||
|
||||
if (xwl_screen->num_formats == 0)
|
||||
return TRUE;
|
||||
|
||||
*formats = calloc(xwl_screen->num_formats, sizeof(CARD32));
|
||||
if (*formats == NULL)
|
||||
return FALSE;
|
||||
|
||||
for (i = 0; i < xwl_screen->num_formats; i++)
|
||||
(*formats)[i] = xwl_screen->formats[i].format;
|
||||
*num_formats = xwl_screen->num_formats;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
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);
|
||||
struct xwl_format *xwl_format = NULL;
|
||||
int i;
|
||||
|
||||
/* Explicitly zero the count as the caller may ignore the return value */
|
||||
*num_modifiers = 0;
|
||||
|
||||
if (!xwl_screen->dmabuf)
|
||||
return FALSE;
|
||||
|
||||
if (xwl_screen->num_formats == 0)
|
||||
return TRUE;
|
||||
|
||||
for (i = 0; i < xwl_screen->num_formats; i++) {
|
||||
if (xwl_screen->formats[i].format == format) {
|
||||
xwl_format = &xwl_screen->formats[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 void
|
||||
xwl_dmabuf_handle_format(void *data, struct zwp_linux_dmabuf_v1 *dmabuf,
|
||||
uint32_t format)
|
||||
{
|
||||
}
|
||||
|
||||
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;
|
||||
struct xwl_format *xwl_format = NULL;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < xwl_screen->num_formats; i++) {
|
||||
if (xwl_screen->formats[i].format == format) {
|
||||
xwl_format = &xwl_screen->formats[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (xwl_format == NULL) {
|
||||
xwl_screen->num_formats++;
|
||||
xwl_screen->formats = realloc(xwl_screen->formats,
|
||||
xwl_screen->num_formats * sizeof(*xwl_format));
|
||||
if (!xwl_screen->formats)
|
||||
return;
|
||||
xwl_format = &xwl_screen->formats[xwl_screen->num_formats - 1];
|
||||
xwl_format->format = format;
|
||||
xwl_format->num_modifiers = 0;
|
||||
xwl_format->modifiers = NULL;
|
||||
}
|
||||
|
||||
xwl_format->num_modifiers++;
|
||||
xwl_format->modifiers = realloc(xwl_format->modifiers,
|
||||
xwl_format->num_modifiers * sizeof(uint64_t));
|
||||
if (!xwl_format->modifiers)
|
||||
return;
|
||||
xwl_format->modifiers[xwl_format->num_modifiers - 1] = (uint64_t) modifier_lo;
|
||||
xwl_format->modifiers[xwl_format->num_modifiers - 1] |= (uint64_t) modifier_hi << 32;
|
||||
}
|
||||
|
||||
static const struct zwp_linux_dmabuf_v1_listener xwl_dmabuf_listener = {
|
||||
.format = xwl_dmabuf_handle_format,
|
||||
.modifier = xwl_dmabuf_handle_modifier
|
||||
};
|
||||
|
||||
Bool
|
||||
xwl_screen_set_dmabuf_interface(struct xwl_screen *xwl_screen,
|
||||
uint32_t id, uint32_t version)
|
||||
{
|
||||
if (version < 3)
|
||||
return FALSE;
|
||||
|
||||
xwl_screen->dmabuf =
|
||||
wl_registry_bind(xwl_screen->registry, id, &zwp_linux_dmabuf_v1_interface, 3);
|
||||
zwp_linux_dmabuf_v1_add_listener(xwl_screen->dmabuf, &xwl_dmabuf_listener, xwl_screen);
|
||||
|
||||
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 (xwl_screen->gbm_backend.is_available &&
|
||||
xwl_screen->gbm_backend.init_wl_registry(xwl_screen,
|
||||
registry,
|
||||
id,
|
||||
interface,
|
||||
version)) {
|
||||
/* no-op */
|
||||
} else if (xwl_screen->eglstream_backend.is_available &&
|
||||
xwl_screen->eglstream_backend.init_wl_registry(xwl_screen,
|
||||
registry,
|
||||
id,
|
||||
interface,
|
||||
version)) {
|
||||
/* no-op */
|
||||
}
|
||||
}
|
||||
|
||||
Bool
|
||||
xwl_glamor_has_wl_interfaces(struct xwl_screen *xwl_screen,
|
||||
struct xwl_egl_backend *xwl_egl_backend)
|
||||
{
|
||||
return xwl_egl_backend->has_wl_interfaces(xwl_screen);
|
||||
}
|
||||
|
||||
struct wl_buffer *
|
||||
xwl_glamor_pixmap_get_wl_buffer(PixmapPtr pixmap)
|
||||
{
|
||||
struct xwl_screen *xwl_screen = xwl_screen_get(pixmap->drawable.pScreen);
|
||||
|
||||
if (xwl_screen->egl_backend->get_wl_buffer_for_pixmap)
|
||||
return xwl_screen->egl_backend->get_wl_buffer_for_pixmap(pixmap);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Bool
|
||||
xwl_glamor_post_damage(struct xwl_window *xwl_window,
|
||||
PixmapPtr pixmap, RegionPtr region)
|
||||
{
|
||||
struct xwl_screen *xwl_screen = xwl_window->xwl_screen;
|
||||
|
||||
if (xwl_screen->egl_backend->post_damage)
|
||||
return xwl_screen->egl_backend->post_damage(xwl_window, pixmap, region);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
Bool
|
||||
xwl_glamor_allow_commits(struct xwl_window *xwl_window)
|
||||
{
|
||||
struct xwl_screen *xwl_screen = xwl_window->xwl_screen;
|
||||
|
||||
if (xwl_screen->egl_backend->allow_commits)
|
||||
return xwl_screen->egl_backend->allow_commits(xwl_window);
|
||||
else
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static Bool
|
||||
xwl_glamor_create_screen_resources(ScreenPtr screen)
|
||||
{
|
||||
struct xwl_screen *xwl_screen = xwl_screen_get(screen);
|
||||
int ret;
|
||||
|
||||
screen->CreateScreenResources = xwl_screen->CreateScreenResources;
|
||||
ret = (*screen->CreateScreenResources) (screen);
|
||||
xwl_screen->CreateScreenResources = screen->CreateScreenResources;
|
||||
screen->CreateScreenResources = xwl_glamor_create_screen_resources;
|
||||
|
||||
if (!ret)
|
||||
return ret;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
Bool
|
||||
xwl_glamor_needs_buffer_flush(struct xwl_screen *xwl_screen)
|
||||
{
|
||||
if (!xwl_screen->glamor || !xwl_screen->egl_backend)
|
||||
return FALSE;
|
||||
|
||||
return (xwl_screen->egl_backend->backend_flags &
|
||||
XWL_EGL_BACKEND_NEEDS_BUFFER_FLUSH);
|
||||
}
|
||||
|
||||
Bool
|
||||
xwl_glamor_needs_n_buffering(struct xwl_screen *xwl_screen)
|
||||
{
|
||||
/* wl_shm benefits from n-buffering */
|
||||
if (!xwl_screen->glamor || !xwl_screen->egl_backend)
|
||||
return TRUE;
|
||||
|
||||
return (xwl_screen->egl_backend->backend_flags &
|
||||
XWL_EGL_BACKEND_NEEDS_N_BUFFERING);
|
||||
}
|
||||
|
||||
void
|
||||
xwl_glamor_init_backends(struct xwl_screen *xwl_screen, Bool use_eglstream)
|
||||
{
|
||||
#ifdef GLAMOR_HAS_GBM
|
||||
xwl_glamor_init_gbm(xwl_screen);
|
||||
if (!xwl_screen->gbm_backend.is_available && !use_eglstream)
|
||||
ErrorF("xwayland glamor: GBM backend (default) is not available\n");
|
||||
#endif
|
||||
#ifdef XWL_HAS_EGLSTREAM
|
||||
xwl_glamor_init_eglstream(xwl_screen);
|
||||
if (!xwl_screen->eglstream_backend.is_available && use_eglstream)
|
||||
ErrorF("xwayland glamor: EGLStream backend requested but not available\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
static Bool
|
||||
xwl_glamor_select_gbm_backend(struct xwl_screen *xwl_screen)
|
||||
{
|
||||
#ifdef GLAMOR_HAS_GBM
|
||||
if (xwl_screen->gbm_backend.is_available &&
|
||||
xwl_glamor_has_wl_interfaces(xwl_screen, &xwl_screen->gbm_backend)) {
|
||||
xwl_screen->egl_backend = &xwl_screen->gbm_backend;
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
ErrorF("Missing Wayland requirements for glamor GBM backend\n");
|
||||
#endif
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static Bool
|
||||
xwl_glamor_select_eglstream_backend(struct xwl_screen *xwl_screen)
|
||||
{
|
||||
#ifdef XWL_HAS_EGLSTREAM
|
||||
if (xwl_screen->eglstream_backend.is_available &&
|
||||
xwl_glamor_has_wl_interfaces(xwl_screen, &xwl_screen->eglstream_backend)) {
|
||||
xwl_screen->egl_backend = &xwl_screen->eglstream_backend;
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
ErrorF("Missing Wayland requirements for glamor EGLStream backend\n");
|
||||
#endif
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
xwl_glamor_select_backend(struct xwl_screen *xwl_screen, Bool use_eglstream)
|
||||
{
|
||||
if (use_eglstream) {
|
||||
if (!xwl_glamor_select_eglstream_backend(xwl_screen))
|
||||
xwl_glamor_select_gbm_backend(xwl_screen);
|
||||
}
|
||||
else {
|
||||
if (!xwl_glamor_select_gbm_backend(xwl_screen))
|
||||
xwl_glamor_select_eglstream_backend(xwl_screen);
|
||||
}
|
||||
}
|
||||
|
||||
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_screen->egl_backend->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_screen->egl_backend->init_screen(xwl_screen)) {
|
||||
ErrorF("EGL backend init_screen() failed, disabling glamor\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
xwl_screen->CreateScreenResources = screen->CreateScreenResources;
|
||||
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;
|
||||
}
|
|
@ -1,158 +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 <xwayland-config.h>
|
||||
|
||||
#include <wayland-client.h>
|
||||
|
||||
#include "xwayland-types.h"
|
||||
|
||||
typedef enum _xwl_egl_backend_flags {
|
||||
XWL_EGL_BACKEND_NO_FLAG = 0,
|
||||
XWL_EGL_BACKEND_NEEDS_BUFFER_FLUSH = (1 << 0),
|
||||
XWL_EGL_BACKEND_NEEDS_N_BUFFERING = (1 << 1),
|
||||
} xwl_egl_backend_flags;
|
||||
|
||||
struct xwl_egl_backend {
|
||||
/* Set by the backend if available */
|
||||
Bool is_available;
|
||||
|
||||
/* Features and requirements set by the backend */
|
||||
xwl_egl_backend_flags backend_flags;
|
||||
|
||||
/* Called once for each interface in the global registry. Backends
|
||||
* should use this to bind to any wayland interfaces they need.
|
||||
*/
|
||||
Bool (*init_wl_registry)(struct xwl_screen *xwl_screen,
|
||||
struct wl_registry *wl_registry,
|
||||
uint32_t id, const char *name,
|
||||
uint32_t version);
|
||||
|
||||
/* Check that the required Wayland interfaces are available.
|
||||
*/
|
||||
Bool (*has_wl_interfaces)(struct xwl_screen *xwl_screen);
|
||||
|
||||
/* Called before glamor has been initialized. Backends should setup a
|
||||
* valid, glamor compatible EGL context in this hook.
|
||||
*/
|
||||
Bool (*init_egl)(struct xwl_screen *xwl_screen);
|
||||
|
||||
/* Called after glamor has been initialized, and after all of the
|
||||
* common Xwayland DDX hooks have been connected. Backends should use
|
||||
* this to setup any required wraps around X server callbacks like
|
||||
* CreatePixmap.
|
||||
*/
|
||||
Bool (*init_screen)(struct xwl_screen *xwl_screen);
|
||||
|
||||
/* Called by Xwayland to retrieve a pointer to a valid wl_buffer for
|
||||
* the given window/pixmap combo so that damage to the pixmap may be
|
||||
* displayed on-screen. Backends should use this to create a new
|
||||
* wl_buffer for a currently buffer-less pixmap, or simply return the
|
||||
* pixmap they've prepared beforehand.
|
||||
*/
|
||||
struct wl_buffer *(*get_wl_buffer_for_pixmap)(PixmapPtr pixmap);
|
||||
|
||||
/* Called by Xwayland to perform any pre-wl_surface damage routines
|
||||
* that are required by the backend. If your backend is poorly
|
||||
* designed and lacks the ability to render directly to a surface,
|
||||
* you should implement blitting from the glamor pixmap to the wayland
|
||||
* pixmap here. Otherwise, this callback is optional.
|
||||
*/
|
||||
Bool (*post_damage)(struct xwl_window *xwl_window,
|
||||
PixmapPtr pixmap, RegionPtr region);
|
||||
|
||||
/* Called by Xwayland to confirm with the egl backend that the given
|
||||
* pixmap is completely setup and ready for display on-screen. This
|
||||
* callback is optional.
|
||||
*/
|
||||
Bool (*allow_commits)(struct xwl_window *xwl_window);
|
||||
|
||||
/* Called by Xwayland to check whether the given pixmap can be
|
||||
* presented by xwl_present_flip. If not implemented, assumed TRUE.
|
||||
*/
|
||||
Bool (*check_flip)(PixmapPtr pixmap);
|
||||
};
|
||||
|
||||
#ifdef XWL_HAS_GLAMOR
|
||||
|
||||
void xwl_glamor_init_backends(struct xwl_screen *xwl_screen,
|
||||
Bool use_eglstream);
|
||||
void xwl_glamor_select_backend(struct xwl_screen *xwl_screen,
|
||||
Bool use_eglstream);
|
||||
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_dmabuf_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);
|
||||
Bool xwl_glamor_has_wl_interfaces(struct xwl_screen *xwl_screen,
|
||||
struct xwl_egl_backend *xwl_egl_backend);
|
||||
Bool xwl_glamor_post_damage(struct xwl_window *xwl_window,
|
||||
PixmapPtr pixmap, RegionPtr region);
|
||||
Bool xwl_glamor_allow_commits(struct xwl_window *xwl_window);
|
||||
void xwl_glamor_egl_make_current(struct xwl_screen *xwl_screen);
|
||||
Bool xwl_glamor_needs_buffer_flush(struct xwl_screen *xwl_screen);
|
||||
Bool xwl_glamor_needs_n_buffering(struct xwl_screen *xwl_screen);
|
||||
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_check_flip(PixmapPtr pixmap);
|
||||
|
||||
#ifdef XV
|
||||
/* glamor Xv Adaptor */
|
||||
Bool xwl_glamor_xv_init(ScreenPtr pScreen);
|
||||
#endif /* XV */
|
||||
|
||||
#endif /* XWL_HAS_GLAMOR */
|
||||
|
||||
#ifdef GLAMOR_HAS_GBM
|
||||
void xwl_glamor_init_gbm(struct xwl_screen *xwl_screen);
|
||||
#else
|
||||
static inline void xwl_glamor_init_gbm(struct xwl_screen *xwl_screen)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef XWL_HAS_EGLSTREAM
|
||||
void xwl_glamor_init_eglstream(struct xwl_screen *xwl_screen);
|
||||
#else
|
||||
static inline void xwl_glamor_init_eglstream(struct xwl_screen *xwl_screen)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* XWAYLAND_GLAMOR_H */
|
|
@ -1,397 +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:
|
||||
* Adam Jackson <ajax@redhat.com>
|
||||
*/
|
||||
|
||||
/*
|
||||
* Sets up GLX capabilities based on the EGL capabilities of the glamor
|
||||
* renderer for the screen. Without this you will get whatever swrast
|
||||
* can do, which often does not include things like multisample visuals.
|
||||
*/
|
||||
|
||||
#include <xwayland-config.h>
|
||||
|
||||
#define MESA_EGL_NO_X11_HEADERS
|
||||
#define EGL_NO_X11
|
||||
// #include <EGL/egl.h>
|
||||
#include <epoxy/egl.h>
|
||||
#include "glxserver.h"
|
||||
#include "glxutil.h"
|
||||
#include "compint.h"
|
||||
#include <X11/extensions/composite.h>
|
||||
#include "glamor_context.h"
|
||||
#include "glamor.h"
|
||||
|
||||
#include "xwayland-screen.h"
|
||||
|
||||
/* Can't get these from <GL/glx.h> since it pulls in client headers */
|
||||
#define GLX_RGBA_BIT 0x00000001
|
||||
#define GLX_WINDOW_BIT 0x00000001
|
||||
#define GLX_PIXMAP_BIT 0x00000002
|
||||
#define GLX_PBUFFER_BIT 0x00000004
|
||||
#define GLX_NONE 0x8000
|
||||
#define GLX_SLOW_CONFIG 0x8001
|
||||
#define GLX_TRUE_COLOR 0x8002
|
||||
#define GLX_DIRECT_COLOR 0x8003
|
||||
#define GLX_NON_CONFORMANT_CONFIG 0x800D
|
||||
#define GLX_DONT_CARE 0xFFFFFFFF
|
||||
#define GLX_RGBA_FLOAT_BIT_ARB 0x00000004
|
||||
#define GLX_SWAP_UNDEFINED_OML 0x8063
|
||||
|
||||
struct egl_config {
|
||||
__GLXconfig base;
|
||||
EGLConfig config;
|
||||
};
|
||||
|
||||
struct egl_screen {
|
||||
__GLXscreen base;
|
||||
EGLDisplay display;
|
||||
EGLConfig *configs;
|
||||
};
|
||||
|
||||
static void
|
||||
egl_screen_destroy(__GLXscreen *_screen)
|
||||
{
|
||||
struct egl_screen *screen = (struct egl_screen *)_screen;
|
||||
|
||||
/* XXX do we leak the fbconfig list? */
|
||||
|
||||
free(screen->configs);
|
||||
__glXScreenDestroy(_screen);
|
||||
free(_screen);
|
||||
}
|
||||
|
||||
static void
|
||||
egl_drawable_destroy(__GLXdrawable *draw)
|
||||
{
|
||||
free(draw);
|
||||
}
|
||||
|
||||
static GLboolean
|
||||
egl_drawable_swap_buffers(ClientPtr client, __GLXdrawable *draw)
|
||||
{
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
egl_drawable_copy_sub_buffer(__GLXdrawable *draw, int x, int y, int w, int h)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
egl_drawable_wait_x(__GLXdrawable *draw)
|
||||
{
|
||||
glamor_block_handler(draw->pDraw->pScreen);
|
||||
}
|
||||
|
||||
static void
|
||||
egl_drawable_wait_gl(__GLXdrawable *draw)
|
||||
{
|
||||
}
|
||||
|
||||
static __GLXdrawable *
|
||||
egl_create_glx_drawable(ClientPtr client, __GLXscreen *screen,
|
||||
DrawablePtr draw, XID drawid, int type,
|
||||
XID glxdrawid, __GLXconfig *modes)
|
||||
{
|
||||
__GLXdrawable *ret;
|
||||
|
||||
ret = calloc(1, sizeof *ret);
|
||||
if (!ret)
|
||||
return NULL;
|
||||
|
||||
if (!__glXDrawableInit(ret, screen, draw, type, glxdrawid, modes)) {
|
||||
free(ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret->destroy = egl_drawable_destroy;
|
||||
ret->swapBuffers = egl_drawable_swap_buffers;
|
||||
ret->copySubBuffer = egl_drawable_copy_sub_buffer;
|
||||
ret->waitX = egl_drawable_wait_x;
|
||||
ret->waitGL = egl_drawable_wait_gl;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO:
|
||||
*
|
||||
* - figure out sRGB
|
||||
* - bindToTextureTargets is suspicious
|
||||
* - better channel mask setup
|
||||
* - drawable type masks is suspicious
|
||||
*/
|
||||
static struct egl_config *
|
||||
translate_eglconfig(struct egl_screen *screen, EGLConfig hc,
|
||||
struct egl_config *chain, Bool direct_color,
|
||||
Bool double_buffer, Bool duplicate_for_composite)
|
||||
{
|
||||
EGLint value;
|
||||
struct egl_config *c = calloc(1, sizeof *c);
|
||||
|
||||
if (!c)
|
||||
return chain;
|
||||
|
||||
/* constants. changing these requires (at least) new EGL extensions */
|
||||
c->base.stereoMode = GL_FALSE;
|
||||
c->base.numAuxBuffers = 0;
|
||||
c->base.level = 0;
|
||||
c->base.transparentAlpha = 0;
|
||||
c->base.transparentIndex = 0;
|
||||
c->base.transparentPixel = GLX_NONE;
|
||||
c->base.visualSelectGroup = 0;
|
||||
c->base.indexBits = 0;
|
||||
c->base.optimalPbufferWidth = 0;
|
||||
c->base.optimalPbufferHeight = 0;
|
||||
c->base.bindToMipmapTexture = 0;
|
||||
c->base.bindToTextureTargets = GLX_DONT_CARE;
|
||||
c->base.sRGBCapable = 0;
|
||||
c->base.swapMethod = GLX_SWAP_UNDEFINED_OML;
|
||||
|
||||
/* this is... suspect */
|
||||
c->base.drawableType = GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT;
|
||||
|
||||
/* hmm */
|
||||
c->base.bindToTextureRgb = GL_TRUE;
|
||||
c->base.bindToTextureRgba = GL_TRUE;
|
||||
|
||||
/*
|
||||
* glx conformance failure: there's no such thing as accumulation
|
||||
* buffers in EGL. they should be emulable with shaders and fbos,
|
||||
* but i'm pretty sure nobody's using this feature since it's
|
||||
* entirely software. note that glx conformance merely requires
|
||||
* that an accum buffer _exist_, not a minimum bitness.
|
||||
*/
|
||||
c->base.accumRedBits = 0;
|
||||
c->base.accumGreenBits = 0;
|
||||
c->base.accumBlueBits = 0;
|
||||
c->base.accumAlphaBits = 0;
|
||||
|
||||
/* parametric state */
|
||||
if (direct_color)
|
||||
c->base.visualType = GLX_DIRECT_COLOR;
|
||||
else
|
||||
c->base.visualType = GLX_TRUE_COLOR;
|
||||
|
||||
if (double_buffer)
|
||||
c->base.doubleBufferMode = GL_TRUE;
|
||||
else
|
||||
c->base.doubleBufferMode = GL_FALSE;
|
||||
|
||||
/* direct-mapped state */
|
||||
#define GET(attr, slot) \
|
||||
eglGetConfigAttrib(screen->display, hc, attr, &c->base.slot)
|
||||
GET(EGL_RED_SIZE, redBits);
|
||||
GET(EGL_GREEN_SIZE, greenBits);
|
||||
GET(EGL_BLUE_SIZE, blueBits);
|
||||
GET(EGL_ALPHA_SIZE, alphaBits);
|
||||
GET(EGL_BUFFER_SIZE, rgbBits);
|
||||
GET(EGL_DEPTH_SIZE, depthBits);
|
||||
GET(EGL_STENCIL_SIZE, stencilBits);
|
||||
GET(EGL_TRANSPARENT_RED_VALUE, transparentRed);
|
||||
GET(EGL_TRANSPARENT_GREEN_VALUE, transparentGreen);
|
||||
GET(EGL_TRANSPARENT_BLUE_VALUE, transparentBlue);
|
||||
GET(EGL_SAMPLE_BUFFERS, sampleBuffers);
|
||||
GET(EGL_SAMPLES, samples);
|
||||
if (c->base.renderType & GLX_PBUFFER_BIT) {
|
||||
GET(EGL_MAX_PBUFFER_WIDTH, maxPbufferWidth);
|
||||
GET(EGL_MAX_PBUFFER_HEIGHT, maxPbufferHeight);
|
||||
GET(EGL_MAX_PBUFFER_PIXELS, maxPbufferPixels);
|
||||
}
|
||||
#undef GET
|
||||
|
||||
/* derived state: config caveats */
|
||||
eglGetConfigAttrib(screen->display, hc, EGL_CONFIG_CAVEAT, &value);
|
||||
if (value == EGL_NONE)
|
||||
c->base.visualRating = GLX_NONE;
|
||||
else if (value == EGL_SLOW_CONFIG)
|
||||
c->base.visualRating = GLX_SLOW_CONFIG;
|
||||
else if (value == EGL_NON_CONFORMANT_CONFIG)
|
||||
c->base.visualRating = GLX_NON_CONFORMANT_CONFIG;
|
||||
/* else panic */
|
||||
|
||||
/* derived state: float configs */
|
||||
c->base.renderType = GLX_RGBA_BIT;
|
||||
if (eglGetConfigAttrib(screen->display, hc, EGL_COLOR_COMPONENT_TYPE_EXT,
|
||||
&value) == EGL_TRUE) {
|
||||
if (value == EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT) {
|
||||
c->base.renderType = GLX_RGBA_FLOAT_BIT_ARB;
|
||||
}
|
||||
/* else panic */
|
||||
}
|
||||
|
||||
/* map to the backend's config */
|
||||
c->config = hc;
|
||||
|
||||
/*
|
||||
* XXX do something less ugly
|
||||
*/
|
||||
if (c->base.renderType == GLX_RGBA_BIT) {
|
||||
if (c->base.redBits == 5 &&
|
||||
(c->base.rgbBits == 15 || c->base.rgbBits == 16)) {
|
||||
c->base.blueMask = 0x0000001f;
|
||||
if (c->base.alphaBits) {
|
||||
c->base.greenMask = 0x000003e0;
|
||||
c->base.redMask = 0x00007c00;
|
||||
c->base.alphaMask = 0x00008000;
|
||||
} else {
|
||||
c->base.greenMask = 0x000007e0;
|
||||
c->base.redMask = 0x0000f800;
|
||||
c->base.alphaMask = 0x00000000;
|
||||
}
|
||||
}
|
||||
else if (c->base.redBits == 8 &&
|
||||
(c->base.rgbBits == 24 || c->base.rgbBits == 32)) {
|
||||
c->base.blueMask = 0x000000ff;
|
||||
c->base.greenMask = 0x0000ff00;
|
||||
c->base.redMask = 0x00ff0000;
|
||||
if (c->base.alphaBits)
|
||||
/* assume all remaining bits are alpha */
|
||||
c->base.alphaMask = 0xff000000;
|
||||
}
|
||||
else if (c->base.redBits == 10 &&
|
||||
(c->base.rgbBits == 30 || c->base.rgbBits == 32)) {
|
||||
c->base.blueMask = 0x000003ff;
|
||||
c->base.greenMask = 0x000ffc00;
|
||||
c->base.redMask = 0x3ff00000;
|
||||
if (c->base.alphaBits)
|
||||
/* assume all remaining bits are alpha */
|
||||
c->base.alphaMask = 0xc000000;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Here we decide which fbconfigs will be duplicated for compositing.
|
||||
* fgbconfigs marked with duplicatedForComp will be reserved for
|
||||
* compositing visuals.
|
||||
* It might look strange to do this decision this late when translation
|
||||
* from an EGLConfig is already done, but using the EGLConfig
|
||||
* accessor functions becomes worse both with respect to code complexity
|
||||
* and CPU usage.
|
||||
*/
|
||||
if (duplicate_for_composite &&
|
||||
(c->base.renderType == GLX_RGBA_FLOAT_BIT_ARB ||
|
||||
c->base.rgbBits != 32 ||
|
||||
c->base.redBits != 8 ||
|
||||
c->base.greenBits != 8 ||
|
||||
c->base.blueBits != 8 ||
|
||||
c->base.visualRating != GLX_NONE ||
|
||||
c->base.sampleBuffers != 0)) {
|
||||
free(c);
|
||||
return chain;
|
||||
}
|
||||
c->base.duplicatedForComp = duplicate_for_composite;
|
||||
|
||||
c->base.next = chain ? &chain->base : NULL;
|
||||
return c;
|
||||
}
|
||||
|
||||
static __GLXconfig *
|
||||
egl_mirror_configs(ScreenPtr pScreen, struct egl_screen *screen)
|
||||
{
|
||||
int i, j, k, nconfigs;
|
||||
struct egl_config *c = NULL;
|
||||
EGLConfig *host_configs = NULL;
|
||||
|
||||
eglGetConfigs(screen->display, NULL, 0, &nconfigs);
|
||||
if (!(host_configs = calloc(nconfigs, sizeof *host_configs)))
|
||||
return NULL;
|
||||
|
||||
eglGetConfigs(screen->display, host_configs, nconfigs, &nconfigs);
|
||||
|
||||
/* We walk the EGL configs backwards to make building the
|
||||
* ->next chain easier.
|
||||
*/
|
||||
for (i = nconfigs - 1; i > 0; i--)
|
||||
for (j = 0; j < 3; j++) /* direct_color */
|
||||
for (k = 0; k < 2; k++) /* double_buffer */
|
||||
c = translate_eglconfig(screen, host_configs[i], c,
|
||||
/* direct_color */ j == 1,
|
||||
/* double_buffer */ k > 0,
|
||||
/* duplicate_for_composite */ j == 0);
|
||||
|
||||
screen->configs = host_configs;
|
||||
return c ? &c->base : NULL;
|
||||
}
|
||||
|
||||
static __GLXscreen *
|
||||
egl_screen_probe(ScreenPtr pScreen)
|
||||
{
|
||||
struct egl_screen *screen;
|
||||
struct xwl_screen *xwl_screen = xwl_screen_get(pScreen);
|
||||
__GLXscreen *base;
|
||||
|
||||
if (enableIndirectGLX)
|
||||
return NULL; /* not implemented */
|
||||
|
||||
if (!(screen = calloc(1, sizeof *screen)))
|
||||
return NULL;
|
||||
|
||||
base = &screen->base;
|
||||
base->destroy = egl_screen_destroy;
|
||||
base->createDrawable = egl_create_glx_drawable;
|
||||
/* base.swapInterval = NULL; */
|
||||
|
||||
screen->display = xwl_screen->glamor_ctx->display;
|
||||
|
||||
__glXInitExtensionEnableBits(screen->base.glx_enable_bits);
|
||||
__glXEnableExtension(base->glx_enable_bits, "GLX_ARB_context_flush_control");
|
||||
__glXEnableExtension(base->glx_enable_bits, "GLX_ARB_create_context");
|
||||
__glXEnableExtension(base->glx_enable_bits, "GLX_ARB_create_context_no_error");
|
||||
__glXEnableExtension(base->glx_enable_bits, "GLX_ARB_create_context_profile");
|
||||
__glXEnableExtension(base->glx_enable_bits, "GLX_ARB_create_context_robustness");
|
||||
__glXEnableExtension(base->glx_enable_bits, "GLX_ARB_fbconfig_float");
|
||||
__glXEnableExtension(base->glx_enable_bits, "GLX_EXT_create_context_es2_profile");
|
||||
__glXEnableExtension(base->glx_enable_bits, "GLX_EXT_create_context_es_profile");
|
||||
__glXEnableExtension(base->glx_enable_bits, "GLX_EXT_fbconfig_packed_float");
|
||||
__glXEnableExtension(base->glx_enable_bits, "GLX_EXT_framebuffer_sRGB");
|
||||
__glXEnableExtension(base->glx_enable_bits, "GLX_EXT_no_config_context");
|
||||
__glXEnableExtension(base->glx_enable_bits, "GLX_EXT_texture_from_pixmap");
|
||||
__glXEnableExtension(base->glx_enable_bits, "GLX_MESA_copy_sub_buffer");
|
||||
// __glXEnableExtension(base->glx_enable_bits, "GLX_SGI_swap_control");
|
||||
|
||||
base->fbconfigs = egl_mirror_configs(pScreen, screen);
|
||||
if (!base->fbconfigs) {
|
||||
free(screen);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!screen->base.glvnd && xwl_screen->glvnd_vendor)
|
||||
screen->base.glvnd = strdup(xwl_screen->glvnd_vendor);
|
||||
|
||||
if (!screen->base.glvnd)
|
||||
screen->base.glvnd = strdup("mesa");
|
||||
|
||||
__glXScreenInit(base, pScreen);
|
||||
__glXsetGetProcAddress(eglGetProcAddress);
|
||||
|
||||
return base;
|
||||
}
|
||||
|
||||
__GLXprovider glamor_provider = {
|
||||
egl_screen_probe,
|
||||
"glamor",
|
||||
NULL
|
||||
};
|
|
@ -1,37 +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:
|
||||
* Adam Jackson <ajax@redhat.com>
|
||||
*/
|
||||
|
||||
#ifndef XWAYLAND_GLX_H
|
||||
#define XWAYLAND_GLX_H
|
||||
|
||||
#include <xwayland-config.h>
|
||||
|
||||
#ifdef GLXEXT
|
||||
#include "glx_extinit.h"
|
||||
extern __GLXprovider glamor_provider;
|
||||
#endif
|
||||
|
||||
#endif /* XWAYLAND_GLX_H */
|
File diff suppressed because it is too large
Load Diff
|
@ -1,197 +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 <xwayland-config.h>
|
||||
#include <wayland-client.h>
|
||||
|
||||
#include <dix.h>
|
||||
#include <input.h>
|
||||
|
||||
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 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 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;
|
||||
WindowPtr last_xwindow;
|
||||
|
||||
struct xorg_list touches;
|
||||
|
||||
size_t keymap_size;
|
||||
char *keymap;
|
||||
struct wl_surface *keyboard_focus;
|
||||
|
||||
struct xorg_list axis_discrete_pending;
|
||||
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;
|
||||
} 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_destroy(struct xwl_seat *xwl_seat);
|
||||
|
||||
void xwl_seat_clear_touch(struct xwl_seat *xwl_seat, WindowPtr 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 */
|
|
@ -1,881 +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 <xwayland-config.h>
|
||||
|
||||
#include <randrstr.h>
|
||||
#include <X11/Xatom.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"
|
||||
|
||||
#define ALL_ROTATIONS (RR_Rotate_0 | \
|
||||
RR_Rotate_90 | \
|
||||
RR_Rotate_180 | \
|
||||
RR_Rotate_270 | \
|
||||
RR_Reflect_X | \
|
||||
RR_Reflect_Y)
|
||||
|
||||
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;
|
||||
|
||||
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);
|
||||
pScreen->DestroyPixmap(old_pixmap);
|
||||
}
|
||||
|
||||
pScreen->ResizeWindow(pRoot, 0, 0, width, height, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
update_screen_size(struct xwl_output *xwl_output, int width, int height)
|
||||
{
|
||||
struct xwl_screen *xwl_screen = xwl_output->xwl_screen;
|
||||
|
||||
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->width = width;
|
||||
xwl_screen->height = 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;
|
||||
|
||||
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->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 },
|
||||
{ 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 = xallocarray(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))
|
||||
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, which is idx 0 */
|
||||
if (width == -1 && height == -1 && output->modes)
|
||||
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, RT_WINDOW,
|
||||
xwl_output_set_randr_emu_prop_callback, &prop);
|
||||
}
|
||||
|
||||
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, wClient(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)
|
||||
{
|
||||
DebugF("XWAYLAND: xwl_output_set_emulated_mode from %s: %dx%d\n",
|
||||
from_vidmode ? "vidmode" : "randr",
|
||||
mode->mode.width, mode->mode.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);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
update_screen_size(xwl_output, width, height);
|
||||
}
|
||||
|
||||
static void
|
||||
output_handle_done(void *data, struct wl_output *wl_output)
|
||||
{
|
||||
struct xwl_output *xwl_output = data;
|
||||
|
||||
xwl_output->wl_output_done = TRUE;
|
||||
/* 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)
|
||||
{
|
||||
}
|
||||
|
||||
static const struct wl_output_listener output_listener = {
|
||||
output_handle_geometry,
|
||||
output_handle_mode,
|
||||
output_handle_done,
|
||||
output_handle_scale
|
||||
};
|
||||
|
||||
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;
|
||||
|
||||
xwl_output->xdg_output_done = TRUE;
|
||||
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)
|
||||
{
|
||||
}
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
struct xwl_output *
|
||||
xwl_output_create(struct xwl_screen *xwl_screen, uint32_t id)
|
||||
{
|
||||
struct xwl_output *xwl_output;
|
||||
static int serial;
|
||||
char name[256];
|
||||
|
||||
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, 2);
|
||||
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);
|
||||
|
||||
snprintf(name, sizeof name, "XWAYLAND%d", serial++);
|
||||
|
||||
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);
|
||||
|
||||
xwl_output->randr_output = RROutputCreate(xwl_screen->screen, name,
|
||||
strlen(name), xwl_output);
|
||||
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);
|
||||
RRTellChanged(xwl_screen->screen);
|
||||
|
||||
/* 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);
|
||||
--xwl_screen->expecting_event;
|
||||
|
||||
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->xdg_output)
|
||||
zxdg_output_v1_destroy(xwl_output->xdg_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;
|
||||
int width = 0, height = 0;
|
||||
|
||||
xorg_list_del(&xwl_output->link);
|
||||
|
||||
xorg_list_for_each_entry(it, &xwl_screen->output_list, link)
|
||||
output_get_new_size(it, &width, &height);
|
||||
update_screen_size(xwl_output, width, height);
|
||||
|
||||
RRCrtcDestroy(xwl_output->randr_crtc);
|
||||
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 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)
|
||||
{
|
||||
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->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
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
xwl_output_get_xdg_output(struct xwl_output *xwl_output)
|
||||
{
|
||||
struct xwl_screen *xwl_screen = xwl_output->xwl_screen;
|
||||
|
||||
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);
|
||||
}
|
|
@ -1,82 +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 <xwayland-config.h>
|
||||
#include <wayland-client.h>
|
||||
|
||||
#include <dix.h>
|
||||
#include <input.h>
|
||||
#include <randrstr.h>
|
||||
|
||||
#include "xwayland-types.h"
|
||||
|
||||
struct xwl_output {
|
||||
struct xorg_list link;
|
||||
struct wl_output *output;
|
||||
struct zxdg_output_v1 *xdg_output;
|
||||
uint32_t server_output_id;
|
||||
struct xwl_screen *xwl_screen;
|
||||
RROutputPtr randr_output;
|
||||
RRCrtcPtr randr_crtc;
|
||||
int32_t x, y, width, height, refresh;
|
||||
Rotation rotation;
|
||||
Bool wl_output_done;
|
||||
Bool xdg_output_done;
|
||||
};
|
||||
|
||||
/* Per client per output emulated randr/vidmode resolution info. */
|
||||
struct xwl_emulated_mode {
|
||||
uint32_t server_output_id;
|
||||
int32_t width;
|
||||
int32_t height;
|
||||
Bool from_vidmode;
|
||||
};
|
||||
|
||||
Bool xwl_screen_init_output(struct xwl_screen *xwl_screen);
|
||||
|
||||
struct xwl_output *xwl_output_create(struct xwl_screen *xwl_screen,
|
||||
uint32_t id);
|
||||
|
||||
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 */
|
|
@ -1,123 +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 <xwayland-config.h>
|
||||
|
||||
#include <X11/X.h>
|
||||
|
||||
#include "os.h"
|
||||
#include "privates.h"
|
||||
#include "dix.h"
|
||||
#include "fb.h"
|
||||
#include "pixmapstr.h"
|
||||
|
||||
#include "xwayland-types.h"
|
||||
#include "xwayland-pixmap.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);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
|
@ -1,47 +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 <xwayland-config.h>
|
||||
#include <wayland-client.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);
|
||||
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);
|
||||
|
||||
#endif /* XWAYLAND_PIXMAP_H */
|
|
@ -1,965 +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 <xwayland-config.h>
|
||||
|
||||
#include <windowstr.h>
|
||||
#include <present.h>
|
||||
|
||||
#include "xwayland-present.h"
|
||||
#include "xwayland-screen.h"
|
||||
#include "xwayland-window.h"
|
||||
#include "xwayland-pixmap.h"
|
||||
#include "glamor.h"
|
||||
|
||||
|
||||
#define XWL_PRESENT_CAPS PresentCapabilityAsync
|
||||
|
||||
|
||||
/*
|
||||
* 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->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);
|
||||
|
||||
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(uint64_t event_id)
|
||||
{
|
||||
return (struct xwl_present_event*)(uintptr_t)event_id;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
static void
|
||||
xwl_present_reset_timer(struct xwl_present_window *xwl_present_window)
|
||||
{
|
||||
if (xwl_present_has_pending_events(xwl_present_window)) {
|
||||
CARD32 timeout;
|
||||
|
||||
if (!xorg_list_is_empty(&xwl_present_window->frame_callback_list))
|
||||
timeout = TIMER_LEN_FLIP;
|
||||
else
|
||||
timeout = TIMER_LEN_COPY;
|
||||
|
||||
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 uint32_t
|
||||
xwl_present_query_capabilities(present_screen_priv_ptr screen_priv)
|
||||
{
|
||||
return XWL_PRESENT_CAPS;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
uint64_t ust = 0, crtc_msc = 0;
|
||||
|
||||
(void) xwl_present_get_ust_msc(vblank->screen, vblank->window, &ust, &crtc_msc);
|
||||
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)
|
||||
{
|
||||
present_pixmap_idle(vblank->pixmap, vblank->window, vblank->serial, vblank->idle_fence);
|
||||
xwl_present_free_event(xwl_present_event_from_id((uintptr_t)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) {
|
||||
xwl_present_free_idle_vblank(xwl_present_window->flip_active);
|
||||
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;
|
||||
struct xwl_present_window *xwl_present_window = xwl_present_window_priv(window);
|
||||
|
||||
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_id((uintptr_t)xwl_present_window->flip_active);
|
||||
|
||||
if (!event->pixmap)
|
||||
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;
|
||||
|
||||
present_vblank_notify(vblank, PresentCompleteKindPixmap, PresentCompleteModeFlip, 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;
|
||||
}
|
||||
|
||||
/* 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);
|
||||
|
||||
/* 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;
|
||||
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();
|
||||
|
||||
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(event_id);
|
||||
|
||||
event->vblank.exec_msc = msc;
|
||||
|
||||
xorg_list_del(&event->vblank.event_queue);
|
||||
xorg_list_append(&event->vblank.event_queue, &xwl_present_window->wait_list);
|
||||
|
||||
/* If there's a pending frame callback, use that */
|
||||
if (xwl_window && xwl_window->frame_callback &&
|
||||
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)
|
||||
{
|
||||
glamor_block_handler(window->drawable.pScreen);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
/* 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;
|
||||
|
||||
if (!xwl_glamor_check_flip(pixmap))
|
||||
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->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->window->winSize, &present_window->winSize))
|
||||
return FALSE;
|
||||
|
||||
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(WindowPtr present_window,
|
||||
RRCrtcPtr crtc,
|
||||
uint64_t event_id,
|
||||
PixmapPtr pixmap,
|
||||
Bool sync_flip,
|
||||
RegionPtr damage)
|
||||
{
|
||||
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_id(event_id);
|
||||
|
||||
if (!xwl_window)
|
||||
return FALSE;
|
||||
|
||||
buffer = xwl_glamor_pixmap_get_wl_buffer(pixmap);
|
||||
if (!buffer) {
|
||||
ErrorF("present: Error getting buffer\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
damage_box = RegionExtents(damage);
|
||||
|
||||
pixmap->refcnt++;
|
||||
|
||||
event->pixmap = pixmap;
|
||||
|
||||
xwl_pixmap_set_buffer_release_cb(pixmap, xwl_present_buffer_release, event);
|
||||
|
||||
/* We can flip directly to the main surface (full screen window without clips) */
|
||||
wl_surface_attach(xwl_window->surface, buffer, 0, 0);
|
||||
|
||||
if (!xwl_window->frame_callback)
|
||||
xwl_window_create_frame_callback(xwl_window);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/* Realign timer */
|
||||
xwl_present_reset_timer(xwl_present_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);
|
||||
|
||||
wl_surface_commit(xwl_window->surface);
|
||||
|
||||
if (!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);
|
||||
xwl_window->present_flipped = TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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);
|
||||
|
||||
xorg_list_del(&vblank->event_queue);
|
||||
|
||||
if (present_execute_wait(vblank, crtc_msc))
|
||||
return;
|
||||
|
||||
if (flip_pending && vblank->flip && vblank->pixmap && vblank->window) {
|
||||
DebugPresent(("\tr %" PRIu64 " %p (pending %p)\n",
|
||||
vblank->event_id, vblank, flip_pending));
|
||||
xorg_list_append(&vblank->event_queue, &xwl_present_window->flip_queue);
|
||||
vblank->flip_ready = TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
vblank->queued = FALSE;
|
||||
|
||||
if (vblank->pixmap && vblank->window) {
|
||||
ScreenPtr screen = window->drawable.pScreen;
|
||||
|
||||
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->window, vblank->crtc, vblank->event_id,
|
||||
vblank->pixmap, vblank->sync_flip, damage)) {
|
||||
WindowPtr toplvl_window = xwl_present_toplvl_pixmap_window(vblank->window);
|
||||
PixmapPtr old_pixmap = screen->GetWindowPixmap(window);
|
||||
|
||||
/* Replace window pixmap with flip pixmap */
|
||||
#ifdef COMPOSITE
|
||||
vblank->pixmap->screen_x = old_pixmap->screen_x;
|
||||
vblank->pixmap->screen_y = old_pixmap->screen_y;
|
||||
#endif
|
||||
present_set_tree_pixmap(toplvl_window, old_pixmap, vblank->pixmap);
|
||||
vblank->pixmap->refcnt++;
|
||||
dixDestroyPixmap(old_pixmap, old_pixmap->drawable.id);
|
||||
|
||||
/* Report damage */
|
||||
DamageDamageRegion(&vblank->window->drawable, damage);
|
||||
RegionDestroy(damage);
|
||||
|
||||
/* Put pending flip at the flip queue head */
|
||||
xorg_list_add(&vblank->event_queue, &xwl_present_window->flip_queue);
|
||||
return;
|
||||
}
|
||||
|
||||
vblank->flip = FALSE;
|
||||
}
|
||||
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);
|
||||
|
||||
if (xwl_present_queue_vblank(screen, window, vblank->crtc,
|
||||
vblank->event_id, crtc_msc + 1)
|
||||
== Success) {
|
||||
/* Clear the pixmap field, so this will fall through to present_execute_post next time */
|
||||
dixDestroyPixmap(vblank->pixmap, vblank->pixmap->drawable.id);
|
||||
vblank->pixmap = NULL;
|
||||
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,
|
||||
uint32_t options,
|
||||
uint64_t target_window_msc,
|
||||
uint64_t divisor,
|
||||
uint64_t remainder,
|
||||
present_notify_ptr notifies,
|
||||
int num_notifies)
|
||||
{
|
||||
uint64_t ust = 0;
|
||||
uint64_t target_msc;
|
||||
uint64_t crtc_msc = 0;
|
||||
int ret;
|
||||
present_vblank_ptr vblank, tmp;
|
||||
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_present_event *event;
|
||||
|
||||
if (!window_priv)
|
||||
return BadAlloc;
|
||||
|
||||
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);
|
||||
|
||||
/*
|
||||
* Look for a matching presentation already on the list...
|
||||
*/
|
||||
|
||||
if (!update && pixmap) {
|
||||
xorg_list_for_each_entry_safe(vblank, tmp, &window_priv->vblank, window_list) {
|
||||
|
||||
if (!vblank->pixmap)
|
||||
continue;
|
||||
|
||||
if (!vblank->queued)
|
||||
continue;
|
||||
|
||||
if (vblank->target_msc != target_msc)
|
||||
continue;
|
||||
|
||||
present_vblank_scrap(vblank);
|
||||
if (vblank->flip_ready)
|
||||
xwl_present_re_execute(vblank);
|
||||
}
|
||||
}
|
||||
|
||||
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, options, XWL_PRESENT_CAPS,
|
||||
notifies, num_notifies, target_msc, crtc_msc)) {
|
||||
present_vblank_destroy(vblank);
|
||||
return BadAlloc;
|
||||
}
|
||||
|
||||
vblank->event_id = (uintptr_t)event;
|
||||
|
||||
/* Xwayland presentations always complete (at least) one frame after they
|
||||
* are executed
|
||||
*/
|
||||
vblank->exec_msc = vblank->target_msc - 1;
|
||||
|
||||
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);
|
||||
xwl_present_reset_timer(xwl_present_window);
|
||||
}
|
||||
|
||||
Bool
|
||||
xwl_present_init(ScreenPtr screen)
|
||||
{
|
||||
struct xwl_screen *xwl_screen = xwl_screen_get(screen);
|
||||
present_screen_priv_ptr screen_priv;
|
||||
|
||||
if (!xwl_screen->glamor || !xwl_screen->egl_backend)
|
||||
return FALSE;
|
||||
|
||||
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;
|
||||
|
||||
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->re_execute = xwl_present_re_execute;
|
||||
|
||||
screen_priv->abort_vblank = xwl_present_abort_vblank;
|
||||
|
||||
return TRUE;
|
||||
}
|
|
@ -1,67 +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 <xwayland-config.h>
|
||||
|
||||
#include <dix.h>
|
||||
#include <present_priv.h>
|
||||
|
||||
#include "xwayland-types.h"
|
||||
|
||||
#ifdef GLAMOR_HAS_GBM
|
||||
struct xwl_present_window {
|
||||
struct xorg_list frame_callback_list;
|
||||
|
||||
uint64_t msc;
|
||||
uint64_t ust;
|
||||
|
||||
OsTimerPtr frame_timer;
|
||||
|
||||
struct wl_callback *sync_callback;
|
||||
|
||||
struct xorg_list wait_list;
|
||||
struct xorg_list flip_queue;
|
||||
struct xorg_list idle_queue;
|
||||
|
||||
present_vblank_ptr flip_active;
|
||||
};
|
||||
|
||||
struct xwl_present_event {
|
||||
present_vblank_rec vblank;
|
||||
|
||||
PixmapPtr pixmap;
|
||||
};
|
||||
|
||||
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);
|
||||
|
||||
#endif /* GLAMOR_HAS_GBM */
|
||||
|
||||
#endif /* XWAYLAND_PRESENT_H */
|
|
@ -1,751 +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 <xwayland-config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef XWL_HAS_GLAMOR
|
||||
#include <glamor.h>
|
||||
#endif
|
||||
|
||||
#include <X11/Xatom.h>
|
||||
#include <micmap.h>
|
||||
#include <misyncshm.h>
|
||||
#include <os.h>
|
||||
#include <fb.h>
|
||||
#include <dixstruct.h>
|
||||
#include <propertyst.h>
|
||||
#include <inputstr.h>
|
||||
#include <xserver_poll.h>
|
||||
|
||||
#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 MITSHM
|
||||
#include "shmint.h"
|
||||
#endif
|
||||
|
||||
#include "xdg-output-unstable-v1-client-protocol.h"
|
||||
#include "viewporter-client-protocol.h"
|
||||
#include "xdg-shell-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);
|
||||
VErrorFSigSafe(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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
Bool
|
||||
xwl_close_screen(ScreenPtr screen)
|
||||
{
|
||||
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;
|
||||
|
||||
DeleteCallback(&PropertyStateCallback, xwl_property_callback, screen);
|
||||
|
||||
xorg_list_for_each_entry_safe(xwl_output, next_xwl_output,
|
||||
&xwl_screen->output_list, link)
|
||||
xwl_output_destroy(xwl_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);
|
||||
|
||||
RemoveNotifyFd(xwl_screen->wayland_fd);
|
||||
|
||||
wl_display_disconnect(xwl_screen->display);
|
||||
|
||||
screen->CloseScreen = xwl_screen->CloseScreen;
|
||||
free(xwl_screen);
|
||||
|
||||
return screen->CloseScreen(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->focus_window) {
|
||||
focus = xwl_seat->focus_window->window;
|
||||
|
||||
/* 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 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->window->drawable.x ||
|
||||
window->drawable.x + window->drawable.width >
|
||||
xwl_window->window->drawable.x + xwl_window->window->drawable.width ||
|
||||
window->drawable.y < xwl_window->window->drawable.y ||
|
||||
window->drawable.y + window->drawable.height >
|
||||
xwl_window->window->drawable.y + xwl_window->window->drawable.height)
|
||||
continue;
|
||||
|
||||
if (xwl_window->window->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 (!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;
|
||||
|
||||
#ifdef XWL_HAS_GLAMOR
|
||||
if (xwl_screen->glamor && !xwl_glamor_allow_commits(xwl_window))
|
||||
continue;
|
||||
#endif
|
||||
|
||||
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_glamor_needs_buffer_flush(xwl_screen))
|
||||
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") == 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") == 0) {
|
||||
xwl_screen->shm = wl_registry_bind(registry, id, &wl_shm_interface, 1);
|
||||
}
|
||||
else if (strcmp(interface, "xdg_wm_base") == 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") == 0 && version >= 2) {
|
||||
if (xwl_output_create(xwl_screen, id))
|
||||
xwl_screen->expecting_event++;
|
||||
}
|
||||
else if (strcmp(interface, "zxdg_output_manager_v1") == 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_viewporter") == 0) {
|
||||
xwl_screen->viewporter = wl_registry_bind(registry, id, &wp_viewporter_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;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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);
|
||||
xwl_dispatch_events (xwl_screen);
|
||||
}
|
||||
|
||||
void
|
||||
xwl_sync_events (struct xwl_screen *xwl_screen)
|
||||
{
|
||||
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;
|
||||
|
||||
ret = wl_display_roundtrip(xwl_screen->display);
|
||||
while (ret >= 0 && xwl_screen->expecting_event)
|
||||
ret = wl_display_roundtrip(xwl_screen->display);
|
||||
|
||||
if (ret < 0)
|
||||
xwl_give_up("could not connect to wayland server\n");
|
||||
}
|
||||
|
||||
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;
|
||||
#ifdef XWL_HAS_GLAMOR
|
||||
Bool use_eglstreams = FALSE;
|
||||
#endif
|
||||
|
||||
xwl_screen = calloc(1, sizeof *xwl_screen);
|
||||
if (xwl_screen == NULL)
|
||||
return 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;
|
||||
|
||||
dixSetPrivate(&pScreen->devPrivates, &xwl_screen_private_key, xwl_screen);
|
||||
xwl_screen->screen = pScreen;
|
||||
|
||||
#ifdef XWL_HAS_GLAMOR
|
||||
xwl_screen->glamor = 1;
|
||||
#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 = 0;
|
||||
}
|
||||
else if (strcmp(argv[i], "-eglstream") == 0) {
|
||||
#ifdef XWL_HAS_EGLSTREAM
|
||||
use_eglstreams = TRUE;
|
||||
#else
|
||||
ErrorF("xwayland glamor: this build does not have EGLStream support\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef XWL_HAS_GLAMOR
|
||||
if (xwl_screen->glamor)
|
||||
xwl_glamor_init_backends(xwl_screen, use_eglstreams);
|
||||
#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);
|
||||
xwl_screen->depth = 24;
|
||||
|
||||
if (!monitorResolution)
|
||||
monitorResolution = DEFAULT_DPI;
|
||||
|
||||
xwl_screen->display = wl_display_connect(NULL);
|
||||
if (xwl_screen->display == NULL) {
|
||||
ErrorF("could not connect to wayland server\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
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->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->width, xwl_screen->height,
|
||||
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
|
||||
|
||||
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_select_backend(xwl_screen, use_eglstreams);
|
||||
|
||||
if (xwl_screen->egl_backend == NULL || !xwl_glamor_init(xwl_screen)) {
|
||||
ErrorF("Failed to initialize glamor, falling back to sw\n");
|
||||
xwl_screen->glamor = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (xwl_screen->glamor && xwl_screen->rootless)
|
||||
xwl_screen->present = xwl_present_init(pScreen);
|
||||
#endif
|
||||
|
||||
if (!xwl_screen->glamor) {
|
||||
xwl_screen->CreateScreenResources = pScreen->CreateScreenResources;
|
||||
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;
|
||||
|
||||
xwl_screen->DestroyWindow = pScreen->DestroyWindow;
|
||||
pScreen->DestroyWindow = xwl_destroy_window;
|
||||
|
||||
xwl_screen->CloseScreen = pScreen->CloseScreen;
|
||||
pScreen->CloseScreen = xwl_close_screen;
|
||||
|
||||
xwl_screen->ChangeWindowAttributes = pScreen->ChangeWindowAttributes;
|
||||
pScreen->ChangeWindowAttributes = xwl_change_window_attributes;
|
||||
|
||||
xwl_screen->ResizeWindow = pScreen->ResizeWindow;
|
||||
pScreen->ResizeWindow = xwl_resize_window;
|
||||
|
||||
xwl_screen->MoveWindow = pScreen->MoveWindow;
|
||||
pScreen->MoveWindow = xwl_move_window;
|
||||
|
||||
if (xwl_screen->rootless) {
|
||||
xwl_screen->SetWindowPixmap = pScreen->SetWindowPixmap;
|
||||
pScreen->SetWindowPixmap = xwl_window_set_window_pixmap;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
xwl_screen_roundtrip(xwl_screen);
|
||||
|
||||
return ret;
|
||||
}
|
|
@ -1,138 +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 <xwayland-config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <X11/X.h>
|
||||
#include <dix.h>
|
||||
|
||||
#include "xwayland-types.h"
|
||||
#include "xwayland-output.h"
|
||||
#include "xwayland-glamor.h"
|
||||
|
||||
struct xwl_format {
|
||||
uint32_t format;
|
||||
int num_modifiers;
|
||||
uint64_t *modifiers;
|
||||
};
|
||||
|
||||
struct xwl_screen {
|
||||
int width;
|
||||
int height;
|
||||
int depth;
|
||||
ScreenPtr screen;
|
||||
int wm_client_id;
|
||||
int expecting_event;
|
||||
enum RootClipMode root_clip_mode;
|
||||
|
||||
int rootless;
|
||||
int glamor;
|
||||
int present;
|
||||
|
||||
CreateScreenResourcesProcPtr CreateScreenResources;
|
||||
CloseScreenProcPtr CloseScreen;
|
||||
RealizeWindowProcPtr RealizeWindow;
|
||||
UnrealizeWindowProcPtr UnrealizeWindow;
|
||||
DestroyWindowProcPtr DestroyWindow;
|
||||
XYToWindowProcPtr XYToWindow;
|
||||
SetWindowPixmapProcPtr SetWindowPixmap;
|
||||
ChangeWindowAttributesProcPtr ChangeWindowAttributes;
|
||||
ResizeWindowProcPtr ResizeWindow;
|
||||
MoveWindowProcPtr MoveWindow;
|
||||
|
||||
struct xorg_list output_list;
|
||||
struct xorg_list seat_list;
|
||||
struct xorg_list damage_window_list;
|
||||
struct xorg_list window_list;
|
||||
|
||||
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_xwayland_keyboard_grab_manager_v1 *wp_grab;
|
||||
struct zwp_linux_dmabuf_v1 *dmabuf;
|
||||
struct zxdg_output_manager_v1 *xdg_output_manager;
|
||||
struct wp_viewporter *viewporter;
|
||||
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 xwl_egl_backend gbm_backend;
|
||||
struct xwl_egl_backend eglstream_backend;
|
||||
/* pointer to the current backend for creating pixmaps on wayland */
|
||||
struct xwl_egl_backend *egl_backend;
|
||||
|
||||
struct glamor_context *glamor_ctx;
|
||||
|
||||
Atom allow_commits_prop;
|
||||
|
||||
/* The preferred GLVND vendor. If NULL, "mesa" is assumed. */
|
||||
const char *glvnd_vendor;
|
||||
};
|
||||
|
||||
/* 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);
|
||||
Bool xwl_close_screen(ScreenPtr 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);
|
||||
|
||||
#endif /* XWAYLAND_SCREEN_H */
|
|
@ -1,339 +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 <xwayland-config.h>
|
||||
|
||||
#include "os.h"
|
||||
|
||||
#include <sys/mman.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.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;
|
||||
char *name;
|
||||
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;
|
||||
}
|
||||
|
||||
name = malloc(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 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 ||
|
||||
(!xwl_screen->rootless && hint != CREATE_PIXMAP_USAGE_BACKING_PIXMAP) ||
|
||||
(width == 0 && height == 0) || depth < 15)
|
||||
return fbCreatePixmap(screen, width, height, depth, hint);
|
||||
|
||||
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;
|
||||
|
||||
stride = PixmapBytePad(width, depth);
|
||||
size = stride * height;
|
||||
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)
|
||||
{
|
||||
return xwl_pixmap_get(pixmap)->buffer;
|
||||
}
|
||||
|
||||
Bool
|
||||
xwl_shm_create_screen_resources(ScreenPtr screen)
|
||||
{
|
||||
struct xwl_screen *xwl_screen = xwl_screen_get(screen);
|
||||
int ret;
|
||||
|
||||
screen->CreateScreenResources = xwl_screen->CreateScreenResources;
|
||||
ret = (*screen->CreateScreenResources) (screen);
|
||||
xwl_screen->CreateScreenResources = screen->CreateScreenResources;
|
||||
screen->CreateScreenResources = xwl_shm_create_screen_resources;
|
||||
|
||||
if (!ret)
|
||||
return ret;
|
||||
|
||||
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;
|
||||
}
|
|
@ -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 <xwayland-config.h>
|
||||
|
||||
#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 */
|
|
@ -1,34 +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_egl_backend;
|
||||
|
||||
#endif /* XWAYLAND_TYPES_H */
|
|
@ -1,492 +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).
|
||||
*/
|
||||
|
||||
#ifdef HAVE_DIX_CONFIG_H
|
||||
#include <dix-config.h>
|
||||
#endif
|
||||
|
||||
#include <X11/X.h>
|
||||
#include "misc.h"
|
||||
#include "os.h"
|
||||
#include "extinit.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_screen_get_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_output *xwl_output = xwl_screen_get_first_output(xwl_screen);
|
||||
struct xwl_emulated_mode *emulated_mode;
|
||||
|
||||
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 = xwl_screen_get_first_output(xwl_screen);
|
||||
VidModePtr pVidMode;
|
||||
DisplayModePtr pMod;
|
||||
intptr_t index;
|
||||
|
||||
pMod = dixLookupPrivate(&pScreen->devPrivates, xwlVidModePrivateKey);
|
||||
pVidMode = VidModeGetPtr(pScreen);
|
||||
if (xwl_output == NULL || 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_screen_get_first_output(xwl_screen);
|
||||
|
||||
if (!xwl_output)
|
||||
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_screen_get_first_output(xwl_screen);
|
||||
|
||||
if (!xwl_output)
|
||||
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 = xwl_screen_get_first_output(xwl_screen);
|
||||
RRModePtr rrmode;
|
||||
|
||||
if (!xwl_output)
|
||||
return FALSE;
|
||||
|
||||
rrmode = xwl_output_find_mode(xwl_output, mode->HDisplay, mode->VDisplay);
|
||||
if (rrmode == NULL)
|
||||
return FALSE;
|
||||
|
||||
xwl_output_set_emulated_mode(xwl_output, GetCurrentClient(), rrmode, TRUE);
|
||||
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_screen_get_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 */
|
|
@ -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 <xwayland-config.h>
|
||||
|
||||
#ifdef XF86VIDMODE
|
||||
void xwlVidModeExtensionInit(void);
|
||||
#endif
|
||||
|
||||
#endif /* XWAYLAND_VIDMODE_H */
|
|
@ -1,367 +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 <ofourdan@redhat.com>
|
||||
*/
|
||||
|
||||
#include <xwayland-config.h>
|
||||
|
||||
#include "gcstruct.h"
|
||||
|
||||
#include "xwayland-window.h"
|
||||
#include "xwayland-pixmap.h"
|
||||
#include "xwayland-screen.h"
|
||||
#include "xwayland-window-buffers.h"
|
||||
|
||||
#define BUFFER_TIMEOUT 1 * 1000 /* ms */
|
||||
|
||||
struct xwl_window_buffer {
|
||||
struct xwl_window *xwl_window;
|
||||
PixmapPtr pixmap;
|
||||
RegionPtr damage_region;
|
||||
Bool recycle_on_release;
|
||||
int refcnt;
|
||||
uint32_t time;
|
||||
struct xorg_list link_buffer;
|
||||
};
|
||||
|
||||
static Bool
|
||||
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) {
|
||||
ValidateGC(&dst_pixmap->drawable, pGC);
|
||||
(void) (*pGC->ops->CopyArea) (&src_pixmap->drawable,
|
||||
&dst_pixmap->drawable,
|
||||
pGC,
|
||||
x, y,
|
||||
width, height,
|
||||
x, y);
|
||||
FreeScratchGC(pGC);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
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_append(&xwl_window_buffer->link_buffer,
|
||||
&xwl_window->window_buffers_available);
|
||||
|
||||
return xwl_window_buffer;
|
||||
}
|
||||
|
||||
static void
|
||||
xwl_window_buffer_destroy_pixmap(struct xwl_window_buffer *xwl_window_buffer)
|
||||
{
|
||||
ScreenPtr pScreen = xwl_window_buffer->pixmap->drawable.pScreen;
|
||||
|
||||
xwl_pixmap_del_buffer_release_cb(xwl_window_buffer->pixmap);
|
||||
(*pScreen->DestroyPixmap) (xwl_window_buffer->pixmap);
|
||||
xwl_window_buffer->pixmap = NullPixmap;
|
||||
}
|
||||
|
||||
static Bool
|
||||
xwl_window_buffer_dispose(struct xwl_window_buffer *xwl_window_buffer)
|
||||
{
|
||||
assert(xwl_window_buffer->refcnt > 0);
|
||||
|
||||
if (--xwl_window_buffer->refcnt)
|
||||
return FALSE;
|
||||
|
||||
RegionDestroy(xwl_window_buffer->damage_region);
|
||||
|
||||
if (xwl_window_buffer->pixmap)
|
||||
xwl_window_buffer_destroy_pixmap (xwl_window_buffer);
|
||||
|
||||
xorg_list_del(&xwl_window_buffer->link_buffer);
|
||||
free(xwl_window_buffer);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
xwl_window_buffer_recycle(struct xwl_window_buffer *xwl_window_buffer)
|
||||
{
|
||||
RegionEmpty(xwl_window_buffer->damage_region);
|
||||
xwl_window_buffer->recycle_on_release = FALSE;
|
||||
|
||||
if (xwl_window_buffer->pixmap)
|
||||
xwl_window_buffer_destroy_pixmap (xwl_window_buffer);
|
||||
}
|
||||
|
||||
static void
|
||||
xwl_window_buffer_add_damage_region(struct xwl_window *xwl_window,
|
||||
RegionPtr damage_region)
|
||||
{
|
||||
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,
|
||||
damage_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,
|
||||
damage_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 xwl_window_buffer_new(xwl_window);
|
||||
|
||||
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_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_dispose(xwl_window_buffer))
|
||||
return;
|
||||
|
||||
if (xwl_window_buffer->recycle_on_release)
|
||||
xwl_window_buffer_recycle(xwl_window_buffer);
|
||||
|
||||
/* 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_buffers_init(struct xwl_window *xwl_window)
|
||||
{
|
||||
xorg_list_init(&xwl_window->window_buffers_available);
|
||||
xorg_list_init(&xwl_window->window_buffers_unavailable);
|
||||
}
|
||||
|
||||
void
|
||||
xwl_window_buffers_recycle(struct xwl_window *xwl_window)
|
||||
{
|
||||
struct xwl_window_buffer *xwl_window_buffer, *tmp;
|
||||
|
||||
/* Dispose available buffers */
|
||||
xorg_list_for_each_entry_safe(xwl_window_buffer, tmp,
|
||||
&xwl_window->window_buffers_available,
|
||||
link_buffer) {
|
||||
xwl_window_buffer_dispose(xwl_window_buffer);
|
||||
}
|
||||
|
||||
if (xwl_window->window_buffers_timer)
|
||||
TimerCancel(xwl_window->window_buffers_timer);
|
||||
|
||||
/* Mark the others for recycle on release */
|
||||
xorg_list_for_each_entry(xwl_window_buffer,
|
||||
&xwl_window->window_buffers_unavailable,
|
||||
link_buffer) {
|
||||
xwl_window_buffer->recycle_on_release = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
xwl_window_buffers_dispose(struct xwl_window *xwl_window)
|
||||
{
|
||||
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_dispose(xwl_window_buffer);
|
||||
}
|
||||
|
||||
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_dispose(xwl_window_buffer);
|
||||
}
|
||||
|
||||
if (xwl_window->window_buffers_timer) {
|
||||
TimerFree(xwl_window->window_buffers_timer);
|
||||
xwl_window->window_buffers_timer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
PixmapPtr
|
||||
xwl_window_buffers_get_pixmap(struct xwl_window *xwl_window,
|
||||
RegionPtr damage_region)
|
||||
{
|
||||
struct xwl_screen *xwl_screen = xwl_window->xwl_screen;
|
||||
struct xwl_window_buffer *xwl_window_buffer;
|
||||
PixmapPtr window_pixmap;
|
||||
RegionPtr full_damage;
|
||||
|
||||
window_pixmap = (*xwl_screen->screen->GetWindowPixmap) (xwl_window->window);
|
||||
|
||||
#ifdef XWL_HAS_GLAMOR
|
||||
if (!xwl_glamor_needs_n_buffering(xwl_screen))
|
||||
return window_pixmap;
|
||||
#endif /* XWL_HAS_GLAMOR */
|
||||
|
||||
xwl_window_buffer = xwl_window_buffer_get_available(xwl_window);
|
||||
if (!xwl_window_buffer)
|
||||
return window_pixmap;
|
||||
|
||||
xwl_window_buffer_add_damage_region(xwl_window, damage_region);
|
||||
|
||||
full_damage = xwl_window_buffer->damage_region;
|
||||
|
||||
if (xwl_window_buffer->pixmap) {
|
||||
BoxPtr pBox = RegionRects(full_damage);
|
||||
int nBox = RegionNumRects(full_damage);
|
||||
while (nBox--) {
|
||||
if (!copy_pixmap_area(window_pixmap,
|
||||
xwl_window_buffer->pixmap,
|
||||
pBox->x1 + xwl_window->window->borderWidth,
|
||||
pBox->y1 + xwl_window->window->borderWidth,
|
||||
pBox->x2 - pBox->x1,
|
||||
pBox->y2 - pBox->y1))
|
||||
return window_pixmap;
|
||||
|
||||
pBox++;
|
||||
}
|
||||
} else {
|
||||
xwl_window_buffer->pixmap =
|
||||
(*xwl_screen->screen->CreatePixmap) (window_pixmap->drawable.pScreen,
|
||||
window_pixmap->drawable.width,
|
||||
window_pixmap->drawable.height,
|
||||
window_pixmap->drawable.depth,
|
||||
CREATE_PIXMAP_USAGE_BACKING_PIXMAP);
|
||||
|
||||
if (!xwl_window_buffer->pixmap)
|
||||
return window_pixmap;
|
||||
|
||||
if (!copy_pixmap_area(window_pixmap,
|
||||
xwl_window_buffer->pixmap,
|
||||
0, 0,
|
||||
window_pixmap->drawable.width,
|
||||
window_pixmap->drawable.height)) {
|
||||
xwl_window_buffer_recycle(xwl_window_buffer);
|
||||
return window_pixmap;
|
||||
}
|
||||
}
|
||||
|
||||
RegionEmpty(xwl_window_buffer->damage_region);
|
||||
|
||||
/* Hold a reference on the buffer until it's released by the compositor */
|
||||
xwl_window_buffer->refcnt++;
|
||||
xwl_pixmap_set_buffer_release_cb(xwl_window_buffer->pixmap,
|
||||
xwl_window_buffer_release_callback,
|
||||
xwl_window_buffer);
|
||||
|
||||
xorg_list_del(&xwl_window_buffer->link_buffer);
|
||||
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;
|
||||
}
|
|
@ -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 <ofourdan@redhat.com>
|
||||
*/
|
||||
|
||||
#ifndef XWAYLAND_WINDOW_BUFFERS_H
|
||||
#define XWAYLAND_WINDOW_BUFFERS_H
|
||||
|
||||
#include <xwayland-config.h>
|
||||
|
||||
#include "xwayland-types.h"
|
||||
#include "regionstr.h"
|
||||
|
||||
void xwl_window_buffers_init(struct xwl_window *xwl_window);
|
||||
void xwl_window_buffers_recycle(struct xwl_window *xwl_window);
|
||||
void xwl_window_buffers_dispose(struct xwl_window *xwl_window);
|
||||
PixmapPtr xwl_window_buffers_get_pixmap(struct xwl_window *xwl_window,
|
||||
RegionPtr damage_region);
|
||||
|
||||
#endif /* XWAYLAND_WINDOW_BUFFERS_H */
|
|
@ -1,858 +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.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_DIX_CONFIG_H
|
||||
#include <dix-config.h>
|
||||
#endif
|
||||
|
||||
#include <X11/X.h>
|
||||
#include <X11/Xatom.h>
|
||||
|
||||
#include "compositeext.h"
|
||||
#include "compint.h"
|
||||
#include "inputstr.h"
|
||||
#include "propertyst.h"
|
||||
|
||||
#include "xwayland-types.h"
|
||||
#include "xwayland-input.h"
|
||||
#include "xwayland-present.h"
|
||||
#include "xwayland-screen.h"
|
||||
#include "xwayland-window.h"
|
||||
#include "xwayland-window-buffers.h"
|
||||
#include "xwayland-shm.h"
|
||||
|
||||
#include "viewporter-client-protocol.h"
|
||||
#include "xdg-shell-client-protocol.h"
|
||||
|
||||
static DevPrivateKeyRec xwl_window_private_key;
|
||||
static DevPrivateKeyRec xwl_damage_private_key;
|
||||
|
||||
static void
|
||||
xwl_window_set_allow_commits(struct xwl_window *xwl_window, Bool allow,
|
||||
const char *debug_msg)
|
||||
{
|
||||
xwl_window->allow_commits = allow;
|
||||
DebugF("xwayland: win %d allow_commits = %d (%s)\n",
|
||||
xwl_window->window->drawable.id, allow, debug_msg);
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
damage_report(DamagePtr pDamage, RegionPtr pRegion, void *data)
|
||||
{
|
||||
WindowPtr window = data;
|
||||
struct xwl_window *xwl_window = xwl_window_get(window);
|
||||
struct xwl_screen *xwl_screen;
|
||||
|
||||
if (!xwl_window)
|
||||
return;
|
||||
|
||||
xwl_screen = xwl_window->xwl_screen;
|
||||
|
||||
#ifdef GLAMOR_HAS_GBM
|
||||
if (xwl_window->present_flipped) {
|
||||
/* This damage is from a Present flip, which already committed a new
|
||||
* buffer for the surface, so we don't need to do anything in response
|
||||
*/
|
||||
RegionEmpty(DamageRegion(pDamage));
|
||||
xorg_list_del(&xwl_window->link_damage);
|
||||
xwl_window->present_flipped = FALSE;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
xorg_list_add(&xwl_window->link_damage, &xwl_screen->damage_window_list);
|
||||
}
|
||||
|
||||
static void
|
||||
damage_destroy(DamagePtr pDamage, void *data)
|
||||
{
|
||||
}
|
||||
|
||||
static Bool
|
||||
register_damage(WindowPtr window)
|
||||
{
|
||||
DamagePtr damage;
|
||||
|
||||
damage = DamageCreate(damage_report, damage_destroy, DamageReportNonEmpty,
|
||||
FALSE, window->drawable.pScreen, window);
|
||||
if (damage == NULL) {
|
||||
ErrorF("Failed creating damage\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
DamageRegister(&window->drawable, damage);
|
||||
DamageSetReportAfterOp(damage, TRUE);
|
||||
|
||||
dixSetPrivate(&window->devPrivates, &xwl_damage_private_key, damage);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
unregister_damage(WindowPtr window)
|
||||
{
|
||||
DamagePtr damage;
|
||||
|
||||
damage = dixLookupPrivate(&window->devPrivates, &xwl_damage_private_key);
|
||||
if (!damage)
|
||||
return;
|
||||
|
||||
DamageUnregister(damage);
|
||||
DamageDestroy(damage);
|
||||
|
||||
dixSetPrivate(&window->devPrivates, &xwl_damage_private_key, NULL);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static void
|
||||
xwl_window_enable_viewport(struct xwl_window *xwl_window,
|
||||
struct xwl_output *xwl_output,
|
||||
struct xwl_emulated_mode *emulated_mode)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
wp_viewport_set_source(xwl_window->viewport,
|
||||
wl_fixed_from_int(0),
|
||||
wl_fixed_from_int(0),
|
||||
wl_fixed_from_int(emulated_mode->width),
|
||||
wl_fixed_from_int(emulated_mode->height));
|
||||
wp_viewport_set_destination(xwl_window->viewport,
|
||||
xwl_output->width,
|
||||
xwl_output->height);
|
||||
|
||||
xwl_window->scale_x = (float)emulated_mode->width / xwl_output->width;
|
||||
xwl_window->scale_y = (float)emulated_mode->height / xwl_output->height;
|
||||
}
|
||||
|
||||
static Bool
|
||||
window_is_wm_window(WindowPtr window)
|
||||
{
|
||||
struct xwl_screen *xwl_screen = xwl_screen_get(window->drawable.pScreen);
|
||||
|
||||
return CLIENT_ID(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
|
||||
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_resolution_change_emulation(xwl_screen))
|
||||
return FALSE;
|
||||
|
||||
window = window_get_client_toplevel(xwl_window->window);
|
||||
if (!window)
|
||||
return FALSE;
|
||||
|
||||
owner = wClient(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) {
|
||||
|
||||
*emulated_mode_ret = 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->window->overrideRedirect &&
|
||||
emulated_mode && emulated_mode->from_vidmode &&
|
||||
drawable->x == 0 && drawable->y == 0 &&
|
||||
drawable->width == xwl_screen->width &&
|
||||
drawable->height == xwl_screen->height) {
|
||||
|
||||
*emulated_mode_ret = emulated_mode;
|
||||
*xwl_output_ret = xwl_output;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
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(xwl_window, xwl_output, emulated_mode);
|
||||
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_is_wm_window(window))
|
||||
return FALSE;
|
||||
|
||||
/* CSD and override-redirect toplevel windows */
|
||||
if (window_get_damage(window))
|
||||
return TRUE;
|
||||
|
||||
/* Normal toplevel client windows, reparented to a window-manager window */
|
||||
return window->parent && 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->window,
|
||||
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 void
|
||||
send_surface_id_event(struct xwl_window *xwl_window)
|
||||
{
|
||||
static const char atom_name[] = "WL_SURFACE_ID";
|
||||
static Atom type_atom;
|
||||
DeviceIntPtr dev;
|
||||
xEvent e;
|
||||
|
||||
if (type_atom == None)
|
||||
type_atom = MakeAtom(atom_name, strlen(atom_name), TRUE);
|
||||
|
||||
e.u.u.type = ClientMessage;
|
||||
e.u.u.detail = 32;
|
||||
e.u.clientMessage.window = xwl_window->window->drawable.id;
|
||||
e.u.clientMessage.u.l.type = type_atom;
|
||||
e.u.clientMessage.u.l.longs0 =
|
||||
wl_proxy_get_id((struct wl_proxy *) xwl_window->surface);
|
||||
e.u.clientMessage.u.l.longs1 = 0;
|
||||
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
|
||||
xdg_surface_handle_configure(void *data,
|
||||
struct xdg_surface *xdg_surface,
|
||||
uint32_t serial)
|
||||
{
|
||||
xdg_surface_ack_configure(xdg_surface, serial);
|
||||
}
|
||||
|
||||
static const struct xdg_surface_listener xdg_surface_listener = {
|
||||
xdg_surface_handle_configure,
|
||||
};
|
||||
|
||||
static Bool
|
||||
ensure_surface_for_window(WindowPtr window)
|
||||
{
|
||||
ScreenPtr screen = window->drawable.pScreen;
|
||||
struct xwl_screen *xwl_screen;
|
||||
struct xwl_window *xwl_window;
|
||||
struct wl_region *region;
|
||||
WindowPtr toplevel;
|
||||
|
||||
if (xwl_window_from_window(window))
|
||||
return TRUE;
|
||||
|
||||
xwl_screen = xwl_screen_get(screen);
|
||||
|
||||
if (xwl_screen->rootless) {
|
||||
if (window->redirectDraw != RedirectDrawManual)
|
||||
return TRUE;
|
||||
}
|
||||
else {
|
||||
if (window->parent)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
xwl_window = calloc(1, sizeof *xwl_window);
|
||||
if (xwl_window == NULL)
|
||||
return FALSE;
|
||||
|
||||
xwl_window->xwl_screen = xwl_screen;
|
||||
xwl_window->window = window;
|
||||
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->rootless) {
|
||||
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;
|
||||
}
|
||||
|
||||
xdg_surface_add_listener(xwl_window->xdg_surface,
|
||||
&xdg_surface_listener, xwl_window);
|
||||
|
||||
xdg_surface_get_toplevel(xwl_window->xdg_surface);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
wl_display_flush(xwl_screen->display);
|
||||
|
||||
send_surface_id_event(xwl_window);
|
||||
|
||||
wl_surface_set_user_data(xwl_window->surface, 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);
|
||||
|
||||
#ifdef GLAMOR_HAS_GBM
|
||||
xorg_list_init(&xwl_window->frame_callback_list);
|
||||
#endif
|
||||
|
||||
xwl_window_buffers_init(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 (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);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
||||
err_surf:
|
||||
if (xwl_window->xdg_surface)
|
||||
xdg_surface_destroy(xwl_window->xdg_surface);
|
||||
wl_surface_destroy(xwl_window->surface);
|
||||
err:
|
||||
free(xwl_window);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Bool
|
||||
xwl_realize_window(WindowPtr window)
|
||||
{
|
||||
ScreenPtr screen = window->drawable.pScreen;
|
||||
struct xwl_screen *xwl_screen;
|
||||
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 && !window->parent) {
|
||||
BoxRec box = { 0, 0, xwl_screen->width, xwl_screen->height };
|
||||
|
||||
RegionReset(&window->winSize, &box);
|
||||
RegionNull(&window->clipList);
|
||||
RegionNull(&window->borderClip);
|
||||
}
|
||||
|
||||
if (xwl_screen->rootless ?
|
||||
(window->drawable.class == InputOutput &&
|
||||
window->parent == window->drawable.pScreen->root) :
|
||||
!window->parent) {
|
||||
if (!register_damage(window))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return ensure_surface_for_window(window);
|
||||
}
|
||||
|
||||
Bool
|
||||
xwl_unrealize_window(WindowPtr window)
|
||||
{
|
||||
ScreenPtr screen = window->drawable.pScreen;
|
||||
struct xwl_screen *xwl_screen;
|
||||
struct xwl_window *xwl_window;
|
||||
struct xwl_seat *xwl_seat;
|
||||
Bool ret;
|
||||
|
||||
xwl_screen = xwl_screen_get(screen);
|
||||
|
||||
xorg_list_for_each_entry(xwl_seat, &xwl_screen->seat_list, link) {
|
||||
if (xwl_seat->focus_window && xwl_seat->focus_window->window == window)
|
||||
xwl_seat->focus_window = NULL;
|
||||
if (xwl_seat->tablet_focus_window && xwl_seat->tablet_focus_window->window == window)
|
||||
xwl_seat->tablet_focus_window = NULL;
|
||||
if (xwl_seat->last_xwindow == window)
|
||||
xwl_seat->last_xwindow = NullWindow;
|
||||
if (xwl_seat->cursor_confinement_window &&
|
||||
xwl_seat->cursor_confinement_window->window == window)
|
||||
xwl_seat_unconfine_pointer(xwl_seat);
|
||||
if (xwl_seat->pointer_warp_emulator &&
|
||||
xwl_seat->pointer_warp_emulator->locked_window &&
|
||||
xwl_seat->pointer_warp_emulator->locked_window->window == window)
|
||||
xwl_seat_destroy_pointer_warp_emulator(xwl_seat);
|
||||
xwl_seat_clear_touch(xwl_seat, window);
|
||||
}
|
||||
|
||||
compUnredirectWindow(serverClient, window, CompositeRedirectManual);
|
||||
|
||||
screen->UnrealizeWindow = xwl_screen->UnrealizeWindow;
|
||||
ret = (*screen->UnrealizeWindow) (window);
|
||||
xwl_screen->UnrealizeWindow = screen->UnrealizeWindow;
|
||||
screen->UnrealizeWindow = xwl_unrealize_window;
|
||||
|
||||
xwl_window = xwl_window_get(window);
|
||||
if (!xwl_window)
|
||||
return ret;
|
||||
|
||||
if (xwl_window_has_viewport_enabled(xwl_window))
|
||||
xwl_window_disable_viewport(xwl_window);
|
||||
|
||||
wl_surface_destroy(xwl_window->surface);
|
||||
xorg_list_del(&xwl_window->link_damage);
|
||||
xorg_list_del(&xwl_window->link_window);
|
||||
unregister_damage(window);
|
||||
|
||||
xwl_window_buffers_dispose(xwl_window);
|
||||
|
||||
if (xwl_window->frame_callback)
|
||||
wl_callback_destroy(xwl_window->frame_callback);
|
||||
|
||||
#ifdef GLAMOR_HAS_GBM
|
||||
if (xwl_screen->present) {
|
||||
struct xwl_present_window *xwl_present_window, *tmp;
|
||||
|
||||
xorg_list_for_each_entry_safe(xwl_present_window, tmp,
|
||||
&xwl_window->frame_callback_list,
|
||||
frame_callback_list) {
|
||||
xwl_present_unrealize_window(xwl_present_window);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
free(xwl_window);
|
||||
dixSetPrivate(&window->devPrivates, &xwl_window_private_key, NULL);
|
||||
|
||||
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;
|
||||
|
||||
ensure_surface_for_window(window);
|
||||
|
||||
if (old_pixmap->drawable.width == pixmap->drawable.width &&
|
||||
old_pixmap->drawable.height == pixmap->drawable.height)
|
||||
return;
|
||||
|
||||
xwl_window = xwl_window_get(window);
|
||||
if (xwl_window)
|
||||
xwl_window_buffers_recycle(xwl_window);
|
||||
}
|
||||
|
||||
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 = CLIENT_ID(others->resource);
|
||||
}
|
||||
|
||||
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 && (xwl_window_get(window) || xwl_window_is_toplevel(window)))
|
||||
xwl_window_check_resolution_change_emulation(xwl_window);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
#ifdef GLAMOR_HAS_GBM
|
||||
if (xwl_window->xwl_screen->present) {
|
||||
struct xwl_present_window *xwl_present_window, *tmp;
|
||||
|
||||
xorg_list_for_each_entry_safe(xwl_present_window, tmp,
|
||||
&xwl_window->frame_callback_list,
|
||||
frame_callback_list) {
|
||||
xwl_present_frame_callback(xwl_present_window);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
Bool
|
||||
xwl_destroy_window(WindowPtr window)
|
||||
{
|
||||
ScreenPtr screen = window->drawable.pScreen;
|
||||
struct xwl_screen *xwl_screen = xwl_screen_get(screen);
|
||||
Bool ret;
|
||||
|
||||
#ifdef GLAMOR_HAS_GBM
|
||||
if (xwl_screen->present)
|
||||
xwl_present_cleanup(window);
|
||||
#endif
|
||||
|
||||
screen->DestroyWindow = xwl_screen->DestroyWindow;
|
||||
|
||||
if (screen->DestroyWindow)
|
||||
ret = screen->DestroyWindow (window);
|
||||
else
|
||||
ret = TRUE;
|
||||
|
||||
xwl_screen->DestroyWindow = screen->DestroyWindow;
|
||||
screen->DestroyWindow = xwl_destroy_window;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
xwl_window_post_damage(struct xwl_window *xwl_window)
|
||||
{
|
||||
struct xwl_screen *xwl_screen = xwl_window->xwl_screen;
|
||||
RegionPtr region;
|
||||
BoxPtr box;
|
||||
struct wl_buffer *buffer;
|
||||
PixmapPtr pixmap;
|
||||
int i;
|
||||
|
||||
assert(!xwl_window->frame_callback);
|
||||
|
||||
region = DamageRegion(window_get_damage(xwl_window->window));
|
||||
pixmap = xwl_window_buffers_get_pixmap(xwl_window, region);
|
||||
|
||||
#ifdef XWL_HAS_GLAMOR
|
||||
if (xwl_screen->glamor)
|
||||
buffer = xwl_glamor_pixmap_get_wl_buffer(pixmap);
|
||||
else
|
||||
#endif
|
||||
buffer = xwl_shm_pixmap_get_wl_buffer(pixmap);
|
||||
|
||||
if (!buffer) {
|
||||
ErrorF("Error getting buffer\n");
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef XWL_HAS_GLAMOR
|
||||
if (xwl_screen->glamor) {
|
||||
if (!xwl_glamor_post_damage(xwl_window, pixmap, region)) {
|
||||
ErrorF("glamor: Failed to post damage\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
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.
|
||||
*/
|
||||
if (RegionNumRects(region) > 256) {
|
||||
box = RegionExtents(region);
|
||||
xwl_surface_damage(xwl_screen, xwl_window->surface,
|
||||
box->x1 + xwl_window->window->borderWidth,
|
||||
box->y1 + xwl_window->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 + xwl_window->window->borderWidth,
|
||||
box->y1 + xwl_window->window->borderWidth,
|
||||
box->x2 - box->x1, box->y2 - box->y1);
|
||||
}
|
||||
}
|
||||
|
||||
xwl_window_create_frame_callback(xwl_window);
|
||||
DamageEmpty(window_get_damage(xwl_window->window));
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
|
@ -1,86 +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 <xwayland-config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <X11/X.h>
|
||||
#include <dix.h>
|
||||
#include <propertyst.h>
|
||||
#include <validate.h>
|
||||
|
||||
#include "xwayland-types.h"
|
||||
|
||||
struct xwl_window {
|
||||
struct xwl_screen *xwl_screen;
|
||||
struct wl_surface *surface;
|
||||
struct wp_viewport *viewport;
|
||||
float scale_x, scale_y;
|
||||
struct xdg_surface *xdg_surface;
|
||||
WindowPtr window;
|
||||
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;
|
||||
#ifdef GLAMOR_HAS_GBM
|
||||
struct xorg_list frame_callback_list;
|
||||
Bool present_flipped;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct xwl_window *xwl_window_get(WindowPtr window);
|
||||
struct xwl_window *xwl_window_from_window(WindowPtr window);
|
||||
|
||||
void xwl_window_update_property(struct xwl_window *xwl_window,
|
||||
PropertyStateRec *propstate);
|
||||
Bool xwl_window_has_viewport_enabled(struct xwl_window *xwl_window);
|
||||
Bool xwl_window_is_toplevel(WindowPtr window);
|
||||
void xwl_window_check_resolution_change_emulation(struct xwl_window *xwl_window);
|
||||
|
||||
void xwl_window_set_window_pixmap(WindowPtr window, PixmapPtr pixmap);
|
||||
Bool xwl_realize_window(WindowPtr window);
|
||||
Bool xwl_unrealize_window(WindowPtr window);
|
||||
Bool xwl_change_window_attributes(WindowPtr window, unsigned long mask);
|
||||
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);
|
||||
Bool xwl_destroy_window(WindowPtr window);
|
||||
void xwl_window_post_damage(struct xwl_window *xwl_window);
|
||||
void xwl_window_create_frame_callback(struct xwl_window *xwl_window);
|
||||
Bool xwl_window_init(void);
|
||||
|
||||
#endif /* XWAYLAND_WINDOW_H */
|
|
@ -1,294 +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 <xwayland-config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <X11/Xatom.h>
|
||||
#include <selection.h>
|
||||
#include <micmap.h>
|
||||
#include <misyncshm.h>
|
||||
#include <compositeext.h>
|
||||
#include <compint.h>
|
||||
#include <glx_extinit.h>
|
||||
#include <os.h>
|
||||
#include <xserver_poll.h>
|
||||
#include <propertyst.h>
|
||||
#include <version-config.h>
|
||||
|
||||
#include "xwayland-screen.h"
|
||||
#include "xwayland-vidmode.h"
|
||||
|
||||
#ifdef XF86VIDMODE
|
||||
#include <X11/extensions/xf86vmproto.h>
|
||||
extern _X_EXPORT Bool noXFree86VidModeExtension;
|
||||
#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("-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");
|
||||
#ifdef XWL_HAS_EGLSTREAM
|
||||
ErrorF("-eglstream use eglstream backend for nvidia GPUs\n");
|
||||
#endif
|
||||
ErrorF("-shm use shared memory for passing buffers\n");
|
||||
ErrorF("-verbose [n] verbose startup messages\n");
|
||||
ErrorF("-version show the server version and exit\n");
|
||||
ErrorF("-noTouchPointerEmulation disable touch pointer emulation\n");
|
||||
}
|
||||
|
||||
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
|
||||
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;
|
||||
}
|
||||
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;
|
||||
LogSetParameter(XLOG_VERBOSITY, verbosity);
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
LogSetParameter(XLOG_VERBOSITY, ++verbosity);
|
||||
return 1;
|
||||
}
|
||||
else if (strcmp(argv[i], "-eglstream") == 0) {
|
||||
return 1;
|
||||
}
|
||||
else if (strcmp(argv[i], "-version") == 0) {
|
||||
xwl_show_version();
|
||||
exit(0);
|
||||
}
|
||||
else if (strcmp(argv[i], "-noTouchPointerEmulation") == 0) {
|
||||
touchEmulatePointer = FALSE;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
_X_NORETURN
|
||||
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);
|
||||
FatalError("%s", msg);
|
||||
}
|
||||
|
||||
static const ExtensionModule xwayland_extensions[] = {
|
||||
#ifdef XF86VIDMODE
|
||||
{ xwlVidModeExtensionInit, XF86VIDMODENAME, &noXFree86VidModeExtension },
|
||||
#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)
|
||||
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();
|
||||
}
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
|
||||
Name: Xwayland
|
||||
Description: X Server for Wayland
|
||||
Version: @PACKAGE_VERSION@
|
||||
xwayland=@xwayland_path@/Xwayland
|
||||
have_glamor=@have_glamor@
|
||||
have_eglstream=@have_eglstream@
|
||||
have_initfd=true
|
||||
have_listenfd=true
|
||||
have_verbose=true
|
||||
have_terminate_delay=true
|
||||
have_no_touch_pointer_emulation=true
|
|
@ -81,7 +81,6 @@ EXTRA_DIST = \
|
|||
vidmodestr.h \
|
||||
xorg-config.h.meson.in \
|
||||
xorg-server.h.meson.in \
|
||||
xwayland-config.h.meson.in \
|
||||
xwin-config.h.meson.in \
|
||||
xsha1.h
|
||||
|
||||
|
|
|
@ -412,14 +412,6 @@ configure_file(output : 'xwin-config.h',
|
|||
input : 'xwin-config.h.meson.in',
|
||||
configuration : xwin_data)
|
||||
|
||||
xwayland_data = configuration_data()
|
||||
xwayland_data.set('XWL_HAS_GLAMOR', build_glamor and (gbm_dep.found() or build_eglstream) ? '1' : false)
|
||||
xwayland_data.set('XWL_HAS_EGLSTREAM', build_eglstream ? '1' : false)
|
||||
|
||||
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
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
/* xwayland-config.h.in: not at all generated. */
|
||||
#ifndef _XWAYLAND_CONFIG_H_
|
||||
#define _XWAYLAND_CONFIG_H_
|
||||
|
||||
#include <dix-config.h>
|
||||
|
||||
/* Build glamor support for Xwayland */
|
||||
#undef XWL_HAS_GLAMOR
|
||||
|
||||
/* Build eglstream support for Xwayland */
|
||||
#undef XWL_HAS_EGLSTREAM
|
||||
|
||||
#endif /* _XWAYLAND_CONFIG_H_ */
|
|
@ -1,11 +0,0 @@
|
|||
/* xwayland-config.h.meson.in: not at all generated */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <dix-config.h>
|
||||
|
||||
/* Build glamor support for Xwayland */
|
||||
#mesondefine XWL_HAS_GLAMOR
|
||||
|
||||
/* Build eglstream support for Xwayland */
|
||||
#mesondefine XWL_HAS_EGLSTREAM
|
50
meson.build
50
meson.build
|
@ -196,39 +196,6 @@ endif
|
|||
xorgsdkdir = join_paths(get_option('prefix'), get_option('includedir'), 'xorg')
|
||||
libxcvt_dep = dependency('libxcvt', required: build_xorg)
|
||||
|
||||
build_xwayland = false
|
||||
if (host_machine.system() != 'darwin' and
|
||||
host_machine.system() != 'windows')
|
||||
if 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', required: xwayland_required),
|
||||
]
|
||||
|
||||
if build_glamor
|
||||
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
|
||||
endif
|
||||
|
||||
build_xnest = false
|
||||
if (host_machine.system() != 'darwin' and
|
||||
host_machine.system() != 'windows')
|
||||
|
@ -326,7 +293,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
|
||||
|
@ -338,21 +305,6 @@ if build_glamor
|
|||
epoxy_dep = dependency('epoxy', required: false)
|
||||
endif
|
||||
|
||||
eglstream_option = get_option('xwayland_eglstream')
|
||||
if build_xwayland and build_glamor
|
||||
eglstream_dep = dependency('wayland-eglstream-protocols', required:false)
|
||||
if eglstream_option == 'auto'
|
||||
build_eglstream = eglstream_dep.found()
|
||||
else
|
||||
build_eglstream = eglstream_option == 'true'
|
||||
if build_eglstream and not eglstream_dep.found()
|
||||
error('glamor EGLStream support requested, but wayland-eglstream-protocols not found')
|
||||
endif
|
||||
endif
|
||||
else
|
||||
build_eglstream = false
|
||||
endif
|
||||
|
||||
# Lots of sha1 options, because Linux is about choice :)
|
||||
|
||||
# The idea behind the ordering here is that we should first prefer system
|
||||
|
|
|
@ -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: 'auto',
|
||||
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_eglstream', type: 'combo', choices: ['true', 'false', 'auto'],
|
||||
value: 'auto', description: 'Enable EGLStream support for glamor 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,
|
||||
|
@ -128,8 +124,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('docs', type: 'combo', choices: ['true', 'false', 'auto'], value: 'auto',
|
||||
description: 'Build documentation')
|
||||
option('devel-docs', type: 'combo', choices: ['true', 'false', 'auto'], value: 'auto',
|
||||
|
|
|
@ -10,7 +10,7 @@ hdrs_miext_sync = [
|
|||
'misyncstr.h',
|
||||
]
|
||||
|
||||
if build_dri3 or build_xwayland
|
||||
if build_dri3
|
||||
srcs_miext_sync += 'misyncshm.c'
|
||||
endif
|
||||
|
||||
|
|
|
@ -25,14 +25,9 @@ endif
|
|||
endif
|
||||
endif
|
||||
|
||||
if XWAYLAND
|
||||
XWAYLAND_TESTS = scripts/xwayland-piglit.sh
|
||||
endif
|
||||
|
||||
SCRIPT_TESTS = \
|
||||
$(XVFB_TESTS) \
|
||||
$(XEPHYR_GLAMOR_TESTS) \
|
||||
$(XWAYLAND_TESTS) \
|
||||
$(NULL)
|
||||
|
||||
TESTS = tests \
|
||||
|
@ -193,7 +188,6 @@ EXTRA_DIST = \
|
|||
scripts/xvfb-piglit.sh \
|
||||
scripts/xephyr-glamor-piglit.sh \
|
||||
scripts/xinit-piglit-session.sh \
|
||||
scripts/xwayland-piglit.sh \
|
||||
scripts/run-piglit.sh \
|
||||
$(NULL)
|
||||
|
||||
|
|
|
@ -100,19 +100,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')
|
||||
|
|
|
@ -1,43 +0,0 @@
|
|||
#!/bin/sh -e
|
||||
|
||||
# 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-$$
|
||||
|
||||
# Wait for weston to initialize before starting Xwayland
|
||||
timeout --preserve-status 60s bash -c 'while ! weston-info &>/dev/null; do sleep 1; done'
|
||||
|
||||
# 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"
|
||||
|
||||
export PIGLIT_ARGS
|
||||
|
||||
$XSERVER_DIR/test/scripts/run-piglit.sh
|
||||
PIGLIT_STATUS=$?
|
||||
|
||||
kill $WESTON_PID
|
||||
exit $PIGLIT_STATUS
|
Loading…
Reference in New Issue