aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--X11/xtrans/Xtrans.c13
-rw-r--r--X11/xtrans/Xtrans.h10
-rw-r--r--X11/xtrans/Xtransint.h24
-rw-r--r--X11/xtrans/Xtranssock.c233
-rw-r--r--X11/xtrans/configure.ac2
-rw-r--r--fontconfig/fonts.dtd2
-rw-r--r--fontconfig/src/fcxml.c5
-rw-r--r--mesalib/configure.ac22
-rw-r--r--mesalib/docs/relnotes/10.0.html1
-rw-r--r--mesalib/src/glsl/Makefile.sources1
-rw-r--r--mesalib/src/glsl/builtin_variables.cpp18
-rw-r--r--mesalib/src/glsl/glcpp/glcpp-parse.y3
-rw-r--r--mesalib/src/glsl/glsl_parser_extras.cpp2
-rw-r--r--mesalib/src/glsl/glsl_parser_extras.h2
-rw-r--r--mesalib/src/glsl/glsl_types.h2
-rw-r--r--mesalib/src/glsl/ir.h6
-rw-r--r--mesalib/src/glsl/ir_optimization.h1
-rw-r--r--mesalib/src/glsl/opt_cse.cpp599
-rw-r--r--mesalib/src/glsl/standalone_scaffolding.cpp1
-rw-r--r--mesalib/src/mapi/glapi/gen/ARB_sample_shading.xml19
-rw-r--r--mesalib/src/mapi/glapi/gen/GL4x.xml21
-rw-r--r--mesalib/src/mapi/glapi/gen/Makefile.am5
-rw-r--r--mesalib/src/mapi/glapi/gen/gl_API.xml4
-rw-r--r--mesalib/src/mesa/drivers/common/meta.c28
-rw-r--r--mesalib/src/mesa/main/dd.h8
-rw-r--r--mesalib/src/mesa/main/enable.c18
-rw-r--r--mesalib/src/mesa/main/extensions.c1
-rw-r--r--mesalib/src/mesa/main/get.c8
-rw-r--r--mesalib/src/mesa/main/get_hash_params.py3
-rw-r--r--mesalib/src/mesa/main/mtypes.h19
-rw-r--r--mesalib/src/mesa/main/multisample.c18
-rw-r--r--mesalib/src/mesa/main/multisample.h2
-rw-r--r--mesalib/src/mesa/main/performance_monitor.c6
-rw-r--r--mesalib/src/mesa/main/transformfeedback.c20
-rw-r--r--mesalib/src/mesa/main/transformfeedback.h3
-rw-r--r--mesalib/src/mesa/main/uniforms.c2
-rw-r--r--mesalib/src/mesa/main/vdpau.c6
-rw-r--r--mesalib/src/mesa/program/prog_print.c1
-rw-r--r--mesalib/src/mesa/program/prog_statevars.c11
-rw-r--r--mesalib/src/mesa/program/prog_statevars.h2
-rw-r--r--mesalib/src/mesa/program/program.c32
-rw-r--r--mesalib/src/mesa/program/program.h3
-rw-r--r--mesalib/src/mesa/state_tracker/st_cb_xformfb.c4
-rw-r--r--mesalib/src/mesa/state_tracker/st_draw.h2
-rw-r--r--mesalib/src/mesa/swrast/s_texfetch_tmp.h4
-rw-r--r--mesalib/src/mesa/vbo/vbo_attrib_tmp.h4
-rw-r--r--mesalib/src/mesa/vbo/vbo_exec_array.c10
-rw-r--r--pixman/configure.ac18
-rw-r--r--pixman/pixman/pixman-matrix.c2
-rw-r--r--pixman/pixman/pixman.h2
-rw-r--r--pixman/test/trap-crasher.c14
-rw-r--r--xkbcomp/action.c8
-rw-r--r--xkbcomp/action.h4
-rw-r--r--xkbcomp/compat.c2
-rw-r--r--xkbcomp/expr.c14
-rw-r--r--xkbcomp/geometry.c36
-rw-r--r--xkbcomp/indicators.c2
-rw-r--r--xkbcomp/indicators.h2
-rw-r--r--xkbcomp/keytypes.c2
-rw-r--r--xkbcomp/listing.c9
-rw-r--r--xkbcomp/symbols.c8
-rw-r--r--xkbcomp/utils.c59
-rw-r--r--xkbcomp/utils.h69
-rw-r--r--xkbcomp/xkbcomp.c5
-rw-r--r--xorg-server/Makefile.am12
-rw-r--r--xorg-server/Xext/shm.c168
-rw-r--r--xorg-server/Xext/shmint.h10
-rw-r--r--xorg-server/Xext/sync.c43
-rw-r--r--xorg-server/Xext/syncsrv.h13
-rw-r--r--xorg-server/Xext/xvdisp.c13
-rw-r--r--xorg-server/configure.ac71
-rw-r--r--xorg-server/dix/region.c15
-rw-r--r--xorg-server/dri3/Makefile.am13
-rw-r--r--xorg-server/dri3/dri3.c87
-rw-r--r--xorg-server/dri3/dri3.h59
-rw-r--r--xorg-server/dri3/dri3_event.c163
-rw-r--r--xorg-server/dri3/dri3_priv.h80
-rw-r--r--xorg-server/dri3/dri3_request.c394
-rw-r--r--xorg-server/dri3/dri3_screen.c80
-rw-r--r--xorg-server/dri3/dri3int.h26
-rw-r--r--xorg-server/glx/glxcmds.c3
-rw-r--r--xorg-server/glx/glxdricommon.c1
-rw-r--r--xorg-server/hw/dmx/dmxextension.c3
-rw-r--r--xorg-server/hw/dmx/dmxinit.c2
-rw-r--r--xorg-server/hw/kdrive/ephyr/hostx.c22
-rw-r--r--xorg-server/hw/xfree86/Makefile.am4
-rw-r--r--xorg-server/hw/xfree86/common/xf86Configure.c2
-rw-r--r--xorg-server/hw/xfree86/common/xf86DPMS.c9
-rw-r--r--xorg-server/hw/xfree86/common/xf86Events.c31
-rw-r--r--xorg-server/hw/xfree86/common/xf86RandR.c16
-rw-r--r--xorg-server/hw/xfree86/modes/xf86Crtc.c20
-rw-r--r--xorg-server/hw/xfree86/sdksyms.sh1
-rw-r--r--xorg-server/hw/xquartz/bundle/Info.plist.cpp4
-rw-r--r--xorg-server/include/dix-config.h.in6
-rw-r--r--xorg-server/include/dixstruct.h8
-rw-r--r--xorg-server/include/extinit.h10
-rw-r--r--xorg-server/include/misc.h29
-rw-r--r--xorg-server/include/os.h5
-rw-r--r--xorg-server/include/regionstr.h2
-rw-r--r--xorg-server/include/xorg-config.h.in3
-rw-r--r--xorg-server/include/xorg-server.h.in6
-rw-r--r--xorg-server/mi/miinitext.c4
-rw-r--r--xorg-server/miext/damage/damage.c5
-rw-r--r--xorg-server/miext/sync/Makefile.am3
-rw-r--r--xorg-server/miext/sync/misync.c31
-rw-r--r--xorg-server/miext/sync/misync.h21
-rw-r--r--xorg-server/miext/sync/misyncshm.c176
-rw-r--r--xorg-server/miext/sync/misyncshm.h28
-rw-r--r--xorg-server/miext/sync/misyncstr.h15
-rw-r--r--xorg-server/os/backtrace.c5
-rw-r--r--xorg-server/os/connection.c2
-rw-r--r--xorg-server/os/io.c29
-rw-r--r--xorg-server/os/utils.c27
-rw-r--r--xorg-server/os/xstrans.c2
-rw-r--r--xorg-server/present/Makefile.am17
-rw-r--r--xorg-server/present/present.c775
-rw-r--r--xorg-server/present/present.h118
-rw-r--r--xorg-server/present/present_event.c239
-rw-r--r--xorg-server/present/present_fake.c140
-rw-r--r--xorg-server/present/present_fence.c112
-rw-r--r--xorg-server/present/present_notify.c114
-rw-r--r--xorg-server/present/present_priv.h288
-rw-r--r--xorg-server/present/present_request.c330
-rw-r--r--xorg-server/present/present_screen.c231
-rw-r--r--xorg-server/present/presentext.h29
-rw-r--r--xorg-server/test/Makefile.am11
126 files changed, 5280 insertions, 373 deletions
diff --git a/X11/xtrans/Xtrans.c b/X11/xtrans/Xtrans.c
index 0799f0468..7c7967f5d 100644
--- a/X11/xtrans/Xtrans.c
+++ b/X11/xtrans/Xtrans.c
@@ -866,17 +866,22 @@ TRANS(Write) (XtransConnInfo ciptr, char *buf, int size)
}
int
-TRANS(Readv) (XtransConnInfo ciptr, struct iovec *buf, int size)
+TRANS(Writev) (XtransConnInfo ciptr, struct iovec *buf, int size)
{
- return ciptr->transptr->Readv (ciptr, buf, size);
+ return ciptr->transptr->Writev (ciptr, buf, size);
}
int
-TRANS(Writev) (XtransConnInfo ciptr, struct iovec *buf, int size)
+TRANS(SendFd) (XtransConnInfo ciptr, int fd, int do_close)
+{
+ return ciptr->transptr->SendFd(ciptr, fd, do_close);
+}
+int
+TRANS(RecvFd) (XtransConnInfo ciptr)
{
- return ciptr->transptr->Writev (ciptr, buf, size);
+ return ciptr->transptr->RecvFd(ciptr);
}
int
diff --git a/X11/xtrans/Xtrans.h b/X11/xtrans/Xtrans.h
index 2945b2aba..53b8b627d 100644
--- a/X11/xtrans/Xtrans.h
+++ b/X11/xtrans/Xtrans.h
@@ -344,18 +344,16 @@ int TRANS(Write)(
int /* size */
);
-int TRANS(Readv)(
- XtransConnInfo, /* ciptr */
- struct iovec *, /* buf */
- int /* size */
-);
-
int TRANS(Writev)(
XtransConnInfo, /* ciptr */
struct iovec *, /* buf */
int /* size */
);
+int TRANS(SendFd) (XtransConnInfo ciptr, int fd, int do_close);
+
+int TRANS(RecvFd) (XtransConnInfo ciptr);
+
int TRANS(Disconnect)(
XtransConnInfo /* ciptr */
);
diff --git a/X11/xtrans/Xtransint.h b/X11/xtrans/Xtransint.h
index 3bce8dc6b..dd886db87 100644
--- a/X11/xtrans/Xtransint.h
+++ b/X11/xtrans/Xtransint.h
@@ -72,6 +72,8 @@ from The Open Group.
# define XTRANSDEBUG 1
#endif
+#define XTRANS_SEND_FDS 1
+
#ifdef WIN32
# define _WILLWINSOCK_
#endif
@@ -123,6 +125,16 @@ from The Open Group.
#define X_TCP_PORT 6000
#endif
+#if XTRANS_SEND_FDS
+
+struct _XtransConnFd {
+ struct _XtransConnFd *next;
+ int fd;
+ int do_close;
+};
+
+#endif
+
struct _XtransConnInfo {
struct _Xtransport *transptr;
int index;
@@ -135,6 +147,8 @@ struct _XtransConnInfo {
int addrlen;
char *peeraddr;
int peeraddrlen;
+ struct _XtransConnFd *recv_fds;
+ struct _XtransConnFd *send_fds;
};
#define XTRANS_OPEN_COTS_CLIENT 1
@@ -275,6 +289,16 @@ typedef struct _Xtransport {
int /* size */
);
+ int (*SendFd)(
+ XtransConnInfo, /* connection */
+ int, /* fd */
+ int /* do_close */
+ );
+
+ int (*RecvFd)(
+ XtransConnInfo /* connection */
+ );
+
int (*Disconnect)(
XtransConnInfo /* connection */
);
diff --git a/X11/xtrans/Xtranssock.c b/X11/xtrans/Xtranssock.c
index 24269b241..23150b259 100644
--- a/X11/xtrans/Xtranssock.c
+++ b/X11/xtrans/Xtranssock.c
@@ -2097,47 +2097,176 @@ TRANS(SocketBytesReadable) (XtransConnInfo ciptr, BytesReadable_t *pend)
#endif /* WIN32 */
}
+#if XTRANS_SEND_FDS
+
+static void
+appendFd(struct _XtransConnFd **prev, int fd, int do_close)
+{
+ struct _XtransConnFd *cf, *new;
+
+ new = malloc (sizeof (struct _XtransConnFd));
+ if (!new) {
+ /* XXX mark connection as broken */
+ close(fd);
+ return;
+ }
+ new->next = 0;
+ new->fd = fd;
+ new->do_close = do_close;
+ /* search to end of list */
+ for (; (cf = *prev); prev = &(cf->next));
+ *prev = new;
+}
static int
-TRANS(SocketRead) (XtransConnInfo ciptr, char *buf, int size)
+removeFd(struct _XtransConnFd **prev)
+{
+ struct _XtransConnFd *cf;
+ int fd;
+
+ if ((cf = *prev)) {
+ *prev = cf->next;
+ fd = cf->fd;
+ free(cf);
+ } else
+ fd = -1;
+ return fd;
+}
+static void
+discardFd(struct _XtransConnFd **prev, struct _XtransConnFd *upto, int do_close)
{
- prmsg (2,"SocketRead(%d,%p,%d)\n", ciptr->fd, buf, size);
+ struct _XtransConnFd *cf, *next;
-#if defined(WIN32)
- {
- int ret = recv ((SOCKET)ciptr->fd, buf, size, 0);
-#ifdef WIN32
- if (ret == SOCKET_ERROR) errno = WSAGetLastError();
-#endif
- return ret;
+ for (cf = *prev; cf != upto; cf = next) {
+ next = cf->next;
+ if (do_close || cf->do_close)
+ close(cf->fd);
+ free(cf);
}
-#else
- return read (ciptr->fd, buf, size);
-#endif /* WIN32 */
+ *prev = upto;
}
+static void
+cleanupFds(XtransConnInfo ciptr)
+{
+ /* Clean up the send list but don't close the fds */
+ discardFd(&ciptr->send_fds, NULL, 0);
+ /* Clean up the recv list and *do* close the fds */
+ discardFd(&ciptr->recv_fds, NULL, 1);
+}
static int
-TRANS(SocketWrite) (XtransConnInfo ciptr, char *buf, int size)
+nFd(struct _XtransConnFd **prev)
+{
+ struct _XtransConnFd *cf;
+ int n = 0;
+
+ for (cf = *prev; cf; cf = cf->next)
+ n++;
+ return n;
+}
+
+static int
+TRANS(SocketRecvFd) (XtransConnInfo ciptr)
+{
+ prmsg (2, "SocketRecvFd(%d)\n", ciptr->fd);
+ return removeFd(&ciptr->recv_fds);
+}
+static int
+TRANS(SocketSendFd) (XtransConnInfo ciptr, int fd, int do_close)
{
- prmsg (2,"SocketWrite(%d,%p,%d)\n", ciptr->fd, buf, size);
+ appendFd(&ciptr->send_fds, fd, do_close);
+ return 0;
+}
+
+static int
+TRANS(SocketRecvFdInvalid)(XtransConnInfo ciptr)
+{
+ errno = EINVAL;
+ return -1;
+}
+
+static int
+TRANS(SocketSendFdInvalid)(XtransConnInfo ciptr, int fd, int do_close)
+{
+ errno = EINVAL;
+ return -1;
+}
+
+#define MAX_FDS 128
+
+struct fd_pass {
+ struct cmsghdr cmsghdr;
+ int fd[MAX_FDS];
+};
+
+static inline void init_msg_recv(struct msghdr *msg, struct iovec *iov, int niov, struct fd_pass *pass, int nfd) {
+ msg->msg_name = NULL;
+ msg->msg_namelen = 0;
+ msg->msg_iov = iov;
+ msg->msg_iovlen = niov;
+ msg->msg_control = pass;
+ msg->msg_controllen = sizeof (struct cmsghdr) + nfd * sizeof (int);
+}
+
+static inline void init_msg_send(struct msghdr *msg, struct iovec *iov, int niov, struct fd_pass *pass, int nfd) {
+ init_msg_recv(msg, iov, niov, pass, nfd);
+ pass->cmsghdr.cmsg_len = msg->msg_controllen;
+ pass->cmsghdr.cmsg_level = SOL_SOCKET;
+ pass->cmsghdr.cmsg_type = SCM_RIGHTS;
+}
+
+#endif /* XTRANS_SEND_FDS */
+
+static int
+TRANS(SocketRead) (XtransConnInfo ciptr, char *buf, int size)
+
+{
+ prmsg (2,"SocketRead(%d,%p,%d)\n", ciptr->fd, buf, size);
#if defined(WIN32)
{
- int ret = send ((SOCKET)ciptr->fd, buf, size, 0);
+ int ret = recv ((SOCKET)ciptr->fd, buf, size, 0);
#ifdef WIN32
if (ret == SOCKET_ERROR) errno = WSAGetLastError();
#endif
return ret;
}
#else
- return write (ciptr->fd, buf, size);
+#if XTRANS_SEND_FDS
+ {
+ struct msghdr msg;
+ struct iovec iov;
+ struct fd_pass pass;
+
+ iov.iov_base = buf;
+ iov.iov_len = size;
+
+ init_msg_recv(&msg, &iov, 1, &pass, MAX_FDS);
+ size = recvmsg(ciptr->fd, &msg, 0);
+ if (size >= 0 && msg.msg_controllen > sizeof (struct cmsghdr)) {
+ if (pass.cmsghdr.cmsg_level == SOL_SOCKET &&
+ pass.cmsghdr.cmsg_type == SCM_RIGHTS &&
+ !((msg.msg_flags & MSG_TRUNC) ||
+ (msg.msg_flags & MSG_CTRUNC)))
+ {
+ int nfd = (msg.msg_controllen - sizeof (struct cmsghdr)) / sizeof (int);
+ int *fd = (int *) CMSG_DATA(&pass.cmsghdr);
+ int i;
+ for (i = 0; i < nfd; i++)
+ appendFd(&ciptr->recv_fds, fd[i], 0);
+ }
+ }
+ return size;
+ }
+#else
+ return read(ciptr->fd, buf, size);
+#endif /* XTRANS_SEND_FDS */
#endif /* WIN32 */
}
-
static int
TRANS(SocketReadv) (XtransConnInfo ciptr, struct iovec *buf, int size)
@@ -2154,11 +2283,65 @@ TRANS(SocketWritev) (XtransConnInfo ciptr, struct iovec *buf, int size)
{
prmsg (2,"SocketWritev(%d,%p,%d)\n", ciptr->fd, buf, size);
+#if XTRANS_SEND_FDS
+ if (ciptr->send_fds)
+ {
+ struct msghdr msg;
+ struct fd_pass pass;
+ int nfd;
+ struct _XtransConnFd *cf;
+ int i;
+
+ nfd = nFd(&ciptr->send_fds);
+ cf = ciptr->send_fds;
+
+ /* Set up fds */
+ for (i = 0; i < nfd; i++) {
+ pass.fd[i] = cf->fd;
+ cf = cf->next;
+ }
+
+ init_msg_send(&msg, buf, size, &pass, nfd);
+ i = sendmsg(ciptr->fd, &msg, 0);
+ if (i > 0)
+ discardFd(&ciptr->send_fds, cf, 0);
+ return i;
+ }
+#endif
return WRITEV (ciptr, buf, size);
}
static int
+TRANS(SocketWrite) (XtransConnInfo ciptr, char *buf, int size)
+
+{
+ prmsg (2,"SocketWrite(%d,%p,%d)\n", ciptr->fd, buf, size);
+
+#if defined(WIN32)
+ {
+ int ret = send ((SOCKET)ciptr->fd, buf, size, 0);
+#ifdef WIN32
+ if (ret == SOCKET_ERROR) errno = WSAGetLastError();
+#endif
+ return ret;
+ }
+#else
+#if XTRANS_SEND_FDS
+ if (ciptr->send_fds)
+ {
+ struct iovec iov;
+
+ iov.iov_base = buf;
+ iov.iov_len = size;
+ return TRANS(SocketWritev)(ciptr, &iov, 1);
+ }
+#endif /* XTRANS_SEND_FDS */
+ return write (ciptr->fd, buf, size);
+#endif /* WIN32 */
+}
+
+static int
TRANS(SocketDisconnect) (XtransConnInfo ciptr)
{
@@ -2211,6 +2394,9 @@ TRANS(SocketUNIXClose) (XtransConnInfo ciptr)
prmsg (2,"SocketUNIXClose(%p,%d)\n", ciptr, ciptr->fd);
+#if XTRANS_SEND_FDS
+ cleanupFds(ciptr);
+#endif
ret = close(ciptr->fd);
if (ciptr->flags
@@ -2239,6 +2425,9 @@ TRANS(SocketUNIXCloseForCloning) (XtransConnInfo ciptr)
prmsg (2,"SocketUNIXCloseForCloning(%p,%d)\n",
ciptr, ciptr->fd);
+#if XTRANS_SEND_FDS
+ cleanupFds(ciptr);
+#endif
ret = close(ciptr->fd);
return ret;
@@ -2293,6 +2482,8 @@ Xtransport TRANS(SocketTCPFuncs) = {
TRANS(SocketWrite),
TRANS(SocketReadv),
TRANS(SocketWritev),
+ TRANS(SocketSendFdInvalid),
+ TRANS(SocketRecvFdInvalid),
TRANS(SocketDisconnect),
TRANS(SocketINETClose),
TRANS(SocketINETClose),
@@ -2333,6 +2524,8 @@ Xtransport TRANS(SocketINETFuncs) = {
TRANS(SocketWrite),
TRANS(SocketReadv),
TRANS(SocketWritev),
+ TRANS(SocketSendFdInvalid),
+ TRANS(SocketRecvFdInvalid),
TRANS(SocketDisconnect),
TRANS(SocketINETClose),
TRANS(SocketINETClose),
@@ -2374,6 +2567,8 @@ Xtransport TRANS(SocketINET6Funcs) = {
TRANS(SocketWrite),
TRANS(SocketReadv),
TRANS(SocketWritev),
+ TRANS(SocketSendFdInvalid),
+ TRANS(SocketRecvFdInvalid),
TRANS(SocketDisconnect),
TRANS(SocketINETClose),
TRANS(SocketINETClose),
@@ -2422,6 +2617,8 @@ Xtransport TRANS(SocketLocalFuncs) = {
TRANS(SocketWrite),
TRANS(SocketReadv),
TRANS(SocketWritev),
+ TRANS(SocketSendFd),
+ TRANS(SocketRecvFd),
TRANS(SocketDisconnect),
TRANS(SocketUNIXClose),
TRANS(SocketUNIXCloseForCloning),
@@ -2476,6 +2673,8 @@ Xtransport TRANS(SocketUNIXFuncs) = {
TRANS(SocketWrite),
TRANS(SocketReadv),
TRANS(SocketWritev),
+ TRANS(SocketSendFd),
+ TRANS(SocketRecvFd),
TRANS(SocketDisconnect),
TRANS(SocketUNIXClose),
TRANS(SocketUNIXCloseForCloning),
diff --git a/X11/xtrans/configure.ac b/X11/xtrans/configure.ac
index cc3c006ae..8c3aa3ded 100644
--- a/X11/xtrans/configure.ac
+++ b/X11/xtrans/configure.ac
@@ -21,7 +21,7 @@
# Initialize Autoconf
AC_PREREQ([2.60])
-AC_INIT([xtrans], [1.2.7],
+AC_INIT([xtrans], [1.3.0],
[https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], [xtrans])
AC_CONFIG_SRCDIR([Makefile.am])
diff --git a/fontconfig/fonts.dtd b/fontconfig/fonts.dtd
index 4c38e77f0..479f2c0fb 100644
--- a/fontconfig/fonts.dtd
+++ b/fontconfig/fonts.dtd
@@ -140,7 +140,7 @@
if 'target' is 'font', execute the match on the result of a font
selection.
-->
-<!ELEMENT match (test*, edit*)+>
+<!ELEMENT match (test|edit)+>
<!ATTLIST match
target (pattern|font|scan) "pattern">
diff --git a/fontconfig/src/fcxml.c b/fontconfig/src/fcxml.c
index 8ff10b6e6..bd95580aa 100644
--- a/fontconfig/src/fcxml.c
+++ b/fontconfig/src/fcxml.c
@@ -2566,6 +2566,11 @@ FcParseMatch (FcConfigParse *parse)
}
FcVStackPopAndDestroy (parse);
}
+ if (!rule)
+ {
+ FcConfigMessage (parse, FcSevereWarning, "No <test> nor <edit> elements in <match>");
+ return;
+ }
if (!FcConfigAddRule (parse->config, rule, kind))
FcConfigMessage (parse, FcSevereError, "out of memory");
}
diff --git a/mesalib/configure.ac b/mesalib/configure.ac
index f94c9b979..0a250471e 100644
--- a/mesalib/configure.ac
+++ b/mesalib/configure.ac
@@ -1771,7 +1771,7 @@ if test "x$with_gallium_drivers" != x; then
PKG_CHECK_MODULES([RADEON], [libdrm_radeon >= $LIBDRM_RADEON_REQUIRED])
gallium_require_llvm "Gallium R300"
GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS r300"
- gallium_check_st "radeon/drm" "r300/dri" "" "" "r300/xvmc" "r300/vdpau"
+ gallium_check_st "radeon/drm" "r300/dri" "" "" "" ""
DRICOMMON_NEED_LIBDRM=yes
;;
xr600)
@@ -1789,7 +1789,7 @@ if test "x$with_gallium_drivers" != x; then
if test "x$enable_opencl" = xyes; then
LLVM_COMPONENTS="${LLVM_COMPONENTS} bitreader asmparser"
fi
- gallium_check_st "radeon/drm" "r600/dri" "r600/xorg" "" "r600/xvmc" "r600/vdpau"
+ gallium_check_st "radeon/drm" "r600/dri" "" "" "r600/xvmc" "r600/vdpau"
DRICOMMON_NEED_LIBDRM=yes
;;
xradeonsi)
@@ -1798,7 +1798,7 @@ if test "x$with_gallium_drivers" != x; then
gallium_require_drm_loader
GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS radeonsi"
radeon_llvm_check
- gallium_check_st "radeon/drm" "radeonsi/dri" "radeonsi/xorg" "" "" "radeonsi/vdpau" ""
+ gallium_check_st "radeon/drm" "radeonsi/dri" "" "" "" "radeonsi/vdpau" ""
DRICOMMON_NEED_LIBDRM=yes
;;
xnouveau)
@@ -1828,16 +1828,6 @@ if test "x$with_gallium_drivers" != x; then
if test "x$enable_dri" = xyes; then
GALLIUM_TARGET_DIRS="$GALLIUM_TARGET_DIRS dri-swrast"
fi
- if test "x$enable_vdpau" = xyes; then
- GALLIUM_TARGET_DIRS="$GALLIUM_TARGET_DIRS vdpau-softpipe"
- fi
- if test "x$enable_xvmc" = xyes; then
- GALLIUM_TARGET_DIRS="$GALLIUM_TARGET_DIRS xvmc-softpipe"
- fi
- if test "x$enable_vdpau" = xyes -o "x$enable_xvmc" = xyes; then
- NEED_WINSYS_XLIB=yes
- GALLIUM_WINSYS_DIRS="$GALLIUM_WINSYS_DIRS sw/xlib"
- fi
;;
*)
AC_MSG_ERROR([Unknown Gallium driver: $driver])
@@ -2044,23 +2034,17 @@ AC_CONFIG_FILES([Makefile
src/gallium/targets/pipe-loader/Makefile
src/gallium/targets/radeonsi/dri/Makefile
src/gallium/targets/radeonsi/vdpau/Makefile
- src/gallium/targets/radeonsi/xorg/Makefile
src/gallium/targets/r300/dri/Makefile
- src/gallium/targets/r300/vdpau/Makefile
- src/gallium/targets/r300/xvmc/Makefile
src/gallium/targets/r600/dri/Makefile
src/gallium/targets/r600/vdpau/Makefile
- src/gallium/targets/r600/xorg/Makefile
src/gallium/targets/r600/xvmc/Makefile
src/gallium/targets/libgl-xlib/Makefile
src/gallium/targets/vdpau-nouveau/Makefile
- src/gallium/targets/vdpau-softpipe/Makefile
src/gallium/targets/xa-vmwgfx/Makefile
src/gallium/targets/xa-vmwgfx/xatracker.pc
src/gallium/targets/xorg-i915/Makefile
src/gallium/targets/xorg-nouveau/Makefile
src/gallium/targets/xvmc-nouveau/Makefile
- src/gallium/targets/xvmc-softpipe/Makefile
src/gallium/tests/trivial/Makefile
src/gallium/tests/unit/Makefile
src/gallium/winsys/Makefile
diff --git a/mesalib/docs/relnotes/10.0.html b/mesalib/docs/relnotes/10.0.html
index ef550d154..5ff53398e 100644
--- a/mesalib/docs/relnotes/10.0.html
+++ b/mesalib/docs/relnotes/10.0.html
@@ -49,6 +49,7 @@ Note: some of the new features are only available with certain drivers.
<li>GL_ARB_texture_gather on i965.</li>
<li>GL_ARB_texture_query_levels on i965.</li>
<li>GL_ARB_texture_mirror_clamp_to_edge.</li>
+<li>GL_ARB_transform_feedback2, GL_ARB_transform_feedback3, and GL_ARB_transform_feedback_instanced on i965/Gen7 (with appropriate kernel support).</li>
<li>GL_KHR_debug</li>
</ul>
diff --git a/mesalib/src/glsl/Makefile.sources b/mesalib/src/glsl/Makefile.sources
index 2f7bfa163..2aabc0585 100644
--- a/mesalib/src/glsl/Makefile.sources
+++ b/mesalib/src/glsl/Makefile.sources
@@ -83,6 +83,7 @@ LIBGLSL_FILES = \
$(GLSL_SRCDIR)/opt_constant_variable.cpp \
$(GLSL_SRCDIR)/opt_copy_propagation.cpp \
$(GLSL_SRCDIR)/opt_copy_propagation_elements.cpp \
+ $(GLSL_SRCDIR)/opt_cse.cpp \
$(GLSL_SRCDIR)/opt_dead_builtin_varyings.cpp \
$(GLSL_SRCDIR)/opt_dead_code.cpp \
$(GLSL_SRCDIR)/opt_dead_code_local.cpp \
diff --git a/mesalib/src/glsl/builtin_variables.cpp b/mesalib/src/glsl/builtin_variables.cpp
index 7a3505ace..4d441045a 100644
--- a/mesalib/src/glsl/builtin_variables.cpp
+++ b/mesalib/src/glsl/builtin_variables.cpp
@@ -30,6 +30,9 @@
#include "program/prog_statevars.h"
#include "program/prog_instruction.h"
+static struct gl_builtin_uniform_element gl_NumSamples_elements[] = {
+ {NULL, {STATE_NUM_SAMPLES, 0, 0}, SWIZZLE_XXXX}
+};
static struct gl_builtin_uniform_element gl_DepthRange_elements[] = {
{"near", {STATE_DEPTH_RANGE, 0, 0}, SWIZZLE_XXXX},
@@ -236,6 +239,7 @@ static struct gl_builtin_uniform_element gl_NormalMatrix_elements[] = {
#define STATEVAR(name) {#name, name ## _elements, Elements(name ## _elements)}
static const struct gl_builtin_uniform_desc _mesa_builtin_uniform_desc[] = {
+ STATEVAR(gl_NumSamples),
STATEVAR(gl_DepthRange),
STATEVAR(gl_ClipPlane),
STATEVAR(gl_Point),
@@ -662,6 +666,7 @@ builtin_variable_generator::generate_constants()
void
builtin_variable_generator::generate_uniforms()
{
+ add_uniform(int_t, "gl_NumSamples");
add_uniform(type("gl_DepthRangeParameters"), "gl_DepthRange");
add_uniform(array(vec4_t, VERT_ATTRIB_MAX), "gl_CurrentAttribVertMESA");
add_uniform(array(vec4_t, VARYING_SLOT_MAX), "gl_CurrentAttribFragMESA");
@@ -838,6 +843,19 @@ builtin_variable_generator::generate_fs_special_vars()
if (state->AMD_shader_stencil_export_warn)
var->warn_extension = "GL_AMD_shader_stencil_export";
}
+
+ if (state->ARB_sample_shading_enable) {
+ add_system_value(SYSTEM_VALUE_SAMPLE_ID, int_t, "gl_SampleID");
+ add_system_value(SYSTEM_VALUE_SAMPLE_POS, vec2_t, "gl_SamplePosition");
+ /* From the ARB_sample_shading specification:
+ * "The number of elements in the array is ceil(<s>/32), where
+ * <s> is the maximum number of color samples supported by the
+ * implementation."
+ * Since no drivers expose more than 32x MSAA, we can simply set
+ * the array size to 1 rather than computing it.
+ */
+ add_output(FRAG_RESULT_SAMPLE_MASK, array(int_t, 1), "gl_SampleMask");
+ }
}
diff --git a/mesalib/src/glsl/glcpp/glcpp-parse.y b/mesalib/src/glsl/glcpp/glcpp-parse.y
index 86f3cd5aa..7edc27488 100644
--- a/mesalib/src/glsl/glcpp/glcpp-parse.y
+++ b/mesalib/src/glsl/glcpp/glcpp-parse.y
@@ -1249,6 +1249,9 @@ glcpp_parser_create (const struct gl_extensions *extensions, int api)
if (extensions->ARB_shading_language_420pack)
add_builtin_define(parser, "GL_ARB_shading_language_420pack", 1);
+ if (extensions->ARB_sample_shading)
+ add_builtin_define(parser, "GL_ARB_sample_shading", 1);
+
if (extensions->EXT_shader_integer_mix)
add_builtin_define(parser, "GL_EXT_shader_integer_mix", 1);
diff --git a/mesalib/src/glsl/glsl_parser_extras.cpp b/mesalib/src/glsl/glsl_parser_extras.cpp
index 77e8816c4..d922db9db 100644
--- a/mesalib/src/glsl/glsl_parser_extras.cpp
+++ b/mesalib/src/glsl/glsl_parser_extras.cpp
@@ -540,6 +540,7 @@ static const _mesa_glsl_extension _mesa_glsl_supported_extensions[] = {
EXT(EXT_shader_integer_mix, true, true, EXT_shader_integer_mix),
EXT(ARB_texture_gather, true, false, ARB_texture_gather),
EXT(ARB_shader_atomic_counters, true, false, ARB_shader_atomic_counters),
+ EXT(ARB_sample_shading, true, false, ARB_sample_shading),
};
#undef EXT
@@ -1604,6 +1605,7 @@ do_common_optimization(exec_list *ir, bool linked,
else
progress = do_constant_variable_unlinked(ir) || progress;
progress = do_constant_folding(ir) || progress;
+ progress = do_cse(ir) || progress;
progress = do_algebraic(ir) || progress;
progress = do_lower_jumps(ir) || progress;
progress = do_vec_index_to_swizzle(ir) || progress;
diff --git a/mesalib/src/glsl/glsl_parser_extras.h b/mesalib/src/glsl/glsl_parser_extras.h
index f22dac355..345d7a018 100644
--- a/mesalib/src/glsl/glsl_parser_extras.h
+++ b/mesalib/src/glsl/glsl_parser_extras.h
@@ -350,6 +350,8 @@ struct _mesa_glsl_parse_state {
bool AMD_vertex_shader_layer_warn;
bool ARB_shading_language_420pack_enable;
bool ARB_shading_language_420pack_warn;
+ bool ARB_sample_shading_enable;
+ bool ARB_sample_shading_warn;
bool EXT_shader_integer_mix_enable;
bool EXT_shader_integer_mix_warn;
bool ARB_shader_atomic_counters_enable;
diff --git a/mesalib/src/glsl/glsl_types.h b/mesalib/src/glsl/glsl_types.h
index fdb1f3a6e..96eee5e64 100644
--- a/mesalib/src/glsl/glsl_types.h
+++ b/mesalib/src/glsl/glsl_types.h
@@ -459,7 +459,7 @@ struct glsl_type {
*/
bool contains_atomic() const
{
- return atomic_size();
+ return atomic_size() > 0;
}
/**
diff --git a/mesalib/src/glsl/ir.h b/mesalib/src/glsl/ir.h
index 5b30fe59b..2f06fb9ea 100644
--- a/mesalib/src/glsl/ir.h
+++ b/mesalib/src/glsl/ir.h
@@ -133,6 +133,7 @@ public:
virtual class ir_return * as_return() { return NULL; }
virtual class ir_if * as_if() { return NULL; }
virtual class ir_swizzle * as_swizzle() { return NULL; }
+ virtual class ir_texture * as_texture() { return NULL; }
virtual class ir_constant * as_constant() { return NULL; }
virtual class ir_discard * as_discard() { return NULL; }
virtual class ir_jump * as_jump() { return NULL; }
@@ -1731,6 +1732,11 @@ public:
v->visit(this);
}
+ virtual ir_texture *as_texture()
+ {
+ return this;
+ }
+
virtual ir_visitor_status accept(ir_hierarchical_visitor *);
/**
diff --git a/mesalib/src/glsl/ir_optimization.h b/mesalib/src/glsl/ir_optimization.h
index 074686c5d..3ca9f5744 100644
--- a/mesalib/src/glsl/ir_optimization.h
+++ b/mesalib/src/glsl/ir_optimization.h
@@ -77,6 +77,7 @@ bool do_constant_variable_unlinked(exec_list *instructions);
bool do_copy_propagation(exec_list *instructions);
bool do_copy_propagation_elements(exec_list *instructions);
bool do_constant_propagation(exec_list *instructions);
+bool do_cse(exec_list *instructions);
void do_dead_builtin_varyings(struct gl_context *ctx,
gl_shader *producer, gl_shader *consumer,
unsigned num_tfeedback_decls,
diff --git a/mesalib/src/glsl/opt_cse.cpp b/mesalib/src/glsl/opt_cse.cpp
new file mode 100644
index 000000000..c0fdb23e6
--- /dev/null
+++ b/mesalib/src/glsl/opt_cse.cpp
@@ -0,0 +1,599 @@
+/*
+ * Copyright © 2013 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file opt_cse.cpp
+ *
+ * constant subexpression elimination at the GLSL IR level.
+ *
+ * Compare to brw_fs_cse.cpp for a more complete CSE implementation. This one
+ * is generic and handles texture operations, but it's rather simple currently
+ * and doesn't support modification of variables in the available expressions
+ * list, so it can't do variables other than uniforms or shader inputs.
+ */
+
+#include "ir.h"
+#include "ir_visitor.h"
+#include "ir_rvalue_visitor.h"
+#include "ir_basic_block.h"
+#include "ir_optimization.h"
+#include "ir_builder.h"
+#include "glsl_types.h"
+
+using namespace ir_builder;
+
+static bool debug = false;
+
+namespace {
+
+/**
+ * This is the record of an available expression for common subexpression
+ * elimination.
+ */
+class ae_entry : public exec_node
+{
+public:
+ ae_entry(ir_instruction *base_ir, ir_rvalue **val)
+ : val(val), base_ir(base_ir)
+ {
+ assert(val);
+ assert(*val);
+ assert(base_ir);
+
+ var = NULL;
+ }
+
+ /**
+ * The pointer to the expression that we might be able to reuse
+ *
+ * Note the double pointer -- this is the place in the base_ir expression
+ * tree that we would rewrite to move the expression out to a new variable
+ * assignment.
+ */
+ ir_rvalue **val;
+
+ /**
+ * Root instruction in the basic block where the expression appeared.
+ *
+ * This is used so that we can insert the new variable declaration into the
+ * instruction stream (since *val is just somewhere in base_ir's expression
+ * tree).
+ */
+ ir_instruction *base_ir;
+
+ /**
+ * The variable that the expression has been stored in, if it's been CSEd
+ * once already.
+ */
+ ir_variable *var;
+};
+
+class cse_visitor : public ir_rvalue_visitor {
+public:
+ cse_visitor(exec_list *validate_instructions)
+ : validate_instructions(validate_instructions)
+ {
+ progress = false;
+ mem_ctx = ralloc_context(NULL);
+ this->ae = new(mem_ctx) exec_list;
+ }
+ ~cse_visitor()
+ {
+ ralloc_free(mem_ctx);
+ }
+
+ virtual ir_visitor_status visit_enter(ir_function_signature *ir);
+ virtual ir_visitor_status visit_enter(ir_loop *ir);
+ virtual ir_visitor_status visit_enter(ir_if *ir);
+ virtual ir_visitor_status visit_enter(ir_call *ir);
+ virtual void handle_rvalue(ir_rvalue **rvalue);
+
+ bool progress;
+
+private:
+ void *mem_ctx;
+
+ ir_rvalue *try_cse(ir_rvalue *rvalue);
+ void add_to_ae(ir_rvalue **rvalue);
+
+ /** List of ae_entry: The available expressions to reuse */
+ exec_list *ae;
+
+ /**
+ * The whole shader, so that we can validate_ir_tree in debug mode.
+ *
+ * This proved quite useful when trying to get the tree manipulation
+ * right.
+ */
+ exec_list *validate_instructions;
+};
+
+/**
+ * Visitor to walk an expression tree to check that all variables referenced
+ * are constants.
+ */
+class is_cse_candidate_visitor : public ir_hierarchical_visitor
+{
+public:
+
+ is_cse_candidate_visitor()
+ : ok(true)
+ {
+ }
+
+ virtual ir_visitor_status visit(ir_dereference_variable *ir);
+
+ bool ok;
+};
+
+
+class contains_rvalue_visitor : public ir_rvalue_visitor
+{
+public:
+
+ contains_rvalue_visitor(ir_rvalue *val)
+ : val(val)
+ {
+ found = false;
+ }
+
+ virtual void handle_rvalue(ir_rvalue **rvalue);
+
+ bool found;
+
+private:
+ ir_rvalue *val;
+};
+
+} /* unnamed namespace */
+
+static void
+dump_ae(exec_list *ae)
+{
+ int i = 0;
+
+ printf("CSE: AE contents:\n");
+ foreach_list(node, ae) {
+ ae_entry *entry = (ae_entry *)node;
+
+ printf("CSE: AE %2d (%p): ", i, entry);
+ (*entry->val)->print();
+ printf("\n");
+
+ if (entry->var)
+ printf("CSE: in var %p:\n", entry->var);
+
+ i++;
+ }
+}
+
+ir_visitor_status
+is_cse_candidate_visitor::visit(ir_dereference_variable *ir)
+{
+ /* Currently, since we don't handle kills of the ae based on variables
+ * getting assigned, we can only handle constant variables.
+ */
+ if (ir->var->read_only) {
+ return visit_continue;
+ } else {
+ ok = false;
+ return visit_stop;
+ }
+}
+
+void
+contains_rvalue_visitor::handle_rvalue(ir_rvalue **rvalue)
+{
+ if (*rvalue == val)
+ found = true;
+}
+
+static bool
+contains_rvalue(ir_rvalue *haystack, ir_rvalue *needle)
+{
+ contains_rvalue_visitor v(needle);
+ haystack->accept(&v);
+ return v.found;
+}
+
+static bool
+is_cse_candidate(ir_rvalue *ir)
+{
+ /* Our temporary variable assignment generation isn't ready to handle
+ * anything bigger than a vector.
+ */
+ if (!ir->type->is_vector() && !ir->type->is_scalar())
+ return false;
+
+ /* Only handle expressions and textures currently. We may want to extend
+ * to variable-index array dereferences at some point.
+ */
+ switch (ir->ir_type) {
+ case ir_type_expression:
+ case ir_type_texture:
+ break;
+ default:
+ return false;
+ }
+
+ is_cse_candidate_visitor v;
+
+ ir->accept(&v);
+
+ return v.ok;
+}
+
+static bool
+equals(ir_rvalue *a, ir_rvalue *b);
+
+static bool
+equals(ir_constant *a, ir_constant *b)
+{
+ if (!a || !b)
+ return false;
+
+ if (a->type != b->type)
+ return false;
+
+ for (unsigned i = 0; i < a->type->components(); i++) {
+ if (a->value.u[i] != b->value.u[i])
+ return false;
+ }
+
+ return true;
+}
+
+static bool
+equals(ir_dereference_variable *a, ir_dereference_variable *b)
+{
+ if (!a || !b)
+ return false;
+
+ return a->var == b->var;
+}
+
+static bool
+equals(ir_dereference_array *a, ir_dereference_array *b)
+{
+ if (!a || !b)
+ return false;
+
+ if (!equals(a->array, b->array))
+ return false;
+
+ if (!equals(a->array_index, b->array_index))
+ return false;
+
+ return true;
+}
+
+static bool
+equals(ir_swizzle *a, ir_swizzle *b)
+{
+ if (!a || !b)
+ return false;
+
+ if (a->type != b->type)
+ return false;
+
+ if (a->mask.x != b->mask.x ||
+ a->mask.y != b->mask.y ||
+ a->mask.z != b->mask.z ||
+ a->mask.w != b->mask.w) {
+ return false;
+ }
+
+ return equals(a->val, b->val);
+}
+
+static bool
+equals(ir_texture *a, ir_texture *b)
+{
+ if (!a || !b)
+ return false;
+
+ if (a->type != b->type)
+ return false;
+
+ if (a->op != b->op)
+ return false;
+
+ if (!equals(a->coordinate, b->coordinate))
+ return false;
+
+ if (!equals(a->projector, b->projector))
+ return false;
+
+ if (!equals(a->shadow_comparitor, b->shadow_comparitor))
+ return false;
+
+ if (!equals(a->offset, b->offset))
+ return false;
+
+ if (!equals(a->sampler, b->sampler))
+ return false;
+
+ switch (a->op) {
+ case ir_tex:
+ case ir_lod:
+ case ir_query_levels:
+ break;
+ case ir_txb:
+ if (!equals(a->lod_info.bias, b->lod_info.bias))
+ return false;
+ break;
+ case ir_txl:
+ case ir_txf:
+ case ir_txs:
+ if (!equals(a->lod_info.lod, b->lod_info.lod))
+ return false;
+ break;
+ case ir_txd:
+ if (!equals(a->lod_info.grad.dPdx, b->lod_info.grad.dPdx) ||
+ !equals(a->lod_info.grad.dPdy, b->lod_info.grad.dPdy))
+ return false;
+ case ir_txf_ms:
+ if (!equals(a->lod_info.sample_index, b->lod_info.sample_index))
+ return false;
+ break;
+ case ir_tg4:
+ if (!equals(a->lod_info.component, b->lod_info.component))
+ return false;
+ default:
+ assert(!"Unrecognized texture op");
+ }
+
+ return true;
+}
+
+static bool
+equals(ir_expression *a, ir_expression *b)
+{
+ if (!a || !b)
+ return false;
+
+ if (a->type != b->type)
+ return false;
+
+ if (a->operation != b->operation)
+ return false;
+
+ for (unsigned i = 0; i < a->get_num_operands(); i++) {
+ if (!equals(a->operands[i], b->operands[i]))
+ return false;
+ }
+
+ return true;
+}
+
+static bool
+equals(ir_rvalue *a, ir_rvalue *b)
+{
+ if (!a || !b)
+ return !a && !b;
+
+ if (a->type != b->type)
+ return false;
+
+ switch (a->ir_type) {
+ case ir_type_texture:
+ return equals(a->as_texture(), b->as_texture());
+
+ case ir_type_constant:
+ return equals(a->as_constant(), b->as_constant());
+
+ case ir_type_expression:
+ return equals(a->as_expression(), b->as_expression());
+
+ case ir_type_dereference_variable:
+ return equals(a->as_dereference_variable(), b->as_dereference_variable());
+
+ case ir_type_dereference_array:
+ return equals(a->as_dereference_array(), b->as_dereference_array());
+
+ case ir_type_swizzle:
+ return equals(a->as_swizzle(), b->as_swizzle());
+
+ default:
+ return false;
+ }
+}
+
+/**
+ * Tries to find and return a reference to a previous computation of a given
+ * expression.
+ *
+ * Walk the list of available expressions checking if any of them match the
+ * rvalue, and if so, move the previous copy of the expression to a temporary
+ * and return a reference of the temporary.
+ */
+ir_rvalue *
+cse_visitor::try_cse(ir_rvalue *rvalue)
+{
+ foreach_list(node, ae) {
+ ae_entry *entry = (ae_entry *)node;
+
+ if (debug) {
+ printf("Comparing to AE %p: ", entry);
+ (*entry->val)->print();
+ printf("\n");
+ }
+
+ if (!equals(rvalue, *entry->val))
+ continue;
+
+ if (debug) {
+ printf("CSE: Replacing: ");
+ (*entry->val)->print();
+ printf("\n");
+ printf("CSE: with: ");
+ rvalue->print();
+ printf("\n");
+ }
+
+ if (!entry->var) {
+ ir_instruction *base_ir = entry->base_ir;
+
+ ir_variable *var = new(rvalue) ir_variable(rvalue->type,
+ "cse",
+ ir_var_auto);
+
+ /* Write the previous expression result into a new variable. */
+ base_ir->insert_before(var);
+ ir_assignment *assignment = assign(var, *entry->val);
+ base_ir->insert_before(assignment);
+
+ /* Replace the expression in the original tree with a deref of the
+ * variable, but keep tracking the expression for further reuse.
+ */
+ *entry->val = new(rvalue) ir_dereference_variable(var);
+ entry->val = &assignment->rhs;
+
+ entry->var = var;
+
+ /* Update the base_irs in the AE list. We have to be sure that
+ * they're correct -- expressions from our base_ir that weren't moved
+ * need to stay in this base_ir (so that later consumption of them
+ * puts new variables between our new variable and our base_ir), but
+ * expressions from our base_ir that we *did* move need base_ir
+ * updated so that any further elimination from inside gets its new
+ * assignments put before our new assignment.
+ */
+ foreach_list(fixup_node, ae) {
+ ae_entry *fixup_entry = (ae_entry *)fixup_node;
+ if (contains_rvalue(assignment->rhs, *fixup_entry->val))
+ fixup_entry->base_ir = assignment;
+ }
+
+ if (debug)
+ dump_ae(ae);
+ }
+
+ /* Replace the expression in our current tree with the variable. */
+ return new(rvalue) ir_dereference_variable(entry->var);
+ }
+
+ return NULL;
+}
+
+/** Add the rvalue to the list of available expressions for CSE. */
+void
+cse_visitor::add_to_ae(ir_rvalue **rvalue)
+{
+ if (debug) {
+ printf("CSE: Add to AE: ");
+ (*rvalue)->print();
+ printf("\n");
+ }
+
+ ae->push_tail(new(mem_ctx) ae_entry(base_ir, rvalue));
+
+ if (debug)
+ dump_ae(ae);
+}
+
+void
+cse_visitor::handle_rvalue(ir_rvalue **rvalue)
+{
+ if (!*rvalue)
+ return;
+
+ if (debug) {
+ printf("CSE: handle_rvalue ");
+ (*rvalue)->print();
+ printf("\n");
+ }
+
+ if (!is_cse_candidate(*rvalue))
+ return;
+
+ ir_rvalue *new_rvalue = try_cse(*rvalue);
+ if (new_rvalue) {
+ *rvalue = new_rvalue;
+ progress = true;
+
+ if (debug)
+ validate_ir_tree(validate_instructions);
+ } else {
+ add_to_ae(rvalue);
+ }
+}
+
+ir_visitor_status
+cse_visitor::visit_enter(ir_if *ir)
+{
+ handle_rvalue(&ir->condition);
+
+ ae->make_empty();
+ visit_list_elements(this, &ir->then_instructions);
+
+ ae->make_empty();
+ visit_list_elements(this, &ir->else_instructions);
+
+ ae->make_empty();
+ return visit_continue_with_parent;
+}
+
+ir_visitor_status
+cse_visitor::visit_enter(ir_function_signature *ir)
+{
+ ae->make_empty();
+ visit_list_elements(this, &ir->body);
+
+ ae->make_empty();
+ return visit_continue_with_parent;
+}
+
+ir_visitor_status
+cse_visitor::visit_enter(ir_loop *ir)
+{
+ ae->make_empty();
+ visit_list_elements(this, &ir->body_instructions);
+
+ ae->make_empty();
+ return visit_continue_with_parent;
+}
+
+ir_visitor_status
+cse_visitor::visit_enter(ir_call *ir)
+{
+ /* Because call is an exec_list of ir_rvalues, handle_rvalue gets passed a
+ * pointer to the (ir_rvalue *) on the stack. Since we save those pointers
+ * in the AE list, we can't let handle_rvalue get called.
+ */
+ return visit_continue_with_parent;
+}
+
+/**
+ * Does a (uniform-value) constant subexpression elimination pass on the code
+ * present in the instruction stream.
+ */
+bool
+do_cse(exec_list *instructions)
+{
+ cse_visitor v(instructions);
+
+ visit_list_elements(&v, instructions);
+
+ return v.progress;
+}
diff --git a/mesalib/src/glsl/standalone_scaffolding.cpp b/mesalib/src/glsl/standalone_scaffolding.cpp
index 7a1cf6877..cbff6d182 100644
--- a/mesalib/src/glsl/standalone_scaffolding.cpp
+++ b/mesalib/src/glsl/standalone_scaffolding.cpp
@@ -97,6 +97,7 @@ void initialize_context_to_defaults(struct gl_context *ctx, gl_api api)
ctx->Extensions.ARB_explicit_attrib_location = true;
ctx->Extensions.ARB_fragment_coord_conventions = true;
ctx->Extensions.ARB_gpu_shader5 = true;
+ ctx->Extensions.ARB_sample_shading = true;
ctx->Extensions.ARB_shader_bit_encoding = true;
ctx->Extensions.ARB_shader_stencil_export = true;
ctx->Extensions.ARB_shader_texture_lod = true;
diff --git a/mesalib/src/mapi/glapi/gen/ARB_sample_shading.xml b/mesalib/src/mapi/glapi/gen/ARB_sample_shading.xml
new file mode 100644
index 000000000..cc8296a47
--- /dev/null
+++ b/mesalib/src/mapi/glapi/gen/ARB_sample_shading.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0"?>
+<!DOCTYPE OpenGLAPI SYSTEM "gl_API.dtd">
+
+<!-- Note: no GLX protocol info yet. -->
+
+<OpenGLAPI>
+
+<category name="GL_ARB_sample_shading" number="70">
+
+ <enum name="SAMPLE_SHADING_ARB" value="0x8C36"/>
+ <enum name="MIN_SAMPLE_SHADING_VALUE_ARB" value="0x8C37"/>
+
+ <function name="MinSampleShadingARB" alias="MinSampleShading">
+ <param name="value" type="GLfloat"/>
+ </function>
+
+</category>
+
+</OpenGLAPI>
diff --git a/mesalib/src/mapi/glapi/gen/GL4x.xml b/mesalib/src/mapi/glapi/gen/GL4x.xml
new file mode 100644
index 000000000..6706278ce
--- /dev/null
+++ b/mesalib/src/mapi/glapi/gen/GL4x.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0"?>
+<!DOCTYPE OpenGLAPI SYSTEM "gl_API.dtd">
+
+<!-- Note: no GLX protocol info yet. -->
+
+<OpenGLAPI>
+
+<category name="4.0">
+ <enum name="SAMPLE_SHADING" value="0x8C36"/>
+ <enum name="MIN_SAMPLE_SHADING_VALUE" value="0x8C37"/>
+
+ <function name="MinSampleShading" offset="assign">
+ <param name="value" type="GLfloat"/>
+ </function>
+</category>
+
+<category name="4.3">
+
+</category>
+
+</OpenGLAPI>
diff --git a/mesalib/src/mapi/glapi/gen/Makefile.am b/mesalib/src/mapi/glapi/gen/Makefile.am
index 390245216..cbbf659dd 100644
--- a/mesalib/src/mapi/glapi/gen/Makefile.am
+++ b/mesalib/src/mapi/glapi/gen/Makefile.am
@@ -108,6 +108,7 @@ API_XML = \
ARB_invalidate_subdata.xml \
ARB_map_buffer_range.xml \
ARB_robustness.xml \
+ ARB_sample_shading.xml \
ARB_sampler_objects.xml \
ARB_seamless_cube_map.xml \
ARB_shader_atomic_counters.xml \
@@ -144,7 +145,9 @@ API_XML = \
NV_texture_barrier.xml \
NV_vdpau_interop.xml \
OES_EGL_image.xml \
- GL3x.xml
+ GL3x.xml \
+ GL4x.xml
+
COMMON = $(API_XML) \
diff --git a/mesalib/src/mapi/glapi/gen/gl_API.xml b/mesalib/src/mapi/glapi/gen/gl_API.xml
index 45d69b40a..69014c5d2 100644
--- a/mesalib/src/mapi/glapi/gen/gl_API.xml
+++ b/mesalib/src/mapi/glapi/gen/gl_API.xml
@@ -8187,7 +8187,7 @@
<xi:include href="ARB_draw_buffers_blend.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
<xi:include href="AMD_draw_buffers_blend.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
-<!-- 70. GL_ARB_sample_shading -->
+<xi:include href="ARB_sample_shading.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
<xi:include href="ARB_texture_cube_map_array.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
<xi:include href="ARB_texture_gather.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
<!-- 73. GL_ARB_texture_query_lod -->
@@ -13122,4 +13122,6 @@
<xi:include href="NV_vdpau_interop.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
+<xi:include href="GL4x.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
+
</OpenGLAPI>
diff --git a/mesalib/src/mesa/drivers/common/meta.c b/mesalib/src/mesa/drivers/common/meta.c
index 798efa680..aa50dde73 100644
--- a/mesalib/src/mesa/drivers/common/meta.c
+++ b/mesalib/src/mesa/drivers/common/meta.c
@@ -1729,10 +1729,10 @@ blitframebuffer_texture(struct gl_context *ctx,
}
else {
assert(target == GL_TEXTURE_RECTANGLE_ARB);
- s0 = srcX0;
- s1 = srcX1;
- t0 = srcY0;
- t1 = srcY1;
+ s0 = (float) srcX0;
+ s1 = (float) srcX1;
+ t0 = (float) srcY0;
+ t1 = (float) srcY1;
}
/* setup vertex positions */
@@ -2825,7 +2825,7 @@ _mesa_meta_DrawPixels(struct gl_context *ctx,
_mesa_StencilMask(mask);
_mesa_ProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 0,
- 255.0 / mask, 0.5, 0.0, 0.0);
+ 255.0f / mask, 0.5f, 0.0f, 0.0f);
_mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4);
}
@@ -3184,7 +3184,7 @@ setup_texture_coords(GLenum faceTarget,
r = (slice + 0.5f) / depth;
}
else if (faceTarget == GL_TEXTURE_2D_ARRAY)
- r = slice;
+ r = (float) slice;
else
r = 0.0F;
coords0[0] = 0.0F; /* s */
@@ -3204,28 +3204,28 @@ setup_texture_coords(GLenum faceTarget,
coords0[0] = 0.0F; /* s */
coords0[1] = 0.0F; /* t */
coords0[2] = 0.0F; /* r */
- coords1[0] = width;
+ coords1[0] = (float) width;
coords1[1] = 0.0F;
coords1[2] = 0.0F;
- coords2[0] = width;
- coords2[1] = height;
+ coords2[0] = (float) width;
+ coords2[1] = (float) height;
coords2[2] = 0.0F;
coords3[0] = 0.0F;
- coords3[1] = height;
+ coords3[1] = (float) height;
coords3[2] = 0.0F;
break;
case GL_TEXTURE_1D_ARRAY:
coords0[0] = 0.0F; /* s */
- coords0[1] = slice; /* t */
+ coords0[1] = (float) slice; /* t */
coords0[2] = 0.0F; /* r */
coords1[0] = 1.0f;
- coords1[1] = slice;
+ coords1[1] = (float) slice;
coords1[2] = 0.0F;
coords2[0] = 1.0F;
- coords2[1] = slice;
+ coords2[1] = (float) slice;
coords2[2] = 0.0F;
coords3[0] = 0.0F;
- coords3[1] = slice;
+ coords3[1] = (float) slice;
coords3[2] = 0.0F;
break;
diff --git a/mesalib/src/mesa/main/dd.h b/mesalib/src/mesa/main/dd.h
index 501192199..d7c432713 100644
--- a/mesalib/src/mesa/main/dd.h
+++ b/mesalib/src/mesa/main/dd.h
@@ -843,6 +843,14 @@ struct dd_function_table {
struct gl_transform_feedback_object *obj);
/**
+ * Return the number of vertices written to a stream during the last
+ * Begin/EndTransformFeedback block.
+ */
+ GLsizei (*GetTransformFeedbackVertexCount)(struct gl_context *ctx,
+ struct gl_transform_feedback_object *obj,
+ GLuint stream);
+
+ /**
* \name GL_NV_texture_barrier interface
*/
void (*TextureBarrier)(struct gl_context *ctx);
diff --git a/mesalib/src/mesa/main/enable.c b/mesalib/src/mesa/main/enable.c
index 5e2fd80d2..dd6a772f9 100644
--- a/mesalib/src/mesa/main/enable.c
+++ b/mesalib/src/mesa/main/enable.c
@@ -802,6 +802,17 @@ _mesa_set_enable(struct gl_context *ctx, GLenum cap, GLboolean state)
ctx->Multisample.SampleCoverageInvert = state;
break;
+ /* GL_ARB_sample_shading */
+ case GL_SAMPLE_SHADING:
+ if (!_mesa_is_desktop_gl(ctx))
+ goto invalid_enum_error;
+ CHECK_EXTENSION(ARB_sample_shading, cap);
+ if (ctx->Multisample.SampleShading == state)
+ return;
+ FLUSH_VERTICES(ctx, _NEW_MULTISAMPLE);
+ ctx->Multisample.SampleShading = state;
+ break;
+
/* GL_IBM_rasterpos_clip */
case GL_RASTER_POSITION_UNCLIPPED_IBM:
if (ctx->API != API_OPENGL_COMPAT)
@@ -1594,6 +1605,13 @@ _mesa_IsEnabled( GLenum cap )
CHECK_EXTENSION(ARB_texture_multisample);
return ctx->Multisample.SampleMask;
+ /* ARB_sample_shading */
+ case GL_SAMPLE_SHADING:
+ if (!_mesa_is_desktop_gl(ctx))
+ goto invalid_enum_error;
+ CHECK_EXTENSION(ARB_sample_shading);
+ return ctx->Multisample.SampleShading;
+
default:
goto invalid_enum_error;
}
diff --git a/mesalib/src/mesa/main/extensions.c b/mesalib/src/mesa/main/extensions.c
index 285ec377c..48c4e9f1b 100644
--- a/mesalib/src/mesa/main/extensions.c
+++ b/mesalib/src/mesa/main/extensions.c
@@ -118,6 +118,7 @@ static const struct extension extension_table[] = {
{ "GL_ARB_point_sprite", o(ARB_point_sprite), GL, 2003 },
{ "GL_ARB_provoking_vertex", o(EXT_provoking_vertex), GL, 2009 },
{ "GL_ARB_robustness", o(dummy_true), GL, 2010 },
+ { "GL_ARB_sample_shading", o(ARB_sample_shading), GL, 2009 },
{ "GL_ARB_sampler_objects", o(dummy_true), GL, 2009 },
{ "GL_ARB_seamless_cube_map", o(ARB_seamless_cube_map), GL, 2009 },
{ "GL_ARB_shader_atomic_counters", o(ARB_shader_atomic_counters), GL, 2011 },
diff --git a/mesalib/src/mesa/main/get.c b/mesalib/src/mesa/main/get.c
index 6e72ff5c2..6a0de0c16 100644
--- a/mesalib/src/mesa/main/get.c
+++ b/mesalib/src/mesa/main/get.c
@@ -131,6 +131,7 @@ enum value_extra {
EXTRA_VERSION_30,
EXTRA_VERSION_31,
EXTRA_VERSION_32,
+ EXTRA_VERSION_40,
EXTRA_API_GL,
EXTRA_API_GL_CORE,
EXTRA_API_ES2,
@@ -391,6 +392,7 @@ extra_NV_primitive_restart[] = {
static const int extra_version_30[] = { EXTRA_VERSION_30, EXTRA_END };
static const int extra_version_31[] = { EXTRA_VERSION_31, EXTRA_END };
static const int extra_version_32[] = { EXTRA_VERSION_32, EXTRA_END };
+static const int extra_version_40[] = { EXTRA_VERSION_40, EXTRA_END };
static const int extra_gl30_es3[] = {
EXTRA_VERSION_30,
@@ -410,6 +412,12 @@ static const int extra_gl32_ARB_geometry_shader4[] = {
EXTRA_END
};
+static const int extra_gl40_ARB_sample_shading[] = {
+ EXTRA_VERSION_40,
+ EXT(ARB_sample_shading),
+ EXTRA_END
+};
+
static const int
extra_ARB_vertex_program_api_es2[] = {
EXT(ARB_vertex_program),
diff --git a/mesalib/src/mesa/main/get_hash_params.py b/mesalib/src/mesa/main/get_hash_params.py
index 9f79f3406..0851b7b70 100644
--- a/mesalib/src/mesa/main/get_hash_params.py
+++ b/mesalib/src/mesa/main/get_hash_params.py
@@ -83,6 +83,9 @@ descriptor=[
[ "SAMPLE_BUFFERS_ARB", "BUFFER_INT(Visual.sampleBuffers), extra_new_buffers" ],
[ "SAMPLES_ARB", "BUFFER_INT(Visual.samples), extra_new_buffers" ],
+# GL_ARB_sample_shading
+ [ "MIN_SAMPLE_SHADING_VALUE_ARB", "CONTEXT_FLOAT(Multisample.MinSampleShadingValue), extra_gl40_ARB_sample_shading" ],
+
# GL_SGIS_generate_mipmap
[ "GENERATE_MIPMAP_HINT_SGIS", "CONTEXT_ENUM(Hint.GenerateMipmap), NO_EXTRA" ],
diff --git a/mesalib/src/mesa/main/mtypes.h b/mesalib/src/mesa/main/mtypes.h
index a1a5eb4bf..b5c5583d6 100644
--- a/mesalib/src/mesa/main/mtypes.h
+++ b/mesalib/src/mesa/main/mtypes.h
@@ -274,6 +274,11 @@ typedef enum
#define VARYING_BIT_VAR(V) BITFIELD64_BIT(VARYING_SLOT_VAR0 + (V))
/*@}*/
+/**
+ * Bitflags for system values.
+ */
+#define SYSTEM_BIT_SAMPLE_ID BITFIELD64_BIT(SYSTEM_VALUE_SAMPLE_ID)
+#define SYSTEM_BIT_SAMPLE_POS BITFIELD64_BIT(SYSTEM_VALUE_SAMPLE_POS)
/**
* Determine if the given gl_varying_slot appears in the fragment shader.
@@ -306,12 +311,13 @@ typedef enum
* register is written. No FRAG_RESULT_DATAn will be written.
*/
FRAG_RESULT_COLOR = 2,
+ FRAG_RESULT_SAMPLE_MASK = 3,
/* FRAG_RESULT_DATAn are the per-render-target (GLSL gl_FragData[n]
* or ARB_fragment_program fragment.color[n]) color results. If
* any are written, FRAG_RESULT_COLOR will not be written.
*/
- FRAG_RESULT_DATA0 = 3,
+ FRAG_RESULT_DATA0 = 4,
FRAG_RESULT_MAX = (FRAG_RESULT_DATA0 + MAX_DRAW_BUFFERS)
} gl_frag_result;
@@ -872,6 +878,8 @@ struct gl_multisample_attrib
GLboolean SampleCoverage;
GLfloat SampleCoverageValue;
GLboolean SampleCoverageInvert;
+ GLboolean SampleShading;
+ GLfloat MinSampleShadingValue;
/* ARB_texture_multisample / GL3.2 additions */
GLboolean SampleMask;
@@ -1902,6 +1910,8 @@ typedef enum
SYSTEM_VALUE_FRONT_FACE, /**< Fragment shader only (not done yet) */
SYSTEM_VALUE_VERTEX_ID, /**< Vertex shader only */
SYSTEM_VALUE_INSTANCE_ID, /**< Vertex shader only */
+ SYSTEM_VALUE_SAMPLE_ID, /**< Fragment shader only */
+ SYSTEM_VALUE_SAMPLE_POS, /**< Fragment shader only */
SYSTEM_VALUE_MAX /**< Number of values */
} gl_system_value;
@@ -3156,6 +3166,12 @@ struct gl_constants
*/
GLboolean PrimitiveRestartInSoftware;
+ /**
+ * Always use the GetTransformFeedbackVertexCount() driver hook, rather
+ * than passing the transform feedback object to the drawing function.
+ */
+ GLboolean AlwaysUseGetTransformFeedbackVertexCount;
+
/** GL_ARB_map_buffer_alignment */
GLuint MinMapBufferAlignment;
@@ -3239,6 +3255,7 @@ struct gl_extensions
GLboolean ARB_occlusion_query;
GLboolean ARB_occlusion_query2;
GLboolean ARB_point_sprite;
+ GLboolean ARB_sample_shading;
GLboolean ARB_seamless_cube_map;
GLboolean ARB_shader_atomic_counters;
GLboolean ARB_shader_bit_encoding;
diff --git a/mesalib/src/mesa/main/multisample.c b/mesalib/src/mesa/main/multisample.c
index bd97c5096..599cdee74 100644
--- a/mesalib/src/mesa/main/multisample.c
+++ b/mesalib/src/mesa/main/multisample.c
@@ -119,6 +119,24 @@ _mesa_SampleMaski(GLuint index, GLbitfield mask)
ctx->Multisample.SampleMaskValue = mask;
}
+/**
+ * Called via glMinSampleShadingARB
+ */
+void GLAPIENTRY
+_mesa_MinSampleShading(GLclampf value)
+{
+ GET_CURRENT_CONTEXT(ctx);
+
+ if (!ctx->Extensions.ARB_sample_shading || !_mesa_is_desktop_gl(ctx)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glMinSampleShading");
+ return;
+ }
+
+ FLUSH_VERTICES(ctx, 0);
+
+ ctx->Multisample.MinSampleShadingValue = CLAMP(value, 0.0, 1.0);
+ ctx->NewState |= _NEW_MULTISAMPLE;
+}
/**
* Helper for checking a requested sample count against the limit
diff --git a/mesalib/src/mesa/main/multisample.h b/mesalib/src/mesa/main/multisample.h
index 66848d269..7441d3ee9 100644
--- a/mesalib/src/mesa/main/multisample.h
+++ b/mesalib/src/mesa/main/multisample.h
@@ -44,6 +44,8 @@ _mesa_GetMultisamplefv(GLenum pname, GLuint index, GLfloat* val);
extern void GLAPIENTRY
_mesa_SampleMaski(GLuint index, GLbitfield mask);
+extern void GLAPIENTRY
+_mesa_MinSampleShading(GLclampf value);
extern GLenum
_mesa_check_sample_count(struct gl_context *ctx, GLenum target,
diff --git a/mesalib/src/mesa/main/performance_monitor.c b/mesalib/src/mesa/main/performance_monitor.c
index 8dfa8261e..17cae5183 100644
--- a/mesalib/src/mesa/main/performance_monitor.c
+++ b/mesalib/src/mesa/main/performance_monitor.c
@@ -127,7 +127,7 @@ _mesa_GetPerfMonitorGroupsAMD(GLint *numGroups, GLsizei groupsSize,
if (groupsSize > 0 && groups != NULL) {
unsigned i;
- unsigned n = MIN2(groupsSize, ctx->PerfMonitor.NumGroups);
+ unsigned n = MIN2((GLuint) groupsSize, ctx->PerfMonitor.NumGroups);
/* We just use the index in the Groups array as the ID. */
for (i = 0; i < n; i++)
@@ -156,7 +156,7 @@ _mesa_GetPerfMonitorCountersAMD(GLuint group, GLint *numCounters,
if (counters != NULL) {
unsigned i;
- unsigned n = MIN2(group_obj->NumCounters, countersSize);
+ unsigned n = MIN2(group_obj->NumCounters, (GLuint) countersSize);
for (i = 0; i < n; i++) {
/* We just use the index in the Counters array as the ID. */
counters[i] = i;
@@ -379,7 +379,7 @@ _mesa_SelectPerfMonitorCountersAMD(GLuint monitor, GLboolean enable,
GLuint *counterList)
{
GET_CURRENT_CONTEXT(ctx);
- unsigned i;
+ int i;
struct gl_perf_monitor_object *m;
const struct gl_perf_monitor_group *group_obj;
diff --git a/mesalib/src/mesa/main/transformfeedback.c b/mesalib/src/mesa/main/transformfeedback.c
index bc9b52ab9..76d213b16 100644
--- a/mesalib/src/mesa/main/transformfeedback.c
+++ b/mesalib/src/mesa/main/transformfeedback.c
@@ -205,17 +205,27 @@ _mesa_free_transform_feedback(struct gl_context *ctx)
}
+/** Initialize the fields of a gl_transform_feedback_object. */
+void
+_mesa_init_transform_feedback_object(struct gl_transform_feedback_object *obj,
+ GLuint name)
+{
+ if (!obj)
+ return;
+
+ obj->Name = name;
+ obj->RefCount = 1;
+ obj->EverBound = GL_FALSE;
+}
+
+
/** Default fallback for ctx->Driver.NewTransformFeedback() */
static struct gl_transform_feedback_object *
new_transform_feedback(struct gl_context *ctx, GLuint name)
{
struct gl_transform_feedback_object *obj;
obj = CALLOC_STRUCT(gl_transform_feedback_object);
- if (obj) {
- obj->Name = name;
- obj->RefCount = 1;
- obj->EverBound = GL_FALSE;
- }
+ _mesa_init_transform_feedback_object(obj, name);
return obj;
}
diff --git a/mesalib/src/mesa/main/transformfeedback.h b/mesalib/src/mesa/main/transformfeedback.h
index 0ffaab508..7aecd66a7 100644
--- a/mesalib/src/mesa/main/transformfeedback.h
+++ b/mesalib/src/mesa/main/transformfeedback.h
@@ -91,6 +91,9 @@ _mesa_GetTransformFeedbackVarying(GLuint program, GLuint index,
/*** GL_ARB_transform_feedback2 ***/
+extern void
+_mesa_init_transform_feedback_object(struct gl_transform_feedback_object *obj,
+ GLuint name);
struct gl_transform_feedback_object *
_mesa_lookup_transform_feedback_object(struct gl_context *ctx, GLuint name);
diff --git a/mesalib/src/mesa/main/uniforms.c b/mesalib/src/mesa/main/uniforms.c
index 2e847fe31..17e24f678 100644
--- a/mesalib/src/mesa/main/uniforms.c
+++ b/mesalib/src/mesa/main/uniforms.c
@@ -853,7 +853,7 @@ _mesa_GetActiveAtomicCounterBufferiv(GLuint program, GLuint bufferIndex,
GET_CURRENT_CONTEXT(ctx);
struct gl_shader_program *shProg;
struct gl_active_atomic_buffer *ab;
- int i;
+ GLuint i;
if (!ctx->Extensions.ARB_shader_atomic_counters) {
_mesa_error(ctx, GL_INVALID_OPERATION,
diff --git a/mesalib/src/mesa/main/vdpau.c b/mesalib/src/mesa/main/vdpau.c
index e21a26b43..359757607 100644
--- a/mesalib/src/mesa/main/vdpau.c
+++ b/mesalib/src/mesa/main/vdpau.c
@@ -324,7 +324,7 @@ void GLAPIENTRY
_mesa_VDPAUMapSurfacesNV(GLsizei numSurfaces, const GLintptr *surfaces)
{
GET_CURRENT_CONTEXT(ctx);
- int i, j;
+ int i;
if (!ctx->vdpDevice || !ctx->vdpGetProcAddress || !ctx->vdpSurfaces) {
_mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUUnmapSurfacesNV");
@@ -348,6 +348,7 @@ _mesa_VDPAUMapSurfacesNV(GLsizei numSurfaces, const GLintptr *surfaces)
for (i = 0; i < numSurfaces; ++i) {
struct vdp_surface *surf = (struct vdp_surface *)surfaces[i];
unsigned numTextureNames = surf->output ? 1 : 4;
+ unsigned j;
for (j = 0; j < numTextureNames; ++j) {
struct gl_texture_object *tex = surf->textures[j];
@@ -377,7 +378,7 @@ void GLAPIENTRY
_mesa_VDPAUUnmapSurfacesNV(GLsizei numSurfaces, const GLintptr *surfaces)
{
GET_CURRENT_CONTEXT(ctx);
- int i, j;
+ int i;
if (!ctx->vdpDevice || !ctx->vdpGetProcAddress || !ctx->vdpSurfaces) {
_mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUUnmapSurfacesNV");
@@ -401,6 +402,7 @@ _mesa_VDPAUUnmapSurfacesNV(GLsizei numSurfaces, const GLintptr *surfaces)
for (i = 0; i < numSurfaces; ++i) {
struct vdp_surface *surf = (struct vdp_surface *)surfaces[i];
unsigned numTextureNames = surf->output ? 1 : 4;
+ unsigned j;
for (j = 0; j < numTextureNames; ++j) {
struct gl_texture_object *tex = surf->textures[j];
diff --git a/mesalib/src/mesa/program/prog_print.c b/mesalib/src/mesa/program/prog_print.c
index cf852132d..fa9063f5b 100644
--- a/mesalib/src/mesa/program/prog_print.c
+++ b/mesalib/src/mesa/program/prog_print.c
@@ -311,6 +311,7 @@ arb_output_attrib_string(GLint index, GLenum progType)
"result.depth", /* FRAG_RESULT_DEPTH */
"result.(one)", /* FRAG_RESULT_STENCIL */
"result.color", /* FRAG_RESULT_COLOR */
+ "result.samplemask", /* FRAG_RESULT_SAMPLE_MASK */
"result.color[0]", /* FRAG_RESULT_DATA0 (named for GLSL's gl_FragData) */
"result.color[1]",
"result.color[2]",
diff --git a/mesalib/src/mesa/program/prog_statevars.c b/mesalib/src/mesa/program/prog_statevars.c
index 145c07c67..f6fd53576 100644
--- a/mesalib/src/mesa/program/prog_statevars.c
+++ b/mesalib/src/mesa/program/prog_statevars.c
@@ -349,6 +349,9 @@ _mesa_fetch_state(struct gl_context *ctx, const gl_state_index state[],
}
}
return;
+ case STATE_NUM_SAMPLES:
+ ((int *)value)[0] = ctx->DrawBuffer->Visual.samples;
+ return;
case STATE_DEPTH_RANGE:
value[0] = ctx->Viewport.Near; /* near */
value[1] = ctx->Viewport.Far; /* far */
@@ -665,6 +668,9 @@ _mesa_program_state_flags(const gl_state_index state[STATE_LENGTH])
case STATE_PROGRAM_MATRIX:
return _NEW_TRACK_MATRIX;
+ case STATE_NUM_SAMPLES:
+ return _NEW_BUFFERS;
+
case STATE_DEPTH_RANGE:
return _NEW_VIEWPORT;
@@ -852,6 +858,9 @@ append_token(char *dst, gl_state_index k)
case STATE_TEXENV_COLOR:
append(dst, "texenv");
break;
+ case STATE_NUM_SAMPLES:
+ append(dst, "numsamples");
+ break;
case STATE_DEPTH_RANGE:
append(dst, "depth.range");
break;
@@ -1027,6 +1036,8 @@ _mesa_program_state_string(const gl_state_index state[STATE_LENGTH])
break;
case STATE_FOG_COLOR:
break;
+ case STATE_NUM_SAMPLES:
+ break;
case STATE_DEPTH_RANGE:
break;
case STATE_FRAGMENT_PROGRAM:
diff --git a/mesalib/src/mesa/program/prog_statevars.h b/mesalib/src/mesa/program/prog_statevars.h
index ec22b7376..23a9f48c3 100644
--- a/mesalib/src/mesa/program/prog_statevars.h
+++ b/mesalib/src/mesa/program/prog_statevars.h
@@ -103,6 +103,8 @@ typedef enum gl_state_index_ {
STATE_TEXENV_COLOR,
+ STATE_NUM_SAMPLES, /* An integer, not a float like the other state vars */
+
STATE_DEPTH_RANGE,
STATE_VERTEX_PROGRAM,
diff --git a/mesalib/src/mesa/program/program.c b/mesalib/src/mesa/program/program.c
index 093d37297..a102ec17a 100644
--- a/mesalib/src/mesa/program/program.c
+++ b/mesalib/src/mesa/program/program.c
@@ -32,6 +32,7 @@
#include "main/glheader.h"
#include "main/context.h"
#include "main/hash.h"
+#include "main/macros.h"
#include "program.h"
#include "prog_cache.h"
#include "prog_parameter.h"
@@ -1024,3 +1025,34 @@ _mesa_postprocess_program(struct gl_context *ctx, struct gl_program *prog)
}
}
+
+/* Gets the minimum number of shader invocations per fragment.
+ * This function is useful to determine if we need to do per
+ * sample shading or per fragment shading.
+ */
+GLint
+_mesa_get_min_invocations_per_fragment(struct gl_context *ctx,
+ const struct gl_fragment_program *prog)
+{
+ /* From ARB_sample_shading specification:
+ * "Using gl_SampleID in a fragment shader causes the entire shader
+ * to be evaluated per-sample."
+ *
+ * "Using gl_SamplePosition in a fragment shader causes the entire
+ * shader to be evaluated per-sample."
+ *
+ * "If MULTISAMPLE or SAMPLE_SHADING_ARB is disabled, sample shading
+ * has no effect."
+ */
+ if (ctx->Multisample.Enabled) {
+ if (prog->Base.SystemValuesRead & (SYSTEM_BIT_SAMPLE_ID |
+ SYSTEM_BIT_SAMPLE_POS))
+ return MAX2(ctx->DrawBuffer->Visual.samples, 1);
+ else if (ctx->Multisample.SampleShading)
+ return MAX2(ceil(ctx->Multisample.MinSampleShadingValue *
+ ctx->DrawBuffer->Visual.samples), 1);
+ else
+ return 1;
+ }
+ return 1;
+}
diff --git a/mesalib/src/mesa/program/program.h b/mesalib/src/mesa/program/program.h
index 34965ab99..353ccab47 100644
--- a/mesalib/src/mesa/program/program.h
+++ b/mesalib/src/mesa/program/program.h
@@ -187,6 +187,9 @@ _mesa_valid_register_index(const struct gl_context *ctx,
extern void
_mesa_postprocess_program(struct gl_context *ctx, struct gl_program *prog);
+extern GLint
+_mesa_get_min_invocations_per_fragment(struct gl_context *ctx,
+ const struct gl_fragment_program *prog);
static inline GLuint
_mesa_program_target_to_index(GLenum v)
diff --git a/mesalib/src/mesa/state_tracker/st_cb_xformfb.c b/mesalib/src/mesa/state_tracker/st_cb_xformfb.c
index e1a7a88a1..e824fe9b3 100644
--- a/mesalib/src/mesa/state_tracker/st_cb_xformfb.c
+++ b/mesalib/src/mesa/state_tracker/st_cb_xformfb.c
@@ -74,8 +74,8 @@ st_new_transform_feedback(struct gl_context *ctx, GLuint name)
if (!obj)
return NULL;
- obj->base.Name = name;
- obj->base.RefCount = 1;
+ _mesa_init_transform_feedback_object(&obj->base, name);
+
return &obj->base;
}
diff --git a/mesalib/src/mesa/state_tracker/st_draw.h b/mesalib/src/mesa/state_tracker/st_draw.h
index 3313fc8c7..394473b20 100644
--- a/mesalib/src/mesa/state_tracker/st_draw.h
+++ b/mesalib/src/mesa/state_tracker/st_draw.h
@@ -77,7 +77,7 @@ st_feedback_draw_vbo(struct gl_context *ctx,
static INLINE unsigned
pointer_to_offset(const void *ptr)
{
- return (unsigned) (((unsigned long) ptr) & 0xffffffffUL);
+ return (unsigned) (((GLsizeiptr) ptr) & 0xffffffffUL);
}
diff --git a/mesalib/src/mesa/swrast/s_texfetch_tmp.h b/mesalib/src/mesa/swrast/s_texfetch_tmp.h
index 7a687532d..e2521b50c 100644
--- a/mesalib/src/mesa/swrast/s_texfetch_tmp.h
+++ b/mesalib/src/mesa/swrast/s_texfetch_tmp.h
@@ -1537,7 +1537,7 @@ static void FETCH(f_z24_s8)( const struct swrast_texture_image *texImage,
/* only return Z, not stencil data */
const GLuint *src = TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
const GLdouble scale = 1.0 / (GLdouble) 0xffffff;
- texel[0] = ((*src) >> 8) * scale;
+ texel[0] = (GLfloat) (((*src) >> 8) * scale);
ASSERT(texImage->Base.TexFormat == MESA_FORMAT_Z24_S8 ||
texImage->Base.TexFormat == MESA_FORMAT_Z24_X8);
ASSERT(texel[0] >= 0.0F);
@@ -1555,7 +1555,7 @@ static void FETCH(f_s8_z24)( const struct swrast_texture_image *texImage,
/* only return Z, not stencil data */
const GLuint *src = TEXEL_ADDR(GLuint, texImage, i, j, k, 1);
const GLdouble scale = 1.0 / (GLdouble) 0xffffff;
- texel[0] = ((*src) & 0x00ffffff) * scale;
+ texel[0] = (GLfloat) (((*src) & 0x00ffffff) * scale);
ASSERT(texImage->Base.TexFormat == MESA_FORMAT_S8_Z24 ||
texImage->Base.TexFormat == MESA_FORMAT_X8_Z24);
ASSERT(texel[0] >= 0.0F);
diff --git a/mesalib/src/mesa/vbo/vbo_attrib_tmp.h b/mesalib/src/mesa/vbo/vbo_attrib_tmp.h
index 02c283da4..bbc020539 100644
--- a/mesalib/src/mesa/vbo/vbo_attrib_tmp.h
+++ b/mesalib/src/mesa/vbo/vbo_attrib_tmp.h
@@ -140,7 +140,7 @@ static inline float conv_i10_to_norm_float(const struct gl_context *ctx, int i10
(ctx->API == API_OPENGL_CORE && ctx->Version >= 42)) {
/* Equation 2.3 above. */
float f = ((float) val.x) / 511.0F;
- return MAX2(f, -1.0);
+ return MAX2(f, -1.0f);
} else {
/* Equation 2.2 above. */
return (2.0F * (float)val.x + 1.0F) * (1.0F / 1023.0F);
@@ -156,7 +156,7 @@ static inline float conv_i2_to_norm_float(const struct gl_context *ctx, int i2)
(ctx->API == API_OPENGL_CORE && ctx->Version >= 42)) {
/* Equation 2.3 above. */
float f = (float) val.x;
- return MAX2(f, -1.0);
+ return MAX2(f, -1.0f);
} else {
/* Equation 2.2 above. */
return (2.0F * (float)val.x + 1.0F) * (1.0F / 3.0F);
diff --git a/mesalib/src/mesa/vbo/vbo_exec_array.c b/mesalib/src/mesa/vbo/vbo_exec_array.c
index 1670409d4..f25a9dec3 100644
--- a/mesalib/src/mesa/vbo/vbo_exec_array.c
+++ b/mesalib/src/mesa/vbo/vbo_exec_array.c
@@ -1464,6 +1464,16 @@ vbo_draw_transform_feedback(struct gl_context *ctx, GLenum mode,
return;
}
+ if (ctx->Driver.GetTransformFeedbackVertexCount &&
+ (ctx->Const.AlwaysUseGetTransformFeedbackVertexCount ||
+ (ctx->Const.PrimitiveRestartInSoftware &&
+ ctx->Array._PrimitiveRestart) ||
+ !vbo_all_varyings_in_vbos(exec->array.inputs))) {
+ GLsizei n = ctx->Driver.GetTransformFeedbackVertexCount(ctx, obj, stream);
+ vbo_draw_arrays(ctx, mode, 0, n, numInstances, 0);
+ return;
+ }
+
vbo_bind_arrays(ctx);
/* init most fields to zero */
diff --git a/pixman/configure.ac b/pixman/configure.ac
index 8a3b62268..5e512be8e 100644
--- a/pixman/configure.ac
+++ b/pixman/configure.ac
@@ -54,7 +54,7 @@ AC_PREREQ([2.57])
m4_define([pixman_major], 0)
m4_define([pixman_minor], 31)
-m4_define([pixman_micro], 1)
+m4_define([pixman_micro], 3)
m4_define([pixman_version],[pixman_major.pixman_minor.pixman_micro])
@@ -1044,6 +1044,22 @@ fi
AC_MSG_RESULT($support_for_float128)
+dnl =====================================
+dnl __builtin_clz
+
+support_for_builtin_clz=no
+
+AC_MSG_CHECKING(for __builtin_clz)
+AC_LINK_IFELSE([AC_LANG_SOURCE([[
+unsigned int x = 11; int main (void) { return __builtin_clz(x); }
+]])], support_for_builtin_clz=yes)
+
+if test x$support_for_builtin_clz = xyes; then
+ AC_DEFINE([HAVE_BUILTIN_CLZ], [], [Whether the compiler supports __builtin_clz])
+fi
+
+AC_MSG_RESULT($support_for_builtin_clz)
+
dnl ==================
dnl libpng
diff --git a/pixman/pixman/pixman-matrix.c b/pixman/pixman/pixman-matrix.c
index 89b96826b..4032c137a 100644
--- a/pixman/pixman/pixman-matrix.c
+++ b/pixman/pixman/pixman-matrix.c
@@ -37,7 +37,7 @@
static force_inline int
count_leading_zeros (uint32_t x)
{
-#ifdef __GNUC__
+#ifdef HAVE_BUILTIN_CLZ
return __builtin_clz (x);
#else
int n = 0;
diff --git a/pixman/pixman/pixman.h b/pixman/pixman/pixman.h
index 7ff9fb52a..509ba5e53 100644
--- a/pixman/pixman/pixman.h
+++ b/pixman/pixman/pixman.h
@@ -1030,7 +1030,7 @@ struct pixman_triangle
#define pixman_trapezoid_valid(t) \
((t)->left.p1.y != (t)->left.p2.y && \
(t)->right.p1.y != (t)->right.p2.y && \
- (int) ((t)->bottom - (t)->top) > 0)
+ ((t)->bottom > (t)->top))
struct pixman_span_fix
{
diff --git a/pixman/test/trap-crasher.c b/pixman/test/trap-crasher.c
index 4e4cac297..77be1c98b 100644
--- a/pixman/test/trap-crasher.c
+++ b/pixman/test/trap-crasher.c
@@ -5,7 +5,7 @@ int
main()
{
pixman_image_t *dst;
- pixman_trapezoid_t traps[1] = {
+ pixman_trapezoid_t traps[] = {
{
2147483646,
2147483647,
@@ -18,6 +18,18 @@ main()
{ 0, 2147483647 }
}
},
+ {
+ 32768,
+ - 2147483647,
+ {
+ { 0, 0 },
+ { 0, 2147483647 }
+ },
+ {
+ { 65536, 0 },
+ { 0, 2147483647 }
+ }
+ },
};
dst = pixman_image_create_bits (PIXMAN_a8, 1, 1, NULL, -1);
diff --git a/xkbcomp/action.c b/xkbcomp/action.c
index 3b82e647e..4623c0caf 100644
--- a/xkbcomp/action.c
+++ b/xkbcomp/action.c
@@ -41,7 +41,7 @@ static ExprDef constFalse;
/***====================================================================***/
static Bool
-stringToAction(char *str, unsigned *type_rtrn)
+stringToAction(const char *str, unsigned *type_rtrn)
{
if (str == NULL)
return False;
@@ -134,7 +134,7 @@ stringToAction(char *str, unsigned *type_rtrn)
}
static Bool
-stringToField(char *str, unsigned *field_rtrn)
+stringToField(const char *str, unsigned *field_rtrn)
{
if (str == NULL)
@@ -1397,8 +1397,8 @@ HandleActionDef(ExprDef * def,
int
SetActionField(XkbDescPtr xkb,
- char *elem,
- char *field,
+ const char *elem,
+ const char *field,
ExprDef * array_ndx, ExprDef * value, ActionInfo ** info_rtrn)
{
ActionInfo *new, *old;
diff --git a/xkbcomp/action.h b/xkbcomp/action.h
index 2fb7a5eb9..983b06e20 100644
--- a/xkbcomp/action.h
+++ b/xkbcomp/action.h
@@ -72,8 +72,8 @@ extern int HandleActionDef(ExprDef * /* def */ ,
);
extern int SetActionField(XkbDescPtr /* xkb */ ,
- char * /* elem */ ,
- char * /* field */ ,
+ const char * /* elem */ ,
+ const char * /* field */ ,
ExprDef * /* index */ ,
ExprDef * /* value */ ,
ActionInfo ** /* info_rtrn */
diff --git a/xkbcomp/compat.c b/xkbcomp/compat.c
index f4d82a6de..82fd4e666 100644
--- a/xkbcomp/compat.c
+++ b/xkbcomp/compat.c
@@ -494,7 +494,7 @@ static LookupEntry useModMapValues[] = {
static int
SetInterpField(SymInterpInfo * si,
XkbDescPtr xkb,
- char *field,
+ const char *field,
ExprDef * arrayNdx, ExprDef * value, CompatInfo * info)
{
int ok = 1;
diff --git a/xkbcomp/expr.c b/xkbcomp/expr.c
index 96fd95675..e0f957c15 100644
--- a/xkbcomp/expr.c
+++ b/xkbcomp/expr.c
@@ -292,7 +292,7 @@ ExprResolveModIndex(ExprDef * expr,
IdentLookupFunc lookup, XPointer lookupPriv)
{
int ok = 0;
- char *bogus = NULL;
+ const char *bogus = NULL;
switch (expr->op)
{
@@ -382,7 +382,7 @@ ExprResolveBoolean(ExprDef * expr,
IdentLookupFunc lookup, XPointer lookupPriv)
{
int ok = 0;
- char *bogus = NULL;
+ const char *bogus = NULL;
switch (expr->op)
{
@@ -715,7 +715,7 @@ ExprResolveString(ExprDef * expr,
ExprResult leftRtrn, rightRtrn;
ExprDef *left;
ExprDef *right;
- char *bogus = NULL;
+ const char *bogus = NULL;
switch (expr->op)
{
@@ -729,7 +729,7 @@ ExprResolveString(ExprDef * expr,
val_rtrn->str = XkbAtomGetString(NULL, expr->value.str);
if (val_rtrn->str == NULL)
{
- static char *empty = "";
+ static const char *empty = "";
val_rtrn->str = empty;
}
return True;
@@ -767,7 +767,7 @@ ExprResolveString(ExprDef * expr,
new = (char *) uAlloc(len);
if (new)
{
- sprintf(new, "%s%s", leftRtrn.str, rightRtrn.str);
+ snprintf(new, len, "%s%s", leftRtrn.str, rightRtrn.str);
val_rtrn->str = new;
return True;
}
@@ -822,7 +822,7 @@ ExprResolveKeyName(ExprDef * expr,
int ok = 0;
ExprDef *left;
ExprResult leftRtrn;
- char *bogus = NULL;
+ const char *bogus = NULL;
switch (expr->op)
{
@@ -941,7 +941,7 @@ ExprResolveMask(ExprDef * expr,
int ok = 0;
ExprResult leftRtrn, rightRtrn;
ExprDef *left, *right;
- char *bogus = NULL;
+ const char *bogus = NULL;
switch (expr->op)
{
diff --git a/xkbcomp/geometry.c b/xkbcomp/geometry.c
index 7f65c3af4..2daa213ac 100644
--- a/xkbcomp/geometry.c
+++ b/xkbcomp/geometry.c
@@ -258,9 +258,9 @@ ddText(Display * dpy, DoodadInfo * di)
}
if (di->section)
{
- sprintf(buf, "%s in section %s",
- XkbAtomText(dpy, di->name, XkbMessage), scText(dpy,
- di->section));
+ snprintf(buf, sizeof(buf), "%s in section %s",
+ XkbAtomText(dpy, di->name, XkbMessage),
+ scText(dpy, di->section));
return buf;
}
return XkbAtomText(dpy, di->name, XkbMessage);
@@ -967,7 +967,7 @@ AddDoodad(SectionInfo * si, GeometryInfo * info, DoodadInfo * new)
}
static DoodadInfo *
-FindDfltDoodadByTypeName(char *name, SectionInfo * si, GeometryInfo * info)
+FindDfltDoodadByTypeName(const char *name, SectionInfo *si, GeometryInfo *info)
{
DoodadInfo *dflt;
unsigned type;
@@ -1408,7 +1408,7 @@ HandleIncludeGeometry(IncludeStmt * stmt, XkbDescPtr xkb, GeometryInfo * info,
static int
SetShapeField(ShapeInfo * si,
- char *field,
+ const char *field,
ExprDef * arrayNdx, ExprDef * value, GeometryInfo * info)
{
ExprResult tmp;
@@ -1440,7 +1440,7 @@ SetShapeField(ShapeInfo * si,
static int
SetShapeDoodadField(DoodadInfo * di,
- char *field,
+ const char *field,
ExprDef * arrayNdx,
ExprDef * value, SectionInfo * si, GeometryInfo * info)
{
@@ -1510,14 +1510,14 @@ SetShapeDoodadField(DoodadInfo * di,
static int
SetTextDoodadField(DoodadInfo * di,
- char *field,
+ const char *field,
ExprDef * arrayNdx,
ExprDef * value, SectionInfo * si, GeometryInfo * info)
{
ExprResult tmp;
unsigned def;
unsigned type;
- char *typeName = "text doodad";
+ const char *typeName = "text doodad";
union
{
Atom *str;
@@ -1660,7 +1660,7 @@ SetTextDoodadField(DoodadInfo * di,
static int
SetIndicatorDoodadField(DoodadInfo * di,
- char *field,
+ const char *field,
ExprDef * arrayNdx,
ExprDef * value,
SectionInfo * si, GeometryInfo * info)
@@ -1705,12 +1705,12 @@ SetIndicatorDoodadField(DoodadInfo * di,
static int
SetLogoDoodadField(DoodadInfo * di,
- char *field,
+ const char *field,
ExprDef * arrayNdx,
ExprDef * value, SectionInfo * si, GeometryInfo * info)
{
ExprResult tmp;
- char *typeName = "logo doodad";
+ const char *typeName = "logo doodad";
if ((!uStrCaseCmp(field, "corner"))
|| (!uStrCaseCmp(field, "cornerradius")))
@@ -1786,7 +1786,7 @@ SetLogoDoodadField(DoodadInfo * di,
static int
SetDoodadField(DoodadInfo * di,
- char *field,
+ const char *field,
ExprDef * arrayNdx,
ExprDef * value, SectionInfo * si, GeometryInfo * info)
{
@@ -1889,7 +1889,7 @@ SetDoodadField(DoodadInfo * di,
static int
SetSectionField(SectionInfo * si,
- char *field,
+ const char *field,
ExprDef * arrayNdx, ExprDef * value, GeometryInfo * info)
{
unsigned short *pField;
@@ -1977,7 +1977,7 @@ SetSectionField(SectionInfo * si,
static int
SetRowField(RowInfo * row,
- char *field,
+ const char *field,
ExprDef * arrayNdx, ExprDef * value, GeometryInfo * info)
{
ExprResult tmp;
@@ -2841,7 +2841,7 @@ HandleGeometryFile(XkbFile * file,
XkbDescPtr xkb, unsigned merge, GeometryInfo * info)
{
ParseCommon *stmt;
- char *failWhat;
+ const char *failWhat;
if (merge == MergeDefault)
merge = MergeAugment;
@@ -3273,7 +3273,7 @@ FontFromParts(Atom fontTok,
Atom setWidthTok, Atom varTok, int size, Atom encodingTok)
{
int totalSize;
- char *font, *weight, *slant, *setWidth, *variant, *encoding;
+ const char *font, *weight, *slant, *setWidth, *variant, *encoding;
char *rtrn;
font = (fontTok != None ? XkbAtomGetString(NULL, fontTok) : DFLT_FONT);
@@ -3297,8 +3297,8 @@ FontFromParts(Atom fontTok,
rtrn = uCalloc(totalSize, 1);
if (rtrn)
{
- sprintf(rtrn, FONT_TEMPLATE, font, weight, slant, setWidth, variant,
- size, encoding);
+ snprintf(rtrn, totalSize, FONT_TEMPLATE, font, weight, slant,
+ setWidth, variant, size, encoding);
}
return rtrn;
}
diff --git a/xkbcomp/indicators.c b/xkbcomp/indicators.c
index d4a362fb8..421ad583d 100644
--- a/xkbcomp/indicators.c
+++ b/xkbcomp/indicators.c
@@ -200,7 +200,7 @@ static LookupEntry groupComponentNames[] = {
int
SetIndicatorMapField(LEDInfo * led,
XkbDescPtr xkb,
- char *field, ExprDef * arrayNdx, ExprDef * value)
+ const char *field, ExprDef *arrayNdx, ExprDef *value)
{
ExprResult rtrn;
Bool ok;
diff --git a/xkbcomp/indicators.h b/xkbcomp/indicators.h
index 35ae38a4c..8e7884d7c 100644
--- a/xkbcomp/indicators.h
+++ b/xkbcomp/indicators.h
@@ -62,7 +62,7 @@ extern LEDInfo *AddIndicatorMap(LEDInfo * /* oldLEDs */ ,
extern int SetIndicatorMapField(LEDInfo * /* led */ ,
XkbDescPtr /* xkb */ ,
- char * /* field */ ,
+ const char * /* field */ ,
ExprDef * /* arrayNdx */ ,
ExprDef * /* value */
);
diff --git a/xkbcomp/keytypes.c b/xkbcomp/keytypes.c
index da55d755d..375ca3e0d 100644
--- a/xkbcomp/keytypes.c
+++ b/xkbcomp/keytypes.c
@@ -879,7 +879,7 @@ SetLevelName(KeyTypeInfo * type, ExprDef * arrayNdx, ExprDef * value)
static Bool
SetKeyTypeField(KeyTypeInfo * type,
XkbDescPtr xkb,
- char *field,
+ const char *field,
ExprDef * arrayNdx, ExprDef * value, KeyTypesInfo * info)
{
ExprResult tmp;
diff --git a/xkbcomp/listing.c b/xkbcomp/listing.c
index 11de88a83..c7f5ef83b 100644
--- a/xkbcomp/listing.c
+++ b/xkbcomp/listing.c
@@ -302,18 +302,19 @@ AddDirectory(char *head, char *ptrn, char *rest, char *map)
{
char *tmp, *filename;
struct stat sbuf;
+ size_t tmpsize;
filename = FileName(file);
if (!filename || filename[0] == '.')
continue;
if (ptrn && (!XkbNameMatchesPattern(filename, ptrn)))
continue;
- tmp =
- (char *) uAlloc((head ? strlen(head) : 0) + strlen(filename) + 2);
+ tmpsize = (head ? strlen(head) : 0) + strlen(filename) + 2;
+ tmp = uAlloc(tmpsize);
if (!tmp)
continue;
- sprintf(tmp, "%s%s%s", (head ? head : ""), (head ? "/" : ""),
- filename);
+ snprintf(tmp, tmpsize, "%s%s%s",
+ (head ? head : ""), (head ? "/" : ""), filename);
if (stat(tmp, &sbuf) < 0)
{
uFree(tmp);
diff --git a/xkbcomp/symbols.c b/xkbcomp/symbols.c
index 5547999b5..d43ba9ffb 100644
--- a/xkbcomp/symbols.c
+++ b/xkbcomp/symbols.c
@@ -928,7 +928,7 @@ GetGroupIndex(KeyInfo * key,
static Bool
AddSymbolsToKey(KeyInfo * key,
XkbDescPtr xkb,
- char *field,
+ const char *field,
ExprDef * arrayNdx, ExprDef * value, SymbolsInfo * info)
{
unsigned ndx, nSyms;
@@ -982,7 +982,7 @@ AddSymbolsToKey(KeyInfo * key,
static Bool
AddActionsToKey(KeyInfo * key,
XkbDescPtr xkb,
- char *field,
+ const char *field,
ExprDef * arrayNdx, ExprDef * value, SymbolsInfo * info)
{
register int i;
@@ -1118,7 +1118,7 @@ static LookupEntry rgEntries[] = {
static Bool
SetSymbolsField(KeyInfo * key,
XkbDescPtr xkb,
- char *field,
+ const char *field,
ExprDef * arrayNdx, ExprDef * value, SymbolsInfo * info)
{
Bool ok = True;
@@ -1235,7 +1235,7 @@ SetSymbolsField(KeyInfo * key,
uStrCasePrefix("permanentoverlay", field))
{
Bool permanent = False;
- char *which;
+ const char *which;
int overlayNdx;
if (uStrCasePrefix("permanent", field))
{
diff --git a/xkbcomp/utils.c b/xkbcomp/utils.c
index 55efbe11f..541c33e14 100644
--- a/xkbcomp/utils.c
+++ b/xkbcomp/utils.c
@@ -88,65 +88,6 @@ uFree(Opaque ptr)
}
/***====================================================================***/
-/*** FUNCTION ENTRY TRACKING ***/
-/***====================================================================***/
-
-static FILE *entryFile = NULL;
-int uEntryLevel;
-
-Boolean
-uSetEntryFile(char *name)
-{
- if ((entryFile != NULL) && (entryFile != stderr))
- {
- fprintf(entryFile, "switching to %s\n", name ? name : "stderr");
- fclose(entryFile);
- }
- if (name != NullString)
- entryFile = fopen(name, "w");
- else
- entryFile = stderr;
- if (entryFile == NULL)
- {
- entryFile = stderr;
- return (False);
- }
- return (True);
-}
-
-void
-uEntry(int l, char *s, ...)
-{
- int i;
- va_list args;
-
- for (i = 0; i < uEntryLevel; i++)
- {
- putc(' ', entryFile);
- }
- va_start(args, s);
- vfprintf(entryFile, s, args);
- va_end(args);
- uEntryLevel += l;
-}
-
-void
-uExit(int l, char *rtVal)
-{
- int i;
-
- uEntryLevel -= l;
- if (uEntryLevel < 0)
- uEntryLevel = 0;
- for (i = 0; i < uEntryLevel; i++)
- {
- putc(' ', entryFile);
- }
- fprintf(entryFile, "---> %p\n", rtVal);
- return;
-}
-
-/***====================================================================***/
/*** PRINT FUNCTIONS ***/
/***====================================================================***/
diff --git a/xkbcomp/utils.h b/xkbcomp/utils.h
index b00067d6e..81f5893b6 100644
--- a/xkbcomp/utils.h
+++ b/xkbcomp/utils.h
@@ -219,15 +219,6 @@ uInformation(const char * /* s */ , ...
/***====================================================================***/
-#ifdef ASSERTIONS_ON
-#define uASSERT(where,why) \
- {if (!(why)) uFatalError("assertion botched in %s ( why )\n",where);}
-#else
-#define uASSERT(where,why)
-#endif
-
-/***====================================================================***/
-
#ifndef DEBUG_VAR
#define DEBUG_VAR debugFlags
#endif
@@ -277,64 +268,4 @@ extern
#define uDEBUG_NOI5(f,s,a,b,c,d,e)
#endif
- extern Boolean uSetEntryFile(char *name);
- extern void uEntry(int /* l */ ,
- char * /* s */ , ...
- ) _X_ATTRIBUTE_PRINTF(2, 3);
-
- extern void uExit(int l, char *rtVal);
-#ifdef ENTRY_TRACKING_ON
-#define ENTRY_BIT 0x10
-#define LOW_ENTRY_BIT 0x1000
-#define ENTER (DEBUG_VAR&ENTRY_BIT)
-#define FLAG(fLag) (DEBUG_VAR&(fLag))
-
- extern int uEntryLevel;
-
-#define uENTRY(s) { if (ENTER) uEntry(1,s);}
-#define uENTRY1(s,a) { if (ENTER) uEntry(1,s,a);}
-#define uENTRY2(s,a,b) { if (ENTER) uEntry(1,s,a,b);}
-#define uENTRY3(s,a,b,c) { if (ENTER) uEntry(1,s,a,b,c);}
-#define uENTRY4(s,a,b,c,d) { if (ENTER) uEntry(1,s,a,b,c,d);}
-#define uENTRY5(s,a,b,c,d,e) { if (ENTER) uEntry(1,s,a,b,c,d,e);}
-#define uENTRY6(s,a,b,c,d,e,f) { if (ENTER) uEntry(1,s,a,b,c,d,e,f);}
-#define uENTRY7(s,a,b,c,d,e,f,g) { if (ENTER) uEntry(1,s,a,b,c,d,e,f,g);}
-#define uRETURN(v) { if (ENTER) uEntryLevel--; return(v); }
-#define uVOIDRETURN { if (ENTER) uEntryLevel--; return; }
-
-#define uFLAG_ENTRY(w,s) { if (FLAG(w)) uEntry(0,s);}
-#define uFLAG_ENTRY1(w,s,a) { if (FLAG(w)) uEntry(0,s,a);}
-#define uFLAG_ENTRY2(w,s,a,b) { if (FLAG(w)) uEntry(0,s,a,b);}
-#define uFLAG_ENTRY3(w,s,a,b,c) { if (FLAG(w)) uEntry(0,s,a,b,c);}
-#define uFLAG_ENTRY4(w,s,a,b,c,d) { if (FLAG(w)) uEntry(0,s,a,b,c,d);}
-#define uFLAG_ENTRY5(w,s,a,b,c,d,e) { if (FLAG(w)) uEntry(0,s,a,b,c,d,e);}
-#define uFLAG_ENTRY6(w,s,a,b,c,d,e,f) { if (FLAG(w)) uEntry(0,s,a,b,c,d,e,f);}
-#define uFLAG_ENTRY7(w,s,a,b,c,d,e,f,g) { if(FLAG(w))uEntry(0,s,a,b,c,d,e,f,g);}
-#define uFLAG_RETURN(v) { return(v);}
-#define uFLAG_VOIDRETURN { return; }
-#else
-#define uENTRY(s)
-#define uENTRY1(s,a)
-#define uENTRY2(s,a1,a2)
-#define uENTRY3(s,a1,a2,a3)
-#define uENTRY4(s,a1,a2,a3,a4)
-#define uENTRY5(s,a1,a2,a3,a4,a5)
-#define uENTRY6(s,a1,a2,a3,a4,a5,a6)
-#define uENTRY7(s,a1,a2,a3,a4,a5,a6,a7)
-#define uRETURN(v) { return(v); }
-#define uVOIDRETURN { return; }
-
-#define uFLAG_ENTRY(f,s)
-#define uFLAG_ENTRY1(f,s,a)
-#define uFLAG_ENTRY2(f,s,a,b)
-#define uFLAG_ENTRY3(f,s,a,b,c)
-#define uFLAG_ENTRY4(f,s,a,b,c,d)
-#define uFLAG_ENTRY5(f,s,a,b,c,d,e)
-#define uFLAG_ENTRY6(f,s,a,b,c,d,e,g)
-#define uFLAG_ENTRY7(f,s,a,b,c,d,e,g,h)
-#define uFLAG_RETURN(v) { return(v);}
-#define uFLAG_VOIDRETURN { return; }
-#endif
-
-
#endif /* UTILS_H */
diff --git a/xkbcomp/xkbcomp.c b/xkbcomp/xkbcomp.c
index fb5dec2fc..956e79c0f 100644
--- a/xkbcomp/xkbcomp.c
+++ b/xkbcomp/xkbcomp.c
@@ -745,7 +745,7 @@ parseArgs(int argc, char *argv[])
ACTION("Exiting\n");
exit(1);
}
- sprintf(outputFile, "stdin.%s", fileTypeExt[outputFormat]);
+ snprintf(outputFile, len, "stdin.%s", fileTypeExt[outputFormat]);
}
else if ((outputFile == NULL) && (inputFile != NULL))
{
@@ -773,7 +773,7 @@ parseArgs(int argc, char *argv[])
}
ext = strrchr(base, '.');
if (ext == NULL)
- sprintf(outputFile, "%s.%s", base, fileTypeExt[outputFormat]);
+ snprintf(outputFile, len, "%s.%s", base, fileTypeExt[outputFormat]);
else
{
strcpy(outputFile, base);
@@ -881,7 +881,6 @@ main(int argc, char *argv[])
Status status;
scan_set_file(stdin);
- uSetEntryFile(NullString);
uSetDebugFile(NullString);
uSetErrorFile(NullString);
diff --git a/xorg-server/Makefile.am b/xorg-server/Makefile.am
index 7be4271d4..5bf760b2e 100644
--- a/xorg-server/Makefile.am
+++ b/xorg-server/Makefile.am
@@ -17,6 +17,14 @@ if RECORD
RECORD_DIR=record
endif
+if DRI3
+DRI3_DIR=dri3
+endif
+
+if PRESENT
+PRESENT_DIR=present
+endif
+
SUBDIRS = \
doc \
man \
@@ -38,6 +46,8 @@ SUBDIRS = \
damageext \
$(COMPOSITE_DIR) \
$(GLX_DIR) \
+ $(PRESENT_DIR) \
+ $(DRI3_DIR) \
exa \
config \
hw \
@@ -91,6 +101,8 @@ DIST_SUBDIRS = \
glx \
exa \
config \
+ dri3 \
+ present \
hw \
test
diff --git a/xorg-server/Xext/shm.c b/xorg-server/Xext/shm.c
index 55960907b..1a70260fb 100644
--- a/xorg-server/Xext/shm.c
+++ b/xorg-server/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 */
@@ -89,15 +90,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;
@@ -391,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;
@@ -402,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)) {
@@ -440,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);
@@ -1097,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);
@@ -1125,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;
}
@@ -1226,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);
@@ -1242,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/xorg-server/Xext/shmint.h b/xorg-server/Xext/shmint.h
index fa6941c90..db35fbbbe 100644
--- a/xorg-server/Xext/shmint.h
+++ b/xorg-server/Xext/shmint.h
@@ -56,6 +56,16 @@ typedef struct _ShmFuncs {
void (*PutImage) (XSHM_PUT_IMAGE_ARGS);
} ShmFuncs, *ShmFuncsPtr;
+typedef struct _ShmDesc {
+ struct _ShmDesc *next;
+ int shmid;
+ int refcnt;
+ char *addr;
+ Bool is_fd;
+ Bool writable;
+ unsigned long size;
+} ShmDescRec, *ShmDescPtr;
+
extern _X_EXPORT void
ShmRegisterFuncs(ScreenPtr pScreen, ShmFuncsPtr funcs);
diff --git a/xorg-server/Xext/sync.c b/xorg-server/Xext/sync.c
index b2ee92e37..a04c38388 100644
--- a/xorg-server/Xext/sync.c
+++ b/xorg-server/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)
{
@@ -2654,7 +2682,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
diff --git a/xorg-server/Xext/syncsrv.h b/xorg-server/Xext/syncsrv.h
index c68229f46..45fca04da 100644
--- a/xorg-server/Xext/syncsrv.h
+++ b/xorg-server/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/xorg-server/Xext/xvdisp.c b/xorg-server/Xext/xvdisp.c
index 787729387..613867a6b 100644
--- a/xorg-server/Xext/xvdisp.c
+++ b/xorg-server/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)
diff --git a/xorg-server/configure.ac b/xorg-server/configure.ac
index d29f1706a..0d855f250 100644
--- a/xorg-server/configure.ac
+++ b/xorg-server/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])
@@ -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])
@@ -300,7 +296,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])
@@ -613,6 +609,8 @@ 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(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])
@@ -635,6 +633,8 @@ 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])
+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])
@@ -715,6 +715,7 @@ case $host_os in
CONFIG_UDEV_KMS=no
DGA=no
DRI2=no
+ DRI3=no
INT10MODULE=no
PCI=no
VGAHW=no
@@ -732,6 +733,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 +783,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"
@@ -803,6 +806,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"
@@ -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)
@@ -1141,6 +1160,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
@@ -1306,6 +1333,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])
@@ -1564,7 +1592,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.
@@ -1577,7 +1605,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 $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])
@@ -1598,7 +1626,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 $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])
@@ -1623,7 +1651,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 $PRESENT_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $XI_LIB $XKB_LIB"
dnl ==================================================================
dnl symbol visibility
@@ -1705,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
@@ -1715,11 +1740,16 @@ if test "x$XORG" = xyes; then
linux_alpha=yes
;;
i*86|amd64*|x86_64*|ia64*)
- linux_acpi="yes"
+ linux_acpi=$enable_linux_acpi
;;
*)
;;
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"
@@ -1882,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])
@@ -2036,7 +2067,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 $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])
@@ -2145,7 +2176,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 $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*)
@@ -2267,6 +2298,8 @@ Xext/Makefile
Xi/Makefile
xfixes/Makefile
exa/Makefile
+dri3/Makefile
+present/Makefile
hw/Makefile
hw/xfree86/Makefile
hw/xfree86/common/Makefile
diff --git a/xorg-server/dix/region.c b/xorg-server/dix/region.c
index 737d2a861..15f3d01a5 100644
--- a/xorg-server/dix/region.c
+++ b/xorg-server/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/xorg-server/dri3/Makefile.am b/xorg-server/dri3/Makefile.am
new file mode 100644
index 000000000..e47a734e0
--- /dev/null
+++ b/xorg-server/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/xorg-server/dri3/dri3.c b/xorg-server/dri3/dri3.c
new file mode 100644
index 000000000..2bca7ae9b
--- /dev/null
+++ b/xorg-server/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/xorg-server/dri3/dri3.h b/xorg-server/dri3/dri3.h
new file mode 100644
index 000000000..7774c8757
--- /dev/null
+++ b/xorg-server/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/xorg-server/dri3/dri3_event.c b/xorg-server/dri3/dri3_event.c
new file mode 100644
index 000000000..02f0f6579
--- /dev/null
+++ b/xorg-server/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 = &current->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/xorg-server/dri3/dri3_priv.h b/xorg-server/dri3/dri3_priv.h
new file mode 100644
index 000000000..e2fed839b
--- /dev/null
+++ b/xorg-server/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/xorg-server/dri3/dri3_request.c b/xorg-server/dri3/dri3_request.c
new file mode 100644
index 000000000..3ebb9d509
--- /dev/null
+++ b/xorg-server/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/xorg-server/dri3/dri3_screen.c b/xorg-server/dri3/dri3_screen.c
new file mode 100644
index 000000000..cf2735b8d
--- /dev/null
+++ b/xorg-server/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/xorg-server/dri3/dri3int.h b/xorg-server/dri3/dri3int.h
new file mode 100644
index 000000000..7f53eba45
--- /dev/null
+++ b/xorg-server/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@fooishbar.org>
+ */
+
+extern Bool DRI2ModuleSetup(void);
diff --git a/xorg-server/glx/glxcmds.c b/xorg-server/glx/glxcmds.c
index 64ebf9ecd..efa4aecb2 100644
--- a/xorg-server/glx/glxcmds.c
+++ b/xorg-server/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);
diff --git a/xorg-server/glx/glxdricommon.c b/xorg-server/glx/glxdricommon.c
index 48f0bce21..1022c0075 100644
--- a/xorg-server/glx/glxdricommon.c
+++ b/xorg-server/glx/glxdricommon.c
@@ -178,6 +178,7 @@ createModeFromConfig(const __DRIcoreExtension * core,
config->config.visualType = visualType;
config->config.renderType = renderType;
config->config.drawableType = drawableType;
+ config->config.yInverted = GL_TRUE;
return &config->config;
}
diff --git a/xorg-server/hw/dmx/dmxextension.c b/xorg-server/hw/dmx/dmxextension.c
index d7296ae2d..c6c6a8e6d 100644
--- a/xorg-server/hw/dmx/dmxextension.c
+++ b/xorg-server/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/xorg-server/hw/dmx/dmxinit.c b/xorg-server/hw/dmx/dmxinit.c
index 65416ed26..bd868a092 100644
--- a/xorg-server/hw/dmx/dmxinit.c
+++ b/xorg-server/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/xorg-server/hw/kdrive/ephyr/hostx.c b/xorg-server/hw/kdrive/ephyr/hostx.c
index 5fa33b9db..ee9ae455c 100644
--- a/xorg-server/hw/kdrive/ephyr/hostx.c
+++ b/xorg-server/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,13 +714,21 @@ 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 {
- EPHYR_DBG("server bpp %i", scrpriv->server_depth >> 3);
- scrpriv->fb_data =
- malloc(width * buffer_height * (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", bytes_per_pixel);
+ scrpriv->fb_data = malloc (stride * buffer_height);
return scrpriv->fb_data;
}
}
@@ -762,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:
diff --git a/xorg-server/hw/xfree86/Makefile.am b/xorg-server/hw/xfree86/Makefile.am
index 59cfb5f6f..eea16a851 100644
--- a/xorg-server/hw/xfree86/Makefile.am
+++ b/xorg-server/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/xorg-server/hw/xfree86/common/xf86Configure.c b/xorg-server/hw/xfree86/common/xf86Configure.c
index 6c5e35919..91e8df93d 100644
--- a/xorg-server/hw/xfree86/common/xf86Configure.c
+++ b/xorg-server/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;
diff --git a/xorg-server/hw/xfree86/common/xf86DPMS.c b/xorg-server/hw/xfree86/common/xf86DPMS.c
index 3f1e142c7..881cb2773 100644
--- a/xorg-server/hw/xfree86/common/xf86DPMS.c
+++ b/xorg-server/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;
}
diff --git a/xorg-server/hw/xfree86/common/xf86Events.c b/xorg-server/hw/xfree86/common/xf86Events.c
index 7a949fd74..d0b14314b 100644
--- a/xorg-server/hw/xfree86/common/xf86Events.c
+++ b/xorg-server/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;
}
diff --git a/xorg-server/hw/xfree86/common/xf86RandR.c b/xorg-server/hw/xfree86/common/xf86RandR.c
index 5606bee4b..2418731dc 100644
--- a/xorg-server/hw/xfree86/common/xf86RandR.c
+++ b/xorg-server/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;
}
diff --git a/xorg-server/hw/xfree86/modes/xf86Crtc.c b/xorg-server/hw/xfree86/modes/xf86Crtc.c
index 35845e875..2a02c8507 100644
--- a/xorg-server/hw/xfree86/modes/xf86Crtc.c
+++ b/xorg-server/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);
}
}
diff --git a/xorg-server/hw/xfree86/sdksyms.sh b/xorg-server/hw/xfree86/sdksyms.sh
index 48b48b5db..7c9734c07 100644
--- a/xorg-server/hw/xfree86/sdksyms.sh
+++ b/xorg-server/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/xorg-server/hw/xquartz/bundle/Info.plist.cpp b/xorg-server/hw/xquartz/bundle/Info.plist.cpp
index b0106c6da..b99e417aa 100644
--- a/xorg-server/hw/xquartz/bundle/Info.plist.cpp
+++ b/xorg-server/hw/xquartz/bundle/Info.plist.cpp
@@ -19,9 +19,9 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
- <string>2.7.4</string>
+ <string>2.7.6</string>
<key>CFBundleVersion</key>
- <string>2.7.4</string>
+ <string>2.7.6</string>
<key>CFBundleSignature</key>
<string>x11a</string>
<key>CSResourcesFileMapped</key>
diff --git a/xorg-server/include/dix-config.h.in b/xorg-server/include/dix-config.h.in
index a643dfcc8..397ee967a 100644
--- a/xorg-server/include/dix-config.h.in
+++ b/xorg-server/include/dix-config.h.in
@@ -39,6 +39,9 @@
/* Build DPMS extension */
#undef DPMSExtension
+/* Build DRI3 extension */
+#undef DRI3
+
/* Build GLX extension */
#undef GLXEXT
@@ -252,6 +255,9 @@
/* Internal define for Xinerama */
#undef PANORAMIX
+/* Support Present extension */
+#undef PRESENT
+
/* Overall prefix */
#undef PROJECTROOT
diff --git a/xorg-server/include/dixstruct.h b/xorg-server/include/dixstruct.h
index 7711cde99..456e63360 100644
--- a/xorg-server/include/dixstruct.h
+++ b/xorg-server/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/xorg-server/include/extinit.h b/xorg-server/include/extinit.h
index 6d67bf2e5..fa5f29378 100644
--- a/xorg-server/include/extinit.h
+++ b/xorg-server/include/extinit.h
@@ -176,4 +176,14 @@ extern void XvExtensionInit(void);
extern void XvMCExtensionInit(void);
#endif
+#if defined(DRI3)
+#include <X11/extensions/dri3proto.h>
+extern void dri3_extension_init(void);
+#endif
+
+#if defined(PRESENT)
+#include <X11/extensions/presentproto.h>
+#include "presentext.h"
+#endif
+
#endif
diff --git a/xorg-server/include/misc.h b/xorg-server/include/misc.h
index 0c67f11fe..17de71041 100644
--- a/xorg-server/include/misc.h
+++ b/xorg-server/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)
diff --git a/xorg-server/include/os.h b/xorg-server/include/os.h
index c7108a5d3..11b219845 100644
--- a/xorg-server/include/os.h
+++ b/xorg-server/include/os.h
@@ -98,6 +98,10 @@ extern _X_EXPORT int WaitForSomething(int * /*pClientsReady */
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 */ );
@@ -165,6 +169,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/xorg-server/include/regionstr.h b/xorg-server/include/regionstr.h
index 805257b3f..4a0725d62 100644
--- a/xorg-server/include/regionstr.h
+++ b/xorg-server/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)
{
diff --git a/xorg-server/include/xorg-config.h.in b/xorg-server/include/xorg-config.h.in
index 0df31aeb2..487d7addb 100644
--- a/xorg-server/include/xorg-config.h.in
+++ b/xorg-server/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_ */
diff --git a/xorg-server/include/xorg-server.h.in b/xorg-server/include/xorg-server.h.in
index 81935be5c..1281b3e5e 100644
--- a/xorg-server/include/xorg-server.h.in
+++ b/xorg-server/include/xorg-server.h.in
@@ -28,6 +28,9 @@
/* Build DPMS extension */
#undef DPMSExtension
+/* Build DRI3 extension */
+#undef DRI3
+
/* Build GLX extension */
#undef GLXEXT
@@ -67,6 +70,9 @@
/* Internal define for Xinerama */
#undef PANORAMIX
+/* Support Present extension */
+#undef PRESENT
+
/* Support RANDR extension */
#undef RANDR
diff --git a/xorg-server/mi/miinitext.c b/xorg-server/mi/miinitext.c
index 145da38e9..636618282 100644
--- a/xorg-server/mi/miinitext.c
+++ b/xorg-server/mi/miinitext.c
@@ -287,6 +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/xorg-server/miext/damage/damage.c b/xorg-server/miext/damage/damage.c
index cc0299143..173fe5070 100644
--- a/xorg-server/miext/damage/damage.c
+++ b/xorg-server/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);
}
diff --git a/xorg-server/miext/sync/Makefile.am b/xorg-server/miext/sync/Makefile.am
index 9aa1ba5d5..e25ceacb0 100644
--- a/xorg-server/miext/sync/Makefile.am
+++ b/xorg-server/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/xorg-server/miext/sync/misync.c b/xorg-server/miext/sync/misync.c
index b6914d18d..3d03d1b59 100644
--- a/xorg-server/miext/sync/misync.c
+++ b/xorg-server/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,15 +169,15 @@ miSyncSetup(ScreenPtr pScreen)
&miSyncScreenDestroyFence
};
- if (!dixPrivateKeyRegistered(syncScreenPrivateKey)) {
- if (!dixRegisterPrivateKey(syncScreenPrivateKey, PRIVATE_SCREEN,
+ if (!dixPrivateKeyRegistered(&miSyncScreenPrivateKey)) {
+ if (!dixRegisterPrivateKey(&miSyncScreenPrivateKey, PRIVATE_SCREEN,
sizeof(SyncScreenPrivRec)))
return FALSE;
}
pScreenPriv = SYNC_SCREEN_PRIV(pScreen);
- if (pScreenPriv->funcs.CreateFence) {
+ if (!pScreenPriv->funcs.CreateFence) {
pScreenPriv->funcs = miSyncScreenFuncs;
/* Wrap CloseScreen to clean up */
diff --git a/xorg-server/miext/sync/misync.h b/xorg-server/miext/sync/misync.h
index deebb82bc..f63ec2b82 100644
--- a/xorg-server/miext/sync/misync.h
+++ b/xorg-server/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/xorg-server/miext/sync/misyncshm.c b/xorg-server/miext/sync/misyncshm.c
new file mode 100644
index 000000000..ddd15ae49
--- /dev/null
+++ b/xorg-server/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/xorg-server/miext/sync/misyncshm.h b/xorg-server/miext/sync/misyncshm.h
new file mode 100644
index 000000000..4edbb50c3
--- /dev/null
+++ b/xorg-server/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/xorg-server/miext/sync/misyncstr.h b/xorg-server/miext/sync/misyncstr.h
index e19256fee..b5bf6fd91 100644
--- a/xorg-server/miext/sync/misyncstr.h
+++ b/xorg-server/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/xorg-server/os/backtrace.c b/xorg-server/os/backtrace.c
index 426f9b15b..3d1195b86 100644
--- a/xorg-server/os/backtrace.c
+++ b/xorg-server/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);
diff --git a/xorg-server/os/connection.c b/xorg-server/os/connection.c
index 6cd8bcf43..162e1d93e 100644
--- a/xorg-server/os/connection.c
+++ b/xorg-server/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/xorg-server/os/io.c b/xorg-server/os/io.c
index 380036664..a20faa56f 100644
--- a/xorg-server/os/io.c
+++ b/xorg-server/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,29 @@ 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;
+}
+
+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.
diff --git a/xorg-server/os/utils.c b/xorg-server/os/utils.c
index 97c3125e6..995f62a37 100644
--- a/xorg-server/os/utils.c
+++ b/xorg-server/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
diff --git a/xorg-server/os/xstrans.c b/xorg-server/os/xstrans.c
index 6348a6511..2bc79e7ae 100644
--- a/xorg-server/os/xstrans.c
+++ b/xorg-server/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
diff --git a/xorg-server/present/Makefile.am b/xorg-server/present/Makefile.am
new file mode 100644
index 000000000..7fea6699f
--- /dev/null
+++ b/xorg-server/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/xorg-server/present/present.c b/xorg-server/present/present.c
new file mode 100644
index 000000000..4c97ce40c
--- /dev/null
+++ b/xorg-server/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/xorg-server/present/present.h b/xorg-server/present/present.h
new file mode 100644
index 000000000..6a451fb23
--- /dev/null
+++ b/xorg-server/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/xorg-server/present/present_event.c b/xorg-server/present/present_event.c
new file mode 100644
index 000000000..a30bc8286
--- /dev/null
+++ b/xorg-server/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 = &current->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/xorg-server/present/present_fake.c b/xorg-server/present/present_fake.c
new file mode 100644
index 000000000..a67759254
--- /dev/null
+++ b/xorg-server/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/xorg-server/present/present_fence.c b/xorg-server/present/present_fence.c
new file mode 100644
index 000000000..db5efcaad
--- /dev/null
+++ b/xorg-server/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/xorg-server/present/present_notify.c b/xorg-server/present/present_notify.c
new file mode 100644
index 000000000..e272e08dc
--- /dev/null
+++ b/xorg-server/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(&notify->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(&notify->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(&notifies[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(&notifies[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(&notifies[i]);
+
+ free(notifies);
+}
diff --git a/xorg-server/present/present_priv.h b/xorg-server/present/present_priv.h
new file mode 100644
index 000000000..a92b62a2d
--- /dev/null
+++ b/xorg-server/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/xorg-server/present/present_request.c b/xorg-server/present/present_request.c
new file mode 100644
index 000000000..095fa2daf
--- /dev/null
+++ b/xorg-server/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), &notifies);
+ 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/xorg-server/present/present_screen.c b/xorg-server/present/present_screen.c
new file mode 100644
index 000000000..50b2b2d23
--- /dev/null
+++ b/xorg-server/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/xorg-server/present/presentext.h b/xorg-server/present/presentext.h
new file mode 100644
index 000000000..f177f55dc
--- /dev/null
+++ b/xorg-server/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_ */
diff --git a/xorg-server/test/Makefile.am b/xorg-server/test/Makefile.am
index eff0c9d81..e59c412ee 100644
--- a/xorg-server/test/Makefile.am
+++ b/xorg-server/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