aboutsummaryrefslogtreecommitdiff
path: root/xorg-server
diff options
context:
space:
mode:
Diffstat (limited to 'xorg-server')
-rw-r--r--xorg-server/config/config.c85
-rw-r--r--xorg-server/config/udev.c43
-rw-r--r--xorg-server/configure.ac35
-rw-r--r--xorg-server/dix/main.c4
-rw-r--r--xorg-server/glamor/Makefile.am1
-rw-r--r--xorg-server/glamor/glamor.c21
-rw-r--r--xorg-server/glamor/glamor.h64
-rw-r--r--xorg-server/glamor/glamor_egl.c97
-rw-r--r--xorg-server/glamor/glamor_eglmodule.c3
-rw-r--r--xorg-server/glamor/glamor_xv.c19
-rw-r--r--xorg-server/hw/kdrive/ephyr/Makefile.am20
-rw-r--r--xorg-server/hw/kdrive/ephyr/ephyr.c45
-rw-r--r--xorg-server/hw/kdrive/ephyr/ephyr.h14
-rw-r--r--xorg-server/hw/kdrive/ephyr/ephyr_glamor_glx.c331
-rw-r--r--xorg-server/hw/kdrive/ephyr/ephyr_glamor_glx.h73
-rw-r--r--xorg-server/hw/kdrive/ephyr/ephyrinit.c14
-rw-r--r--xorg-server/hw/kdrive/ephyr/hostx.c131
-rw-r--r--xorg-server/hw/xfree86/Makefile.am7
-rw-r--r--xorg-server/hw/xfree86/common/xf86Events.c15
-rw-r--r--xorg-server/hw/xfree86/common/xf86Init.c3
-rw-r--r--xorg-server/hw/xfree86/common/xf86Module.h4
-rw-r--r--xorg-server/hw/xfree86/common/xf86Xinput.c65
-rw-r--r--xorg-server/hw/xfree86/common/xf86Xinput.h8
-rw-r--r--xorg-server/hw/xfree86/common/xf86platformBus.c60
-rw-r--r--xorg-server/hw/xfree86/common/xf86platformBus.h15
-rw-r--r--xorg-server/hw/xfree86/glamor_egl/Makefile.am43
-rw-r--r--xorg-server/hw/xfree86/os-support/linux/Makefile.am6
-rw-r--r--xorg-server/hw/xfree86/os-support/linux/lnx_init.c25
-rw-r--r--xorg-server/hw/xfree86/os-support/linux/lnx_platform.c45
-rw-r--r--xorg-server/hw/xfree86/os-support/linux/systemd-logind.c532
-rw-r--r--xorg-server/hw/xfree86/os-support/shared/posix_tty.c6
-rw-r--r--xorg-server/include/Makefile.am1
-rw-r--r--xorg-server/include/dix-config.h.in6
-rw-r--r--xorg-server/include/hotplug.h30
-rw-r--r--xorg-server/include/systemd-logind.h45
35 files changed, 1794 insertions, 122 deletions
diff --git a/xorg-server/config/config.c b/xorg-server/config/config.c
index 760cf193a..7971b8740 100644
--- a/xorg-server/config/config.c
+++ b/xorg-server/config/config.c
@@ -27,10 +27,12 @@
#include <dix-config.h>
#endif
+#include <unistd.h>
#include "os.h"
#include "inputstr.h"
#include "hotplug.h"
#include "config-backends.h"
+#include "systemd-logind.h"
void
config_pre_init(void)
@@ -145,30 +147,111 @@ config_odev_free_attribute_list(struct OdevAttributes *attribs)
free(attribs);
}
+static struct OdevAttribute *
+config_odev_find_attribute(struct OdevAttributes *attribs, int attrib_id)
+{
+ struct OdevAttribute *oa;
+
+ xorg_list_for_each_entry(oa, &attribs->list, member) {
+ if (oa->attrib_id == attrib_id)
+ return oa;
+ }
+ return NULL;
+}
+
Bool
config_odev_add_attribute(struct OdevAttributes *attribs, int attrib,
const char *attrib_name)
{
struct OdevAttribute *oa;
- oa = malloc(sizeof(struct OdevAttribute));
+ oa = config_odev_find_attribute(attribs, attrib);
+ if (!oa)
+ oa = calloc(1, sizeof(struct OdevAttribute));
if (!oa)
return FALSE;
oa->attrib_id = attrib;
+ free(oa->attrib_name);
oa->attrib_name = strdup(attrib_name);
+ oa->attrib_type = ODEV_ATTRIB_STRING;
xorg_list_append(&oa->member, &attribs->list);
return TRUE;
}
+Bool
+config_odev_add_int_attribute(struct OdevAttributes *attribs, int attrib,
+ int attrib_value)
+{
+ struct OdevAttribute *oa;
+
+ oa = config_odev_find_attribute(attribs, attrib);
+ if (!oa)
+ oa = calloc(1, sizeof(struct OdevAttribute));
+ if (!oa)
+ return FALSE;
+
+ oa->attrib_id = attrib;
+ oa->attrib_value = attrib_value;
+ oa->attrib_type = ODEV_ATTRIB_INT;
+ xorg_list_append(&oa->member, &attribs->list);
+ return TRUE;
+}
+
+char *
+config_odev_get_attribute(struct OdevAttributes *attribs, int attrib_id)
+{
+ struct OdevAttribute *oa;
+
+ oa = config_odev_find_attribute(attribs, attrib_id);
+ if (!oa)
+ return NULL;
+
+ if (oa->attrib_type != ODEV_ATTRIB_STRING) {
+ LogMessage(X_ERROR, "Error %s called for non string attrib %d\n",
+ __func__, attrib_id);
+ return NULL;
+ }
+ return oa->attrib_name;
+}
+
+int
+config_odev_get_int_attribute(struct OdevAttributes *attribs, int attrib_id, int def)
+{
+ struct OdevAttribute *oa;
+
+ oa = config_odev_find_attribute(attribs, attrib_id);
+ if (!oa)
+ return def;
+
+ if (oa->attrib_type != ODEV_ATTRIB_INT) {
+ LogMessage(X_ERROR, "Error %s called for non integer attrib %d\n",
+ __func__, attrib_id);
+ return def;
+ }
+
+ return oa->attrib_value;
+}
+
void
config_odev_free_attributes(struct OdevAttributes *attribs)
{
struct OdevAttribute *iter, *safe;
+ int major = 0, minor = 0, fd = -1;
xorg_list_for_each_entry_safe(iter, safe, &attribs->list, member) {
+ switch (iter->attrib_id) {
+ case ODEV_ATTRIB_MAJOR: major = iter->attrib_value; break;
+ case ODEV_ATTRIB_MINOR: minor = iter->attrib_value; break;
+ case ODEV_ATTRIB_FD: fd = iter->attrib_value; break;
+ }
xorg_list_del(&iter->member);
free(iter->attrib_name);
free(iter);
}
+
+ if (fd != -1) {
+ systemd_logind_release_fd(major, minor);
+ close(fd);
+ }
}
diff --git a/xorg-server/config/udev.c b/xorg-server/config/udev.c
index 68ed34843..d70eeb48c 100644
--- a/xorg-server/config/udev.c
+++ b/xorg-server/config/udev.c
@@ -29,6 +29,7 @@
#include <libudev.h>
#include <ctype.h>
+#include <unistd.h>
#include "input.h"
#include "inputstr.h"
@@ -36,6 +37,7 @@
#include "config-backends.h"
#include "os.h"
#include "globals.h"
+#include "systemd-logind.h"
#define UDEV_XKB_PROP_KEY "xkb"
@@ -55,9 +57,18 @@ static struct udev_monitor *udev_monitor;
#ifdef CONFIG_UDEV_KMS
static Bool
config_udev_odev_setup_attribs(const char *path, const char *syspath,
+ int major, int minor,
config_odev_probe_proc_ptr probe_callback);
#endif
+static char itoa_buf[16];
+
+static const char *itoa(int i)
+{
+ snprintf(itoa_buf, sizeof(itoa_buf), "%d", i);
+ return itoa_buf;
+}
+
static void
device_added(struct udev_device *udev_device)
{
@@ -73,6 +84,7 @@ device_added(struct udev_device *udev_device)
struct udev_device *parent;
int rc;
const char *dev_seat;
+ dev_t devnum;
path = udev_device_get_devnode(udev_device);
@@ -91,6 +103,8 @@ device_added(struct udev_device *udev_device)
if (!SeatId && strcmp(dev_seat, "seat0"))
return;
+ devnum = udev_device_get_devnum(udev_device);
+
#ifdef CONFIG_UDEV_KMS
if (!strcmp(udev_device_get_subsystem(udev_device), "drm")) {
const char *sysname = udev_device_get_sysname(udev_device);
@@ -98,9 +112,14 @@ device_added(struct udev_device *udev_device)
if (strncmp(sysname, "card", 4) != 0)
return;
+ /* Check for devices already added through xf86platformProbe() */
+ if (xf86_find_platform_device_by_devnum(major(devnum), minor(devnum)))
+ return;
+
LogMessage(X_INFO, "config/udev: Adding drm device (%s)\n", path);
- config_udev_odev_setup_attribs(path, syspath, NewGPUDeviceRequest);
+ config_udev_odev_setup_attribs(path, syspath, major(devnum),
+ minor(devnum), NewGPUDeviceRequest);
return;
}
#endif
@@ -153,6 +172,8 @@ device_added(struct udev_device *udev_device)
input_options = input_option_new(input_options, "name", name);
input_options = input_option_new(input_options, "path", path);
input_options = input_option_new(input_options, "device", path);
+ input_options = input_option_new(input_options, "major", itoa(major(devnum)));
+ input_options = input_option_new(input_options, "minor", itoa(minor(devnum)));
if (path)
attrs.device = strdup(path);
@@ -270,6 +291,7 @@ device_removed(struct udev_device *device)
if (!strcmp(udev_device_get_subsystem(device), "drm")) {
const char *sysname = udev_device_get_sysname(device);
const char *path = udev_device_get_devnode(device);
+ dev_t devnum = udev_device_get_devnum(device);
if (strncmp(sysname,"card", 4) != 0)
return;
@@ -277,7 +299,10 @@ device_removed(struct udev_device *device)
if (!path)
return;
- config_udev_odev_setup_attribs(path, syspath, DeleteGPUDeviceRequest);
+ config_udev_odev_setup_attribs(path, syspath, major(devnum),
+ minor(devnum), DeleteGPUDeviceRequest);
+ /* Retry vtenter after a drm node removal */
+ systemd_logind_vtenter();
return;
}
#endif
@@ -427,6 +452,7 @@ config_udev_fini(void)
static Bool
config_udev_odev_setup_attribs(const char *path, const char *syspath,
+ int major, int minor,
config_odev_probe_proc_ptr probe_callback)
{
struct OdevAttributes *attribs = config_odev_allocate_attribute_list();
@@ -443,6 +469,14 @@ config_udev_odev_setup_attribs(const char *path, const char *syspath,
if (ret == FALSE)
goto fail;
+ ret = config_odev_add_int_attribute(attribs, ODEV_ATTRIB_MAJOR, major);
+ if (ret == FALSE)
+ goto fail;
+
+ ret = config_odev_add_int_attribute(attribs, ODEV_ATTRIB_MINOR, minor);
+ if (ret == FALSE)
+ goto fail;
+
/* ownership of attribs is passed to probe layer */
probe_callback(attribs);
return TRUE;
@@ -477,6 +511,7 @@ config_udev_odev_probe(config_odev_probe_proc_ptr probe_callback)
struct udev_device *udev_device = udev_device_new_from_syspath(udev, syspath);
const char *path = udev_device_get_devnode(udev_device);
const char *sysname = udev_device_get_sysname(udev_device);
+ dev_t devnum = udev_device_get_devnum(udev_device);
if (!path || !syspath)
goto no_probe;
@@ -485,8 +520,8 @@ config_udev_odev_probe(config_odev_probe_proc_ptr probe_callback)
else if (strncmp(sysname, "card", 4) != 0)
goto no_probe;
- config_udev_odev_setup_attribs(path, syspath, probe_callback);
-
+ config_udev_odev_setup_attribs(path, syspath, major(devnum),
+ minor(devnum), probe_callback);
no_probe:
udev_device_unref(udev_device);
}
diff --git a/xorg-server/configure.ac b/xorg-server/configure.ac
index 0fb2fc375..162c0cf3c 100644
--- a/xorg-server/configure.ac
+++ b/xorg-server/configure.ac
@@ -626,6 +626,7 @@ AC_ARG_ENABLE(clientids, AS_HELP_STRING([--disable-clientids], [Build Xorg
AC_ARG_ENABLE(pciaccess, AS_HELP_STRING([--enable-pciaccess], [Build Xorg with pciaccess library (default: enabled)]), [PCI=$enableval], [PCI=yes])
AC_ARG_ENABLE(linux_acpi, AS_HELP_STRING([--disable-linux-acpi], [Disable building ACPI support on Linux (if available).]), [enable_linux_acpi=$enableval], [enable_linux_acpi=yes])
AC_ARG_ENABLE(linux_apm, AS_HELP_STRING([--disable-linux-apm], [Disable building APM support on Linux (if available).]), [enable_linux_apm=$enableval], [enable_linux_apm=yes])
+AC_ARG_ENABLE(systemd-logind, AC_HELP_STRING([--enable-systemd-logind], [Build systemd-logind support (default: auto)]), [SYSTEMD_LOGIND=$enableval], [SYSTEMD_LOGIND=auto])
dnl DDXes.
AC_ARG_ENABLE(xorg, AS_HELP_STRING([--enable-xorg], [Build Xorg server (default: auto)]), [XORG=$enableval], [XORG=auto])
@@ -806,6 +807,8 @@ LIBAPPLEWM="applewm >= 1.4"
LIBDMX="dmx >= 1.0.99.1"
LIBDRI="dri >= 7.8.0"
LIBDRM="libdrm >= 2.3.0"
+LIBEGL="egl"
+LIBGBM="gbm >= 9"
LIBGL="gl >= 7.1.0"
LIBXEXT="xext >= 1.0.99.4"
LIBXFONT="xfont >= 1.4.2"
@@ -901,6 +904,26 @@ if test "x$CONFIG_HAL" = xyes; then
fi
AM_CONDITIONAL(CONFIG_HAL, [test "x$CONFIG_HAL" = xyes])
+if test "x$SYSTEMD_LOGIND" = xauto; then
+ if test "x$HAVE_DBUS" = xyes -a "x$CONFIG_UDEV" = xyes ; then
+ SYSTEMD_LOGIND=yes
+ else
+ SYSTEMD_LOGIND=no
+ fi
+fi
+if test "x$SYSTEMD_LOGIND" = xyes; then
+ if ! test "x$HAVE_DBUS" = xyes; then
+ AC_MSG_ERROR([systemd-logind requested, but D-Bus is not installed.])
+ fi
+ if ! test "x$CONFIG_UDEV" = xyes ; then
+ AC_MSG_ERROR([systemd-logind is only supported in combination with udev configuration.])
+ fi
+
+ AC_DEFINE(SYSTEMD_LOGIND, 1, [Enable systemd-logind integration])
+ NEED_DBUS="yes"
+fi
+AM_CONDITIONAL(SYSTEMD_LOGIND, [test "x$SYSTEMD_LOGIND" = xyes])
+
if test "x$NEED_DBUS" = xyes; then
AC_DEFINE(NEED_DBUS, 1, [Enable D-Bus core])
fi
@@ -2070,7 +2093,15 @@ AM_CONDITIONAL([GLAMOR], [test "x$GLAMOR" = xyes])
if test "x$GLAMOR" = xyes; then
AC_DEFINE(GLAMOR, 1, [Build glamor])
PKG_CHECK_MODULES([GLAMOR], [epoxy])
+
+ PKG_CHECK_MODULES(GBM, "$LIBGBM", [GBM=yes], [GBM=no])
+ if test "x$GBM" = xyes; then
+ AC_DEFINE(GLAMOR_HAS_GBM, 1,
+ [Build glamor with GBM-based EGL support])
+ fi
+
fi
+AM_CONDITIONAL([GLAMOR_EGL], [test "x$GBM" = xyes])
dnl XWin DDX
@@ -2319,6 +2350,9 @@ if test "$KDRIVE" = yes; then
if test "x$DRI" = xyes && test "x$GLX" = xyes; then
XEPHYR_REQUIRED_LIBS="$XEPHYR_REQUIRED_LIBS libdrm xcb-glx xcb-xf86dri > 1.6"
fi
+ if test "x$GLAMOR" = xyes; then
+ XEPHYR_REQUIRED_LIBS="$XEPHYR_REQUIRED_LIBS x11-xcb"
+ fi
if test "x$XEPHYR" = xauto; then
PKG_CHECK_MODULES(XEPHYR, $XEPHYR_REQUIRED_LIBS, [XEPHYR="yes"], [XEPHYR="no"])
@@ -2476,6 +2510,7 @@ hw/xfree86/exa/Makefile
hw/xfree86/exa/man/Makefile
hw/xfree86/fbdevhw/Makefile
hw/xfree86/fbdevhw/man/Makefile
+hw/xfree86/glamor_egl/Makefile
hw/xfree86/i2c/Makefile
hw/xfree86/int10/Makefile
hw/xfree86/loader/Makefile
diff --git a/xorg-server/dix/main.c b/xorg-server/dix/main.c
index fcc1ad30a..7427e08ca 100644
--- a/xorg-server/dix/main.c
+++ b/xorg-server/dix/main.c
@@ -175,6 +175,9 @@ dix_main(int argc, char *argv[], char *envp[])
clients[0] = serverClient;
currentMaxClients = 1;
+ /* clear any existing selections */
+ InitSelections();
+
/* Initialize privates before first allocation */
dixResetPrivates();
@@ -192,7 +195,6 @@ dix_main(int argc, char *argv[], char *envp[])
InitAtoms();
InitEvents();
- InitSelections();
InitGlyphCaching();
dixResetRegistry();
ResetFontPrivateIndex();
diff --git a/xorg-server/glamor/Makefile.am b/xorg-server/glamor/Makefile.am
index 12a57c441..77492bcaa 100644
--- a/xorg-server/glamor/Makefile.am
+++ b/xorg-server/glamor/Makefile.am
@@ -37,7 +37,6 @@ libglamor_la_SOURCES = \
glamor_window.c\
glamor_fbo.c\
glamor_compositerects.c\
- glamor_xv.c\
glamor_utils.h\
glamor.h
diff --git a/xorg-server/glamor/glamor.c b/xorg-server/glamor/glamor.c
index 7d8228cdd..fa753bb1a 100644
--- a/xorg-server/glamor/glamor.c
+++ b/xorg-server/glamor/glamor.c
@@ -123,6 +123,17 @@ glamor_set_screen_pixmap(PixmapPtr screen_pixmap, PixmapPtr *back_pixmap)
glamor_priv->back_pixmap = back_pixmap;
}
+uint32_t
+glamor_get_pixmap_texture(PixmapPtr pixmap)
+{
+ glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);
+
+ if (pixmap_priv->type != GLAMOR_TEXTURE_ONLY)
+ return 0;
+
+ return pixmap_priv->base.fbo->tex;
+}
+
PixmapPtr
glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth,
unsigned int usage)
@@ -556,16 +567,16 @@ glamor_enable_dri3(ScreenPtr screen)
}
Bool
-glamor_is_dri3_support_enabled(ScreenPtr screen)
+glamor_supports_pixmap_import_export(ScreenPtr screen)
{
glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
return glamor_priv->dri3_enabled;
}
-int
-glamor_dri3_fd_from_pixmap(ScreenPtr screen,
- PixmapPtr pixmap, CARD16 *stride, CARD32 *size)
+_X_EXPORT int
+glamor_fd_from_pixmap(ScreenPtr screen,
+ PixmapPtr pixmap, CARD16 *stride, CARD32 *size)
{
glamor_pixmap_private *pixmap_priv;
glamor_screen_private *glamor_priv =
@@ -589,7 +600,7 @@ glamor_dri3_fd_from_pixmap(ScreenPtr screen,
}
int
-glamor_dri3_name_from_pixmap(PixmapPtr pixmap)
+glamor_name_from_pixmap(PixmapPtr pixmap)
{
glamor_pixmap_private *pixmap_priv;
glamor_screen_private *glamor_priv =
diff --git a/xorg-server/glamor/glamor.h b/xorg-server/glamor/glamor.h
index eec687256..e12f497cb 100644
--- a/xorg-server/glamor/glamor.h
+++ b/xorg-server/glamor/glamor.h
@@ -35,6 +35,9 @@
#include <picturestr.h>
#include <fb.h>
#include <fbpict.h>
+#ifdef GLAMOR_FOR_XORG
+#include <xf86xv.h>
+#endif
struct glamor_context;
@@ -64,10 +67,12 @@ typedef enum glamor_pixmap_type {
#define GLAMOR_USE_SCREEN (1 << 1)
#define GLAMOR_USE_PICTURE_SCREEN (1 << 2)
#define GLAMOR_USE_EGL_SCREEN (1 << 3)
+#define GLAMOR_NO_DRI3 (1 << 4)
#define GLAMOR_VALID_FLAGS (GLAMOR_INVERTED_Y_AXIS \
| GLAMOR_USE_SCREEN \
| GLAMOR_USE_PICTURE_SCREEN \
- | GLAMOR_USE_EGL_SCREEN)
+ | GLAMOR_USE_EGL_SCREEN \
+ | GLAMOR_NO_DRI3)
/* @glamor_init: Initialize glamor internal data structure.
*
@@ -124,6 +129,8 @@ extern _X_EXPORT Bool glamor_close_screen(ScreenPtr screen);
extern _X_EXPORT void glamor_set_screen_pixmap(PixmapPtr screen_pixmap,
PixmapPtr *back_pixmap);
+extern _X_EXPORT uint32_t glamor_get_pixmap_texture(PixmapPtr pixmap);
+
/* @glamor_glyphs_init: Initialize glyphs internal data structures.
*
* @pScreen: Current screen pointer.
@@ -168,21 +175,23 @@ extern _X_EXPORT int glamor_egl_dri3_fd_name_from_tex(ScreenPtr, PixmapPtr,
unsigned int, Bool,
CARD16 *, CARD32 *);
-/* @glamor_is_dri3_support_enabled: Returns if DRI3 support is enabled.
+/* @glamor_supports_pixmap_import_export: Returns whether
+ * glamor_fd_from_pixmap(), glamor_name_from_pixmap(), and
+ * glamor_pixmap_from_fd() are supported.
*
* @screen: Current screen pointer.
*
- * To have DRI3 support enabled, glamor and glamor_egl need to be initialized,
- * and glamor_egl_init_textured_pixmap need to be called. glamor also
- * has to be compiled with gbm support.
- * The EGL layer need to have the following extensions working:
+ * To have DRI3 support enabled, glamor and glamor_egl need to be
+ * initialized. glamor also has to be compiled with gbm support.
+ *
+ * The EGL layer needs to have the following extensions working:
+ *
* .EGL_KHR_gl_texture_2D_image
* .EGL_EXT_image_dma_buf_import
- * If DRI3 support is not enabled, the following helpers will return an error.
* */
-extern _X_EXPORT Bool glamor_is_dri3_support_enabled(ScreenPtr screen);
+extern _X_EXPORT Bool glamor_supports_pixmap_import_export(ScreenPtr screen);
-/* @glamor_dri3_fd_from_pixmap: DRI3 helper to get a dma-buf fd from a pixmap.
+/* @glamor_fd_from_pixmap: Get a dma-buf fd from a pixmap.
*
* @screen: Current screen pointer.
* @pixmap: The pixmap from which we want the fd.
@@ -193,22 +202,25 @@ extern _X_EXPORT Bool glamor_is_dri3_support_enabled(ScreenPtr screen);
* content.
* Returns the fd on success, -1 on error.
* */
-extern _X_EXPORT int glamor_dri3_fd_from_pixmap(ScreenPtr screen,
- PixmapPtr pixmap,
- CARD16 *stride, CARD32 *size);
+extern _X_EXPORT int glamor_fd_from_pixmap(ScreenPtr screen,
+ PixmapPtr pixmap,
+ CARD16 *stride, CARD32 *size);
-/* @glamor_dri3_name_from_pixmap: helper to get an gem name from a pixmap.
+/**
+ * @glamor_name_from_pixmap: Gets a gem name from a pixmap.
*
* @pixmap: The pixmap from which we want the gem name.
*
- * the pixmap and the buffer associated by the gem name will share the same
- * content. This function can be used by the DDX to support DRI2, but needs
- * glamor DRI3 support to be activated.
+ * the pixmap and the buffer associated by the gem name will share the
+ * same content. This function can be used by the DDX to support DRI2,
+ * and needs the same set of buffer export GL extensions as DRI3
+ * support.
+ *
* Returns the name on success, -1 on error.
* */
-extern _X_EXPORT int glamor_dri3_name_from_pixmap(PixmapPtr pixmap);
+extern _X_EXPORT int glamor_name_from_pixmap(PixmapPtr pixmap);
-/* @glamor_egl_dri3_pixmap_from_fd: DRI3 helper to get a pixmap from a dma-buf fd.
+/* @glamor_pixmap_from_fd: Creates a pixmap to wrap a dma-buf fd.
*
* @screen: Current screen pointer.
* @fd: The dma-buf fd to import.
@@ -220,13 +232,13 @@ extern _X_EXPORT int glamor_dri3_name_from_pixmap(PixmapPtr pixmap);
*
* Returns a valid pixmap if the import succeeded, else NULL.
* */
-extern _X_EXPORT PixmapPtr glamor_egl_dri3_pixmap_from_fd(ScreenPtr screen,
- int fd,
- CARD16 width,
- CARD16 height,
- CARD16 stride,
- CARD8 depth,
- CARD8 bpp);
+extern _X_EXPORT PixmapPtr glamor_pixmap_from_fd(ScreenPtr screen,
+ int fd,
+ CARD16 width,
+ CARD16 height,
+ CARD16 stride,
+ CARD8 depth,
+ CARD8 bpp);
#ifdef GLAMOR_FOR_XORG
@@ -432,7 +444,7 @@ extern _X_EXPORT Bool glamor_poly_line_nf(DrawablePtr pDrawable, GCPtr pGC,
extern _X_EXPORT Bool glamor_poly_lines_nf(DrawablePtr drawable, GCPtr gc,
int mode, int n, DDXPointPtr points);
-#if 0
+#ifdef GLAMOR_FOR_XORG
extern _X_EXPORT XF86VideoAdaptorPtr glamor_xv_init(ScreenPtr pScreen,
int num_texture_ports);
#endif
diff --git a/xorg-server/glamor/glamor_egl.c b/xorg-server/glamor/glamor_egl.c
index 9dcba71ce..05e6bd02e 100644
--- a/xorg-server/glamor/glamor_egl.c
+++ b/xorg-server/glamor/glamor_egl.c
@@ -50,6 +50,7 @@
#include "glamor.h"
#include "glamor_priv.h"
+#include "dri3.h"
static const char glamor_name[] = "glamor";
@@ -68,6 +69,7 @@ struct glamor_egl_screen_private {
EGLDisplay display;
EGLContext context;
EGLint major, minor;
+ char *device_path;
CreateScreenResourcesProcPtr CreateScreenResources;
CloseScreenProcPtr CloseScreen;
@@ -453,12 +455,12 @@ glamor_egl_dri3_fd_name_from_tex(ScreenPtr screen,
#endif
}
-PixmapPtr
-glamor_egl_dri3_pixmap_from_fd(ScreenPtr screen,
- int fd,
- CARD16 width,
- CARD16 height,
- CARD16 stride, CARD8 depth, CARD8 bpp)
+_X_EXPORT PixmapPtr
+glamor_pixmap_from_fd(ScreenPtr screen,
+ int fd,
+ CARD16 width,
+ CARD16 height,
+ CARD16 stride, CARD8 depth, CARD8 bpp)
{
#ifdef GLAMOR_HAS_GBM
ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
@@ -627,10 +629,67 @@ glamor_egl_has_extension(struct glamor_egl_screen_private *glamor_egl,
return FALSE;
}
+static int
+glamor_dri3_open(ScreenPtr screen,
+ RRProviderPtr provider,
+ int *fdp)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+ struct glamor_egl_screen_private *glamor_egl =
+ glamor_egl_get_screen_private(scrn);
+ int fd;
+ drm_magic_t magic;
+
+ fd = open(glamor_egl->device_path, O_RDWR|O_CLOEXEC);
+ if (fd < 0)
+ return BadAlloc;
+
+ /* Before FD passing in the X protocol with DRI3 (and increased
+ * security of rendering with per-process address spaces on the
+ * GPU), the kernel had to come up with a way to have the server
+ * decide which clients got to access the GPU, which was done by
+ * each client getting a unique (magic) number from the kernel,
+ * passing it to the server, and the server then telling the
+ * kernel which clients were authenticated for using the device.
+ *
+ * Now that we have FD passing, the server can just set up the
+ * authentication on its own and hand the prepared FD off to the
+ * client.
+ */
+ if (drmGetMagic(fd, &magic) < 0) {
+ if (errno == EACCES) {
+ /* Assume that we're on a render node, and the fd is
+ * already as authenticated as it should be.
+ */
+ *fdp = fd;
+ return Success;
+ } else {
+ close(fd);
+ return BadMatch;
+ }
+ }
+
+ if (drmAuthMagic(glamor_egl->fd, magic) < 0) {
+ close(fd);
+ return BadMatch;
+ }
+
+ *fdp = fd;
+ return Success;
+}
+
+static dri3_screen_info_rec glamor_dri3_info = {
+ .version = 0,
+ .open = glamor_dri3_open,
+ .pixmap_from_fd = glamor_pixmap_from_fd,
+ .fd_from_pixmap = glamor_fd_from_pixmap,
+};
+
void
glamor_egl_screen_init(ScreenPtr screen, struct glamor_context *glamor_ctx)
{
ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+ glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
struct glamor_egl_screen_private *glamor_egl =
glamor_egl_get_screen_private(scrn);
@@ -642,6 +701,30 @@ glamor_egl_screen_init(ScreenPtr screen, struct glamor_context *glamor_ctx)
glamor_ctx->get_context = glamor_egl_get_context;
glamor_ctx->put_context = glamor_egl_put_context;
+
+ if (glamor_egl->dri3_capable) {
+ /* Tell the core that we have the interfaces for import/export
+ * of pixmaps.
+ */
+ glamor_enable_dri3(screen);
+
+ /* If the driver wants to do its own auth dance (e.g. Xwayland
+ * on pre-3.15 kernels that don't have render nodes and thus
+ * has the wayland compositor as a master), then it needs us
+ * to stay out of the way and let it init DRI3 on its own.
+ */
+ if (!(glamor_priv->flags & GLAMOR_NO_DRI3)) {
+ /* To do DRI3 device FD generation, we need to open a new fd
+ * to the same device we were handed in originally.
+ */
+ glamor_egl->device_path = drmGetDeviceNameFromFd(glamor_egl->fd);
+
+ if (!dri3_screen_init(screen, &glamor_dri3_info)) {
+ xf86DrvMsg(scrn->scrnIndex, X_ERROR,
+ "Failed to initialize DRI3.\n");
+ }
+ }
+ }
}
static void
@@ -658,6 +741,8 @@ glamor_egl_free_screen(ScrnInfoPtr scrn)
if (glamor_egl->gbm)
gbm_device_destroy(glamor_egl->gbm);
#endif
+ free(glamor_egl->device_path);
+
scrn->FreeScreen = glamor_egl->saved_free_screen;
free(glamor_egl);
scrn->FreeScreen(scrn);
diff --git a/xorg-server/glamor/glamor_eglmodule.c b/xorg-server/glamor/glamor_eglmodule.c
index 5ddd60235..d7e183649 100644
--- a/xorg-server/glamor/glamor_eglmodule.c
+++ b/xorg-server/glamor/glamor_eglmodule.c
@@ -30,6 +30,7 @@
#include "dix-config.h"
#include <xorg-server.h>
+#include <xf86.h>
#define GLAMOR_FOR_XORG
#include <xf86Module.h>
#include "glamor.h"
@@ -40,7 +41,7 @@ static XF86ModuleVersionInfo VersRec = {
MODINFOSTRING1,
MODINFOSTRING2,
XORG_VERSION_CURRENT,
- PACKAGE_VERSION_MAJOR, PACKAGE_VERSION_MINOR, PACKAGE_VERSION_PATCHLEVEL,
+ 1, 0, 0, /* version */
ABI_CLASS_ANSIC, /* Only need the ansic layer */
ABI_ANSIC_VERSION,
MOD_CLASS_NONE,
diff --git a/xorg-server/glamor/glamor_xv.c b/xorg-server/glamor/glamor_xv.c
index dc39476b5..fb9045747 100644
--- a/xorg-server/glamor/glamor_xv.c
+++ b/xorg-server/glamor/glamor_xv.c
@@ -32,10 +32,14 @@
* Xv acceleration implementation
*/
-#include "glamor_priv.h"
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
-#ifdef GLAMOR_XV
#include "xf86xv.h"
+#define GLAMOR_FOR_XORG
+#include "glamor_priv.h"
+
#include <X11/extensions/Xv.h>
#include "fourcc.h"
/* Reference color space transform data */
@@ -430,7 +434,7 @@ glamor_xv_put_image(ScrnInfoPtr pScrn,
Bool sync,
RegionPtr clipBoxes, void *data, DrawablePtr pDrawable)
{
- ScreenPtr screen = xf86ScrnToScreen(pScrn);
+ ScreenPtr screen = pDrawable->pScreen;
glamor_port_private *port_priv = (glamor_port_private *) data;
INT32 x1, x2, y1, y2;
int srcPitch, srcPitch2;
@@ -614,12 +618,3 @@ glamor_xv_init(ScreenPtr screen, int num_texture_ports)
}
return adapt;
}
-#else
-#if 0
-XF86VideoAdaptorPtr
-glamor_xv_init(ScreenPtr screen, int num_texture_ports)
-{
- return NULL;
-}
-#endif
-#endif
diff --git a/xorg-server/hw/kdrive/ephyr/Makefile.am b/xorg-server/hw/kdrive/ephyr/Makefile.am
index 6b790fddd..040993ce0 100644
--- a/xorg-server/hw/kdrive/ephyr/Makefile.am
+++ b/xorg-server/hw/kdrive/ephyr/Makefile.am
@@ -27,12 +27,20 @@ AM_CPPFLAGS = \
@XEPHYR_INCS@ \
@XEPHYR_CFLAGS@ \
-I$(top_srcdir) \
+ -I$(top_srcdir)/glamor \
-I$(top_srcdir)/exa
if XV
XV_SRCS = ephyrvideo.c
endif
+if GLAMOR
+GLAMOR_SRCS = \
+ ephyr_glamor_glx.c \
+ ephyr_glamor_glx.h \
+ ()
+endif
+
if DRI
DRI_SRCS = \
ephyrdriext.c \
@@ -59,14 +67,24 @@ Xephyr_SOURCES = \
hostx.h \
$(XV_SRCS) \
$(DRI_SRCS) \
+ $(GLAMOR_SRCS) \
$()
+if GLAMOR
+AM_CPPFLAGS += $(XLIB_CFLAGS)
+XEPHYR_GLAMOR_LIB = \
+ $(top_builddir)/glamor/libglamor.la \
+ $(top_builddir)/glamor/libglamor_egl_stubs.la \
+ $()
+endif
+
Xephyr_LDADD = \
$(top_builddir)/exa/libexa.la \
+ $(XEPHYR_GLAMOR_LIB) \
@KDRIVE_LIBS@ \
@XEPHYR_LIBS@
-Xephyr_DEPENDENCIES = @KDRIVE_LOCAL_LIBS@
+Xephyr_DEPENDENCIES = @KDRIVE_LOCAL_LIBS@ $(XEPHYR_GLAMOR_LIB)
Xephyr_LDFLAGS = $(LD_EXPORT_SYMBOLS_FLAG)
diff --git a/xorg-server/hw/kdrive/ephyr/ephyr.c b/xorg-server/hw/kdrive/ephyr/ephyr.c
index 968127308..def50d8d8 100644
--- a/xorg-server/hw/kdrive/ephyr/ephyr.c
+++ b/xorg-server/hw/kdrive/ephyr/ephyr.c
@@ -43,9 +43,15 @@
#include "ephyrglxext.h"
#endif /* XF86DRI */
+#ifdef GLAMOR
+#include "glamor.h"
+#endif
+#include "ephyr_glamor_glx.h"
+
#include "xkbsrv.h"
extern int KdTsPhyScreen;
+extern Bool ephyr_glamor;
KdKeyboardInfo *ephyrKbd;
KdPointerInfo *ephyrMouse;
@@ -326,15 +332,19 @@ ephyrInternalDamageRedisplay(ScreenPtr pScreen)
int nbox;
BoxPtr pbox;
- nbox = RegionNumRects(pRegion);
- pbox = RegionRects(pRegion);
-
- while (nbox--) {
- hostx_paint_rect(screen,
- pbox->x1, pbox->y1,
- pbox->x1, pbox->y1,
- pbox->x2 - pbox->x1, pbox->y2 - pbox->y1);
- pbox++;
+ if (ephyr_glamor) {
+ ephyr_glamor_damage_redisplay(scrpriv->glamor, pRegion);
+ } else {
+ nbox = RegionNumRects(pRegion);
+ pbox = RegionRects(pRegion);
+
+ while (nbox--) {
+ hostx_paint_rect(screen,
+ pbox->x1, pbox->y1,
+ pbox->x1, pbox->y1,
+ pbox->x2 - pbox->x1, pbox->y2 - pbox->y1);
+ pbox++;
+ }
}
DamageEmpty(scrpriv->pDamage);
}
@@ -662,6 +672,7 @@ ephyrInitScreen(ScreenPtr pScreen)
return TRUE;
}
+
Bool
ephyrFinishInitScreen(ScreenPtr pScreen)
{
@@ -679,6 +690,12 @@ ephyrFinishInitScreen(ScreenPtr pScreen)
return TRUE;
}
+/**
+ * Called by kdrive after calling down the
+ * pScreen->CreateScreenResources() chain, this gives us a chance to
+ * make any pixmaps after the screen and all extensions have been
+ * initialized.
+ */
Bool
ephyrCreateResources(ScreenPtr pScreen)
{
@@ -693,8 +710,13 @@ ephyrCreateResources(ScreenPtr pScreen)
return KdShadowSet(pScreen,
scrpriv->randr,
ephyrShadowUpdate, ephyrWindowLinear);
- else
+ else {
+#ifdef GLAMOR
+ if (ephyr_glamor)
+ ephyr_glamor_create_screen_resources(pScreen);
+#endif
return ephyrSetInternalDamage(pScreen);
+ }
}
void
@@ -1201,6 +1223,9 @@ ephyrPoll(void)
break;
}
+ if (ephyr_glamor)
+ ephyr_glamor_process_event(xev);
+
free(xev);
}
}
diff --git a/xorg-server/hw/kdrive/ephyr/ephyr.h b/xorg-server/hw/kdrive/ephyr/ephyr.h
index 73fdb59e6..34ce4601b 100644
--- a/xorg-server/hw/kdrive/ephyr/ephyr.h
+++ b/xorg-server/hw/kdrive/ephyr/ephyr.h
@@ -80,6 +80,12 @@ typedef struct _ephyrScrPriv {
KdScreenInfo *screen;
int mynum; /* Screen number */
+
+ /**
+ * Per-screen Xlib-using state for glamor (private to
+ * ephyr_glamor_glx.c)
+ */
+ struct ephyr_glamor *glamor;
} EphyrScrPriv;
extern KdCardFuncs ephyrFuncs;
@@ -203,6 +209,14 @@ void
void
ephyrDrawFini(ScreenPtr pScreen);
+/* hostx.c glamor support */
+Bool ephyr_glamor_init(ScreenPtr pScreen);
+Bool ephyr_glamor_create_screen_resources(ScreenPtr pScreen);
+void ephyr_glamor_enable(ScreenPtr pScreen);
+void ephyr_glamor_disable(ScreenPtr pScreen);
+void ephyr_glamor_fini(ScreenPtr pScreen);
+void ephyr_glamor_host_paint_rect(ScreenPtr pScreen);
+
/*ephyvideo.c*/
Bool ephyrInitVideo(ScreenPtr pScreen);
diff --git a/xorg-server/hw/kdrive/ephyr/ephyr_glamor_glx.c b/xorg-server/hw/kdrive/ephyr/ephyr_glamor_glx.c
new file mode 100644
index 000000000..d56907fe7
--- /dev/null
+++ b/xorg-server/hw/kdrive/ephyr/ephyr_glamor_glx.c
@@ -0,0 +1,331 @@
+/*
+ * Copyright © 2013 Intel Corporation
+ *
+ * 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.
+ */
+
+/** @file ephyr_glamor_glx.c
+ *
+ * Separate file for hiding Xlib and GLX-using parts of xephyr from
+ * the rest of the server-struct-aware build.
+ */
+
+#include <stdlib.h>
+#include <X11/Xlib.h>
+#include <X11/Xlibint.h>
+#undef Xcalloc
+#undef Xrealloc
+#undef Xfree
+#include <X11/Xlib-xcb.h>
+#include <xcb/xcb_aux.h>
+#include <pixman.h>
+#include <epoxy/glx.h>
+#include "ephyr_glamor_glx.h"
+#include "os.h"
+#include <X11/Xproto.h>
+
+/** @{
+ *
+ * global state for Xephyr with glamor.
+ *
+ * Xephyr can render with multiple windows, but all the windows have
+ * to be on the same X connection and all have to have the same
+ * visual.
+ */
+static Display *dpy;
+static XVisualInfo *visual_info;
+static GLXFBConfig fb_config;
+/** @} */
+
+/**
+ * Per-screen state for Xephyr with glamor.
+ */
+struct ephyr_glamor {
+ GLXContext ctx;
+ Window win;
+ GLXWindow glx_win;
+
+ GLuint tex;
+
+ GLuint texture_shader;
+ GLuint texture_shader_position_loc;
+ GLuint texture_shader_texcoord_loc;
+};
+
+static GLint
+ephyr_glamor_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
+ephyr_glamor_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
+ephyr_glamor_setup_texturing_shader(struct ephyr_glamor *glamor)
+{
+ const char *vs_source =
+ "attribute vec2 texcoord;\n"
+ "attribute vec2 position;\n"
+ "varying vec2 t;\n"
+ "\n"
+ "void main()\n"
+ "{\n"
+ " t = texcoord;\n"
+ " gl_Position = vec4(position, 0, 1);\n"
+ "}\n";
+
+ const char *fs_source =
+ "varying vec2 t;\n"
+ "uniform sampler2D s; /* initially 0 */\n"
+ "\n"
+ "void main()\n"
+ "{\n"
+ " gl_FragColor = texture2D(s, t);\n"
+ "}\n";
+
+ GLuint fs, vs, prog;
+
+ vs = ephyr_glamor_compile_glsl_prog(GL_VERTEX_SHADER, vs_source);
+ fs = ephyr_glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, fs_source);
+ prog = ephyr_glamor_build_glsl_prog(vs, fs);
+
+ glamor->texture_shader = prog;
+ glamor->texture_shader_position_loc = glGetAttribLocation(prog, "position");
+ assert(glamor->texture_shader_position_loc != -1);
+ glamor->texture_shader_texcoord_loc = glGetAttribLocation(prog, "texcoord");
+ assert(glamor->texture_shader_texcoord_loc != -1);
+}
+
+xcb_connection_t *
+ephyr_glamor_connect(void)
+{
+ dpy = XOpenDisplay(NULL);
+ if (!dpy)
+ return NULL;
+
+ XSetEventQueueOwner(dpy, XCBOwnsEventQueue);
+
+ return XGetXCBConnection(dpy);
+}
+
+void
+ephyr_glamor_set_texture(struct ephyr_glamor *glamor, uint32_t tex)
+{
+ glamor->tex = tex;
+}
+
+void
+ephyr_glamor_damage_redisplay(struct ephyr_glamor *glamor,
+ struct pixman_region16 *damage)
+{
+ /* Redraw the whole screen, since glXSwapBuffers leaves the back
+ * buffer undefined.
+ */
+ static const float position[] = {
+ -1, -1,
+ 1, -1,
+ 1, 1,
+ -1, 1,
+ };
+ static const float texcoords[] = {
+ 0, 1,
+ 1, 1,
+ 1, 0,
+ 0, 0,
+ };
+
+ glXMakeCurrent(dpy, glamor->glx_win, glamor->ctx);
+
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ glUseProgram(glamor->texture_shader);
+
+ glVertexAttribPointer(glamor->texture_shader_position_loc,
+ 2, GL_FLOAT, FALSE, 0, position);
+ glVertexAttribPointer(glamor->texture_shader_texcoord_loc,
+ 2, GL_FLOAT, FALSE, 0, texcoords);
+ glEnableVertexAttribArray(glamor->texture_shader_position_loc);
+ glEnableVertexAttribArray(glamor->texture_shader_texcoord_loc);
+
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, glamor->tex);
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+
+ glDisableVertexAttribArray(glamor->texture_shader_position_loc);
+ glDisableVertexAttribArray(glamor->texture_shader_texcoord_loc);
+
+ glXSwapBuffers(dpy, glamor->glx_win);
+}
+
+/**
+ * Xlib-based handling of xcb events for glamor.
+ *
+ * We need to let the Xlib event filtering run on the event so that
+ * Mesa's dri2_glx.c userspace event mangling gets run, and we
+ * correctly get our invalidate events propagated into the driver.
+ */
+void
+ephyr_glamor_process_event(xcb_generic_event_t *xev)
+{
+
+ uint32_t response_type = xev->response_type & 0x7f;
+ /* Note the types on wire_to_event: there's an Xlib XEvent (with
+ * the broken types) that it returns, and a protocol xEvent that
+ * it inspects.
+ */
+ Bool (*wire_to_event)(Display *dpy, XEvent *ret, xEvent *event);
+
+ XLockDisplay(dpy);
+ /* Set the event handler to NULL to get access to the current one. */
+ wire_to_event = XESetWireToEvent(dpy, response_type, NULL);
+ if (wire_to_event) {
+ XEvent processed_event;
+
+ /* OK they had an event handler. Plug it back in, and call
+ * through to it.
+ */
+ XESetWireToEvent(dpy, response_type, wire_to_event);
+ xev->sequence = LastKnownRequestProcessed(dpy);
+ wire_to_event(dpy, &processed_event, (xEvent *)xev);
+ }
+ XUnlockDisplay(dpy);
+}
+
+struct ephyr_glamor *
+ephyr_glamor_glx_screen_init(xcb_window_t win)
+{
+ GLXContext ctx;
+ struct ephyr_glamor *glamor;
+ GLXWindow glx_win;
+
+ glamor = calloc(1, sizeof(struct ephyr_glamor));
+ if (!glamor) {
+ FatalError("malloc");
+ return NULL;
+ }
+
+ glx_win = glXCreateWindow(dpy, fb_config, win, NULL);
+
+ ctx = glXCreateContext(dpy, visual_info, NULL, True);
+ if (ctx == NULL)
+ FatalError("glXCreateContext failed\n");
+
+ if (!glXMakeCurrent(dpy, glx_win, ctx))
+ FatalError("glXMakeCurrent failed\n");
+
+ glamor->ctx = ctx;
+ glamor->win = win;
+ glamor->glx_win = glx_win;
+ ephyr_glamor_setup_texturing_shader(glamor);
+
+ return glamor;
+}
+
+void
+ephyr_glamor_glx_screen_fini(struct ephyr_glamor *glamor)
+{
+ glXMakeCurrent(dpy, None, NULL);
+ glXDestroyContext(dpy, glamor->ctx);
+ glXDestroyWindow(dpy, glamor->glx_win);
+
+ free(glamor);
+}
+
+xcb_visualtype_t *
+ephyr_glamor_get_visual(void)
+{
+ xcb_screen_t *xscreen =
+ xcb_aux_get_screen(XGetXCBConnection(dpy), DefaultScreen(dpy));
+ int attribs[] = {
+ GLX_RENDER_TYPE, GLX_RGBA_BIT,
+ GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
+ GLX_RED_SIZE, 1,
+ GLX_GREEN_SIZE, 1,
+ GLX_BLUE_SIZE, 1,
+ GLX_DOUBLEBUFFER, 1,
+ None
+ };
+ int event_base = 0, error_base = 0, nelements;
+ GLXFBConfig *fbconfigs;
+
+ if (!glXQueryExtension (dpy, &error_base, &event_base))
+ FatalError("Couldn't find GLX extension\n");
+
+ fbconfigs = glXChooseFBConfig(dpy, DefaultScreen(dpy), attribs, &nelements);
+ if (!nelements)
+ FatalError("Couldn't choose an FBConfig\n");
+ fb_config = fbconfigs[0];
+ free(fbconfigs);
+
+ visual_info = glXGetVisualFromFBConfig(dpy, fb_config);
+ if (visual_info == NULL)
+ FatalError("Couldn't get RGB visual\n");
+
+ return xcb_aux_find_visual_by_id(xscreen, visual_info->visualid);
+}
diff --git a/xorg-server/hw/kdrive/ephyr/ephyr_glamor_glx.h b/xorg-server/hw/kdrive/ephyr/ephyr_glamor_glx.h
new file mode 100644
index 000000000..8995e1eca
--- /dev/null
+++ b/xorg-server/hw/kdrive/ephyr/ephyr_glamor_glx.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright © 2013 Intel Corporation
+ *
+ * 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.
+ */
+
+/**
+ * ephyr_glamor_glx.h
+ *
+ * Prototypes exposed by ephyr_glamor_glx.c, without including any
+ * server headers.
+ */
+
+#include <xcb/xcb.h>
+#include "dix-config.h"
+
+struct ephyr_glamor;
+struct pixman_region16;
+
+xcb_connection_t *
+ephyr_glamor_connect(void);
+
+void
+ephyr_glamor_set_texture(struct ephyr_glamor *ephyr_glamor, uint32_t tex);
+
+xcb_visualtype_t *
+ephyr_glamor_get_visual(void);
+
+struct ephyr_glamor *
+ephyr_glamor_glx_screen_init(xcb_window_t win);
+
+void
+ephyr_glamor_glx_screen_fini(struct ephyr_glamor *glamor);
+
+#ifdef GLAMOR
+void
+ephyr_glamor_damage_redisplay(struct ephyr_glamor *glamor,
+ struct pixman_region16 *damage);
+
+void
+ephyr_glamor_process_event(xcb_generic_event_t *xev);
+
+#else /* !GLAMOR */
+
+static inline void
+ephyr_glamor_damage_redisplay(struct ephyr_glamor *glamor,
+ struct pixman_region16 *damage)
+{
+}
+
+static inline void
+ephyr_glamor_process_event(xcb_generic_event_t *xev)
+{
+}
+
+#endif /* !GLAMOR */
diff --git a/xorg-server/hw/kdrive/ephyr/ephyrinit.c b/xorg-server/hw/kdrive/ephyr/ephyrinit.c
index 3230e707e..807e717b1 100644
--- a/xorg-server/hw/kdrive/ephyr/ephyrinit.c
+++ b/xorg-server/hw/kdrive/ephyr/ephyrinit.c
@@ -35,6 +35,7 @@ extern Bool EphyrWantGrayScale;
extern Bool EphyrWantResize;
extern Bool kdHasPointer;
extern Bool kdHasKbd;
+extern Bool ephyr_glamor;
#ifdef GLXEXT
extern Bool ephyrNoDRI;
@@ -138,6 +139,9 @@ ddxUseMsg(void)
ErrorF("-fullscreen Attempt to run Xephyr fullscreen\n");
ErrorF("-grayscale Simulate 8bit grayscale\n");
ErrorF("-resizeable Make Xephyr windows resizeable\n");
+#ifdef GLAMOR
+ ErrorF("-glamor Enable 2D acceleration using glamor\n");
+#endif
ErrorF
("-fakexa Simulate acceleration using software rendering\n");
ErrorF("-verbosity <level> Set log verbosity level\n");
@@ -241,6 +245,16 @@ ddxProcessArgument(int argc, char **argv, int i)
EphyrWantResize = 1;
return 1;
}
+#ifdef GLAMOR
+ else if (!strcmp (argv[i], "-glamor")) {
+ ephyr_glamor = TRUE;
+ ephyrFuncs.initAccel = ephyr_glamor_init;
+ ephyrFuncs.enableAccel = ephyr_glamor_enable;
+ ephyrFuncs.disableAccel = ephyr_glamor_disable;
+ ephyrFuncs.finiAccel = ephyr_glamor_fini;
+ return 1;
+ }
+#endif
else if (!strcmp(argv[i], "-fakexa")) {
ephyrFuncs.initAccel = ephyrDrawInit;
ephyrFuncs.enableAccel = ephyrDrawEnable;
diff --git a/xorg-server/hw/kdrive/ephyr/hostx.c b/xorg-server/hw/kdrive/ephyr/hostx.c
index 44ad8e28f..859becaa6 100644
--- a/xorg-server/hw/kdrive/ephyr/hostx.c
+++ b/xorg-server/hw/kdrive/ephyr/hostx.c
@@ -36,6 +36,7 @@
#include <string.h> /* for memset */
#include <errno.h>
#include <time.h>
+#include <err.h>
#include <sys/ipc.h>
#include <sys/shm.h>
@@ -54,6 +55,11 @@
#include <xcb/xf86dri.h>
#include <xcb/glx.h>
#endif /* XF86DRI */
+#ifdef GLAMOR
+#include <epoxy/gl.h>
+#include "glamor.h"
+#include "ephyr_glamor_glx.h"
+#endif
#include "ephyrlog.h"
#include "ephyr.h"
@@ -90,6 +96,7 @@ extern Bool EphyrWantResize;
char *ephyrResName = NULL;
int ephyrResNameFromCmd = 0;
char *ephyrTitle = NULL;
+Bool ephyr_glamor = FALSE;
static void
hostx_set_fullscreen_hint(void);
@@ -302,7 +309,12 @@ hostx_init(void)
| XCB_EVENT_MASK_STRUCTURE_NOTIFY;
EPHYR_DBG("mark");
- HostX.conn = xcb_connect(NULL, &HostX.screen);
+#ifdef GLAMOR
+ if (ephyr_glamor)
+ HostX.conn = ephyr_glamor_connect();
+ else
+#endif
+ HostX.conn = xcb_connect(NULL, &HostX.screen);
if (xcb_connection_has_error(HostX.conn)) {
fprintf(stderr, "\nXephyr cannot open host display. Is DISPLAY set?\n");
exit(1);
@@ -312,7 +324,12 @@ hostx_init(void)
HostX.winroot = xscreen->root;
HostX.gc = xcb_generate_id(HostX.conn);
HostX.depth = xscreen->root_depth;
- HostX.visual = xcb_aux_find_visual_by_id(xscreen, xscreen->root_visual);
+#ifdef GLAMOR
+ if (ephyr_glamor)
+ HostX.visual = ephyr_glamor_get_visual();
+ else
+#endif
+ HostX.visual = xcb_aux_find_visual_by_id(xscreen,xscreen->root_visual);
xcb_create_gc(HostX.conn, HostX.gc, HostX.winroot, 0, NULL);
cookie_WINDOW_STATE = xcb_intern_atom(HostX.conn, FALSE,
@@ -642,7 +659,7 @@ hostx_screen_init(KdScreenInfo *screen,
}
}
- if (HostX.have_shm) {
+ if (!ephyr_glamor && HostX.have_shm) {
scrpriv->ximg = xcb_image_create_native(HostX.conn,
width,
buffer_height,
@@ -677,7 +694,7 @@ hostx_screen_init(KdScreenInfo *screen,
}
}
- if (!shm_success) {
+ if (!ephyr_glamor && !shm_success) {
EPHYR_DBG("Creating image %dx%d for screen scrpriv=%p\n",
width, buffer_height, scrpriv);
scrpriv->ximg = xcb_image_create_native(HostX.conn,
@@ -711,7 +728,11 @@ hostx_screen_init(KdScreenInfo *screen,
scrpriv->win_width = width;
scrpriv->win_height = height;
- if (host_depth_matches_server(scrpriv)) {
+ if (ephyr_glamor) {
+ *bytes_per_line = 0;
+ *bits_per_pixel = 0;
+ return NULL;
+ } else if (host_depth_matches_server(scrpriv)) {
*bytes_per_line = scrpriv->ximg->stride;
*bits_per_pixel = scrpriv->ximg->bpp;
@@ -742,6 +763,23 @@ hostx_paint_rect(KdScreenInfo *screen,
EPHYR_DBG("painting in screen %d\n", scrpriv->mynum);
+#ifdef GLAMOR
+ if (ephyr_glamor) {
+ BoxRec box;
+ RegionRec region;
+
+ box.x1 = dx;
+ box.y1 = dy;
+ box.x2 = dx + width;
+ box.y2 = dy + height;
+
+ RegionInit(&region, &box, 1);
+ ephyr_glamor_damage_redisplay(scrpriv->glamor, &region);
+ RegionUninit(&region);
+ return;
+ }
+#endif
+
/*
* Copy the image data updated by the shadow layer
* on to the window
@@ -1170,3 +1208,86 @@ hostx_get_resource_id_peer(int a_local_resource_id, int *a_remote_resource_id)
}
#endif /* XF86DRI */
+
+#ifdef GLAMOR
+Bool
+ephyr_glamor_init(ScreenPtr screen)
+{
+ KdScreenPriv(screen);
+ KdScreenInfo *kd_screen = pScreenPriv->screen;
+ EphyrScrPriv *scrpriv = kd_screen->driver;
+
+ scrpriv->glamor = ephyr_glamor_glx_screen_init(scrpriv->win);
+
+ glamor_init(screen,
+ GLAMOR_USE_SCREEN |
+ GLAMOR_USE_PICTURE_SCREEN |
+ GLAMOR_INVERTED_Y_AXIS);
+
+ return TRUE;
+}
+
+Bool
+ephyr_glamor_create_screen_resources(ScreenPtr pScreen)
+{
+ KdScreenPriv(pScreen);
+ KdScreenInfo *kd_screen = pScreenPriv->screen;
+ EphyrScrPriv *scrpriv = kd_screen->driver;
+ PixmapPtr screen_pixmap;
+ uint32_t tex;
+
+ if (!ephyr_glamor)
+ return TRUE;
+
+ if (!glamor_glyphs_init(pScreen))
+ return FALSE;
+
+ /* kdrive's fbSetupScreen() told mi to have
+ * miCreateScreenResources() (which is called before this) make a
+ * scratch pixmap wrapping ephyr-glamor's NULL
+ * KdScreenInfo->fb.framebuffer.
+ *
+ * We want a real (texture-based) screen pixmap at this point.
+ * This is what glamor will render into, and we'll then texture
+ * out of that into the host's window to present the results.
+ *
+ * Thus, delete the current screen pixmap, and put a fresh one in.
+ */
+ screen_pixmap = pScreen->GetScreenPixmap(pScreen);
+ pScreen->DestroyPixmap(screen_pixmap);
+
+ screen_pixmap = pScreen->CreatePixmap(pScreen,
+ pScreen->width,
+ pScreen->height,
+ pScreen->rootDepth, 0);
+ pScreen->SetScreenPixmap(screen_pixmap);
+
+ /* Tell the GLX code what to GL texture to read from. */
+ tex = glamor_get_pixmap_texture(screen_pixmap);
+ ephyr_glamor_set_texture(scrpriv->glamor, tex);
+
+ return TRUE;
+}
+
+void
+ephyr_glamor_enable(ScreenPtr screen)
+{
+}
+
+void
+ephyr_glamor_disable(ScreenPtr screen)
+{
+}
+
+void
+ephyr_glamor_fini(ScreenPtr screen)
+{
+ KdScreenPriv(screen);
+ KdScreenInfo *kd_screen = pScreenPriv->screen;
+ EphyrScrPriv *scrpriv = kd_screen->driver;
+
+ glamor_fini(screen);
+ ephyr_glamor_glx_screen_fini(scrpriv->glamor);
+ scrpriv->glamor = NULL;
+}
+#endif
diff --git a/xorg-server/hw/xfree86/Makefile.am b/xorg-server/hw/xfree86/Makefile.am
index 96729043d..73e1b4c1f 100644
--- a/xorg-server/hw/xfree86/Makefile.am
+++ b/xorg-server/hw/xfree86/Makefile.am
@@ -14,6 +14,10 @@ DRI3_BUILDDIR = $(top_builddir)/dri3
DRI3_LIB = $(DRI3_BUILDDIR)/libdri3.la
endif
+if GLAMOR_EGL
+GLAMOR_EGL_SUBDIR = glamor_egl
+endif
+
if XF86UTILS
XF86UTILS_SUBDIR = utils
endif
@@ -33,7 +37,8 @@ endif
SUBDIRS = common ddc x86emu $(INT10_SUBDIR) os-support parser \
ramdac $(VGAHW_SUBDIR) loader modes $(DRI_SUBDIR) \
$(DRI2_SUBDIR) . $(VBE_SUBDIR) i2c dixmods \
- fbdevhw shadowfb exa $(XF86UTILS_SUBDIR) doc man
+ fbdevhw shadowfb exa $(XF86UTILS_SUBDIR) doc man \
+ $(GLAMOR_EGL_SUBDIR)
DIST_SUBDIRS = common ddc i2c x86emu int10 fbdevhw os-support \
parser ramdac shadowfb vbe vgahw \
diff --git a/xorg-server/hw/xfree86/common/xf86Events.c b/xorg-server/hw/xfree86/common/xf86Events.c
index 7b53949fa..06af73903 100644
--- a/xorg-server/hw/xfree86/common/xf86Events.c
+++ b/xorg-server/hw/xfree86/common/xf86Events.c
@@ -85,6 +85,8 @@
#endif
#include "xf86platformBus.h"
+#include "systemd-logind.h"
+
/*
* This is a toggling variable:
* FALSE = No VT switching keys have been pressed last time around
@@ -556,8 +558,11 @@ xf86VTEnter(void)
/* Turn screen saver off when switching back */
dixSaveScreens(serverClient, SCREEN_SAVER_FORCER, ScreenSaverReset);
- for (pInfo = xf86InputDevs; pInfo; pInfo = pInfo->next)
- xf86EnableInputDeviceForVTSwitch(pInfo);
+ /* If we use systemd-logind it will enable input devices for us */
+ if (!systemd_logind_controls_session())
+ for (pInfo = xf86InputDevs; pInfo; pInfo = pInfo->next)
+ xf86EnableInputDeviceForVTSwitch(pInfo);
+
for (ih = InputHandlers; ih; ih = ih->next) {
if (ih->is_input)
xf86EnableInputHandler(ih);
@@ -589,10 +594,14 @@ xf86VTSwitch(void)
/*
* Since all screens are currently all in the same state it is sufficient
* check the first. This might change in future.
+ *
+ * VTLeave is always handled here (VT_PROCESS guarantees this is safe),
+ * if we use systemd_logind xf86VTEnter() gets called by systemd-logind.c
+ * once it has resumed all drm nodes.
*/
if (xf86VTOwner())
xf86VTLeave();
- else
+ else if (!systemd_logind_controls_session())
xf86VTEnter();
}
diff --git a/xorg-server/hw/xfree86/common/xf86Init.c b/xorg-server/hw/xfree86/common/xf86Init.c
index ff4d38f28..4579ff591 100644
--- a/xorg-server/hw/xfree86/common/xf86Init.c
+++ b/xorg-server/hw/xfree86/common/xf86Init.c
@@ -54,6 +54,7 @@
#include "site.h"
#include "mi.h"
#include "dbus-core.h"
+#include "systemd-logind.h"
#include "compiler.h"
@@ -458,6 +459,7 @@ InitOutput(ScreenInfo * pScreenInfo, int argc, char **argv)
DoShowOptions();
dbus_core_init();
+ systemd_logind_init();
/* Do a general bus probe. This will be a PCI probe for x86 platforms */
xf86BusProbe();
@@ -1062,6 +1064,7 @@ ddxGiveUp(enum ExitCode error)
if (xorgHWOpenConsole)
xf86CloseConsole();
+ systemd_logind_fini();
dbus_core_fini();
xf86CloseLog(error);
diff --git a/xorg-server/hw/xfree86/common/xf86Module.h b/xorg-server/hw/xfree86/common/xf86Module.h
index b6ec19d13..e8c24f26c 100644
--- a/xorg-server/hw/xfree86/common/xf86Module.h
+++ b/xorg-server/hw/xfree86/common/xf86Module.h
@@ -80,8 +80,8 @@ typedef enum {
* mask is 0xFFFF0000.
*/
#define ABI_ANSIC_VERSION SET_ABI_VERSION(0, 4)
-#define ABI_VIDEODRV_VERSION SET_ABI_VERSION(15, 0)
-#define ABI_XINPUT_VERSION SET_ABI_VERSION(20, 0)
+#define ABI_VIDEODRV_VERSION SET_ABI_VERSION(16, 0)
+#define ABI_XINPUT_VERSION SET_ABI_VERSION(21, 0)
#define ABI_EXTENSION_VERSION SET_ABI_VERSION(8, 0)
#define ABI_FONT_VERSION SET_ABI_VERSION(0, 6)
diff --git a/xorg-server/hw/xfree86/common/xf86Xinput.c b/xorg-server/hw/xfree86/common/xf86Xinput.c
index f6f2b90dd..7c3e479e5 100644
--- a/xorg-server/hw/xfree86/common/xf86Xinput.c
+++ b/xorg-server/hw/xfree86/common/xf86Xinput.c
@@ -63,6 +63,7 @@
#include "mipointer.h"
#include "extinit.h"
#include "loaderProcs.h"
+#include "systemd-logind.h"
#include "exevents.h" /* AddInputDevice */
#include "exglobals.h"
@@ -80,6 +81,7 @@
#include <stdarg.h>
#include <stdint.h> /* for int64_t */
+#include <unistd.h>
#include "mi.h"
@@ -103,6 +105,9 @@
static int
xf86InputDevicePostInit(DeviceIntPtr dev);
+static InputInfoPtr *new_input_devices;
+static int new_input_devices_count;
+
/**
* Eval config and modify DeviceVelocityRec accordingly
*/
@@ -773,6 +778,11 @@ xf86DeleteInput(InputInfoPtr pInp, int flags)
/* Else the entry wasn't in the xf86InputDevs list (ignore this). */
}
+ if (pInp->flags & XI86_SERVER_FD) {
+ systemd_logind_release_fd(pInp->major, pInp->minor);
+ close(pInp->fd);
+ }
+
free((void *) pInp->driver);
free((void *) pInp->name);
xf86optionListFree(pInp->options);
@@ -816,6 +826,7 @@ xf86NewInputDevice(InputInfoPtr pInfo, DeviceIntPtr *pdev, BOOL enable)
{
InputDriverPtr drv = NULL;
DeviceIntPtr dev = NULL;
+ Bool paused;
int rval;
/* Memory leak for every attached device if we don't
@@ -830,6 +841,26 @@ xf86NewInputDevice(InputInfoPtr pInfo, DeviceIntPtr *pdev, BOOL enable)
goto unwind;
}
+ if (drv->capabilities & XI86_DRV_CAP_SERVER_FD) {
+ int fd = systemd_logind_take_fd(pInfo->major, pInfo->minor,
+ pInfo->attrs->device, &paused);
+ if (fd != -1) {
+ if (paused) {
+ /* Put on new_input_devices list for delayed probe */
+ new_input_devices = xnfrealloc(new_input_devices,
+ sizeof(pInfo) * (new_input_devices_count + 1));
+ new_input_devices[new_input_devices_count] = pInfo;
+ new_input_devices_count++;
+ systemd_logind_release_fd(pInfo->major, pInfo->minor);
+ close(fd);
+ return BadMatch;
+ }
+ pInfo->fd = fd;
+ pInfo->flags |= XI86_SERVER_FD;
+ pInfo->options = xf86ReplaceIntOption(pInfo->options, "fd", fd);
+ }
+ }
+
xf86Msg(X_INFO, "Using input driver '%s' for '%s'\n", drv->driverName,
pInfo->name);
@@ -949,6 +980,12 @@ NewInputDeviceRequest(InputOption *options, InputAttributes * attrs,
goto unwind;
}
}
+
+ if (strcmp(key, "major") == 0)
+ pInfo->major = atoi(value);
+
+ if (strcmp(key, "minor") == 0)
+ pInfo->minor = atoi(value);
}
nt_list_for_each_entry(option, options, list.next) {
@@ -1469,4 +1506,32 @@ xf86PostTouchEvent(DeviceIntPtr dev, uint32_t touchid, uint16_t type,
QueueTouchEvents(dev, type, touchid, flags, mask);
}
+void
+xf86InputEnableVTProbe(void)
+{
+ int i, is_auto = 0;
+ InputOption *option = NULL;
+ DeviceIntPtr pdev;
+
+ for (i = 0; i < new_input_devices_count; i++) {
+ InputInfoPtr pInfo = new_input_devices[i];
+
+ is_auto = 0;
+ nt_list_for_each_entry(option, pInfo->options, list.next) {
+ const char *key = input_option_get_key(option);
+ const char *value = input_option_get_value(option);
+
+ if (strcmp(key, "_source") == 0 &&
+ (strcmp(value, "server/hal") == 0 ||
+ strcmp(value, "server/udev") == 0 ||
+ strcmp(value, "server/wscons") == 0))
+ is_auto = 1;
+ }
+ xf86NewInputDevice(pInfo, &pdev,
+ (!is_auto ||
+ (is_auto && xf86Info.autoEnableDevices)));
+ }
+ new_input_devices_count = 0;
+}
+
/* end of xf86Xinput.c */
diff --git a/xorg-server/hw/xfree86/common/xf86Xinput.h b/xorg-server/hw/xfree86/common/xf86Xinput.h
index b6d125128..9fe8c87b6 100644
--- a/xorg-server/hw/xfree86/common/xf86Xinput.h
+++ b/xorg-server/hw/xfree86/common/xf86Xinput.h
@@ -64,6 +64,10 @@
/* 0x08 is reserved for legacy XI86_SEND_DRAG_EVENTS, do not use for now */
/* server-internal only */
#define XI86_DEVICE_DISABLED 0x10 /* device was disabled before vt switch */
+#define XI86_SERVER_FD 0x20 /* fd is managed by xserver */
+
+/* Input device driver capabilities */
+#define XI86_DRV_CAP_SERVER_FD 0x01
/* This holds the input driver entry and module information. */
typedef struct _InputDriverRec {
@@ -76,6 +80,7 @@ typedef struct _InputDriverRec {
struct _InputInfoRec * pInfo, int flags);
void *module;
const char **default_options;
+ int capabilities;
} InputDriverRec, *InputDriverPtr;
/* This is to input devices what the ScrnInfoRec is to screens. */
@@ -96,6 +101,8 @@ typedef struct _InputInfoRec {
int *valuators, int first_valuator, int num_valuators);
int fd;
+ int major;
+ int minor;
DeviceIntPtr dev;
void *private;
const char *type_name;
@@ -172,6 +179,7 @@ extern _X_EXPORT void xf86AddEnabledDevice(InputInfoPtr pInfo);
extern _X_EXPORT void xf86RemoveEnabledDevice(InputInfoPtr pInfo);
extern _X_EXPORT void xf86DisableDevice(DeviceIntPtr dev, Bool panic);
extern _X_EXPORT void xf86EnableDevice(DeviceIntPtr dev);
+extern _X_EXPORT void xf86InputEnableVTProbe(void);
/* not exported */
int xf86NewInputDevice(InputInfoPtr pInfo, DeviceIntPtr *pdev, BOOL is_auto);
diff --git a/xorg-server/hw/xfree86/common/xf86platformBus.c b/xorg-server/hw/xfree86/common/xf86platformBus.c
index 5875a9136..4447e19df 100644
--- a/xorg-server/hw/xfree86/common/xf86platformBus.c
+++ b/xorg-server/hw/xfree86/common/xf86platformBus.c
@@ -52,10 +52,10 @@ int platformSlotClaimed;
int xf86_num_platform_devices;
-static struct xf86_platform_device *xf86_platform_devices;
+struct xf86_platform_device *xf86_platform_devices;
int
-xf86_add_platform_device(struct OdevAttributes *attribs)
+xf86_add_platform_device(struct OdevAttributes *attribs, Bool unowned)
{
xf86_platform_devices = xnfrealloc(xf86_platform_devices,
(sizeof(struct xf86_platform_device)
@@ -63,6 +63,8 @@ xf86_add_platform_device(struct OdevAttributes *attribs)
xf86_platform_devices[xf86_num_platform_devices].attribs = attribs;
xf86_platform_devices[xf86_num_platform_devices].pdev = NULL;
+ xf86_platform_devices[xf86_num_platform_devices].flags =
+ unowned ? XF86_PDEV_UNOWNED : 0;
xf86_num_platform_devices++;
return 0;
@@ -89,35 +91,55 @@ xf86_add_platform_device_attrib(int index, int attrib_id, char *attrib_name)
return config_odev_add_attribute(device->attribs, attrib_id, attrib_name);
}
+Bool
+xf86_add_platform_device_int_attrib(int index, int attrib_id, int attrib_value)
+{
+ return config_odev_add_int_attribute(xf86_platform_devices[index].attribs, attrib_id, attrib_value);
+}
+
char *
xf86_get_platform_attrib(int index, int attrib_id)
{
- struct xf86_platform_device *device = &xf86_platform_devices[index];
- struct OdevAttribute *oa;
-
- xorg_list_for_each_entry(oa, &device->attribs->list, member) {
- if (oa->attrib_id == attrib_id)
- return oa->attrib_name;
- }
- return NULL;
+ return config_odev_get_attribute(xf86_platform_devices[index].attribs, attrib_id);
}
char *
xf86_get_platform_device_attrib(struct xf86_platform_device *device, int attrib_id)
{
- struct OdevAttribute *oa;
+ return config_odev_get_attribute(device->attribs, attrib_id);
+}
- xorg_list_for_each_entry(oa, &device->attribs->list, member) {
- if (oa->attrib_id == attrib_id)
- return oa->attrib_name;
- }
- return NULL;
+int
+xf86_get_platform_int_attrib(int index, int attrib_id, int def)
+{
+ return config_odev_get_int_attribute(xf86_platform_devices[index].attribs, attrib_id, def);
+}
+
+int
+xf86_get_platform_device_int_attrib(struct xf86_platform_device *device, int attrib_id, int def)
+{
+ return config_odev_get_int_attribute(device->attribs, attrib_id, def);
}
Bool
xf86_get_platform_device_unowned(int index)
{
- return xf86_platform_devices[index].attribs->unowned;
+ return (xf86_platform_devices[index].flags & XF86_PDEV_UNOWNED) ?
+ TRUE : FALSE;
+}
+
+struct xf86_platform_device *
+xf86_find_platform_device_by_devnum(int major, int minor)
+{
+ int i, attr_major, attr_minor;
+
+ for (i = 0; i < xf86_num_platform_devices; i++) {
+ attr_major = xf86_get_platform_int_attrib(i, ODEV_ATTRIB_MAJOR, 0);
+ attr_minor = xf86_get_platform_int_attrib(i, ODEV_ATTRIB_MINOR, 0);
+ if (attr_major == major && attr_minor == minor)
+ return &xf86_platform_devices[i];
+ }
+ return NULL;
}
/*
@@ -524,10 +546,10 @@ void xf86platformVTProbe(void)
int i;
for (i = 0; i < xf86_num_platform_devices; i++) {
- if (xf86_platform_devices[i].attribs->unowned == FALSE)
+ if (!(xf86_platform_devices[i].flags & XF86_PDEV_UNOWNED))
continue;
- xf86_platform_devices[i].attribs->unowned = FALSE;
+ xf86_platform_devices[i].flags &= ~XF86_PDEV_UNOWNED;
xf86PlatformReprobeDevice(i, xf86_platform_devices[i].attribs);
}
}
diff --git a/xorg-server/hw/xfree86/common/xf86platformBus.h b/xorg-server/hw/xfree86/common/xf86platformBus.h
index 4e1757854..78b5a5bea 100644
--- a/xorg-server/hw/xfree86/common/xf86platformBus.h
+++ b/xorg-server/hw/xfree86/common/xf86platformBus.h
@@ -30,23 +30,34 @@ struct xf86_platform_device {
struct OdevAttributes *attribs;
/* for PCI devices */
struct pci_device *pdev;
+ int flags;
};
+/* xf86_platform_device flags */
+#define XF86_PDEV_UNOWNED 0x01
+#define XF86_PDEV_SERVER_FD 0x02
+#define XF86_PDEV_PAUSED 0x04
+
#ifdef XSERVER_PLATFORM_BUS
int xf86platformProbe(void);
int xf86platformProbeDev(DriverPtr drvp);
extern int xf86_num_platform_devices;
+extern struct xf86_platform_device *xf86_platform_devices;
extern char *
xf86_get_platform_attrib(int index, int attrib_id);
extern int
-xf86_add_platform_device(struct OdevAttributes *attribs);
+xf86_get_platform_int_attrib(int index, int attrib_id, int def);
+extern int
+xf86_add_platform_device(struct OdevAttributes *attribs, Bool unowned);
extern int
xf86_remove_platform_device(int dev_index);
extern Bool
xf86_add_platform_device_attrib(int index, int attrib_id, char *attrib_str);
extern Bool
+xf86_add_platform_device_int_attrib(int index, int attrib_id, int attrib_value);
+extern Bool
xf86_get_platform_device_unowned(int index);
extern int
@@ -56,6 +67,8 @@ xf86platformRemoveDevice(int index);
extern _X_EXPORT char *
xf86_get_platform_device_attrib(struct xf86_platform_device *device, int attrib_id);
+extern _X_EXPORT int
+xf86_get_platform_device_int_attrib(struct xf86_platform_device *device, int attrib_id, int def);
extern _X_EXPORT Bool
xf86PlatformDeviceCheckBusID(struct xf86_platform_device *device, const char *busid);
diff --git a/xorg-server/hw/xfree86/glamor_egl/Makefile.am b/xorg-server/hw/xfree86/glamor_egl/Makefile.am
new file mode 100644
index 000000000..85e1c0c06
--- /dev/null
+++ b/xorg-server/hw/xfree86/glamor_egl/Makefile.am
@@ -0,0 +1,43 @@
+# Copyright © 2013 Intel Corporation
+#
+# 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.
+
+module_LTLIBRARIES = libglamoregl.la
+
+libglamoregl_la_SOURCES = \
+ $(top_srcdir)/glamor/glamor_egl.c \
+ $(top_srcdir)/glamor/glamor_eglmodule.c \
+ $(top_srcdir)/glamor/glamor_xv.c \
+ $()
+
+libglamoregl_la_LDFLAGS = \
+ -avoid-version \
+ $(GBM_LIBS) \
+ $()
+
+libglamoregl_la_LIBADD = \
+ $(top_builddir)/glamor/libglamor.la \
+ $()
+
+AM_CPPFLAGS = $(XORG_INCS) \
+ -I$(top_srcdir)/dri3 \
+ $()
+
+AM_CFLAGS = $(DIX_CFLAGS) $(XORG_CFLAGS) $(GLAMOR_CFLAGS) $(GBM_CFLAGS)
diff --git a/xorg-server/hw/xfree86/os-support/linux/Makefile.am b/xorg-server/hw/xfree86/os-support/linux/Makefile.am
index 83e7e0027..1686dc2c1 100644
--- a/xorg-server/hw/xfree86/os-support/linux/Makefile.am
+++ b/xorg-server/hw/xfree86/os-support/linux/Makefile.am
@@ -21,6 +21,11 @@ APM_SRCS = lnx_apm.c
XORG_CFLAGS += -DHAVE_APM
endif
+if SYSTEMD_LOGIND
+LOGIND_SRCS = systemd-logind.c
+XORG_CFLAGS += $(DBUS_CFLAGS)
+endif
+
liblinux_la_SOURCES = lnx_init.c lnx_video.c \
lnx_agp.c lnx_kmod.c lnx_bell.c lnx_platform.c \
$(srcdir)/../shared/bios_mmap.c \
@@ -30,6 +35,7 @@ liblinux_la_SOURCES = lnx_init.c lnx_video.c \
$(srcdir)/../shared/sigio.c \
$(ACPI_SRCS) \
$(APM_SRCS) \
+ $(LOGIND_SRCS) \
$(PLATFORM_PCI_SUPPORT)
AM_CFLAGS = -DUSESTDRES -DHAVE_SYSV_IPC $(DIX_CFLAGS) $(XORG_CFLAGS) $(PLATFORM_DEFINES)
diff --git a/xorg-server/hw/xfree86/os-support/linux/lnx_init.c b/xorg-server/hw/xfree86/os-support/linux/lnx_init.c
index 46438e655..85709c629 100644
--- a/xorg-server/hw/xfree86/os-support/linux/lnx_init.c
+++ b/xorg-server/hw/xfree86/os-support/linux/lnx_init.c
@@ -79,20 +79,15 @@ switch_to(int vt, const char *from)
void
xf86OpenConsole(void)
{
- int i, fd = -1, ret;
+ int i, fd = -1, ret, current_vt = -1;
struct vt_mode VT;
struct vt_stat vts;
+ struct stat st;
MessageType from = X_PROBED;
const char *tty0[] = { "/dev/tty0", "/dev/vc/0", NULL };
const char *vcs[] = { "/dev/vc/%d", "/dev/tty%d", NULL };
if (serverGeneration == 1) {
-
- /* when KeepTty check if we're run with euid==0 */
- if (KeepTty && geteuid() != 0)
- FatalError("xf86OpenConsole:"
- " Server must be suid root for option \"KeepTTY\"\n");
-
/*
* setup the virtual terminal manager
*/
@@ -132,6 +127,22 @@ xf86OpenConsole(void)
xf86Msg(from, "using VT number %d\n\n", xf86Info.vtno);
+ /* Some of stdin / stdout / stderr maybe redirected to a file */
+ for (i = STDIN_FILENO; i <= STDERR_FILENO; i++) {
+ ret = fstat(i, &st);
+ if (ret == 0 && S_ISCHR(st.st_mode) && major(st.st_rdev) == 4) {
+ current_vt = minor(st.st_rdev);
+ break;
+ }
+ }
+
+ if (!KeepTty && current_vt == xf86Info.vtno) {
+ xf86Msg(X_PROBED,
+ "controlling tty is VT number %d, auto-enabling KeepTty\n",
+ current_vt);
+ KeepTty = TRUE;
+ }
+
if (!KeepTty) {
pid_t ppid = getppid();
pid_t ppgid;
diff --git a/xorg-server/hw/xfree86/os-support/linux/lnx_platform.c b/xorg-server/hw/xfree86/os-support/linux/lnx_platform.c
index 1865b31b9..109a9a774 100644
--- a/xorg-server/hw/xfree86/os-support/linux/lnx_platform.c
+++ b/xorg-server/hw/xfree86/os-support/linux/lnx_platform.c
@@ -18,16 +18,38 @@
#include "xf86Bus.h"
#include "hotplug.h"
+#include "systemd-logind.h"
static Bool
get_drm_info(struct OdevAttributes *attribs, char *path, int delayed_index)
{
drmSetVersion sv;
char *buf;
- int fd;
+ int major, minor, fd;
int err = 0;
+ Bool paused, server_fd = FALSE;
+
+ major = config_odev_get_int_attribute(attribs, ODEV_ATTRIB_MAJOR, 0);
+ minor = config_odev_get_int_attribute(attribs, ODEV_ATTRIB_MINOR, 0);
+
+ fd = systemd_logind_take_fd(major, minor, path, &paused);
+ if (fd != -1) {
+ if (paused) {
+ LogMessage(X_ERROR,
+ "Error systemd-logind returned paused fd for drm node\n");
+ systemd_logind_release_fd(major, minor);
+ return FALSE;
+ }
+ if (!config_odev_add_int_attribute(attribs, ODEV_ATTRIB_FD, fd)) {
+ systemd_logind_release_fd(major, minor);
+ return FALSE;
+ }
+ server_fd = TRUE;
+ }
+
+ if (fd == -1)
+ fd = open(path, O_RDWR, O_CLOEXEC);
- fd = open(path, O_RDWR, O_CLOEXEC);
if (fd == -1)
return FALSE;
@@ -44,16 +66,20 @@ get_drm_info(struct OdevAttributes *attribs, char *path, int delayed_index)
/* for a delayed probe we've already added the device */
if (delayed_index == -1) {
- xf86_add_platform_device(attribs);
+ xf86_add_platform_device(attribs, FALSE);
delayed_index = xf86_num_platform_devices - 1;
}
+ if (server_fd)
+ xf86_platform_devices[delayed_index].flags |= XF86_PDEV_SERVER_FD;
+
buf = drmGetBusid(fd);
xf86_add_platform_device_attrib(delayed_index,
ODEV_ATTRIB_BUSID, buf);
drmFreeBusid(buf);
out:
- close(fd);
+ if (!server_fd)
+ close(fd);
return (err == 0);
}
@@ -118,17 +144,11 @@ xf86PlatformReprobeDevice(int index, struct OdevAttributes *attribs)
void
xf86PlatformDeviceProbe(struct OdevAttributes *attribs)
{
- struct OdevAttribute *attrib;
int i;
char *path = NULL;
Bool ret;
- xorg_list_for_each_entry(attrib, &attribs->list, member) {
- if (attrib->attrib_id == ODEV_ATTRIB_PATH) {
- path = attrib->attrib_name;
- break;
- }
- }
+ path = config_odev_get_attribute(attribs, ODEV_ATTRIB_PATH);
if (!path)
goto out_free;
@@ -148,8 +168,7 @@ xf86PlatformDeviceProbe(struct OdevAttributes *attribs)
if (!xf86VTOwner()) {
/* if we don't currently own the VT then don't probe the device,
just mark it as unowned for later use */
- attribs->unowned = TRUE;
- xf86_add_platform_device(attribs);
+ xf86_add_platform_device(attribs, TRUE);
return;
}
diff --git a/xorg-server/hw/xfree86/os-support/linux/systemd-logind.c b/xorg-server/hw/xfree86/os-support/linux/systemd-logind.c
new file mode 100644
index 000000000..abb8e44d9
--- /dev/null
+++ b/xorg-server/hw/xfree86/os-support/linux/systemd-logind.c
@@ -0,0 +1,532 @@
+/*
+ * Copyright © 2013 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.
+ *
+ * Author: Hans de Goede <hdegoede@redhat.com>
+ */
+
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#endif
+
+#include <dbus/dbus.h>
+#include <string.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "os.h"
+#include "dbus-core.h"
+#include "xf86.h"
+#include "xf86platformBus.h"
+#include "xf86Xinput.h"
+
+#include "systemd-logind.h"
+
+#define DBUS_TIMEOUT 500 /* Wait max 0.5 seconds */
+
+struct systemd_logind_info {
+ DBusConnection *conn;
+ char *session;
+ Bool active;
+ Bool vt_active;
+};
+
+static struct systemd_logind_info logind_info;
+
+int
+systemd_logind_take_fd(int _major, int _minor, const char *path,
+ Bool *paused_ret)
+{
+ struct systemd_logind_info *info = &logind_info;
+ DBusError error;
+ DBusMessage *msg = NULL;
+ DBusMessage *reply = NULL;
+ dbus_int32_t major = _major;
+ dbus_int32_t minor = _minor;
+ dbus_bool_t paused;
+ int fd = -1;
+
+ if (!info->session || major == 0)
+ return -1;
+
+ /* logind does not support mouse devs (with evdev we don't need them) */
+ if (strstr(path, "mouse"))
+ return -1;
+
+ dbus_error_init(&error);
+
+ msg = dbus_message_new_method_call("org.freedesktop.login1", info->session,
+ "org.freedesktop.login1.Session", "TakeDevice");
+ if (!msg) {
+ LogMessage(X_ERROR, "systemd-logind: out of memory\n");
+ goto cleanup;
+ }
+
+ if (!dbus_message_append_args(msg, DBUS_TYPE_UINT32, &major,
+ DBUS_TYPE_UINT32, &minor,
+ DBUS_TYPE_INVALID)) {
+ LogMessage(X_ERROR, "systemd-logind: out of memory\n");
+ goto cleanup;
+ }
+
+ reply = dbus_connection_send_with_reply_and_block(info->conn, msg,
+ DBUS_TIMEOUT, &error);
+ if (!reply) {
+ LogMessage(X_ERROR, "systemd-logind: failed to take device %s: %s\n",
+ path, error.message);
+ goto cleanup;
+ }
+
+ if (!dbus_message_get_args(reply, &error,
+ DBUS_TYPE_UNIX_FD, &fd,
+ DBUS_TYPE_BOOLEAN, &paused,
+ DBUS_TYPE_INVALID)) {
+ LogMessage(X_ERROR, "systemd-logind: TakeDevice %s: %s\n",
+ path, error.message);
+ goto cleanup;
+ }
+
+ *paused_ret = paused;
+
+ LogMessage(X_INFO, "systemd-logind: got fd for %s %u:%u fd %d paused %d\n",
+ path, major, minor, fd, paused);
+
+cleanup:
+ if (msg)
+ dbus_message_unref(msg);
+ if (reply)
+ dbus_message_unref(reply);
+ dbus_error_free(&error);
+
+ return fd;
+}
+
+void
+systemd_logind_release_fd(int _major, int _minor)
+{
+ struct systemd_logind_info *info = &logind_info;
+ DBusError error;
+ DBusMessage *msg = NULL;
+ DBusMessage *reply = NULL;
+ dbus_int32_t major = _major;
+ dbus_int32_t minor = _minor;
+
+ if (!info->session || major == 0)
+ return;
+
+ dbus_error_init(&error);
+
+ msg = dbus_message_new_method_call("org.freedesktop.login1", info->session,
+ "org.freedesktop.login1.Session", "ReleaseDevice");
+ if (!msg) {
+ LogMessage(X_ERROR, "systemd-logind: out of memory\n");
+ goto cleanup;
+ }
+
+ if (!dbus_message_append_args(msg, DBUS_TYPE_UINT32, &major,
+ DBUS_TYPE_UINT32, &minor,
+ DBUS_TYPE_INVALID)) {
+ LogMessage(X_ERROR, "systemd-logind: out of memory\n");
+ goto cleanup;
+ }
+
+ reply = dbus_connection_send_with_reply_and_block(info->conn, msg,
+ DBUS_TIMEOUT, &error);
+ if (!reply)
+ LogMessage(X_ERROR, "systemd-logind: failed to release device: %s\n",
+ error.message);
+
+cleanup:
+ if (msg)
+ dbus_message_unref(msg);
+ if (reply)
+ dbus_message_unref(reply);
+ dbus_error_free(&error);
+}
+
+int
+systemd_logind_controls_session(void)
+{
+ return logind_info.session ? 1 : 0;
+}
+
+void
+systemd_logind_vtenter(void)
+{
+ struct systemd_logind_info *info = &logind_info;
+ InputInfoPtr pInfo;
+ int i;
+
+ if (!info->session)
+ return; /* Not using systemd-logind */
+
+ if (!info->active)
+ return; /* Session not active */
+
+ if (info->vt_active)
+ return; /* Already did vtenter */
+
+ for (i = 0; i < xf86_num_platform_devices; i++) {
+ if (xf86_platform_devices[i].flags & XF86_PDEV_PAUSED)
+ break;
+ }
+ if (i != xf86_num_platform_devices)
+ return; /* Some drm nodes are still paused wait for resume */
+
+ xf86VTEnter();
+ info->vt_active = TRUE;
+
+ /* Activate any input devices which were resumed before the drm nodes */
+ for (pInfo = xf86InputDevs; pInfo; pInfo = pInfo->next)
+ if ((pInfo->flags & XI86_SERVER_FD) && pInfo->fd != -1)
+ xf86EnableInputDeviceForVTSwitch(pInfo);
+
+ /* Do delayed input probing, this must be done after the above enabling */
+ xf86InputEnableVTProbe();
+}
+
+static InputInfoPtr
+systemd_logind_find_info_ptr_by_devnum(int major, int minor)
+{
+ InputInfoPtr pInfo;
+
+ for (pInfo = xf86InputDevs; pInfo; pInfo = pInfo->next)
+ if (pInfo->major == major && pInfo->minor == minor &&
+ (pInfo->flags & XI86_SERVER_FD))
+ return pInfo;
+
+ return NULL;
+}
+
+static void
+systemd_logind_ack_pause(struct systemd_logind_info *info,
+ dbus_int32_t minor, dbus_int32_t major)
+{
+ DBusError error;
+ DBusMessage *msg = NULL;
+ DBusMessage *reply = NULL;
+
+ dbus_error_init(&error);
+
+ msg = dbus_message_new_method_call("org.freedesktop.login1", info->session,
+ "org.freedesktop.login1.Session", "PauseDeviceComplete");
+ if (!msg) {
+ LogMessage(X_ERROR, "systemd-logind: out of memory\n");
+ goto cleanup;
+ }
+
+ if (!dbus_message_append_args(msg, DBUS_TYPE_UINT32, &major,
+ DBUS_TYPE_UINT32, &minor,
+ DBUS_TYPE_INVALID)) {
+ LogMessage(X_ERROR, "systemd-logind: out of memory\n");
+ goto cleanup;
+ }
+
+ reply = dbus_connection_send_with_reply_and_block(info->conn, msg,
+ DBUS_TIMEOUT, &error);
+ if (!reply)
+ LogMessage(X_ERROR, "systemd-logind: failed to ack pause: %s\n",
+ error.message);
+
+cleanup:
+ if (msg)
+ dbus_message_unref(msg);
+ if (reply)
+ dbus_message_unref(reply);
+ dbus_error_free(&error);
+}
+
+static DBusHandlerResult
+message_filter(DBusConnection * connection, DBusMessage * message, void *data)
+{
+ struct systemd_logind_info *info = data;
+ struct xf86_platform_device *pdev = NULL;
+ InputInfoPtr pInfo = NULL;
+ int ack = 0, pause = 0, fd = -1;
+ DBusError error;
+ dbus_int32_t major, minor;
+ char *pause_str;
+
+ if (strcmp(dbus_message_get_path(message), info->session) != 0)
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ dbus_error_init(&error);
+
+ if (dbus_message_is_signal(message, "org.freedesktop.login1.Session",
+ "PauseDevice")) {
+ if (!dbus_message_get_args(message, &error,
+ DBUS_TYPE_UINT32, &major,
+ DBUS_TYPE_UINT32, &minor,
+ DBUS_TYPE_STRING, &pause_str,
+ DBUS_TYPE_INVALID)) {
+ LogMessage(X_ERROR, "systemd-logind: PauseDevice: %s\n",
+ error.message);
+ dbus_error_free(&error);
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ }
+
+ if (strcmp(pause_str, "pause") == 0) {
+ pause = 1;
+ ack = 1;
+ }
+ else if (strcmp(pause_str, "force") == 0) {
+ pause = 1;
+ }
+ else if (strcmp(pause_str, "gone") == 0) {
+ /* Device removal is handled through udev */
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ }
+ else {
+ LogMessage(X_WARNING, "systemd-logind: unknown pause type: %s\n",
+ pause_str);
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ }
+ }
+ else if (dbus_message_is_signal(message, "org.freedesktop.login1.Session",
+ "ResumeDevice")) {
+ if (!dbus_message_get_args(message, &error,
+ DBUS_TYPE_UINT32, &major,
+ DBUS_TYPE_UINT32, &minor,
+ DBUS_TYPE_UNIX_FD, &fd,
+ DBUS_TYPE_INVALID)) {
+ LogMessage(X_ERROR, "systemd-logind: ResumeDevice: %s\n",
+ error.message);
+ dbus_error_free(&error);
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ }
+ } else
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ LogMessage(X_INFO, "systemd-logind: got %s for %u:%u\n",
+ pause ? "pause" : "resume", major, minor);
+
+ pdev = xf86_find_platform_device_by_devnum(major, minor);
+ if (!pdev)
+ pInfo = systemd_logind_find_info_ptr_by_devnum(major, minor);
+ if (!pdev && !pInfo) {
+ LogMessage(X_WARNING, "systemd-logind: could not find dev %u:%u\n",
+ major, minor);
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ }
+
+ if (pause) {
+ /* Our VT_PROCESS usage guarantees we've already given up the vt */
+ info->active = info->vt_active = FALSE;
+ /* Note the actual vtleave has already been handled by xf86Events.c */
+ if (pdev)
+ pdev->flags |= XF86_PDEV_PAUSED;
+ else {
+ close(pInfo->fd);
+ pInfo->fd = -1;
+ pInfo->options = xf86ReplaceIntOption(pInfo->options, "fd", -1);
+ }
+ if (ack)
+ systemd_logind_ack_pause(info, major, minor);
+ }
+ else {
+ /* info->vt_active gets set by systemd_logind_vtenter() */
+ info->active = TRUE;
+
+ if (pdev) {
+ pdev->flags &= ~XF86_PDEV_PAUSED;
+ systemd_logind_vtenter();
+ }
+ else {
+ pInfo->fd = fd;
+ pInfo->options = xf86ReplaceIntOption(pInfo->options, "fd", fd);
+ if (info->vt_active)
+ xf86EnableInputDeviceForVTSwitch(pInfo);
+ }
+ }
+ return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static void
+connect_hook(DBusConnection *connection, void *data)
+{
+ struct systemd_logind_info *info = data;
+ DBusError error;
+ DBusMessage *msg = NULL;
+ DBusMessage *reply = NULL;
+ dbus_int32_t arg;
+ char *session = NULL;
+
+ dbus_error_init(&error);
+
+ msg = dbus_message_new_method_call("org.freedesktop.login1",
+ "/org/freedesktop/login1", "org.freedesktop.login1.Manager",
+ "GetSessionByPID");
+ if (!msg) {
+ LogMessage(X_ERROR, "systemd-logind: out of memory\n");
+ goto cleanup;
+ }
+
+ arg = getpid();
+ if (!dbus_message_append_args(msg, DBUS_TYPE_UINT32, &arg,
+ DBUS_TYPE_INVALID)) {
+ LogMessage(X_ERROR, "systemd-logind: out of memory\n");
+ goto cleanup;
+ }
+
+ reply = dbus_connection_send_with_reply_and_block(connection, msg,
+ DBUS_TIMEOUT, &error);
+ if (!reply) {
+ LogMessage(X_ERROR, "systemd-logind: failed to get session: %s\n",
+ error.message);
+ goto cleanup;
+ }
+ dbus_message_unref(msg);
+
+ if (!dbus_message_get_args(reply, &error, DBUS_TYPE_OBJECT_PATH, &session,
+ DBUS_TYPE_INVALID)) {
+ LogMessage(X_ERROR, "systemd-logind: GetSessionByPID: %s\n",
+ error.message);
+ goto cleanup;
+ }
+ session = XNFstrdup(session);
+
+ dbus_message_unref(reply);
+ reply = NULL;
+
+
+ msg = dbus_message_new_method_call("org.freedesktop.login1",
+ session, "org.freedesktop.login1.Session", "TakeControl");
+ if (!msg) {
+ LogMessage(X_ERROR, "systemd-logind: out of memory\n");
+ goto cleanup;
+ }
+
+ arg = FALSE; /* Don't forcibly take over over the session */
+ if (!dbus_message_append_args(msg, DBUS_TYPE_BOOLEAN, &arg,
+ DBUS_TYPE_INVALID)) {
+ LogMessage(X_ERROR, "systemd-logind: out of memory\n");
+ goto cleanup;
+ }
+
+ reply = dbus_connection_send_with_reply_and_block(connection, msg,
+ DBUS_TIMEOUT, &error);
+ if (!reply) {
+ LogMessage(X_ERROR, "systemd-logind: TakeControl failed: %s\n",
+ error.message);
+ goto cleanup;
+ }
+
+ /*
+ * HdG: This is not useful with systemd <= 208 since the signal only
+ * contains invalidated property names there, rather than property, val
+ * pairs as it should. Instead we just use the first resume / pause now.
+ */
+#if 0
+ snprintf(match, sizeof(match),
+ "type='signal',sender='org.freedesktop.login1',interface='org.freedesktop.DBus.Properties',member='PropertiesChanged',path='%s'",
+ session);
+ dbus_bus_add_match(connection, match, &error);
+ if (dbus_error_is_set(&error)) {
+ LogMessage(X_ERROR, "systemd-logind: could not add match: %s\n",
+ error.message);
+ goto cleanup;
+ }
+#endif
+
+ if (!dbus_connection_add_filter(connection, message_filter, info, NULL)) {
+ LogMessage(X_ERROR, "systemd-logind: could not add filter: %s\n",
+ error.message);
+ goto cleanup;
+ }
+
+ LogMessage(X_INFO, "systemd-logind: took control of session %s\n",
+ session);
+ info->conn = connection;
+ info->session = session;
+ info->vt_active = info->active = TRUE; /* The server owns the vt during init */
+ session = NULL;
+
+cleanup:
+ free(session);
+ if (msg)
+ dbus_message_unref(msg);
+ if (reply)
+ dbus_message_unref(reply);
+ dbus_error_free(&error);
+}
+
+static void
+systemd_logind_release_control(struct systemd_logind_info *info)
+{
+ DBusError error;
+ DBusMessage *msg = NULL;
+ DBusMessage *reply = NULL;
+
+ dbus_error_init(&error);
+
+ msg = dbus_message_new_method_call("org.freedesktop.login1",
+ info->session, "org.freedesktop.login1.Session", "ReleaseControl");
+ if (!msg) {
+ LogMessage(X_ERROR, "systemd-logind: out of memory\n");
+ goto cleanup;
+ }
+
+ reply = dbus_connection_send_with_reply_and_block(info->conn, msg,
+ DBUS_TIMEOUT, &error);
+ if (!reply) {
+ LogMessage(X_ERROR, "systemd-logind: ReleaseControl failed: %s\n",
+ error.message);
+ goto cleanup;
+ }
+
+cleanup:
+ if (msg)
+ dbus_message_unref(msg);
+ if (reply)
+ dbus_message_unref(reply);
+ dbus_error_free(&error);
+}
+
+static void
+disconnect_hook(void *data)
+{
+ struct systemd_logind_info *info = data;
+
+ free(info->session);
+ info->session = NULL;
+ info->conn = NULL;
+}
+
+static struct dbus_core_hook core_hook = {
+ .connect = connect_hook,
+ .disconnect = disconnect_hook,
+ .data = &logind_info,
+};
+
+int
+systemd_logind_init(void)
+{
+ return dbus_core_add_hook(&core_hook);
+}
+
+void
+systemd_logind_fini(void)
+{
+ if (logind_info.session)
+ systemd_logind_release_control(&logind_info);
+
+ dbus_core_remove_hook(&core_hook);
+}
diff --git a/xorg-server/hw/xfree86/os-support/shared/posix_tty.c b/xorg-server/hw/xfree86/os-support/shared/posix_tty.c
index 4d08c1e85..6e2af001a 100644
--- a/xorg-server/hw/xfree86/os-support/shared/posix_tty.c
+++ b/xorg-server/hw/xfree86/os-support/shared/posix_tty.c
@@ -124,7 +124,11 @@ xf86OpenSerial(XF86OptionPtr options)
return -1;
}
- SYSCALL(fd = open(dev, O_RDWR | O_NONBLOCK));
+ fd = xf86CheckIntOption(options, "fd", -1);
+
+ if (fd == -1)
+ SYSCALL(fd = open(dev, O_RDWR | O_NONBLOCK));
+
if (fd == -1) {
xf86Msg(X_ERROR,
"xf86OpenSerial: Cannot open device %s\n\t%s.\n",
diff --git a/xorg-server/include/Makefile.am b/xorg-server/include/Makefile.am
index fa6da00ec..6578038a5 100644
--- a/xorg-server/include/Makefile.am
+++ b/xorg-server/include/Makefile.am
@@ -72,4 +72,5 @@ EXTRA_DIST = \
dix-config-apple-verbatim.h \
dixfontstubs.h eventconvert.h eventstr.h inpututils.h \
protocol-versions.h \
+ systemd-logind.h \
xsha1.h
diff --git a/xorg-server/include/dix-config.h.in b/xorg-server/include/dix-config.h.in
index 7c77956b1..06455a837 100644
--- a/xorg-server/include/dix-config.h.in
+++ b/xorg-server/include/dix-config.h.in
@@ -420,6 +420,9 @@
/* Support HAL for hotplug */
#undef CONFIG_HAL
+/* Enable systemd-logind integration */
+#undef SYSTEMD_LOGIND 1
+
/* Have a monotonic clock from clock_gettime() */
#undef MONOTONIC_CLOCK
@@ -481,4 +484,7 @@
/* Build GLAMOR */
#undef GLAMOR
+/* Build glamor's GBM-based EGL support */
+#undef GLAMOR_HAS_GBM
+
#endif /* _DIX_CONFIG_H_ */
diff --git a/xorg-server/include/hotplug.h b/xorg-server/include/hotplug.h
index 29a22c4da..1d9364eee 100644
--- a/xorg-server/include/hotplug.h
+++ b/xorg-server/include/hotplug.h
@@ -32,15 +32,20 @@ extern _X_EXPORT void config_pre_init(void);
extern _X_EXPORT void config_init(void);
extern _X_EXPORT void config_fini(void);
+enum { ODEV_ATTRIB_STRING, ODEV_ATTRIB_INT };
+
struct OdevAttribute {
struct xorg_list member;
int attrib_id;
- char *attrib_name;
+ union {
+ char *attrib_name;
+ int attrib_value;
+ };
+ int attrib_type;
};
struct OdevAttributes {
struct xorg_list list;
- Bool unowned;
};
struct OdevAttributes *
@@ -53,6 +58,17 @@ Bool
config_odev_add_attribute(struct OdevAttributes *attribs, int attrib,
const char *attrib_name);
+char *
+config_odev_get_attribute(struct OdevAttributes *attribs, int attrib_id);
+
+Bool
+config_odev_add_int_attribute(struct OdevAttributes *attribs, int attrib,
+ int attrib_value);
+
+int
+config_odev_get_int_attribute(struct OdevAttributes *attribs, int attrib,
+ int def);
+
void
config_odev_free_attributes(struct OdevAttributes *attribs);
@@ -62,6 +78,12 @@ config_odev_free_attributes(struct OdevAttributes *attribs);
#define ODEV_ATTRIB_SYSPATH 2
/* DRI-style bus id */
#define ODEV_ATTRIB_BUSID 3
+/* Server managed FD */
+#define ODEV_ATTRIB_FD 4
+/* Major number of the device node pointed to by ODEV_ATTRIB_PATH */
+#define ODEV_ATTRIB_MAJOR 5
+/* Minor number of the device node pointed to by ODEV_ATTRIB_PATH */
+#define ODEV_ATTRIB_MINOR 6
typedef void (*config_odev_probe_proc_ptr)(struct OdevAttributes *attribs);
void config_odev_probe(config_odev_probe_proc_ptr probe_callback);
@@ -72,4 +94,8 @@ void DeleteGPUDeviceRequest(struct OdevAttributes *attribs);
#endif
#define ServerIsNotSeat0() (SeatId && strcmp(SeatId, "seat0"))
+
+struct xf86_platform_device *
+xf86_find_platform_device_by_devnum(int major, int minor);
+
#endif /* HOTPLUG_H */
diff --git a/xorg-server/include/systemd-logind.h b/xorg-server/include/systemd-logind.h
new file mode 100644
index 000000000..8b0908186
--- /dev/null
+++ b/xorg-server/include/systemd-logind.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright © 2013 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.
+ *
+ * Author: Hans de Goede <hdegoede@redhat.com>
+ */
+
+#ifndef SYSTEMD_LOGIND_H
+#define SYSTEMD_LOGIND_H
+
+#ifdef SYSTEMD_LOGIND
+int systemd_logind_init(void);
+void systemd_logind_fini(void);
+int systemd_logind_take_fd(int major, int minor, const char *path, Bool *paus);
+void systemd_logind_release_fd(int major, int minor);
+int systemd_logind_controls_session(void);
+void systemd_logind_vtenter(void);
+#else
+#define systemd_logind_init()
+#define systemd_logind_fini()
+#define systemd_logind_take_fd(major, minor, path) -1
+#define systemd_logind_release_fd(dev)
+#define systemd_logind_controls_session() 0
+#define systemd_logind_vtenter()
+#endif
+
+#endif