Drop XWayland DDX

This commit is contained in:
Povilas Kanapickas 2021-09-15 21:49:17 +03:00
parent 72c5d153c9
commit 4ee66f574a
52 changed files with 6 additions and 14017 deletions

View File

@ -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 \

View File

@ -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

View File

@ -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

View File

@ -18,10 +18,6 @@ if build_xquartz
subdir('xquartz')
endif
if build_xwayland
subdir('xwayland')
endif
if build_xwin
subdir('xwin')
endif

View File

@ -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

View File

@ -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 < $< > $@

View File

@ -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>

View File

@ -1,2 +0,0 @@
include $(top_srcdir)/manpages.am
appman_PRE = Xwayland.man

View File

@ -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@)

View File

@ -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)

View File

@ -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);
}

View File

@ -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 */

View File

@ -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);
}

View File

@ -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

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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 */

View File

@ -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
};

View File

@ -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

View File

@ -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 */

View File

@ -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);
}

View File

@ -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 */

View File

@ -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;
}

View File

@ -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 */

View File

@ -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;
}

View File

@ -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 */

View File

@ -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,
&registry_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;
}

View File

@ -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 */

View File

@ -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;
}

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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;
}

View File

@ -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 */

View File

@ -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;
}

View File

@ -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 */

View File

@ -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();
}
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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_ */

View File

@ -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

View File

@ -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

View File

@ -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',

View File

@ -10,7 +10,7 @@ hdrs_miext_sync = [
'misyncstr.h',
]
if build_dri3 or build_xwayland
if build_dri3
srcs_miext_sync += 'misyncshm.c'
endif

View File

@ -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)

View File

@ -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')

View File

@ -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