[Xquartz-changes] xserver: Branch 'master' - 35 commits
Jeremy Huddleston
jeremyhu at freedesktop.org
Fri Nov 8 10:18:20 PST 2013
Makefile.am | 12
Xext/shm.c | 168 ++++++
Xext/shmint.h | 10
Xext/sync.c | 51 +-
Xext/syncsrv.h | 13
Xext/xvdisp.c | 13
configure.ac | 116 +++-
dix/region.c | 15
dri3/Makefile.am | 13
dri3/dri3.c | 87 +++
dri3/dri3.h | 65 ++
dri3/dri3_event.c | 163 ++++++
dri3/dri3_priv.h | 80 +++
dri3/dri3_request.c | 394 ++++++++++++++++
dri3/dri3_screen.c | 80 +++
dri3/dri3int.h | 26 +
glx/glxcmds.c | 3
hw/dmx/dmxextension.c | 3
hw/dmx/dmxinit.c | 2
hw/kdrive/ephyr/hostx.c | 22
hw/xfree86/Makefile.am | 9
hw/xfree86/common/compiler.h | 2
hw/xfree86/common/xf86Configure.c | 2
hw/xfree86/common/xf86DPMS.c | 9
hw/xfree86/common/xf86Events.c | 31 -
hw/xfree86/common/xf86RandR.c | 16
hw/xfree86/modes/xf86Crtc.c | 20
hw/xfree86/os-support/linux/lnx_video.c | 3
hw/xfree86/sdksyms.sh | 4
include/dix-config.h.in | 9
include/dixstruct.h | 8
include/extinit.h | 10
include/misc.h | 29 +
include/os.h | 5
include/regionstr.h | 2
include/servermd.h | 14
include/xorg-config.h.in | 6
include/xorg-server.h.in | 9
mi/miinitext.c | 4
miext/damage/damage.c | 5
miext/sync/Makefile.am | 8
miext/sync/misync.c | 31 -
miext/sync/misync.h | 21
miext/sync/misyncshm.c | 176 +++++++
miext/sync/misyncshm.h | 28 +
miext/sync/misyncstr.h | 15
os/backtrace.c | 5
os/connection.c | 2
os/io.c | 29 +
os/utils.c | 27 +
os/xstrans.c | 2
present/Makefile.am | 17
present/present.c | 775 ++++++++++++++++++++++++++++++++
present/present.h | 118 ++++
present/present_event.c | 239 +++++++++
present/present_fake.c | 140 +++++
present/present_fence.c | 112 ++++
present/present_notify.c | 114 ++++
present/present_priv.h | 288 +++++++++++
present/present_request.c | 330 +++++++++++++
present/present_screen.c | 231 +++++++++
present/presentext.h | 29 +
test/Makefile.am | 11
63 files changed, 4169 insertions(+), 112 deletions(-)
New commits:
commit ab4b1fb38a61feb73d8336cc7a3399eb9d3d25be
Author: Andreas Schwab <schwab at suse.de>
Date: Thu Aug 15 12:03:42 2013 +0200
ARM64: Add support for aarch64
Signed-off-by: Andreas Schwab <schwab at suse.de>
Reviewed-by: Mark Kettenis <kettenis at openbsd.org>
Reviewed-by: Adam Jackson <ajax at redhat.com>
Signed-off-by: Keith Packard <keithp at keithp.com>
diff --git a/hw/xfree86/common/compiler.h b/hw/xfree86/common/compiler.h
index c980bee..3a57186 100644
--- a/hw/xfree86/common/compiler.h
+++ b/hw/xfree86/common/compiler.h
@@ -1351,7 +1351,7 @@ stl_u(unsigned long val, unsigned int *p)
#else /* ix86 */
#if !defined(__SUNPRO_C)
-#if !defined(FAKEIT) && !defined(__mc68000__) && !defined(__arm__) && !defined(__sh__) && !defined(__hppa__) && !defined(__s390__) && !defined(__m32r__)
+#if !defined(FAKEIT) && !defined(__mc68000__) && !defined(__arm__) && !defined(__sh__) && !defined(__hppa__) && !defined(__s390__) && !defined(__m32r__) && !defined(__aarch64__)
#ifdef GCCUSESGAS
/*
diff --git a/hw/xfree86/os-support/linux/lnx_video.c b/hw/xfree86/os-support/linux/lnx_video.c
index d9a5da1..43d0a36 100644
--- a/hw/xfree86/os-support/linux/lnx_video.c
+++ b/hw/xfree86/os-support/linux/lnx_video.c
@@ -58,7 +58,8 @@ static Bool ExtendedEnabled = FALSE;
!defined(__sparc__) && \
!defined(__mips__) && \
!defined(__nds32__) && \
- !defined(__arm__)
+ !defined(__arm__) && \
+ !defined(__aarch64__)
/*
* Due to conflicts with "compiler.h", don't rely on <sys/io.h> to declare
diff --git a/include/servermd.h b/include/servermd.h
index d6a9a3a..11f6c10 100644
--- a/include/servermd.h
+++ b/include/servermd.h
@@ -286,6 +286,20 @@ SOFTWARE.
#define GLYPHPADBYTES 4
#endif /* linux/s390 */
+#ifdef __aarch64__
+
+#ifdef __AARCH64EL__
+#define IMAGE_BYTE_ORDER LSBFirst
+#define BITMAP_BIT_ORDER LSBFirst
+#endif
+#ifdef __AARCH64EB__
+#define IMAGE_BYTE_ORDER MSBFirst
+#define BITMAP_BIT_ORDER MSBFirst
+#endif
+#define GLYPHPADBYTES 4
+
+#endif /* __aarch64__ */
+
/* size of buffer to use with GetImage, measured in bytes. There's obviously
* a trade-off between the amount of heap used and the number of times the
* ddx routine has to be called.
commit 8fcf82cbf015609e00b3feb9bc567133c7aee5cf
Author: Keith Packard <keithp at keithp.com>
Date: Tue Nov 5 18:39:11 2013 -0800
Use $GL_LIBS instead of -lGL for linking
-lGL presumes that the GL library is in the system path, while
$GL_LIBS is auto-detected.
Signed-off-by: Keith Packard <keithp at keithp.com>
diff --git a/configure.ac b/configure.ac
index feeae04..6925df8 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1075,7 +1075,7 @@ if test "x$GLX" = xyes; then
AC_SUBST(XLIB_CFLAGS)
AC_DEFINE(GLXEXT, 1, [Build GLX extension])
GLX_LIBS='$(top_builddir)/glx/libglx.la'
- GLX_SYS_LIBS="$GLX_SYS_LIBS -lGL"
+ GLX_SYS_LIBS="$GLX_SYS_LIBS $GL_LIBS"
else
GLX=no
fi
commit f348935e7d2c84a438aba08eee2f2c4e0dc77d20
Author: Keith Packard <keithp at keithp.com>
Date: Tue Nov 5 18:37:12 2013 -0800
Link with xshmfence, reference miSyncShmScreenInit in sdksyms
This gets the server to link with xshmfence again, and also ensures
that the miSyncShm code is linked into the server with the reference
from sdksyms.
Signed-off-by: Keith Packard <keithp at keithp.com>
diff --git a/configure.ac b/configure.ac
index a7515a3..feeae04 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1144,6 +1144,7 @@ AM_CONDITIONAL(XSHMFENCE, test "x$HAVE_XSHMFENCE" = xyes)
case x"$HAVE_XSHMFENCE" in
xyes)
AC_DEFINE(HAVE_XSHMFENCE, 1, [Have X Shared Memory Fence library])
+ REQUIRED_LIBS="$REQUIRED_LIBS xshmfence"
;;
esac
diff --git a/hw/xfree86/sdksyms.sh b/hw/xfree86/sdksyms.sh
index 7c9734c..d7f259d 100755
--- a/hw/xfree86/sdksyms.sh
+++ b/hw/xfree86/sdksyms.sh
@@ -44,6 +44,9 @@ cat > sdksyms.c << EOF
/* miext/sync/Makefile.am */
#include "misync.h"
#include "misyncstr.h"
+#if HAVE_XSHMFENCE
+#include "misyncshm.h"
+#endif
/* Xext/Makefile.am -- half is module, half is builtin */
#ifdef XV
diff --git a/include/dix-config.h.in b/include/dix-config.h.in
index 397ee96..156383b 100644
--- a/include/dix-config.h.in
+++ b/include/dix-config.h.in
@@ -449,4 +449,7 @@
#include "dix-config-apple-verbatim.h"
#endif
+/* Have support for X shared memory fence library (xshmfence) */
+#undef HAVE_XSHMFENCE
+
#endif /* _DIX_CONFIG_H_ */
diff --git a/include/xorg-config.h.in b/include/xorg-config.h.in
index 487d7ad..e3444da 100644
--- a/include/xorg-config.h.in
+++ b/include/xorg-config.h.in
@@ -145,4 +145,7 @@
/* Support APM/ACPI power management in the server */
#undef XF86PM
+/* Have support for X shared memory fence library (xshmfence) */
+#undef HAVE_XSHMFENCE
+
#endif /* _XORG_CONFIG_H_ */
commit 5f1e832694e57986c0185048a941b3af51b2f85f
Author: Julien Cristau <jcristau at debian.org>
Date: Tue Nov 5 07:08:21 2013 -0800
os: Actually use the computed clockid in GetTimeInMicros
The selection of which clock to use for this function was not actually
getting used when fetching the final clock value.
Reported-by: Julien Cristau <jcristau at debian.org>
Signed-off-by: Keith Packard <keithp at keithp.com>
diff --git a/os/utils.c b/os/utils.c
index 995f62a..fb20da7 100644
--- a/os/utils.c
+++ b/os/utils.c
@@ -480,7 +480,7 @@ GetTimeInMicros(void)
else
clockid = ~0L;
}
- if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0)
+ if (clockid != ~0L && clock_gettime(clockid, &tp) == 0)
return (CARD64) tp.tv_sec * (CARD64)1000000 + tp.tv_nsec / 1000;
#endif
commit 903a058370645ea075ea98d380fd565efb6160c9
Author: Keith Packard <keithp at keithp.com>
Date: Mon Nov 4 19:01:26 2013 -0800
hw/xfree86: Link libdri3 only when DRI3 is defined
Don't attempt to link non-existant libraries...
Signed-off-by: Keith Packard <keithp at keithp.com>
diff --git a/hw/xfree86/Makefile.am b/hw/xfree86/Makefile.am
index eea16a8..485386f 100644
--- a/hw/xfree86/Makefile.am
+++ b/hw/xfree86/Makefile.am
@@ -9,6 +9,11 @@ DRI2_SUBDIR = dri2
DRI2_LIB = dri2/libdri2.la
endif
+if DRI3
+DRI3_BUILDDIR = $(top_builddir)/dri3
+DRI3_LIB = $(DRI3_BUILDDIR)/libdri3.la
+endif
+
if XF86UTILS
XF86UTILS_SUBDIR = utils
endif
@@ -59,7 +64,7 @@ LOCAL_LIBS = \
dixmods/libxorgxkb.la \
$(DRI_LIB) \
$(DRI2_LIB) \
- $(top_builddir)/dri3/libdri3.la \
+ $(DRI3_LIB) \
$(top_builddir)/miext/sync/libsync.la \
$(top_builddir)/mi/libmi.la \
$(top_builddir)/os/libos.la
commit aaf0e29619196a283fee7ead2020a91032d84f48
Author: Keith Packard <keithp at keithp.com>
Date: Sun Nov 3 09:56:02 2013 -0800
Disable DRI3 and sync fence FD functions if xshmfence isn't available
Make sure the server can build when the xshmfence library isn't present
Signed-off-by: Keith Packard <keithp at keithp.com>
diff --git a/Xext/sync.c b/Xext/sync.c
index a04c383..dd18cde 100644
--- a/Xext/sync.c
+++ b/Xext/sync.c
@@ -919,6 +919,7 @@ SyncCreate(ClientPtr client, XID id, unsigned char type)
int
SyncCreateFenceFromFD(ClientPtr client, DrawablePtr pDraw, XID id, int fd, BOOL initially_triggered)
{
+#if HAVE_XSHMFENCE
SyncFence *pFence;
int status;
@@ -936,12 +937,19 @@ SyncCreateFenceFromFD(ClientPtr client, DrawablePtr pDraw, XID id, int fd, BOOL
return BadAlloc;
return Success;
+#else
+ return BadImplementation;
+#endif
}
int
SyncFDFromFence(ClientPtr client, DrawablePtr pDraw, SyncFence *pFence)
{
+#if HAVE_XSHMFENCE
return miSyncFDFromFence(pDraw, pFence);
+#else
+ return BadImplementation;
+#endif
}
static SyncCounter *
diff --git a/configure.ac b/configure.ac
index 0d855f2..a7515a3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -792,6 +792,7 @@ DMXPROTO="dmxproto >= 2.2.99.1"
VIDMODEPROTO="xf86vidmodeproto >= 2.2.99.1"
WINDOWSWMPROTO="windowswmproto"
APPLEWMPROTO="applewmproto >= 1.4"
+XSHMFENCE="xshmfence"
dnl Required modules
XPROTO="xproto >= 7.0.22"
@@ -1119,17 +1120,59 @@ AM_CONDITIONAL(DRI2, test "x$DRI2" = xyes)
PKG_CHECK_MODULES([DRI3PROTO], $DRI3PROTO,
[HAVE_DRI3PROTO=yes], [HAVE_DRI3PROTO=no])
+
case "$DRI3,$HAVE_DRI3PROTO" in
+ yes,yes | auto,yes)
+ ;;
yes,no)
AC_MSG_ERROR([DRI3 requested, but dri3proto not found.])
+ DRI3=no
+ ;;
+ no,*)
+ ;;
+ *)
+ AC_MSG_NOTICE([DRI3 disabled because dri3proto not found.])
+ DRI3=no
;;
+esac
+
+PKG_CHECK_MODULES([XSHMFENCE], $XSHMFENCE,
+ [HAVE_XSHMFENCE=yes], [HAVE_XSHMFENCE=no])
+
+AM_CONDITIONAL(XSHMFENCE, test "x$HAVE_XSHMFENCE" = xyes)
+
+case x"$HAVE_XSHMFENCE" in
+ xyes)
+ AC_DEFINE(HAVE_XSHMFENCE, 1, [Have X Shared Memory Fence library])
+ ;;
+esac
+
+
+case "$DRI3,$HAVE_XSHMFENCE" in
yes,yes | auto,yes)
- AC_DEFINE(DRI3, 1, [Build DRI3 extension])
+ ;;
+ yes,no)
+ AC_MSG_ERROR("DRI3 requested, but xshmfence not found.])
+ DRI3=no
+ ;;
+ no,*)
+ ;;
+ *)
+ AC_MSG_NOTICE([DRI3 disabled because xshmfence not found.])
+ DRI3=no
+ ;;
+esac
+
+case x"$DRI3" in
+ xyes|xauto)
DRI3=yes
+ AC_DEFINE(DRI3, 1, [Build DRI3 extension])
DRI3_LIB='$(top_builddir)/dri3/libdri3.la'
SDK_REQUIRED_MODULES="$SDK_REQUIRED_MODULES $DRI3PROTO"
+ AC_MSG_NOTICE([DRI3 enabled]);
;;
esac
+
AM_CONDITIONAL(DRI3, test "x$DRI3" = xyes)
if test "x$DRI" = xyes || test "x$DRI2" = xyes || test "x$DRI3" = xyes || test "x$CONFIG_UDEV_KMS" = xyes; then
@@ -1333,7 +1376,6 @@ if test "x$XDMAUTH" = xyes; then
XDMCP_MODULES="xdmcp"
fi
fi
-REQUIRED_LIBS="$REQUIRED_LIBS xshmfence"
AC_DEFINE_DIR(COMPILEDDEFAULTFONTPATH, FONTPATH, [Default font path])
AC_DEFINE_DIR(SERVER_MISC_CONFIG_PATH, SERVERCONFIG, [Server miscellaneous config path])
diff --git a/dri3/dri3.h b/dri3/dri3.h
index 7774c87..7c0c330 100644
--- a/dri3/dri3.h
+++ b/dri3/dri3.h
@@ -23,6 +23,10 @@
#ifndef _DRI3_H_
#define _DRI3_H_
+#include <xorg-server.h>
+
+#ifdef DRI3
+
#include <X11/extensions/dri3proto.h>
#include <randrstr.h>
@@ -56,4 +60,6 @@ typedef struct dri3_screen_info {
extern _X_EXPORT Bool
dri3_screen_init(ScreenPtr screen, dri3_screen_info_ptr info);
+#endif
+
#endif /* _DRI3_H_ */
diff --git a/include/xorg-server.h.in b/include/xorg-server.h.in
index 1281b3e..960817e 100644
--- a/include/xorg-server.h.in
+++ b/include/xorg-server.h.in
@@ -218,4 +218,7 @@
#define _XSERVER64 1
#endif
+/* Have support for X shared memory fence library (xshmfence) */
+#undef HAVE_XSHMFENCE
+
#endif /* _XORG_SERVER_H_ */
diff --git a/miext/sync/Makefile.am b/miext/sync/Makefile.am
index e25ceac..ac13c52 100644
--- a/miext/sync/Makefile.am
+++ b/miext/sync/Makefile.am
@@ -8,8 +8,13 @@ if XORG
sdk_HEADERS = misync.h misyncstr.h misyncshm.h
endif
+XSHMFENCE_SRCS = misyncshm.c
+
libsync_la_SOURCES = \
misync.c \
misync.h \
- misyncshm.c \
misyncstr.h
+
+if XSHMFENCE
+libsync_la_SOURCES += $(XSHMFENCE_SRCS)
+endif
commit 33c85beed521c9db140cadd8c5aa9992398ee1fe
Author: Keith Packard <keithp at keithp.com>
Date: Fri Nov 1 01:01:58 2013 -0700
Set version to 1.14.99.901 (1.15 RC1)
Signed-off-by: Keith Packard <keithp at keithp.com>
diff --git a/configure.ac b/configure.ac
index 3d9832b..0d855f2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -26,9 +26,9 @@ dnl
dnl Process this file with autoconf to create configure.
AC_PREREQ(2.60)
-AC_INIT([xorg-server], 1.14.99.3, [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], xorg-server)
-RELEASE_DATE="2013-10-18"
-RELEASE_NAME="Bundaberg"
+AC_INIT([xorg-server], 1.14.99.901, [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], xorg-server)
+RELEASE_DATE="2013-10-31"
+RELEASE_NAME="Bom Retiro"
AC_CONFIG_SRCDIR([Makefile.am])
AM_INIT_AUTOMAKE([foreign dist-bzip2])
commit 9db1d66f6d2c6857de220d8f1c08965962fe1416
Author: Keith Packard <keithp at keithp.com>
Date: Fri Nov 1 01:43:59 2013 -0700
Add dri3 and present directorys to distribution
Signed-off-by: Keith Packard <keithp at keithp.com>
diff --git a/Makefile.am b/Makefile.am
index 28266c5..5bf760b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -101,6 +101,8 @@ DIST_SUBDIRS = \
glx \
exa \
config \
+ dri3 \
+ present \
hw \
test
commit 977e2644b1d9e13b44debcb9a372bbc832ee32a3
Merge: 66c5ee0 f36f5a6
Author: Keith Packard <keithp at keithp.com>
Date: Fri Nov 1 00:34:18 2013 -0700
Merge remote-tracking branch 'whot/for-keith'
commit 66c5ee0ff4690e630a69656331fd9d545c99c26c
Author: Egbert Eich <eich at freedesktop.org>
Date: Wed Aug 14 18:18:56 2013 +0200
config/APM: Add option to disable building of APM support on Linux
APM support in the Xserver was used to restore the console mode
prior to a power management event. This was to ensure the mode
upon suspend/resume was one that the system firmware or kernel
could deal with.
APM support is now largely obsolete, KMS drivers don't require a
mode restoration anyhow. Therefore it should be possible to disable
this feature.
(small modification by keithp - move test for XF86PM flag after check
for APM, then move XF86PM flag to xorg-config.h.in)
Signed-off-by: Egbert Eich <eich at freedesktop.org>
Tested-by: Keith Packard <keithp at keithp.com>
Signed-off-by: Keith Packard <keithp at keithp.com>
diff --git a/configure.ac b/configure.ac
index 9b8b89f..c48d2aa 100644
--- a/configure.ac
+++ b/configure.ac
@@ -228,10 +228,6 @@ dnl AGPGART headers
AC_CHECK_HEADERS([linux/agpgart.h sys/agpio.h sys/agpgart.h], AGP=yes)
AM_CONDITIONAL(AGP, [test "x$AGP" = xyes])
-dnl APM header
-AC_CHECK_HEADERS([linux/apm_bios.h], LNXAPM=yes)
-AM_CONDITIONAL(LNXAPM, [test "x$LNXAPM" = xyes])
-
dnl fbdev header
AC_CHECK_HEADERS([linux/fb.h], FBDEV=yes)
AM_CONDITIONAL(FBDEVHW, [test "x$FBDEV" = xyes])
@@ -638,6 +634,7 @@ AC_ARG_ENABLE(libdrm, AS_HELP_STRING([--enable-libdrm], [Build Xorg with
AC_ARG_ENABLE(clientids, AS_HELP_STRING([--disable-clientids], [Build Xorg with client ID tracking (default: enabled)]), [CLIENTIDS=$enableval], [CLIENTIDS=yes])
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, AC_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, AC_HELP_STRING([--disable-linux-apm], [Disable building APM support on Linux (if available).]), [enable_linux_apm=$enableval], [enable_linux_apm=yes])
dnl DDXes.
AC_ARG_ENABLE(xorg, AS_HELP_STRING([--enable-xorg], [Build Xorg server (default: auto)]), [XORG=$enableval], [XORG=auto])
@@ -1736,9 +1733,6 @@ if test "x$XORG" = xyes; then
case $host_os in
linux*)
- if test "x$LNXAPM" = xyes; then
- XORG_CFLAGS="$XORG_CFLAGS -DXF86PM"
- fi
XORG_OS_SUBDIR="linux"
linux_acpi="no"
case $host_cpu in
@@ -1751,6 +1745,11 @@ if test "x$XORG" = xyes; then
*)
;;
esac
+ dnl APM header
+ AC_CHECK_HEADERS([linux/apm_bios.h], [linux_apm=$enable_linux_apm])
+ if test "x$linux_apm" = xyes -o "x$linux_acpi" = xyes; then
+ AC_DEFINE(XF86PM, 1, [Support APM/ACPI power management in the server])
+ fi
;;
freebsd* | kfreebsd*-gnu | dragonfly*)
XORG_OS_SUBDIR="bsd"
@@ -1913,6 +1912,7 @@ AM_CONDITIONAL([XORG_BUS_BSDPCI], [test "x$xorg_bus_bsdpci" = xyes])
AM_CONDITIONAL([XORG_BUS_SPARC], [test "x$xorg_bus_sparc" = xyes])
AM_CONDITIONAL([LINUX_ALPHA], [test "x$linux_alpha" = xyes])
AM_CONDITIONAL([LNXACPI], [test "x$linux_acpi" = xyes])
+AM_CONDITIONAL([LNXAPM], [test "x$linux_apm" = xyes])
AM_CONDITIONAL([SOLARIS_ASM_INLINE], [test "x$solaris_asm_inline" = xyes])
AM_CONDITIONAL([SOLARIS_VT], [test "x$solaris_vt" = xyes])
AM_CONDITIONAL([DGA], [test "x$DGA" = xyes])
diff --git a/include/xorg-config.h.in b/include/xorg-config.h.in
index 0df31ae..487d7ad 100644
--- a/include/xorg-config.h.in
+++ b/include/xorg-config.h.in
@@ -142,4 +142,7 @@
/* Define to 1 if you have the `seteuid' function. */
#undef HAVE_SETEUID
+/* Support APM/ACPI power management in the server */
+#undef XF86PM
+
#endif /* _XORG_CONFIG_H_ */
commit f36f5a65f639b6524191d888d5bf89e73027156c
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date: Wed Oct 30 15:40:58 2013 +1000
sync: fix corner-case in triggering idle alarms
ProcessInputEvent() resets the device idle times. If idle time was higher than
the lower bracket, this should trigger an event in the idle time wakeup
handler.
If processing is slow, the idle time may advance past the lower bracket
between the reset and the time the BlockHandler is called. In that case, we'd
never schedule a wakeup to handle the event, causing us to randomly miss
events.
Ran tests with a neg transition trigger on 5ms with 200 repeats of the test
and it succeeded. Anything below that gets a bit tricky to make sure the
server sees the same idle time as the client usleeps for.
Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
Reviewed-by: Keith Packard <keithp at keithp.com>
diff --git a/Xext/sync.c b/Xext/sync.c
index b2ee92e..53f769d 100644
--- a/Xext/sync.c
+++ b/Xext/sync.c
@@ -2654,7 +2654,16 @@ IdleTimeBlockHandler(pointer pCounter, struct timeval **wt, pointer LastSelectMa
IdleTimeQueryValue(counter, &idle);
counter->value = idle; /* push, so CheckTrigger works */
- if (less && XSyncValueLessOrEqual(idle, *less)) {
+ /**
+ * There's an indefinite amount of time between ProcessInputEvents()
+ * where the idle time is reset and the time we actually get here. idle
+ * may be past the lower bracket if we dawdled with the events, so
+ * check for whether we did reset and bomb out of select immediately.
+ */
+ if (less && XSyncValueGreaterThan(idle, *less) &&
+ LastEventTimeWasReset(priv->deviceid)) {
+ AdjustWaitForDelay(wt, 0);
+ } else if (less && XSyncValueLessOrEqual(idle, *less)) {
/*
* We've been idle for less than the threshold value, and someone
* wants to know about that, but now we need to know whether they
commit f994d99539192a10a8c83047e11991f52e0ca677
Author: Egbert Eich <eich at freedesktop.org>
Date: Wed Aug 14 18:18:39 2013 +0200
config/ACPI: Add option to disable building of ACPI support on Linux
ACPI support in the Xserver was used to restore the console mode
prior to a power management event. This was to ensure the mode
upon suspend/resume was one that the system firmware or kernel
could deal with.
The feature depended on acpid to be running. Most of this functionality
is now take over by systemd, KMS drivers don't require a mode restoration
anyhow. Therefore it should be possible to disable this feature under
some circumstances.
Tested-by: Keith Packard <keithp at keithp.com>
Signed-off-by: Keith Packard <keithp at keithp.com>
diff --git a/configure.ac b/configure.ac
index 7432912..9b8b89f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -637,6 +637,7 @@ AC_ARG_ENABLE(windowswm, AS_HELP_STRING([--enable-windowswm], [Build XWin w
AC_ARG_ENABLE(libdrm, AS_HELP_STRING([--enable-libdrm], [Build Xorg with libdrm support (default: enabled)]), [DRM=$enableval],[DRM=yes])
AC_ARG_ENABLE(clientids, AS_HELP_STRING([--disable-clientids], [Build Xorg with client ID tracking (default: enabled)]), [CLIENTIDS=$enableval], [CLIENTIDS=yes])
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, AC_HELP_STRING([--disable-linux-acpi], [Disable building ACPI support on Linux (if available).]), [enable_linux_acpi=$enableval], [enable_linux_acpi=yes])
dnl DDXes.
AC_ARG_ENABLE(xorg, AS_HELP_STRING([--enable-xorg], [Build Xorg server (default: auto)]), [XORG=$enableval], [XORG=auto])
@@ -1745,7 +1746,7 @@ if test "x$XORG" = xyes; then
linux_alpha=yes
;;
i*86|amd64*|x86_64*|ia64*)
- linux_acpi="yes"
+ linux_acpi=$enable_linux_acpi
;;
*)
;;
commit 2aa5092b88174cb9988076ae96298217c97ad75f
Author: Egbert Eich <eich at freedesktop.org>
Date: Mon Aug 12 18:21:33 2013 +0200
DDX/Randr: Avoid server crash when xrandr SetConfig is called while switched away
A call to Xrandr SetScreenConfig (for randr 1.1) causes the Xserver to
crash when xf86SetViewport() which does not check if the hardware is
accessible.
Wrap accesses to xf86SetViewport() with if (vtSema) { ... } to avoid that.
Signed-off-by: Egbert Eich <eich at freedesktop.org>
Reviewed-by: Keith Packard <keithp at keithp.com>
Signed-off-by: Keith Packard <keithp at keithp.com>
diff --git a/hw/xfree86/common/xf86RandR.c b/hw/xfree86/common/xf86RandR.c
index 5606bee..2418731 100644
--- a/hw/xfree86/common/xf86RandR.c
+++ b/hw/xfree86/common/xf86RandR.c
@@ -214,13 +214,15 @@ xf86RandRSetMode(ScreenPtr pScreen,
*/
xf86ReconfigureLayout();
- /*
- * Make sure the whole screen is visible
- */
- xf86SetViewport(pScreen, pScreen->width, pScreen->height);
- xf86SetViewport(pScreen, 0, 0);
- if (pRoot && scrp->vtSema)
- (*scrp->EnableDisableFBAccess) (scrp, TRUE);
+ if (scrp->vtSema) {
+ /*
+ * Make sure the whole screen is visible
+ */
+ xf86SetViewport (pScreen, pScreen->width, pScreen->height);
+ xf86SetViewport (pScreen, 0, 0);
+ if (pRoot)
+ (*scrp->EnableDisableFBAccess) (scrp, TRUE);
+ }
return ret;
}
commit 508e05777aba823c93a2417cc26d18c9f061ca26
Author: Egbert Eich <eich at freedesktop.org>
Date: Mon Aug 12 18:20:36 2013 +0200
DDX/Events: Distinguish between Input- and GeneralHandlers in xf86VTSwitch()
When enabling/disabling input handlers in xf86VTSwitch() we treat Input-
and GeneralHandlers equally. The result is that after a VT switch the
masks for EnabledDevices and AllSockets are equal and the distiction
between both types is lost.
Signed-off-by: Egbert Eich <eich at freedesktop.org>
Reviewed-by: Daniel Stone <daniel at fooishbar.org>
Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
Signed-off-by: Keith Packard <keithp at keithp.com>
diff --git a/hw/xfree86/common/xf86Events.c b/hw/xfree86/common/xf86Events.c
index 7a949fd..d0b1431 100644
--- a/hw/xfree86/common/xf86Events.c
+++ b/hw/xfree86/common/xf86Events.c
@@ -116,6 +116,7 @@ typedef struct x_IHRec {
InputHandlerProc ihproc;
pointer data;
Bool enabled;
+ Bool is_input;
struct x_IHRec *next;
} IHRec, *IHPtr;
@@ -446,8 +447,12 @@ xf86VTSwitch(void)
* Keep the order: Disable Device > LeaveVT
* EnterVT > EnableDevice
*/
- for (ih = InputHandlers; ih; ih = ih->next)
- xf86DisableInputHandler(ih);
+ for (ih = InputHandlers; ih; ih = ih->next) {
+ if (ih->is_input)
+ xf86DisableInputHandler(ih);
+ else
+ xf86DisableGeneralHandler(ih);
+ }
for (pInfo = xf86InputDevs; pInfo; pInfo = pInfo->next) {
if (pInfo->dev) {
if (!pInfo->dev->enabled)
@@ -496,9 +501,12 @@ xf86VTSwitch(void)
pInfo->flags &= ~XI86_DEVICE_DISABLED;
pInfo = pInfo->next;
}
- for (ih = InputHandlers; ih; ih = ih->next)
- xf86EnableInputHandler(ih);
-
+ for (ih = InputHandlers; ih; ih = ih->next) {
+ if (ih->is_input)
+ xf86EnableInputHandler(ih);
+ else
+ xf86EnableGeneralHandler(ih);
+ }
OsReleaseSIGIO();
}
@@ -558,9 +566,12 @@ xf86VTSwitch(void)
pInfo = pInfo->next;
}
- for (ih = InputHandlers; ih; ih = ih->next)
- xf86EnableInputHandler(ih);
-
+ for (ih = InputHandlers; ih; ih = ih->next) {
+ if (ih->is_input)
+ xf86EnableInputHandler(ih);
+ else
+ xf86EnableGeneralHandler(ih);
+ }
#ifdef XSERVER_PLATFORM_BUS
/* check for any new output devices */
xf86platformVTProbe();
@@ -600,8 +611,10 @@ xf86AddInputHandler(int fd, InputHandlerProc proc, pointer data)
{
IHPtr ih = addInputHandler(fd, proc, data);
- if (ih)
+ if (ih) {
AddEnabledDevice(fd);
+ ih->is_input = TRUE;
+ }
return ih;
}
commit 0cb33ce34081d7d123ec565582d7d19bdb3964ad
Author: Egbert Eich <eich at freedesktop.org>
Date: Sat Oct 5 08:02:28 2013 +0200
DDX/modes: Add a sanity check when using screen sizes from EDID
EDID sometimes lies about screen sizes. Since the screen size is used
by clients to determine the DPI a wrong ration will lead to terrible
looking fonts.
Add a sanity check for the h/v ratio cutting off at 2.4. This would
still accept the cinemascope aspect ratio as valid.
Also add message suggesting to add a quirk table entry.
Signed-off-by: Egbert Eich <eich at freedesktop.org>
Reviewed-by: Keith Packard <keithp at keithp.com>
Signed-off-by: Keith Packard <keithp at keithp.com>
diff --git a/hw/xfree86/modes/xf86Crtc.c b/hw/xfree86/modes/xf86Crtc.c
index 35845e8..2a02c85 100644
--- a/hw/xfree86/modes/xf86Crtc.c
+++ b/hw/xfree86/modes/xf86Crtc.c
@@ -3045,10 +3045,22 @@ handle_detailed_physical_size(struct detailed_monitor_section
if (det_mon->type == DT &&
det_mon->section.d_timings.h_size != 0 &&
det_mon->section.d_timings.v_size != 0) {
-
- p->output->mm_width = det_mon->section.d_timings.h_size;
- p->output->mm_height = det_mon->section.d_timings.v_size;
- p->ret = TRUE;
+ /* some sanity checking for aspect ratio:
+ assume any h / v (or v / h) > 2.4 to be bogus.
+ This would even include cinemascope */
+ if (((det_mon->section.d_timings.h_size * 5) <
+ (det_mon->section.d_timings.v_size * 12)) &&
+ ((det_mon->section.d_timings.v_size * 5) <
+ (det_mon->section.d_timings.h_size * 12))) {
+ p->output->mm_width = det_mon->section.d_timings.h_size;
+ p->output->mm_height = det_mon->section.d_timings.v_size;
+ p->ret = TRUE;
+ } else
+ xf86DrvMsg(p->output->scrn->scrnIndex, X_WARNING,
+ "Output %s: Strange aspect ratio (%i/%i), "
+ "consider adding a quirk\n", p->output->name,
+ det_mon->section.d_timings.h_size,
+ det_mon->section.d_timings.v_size);
}
}
commit 41d4beb2616ceb3f1a1b8694733e85bae70de59a
Author: Egbert Eich <eich at freedesktop.org>
Date: Wed Aug 14 11:50:26 2013 +0200
DDX/DPMS: Call dixSaveScreens() also when screen is turned on
DMPS calls dixSaveScreens() when turned off but not when turned
on. In most cases this is irrelevant as DPMS is done when a
key is hit in which case dixSaveScreens() will be called to
unblank anyhow. This isn't the case if we use xset (or the
DPMS extension directly) to unblank.
Check screenIsSaved to make sure the state needs to be changed
before calling dixSaveScreens().
Signed-off-by: Egbert Eich <eich at freedesktop.org>
Reviewed-by: Keith Packard <keithp at keithp.com>
Signed-off-by: Keith Packard <keithp at keithp.com>
diff --git a/hw/xfree86/common/xf86DPMS.c b/hw/xfree86/common/xf86DPMS.c
index 3f1e142..881cb27 100644
--- a/hw/xfree86/common/xf86DPMS.c
+++ b/hw/xfree86/common/xf86DPMS.c
@@ -36,6 +36,7 @@
#include <X11/X.h>
#include "os.h"
#include "globals.h"
+#include "windowstr.h"
#include "xf86.h"
#include "xf86Priv.h"
#ifdef DPMSExtension
@@ -159,7 +160,13 @@ DPMSSet(ClientPtr client, int level)
return Success;
if (level != DPMSModeOn) {
- rc = dixSaveScreens(client, SCREEN_SAVER_FORCER, ScreenSaverActive);
+ if (xf86IsUnblank(screenIsSaved)) {
+ rc = dixSaveScreens(client, SCREEN_SAVER_FORCER, ScreenSaverActive);
+ if (rc != Success)
+ return rc;
+ }
+ } else if (!xf86IsUnblank(screenIsSaved)) {
+ rc = dixSaveScreens(client, SCREEN_SAVER_FORCER, ScreenSaverReset);
if (rc != Success)
return rc;
}
commit 623c4147650d0404cfbea0f9b7df66dc7d928e00
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date: Mon Oct 21 17:11:56 2013 -0400
ephyr: Ensure stride of private framebuffer is multiple of 4
The fb layer of X can't deal with strides that are not a multiple of
4, so when Xephyr allocates its own framebuffer it should make sure to
align it.
This fixes crashes and rendering corruption when Xephyr runs in a
depth that is different from the host X server and its screen size is
not a multiple of 4 / depth. (This is particularly easy to trigger if
you use the -resizeable option).
Reviewed-by: Eric Anholt <eric at anholt.net>
Signed-off-by: Soren Sandmann <ssp at redhat.com>
Reviewed-by: Adam Jackson <ajax at redhat.com>
diff --git a/hw/kdrive/ephyr/hostx.c b/hw/kdrive/ephyr/hostx.c
index 6020e8d..ee9ae45 100644
--- a/hw/kdrive/ephyr/hostx.c
+++ b/hw/kdrive/ephyr/hostx.c
@@ -721,12 +721,14 @@ hostx_screen_init(KdScreenInfo *screen,
return scrpriv->ximg->data;
}
else {
- *bytes_per_line = width * (scrpriv->server_depth >> 3);
+ int bytes_per_pixel = scrpriv->server_depth >> 3;
+ int stride = (width * bytes_per_pixel + 0x3) & ~0x3;
+
+ *bytes_per_line = stride;
*bits_per_pixel = scrpriv->server_depth;
- EPHYR_DBG("server bpp %i", scrpriv->server_depth >> 3);
- scrpriv->fb_data =
- malloc(width * buffer_height * (scrpriv->server_depth >> 3));
+ EPHYR_DBG("server bpp %i", bytes_per_pixel);
+ scrpriv->fb_data = malloc (stride * buffer_height);
return scrpriv->fb_data;
}
}
@@ -765,15 +767,14 @@ hostx_paint_rect(KdScreenInfo *screen,
if (!host_depth_matches_server(scrpriv)) {
int x, y, idx, bytes_per_pixel = (scrpriv->server_depth >> 3);
+ int stride = (scrpriv->win_width * bytes_per_pixel + 0x3) & ~0x3;
unsigned char r, g, b;
unsigned long host_pixel;
EPHYR_DBG("Unmatched host depth scrpriv=%p\n", scrpriv);
for (y = sy; y < sy + height; y++)
for (x = sx; x < sx + width; x++) {
- idx =
- (scrpriv->win_width * y * bytes_per_pixel) +
- (x * bytes_per_pixel);
+ idx = y * stride + x * bytes_per_pixel;
switch (scrpriv->server_depth) {
case 16:
commit 97cf53cc2ad7ecfdd495133bad31d0ec7d939326
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date: Mon Oct 21 16:58:54 2013 -0400
ephyr: hostx_screen_init(): Fix bits_per_pixel and bytes_per_line
When the depth of the Xephyr server matches that of the host X server,
Xephyr simply uses the buffer associated with the XImage as its
framebuffer. In this case, it is correct to get the bits_per_pixel and
bytes_per_line values returned from hostx_screen_init() from the XImage.
However, when the depth doesn't match the host, Xephyr uses a private
framebuffer that is periodically copied to the XImage. In this case,
the returned values of bits_per_pixel and bytes_per_line should be
those of the private framebuffer, not those of the XImage.
Reviewed-by: Eric Anholt <eric at anholt.net>
Signed-off-by: Soren Sandmann <ssp at redhat.com>
Reviewed-by: Adam Jackson <ajax at redhat.com>
diff --git a/hw/kdrive/ephyr/hostx.c b/hw/kdrive/ephyr/hostx.c
index 5fa33b9..6020e8d 100644
--- a/hw/kdrive/ephyr/hostx.c
+++ b/hw/kdrive/ephyr/hostx.c
@@ -695,9 +695,6 @@ hostx_screen_init(KdScreenInfo *screen,
malloc(scrpriv->ximg->stride * buffer_height);
}
- *bytes_per_line = scrpriv->ximg->stride;
- *bits_per_pixel = scrpriv->ximg->bpp;
-
if (scrpriv->win_pre_existing == None && !EphyrWantResize) {
/* Ask the WM to keep our size static */
xcb_size_hints_t size_hints = {0};
@@ -717,10 +714,16 @@ hostx_screen_init(KdScreenInfo *screen,
scrpriv->win_height = height;
if (host_depth_matches_server(scrpriv)) {
+ *bytes_per_line = scrpriv->ximg->stride;
+ *bits_per_pixel = scrpriv->ximg->bpp;
+
EPHYR_DBG("Host matches server");
return scrpriv->ximg->data;
}
else {
+ *bytes_per_line = width * (scrpriv->server_depth >> 3);
+ *bits_per_pixel = scrpriv->server_depth;
+
EPHYR_DBG("server bpp %i", scrpriv->server_depth >> 3);
scrpriv->fb_data =
malloc(width * buffer_height * (scrpriv->server_depth >> 3));
commit 55246b67b755d4c1039d54971fe3f77ea60d604e
Author: Søren Sandmann Pedersen <ssp at redhat.com>
Date: Tue Oct 8 17:45:40 2013 -0400
xf86AddBusDeviceToConfigure(): Store device in DevToConfig[i].pVideo
After fc3ab84d the pVideo field in DevToConfig[i] is no longer
initialized, so it's always NULL. This causes the duplicate finding
algorithm in the beginning of the function to not work anymore as it
is based on this field.
The symptom of this bug is that X -configure reports
Number of created screens does not match number of detected devices.
Configuration failed.
Server terminated with error (2). Closing log file.
rather than producing a working config file.
This patch fixes that bug by initializing the field before calling
xf86PciConfigureNewDev().
Cc: tvignatti at gmail.com
Signed-off-by: Soren Sandmann <ssp at redhat.com>
Reviewed-by: Adam Jackson <ajax at redhat.com>
diff --git a/hw/xfree86/common/xf86Configure.c b/hw/xfree86/common/xf86Configure.c
index 6c5e359..91e8df9 100644
--- a/hw/xfree86/common/xf86Configure.c
+++ b/hw/xfree86/common/xf86Configure.c
@@ -123,12 +123,14 @@ xf86AddBusDeviceToConfigure(const char *driver, BusType bus, void *busData,
switch (bus) {
#ifdef XSERVER_LIBPCIACCESS
case BUS_PCI:
+ DevToConfig[i].pVideo = busData;
xf86PciConfigureNewDev(busData, DevToConfig[i].pVideo,
&DevToConfig[i].GDev, &chipset);
break;
#endif
#if (defined(__sparc__) || defined(__sparc)) && !defined(__OpenBSD__)
case BUS_SBUS:
+ DevToConfig[i].sVideo = busData;
xf86SbusConfigureNewDev(busData, DevToConfig[i].sVideo,
&DevToConfig[i].GDev);
break;
commit 95bf478b78e466002c382bcde7d4d62591e9215d
Merge: abf5d5a bb745f2
Author: Keith Packard <keithp at keithp.com>
Date: Thu Oct 31 18:18:19 2013 -0700
Merge remote-tracking branch 'jeremyhu/master'
commit abf5d5ac12437ebe156b4dd500c2acd69eea3654
Author: Jeremy Huddleston Sequoia <jeremyhu at apple.com>
Date: Thu Oct 31 08:57:56 2013 -0700
miext/damage: Partial revert of "Only wrap into the GC ops chain if there's a listener (v3)"
Fixes regression from: 4dc2a76740d921c824a4d8193f39dd373475f02a
http://lists.x.org/archives/xorg-devel/2013-May/036241.html
https://trac.macports.org/ticket/38993
Signed-off-by: Jeremy Huddleston Sequoia <jeremyhu at apple.com>
Reviewed-by: Adam Jackson <ajax at redhat.com>
Signed-off-by: Keith Packard <keithp at keithp.com>
diff --git a/miext/damage/damage.c b/miext/damage/damage.c
index cc02991..173fe50 100644
--- a/miext/damage/damage.c
+++ b/miext/damage/damage.c
@@ -382,10 +382,7 @@ damageValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable)
drawableDamage(pDrawable);
DAMAGE_GC_FUNC_PROLOGUE(pGC);
(*pGC->funcs->ValidateGC) (pGC, changes, pDrawable);
- if (pDamage)
- pGCPriv->ops = pGC->ops; /* so it's not NULL, so FUNC_EPILOGUE does work */
- else
- pGCPriv->ops = NULL;
+ pGCPriv->ops = pGC->ops; /* just so it's not NULL */
DAMAGE_GC_FUNC_EPILOGUE(pGC);
}
commit e4636072949a76477fe7c9d54662a0b3536b1372
Merge: 17ed7ac 5c5c1b7
Author: Keith Packard <keithp at keithp.com>
Date: Thu Oct 31 17:05:48 2013 -0700
Merge remote-tracking branch 'keithp/dri3'
commit 17ed7ac1fe7426d66f688087c09da5ff1dbb41d3
Author: Adam Jackson <ajax at redhat.com>
Date: Thu Oct 31 18:39:22 2013 -0400
glx: Lie about GLX_Y_INVERTED_EXT
Well, that was lame. The problem with reporting y inversion honestly is
that libGL asks the driver _its_ opinion of Y inversion, which it just
fabricates from whole cloth. So then when libGL goes to compare the
driver's idea of fbconfigs with that of the server - a fairly dumb idea
to begin with - nothing matches, and direct rendering fails, and
sadness.
So until the DRI drivers are fixed we should just continue to lie about
Y inversion. GLX_DONT_CARE is what libGL would make up for that
attribute if we hadn't sent it, so just send that instead.
Signed-off-by: Adam Jackson <ajax at redhat.com>
Tested-by: Keith Packard <keithp at keithp.com>
Signed-off-by: Keith Packard <keithp at keithp.com>
diff --git a/glx/glxcmds.c b/glx/glxcmds.c
index 64ebf9e..efa4aec 100644
--- a/glx/glxcmds.c
+++ b/glx/glxcmds.c
@@ -1118,7 +1118,8 @@ DoGetFBConfigs(__GLXclientState * cl, unsigned screen)
WRITE_PAIR(GLX_BIND_TO_MIPMAP_TEXTURE_EXT, modes->bindToMipmapTexture);
WRITE_PAIR(GLX_BIND_TO_TEXTURE_TARGETS_EXT,
modes->bindToTextureTargets);
- WRITE_PAIR(GLX_Y_INVERTED_EXT, modes->yInverted);
+ /* can't report honestly until mesa is fixed */
+ WRITE_PAIR(GLX_Y_INVERTED_EXT, GLX_DONT_CARE);
if (modes->drawableType & GLX_PBUFFER_BIT) {
WRITE_PAIR(GLX_MAX_PBUFFER_WIDTH, modes->maxPbufferWidth);
WRITE_PAIR(GLX_MAX_PBUFFER_HEIGHT, modes->maxPbufferHeight);
commit 5c5c1b77982a9af7279a90bc3c2be48adaa9c778
Author: Keith Packard <keithp at keithp.com>
Date: Thu Jul 11 16:11:57 2013 -0700
present: Add Present extension
Provides both a software implementation using timers and driver hooks
to base everything on vblank intervals.
Signed-off-by: Keith Packard <keithp at keithp.com>
Reviewed-by: Adam Jackson <ajax at redhat.com>
diff --git a/Makefile.am b/Makefile.am
index 7a8fc5b..28266c5 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -21,6 +21,10 @@ if DRI3
DRI3_DIR=dri3
endif
+if PRESENT
+PRESENT_DIR=present
+endif
+
SUBDIRS = \
doc \
man \
@@ -42,6 +46,7 @@ SUBDIRS = \
damageext \
$(COMPOSITE_DIR) \
$(GLX_DIR) \
+ $(PRESENT_DIR) \
$(DRI3_DIR) \
exa \
config \
diff --git a/configure.ac b/configure.ac
index 546790d..7432912 100644
--- a/configure.ac
+++ b/configure.ac
@@ -614,6 +614,7 @@ AC_ARG_ENABLE(glx, AS_HELP_STRING([--disable-glx], [Build GLX extensi
AC_ARG_ENABLE(dri, AS_HELP_STRING([--enable-dri], [Build DRI extension (default: auto)]), [DRI=$enableval])
AC_ARG_ENABLE(dri2, AS_HELP_STRING([--enable-dri2], [Build DRI2 extension (default: auto)]), [DRI2=$enableval], [DRI2=auto])
AC_ARG_ENABLE(dri3, AS_HELP_STRING([--enable-dri3], [Build DRI3 extension (default: auto)]), [DRI3=$enableval], [DRI3=auto])
+AC_ARG_ENABLE(present, AS_HELP_STRING([--disable-present], [Build Present extension (default: enabled)]), [PRESENT=$enableval], [PRESENT=yes])
AC_ARG_ENABLE(xinerama, AS_HELP_STRING([--disable-xinerama], [Build Xinerama extension (default: enabled)]), [XINERAMA=$enableval], [XINERAMA=yes])
AC_ARG_ENABLE(xf86vidmode, AS_HELP_STRING([--disable-xf86vidmode], [Build XF86VidMode extension (default: auto)]), [XF86VIDMODE=$enableval], [XF86VIDMODE=auto])
AC_ARG_ENABLE(xace, AS_HELP_STRING([--disable-xace], [Build X-ACE extension (default: enabled)]), [XACE=$enableval], [XACE=yes])
@@ -807,6 +808,7 @@ DAMAGEPROTO="damageproto >= 1.1"
XCMISCPROTO="xcmiscproto >= 1.2.0"
BIGREQSPROTO="bigreqsproto >= 1.1.0"
XTRANS="xtrans >= 1.2.2"
+PRESENTPROTO="presentproto >= 1.0"
dnl List of libraries that require a specific version
LIBAPPLEWM="applewm >= 1.4"
@@ -1160,6 +1162,14 @@ if test "x$DRI2" = xyes; then
fi
AM_CONDITIONAL(DRI2_AIGLX, test "x$DRI2_AIGLX" = xyes)
+AM_CONDITIONAL(PRESENT, [test "x$PRESENT" = xyes])
+if test "x$PRESENT" = xyes; then
+ AC_DEFINE(PRESENT, 1, [Support Present extension])
+ REQUIRED_MODULES="$REQUIRED_MODULES $PRESENTPROTO"
+ SDK_REQUIRED_MODULES="$SDK_REQUIRED_MODULES $PRESENTPROTO"
+ PRESENT_INC='-I$(top_srcdir)/present'
+ PRESENT_LIB='$(top_builddir)/present/libpresent.la'
+fi
AM_CONDITIONAL(XINERAMA, [test "x$XINERAMA" = xyes])
if test "x$XINERAMA" = xyes; then
@@ -1584,7 +1594,7 @@ AC_EGREP_CPP([I_AM_SVR4],[
AC_DEFINE([SVR4],1,[Define to 1 on systems derived from System V Release 4])
AC_MSG_RESULT([yes])], AC_MSG_RESULT([no]))
-XSERVER_CFLAGS="$XSERVER_CFLAGS $CORE_INCS $XEXT_INC $COMPOSITE_INC $DAMAGE_INC $FIXES_INC $XI_INC $MI_INC $MIEXT_SYNC_INC $MIEXT_SHADOW_INC $MIEXT_LAYER_INC $MIEXT_DAMAGE_INC $RENDER_INC $RANDR_INC $FB_INC $DBE_INC"
+XSERVER_CFLAGS="$XSERVER_CFLAGS $CORE_INCS $XEXT_INC $COMPOSITE_INC $DAMAGE_INC $FIXES_INC $XI_INC $MI_INC $MIEXT_SYNC_INC $MIEXT_SHADOW_INC $MIEXT_LAYER_INC $MIEXT_DAMAGE_INC $RENDER_INC $RANDR_INC $FB_INC $DBE_INC $PRESENT_INC"
dnl ---------------------------------------------------------------------------
dnl DDX section.
@@ -1597,7 +1607,7 @@ AC_MSG_RESULT([$XVFB])
AM_CONDITIONAL(XVFB, [test "x$XVFB" = xyes])
if test "x$XVFB" = xyes; then
- XVFB_LIBS="$FB_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $DRI3_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB"
+ XVFB_LIBS="$FB_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $DRI3_LIB $PRESENT_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB"
XVFB_SYS_LIBS="$XVFBMODULES_LIBS $GLX_SYS_LIBS"
AC_SUBST([XVFB_LIBS])
AC_SUBST([XVFB_SYS_LIBS])
@@ -1618,7 +1628,7 @@ if test "x$XNEST" = xyes; then
if test "x$have_xnest" = xno; then
AC_MSG_ERROR([Xnest build explicitly requested, but required modules not found.])
fi
- XNEST_LIBS="$FB_LIB $FIXES_LIB $MI_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $DRI3_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $MAIN_LIB $DIX_LIB $OS_LIB"
+ XNEST_LIBS="$FB_LIB $FIXES_LIB $MI_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $DRI3_LIB $PRESENT_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $MAIN_LIB $DIX_LIB $OS_LIB"
XNEST_SYS_LIBS="$XNESTMODULES_LIBS $GLX_SYS_LIBS"
AC_SUBST([XNEST_LIBS])
AC_SUBST([XNEST_SYS_LIBS])
@@ -1643,7 +1653,7 @@ if test "x$XORG" = xyes; then
XORG_OSINCS='-I$(top_srcdir)/hw/xfree86/os-support -I$(top_srcdir)/hw/xfree86/os-support/bus -I$(top_srcdir)/os'
XORG_INCS="$XORG_DDXINCS $XORG_OSINCS"
XORG_CFLAGS="$XORGSERVER_CFLAGS -DHAVE_XORG_CONFIG_H"
- XORG_LIBS="$COMPOSITE_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $DRI3_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $XI_LIB $XKB_LIB"
+ XORG_LIBS="$COMPOSITE_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $DRI3_LIB $PRESENT_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $XI_LIB $XKB_LIB"
dnl ==================================================================
dnl symbol visibility
@@ -2056,7 +2066,7 @@ if test "x$DMX" = xyes; then
fi
DMX_INCLUDES="$XEXT_INC $RENDER_INC $RECORD_INC"
XDMX_CFLAGS="$DMXMODULES_CFLAGS"
- XDMX_LIBS="$FB_LIB $MI_LIB $XEXT_LIB $RENDER_LIB $RECORD_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $DRI3_LIB $MIEXT_SYNC_LIB $MIEXT_SHADOW_LIB $MIEXT_DAMAGE_LIB $COMPOSITE_LIB $DAMAGE_LIB $MAIN_LIB $DIX_LIB $CONFIG_LIB $OS_LIB $FIXES_LIB"
+ XDMX_LIBS="$FB_LIB $MI_LIB $XEXT_LIB $RENDER_LIB $RECORD_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $DRI3_LIB $PRESENT_LIB $MIEXT_SYNC_LIB $MIEXT_SHADOW_LIB $MIEXT_DAMAGE_LIB $COMPOSITE_LIB $DAMAGE_LIB $MAIN_LIB $DIX_LIB $CONFIG_LIB $OS_LIB $FIXES_LIB"
XDMX_SYS_LIBS="$DMXMODULES_LIBS"
AC_SUBST([XDMX_CFLAGS])
AC_SUBST([XDMX_LIBS])
@@ -2165,7 +2175,7 @@ if test "$KDRIVE" = yes; then
KDRIVE_CFLAGS="$XSERVER_CFLAGS -DHAVE_KDRIVE_CONFIG_H $TSLIB_CFLAGS"
- KDRIVE_PURE_LIBS="$FB_LIB $MI_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $DRI3_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $OS_LIB"
+ KDRIVE_PURE_LIBS="$FB_LIB $MI_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $DRI3_LIB $PRESENT_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $OS_LIB"
KDRIVE_LIB='$(top_builddir)/hw/kdrive/src/libkdrive.la'
case $host_os in
*linux*)
@@ -2288,6 +2298,7 @@ Xi/Makefile
xfixes/Makefile
exa/Makefile
dri3/Makefile
+present/Makefile
hw/Makefile
hw/xfree86/Makefile
hw/xfree86/common/Makefile
diff --git a/hw/dmx/dmxextension.c b/hw/dmx/dmxextension.c
index d7296ae..c6c6a8e 100644
--- a/hw/dmx/dmxextension.c
+++ b/hw/dmx/dmxextension.c
@@ -68,6 +68,9 @@
* _any_ header files. */
extern FontPtr defaultFont;
+/* Hack to get Present to build (present requires RandR) */
+RESTYPE RRCrtcType;
+
/** This routine provides information to the DMX protocol extension
* about a particular screen. */
Bool
diff --git a/include/dix-config.h.in b/include/dix-config.h.in
index d96da6a..397ee96 100644
--- a/include/dix-config.h.in
+++ b/include/dix-config.h.in
@@ -255,6 +255,9 @@
/* Internal define for Xinerama */
#undef PANORAMIX
+/* Support Present extension */
+#undef PRESENT
+
/* Overall prefix */
#undef PROJECTROOT
diff --git a/include/extinit.h b/include/extinit.h
index bdb149c..fa5f293 100644
--- a/include/extinit.h
+++ b/include/extinit.h
@@ -181,4 +181,9 @@ extern void XvMCExtensionInit(void);
extern void dri3_extension_init(void);
#endif
+#if defined(PRESENT)
+#include <X11/extensions/presentproto.h>
+#include "presentext.h"
+#endif
+
#endif
diff --git a/include/xorg-server.h.in b/include/xorg-server.h.in
index 5b3b664..1281b3e 100644
--- a/include/xorg-server.h.in
+++ b/include/xorg-server.h.in
@@ -70,6 +70,9 @@
/* Internal define for Xinerama */
#undef PANORAMIX
+/* Support Present extension */
+#undef PRESENT
+
/* Support RANDR extension */
#undef RANDR
diff --git a/mi/miinitext.c b/mi/miinitext.c
index e49948b..6366182 100644
--- a/mi/miinitext.c
+++ b/mi/miinitext.c
@@ -287,7 +287,10 @@ static ExtensionModule staticExtensions[] = {
#ifdef DPMSExtension
{DPMSExtensionInit, DPMSExtensionName, &noDPMSExtension},
#endif
+ {present_extension_init, PRESENT_NAME, NULL},
+#ifdef DRI3
{dri3_extension_init, DRI3_NAME, NULL},
+#endif
#ifdef RES
{ResExtensionInit, XRES_NAME, &noResExtension},
#endif
diff --git a/present/Makefile.am b/present/Makefile.am
new file mode 100644
index 0000000..7fea669
--- /dev/null
+++ b/present/Makefile.am
@@ -0,0 +1,17 @@
+noinst_LTLIBRARIES = libpresent.la
+AM_CFLAGS = \
+ -DHAVE_XORG_CONFIG_H \
+ @DIX_CFLAGS@ @XORG_CFLAGS@
+
+libpresent_la_SOURCES = \
+ present.h \
+ present.c \
+ present_event.c \
+ present_fake.c \
+ present_fence.c \
+ present_notify.c \
+ present_priv.h \
+ present_request.c \
+ present_screen.c
+
+sdk_HEADERS = present.h presentext.h
diff --git a/present/present.c b/present/present.c
new file mode 100644
index 0000000..4c97ce4
--- /dev/null
+++ b/present/present.c
@@ -0,0 +1,775 @@
+/*
+ * Copyright © 2013 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#endif
+
+#include "present_priv.h"
+#include <gcstruct.h>
+#include <misync.h>
+#include <misyncstr.h>
+#ifdef MONOTONIC_CLOCK
+#include <time.h>
+#endif
+
+static uint64_t present_event_id;
+static struct xorg_list present_exec_queue;
+static struct xorg_list present_flip_queue;
+
+#if 0
+#define DebugPresent(x) ErrorF x
+#else
+#define DebugPresent(x)
+#endif
+
+/*
+ * Copies the update region from a pixmap to the target drawable
+ */
+static void
+present_copy_region(DrawablePtr drawable,
+ PixmapPtr pixmap,
+ RegionPtr update,
+ int16_t x_off,
+ int16_t y_off)
+{
+ ScreenPtr screen = drawable->pScreen;
+ GCPtr gc;
+
+ gc = GetScratchGC(drawable->depth, screen);
+ if (update) {
+ ChangeGCVal changes[2];
+
+ changes[0].val = x_off;
+ changes[1].val = y_off;
+ ChangeGC(serverClient, gc,
+ GCClipXOrigin|GCClipYOrigin,
+ changes);
+ (*gc->funcs->ChangeClip)(gc, CT_REGION, update, 0);
+ }
+ ValidateGC(drawable, gc);
+ (*gc->ops->CopyArea)(&pixmap->drawable,
+ drawable,
+ gc,
+ 0, 0,
+ pixmap->drawable.width, pixmap->drawable.height,
+ x_off, y_off);
+ if (update)
+ (*gc->funcs->ChangeClip)(gc, CT_NONE, NULL, 0);
+ FreeScratchGC(gc);
+}
+
+static Bool
+present_check_flip(RRCrtcPtr crtc,
+ WindowPtr window,
+ PixmapPtr pixmap,
+ Bool sync_flip,
+ RegionPtr valid,
+ int16_t x_off,
+ int16_t y_off)
+{
+ ScreenPtr screen = window->drawable.pScreen;
+ WindowPtr root = screen->root;
+ present_screen_priv_ptr screen_priv = present_screen_priv(screen);
+
+ if (!screen_priv)
+ return FALSE;
+
+ if (!screen_priv->info)
+ return FALSE;
+
+ if (!crtc)
+ return FALSE;
+
+ /* Check to see if the driver supports flips at all */
+ if (!screen_priv->info->flip)
+ return FALSE;
+
+ /* Can't pend a flip while unflipping */
+ if (screen_priv->unflip_event_id) {
+ return FALSE;
+ }
+
+ /* Can't have two pending flips at the same time */
+ if (screen_priv->flip_pending) {
+ return FALSE;
+ }
+
+ /* Make sure the window hasn't been redirected with Composite */
+ if (screen->GetWindowPixmap(window) != screen->GetScreenPixmap(screen))
+ return FALSE;
+
+ /* Check for full-screen window */
+ if (!RegionEqual(&window->clipList, &root->winSize)) {
+ return FALSE;
+ }
+
+ /* Source pixmap must align with window exactly */
+ if (x_off || y_off) {
+ return FALSE;
+ }
+
+ /* Make sure the area marked as valid fills the screen */
+ if (valid && !RegionEqual(valid, &root->winSize)) {
+ return FALSE;
+ }
+
+ /* Does the window match the pixmap exactly? */
+ if (window->drawable.x != 0 || window->drawable.y != 0 ||
+#ifdef COMPOSITE
+ window->drawable.x != pixmap->screen_x || window->drawable.y != pixmap->screen_y ||
+#endif
+ window->drawable.width != pixmap->drawable.width ||
+ window->drawable.height != pixmap->drawable.height) {
+ return FALSE;
+ }
+
+ /* Ask the driver for permission */
+ if (screen_priv->info->check_flip) {
+ if (!(*screen_priv->info->check_flip) (crtc, window, pixmap, sync_flip)) {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+static Bool
+present_flip(RRCrtcPtr crtc,
+ uint64_t event_id,
+ uint64_t target_msc,
+ PixmapPtr pixmap,
+ Bool sync_flip)
+{
+ ScreenPtr screen = crtc->pScreen;
+ present_screen_priv_ptr screen_priv = present_screen_priv(screen);
+
+ return (*screen_priv->info->flip) (crtc, event_id, target_msc, pixmap, sync_flip);
+}
+
+static void
+present_vblank_notify(present_vblank_ptr vblank, CARD8 kind, CARD8 mode, uint64_t ust, uint64_t crtc_msc)
+{
+ int n;
+
+ present_send_complete_notify(vblank->window, kind, mode, vblank->serial, ust, crtc_msc - vblank->msc_offset);
+ for (n = 0; n < vblank->num_notifies; n++) {
+ WindowPtr window = vblank->notifies[n].window;
+ CARD32 serial = vblank->notifies[n].serial;
+
+ if (window)
+ present_send_complete_notify(window, kind, mode, serial, ust, crtc_msc - vblank->msc_offset);
+ }
+}
+
+static void
+present_pixmap_idle(PixmapPtr pixmap, WindowPtr window, CARD32 serial, struct present_fence *present_fence)
+{
+ present_fence_set_triggered(present_fence);
+ present_send_idle_notify(window, serial, pixmap, present_fence);
+}
+
+RRCrtcPtr
+present_get_crtc(WindowPtr window)
+{
+ ScreenPtr screen = window->drawable.pScreen;
+ present_screen_priv_ptr screen_priv = present_screen_priv(screen);
+
+ if (!screen_priv)
+ return NULL;
+
+ if (!screen_priv->info)
+ return NULL;
+
+ return (*screen_priv->info->get_crtc)(window);
+}
+
+uint32_t
+present_query_capabilities(RRCrtcPtr crtc)
+{
+ present_screen_priv_ptr screen_priv;
+
+ if (!crtc)
+ return 0;
+
+ screen_priv = present_screen_priv(crtc->pScreen);
+
+ if (!screen_priv)
+ return 0;
+
+ if (!screen_priv->info)
+ return 0;
+
+ return screen_priv->info->capabilities;
+}
+
+static int
+present_get_ust_msc(WindowPtr window, RRCrtcPtr crtc, uint64_t *ust, uint64_t *msc)
+{
+ ScreenPtr screen = window->drawable.pScreen;
+ present_screen_priv_ptr screen_priv = present_screen_priv(screen);
+
+ if (crtc == NULL)
+ return present_fake_get_ust_msc(screen, ust, msc);
+ else
+ return (*screen_priv->info->get_ust_msc)(crtc, ust, msc);
+}
+
+static void
+present_flush(WindowPtr window)
+{
+ ScreenPtr screen = window->drawable.pScreen;
+ present_screen_priv_ptr screen_priv = present_screen_priv(screen);
+
+ if (!screen_priv)
+ return;
+
+ if (!screen_priv->info)
+ return;
+
+ (*screen_priv->info->flush) (window);
+}
+
+static int
+present_queue_vblank(ScreenPtr screen,
+ RRCrtcPtr crtc,
+ uint64_t event_id,
+ uint64_t msc)
+{
+ Bool ret;
+
+ if (crtc == NULL)
+ ret = present_fake_queue_vblank(screen, event_id, msc);
+ else
+ {
+ present_screen_priv_ptr screen_priv = present_screen_priv(screen);
+ ret = (*screen_priv->info->queue_vblank) (crtc, event_id, msc);
+ }
+ return ret;
+}
+
+static uint64_t
+present_window_to_crtc_msc(WindowPtr window, RRCrtcPtr crtc, uint64_t window_msc, uint64_t new_msc)
+{
+ present_window_priv_ptr window_priv = present_get_window_priv(window, TRUE);
+
+ if (crtc != window_priv->crtc) {
+ uint64_t old_ust, old_msc;
+
+ /* The old CRTC may have been turned off, in which case
+ * we'll just use whatever previous MSC we'd seen from this CRTC
+ */
+
+ if (present_get_ust_msc(window, window_priv->crtc, &old_ust, &old_msc) != Success)
+ old_msc = window_priv->msc;
+
+ window_priv->msc_offset += new_msc - old_msc;
+ window_priv->crtc = crtc;
+ }
+
+ return window_msc + window_priv->msc_offset;
+}
+
+static void
+present_flip_idle(ScreenPtr screen)
+{
+ present_screen_priv_ptr screen_priv = present_screen_priv(screen);
+
+ if (screen_priv->flip_pixmap) {
+ present_pixmap_idle(screen_priv->flip_pixmap, screen_priv->flip_window,
+ screen_priv->flip_serial, screen_priv->flip_idle_fence);
+ present_fence_destroy(screen_priv->flip_idle_fence);
+ dixDestroyPixmap(screen_priv->flip_pixmap, screen_priv->flip_pixmap->drawable.id);
+ screen_priv->flip_crtc = NULL;
+ screen_priv->flip_window = NULL;
+ screen_priv->flip_serial = 0;
+ screen_priv->flip_pixmap = NULL;
+ screen_priv->flip_idle_fence = NULL;
+ }
+}
+
+static void
+present_unflip(ScreenPtr screen)
+{
+ present_screen_priv_ptr screen_priv = present_screen_priv(screen);
+
+ assert (!screen_priv->unflip_event_id);
+ assert (!screen_priv->flip_pending);
+
+ /* Update the screen pixmap with the current flip pixmap contents
+ */
+ if (screen_priv->flip_pixmap) {
+ present_copy_region(&screen->GetScreenPixmap(screen)->drawable,
+ screen_priv->flip_pixmap,
+ NULL, 0, 0);
+ }
+ screen_priv->unflip_event_id = ++present_event_id;
+ DebugPresent(("u %lld\n", screen_priv->unflip_event_id));
+ (*screen_priv->info->unflip) (screen, screen_priv->unflip_event_id);
+}
+
+static void
+present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc);
+
+static void
+present_flip_notify(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc)
+{
+ WindowPtr window = vblank->window;
+ ScreenPtr screen = window->drawable.pScreen;
+ present_screen_priv_ptr screen_priv = present_screen_priv(screen);
+
+ DebugPresent(("\tn %p %8lld: %08lx -> %08lx\n", vblank, vblank->target_msc,
+ vblank->pixmap ? vblank->pixmap->drawable.id : 0,
+ vblank->window->drawable.id));
+
+ assert (vblank == screen_priv->flip_pending);
+
+ present_flip_idle(screen);
+
+ /* Transfer reference for pixmap and fence from vblank to screen_priv */
+ screen_priv->flip_crtc = vblank->crtc;
+ screen_priv->flip_window = vblank->window;
+ screen_priv->flip_serial = vblank->serial;
+ screen_priv->flip_pixmap = vblank->pixmap;
+ screen_priv->flip_idle_fence = vblank->idle_fence;
+
+ vblank->pixmap = NULL;
+ vblank->idle_fence = NULL;
+
+ screen_priv->flip_pending = NULL;
+
+ if (vblank->abort_flip)
+ present_unflip(screen);
+
+ if (!vblank->window_destroyed)
+ present_vblank_notify(vblank, PresentCompleteKindPixmap, PresentCompleteModeFlip, ust, crtc_msc);
+ present_vblank_destroy(vblank);
+}
+
+void
+present_event_notify(uint64_t event_id, uint64_t ust, uint64_t msc)
+{
+ present_vblank_ptr vblank, tmp;
+ int s;
+
+ xorg_list_for_each_entry_safe(vblank, tmp, &present_exec_queue, event_queue) {
+ if (vblank->event_id == event_id) {
+ xorg_list_del(&vblank->event_queue);
+ present_execute(vblank, ust, msc);
+ return;
+ }
+ }
+ xorg_list_for_each_entry_safe(vblank, tmp, &present_flip_queue, event_queue) {
+ if (vblank->event_id == event_id) {
+ xorg_list_del(&vblank->event_queue);
+ present_flip_notify(vblank, ust, msc);
+ return;
+ }
+ }
+
+ for (s = 0; s < screenInfo.numScreens; s++) {
+ ScreenPtr screen = screenInfo.screens[s];
+ present_screen_priv_ptr screen_priv = present_screen_priv(screen);
+
+ if (event_id == screen_priv->unflip_event_id) {
+ DebugPresent(("\tun %lld\n", event_id));
+ screen_priv->unflip_event_id = 0;
+ present_flip_idle(screen);
+ }
+ }
+}
+
+/*
+ * 'window' is being reconfigured. Check to see if it is involved
+ * in flipping and clean up as necessary
+ */
+void
+present_check_flip_window (WindowPtr window)
+{
+ ScreenPtr screen = window->drawable.pScreen;
+ present_screen_priv_ptr screen_priv = present_screen_priv(screen);
+ present_window_priv_ptr window_priv = present_window_priv(window);
+ present_vblank_ptr flip_pending = screen_priv->flip_pending;
+ present_vblank_ptr vblank;
+
+ /* If this window hasn't ever been used with Present, it can't be
+ * flipping
+ */
+ if (!window_priv)
+ return;
+
+ if (screen_priv->unflip_event_id)
+ return;
+
+ if (flip_pending) {
+ /*
+ * Check pending flip
+ */
+ if (flip_pending->window == window) {
+ if (!present_check_flip(flip_pending->crtc, window, flip_pending->pixmap,
+ flip_pending->sync_flip, NULL, 0, 0))
+ flip_pending->abort_flip = TRUE;
+ }
+ } else {
+ /*
+ * Check current flip
+ */
+ if (window == screen_priv->flip_window) {
+ if (!present_check_flip(screen_priv->flip_crtc, window, screen_priv->flip_pixmap, FALSE, NULL, 0, 0))
+ present_unflip(screen);
+ }
+ }
+
+ /* Now check any queued vblanks */
+ xorg_list_for_each_entry(vblank, &window_priv->vblank, window_list) {
+ if (vblank->flip && !present_check_flip(vblank->crtc, window, vblank->pixmap, FALSE, NULL, 0, 0))
+ vblank->flip = FALSE;
+ }
+}
+
+/*
+ * Once the required MSC has been reached, execute the pending request.
+ *
+ * For requests to actually present something, either blt contents to
+ * the screen or queue a frame buffer swap.
+ *
+ * For requests to just get the current MSC/UST combo, skip that part and
+ * go straight to event delivery
+ */
+
+static void
+present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc)
+{
+ WindowPtr window = vblank->window;
+ present_screen_priv_ptr screen_priv = present_screen_priv(window->drawable.pScreen);
+
+ if (vblank->wait_fence) {
+ /* XXX check fence, queue if not ready */
+ }
+
+ xorg_list_del(&vblank->event_queue);
+ if (vblank->pixmap) {
+
+ if (vblank->flip && screen_priv->flip_pending == NULL && !screen_priv->unflip_event_id) {
+
+ DebugPresent(("\tf %p %8lld: %08lx -> %08lx\n", vblank, crtc_msc, vblank->pixmap->drawable.id, vblank->window->drawable.id));
+ /* Prepare to flip by removing from the window/screen lists
+ * and sticking it into the flip_pending field
+ */
+ screen_priv->flip_pending = vblank;
+ xorg_list_del(&vblank->window_list);
+
+ xorg_list_add(&vblank->event_queue, &present_flip_queue);
+ /* Try to flip
+ */
+ if (present_flip(vblank->crtc, vblank->event_id, vblank->target_msc, vblank->pixmap, vblank->sync_flip))
+ return;
+
+ xorg_list_del(&vblank->event_queue);
+ /* Oops, flip failed. Clear the flip_pending field
+ */
+ screen_priv->flip_pending = NULL;
+ vblank->flip = FALSE;
+ }
+ DebugPresent(("\tc %p %8lld: %08lx -> %08lx\n", vblank, crtc_msc, vblank->pixmap->drawable.id, vblank->window->drawable.id));
+ if (screen_priv->flip_pending) {
+
+ /* Check pending flip
+ */
+ if (window == screen_priv->flip_pending->window)
+ screen_priv->flip_pending->abort_flip = TRUE;
+ } else if (!screen_priv->unflip_event_id) {
+
+ /* Check current flip
+ */
+ if (window == screen_priv->flip_window)
+ present_unflip(window->drawable.pScreen);
+ }
+ present_copy_region(&window->drawable, vblank->pixmap, vblank->update, vblank->x_off, vblank->y_off);
+
+ /* present_copy_region sticks the region into a scratch GC,
+ * which is then freed, freeing the region
+ */
+ vblank->update = NULL;
+ present_flush(window);
+
+ present_pixmap_idle(vblank->pixmap, vblank->window, vblank->serial, vblank->idle_fence);
+ }
+ present_vblank_notify(vblank, vblank->kind, PresentCompleteModeCopy, ust, crtc_msc);
+ present_vblank_destroy(vblank);
+}
+
+int
+present_pixmap(WindowPtr window,
+ PixmapPtr pixmap,
+ CARD32 serial,
+ RegionPtr valid,
+ RegionPtr update,
+ int16_t x_off,
+ int16_t y_off,
+ RRCrtcPtr target_crtc,
+ SyncFence *wait_fence,
+ SyncFence *idle_fence,
+ uint32_t options,
+ uint64_t window_msc,
+ uint64_t divisor,
+ uint64_t remainder,
+ present_notify_ptr notifies,
+ int num_notifies)
+{
+ uint64_t ust;
+ uint64_t target_msc;
+ uint64_t crtc_msc;
+ int ret;
+ present_vblank_ptr vblank;
+ ScreenPtr screen = window->drawable.pScreen;
+ present_window_priv_ptr window_priv = present_get_window_priv(window, TRUE);
+ present_screen_priv_ptr screen_priv = present_screen_priv(screen);
+
+ if (!window_priv)
+ return BadAlloc;
+
+ if (!target_crtc) {
+ /* Update the CRTC if we have a pixmap or we don't have a CRTC
+ */
+ if (!pixmap)
+ target_crtc = window_priv->crtc;
+
+ if (!target_crtc)
+ target_crtc = present_get_crtc(window);
+ }
+
+ present_get_ust_msc(window, target_crtc, &ust, &crtc_msc);
+
+ target_msc = present_window_to_crtc_msc(window, target_crtc, window_msc, crtc_msc);
+
+ /* Stash the current MSC away in case we need it later
+ */
+ window_priv->msc = crtc_msc;
+
+ /* Adjust target_msc to match modulus
+ */
+ if (crtc_msc >= target_msc) {
+ if (divisor != 0) {
+ target_msc = crtc_msc - (crtc_msc % divisor) + remainder;
+ if (target_msc <= crtc_msc)
+ target_msc += divisor;
+ } else
+ target_msc = crtc_msc;
+ }
+
+ /*
+ * Look for a matching presentation already on the list and
+ * don't bother doing the previous one if this one will overwrite it
+ * in the same frame
+ */
+
+ if (!update) {
+ xorg_list_for_each_entry(vblank, &window_priv->vblank, window_list) {
+
+ if (!vblank->pixmap)
+ continue;
+
+ if (vblank->crtc != target_crtc || vblank->target_msc != target_msc)
+ continue;
+
+ present_pixmap_idle(vblank->pixmap, vblank->window, vblank->serial, vblank->idle_fence);
+ present_fence_destroy(vblank->idle_fence);
+ dixDestroyPixmap(vblank->pixmap, vblank->pixmap->drawable.id);
+
+ vblank->pixmap = NULL;
+ vblank->idle_fence = NULL;
+ }
+ }
+
+ vblank = calloc (1, sizeof (present_vblank_rec));
+ if (!vblank)
+ return BadAlloc;
+
+ xorg_list_append(&vblank->window_list, &window_priv->vblank);
+ xorg_list_init(&vblank->event_queue);
+
+ vblank->screen = screen;
+ vblank->window = window;
+ vblank->pixmap = pixmap;
+ vblank->event_id = ++present_event_id;
+ if (pixmap) {
+ vblank->kind = PresentCompleteKindPixmap;
+ pixmap->refcnt++;
+ } else
+ vblank->kind = PresentCompleteKindNotifyMSC;
+
+ vblank->serial = serial;
+
+ if (valid) {
+ vblank->valid = RegionDuplicate(valid);
+ if (!vblank->valid)
+ goto no_mem;
+ }
+ if (update) {
+ vblank->update = RegionDuplicate(update);
+ if (!vblank->update)
+ goto no_mem;
+ }
+
+ vblank->x_off = x_off;
+ vblank->y_off = y_off;
+ vblank->target_msc = target_msc;
+ vblank->crtc = target_crtc;
+ vblank->msc_offset = window_priv->msc_offset;
+ vblank->notifies = notifies;
+ vblank->num_notifies = num_notifies;
+
+ if (!screen_priv->info || !(screen_priv->info->capabilities & PresentCapabilityAsync))
+ vblank->sync_flip = TRUE;
+
+ if (pixmap && present_check_flip (target_crtc, window, pixmap, vblank->sync_flip, valid, x_off, y_off)) {
+ vblank->flip = TRUE;
+ if (vblank->sync_flip)
+ target_msc--;
+ }
+
+ if (idle_fence) {
+ vblank->idle_fence = present_fence_create(idle_fence);
+ if (!vblank->idle_fence)
+ goto no_mem;
+ }
+
+ if (pixmap)
+ DebugPresent(("q %p %8lld: %08lx -> %08lx (crtc %d)\n",
+ vblank, target_msc, vblank->pixmap->drawable.id, vblank->window->drawable.id, target_crtc ? 1 : 0));
+
+ xorg_list_add(&vblank->event_queue, &present_exec_queue);
+ if (target_msc >= crtc_msc) {
+ ret = present_queue_vblank(screen, target_crtc, vblank->event_id, target_msc);
+ if (ret != Success) {
+ xorg_list_del(&vblank->event_queue);
+ goto failure;
+ }
+ } else
+ present_execute(vblank, ust, crtc_msc);
+
+ return Success;
+
+no_mem:
+ ret = BadAlloc;
+failure:
+ vblank->notifies = NULL;
+ present_vblank_destroy(vblank);
+ return ret;
+}
+
+void
+present_abort_vblank(ScreenPtr screen, RRCrtcPtr crtc, uint64_t event_id, uint64_t msc)
+{
+ present_vblank_ptr vblank, tmp;
+
+ if (crtc == NULL)
+ present_fake_abort_vblank(screen, event_id, msc);
+ else
+ {
+ present_screen_priv_ptr screen_priv = present_screen_priv(screen);
+
+ (*screen_priv->info->abort_vblank) (crtc, event_id, msc);
+ }
+
+ xorg_list_for_each_entry_safe(vblank, tmp, &present_exec_queue, event_queue) {
+ if (vblank->event_id == event_id) {
+ xorg_list_del(&vblank->event_queue);
+ return;
+ }
+ }
+ xorg_list_for_each_entry_safe(vblank, tmp, &present_flip_queue, event_queue) {
+ if (vblank->event_id == event_id) {
+ xorg_list_del(&vblank->event_queue);
+ return;
+ }
+ }
+}
+
+int
+present_notify_msc(WindowPtr window,
+ CARD32 serial,
+ uint64_t target_msc,
+ uint64_t divisor,
+ uint64_t remainder)
+{
+ return present_pixmap(window,
+ NULL,
+ serial,
+ NULL, NULL,
+ 0, 0,
+ NULL,
+ NULL, NULL,
+ 0,
+ target_msc, divisor, remainder, NULL, 0);
+}
+
+void
+present_flip_destroy(ScreenPtr screen)
+{
+ present_screen_priv_ptr screen_priv = present_screen_priv(screen);
+
+ /* XXX this needs to be synchronous for server reset */
+
+ /* Do the actual cleanup once the flip has been performed by the hardware */
+ if (screen_priv->flip_pending)
+ screen_priv->flip_pending->abort_flip = TRUE;
+}
+
+void
+present_vblank_destroy(present_vblank_ptr vblank)
+{
+ /* Remove vblank from window and screen lists */
+ xorg_list_del(&vblank->window_list);
+
+ DebugPresent(("\td %p %8lld: %08lx -> %08lx\n", vblank, vblank->target_msc,
+ vblank->pixmap ? vblank->pixmap->drawable.id : 0,
+ vblank->window->drawable.id));
+
+ /* Drop pixmap reference */
+ if (vblank->pixmap)
+ dixDestroyPixmap(vblank->pixmap, vblank->pixmap->drawable.id);
+
+ /* Free regions */
+ if (vblank->valid)
+ RegionDestroy(vblank->valid);
+ if (vblank->update)
+ RegionDestroy(vblank->update);
+
+ if (vblank->idle_fence)
+ present_fence_destroy(vblank->idle_fence);
+
+ if (vblank->notifies)
+ present_destroy_notifies(vblank->notifies, vblank->num_notifies);
+
+ free(vblank);
+}
+
+Bool
+present_init(void)
+{
+ xorg_list_init(&present_exec_queue);
+ xorg_list_init(&present_flip_queue);
+ present_fake_queue_init();
+ return TRUE;
+}
diff --git a/present/present.h b/present/present.h
new file mode 100644
index 0000000..6a451fb
--- /dev/null
+++ b/present/present.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright © 2013 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#ifndef _PRESENT_H_
+#define _PRESENT_H_
+
+#include <X11/extensions/presentproto.h>
+#include "randrstr.h"
+#include "presentext.h"
+
+typedef struct present_vblank present_vblank_rec, *present_vblank_ptr;
+
+/* Return the current CRTC for 'window'.
+ */
+typedef RRCrtcPtr (*present_get_crtc_ptr) (WindowPtr window);
+
+/* Return the current ust/msc for 'crtc'
+ */
+typedef int (*present_get_ust_msc_ptr) (RRCrtcPtr crtc, uint64_t *ust, uint64_t *msc);
+
+/* Queue callback on 'crtc' for time 'msc'. Call present_event_notify with 'event_id'
+ * at or after 'msc'. Return false if it didn't happen (which might occur if 'crtc'
+ * is not currently generating vblanks).
+ */
+typedef Bool (*present_queue_vblank_ptr) (RRCrtcPtr crtc,
+ uint64_t event_id,
+ uint64_t msc);
+
+/* Abort pending vblank. The extension is no longer interested in
+ * 'event_id' which was to be notified at 'msc'. If possible, the
+ * driver is free to de-queue the notification.
+ */
+typedef void (*present_abort_vblank_ptr) (RRCrtcPtr crtc, uint64_t event_id, uint64_t msc);
+
+/* Flush pending drawing on 'window' to the hardware.
+ */
+typedef void (*present_flush_ptr) (WindowPtr window);
+
+/* Check if 'pixmap' is suitable for flipping to 'window'.
+ */
+typedef Bool (*present_check_flip_ptr) (RRCrtcPtr crtc, WindowPtr window, PixmapPtr pixmap, Bool sync_flip);
+
+/* Flip pixmap, return false if it didn't happen.
+ *
+ * 'crtc' is to be used for any necessary synchronization.
+ *
+ * 'sync_flip' requests that the flip be performed at the next
+ * vertical blank interval to avoid tearing artifacts. If false, the
+ * flip should be performed as soon as possible.
+ *
+ * present_event_notify should be called with 'event_id' when the flip
+ * occurs
+ */
+typedef Bool (*present_flip_ptr) (RRCrtcPtr crtc,
+ uint64_t event_id,
+ uint64_t target_msc,
+ PixmapPtr pixmap,
+ Bool sync_flip);
+
+/* "unflip" back to the regular screen scanout buffer
+ *
+ * present_event_notify should be called with 'event_id' when the unflip occurs.
+ */
+typedef void (*present_unflip_ptr) (ScreenPtr screen,
+ uint64_t event_id);
+
+#define PRESENT_SCREEN_INFO_VERSION 0
+
+typedef struct present_screen_info {
+ uint32_t version;
+
+ present_get_crtc_ptr get_crtc;
+ present_get_ust_msc_ptr get_ust_msc;
+ present_queue_vblank_ptr queue_vblank;
+ present_abort_vblank_ptr abort_vblank;
+ present_flush_ptr flush;
+ uint32_t capabilities;
+ present_check_flip_ptr check_flip;
+ present_flip_ptr flip;
+ present_unflip_ptr unflip;
+
+} present_screen_info_rec, *present_screen_info_ptr;
+
+/*
+ * Called when 'event_id' occurs. 'ust' and 'msc' indicate when the
+ * event actually happened
+ */
+extern _X_EXPORT void
+present_event_notify(uint64_t event_id, uint64_t ust, uint64_t msc);
+
+/* 'crtc' has been turned off, so any pending events will never occur.
+ */
+extern _X_EXPORT void
+present_event_abandon(RRCrtcPtr crtc);
+
+extern _X_EXPORT Bool
+present_screen_init(ScreenPtr screen, present_screen_info_ptr info);
+
+#endif /* _PRESENT_H_ */
diff --git a/present/present_event.c b/present/present_event.c
new file mode 100644
index 0000000..a30bc82
--- /dev/null
+++ b/present/present_event.c
@@ -0,0 +1,239 @@
+/*
+ * Copyright © 2013 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#endif
+
+#include "present_priv.h"
+
+#include "present_priv.h"
+
+RESTYPE present_event_type;
+
+static int
+present_free_event(pointer data, XID id)
+{
+ present_event_ptr present_event = (present_event_ptr) data;
+ present_window_priv_ptr window_priv = present_window_priv(present_event->window);
+ present_event_ptr *previous, current;
+
+ for (previous = &window_priv->events; (current = *previous); previous = ¤t->next) {
+ if (current == present_event) {
+ *previous = present_event->next;
+ break;
+ }
+ }
+ free((pointer) present_event);
+ return 1;
+
+}
+
+void
+present_free_events(WindowPtr window)
+{
+ present_window_priv_ptr window_priv = present_window_priv(window);
+ present_event_ptr event;
+
+ if (!window_priv)
+ return;
+
+ while ((event = window_priv->events))
+ FreeResource(event->id, RT_NONE);
+}
+
+static void
+present_event_swap(xGenericEvent *from, xGenericEvent *to)
+{
+ *to = *from;
+ swaps(&to->sequenceNumber);
+ swapl(&to->length);
+ swaps(&to->evtype);
+ switch (from->evtype) {
+ case PresentConfigureNotify: {
+ xPresentConfigureNotify *c = (xPresentConfigureNotify *) to;
+
+ swapl(&c->eid);
+ swapl(&c->window);
+ swaps(&c->x);
+ swaps(&c->y);
+ swaps(&c->width);
+ swaps(&c->height);
+ swaps(&c->off_x);
+ swaps(&c->off_y);
+ swaps(&c->pixmap_width);
+ swaps(&c->pixmap_height);
+ swapl(&c->pixmap_flags);
+ break;
+ }
+ case PresentCompleteNotify:
+ {
+ xPresentCompleteNotify *c = (xPresentCompleteNotify *) to;
+ swapl(&c->eid);
+ swapl(&c->window);
+ swapl(&c->serial);
+ swapll(&c->ust);
+ swapll(&c->msc);
+ }
+ case PresentIdleNotify:
+ {
+ xPresentIdleNotify *c = (xPresentIdleNotify *) to;
+ swapl(&c->eid);
+ swapl(&c->window);
+ swapl(&c->serial);
+ swapl(&c->idle_fence);
+ }
+ }
+}
+
+void
+present_send_config_notify(WindowPtr window, int x, int y, int w, int h, int bw, WindowPtr sibling)
+{
+ present_window_priv_ptr window_priv = present_window_priv(window);
+
+ if (window_priv) {
+ xPresentConfigureNotify cn = {
+ .type = GenericEvent,
+ .extension = present_request,
+ .length = (sizeof(xPresentConfigureNotify) - 32) >> 2,
+ .evtype = PresentConfigureNotify,
+ .eid = 0,
+ .window = window->drawable.id,
+ .x = x,
+ .y = y,
+ .width = w,
+ .height = h,
+ .off_x = 0,
+ .off_y = 0,
+ .pixmap_width = w,
+ .pixmap_height = h,
+ .pixmap_flags = 0
+ };
+ present_event_ptr event;
+
+ for (event = window_priv->events; event; event = event->next) {
+ if (event->mask & (1 << PresentConfigureNotify)) {
+ cn.eid = event->id;
+ WriteEventsToClient(event->client, 1, (xEvent *) &cn);
+ }
+ }
+ }
+}
+
+void
+present_send_complete_notify(WindowPtr window, CARD8 kind, CARD8 mode, CARD32 serial, uint64_t ust, uint64_t msc)
+{
+ present_window_priv_ptr window_priv = present_window_priv(window);
+
+ if (window_priv) {
+ xPresentCompleteNotify cn = {
+ .type = GenericEvent,
+ .extension = present_request,
+ .length = (sizeof(xPresentCompleteNotify) - 32) >> 2,
+ .evtype = PresentCompleteNotify,
+ .kind = kind,
+ .mode = mode,
+ .eid = 0,
+ .window = window->drawable.id,
+ .serial = serial,
+ .ust = ust,
+ .msc = msc,
+ };
+ present_event_ptr event;
+
+ for (event = window_priv->events; event; event = event->next) {
+ if (event->mask & PresentCompleteNotifyMask) {
+ cn.eid = event->id;
+ WriteEventsToClient(event->client, 1, (xEvent *) &cn);
+ }
+ }
+ }
+}
+
+void
+present_send_idle_notify(WindowPtr window, CARD32 serial, PixmapPtr pixmap, struct present_fence *idle_fence)
+{
+ present_window_priv_ptr window_priv = present_window_priv(window);
+
+ if (window_priv) {
+ xPresentIdleNotify in = {
+ .type = GenericEvent,
+ .extension = present_request,
+ .length = (sizeof(xPresentIdleNotify) - 32) >> 2,
+ .evtype = PresentIdleNotify,
+ .eid = 0,
+ .window = window->drawable.id,
+ .serial = serial,
+ .pixmap = pixmap->drawable.id,
+ .idle_fence = present_fence_id(idle_fence)
+ };
+ present_event_ptr event;
+
+ for (event = window_priv->events; event; event = event->next) {
+ if (event->mask & PresentIdleNotifyMask) {
+ in.eid = event->id;
+ WriteEventsToClient(event->client, 1, (xEvent *) &in);
+ }
+ }
+ }
+}
+
+int
+present_select_input(ClientPtr client, XID eid, WindowPtr window, CARD32 mask)
+{
+ present_window_priv_ptr window_priv = present_get_window_priv(window, mask != 0);
+ present_event_ptr event;
+
+ if (!window_priv) {
+ if (mask)
+ return BadAlloc;
+ return Success;
+ }
+
+ event = calloc (1, sizeof (present_event_rec));
+ if (!event)
+ return BadAlloc;
+
+ event->client = client;
+ event->window = window;
+ event->id = eid;
+ event->mask = mask;
+
+ event->next = window_priv->events;
+ window_priv->events = event;
+
+ if (!AddResource(event->id, present_event_type, (pointer) event))
+ return BadAlloc;
+
+ return Success;
+}
+
+Bool
+present_event_init(void)
+{
+ present_event_type = CreateNewResourceType(present_free_event, "PresentEvent");
+ if (!present_event_type)
+ return FALSE;
+
+ GERegisterExtension(present_request, present_event_swap);
+ return TRUE;
+}
diff --git a/present/present_fake.c b/present/present_fake.c
new file mode 100644
index 0000000..a677592
--- /dev/null
+++ b/present/present_fake.c
@@ -0,0 +1,140 @@
+/*
+ * Copyright © 2013 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#endif
+
+#include "present_priv.h"
+#include "list.h"
+
+static struct xorg_list fake_vblank_queue;
+
+typedef struct present_fake_vblank {
+ struct xorg_list list;
+ uint64_t event_id;
+ OsTimerPtr timer;
+ ScreenPtr screen;
+} present_fake_vblank_rec, *present_fake_vblank_ptr;
+
+int
+present_fake_get_ust_msc(ScreenPtr screen, uint64_t *ust, uint64_t *msc)
+{
+ present_screen_priv_ptr screen_priv = present_screen_priv(screen);
+
+ *ust = GetTimeInMicros();
+ *msc = *ust / screen_priv->fake_interval;
+ return Success;
+}
+
+static void
+present_fake_notify(ScreenPtr screen, uint64_t event_id)
+{
+ uint64_t ust, msc;
+
+ present_fake_get_ust_msc(screen, &ust, &msc);
+ present_event_notify(event_id, ust, msc);
+}
+
+static CARD32
+present_fake_do_timer(OsTimerPtr timer,
+ CARD32 time,
+ pointer arg)
+{
+ present_fake_vblank_ptr fake_vblank = arg;
+
+ present_fake_notify(fake_vblank->screen, fake_vblank->event_id);
+ xorg_list_del(&fake_vblank->list);
+ free(fake_vblank);
+ return 0;
+}
+
+void
+present_fake_abort_vblank(ScreenPtr screen, uint64_t event_id, uint64_t msc)
+{
+ present_fake_vblank_ptr fake_vblank, tmp;
+
+ xorg_list_for_each_entry_safe(fake_vblank, tmp, &fake_vblank_queue, list) {
+ if (fake_vblank->event_id == event_id) {
+ TimerCancel(fake_vblank->timer);
+ xorg_list_del(&fake_vblank->list);
+ free (fake_vblank);
+ break;
+ }
+ }
+}
+
+int
+present_fake_queue_vblank(ScreenPtr screen,
+ uint64_t event_id,
+ uint64_t msc)
+{
+ present_screen_priv_ptr screen_priv = present_screen_priv(screen);
+ uint64_t ust = msc * screen_priv->fake_interval;
+ uint64_t now = GetTimeInMicros();
+ INT32 delay = ((int64_t) (ust - now)) / 1000;
+ present_fake_vblank_ptr fake_vblank;
+
+ if (delay <= 0) {
+ present_fake_notify(screen, event_id);
+ return Success;
+ }
+
+ fake_vblank = calloc (1, sizeof (present_fake_vblank_rec));
+ if (!fake_vblank)
+ return BadAlloc;
+
+ fake_vblank->screen = screen;
+ fake_vblank->event_id = event_id;
+ fake_vblank->timer = TimerSet(NULL, 0, delay, present_fake_do_timer, fake_vblank);
+ if (!fake_vblank->timer) {
+ free(fake_vblank);
+ return BadAlloc;
+ }
+
+ xorg_list_add(&fake_vblank->list, &fake_vblank_queue);
+
+ return Success;
+}
+
+void
+present_fake_screen_init(ScreenPtr screen)
+{
+ present_screen_priv_ptr screen_priv = present_screen_priv(screen);
+
+ /* For screens with hardware vblank support, the fake code
+ * will be used for off-screen windows and while screens are blanked,
+ * in which case we want a slow interval here
+ *
+ * Otherwise, pretend that the screen runs at 60Hz
+ */
+ if (screen_priv->info && screen_priv->info->get_crtc)
+ screen_priv->fake_interval = 1000000;
+ else
+ screen_priv->fake_interval = 16667;
+}
+
+void
+present_fake_queue_init(void)
+{
+ xorg_list_init(&fake_vblank_queue);
+}
diff --git a/present/present_fence.c b/present/present_fence.c
new file mode 100644
index 0000000..db5efca
--- /dev/null
+++ b/present/present_fence.c
@@ -0,0 +1,112 @@
+/*
+ * Copyright © 2013 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#endif
+
+#include "present_priv.h"
+#include <gcstruct.h>
+#include <misync.h>
+#include <misyncstr.h>
+
+/*
+ * Wraps SyncFence objects so we can add a SyncTrigger to find out
+ * when the SyncFence gets destroyed and clean up appropriately
+ */
+
+struct present_fence {
+ SyncTrigger trigger;
+ SyncFence *fence;
+};
+
+/*
+ * SyncTrigger callbacks
+ */
+static Bool
+present_fence_sync_check_trigger(SyncTrigger *trigger, XSyncValue oldval)
+{
+ return FALSE;
+}
+
+static void
+present_fence_sync_trigger_fired(SyncTrigger *trigger)
+{
+}
+
+static void
+present_fence_sync_counter_destroyed(SyncTrigger *trigger)
+{
+ struct present_fence *present_fence = container_of(trigger, struct present_fence, trigger);
+
+ present_fence->fence = NULL;
+}
+
+struct present_fence *
+present_fence_create(SyncFence *fence)
+{
+ struct present_fence *present_fence;
+
+ present_fence = calloc (1, sizeof (struct present_fence));
+ if (!present_fence)
+ return NULL;
+
+ present_fence->fence = fence;
+ present_fence->trigger.pSync = (SyncObject *) fence;
+ present_fence->trigger.CheckTrigger = present_fence_sync_check_trigger;
+ present_fence->trigger.TriggerFired = present_fence_sync_trigger_fired;
+ present_fence->trigger.CounterDestroyed = present_fence_sync_counter_destroyed;
+
+ if (SyncAddTriggerToSyncObject(&present_fence->trigger) != Success) {
+ free (present_fence);
+ return NULL;
+ }
+ return present_fence;
+}
+
+void
+present_fence_destroy(struct present_fence *present_fence)
+{
+ if (present_fence) {
+ if (present_fence->fence)
+ SyncDeleteTriggerFromSyncObject(&present_fence->trigger);
+ free(present_fence);
+ }
+}
+
+void
+present_fence_set_triggered(struct present_fence *present_fence)
+{
+ if (present_fence)
+ if (present_fence->fence)
+ (*present_fence->fence->funcs.SetTriggered) (present_fence->fence);
+}
+
+XID
+present_fence_id(struct present_fence *present_fence)
+{
+ if (!present_fence)
+ return None;
+ if (!present_fence->fence)
+ return None;
+ return present_fence->fence->sync.id;
+}
diff --git a/present/present_notify.c b/present/present_notify.c
new file mode 100644
index 0000000..e272e08
--- /dev/null
+++ b/present/present_notify.c
@@ -0,0 +1,114 @@
+/*
+ * Copyright © 2013 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#endif
+
+#include "present_priv.h"
+
+/*
+ * Mark all pending notifies for 'window' as invalid when
+ * the window is destroyed
+ */
+
+void
+present_clear_window_notifies(WindowPtr window)
+{
+ present_notify_ptr notify;
+ present_window_priv_ptr window_priv = present_window_priv(window);
+
+ if (!window_priv)
+ return;
+
+ xorg_list_for_each_entry(notify, &window_priv->notifies, window_list) {
+ notify->window = NULL;
+ }
+}
+
+/*
+ * 'notify' is being freed; remove it from the window's notify list
+ */
+
+void
+present_free_window_notify(present_notify_ptr notify)
+{
+ xorg_list_del(¬ify->window_list);
+}
+
+/*
+ * 'notify' is new; add it to the specified window
+ */
+
+int
+present_add_window_notify(present_notify_ptr notify)
+{
+ WindowPtr window = notify->window;
+ present_window_priv_ptr window_priv = present_get_window_priv(window, TRUE);
+
+ if (!window_priv)
+ return BadAlloc;
+
+ xorg_list_add(¬ify->window_list, &window_priv->notifies);
+ return Success;
+}
+
+int
+present_create_notifies(ClientPtr client, int num_notifies, xPresentNotify *x_notifies, present_notify_ptr *p_notifies)
+{
+ present_notify_ptr notifies;
+ int i;
+ int added = 0;
+ int status;
+
+ notifies = calloc (num_notifies, sizeof (present_notify_rec));
+ if (!notifies)
+ return BadAlloc;
+
+ for (i = 0; i < num_notifies; i++) {
+ status = dixLookupWindow(¬ifies[i].window, x_notifies[i].window, client, DixGetAttrAccess);
+ if (status != Success)
+ goto bail;
+
+ notifies[i].serial = x_notifies[i].serial;
+ status = present_add_window_notify(¬ifies[i]);
+ if (status != Success)
+ goto bail;
+
+ added = i;
+ }
+ return Success;
+
+bail:
+ present_destroy_notifies(notifies, added);
+ return status;
+}
+
+void
+present_destroy_notifies(present_notify_ptr notifies, int num_notifies)
+{
+ int i;
+ for (i = 0; i < num_notifies; i++)
+ present_free_window_notify(¬ifies[i]);
+
+ free(notifies);
+}
diff --git a/present/present_priv.h b/present/present_priv.h
new file mode 100644
index 0000000..a92b62a
--- /dev/null
+++ b/present/present_priv.h
@@ -0,0 +1,288 @@
+/*
+ * Copyright © 2013 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#ifndef _PRESENT_PRIV_H_
+#define _PRESENT_PRIV_H_
+
+#include <X11/X.h>
+#include "scrnintstr.h"
+#include "misc.h"
+#include "list.h"
+#include "windowstr.h"
+#include "dixstruct.h"
+#include "present.h"
+#include <syncsdk.h>
+#include <syncsrv.h>
+#include <xfixes.h>
+#include <randrstr.h>
+
+extern int present_request;
+
+extern DevPrivateKeyRec present_screen_private_key;
+
+typedef struct present_fence *present_fence_ptr;
+
+typedef struct present_notify present_notify_rec, *present_notify_ptr;
+
+struct present_notify {
+ struct xorg_list window_list;
+ WindowPtr window;
+ CARD32 serial;
+};
+
+struct present_vblank {
+ struct xorg_list window_list;
+ struct xorg_list event_queue;
+ ScreenPtr screen;
+ WindowPtr window;
+ PixmapPtr pixmap;
+ RegionPtr valid;
+ RegionPtr update;
+ RRCrtcPtr crtc;
+ uint32_t serial;
+ int16_t x_off;
+ int16_t y_off;
+ CARD16 kind;
+ uint64_t event_id;
+ uint64_t target_msc;
+ uint64_t msc_offset;
+ present_fence_ptr idle_fence;
+ present_fence_ptr wait_fence;
+ present_notify_ptr notifies;
+ int num_notifies;
+ Bool flip;
+ Bool sync_flip;
+ Bool abort_flip;
+
+ Bool window_destroyed;
+};
+
+typedef struct present_screen_priv {
+ CloseScreenProcPtr CloseScreen;
+ ConfigNotifyProcPtr ConfigNotify;
+ DestroyWindowProcPtr DestroyWindow;
+ ClipNotifyProcPtr ClipNotify;
+
+ present_vblank_ptr flip_pending;
+ uint64_t unflip_event_id;
+
+ uint32_t fake_interval;
+
+ /* Currently active flipped pixmap and fence */
+ RRCrtcPtr flip_crtc;
+ WindowPtr flip_window;
+ uint32_t flip_serial;
+ PixmapPtr flip_pixmap;
+ present_fence_ptr flip_idle_fence;
+
+ present_screen_info_ptr info;
+} present_screen_priv_rec, *present_screen_priv_ptr;
+
+#define wrap(priv,real,mem,func) {\
+ priv->mem = real->mem; \
+ real->mem = func; \
+}
+
+#define unwrap(priv,real,mem) {\
+ real->mem = priv->mem; \
+}
+
+static inline present_screen_priv_ptr
+present_screen_priv(ScreenPtr screen)
+{
+ return (present_screen_priv_ptr)dixLookupPrivate(&(screen)->devPrivates, &present_screen_private_key);
+}
+
+/*
+ * Each window has a list of clients and event masks
+ */
+typedef struct present_event *present_event_ptr;
+
+typedef struct present_event {
+ present_event_ptr next;
+ ClientPtr client;
+ WindowPtr window;
+ XID id;
+ int mask;
+} present_event_rec;
+
+typedef struct present_window_priv {
+ present_event_ptr events;
+ RRCrtcPtr crtc; /* Last reported CRTC from get_ust_msc */
+ uint64_t msc_offset;
+ uint64_t msc; /* Last reported MSC from the current crtc */
+ struct xorg_list vblank;
+ struct xorg_list notifies;
+} present_window_priv_rec, *present_window_priv_ptr;
+
+extern DevPrivateKeyRec present_window_private_key;
+
+static inline present_window_priv_ptr
+present_window_priv(WindowPtr window)
+{
+ return (present_window_priv_ptr)dixGetPrivate(&(window)->devPrivates, &present_window_private_key);
+}
+
+present_window_priv_ptr
+present_get_window_priv(WindowPtr window, Bool create);
+
+extern RESTYPE present_event_type;
+
+/*
+ * present.c
+ */
+int
+present_pixmap(WindowPtr window,
+ PixmapPtr pixmap,
+ CARD32 serial,
+ RegionPtr valid,
+ RegionPtr update,
+ int16_t x_off,
+ int16_t y_off,
+ RRCrtcPtr target_crtc,
+ SyncFence *wait_fence,
+ SyncFence *idle_fence,
+ uint32_t options,
+ uint64_t target_msc,
+ uint64_t divisor,
+ uint64_t remainder,
+ present_notify_ptr notifies,
+ int num_notifies);
+
+int
+present_notify_msc(WindowPtr window,
+ CARD32 serial,
+ uint64_t target_msc,
+ uint64_t divisor,
+ uint64_t remainder);
+
+void
+present_abort_vblank(ScreenPtr screen, RRCrtcPtr crtc, uint64_t event_id, uint64_t msc);
+
+void
+present_vblank_destroy(present_vblank_ptr vblank);
+
+void
+present_flip_destroy(ScreenPtr screen);
+
+void
+present_check_flip_window(WindowPtr window);
+
+RRCrtcPtr
+present_get_crtc(WindowPtr window);
+
+uint32_t
+present_query_capabilities(RRCrtcPtr crtc);
+
+Bool
+present_init(void);
+
+/*
+ * present_event.c
+ */
+
+void
+present_free_events(WindowPtr window);
+
+void
+present_send_config_notify(WindowPtr window, int x, int y, int w, int h, int bw, WindowPtr sibling);
+
+void
+present_send_complete_notify(WindowPtr window, CARD8 kind, CARD8 mode, CARD32 serial, uint64_t ust, uint64_t msc);
+
+void
+present_send_idle_notify(WindowPtr window, CARD32 serial, PixmapPtr pixmap, present_fence_ptr idle_fence);
+
+int
+present_select_input(ClientPtr client,
+ CARD32 eid,
+ WindowPtr window,
+ CARD32 event_mask);
+
+Bool
+present_event_init(void);
+
+/*
+ * present_fake.c
+ */
+int
+present_fake_get_ust_msc(ScreenPtr screen, uint64_t *ust, uint64_t *msc);
+
+int
+present_fake_queue_vblank(ScreenPtr screen, uint64_t event_id, uint64_t msc);
+
+void
+present_fake_abort_vblank(ScreenPtr screen, uint64_t event_id, uint64_t msc);
+
+void
+present_fake_screen_init(ScreenPtr screen);
+
+void
+present_fake_queue_init(void);
+
+/*
+ * present_fence.c
+ */
+struct present_fence *
+present_fence_create(SyncFence *sync_fence);
+
+void
+present_fence_destroy(struct present_fence *present_fence);
+
+void
+present_fence_set_triggered(struct present_fence *present_fence);
+
+XID
+present_fence_id(struct present_fence *present_fence);
+
+/*
+ * present_notify.c
+ */
+void
+present_clear_window_notifies(WindowPtr window);
+
+void
+present_free_window_notify(present_notify_ptr notify);
+
+int
+present_add_window_notify(present_notify_ptr notify);
+
+int
+present_create_notifies(ClientPtr client, int num_notifies, xPresentNotify *x_notifies, present_notify_ptr *p_notifies);
+
+void
+present_destroy_notifies(present_notify_ptr notifies, int num_notifies);
+
+/*
+ * present_request.c
+ */
+int
+proc_present_dispatch(ClientPtr client);
+
+int
+sproc_present_dispatch(ClientPtr client);
+
+/*
+ * present_screen.c
+ */
+
+#endif /* _PRESENT_PRIV_H_ */
diff --git a/present/present_request.c b/present/present_request.c
new file mode 100644
index 0000000..095fa2d
--- /dev/null
+++ b/present/present_request.c
@@ -0,0 +1,330 @@
+/*
+ * Copyright © 2013 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#endif
+
+#include "present_priv.h"
+#include "randrstr.h"
+
+static int
+proc_present_query_version(ClientPtr client)
+{
+ REQUEST(xPresentQueryVersionReq);
+ xPresentQueryVersionReply rep = {
+ .type = X_Reply,
+ .sequenceNumber = client->sequence,
+ .length = 0,
+ .majorVersion = PRESENT_MAJOR,
+ .minorVersion = PRESENT_MINOR
+ };
+
+ REQUEST_SIZE_MATCH(xPresentQueryVersionReq);
+ (void) stuff;
+ if (client->swapped) {
+ swaps(&rep.sequenceNumber);
+ swapl(&rep.length);
+ swapl(&rep.majorVersion);
+ swapl(&rep.minorVersion);
+ }
+ WriteToClient(client, sizeof(rep), &rep);
+ return Success;
+}
+
+#define VERIFY_FENCE_OR_NONE(fence_ptr, fence_id, client, access) do { \
+ if ((fence_id) == None) \
+ (fence_ptr) = NULL; \
+ else { \
+ int __rc__ = SyncVerifyFence(&fence_ptr, fence_id, client, access); \
+ if (__rc__ != Success) \
+ return __rc__; \
+ } \
+ } while (0)
+
+#define VERIFY_CRTC_OR_NONE(crtc_ptr, crtc_id, client, access) do { \
+ if ((crtc_id) == None) \
+ (crtc_ptr) = NULL; \
+ else { \
+ VERIFY_RR_CRTC(crtc_id, crtc_ptr, access); \
+ } \
+ } while (0)
+
+static int
+proc_present_pixmap(ClientPtr client)
+{
+ REQUEST(xPresentPixmapReq);
+ WindowPtr window;
+ PixmapPtr pixmap;
+ RegionPtr valid = NULL;
+ RegionPtr update = NULL;
+ SyncFence *wait_fence;
+ SyncFence *idle_fence;
+ RRCrtcPtr target_crtc;
+ int ret;
+ int nnotifies;
+ present_notify_ptr notifies = NULL;
+
+ REQUEST_AT_LEAST_SIZE(xPresentPixmapReq);
+ ret = dixLookupWindow(&window, stuff->window, client, DixWriteAccess);
+ if (ret != Success)
+ return ret;
+ ret = dixLookupResourceByType((pointer *) &pixmap, stuff->pixmap, RT_PIXMAP, client, DixReadAccess);
+ if (ret != Success)
+ return ret;
+
+ if (window->drawable.depth != pixmap->drawable.depth)
+ return BadMatch;
+
+ VERIFY_REGION_OR_NONE(valid, stuff->valid, client, DixReadAccess);
+ VERIFY_REGION_OR_NONE(update, stuff->update, client, DixReadAccess);
+
+ VERIFY_CRTC_OR_NONE(target_crtc, stuff->target_crtc, client, DixReadAccess);
+
+ VERIFY_FENCE_OR_NONE(wait_fence, stuff->wait_fence, client, DixReadAccess);
+ VERIFY_FENCE_OR_NONE(idle_fence, stuff->idle_fence, client, DixWriteAccess);
+
+ if (stuff->options & ~(PresentAllOptions)) {
+ client->errorValue = stuff->options;
+ return BadValue;
+ }
+
+ /*
+ * Check to see if remainder is sane
+ */
+ if (stuff->divisor == 0) {
+ if (stuff->remainder != 0) {
+ client->errorValue = (CARD32) stuff->remainder;
+ return BadValue;
+ }
+ } else {
+ if (stuff->remainder >= stuff->divisor) {
+ client->errorValue = (CARD32) stuff->remainder;
+ return BadValue;
+ }
+ }
+
+ nnotifies = (client->req_len << 2) - sizeof (xPresentPixmapReq);
+ if (nnotifies % sizeof (xPresentNotify))
+ return BadLength;
+
+ nnotifies /= sizeof (xPresentNotify);
+ if (nnotifies) {
+ ret = present_create_notifies(client, nnotifies, (xPresentNotify *) (stuff + 1), ¬ifies);
+ if (ret != Success)
+ return ret;
+ }
+
+ ret = present_pixmap(window, pixmap, stuff->serial, valid, update,
+ stuff->x_off, stuff->y_off, target_crtc,
+ wait_fence, idle_fence, stuff->options,
+ stuff->target_msc, stuff->divisor, stuff->remainder, notifies, nnotifies);
+ if (ret != Success)
+ present_destroy_notifies(notifies, nnotifies);
+ return ret;
+}
+
+static int
+proc_present_notify_msc(ClientPtr client)
+{
+ REQUEST(xPresentNotifyMSCReq);
+ WindowPtr window;
+ int rc;
+
+ REQUEST_SIZE_MATCH(xPresentNotifyMSCReq);
+ rc = dixLookupWindow(&window, stuff->window, client, DixReadAccess);
+ if (rc != Success)
+ return rc;
+
+ /*
+ * Check to see if remainder is sane
+ */
+ if (stuff->divisor == 0) {
+ if (stuff->remainder != 0) {
+ client->errorValue = (CARD32) stuff->remainder;
+ return BadValue;
+ }
+ } else {
+ if (stuff->remainder >= stuff->divisor) {
+ client->errorValue = (CARD32) stuff->remainder;
+ return BadValue;
+ }
+ }
+
+ return present_notify_msc(window, stuff->serial,
+ stuff->target_msc, stuff->divisor, stuff->remainder);
+}
+
+static int
+proc_present_select_input (ClientPtr client)
+{
+ REQUEST(xPresentSelectInputReq);
+ WindowPtr window;
+ int rc;
+
+ REQUEST_SIZE_MATCH(xPresentSelectInputReq);
+
+ LEGAL_NEW_RESOURCE(stuff->eid, client);
+
+ rc = dixLookupWindow(&window, stuff->window, client, DixGetAttrAccess);
+ if (rc != Success)
+ return rc;
+
+ if (stuff->eventMask & ~PresentAllEvents) {
+ client->errorValue = stuff->eventMask;
+ return BadValue;
+ }
+ return present_select_input(client, stuff->eid, window, stuff->eventMask);
+}
+
+static int
+proc_present_query_capabilities (ClientPtr client)
+{
+ REQUEST(xPresentQueryCapabilitiesReq);
+ xPresentQueryCapabilitiesReply rep = {
+ .type = X_Reply,
+ .sequenceNumber = client->sequence,
+ .length = 0,
+ };
+ WindowPtr window;
+ RRCrtcPtr crtc = NULL;
+ int r;
+
+ r = dixLookupWindow(&window, stuff->target, client, DixGetAttrAccess);
+ switch (r) {
+ case Success:
+ crtc = present_get_crtc(window);
+ break;
+ case BadWindow:
+ VERIFY_RR_CRTC(stuff->target, crtc, DixGetAttrAccess);
+ break;
+ default:
+ return r;
+ }
+
+ rep.capabilities = present_query_capabilities(crtc);
+
+ if (client->swapped) {
+ swaps(&rep.sequenceNumber);
+ swapl(&rep.length);
+ swapl(&rep.capabilities);
+ }
+ WriteToClient(client, sizeof(rep), &rep);
+ return Success;
+}
+
+int (*proc_present_vector[PresentNumberRequests]) (ClientPtr) = {
+ proc_present_query_version, /* 0 */
+ proc_present_pixmap, /* 1 */
+ proc_present_notify_msc, /* 2 */
+ proc_present_select_input, /* 3 */
+ proc_present_query_capabilities, /* 4 */
+};
+
+int
+proc_present_dispatch(ClientPtr client)
+{
+ REQUEST(xReq);
+ if (stuff->data >= PresentNumberRequests || !proc_present_vector[stuff->data])
+ return BadRequest;
+ return (*proc_present_vector[stuff->data]) (client);
+}
+
+static int
+sproc_present_query_version(ClientPtr client)
+{
+ REQUEST(xPresentQueryVersionReq);
+
+ swaps(&stuff->length);
+ swapl(&stuff->majorVersion);
+ swapl(&stuff->minorVersion);
+ return (*proc_present_vector[stuff->presentReqType]) (client);
+}
+
+static int
+sproc_present_pixmap(ClientPtr client)
+{
+ REQUEST(xPresentPixmapReq);
+
+ swaps(&stuff->length);
+ swapl(&stuff->window);
+ swapl(&stuff->pixmap);
+ swapl(&stuff->valid);
+ swapl(&stuff->update);
+ swaps(&stuff->x_off);
+ swaps(&stuff->y_off);
+ swapll(&stuff->target_msc);
+ swapll(&stuff->divisor);
+ swapll(&stuff->remainder);
+ swapl(&stuff->idle_fence);
+ return (*proc_present_vector[stuff->presentReqType]) (client);
+}
+
+static int
+sproc_present_notify_msc(ClientPtr client)
+{
+ REQUEST(xPresentNotifyMSCReq);
+
+ swaps(&stuff->length);
+ swapl(&stuff->window);
+ swapll(&stuff->target_msc);
+ swapll(&stuff->divisor);
+ swapll(&stuff->remainder);
+ return (*proc_present_vector[stuff->presentReqType]) (client);
+}
+
+static int
+sproc_present_select_input (ClientPtr client)
+{
+ REQUEST(xPresentSelectInputReq);
+
+ swaps(&stuff->length);
+ swapl(&stuff->window);
+ swapl(&stuff->eventMask);
+ return (*proc_present_vector[stuff->presentReqType]) (client);
+}
+
+static int
+sproc_present_query_capabilities (ClientPtr client)
+{
+ REQUEST(xPresentQueryCapabilitiesReq);
+ swaps(&stuff->length);
+ swapl(&stuff->target);
+ return (*proc_present_vector[stuff->presentReqType]) (client);
+}
+
+int (*sproc_present_vector[PresentNumberRequests]) (ClientPtr) = {
+ sproc_present_query_version, /* 0 */
+ sproc_present_pixmap, /* 1 */
+ sproc_present_notify_msc, /* 2 */
+ sproc_present_select_input, /* 3 */
+ sproc_present_query_capabilities, /* 4 */
+};
+
+int
+sproc_present_dispatch(ClientPtr client)
+{
+ REQUEST(xReq);
+ if (stuff->data >= PresentNumberRequests || !sproc_present_vector[stuff->data])
+ return BadRequest;
+ return (*sproc_present_vector[stuff->data]) (client);
+}
diff --git a/present/present_screen.c b/present/present_screen.c
new file mode 100644
index 0000000..50b2b2d
--- /dev/null
+++ b/present/present_screen.c
@@ -0,0 +1,231 @@
+/*
+ * Copyright © 2013 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#endif
+
+#include "present_priv.h"
+
+int present_request;
+DevPrivateKeyRec present_screen_private_key;
+DevPrivateKeyRec present_window_private_key;
+
+/*
+ * Get a pointer to a present window private, creating if necessary
+ */
+present_window_priv_ptr
+present_get_window_priv(WindowPtr window, Bool create)
+{
+ present_window_priv_ptr window_priv = present_window_priv(window);
+
+ if (!create || window_priv != NULL)
+ return window_priv;
+ window_priv = calloc (1, sizeof (present_window_priv_rec));
+ if (!window_priv)
+ return NULL;
+ xorg_list_init(&window_priv->vblank);
+ xorg_list_init(&window_priv->notifies);
+ dixSetPrivate(&window->devPrivates, &present_window_private_key, window_priv);
+ return window_priv;
+}
+
+/*
+ * Hook the close screen function to clean up our screen private
+ */
+static Bool
+present_close_screen(ScreenPtr screen)
+{
+ present_screen_priv_ptr screen_priv = present_screen_priv(screen);
+
+ present_flip_destroy(screen);
+
+ unwrap(screen_priv, screen, CloseScreen);
+ (*screen->CloseScreen) (screen);
+ free(screen_priv);
+ return TRUE;
+}
+
+/*
+ * Free any queued presentations for this window
+ */
+static void
+present_free_window_vblank(WindowPtr window)
+{
+ present_window_priv_ptr window_priv = present_window_priv(window);
+ present_vblank_ptr vblank, tmp;
+
+ xorg_list_for_each_entry_safe(vblank, tmp, &window_priv->vblank, window_list) {
+ present_abort_vblank(window->drawable.pScreen, vblank->crtc, vblank->event_id, vblank->target_msc);
+ present_vblank_destroy(vblank);
+ }
+}
+
+/*
+ * Clean up any pending or current flips for this window
+ */
+static void
+present_clear_window_flip(WindowPtr window)
+{
+ ScreenPtr screen = window->drawable.pScreen;
+ present_screen_priv_ptr screen_priv = present_screen_priv(screen);
+ present_vblank_ptr flip_pending = screen_priv->flip_pending;
+
+ if (flip_pending && flip_pending->window == window) {
+ assert (flip_pending->abort_flip);
+ flip_pending->window_destroyed = TRUE;
+ }
+ if (screen_priv->flip_window == window)
+ screen_priv->flip_window = NULL;
+}
+
+/*
+ * Hook the close window function to clean up our window private
+ */
+static Bool
+present_destroy_window(WindowPtr window)
+{
+ Bool ret;
+ ScreenPtr screen = window->drawable.pScreen;
+ present_screen_priv_ptr screen_priv = present_screen_priv(screen);
+ present_window_priv_ptr window_priv = present_window_priv(window);
+
+ if (window_priv) {
+ present_clear_window_notifies(window);
+ present_free_events(window);
+ present_free_window_vblank(window);
+ present_clear_window_flip(window);
+ free(window_priv);
+ }
+ unwrap(screen_priv, screen, DestroyWindow);
+ if (screen->DestroyWindow)
+ ret = screen->DestroyWindow (window);
+ else
+ ret = TRUE;
+ wrap(screen_priv, screen, DestroyWindow, present_destroy_window);
+ return ret;
+}
+
+/*
+ * Hook the config notify screen function to deliver present config notify events
+ */
+static int
+present_config_notify(WindowPtr window,
+ int x, int y, int w, int h, int bw,
+ WindowPtr sibling)
+{
+ int ret;
+ ScreenPtr screen = window->drawable.pScreen;
+ present_screen_priv_ptr screen_priv = present_screen_priv(screen);
+
+ present_send_config_notify(window, x, y, w, h, bw, sibling);
+
+ unwrap(screen_priv, screen, ConfigNotify);
+ if (screen->ConfigNotify)
+ ret = screen->ConfigNotify (window, x, y, w, h, bw, sibling);
+ else
+ ret = 0;
+ wrap(screen_priv, screen, ConfigNotify, present_config_notify);
+ return ret;
+}
+
+/*
+ * Hook the clip notify screen function to un-flip as necessary
+ */
+
+static void
+present_clip_notify(WindowPtr window, int dx, int dy)
+{
+ ScreenPtr screen = window->drawable.pScreen;
+ present_screen_priv_ptr screen_priv = present_screen_priv(screen);
+
+ present_check_flip_window(window);
+ unwrap(screen_priv, screen, ClipNotify)
+ if (screen->ClipNotify)
+ screen->ClipNotify (window, dx, dy);
+ wrap(screen_priv, screen, ClipNotify, present_clip_notify);
+}
+
+/*
+ * Initialize a screen for use with present
+ */
+int
+present_screen_init(ScreenPtr screen, present_screen_info_ptr info)
+{
+ if (!dixRegisterPrivateKey(&present_screen_private_key, PRIVATE_SCREEN, 0))
+ return FALSE;
+
+ if (!dixRegisterPrivateKey(&present_window_private_key, PRIVATE_WINDOW, 0))
+ return FALSE;
+
+ if (!present_screen_priv(screen)) {
+ present_screen_priv_ptr screen_priv = calloc(1, sizeof (present_screen_priv_rec));
+ if (!screen_priv)
+ return FALSE;
+
+ wrap(screen_priv, screen, CloseScreen, present_close_screen);
+ wrap(screen_priv, screen, DestroyWindow, present_destroy_window);
+ wrap(screen_priv, screen, ConfigNotify, present_config_notify);
+ wrap(screen_priv, screen, ClipNotify, present_clip_notify);
+
+ screen_priv->info = info;
+
+ dixSetPrivate(&screen->devPrivates, &present_screen_private_key, screen_priv);
+
+ present_fake_screen_init(screen);
+ }
+
+ return TRUE;
+}
+
+/*
+ * Initialize the present extension
+ */
+void
+present_extension_init(void)
+{
+ ExtensionEntry *extension;
+ int i;
+
+ extension = AddExtension(PRESENT_NAME, PresentNumberEvents, PresentNumberErrors,
+ proc_present_dispatch, sproc_present_dispatch,
+ NULL, StandardMinorOpcode);
+ if (!extension)
+ goto bail;
+
+ present_request = extension->base;
+
+ if (!present_init())
+ goto bail;
+
+ if (!present_event_init())
+ goto bail;
+
+ for (i = 0; i < screenInfo.numScreens; i++) {
+ if (!present_screen_init(screenInfo.screens[i], NULL))
+ goto bail;
+ }
+ return;
+
+bail:
+ FatalError("Cannot initialize Present extension");
+}
diff --git a/present/presentext.h b/present/presentext.h
new file mode 100644
index 0000000..f177f55
--- /dev/null
+++ b/present/presentext.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright © 2013 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#ifndef _PRESENTEXT_H_
+#define _PRESENTEXT_H_
+
+extern _X_EXPORT void
+present_extension_init(void);
+
+#endif /* _PRESENTEXT_H_ */
commit 563138298868f62501875d3016f03469dcffaad0
Author: Keith Packard <keithp at keithp.com>
Date: Tue Apr 9 19:59:39 2013 -0700
dri3: Add DRI3 extension
Adds DRM compatible fences using futexes.
Uses FD passing to get pixmaps from DRM applications.
Signed-off-by: Keith Packard <keithp at keithp.com>
Reviewed-by: Adam Jackson <ajax at redhat.com>
diff --git a/Makefile.am b/Makefile.am
index 7be4271..7a8fc5b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -17,6 +17,10 @@ if RECORD
RECORD_DIR=record
endif
+if DRI3
+DRI3_DIR=dri3
+endif
+
SUBDIRS = \
doc \
man \
@@ -38,6 +42,7 @@ SUBDIRS = \
damageext \
$(COMPOSITE_DIR) \
$(GLX_DIR) \
+ $(DRI3_DIR) \
exa \
config \
hw \
diff --git a/Xext/sync.c b/Xext/sync.c
index b2ee92e..126ce43 100644
--- a/Xext/sync.c
+++ b/Xext/sync.c
@@ -141,7 +141,7 @@ SyncCheckWarnIsCounter(const SyncObject * pSync, const char *warning)
* interested in the counter. The two functions below are used to
* delete and add triggers on this list.
*/
-static void
+void
SyncDeleteTriggerFromSyncObject(SyncTrigger * pTrigger)
{
SyncTriggerList *pCur;
@@ -184,7 +184,7 @@ SyncDeleteTriggerFromSyncObject(SyncTrigger * pTrigger)
}
}
-static int
+int
SyncAddTriggerToSyncObject(SyncTrigger * pTrigger)
{
SyncTriggerList *pCur;
@@ -916,6 +916,34 @@ SyncCreate(ClientPtr client, XID id, unsigned char type)
return pSync;
}
+int
+SyncCreateFenceFromFD(ClientPtr client, DrawablePtr pDraw, XID id, int fd, BOOL initially_triggered)
+{
+ SyncFence *pFence;
+ int status;
+
+ pFence = (SyncFence *) SyncCreate(client, id, SYNC_FENCE);
+ if (!pFence)
+ return BadAlloc;
+
+ status = miSyncInitFenceFromFD(pDraw, pFence, fd, initially_triggered);
+ if (status != Success) {
+ miSyncDestroyFence(pFence);
+ return status;
+ }
+
+ if (!AddResource(id, RTFence, (pointer) pFence))
+ return BadAlloc;
+
+ return Success;
+}
+
+int
+SyncFDFromFence(ClientPtr client, DrawablePtr pDraw, SyncFence *pFence)
+{
+ return miSyncFDFromFence(pDraw, pFence);
+}
+
static SyncCounter *
SyncCreateCounter(ClientPtr client, XSyncCounter id, CARD64 initialvalue)
{
diff --git a/Xext/syncsrv.h b/Xext/syncsrv.h
index c68229f..45fca04 100644
--- a/Xext/syncsrv.h
+++ b/Xext/syncsrv.h
@@ -136,4 +136,17 @@ extern void SyncDestroySystemCounter(pointer pCounter);
extern SyncCounter *SyncInitDeviceIdleTime(DeviceIntPtr dev);
extern void SyncRemoveDeviceIdleTime(SyncCounter *counter);
+
+int
+SyncCreateFenceFromFD(ClientPtr client, DrawablePtr pDraw, XID id, int fd, BOOL initially_triggered);
+
+int
+SyncFDFromFence(ClientPtr client, DrawablePtr pDraw, SyncFence *fence);
+
+void
+SyncDeleteTriggerFromSyncObject(SyncTrigger * pTrigger);
+
+int
+SyncAddTriggerToSyncObject(SyncTrigger * pTrigger);
+
#endif /* _SYNCSRV_H_ */
diff --git a/configure.ac b/configure.ac
index d29f170..546790d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -613,6 +613,7 @@ AC_ARG_ENABLE(xdm-auth-1, AS_HELP_STRING([--disable-xdm-auth-1], [Build XDM-
AC_ARG_ENABLE(glx, AS_HELP_STRING([--disable-glx], [Build GLX extension (default: enabled)]), [GLX=$enableval], [GLX=yes])
AC_ARG_ENABLE(dri, AS_HELP_STRING([--enable-dri], [Build DRI extension (default: auto)]), [DRI=$enableval])
AC_ARG_ENABLE(dri2, AS_HELP_STRING([--enable-dri2], [Build DRI2 extension (default: auto)]), [DRI2=$enableval], [DRI2=auto])
+AC_ARG_ENABLE(dri3, AS_HELP_STRING([--enable-dri3], [Build DRI3 extension (default: auto)]), [DRI3=$enableval], [DRI3=auto])
AC_ARG_ENABLE(xinerama, AS_HELP_STRING([--disable-xinerama], [Build Xinerama extension (default: enabled)]), [XINERAMA=$enableval], [XINERAMA=yes])
AC_ARG_ENABLE(xf86vidmode, AS_HELP_STRING([--disable-xf86vidmode], [Build XF86VidMode extension (default: auto)]), [XF86VIDMODE=$enableval], [XF86VIDMODE=auto])
AC_ARG_ENABLE(xace, AS_HELP_STRING([--disable-xace], [Build X-ACE extension (default: enabled)]), [XACE=$enableval], [XACE=yes])
@@ -715,6 +716,7 @@ case $host_os in
CONFIG_UDEV_KMS=no
DGA=no
DRI2=no
+ DRI3=no
INT10MODULE=no
PCI=no
VGAHW=no
@@ -732,6 +734,7 @@ case $host_os in
VBE=no
DRM=no
DRI2=no
+ DRI3=no
if test x$XQUARTZ = xauto; then
AC_CACHE_CHECK([whether to build Xquartz],xorg_cv_Carbon_framework,[
@@ -781,6 +784,7 @@ SCRNSAVERPROTO="scrnsaverproto >= 1.1"
RESOURCEPROTO="resourceproto >= 1.2.0"
DRIPROTO="xf86driproto >= 2.1.0"
DRI2PROTO="dri2proto >= 2.8"
+DRI3PROTO="dri3proto >= 1.0"
XINERAMAPROTO="xineramaproto"
BIGFONTPROTO="xf86bigfontproto >= 1.2.0"
DGAPROTO="xf86dgaproto >= 2.0.99.1"
@@ -1113,7 +1117,22 @@ case "$DRI2,$HAVE_DRI2PROTO" in
esac
AM_CONDITIONAL(DRI2, test "x$DRI2" = xyes)
-if test "x$DRI" = xyes || test "x$DRI2" = xyes || test "x$CONFIG_UDEV_KMS" = xyes; then
+PKG_CHECK_MODULES([DRI3PROTO], $DRI3PROTO,
+ [HAVE_DRI3PROTO=yes], [HAVE_DRI3PROTO=no])
+case "$DRI3,$HAVE_DRI3PROTO" in
+ yes,no)
+ AC_MSG_ERROR([DRI3 requested, but dri3proto not found.])
+ ;;
+ yes,yes | auto,yes)
+ AC_DEFINE(DRI3, 1, [Build DRI3 extension])
+ DRI3=yes
+ DRI3_LIB='$(top_builddir)/dri3/libdri3.la'
+ SDK_REQUIRED_MODULES="$SDK_REQUIRED_MODULES $DRI3PROTO"
+ ;;
+esac
+AM_CONDITIONAL(DRI3, test "x$DRI3" = xyes)
+
+if test "x$DRI" = xyes || test "x$DRI2" = xyes || test "x$DRI3" = xyes || test "x$CONFIG_UDEV_KMS" = xyes; then
if test "x$DRM" = xyes; then
AC_DEFINE(WITH_LIBDRM, 1, [Building with libdrm support])
PKG_CHECK_MODULES([LIBDRM], $LIBDRM)
@@ -1306,6 +1325,7 @@ if test "x$XDMAUTH" = xyes; then
XDMCP_MODULES="xdmcp"
fi
fi
+REQUIRED_LIBS="$REQUIRED_LIBS xshmfence"
AC_DEFINE_DIR(COMPILEDDEFAULTFONTPATH, FONTPATH, [Default font path])
AC_DEFINE_DIR(SERVER_MISC_CONFIG_PATH, SERVERCONFIG, [Server miscellaneous config path])
@@ -1577,7 +1597,7 @@ AC_MSG_RESULT([$XVFB])
AM_CONDITIONAL(XVFB, [test "x$XVFB" = xyes])
if test "x$XVFB" = xyes; then
- XVFB_LIBS="$FB_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB"
+ XVFB_LIBS="$FB_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $DRI3_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB"
XVFB_SYS_LIBS="$XVFBMODULES_LIBS $GLX_SYS_LIBS"
AC_SUBST([XVFB_LIBS])
AC_SUBST([XVFB_SYS_LIBS])
@@ -1598,7 +1618,7 @@ if test "x$XNEST" = xyes; then
if test "x$have_xnest" = xno; then
AC_MSG_ERROR([Xnest build explicitly requested, but required modules not found.])
fi
- XNEST_LIBS="$FB_LIB $FIXES_LIB $MI_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $MAIN_LIB $DIX_LIB $OS_LIB"
+ XNEST_LIBS="$FB_LIB $FIXES_LIB $MI_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $DRI3_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $MAIN_LIB $DIX_LIB $OS_LIB"
XNEST_SYS_LIBS="$XNESTMODULES_LIBS $GLX_SYS_LIBS"
AC_SUBST([XNEST_LIBS])
AC_SUBST([XNEST_SYS_LIBS])
@@ -1623,7 +1643,7 @@ if test "x$XORG" = xyes; then
XORG_OSINCS='-I$(top_srcdir)/hw/xfree86/os-support -I$(top_srcdir)/hw/xfree86/os-support/bus -I$(top_srcdir)/os'
XORG_INCS="$XORG_DDXINCS $XORG_OSINCS"
XORG_CFLAGS="$XORGSERVER_CFLAGS -DHAVE_XORG_CONFIG_H"
- XORG_LIBS="$COMPOSITE_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $XI_LIB $XKB_LIB"
+ XORG_LIBS="$COMPOSITE_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $DRI3_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $XI_LIB $XKB_LIB"
dnl ==================================================================
dnl symbol visibility
@@ -2036,7 +2056,7 @@ if test "x$DMX" = xyes; then
fi
DMX_INCLUDES="$XEXT_INC $RENDER_INC $RECORD_INC"
XDMX_CFLAGS="$DMXMODULES_CFLAGS"
- XDMX_LIBS="$FB_LIB $MI_LIB $XEXT_LIB $RENDER_LIB $RECORD_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $MIEXT_SYNC_LIB $MIEXT_SHADOW_LIB $MIEXT_DAMAGE_LIB $COMPOSITE_LIB $DAMAGE_LIB $MAIN_LIB $DIX_LIB $CONFIG_LIB $OS_LIB $FIXES_LIB"
+ XDMX_LIBS="$FB_LIB $MI_LIB $XEXT_LIB $RENDER_LIB $RECORD_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $DRI3_LIB $MIEXT_SYNC_LIB $MIEXT_SHADOW_LIB $MIEXT_DAMAGE_LIB $COMPOSITE_LIB $DAMAGE_LIB $MAIN_LIB $DIX_LIB $CONFIG_LIB $OS_LIB $FIXES_LIB"
XDMX_SYS_LIBS="$DMXMODULES_LIBS"
AC_SUBST([XDMX_CFLAGS])
AC_SUBST([XDMX_LIBS])
@@ -2145,7 +2165,7 @@ if test "$KDRIVE" = yes; then
KDRIVE_CFLAGS="$XSERVER_CFLAGS -DHAVE_KDRIVE_CONFIG_H $TSLIB_CFLAGS"
- KDRIVE_PURE_LIBS="$FB_LIB $MI_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $OS_LIB"
+ KDRIVE_PURE_LIBS="$FB_LIB $MI_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $DRI3_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $OS_LIB"
KDRIVE_LIB='$(top_builddir)/hw/kdrive/src/libkdrive.la'
case $host_os in
*linux*)
@@ -2267,6 +2287,7 @@ Xext/Makefile
Xi/Makefile
xfixes/Makefile
exa/Makefile
+dri3/Makefile
hw/Makefile
hw/xfree86/Makefile
hw/xfree86/common/Makefile
diff --git a/dri3/Makefile.am b/dri3/Makefile.am
new file mode 100644
index 0000000..e47a734
--- /dev/null
+++ b/dri3/Makefile.am
@@ -0,0 +1,13 @@
+noinst_LTLIBRARIES = libdri3.la
+AM_CFLAGS = \
+ -DHAVE_XORG_CONFIG_H \
+ @DIX_CFLAGS@ @XORG_CFLAGS@
+
+libdri3_la_SOURCES = \
+ dri3.h \
+ dri3_priv.h \
+ dri3.c \
+ dri3_request.c \
+ dri3_screen.c
+
+sdk_HEADERS = dri3.h
diff --git a/dri3/dri3.c b/dri3/dri3.c
new file mode 100644
index 0000000..2bca7ae
--- /dev/null
+++ b/dri3/dri3.c
@@ -0,0 +1,87 @@
+/*
+ * Copyright © 2013 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#endif
+
+#include "dri3_priv.h"
+
+int dri3_request;
+DevPrivateKeyRec dri3_screen_private_key;
+DevPrivateKeyRec dri3_window_private_key;
+
+static Bool
+dri3_close_screen(ScreenPtr screen)
+{
+ dri3_screen_priv_ptr screen_priv = dri3_screen_priv(screen);
+
+ unwrap(screen_priv, screen, CloseScreen);
+
+ free(screen_priv);
+ return (*screen->CloseScreen) (screen);
+}
+
+Bool
+dri3_screen_init(ScreenPtr screen, dri3_screen_info_ptr info)
+{
+ if (!dixRegisterPrivateKey(&dri3_screen_private_key, PRIVATE_SCREEN, 0))
+ return FALSE;
+
+ if (!dri3_screen_priv(screen)) {
+ dri3_screen_priv_ptr screen_priv = calloc(1, sizeof (dri3_screen_priv_rec));
+ if (!screen_priv)
+ return FALSE;
+
+ wrap(screen_priv, screen, CloseScreen, dri3_close_screen);
+
+ screen_priv->info = info;
+
+ dixSetPrivate(&screen->devPrivates, &dri3_screen_private_key, screen_priv);
+ }
+
+ return TRUE;
+}
+
+void
+dri3_extension_init(void)
+{
+ ExtensionEntry *extension;
+ int i;
+
+ extension = AddExtension(DRI3_NAME, DRI3NumberEvents, DRI3NumberErrors,
+ proc_dri3_dispatch, sproc_dri3_dispatch,
+ NULL, StandardMinorOpcode);
+ if (!extension)
+ goto bail;
+
+ dri3_request = extension->base;
+
+ for (i = 0; i < screenInfo.numScreens; i++) {
+ if (!dri3_screen_init(screenInfo.screens[i], NULL))
+ goto bail;
+ }
+ return;
+
+bail:
+ FatalError("Cannot initialize DRI3 extension");
+}
diff --git a/dri3/dri3.h b/dri3/dri3.h
new file mode 100644
index 0000000..7774c87
--- /dev/null
+++ b/dri3/dri3.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright © 2013 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#ifndef _DRI3_H_
+#define _DRI3_H_
+
+#include <X11/extensions/dri3proto.h>
+#include <randrstr.h>
+
+#define DRI3_SCREEN_INFO_VERSION 0
+
+typedef int (*dri3_open_proc)(ScreenPtr screen,
+ RRProviderPtr provider,
+ int *fd);
+
+typedef PixmapPtr (*dri3_pixmap_from_fd_proc) (ScreenPtr screen,
+ int fd,
+ CARD16 width,
+ CARD16 height,
+ CARD16 stride,
+ CARD8 depth,
+ CARD8 bpp);
+
+typedef int (*dri3_fd_from_pixmap_proc) (ScreenPtr screen,
+ PixmapPtr pixmap,
+ CARD16 *stride,
+ CARD32 *size);
+
+typedef struct dri3_screen_info {
+ uint32_t version;
+
+ dri3_open_proc open;
+ dri3_pixmap_from_fd_proc pixmap_from_fd;
+ dri3_fd_from_pixmap_proc fd_from_pixmap;
+} dri3_screen_info_rec, *dri3_screen_info_ptr;
+
+extern _X_EXPORT Bool
+dri3_screen_init(ScreenPtr screen, dri3_screen_info_ptr info);
+
+#endif /* _DRI3_H_ */
diff --git a/dri3/dri3_event.c b/dri3/dri3_event.c
new file mode 100644
index 0000000..02f0f65
--- /dev/null
+++ b/dri3/dri3_event.c
@@ -0,0 +1,163 @@
+/*
+ * Copyright © 2013 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#endif
+
+#include "dri3_priv.h"
+
+RESTYPE dri3_event_type;
+
+static int
+dri3_free_event(pointer data, XID id)
+{
+ dri3_event_ptr dri3_event = (dri3_event_ptr) data;
+ dri3_window_priv_ptr window_priv = dri3_window_priv(dri3_event->window);
+ dri3_event_ptr *previous, current;
+
+ for (previous = &window_priv->events; (current = *previous); previous = ¤t->next) {
+ if (current == dri3_event) {
+ *previous = dri3_event->next;
+ break;
+ }
+ }
+ free((pointer) dri3_event);
+ return 1;
+
+}
+
+void
+dri3_free_events(WindowPtr window)
+{
+ dri3_window_priv_ptr window_priv = dri3_window_priv(window);
+ dri3_event_ptr event;
+
+ if (!window_priv)
+ return;
+
+ while ((event = window_priv->events))
+ FreeResource(event->id, RT_NONE);
+}
+
+static void
+dri3_event_swap(xGenericEvent *from, xGenericEvent *to)
+{
+ *to = *from;
+ swaps(&to->sequenceNumber);
+ swapl(&to->length);
+ swaps(&to->evtype);
+ switch (from->evtype) {
+ case DRI3_ConfigureNotify: {
+ xDRI3ConfigureNotify *c = (xDRI3ConfigureNotify *) to;
+
+ swapl(&c->eid);
+ swapl(&c->window);
+ swaps(&c->x);
+ swaps(&c->y);
+ swaps(&c->width);
+ swaps(&c->height);
+ swaps(&c->off_x);
+ swaps(&c->off_y);
+ swaps(&c->pixmap_width);
+ swaps(&c->pixmap_height);
+ swapl(&c->pixmap_flags);
+ break;
+ }
+ }
+}
+
+void
+dri3_send_config_notify(WindowPtr window, int x, int y, int w, int h, int bw, WindowPtr sibling)
+{
+ dri3_window_priv_ptr window_priv = dri3_window_priv(window);
+
+ if (window_priv) {
+ xDRI3ConfigureNotify cn = {
+ .type = GenericEvent,
+ .extension = dri3_request,
+ .length = (sizeof(xDRI3ConfigureNotify) - 32) >> 2,
+ .evtype = DRI3_ConfigureNotify,
+ .eid = 0,
+ .window = window->drawable.id,
+ .x = x,
+ .y = y,
+ .width = w,
+ .height = h,
+ .off_x = 0,
+ .off_y = 0,
+ .pixmap_width = w,
+ .pixmap_height = h,
+ .pixmap_flags = 0
+ };
+ dri3_event_ptr event;
+ dri3_screen_priv_ptr screen_priv = dri3_screen_priv(window->drawable.pScreen);
+
+ if (screen_priv->info && screen_priv->info->driver_config)
+ screen_priv->info->driver_config(window, &cn);
+
+ for (event = window_priv->events; event; event = event->next) {
+ if (event->mask & (1 << DRI3ConfigureNotify)) {
+ cn.eid = event->id;
+ WriteEventsToClient(event->client, 1, (xEvent *) &cn);
+ }
+ }
+ }
+}
+
+int
+dri3_select_input(ClientPtr client, XID eid, WindowPtr window, CARD32 mask)
+{
+ dri3_window_priv_ptr window_priv = dri3_window_priv(window);
+ dri3_event_ptr event;
+
+ if (!window_priv)
+ return BadAlloc;
+
+ event = calloc (1, sizeof (dri3_event_rec));
+ if (!event)
+ return BadAlloc;
+
+ event->client = client;
+ event->window = window;
+ event->id = eid;
+ event->mask = mask;
+
+ event->next = window_priv->events;
+ window_priv->events = event;
+
+ if (!AddResource(event->id, dri3_event_type, (pointer) event))
+ return BadAlloc;
+
+ return Success;
+}
+
+Bool
+dri3_event_init(void)
+{
+ dri3_event_type = CreateNewResourceType(dri3_free_event, "DRI3Event");
+ if (!dri3_event_type)
+ return FALSE;
+
+ GERegisterExtension(dri3_request, dri3_event_swap);
+ return TRUE;
+}
diff --git a/dri3/dri3_priv.h b/dri3/dri3_priv.h
new file mode 100644
index 0000000..e2fed83
--- /dev/null
+++ b/dri3/dri3_priv.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright © 2013 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#ifndef _DRI3PRIV_H_
+#define _DRI3PRIV_H_
+
+#include <X11/X.h>
+#include "scrnintstr.h"
+#include "misc.h"
+#include "list.h"
+#include "windowstr.h"
+#include "dixstruct.h"
+#include <randrstr.h>
+#include "dri3.h"
+
+extern int dri3_request;
+
+extern DevPrivateKeyRec dri3_screen_private_key;
+
+typedef struct dri3_screen_priv {
+ CloseScreenProcPtr CloseScreen;
+ ConfigNotifyProcPtr ConfigNotify;
+ DestroyWindowProcPtr DestroyWindow;
+
+ dri3_screen_info_ptr info;
+} dri3_screen_priv_rec, *dri3_screen_priv_ptr;
+
+#define wrap(priv,real,mem,func) {\
+ priv->mem = real->mem; \
+ real->mem = func; \
+}
+
+#define unwrap(priv,real,mem) {\
+ real->mem = priv->mem; \
+}
+
+static inline dri3_screen_priv_ptr
+dri3_screen_priv(ScreenPtr screen)
+{
+ return (dri3_screen_priv_ptr)dixLookupPrivate(&(screen)->devPrivates, &dri3_screen_private_key);
+}
+
+int
+proc_dri3_dispatch(ClientPtr client);
+
+int
+sproc_dri3_dispatch(ClientPtr client);
+
+/* DDX interface */
+
+int
+dri3_open(ClientPtr client, ScreenPtr screen, RRProviderPtr provider, int *fd);
+
+int
+dri3_pixmap_from_fd(PixmapPtr *ppixmap, ScreenPtr screen, int fd,
+ CARD16 width, CARD16 height, CARD16 stride, CARD8 depth, CARD8 bpp);
+
+int
+dri3_fd_from_pixmap(int *pfd, PixmapPtr pixmap, CARD16 *stride, CARD32 *size);
+
+#endif /* _DRI3PRIV_H_ */
diff --git a/dri3/dri3_request.c b/dri3/dri3_request.c
new file mode 100644
index 0000000..3ebb9d5
--- /dev/null
+++ b/dri3/dri3_request.c
@@ -0,0 +1,394 @@
+/*
+ * Copyright © 2013 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#endif
+
+#include "dri3_priv.h"
+#include <syncsrv.h>
+#include <unistd.h>
+#include <xace.h>
+#include "../Xext/syncsdk.h"
+
+static int
+proc_dri3_query_version(ClientPtr client)
+{
+ REQUEST(xDRI3QueryVersionReq);
+ xDRI3QueryVersionReply rep = {
+ .type = X_Reply,
+ .sequenceNumber = client->sequence,
+ .length = 0,
+ .majorVersion = DRI3_MAJOR,
+ .minorVersion = DRI3_MINOR
+ };
+
+ REQUEST_SIZE_MATCH(xDRI3QueryVersionReq);
+ (void) stuff;
+ if (client->swapped) {
+ swaps(&rep.sequenceNumber);
+ swapl(&rep.length);
+ swapl(&rep.majorVersion);
+ swapl(&rep.minorVersion);
+ }
+ WriteToClient(client, sizeof(rep), &rep);
+ return Success;
+}
+
+static int
+proc_dri3_open(ClientPtr client)
+{
+ REQUEST(xDRI3OpenReq);
+ xDRI3OpenReply rep = {
+ .type = X_Reply,
+ .nfd = 1,
+ .sequenceNumber = client->sequence,
+ .length = 0,
+ };
+ RRProviderPtr provider;
+ DrawablePtr drawable;
+ ScreenPtr screen;
+ int fd;
+ int status;
+
+ REQUEST_SIZE_MATCH(xDRI3OpenReq);
+
+ status = dixLookupDrawable(&drawable, stuff->drawable, client, 0, DixReadAccess);
+ if (status != Success)
+ return status;
+
+ if (stuff->provider == None)
+ provider = NULL;
+ else if (!RRProviderType) {
+ return BadMatch;
+ } else {
+ VERIFY_RR_PROVIDER(stuff->provider, provider, DixReadAccess);
+ if (drawable->pScreen != provider->pScreen)
+ return BadMatch;
+ }
+ screen = drawable->pScreen;
+
+ status = dri3_open(client, screen, provider, &fd);
+ if (status != Success)
+ return status;
+
+ if (client->swapped) {
+ swaps(&rep.sequenceNumber);
+ swapl(&rep.length);
+ }
+
+ if (WriteFdToClient(client, fd, TRUE) < 0) {
+ close(fd);
+ return BadAlloc;
+ }
+
+ WriteToClient(client, sizeof (rep), &rep);
+
+ return Success;
+}
+
+static int
+proc_dri3_pixmap_from_buffer(ClientPtr client)
+{
+ REQUEST(xDRI3PixmapFromBufferReq);
+ int fd;
+ DrawablePtr drawable;
+ PixmapPtr pixmap;
+ int rc;
+
+ SetReqFds(client, 1);
+ REQUEST_SIZE_MATCH(xDRI3PixmapFromBufferReq);
+ LEGAL_NEW_RESOURCE(stuff->pixmap, client);
+ rc = dixLookupDrawable(&drawable, stuff->drawable, client, M_ANY, DixGetAttrAccess);
+ if (rc != Success) {
+ client->errorValue = stuff->drawable;
+ return rc;
+ }
+
+ if (!stuff->width || !stuff->height) {
+ client->errorValue = 0;
+ return BadValue;
+ }
+
+ if (stuff->width > 32767 || stuff->height > 32767)
+ return BadAlloc;
+
+ if (stuff->depth != 1) {
+ DepthPtr depth = drawable->pScreen->allowedDepths;
+ int i;
+ for (i = 0; i < drawable->pScreen->numDepths; i++, depth++)
+ if (depth->depth == stuff->depth)
+ break;
+ if (i == drawable->pScreen->numDepths) {
+ client->errorValue = stuff->depth;
+ return BadValue;
+ }
+ }
+
+ fd = ReadFdFromClient(client);
+ if (fd < 0)
+ return BadValue;
+
+ rc = dri3_pixmap_from_fd(&pixmap,
+ drawable->pScreen, fd,
+ stuff->width, stuff->height,
+ stuff->stride, stuff->depth,
+ stuff->bpp);
+ close (fd);
+ if (rc != Success)
+ return rc;
+
+ pixmap->drawable.id = stuff->pixmap;
+
+ /* security creation/labeling check */
+ rc = XaceHook(XACE_RESOURCE_ACCESS, client, stuff->pixmap, RT_PIXMAP,
+ pixmap, RT_NONE, NULL, DixCreateAccess);
+
+ if (rc != Success) {
+ (*drawable->pScreen->DestroyPixmap) (pixmap);
+ return rc;
+ }
+ if (AddResource(stuff->pixmap, RT_PIXMAP, (pointer) pixmap))
+ return Success;
+
+ return Success;
+}
+
+static int
+proc_dri3_buffer_from_pixmap(ClientPtr client)
+{
+ REQUEST(xDRI3BufferFromPixmapReq);
+ xDRI3BufferFromPixmapReply rep = {
+ .type = X_Reply,
+ .nfd = 1,
+ .sequenceNumber = client->sequence,
+ .length = 0,
+ };
+ int rc;
+ int fd;
+ PixmapPtr pixmap;
+
+ REQUEST_SIZE_MATCH(xDRI3BufferFromPixmapReq);
+ rc = dixLookupResourceByType((pointer *) &pixmap, stuff->pixmap, RT_PIXMAP,
+ client, DixWriteAccess);
+ if (rc != Success) {
+ client->errorValue = stuff->pixmap;
+ return rc;
+ }
+
+ rep.width = pixmap->drawable.width;
+ rep.height = pixmap->drawable.height;
+ rep.depth = pixmap->drawable.depth;
+ rep.bpp = pixmap->drawable.bitsPerPixel;
+
+ rc = dri3_fd_from_pixmap(&fd, pixmap, &rep.stride, &rep.size);
+ if (rc != Success)
+ return rc;
+
+ if (client->swapped) {
+ swaps(&rep.sequenceNumber);
+ swapl(&rep.length);
+ swapl(&rep.size);
+ swaps(&rep.width);
+ swaps(&rep.height);
+ swaps(&rep.stride);
+ }
+ if (WriteFdToClient(client, fd, TRUE) < 0) {
+ close(fd);
+ return BadAlloc;
+ }
+
+ WriteToClient(client, sizeof(rep), &rep);
+
+ return client->noClientException;
+}
+
+static int
+proc_dri3_fence_from_fd(ClientPtr client)
+{
+ REQUEST(xDRI3FenceFromFDReq);
+ DrawablePtr drawable;
+ int fd;
+ int status;
+
+ SetReqFds(client, 1);
+ REQUEST_SIZE_MATCH(xDRI3FenceFromFDReq);
+ LEGAL_NEW_RESOURCE(stuff->fence, client);
+
+ status = dixLookupDrawable(&drawable, stuff->drawable, client, M_ANY, DixGetAttrAccess);
+ if (status != Success)
+ return status;
+
+ fd = ReadFdFromClient(client);
+ if (fd < 0)
+ return BadValue;
+
+ status = SyncCreateFenceFromFD(client, drawable, stuff->fence,
+ fd, stuff->initially_triggered);
+
+ return status;
+}
+
+static int
+proc_dri3_fd_from_fence(ClientPtr client)
+{
+ REQUEST(xDRI3FDFromFenceReq);
+ xDRI3FDFromFenceReply rep = {
+ .type = X_Reply,
+ .nfd = 1,
+ .sequenceNumber = client->sequence,
+ .length = 0,
+ };
+ DrawablePtr drawable;
+ int fd;
+ int status;
+ SyncFence *fence;
+
+ REQUEST_SIZE_MATCH(xDRI3FDFromFenceReq);
+
+ status = dixLookupDrawable(&drawable, stuff->drawable, client, M_ANY, DixGetAttrAccess);
+ if (status != Success)
+ return status;
+ status = SyncVerifyFence(&fence, stuff->fence, client, DixWriteAccess);
+ if (status != Success)
+ return status;
+
+ fd = SyncFDFromFence(client, drawable, fence);
+ if (fd < 0)
+ return BadMatch;
+
+ if (client->swapped) {
+ swaps(&rep.sequenceNumber);
+ swapl(&rep.length);
+ }
+ if (WriteFdToClient(client, fd, FALSE) < 0)
+ return BadAlloc;
+
+ WriteToClient(client, sizeof(rep), &rep);
+
+ return client->noClientException;
+}
+
+int (*proc_dri3_vector[DRI3NumberRequests]) (ClientPtr) = {
+ proc_dri3_query_version, /* 0 */
+ proc_dri3_open, /* 1 */
+ proc_dri3_pixmap_from_buffer, /* 2 */
+ proc_dri3_buffer_from_pixmap, /* 3 */
+ proc_dri3_fence_from_fd, /* 4 */
+ proc_dri3_fd_from_fence, /* 5 */
+};
+
+int
+proc_dri3_dispatch(ClientPtr client)
+{
+ REQUEST(xReq);
+ if (stuff->data >= DRI3NumberRequests || !proc_dri3_vector[stuff->data])
+ return BadRequest;
+ return (*proc_dri3_vector[stuff->data]) (client);
+}
+
+static int
+sproc_dri3_query_version(ClientPtr client)
+{
+ REQUEST(xDRI3QueryVersionReq);
+
+ swaps(&stuff->length);
+ swapl(&stuff->majorVersion);
+ swapl(&stuff->minorVersion);
+ return (*proc_dri3_vector[stuff->dri3ReqType]) (client);
+}
+
+static int
+sproc_dri3_open(ClientPtr client)
+{
+ REQUEST(xDRI3OpenReq);
+
+ swaps(&stuff->length);
+ swapl(&stuff->drawable);
+ swapl(&stuff->provider);
+ return (*proc_dri3_vector[stuff->dri3ReqType]) (client);
+}
+
+static int
+sproc_dri3_pixmap_from_buffer(ClientPtr client)
+{
+ REQUEST(xDRI3PixmapFromBufferReq);
+
+ swaps(&stuff->length);
+ swapl(&stuff->pixmap);
+ swapl(&stuff->drawable);
+ swapl(&stuff->size);
+ swaps(&stuff->width);
+ swaps(&stuff->height);
+ swaps(&stuff->stride);
+ return (*proc_dri3_vector[stuff->dri3ReqType]) (client);
+}
+
+static int
+sproc_dri3_buffer_from_pixmap(ClientPtr client)
+{
+ REQUEST(xDRI3BufferFromPixmapReq);
+
+ swaps(&stuff->length);
+ swapl(&stuff->pixmap);
+ return (*proc_dri3_vector[stuff->dri3ReqType]) (client);
+}
+
+static int
+sproc_dri3_fence_from_fd(ClientPtr client)
+{
+ REQUEST(xDRI3FenceFromFDReq);
+
+ swaps(&stuff->length);
+ swapl(&stuff->drawable);
+ swapl(&stuff->fence);
+ return (*proc_dri3_vector[stuff->dri3ReqType]) (client);
+}
+
+static int
+sproc_dri3_fd_from_fence(ClientPtr client)
+{
+ REQUEST(xDRI3FDFromFenceReq);
+
+ swaps(&stuff->length);
+ swapl(&stuff->drawable);
+ swapl(&stuff->fence);
+ return (*proc_dri3_vector[stuff->dri3ReqType]) (client);
+}
+
+int (*sproc_dri3_vector[DRI3NumberRequests]) (ClientPtr) = {
+ sproc_dri3_query_version, /* 0 */
+ sproc_dri3_open, /* 1 */
+ sproc_dri3_pixmap_from_buffer, /* 2 */
+ sproc_dri3_buffer_from_pixmap, /* 3 */
+ sproc_dri3_fence_from_fd, /* 4 */
+ sproc_dri3_fd_from_fence, /* 5 */
+};
+
+int
+sproc_dri3_dispatch(ClientPtr client)
+{
+ REQUEST(xReq);
+ if (stuff->data >= DRI3NumberRequests || !sproc_dri3_vector[stuff->data])
+ return BadRequest;
+ return (*sproc_dri3_vector[stuff->data]) (client);
+}
diff --git a/dri3/dri3_screen.c b/dri3/dri3_screen.c
new file mode 100644
index 0000000..cf2735b
--- /dev/null
+++ b/dri3/dri3_screen.c
@@ -0,0 +1,80 @@
+/*
+ * Copyright © 2013 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#endif
+
+#include "dri3_priv.h"
+#include <syncsdk.h>
+#include <misync.h>
+#include <misyncshm.h>
+#include <randrstr.h>
+
+int
+dri3_open(ClientPtr client, ScreenPtr screen, RRProviderPtr provider, int *fd)
+{
+ dri3_screen_priv_ptr ds = dri3_screen_priv(screen);
+ dri3_screen_info_ptr info = ds->info;
+ int rc;
+
+ if (!info || !info->open)
+ return BadMatch;
+
+ rc = (*info->open) (screen, provider, fd);
+ if (rc != Success)
+ return rc;
+
+ return Success;
+}
+
+int
+dri3_pixmap_from_fd(PixmapPtr *ppixmap, ScreenPtr screen, int fd,
+ CARD16 width, CARD16 height, CARD16 stride, CARD8 depth, CARD8 bpp)
+{
+ dri3_screen_priv_ptr ds = dri3_screen_priv(screen);
+ dri3_screen_info_ptr info = ds->info;
+ PixmapPtr pixmap;
+
+ pixmap = (*info->pixmap_from_fd) (screen, fd, width, height, stride, depth, bpp);
+ if (!pixmap)
+ return BadAlloc;
+
+ *ppixmap = pixmap;
+ return Success;
+}
+
+int
+dri3_fd_from_pixmap(int *pfd, PixmapPtr pixmap, CARD16 *stride, CARD32 *size)
+{
+ ScreenPtr screen = pixmap->drawable.pScreen;
+ dri3_screen_priv_ptr ds = dri3_screen_priv(screen);
+ dri3_screen_info_ptr info = ds->info;
+ int fd;
+
+ fd = (*info->fd_from_pixmap)(screen, pixmap, stride, size);
+ if (fd < 0)
+ return BadAlloc;
+ *pfd = fd;
+ return Success;
+}
+
diff --git a/dri3/dri3int.h b/dri3/dri3int.h
new file mode 100644
index 0000000..7f53eba
--- /dev/null
+++ b/dri3/dri3int.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright © 2011 Daniel Stone
+ *
+ * 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: Daniel Stone <daniel at fooishbar.org>
+ */
+
+extern Bool DRI2ModuleSetup(void);
diff --git a/hw/dmx/dmxinit.c b/hw/dmx/dmxinit.c
index 65416ed..bd868a0 100644
--- a/hw/dmx/dmxinit.c
+++ b/hw/dmx/dmxinit.c
@@ -109,6 +109,8 @@ Bool dmxGLXSyncSwap = FALSE;
Bool dmxGLXFinishSwap = FALSE;
#endif
+RESTYPE RRProviderType = 0;
+
Bool dmxIgnoreBadFontPaths = FALSE;
Bool dmxAddRemoveScreens = FALSE;
diff --git a/hw/xfree86/Makefile.am b/hw/xfree86/Makefile.am
index 59cfb5f..eea16a8 100644
--- a/hw/xfree86/Makefile.am
+++ b/hw/xfree86/Makefile.am
@@ -41,7 +41,7 @@ nodist_Xorg_SOURCES = sdksyms.c
AM_CFLAGS = $(DIX_CFLAGS) @XORG_CFLAGS@
AM_CPPFLAGS = $(XORG_INCS) -I$(srcdir)/parser -I$(top_srcdir)/miext/cw \
-I$(srcdir)/ddc -I$(srcdir)/i2c -I$(srcdir)/modes -I$(srcdir)/ramdac \
- -I$(srcdir)/dri -I$(srcdir)/dri2
+ -I$(srcdir)/dri -I$(srcdir)/dri2 -I$(top_srcdir)/dri3
LOCAL_LIBS = \
$(MAIN_LIB) \
@@ -59,6 +59,8 @@ LOCAL_LIBS = \
dixmods/libxorgxkb.la \
$(DRI_LIB) \
$(DRI2_LIB) \
+ $(top_builddir)/dri3/libdri3.la \
+ $(top_builddir)/miext/sync/libsync.la \
$(top_builddir)/mi/libmi.la \
$(top_builddir)/os/libos.la
Xorg_LDADD = \
diff --git a/hw/xfree86/sdksyms.sh b/hw/xfree86/sdksyms.sh
index 48b48b5..7c9734c 100755
--- a/hw/xfree86/sdksyms.sh
+++ b/hw/xfree86/sdksyms.sh
@@ -99,6 +99,7 @@ cat > sdksyms.c << EOF
# include "dri2.h"
#endif
+# include "dri3.h"
/* hw/xfree86/vgahw/Makefile.am -- module */
/*
diff --git a/include/dix-config.h.in b/include/dix-config.h.in
index a643dfc..d96da6a 100644
--- a/include/dix-config.h.in
+++ b/include/dix-config.h.in
@@ -39,6 +39,9 @@
/* Build DPMS extension */
#undef DPMSExtension
+/* Build DRI3 extension */
+#undef DRI3
+
/* Build GLX extension */
#undef GLXEXT
diff --git a/include/extinit.h b/include/extinit.h
index 6d67bf2..bdb149c 100644
--- a/include/extinit.h
+++ b/include/extinit.h
@@ -176,4 +176,9 @@ extern void XvExtensionInit(void);
extern void XvMCExtensionInit(void);
#endif
+#if defined(DRI3)
+#include <X11/extensions/dri3proto.h>
+extern void dri3_extension_init(void);
+#endif
+
#endif
diff --git a/include/xorg-server.h.in b/include/xorg-server.h.in
index 81935be..5b3b664 100644
--- a/include/xorg-server.h.in
+++ b/include/xorg-server.h.in
@@ -28,6 +28,9 @@
/* Build DPMS extension */
#undef DPMSExtension
+/* Build DRI3 extension */
+#undef DRI3
+
/* Build GLX extension */
#undef GLXEXT
diff --git a/mi/miinitext.c b/mi/miinitext.c
index 145da38..e49948b 100644
--- a/mi/miinitext.c
+++ b/mi/miinitext.c
@@ -287,6 +287,7 @@ static ExtensionModule staticExtensions[] = {
#ifdef DPMSExtension
{DPMSExtensionInit, DPMSExtensionName, &noDPMSExtension},
#endif
+ {dri3_extension_init, DRI3_NAME, NULL},
#ifdef RES
{ResExtensionInit, XRES_NAME, &noResExtension},
#endif
diff --git a/miext/sync/Makefile.am b/miext/sync/Makefile.am
index 9aa1ba5..e25ceac 100644
--- a/miext/sync/Makefile.am
+++ b/miext/sync/Makefile.am
@@ -5,10 +5,11 @@ AM_CFLAGS = $(DIX_CFLAGS)
AM_CPPFLAGS =
if XORG
-sdk_HEADERS = misync.h misyncstr.h
+sdk_HEADERS = misync.h misyncstr.h misyncshm.h
endif
libsync_la_SOURCES = \
misync.c \
misync.h \
+ misyncshm.c \
misyncstr.h
diff --git a/miext/sync/misync.c b/miext/sync/misync.c
index f380547..3d03d1b 100644
--- a/miext/sync/misync.c
+++ b/miext/sync/misync.c
@@ -29,20 +29,7 @@
#include "misync.h"
#include "misyncstr.h"
-static DevPrivateKeyRec syncScreenPrivateKeyRec;
-static DevPrivateKey syncScreenPrivateKey = &syncScreenPrivateKeyRec;
-
-#define SYNC_SCREEN_PRIV(pScreen) \
- (SyncScreenPrivPtr) dixLookupPrivate(&pScreen->devPrivates, \
- syncScreenPrivateKey)
-
-typedef struct _syncScreenPriv {
- /* Wrappable sync-specific screen functions */
- SyncScreenFuncsRec funcs;
-
- /* Wrapped screen functions */
- CloseScreenProcPtr CloseScreen;
-} SyncScreenPrivRec, *SyncScreenPrivPtr;
+DevPrivateKeyRec miSyncScreenPrivateKey;
/* Default implementations of the sync screen functions */
void
@@ -62,25 +49,25 @@ miSyncScreenDestroyFence(ScreenPtr pScreen, SyncFence * pFence)
}
/* Default implementations of the per-object functions */
-static void
+void
miSyncFenceSetTriggered(SyncFence * pFence)
{
pFence->triggered = TRUE;
}
-static void
+void
miSyncFenceReset(SyncFence * pFence)
{
pFence->triggered = FALSE;
}
-static Bool
+Bool
miSyncFenceCheckTriggered(SyncFence * pFence)
{
return pFence->triggered;
}
-static void
+void
miSyncFenceAddTrigger(SyncTrigger * pTrigger)
{
(void) pTrigger;
@@ -88,7 +75,7 @@ miSyncFenceAddTrigger(SyncTrigger * pTrigger)
return;
}
-static void
+void
miSyncFenceDeleteTrigger(SyncTrigger * pTrigger)
{
(void) pTrigger;
@@ -182,8 +169,8 @@ miSyncSetup(ScreenPtr pScreen)
&miSyncScreenDestroyFence
};
- if (!dixPrivateKeyRegistered(syncScreenPrivateKey)) {
- if (!dixRegisterPrivateKey(syncScreenPrivateKey, PRIVATE_SCREEN,
+ if (!dixPrivateKeyRegistered(&miSyncScreenPrivateKey)) {
+ if (!dixRegisterPrivateKey(&miSyncScreenPrivateKey, PRIVATE_SCREEN,
sizeof(SyncScreenPrivRec)))
return FALSE;
}
diff --git a/miext/sync/misync.h b/miext/sync/misync.h
index deebb82..f63ec2b 100644
--- a/miext/sync/misync.h
+++ b/miext/sync/misync.h
@@ -76,4 +76,25 @@ extern _X_EXPORT SyncScreenFuncsPtr miSyncGetScreenFuncs(ScreenPtr pScreen);
extern _X_EXPORT Bool
miSyncSetup(ScreenPtr pScreen);
+Bool
+miSyncFenceCheckTriggered(SyncFence * pFence);
+
+void
+miSyncFenceSetTriggered(SyncFence * pFence);
+
+void
+miSyncFenceReset(SyncFence * pFence);
+
+void
+miSyncFenceAddTrigger(SyncTrigger * pTrigger);
+
+void
+miSyncFenceDeleteTrigger(SyncTrigger * pTrigger);
+
+int
+miSyncInitFenceFromFD(DrawablePtr pDraw, SyncFence *pFence, int fd, BOOL initially_triggered);
+
+int
+miSyncFDFromFence(DrawablePtr pDraw, SyncFence *pFence);
+
#endif /* _MISYNC_H_ */
diff --git a/miext/sync/misyncshm.c b/miext/sync/misyncshm.c
new file mode 100644
index 0000000..ddd15ae
--- /dev/null
+++ b/miext/sync/misyncshm.c
@@ -0,0 +1,176 @@
+/*
+ * Copyright © 2013 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include "scrnintstr.h"
+#include "misync.h"
+#include "misyncstr.h"
+#include "misyncshm.h"
+#include "pixmapstr.h"
+#include <sys/mman.h>
+#include <unistd.h>
+#include <X11/xshmfence.h>
+
+static DevPrivateKeyRec syncShmFencePrivateKey;
+
+typedef struct _SyncShmFencePrivate {
+ int32_t *fence;
+ int fd;
+} SyncShmFencePrivateRec, *SyncShmFencePrivatePtr;
+
+#define SYNC_FENCE_PRIV(pFence) \
+ (SyncShmFencePrivatePtr) dixLookupPrivate(&pFence->devPrivates, &syncShmFencePrivateKey)
+
+static void
+miSyncShmFenceSetTriggered(SyncFence * pFence)
+{
+ SyncShmFencePrivatePtr pPriv = SYNC_FENCE_PRIV(pFence);
+
+ if (pPriv->fence)
+ xshmfence_trigger(pPriv->fence);
+ miSyncFenceSetTriggered(pFence);
+}
+
+static void
+miSyncShmFenceReset(SyncFence * pFence)
+{
+ SyncShmFencePrivatePtr pPriv = SYNC_FENCE_PRIV(pFence);
+
+ if (pPriv->fence)
+ xshmfence_reset(pPriv->fence);
+ miSyncFenceReset(pFence);
+}
+
+static Bool
+miSyncShmFenceCheckTriggered(SyncFence * pFence)
+{
+ SyncShmFencePrivatePtr pPriv = SYNC_FENCE_PRIV(pFence);
+
+ if (pPriv->fence)
+ return xshmfence_query(pPriv->fence);
+ else
+ return miSyncFenceCheckTriggered(pFence);
+}
+
+static void
+miSyncShmFenceAddTrigger(SyncTrigger * pTrigger)
+{
+ miSyncFenceAddTrigger(pTrigger);
+}
+
+static void
+miSyncShmFenceDeleteTrigger(SyncTrigger * pTrigger)
+{
+ miSyncFenceDeleteTrigger(pTrigger);
+}
+
+static const SyncFenceFuncsRec miSyncShmFenceFuncs = {
+ &miSyncShmFenceSetTriggered,
+ &miSyncShmFenceReset,
+ &miSyncShmFenceCheckTriggered,
+ &miSyncShmFenceAddTrigger,
+ &miSyncShmFenceDeleteTrigger
+};
+
+static void
+miSyncShmScreenCreateFence(ScreenPtr pScreen, SyncFence * pFence,
+ Bool initially_triggered)
+{
+ SyncShmFencePrivatePtr pPriv = SYNC_FENCE_PRIV(pFence);
+
+ pPriv->fence = NULL;
+ miSyncScreenCreateFence(pScreen, pFence, initially_triggered);
+ pFence->funcs = miSyncShmFenceFuncs;
+}
+
+static void
+miSyncShmScreenDestroyFence(ScreenPtr pScreen, SyncFence * pFence)
+{
+ SyncShmFencePrivatePtr pPriv = SYNC_FENCE_PRIV(pFence);
+
+ if (pPriv->fence) {
+ xshmfence_trigger(pPriv->fence);
+ xshmfence_unmap_shm(pPriv->fence);
+ close(pPriv->fd);
+ }
+ miSyncScreenDestroyFence(pScreen, pFence);
+}
+
+int
+miSyncInitFenceFromFD(DrawablePtr pDraw, SyncFence *pFence, int fd, BOOL initially_triggered)
+
+{
+ SyncShmFencePrivatePtr pPriv = SYNC_FENCE_PRIV(pFence);
+
+ miSyncInitFence(pDraw->pScreen, pFence, initially_triggered);
+
+ pPriv->fence = xshmfence_map_shm(fd);
+ if (pPriv->fence) {
+ pPriv->fd = fd;
+ return Success;
+ }
+ else
+ close(fd);
+ return BadValue;
+}
+
+int
+miSyncFDFromFence(DrawablePtr pDraw, SyncFence *pFence)
+{
+ SyncShmFencePrivatePtr pPriv = SYNC_FENCE_PRIV(pFence);
+
+ if (!pPriv->fence) {
+ pPriv->fd = xshmfence_alloc_shm();
+ if (pPriv->fd < 0)
+ return -1;
+ pPriv->fence = xshmfence_map_shm(pPriv->fd);
+ if (!pPriv->fence) {
+ close (pPriv->fd);
+ return -1;
+ }
+ }
+ return pPriv->fd;
+}
+
+_X_EXPORT Bool miSyncShmScreenInit(ScreenPtr pScreen)
+{
+ SyncScreenFuncsPtr funcs;
+
+ if (!miSyncSetup(pScreen))
+ return FALSE;
+
+ if (!dixPrivateKeyRegistered(&syncShmFencePrivateKey)) {
+ if (!dixRegisterPrivateKey(&syncShmFencePrivateKey, PRIVATE_SYNC_FENCE,
+ sizeof(SyncShmFencePrivateRec)))
+ return FALSE;
+ }
+
+ funcs = miSyncGetScreenFuncs(pScreen);
+
+ funcs->CreateFence = miSyncShmScreenCreateFence;
+ funcs->DestroyFence = miSyncShmScreenDestroyFence;
+ return TRUE;
+}
+
diff --git a/miext/sync/misyncshm.h b/miext/sync/misyncshm.h
new file mode 100644
index 0000000..4edbb50
--- /dev/null
+++ b/miext/sync/misyncshm.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright © 2013 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#ifndef _MISYNCSHM_H_
+#define _MISYNCSYM_H_
+
+extern _X_EXPORT Bool miSyncShmScreenInit(ScreenPtr pScreen);
+
+#endif /* _MISYNCSHM_H_ */
diff --git a/miext/sync/misyncstr.h b/miext/sync/misyncstr.h
index e19256f..b5bf6fd 100644
--- a/miext/sync/misyncstr.h
+++ b/miext/sync/misyncstr.h
@@ -29,6 +29,7 @@
#define _MISYNCSTR_H_
#include "dix.h"
+#include "scrnintstr.h"
#include <X11/extensions/syncconst.h>
#define CARD64 XSyncValue /* XXX temporary! need real 64 bit values for Alpha */
@@ -79,4 +80,18 @@ typedef struct _SyncTriggerList {
struct _SyncTriggerList *next;
} SyncTriggerList;
+extern DevPrivateKeyRec miSyncScreenPrivateKey;
+
+#define SYNC_SCREEN_PRIV(pScreen) \
+ (SyncScreenPrivPtr) dixLookupPrivate(&pScreen->devPrivates, \
+ &miSyncScreenPrivateKey)
+
+typedef struct _syncScreenPriv {
+ /* Wrappable sync-specific screen functions */
+ SyncScreenFuncsRec funcs;
+
+ /* Wrapped screen functions */
+ CloseScreenProcPtr CloseScreen;
+} SyncScreenPrivRec, *SyncScreenPrivPtr;
+
#endif /* _MISYNCSTR_H_ */
diff --git a/test/Makefile.am b/test/Makefile.am
index eff0c9d..e59c412 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -19,7 +19,7 @@ AM_CPPFLAGS += -I$(top_srcdir)/hw/xfree86/parser \
-I$(top_srcdir)/hw/xfree86/ddc \
-I$(top_srcdir)/hw/xfree86/i2c -I$(top_srcdir)/hw/xfree86/modes \
-I$(top_srcdir)/hw/xfree86/ramdac -I$(top_srcdir)/hw/xfree86/dri \
- -I$(top_srcdir)/hw/xfree86/dri2
+ -I$(top_srcdir)/hw/xfree86/dri2 -I$(top_srcdir)/dri3
endif
TEST_LDADD=libxservertest.la $(XORG_SYS_LIBS) $(XSERVER_SYS_LIBS) $(GLX_SYS_LIBS)
@@ -64,6 +64,10 @@ if DRI2
libxservertest_la_LIBADD += $(top_builddir)/hw/xfree86/dri2/libdri2.la
endif
+if DRI3
+libxservertest_la_LIBADD += $(top_builddir)/dri3/libdri3.la
+endif
+
else
nodist_libxservertest_la_SOURCES = \
ddxstubs.c \
@@ -105,6 +109,11 @@ libxservertest_la_LIBADD += \
$(top_builddir)/record/librecord.la
endif
+if DRI3
+libxservertest_la_LIBADD += \
+ $(top_builddir)/dri3/libdri3.la
+endif
+
if XQUARTZ
libxservertest_la_LIBADD += \
$(top_builddir)/miext/rootless/librootless.la
commit fdec793cdc2ef9a6ea66b311cb1068a7bd4a3be3
Author: Keith Packard <keithp at keithp.com>
Date: Thu Jan 17 13:46:55 2013 -0800
Add support for MIT-SHM AttachFd request
This passes a file descriptor from the client to the server, which is
then mmap'd
Signed-off-by: Keith Packard <keithp at keithp.com>
Reviewed-by: Adam Jackson <ajax at redhat.com>
diff --git a/Xext/shm.c b/Xext/shm.c
index f6995cc..1a70260 100644
--- a/Xext/shm.c
+++ b/Xext/shm.c
@@ -53,6 +53,7 @@ in this Software without prior written authorization from The Open Group.
#include "xace.h"
#include <X11/extensions/shmproto.h>
#include <X11/Xfuncproto.h>
+#include <sys/mman.h>
#include "protocol-versions.h"
/* Needed for Solaris cross-zone shared memory extension */
@@ -382,8 +383,10 @@ ProcShmAttach(ClientPtr client)
client->errorValue = stuff->readOnly;
return BadValue;
}
- for (shmdesc = Shmsegs;
- shmdesc && (shmdesc->shmid != stuff->shmid); shmdesc = shmdesc->next);
+ for (shmdesc = Shmsegs; shmdesc; shmdesc = shmdesc->next) {
+ if (!shmdesc->is_fd && shmdesc->shmid == stuff->shmid)
+ break;
+ }
if (shmdesc) {
if (!stuff->readOnly && !shmdesc->writable)
return BadAccess;
@@ -393,6 +396,7 @@ ProcShmAttach(ClientPtr client)
shmdesc = malloc(sizeof(ShmDescRec));
if (!shmdesc)
return BadAlloc;
+ shmdesc->is_fd = FALSE;
shmdesc->addr = shmat(stuff->shmid, 0,
stuff->readOnly ? SHM_RDONLY : 0);
if ((shmdesc->addr == ((char *) -1)) || SHMSTAT(stuff->shmid, &buf)) {
@@ -431,7 +435,10 @@ ShmDetachSegment(pointer value, /* must conform to DeleteType */
if (--shmdesc->refcnt)
return TRUE;
- shmdt(shmdesc->addr);
+ if (shmdesc->is_fd)
+ munmap(shmdesc->addr, shmdesc->size);
+ else
+ shmdt(shmdesc->addr);
for (prev = &Shmsegs; *prev != shmdesc; prev = &(*prev)->next);
*prev = shmdesc->next;
free(shmdesc);
@@ -1088,6 +1095,122 @@ ProcShmCreatePixmap(ClientPtr client)
}
static int
+ProcShmAttachFd(ClientPtr client)
+{
+ int fd;
+ ShmDescPtr shmdesc;
+ REQUEST(xShmAttachFdReq);
+ struct stat statb;
+
+ SetReqFds(client, 1);
+ REQUEST_SIZE_MATCH(xShmAttachFdReq);
+ LEGAL_NEW_RESOURCE(stuff->shmseg, client);
+ if ((stuff->readOnly != xTrue) && (stuff->readOnly != xFalse)) {
+ client->errorValue = stuff->readOnly;
+ return BadValue;
+ }
+ fd = ReadFdFromClient(client);
+ if (fd < 0)
+ return BadMatch;
+
+ if (fstat(fd, &statb) < 0 || statb.st_size == 0) {
+ close(fd);
+ return BadMatch;
+ }
+
+ shmdesc = malloc(sizeof(ShmDescRec));
+ if (!shmdesc) {
+ close(fd);
+ return BadAlloc;
+ }
+ shmdesc->is_fd = TRUE;
+ shmdesc->addr = mmap(NULL, statb.st_size,
+ stuff->readOnly ? PROT_READ : PROT_READ|PROT_WRITE,
+ MAP_SHARED,
+ fd, 0);
+
+ close(fd);
+ if ((shmdesc->addr == ((char *) -1))) {
+ free(shmdesc);
+ return BadAccess;
+ }
+
+ shmdesc->refcnt = 1;
+ shmdesc->writable = !stuff->readOnly;
+ shmdesc->size = statb.st_size;
+ shmdesc->next = Shmsegs;
+ Shmsegs = shmdesc;
+
+ if (!AddResource(stuff->shmseg, ShmSegType, (pointer) shmdesc))
+ return BadAlloc;
+ return Success;
+}
+
+static int
+ProcShmCreateSegment(ClientPtr client)
+{
+ int fd;
+ ShmDescPtr shmdesc;
+ REQUEST(xShmCreateSegmentReq);
+ xShmCreateSegmentReply rep = {
+ .type = X_Reply,
+ .nfd = 1,
+ .sequenceNumber = client->sequence,
+ .length = 0,
+ };
+ char template[] = "/tmp/shm-XXXXXX";
+
+ REQUEST_SIZE_MATCH(xShmCreateSegmentReq);
+ if ((stuff->readOnly != xTrue) && (stuff->readOnly != xFalse)) {
+ client->errorValue = stuff->readOnly;
+ return BadValue;
+ }
+ fd = mkstemp(template);
+ if (fd < 0)
+ return BadAlloc;
+ unlink(template);
+ if (ftruncate(fd, stuff->size) < 0) {
+ close(fd);
+ return BadAlloc;
+ }
+ shmdesc = malloc(sizeof(ShmDescRec));
+ if (!shmdesc) {
+ close(fd);
+ return BadAlloc;
+ }
+ shmdesc->is_fd = TRUE;
+ shmdesc->addr = mmap(NULL, stuff->size,
+ stuff->readOnly ? PROT_READ : PROT_READ|PROT_WRITE,
+ MAP_SHARED,
+ fd, 0);
+
+ if ((shmdesc->addr == ((char *) -1))) {
+ close(fd);
+ free(shmdesc);
+ return BadAccess;
+ }
+
+ shmdesc->refcnt = 1;
+ shmdesc->writable = !stuff->readOnly;
+ shmdesc->size = stuff->size;
+ shmdesc->next = Shmsegs;
+ Shmsegs = shmdesc;
+
+ if (!AddResource(stuff->shmseg, ShmSegType, (pointer) shmdesc)) {
+ close(fd);
+ return BadAlloc;
+ }
+
+ if (WriteFdToClient(client, fd, TRUE) < 0) {
+ FreeResource(stuff->shmseg, RT_NONE);
+ close(fd);
+ return BadAlloc;
+ }
+ WriteToClient(client, sizeof (xShmCreateSegmentReply), &rep);
+ return Success;
+}
+
+static int
ProcShmDispatch(ClientPtr client)
{
REQUEST(xReq);
@@ -1116,6 +1239,10 @@ ProcShmDispatch(ClientPtr client)
return ProcPanoramiXShmCreatePixmap(client);
#endif
return ProcShmCreatePixmap(client);
+ case X_ShmAttachFd:
+ return ProcShmAttachFd(client);
+ case X_ShmCreateSegment:
+ return ProcShmCreateSegment(client);
default:
return BadRequest;
}
@@ -1217,6 +1344,28 @@ SProcShmCreatePixmap(ClientPtr client)
}
static int
+SProcShmAttachFd(ClientPtr client)
+{
+ REQUEST(xShmAttachFdReq);
+ SetReqFds(client, 1);
+ swaps(&stuff->length);
+ REQUEST_SIZE_MATCH(xShmAttachFdReq);
+ swapl(&stuff->shmseg);
+ return ProcShmAttachFd(client);
+}
+
+static int
+SProcShmCreateSegment(ClientPtr client)
+{
+ REQUEST(xShmCreateSegmentReq);
+ swaps(&stuff->length);
+ REQUEST_SIZE_MATCH(xShmCreateSegmentReq);
+ swapl(&stuff->shmseg);
+ swapl(&stuff->size);
+ return ProcShmCreateSegment(client);
+}
+
+static int
SProcShmDispatch(ClientPtr client)
{
REQUEST(xReq);
@@ -1233,6 +1382,10 @@ SProcShmDispatch(ClientPtr client)
return SProcShmGetImage(client);
case X_ShmCreatePixmap:
return SProcShmCreatePixmap(client);
+ case X_ShmAttachFd:
+ return SProcShmAttachFd(client);
+ case X_ShmCreateSegment:
+ return SProcShmCreateSegment(client);
default:
return BadRequest;
}
diff --git a/Xext/shmint.h b/Xext/shmint.h
index 9002ce5..db35fbb 100644
--- a/Xext/shmint.h
+++ b/Xext/shmint.h
@@ -61,6 +61,7 @@ typedef struct _ShmDesc {
int shmid;
int refcnt;
char *addr;
+ Bool is_fd;
Bool writable;
unsigned long size;
} ShmDescRec, *ShmDescPtr;
diff --git a/include/os.h b/include/os.h
index b654a0d..11b2198 100644
--- a/include/os.h
+++ b/include/os.h
@@ -100,6 +100,8 @@ extern _X_EXPORT int ReadRequestFromClient(ClientPtr /*client */ );
extern _X_EXPORT int ReadFdFromClient(ClientPtr client);
+extern _X_EXPORT int WriteFdToClient(ClientPtr client, int fd, Bool do_close);
+
extern _X_EXPORT Bool InsertFakeRequest(ClientPtr /*client */ ,
char * /*data */ ,
int /*count */ );
diff --git a/os/io.c b/os/io.c
index 83df6e9..a20faa5 100644
--- a/os/io.c
+++ b/os/io.c
@@ -506,6 +506,14 @@ ReadFdFromClient(ClientPtr client)
return fd;
}
+int
+WriteFdToClient(ClientPtr client, int fd, Bool do_close)
+{
+ OsCommPtr oc = (OsCommPtr) client->osPrivate;
+
+ return _XSERVTransSendFd(oc->trans_conn, fd, do_close);
+}
+
/*****************************************************************
* InsertFakeRequest
* Splice a consed up (possibly partial) request in as the next request.
commit 9fd35daa3160fd36f00ed354bfcbefefa1353cce
Author: Keith Packard <keithp at keithp.com>
Date: Thu Jan 17 13:43:02 2013 -0800
Add interfaces to get FDs from clients over the socket
This adds two interfaces:
void SetReqFds(ClientPtr client, int req_fds)
Marks the number of file descriptors expected for this
request. Call this before any request processing so that
any un-retrieved file descriptors will be closed
automatically.
int ReadFdFromClient(ClientPtr client)
Reads the next queued file descriptor from the connection. If
this request is not expecting any more file descriptors, or
if there are no more file descriptors available from the
connection, then this will return -1.
Signed-off-by: Keith Packard <keithp at keithp.com>
Reviewed-by: Adam Jackson <ajax at redhat.com>
diff --git a/include/dixstruct.h b/include/dixstruct.h
index 7711cde..456e633 100644
--- a/include/dixstruct.h
+++ b/include/dixstruct.h
@@ -110,8 +110,16 @@ typedef struct _Client {
DeviceIntPtr clientPtr;
ClientIdPtr clientIds;
+ int req_fds;
} ClientRec;
+static inline void
+SetReqFds(ClientPtr client, int req_fds) {
+ if (client->req_fds != 0 && req_fds != client->req_fds)
+ LogMessage(X_ERROR, "Mismatching number of request fds %d != %d\n", req_fds, client->req_fds);
+ client->req_fds = req_fds;
+}
+
/*
* Scheduling interface
*/
diff --git a/include/os.h b/include/os.h
index 3840ab9..b654a0d 100644
--- a/include/os.h
+++ b/include/os.h
@@ -98,6 +98,8 @@ extern _X_EXPORT int WaitForSomething(int * /*pClientsReady */
extern _X_EXPORT int ReadRequestFromClient(ClientPtr /*client */ );
+extern _X_EXPORT int ReadFdFromClient(ClientPtr client);
+
extern _X_EXPORT Bool InsertFakeRequest(ClientPtr /*client */ ,
char * /*data */ ,
int /*count */ );
diff --git a/os/io.c b/os/io.c
index 3800366..83df6e9 100644
--- a/os/io.c
+++ b/os/io.c
@@ -259,6 +259,12 @@ ReadRequestFromClient(ClientPtr client)
oc->input = oci;
}
+ /* Discard any unused file descriptors */
+ while (client->req_fds > 0) {
+ int req_fd = ReadFdFromClient(client);
+ if (req_fd >= 0)
+ close(req_fd);
+ }
/* advance to start of next request */
oci->bufptr += oci->lenLastReq;
@@ -485,6 +491,21 @@ ReadRequestFromClient(ClientPtr client)
return needed;
}
+int
+ReadFdFromClient(ClientPtr client)
+{
+ int fd = -1;
+
+ if (client->req_fds > 0) {
+ OsCommPtr oc = (OsCommPtr) client->osPrivate;
+
+ --client->req_fds;
+ fd = _XSERVTransRecvFd(oc->trans_conn);
+ } else
+ LogMessage(X_ERROR, "Request asks for FD without setting req_fds\n");
+ return fd;
+}
+
/*****************************************************************
* InsertFakeRequest
* Splice a consed up (possibly partial) request in as the next request.
commit 264fc3abe5f18341d0cf9ddb6766e10e4154e447
Author: Keith Packard <keithp at keithp.com>
Date: Thu Oct 31 13:01:46 2013 -0700
misync: Don't smash custom screen sync functions
There was a check to avoid smashing custom functions, but the sense
was backwards causing it to always smash them, and also not set them otherwise.
Signed-off-by: Keith Packard <keithp at keithp.com>
Reviewed-by: Adam Jackson <ajax at redhat.com>
diff --git a/miext/sync/misync.c b/miext/sync/misync.c
index b6914d1..f380547 100644
--- a/miext/sync/misync.c
+++ b/miext/sync/misync.c
@@ -190,7 +190,7 @@ miSyncSetup(ScreenPtr pScreen)
pScreenPriv = SYNC_SCREEN_PRIV(pScreen);
- if (pScreenPriv->funcs.CreateFence) {
+ if (!pScreenPriv->funcs.CreateFence) {
pScreenPriv->funcs = miSyncScreenFuncs;
/* Wrap CloseScreen to clean up */
commit 2d96948ab5c952b68875ac63844cf7d778d4bf63
Author: Keith Packard <keithp at keithp.com>
Date: Thu Jul 11 16:10:34 2013 -0700
os: Add GetTimeInMicros
64-bit higher resolution current time value.
Signed-off-by: Keith Packard <keithp at keithp.com>
Reviewed-by: Adam Jackson <ajax at redhat.com>
diff --git a/include/os.h b/include/os.h
index c7108a5..3840ab9 100644
--- a/include/os.h
+++ b/include/os.h
@@ -165,6 +165,7 @@ extern void ListenOnOpenFD(int /* fd */ , int /* noxauth */ );
#endif
extern _X_EXPORT CARD32 GetTimeInMillis(void);
+extern _X_EXPORT CARD64 GetTimeInMicros(void);
extern _X_EXPORT void AdjustWaitForDelay(pointer /*waitTime */ ,
unsigned long /*newdelay */ );
diff --git a/os/utils.c b/os/utils.c
index 97c3125..995f62a 100644
--- a/os/utils.c
+++ b/os/utils.c
@@ -430,6 +430,11 @@ GetTimeInMillis(void)
{
return GetTickCount();
}
+CARD64
+GetTimeInMicros(void)
+{
+ return (CARD64) GetTickCount() * 1000;
+}
#else
CARD32
GetTimeInMillis(void)
@@ -460,6 +465,28 @@ GetTimeInMillis(void)
X_GETTIMEOFDAY(&tv);
return (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
}
+
+CARD64
+GetTimeInMicros(void)
+{
+ struct timeval tv;
+#ifdef MONOTONIC_CLOCK
+ struct timespec tp;
+ static clockid_t clockid;
+
+ if (!clockid) {
+ if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0)
+ clockid = CLOCK_MONOTONIC;
+ else
+ clockid = ~0L;
+ }
+ if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0)
+ return (CARD64) tp.tv_sec * (CARD64)1000000 + tp.tv_nsec / 1000;
+#endif
+
+ X_GETTIMEOFDAY(&tv);
+ return (CARD64) tv.tv_sec * (CARD64)1000000000 + (CARD64) tv.tv_usec * 1000;
+}
#endif
void
commit 0c33f47281c36726848daf513fb0483cdea57bff
Author: Keith Packard <keithp at keithp.com>
Date: Thu Jul 11 16:09:34 2013 -0700
Add swapll to byte swap 64-bit datatypes
Signed-off-by: Keith Packard <keithp at keithp.com>
Reviewed-by: Adam Jackson <ajax at redhat.com>
diff --git a/include/misc.h b/include/misc.h
index 0c67f11..17de710 100644
--- a/include/misc.h
+++ b/include/misc.h
@@ -305,6 +305,35 @@ __builtin_constant_p(int x)
}
#endif
+/* byte swap a 64-bit value */
+static inline void
+swap_uint64(uint64_t *x)
+{
+ char n;
+
+ n = ((char *) x)[0];
+ ((char *) x)[0] = ((char *) x)[7];
+ ((char *) x)[7] = n;
+
+ n = ((char *) x)[1];
+ ((char *) x)[1] = ((char *) x)[6];
+ ((char *) x)[6] = n;
+
+ n = ((char *) x)[2];
+ ((char *) x)[2] = ((char *) x)[5];
+ ((char *) x)[5] = n;
+
+ n = ((char *) x)[3];
+ ((char *) x)[3] = ((char *) x)[4];
+ ((char *) x)[4] = n;
+}
+
+#define swapll(x) do { \
+ if (sizeof(*(x)) != 8) \
+ wrong_size(); \
+ swap_uint64((uint64_t *)(x)); \
+ } while (0)
+
/* byte swap a 32-bit value */
static inline void
swap_uint32(uint32_t * x)
commit 26f013ba45b08a02bb028a461af68288a86fadb1
Author: Keith Packard <keithp at keithp.com>
Date: Thu Jul 11 16:08:41 2013 -0700
Add a RegionDuplicate function
This allocates a new region structure and copies a source region into
it in a single API rather than forcing the caller to do both steps themselves.
Signed-off-by: Keith Packard <keithp at keithp.com>
Reviewed-by: Adam Jackson <ajax at redhat.com>
diff --git a/dix/region.c b/dix/region.c
index 737d2a8..15f3d01 100644
--- a/dix/region.c
+++ b/dix/region.c
@@ -255,6 +255,21 @@ RegionDestroy(RegionPtr pReg)
free(pReg);
}
+RegionPtr
+RegionDuplicate(RegionPtr pOld)
+{
+ RegionPtr pNew;
+
+ pNew = RegionCreate(&pOld->extents, 0);
+ if (!pNew)
+ return NULL;
+ if (!RegionCopy(pNew, pOld)) {
+ RegionDestroy(pNew);
+ return NULL;
+ }
+ return pNew;
+}
+
void
RegionPrint(RegionPtr rgn)
{
diff --git a/include/regionstr.h b/include/regionstr.h
index 805257b..4a0725d 100644
--- a/include/regionstr.h
+++ b/include/regionstr.h
@@ -213,6 +213,8 @@ extern _X_EXPORT RegionPtr RegionCreate(BoxPtr /*rect */ ,
extern _X_EXPORT void RegionDestroy(RegionPtr /*pReg */ );
+extern _X_EXPORT RegionPtr RegionDuplicate(RegionPtr /* pOld */);
+
static inline Bool
RegionCopy(RegionPtr dst, RegionPtr src)
{
commit d25c217964eb1fe54c3a54bca4cac7f47b4b9fdf
Author: Keith Packard <keithp at keithp.com>
Date: Mon Jan 14 14:24:36 2013 -0800
Clean up a couple of warnings in os/
Signed-off-by: Keith Packard <keithp at keithp.com>
Reviewed-by: Adam Jackson <ajax at redhat.com>
diff --git a/os/connection.c b/os/connection.c
index 6cd8bcf..162e1d9 100644
--- a/os/connection.c
+++ b/os/connection.c
@@ -923,7 +923,7 @@ ErrorConnMax(XtransConnInfo trans_conn)
iov[0].iov_len = sz_xConnSetupPrefix;
iov[0].iov_base = (char *) &csp;
iov[1].iov_len = csp.lengthReason;
- iov[1].iov_base = NOROOM;
+ iov[1].iov_base = (void *) NOROOM;
iov[2].iov_len = (4 - (csp.lengthReason & 3)) & 3;
iov[2].iov_base = pad;
(void) _XSERVTransWritev(trans_conn, iov, 3);
diff --git a/os/xstrans.c b/os/xstrans.c
index 6348a65..2bc79e7 100644
--- a/os/xstrans.c
+++ b/os/xstrans.c
@@ -5,9 +5,11 @@
#include <X11/Xfuncproto.h>
/* ErrorF is used by xtrans */
+#ifndef HAVE_DIX_CONFIG_H
extern _X_EXPORT void
ErrorF(const char *f, ...)
_X_ATTRIBUTE_PRINTF(1, 2);
+#endif
#define TRANS_REOPEN
#define TRANS_SERVER
commit 7710f2b927ec8e3c631f72d66d494b523377b48e
Author: Keith Packard <keithp at keithp.com>
Date: Fri Jan 18 21:43:40 2013 -0800
Xext: Move MIT-SHM 'ShmDesc' to shmint.h
This data structure is required to use shared memory objects in any
extension. That includes the Xv extension, which (before this patch)
duplicated the definition of this structure in its own code.
Signed-off-by: Keith Packard <keithp at keithp.com>
Reviewed-by: Adam Jackson <ajax at redhat.com>
diff --git a/Xext/shm.c b/Xext/shm.c
index 5596090..f6995cc 100644
--- a/Xext/shm.c
+++ b/Xext/shm.c
@@ -89,15 +89,6 @@ in this Software without prior written authorization from The Open Group.
#include "extinit.h"
-typedef struct _ShmDesc {
- struct _ShmDesc *next;
- int shmid;
- int refcnt;
- char *addr;
- Bool writable;
- unsigned long size;
-} ShmDescRec, *ShmDescPtr;
-
typedef struct _ShmScrPrivateRec {
CloseScreenProcPtr CloseScreen;
ShmFuncsPtr shmFuncs;
diff --git a/Xext/shmint.h b/Xext/shmint.h
index fa6941c..9002ce5 100644
--- a/Xext/shmint.h
+++ b/Xext/shmint.h
@@ -56,6 +56,15 @@ typedef struct _ShmFuncs {
void (*PutImage) (XSHM_PUT_IMAGE_ARGS);
} ShmFuncs, *ShmFuncsPtr;
+typedef struct _ShmDesc {
+ struct _ShmDesc *next;
+ int shmid;
+ int refcnt;
+ char *addr;
+ Bool writable;
+ unsigned long size;
+} ShmDescRec, *ShmDescPtr;
+
extern _X_EXPORT void
ShmRegisterFuncs(ScreenPtr pScreen, ShmFuncsPtr funcs);
diff --git a/Xext/xvdisp.c b/Xext/xvdisp.c
index 7877293..613867a 100644
--- a/Xext/xvdisp.c
+++ b/Xext/xvdisp.c
@@ -43,6 +43,7 @@ SOFTWARE.
#include "xvdix.h"
#ifdef MITSHM
#include <X11/extensions/shmproto.h>
+#include "shmint.h"
#endif
#include "xvdisp.h"
@@ -949,18 +950,6 @@ ProcXvPutImage(ClientPtr client)
}
#ifdef MITSHM
-/* redefined here since it's not in any header file */
-typedef struct _ShmDesc {
- struct _ShmDesc *next;
- int shmid;
- int refcnt;
- char *addr;
- Bool writable;
- unsigned long size;
-} ShmDescRec, *ShmDescPtr;
-
-extern RESTYPE ShmSegType;
-extern int ShmCompletionCode;
static int
ProcXvShmPutImage(ClientPtr client)
commit e8961b718d82f1c081ec110d8d962f64e8406b82
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date: Tue Oct 22 14:24:52 2013 +1000
os: use a constant for backtrace array size
Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
Reviewed-by: Jasper St. Pierre <jstpierre at mecheye.net>
diff --git a/os/backtrace.c b/os/backtrace.c
index 426f9b1..3d1195b 100644
--- a/os/backtrace.c
+++ b/os/backtrace.c
@@ -114,14 +114,15 @@ xorg_backtrace(void)
void
xorg_backtrace(void)
{
- void *array[64];
+ const int BT_SIZE = 64;
+ void *array[BT_SIZE];
const char *mod;
int size, i;
Dl_info info;
ErrorFSigSafe("\n");
ErrorFSigSafe("Backtrace:\n");
- size = backtrace(array, 64);
+ size = backtrace(array, BT_SIZE);
for (i = 0; i < size; i++) {
int rc = dladdr(array[i], &info);
commit f12a9ed870017f35cf6d2a82b1405e843aae42ac
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date: Tue Oct 29 15:24:11 2013 +1000
configure: remove a comment
94ed0ba1b5043ad9fc33b42756af447d5ab15bbd moved backtracing into the DIX, so
this comment is outdated. since no-one noticed and it's easier to just grep
than update file references, remove the comment.
Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
Reviewed-by: Jasper St. Pierre <jstpierre at mecheye.net>
diff --git a/configure.ac b/configure.ac
index e7385f8..75ec70b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -300,7 +300,7 @@ AC_CHECK_HEADER([machine/apmvar.h],[
AM_CONDITIONAL(BSD_APM, [test "x$ac_cv_BSD_APM" = xyes])
AM_CONDITIONAL(BSD_KQUEUE_APM, [test "x$ac_cv_BSD_KQUEUE_APM" = xyes])
-dnl glibc backtrace support check (hw/xfree86/common/xf86Events.c)
+dnl glibc backtrace support check
AC_CHECK_HEADER([execinfo.h],[
AC_CHECK_LIB(c, backtrace, [
AC_DEFINE(HAVE_BACKTRACE, 1, [Has backtrace support])
More information about the Xquartz-changes
mailing list