summaryrefslogtreecommitdiff
path: root/xserver/hw/xwayland
diff options
context:
space:
mode:
authorMatthieu Herrb <matthieu@cvs.openbsd.org>2019-07-27 07:57:27 +0000
committerMatthieu Herrb <matthieu@cvs.openbsd.org>2019-07-27 07:57:27 +0000
commitd4a0bed4b91da9de86c311c7fef9a8aa9a6f500c (patch)
treea1b439049dee87bc951e190db93f5bbe8b43b0b5 /xserver/hw/xwayland
parentb6bc775539a31f663f9e22ce3ccaf0aa96adf3b6 (diff)
Update to xserver 1.20.5. Tested by jsg@
Diffstat (limited to 'xserver/hw/xwayland')
-rw-r--r--xserver/hw/xwayland/Makefile.am65
-rw-r--r--xserver/hw/xwayland/Makefile.in277
-rw-r--r--xserver/hw/xwayland/xwayland-cursor.c95
-rw-r--r--xserver/hw/xwayland/xwayland-glamor-eglstream.c932
-rw-r--r--xserver/hw/xwayland/xwayland-glamor-gbm.c1035
-rw-r--r--xserver/hw/xwayland/xwayland-glamor-xv.c2
-rw-r--r--xserver/hw/xwayland/xwayland-glamor.c582
-rw-r--r--xserver/hw/xwayland/xwayland-input.c1305
-rw-r--r--xserver/hw/xwayland/xwayland-output.c147
-rw-r--r--xserver/hw/xwayland/xwayland-present.c578
-rw-r--r--xserver/hw/xwayland/xwayland-shm.c2
-rw-r--r--xserver/hw/xwayland/xwayland.c343
-rw-r--r--xserver/hw/xwayland/xwayland.h280
13 files changed, 5000 insertions, 643 deletions
diff --git a/xserver/hw/xwayland/Makefile.am b/xserver/hw/xwayland/Makefile.am
index a3c9fce48..bc1cb8506 100644
--- a/xserver/hw/xwayland/Makefile.am
+++ b/xserver/hw/xwayland/Makefile.am
@@ -18,13 +18,13 @@ Xwayland_SOURCES = \
xwayland-cvt.c \
xwayland-vidmode.c \
xwayland.h \
- $(top_srcdir)/Xext/dpmsstubs.c \
$(top_srcdir)/Xi/stubs.c \
$(top_srcdir)/mi/miinitext.c
Xwayland_LDADD = \
$(glamor_lib) \
$(XWAYLAND_LIBS) \
+ $(top_builddir)/glx/libglxvnd.la \
$(XWAYLAND_SYS_LIBS) \
$(top_builddir)/Xext/libXvidmode.la \
$(XSERVER_SYS_LIBS)
@@ -34,12 +34,19 @@ Xwayland_built_sources =
if GLAMOR_EGL
Xwayland_SOURCES += \
- xwayland-glamor.c
+ 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
@@ -56,31 +63,75 @@ 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
+ 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
+
+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)
EXTRA_DIST = 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) code < $< > $@
+ $(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) code < $< > $@
+ $(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 < $< > $@
-%-protocol.c : %.xml
+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 < $< > $@
+
+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 < $< > $@
diff --git a/xserver/hw/xwayland/Makefile.in b/xserver/hw/xwayland/Makefile.in
index 7b9a37e89..5a110e736 100644
--- a/xserver/hw/xwayland/Makefile.in
+++ b/xserver/hw/xwayland/Makefile.in
@@ -52,17 +52,30 @@ build_triplet = @build@
host_triplet = @host@
bin_PROGRAMS = Xwayland$(EXEEXT)
@GLAMOR_EGL_TRUE@am__append_1 = \
-@GLAMOR_EGL_TRUE@ xwayland-glamor.c
+@GLAMOR_EGL_TRUE@ xwayland-glamor.c \
+@GLAMOR_EGL_TRUE@ xwayland-glamor-gbm.c \
+@GLAMOR_EGL_TRUE@ xwayland-present.c
@GLAMOR_EGL_TRUE@@XV_TRUE@am__append_2 = \
@GLAMOR_EGL_TRUE@@XV_TRUE@ xwayland-glamor-xv.c
-@GLAMOR_EGL_TRUE@am__append_3 = $(glamor_built_sources)
-@GLAMOR_EGL_TRUE@am__append_4 = $(GLAMOR_LIBS) $(GBM_LIBS) -lEGL -lGL
+@GLAMOR_EGL_TRUE@@XWAYLAND_EGLSTREAM_TRUE@am__append_3 = \
+@GLAMOR_EGL_TRUE@@XWAYLAND_EGLSTREAM_TRUE@ xwayland-glamor-eglstream.c
+
+@GLAMOR_EGL_TRUE@am__append_4 = $(glamor_built_sources)
+@GLAMOR_EGL_TRUE@am__append_5 = $(GLAMOR_LIBS) $(GBM_LIBS) -lEGL -lGL
@GLAMOR_EGL_FALSE@Xwayland_DEPENDENCIES = $(glamor_lib) \
-@GLAMOR_EGL_FALSE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+@GLAMOR_EGL_FALSE@ $(am__DEPENDENCIES_1) \
+@GLAMOR_EGL_FALSE@ $(top_builddir)/glx/libglxvnd.la \
+@GLAMOR_EGL_FALSE@ $(am__DEPENDENCIES_1) \
@GLAMOR_EGL_FALSE@ $(top_builddir)/Xext/libXvidmode.la \
@GLAMOR_EGL_FALSE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2)
+@XWAYLAND_EGLSTREAM_TRUE@am__append_6 = \
+@XWAYLAND_EGLSTREAM_TRUE@ wayland-eglstream-client-protocol.h \
+@XWAYLAND_EGLSTREAM_TRUE@ wayland-eglstream-protocol.c \
+@XWAYLAND_EGLSTREAM_TRUE@ wayland-eglstream-controller-client-protocol.h \
+@XWAYLAND_EGLSTREAM_TRUE@ wayland-eglstream-controller-protocol.c
+
subdir = hw/xwayland
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
$(top_srcdir)/depcomp
@@ -81,7 +94,7 @@ CONFIG_HEADER = $(top_builddir)/include/do-not-use-config.h \
$(top_builddir)/include/xorg-config.h \
$(top_builddir)/include/xkb-config.h \
$(top_builddir)/include/xwin-config.h \
- $(top_builddir)/include/kdrive-config.h \
+ $(top_builddir)/include/xwayland-config.h \
$(top_builddir)/include/version-config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
@@ -90,26 +103,36 @@ PROGRAMS = $(bin_PROGRAMS)
am__Xwayland_SOURCES_DIST = xwayland.c xwayland-input.c \
xwayland-cursor.c xwayland-shm.c xwayland-output.c \
xwayland-cvt.c xwayland-vidmode.c xwayland.h \
- $(top_srcdir)/Xext/dpmsstubs.c $(top_srcdir)/Xi/stubs.c \
- $(top_srcdir)/mi/miinitext.c xwayland-glamor.c \
- xwayland-glamor-xv.c
-@GLAMOR_EGL_TRUE@am__objects_1 = Xwayland-xwayland-glamor.$(OBJEXT)
+ $(top_srcdir)/Xi/stubs.c $(top_srcdir)/mi/miinitext.c \
+ xwayland-glamor.c xwayland-glamor-gbm.c xwayland-present.c \
+ xwayland-glamor-xv.c xwayland-glamor-eglstream.c
+@GLAMOR_EGL_TRUE@am__objects_1 = Xwayland-xwayland-glamor.$(OBJEXT) \
+@GLAMOR_EGL_TRUE@ Xwayland-xwayland-glamor-gbm.$(OBJEXT) \
+@GLAMOR_EGL_TRUE@ Xwayland-xwayland-present.$(OBJEXT)
@GLAMOR_EGL_TRUE@@XV_TRUE@am__objects_2 = Xwayland-xwayland-glamor-xv.$(OBJEXT)
+@GLAMOR_EGL_TRUE@@XWAYLAND_EGLSTREAM_TRUE@am__objects_3 = Xwayland-xwayland-glamor-eglstream.$(OBJEXT)
am_Xwayland_OBJECTS = Xwayland-xwayland.$(OBJEXT) \
Xwayland-xwayland-input.$(OBJEXT) \
Xwayland-xwayland-cursor.$(OBJEXT) \
Xwayland-xwayland-shm.$(OBJEXT) \
Xwayland-xwayland-output.$(OBJEXT) \
Xwayland-xwayland-cvt.$(OBJEXT) \
- Xwayland-xwayland-vidmode.$(OBJEXT) \
- Xwayland-dpmsstubs.$(OBJEXT) Xwayland-stubs.$(OBJEXT) \
- Xwayland-miinitext.$(OBJEXT) $(am__objects_1) $(am__objects_2)
-@GLAMOR_EGL_TRUE@am__objects_3 = Xwayland-drm-protocol.$(OBJEXT)
-@GLAMOR_EGL_TRUE@am__objects_4 = $(am__objects_3)
-am__objects_5 = $(am__objects_4) \
+ Xwayland-xwayland-vidmode.$(OBJEXT) Xwayland-stubs.$(OBJEXT) \
+ Xwayland-miinitext.$(OBJEXT) $(am__objects_1) $(am__objects_2) \
+ $(am__objects_3)
+@GLAMOR_EGL_TRUE@am__objects_4 = Xwayland-drm-protocol.$(OBJEXT)
+@GLAMOR_EGL_TRUE@am__objects_5 = $(am__objects_4)
+@XWAYLAND_EGLSTREAM_TRUE@am__objects_6 = Xwayland-wayland-eglstream-protocol.$(OBJEXT) \
+@XWAYLAND_EGLSTREAM_TRUE@ Xwayland-wayland-eglstream-controller-protocol.$(OBJEXT)
+am__objects_7 = $(am__objects_5) \
Xwayland-relative-pointer-unstable-v1-protocol.$(OBJEXT) \
- Xwayland-pointer-constraints-unstable-v1-protocol.$(OBJEXT)
-nodist_Xwayland_OBJECTS = $(am__objects_5)
+ Xwayland-pointer-constraints-unstable-v1-protocol.$(OBJEXT) \
+ Xwayland-tablet-unstable-v2-protocol.$(OBJEXT) \
+ Xwayland-xwayland-keyboard-grab-unstable-v1-protocol.$(OBJEXT) \
+ Xwayland-xdg-output-unstable-v1-protocol.$(OBJEXT) \
+ Xwayland-linux-dmabuf-unstable-v1-protocol.$(OBJEXT) \
+ $(am__objects_6)
+nodist_Xwayland_OBJECTS = $(am__objects_7)
Xwayland_OBJECTS = $(am_Xwayland_OBJECTS) $(nodist_Xwayland_OBJECTS)
am__DEPENDENCIES_1 =
@GLAMOR_EGL_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) \
@@ -348,6 +371,7 @@ RANLIB = @RANLIB@
RAWCPP = @RAWCPP@
RAWCPPFLAGS = @RAWCPPFLAGS@
RELEASE_DATE = @RELEASE_DATE@
+SCANNER_ARG = @SCANNER_ARG@
SDK_REQUIRED_MODULES = @SDK_REQUIRED_MODULES@
SED = @SED@
SELINUX_CFLAGS = @SELINUX_CFLAGS@
@@ -366,15 +390,18 @@ SYSCONFDIR = @SYSCONFDIR@
SYSTEMD_DAEMON_CFLAGS = @SYSTEMD_DAEMON_CFLAGS@
SYSTEMD_DAEMON_LIBS = @SYSTEMD_DAEMON_LIBS@
TRADITIONALCPPFLAGS = @TRADITIONALCPPFLAGS@
-TSLIB_CFLAGS = @TSLIB_CFLAGS@
-TSLIB_LIBS = @TSLIB_LIBS@
UDEV_CFLAGS = @UDEV_CFLAGS@
UDEV_LIBS = @UDEV_LIBS@
UTILS_SYS_LIBS = @UTILS_SYS_LIBS@
VENDOR_NAME_SHORT = @VENDOR_NAME_SHORT@
VERSION = @VERSION@
+WAYLAND_EGLSTREAM_CFLAGS = @WAYLAND_EGLSTREAM_CFLAGS@
+WAYLAND_EGLSTREAM_DATADIR = @WAYLAND_EGLSTREAM_DATADIR@
+WAYLAND_EGLSTREAM_LIBS = @WAYLAND_EGLSTREAM_LIBS@
WAYLAND_PROTOCOLS_DATADIR = @WAYLAND_PROTOCOLS_DATADIR@
WAYLAND_SCANNER = @WAYLAND_SCANNER@
+WAYLAND_SCANNER_CFLAGS = @WAYLAND_SCANNER_CFLAGS@
+WAYLAND_SCANNER_LIBS = @WAYLAND_SCANNER_LIBS@
WINDOWSDRI_CFLAGS = @WINDOWSDRI_CFLAGS@
WINDOWSDRI_LIBS = @WINDOWSDRI_LIBS@
WINDOWSWM_CFLAGS = @WINDOWSWM_CFLAGS@
@@ -382,6 +409,8 @@ WINDOWSWM_LIBS = @WINDOWSWM_LIBS@
WINDRES = @WINDRES@
X11EXAMPLES_DEP_CFLAGS = @X11EXAMPLES_DEP_CFLAGS@
X11EXAMPLES_DEP_LIBS = @X11EXAMPLES_DEP_LIBS@
+XCONFIGDIR = @XCONFIGDIR@
+XCONFIGFILE = @XCONFIGFILE@
XDMCP_CFLAGS = @XDMCP_CFLAGS@
XDMCP_LIBS = @XDMCP_LIBS@
XDMXCONFIG_DEP_CFLAGS = @XDMXCONFIG_DEP_CFLAGS@
@@ -453,8 +482,6 @@ XWIN_SERVER_NAME = @XWIN_SERVER_NAME@
XWIN_SYS_LIBS = @XWIN_SYS_LIBS@
YACC = @YACC@
YFLAGS = @YFLAGS@
-__XCONFIGDIR__ = @__XCONFIGDIR__@
-__XCONFIGFILE__ = @__XCONFIGFILE__@
abi_ansic = @abi_ansic@
abi_extension = @abi_extension@
abi_videodrv = @abi_videodrv@
@@ -530,18 +557,27 @@ Xwayland_CFLAGS = \
Xwayland_SOURCES = xwayland.c xwayland-input.c xwayland-cursor.c \
xwayland-shm.c xwayland-output.c xwayland-cvt.c \
- xwayland-vidmode.c xwayland.h $(top_srcdir)/Xext/dpmsstubs.c \
- $(top_srcdir)/Xi/stubs.c $(top_srcdir)/mi/miinitext.c \
- $(am__append_1) $(am__append_2)
-Xwayland_LDADD = $(glamor_lib) $(XWAYLAND_LIBS) $(XWAYLAND_SYS_LIBS) \
+ xwayland-vidmode.c xwayland.h $(top_srcdir)/Xi/stubs.c \
+ $(top_srcdir)/mi/miinitext.c $(am__append_1) $(am__append_2) \
+ $(am__append_3)
+Xwayland_LDADD = $(glamor_lib) $(XWAYLAND_LIBS) \
+ $(top_builddir)/glx/libglxvnd.la $(XWAYLAND_SYS_LIBS) \
$(top_builddir)/Xext/libXvidmode.la $(XSERVER_SYS_LIBS) \
- $(am__append_4)
+ $(am__append_5)
Xwayland_LDFLAGS = $(LD_EXPORT_SYMBOLS_FLAG)
-Xwayland_built_sources = $(am__append_3) \
+Xwayland_built_sources = $(am__append_4) \
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
+ 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 $(am__append_6)
@GLAMOR_EGL_TRUE@glamor_built_sources = \
@GLAMOR_EGL_TRUE@ drm-client-protocol.h \
@GLAMOR_EGL_TRUE@ drm-protocol.c
@@ -641,18 +677,26 @@ mostlyclean-compile:
distclean-compile:
-rm -f *.tab.c
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Xwayland-dpmsstubs.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Xwayland-drm-protocol.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Xwayland-linux-dmabuf-unstable-v1-protocol.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Xwayland-miinitext.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Xwayland-pointer-constraints-unstable-v1-protocol.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Xwayland-relative-pointer-unstable-v1-protocol.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Xwayland-stubs.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Xwayland-tablet-unstable-v2-protocol.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Xwayland-wayland-eglstream-controller-protocol.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Xwayland-wayland-eglstream-protocol.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Xwayland-xdg-output-unstable-v1-protocol.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Xwayland-xwayland-cursor.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Xwayland-xwayland-cvt.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Xwayland-xwayland-glamor-eglstream.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Xwayland-xwayland-glamor-gbm.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Xwayland-xwayland-glamor-xv.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Xwayland-xwayland-glamor.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Xwayland-xwayland-input.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Xwayland-xwayland-keyboard-grab-unstable-v1-protocol.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Xwayland-xwayland-output.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Xwayland-xwayland-present.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Xwayland-xwayland-shm.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Xwayland-xwayland-vidmode.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Xwayland-xwayland.Po@am__quote@
@@ -776,20 +820,6 @@ Xwayland-xwayland-vidmode.obj: xwayland-vidmode.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(Xwayland_CFLAGS) $(CFLAGS) -c -o Xwayland-xwayland-vidmode.obj `if test -f 'xwayland-vidmode.c'; then $(CYGPATH_W) 'xwayland-vidmode.c'; else $(CYGPATH_W) '$(srcdir)/xwayland-vidmode.c'; fi`
-Xwayland-dpmsstubs.o: $(top_srcdir)/Xext/dpmsstubs.c
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(Xwayland_CFLAGS) $(CFLAGS) -MT Xwayland-dpmsstubs.o -MD -MP -MF $(DEPDIR)/Xwayland-dpmsstubs.Tpo -c -o Xwayland-dpmsstubs.o `test -f '$(top_srcdir)/Xext/dpmsstubs.c' || echo '$(srcdir)/'`$(top_srcdir)/Xext/dpmsstubs.c
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/Xwayland-dpmsstubs.Tpo $(DEPDIR)/Xwayland-dpmsstubs.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(top_srcdir)/Xext/dpmsstubs.c' object='Xwayland-dpmsstubs.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(Xwayland_CFLAGS) $(CFLAGS) -c -o Xwayland-dpmsstubs.o `test -f '$(top_srcdir)/Xext/dpmsstubs.c' || echo '$(srcdir)/'`$(top_srcdir)/Xext/dpmsstubs.c
-
-Xwayland-dpmsstubs.obj: $(top_srcdir)/Xext/dpmsstubs.c
-@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(Xwayland_CFLAGS) $(CFLAGS) -MT Xwayland-dpmsstubs.obj -MD -MP -MF $(DEPDIR)/Xwayland-dpmsstubs.Tpo -c -o Xwayland-dpmsstubs.obj `if test -f '$(top_srcdir)/Xext/dpmsstubs.c'; then $(CYGPATH_W) '$(top_srcdir)/Xext/dpmsstubs.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/Xext/dpmsstubs.c'; fi`
-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/Xwayland-dpmsstubs.Tpo $(DEPDIR)/Xwayland-dpmsstubs.Po
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(top_srcdir)/Xext/dpmsstubs.c' object='Xwayland-dpmsstubs.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(Xwayland_CFLAGS) $(CFLAGS) -c -o Xwayland-dpmsstubs.obj `if test -f '$(top_srcdir)/Xext/dpmsstubs.c'; then $(CYGPATH_W) '$(top_srcdir)/Xext/dpmsstubs.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/Xext/dpmsstubs.c'; fi`
-
Xwayland-stubs.o: $(top_srcdir)/Xi/stubs.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(Xwayland_CFLAGS) $(CFLAGS) -MT Xwayland-stubs.o -MD -MP -MF $(DEPDIR)/Xwayland-stubs.Tpo -c -o Xwayland-stubs.o `test -f '$(top_srcdir)/Xi/stubs.c' || echo '$(srcdir)/'`$(top_srcdir)/Xi/stubs.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/Xwayland-stubs.Tpo $(DEPDIR)/Xwayland-stubs.Po
@@ -832,6 +862,34 @@ Xwayland-xwayland-glamor.obj: xwayland-glamor.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(Xwayland_CFLAGS) $(CFLAGS) -c -o Xwayland-xwayland-glamor.obj `if test -f 'xwayland-glamor.c'; then $(CYGPATH_W) 'xwayland-glamor.c'; else $(CYGPATH_W) '$(srcdir)/xwayland-glamor.c'; fi`
+Xwayland-xwayland-glamor-gbm.o: xwayland-glamor-gbm.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(Xwayland_CFLAGS) $(CFLAGS) -MT Xwayland-xwayland-glamor-gbm.o -MD -MP -MF $(DEPDIR)/Xwayland-xwayland-glamor-gbm.Tpo -c -o Xwayland-xwayland-glamor-gbm.o `test -f 'xwayland-glamor-gbm.c' || echo '$(srcdir)/'`xwayland-glamor-gbm.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/Xwayland-xwayland-glamor-gbm.Tpo $(DEPDIR)/Xwayland-xwayland-glamor-gbm.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='xwayland-glamor-gbm.c' object='Xwayland-xwayland-glamor-gbm.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(Xwayland_CFLAGS) $(CFLAGS) -c -o Xwayland-xwayland-glamor-gbm.o `test -f 'xwayland-glamor-gbm.c' || echo '$(srcdir)/'`xwayland-glamor-gbm.c
+
+Xwayland-xwayland-glamor-gbm.obj: xwayland-glamor-gbm.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(Xwayland_CFLAGS) $(CFLAGS) -MT Xwayland-xwayland-glamor-gbm.obj -MD -MP -MF $(DEPDIR)/Xwayland-xwayland-glamor-gbm.Tpo -c -o Xwayland-xwayland-glamor-gbm.obj `if test -f 'xwayland-glamor-gbm.c'; then $(CYGPATH_W) 'xwayland-glamor-gbm.c'; else $(CYGPATH_W) '$(srcdir)/xwayland-glamor-gbm.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/Xwayland-xwayland-glamor-gbm.Tpo $(DEPDIR)/Xwayland-xwayland-glamor-gbm.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='xwayland-glamor-gbm.c' object='Xwayland-xwayland-glamor-gbm.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(Xwayland_CFLAGS) $(CFLAGS) -c -o Xwayland-xwayland-glamor-gbm.obj `if test -f 'xwayland-glamor-gbm.c'; then $(CYGPATH_W) 'xwayland-glamor-gbm.c'; else $(CYGPATH_W) '$(srcdir)/xwayland-glamor-gbm.c'; fi`
+
+Xwayland-xwayland-present.o: xwayland-present.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(Xwayland_CFLAGS) $(CFLAGS) -MT Xwayland-xwayland-present.o -MD -MP -MF $(DEPDIR)/Xwayland-xwayland-present.Tpo -c -o Xwayland-xwayland-present.o `test -f 'xwayland-present.c' || echo '$(srcdir)/'`xwayland-present.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/Xwayland-xwayland-present.Tpo $(DEPDIR)/Xwayland-xwayland-present.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='xwayland-present.c' object='Xwayland-xwayland-present.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(Xwayland_CFLAGS) $(CFLAGS) -c -o Xwayland-xwayland-present.o `test -f 'xwayland-present.c' || echo '$(srcdir)/'`xwayland-present.c
+
+Xwayland-xwayland-present.obj: xwayland-present.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(Xwayland_CFLAGS) $(CFLAGS) -MT Xwayland-xwayland-present.obj -MD -MP -MF $(DEPDIR)/Xwayland-xwayland-present.Tpo -c -o Xwayland-xwayland-present.obj `if test -f 'xwayland-present.c'; then $(CYGPATH_W) 'xwayland-present.c'; else $(CYGPATH_W) '$(srcdir)/xwayland-present.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/Xwayland-xwayland-present.Tpo $(DEPDIR)/Xwayland-xwayland-present.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='xwayland-present.c' object='Xwayland-xwayland-present.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(Xwayland_CFLAGS) $(CFLAGS) -c -o Xwayland-xwayland-present.obj `if test -f 'xwayland-present.c'; then $(CYGPATH_W) 'xwayland-present.c'; else $(CYGPATH_W) '$(srcdir)/xwayland-present.c'; fi`
+
Xwayland-xwayland-glamor-xv.o: xwayland-glamor-xv.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(Xwayland_CFLAGS) $(CFLAGS) -MT Xwayland-xwayland-glamor-xv.o -MD -MP -MF $(DEPDIR)/Xwayland-xwayland-glamor-xv.Tpo -c -o Xwayland-xwayland-glamor-xv.o `test -f 'xwayland-glamor-xv.c' || echo '$(srcdir)/'`xwayland-glamor-xv.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/Xwayland-xwayland-glamor-xv.Tpo $(DEPDIR)/Xwayland-xwayland-glamor-xv.Po
@@ -846,6 +904,20 @@ Xwayland-xwayland-glamor-xv.obj: xwayland-glamor-xv.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(Xwayland_CFLAGS) $(CFLAGS) -c -o Xwayland-xwayland-glamor-xv.obj `if test -f 'xwayland-glamor-xv.c'; then $(CYGPATH_W) 'xwayland-glamor-xv.c'; else $(CYGPATH_W) '$(srcdir)/xwayland-glamor-xv.c'; fi`
+Xwayland-xwayland-glamor-eglstream.o: xwayland-glamor-eglstream.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(Xwayland_CFLAGS) $(CFLAGS) -MT Xwayland-xwayland-glamor-eglstream.o -MD -MP -MF $(DEPDIR)/Xwayland-xwayland-glamor-eglstream.Tpo -c -o Xwayland-xwayland-glamor-eglstream.o `test -f 'xwayland-glamor-eglstream.c' || echo '$(srcdir)/'`xwayland-glamor-eglstream.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/Xwayland-xwayland-glamor-eglstream.Tpo $(DEPDIR)/Xwayland-xwayland-glamor-eglstream.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='xwayland-glamor-eglstream.c' object='Xwayland-xwayland-glamor-eglstream.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(Xwayland_CFLAGS) $(CFLAGS) -c -o Xwayland-xwayland-glamor-eglstream.o `test -f 'xwayland-glamor-eglstream.c' || echo '$(srcdir)/'`xwayland-glamor-eglstream.c
+
+Xwayland-xwayland-glamor-eglstream.obj: xwayland-glamor-eglstream.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(Xwayland_CFLAGS) $(CFLAGS) -MT Xwayland-xwayland-glamor-eglstream.obj -MD -MP -MF $(DEPDIR)/Xwayland-xwayland-glamor-eglstream.Tpo -c -o Xwayland-xwayland-glamor-eglstream.obj `if test -f 'xwayland-glamor-eglstream.c'; then $(CYGPATH_W) 'xwayland-glamor-eglstream.c'; else $(CYGPATH_W) '$(srcdir)/xwayland-glamor-eglstream.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/Xwayland-xwayland-glamor-eglstream.Tpo $(DEPDIR)/Xwayland-xwayland-glamor-eglstream.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='xwayland-glamor-eglstream.c' object='Xwayland-xwayland-glamor-eglstream.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(Xwayland_CFLAGS) $(CFLAGS) -c -o Xwayland-xwayland-glamor-eglstream.obj `if test -f 'xwayland-glamor-eglstream.c'; then $(CYGPATH_W) 'xwayland-glamor-eglstream.c'; else $(CYGPATH_W) '$(srcdir)/xwayland-glamor-eglstream.c'; fi`
+
Xwayland-drm-protocol.o: drm-protocol.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(Xwayland_CFLAGS) $(CFLAGS) -MT Xwayland-drm-protocol.o -MD -MP -MF $(DEPDIR)/Xwayland-drm-protocol.Tpo -c -o Xwayland-drm-protocol.o `test -f 'drm-protocol.c' || echo '$(srcdir)/'`drm-protocol.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/Xwayland-drm-protocol.Tpo $(DEPDIR)/Xwayland-drm-protocol.Po
@@ -888,6 +960,90 @@ Xwayland-pointer-constraints-unstable-v1-protocol.obj: pointer-constraints-unsta
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(Xwayland_CFLAGS) $(CFLAGS) -c -o Xwayland-pointer-constraints-unstable-v1-protocol.obj `if test -f 'pointer-constraints-unstable-v1-protocol.c'; then $(CYGPATH_W) 'pointer-constraints-unstable-v1-protocol.c'; else $(CYGPATH_W) '$(srcdir)/pointer-constraints-unstable-v1-protocol.c'; fi`
+Xwayland-tablet-unstable-v2-protocol.o: tablet-unstable-v2-protocol.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(Xwayland_CFLAGS) $(CFLAGS) -MT Xwayland-tablet-unstable-v2-protocol.o -MD -MP -MF $(DEPDIR)/Xwayland-tablet-unstable-v2-protocol.Tpo -c -o Xwayland-tablet-unstable-v2-protocol.o `test -f 'tablet-unstable-v2-protocol.c' || echo '$(srcdir)/'`tablet-unstable-v2-protocol.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/Xwayland-tablet-unstable-v2-protocol.Tpo $(DEPDIR)/Xwayland-tablet-unstable-v2-protocol.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tablet-unstable-v2-protocol.c' object='Xwayland-tablet-unstable-v2-protocol.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(Xwayland_CFLAGS) $(CFLAGS) -c -o Xwayland-tablet-unstable-v2-protocol.o `test -f 'tablet-unstable-v2-protocol.c' || echo '$(srcdir)/'`tablet-unstable-v2-protocol.c
+
+Xwayland-tablet-unstable-v2-protocol.obj: tablet-unstable-v2-protocol.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(Xwayland_CFLAGS) $(CFLAGS) -MT Xwayland-tablet-unstable-v2-protocol.obj -MD -MP -MF $(DEPDIR)/Xwayland-tablet-unstable-v2-protocol.Tpo -c -o Xwayland-tablet-unstable-v2-protocol.obj `if test -f 'tablet-unstable-v2-protocol.c'; then $(CYGPATH_W) 'tablet-unstable-v2-protocol.c'; else $(CYGPATH_W) '$(srcdir)/tablet-unstable-v2-protocol.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/Xwayland-tablet-unstable-v2-protocol.Tpo $(DEPDIR)/Xwayland-tablet-unstable-v2-protocol.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tablet-unstable-v2-protocol.c' object='Xwayland-tablet-unstable-v2-protocol.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(Xwayland_CFLAGS) $(CFLAGS) -c -o Xwayland-tablet-unstable-v2-protocol.obj `if test -f 'tablet-unstable-v2-protocol.c'; then $(CYGPATH_W) 'tablet-unstable-v2-protocol.c'; else $(CYGPATH_W) '$(srcdir)/tablet-unstable-v2-protocol.c'; fi`
+
+Xwayland-xwayland-keyboard-grab-unstable-v1-protocol.o: xwayland-keyboard-grab-unstable-v1-protocol.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(Xwayland_CFLAGS) $(CFLAGS) -MT Xwayland-xwayland-keyboard-grab-unstable-v1-protocol.o -MD -MP -MF $(DEPDIR)/Xwayland-xwayland-keyboard-grab-unstable-v1-protocol.Tpo -c -o Xwayland-xwayland-keyboard-grab-unstable-v1-protocol.o `test -f 'xwayland-keyboard-grab-unstable-v1-protocol.c' || echo '$(srcdir)/'`xwayland-keyboard-grab-unstable-v1-protocol.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/Xwayland-xwayland-keyboard-grab-unstable-v1-protocol.Tpo $(DEPDIR)/Xwayland-xwayland-keyboard-grab-unstable-v1-protocol.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='xwayland-keyboard-grab-unstable-v1-protocol.c' object='Xwayland-xwayland-keyboard-grab-unstable-v1-protocol.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(Xwayland_CFLAGS) $(CFLAGS) -c -o Xwayland-xwayland-keyboard-grab-unstable-v1-protocol.o `test -f 'xwayland-keyboard-grab-unstable-v1-protocol.c' || echo '$(srcdir)/'`xwayland-keyboard-grab-unstable-v1-protocol.c
+
+Xwayland-xwayland-keyboard-grab-unstable-v1-protocol.obj: xwayland-keyboard-grab-unstable-v1-protocol.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(Xwayland_CFLAGS) $(CFLAGS) -MT Xwayland-xwayland-keyboard-grab-unstable-v1-protocol.obj -MD -MP -MF $(DEPDIR)/Xwayland-xwayland-keyboard-grab-unstable-v1-protocol.Tpo -c -o Xwayland-xwayland-keyboard-grab-unstable-v1-protocol.obj `if test -f 'xwayland-keyboard-grab-unstable-v1-protocol.c'; then $(CYGPATH_W) 'xwayland-keyboard-grab-unstable-v1-protocol.c'; else $(CYGPATH_W) '$(srcdir)/xwayland-keyboard-grab-unstable-v1-protocol.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/Xwayland-xwayland-keyboard-grab-unstable-v1-protocol.Tpo $(DEPDIR)/Xwayland-xwayland-keyboard-grab-unstable-v1-protocol.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='xwayland-keyboard-grab-unstable-v1-protocol.c' object='Xwayland-xwayland-keyboard-grab-unstable-v1-protocol.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(Xwayland_CFLAGS) $(CFLAGS) -c -o Xwayland-xwayland-keyboard-grab-unstable-v1-protocol.obj `if test -f 'xwayland-keyboard-grab-unstable-v1-protocol.c'; then $(CYGPATH_W) 'xwayland-keyboard-grab-unstable-v1-protocol.c'; else $(CYGPATH_W) '$(srcdir)/xwayland-keyboard-grab-unstable-v1-protocol.c'; fi`
+
+Xwayland-xdg-output-unstable-v1-protocol.o: xdg-output-unstable-v1-protocol.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(Xwayland_CFLAGS) $(CFLAGS) -MT Xwayland-xdg-output-unstable-v1-protocol.o -MD -MP -MF $(DEPDIR)/Xwayland-xdg-output-unstable-v1-protocol.Tpo -c -o Xwayland-xdg-output-unstable-v1-protocol.o `test -f 'xdg-output-unstable-v1-protocol.c' || echo '$(srcdir)/'`xdg-output-unstable-v1-protocol.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/Xwayland-xdg-output-unstable-v1-protocol.Tpo $(DEPDIR)/Xwayland-xdg-output-unstable-v1-protocol.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='xdg-output-unstable-v1-protocol.c' object='Xwayland-xdg-output-unstable-v1-protocol.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(Xwayland_CFLAGS) $(CFLAGS) -c -o Xwayland-xdg-output-unstable-v1-protocol.o `test -f 'xdg-output-unstable-v1-protocol.c' || echo '$(srcdir)/'`xdg-output-unstable-v1-protocol.c
+
+Xwayland-xdg-output-unstable-v1-protocol.obj: xdg-output-unstable-v1-protocol.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(Xwayland_CFLAGS) $(CFLAGS) -MT Xwayland-xdg-output-unstable-v1-protocol.obj -MD -MP -MF $(DEPDIR)/Xwayland-xdg-output-unstable-v1-protocol.Tpo -c -o Xwayland-xdg-output-unstable-v1-protocol.obj `if test -f 'xdg-output-unstable-v1-protocol.c'; then $(CYGPATH_W) 'xdg-output-unstable-v1-protocol.c'; else $(CYGPATH_W) '$(srcdir)/xdg-output-unstable-v1-protocol.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/Xwayland-xdg-output-unstable-v1-protocol.Tpo $(DEPDIR)/Xwayland-xdg-output-unstable-v1-protocol.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='xdg-output-unstable-v1-protocol.c' object='Xwayland-xdg-output-unstable-v1-protocol.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(Xwayland_CFLAGS) $(CFLAGS) -c -o Xwayland-xdg-output-unstable-v1-protocol.obj `if test -f 'xdg-output-unstable-v1-protocol.c'; then $(CYGPATH_W) 'xdg-output-unstable-v1-protocol.c'; else $(CYGPATH_W) '$(srcdir)/xdg-output-unstable-v1-protocol.c'; fi`
+
+Xwayland-linux-dmabuf-unstable-v1-protocol.o: linux-dmabuf-unstable-v1-protocol.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(Xwayland_CFLAGS) $(CFLAGS) -MT Xwayland-linux-dmabuf-unstable-v1-protocol.o -MD -MP -MF $(DEPDIR)/Xwayland-linux-dmabuf-unstable-v1-protocol.Tpo -c -o Xwayland-linux-dmabuf-unstable-v1-protocol.o `test -f 'linux-dmabuf-unstable-v1-protocol.c' || echo '$(srcdir)/'`linux-dmabuf-unstable-v1-protocol.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/Xwayland-linux-dmabuf-unstable-v1-protocol.Tpo $(DEPDIR)/Xwayland-linux-dmabuf-unstable-v1-protocol.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='linux-dmabuf-unstable-v1-protocol.c' object='Xwayland-linux-dmabuf-unstable-v1-protocol.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(Xwayland_CFLAGS) $(CFLAGS) -c -o Xwayland-linux-dmabuf-unstable-v1-protocol.o `test -f 'linux-dmabuf-unstable-v1-protocol.c' || echo '$(srcdir)/'`linux-dmabuf-unstable-v1-protocol.c
+
+Xwayland-linux-dmabuf-unstable-v1-protocol.obj: linux-dmabuf-unstable-v1-protocol.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(Xwayland_CFLAGS) $(CFLAGS) -MT Xwayland-linux-dmabuf-unstable-v1-protocol.obj -MD -MP -MF $(DEPDIR)/Xwayland-linux-dmabuf-unstable-v1-protocol.Tpo -c -o Xwayland-linux-dmabuf-unstable-v1-protocol.obj `if test -f 'linux-dmabuf-unstable-v1-protocol.c'; then $(CYGPATH_W) 'linux-dmabuf-unstable-v1-protocol.c'; else $(CYGPATH_W) '$(srcdir)/linux-dmabuf-unstable-v1-protocol.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/Xwayland-linux-dmabuf-unstable-v1-protocol.Tpo $(DEPDIR)/Xwayland-linux-dmabuf-unstable-v1-protocol.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='linux-dmabuf-unstable-v1-protocol.c' object='Xwayland-linux-dmabuf-unstable-v1-protocol.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(Xwayland_CFLAGS) $(CFLAGS) -c -o Xwayland-linux-dmabuf-unstable-v1-protocol.obj `if test -f 'linux-dmabuf-unstable-v1-protocol.c'; then $(CYGPATH_W) 'linux-dmabuf-unstable-v1-protocol.c'; else $(CYGPATH_W) '$(srcdir)/linux-dmabuf-unstable-v1-protocol.c'; fi`
+
+Xwayland-wayland-eglstream-protocol.o: wayland-eglstream-protocol.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(Xwayland_CFLAGS) $(CFLAGS) -MT Xwayland-wayland-eglstream-protocol.o -MD -MP -MF $(DEPDIR)/Xwayland-wayland-eglstream-protocol.Tpo -c -o Xwayland-wayland-eglstream-protocol.o `test -f 'wayland-eglstream-protocol.c' || echo '$(srcdir)/'`wayland-eglstream-protocol.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/Xwayland-wayland-eglstream-protocol.Tpo $(DEPDIR)/Xwayland-wayland-eglstream-protocol.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wayland-eglstream-protocol.c' object='Xwayland-wayland-eglstream-protocol.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(Xwayland_CFLAGS) $(CFLAGS) -c -o Xwayland-wayland-eglstream-protocol.o `test -f 'wayland-eglstream-protocol.c' || echo '$(srcdir)/'`wayland-eglstream-protocol.c
+
+Xwayland-wayland-eglstream-protocol.obj: wayland-eglstream-protocol.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(Xwayland_CFLAGS) $(CFLAGS) -MT Xwayland-wayland-eglstream-protocol.obj -MD -MP -MF $(DEPDIR)/Xwayland-wayland-eglstream-protocol.Tpo -c -o Xwayland-wayland-eglstream-protocol.obj `if test -f 'wayland-eglstream-protocol.c'; then $(CYGPATH_W) 'wayland-eglstream-protocol.c'; else $(CYGPATH_W) '$(srcdir)/wayland-eglstream-protocol.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/Xwayland-wayland-eglstream-protocol.Tpo $(DEPDIR)/Xwayland-wayland-eglstream-protocol.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wayland-eglstream-protocol.c' object='Xwayland-wayland-eglstream-protocol.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(Xwayland_CFLAGS) $(CFLAGS) -c -o Xwayland-wayland-eglstream-protocol.obj `if test -f 'wayland-eglstream-protocol.c'; then $(CYGPATH_W) 'wayland-eglstream-protocol.c'; else $(CYGPATH_W) '$(srcdir)/wayland-eglstream-protocol.c'; fi`
+
+Xwayland-wayland-eglstream-controller-protocol.o: wayland-eglstream-controller-protocol.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(Xwayland_CFLAGS) $(CFLAGS) -MT Xwayland-wayland-eglstream-controller-protocol.o -MD -MP -MF $(DEPDIR)/Xwayland-wayland-eglstream-controller-protocol.Tpo -c -o Xwayland-wayland-eglstream-controller-protocol.o `test -f 'wayland-eglstream-controller-protocol.c' || echo '$(srcdir)/'`wayland-eglstream-controller-protocol.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/Xwayland-wayland-eglstream-controller-protocol.Tpo $(DEPDIR)/Xwayland-wayland-eglstream-controller-protocol.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wayland-eglstream-controller-protocol.c' object='Xwayland-wayland-eglstream-controller-protocol.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(Xwayland_CFLAGS) $(CFLAGS) -c -o Xwayland-wayland-eglstream-controller-protocol.o `test -f 'wayland-eglstream-controller-protocol.c' || echo '$(srcdir)/'`wayland-eglstream-controller-protocol.c
+
+Xwayland-wayland-eglstream-controller-protocol.obj: wayland-eglstream-controller-protocol.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(Xwayland_CFLAGS) $(CFLAGS) -MT Xwayland-wayland-eglstream-controller-protocol.obj -MD -MP -MF $(DEPDIR)/Xwayland-wayland-eglstream-controller-protocol.Tpo -c -o Xwayland-wayland-eglstream-controller-protocol.obj `if test -f 'wayland-eglstream-controller-protocol.c'; then $(CYGPATH_W) 'wayland-eglstream-controller-protocol.c'; else $(CYGPATH_W) '$(srcdir)/wayland-eglstream-controller-protocol.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/Xwayland-wayland-eglstream-controller-protocol.Tpo $(DEPDIR)/Xwayland-wayland-eglstream-controller-protocol.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='wayland-eglstream-controller-protocol.c' object='Xwayland-wayland-eglstream-controller-protocol.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(Xwayland_CFLAGS) $(CFLAGS) -c -o Xwayland-wayland-eglstream-controller-protocol.obj `if test -f 'wayland-eglstream-controller-protocol.c'; then $(CYGPATH_W) 'wayland-eglstream-controller-protocol.c'; else $(CYGPATH_W) '$(srcdir)/wayland-eglstream-controller-protocol.c'; fi`
+
mostlyclean-libtool:
-rm -f *.lo
@@ -1121,17 +1277,46 @@ 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) code < $< > $@
+ $(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) code < $< > $@
+ $(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 < $< > $@
-%-protocol.c : %.xml
+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 < $< > $@
+
+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 < $< > $@
diff --git a/xserver/hw/xwayland/xwayland-cursor.c b/xserver/hw/xwayland/xwayland-cursor.c
index 7b6a698fd..cf8395f1d 100644
--- a/xserver/hw/xwayland/xwayland-cursor.c
+++ b/xserver/hw/xwayland/xwayland-cursor.c
@@ -96,11 +96,11 @@ xwl_unrealize_cursor(DeviceIntPtr device, ScreenPtr screen, CursorPtr cursor)
}
static void
-clear_cursor_frame_callback(struct xwl_seat *xwl_seat)
+clear_cursor_frame_callback(struct xwl_cursor *xwl_cursor)
{
- if (xwl_seat->cursor_frame_cb) {
- wl_callback_destroy (xwl_seat->cursor_frame_cb);
- xwl_seat->cursor_frame_cb = NULL;
+ if (xwl_cursor->frame_cb) {
+ wl_callback_destroy (xwl_cursor->frame_cb);
+ xwl_cursor->frame_cb = NULL;
}
}
@@ -109,12 +109,12 @@ frame_callback(void *data,
struct wl_callback *callback,
uint32_t time)
{
- struct xwl_seat *xwl_seat = data;
+ struct xwl_cursor *xwl_cursor = data;
- clear_cursor_frame_callback(xwl_seat);
- if (xwl_seat->cursor_needs_update) {
- xwl_seat->cursor_needs_update = FALSE;
- xwl_seat_set_cursor(xwl_seat);
+ clear_cursor_frame_callback(xwl_cursor);
+ if (xwl_cursor->needs_update) {
+ xwl_cursor->needs_update = FALSE;
+ xwl_cursor->update_proc(xwl_cursor);
}
}
@@ -125,6 +125,7 @@ static const struct wl_callback_listener frame_listener = {
void
xwl_seat_set_cursor(struct xwl_seat *xwl_seat)
{
+ struct xwl_cursor *xwl_cursor = &xwl_seat->cursor;
PixmapPtr pixmap;
CursorPtr cursor;
int stride;
@@ -135,13 +136,13 @@ xwl_seat_set_cursor(struct xwl_seat *xwl_seat)
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_seat);
- xwl_seat->cursor_needs_update = FALSE;
+ clear_cursor_frame_callback(xwl_cursor);
+ xwl_cursor->needs_update = FALSE;
return;
}
- if (xwl_seat->cursor_frame_cb) {
- xwl_seat->cursor_needs_update = TRUE;
+ if (xwl_cursor->frame_cb) {
+ xwl_cursor->needs_update = TRUE;
return;
}
@@ -159,19 +160,69 @@ xwl_seat_set_cursor(struct xwl_seat *xwl_seat)
wl_pointer_set_cursor(xwl_seat->wl_pointer,
xwl_seat->pointer_enter_serial,
- xwl_seat->cursor,
+ xwl_cursor->surface,
xwl_seat->x_cursor->bits->xhot,
xwl_seat->x_cursor->bits->yhot);
- wl_surface_attach(xwl_seat->cursor,
+ wl_surface_attach(xwl_cursor->surface,
xwl_shm_pixmap_get_wl_buffer(pixmap), 0, 0);
- wl_surface_damage(xwl_seat->cursor, 0, 0,
+ wl_surface_damage(xwl_cursor->surface, 0, 0,
xwl_seat->x_cursor->bits->width,
xwl_seat->x_cursor->bits->height);
- xwl_seat->cursor_frame_cb = wl_surface_frame(xwl_seat->cursor);
- wl_callback_add_listener(xwl_seat->cursor_frame_cb, &frame_listener, xwl_seat);
+ xwl_cursor->frame_cb = wl_surface_frame(xwl_cursor->surface);
+ wl_callback_add_listener(xwl_cursor->frame_cb, &frame_listener, xwl_cursor);
- wl_surface_commit(xwl_seat->cursor);
+ wl_surface_commit(xwl_cursor->surface);
+}
+
+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;
+ int stride;
+
+ if (!xwl_seat->x_cursor) {
+ zwp_tablet_tool_v2_set_cursor(xwl_tablet_tool->tool,
+ xwl_tablet_tool->proximity_in_serial,
+ NULL, 0, 0);
+ 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;
+
+ 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);
+
+ 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);
+ wl_surface_attach(xwl_cursor->surface,
+ xwl_shm_pixmap_get_wl_buffer(pixmap), 0, 0);
+ wl_surface_damage(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);
+
+ wl_surface_commit(xwl_cursor->surface);
}
static void
@@ -179,6 +230,7 @@ xwl_set_cursor(DeviceIntPtr device,
ScreenPtr screen, CursorPtr cursor, int x, int y)
{
struct xwl_seat *xwl_seat;
+ struct xwl_tablet_tool *xwl_tablet_tool;
Bool cursor_visibility_changed;
xwl_seat = device->public.devicePrivate;
@@ -193,6 +245,11 @@ xwl_set_cursor(DeviceIntPtr device,
xwl_seat_cursor_visibility_changed(xwl_seat);
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);
+ }
}
static void
diff --git a/xserver/hw/xwayland/xwayland-glamor-eglstream.c b/xserver/hw/xwayland/xwayland-glamor-eglstream.c
new file mode 100644
index 000000000..c62c0d2ac
--- /dev/null
+++ b/xserver/hw/xwayland/xwayland-glamor-eglstream.c
@@ -0,0 +1,932 @@
+/*
+ * 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.h"
+
+#include "wayland-eglstream-client-protocol.h"
+#include "wayland-eglstream-controller-client-protocol.h"
+
+#define MESA_EGL_NO_X11_HEADERS
+#include <glamor_egl.h>
+#include <glamor.h>
+#include <glamor_transform.h>
+#include <glamor_transfer.h>
+
+#include <xf86drm.h>
+
+#include <epoxy/egl.h>
+
+struct xwl_eglstream_pending_stream {
+ PixmapPtr pixmap;
+ WindowPtr window;
+
+ struct xwl_pixmap *xwl_pixmap;
+ struct wl_callback *cb;
+
+ Bool is_valid;
+
+ struct xorg_list link;
+};
+
+struct xwl_eglstream_private {
+ EGLDeviceEXT egl_device;
+ struct wl_eglstream_display *display;
+ struct wl_eglstream_controller *controller;
+ uint32_t display_caps;
+
+ EGLConfig config;
+
+ SetWindowPixmapProcPtr SetWindowPixmap;
+
+ struct xorg_list pending_streams;
+
+ Bool have_egl_damage;
+
+ GLint blit_prog;
+ GLuint blit_vao;
+ GLuint blit_vbo;
+ GLuint blit_is_rgba_pos;
+};
+
+struct xwl_pixmap {
+ struct wl_buffer *buffer;
+ struct xwl_screen *xwl_screen;
+
+ /* The stream and associated resources have their own lifetime seperate
+ * from the pixmap's */
+ int refcount;
+
+ EGLStreamKHR stream;
+ EGLSurface surface;
+};
+
+static DevPrivateKeyRec xwl_eglstream_private_key;
+static DevPrivateKeyRec xwl_eglstream_window_private_key;
+
+static inline struct xwl_eglstream_private *
+xwl_eglstream_get(struct xwl_screen *xwl_screen)
+{
+ return dixLookupPrivate(&xwl_screen->screen->devPrivates,
+ &xwl_eglstream_private_key);
+}
+
+static inline struct xwl_eglstream_pending_stream *
+xwl_eglstream_window_get_pending(WindowPtr window)
+{
+ return dixLookupPrivate(&window->devPrivates,
+ &xwl_eglstream_window_private_key);
+}
+
+static inline void
+xwl_eglstream_window_set_pending(WindowPtr window,
+ struct xwl_eglstream_pending_stream *stream)
+{
+ dixSetPrivate(&window->devPrivates,
+ &xwl_eglstream_window_private_key, stream);
+}
+
+static GLint
+xwl_eglstream_compile_glsl_prog(GLenum type, const char *source)
+{
+ GLint ok;
+ GLint prog;
+
+ prog = glCreateShader(type);
+ glShaderSource(prog, 1, (const GLchar **) &source, NULL);
+ glCompileShader(prog);
+ glGetShaderiv(prog, GL_COMPILE_STATUS, &ok);
+ if (!ok) {
+ GLchar *info;
+ GLint size;
+
+ glGetShaderiv(prog, GL_INFO_LOG_LENGTH, &size);
+ info = malloc(size);
+ if (info) {
+ glGetShaderInfoLog(prog, size, NULL, info);
+ ErrorF("Failed to compile %s: %s\n",
+ type == GL_FRAGMENT_SHADER ? "FS" : "VS", info);
+ ErrorF("Program source:\n%s", source);
+ free(info);
+ }
+ else
+ ErrorF("Failed to get shader compilation info.\n");
+ FatalError("GLSL compile failure\n");
+ }
+
+ return prog;
+}
+
+static GLuint
+xwl_eglstream_build_glsl_prog(GLuint vs, GLuint fs)
+{
+ GLint ok;
+ GLuint prog;
+
+ prog = glCreateProgram();
+ glAttachShader(prog, vs);
+ glAttachShader(prog, fs);
+
+ glLinkProgram(prog);
+ glGetProgramiv(prog, GL_LINK_STATUS, &ok);
+ if (!ok) {
+ GLchar *info;
+ GLint size;
+
+ glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &size);
+ info = malloc(size);
+
+ glGetProgramInfoLog(prog, size, NULL, info);
+ ErrorF("Failed to link: %s\n", info);
+ FatalError("GLSL link failure\n");
+ }
+
+ return prog;
+}
+
+static void
+xwl_eglstream_cleanup(struct xwl_screen *xwl_screen)
+{
+ struct xwl_eglstream_private *xwl_eglstream =
+ xwl_eglstream_get(xwl_screen);
+
+ if (xwl_eglstream->display)
+ wl_eglstream_display_destroy(xwl_eglstream->display);
+ if (xwl_eglstream->controller)
+ wl_eglstream_controller_destroy(xwl_eglstream->controller);
+ if (xwl_eglstream->blit_prog) {
+ glDeleteProgram(xwl_eglstream->blit_prog);
+ glDeleteBuffers(1, &xwl_eglstream->blit_vbo);
+ }
+
+ free(xwl_eglstream);
+}
+
+static Bool
+xwl_glamor_egl_supports_device_probing(void)
+{
+ return epoxy_has_egl_extension(NULL, "EGL_EXT_device_base");
+}
+
+static void **
+xwl_glamor_egl_get_devices(int *num_devices)
+{
+ EGLDeviceEXT *devices, *tmp;
+ Bool ret;
+ int drm_dev_count = 0;
+ int i;
+
+ if (!xwl_glamor_egl_supports_device_probing())
+ return NULL;
+
+ /* Get the number of devices */
+ ret = eglQueryDevicesEXT(0, NULL, num_devices);
+ if (!ret || *num_devices < 1)
+ return NULL;
+
+ devices = calloc(*num_devices, sizeof(EGLDeviceEXT));
+ if (!devices)
+ return NULL;
+
+ ret = eglQueryDevicesEXT(*num_devices, devices, num_devices);
+ if (!ret)
+ goto error;
+
+ /* We're only ever going to care about devices that support
+ * EGL_EXT_device_drm, so filter out the ones that don't
+ */
+ for (i = 0; i < *num_devices; i++) {
+ const char *extension_str =
+ eglQueryDeviceStringEXT(devices[i], EGL_EXTENSIONS);
+
+ if (!epoxy_extension_in_string(extension_str, "EGL_EXT_device_drm"))
+ continue;
+
+ devices[drm_dev_count++] = devices[i];
+ }
+ if (!drm_dev_count)
+ goto error;
+
+ *num_devices = drm_dev_count;
+ tmp = realloc(devices, sizeof(EGLDeviceEXT) * drm_dev_count);
+ if (!tmp)
+ goto error;
+
+ devices = tmp;
+
+ return devices;
+
+error:
+ free(devices);
+
+ return NULL;
+}
+
+static Bool
+xwl_glamor_egl_device_has_egl_extensions(void *device,
+ const char **ext_list, size_t size)
+{
+ EGLDisplay egl_display;
+ int i;
+ Bool has_exts = TRUE;
+
+ egl_display = glamor_egl_get_display(EGL_PLATFORM_DEVICE_EXT, device);
+ if (!egl_display || !eglInitialize(egl_display, NULL, NULL))
+ return FALSE;
+
+ for (i = 0; i < size; i++) {
+ if (!epoxy_has_egl_extension(egl_display, ext_list[i])) {
+ has_exts = FALSE;
+ break;
+ }
+ }
+
+ eglTerminate(egl_display);
+ return has_exts;
+}
+
+static void
+xwl_eglstream_unref_pixmap_stream(struct xwl_pixmap *xwl_pixmap)
+{
+ struct xwl_screen *xwl_screen = xwl_pixmap->xwl_screen;
+
+ if (--xwl_pixmap->refcount >= 1)
+ return;
+
+ /* If we're using this stream in the current egl context, unbind it so the
+ * driver doesn't keep it around until the next eglMakeCurrent()
+ * don't have to keep it around until something else changes the surface
+ */
+ xwl_glamor_egl_make_current(xwl_screen);
+ if (eglGetCurrentSurface(EGL_READ) == xwl_pixmap->surface ||
+ eglGetCurrentSurface(EGL_DRAW) == xwl_pixmap->surface) {
+ eglMakeCurrent(xwl_screen->egl_display,
+ EGL_NO_SURFACE, EGL_NO_SURFACE,
+ xwl_screen->egl_context);
+ }
+
+ if (xwl_pixmap->surface)
+ eglDestroySurface(xwl_screen->egl_display, xwl_pixmap->surface);
+
+ eglDestroyStreamKHR(xwl_screen->egl_display, xwl_pixmap->stream);
+
+ wl_buffer_destroy(xwl_pixmap->buffer);
+ free(xwl_pixmap);
+}
+
+static Bool
+xwl_glamor_eglstream_destroy_pixmap(PixmapPtr pixmap)
+{
+ struct xwl_pixmap *xwl_pixmap = xwl_pixmap_get(pixmap);
+
+ if (xwl_pixmap && pixmap->refcnt == 1)
+ xwl_eglstream_unref_pixmap_stream(xwl_pixmap);
+
+ return glamor_destroy_pixmap(pixmap);
+}
+
+static struct wl_buffer *
+xwl_glamor_eglstream_get_wl_buffer_for_pixmap(PixmapPtr pixmap,
+ Bool *created)
+{
+ /* XXX created? */
+ return xwl_pixmap_get(pixmap)->buffer;
+}
+
+static void
+xwl_eglstream_set_window_pixmap(WindowPtr window, PixmapPtr pixmap)
+{
+ struct xwl_screen *xwl_screen = xwl_screen_get(window->drawable.pScreen);
+ struct xwl_eglstream_private *xwl_eglstream =
+ xwl_eglstream_get(xwl_screen);
+ struct xwl_eglstream_pending_stream *pending;
+
+ pending = xwl_eglstream_window_get_pending(window);
+ if (pending) {
+ /* The pixmap for this window has changed before the compositor
+ * finished attaching the consumer for the window's pixmap's original
+ * eglstream. A producer can no longer be attached, so the stream's
+ * useless
+ */
+ pending->is_valid = FALSE;
+
+ /* The compositor may still be using the stream, so we can't destroy
+ * it yet. We'll only have a guarantee that the stream is safe to
+ * destroy once we receive the pending wl_display_sync() for this
+ * stream
+ */
+ pending->xwl_pixmap->refcount++;
+ }
+
+ xwl_screen->screen->SetWindowPixmap = xwl_eglstream->SetWindowPixmap;
+ (*xwl_screen->screen->SetWindowPixmap)(window, pixmap);
+ xwl_eglstream->SetWindowPixmap = xwl_screen->screen->SetWindowPixmap;
+ xwl_screen->screen->SetWindowPixmap = xwl_eglstream_set_window_pixmap;
+}
+
+/* Because we run asynchronously with our wayland compositor, it's possible
+ * that an X client event could cause us to begin creating a stream for a
+ * pixmap/window combo before the stream for the pixmap this window
+ * previously used has been fully initialized. An example:
+ *
+ * - Start processing X client events.
+ * - X window receives resize event, causing us to create a new pixmap and
+ * begin creating the corresponding eglstream. This pixmap is known as
+ * pixmap A.
+ * - X window receives another resize event, and again changes it's current
+ * pixmap causing us to create another corresponding eglstream for the same
+ * window. This pixmap is known as pixmap B.
+ * - Start handling events from the wayland compositor.
+ *
+ * Since both pixmap A and B will have scheduled wl_display_sync events to
+ * indicate when their respective streams are connected, we will receive each
+ * callback in the original order the pixmaps were created. This means the
+ * following would happen:
+ *
+ * - Receive pixmap A's stream callback, attach it's stream to the surface of
+ * the window that just orphaned it.
+ * - Receive pixmap B's stream callback, fall over and fail because the
+ * window's surface now incorrectly has pixmap A's stream attached to it.
+ *
+ * We work around this problem by keeping a queue of pending streams, and
+ * only allowing one queue entry to exist for each window. In the scenario
+ * listed above, this should happen:
+ *
+ * - Begin processing X events...
+ * - A window is resized, causing us to add an eglstream (known as eglstream
+ * A) waiting for it's consumer to finish attachment to be added to the
+ * queue.
+ * - Resize on same window happens. We invalidate the previously pending
+ * stream and add another one to the pending queue (known as eglstream B).
+ * - Begin processing Wayland events...
+ * - Receive invalidated callback from compositor for eglstream A, destroy
+ * stream.
+ * - Receive callback from compositor for eglstream B, create producer.
+ * - Success!
+ */
+static void
+xwl_eglstream_consumer_ready_callback(void *data,
+ struct wl_callback *callback,
+ uint32_t time)
+{
+ struct xwl_screen *xwl_screen = data;
+ struct xwl_eglstream_private *xwl_eglstream =
+ xwl_eglstream_get(xwl_screen);
+ struct xwl_pixmap *xwl_pixmap;
+ struct xwl_eglstream_pending_stream *pending;
+ Bool found = FALSE;
+
+ wl_callback_destroy(callback);
+
+ xorg_list_for_each_entry(pending, &xwl_eglstream->pending_streams, link) {
+ if (pending->cb == callback) {
+ found = TRUE;
+ break;
+ }
+ }
+ assert(found);
+
+ if (!pending->is_valid) {
+ xwl_eglstream_unref_pixmap_stream(pending->xwl_pixmap);
+ goto out;
+ }
+
+ xwl_glamor_egl_make_current(xwl_screen);
+
+ xwl_pixmap = pending->xwl_pixmap;
+ xwl_pixmap->surface = eglCreateStreamProducerSurfaceKHR(
+ xwl_screen->egl_display, xwl_eglstream->config,
+ xwl_pixmap->stream, (int[]) {
+ EGL_WIDTH, pending->pixmap->drawable.width,
+ EGL_HEIGHT, pending->pixmap->drawable.height,
+ EGL_NONE
+ });
+
+ DebugF("eglstream: win %d completes eglstream for pixmap %p, congrats!\n",
+ pending->window->drawable.id, pending->pixmap);
+
+ xwl_eglstream_window_set_pending(pending->window, NULL);
+out:
+ xorg_list_del(&pending->link);
+ free(pending);
+}
+
+static const struct wl_callback_listener consumer_ready_listener = {
+ xwl_eglstream_consumer_ready_callback
+};
+
+static void
+xwl_eglstream_queue_pending_stream(struct xwl_screen *xwl_screen,
+ WindowPtr window, PixmapPtr pixmap)
+{
+ struct xwl_eglstream_private *xwl_eglstream =
+ xwl_eglstream_get(xwl_screen);
+ struct xwl_eglstream_pending_stream *pending_stream;
+
+#ifdef DEBUG
+ if (!xwl_eglstream_window_get_pending(window))
+ DebugF("eglstream: win %d begins new eglstream for pixmap %p\n",
+ window->drawable.id, pixmap);
+ else
+ DebugF("eglstream: win %d interrupts and replaces pending eglstream for pixmap %p\n",
+ window->drawable.id, pixmap);
+#endif
+
+ pending_stream = malloc(sizeof(*pending_stream));
+ pending_stream->window = window;
+ pending_stream->pixmap = pixmap;
+ pending_stream->xwl_pixmap = xwl_pixmap_get(pixmap);
+ pending_stream->is_valid = TRUE;
+ xorg_list_init(&pending_stream->link);
+ xorg_list_add(&pending_stream->link, &xwl_eglstream->pending_streams);
+ xwl_eglstream_window_set_pending(window, pending_stream);
+
+ pending_stream->cb = wl_display_sync(xwl_screen->display);
+ wl_callback_add_listener(pending_stream->cb, &consumer_ready_listener,
+ xwl_screen);
+}
+
+static void
+xwl_eglstream_buffer_release_callback(void *data, struct wl_buffer *wl_buffer)
+{
+ xwl_eglstream_unref_pixmap_stream(data);
+}
+
+static const struct wl_buffer_listener xwl_eglstream_buffer_release_listener = {
+ xwl_eglstream_buffer_release_callback
+};
+
+static void
+xwl_eglstream_create_pending_stream(struct xwl_screen *xwl_screen,
+ WindowPtr window, PixmapPtr pixmap)
+{
+ struct xwl_eglstream_private *xwl_eglstream =
+ xwl_eglstream_get(xwl_screen);
+ struct xwl_pixmap *xwl_pixmap;
+ struct xwl_window *xwl_window = xwl_window_from_window(window);
+ struct wl_array stream_attribs;
+ int stream_fd = -1;
+
+ xwl_pixmap = calloc(sizeof(*xwl_pixmap), 1);
+ if (!xwl_pixmap)
+ FatalError("Not enough memory to create pixmap\n");
+ xwl_pixmap_set_private(pixmap, xwl_pixmap);
+
+ xwl_glamor_egl_make_current(xwl_screen);
+
+ xwl_pixmap->xwl_screen = xwl_screen;
+ xwl_pixmap->refcount = 1;
+ xwl_pixmap->stream = eglCreateStreamKHR(xwl_screen->egl_display, NULL);
+ stream_fd = eglGetStreamFileDescriptorKHR(xwl_screen->egl_display,
+ xwl_pixmap->stream);
+
+ wl_array_init(&stream_attribs);
+ xwl_pixmap->buffer =
+ wl_eglstream_display_create_stream(xwl_eglstream->display,
+ pixmap->drawable.width,
+ pixmap->drawable.height,
+ stream_fd,
+ WL_EGLSTREAM_HANDLE_TYPE_FD,
+ &stream_attribs);
+
+ wl_buffer_add_listener(xwl_pixmap->buffer,
+ &xwl_eglstream_buffer_release_listener,
+ xwl_pixmap);
+
+ wl_eglstream_controller_attach_eglstream_consumer(
+ xwl_eglstream->controller, xwl_window->surface, xwl_pixmap->buffer);
+
+ xwl_eglstream_queue_pending_stream(xwl_screen, window, pixmap);
+
+ close(stream_fd);
+}
+
+static Bool
+xwl_glamor_eglstream_allow_commits(struct xwl_window *xwl_window)
+{
+ struct xwl_screen *xwl_screen = xwl_window->xwl_screen;
+ struct xwl_eglstream_pending_stream *pending =
+ xwl_eglstream_window_get_pending(xwl_window->window);
+ PixmapPtr pixmap =
+ (*xwl_screen->screen->GetWindowPixmap)(xwl_window->window);
+ struct xwl_pixmap *xwl_pixmap = xwl_pixmap_get(pixmap);
+
+ if (xwl_pixmap) {
+ if (pending) {
+ /* Wait for the compositor to finish connecting the consumer for
+ * this eglstream */
+ if (pending->is_valid)
+ return FALSE;
+
+ /* The pixmap for this window was changed before the compositor
+ * finished connecting the eglstream for the window's previous
+ * pixmap. Begin creating a new eglstream. */
+ } else {
+ return TRUE;
+ }
+ }
+
+ /* Glamor pixmap has no backing stream yet; begin making one and disallow
+ * commits until then
+ */
+ xwl_eglstream_create_pending_stream(xwl_screen, xwl_window->window,
+ pixmap);
+
+ return FALSE;
+}
+
+static void
+xwl_glamor_eglstream_post_damage(struct xwl_window *xwl_window,
+ PixmapPtr pixmap, RegionPtr region)
+{
+ struct xwl_screen *xwl_screen = xwl_window->xwl_screen;
+ struct xwl_eglstream_private *xwl_eglstream =
+ xwl_eglstream_get(xwl_screen);
+ struct xwl_pixmap *xwl_pixmap = xwl_pixmap_get(pixmap);
+ BoxPtr box = RegionExtents(region);
+ EGLint egl_damage[] = {
+ box->x1, box->y1,
+ box->x2 - box->x1, box->y2 - box->y1
+ };
+ GLint saved_vao;
+
+ /* Unbind the framebuffer BEFORE binding the EGLSurface, otherwise we
+ * won't actually draw to it
+ */
+ xwl_glamor_egl_make_current(xwl_screen);
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+ if (eglGetCurrentSurface(EGL_READ) != xwl_pixmap->surface ||
+ eglGetCurrentSurface(EGL_DRAW) != xwl_pixmap->surface)
+ eglMakeCurrent(xwl_screen->egl_display,
+ xwl_pixmap->surface, xwl_pixmap->surface,
+ xwl_screen->egl_context);
+
+ /* Save current GL state */
+ glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &saved_vao);
+
+ /* Setup our GL state */
+ glUseProgram(xwl_eglstream->blit_prog);
+ glViewport(0, 0, pixmap->drawable.width, pixmap->drawable.height);
+ glActiveTexture(GL_TEXTURE0);
+ glBindVertexArray(xwl_eglstream->blit_vao);
+ glBindTexture(GL_TEXTURE_2D, glamor_get_pixmap_texture(pixmap));
+
+ glUniform1i(xwl_eglstream->blit_is_rgba_pos,
+ pixmap->drawable.depth >= 32);
+
+ /* Blit rendered image into EGLStream surface */
+ glDrawBuffer(GL_BACK);
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+
+ if (xwl_eglstream->have_egl_damage)
+ eglSwapBuffersWithDamageKHR(xwl_screen->egl_display,
+ xwl_pixmap->surface, egl_damage, 1);
+ else
+ eglSwapBuffers(xwl_screen->egl_display, xwl_pixmap->surface);
+
+ /* Restore previous state */
+ glBindVertexArray(saved_vao);
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ /* After this we will hand off the eglstream's wl_buffer to the
+ * compositor, which will own it until it sends a release() event. */
+ xwl_pixmap->refcount++;
+}
+
+static void
+xwl_eglstream_display_handle_caps(void *data,
+ struct wl_eglstream_display *disp,
+ int32_t caps)
+{
+ xwl_eglstream_get(data)->display_caps = caps;
+}
+
+static void
+xwl_eglstream_display_handle_swapinterval_override(void *data,
+ struct wl_eglstream_display *disp,
+ int32_t swapinterval,
+ struct wl_buffer *stream)
+{
+}
+
+const struct wl_eglstream_display_listener eglstream_display_listener = {
+ .caps = xwl_eglstream_display_handle_caps,
+ .swapinterval_override = xwl_eglstream_display_handle_swapinterval_override,
+};
+
+static Bool
+xwl_glamor_eglstream_init_wl_registry(struct xwl_screen *xwl_screen,
+ struct wl_registry *wl_registry,
+ uint32_t id, const char *name,
+ uint32_t version)
+{
+ struct xwl_eglstream_private *xwl_eglstream =
+ xwl_eglstream_get(xwl_screen);
+
+ if (strcmp(name, "wl_eglstream_display") == 0) {
+ xwl_eglstream->display = wl_registry_bind(
+ wl_registry, id, &wl_eglstream_display_interface, version);
+
+ wl_eglstream_display_add_listener(xwl_eglstream->display,
+ &eglstream_display_listener,
+ xwl_screen);
+ return TRUE;
+ } else if (strcmp(name, "wl_eglstream_controller") == 0) {
+ xwl_eglstream->controller = wl_registry_bind(
+ wl_registry, id, &wl_eglstream_controller_interface, version);
+ return TRUE;
+ }
+
+ /* no match */
+ return FALSE;
+}
+
+static Bool
+xwl_glamor_eglstream_has_wl_interfaces(struct xwl_screen *xwl_screen)
+{
+ struct xwl_eglstream_private *xwl_eglstream =
+ xwl_eglstream_get(xwl_screen);
+
+ if (xwl_eglstream->display == NULL) {
+ ErrorF("glamor: 'wl_eglstream_display' not supported\n");
+ return FALSE;
+ }
+
+ if (xwl_eglstream->controller == NULL) {
+ ErrorF("glamor: 'wl_eglstream_controller' not supported\n");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static inline void
+xwl_eglstream_init_shaders(struct xwl_screen *xwl_screen)
+{
+ struct xwl_eglstream_private *xwl_eglstream =
+ xwl_eglstream_get(xwl_screen);
+ GLint fs, vs, attrib;
+ GLuint vbo;
+
+ const char *blit_vs_src =
+ "attribute vec2 texcoord;\n"
+ "attribute vec2 position;\n"
+ "varying vec2 t;\n"
+ "void main() {\n"
+ " t = texcoord;\n"
+ " gl_Position = vec4(position, 0, 1);\n"
+ "}";
+
+ const char *blit_fs_src =
+ "varying vec2 t;\n"
+ "uniform sampler2D s;\n"
+ "uniform bool is_rgba;\n"
+ "void main() {\n"
+ " if (is_rgba)\n"
+ " gl_FragColor = texture2D(s, t);\n"
+ " else\n"
+ " gl_FragColor = vec4(texture2D(s, t).rgb, 1.0);\n"
+ "}";
+
+ static const float position[] = {
+ /* position */
+ -1, -1,
+ 1, -1,
+ 1, 1,
+ -1, 1,
+ /* texcoord */
+ 0, 1,
+ 1, 1,
+ 1, 0,
+ 0, 0,
+ };
+
+ vs = xwl_eglstream_compile_glsl_prog(GL_VERTEX_SHADER, blit_vs_src);
+ fs = xwl_eglstream_compile_glsl_prog(GL_FRAGMENT_SHADER, blit_fs_src);
+
+ xwl_eglstream->blit_prog = xwl_eglstream_build_glsl_prog(vs, fs);
+ glDeleteShader(vs);
+ glDeleteShader(fs);
+
+ /* Create the blitter's vao */
+ glGenVertexArrays(1, &xwl_eglstream->blit_vao);
+ glBindVertexArray(xwl_eglstream->blit_vao);
+
+ /* Set the data for both position and texcoord in the vbo */
+ glGenBuffers(1, &vbo);
+ glBindBuffer(GL_ARRAY_BUFFER, vbo);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(position), position, GL_STATIC_DRAW);
+ xwl_eglstream->blit_vbo = vbo;
+
+ /* Define each shader attribute's data location in our vbo */
+ attrib = glGetAttribLocation(xwl_eglstream->blit_prog, "position");
+ glVertexAttribPointer(attrib, 2, GL_FLOAT, TRUE, 0, NULL);
+ glEnableVertexAttribArray(attrib);
+
+ attrib = glGetAttribLocation(xwl_eglstream->blit_prog, "texcoord");
+ glVertexAttribPointer(attrib, 2, GL_FLOAT, TRUE, 0,
+ (void*)(sizeof(float) * 8));
+ glEnableVertexAttribArray(attrib);
+
+ /* Save the location of uniforms we'll set later */
+ xwl_eglstream->blit_is_rgba_pos =
+ glGetUniformLocation(xwl_eglstream->blit_prog, "is_rgba");
+}
+
+static Bool
+xwl_glamor_eglstream_init_egl(struct xwl_screen *xwl_screen)
+{
+ struct xwl_eglstream_private *xwl_eglstream =
+ xwl_eglstream_get(xwl_screen);
+ EGLConfig config;
+ const EGLint attrib_list[] = {
+ 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_CONTEXT_PRIORITY_LEVEL_IMG, EGL_CONTEXT_PRIORITY_HIGH_IMG,
+ EGL_NONE
+ };
+ const EGLint config_attribs[] = {
+ EGL_SURFACE_TYPE, EGL_STREAM_BIT_KHR,
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
+ EGL_RED_SIZE, 8,
+ EGL_GREEN_SIZE, 8,
+ EGL_BLUE_SIZE, 8,
+ EGL_ALPHA_SIZE, 8,
+ EGL_NONE,
+ };
+ int n;
+
+ xwl_screen->egl_display = glamor_egl_get_display(
+ EGL_PLATFORM_DEVICE_EXT, xwl_eglstream->egl_device);
+ if (!xwl_screen->egl_display)
+ goto error;
+
+ if (!eglInitialize(xwl_screen->egl_display, NULL, NULL)) {
+ xwl_screen->egl_display = NULL;
+ goto error;
+ }
+
+ if (!epoxy_has_egl_extension(xwl_screen->egl_display,
+ "EGL_IMG_context_priority")) {
+ ErrorF("EGL_IMG_context_priority not available\n");
+ goto error;
+ }
+
+ eglChooseConfig(xwl_screen->egl_display, config_attribs, &config, 1, &n);
+ if (!n) {
+ ErrorF("No acceptable EGL configs found\n");
+ goto error;
+ }
+
+ xwl_eglstream->config = config;
+#if 0
+ xwl_screen->formats =
+ XWL_FORMAT_RGB565 | XWL_FORMAT_XRGB8888 | XWL_FORMAT_ARGB8888;
+#endif
+
+ eglBindAPI(EGL_OPENGL_API);
+ xwl_screen->egl_context = eglCreateContext(
+ xwl_screen->egl_display, config, EGL_NO_CONTEXT, attrib_list);
+ if (xwl_screen->egl_context == EGL_NO_CONTEXT) {
+ ErrorF("Failed to create main EGL context: 0x%x\n", eglGetError());
+ goto error;
+ }
+
+ if (!eglMakeCurrent(xwl_screen->egl_display,
+ EGL_NO_SURFACE, EGL_NO_SURFACE,
+ xwl_screen->egl_context)) {
+ ErrorF("Failed to make EGL context current\n");
+ goto error;
+ }
+
+ xwl_eglstream->have_egl_damage =
+ epoxy_has_egl_extension(xwl_screen->egl_display,
+ "EGL_KHR_swap_buffers_with_damage");
+ if (!xwl_eglstream->have_egl_damage)
+ ErrorF("Driver lacks EGL_KHR_swap_buffers_with_damage, performance "
+ "will be affected\n");
+
+ xwl_eglstream_init_shaders(xwl_screen);
+
+ return TRUE;
+error:
+ xwl_eglstream_cleanup(xwl_screen);
+ return FALSE;
+}
+
+static Bool
+xwl_glamor_eglstream_init_screen(struct xwl_screen *xwl_screen)
+{
+ struct xwl_eglstream_private *xwl_eglstream =
+ xwl_eglstream_get(xwl_screen);
+ ScreenPtr screen = xwl_screen->screen;
+
+ /* We can just let glamor handle CreatePixmap */
+ screen->DestroyPixmap = xwl_glamor_eglstream_destroy_pixmap;
+
+ xwl_eglstream->SetWindowPixmap = screen->SetWindowPixmap;
+ screen->SetWindowPixmap = xwl_eglstream_set_window_pixmap;
+
+ if (!dixRegisterPrivateKey(&xwl_eglstream_window_private_key,
+ PRIVATE_WINDOW, 0))
+ return FALSE;
+
+ return TRUE;
+}
+
+static EGLDeviceEXT
+xwl_eglstream_get_device(struct xwl_screen *xwl_screen)
+{
+ void **devices = NULL;
+ const char *exts[] = {
+ "EGL_KHR_stream",
+ "EGL_KHR_stream_producer_eglsurface",
+ };
+ int num_devices, i;
+ EGLDeviceEXT device = EGL_NO_DEVICE_EXT;
+
+ /* No device specified by the user, so find one ourselves */
+ devices = xwl_glamor_egl_get_devices(&num_devices);
+ if (!devices)
+ goto out;
+
+ for (i = 0; i < num_devices; i++) {
+ if (xwl_glamor_egl_device_has_egl_extensions(devices[i], exts,
+ ARRAY_SIZE(exts))) {
+ device = devices[i];
+ break;
+ }
+ }
+
+ free(devices);
+out:
+ if (!device)
+ ErrorF("glamor: No eglstream capable devices found\n");
+ return device;
+}
+
+void
+xwl_glamor_init_eglstream(struct xwl_screen *xwl_screen)
+{
+ struct xwl_eglstream_private *xwl_eglstream;
+ EGLDeviceEXT egl_device;
+
+ xwl_screen->eglstream_backend.is_available = FALSE;
+ egl_device = xwl_eglstream_get_device(xwl_screen);
+ if (egl_device == EGL_NO_DEVICE_EXT)
+ return;
+
+ if (!dixRegisterPrivateKey(&xwl_eglstream_private_key, PRIVATE_SCREEN, 0))
+ return;
+
+ xwl_eglstream = calloc(sizeof(*xwl_eglstream), 1);
+ if (!xwl_eglstream) {
+ ErrorF("Failed to allocate memory required to init EGLStream support\n");
+ return;
+ }
+
+ dixSetPrivate(&xwl_screen->screen->devPrivates,
+ &xwl_eglstream_private_key, xwl_eglstream);
+
+ xwl_eglstream->egl_device = egl_device;
+ xorg_list_init(&xwl_eglstream->pending_streams);
+
+ xwl_screen->eglstream_backend.init_egl = xwl_glamor_eglstream_init_egl;
+ xwl_screen->eglstream_backend.init_wl_registry = xwl_glamor_eglstream_init_wl_registry;
+ xwl_screen->eglstream_backend.has_wl_interfaces = xwl_glamor_eglstream_has_wl_interfaces;
+ xwl_screen->eglstream_backend.init_screen = xwl_glamor_eglstream_init_screen;
+ xwl_screen->eglstream_backend.get_wl_buffer_for_pixmap = xwl_glamor_eglstream_get_wl_buffer_for_pixmap;
+ xwl_screen->eglstream_backend.post_damage = xwl_glamor_eglstream_post_damage;
+ xwl_screen->eglstream_backend.allow_commits = xwl_glamor_eglstream_allow_commits;
+ xwl_screen->eglstream_backend.is_available = TRUE;
+}
diff --git a/xserver/hw/xwayland/xwayland-glamor-gbm.c b/xserver/hw/xwayland/xwayland-glamor-gbm.c
new file mode 100644
index 000000000..a211e0915
--- /dev/null
+++ b/xserver/hw/xwayland/xwayland-glamor-gbm.c
@@ -0,0 +1,1035 @@
+/*
+ * 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.h"
+
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <xf86drm.h>
+#include <drm_fourcc.h>
+
+#define MESA_EGL_NO_X11_HEADERS
+#include <gbm.h>
+#include <glamor_egl.h>
+
+#include <glamor.h>
+#include <glamor_context.h>
+#include <dri3.h>
+#include "drm-client-protocol.h"
+
+struct xwl_gbm_private {
+ char *device_name;
+ struct gbm_device *gbm;
+ struct wl_drm *drm;
+ struct zwp_linux_dmabuf_v1 *dmabuf;
+ 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 uint32_t
+wl_drm_format_for_depth(int depth)
+{
+ switch (depth) {
+ case 15:
+ return WL_DRM_FORMAT_XRGB1555;
+ case 16:
+ return WL_DRM_FORMAT_RGB565;
+ case 24:
+ return WL_DRM_FORMAT_XRGB8888;
+ case 30:
+ return WL_DRM_FORMAT_ARGB2101010;
+ default:
+ ErrorF("unexpected depth: %d\n", depth);
+ case 32:
+ return WL_DRM_FORMAT_ARGB8888;
+ }
+}
+
+static char
+is_fd_render_node(int fd)
+{
+ struct stat render;
+
+ if (fstat(fd, &render))
+ return 0;
+ if (!S_ISCHR(render.st_mode))
+ return 0;
+ if (render.st_rdev & 0x80)
+ return 1;
+
+ return 0;
+}
+
+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 = is_fd_render_node(fd);
+ 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 = malloc(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);
+
+ 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);
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ xwl_pixmap_set_private(pixmap, xwl_pixmap);
+
+ glamor_set_pixmap_texture(pixmap, xwl_pixmap->texture);
+ glamor_set_pixmap_type(pixmap, GLAMOR_TEXTURE_DRM);
+
+ return pixmap;
+}
+
+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;
+
+ if (width > 0 && height > 0 && depth >= 15 &&
+ (hint == 0 ||
+ hint == CREATE_PIXMAP_USAGE_BACKING_PIXMAP ||
+ hint == CREATE_PIXMAP_USAGE_SHARED)) {
+ 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;
+
+ 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_SCANOUT | GBM_BO_USE_RENDERING);
+ }
+
+ if (bo)
+ return xwl_glamor_gbm_create_pixmap_for_bo(screen, bo, depth);
+ }
+
+ return glamor_create_pixmap(screen, width, height, depth, hint);
+}
+
+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) {
+ 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 struct wl_buffer *
+xwl_glamor_gbm_get_wl_buffer_for_pixmap(PixmapPtr pixmap,
+ Bool *created)
+{
+ 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;
+ 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 it and inform caller if interested. */
+ if (created)
+ *created = FALSE;
+ return xwl_pixmap->buffer;
+ }
+
+ /* Buffer does not exist yet. Create now and inform caller if interested. */
+ if (created)
+ *created = TRUE;
+
+ if (!xwl_pixmap->bo)
+ return NULL;
+
+ 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_gbm->dmabuf && modifier != DRM_FORMAT_MOD_INVALID) {
+ struct zwp_linux_buffer_params_v1 *params;
+
+ params = zwp_linux_dmabuf_v1_create_params(xwl_gbm->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,
+ wl_drm_format_for_depth(pixmap->drawable.depth),
+ 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,
+ wl_drm_format_for_depth(pixmap->drawable.depth),
+ 0, gbm_bo_get_stride(xwl_pixmap->bo),
+ 0, 0,
+ 0, 0);
+ }
+
+ close(prime_fd);
+ 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, 0);
+#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_SCANOUT | 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;
+}
+
+_X_EXPORT Bool
+glamor_get_formats(ScreenPtr screen,
+ CARD32 *num_formats, CARD32 **formats)
+{
+ struct xwl_screen *xwl_screen = xwl_screen_get(screen);
+ struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen);
+ int i;
+
+ /* Explicitly zero the count as the caller may ignore the return value */
+ *num_formats = 0;
+
+ if (!xwl_gbm->dmabuf_capable || !xwl_gbm->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;
+}
+
+_X_EXPORT Bool
+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_gbm_private *xwl_gbm = xwl_gbm_get(xwl_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_gbm->dmabuf_capable || !xwl_gbm->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)
+ 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 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 = glamor_get_formats,
+ .get_modifiers = 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 (is_fd_render_node(xwl_gbm->drm_fd)) {
+ 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
+};
+
+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_drm_interface(struct xwl_screen *xwl_screen,
+ uint32_t id, uint32_t version)
+{
+ struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen);
+
+ if (version < 2)
+ return FALSE;
+
+ xwl_gbm->drm =
+ wl_registry_bind(xwl_screen->registry, id, &wl_drm_interface, 2);
+ wl_drm_add_listener(xwl_gbm->drm, &xwl_drm_listener, xwl_screen);
+ xwl_screen->expecting_event++;
+
+ return TRUE;
+}
+
+Bool
+xwl_screen_set_dmabuf_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 < 3)
+ return FALSE;
+
+ xwl_gbm->dmabuf =
+ wl_registry_bind(xwl_screen->registry, id, &zwp_linux_dmabuf_v1_interface, 3);
+ zwp_linux_dmabuf_v1_add_listener(xwl_gbm->dmabuf, &xwl_dmabuf_listener, xwl_screen);
+
+ 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_gbm_init_egl(struct xwl_screen *xwl_screen)
+{
+ struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen);
+ EGLint major, minor;
+ Bool egl_initialized = FALSE;
+ 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
+ };
+ 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;
+ }
+
+ egl_initialized = eglInitialize(xwl_screen->egl_display, &major, &minor);
+ if (!egl_initialized) {
+ ErrorF("eglInitialize() failed\n");
+ goto error;
+ }
+
+ 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_screen->egl_context == EGL_NO_CONTEXT) {
+ ErrorF("Failed to create EGL context\n");
+ goto error;
+ }
+
+ if (!eglMakeCurrent(xwl_screen->egl_display,
+ EGL_NO_SURFACE, EGL_NO_SURFACE,
+ xwl_screen->egl_context)) {
+ ErrorF("Failed to make EGL context current\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_context != EGL_NO_CONTEXT) {
+ eglDestroyContext(xwl_screen->egl_display, xwl_screen->egl_context);
+ xwl_screen->egl_context = EGL_NO_CONTEXT;
+ }
+
+ if (xwl_screen->egl_display != EGL_NO_DISPLAY) {
+ 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.is_available = TRUE;
+}
diff --git a/xserver/hw/xwayland/xwayland-glamor-xv.c b/xserver/hw/xwayland/xwayland-glamor-xv.c
index 65f93c693..8e0f8da94 100644
--- a/xserver/hw/xwayland/xwayland-glamor-xv.c
+++ b/xserver/hw/xwayland/xwayland-glamor-xv.c
@@ -213,7 +213,7 @@ xwl_glamor_xv_add_formats(XvAdaptorPtr pa)
void *moreSpace;
totFormat *= 2;
- moreSpace = XNFreallocarray(pFormat, totFormat,
+ moreSpace = xnfreallocarray(pFormat, totFormat,
sizeof(XvFormatRec));
pFormat = moreSpace;
pf = pFormat + numFormat;
diff --git a/xserver/hw/xwayland/xwayland-glamor.c b/xserver/hw/xwayland/xwayland-glamor.c
index 63f230369..7ea6def61 100644
--- a/xserver/hw/xwayland/xwayland-glamor.c
+++ b/xserver/hw/xwayland/xwayland-glamor.c
@@ -25,30 +25,14 @@
#include "xwayland.h"
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <xf86drm.h>
-
#define MESA_EGL_NO_X11_HEADERS
-#include <gbm.h>
#include <glamor_egl.h>
#include <glamor.h>
#include <glamor_context.h>
-#include <dri3.h>
-#include "drm-client-protocol.h"
-
-static DevPrivateKeyRec xwl_auth_state_private_key;
-
-struct xwl_pixmap {
- struct wl_buffer *buffer;
- struct gbm_bo *bo;
- void *image;
- unsigned int texture;
-};
static void
-xwl_glamor_egl_make_current(struct glamor_context *glamor_ctx)
+glamor_egl_make_current(struct glamor_context *glamor_ctx)
{
eglMakeCurrent(glamor_ctx->display, EGL_NO_SURFACE,
EGL_NO_SURFACE, EGL_NO_CONTEXT);
@@ -58,36 +42,14 @@ xwl_glamor_egl_make_current(struct glamor_context *glamor_ctx)
FatalError("Failed to make EGL context current\n");
}
-static uint32_t
-drm_format_for_depth(int depth)
+void
+xwl_glamor_egl_make_current(struct xwl_screen *xwl_screen)
{
- switch (depth) {
- case 15:
- return WL_DRM_FORMAT_XRGB1555;
- case 16:
- return WL_DRM_FORMAT_RGB565;
- case 24:
- return WL_DRM_FORMAT_XRGB8888;
- default:
- ErrorF("unexpected depth: %d\n", depth);
- case 32:
- return WL_DRM_FORMAT_ARGB8888;
- }
-}
+ if (lastGLContext == xwl_screen->glamor_ctx)
+ return;
-static uint32_t
-gbm_format_for_depth(int depth)
-{
- switch (depth) {
- case 16:
- return GBM_FORMAT_RGB565;
- case 24:
- return GBM_FORMAT_XRGB8888;
- default:
- ErrorF("unexpected depth: %d\n", depth);
- case 32:
- return GBM_FORMAT_ARGB8888;
- }
+ lastGLContext = xwl_screen->glamor_ctx;
+ xwl_screen->glamor_ctx->make_current(xwl_screen->glamor_ctx);
}
void
@@ -95,129 +57,74 @@ 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 = xwl_glamor_egl_make_current;
+ glamor_ctx->make_current = glamor_egl_make_current;
xwl_screen->glamor_ctx = glamor_ctx;
}
-static PixmapPtr
-xwl_glamor_create_pixmap_for_bo(ScreenPtr screen, struct gbm_bo *bo, int depth)
+void
+xwl_glamor_init_wl_registry(struct xwl_screen *xwl_screen,
+ struct wl_registry *registry,
+ uint32_t id, const char *interface,
+ uint32_t version)
{
- PixmapPtr pixmap;
- struct xwl_pixmap *xwl_pixmap;
- struct xwl_screen *xwl_screen = xwl_screen_get(screen);
-
- xwl_pixmap = malloc(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 == NULL) {
- free(xwl_pixmap);
- return NULL;
- }
-
- if (lastGLContext != xwl_screen->glamor_ctx) {
- lastGLContext = xwl_screen->glamor_ctx;
- xwl_glamor_egl_make_current(xwl_screen->glamor_ctx);
- }
-
- 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);
-
- 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);
- glBindTexture(GL_TEXTURE_2D, 0);
-
- xwl_pixmap_set_private(pixmap, xwl_pixmap);
-
- glamor_set_pixmap_texture(pixmap, xwl_pixmap->texture);
- glamor_set_pixmap_type(pixmap, GLAMOR_TEXTURE_DRM);
+ 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 */
+}
- return pixmap;
+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)
+xwl_glamor_pixmap_get_wl_buffer(PixmapPtr pixmap,
+ Bool *created)
{
struct xwl_screen *xwl_screen = xwl_screen_get(pixmap->drawable.pScreen);
- struct xwl_pixmap *xwl_pixmap = xwl_pixmap_get(pixmap);
- int prime_fd;
- if (xwl_pixmap->buffer)
- return xwl_pixmap->buffer;
+ if (xwl_screen->egl_backend->get_wl_buffer_for_pixmap)
+ return xwl_screen->egl_backend->get_wl_buffer_for_pixmap(pixmap,
+ created);
- prime_fd = gbm_bo_get_fd(xwl_pixmap->bo);
- if (prime_fd == -1)
- return NULL;
-
- xwl_pixmap->buffer =
- wl_drm_create_prime_buffer(xwl_screen->drm, prime_fd,
- pixmap->drawable.width,
- pixmap->drawable.height,
- drm_format_for_depth(pixmap->drawable.depth),
- 0, gbm_bo_get_stride(xwl_pixmap->bo),
- 0, 0,
- 0, 0);
-
- close(prime_fd);
-
- return xwl_pixmap->buffer;
+ return NULL;
}
-static PixmapPtr
-xwl_glamor_create_pixmap(ScreenPtr screen,
- int width, int height, int depth, unsigned int hint)
+void
+xwl_glamor_post_damage(struct xwl_window *xwl_window,
+ PixmapPtr pixmap, RegionPtr region)
{
- struct xwl_screen *xwl_screen = xwl_screen_get(screen);
- struct gbm_bo *bo;
-
- if (width > 0 && height > 0 && depth >= 15 &&
- (hint == 0 ||
- hint == CREATE_PIXMAP_USAGE_BACKING_PIXMAP ||
- hint == CREATE_PIXMAP_USAGE_SHARED)) {
- bo = gbm_bo_create(xwl_screen->gbm, width, height,
- gbm_format_for_depth(depth),
- GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
-
- if (bo)
- return xwl_glamor_create_pixmap_for_bo(screen, bo, depth);
- }
+ struct xwl_screen *xwl_screen = xwl_window->xwl_screen;
- return glamor_create_pixmap(screen, width, height, depth, hint);
+ if (xwl_screen->egl_backend->post_damage)
+ xwl_screen->egl_backend->post_damage(xwl_window, pixmap, region);
}
-static Bool
-xwl_glamor_destroy_pixmap(PixmapPtr pixmap)
+Bool
+xwl_glamor_allow_commits(struct xwl_window *xwl_window)
{
- 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) {
- if (xwl_pixmap->buffer)
- wl_buffer_destroy(xwl_pixmap->buffer);
-
- eglDestroyImageKHR(xwl_screen->egl_display, xwl_pixmap->image);
- gbm_bo_destroy(xwl_pixmap->bo);
- free(xwl_pixmap);
- }
+ struct xwl_screen *xwl_screen = xwl_window->xwl_screen;
- return glamor_destroy_pixmap(pixmap);
+ if (xwl_screen->egl_backend->allow_commits)
+ return xwl_screen->egl_backend->allow_commits(xwl_window);
+ else
+ return TRUE;
}
static Bool
@@ -239,12 +146,9 @@ xwl_glamor_create_screen_resources(ScreenPtr screen)
fbCreatePixmap(screen, 0, 0, screen->rootDepth, 0);
}
else {
- screen->devPrivate =
- xwl_glamor_create_pixmap(screen, screen->width, screen->height,
- screen->rootDepth,
- CREATE_PIXMAP_USAGE_BACKING_PIXMAP);
- if (screen->devPrivate)
- glamor_set_screen_pixmap(screen->devPrivate, NULL);
+ screen->devPrivate = screen->CreatePixmap(
+ screen, screen->width, screen->height, screen->rootDepth,
+ CREATE_PIXMAP_USAGE_BACKING_PIXMAP);
}
SetRootClip(screen, xwl_screen->root_clip_mode);
@@ -252,367 +156,105 @@ xwl_glamor_create_screen_resources(ScreenPtr screen)
return screen->devPrivate != NULL;
}
-static char
-is_fd_render_node(int fd)
-{
- struct stat render;
-
- if (fstat(fd, &render))
- return 0;
- if (!S_ISCHR(render.st_mode))
- return 0;
- if (render.st_rdev & 0x80)
- return 1;
-
- return 0;
-}
-
-static void
-xwl_drm_init_egl(struct xwl_screen *xwl_screen)
-{
- EGLint major, minor;
- const char *version;
- 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
- };
-
- if (xwl_screen->egl_display)
- return;
-
- xwl_screen->expecting_event--;
-
- xwl_screen->gbm = gbm_create_device(xwl_screen->drm_fd);
- if (xwl_screen->gbm == NULL) {
- ErrorF("couldn't get display device\n");
- return;
- }
-
- xwl_screen->egl_display = glamor_egl_get_display(EGL_PLATFORM_GBM_MESA,
- xwl_screen->gbm);
- if (xwl_screen->egl_display == EGL_NO_DISPLAY) {
- ErrorF("glamor_egl_get_display() failed\n");
- return;
- }
-
- if (!eglInitialize(xwl_screen->egl_display, &major, &minor)) {
- ErrorF("eglInitialize() failed\n");
- return;
- }
-
- eglBindAPI(EGL_OPENGL_API);
-
- version = eglQueryString(xwl_screen->egl_display, EGL_VERSION);
- ErrorF("glamor: EGL version %s:\n", version);
-
- xwl_screen->egl_context = eglCreateContext(xwl_screen->egl_display,
- NULL, EGL_NO_CONTEXT, config_attribs_core);
- if (!xwl_screen->egl_context)
- xwl_screen->egl_context = eglCreateContext(xwl_screen->egl_display,
- NULL, EGL_NO_CONTEXT, NULL);
-
- if (xwl_screen->egl_context == EGL_NO_CONTEXT) {
- ErrorF("Failed to create EGL context\n");
- return;
- }
-
- if (!eglMakeCurrent(xwl_screen->egl_display,
- EGL_NO_SURFACE, EGL_NO_SURFACE,
- xwl_screen->egl_context)) {
- ErrorF("Failed to make EGL context current\n");
- return;
- }
-
- if (!epoxy_has_gl_extension("GL_OES_EGL_image")) {
- ErrorF("GL_OES_EGL_image not available\n");
- return;
- }
-
- return;
-}
-
-static void
-xwl_drm_handle_device(void *data, struct wl_drm *drm, const char *device)
-{
- struct xwl_screen *xwl_screen = data;
- drm_magic_t magic;
-
- xwl_screen->device_name = strdup(device);
- if (!xwl_screen->device_name)
- return;
-
- xwl_screen->drm_fd = open(xwl_screen->device_name, O_RDWR | O_CLOEXEC);
- if (xwl_screen->drm_fd == -1) {
- ErrorF("wayland-egl: could not open %s (%s)\n",
- xwl_screen->device_name, strerror(errno));
- return;
- }
-
- if (is_fd_render_node(xwl_screen->drm_fd)) {
- xwl_screen->fd_render_node = 1;
- xwl_drm_init_egl(xwl_screen);
- } else {
- drmGetMagic(xwl_screen->drm_fd, &magic);
- wl_drm_authenticate(xwl_screen->drm, magic);
- }
-}
-
-static void
-xwl_drm_handle_format(void *data, struct wl_drm *drm, uint32_t format)
-{
- struct xwl_screen *xwl_screen = data;
-
- switch (format) {
- case WL_DRM_FORMAT_ARGB8888:
- xwl_screen->formats |= XWL_FORMAT_ARGB8888;
- break;
- case WL_DRM_FORMAT_XRGB8888:
- xwl_screen->formats |= XWL_FORMAT_XRGB8888;
- break;
- case WL_DRM_FORMAT_RGB565:
- xwl_screen->formats |= XWL_FORMAT_RGB565;
- break;
- }
-}
-
-static void
-xwl_drm_handle_authenticated(void *data, struct wl_drm *drm)
-{
- struct xwl_screen *xwl_screen = data;
-
- if (!xwl_screen->egl_display)
- xwl_drm_init_egl(xwl_screen);
-}
-
-static void
-xwl_drm_handle_capabilities(void *data, struct wl_drm *drm, uint32_t value)
-{
- struct xwl_screen *xwl_screen = data;
-
- xwl_screen->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_init_glamor(struct xwl_screen *xwl_screen,
- uint32_t id, uint32_t version)
-{
- if (version < 2)
- return FALSE;
-
- xwl_screen->drm =
- wl_registry_bind(xwl_screen->registry, id, &wl_drm_interface, 2);
- wl_drm_add_listener(xwl_screen->drm, &xwl_drm_listener, xwl_screen);
- xwl_screen->expecting_event++;
-
- return TRUE;
-}
-
int
-glamor_egl_dri3_fd_name_from_tex(ScreenPtr screen,
- PixmapPtr pixmap,
- unsigned int tex,
- Bool want_name, CARD16 *stride, CARD32 *size)
+glamor_egl_fd_name_from_pixmap(ScreenPtr screen,
+ PixmapPtr pixmap,
+ CARD16 *stride, CARD32 *size)
{
return 0;
}
-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)
+void
+xwl_glamor_init_backends(struct xwl_screen *xwl_screen, Bool use_eglstream)
{
- dixSetPrivate(&pClient->devPrivates, &xwl_auth_state_private_key, NULL);
- if (state) {
- wl_callback_destroy(state->callback);
- free(state);
- }
+#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 void
-xwl_auth_state_client_callback(CallbackListPtr *pcbl, void *unused, void *data)
+static Bool
+xwl_glamor_select_gbm_backend(struct xwl_screen *xwl_screen)
{
- NewClientInfoRec *clientinfo = (NewClientInfoRec *) data;
- ClientPtr pClient = clientinfo->client;
- struct xwl_auth_state *state;
-
- switch (pClient->clientState) {
- case ClientStateGone:
- case ClientStateRetained:
- state = dixLookupPrivate(&pClient->devPrivates, &xwl_auth_state_private_key);
- free_xwl_auth_state(pClient, state);
- break;
- default:
- break;
+#ifdef 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
-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);
+ return FALSE;
}
-static const struct wl_callback_listener sync_listener = {
- sync_callback
-};
-
-static int
-xwl_dri3_open_client(ClientPtr client,
- ScreenPtr screen,
- RRProviderPtr provider,
- int *pfd)
+static Bool
+xwl_glamor_select_eglstream_backend(struct xwl_screen *xwl_screen)
{
- struct xwl_screen *xwl_screen = xwl_screen_get(screen);
- struct xwl_auth_state *state;
- drm_magic_t magic;
- int fd;
-
- fd = open(xwl_screen->device_name, O_RDWR | O_CLOEXEC);
- if (fd < 0)
- return BadAlloc;
- if (xwl_screen->fd_render_node) {
- *pfd = fd;
- return Success;
- }
-
- state = malloc(sizeof *state);
- if (state == NULL) {
- close(fd);
- return BadAlloc;
+#ifdef XWL_HAS_EGLSTREAM
+ if (xwl_screen->eglstream_backend.is_available &&
+ xwl_glamor_has_wl_interfaces(xwl_screen, &xwl_screen->eglstream_backend)) {
+ ErrorF("glamor: Using nvidia's EGLStream interface, direct rendering impossible.\n");
+ ErrorF("glamor: Performance may be affected. Ask your vendor to support GBM!\n");
+ xwl_screen->egl_backend = &xwl_screen->eglstream_backend;
+ return TRUE;
}
+ else
+ ErrorF("Missing Wayland requirements for glamor EGLStream backend\n");
+#endif
- state->client = client;
- state->fd = fd;
-
- if (drmGetMagic(state->fd, &magic) < 0) {
- close(state->fd);
- free(state);
- return BadMatch;
- }
-
- wl_drm_authenticate(xwl_screen->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;
+ return FALSE;
}
-static PixmapPtr
-xwl_dri3_pixmap_from_fd(ScreenPtr screen, int fd,
- CARD16 width, CARD16 height, CARD16 stride,
- CARD8 depth, CARD8 bpp)
+void
+xwl_glamor_select_backend(struct xwl_screen *xwl_screen, Bool use_eglstream)
{
- struct xwl_screen *xwl_screen = xwl_screen_get(screen);
- struct gbm_import_fd_data data;
- struct gbm_bo *bo;
- PixmapPtr pixmap;
-
- if (width == 0 || height == 0 ||
- depth < 15 || bpp != BitsPerPixel(depth) || stride < width * bpp / 8)
- return NULL;
-
- data.fd = fd;
- data.width = width;
- data.height = height;
- data.stride = stride;
- data.format = gbm_format_for_depth(depth);
- bo = gbm_bo_import(xwl_screen->gbm, GBM_BO_IMPORT_FD, &data,
- GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
- if (bo == NULL)
- return NULL;
-
- pixmap = xwl_glamor_create_pixmap_for_bo(screen, bo, depth);
- if (pixmap == NULL) {
- gbm_bo_destroy(bo);
- return NULL;
+ 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);
}
-
- return pixmap;
-}
-
-static int
-xwl_dri3_fd_from_pixmap(ScreenPtr screen, PixmapPtr pixmap,
- CARD16 *stride, CARD32 *size)
-{
- struct xwl_pixmap *xwl_pixmap;
-
- xwl_pixmap = xwl_pixmap_get(pixmap);
-
- *stride = gbm_bo_get_stride(xwl_pixmap->bo);
- *size = pixmap->drawable.width * *stride;
-
- return gbm_bo_get_fd(xwl_pixmap->bo);
}
-static dri3_screen_info_rec xwl_dri3_info = {
- .version = 1,
- .open = NULL,
- .pixmap_from_fd = xwl_dri3_pixmap_from_fd,
- .fd_from_pixmap = xwl_dri3_fd_from_pixmap,
- .open_client = xwl_dri3_open_client,
-};
-
Bool
xwl_glamor_init(struct xwl_screen *xwl_screen)
{
ScreenPtr screen = xwl_screen->screen;
+ const char *no_glamor_env;
- if (xwl_screen->egl_context == EGL_NO_CONTEXT) {
- ErrorF("Disabling glamor and dri3, EGL setup failed\n");
- return FALSE;
- }
-
- if (!glamor_init(xwl_screen->screen, GLAMOR_USE_EGL_SCREEN)) {
- ErrorF("Failed to initialize glamor\n");
+ 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 (!dri3_screen_init(xwl_screen->screen, &xwl_dri3_info)) {
- ErrorF("Failed to initialize dri3\n");
+ if (!xwl_screen->egl_backend->init_egl(xwl_screen)) {
+ ErrorF("EGL setup failed, disabling glamor\n");
return FALSE;
}
- if (!dixRegisterPrivateKey(&xwl_auth_state_private_key, PRIVATE_CLIENT, 0)) {
- ErrorF("Failed to register private key\n");
+ if (!glamor_init(xwl_screen->screen, GLAMOR_USE_EGL_SCREEN)) {
+ ErrorF("Failed to initialize glamor\n");
return FALSE;
}
- if (!AddCallback(&ClientStateCallback, xwl_auth_state_client_callback, NULL)) {
- ErrorF("Failed to add client state callback\n");
+ 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;
- screen->CreatePixmap = xwl_glamor_create_pixmap;
- screen->DestroyPixmap = xwl_glamor_destroy_pixmap;
#ifdef XV
if (!xwl_glamor_xv_init(screen))
diff --git a/xserver/hw/xwayland/xwayland-input.c b/xserver/hw/xwayland/xwayland-input.c
index d96e6f2a4..fbbcb39cc 100644
--- a/xserver/hw/xwayland/xwayland-input.c
+++ b/xserver/hw/xwayland/xwayland-input.c
@@ -34,12 +34,14 @@
#include <inpututils.h>
#include <mipointer.h>
#include <mipointrst.h>
+#include <misc.h>
+#include "tablet-unstable-v2-client-protocol.h"
-/* Copied from mipointer.c */
-#define MIPOINTER(dev) \
- (IsFloating(dev) ? \
- (miPointerPtr)dixLookupPrivate(&(dev)->devPrivates, miPointerPrivKey): \
- (miPointerPtr)dixLookupPrivate(&(GetMaster(dev, MASTER_POINTER))->devPrivates, miPointerPrivKey))
+struct axis_discrete_pending {
+ struct xorg_list l;
+ uint32_t axis;
+ int32_t discrete;
+};
struct sync_pending {
struct xorg_list l;
@@ -62,6 +64,12 @@ static void
xwl_seat_destroy_confined_pointer(struct xwl_seat *xwl_seat);
static void
+init_tablet_manager_seat(struct xwl_screen *xwl_screen,
+ struct xwl_seat *xwl_seat);
+static void
+release_tablet_manager_seat(struct xwl_seat *xwl_seat);
+
+static void
xwl_pointer_control(DeviceIntPtr device, PtrCtrl *ctrl)
{
/* Nothing to do, dix handles all settings */
@@ -287,6 +295,75 @@ xwl_touch_proc(DeviceIntPtr device, int what)
#undef NTOUCHPOINTS
}
+static int
+xwl_tablet_proc(DeviceIntPtr device, int what)
+{
+#define NBUTTONS 9
+#define NAXES 6
+ Atom btn_labels[NBUTTONS] = { 0 };
+ Atom axes_labels[NAXES] = { 0 };
+ BYTE map[NBUTTONS + 1] = { 0 };
+ int i;
+
+ switch (what) {
+ case DEVICE_INIT:
+ device->public.on = FALSE;
+
+ for (i = 1; i <= NBUTTONS; i++)
+ map[i] = i;
+
+ axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_X);
+ axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_Y);
+ axes_labels[2] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_PRESSURE);
+ axes_labels[3] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_TILT_X);
+ axes_labels[4] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_TILT_Y);
+ axes_labels[5] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_WHEEL);
+
+ if (!InitValuatorClassDeviceStruct(device, NAXES, axes_labels,
+ GetMotionHistorySize(), Absolute))
+ return BadValue;
+
+ /* Valuators - match the xf86-input-wacom ranges */
+ InitValuatorAxisStruct(device, 0, axes_labels[0],
+ 0, 262143, 10000, 0, 10000, Absolute);
+ InitValuatorAxisStruct(device, 1, axes_labels[1],
+ 0, 262143, 10000, 0, 10000, Absolute);
+ /* pressure */
+ InitValuatorAxisStruct(device, 2, axes_labels[2],
+ 0, 65535, 1, 0, 1, Absolute);
+ /* tilt x */
+ InitValuatorAxisStruct(device, 3, axes_labels[3],
+ -64, 63, 57, 0, 57, Absolute);
+ /* tilt y */
+ InitValuatorAxisStruct(device, 4, axes_labels[4],
+ -64, 63, 57, 0, 57, Absolute);
+ /* abs wheel (airbrush) or rotation (artpen) */
+ InitValuatorAxisStruct(device, 5, axes_labels[5],
+ -900, 899, 1, 0, 1, Absolute);
+
+ if (!InitPtrFeedbackClassDeviceStruct(device, xwl_pointer_control))
+ return BadValue;
+
+ if (!InitButtonClassDeviceStruct(device, NBUTTONS, btn_labels, map))
+ return BadValue;
+
+ return Success;
+
+ case DEVICE_ON:
+ device->public.on = TRUE;
+ return Success;
+
+ case DEVICE_OFF:
+ case DEVICE_CLOSE:
+ device->public.on = FALSE;
+ return Success;
+ }
+
+ return BadMatch;
+#undef NAXES
+#undef NBUTTONS
+}
+
static void
pointer_handle_enter(void *data, struct wl_pointer *pointer,
uint32_t serial, struct wl_surface *surface,
@@ -347,9 +424,9 @@ pointer_handle_enter(void *data, struct wl_pointer *pointer,
* of our surfaces might not have been shown. In that case we'll
* have a cursor surface frame callback pending which we need to
* clear so that we can continue submitting new cursor frames. */
- if (xwl_seat->cursor_frame_cb) {
- wl_callback_destroy(xwl_seat->cursor_frame_cb);
- xwl_seat->cursor_frame_cb = NULL;
+ if (xwl_seat->cursor.frame_cb) {
+ wl_callback_destroy(xwl_seat->cursor.frame_cb);
+ xwl_seat->cursor.frame_cb = NULL;
xwl_seat_set_cursor(xwl_seat);
}
@@ -494,6 +571,8 @@ pointer_handle_axis(void *data, struct wl_pointer *pointer,
int index;
const int divisor = 10;
ValuatorMask mask;
+ struct axis_discrete_pending *pending = NULL;
+ struct axis_discrete_pending *iter;
switch (axis) {
case WL_POINTER_AXIS_VERTICAL_SCROLL:
@@ -506,8 +585,22 @@ pointer_handle_axis(void *data, struct wl_pointer *pointer,
return;
}
+ xorg_list_for_each_entry(iter, &xwl_seat->axis_discrete_pending, l) {
+ if (iter->axis == axis) {
+ pending = iter;
+ break;
+ }
+ }
+
valuator_mask_zero(&mask);
- valuator_mask_set_double(&mask, index, wl_fixed_to_double(value) / divisor);
+
+ if (pending) {
+ valuator_mask_set(&mask, index, pending->discrete);
+ xorg_list_del(&pending->l);
+ free(pending);
+ } else {
+ valuator_mask_set_double(&mask, index, wl_fixed_to_double(value) / divisor);
+ }
QueuePointerEvents(xwl_seat->pointer, MotionNotify, 0, POINTER_RELATIVE, &mask);
}
@@ -537,6 +630,16 @@ static void
pointer_handle_axis_discrete(void *data, struct wl_pointer *wl_pointer,
uint32_t axis, int32_t discrete)
{
+ struct xwl_seat *xwl_seat = data;
+
+ struct axis_discrete_pending *pending = malloc(sizeof *pending);
+ if (!pending)
+ return;
+
+ pending->axis = axis;
+ pending->discrete = discrete;
+
+ xorg_list_add(&pending->l, &xwl_seat->axis_discrete_pending);
}
static const struct wl_pointer_listener pointer_listener = {
@@ -864,9 +967,9 @@ touch_handle_down(void *data, struct wl_touch *wl_touch,
if (surface == NULL)
return;
- xwl_touch = calloc(sizeof *xwl_touch, 1);
+ xwl_touch = calloc(1, sizeof *xwl_touch);
if (xwl_touch == NULL) {
- ErrorF("touch_handle_down ENOMEM");
+ ErrorF("%s: ENOMEM\n", __func__);
return;
}
@@ -945,6 +1048,84 @@ static const struct wl_touch_listener touch_listener = {
touch_handle_cancel
};
+static struct xwl_seat *
+find_matching_seat(DeviceIntPtr device)
+{
+ DeviceIntPtr dev;
+
+ for (dev = inputInfo.devices; dev; dev = dev->next)
+ if (dev->deviceProc == xwl_keyboard_proc &&
+ device == GetMaster(dev, MASTER_KEYBOARD))
+ return (struct xwl_seat *) dev->public.devicePrivate;
+
+ return NULL;
+}
+
+static void
+release_grab(struct xwl_seat *xwl_seat)
+{
+ if (xwl_seat->keyboard_grab)
+ zwp_xwayland_keyboard_grab_v1_destroy(xwl_seat->keyboard_grab);
+ xwl_seat->keyboard_grab = NULL;
+}
+
+static void
+set_grab(struct xwl_seat *xwl_seat, struct xwl_window *xwl_window)
+{
+ struct xwl_screen *xwl_screen;
+
+ if (!xwl_window)
+ return;
+
+ /* We already have a grab */
+ if (xwl_seat->keyboard_grab)
+ release_grab (xwl_seat);
+
+ xwl_screen = xwl_seat->xwl_screen;
+ xwl_seat->keyboard_grab =
+ zwp_xwayland_keyboard_grab_manager_v1_grab_keyboard(xwl_screen->wp_grab,
+ xwl_window->surface,
+ xwl_seat->seat);
+}
+
+static void
+xwl_keyboard_activate_grab(DeviceIntPtr device, GrabPtr grab, TimeStamp time, Bool passive)
+{
+ struct xwl_seat *xwl_seat = device->public.devicePrivate;
+
+ /* We are not interested in passive grabs */
+ if (!passive) {
+ /* If the device is the MASTER_KEYBOARD, we don't have an xwl_seat */
+ if (xwl_seat == NULL)
+ xwl_seat = find_matching_seat(device);
+ if (xwl_seat)
+ set_grab(xwl_seat, xwl_window_from_window(grab->window));
+ }
+
+ ActivateKeyboardGrab(device, grab, time, passive);
+}
+
+static void
+xwl_keyboard_deactivate_grab(DeviceIntPtr device)
+{
+ struct xwl_seat *xwl_seat = device->public.devicePrivate;
+
+ /* If the device is the MASTER_KEYBOARD, we don't have an xwl_seat */
+ if (xwl_seat == NULL)
+ xwl_seat = find_matching_seat(device);
+ if (xwl_seat)
+ release_grab (xwl_seat);
+
+ DeactivateKeyboardGrab(device);
+}
+
+static void
+setup_keyboard_grab_handler (DeviceIntPtr device)
+{
+ device->deviceGrab.ActivateGrab = xwl_keyboard_activate_grab;
+ device->deviceGrab.DeactivateGrab = xwl_keyboard_deactivate_grab;
+}
+
static DeviceIntPtr
add_device(struct xwl_seat *xwl_seat,
const char *driver, DeviceProc device_proc)
@@ -1033,6 +1214,8 @@ release_relative_pointer(struct xwl_seat *xwl_seat)
static void
init_keyboard(struct xwl_seat *xwl_seat)
{
+ DeviceIntPtr master;
+
xwl_seat->wl_keyboard = wl_seat_get_keyboard(xwl_seat->seat);
wl_keyboard_add_listener(xwl_seat->wl_keyboard,
&keyboard_listener, xwl_seat);
@@ -1044,11 +1227,19 @@ init_keyboard(struct xwl_seat *xwl_seat)
}
EnableDevice(xwl_seat->keyboard, TRUE);
xwl_seat->keyboard->key->xkbInfo->checkRepeat = keyboard_check_repeat;
+
+ if (xwl_seat->xwl_screen->wp_grab) {
+ /* We have Xwayland grab protocol supported by the compositor */
+ master = GetMaster(xwl_seat->keyboard, MASTER_KEYBOARD);
+ if (master)
+ setup_keyboard_grab_handler(master);
+ }
}
static void
release_keyboard(struct xwl_seat *xwl_seat)
{
+ release_grab(xwl_seat);
wl_keyboard_release(xwl_seat->wl_keyboard);
xwl_seat->wl_keyboard = NULL;
@@ -1126,13 +1317,38 @@ static const struct wl_seat_listener seat_listener = {
};
static void
+xwl_cursor_init(struct xwl_cursor *xwl_cursor, struct xwl_screen *xwl_screen,
+ void (* update_proc)(struct xwl_cursor *))
+{
+ xwl_cursor->surface = wl_compositor_create_surface(xwl_screen->compositor);
+ xwl_cursor->update_proc = update_proc;
+ xwl_cursor->frame_cb = NULL;
+ xwl_cursor->needs_update = FALSE;
+}
+
+static void
+xwl_cursor_release(struct xwl_cursor *xwl_cursor)
+{
+ wl_surface_destroy(xwl_cursor->surface);
+ if (xwl_cursor->frame_cb)
+ wl_callback_destroy(xwl_cursor->frame_cb);
+}
+
+static void
+xwl_seat_update_cursor(struct xwl_cursor *xwl_cursor)
+{
+ struct xwl_seat *xwl_seat = wl_container_of(xwl_cursor, xwl_seat, cursor);
+ xwl_seat_set_cursor(xwl_seat);
+}
+
+static void
create_input_device(struct xwl_screen *xwl_screen, uint32_t id, uint32_t version)
{
struct xwl_seat *xwl_seat;
- xwl_seat = calloc(sizeof *xwl_seat, 1);
+ xwl_seat = calloc(1, sizeof *xwl_seat);
if (xwl_seat == NULL) {
- ErrorF("create_input ENOMEM\n");
+ ErrorF("%s: ENOMEM\n", __func__);
return;
}
@@ -1144,11 +1360,16 @@ create_input_device(struct xwl_screen *xwl_screen, uint32_t id, uint32_t version
&wl_seat_interface, min(version, 5));
xwl_seat->id = id;
- xwl_seat->cursor = wl_compositor_create_surface(xwl_screen->compositor);
+ xwl_cursor_init(&xwl_seat->cursor, xwl_seat->xwl_screen,
+ xwl_seat_update_cursor);
wl_seat_add_listener(xwl_seat->seat, &seat_listener, xwl_seat);
+
+ init_tablet_manager_seat(xwl_screen, xwl_seat);
+
wl_array_init(&xwl_seat->keys);
xorg_list_init(&xwl_seat->touches);
+ xorg_list_init(&xwl_seat->axis_discrete_pending);
xorg_list_init(&xwl_seat->sync_pending);
}
@@ -1157,6 +1378,7 @@ xwl_seat_destroy(struct xwl_seat *xwl_seat)
{
struct xwl_touch *xwl_touch, *next_xwl_touch;
struct sync_pending *p, *npd;
+ struct axis_discrete_pending *ad, *ad_next;
xorg_list_for_each_entry_safe(xwl_touch, next_xwl_touch,
&xwl_seat->touches, link_touch) {
@@ -1169,15 +1391,1035 @@ xwl_seat_destroy(struct xwl_seat *xwl_seat)
free (p);
}
+ xorg_list_for_each_entry_safe(ad, ad_next, &xwl_seat->axis_discrete_pending, l) {
+ xorg_list_del(&ad->l);
+ free(ad);
+ }
+
+ release_tablet_manager_seat(xwl_seat);
+
+ release_grab(xwl_seat);
wl_seat_destroy(xwl_seat->seat);
- wl_surface_destroy(xwl_seat->cursor);
- if (xwl_seat->cursor_frame_cb)
- wl_callback_destroy(xwl_seat->cursor_frame_cb);
+ xwl_cursor_release(&xwl_seat->cursor);
wl_array_release(&xwl_seat->keys);
free(xwl_seat);
}
static void
+tablet_handle_name(void *data, struct zwp_tablet_v2 *tablet, const char *name)
+{
+}
+
+static void
+tablet_handle_id(void *data, struct zwp_tablet_v2 *tablet, uint32_t vid,
+ uint32_t pid)
+{
+}
+
+static void
+tablet_handle_path(void *data, struct zwp_tablet_v2 *tablet, const char *path)
+{
+}
+
+static void
+tablet_handle_done(void *data, struct zwp_tablet_v2 *tablet)
+{
+ struct xwl_tablet *xwl_tablet = data;
+ struct xwl_seat *xwl_seat = xwl_tablet->seat;
+
+ if (xwl_seat->stylus == NULL) {
+ xwl_seat->stylus = add_device(xwl_seat, "xwayland-stylus", xwl_tablet_proc);
+ ActivateDevice(xwl_seat->stylus, TRUE);
+ }
+ EnableDevice(xwl_seat->stylus, TRUE);
+
+ if (xwl_seat->eraser == NULL) {
+ xwl_seat->eraser = add_device(xwl_seat, "xwayland-eraser", xwl_tablet_proc);
+ ActivateDevice(xwl_seat->eraser, TRUE);
+ }
+ EnableDevice(xwl_seat->eraser, TRUE);
+
+ if (xwl_seat->puck == NULL) {
+ xwl_seat->puck = add_device(xwl_seat, "xwayland-cursor", xwl_tablet_proc);
+ ActivateDevice(xwl_seat->puck, TRUE);
+ }
+ EnableDevice(xwl_seat->puck, TRUE);
+}
+
+static void
+tablet_handle_removed(void *data, struct zwp_tablet_v2 *tablet)
+{
+ struct xwl_tablet *xwl_tablet = data;
+ struct xwl_seat *xwl_seat = xwl_tablet->seat;
+
+ xorg_list_del(&xwl_tablet->link);
+
+ /* The tablet is merely disabled, not removed. The next tablet
+ will re-use the same X devices */
+ if (xorg_list_is_empty(&xwl_seat->tablets)) {
+ if (xwl_seat->stylus)
+ DisableDevice(xwl_seat->stylus, TRUE);
+ if (xwl_seat->eraser)
+ DisableDevice(xwl_seat->eraser, TRUE);
+ if (xwl_seat->puck)
+ DisableDevice(xwl_seat->puck, TRUE);
+ /* pads are removed separately */
+ }
+
+ zwp_tablet_v2_destroy(tablet);
+ free(xwl_tablet);
+}
+
+static const struct zwp_tablet_v2_listener tablet_listener = {
+ tablet_handle_name,
+ tablet_handle_id,
+ tablet_handle_path,
+ tablet_handle_done,
+ tablet_handle_removed
+};
+
+static void
+tablet_tool_receive_type(void *data, struct zwp_tablet_tool_v2 *tool,
+ uint32_t type)
+{
+ struct xwl_tablet_tool *xwl_tablet_tool = data;
+ struct xwl_seat *xwl_seat = xwl_tablet_tool->seat;
+
+ switch (type) {
+ case ZWP_TABLET_TOOL_V2_TYPE_ERASER:
+ xwl_tablet_tool->xdevice = xwl_seat->eraser;
+ break;
+ case ZWP_TABLET_TOOL_V2_TYPE_MOUSE:
+ case ZWP_TABLET_TOOL_V2_TYPE_LENS:
+ xwl_tablet_tool->xdevice = xwl_seat->puck;
+ break;
+ default:
+ xwl_tablet_tool->xdevice = xwl_seat->stylus;
+ break;
+ }
+}
+
+static void
+tablet_tool_receive_hardware_serial(void *data, struct zwp_tablet_tool_v2 *tool,
+ uint32_t hi, uint32_t low)
+{
+}
+
+static void
+tablet_tool_receive_hardware_id_wacom(void *data, struct zwp_tablet_tool_v2 *tool,
+ uint32_t hi, uint32_t low)
+{
+}
+
+static void
+tablet_tool_receive_capability(void *data, struct zwp_tablet_tool_v2 *tool,
+ uint32_t capability)
+{
+}
+
+static void
+tablet_tool_receive_done(void *data, struct zwp_tablet_tool_v2 *tool)
+{
+}
+
+static void
+tablet_tool_receive_removed(void *data, struct zwp_tablet_tool_v2 *tool)
+{
+ struct xwl_tablet_tool *xwl_tablet_tool = data;
+
+ xorg_list_del(&xwl_tablet_tool->link);
+ xwl_cursor_release(&xwl_tablet_tool->cursor);
+ zwp_tablet_tool_v2_destroy(tool);
+ free(xwl_tablet_tool);
+}
+
+static void
+tablet_tool_proximity_in(void *data, struct zwp_tablet_tool_v2 *tool,
+ uint32_t serial, struct zwp_tablet_v2 *tablet,
+ struct wl_surface *wl_surface)
+{
+ struct xwl_tablet_tool *xwl_tablet_tool = data;
+ struct xwl_seat *xwl_seat = xwl_tablet_tool->seat;
+
+ /* There's a race here where if we create and then immediately
+ * destroy a surface, we might end up in a state where the Wayland
+ * compositor sends us an event for a surface that doesn't exist.
+ *
+ * Don't process enter events in this case.
+ *
+ * see pointer_handle_enter()
+ */
+ if (wl_surface == NULL)
+ return;
+
+ xwl_tablet_tool->proximity_in_serial = serial;
+ xwl_seat->tablet_focus_window = wl_surface_get_user_data(wl_surface);
+
+ xwl_tablet_tool_set_cursor(xwl_tablet_tool);
+}
+
+static void
+tablet_tool_proximity_out(void *data, struct zwp_tablet_tool_v2 *tool)
+{
+ struct xwl_tablet_tool *xwl_tablet_tool = data;
+ struct xwl_seat *xwl_seat = xwl_tablet_tool->seat;
+
+ xwl_tablet_tool->proximity_in_serial = 0;
+ xwl_seat->tablet_focus_window = NULL;
+
+ xwl_tablet_tool->pressure = 0;
+ xwl_tablet_tool->tilt_x = 0;
+ xwl_tablet_tool->tilt_y = 0;
+ xwl_tablet_tool->rotation = 0;
+ xwl_tablet_tool->slider = 0;
+}
+
+static void
+tablet_tool_down(void *data, struct zwp_tablet_tool_v2 *tool, uint32_t serial)
+{
+ struct xwl_tablet_tool *xwl_tablet_tool = data;
+ struct xwl_seat *xwl_seat = xwl_tablet_tool->seat;
+ ValuatorMask mask;
+
+ xwl_seat->xwl_screen->serial = serial;
+
+ valuator_mask_zero(&mask);
+ QueuePointerEvents(xwl_tablet_tool->xdevice, ButtonPress, 1, 0, &mask);
+}
+
+static void
+tablet_tool_up(void *data, struct zwp_tablet_tool_v2 *tool)
+{
+ struct xwl_tablet_tool *xwl_tablet_tool = data;
+ ValuatorMask mask;
+
+ valuator_mask_zero(&mask);
+ QueuePointerEvents(xwl_tablet_tool->xdevice, ButtonRelease, 1, 0, &mask);
+}
+
+static void
+tablet_tool_motion(void *data, struct zwp_tablet_tool_v2 *tool,
+ wl_fixed_t x, wl_fixed_t y)
+{
+ struct xwl_tablet_tool *xwl_tablet_tool = data;
+ struct xwl_seat *xwl_seat = xwl_tablet_tool->seat;
+ int32_t dx, dy;
+ double sx = wl_fixed_to_double(x);
+ double sy = wl_fixed_to_double(y);
+
+ if (!xwl_seat->tablet_focus_window)
+ return;
+
+ dx = xwl_seat->tablet_focus_window->window->drawable.x;
+ dy = xwl_seat->tablet_focus_window->window->drawable.y;
+
+ xwl_tablet_tool->x = (double) dx + sx;
+ xwl_tablet_tool->y = (double) dy + sy;
+}
+
+static void
+tablet_tool_pressure(void *data, struct zwp_tablet_tool_v2 *tool,
+ uint32_t pressure)
+{
+ struct xwl_tablet_tool *xwl_tablet_tool = data;
+ struct xwl_seat *xwl_seat = xwl_tablet_tool->seat;
+
+ if (!xwl_seat->tablet_focus_window)
+ return;
+
+ /* normalized to 65535 already */
+ xwl_tablet_tool->pressure = pressure;
+}
+
+static void
+tablet_tool_distance(void *data, struct zwp_tablet_tool_v2 *tool,
+ uint32_t distance_raw)
+{
+}
+
+static void
+tablet_tool_tilt(void *data, struct zwp_tablet_tool_v2 *tool,
+ wl_fixed_t tilt_x, wl_fixed_t tilt_y)
+{
+ struct xwl_tablet_tool *xwl_tablet_tool = data;
+ struct xwl_seat *xwl_seat = xwl_tablet_tool->seat;
+
+ if (!xwl_seat->tablet_focus_window)
+ return;
+
+ xwl_tablet_tool->tilt_x = wl_fixed_to_double(tilt_x);
+ xwl_tablet_tool->tilt_y = wl_fixed_to_double(tilt_y);
+}
+
+static void
+tablet_tool_rotation(void *data, struct zwp_tablet_tool_v2 *tool,
+ wl_fixed_t angle)
+{
+ struct xwl_tablet_tool *xwl_tablet_tool = data;
+ struct xwl_seat *xwl_seat = xwl_tablet_tool->seat;
+ double rotation = wl_fixed_to_double(angle);
+
+ if (!xwl_seat->tablet_focus_window)
+ return;
+
+ /* change origin (buttons facing right [libinput +90 degrees]) and
+ * scaling (5 points per degree) to match wacom driver behavior
+ */
+ rotation = remainderf(rotation + 90.0f, 360.0f);
+ rotation *= 5.0f;
+ xwl_tablet_tool->rotation = rotation;
+}
+
+static void
+tablet_tool_slider(void *data, struct zwp_tablet_tool_v2 *tool,
+ int32_t position_raw)
+{
+ struct xwl_tablet_tool *xwl_tablet_tool = data;
+ struct xwl_seat *xwl_seat = xwl_tablet_tool->seat;
+ float position = position_raw / 65535.0;
+
+ if (!xwl_seat->tablet_focus_window)
+ return;
+
+ xwl_tablet_tool->slider = (position * 1799.0f) - 900.0f;
+}
+
+static void
+tablet_tool_wheel(void *data, struct zwp_tablet_tool_v2 *tool,
+ wl_fixed_t degrees, int32_t clicks)
+{
+ struct xwl_tablet_tool *xwl_tablet_tool = data;
+ struct xwl_seat *xwl_seat = xwl_tablet_tool->seat;
+
+ if (!xwl_seat->tablet_focus_window)
+ return;
+
+ xwl_tablet_tool->wheel_clicks = clicks;
+}
+
+static void
+tablet_tool_button_state(void *data, struct zwp_tablet_tool_v2 *tool,
+ uint32_t serial, uint32_t button, uint32_t state)
+{
+ struct xwl_tablet_tool *xwl_tablet_tool = data;
+ struct xwl_seat *xwl_seat = xwl_tablet_tool->seat;
+ uint32_t *mask = &xwl_tablet_tool->buttons_now;
+ int xbtn = 0;
+
+ /* BTN_0 .. BTN_9 */
+ if (button >= 0x100 && button <= 0x109) {
+ xbtn = button - 0x100 + 1;
+ }
+ /* BTN_A .. BTN_Z */
+ else if (button >= 0x130 && button <= 0x135) {
+ xbtn = button - 0x130 + 10;
+ }
+ /* BTN_BASE .. BTN_BASE6 */
+ else if (button >= 0x126 && button <= 0x12b) {
+ xbtn = button - 0x126 + 16;
+ }
+ else {
+ switch (button) {
+ case 0x110: /* BTN_LEFT */
+ case 0x14a: /* BTN_TOUCH */
+ xbtn = 1;
+ break;
+
+ case 0x112: /* BTN_MIDDLE */
+ case 0x14b: /* BTN_STYLUS */
+ xbtn = 2;
+ break;
+
+ case 0x111: /* BTN_RIGHT */
+ case 0x14c: /* BTN_STYLUS2 */
+ xbtn = 3;
+ break;
+
+ case 0x113: /* BTN_SIDE */
+ case 0x116: /* BTN_BACK */
+ case 0x149: /* BTN_STYLUS3 */
+ xbtn = 8;
+ break;
+
+ case 0x114: /* BTN_EXTRA */
+ case 0x115: /* BTN_FORWARD */
+ xbtn = 9;
+ break;
+ }
+ }
+
+ if (!xbtn) {
+ ErrorF("unknown tablet button number %d\n", button);
+ return;
+ }
+
+ BUG_RETURN(xbtn >= 8 * sizeof(*mask));
+
+ if (state)
+ SetBit(mask, xbtn - 1);
+ else
+ ClearBit(mask, xbtn - 1);
+
+ xwl_seat->xwl_screen->serial = serial;
+}
+
+static void
+tablet_tool_frame(void *data, struct zwp_tablet_tool_v2 *tool, uint32_t time)
+{
+ struct xwl_tablet_tool *xwl_tablet_tool = data;
+ ValuatorMask mask;
+ uint32_t released, pressed, diff;
+ int button;
+
+ valuator_mask_zero(&mask);
+ valuator_mask_set_double(&mask, 0, xwl_tablet_tool->x);
+ valuator_mask_set_double(&mask, 1, xwl_tablet_tool->y);
+ valuator_mask_set(&mask, 2, xwl_tablet_tool->pressure);
+ valuator_mask_set_double(&mask, 3, xwl_tablet_tool->tilt_x);
+ valuator_mask_set_double(&mask, 4, xwl_tablet_tool->tilt_y);
+ valuator_mask_set_double(&mask, 5, xwl_tablet_tool->rotation + xwl_tablet_tool->slider);
+
+ QueuePointerEvents(xwl_tablet_tool->xdevice, MotionNotify, 0,
+ POINTER_ABSOLUTE | POINTER_DESKTOP, &mask);
+
+ valuator_mask_zero(&mask);
+
+ diff = xwl_tablet_tool->buttons_prev ^ xwl_tablet_tool->buttons_now;
+ released = diff & ~xwl_tablet_tool->buttons_now;
+ pressed = diff & xwl_tablet_tool->buttons_now;
+
+ button = 1;
+ while (released) {
+ if (released & 0x1)
+ QueuePointerEvents(xwl_tablet_tool->xdevice,
+ ButtonRelease, button, 0, &mask);
+ button++;
+ released >>= 1;
+ }
+
+ button = 1;
+ while (pressed) {
+ if (pressed & 0x1)
+ QueuePointerEvents(xwl_tablet_tool->xdevice,
+ ButtonPress, button, 0, &mask);
+ button++;
+ pressed >>= 1;
+ }
+
+ xwl_tablet_tool->buttons_prev = xwl_tablet_tool->buttons_now;
+
+ while (xwl_tablet_tool->wheel_clicks) {
+ if (xwl_tablet_tool->wheel_clicks < 0) {
+ button = 4;
+ xwl_tablet_tool->wheel_clicks++;
+ }
+ else {
+ button = 5;
+ xwl_tablet_tool->wheel_clicks--;
+ }
+
+ QueuePointerEvents(xwl_tablet_tool->xdevice,
+ ButtonPress, button, 0, &mask);
+ QueuePointerEvents(xwl_tablet_tool->xdevice,
+ ButtonRelease, button, 0, &mask);
+
+ }
+}
+
+static const struct zwp_tablet_tool_v2_listener tablet_tool_listener = {
+ tablet_tool_receive_type,
+ tablet_tool_receive_hardware_serial,
+ tablet_tool_receive_hardware_id_wacom,
+ tablet_tool_receive_capability,
+ tablet_tool_receive_done,
+ tablet_tool_receive_removed,
+ tablet_tool_proximity_in,
+ tablet_tool_proximity_out,
+ tablet_tool_down,
+ tablet_tool_up,
+ tablet_tool_motion,
+ tablet_tool_pressure,
+ tablet_tool_distance,
+ tablet_tool_tilt,
+ tablet_tool_rotation,
+ tablet_tool_slider,
+ tablet_tool_wheel,
+ tablet_tool_button_state,
+ tablet_tool_frame
+};
+
+static void
+tablet_pad_ring_destroy(struct xwl_tablet_pad_ring *ring)
+{
+ zwp_tablet_pad_ring_v2_destroy(ring->ring);
+ xorg_list_del(&ring->link);
+ free(ring);
+}
+
+static void
+tablet_pad_ring_source(void *data,
+ struct zwp_tablet_pad_ring_v2 *zwp_tablet_pad_ring_v2,
+ uint32_t source)
+{
+}
+
+static void
+tablet_pad_ring_angle(void *data,
+ struct zwp_tablet_pad_ring_v2 *zwp_tablet_pad_ring_v2,
+ wl_fixed_t degrees)
+{
+ struct xwl_tablet_pad_ring *ring = data;
+ struct xwl_tablet_pad *pad = ring->group->pad;
+ double deg = wl_fixed_to_double(degrees);
+ ValuatorMask mask;
+
+ valuator_mask_zero(&mask);
+ valuator_mask_set(&mask, 5 + ring->index, deg/360.0 * 71);
+ QueuePointerEvents(pad->xdevice, MotionNotify, 0, 0, &mask);
+}
+
+static void
+tablet_pad_ring_stop(void *data,
+ struct zwp_tablet_pad_ring_v2 *zwp_tablet_pad_ring_v2)
+{
+}
+
+static void
+tablet_pad_ring_frame(void *data,
+ struct zwp_tablet_pad_ring_v2 *zwp_tablet_pad_ring_v2,
+ uint32_t time)
+{
+}
+
+static const struct zwp_tablet_pad_ring_v2_listener tablet_pad_ring_listener = {
+ tablet_pad_ring_source,
+ tablet_pad_ring_angle,
+ tablet_pad_ring_stop,
+ tablet_pad_ring_frame,
+};
+
+
+static void
+tablet_pad_strip_destroy(struct xwl_tablet_pad_strip *strip)
+{
+ zwp_tablet_pad_strip_v2_destroy(strip->strip);
+ xorg_list_del(&strip->link);
+ free(strip);
+}
+
+static void
+tablet_pad_strip_source(void *data,
+ struct zwp_tablet_pad_strip_v2 *zwp_tablet_pad_strip_v2,
+ uint32_t source)
+{
+}
+
+static void
+tablet_pad_strip_position(void *data,
+ struct zwp_tablet_pad_strip_v2 *zwp_tablet_pad_strip_v2,
+ uint32_t position)
+{
+ struct xwl_tablet_pad_strip *strip = data;
+ struct xwl_tablet_pad *pad = strip->group->pad;
+ ValuatorMask mask;
+
+ valuator_mask_zero(&mask);
+ valuator_mask_set(&mask, 3 + strip->index, position/65535.0 * 2048);
+ QueuePointerEvents(pad->xdevice, MotionNotify, 0, 0, &mask);
+}
+
+static void
+tablet_pad_strip_stop(void *data,
+ struct zwp_tablet_pad_strip_v2 *zwp_tablet_pad_strip_v2)
+{
+}
+
+static void
+tablet_pad_strip_frame(void *data,
+ struct zwp_tablet_pad_strip_v2 *zwp_tablet_pad_strip_v2,
+ uint32_t time)
+{
+}
+
+static const struct zwp_tablet_pad_strip_v2_listener tablet_pad_strip_listener = {
+ tablet_pad_strip_source,
+ tablet_pad_strip_position,
+ tablet_pad_strip_stop,
+ tablet_pad_strip_frame,
+};
+
+static void
+tablet_pad_group_destroy(struct xwl_tablet_pad_group *group)
+{
+ struct xwl_tablet_pad_ring *r, *tr;
+ struct xwl_tablet_pad_strip *s, *ts;
+
+ xorg_list_for_each_entry_safe(r, tr,
+ &group->pad_group_ring_list,
+ link)
+ tablet_pad_ring_destroy(r);
+
+ xorg_list_for_each_entry_safe(s, ts,
+ &group->pad_group_strip_list,
+ link)
+ tablet_pad_strip_destroy(s);
+
+ zwp_tablet_pad_group_v2_destroy(group->group);
+ xorg_list_del(&group->link);
+ free(group);
+}
+
+static void
+tablet_pad_group_buttons(void *data,
+ struct zwp_tablet_pad_group_v2 *zwp_tablet_pad_group_v2,
+ struct wl_array *buttons)
+{
+
+}
+
+static void
+tablet_pad_group_ring(void *data,
+ struct zwp_tablet_pad_group_v2 *zwp_tablet_pad_group_v2,
+ struct zwp_tablet_pad_ring_v2 *wp_ring)
+{
+ static unsigned int ring_index = 0;
+ struct xwl_tablet_pad_group *group = data;
+ struct xwl_tablet_pad_ring *ring;
+
+ ring = calloc(1, sizeof *ring);
+ if (ring == NULL) {
+ ErrorF("%s ENOMEM\n", __func__);
+ return;
+ }
+
+ ring->index = ring_index++;
+ ring->group = group;
+ ring->ring = wp_ring;
+
+ xorg_list_add(&ring->link, &group->pad_group_ring_list);
+
+ zwp_tablet_pad_ring_v2_add_listener(wp_ring, &tablet_pad_ring_listener,
+ ring);
+}
+
+static void
+tablet_pad_group_strip(void *data,
+ struct zwp_tablet_pad_group_v2 *zwp_tablet_pad_group_v2,
+ struct zwp_tablet_pad_strip_v2 *wp_strip)
+{
+ static unsigned int strip_index = 0;
+ struct xwl_tablet_pad_group *group = data;
+ struct xwl_tablet_pad_strip *strip;
+
+ strip = calloc(1, sizeof *strip);
+ if (strip == NULL) {
+ ErrorF("%s ENOMEM\n", __func__);
+ return;
+ }
+
+ strip->index = strip_index++;
+ strip->group = group;
+ strip->strip = wp_strip;
+
+ xorg_list_add(&strip->link, &group->pad_group_strip_list);
+
+ zwp_tablet_pad_strip_v2_add_listener(wp_strip, &tablet_pad_strip_listener,
+ strip);
+}
+
+static void
+tablet_pad_group_modes(void *data,
+ struct zwp_tablet_pad_group_v2 *zwp_tablet_pad_group_v2,
+ uint32_t modes)
+{
+
+}
+
+static void
+tablet_pad_group_done(void *data,
+ struct zwp_tablet_pad_group_v2 *zwp_tablet_pad_group_v2)
+{
+
+}
+
+static void
+tablet_pad_group_mode_switch(void *data,
+ struct zwp_tablet_pad_group_v2 *zwp_tablet_pad_group_v2,
+ uint32_t time,
+ uint32_t serial,
+ uint32_t mode)
+{
+
+}
+
+static struct zwp_tablet_pad_group_v2_listener tablet_pad_group_listener = {
+ tablet_pad_group_buttons,
+ tablet_pad_group_ring,
+ tablet_pad_group_strip,
+ tablet_pad_group_modes,
+ tablet_pad_group_done,
+ tablet_pad_group_mode_switch,
+};
+
+static int
+xwl_tablet_pad_proc(DeviceIntPtr device, int what)
+{
+ struct xwl_tablet_pad *pad = device->public.devicePrivate;
+ /* Axis layout mirrors that of xf86-input-wacom to have better
+ compatibility with existing clients */
+#define NAXES 7
+ Atom axes_labels[NAXES] = { 0 };
+ BYTE map[MAX_BUTTONS + 1];
+ int i = 0;
+ Atom btn_labels[MAX_BUTTONS] = { 0 }; /* btn labels are meaningless */
+ int nbuttons;
+
+ switch (what) {
+ case DEVICE_INIT:
+ device->public.on = FALSE;
+
+ axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_X);
+ axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_Y);
+ /* The others have no good mapping */
+
+ if (!InitValuatorClassDeviceStruct(device, NAXES, axes_labels,
+ GetMotionHistorySize(), Absolute))
+ return BadValue;
+
+ for (i = 1; i <= MAX_BUTTONS; i++)
+ map[i] = i;
+
+ /* We need at least 7 buttons to allow scrolling */
+ nbuttons = min(max(pad->nbuttons + 4, 7), MAX_BUTTONS);
+
+ if (!InitButtonClassDeviceStruct(device, nbuttons,
+ btn_labels, map))
+ return BadValue;
+
+ /* Valuators */
+ InitValuatorAxisStruct(device, 0, axes_labels[0],
+ 0, 100, 1, 0, 1, Absolute);
+ InitValuatorAxisStruct(device, 1, axes_labels[1],
+ 0, 100, 1, 0, 1, Absolute);
+ /* Pressure - unused, for backwards compat only */
+ InitValuatorAxisStruct(device, 2, axes_labels[2],
+ 0, 2048, 1, 0, 1, Absolute);
+ /* strip x */
+ InitValuatorAxisStruct(device, 3, axes_labels[3],
+ 0, 2048, 1, 0, 1, Absolute);
+ /* strip y */
+ InitValuatorAxisStruct(device, 4, axes_labels[4],
+ 0, 2048, 1, 0, 1, Absolute);
+ /* ring */
+ InitValuatorAxisStruct(device, 5, axes_labels[5],
+ 0, 71, 1, 0, 1, Absolute);
+ /* ring2 */
+ InitValuatorAxisStruct(device, 6, axes_labels[6],
+ 0, 71, 1, 0, 1, Absolute);
+
+ if (!InitPtrFeedbackClassDeviceStruct(device, xwl_pointer_control))
+ return BadValue;
+
+ return Success;
+
+ case DEVICE_ON:
+ device->public.on = TRUE;
+ return Success;
+
+ case DEVICE_OFF:
+ case DEVICE_CLOSE:
+ device->public.on = FALSE;
+ return Success;
+ }
+
+ return BadMatch;
+#undef NAXES
+}
+
+static void
+tablet_pad_group(void *data,
+ struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2,
+ struct zwp_tablet_pad_group_v2 *pad_group)
+{
+ struct xwl_tablet_pad *pad = data;
+ struct xwl_tablet_pad_group *group;
+
+ group = calloc(1, sizeof *group);
+ if (pad == NULL) {
+ ErrorF("%s ENOMEM\n", __func__);
+ return;
+ }
+
+ group->pad = pad;
+ group->group = pad_group;
+ xorg_list_init(&group->pad_group_ring_list);
+ xorg_list_init(&group->pad_group_strip_list);
+
+ xorg_list_add(&group->link, &pad->pad_group_list);
+
+ zwp_tablet_pad_group_v2_add_listener(pad_group,
+ &tablet_pad_group_listener,
+ group);
+}
+
+static void
+tablet_pad_path(void *data,
+ struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2,
+ const char *path)
+{
+
+}
+
+static void
+tablet_pad_buttons(void *data,
+ struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2,
+ uint32_t buttons)
+{
+ struct xwl_tablet_pad *pad = data;
+
+ pad->nbuttons = buttons;
+}
+
+static void
+tablet_pad_done(void *data,
+ struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2)
+{
+ struct xwl_tablet_pad *pad = data;
+
+ pad->xdevice = add_device(pad->seat, "xwayland-pad",
+ xwl_tablet_pad_proc);
+ pad->xdevice->public.devicePrivate = pad;
+ ActivateDevice(pad->xdevice, TRUE);
+ EnableDevice(pad->xdevice, TRUE);
+}
+
+static void
+tablet_pad_button(void *data,
+ struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2,
+ uint32_t time,
+ uint32_t button,
+ uint32_t state)
+{
+ struct xwl_tablet_pad *pad = data;
+ ValuatorMask mask;
+
+ button++; /* wayland index vs X's 1-offset */
+ /* skip scroll wheel buttons 4-7 */
+ button = button > 3 ? button + 4 : button;
+
+ valuator_mask_zero(&mask);
+ QueuePointerEvents(pad->xdevice,
+ state ? ButtonPress : ButtonRelease, button, 0, &mask);
+}
+
+static void
+tablet_pad_enter(void *data,
+ struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2,
+ uint32_t serial,
+ struct zwp_tablet_v2 *tablet,
+ struct wl_surface *surface)
+{
+ /* pairs the pad with the tablet but also to set the focus. We
+ * don't care about the pairing and always use X's focus */
+}
+
+static void
+tablet_pad_leave(void *data,
+ struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2,
+ uint32_t serial,
+ struct wl_surface *surface)
+{
+ /* pairs the pad with the tablet but also to set the focus. We
+ * don't care about the pairing and always use X's focus */
+}
+
+static void
+tablet_pad_removed(void *data,
+ struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2)
+{
+ struct xwl_tablet_pad *pad = data;
+ struct xwl_tablet_pad_group *g, *tg;
+
+ xorg_list_for_each_entry_safe(g, tg, &pad->pad_group_list, link)
+ tablet_pad_group_destroy(g);
+
+ RemoveDevice(pad->xdevice, TRUE);
+ xorg_list_del(&pad->link);
+ zwp_tablet_pad_v2_destroy(pad->pad);
+ free(pad);
+}
+
+static const struct zwp_tablet_pad_v2_listener tablet_pad_listener = {
+ tablet_pad_group,
+ tablet_pad_path,
+ tablet_pad_buttons,
+ tablet_pad_done,
+ tablet_pad_button,
+ tablet_pad_enter,
+ tablet_pad_leave,
+ tablet_pad_removed,
+};
+
+static void
+tablet_seat_handle_add_tablet(void *data, struct zwp_tablet_seat_v2 *tablet_seat,
+ struct zwp_tablet_v2 *tablet)
+{
+ struct xwl_seat *xwl_seat = data;
+ struct xwl_tablet *xwl_tablet;
+
+ xwl_tablet = calloc(sizeof *xwl_tablet, 1);
+ if (xwl_tablet == NULL) {
+ ErrorF("%s ENOMEM\n", __func__);
+ return;
+ }
+
+ xwl_tablet->tablet = tablet;
+ xwl_tablet->seat = xwl_seat;
+
+ xorg_list_add(&xwl_tablet->link, &xwl_seat->tablets);
+
+ zwp_tablet_v2_add_listener(tablet, &tablet_listener, xwl_tablet);
+}
+
+static void
+xwl_tablet_tool_update_cursor(struct xwl_cursor *xwl_cursor)
+{
+ struct xwl_tablet_tool *xwl_tablet_tool = wl_container_of(xwl_cursor,
+ xwl_tablet_tool,
+ cursor);
+ xwl_tablet_tool_set_cursor(xwl_tablet_tool);
+}
+
+static void
+tablet_seat_handle_add_tool(void *data, struct zwp_tablet_seat_v2 *tablet_seat,
+ struct zwp_tablet_tool_v2 *tool)
+{
+ struct xwl_seat *xwl_seat = data;
+ struct xwl_screen *xwl_screen = xwl_seat->xwl_screen;
+ struct xwl_tablet_tool *xwl_tablet_tool;
+
+ xwl_tablet_tool = calloc(sizeof *xwl_tablet_tool, 1);
+ if (xwl_tablet_tool == NULL) {
+ ErrorF("%s ENOMEM\n", __func__);
+ return;
+ }
+
+ xwl_tablet_tool->tool = tool;
+ xwl_tablet_tool->seat = xwl_seat;
+ xwl_cursor_init(&xwl_tablet_tool->cursor, xwl_screen,
+ xwl_tablet_tool_update_cursor);
+
+ xorg_list_add(&xwl_tablet_tool->link, &xwl_seat->tablet_tools);
+
+ zwp_tablet_tool_v2_add_listener(tool, &tablet_tool_listener, xwl_tablet_tool);
+}
+
+static void
+tablet_seat_handle_add_pad(void *data, struct zwp_tablet_seat_v2 *tablet_seat,
+ struct zwp_tablet_pad_v2 *pad)
+{
+ struct xwl_seat *xwl_seat = data;
+ struct xwl_tablet_pad *xwl_tablet_pad;
+
+ xwl_tablet_pad = calloc(sizeof *xwl_tablet_pad, 1);
+ if (xwl_tablet_pad == NULL) {
+ ErrorF("%s ENOMEM\n", __func__);
+ return;
+ }
+
+ xwl_tablet_pad->pad = pad;
+ xwl_tablet_pad->seat = xwl_seat;
+ xorg_list_init(&xwl_tablet_pad->pad_group_list);
+
+ xorg_list_add(&xwl_tablet_pad->link, &xwl_seat->tablet_pads);
+
+ zwp_tablet_pad_v2_add_listener(pad, &tablet_pad_listener,
+ xwl_tablet_pad);
+}
+
+static const struct zwp_tablet_seat_v2_listener tablet_seat_listener = {
+ tablet_seat_handle_add_tablet,
+ tablet_seat_handle_add_tool,
+ tablet_seat_handle_add_pad
+};
+
+static void
+init_tablet_manager_seat(struct xwl_screen *xwl_screen,
+ struct xwl_seat *xwl_seat)
+{
+ xorg_list_init(&xwl_seat->tablets);
+ xorg_list_init(&xwl_seat->tablet_tools);
+ xorg_list_init(&xwl_seat->tablet_pads);
+
+ if (!xwl_screen->tablet_manager)
+ return;
+
+ xwl_seat->tablet_seat =
+ zwp_tablet_manager_v2_get_tablet_seat(xwl_screen->tablet_manager,
+ xwl_seat->seat);
+
+ zwp_tablet_seat_v2_add_listener(xwl_seat->tablet_seat, &tablet_seat_listener, xwl_seat);
+}
+
+static void
+release_tablet_manager_seat(struct xwl_seat *xwl_seat)
+{
+ struct xwl_tablet *xwl_tablet, *next_xwl_tablet;
+ struct xwl_tablet_tool *xwl_tablet_tool, *next_xwl_tablet_tool;
+ struct xwl_tablet_pad *xwl_tablet_pad, *next_xwl_tablet_pad;
+
+ xorg_list_for_each_entry_safe(xwl_tablet_pad, next_xwl_tablet_pad,
+ &xwl_seat->tablet_pads, link) {
+ xorg_list_del(&xwl_tablet_pad->link);
+ zwp_tablet_pad_v2_destroy(xwl_tablet_pad->pad);
+ free(xwl_tablet_pad);
+ }
+
+ xorg_list_for_each_entry_safe(xwl_tablet_tool, next_xwl_tablet_tool,
+ &xwl_seat->tablet_tools, link) {
+ xorg_list_del(&xwl_tablet_tool->link);
+ zwp_tablet_tool_v2_destroy(xwl_tablet_tool->tool);
+ free(xwl_tablet_tool);
+ }
+
+ xorg_list_for_each_entry_safe(xwl_tablet, next_xwl_tablet,
+ &xwl_seat->tablets, link) {
+ xorg_list_del(&xwl_tablet->link);
+ zwp_tablet_v2_destroy(xwl_tablet->tablet);
+ free(xwl_tablet);
+ }
+
+ if (xwl_seat->tablet_seat) {
+ zwp_tablet_seat_v2_destroy(xwl_seat->tablet_seat);
+ xwl_seat->tablet_seat = NULL;
+ }
+}
+
+static void
+init_tablet_manager(struct xwl_screen *xwl_screen, uint32_t id, uint32_t version)
+{
+ struct xwl_seat *xwl_seat;
+
+ xwl_screen->tablet_manager = wl_registry_bind(xwl_screen->registry,
+ id,
+ &zwp_tablet_manager_v2_interface,
+ min(version,1));
+
+ xorg_list_for_each_entry(xwl_seat, &xwl_screen->seat_list, link) {
+ init_tablet_manager_seat(xwl_screen, xwl_seat);
+ }
+}
+
+void
+xwl_screen_release_tablet_manager(struct xwl_screen *xwl_screen)
+{
+ if (xwl_screen->tablet_manager) {
+ zwp_tablet_manager_v2_destroy(xwl_screen->tablet_manager);
+ xwl_screen->tablet_manager = NULL;
+ }
+}
+
+static void
init_relative_pointer_manager(struct xwl_screen *xwl_screen,
uint32_t id, uint32_t version)
{
@@ -1198,6 +2440,27 @@ init_pointer_constraints(struct xwl_screen *xwl_screen,
}
static void
+init_keyboard_grab(struct xwl_screen *xwl_screen,
+ uint32_t id, uint32_t version)
+{
+ struct xwl_seat *xwl_seat;
+ DeviceIntPtr master;
+
+ xwl_screen->wp_grab =
+ wl_registry_bind(xwl_screen->registry, id,
+ &zwp_xwayland_keyboard_grab_manager_v1_interface,
+ 1);
+
+ xorg_list_for_each_entry(xwl_seat, &xwl_screen->seat_list, link) {
+ if (xwl_seat->keyboard) {
+ master = GetMaster(xwl_seat->keyboard, MASTER_KEYBOARD);
+ if (master)
+ setup_keyboard_grab_handler(master);
+ }
+ }
+}
+
+static void
input_handler(void *data, struct wl_registry *registry, uint32_t id,
const char *interface, uint32_t version)
{
@@ -1210,6 +2473,10 @@ input_handler(void *data, struct wl_registry *registry, uint32_t id,
init_relative_pointer_manager(xwl_screen, id, version);
} else if (strcmp(interface, "zwp_pointer_constraints_v1") == 0) {
init_pointer_constraints(xwl_screen, id, version);
+ } else if (strcmp(interface, "zwp_tablet_manager_v2") == 0) {
+ init_tablet_manager(xwl_screen, id, version);
+ } else if (strcmp(interface, "zwp_xwayland_keyboard_grab_manager_v1") == 0) {
+ init_keyboard_grab(xwl_screen, id, version);
}
}
@@ -1457,9 +2724,9 @@ xwl_pointer_warp_emulator_create(struct xwl_seat *xwl_seat)
{
struct xwl_pointer_warp_emulator *warp_emulator;
- warp_emulator = calloc(sizeof *warp_emulator, 1);
+ warp_emulator = calloc(1, sizeof *warp_emulator);
if (!warp_emulator) {
- ErrorF("%s: ENOMEM", __func__);
+ ErrorF("%s: ENOMEM\n", __func__);
return NULL;
}
diff --git a/xserver/hw/xwayland/xwayland-output.c b/xserver/hw/xwayland/xwayland-output.c
index 5a0f739f3..cc68f0340 100644
--- a/xserver/hw/xwayland/xwayland-output.c
+++ b/xserver/hw/xwayland/xwayland-output.c
@@ -38,6 +38,8 @@
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)
{
@@ -93,9 +95,12 @@ output_handle_geometry(void *data, struct wl_output *wl_output, int x, int y,
physical_width, physical_height);
RROutputSetSubpixelOrder(xwl_output->randr_output,
wl_subpixel_to_xrandr(subpixel));
- xwl_output->x = x;
- xwl_output->y = y;
+ /* 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);
}
@@ -108,18 +113,22 @@ output_handle_mode(void *data, struct wl_output *wl_output, uint32_t flags,
if (!(flags & WL_OUTPUT_MODE_CURRENT))
return;
- xwl_output->width = width;
- xwl_output->height = height;
+ /* 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;
}
static inline void
output_get_new_size(struct xwl_output *xwl_output,
+ Bool need_rotate,
int *height, int *width)
{
int output_width, output_height;
- if (xwl_output->rotation & (RR_Rotate_0 | RR_Rotate_180)) {
+ if (!need_rotate || (xwl_output->rotation & (RR_Rotate_0 | RR_Rotate_180))) {
output_width = xwl_output->width;
output_height = xwl_output->height;
} else {
@@ -137,8 +146,9 @@ output_get_new_size(struct xwl_output *xwl_output,
/* Approximate some kind of mmpd (m.m. per dot) of the screen given the outputs
* associated with it.
*
- * It will either calculate the mean mmpd of all the outputs, or default to
- * 96 DPI if no reasonable value could be calculated.
+ * It either calculates the mean mmpd of all the outputs or, if no reasonable
+ * value could be calculated, defaults to the mmpd of a screen with a DPI value
+ * of DEFAULT_DPI.
*/
static double
approximate_mmpd(struct xwl_screen *xwl_screen)
@@ -199,14 +209,32 @@ update_screen_size(struct xwl_output *xwl_output, int width, int height)
}
static void
-output_handle_done(void *data, struct wl_output *wl_output)
+apply_output_change(struct xwl_output *xwl_output)
{
- struct xwl_output *it, *xwl_output = data;
struct xwl_screen *xwl_screen = xwl_output->xwl_screen;
+ struct xwl_output *it;
+ int mode_width, mode_height;
int width = 0, height = 0, has_this_output = 0;
RRModePtr randr_mode;
+ Bool need_rotate;
- randr_mode = xwayland_cvt(xwl_output->width, xwl_output->height,
+ /* Clear out the "done" received flags */
+ xwl_output->wl_output_done = FALSE;
+ xwl_output->xdg_output_done = FALSE;
+
+ /* xdg-output sends output size in compositor space. so already rotated */
+ need_rotate = (xwl_output->xdg_output == NULL);
+
+ /* We need to rotate back the logical size for the mode */
+ if (need_rotate || 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;
+ }
+
+ randr_mode = xwayland_cvt(mode_width, mode_height,
xwl_output->refresh / 1000.0, 0, 0);
RROutputSetModes(xwl_output->randr_output, &randr_mode, 1, 1);
RRCrtcNotify(xwl_output->randr_crtc, randr_mode,
@@ -221,14 +249,14 @@ output_handle_done(void *data, struct wl_output *wl_output)
if (it == xwl_output)
has_this_output = 1;
- output_get_new_size(it, &height, &width);
+ output_get_new_size(it, need_rotate, &height, &width);
}
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, &height, &width);
+ output_get_new_size(xwl_output, need_rotate, &height, &width);
--xwl_screen->expecting_event;
}
@@ -237,6 +265,19 @@ output_handle_done(void *data, struct wl_output *wl_output)
}
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,
+ * or if xdg-output is not supported.
+ */
+ if (xwl_output->xdg_output_done || !xwl_output->xdg_output)
+ apply_output_change(xwl_output);
+}
+
+static void
output_handle_scale(void *data, struct wl_output *wl_output, int32_t factor)
{
}
@@ -248,6 +289,42 @@ static const struct wl_output_listener output_listener = {
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)
+ apply_output_change(xwl_output);
+}
+
+static const struct zxdg_output_v1_listener xdg_output_listener = {
+ xdg_output_handle_logical_position,
+ xdg_output_handle_logical_size,
+ xdg_output_handle_done,
+};
+
struct xwl_output *
xwl_output_create(struct xwl_screen *xwl_screen, uint32_t id)
{
@@ -255,9 +332,9 @@ xwl_output_create(struct xwl_screen *xwl_screen, uint32_t id)
static int serial;
char name[256];
- xwl_output = calloc(sizeof *xwl_output, 1);
+ xwl_output = calloc(1, sizeof *xwl_output);
if (xwl_output == NULL) {
- ErrorF("create_output ENOMEM\n");
+ ErrorF("%s ENOMEM\n", __func__);
return NULL;
}
@@ -292,6 +369,15 @@ xwl_output_create(struct xwl_screen *xwl_screen, uint32_t id)
RROutputSetCrtcs(xwl_output->randr_output, &xwl_output->randr_crtc, 1);
RROutputSetConnection(xwl_output->randr_output, RR_Connected);
+ /* 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:
@@ -316,15 +402,17 @@ 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;
+ Bool need_rotate = (xwl_output->xdg_output == NULL);
- RRCrtcDestroy(xwl_output->randr_crtc);
- RROutputDestroy(xwl_output->randr_output);
xorg_list_del(&xwl_output->link);
xorg_list_for_each_entry(it, &xwl_screen->output_list, link)
- output_get_new_size(it, &height, &width);
+ output_get_new_size(it, need_rotate, &height, &width);
update_screen_size(xwl_output, width, height);
+ RRCrtcDestroy(xwl_output->randr_crtc);
+ RROutputDestroy(xwl_output->randr_output);
+
xwl_output_destroy(xwl_output);
}
@@ -359,3 +447,28 @@ xwl_screen_init_output(struct xwl_screen *xwl_screen)
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);
+}
diff --git a/xserver/hw/xwayland/xwayland-present.c b/xserver/hw/xwayland/xwayland-present.c
new file mode 100644
index 000000000..2937d9c97
--- /dev/null
+++ b/xserver/hw/xwayland/xwayland-present.c
@@ -0,0 +1,578 @@
+/*
+ * 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.h"
+
+#include <present.h>
+
+/*
+ * When not flipping let Present copy with 60fps.
+ * When flipping wait on frame_callback, otherwise
+ * the surface is not visible, in this case update
+ * with long interval.
+ */
+#define TIMER_LEN_COPY 17 // ~60fps
+#define TIMER_LEN_FLIP 1000 // 1fps
+
+static DevPrivateKeyRec xwl_present_window_private_key;
+
+static struct xwl_present_window *
+xwl_present_window_priv(WindowPtr window)
+{
+ return dixGetPrivate(&window->devPrivates,
+ &xwl_present_window_private_key);
+}
+
+static struct xwl_present_window *
+xwl_present_window_get_priv(WindowPtr window)
+{
+ struct xwl_present_window *xwl_present_window = xwl_present_window_priv(window);
+
+ if (xwl_present_window == NULL) {
+ xwl_present_window = calloc (1, sizeof (struct xwl_present_window));
+ if (!xwl_present_window)
+ return NULL;
+
+ xwl_present_window->window = window;
+ xwl_present_window->msc = 1;
+ xwl_present_window->ust = GetTimeInMicros();
+
+ xorg_list_init(&xwl_present_window->event_list);
+ xorg_list_init(&xwl_present_window->release_queue);
+
+ dixSetPrivate(&window->devPrivates,
+ &xwl_present_window_private_key,
+ xwl_present_window);
+ }
+
+ return xwl_present_window;
+}
+
+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 inline Bool
+xwl_present_has_events(struct xwl_present_window *xwl_present_window)
+{
+ return !!xwl_present_window->sync_flip ||
+ !xorg_list_is_empty(&xwl_present_window->event_list);
+}
+
+static void
+xwl_present_reset_timer(struct xwl_present_window *xwl_present_window)
+{
+ if (xwl_present_has_events(xwl_present_window)) {
+ CARD32 timeout;
+
+ if (xwl_present_window->frame_callback)
+ 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);
+ }
+}
+
+void
+xwl_present_cleanup(WindowPtr window)
+{
+ struct xwl_present_window *xwl_present_window = xwl_present_window_priv(window);
+ struct xwl_present_event *event, *tmp;
+
+ if (!xwl_present_window)
+ return;
+
+ if (xwl_present_window->frame_callback) {
+ wl_callback_destroy(xwl_present_window->frame_callback);
+ xwl_present_window->frame_callback = NULL;
+ }
+
+ 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, &xwl_present_window->event_list, list) {
+ xorg_list_del(&event->list);
+ free(event);
+ }
+
+ /* Clear remaining buffer releases and inform Present about free ressources */
+ event = xwl_present_window->sync_flip;
+ xwl_present_window->sync_flip = NULL;
+ if (event) {
+ if (event->buffer_released) {
+ free(event);
+ } else {
+ event->pending = FALSE;
+ event->abort = TRUE;
+ }
+ }
+ xorg_list_for_each_entry_safe(event, tmp, &xwl_present_window->release_queue, list) {
+ xorg_list_del(&event->list);
+ event->abort = TRUE;
+ }
+
+ /* 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_free_event(struct xwl_present_event *event)
+{
+ xorg_list_del(&event->list);
+ free(event);
+}
+
+static void
+xwl_present_buffer_release(void *data, struct wl_buffer *buffer)
+{
+ struct xwl_present_event *event = data;
+ if (!event)
+ return;
+
+ wl_buffer_set_user_data(buffer, NULL);
+ event->buffer_released = TRUE;
+
+ if (event->abort) {
+ if (!event->pending)
+ xwl_present_free_event(event);
+ return;
+ }
+
+ if (!event->pending) {
+ present_wnmd_event_notify(event->xwl_present_window->window,
+ event->event_id,
+ event->xwl_present_window->ust,
+ event->xwl_present_window->msc);
+ xwl_present_free_event(event);
+ }
+}
+
+static const struct wl_buffer_listener xwl_present_release_listener = {
+ xwl_present_buffer_release
+};
+
+static void
+xwl_present_msc_bump(struct xwl_present_window *xwl_present_window)
+{
+ uint64_t msc = ++xwl_present_window->msc;
+ struct xwl_present_event *event, *tmp;
+
+ xwl_present_window->ust = GetTimeInMicros();
+
+ event = xwl_present_window->sync_flip;
+ xwl_present_window->sync_flip = NULL;
+ if (event) {
+ event->pending = FALSE;
+
+ present_wnmd_event_notify(xwl_present_window->window, event->event_id,
+ xwl_present_window->ust, msc);
+
+ if (event->buffer_released) {
+ /* If the buffer was already released, clean up now */
+ present_wnmd_event_notify(xwl_present_window->window, event->event_id,
+ xwl_present_window->ust, msc);
+ free(event);
+ } else {
+ xorg_list_add(&event->list, &xwl_present_window->release_queue);
+ }
+ }
+
+ xorg_list_for_each_entry_safe(event, tmp,
+ &xwl_present_window->event_list,
+ list) {
+ if (event->target_msc <= msc) {
+ present_wnmd_event_notify(xwl_present_window->window,
+ event->event_id,
+ xwl_present_window->ust,
+ msc);
+ xwl_present_free_event(event);
+ }
+ }
+}
+
+CARD32
+xwl_present_timer_callback(OsTimerPtr timer,
+ CARD32 time,
+ void *arg)
+{
+ struct xwl_present_window *xwl_present_window = arg;
+
+ xwl_present_window->frame_timer_firing = TRUE;
+
+ xwl_present_msc_bump(xwl_present_window);
+ xwl_present_reset_timer(xwl_present_window);
+
+ return 0;
+}
+
+static void
+xwl_present_frame_callback(void *data,
+ struct wl_callback *callback,
+ uint32_t time)
+{
+ struct xwl_present_window *xwl_present_window = data;
+
+ wl_callback_destroy(xwl_present_window->frame_callback);
+ xwl_present_window->frame_callback = NULL;
+
+ if (xwl_present_window->frame_timer_firing) {
+ /* If the timer is firing, this frame callback is too late */
+ return;
+ }
+
+ 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 const struct wl_callback_listener xwl_present_frame_listener = {
+ xwl_present_frame_callback
+};
+
+static void
+xwl_present_sync_callback(void *data,
+ struct wl_callback *callback,
+ uint32_t time)
+{
+ struct xwl_present_event *event = data;
+ struct xwl_present_window *xwl_present_window = event->xwl_present_window;
+
+ wl_callback_destroy(xwl_present_window->sync_callback);
+ xwl_present_window->sync_callback = NULL;
+
+ event->pending = FALSE;
+
+ if (event->abort) {
+ /* Event might have been aborted */
+ if (event->buffer_released)
+ /* Buffer was already released, cleanup now */
+ xwl_present_free_event(event);
+ return;
+ }
+
+ present_wnmd_event_notify(xwl_present_window->window,
+ event->event_id,
+ xwl_present_window->ust,
+ xwl_present_window->msc);
+
+ if (event->buffer_released) {
+ /* If the buffer was already released, send the event now again */
+ present_wnmd_event_notify(xwl_present_window->window,
+ event->event_id,
+ xwl_present_window->ust,
+ xwl_present_window->msc);
+ xwl_present_free_event(event);
+ }
+}
+
+static const struct wl_callback_listener xwl_present_sync_listener = {
+ xwl_present_sync_callback
+};
+
+static RRCrtcPtr
+xwl_present_get_crtc(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];
+}
+
+static int
+xwl_present_get_ust_msc(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;
+}
+
+/*
+ * Queue an event to report back to the Present extension when the specified
+ * MSC has past
+ */
+static int
+xwl_present_queue_vblank(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_present_event *event;
+
+ event = malloc(sizeof *event);
+ if (!event)
+ return BadAlloc;
+
+ event->event_id = event_id;
+ event->xwl_present_window = xwl_present_window;
+ event->target_msc = msc;
+
+ xorg_list_append(&event->list, &xwl_present_window->event_list);
+
+ if (!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(WindowPtr present_window,
+ RRCrtcPtr crtc,
+ uint64_t event_id,
+ uint64_t msc)
+{
+ struct xwl_present_window *xwl_present_window = xwl_present_window_priv(present_window);
+ struct xwl_present_event *event, *tmp;
+
+ if (!xwl_present_window)
+ return;
+
+ xorg_list_for_each_entry_safe(event, tmp, &xwl_present_window->event_list, list) {
+ if (event->event_id == event_id) {
+ xorg_list_del(&event->list);
+ free(event);
+ return;
+ }
+ }
+
+ xorg_list_for_each_entry(event, &xwl_present_window->release_queue, list) {
+ if (event->event_id == event_id) {
+ event->abort = TRUE;
+ return;
+ }
+ }
+}
+
+static void
+xwl_present_flush(WindowPtr window)
+{
+ /* Only called when a Pixmap is copied instead of flipped,
+ * but in this case we wait on the next block_handler.
+ */
+}
+
+static Bool
+xwl_present_check_flip2(RRCrtcPtr crtc,
+ WindowPtr present_window,
+ PixmapPtr pixmap,
+ Bool sync_flip,
+ PresentFlipReason *reason)
+{
+ struct xwl_window *xwl_window = xwl_window_from_window(present_window);
+
+ if (!xwl_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;
+}
+
+static Bool
+xwl_present_flip(WindowPtr present_window,
+ RRCrtcPtr crtc,
+ uint64_t event_id,
+ uint64_t target_msc,
+ 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;
+ Bool buffer_created;
+ struct wl_buffer *buffer;
+ struct xwl_present_event *event;
+
+ if (!xwl_window)
+ return FALSE;
+
+ damage_box = RegionExtents(damage);
+
+ event = malloc(sizeof *event);
+ if (!event)
+ return FALSE;
+
+ buffer = xwl_glamor_pixmap_get_wl_buffer(pixmap, &buffer_created);
+
+ event->event_id = event_id;
+ event->xwl_present_window = xwl_present_window;
+ event->buffer = buffer;
+ event->target_msc = target_msc;
+ event->pending = TRUE;
+ event->abort = FALSE;
+ event->buffer_released = FALSE;
+
+ if (sync_flip) {
+ xorg_list_init(&event->list);
+ xwl_present_window->sync_flip = event;
+ } else {
+ xorg_list_add(&event->list, &xwl_present_window->release_queue);
+ }
+
+ if (buffer_created)
+ wl_buffer_add_listener(buffer, &xwl_present_release_listener, NULL);
+ wl_buffer_set_user_data(buffer, 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_present_window->frame_callback) {
+ xwl_present_window->frame_callback = wl_surface_frame(xwl_window->surface);
+ wl_callback_add_listener(xwl_present_window->frame_callback,
+ &xwl_present_frame_listener,
+ xwl_present_window);
+ }
+
+ /* Realign timer */
+ xwl_present_window->frame_timer_firing = FALSE;
+ xwl_present_reset_timer(xwl_present_window);
+
+ wl_surface_damage(xwl_window->surface, 0, 0,
+ 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);
+ }
+
+ wl_display_flush(xwl_window->xwl_screen->display);
+ xwl_window->present_flipped = TRUE;
+ return TRUE;
+}
+
+static void
+xwl_present_flips_stop(WindowPtr window)
+{
+ struct xwl_present_window *xwl_present_window = xwl_present_window_priv(window);
+
+ /* Change back to the fast refresh rate */
+ xwl_present_reset_timer(xwl_present_window);
+}
+
+void
+xwl_present_unrealize_window(WindowPtr window)
+{
+ struct xwl_present_window *xwl_present_window = xwl_present_window_priv(window);
+
+ if (!xwl_present_window || !xwl_present_window->frame_callback)
+ return;
+
+ /* The pending frame callback may never be called, so drop it and shorten
+ * the frame timer interval.
+ */
+ wl_callback_destroy(xwl_present_window->frame_callback);
+ xwl_present_window->frame_callback = NULL;
+ xwl_present_reset_timer(xwl_present_window);
+}
+
+static present_wnmd_info_rec xwl_present_info = {
+ .version = PRESENT_SCREEN_INFO_VERSION,
+ .get_crtc = xwl_present_get_crtc,
+
+ .get_ust_msc = xwl_present_get_ust_msc,
+ .queue_vblank = xwl_present_queue_vblank,
+ .abort_vblank = xwl_present_abort_vblank,
+
+ .flush = xwl_present_flush,
+
+ .capabilities = PresentCapabilityAsync,
+ .check_flip2 = xwl_present_check_flip2,
+ .flip = xwl_present_flip,
+ .flips_stop = xwl_present_flips_stop
+};
+
+Bool
+xwl_present_init(ScreenPtr screen)
+{
+ struct xwl_screen *xwl_screen = xwl_screen_get(screen);
+
+ /*
+ * doesn't work with the EGLStream backend.
+ */
+ if (xwl_screen->egl_backend == &xwl_screen->eglstream_backend)
+ return FALSE;
+
+ if (!dixRegisterPrivateKey(&xwl_present_window_private_key, PRIVATE_WINDOW, 0))
+ return FALSE;
+
+ return present_wnmd_screen_init(screen, &xwl_present_info);
+}
diff --git a/xserver/hw/xwayland/xwayland-shm.c b/xserver/hw/xwayland/xwayland-shm.c
index 452d1f509..29732eaca 100644
--- a/xserver/hw/xwayland/xwayland-shm.c
+++ b/xserver/hw/xwayland/xwayland-shm.c
@@ -24,7 +24,7 @@
* SOFTWARE.
*/
-#ifdef HAVE_CONFIG_H
+#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
diff --git a/xserver/hw/xwayland/xwayland.c b/xserver/hw/xwayland/xwayland.c
index d0bdf36a4..7e6e0ab25 100644
--- a/xserver/hw/xwayland/xwayland.c
+++ b/xserver/hw/xwayland/xwayland.c
@@ -27,13 +27,16 @@
#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>
#ifdef XF86VIDMODE
#include <X11/extensions/xf86vmproto.h>
@@ -71,12 +74,29 @@ ddxBeforeReset(void)
}
#endif
+ _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);
+}
+
void
ddxUseMsg(void)
{
ErrorF("-rootless run rootless, requires wm support\n");
ErrorF("-wm fd create X client for wm on given fd\n");
ErrorF("-listen fd add give fd as a listen socket\n");
+ ErrorF("-eglstream use eglstream backend for nvidia GPUs\n");
}
int
@@ -95,6 +115,9 @@ ddxProcessArgument(int argc, char *argv[], int i)
else if (strcmp(argv[i], "-shm") == 0) {
return 1;
}
+ else if (strcmp(argv[i], "-eglstream") == 0) {
+ return 1;
+ }
return 0;
}
@@ -115,6 +138,94 @@ xwl_screen_get(ScreenPtr screen)
return dixLookupPrivate(&screen->devPrivates, &xwl_screen_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) {
+ LogMessage(X_WARNING, "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");
+}
+
+static void
+xwl_window_property_allow_commits(struct xwl_window *xwl_window,
+ PropertyStateRec *propstate)
+{
+ Bool old_allow_commits = xwl_window->allow_commits;
+
+ 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;
+ }
+
+ /* If allow_commits turned from off to on, discard any frame
+ * callback we might be waiting for so that a new buffer is posted
+ * immediately through block_handler() if there is damage to post.
+ */
+ if (!old_allow_commits && xwl_window->allow_commits) {
+ if (xwl_window->frame_callback) {
+ wl_callback_destroy(xwl_window->frame_callback);
+ xwl_window->frame_callback = NULL;
+ }
+ }
+}
+
+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_property_allow_commits(xwl_window, rec);
+}
+
static Bool
xwl_close_screen(ScreenPtr screen)
{
@@ -122,6 +233,8 @@ xwl_close_screen(ScreenPtr 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);
@@ -130,6 +243,8 @@ xwl_close_screen(ScreenPtr screen)
&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);
@@ -140,7 +255,7 @@ xwl_close_screen(ScreenPtr screen)
return screen->CloseScreen(screen);
}
-static struct xwl_window *
+struct xwl_window *
xwl_window_from_window(WindowPtr window)
{
struct xwl_window *xwl_window;
@@ -183,6 +298,9 @@ xwl_cursor_warped_to(DeviceIntPtr device,
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;
@@ -252,6 +370,18 @@ damage_report(DamagePtr pDamage, RegionPtr pRegion, void *data)
struct xwl_window *xwl_window = data;
struct xwl_screen *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);
}
@@ -298,6 +428,21 @@ xwl_pixmap_get(PixmapPtr pixmap)
}
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";
@@ -357,7 +502,7 @@ xwl_realize_window(WindowPtr window)
return ret;
}
- xwl_window = calloc(sizeof *xwl_window, 1);
+ xwl_window = calloc(1, sizeof *xwl_window);
if (xwl_window == NULL)
return FALSE;
@@ -408,12 +553,16 @@ xwl_realize_window(WindowPtr window)
goto err_surf;
}
+ compRedirectWindow(serverClient, window, CompositeRedirectManual);
+
DamageRegister(&window->drawable, xwl_window->damage);
DamageSetReportAfterOp(xwl_window->damage, TRUE);
dixSetPrivate(&window->devPrivates, &xwl_window_private_key, xwl_window);
xorg_list_init(&xwl_window->link_damage);
+ xwl_window_init_allow_commits(xwl_window);
+
return ret;
err_surf:
@@ -439,6 +588,8 @@ xwl_unrealize_window(WindowPtr window)
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 &&
@@ -451,11 +602,18 @@ xwl_unrealize_window(WindowPtr window)
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;
+#ifdef GLAMOR_HAS_GBM
+ if (xwl_screen->present)
+ xwl_present_unrealize_window(window);
+#endif
+
xwl_window = xwl_window_get(window);
if (!xwl_window)
return ret;
@@ -494,45 +652,106 @@ static const struct wl_callback_listener frame_listener = {
frame_callback
};
+static 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;
+}
+
static void
-xwl_screen_post_damage(struct xwl_screen *xwl_screen)
+xwl_window_post_damage(struct xwl_window *xwl_window)
{
- struct xwl_window *xwl_window, *next_xwl_window;
+ struct xwl_screen *xwl_screen = xwl_window->xwl_screen;
RegionPtr region;
BoxPtr box;
struct wl_buffer *buffer;
PixmapPtr pixmap;
+ int i;
- 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;
+ assert(!xwl_window->frame_callback);
- region = DamageRegion(xwl_window->damage);
- pixmap = (*xwl_screen->screen->GetWindowPixmap) (xwl_window->window);
+ region = DamageRegion(xwl_window->damage);
+ pixmap = (*xwl_screen->screen->GetWindowPixmap) (xwl_window->window);
-#if GLAMOR_HAS_GBM
- if (xwl_screen->glamor)
- buffer = xwl_glamor_pixmap_get_wl_buffer(pixmap);
+#ifdef XWL_HAS_GLAMOR
+ if (xwl_screen->glamor)
+ buffer = xwl_glamor_pixmap_get_wl_buffer(pixmap,
+ NULL);
+ else
#endif
- if (!xwl_screen->glamor)
- buffer = xwl_shm_pixmap_get_wl_buffer(pixmap);
+ buffer = xwl_shm_pixmap_get_wl_buffer(pixmap);
- wl_surface_attach(xwl_window->surface, buffer, 0, 0);
+#ifdef XWL_HAS_GLAMOR
+ if (xwl_screen->glamor)
+ xwl_glamor_post_damage(xwl_window, pixmap, region);
+#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);
wl_surface_damage(xwl_window->surface, box->x1, box->y1,
box->x2 - box->x1, box->y2 - box->y1);
+ } else {
+ box = RegionRects(region);
+ for (i = 0; i < RegionNumRects(region); i++, box++)
+ wl_surface_damage(xwl_window->surface, box->x1, box->y1,
+ box->x2 - box->x1, box->y2 - box->y1);
+ }
- xwl_window->frame_callback = wl_surface_frame(xwl_window->surface);
- wl_callback_add_listener(xwl_window->frame_callback, &frame_listener, xwl_window);
+ xwl_window->frame_callback = wl_surface_frame(xwl_window->surface);
+ wl_callback_add_listener(xwl_window->frame_callback, &frame_listener, xwl_window);
- wl_surface_commit(xwl_window->surface);
- DamageEmpty(xwl_window->damage);
+ wl_surface_commit(xwl_window->surface);
+ DamageEmpty(xwl_window->damage);
- xorg_list_del(&xwl_window->link_damage);
+ xorg_list_del(&xwl_window->link_damage);
+}
+
+static void
+xwl_screen_post_damage(struct xwl_screen *xwl_screen)
+{
+ struct xwl_window *xwl_window, *next_xwl_window;
+
+ 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);
}
}
@@ -557,10 +776,15 @@ registry_global(void *data, struct wl_registry *registry, uint32_t id,
if (xwl_output_create(xwl_screen, id))
xwl_screen->expecting_event++;
}
-#ifdef GLAMOR_HAS_GBM
- else if (xwl_screen->glamor &&
- strcmp(interface, "wl_drm") == 0 && version >= 2) {
- xwl_screen_init_glamor(xwl_screen, id, version);
+ else if (strcmp(interface, "zxdg_output_manager_v1") == 0) {
+ xwl_screen->xdg_output_manager =
+ wl_registry_bind(registry, id, &zxdg_output_manager_v1_interface, 1);
+ xwl_screen_init_xdg_output(xwl_screen);
+ }
+#ifdef XWL_HAS_GLAMOR
+ else if (xwl_screen->glamor) {
+ xwl_glamor_init_wl_registry(xwl_screen, registry, id, interface,
+ version);
}
#endif
}
@@ -595,13 +819,13 @@ xwl_read_events (struct xwl_screen *xwl_screen)
ret = wl_display_read_events(xwl_screen->display);
if (ret == -1)
- FatalError("failed to read Wayland events: %s\n", strerror(errno));
+ 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)
- FatalError("failed to dispatch Wayland events: %s\n", strerror(errno));
+ xwl_give_up("failed to dispatch Wayland events: %s\n", strerror(errno));
}
static int
@@ -628,7 +852,7 @@ xwl_dispatch_events (struct xwl_screen *xwl_screen)
wl_display_prepare_read(xwl_screen->display) == -1) {
ret = wl_display_dispatch_pending(xwl_screen->display);
if (ret == -1)
- FatalError("failed to dispatch Wayland events: %s\n",
+ xwl_give_up("failed to dispatch Wayland events: %s\n",
strerror(errno));
}
@@ -637,13 +861,13 @@ xwl_dispatch_events (struct xwl_screen *xwl_screen)
pollout:
ready = xwl_display_pollout(xwl_screen, 5);
if (ready == -1 && errno != EINTR)
- FatalError("error polling on XWayland fd: %s\n", strerror(errno));
+ 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)
- FatalError("failed to write to XWayland fd: %s\n", strerror(errno));
+ xwl_give_up("failed to write to XWayland fd: %s\n", strerror(errno));
xwl_screen->wait_flush = (ready == 0 || ready == -1 || ret == -1);
}
@@ -721,11 +945,13 @@ wm_selection_callback(CallbackListPtr *p, void *data, void *arg)
static 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;
+ Bool use_eglstreams = FALSE;
- xwl_screen = calloc(sizeof *xwl_screen, 1);
+ xwl_screen = calloc(1, sizeof *xwl_screen);
if (xwl_screen == NULL)
return FALSE;
xwl_screen->wm_fd = -1;
@@ -740,7 +966,7 @@ xwl_screen_init(ScreenPtr pScreen, int argc, char **argv)
dixSetPrivate(&pScreen->devPrivates, &xwl_screen_private_key, xwl_screen);
xwl_screen->screen = pScreen;
-#ifdef GLAMOR_HAS_GBM
+#ifdef XWL_HAS_GLAMOR
xwl_screen->glamor = 1;
#endif
@@ -756,7 +982,7 @@ xwl_screen_init(ScreenPtr pScreen, int argc, char **argv)
else if (strcmp(argv[i], "-listen") == 0) {
if (xwl_screen->listen_fd_count ==
ARRAY_SIZE(xwl_screen->listen_fds))
- FatalError("Too many -listen arguments given, max is %ld\n",
+ FatalError("Too many -listen arguments given, max is %zu\n",
ARRAY_SIZE(xwl_screen->listen_fds));
xwl_screen->listen_fds[xwl_screen->listen_fd_count++] =
@@ -766,8 +992,20 @@ xwl_screen_init(ScreenPtr pScreen, int argc, char **argv)
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)
@@ -850,11 +1088,18 @@ xwl_screen_init(ScreenPtr pScreen, int argc, char **argv)
if (!xwl_screen_init_cursor(xwl_screen))
return FALSE;
-#ifdef GLAMOR_HAS_GBM
- if (xwl_screen->glamor && !xwl_glamor_init(xwl_screen)) {
- ErrorF("Failed to initialize glamor, falling back to sw\n");
- xwl_screen->glamor = 0;
+#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) {
@@ -870,12 +1115,27 @@ xwl_screen_init(ScreenPtr pScreen, int argc, char **argv)
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;
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);
+
+ wl_display_roundtrip(xwl_screen->display);
+ while (xwl_screen->expecting_event)
+ wl_display_roundtrip(xwl_screen->display);
+
return ret;
}
@@ -890,9 +1150,6 @@ xwl_log_handler(const char *format, va_list args)
}
static const ExtensionModule xwayland_extensions[] = {
-#ifdef GLXEXT
- { GlxExtensionInit, "GLX", &noGlxExtension },
-#endif
#ifdef XF86VIDMODE
{ xwlVidModeExtensionInit, XF86VIDMODENAME, &noXFree86VidModeExtension },
#endif
@@ -930,5 +1187,7 @@ InitOutput(ScreenInfo * screen_info, int argc, char **argv)
FatalError("Couldn't add screen\n");
}
+ xorgGlxCreateVendor();
+
LocalAccessScopeUser();
}
diff --git a/xserver/hw/xwayland/xwayland.h b/xserver/hw/xwayland/xwayland.h
index 5e5624be0..463622669 100644
--- a/xserver/hw/xwayland/xwayland.h
+++ b/xserver/hw/xwayland/xwayland.h
@@ -26,7 +26,7 @@
#ifndef XWAYLAND_H
#define XWAYLAND_H
-#include <dix-config.h>
+#include <xwayland-config.h>
#include <stdio.h>
#include <unistd.h>
@@ -44,6 +44,73 @@
#include "relative-pointer-unstable-v1-client-protocol.h"
#include "pointer-constraints-unstable-v1-client-protocol.h"
+#include "tablet-unstable-v2-client-protocol.h"
+#include "xwayland-keyboard-grab-unstable-v1-client-protocol.h"
+#include "xdg-output-unstable-v1-client-protocol.h"
+#include "linux-dmabuf-unstable-v1-client-protocol.h"
+
+struct xwl_format {
+ uint32_t format;
+ int num_modifiers;
+ uint64_t *modifiers;
+};
+
+struct xwl_pixmap;
+struct xwl_window;
+struct xwl_screen;
+
+struct xwl_egl_backend {
+ /* Set by the backend if available */
+ Bool is_available;
+
+ /* 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,
+ Bool *created);
+
+ /* 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.
+ */
+ void (*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);
+};
struct xwl_screen {
int width;
@@ -58,13 +125,13 @@ struct xwl_screen {
int listen_fd_count;
int rootless;
int glamor;
+ int present;
CreateScreenResourcesProcPtr CreateScreenResources;
CloseScreenProcPtr CloseScreen;
- CreateWindowProcPtr CreateWindow;
- DestroyWindowProcPtr DestroyWindow;
RealizeWindowProcPtr RealizeWindow;
UnrealizeWindowProcPtr UnrealizeWindow;
+ DestroyWindowProcPtr DestroyWindow;
XYToWindowProcPtr XYToWindow;
struct xorg_list output_list;
@@ -76,11 +143,13 @@ struct xwl_screen {
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 wl_shell *shell;
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 zxdg_output_manager_v1 *xdg_output_manager;
uint32_t serial;
#define XWL_FORMAT_ARGB8888 (1 << 0)
@@ -90,15 +159,18 @@ struct xwl_screen {
int prepare_read;
int wait_flush;
- char *device_name;
- int drm_fd;
- int fd_render_node;
- struct wl_drm *drm;
- uint32_t formats;
- uint32_t capabilities;
+ uint32_t num_formats;
+ struct xwl_format *formats;
void *egl_display, *egl_context;
- struct gbm_device *gbm;
+
+ 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;
};
struct xwl_window {
@@ -109,8 +181,47 @@ struct xwl_window {
DamagePtr damage;
struct xorg_list link_damage;
struct wl_callback *frame_callback;
+ Bool allow_commits;
+#ifdef GLAMOR_HAS_GBM
+ Bool present_flipped;
+#endif
+};
+
+#ifdef GLAMOR_HAS_GBM
+struct xwl_present_window {
+ struct xwl_screen *xwl_screen;
+ struct xwl_present_event *sync_flip;
+ WindowPtr window;
+ struct xorg_list link;
+
+ uint64_t msc;
+ uint64_t ust;
+
+ OsTimerPtr frame_timer;
+ Bool frame_timer_firing;
+
+ struct wl_callback *frame_callback;
+ struct wl_callback *sync_callback;
+
+ struct xorg_list event_list;
+ struct xorg_list release_queue;
};
+struct xwl_present_event {
+ uint64_t event_id;
+ uint64_t target_msc;
+
+ Bool abort;
+ Bool pending;
+ Bool buffer_released;
+
+ struct xwl_present_window *xwl_present_window;
+ struct wl_buffer *buffer;
+
+ struct xorg_list list;
+};
+#endif
+
#define MODIFIER_META 0x01
struct xwl_touch {
@@ -126,26 +237,36 @@ struct xwl_pointer_warp_emulator {
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;
- struct wl_surface *cursor;
- struct wl_callback *cursor_frame_cb;
- Bool cursor_needs_update;
+ struct xwl_cursor cursor;
WindowPtr last_xwindow;
struct xorg_list touches;
@@ -154,6 +275,7 @@ struct xwl_seat {
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;
@@ -172,27 +294,97 @@ struct xwl_seat {
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;
};
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;
};
-struct xwl_pixmap;
-
void xwl_sync_events (struct xwl_screen *xwl_screen);
Bool xwl_screen_init_cursor(struct xwl_screen *xwl_screen);
struct xwl_screen *xwl_screen_get(ScreenPtr screen);
+void xwl_tablet_tool_set_cursor(struct xwl_tablet_tool *tool);
void xwl_seat_set_cursor(struct xwl_seat *xwl_seat);
void xwl_seat_destroy(struct xwl_seat *xwl_seat);
@@ -227,6 +419,7 @@ RRModePtr xwayland_cvt(int HDisplay, int VDisplay,
void xwl_pixmap_set_private(PixmapPtr pixmap, struct xwl_pixmap *xwl_pixmap);
struct xwl_pixmap *xwl_pixmap_get(PixmapPtr pixmap);
+struct xwl_window *xwl_window_from_window(WindowPtr window);
Bool xwl_shm_create_screen_resources(ScreenPtr screen);
PixmapPtr xwl_shm_create_pixmap(ScreenPtr screen, int width, int height,
@@ -234,20 +427,65 @@ PixmapPtr xwl_shm_create_pixmap(ScreenPtr screen, int width, int height,
Bool xwl_shm_destroy_pixmap(PixmapPtr pixmap);
struct wl_buffer *xwl_shm_pixmap_get_wl_buffer(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_init_glamor(struct xwl_screen *xwl_screen,
- uint32_t id, uint32_t version);
-struct wl_buffer *xwl_glamor_pixmap_get_wl_buffer(PixmapPtr pixmap);
+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,
+ Bool *created);
+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);
+void 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);
+
+#ifdef GLAMOR_HAS_GBM
+Bool xwl_present_init(ScreenPtr screen);
+void xwl_present_cleanup(WindowPtr window);
+void xwl_present_unrealize_window(WindowPtr window);
+#endif /* GLAMOR_HAS_GBM */
#ifdef XV
/* glamor Xv Adaptor */
Bool xwl_glamor_xv_init(ScreenPtr pScreen);
-#endif
+#endif /* XV */
+
+#endif /* XWL_HAS_GLAMOR */
+
+void xwl_screen_release_tablet_manager(struct xwl_screen *xwl_screen);
+
+void xwl_screen_init_xdg_output(struct xwl_screen *xwl_screen);
#ifdef XF86VIDMODE
void xwlVidModeExtensionInit(void);
#endif
+#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