From 401eb04e4dfb179291befb19d74e2e3148c4e268 Mon Sep 17 00:00:00 2001 From: marha Date: Fri, 8 Nov 2013 11:09:17 +0100 Subject: libxtrans libxcb xcb-proto mesa git update 8 nov 2013 libxcb commit e8663a935890ff366f49e356211049dfd0d9756a libxcb/xcb-proto commit 29beba6bf02bda86a5b163ace63e1d0a4d3eee5b libxtrans commit 0153d1670e4a1883e1bb6dd971435d6268eac5ba mesa commit 035cce83f7b3d9a037c9e7cc17a212d6cf7e927f --- X11/xtrans/Xtrans.c | 9 + X11/xtrans/Xtrans.h | 6 + X11/xtrans/Xtransint.h | 6 +- X11/xtrans/Xtranslcl.c | 35 ++ X11/xtrans/Xtranssock.c | 110 +++- X11/xtrans/configure.ac | 2 +- X11/xtrans/xtrans.m4 | 35 ++ libxcb/Makefile.am | 6 + libxcb/configure.ac | 59 +- libxcb/src/.gitignore | 2 + libxcb/src/Makefile.am | 18 +- libxcb/src/c_client.py | 69 +- libxcb/src/xcb.h | 58 +- libxcb/src/xcb_conn.c | 36 +- libxcb/src/xcb_in.c | 290 ++++++++- libxcb/src/xcb_out.c | 18 + libxcb/src/xcbext.h | 6 +- libxcb/src/xcbint.h | 17 + libxcb/xcb-dri3.pc.in | 11 + libxcb/xcb-present.pc.in | 11 + libxcb/xcb-proto/configure.ac | 2 +- libxcb/xcb-proto/src/present.xml | 2 +- libxcb/xcb-proto/src/xcb.xsd | 4 + libxcb/xcb-proto/xcbgen/xtypes.py | 38 -- mesalib/configure.ac | 82 +-- mesalib/docs/GL3.txt | 12 +- mesalib/docs/relnotes/10.0.html | 3 + mesalib/docs/specs/MESA_query_renderer.spec | 405 ++++++++++++ mesalib/include/GL/glx.h | 27 +- mesalib/include/GL/internal/dri_interface.h | 167 ++++- mesalib/src/gallium/SConscript | 8 - mesalib/src/gallium/auxiliary/util/u_format.c | 16 +- mesalib/src/gallium/auxiliary/util/u_format.h | 18 +- mesalib/src/gallium/auxiliary/util/u_math.h | 13 + mesalib/src/glsl/Makefile.sources | 1 + mesalib/src/glsl/ast.h | 15 + mesalib/src/glsl/ast_to_hir.cpp | 63 +- mesalib/src/glsl/ast_type.cpp | 13 +- mesalib/src/glsl/builtin_functions.cpp | 3 +- mesalib/src/glsl/glsl_lexer.ll | 2 +- mesalib/src/glsl/glsl_parser.yy | 13 +- mesalib/src/glsl/glsl_parser_extras.h | 3 + mesalib/src/glsl/link_atomics.cpp | 277 ++++++++ mesalib/src/glsl/linker.cpp | 21 +- mesalib/src/glsl/linker.h | 8 + mesalib/src/mapi/glapi/Makefile.am | 5 +- .../mapi/glapi/gen/ARB_vertex_attrib_binding.xml | 58 ++ mesalib/src/mapi/glapi/gen/Makefile.am | 7 +- mesalib/src/mapi/glapi/gen/gl_API.xml | 6 +- mesalib/src/mesa/.gitignore | 2 + mesalib/src/mesa/Makefile.am | 33 +- mesalib/src/mesa/drivers/dri/common/dri_util.c | 156 +++-- mesalib/src/mesa/drivers/dri/common/dri_util.h | 14 + mesalib/src/mesa/drivers/dri/common/utils.c | 64 ++ mesalib/src/mesa/drivers/dri/common/utils.h | 3 + mesalib/src/mesa/main/api_arrayelt.c | 43 +- mesalib/src/mesa/main/arrayobj.c | 73 ++- mesalib/src/mesa/main/arrayobj.h | 5 + mesalib/src/mesa/main/attrib.c | 7 +- mesalib/src/mesa/main/bufferobj.c | 28 +- mesalib/src/mesa/main/bufferobj.h | 9 +- mesalib/src/mesa/main/context.c | 6 +- mesalib/src/mesa/main/dd.h | 9 + mesalib/src/mesa/main/enable.c | 2 + mesalib/src/mesa/main/extensions.c | 2 + mesalib/src/mesa/main/get.c | 30 +- mesalib/src/mesa/main/get_hash_params.py | 18 +- mesalib/src/mesa/main/getstring.c | 49 +- mesalib/src/mesa/main/glformats.c | 5 + mesalib/src/mesa/main/mtypes.h | 76 ++- mesalib/src/mesa/main/state.c | 4 + mesalib/src/mesa/main/streaming-load-memcpy.c | 85 +++ mesalib/src/mesa/main/streaming-load-memcpy.h | 33 + mesalib/src/mesa/main/varray.c | 699 ++++++++++++++++++--- mesalib/src/mesa/main/varray.h | 77 ++- mesalib/src/mesa/state_tracker/st_atom_array.c | 11 +- mesalib/src/mesa/state_tracker/st_extensions.c | 2 + mesalib/src/mesa/vbo/vbo_attrib_tmp.h | 32 +- mesalib/src/mesa/vbo/vbo_exec_array.c | 12 +- mesalib/src/mesa/x86/.gitignore | 2 - mesalib/src/mesa/x86/Makefile.am | 49 -- 81 files changed, 3240 insertions(+), 496 deletions(-) create mode 100644 libxcb/xcb-dri3.pc.in create mode 100644 libxcb/xcb-present.pc.in create mode 100644 mesalib/docs/specs/MESA_query_renderer.spec create mode 100644 mesalib/src/glsl/link_atomics.cpp create mode 100644 mesalib/src/mapi/glapi/gen/ARB_vertex_attrib_binding.xml create mode 100644 mesalib/src/mesa/.gitignore create mode 100644 mesalib/src/mesa/main/streaming-load-memcpy.c create mode 100644 mesalib/src/mesa/main/streaming-load-memcpy.h delete mode 100644 mesalib/src/mesa/x86/.gitignore delete mode 100644 mesalib/src/mesa/x86/Makefile.am diff --git a/X11/xtrans/Xtrans.c b/X11/xtrans/Xtrans.c index 7c7967f5d..735d7b87f 100644 --- a/X11/xtrans/Xtrans.c +++ b/X11/xtrans/Xtrans.c @@ -865,6 +865,13 @@ TRANS(Write) (XtransConnInfo ciptr, char *buf, int size) return ciptr->transptr->Write (ciptr, buf, size); } +int +TRANS(Readv) (XtransConnInfo ciptr, struct iovec *buf, int size) + +{ + return ciptr->transptr->Readv (ciptr, buf, size); +} + int TRANS(Writev) (XtransConnInfo ciptr, struct iovec *buf, int size) @@ -872,6 +879,7 @@ TRANS(Writev) (XtransConnInfo ciptr, struct iovec *buf, int size) return ciptr->transptr->Writev (ciptr, buf, size); } +#if XTRANS_SEND_FDS int TRANS(SendFd) (XtransConnInfo ciptr, int fd, int do_close) { @@ -883,6 +891,7 @@ TRANS(RecvFd) (XtransConnInfo ciptr) { return ciptr->transptr->RecvFd(ciptr); } +#endif int TRANS(Disconnect) (XtransConnInfo ciptr) diff --git a/X11/xtrans/Xtrans.h b/X11/xtrans/Xtrans.h index 53b8b627d..69accd780 100644 --- a/X11/xtrans/Xtrans.h +++ b/X11/xtrans/Xtrans.h @@ -344,6 +344,12 @@ int TRANS(Write)( int /* size */ ); +int TRANS(Readv)( + XtransConnInfo, /* ciptr */ + struct iovec *, /* buf */ + int /* size */ +); + int TRANS(Writev)( XtransConnInfo, /* ciptr */ struct iovec *, /* buf */ diff --git a/X11/xtrans/Xtransint.h b/X11/xtrans/Xtransint.h index dd886db87..1f32f0cae 100644 --- a/X11/xtrans/Xtransint.h +++ b/X11/xtrans/Xtransint.h @@ -72,7 +72,9 @@ from The Open Group. # define XTRANSDEBUG 1 #endif -#define XTRANS_SEND_FDS 1 +#if XTRANS_SEND_FDS && !(defined(linux) || defined(__sun)) +#error "FD passing support only on Linux & Solaris" +#endif #ifdef WIN32 # define _WILLWINSOCK_ @@ -289,6 +291,7 @@ typedef struct _Xtransport { int /* size */ ); +#if XTRANS_SEND_FDS int (*SendFd)( XtransConnInfo, /* connection */ int, /* fd */ @@ -298,6 +301,7 @@ typedef struct _Xtransport { int (*RecvFd)( XtransConnInfo /* connection */ ); +#endif int (*Disconnect)( XtransConnInfo /* connection */ diff --git a/X11/xtrans/Xtranslcl.c b/X11/xtrans/Xtranslcl.c index 5beef7c98..4deb86c40 100644 --- a/X11/xtrans/Xtranslcl.c +++ b/X11/xtrans/Xtranslcl.c @@ -140,6 +140,21 @@ TRANS(ReopenFail)(XtransConnInfo ciptr _X_UNUSED, int fd _X_UNUSED, char *port _ #endif /* TRANS_REOPEN */ +#if XTRANS_SEND_FDS +static int +TRANS(LocalRecvFdInvalid)(XtransConnInfo ciptr) +{ + errno = EINVAL; + return -1; +} + +static int +TRANS(LocalSendFdInvalid)(XtransConnInfo ciptr, int fd, int do_close) +{ + errno = EINVAL; + return -1; +} +#endif static int @@ -2368,6 +2383,10 @@ Xtransport TRANS(LocalFuncs) = { TRANS(LocalWrite), TRANS(LocalReadv), TRANS(LocalWritev), +#if XTRANS_SEND_FDS + TRANS(LocalSendFdInvalid), + TRANS(LocalRecvFdInvalid), +#endif TRANS(LocalDisconnect), TRANS(LocalClose), TRANS(LocalCloseForCloning), @@ -2410,6 +2429,10 @@ Xtransport TRANS(PTSFuncs) = { TRANS(LocalWrite), TRANS(LocalReadv), TRANS(LocalWritev), +#if XTRANS_SEND_FDS + TRANS(LocalSendFdInvalid), + TRANS(LocalRecvFdInvalid), +#endif TRANS(LocalDisconnect), TRANS(LocalClose), TRANS(LocalCloseForCloning), @@ -2454,6 +2477,10 @@ Xtransport TRANS(NAMEDFuncs) = { TRANS(LocalWrite), TRANS(LocalReadv), TRANS(LocalWritev), +#if XTRANS_SEND_FDS + TRANS(LocalSendFdInvalid), + TRANS(LocalRecvFdInvalid), +#endif TRANS(LocalDisconnect), TRANS(LocalClose), TRANS(LocalCloseForCloning), @@ -2495,6 +2522,10 @@ Xtransport TRANS(PIPEFuncs) = { TRANS(LocalWrite), TRANS(LocalReadv), TRANS(LocalWritev), +#if XTRANS_SEND_FDS + TRANS(LocalSendFdInvalid), + TRANS(LocalRecvFdInvalid), +#endif TRANS(LocalDisconnect), TRANS(LocalClose), TRANS(LocalCloseForCloning), @@ -2539,6 +2570,10 @@ Xtransport TRANS(SCOFuncs) = { TRANS(LocalWrite), TRANS(LocalReadv), TRANS(LocalWritev), +#if XTRANS_SEND_FDS + TRANS(LocalSendFdInvalid), + TRANS(LocalRecvFdInvalid), +#endif TRANS(LocalDisconnect), TRANS(LocalClose), TRANS(LocalCloseForCloning), diff --git a/X11/xtrans/Xtranssock.c b/X11/xtrans/Xtranssock.c index 23150b259..c9d103352 100644 --- a/X11/xtrans/Xtranssock.c +++ b/X11/xtrans/Xtranssock.c @@ -2237,26 +2237,33 @@ TRANS(SocketRead) (XtransConnInfo ciptr, char *buf, int size) #else #if XTRANS_SEND_FDS { - struct msghdr msg; - struct iovec iov; - struct fd_pass pass; + struct iovec iov = { + .iov_base = buf, + .iov_len = size + }; + char cmsgbuf[CMSG_SPACE(sizeof(int) * MAX_FDS)]; + struct msghdr msg = { + .msg_name = NULL, + .msg_namelen = 0, + .msg_iov = &iov, + .msg_iovlen = 1, + .msg_control = cmsgbuf, + .msg_controllen = CMSG_LEN(MAX_FDS * sizeof(int)) + }; - 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); + if (size >= 0) { + struct cmsghdr *hdr; + + for (hdr = CMSG_FIRSTHDR(&msg); hdr; hdr = CMSG_NXTHDR(&msg, hdr)) { + if (hdr->cmsg_level == SOL_SOCKET && hdr->cmsg_type == SCM_RIGHTS) { + int nfd = (hdr->cmsg_len - CMSG_LEN(0)) / sizeof (int); + int i; + int *fd = (int *) CMSG_DATA(hdr); + + for (i = 0; i < nfd; i++) + appendFd(&ciptr->recv_fds, fd[i], 0); + } } } return size; @@ -2273,7 +2280,38 @@ TRANS(SocketReadv) (XtransConnInfo ciptr, struct iovec *buf, int size) { prmsg (2,"SocketReadv(%d,%p,%d)\n", ciptr->fd, buf, size); +#if XTRANS_SEND_FDS + { + char cmsgbuf[CMSG_SPACE(sizeof(int) * MAX_FDS)]; + struct msghdr msg = { + .msg_name = NULL, + .msg_namelen = 0, + .msg_iov = buf, + .msg_iovlen = size, + .msg_control = cmsgbuf, + .msg_controllen = CMSG_LEN(MAX_FDS * sizeof(int)) + }; + + size = recvmsg(ciptr->fd, &msg, 0); + if (size >= 0) { + struct cmsghdr *hdr; + + for (hdr = CMSG_FIRSTHDR(&msg); hdr; hdr = CMSG_NXTHDR(&msg, hdr)) { + if (hdr->cmsg_level == SOL_SOCKET && hdr->cmsg_type == SCM_RIGHTS) { + int nfd = (hdr->cmsg_len - CMSG_LEN(0)) / sizeof (int); + int i; + int *fd = (int *) CMSG_DATA(hdr); + + for (i = 0; i < nfd; i++) + appendFd(&ciptr->recv_fds, fd[i], 0); + } + } + } + return size; + } +#else return READV (ciptr, buf, size); +#endif } @@ -2286,22 +2324,32 @@ TRANS(SocketWritev) (XtransConnInfo ciptr, struct iovec *buf, int size) #if XTRANS_SEND_FDS if (ciptr->send_fds) { - struct msghdr msg; - struct fd_pass pass; - int nfd; - struct _XtransConnFd *cf; + char cmsgbuf[CMSG_SPACE(sizeof(int) * MAX_FDS)]; + int nfd = nFd(&ciptr->send_fds); + struct _XtransConnFd *cf = ciptr->send_fds; + struct msghdr msg = { + .msg_name = NULL, + .msg_namelen = 0, + .msg_iov = buf, + .msg_iovlen = size, + .msg_control = cmsgbuf, + .msg_controllen = CMSG_LEN(nfd * sizeof(int)) + }; + struct cmsghdr *hdr = CMSG_FIRSTHDR(&msg); int i; + int *fds; - nfd = nFd(&ciptr->send_fds); - cf = ciptr->send_fds; + hdr->cmsg_len = msg.msg_controllen; + hdr->cmsg_level = SOL_SOCKET; + hdr->cmsg_type = SCM_RIGHTS; + fds = (int *) CMSG_DATA(hdr); /* Set up fds */ for (i = 0; i < nfd; i++) { - pass.fd[i] = cf->fd; + fds[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); @@ -2482,8 +2530,10 @@ Xtransport TRANS(SocketTCPFuncs) = { TRANS(SocketWrite), TRANS(SocketReadv), TRANS(SocketWritev), +#if XTRANS_SEND_FDS TRANS(SocketSendFdInvalid), TRANS(SocketRecvFdInvalid), +#endif TRANS(SocketDisconnect), TRANS(SocketINETClose), TRANS(SocketINETClose), @@ -2524,8 +2574,10 @@ Xtransport TRANS(SocketINETFuncs) = { TRANS(SocketWrite), TRANS(SocketReadv), TRANS(SocketWritev), +#if XTRANS_SEND_FDS TRANS(SocketSendFdInvalid), TRANS(SocketRecvFdInvalid), +#endif TRANS(SocketDisconnect), TRANS(SocketINETClose), TRANS(SocketINETClose), @@ -2567,8 +2619,10 @@ Xtransport TRANS(SocketINET6Funcs) = { TRANS(SocketWrite), TRANS(SocketReadv), TRANS(SocketWritev), +#if XTRANS_SEND_FDS TRANS(SocketSendFdInvalid), TRANS(SocketRecvFdInvalid), +#endif TRANS(SocketDisconnect), TRANS(SocketINETClose), TRANS(SocketINETClose), @@ -2617,8 +2671,10 @@ Xtransport TRANS(SocketLocalFuncs) = { TRANS(SocketWrite), TRANS(SocketReadv), TRANS(SocketWritev), +#if XTRANS_SEND_FDS TRANS(SocketSendFd), TRANS(SocketRecvFd), +#endif TRANS(SocketDisconnect), TRANS(SocketUNIXClose), TRANS(SocketUNIXCloseForCloning), @@ -2673,8 +2729,10 @@ Xtransport TRANS(SocketUNIXFuncs) = { TRANS(SocketWrite), TRANS(SocketReadv), TRANS(SocketWritev), +#if XTRANS_SEND_FDS TRANS(SocketSendFd), TRANS(SocketRecvFd), +#endif TRANS(SocketDisconnect), TRANS(SocketUNIXClose), TRANS(SocketUNIXCloseForCloning), diff --git a/X11/xtrans/configure.ac b/X11/xtrans/configure.ac index 8c3aa3ded..998fb06cf 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.3.0], +AC_INIT([xtrans], [1.3.2], [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], [xtrans]) AC_CONFIG_SRCDIR([Makefile.am]) diff --git a/X11/xtrans/xtrans.m4 b/X11/xtrans/xtrans.m4 index 91c6f9d2f..d84442e86 100644 --- a/X11/xtrans/xtrans.m4 +++ b/X11/xtrans/xtrans.m4 @@ -57,6 +57,41 @@ AC_DEFUN([XTRANS_TCP_FLAGS],[ AC_INCLUDES_DEFAULT #include ]) + # XPG4v2/UNIX95 added msg_control - check to see if we need to define + # _XOPEN_SOURCE to get it (such as on Solaris) + AC_CHECK_MEMBER([struct msghdr.msg_control], [], [], + [ +AC_INCLUDES_DEFAULT +#include + ]) + # First try for Solaris in C99 compliant mode, which requires XPG6/UNIX03 + if test "x$ac_cv_member_struct_msghdr_msg_control" = xno; then + unset ac_cv_member_struct_msghdr_msg_control + AC_MSG_NOTICE([trying again with _XOPEN_SOURCE=600]) + AC_CHECK_MEMBER([struct msghdr.msg_control], + [AC_DEFINE([_XOPEN_SOURCE], [600], + [Defined if needed to expose struct msghdr.msg_control]) + ], [], [ +#define _XOPEN_SOURCE 600 +AC_INCLUDES_DEFAULT +#include + ]) + fi + # If that didn't work, fall back to XPG5/UNIX98 with C89 + if test "x$ac_cv_member_struct_msghdr_msg_control" = xno; then + unset ac_cv_member_struct_msghdr_msg_control + AC_MSG_NOTICE([trying again with _XOPEN_SOURCE=500]) + AC_CHECK_MEMBER([struct msghdr.msg_control], + [AC_DEFINE([_XOPEN_SOURCE], [500], + [Defined if needed to expose struct msghdr.msg_control]) + ], [], [ +#define _XOPEN_SOURCE 500 +AC_INCLUDES_DEFAULT +#include + ]) + fi + + ]) # XTRANS_TCP_FLAGS # XTRANS_CONNECTION_FLAGS() diff --git a/libxcb/Makefile.am b/libxcb/Makefile.am index 961595ba3..1cb3d9a7b 100644 --- a/libxcb/Makefile.am +++ b/libxcb/Makefile.am @@ -18,9 +18,15 @@ endif if BUILD_DRI2 pkgconfig_DATA += xcb-dri2.pc endif +if BUILD_DRI3 +pkgconfig_DATA += xcb-dri3.pc +endif if BUILD_GLX pkgconfig_DATA += xcb-glx.pc endif +if BUILD_PRESENT +pkgconfig_DATA += xcb-present.pc +endif if BUILD_RANDR pkgconfig_DATA += xcb-randr.pc endif diff --git a/libxcb/configure.ac b/libxcb/configure.ac index 6c107bcd0..87804ba26 100644 --- a/libxcb/configure.ac +++ b/libxcb/configure.ac @@ -41,7 +41,7 @@ fi AC_SUBST(HTML_CHECK_RESULT) # Checks for pkg-config packages -PKG_CHECK_MODULES(XCBPROTO, xcb-proto >= 1.7) +PKG_CHECK_MODULES(XCBPROTO, xcb-proto >= 1.9) NEEDED="pthread-stubs xau >= 0.99.2" PKG_CHECK_MODULES(NEEDED, $NEEDED) @@ -81,6 +81,55 @@ AC_HEADER_STDC AC_SEARCH_LIBS(getaddrinfo, socket) AC_SEARCH_LIBS(connect, socket) +AC_ARG_ENABLE(sendfds, AS_HELP_STRING([--disable-sendfds], [Support FD passing (default: auto)]), + [sendfds=$enableval], [sendfds=auto]) + +case x$sendfds in +xauto) + AC_SEARCH_LIBS(sendmsg, socket, [sendfds="yes"], [sendfds="no"]) + ;; +esac + +# XPG4v2/UNIX95 added msg_control - check to see if we need to define +# _XOPEN_SOURCE to get it (such as on Solaris) +AC_CHECK_MEMBER([struct msghdr.msg_control], [], [], + [ +AC_INCLUDES_DEFAULT +#include + ]) +# First try for Solaris in C99 compliant mode, which requires XPG6/UNIX03 +if test "x$ac_cv_member_struct_msghdr_msg_control" = xno; then + unset ac_cv_member_struct_msghdr_msg_control + AC_MSG_NOTICE([trying again with _XOPEN_SOURCE=600]) + AC_CHECK_MEMBER([struct msghdr.msg_control], + [AC_DEFINE([_XOPEN_SOURCE], [600], + [Defined if needed to expose struct msghdr.msg_control]) + ], [], [ +#define _XOPEN_SOURCE 600 +AC_INCLUDES_DEFAULT +#include + ]) +fi +# If that didn't work, fall back to XPG5/UNIX98 with C89 +if test "x$ac_cv_member_struct_msghdr_msg_control" = xno; then + unset ac_cv_member_struct_msghdr_msg_control + AC_MSG_NOTICE([trying again with _XOPEN_SOURCE=500]) + AC_CHECK_MEMBER([struct msghdr.msg_control], + [AC_DEFINE([_XOPEN_SOURCE], [500], + [Defined if needed to expose struct msghdr.msg_control]) + ], [sendfds="no"], [ +#define _XOPEN_SOURCE 500 +AC_INCLUDES_DEFAULT +#include + ]) +fi + +case x$sendfds in +xyes) + AC_DEFINE([HAVE_SENDMSG],1,[Define if your platform supports sendmsg]) + ;; +esac + have_win32="no" lt_enable_auto_import="" case $host_os in @@ -128,7 +177,7 @@ xcbincludedir='${includedir}/xcb' AC_SUBST(xcbincludedir) if test "x$GCC" = xyes ; then - CWARNFLAGS="-Wall -pedantic -Wpointer-arith -Wold-style-definition \ + CWARNFLAGS="-Wall -Wpointer-arith -Wold-style-definition \ -Wstrict-prototypes -Wmissing-declarations -Wnested-externs" else AC_CHECK_DECL([__SUNPRO_C], [SUNCC="yes"], [SUNCC="no"]) @@ -171,7 +220,9 @@ XCB_EXTENSION(Composite, "yes") XCB_EXTENSION(Damage, "yes") XCB_EXTENSION(DPMS, "yes") XCB_EXTENSION(DRI2, "yes") +XCB_EXTENSION(DRI3, "$sendfds") XCB_EXTENSION(GLX, "yes") +XCB_EXTENSION(Present, "yes") XCB_EXTENSION(RandR, "yes") XCB_EXTENSION(Record, "yes") XCB_EXTENSION(Render, "yes") @@ -215,7 +266,9 @@ xcb-composite.pc xcb-damage.pc xcb-dpms.pc xcb-dri2.pc +xcb-dri3.pc xcb-glx.pc +xcb-present.pc xcb-randr.pc xcb-record.pc xcb-render.pc @@ -250,6 +303,7 @@ echo " Package: ${PACKAGE_NAME} ${PACKAGE_VERSION}" echo "" echo " Configuration" echo " XDM support.........: ${have_xdmcp}" +echo " sendmsg fd passing..: ${sendfds}" echo " Build unit tests....: ${HAVE_CHECK}" echo " with html results.: ${HTML_CHECK_RESULT}" echo " XCB buffer size.....: ${xcb_queue_buffer_size}" @@ -259,6 +313,7 @@ echo " Composite...........: ${BUILD_COMPOSITE}" echo " Damage..............: ${BUILD_DAMAGE}" echo " Dpms................: ${BUILD_DPMS}" echo " Dri2................: ${BUILD_DRI2}" +echo " Dri3................: ${BUILD_DRI3}" echo " Glx.................: ${BUILD_GLX}" echo " Randr...............: ${BUILD_RANDR}" echo " Record..............: ${BUILD_RECORD}" diff --git a/libxcb/src/.gitignore b/libxcb/src/.gitignore index a402afe57..a2a901006 100644 --- a/libxcb/src/.gitignore +++ b/libxcb/src/.gitignore @@ -3,7 +3,9 @@ composite.* damage.* dpms.* dri2.* +dri3.* glx.* +present.* randr.* record.* render.* diff --git a/libxcb/src/Makefile.am b/libxcb/src/Makefile.am index 6b5a2c3c4..346ee03cc 100644 --- a/libxcb/src/Makefile.am +++ b/libxcb/src/Makefile.am @@ -56,6 +56,22 @@ libxcb_dri2_la_LIBADD = $(XCB_LIBS) nodist_libxcb_dri2_la_SOURCES = dri2.c dri2.h endif +EXTSOURCES += dri3.c +if BUILD_DRI3 +lib_LTLIBRARIES += libxcb-dri3.la +libxcb_dri3_la_LDFLAGS = -version-info 0:0:0 -no-undefined @lt_enable_auto_import@ +libxcb_dri3_la_LIBADD = $(XCB_LIBS) +nodist_libxcb_dri3_la_SOURCES = dri3.c dri3.h +endif + +EXTSOURCES += present.c +if BUILD_PRESENT +lib_LTLIBRARIES += libxcb-present.la +libxcb_present_la_LDFLAGS = -version-info 0:0:0 -no-undefined @lt_enable_auto_import@ +libxcb_present_la_LIBADD = $(XCB_LIBS) +nodist_libxcb_present_la_SOURCES = present.c present.h +endif + EXTSOURCES += glx.c if BUILD_GLX lib_LTLIBRARIES += libxcb-glx.la @@ -233,7 +249,7 @@ EXTRA_DIST = $(STATIC_MANS) BUILT_SOURCES = $(EXTSOURCES) $(BUILT_MANS) CLEANFILES = $(EXTSOURCES) $(EXTHEADERS) $(BUILT_MANS) -$(EXTSOURCES): c_client.py +$(EXTSOURCES): c_client.py $(XCBPROTO_XCBINCLUDEDIR)/$(@:.c=.xml) $(PYTHON) $(srcdir)/c_client.py -p $(XCBPROTO_XCBPYTHONDIR) $(XCBPROTO_XCBINCLUDEDIR)/$(@:.c=.xml) $(man_MANS): $(EXTSOURCES) diff --git a/libxcb/src/c_client.py b/libxcb/src/c_client.py index a6f8edd73..72800045e 100644 --- a/libxcb/src/c_client.py +++ b/libxcb/src/c_client.py @@ -303,6 +303,7 @@ def _c_type_setup(self, name, postfix): self.c_reply_name = _n(name + ('reply',)) self.c_reply_type = _t(name + ('reply',)) self.c_cookie_type = _t(name + ('cookie',)) + self.c_reply_fds_name = _n(name + ('reply_fds',)) self.need_aux = False self.need_serialize = False @@ -1835,7 +1836,7 @@ def c_union(self, name): _c_complex(self) _c_iterator(self, name) -def _c_request_helper(self, name, cookie_type, void, regular, aux=False): +def _c_request_helper(self, name, cookie_type, void, regular, aux=False, reply_fds=False): ''' Declares a request function. ''' @@ -1864,6 +1865,12 @@ def _c_request_helper(self, name, cookie_type, void, regular, aux=False): # What flag is passed to xcb_request func_flags = '0' if (void and regular) or (not void and not regular) else 'XCB_REQUEST_CHECKED' + if reply_fds: + if func_flags == '0': + func_flags = 'XCB_REQUEST_REPLY_FDS' + else: + func_flags = func_flags + '|XCB_REQUEST_REPLY_FDS' + # Global extension id variable or NULL for xproto func_ext_global = '&' + _ns.c_ext_global_name if _ns.is_ext else '0' @@ -2149,6 +2156,10 @@ def _c_request_helper(self, name, cookie_type, void, regular, aux=False): # no padding necessary - _serialize() keeps track of padding automatically _c(' ') + for field in param_fields: + if field.isfd: + _c(' xcb_send_fd(c, %s);', field.c_field_name) + _c(' xcb_ret.sequence = xcb_send_request(c, %s, xcb_parts + 2, &xcb_req);', func_flags) # free dyn. all. data, if any @@ -2252,6 +2263,51 @@ def _c_reply(self, name): _c('}') +def _c_reply_has_fds(self): + for field in self.fields: + if field.isfd: + return True + return False + +def _c_reply_fds(self, name): + ''' + Declares the function that returns fds related to the reply. + ''' + spacing1 = ' ' * (len(self.c_reply_type) - len('xcb_connection_t')) + spacing3 = ' ' * (len(self.c_reply_fds_name) + 2) + _h('') + _h('/**') + _h(' * Return the reply fds') + _h(' * @param c The connection') + _h(' * @param reply The reply') + _h(' *') + _h(' * Returns the array of reply fds of the request asked by') + _h(' * ') + _h(' * The returned value must be freed by the caller using free().') + _h(' */') + _c('') + _hc('') + _hc('/*****************************************************************************') + _hc(' **') + _hc(' ** int * %s', self.c_reply_fds_name) + _hc(' ** ') + _hc(' ** @param xcb_connection_t%s *c', spacing1) + _hc(' ** @param %s *reply', self.c_reply_type) + _hc(' ** @returns int *') + _hc(' **') + _hc(' *****************************************************************************/') + _hc(' ') + _hc('int *') + _hc('%s (xcb_connection_t%s *c /**< */,', self.c_reply_fds_name, spacing1) + _h('%s%s *reply /**< */);', spacing3, self.c_reply_type) + _c('%s%s *reply /**< */)', spacing3, self.c_reply_type) + _c('{') + + _c(' return xcb_get_reply_fds(c, reply, sizeof(%s) + 4 * reply->length);', self.c_reply_type) + + _c('}') + + def _c_opcode(name, opcode): ''' Declares the opcode define for requests, events, and errors. @@ -2812,14 +2868,17 @@ def c_request(self, name): # Reply structure definition _c_complex(self.reply) # Request prototypes - _c_request_helper(self, name, self.c_cookie_type, False, True) - _c_request_helper(self, name, self.c_cookie_type, False, False) + has_fds = _c_reply_has_fds(self.reply) + _c_request_helper(self, name, self.c_cookie_type, False, True, False, has_fds) + _c_request_helper(self, name, self.c_cookie_type, False, False, False, has_fds) if self.need_aux: - _c_request_helper(self, name, self.c_cookie_type, False, True, True) - _c_request_helper(self, name, self.c_cookie_type, False, False, True) + _c_request_helper(self, name, self.c_cookie_type, False, True, True, has_fds) + _c_request_helper(self, name, self.c_cookie_type, False, False, True, has_fds) # Reply accessors _c_accessors(self.reply, name + ('reply',), name) _c_reply(self, name) + if has_fds: + _c_reply_fds(self, name) else: # Request prototypes _c_request_helper(self, name, 'xcb_void_cookie_t', True, False) diff --git a/libxcb/src/xcb.h b/libxcb/src/xcb.h index 071413077..63864dc37 100644 --- a/libxcb/src/xcb.h +++ b/libxcb/src/xcb.h @@ -87,6 +87,9 @@ extern "C" { /** Connection closed because the server does not have a screen matching the display. */ #define XCB_CONN_CLOSED_INVALID_SCREEN 6 +/** Connection closed because some FD passing operation failed */ +#define XCB_CONN_CLOSED_FDPASSING_FAILED 7 + #define XCB_TYPE_PAD(T,I) (-(I) & (sizeof(T) > 4 ? 3 : sizeof(T) - 1)) /* Opaque structures */ @@ -137,23 +140,6 @@ typedef struct { uint32_t full_sequence; /**< full sequence */ } xcb_generic_event_t; -/** - * @brief GE event - * - * An event as sent by the XGE extension. The length field specifies the - * number of 4-byte blocks trailing the struct. - */ -typedef struct { - uint8_t response_type; /**< Type of the response */ - uint8_t pad0; /**< Padding */ - uint16_t sequence; /**< Sequence number */ - uint32_t length; - uint16_t event_type; - uint16_t pad1; - uint32_t pad[5]; /**< Padding */ - uint32_t full_sequence; /**< full sequence */ -} xcb_ge_event_t; - /** * @brief Generic error. * @@ -304,6 +290,39 @@ xcb_generic_event_t *xcb_poll_for_event(xcb_connection_t *c); */ xcb_generic_event_t *xcb_poll_for_queued_event(xcb_connection_t *c); +typedef struct xcb_special_event xcb_special_event_t; + +/** + * @brief Returns the next event from a special queue + */ +xcb_generic_event_t *xcb_poll_for_special_event(xcb_connection_t *c, + xcb_special_event_t *se); + +/** + * @brief Returns the next event from a special queue, blocking until one arrives + */ +xcb_generic_event_t *xcb_wait_for_special_event(xcb_connection_t *c, + xcb_special_event_t *se); +/** + * @typedef typedef struct xcb_extension_t xcb_extension_t + */ +typedef struct xcb_extension_t xcb_extension_t; /**< Opaque structure used as key for xcb_get_extension_data_t. */ + + +/** + * @brief Listen for a special event + */ +xcb_special_event_t *xcb_register_for_special_xge(xcb_connection_t *c, + xcb_extension_t *ext, + uint32_t eid, + uint32_t *stamp); + +/** + * @brief Stop listening for a special event + */ +void xcb_unregister_for_special_event(xcb_connection_t *c, + xcb_special_event_t *se); + /** * @brief Return the error for a request, or NULL if none can ever arrive. * @param c: The connection to the X server. @@ -341,11 +360,6 @@ void xcb_discard_reply(xcb_connection_t *c, unsigned int sequence); /* xcb_ext.c */ -/** - * @typedef typedef struct xcb_extension_t xcb_extension_t - */ -typedef struct xcb_extension_t xcb_extension_t; /**< Opaque structure used as key for xcb_get_extension_data_t. */ - /** * @brief Caches reply information from QueryExtension requests. * @param c: The connection. diff --git a/libxcb/src/xcb_conn.c b/libxcb/src/xcb_conn.c index 7dd25d373..50e7fb604 100644 --- a/libxcb/src/xcb_conn.c +++ b/libxcb/src/xcb_conn.c @@ -214,9 +214,39 @@ static int write_vec(xcb_connection_t *c, struct iovec **vector, int *count) if (n > IOV_MAX) n = IOV_MAX; - n = writev(c->fd, *vector, n); - if(n < 0 && errno == EAGAIN) - return 1; +#if HAVE_SENDMSG + if (c->out.out_fd.nfd) { + char cmsgbuf[CMSG_SPACE(sizeof(int) * XCB_MAX_PASS_FD)]; + struct msghdr msg = { + .msg_name = NULL, + .msg_namelen = 0, + .msg_iov = *vector, + .msg_iovlen = n, + .msg_control = cmsgbuf, + .msg_controllen = CMSG_LEN(c->out.out_fd.nfd * sizeof (int)), + }; + int i; + struct cmsghdr *hdr = CMSG_FIRSTHDR(&msg); + + hdr->cmsg_len = msg.msg_controllen; + hdr->cmsg_level = SOL_SOCKET; + hdr->cmsg_type = SCM_RIGHTS; + memcpy(CMSG_DATA(hdr), c->out.out_fd.fd, c->out.out_fd.nfd * sizeof (int)); + + n = sendmsg(c->fd, &msg, 0); + if(n < 0 && errno == EAGAIN) + return 1; + for (i = 0; i < c->out.out_fd.nfd; i++) + close(c->out.out_fd.fd[i]); + c->out.out_fd.nfd = 0; + } else +#endif + { + n = writev(c->fd, *vector, n); + if(n < 0 && errno == EAGAIN) + return 1; + } + #endif /* _WIN32 */ if(n <= 0) diff --git a/libxcb/src/xcb_in.c b/libxcb/src/xcb_in.c index 8a7af920b..8c3a58cc3 100644 --- a/libxcb/src/xcb_in.c +++ b/libxcb/src/xcb_in.c @@ -60,6 +60,23 @@ struct event_list { struct event_list *next; }; +struct xcb_special_event { + + struct xcb_special_event *next; + + /* Match XGE events for the specific extension and event ID (the + * first 32 bit word after evtype) + */ + uint8_t extension; + uint32_t eid; + uint32_t *stamp; + + struct event_list *events; + struct event_list **events_tail; + + pthread_cond_t special_event_cond; +}; + struct reply_list { void *reply; struct reply_list *next; @@ -90,11 +107,66 @@ static void remove_finished_readers(reader_list **prev_reader, uint64_t complete } } +#if HAVE_SENDMSG +static int read_fds(xcb_connection_t *c, int *fds, int nfd) +{ + int *ifds = &c->in.in_fd.fd[c->in.in_fd.ifd]; + int infd = c->in.in_fd.nfd - c->in.in_fd.ifd; + + if (nfd > infd) + return 0; + memcpy(fds, ifds, nfd * sizeof (int)); + c->in.in_fd.ifd += nfd; + return 1; +} +#endif + +typedef struct xcb_ge_special_event_t { + uint8_t response_type; /**< */ + uint8_t extension; /**< */ + uint16_t sequence; /**< */ + uint32_t length; /**< */ + uint16_t evtype; /**< */ + uint8_t pad0[2]; /**< */ + uint32_t eid; /**< */ + uint8_t pad1[16]; /**< */ +} xcb_ge_special_event_t; + +static int event_special(xcb_connection_t *c, + struct event_list *event) +{ + struct xcb_special_event *special_event; + struct xcb_ge_special_event_t *ges = (void *) event->event; + + /* Special events are always XGE events */ + if ((ges->response_type & 0x7f) != XCB_XGE_EVENT) + return 0; + + for (special_event = c->in.special_events; + special_event; + special_event = special_event->next) + { + if (ges->extension == special_event->extension && + ges->eid == special_event->eid) + { + *special_event->events_tail = event; + special_event->events_tail = &event->next; + if (special_event->stamp) + ++(*special_event->stamp); + pthread_cond_signal(&special_event->special_event_cond); + return 1; + } + } + + return 0; +} + static int read_packet(xcb_connection_t *c) { xcb_generic_reply_t genrep; uint64_t length = 32; uint64_t eventlength = 0; /* length after first 32 bytes for GenericEvents */ + int nfd = 0; /* Number of file descriptors attached to the reply */ uint64_t bufsize; void *buf; pending_reply *pend = 0; @@ -164,13 +236,18 @@ static int read_packet(xcb_connection_t *c) genrep.length = p[2] * p[3] * 2; } length += genrep.length * 4; + + /* XXX a bit of a hack -- we "know" that all FD replys place + * the number of fds in the pad0 byte */ + if (pend && pend->flags & XCB_REQUEST_REPLY_FDS) + nfd = genrep.pad0; } /* XGE events may have sizes > 32 */ if ((genrep.response_type & 0x7f) == XCB_XGE_EVENT) eventlength = genrep.length * 4; - bufsize = length + eventlength + + bufsize = length + eventlength + nfd * sizeof(int) + (genrep.response_type == XCB_REPLY ? 0 : sizeof(uint32_t)); if (bufsize < INT32_MAX) buf = malloc((size_t) bufsize); @@ -198,6 +275,17 @@ static int read_packet(xcb_connection_t *c) } } +#if HAVE_SENDMSG + if (nfd) + { + if (!read_fds(c, (int *) &((char *) buf)[length], nfd)) + { + free(buf); + return 0; + } + } +#endif + if(pend && (pend->flags & XCB_REQUEST_DISCARD_REPLY)) { free(buf); @@ -237,9 +325,12 @@ static int read_packet(xcb_connection_t *c) } event->event = buf; event->next = 0; - *c->in.events_tail = event; - c->in.events_tail = &event->next; - pthread_cond_signal(&c->in.event_cond); + + if (!event_special(c, event)) { + *c->in.events_tail = event; + c->in.events_tail = &event->next; + pthread_cond_signal(&c->in.event_cond); + } return 1; /* I have something for you... */ } @@ -431,6 +522,11 @@ void *xcb_wait_for_reply(xcb_connection_t *c, unsigned int request, xcb_generic_ return ret; } +int *xcb_get_reply_fds(xcb_connection_t *c, void *reply, size_t reply_size) +{ + return (int *) (&((char *) reply)[reply_size]); +} + static void insert_pending_discard(xcb_connection_t *c, pending_reply **prev_next, uint64_t seq) { pending_reply *pend; @@ -577,6 +673,126 @@ xcb_generic_error_t *xcb_request_check(xcb_connection_t *c, xcb_void_cookie_t co return ret; } +static xcb_generic_event_t *get_special_event(xcb_connection_t *c, + xcb_special_event_t *se) +{ + xcb_generic_event_t *event = NULL; + struct event_list *events; + + if ((events = se->events) != NULL) { + event = events->event; + if (!(se->events = events->next)) + se->events_tail = &se->events; + free (events); + } + return event; +} + +xcb_generic_event_t *xcb_poll_for_special_event(xcb_connection_t *c, + xcb_special_event_t *se) +{ + xcb_generic_event_t *event; + + if(c->has_error) + return 0; + pthread_mutex_lock(&c->iolock); + event = get_special_event(c, se); + pthread_mutex_unlock(&c->iolock); + return event; +} + +xcb_generic_event_t *xcb_wait_for_special_event(xcb_connection_t *c, + xcb_special_event_t *se) +{ + xcb_generic_event_t *event; + + if(c->has_error) + return 0; + pthread_mutex_lock(&c->iolock); + + /* get_special_event returns 0 on empty list. */ + while(!(event = get_special_event(c, se))) + if(!_xcb_conn_wait(c, &se->special_event_cond, 0, 0)) + break; + + pthread_mutex_unlock(&c->iolock); + return event; +} + +xcb_special_event_t * +xcb_register_for_special_xge(xcb_connection_t *c, + xcb_extension_t *ext, + uint32_t eid, + uint32_t *stamp) +{ + xcb_special_event_t *se; + const xcb_query_extension_reply_t *ext_reply; + + if(c->has_error) + return NULL; + ext_reply = xcb_get_extension_data(c, ext); + if (!ext_reply) + return NULL; + pthread_mutex_lock(&c->iolock); + for (se = c->in.special_events; se; se = se->next) { + if (se->extension == ext_reply->major_opcode && + se->eid == eid) { + pthread_mutex_unlock(&c->iolock); + return NULL; + } + } + se = calloc(1, sizeof(xcb_special_event_t)); + if (!se) { + pthread_mutex_unlock(&c->iolock); + return NULL; + } + + se->extension = ext_reply->major_opcode; + se->eid = eid; + + se->events = NULL; + se->events_tail = &se->events; + se->stamp = stamp; + + pthread_cond_init(&se->special_event_cond, 0); + + se->next = c->in.special_events; + c->in.special_events = se; + pthread_mutex_unlock(&c->iolock); + return se; +} + +void +xcb_unregister_for_special_event(xcb_connection_t *c, + xcb_special_event_t *se) +{ + xcb_special_event_t *s, **prev; + struct event_list *events, *next; + + if (!se) + return; + + if (c->has_error) + return; + + pthread_mutex_lock(&c->iolock); + + for (prev = &c->in.special_events; (s = *prev) != NULL; prev = &(s->next)) { + if (s == se) { + *prev = se->next; + for (events = se->events; events; events = next) { + next = events->next; + free (events->event); + free (events); + } + pthread_cond_destroy(&se->special_event_cond); + free (se); + break; + } + } + pthread_mutex_unlock(&c->iolock); +} + /* Private interface */ int _xcb_in_init(_xcb_in *in) @@ -665,11 +881,73 @@ void _xcb_in_replies_done(xcb_connection_t *c) int _xcb_in_read(xcb_connection_t *c) { - int n = recv(c->fd, c->in.queue + c->in.queue_len, sizeof(c->in.queue) - c->in.queue_len, 0); - if(n > 0) + int n; + +#if HAVE_SENDMSG + struct iovec iov = { + .iov_base = c->in.queue + c->in.queue_len, + .iov_len = sizeof(c->in.queue) - c->in.queue_len, + }; + char cmsgbuf[CMSG_SPACE(sizeof(int) * XCB_MAX_PASS_FD)]; + struct msghdr msg = { + .msg_name = NULL, + .msg_namelen = 0, + .msg_iov = &iov, + .msg_iovlen = 1, + .msg_control = cmsgbuf, + .msg_controllen = CMSG_SPACE(sizeof(int) * (XCB_MAX_PASS_FD - c->in.in_fd.nfd)), + }; + n = recvmsg(c->fd, &msg, 0); + + /* Check for truncation errors. Only MSG_CTRUNC is + * probably possible here, which would indicate that + * the sender tried to transmit more than XCB_MAX_PASS_FD + * file descriptors. + */ + if (msg.msg_flags & (MSG_TRUNC|MSG_CTRUNC)) { + _xcb_conn_shutdown(c, XCB_CONN_CLOSED_FDPASSING_FAILED); + return 0; + } +#else + n = recv(c->fd, c->in.queue + c->in.queue_len, sizeof(c->in.queue) - c->in.queue_len, 0); +#endif + if(n > 0) { +#if HAVE_SENDMSG + struct cmsghdr *hdr; + + for (hdr = CMSG_FIRSTHDR(&msg); hdr; hdr = CMSG_NXTHDR(&msg, hdr)) { + if (hdr->cmsg_level == SOL_SOCKET && hdr->cmsg_type == SCM_RIGHTS) { + int nfd = (hdr->cmsg_len - CMSG_LEN(0)) / sizeof (int); + memcpy(&c->in.in_fd.fd[c->in.in_fd.nfd], CMSG_DATA(hdr), nfd * sizeof (int)); + c->in.in_fd.nfd += nfd; + } + } +#endif c->in.queue_len += n; + } while(read_packet(c)) /* empty */; +#if HAVE_SENDMSG + if (c->in.in_fd.nfd) { + c->in.in_fd.nfd -= c->in.in_fd.ifd; + memmove(&c->in.in_fd.fd[0], + &c->in.in_fd.fd[c->in.in_fd.ifd], + c->in.in_fd.nfd * sizeof (int)); + c->in.in_fd.ifd = 0; + + /* If we have any left-over file descriptors after emptying + * the input buffer, then the server sent some that we weren't + * expecting. Close them and mark the connection as broken; + */ + if (c->in.queue_len == 0 && c->in.in_fd.nfd != 0) { + int i; + for (i = 0; i < c->in.in_fd.nfd; i++) + close(c->in.in_fd.fd[i]); + _xcb_conn_shutdown(c, XCB_CONN_CLOSED_FDPASSING_FAILED); + return 0; + } + } +#endif #ifndef _WIN32 if((n > 0) || (n < 0 && errno == EAGAIN)) #else diff --git a/libxcb/src/xcb_out.c b/libxcb/src/xcb_out.c index 429fa99d3..1a3aca515 100644 --- a/libxcb/src/xcb_out.c +++ b/libxcb/src/xcb_out.c @@ -263,6 +263,24 @@ unsigned int xcb_send_request(xcb_connection_t *c, int flags, struct iovec *vect return request; } +void +xcb_send_fd(xcb_connection_t *c, int fd) +{ +#if HAVE_SENDMSG + if (c->has_error) + return; + pthread_mutex_lock(&c->iolock); + while (c->out.out_fd.nfd == XCB_MAX_PASS_FD) { + _xcb_out_flush_to(c, c->out.request); + if (c->has_error) + break; + } + if (!c->has_error) + c->out.out_fd.fd[c->out.out_fd.nfd++] = fd; + pthread_mutex_unlock(&c->iolock); +#endif +} + int xcb_take_socket(xcb_connection_t *c, void (*return_socket)(void *closure), void *closure, int flags, uint64_t *sent) { int ret; diff --git a/libxcb/src/xcbext.h b/libxcb/src/xcbext.h index 4e1f2f73d..1eb1be77f 100644 --- a/libxcb/src/xcbext.h +++ b/libxcb/src/xcbext.h @@ -54,11 +54,14 @@ typedef struct { enum xcb_send_request_flags_t { XCB_REQUEST_CHECKED = 1 << 0, XCB_REQUEST_RAW = 1 << 1, - XCB_REQUEST_DISCARD_REPLY = 1 << 2 + XCB_REQUEST_DISCARD_REPLY = 1 << 2, + XCB_REQUEST_REPLY_FDS = 1 << 3 }; unsigned int xcb_send_request(xcb_connection_t *c, int flags, struct iovec *vector, const xcb_protocol_request_t *request); +void xcb_send_fd(xcb_connection_t *c, int fd); + /* xcb_take_socket allows external code to ask XCB for permission to * take over the write side of the socket and send raw data with * xcb_writev. xcb_take_socket provides the sequence number of the last @@ -89,6 +92,7 @@ int xcb_writev(xcb_connection_t *c, struct iovec *vector, int count, uint64_t re void *xcb_wait_for_reply(xcb_connection_t *c, unsigned int request, xcb_generic_error_t **e); int xcb_poll_for_reply(xcb_connection_t *c, unsigned int request, void **reply, xcb_generic_error_t **error); +int *xcb_get_reply_fds(xcb_connection_t *c, void *reply, size_t replylen); /* xcb_util.c */ diff --git a/libxcb/src/xcbint.h b/libxcb/src/xcbint.h index 7f9ab2838..5c904fbb7 100644 --- a/libxcb/src/xcbint.h +++ b/libxcb/src/xcbint.h @@ -81,6 +81,16 @@ void *_xcb_map_remove(_xcb_map *q, unsigned int key); typedef void (*xcb_return_socket_func_t)(void *closure); +#if HAVE_SENDMSG +#define XCB_MAX_PASS_FD 16 + +typedef struct _xcb_fd { + int fd[XCB_MAX_PASS_FD]; + int nfd; + int ifd; +} _xcb_fd; +#endif + typedef struct _xcb_out { pthread_cond_t cond; int writing; @@ -101,6 +111,9 @@ typedef struct _xcb_out { xcb_big_requests_enable_cookie_t cookie; uint32_t value; } maximum_request_length; +#if HAVE_SENDMSG + _xcb_fd out_fd; +#endif } _xcb_out; int _xcb_out_init(_xcb_out *out); @@ -133,6 +146,10 @@ typedef struct _xcb_in { struct pending_reply *pending_replies; struct pending_reply **pending_replies_tail; +#if HAVE_SENDMSG + _xcb_fd in_fd; +#endif + struct xcb_special_event *special_events; } _xcb_in; int _xcb_in_init(_xcb_in *in); diff --git a/libxcb/xcb-dri3.pc.in b/libxcb/xcb-dri3.pc.in new file mode 100644 index 000000000..0eb73908a --- /dev/null +++ b/libxcb/xcb-dri3.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: XCB DRI3 +Description: XCB DRI3 Extension +Version: @PACKAGE_VERSION@ +Requires: xcb +Libs: -L${libdir} -lxcb-dri3 +Cflags: -I${includedir} diff --git a/libxcb/xcb-present.pc.in b/libxcb/xcb-present.pc.in new file mode 100644 index 000000000..848ac02ef --- /dev/null +++ b/libxcb/xcb-present.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: XCB Present +Description: XCB Present Extension +Version: @PACKAGE_VERSION@ +Requires: xcb +Libs: -L${libdir} -lxcb-present +Cflags: -I${includedir} diff --git a/libxcb/xcb-proto/configure.ac b/libxcb/xcb-proto/configure.ac index ba6a90cd8..c82c8c749 100644 --- a/libxcb/xcb-proto/configure.ac +++ b/libxcb/xcb-proto/configure.ac @@ -3,7 +3,7 @@ AC_PREREQ(2.57) AC_INIT([XCB Proto], - 1.8, + 1.9, [xcb@lists.freedesktop.org]) AC_CONFIG_SRCDIR([xcb-proto.pc.in]) AM_INIT_AUTOMAKE([foreign dist-bzip2]) diff --git a/libxcb/xcb-proto/src/present.xml b/libxcb/xcb-proto/src/present.xml index d12ae4879..57e7cd364 100644 --- a/libxcb/xcb-proto/src/present.xml +++ b/libxcb/xcb-proto/src/present.xml @@ -133,7 +133,7 @@ OF THIS SOFTWARE. - + diff --git a/libxcb/xcb-proto/src/xcb.xsd b/libxcb/xcb-proto/src/xcb.xsd index 7a9c80018..73dbf8a77 100644 --- a/libxcb/xcb-proto/src/xcb.xsd +++ b/libxcb/xcb-proto/src/xcb.xsd @@ -89,6 +89,9 @@ authorization from the authors. + + + @@ -185,6 +188,7 @@ authorization from the authors. + diff --git a/libxcb/xcb-proto/xcbgen/xtypes.py b/libxcb/xcb-proto/xcbgen/xtypes.py index 6150d1818..951731afc 100644 --- a/libxcb/xcb-proto/xcbgen/xtypes.py +++ b/libxcb/xcb-proto/xcbgen/xtypes.py @@ -164,44 +164,6 @@ class Enum(SimpleType): out = __main__.output['enum'] -class FileDescriptor(SimpleType): - ''' - Derived class which represents a file descriptor. Passed via magic kernel stuff - - Public fields added: - values contains a list of (name, value) tuples. value is empty, or a number. - bits contains a list of (name, bitnum) tuples. items only appear if specified as a bit. bitnum is a number. - ''' - def __init__(self, name, elt): - SimpleType.__init__(self, name, 4) - self.values = [] - self.bits = [] - self.doc = None - for item in list(elt): - if item.tag == 'doc': - self.doc = Doc(name, item) - - # First check if we're using a default value - if len(list(item)) == 0: - self.values.append((item.get('name'), '')) - continue - - # An explicit value or bit was specified. - value = list(item)[0] - if value.tag == 'value': - self.values.append((item.get('name'), value.text)) - elif value.tag == 'bit': - self.values.append((item.get('name'), '%u' % (1 << int(value.text, 0)))) - self.bits.append((item.get('name'), value.text)) - - def resolve(self, module): - self.resolved = True - - def fixed_size(self): - return True - - out = __main__.output['enum'] - class ListType(Type): ''' Derived class which represents a list of some other datatype. Fixed- or variable-sized. diff --git a/mesalib/configure.ac b/mesalib/configure.ac index a8366ee2f..8fb5e0d8b 100644 --- a/mesalib/configure.ac +++ b/mesalib/configure.ac @@ -34,9 +34,10 @@ LIBDRM_NVVIEUX_REQUIRED=2.4.33 LIBDRM_NOUVEAU_REQUIRED="2.4.33 libdrm >= 2.4.41" LIBDRM_FREEDRENO_REQUIRED=2.4.39 DRI2PROTO_REQUIRED=2.6 +DRI3PROTO_REQUIRED=1.0 +PRESENTPROTO_REQUIRED=1.0 +LIBUDEV_REQUIRED=151 GLPROTO_REQUIRED=1.4.14 -LIBDRM_XORG_REQUIRED=2.4.24 -LIBKMS_XORG_REQUIRED=1.0.0 dnl Check for progs AC_PROG_CPP @@ -556,11 +557,6 @@ AC_ARG_ENABLE([egl], [enable_egl="$enableval"], [enable_egl=yes]) -AC_ARG_ENABLE([xorg], - [AS_HELP_STRING([--enable-xorg], - [enable support for X.Org DDX API @<:@default=no@:>@])], - [enable_xorg="$enableval"], - [enable_xorg=no]) AC_ARG_ENABLE([xa], [AS_HELP_STRING([--enable-xa], [enable build of the XA X Acceleration API @<:@default=no@:>@])], @@ -651,7 +647,6 @@ if test "x$enable_opengl" = xno -a \ "x$enable_gles1" = xno -a \ "x$enable_gles2" = xno -a \ "x$enable_openvg" = xno -a \ - "x$enable_xorg" = xno -a \ "x$enable_xa" = xno -a \ "x$enable_xvmc" = xno -a \ "x$enable_vdpau" = xno -a \ @@ -816,10 +811,13 @@ xyesno) fi PKG_CHECK_MODULES([DRI2PROTO], [dri2proto >= $DRI2PROTO_REQUIRED]) GL_PC_REQ_PRIV="$GL_PC_REQ_PRIV libdrm >= $LIBDRM_REQUIRED" + PKG_CHECK_MODULES([DRI3PROTO], [dri3proto >= $DRI3PROTO_REQUIRED]) + PKG_CHECK_MODULES([PRESENTPROTO], [presentproto >= $PRESENTPROTO_REQUIRED]) + PKG_CHECK_MODULES([LIBUDEV], [libudev >= $LIBUDEV_REQUIRED]) fi # find the DRI deps for libGL - dri_modules="x11 xext xdamage xfixes x11-xcb xcb-glx >= 1.8.1 xcb-dri2 >= 1.8" + dri_modules="x11 xext xdamage xfixes x11-xcb xcb-glx >= 1.8.1 xcb-dri2 >= 1.8 xcb-dri3 xcb-present xcb-sync xshmfence" # add xf86vidmode if available PKG_CHECK_MODULES([XF86VIDMODE], [xxf86vm], HAVE_XF86VIDMODE=yes, HAVE_XF86VIDMODE=no) @@ -829,8 +827,8 @@ xyesno) PKG_CHECK_MODULES([DRIGL], [$dri_modules]) GL_PC_REQ_PRIV="$GL_PC_REQ_PRIV $dri_modules" - X11_INCLUDES="$X11_INCLUDES $DRIGL_CFLAGS" - GL_LIB_DEPS="$DRIGL_LIBS" + X11_INCLUDES="$X11_INCLUDES $DRIGL_CFLAGS $LIBUDEV_CFLAGS" + GL_LIB_DEPS="$DRIGL_LIBS $LIBUDEV_LIBS" # need DRM libs, $PTHREAD_LIBS, etc. GL_LIB_DEPS="$GL_LIB_DEPS $LIBDRM_LIBS -lm $PTHREAD_LIBS $DLOPEN_LIBS" @@ -1235,20 +1233,6 @@ if test "x$enable_gallium_gbm" = xyes; then fi AM_CONDITIONAL(HAVE_GALLIUM_GBM, test "x$enable_gallium_gbm" = xyes) -dnl -dnl X.Org DDX configuration -dnl -if test "x$enable_xorg" = xyes; then - PKG_CHECK_MODULES([XORG], [xorg-server >= 1.6.0]) - PKG_CHECK_MODULES([LIBDRM_XORG], [libdrm >= $LIBDRM_XORG_REQUIRED]) - PKG_CHECK_MODULES([LIBKMS_XORG], [libkms >= $LIBKMS_XORG_REQUIRED]) - PKG_CHECK_MODULES(XEXT, [xextproto >= 7.0.99.1], - HAVE_XEXTPROTO_71="yes"; DEFINES="$DEFINES -DHAVE_XEXTPROTO_71", - HAVE_XEXTPROTO_71="no") - GALLIUM_STATE_TRACKERS_DIRS="xorg $GALLIUM_STATE_TRACKERS_DIRS" -fi -AM_CONDITIONAL(HAVE_ST_XORG, test "x$enable_xorg" = xyes) - dnl dnl XA configuration dnl @@ -1487,13 +1471,6 @@ AC_ARG_WITH([egl-driver-dir], [EGL_DRIVER_INSTALL_DIR='${libdir}/egl']) AC_SUBST([EGL_DRIVER_INSTALL_DIR]) -AC_ARG_WITH([xorg-driver-dir], - [AS_HELP_STRING([--with-xorg-driver-dir=DIR], - [Default xorg driver directory[[default=${libdir}/xorg/modules/drivers]]])], - [XORG_DRIVER_INSTALL_DIR="$withval"], - [XORG_DRIVER_INSTALL_DIR="${libdir}/xorg/modules/drivers"]) -AC_SUBST([XORG_DRIVER_INSTALL_DIR]) - AC_ARG_WITH([max-width], [AS_HELP_STRING([--with-max-width=N], [Maximum framebuffer width (4096)])], @@ -1675,18 +1652,15 @@ gallium_check_st() { if test "x$enable_dri" = xyes && test "x$2" != x; then GALLIUM_TARGET_DIRS="$GALLIUM_TARGET_DIRS $2" fi - if test "x$enable_xorg" = xyes && test "x$3" != x; then + if test "x$enable_xa" = xyes && test "x$3" != x; then GALLIUM_TARGET_DIRS="$GALLIUM_TARGET_DIRS $3" fi - if test "x$enable_xa" = xyes && test "x$4" != x; then + if test "x$enable_xvmc" = xyes && test "x$4" != x; then GALLIUM_TARGET_DIRS="$GALLIUM_TARGET_DIRS $4" fi - if test "x$enable_xvmc" = xyes && test "x$5" != x; then + if test "x$enable_vdpau" = xyes && test "x$5" != x; then GALLIUM_TARGET_DIRS="$GALLIUM_TARGET_DIRS $5" fi - if test "x$enable_vdpau" = xyes && test "x$6" != x; then - GALLIUM_TARGET_DIRS="$GALLIUM_TARGET_DIRS $6" - fi } gallium_require_llvm() { @@ -1726,9 +1700,8 @@ radeon_llvm_check() { } dnl Gallium drivers -if test "x$enable_dri" = xyes -o "x$enable_xorg" = xyes -o \ - "x$enable_xa" = xyes -o "x$enable_xvmc" = xyes -o \ - "x$enable_vdpau" = xyes; then +if test "x$enable_dri" = xyes -o "x$enable_xa" = xyes -o \ + "x$enable_xvmc" = xyes -o "x$enable_vdpau" = xyes; then NEED_NONNULL_WINSYS=yes fi AM_CONDITIONAL(NEED_NONNULL_WINSYS, test "x$NEED_NONNULL_WINSYS" = xyes) @@ -1741,7 +1714,7 @@ if test "x$with_gallium_drivers" != x; then xsvga) HAVE_GALLIUM_SVGA=yes GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS svga softpipe" - gallium_check_st "svga/drm" "dri-vmwgfx" "" "xa-vmwgfx" + gallium_check_st "svga/drm" "dri-vmwgfx" "xa-vmwgfx" ;; xi915) HAVE_GALLIUM_I915=yes @@ -1751,7 +1724,7 @@ if test "x$with_gallium_drivers" != x; then GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS llvmpipe" fi GALLIUM_WINSYS_DIRS="$GALLIUM_WINSYS_DIRS i915/sw" - gallium_check_st "i915/drm" "dri-i915" "xorg-i915" + gallium_check_st "i915/drm" "dri-i915" DRICOMMON_NEED_LIBDRM=yes ;; xilo) @@ -1767,7 +1740,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" "" "" "" "" + gallium_check_st "radeon/drm" "r300/dri" "" "" "" DRICOMMON_NEED_LIBDRM=yes ;; xr600) @@ -1785,7 +1758,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/xvmc" "r600/vdpau" + gallium_check_st "radeon/drm" "r600/dri" "" "r600/xvmc" "r600/vdpau" DRICOMMON_NEED_LIBDRM=yes ;; xradeonsi) @@ -1794,7 +1767,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/vdpau" "" + gallium_check_st "radeon/drm" "radeonsi/dri" "" "" "radeonsi/vdpau" DRICOMMON_NEED_LIBDRM=yes ;; xnouveau) @@ -1802,7 +1775,7 @@ if test "x$with_gallium_drivers" != x; then PKG_CHECK_MODULES([NOUVEAU], [libdrm_nouveau >= $LIBDRM_NOUVEAU_REQUIRED]) gallium_require_drm_loader GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS nouveau" - gallium_check_st "nouveau/drm" "dri-nouveau" "xorg-nouveau" "" "xvmc-nouveau" "vdpau-nouveau" + gallium_check_st "nouveau/drm" "dri-nouveau" "" "xvmc-nouveau" "vdpau-nouveau" DRICOMMON_NEED_LIBDRM=yes ;; xfreedreno) @@ -1810,7 +1783,7 @@ if test "x$with_gallium_drivers" != x; then PKG_CHECK_MODULES([FREEDRENO], [libdrm_freedreno >= $LIBDRM_FREEDRENO_REQUIRED]) gallium_require_drm_loader GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS freedreno" - gallium_check_st "freedreno/drm" "dri-freedreno" "" "" "" "" + gallium_check_st "freedreno/drm" "dri-freedreno" "" "" "" DRICOMMON_NEED_LIBDRM=yes ;; xswrast) @@ -1938,9 +1911,9 @@ AM_CONDITIONAL(HAVE_X11_DRIVER, test "x$enable_xlib_glx" = xyes) AM_CONDITIONAL(HAVE_OSMESA, test "x$enable_osmesa" = xyes) AM_CONDITIONAL(HAVE_GALLIUM_OSMESA, test "x$enable_gallium_osmesa" = xyes) -AM_CONDITIONAL(HAVE_X86_ASM, echo "$DEFINES" | grep 'X86_ASM' >/dev/null 2>&1) -AM_CONDITIONAL(HAVE_X86_64_ASM, echo "$DEFINES" | grep 'X86_64_ASM' >/dev/null 2>&1) -AM_CONDITIONAL(HAVE_SPARC_ASM, echo "$DEFINES" | grep 'SPARC_ASM' >/dev/null 2>&1) +AM_CONDITIONAL(HAVE_X86_ASM, test "x$asm_arch" = xx86 -o "x$asm_arch" = xx86_64) +AM_CONDITIONAL(HAVE_X86_64_ASM, test "x$asm_arch" = xx86_64) +AM_CONDITIONAL(HAVE_SPARC_ASM, test "x$asm_arch" = xsparc) AC_SUBST([VDPAU_MAJOR], 1) AC_SUBST([VDPAU_MINOR], 0) @@ -2013,7 +1986,6 @@ AC_CONFIG_FILES([Makefile src/gallium/state_trackers/vdpau/Makefile src/gallium/state_trackers/vega/Makefile src/gallium/state_trackers/xa/Makefile - src/gallium/state_trackers/xorg/Makefile src/gallium/state_trackers/xvmc/Makefile src/gallium/targets/Makefile src/gallium/targets/dri-freedreno/Makefile @@ -2038,8 +2010,6 @@ AC_CONFIG_FILES([Makefile src/gallium/targets/vdpau-nouveau/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/tests/trivial/Makefile src/gallium/tests/unit/Makefile @@ -2091,9 +2061,7 @@ AC_CONFIG_FILES([Makefile src/mesa/drivers/osmesa/osmesa.pc src/mesa/drivers/x11/Makefile src/mesa/main/tests/Makefile - src/mesa/main/tests/hash_table/Makefile - src/mesa/x86-64/Makefile - src/mesa/x86/Makefile]) + src/mesa/main/tests/hash_table/Makefile]) dnl Sort the dirs alphabetically GALLIUM_TARGET_DIRS=`echo $GALLIUM_TARGET_DIRS|tr " " "\n"|sort -u|tr "\n" " "` diff --git a/mesalib/docs/GL3.txt b/mesalib/docs/GL3.txt index 7d100dff1..a8cffab44 100644 --- a/mesalib/docs/GL3.txt +++ b/mesalib/docs/GL3.txt @@ -106,8 +106,8 @@ GL_ARB_tessellation_shader not started GL_ARB_texture_buffer_object_rgb32 DONE (i965, r600, radeonsi, softpipe) GL_ARB_texture_cube_map_array DONE (i965, r600, softpipe) GL_ARB_texture_gather DONE (i965) -GL_ARB_transform_feedback2 DONE (r600, radeonsi) -GL_ARB_transform_feedback3 DONE (r600, radeonsi) +GL_ARB_transform_feedback2 DONE (i965, r600, radeonsi) +GL_ARB_transform_feedback3 DONE (i965, r600, radeonsi) GL 4.1: @@ -126,9 +126,9 @@ GL 4.2: GLSL 4.2 not started GL_ARB_texture_compression_bptc not started GL_ARB_compressed_texture_pixel_storage not started -GL_ARB_shader_atomic_counters in progress (Curro) +GL_ARB_shader_atomic_counters DONE (i965) GL_ARB_texture_storage DONE (all drivers) -GL_ARB_transform_feedback_instanced DONE (r600, radeonsi) +GL_ARB_transform_feedback_instanced DONE (i965, r600, radeonsi) GL_ARB_base_instance DONE (i965, nv50, nvc0, r600, radeonsi) GL_ARB_shader_image_load_store not started GL_ARB_conservative_depth DONE (all drivers that support GLSL 1.30) @@ -161,7 +161,7 @@ GL_ARB_texture_buffer_range DONE (nv50, nvc0, i965, r60 GL_ARB_texture_query_levels DONE (i965) GL_ARB_texture_storage_multisample DONE (all drivers that support GL_ARB_texture_multisample) GL_ARB_texture_view not started -GL_ARB_vertex_attrib_binding started (Fredrik) +GL_ARB_vertex_attrib_binding DONE (all drivers) GL 4.4: @@ -175,7 +175,7 @@ GL_ARB_multi_bind not started GL_ARB_query_buffer_object not started GL_ARB_texture_mirror_clamp_to_edge DONE (i965, nv30, nv50, nvc0, r300, r600, radeonsi, swrast) GL_ARB_texture_stencil8 not started -GL_ARB_vertex_type_10f_11f_11f_rev not started +GL_ARB_vertex_type_10f_11f_11f_rev DONE (i965, r600) More info about these features and the work involved can be found at diff --git a/mesalib/docs/relnotes/10.0.html b/mesalib/docs/relnotes/10.0.html index b74d03dc2..eabe77f83 100644 --- a/mesalib/docs/relnotes/10.0.html +++ b/mesalib/docs/relnotes/10.0.html @@ -51,6 +51,9 @@ Note: some of the new features are only available with certain drivers.
  • GL_ARB_texture_mirror_clamp_to_edge.
  • GL_ARB_transform_feedback2, GL_ARB_transform_feedback3, and GL_ARB_transform_feedback_instanced on i965/Gen7 (with appropriate kernel support).
  • GL_ARB_sample_shading on i965.
  • +
  • GL_ARB_shader_atomic_counters on i965.
  • +
  • GL_ARB_vertex_attrib_binding
  • +
  • GL_ARB_vertex_type_10f_11f_11f_rev on i965 and r600g
  • GL_KHR_debug
  • diff --git a/mesalib/docs/specs/MESA_query_renderer.spec b/mesalib/docs/specs/MESA_query_renderer.spec new file mode 100644 index 000000000..bf0975669 --- /dev/null +++ b/mesalib/docs/specs/MESA_query_renderer.spec @@ -0,0 +1,405 @@ +Name + + MESA_query_renderer + +Name Strings + + GLX_MESA_query_renderer + +Contact + + Ian Romanick + +IP Status + + No known IP claims. + +Status + + Incomplete. DO NOT SHIP. + +Version + + Version 6, 7-November-2013 + +Number + + TBD. + +Dependencies + + GLX 1.4 is required. + + GLX_ARB_create_context and GLX_ARB_create_context_profile are required. + + This extension interacts with GLX_EXT_create_context_es2_profile and + GLX_EXT_create_context_es_profile. + +Overview + + In many situations, applications want to detect characteristics of a + rendering device before creating a context for that device. Information + gathered at this stage may guide choices the application makes about + color depth, number of samples per-pixel, texture quality, and so on. + In addition, versions of supported APIs and implementation API + preference may also guide start-up decisions made by the application. + For example, one implementation may prefer vertex data be supplied using + methods only available in a compatibility profile, but another + implementation may only support the desired version in a core profile. + + There are also cases where more than one renderer may be available per + display. For example, there is typically a hardware implementation and + a software based implementation. There are cases where an application + may want to pick one over the other. One such situation is when the + software implementation supports more features than the hardware + implementation. Another situation is when a particular version of the + hardware implementation is blacklisted due to known bugs. + + This extension provides a mechanism for the application to query all of + the available renderers for a particular display and screen. In + addition, this extension provides a mechanism for applications to create + contexts with respect to a specific renderer. + +New Procedures and Functions + + Bool glXQueryRendererIntegerMESA(Display *dpy, int screen, + int renderer, int attribute, + unsigned int *value); + Bool glXQueryCurrentRendererIntegerMESA(int attribute, unsigned int *value); + + const char *glXQueryRendererStringMESA(Display *dpy, int screen, + int renderer, int attribute); + + const char *glXQueryCurrentRendererStringMESA(int attribute); + +New Tokens + + Accepted as an in glXQueryRendererIntegerMESA and + glXQueryCurrentRendererIntegerMESA: + + GLX_RENDERER_VENDOR_ID_MESA 0x8183 + GLX_RENDERER_DEVICE_ID_MESA 0x8184 + GLX_RENDERER_VERSION_MESA 0x8185 + GLX_RENDERER_ACCELERATED_MESA 0x8186 + GLX_RENDERER_VIDEO_MEMORY_MESA 0x8187 + GLX_RENDERER_UNIFIED_MEMORY_ARCHITECTURE_MESA 0x8188 + GLX_RENDERER_PREFERRED_PROFILE_MESA 0x8189 + GLX_RENDERER_OPENGL_CORE_PROFILE_VERSION_MESA 0x818A + GLX_RENDERER_OPENGL_COMPATIBILITY_PROFILE_VERSION_MESA 0x818B + GLX_RENDERER_OPENGL_ES_PROFILE_VERSION_MESA 0x818C + GLX_RENDERER_OPENGL_ES2_PROFILE_VERSION_MESA 0x818D + + Accepted as an in glXQueryRendererStringMESA and + glXQueryCurrentRendererStringMESA: + + GLX_RENDERER_VENDOR_ID_MESA + GLX_RENDERER_DEVICE_ID_MESA + + Accepted as an attribute name in <*attrib_list> in + glXCreateContextAttribsARB: + + GLX_RENDERER_ID_MESA 0x818E + +Additions to the OpenGL / WGL Specifications + + None. This specification is written for GLX. + +Additions to the GLX 1.4 Specification + + [Add the following to Section X.Y.Z of the GLX Specification] + + To obtain information about the available renderers for a particular + display and screen, + + Bool glXQueryRendererIntegerMESA(Display *dpy, int screen, int renderer, + int attribute, unsigned int *value); + + can be used. The value for will be returned in one or more + integers specified by . The values, data sizes, and descriptions + of each renderer attribute are listed in the table below. + + GLX renderer attribute number description + of values + ---------------------- --------- ----------- + GLX_RENDERER_VENDOR_ID_MESA 1 PCI ID of the device vendor + GLX_RENDERER_DEVICE_ID_MESA 1 PCI ID of the device + GLX_RENDERER_VERSION_MESA 3 Major, minor, and patch level of + the renderer implementation + GLX_RENDERER_ACCELERATED_MESA 1 Boolean indicating whether or + not the renderer is hardware + accelerated + GLX_RENDERER_VIDEO_MEMORY_MESA 1 Number of megabytes of video + memory available to the renderer + GLX_RENDERER_UNIFIED_MEMORY_ARCHITECTURE_MESA + 1 Boolean indicating whether or + not the renderer uses a unified + memory architecture or has + separate "on-card" and GART + memory. + GLX_RENDERER_PREFERRED_PROFILE_MESA + 1 Bitmask of the preferred context + profile for this renderer. This + value is suitable to be supplied + with the + GLX_CONTEXT_PROFILE_MASK_ARB + attribute to + glXCreateContextAttribsARB + GLX_RENDERER_OPENGL_CORE_PROFILE_VERSION_MESA + 2 Maximum core profile major and + minor version supported by the + renderer + GLX_RENDERER_OPENGL_COMPATIBILITY_PROFILE_VERSION_MESA + 2 Maximum compatibility profile + major and minor version + supported by the renderer + GLX_RENDERER_OPENGL_ES_PROFILE_VERSION_MESA + 2 Maximum OpenGL ES 1.x + major and minor version + supported by the renderer + GLX_RENDERER_OPENGL_ES2_PROFILE_VERSION_MESA + 2 Maximum OpenGL ES 2.x or 3.x + major and minor version + supported by the renderer + + In the table, boolean attributes will have either the value 0 or 1. + + GLX_RENDERER_OPENGL_CORE_PROFILE_VERSION_MESA, + GLX_RENDERER_OPENGL_COMPATIBILITY_PROFILE_VERSION_MESA, + GLX_RENDERER_OPENGL_ES_PROFILE_VERSION_MESA, and + GLX_RENDERER_OPENGL_ES2_PROFILE_VERSION_MESA each return <0, 0> in + *value if no version of that profile is supported. + + GLX_RENDERER_VENDOR_ID_MESA and GLX_RENDERER_DEVICE_ID_MESA may return + 0xFFFFFFFF if the device does not have a PCI ID (because it is not a PCI + device) or if the PCI ID is not available. In this case the application + should rely on the string query instead. + + If is not a recognized value, False is returned, but no GLX + error is generated. Otherwise, True is returned. + + String versions of some attributes may also be queried using + + const char *glXQueryRendererStringMESA(Display *dpy, int screen, + int renderer, int attribute); + + The value for will be returned in one or more + integers specified by . The values, data sizes, and descriptions + of each renderer attribute are listed in the table below. + + GLX renderer attribute description + ---------------------- ----------- + GLX_RENDERER_VENDOR_ID_MESA Name of the renderer provider. This may + differ from the vendor name of the + underlying hardware. + GLX_RENDERER_DEVICE_ID_MESA Name of the renderer. This may differ from + the name of the underlying hardware (e.g., + for a software renderer). + + If is not a recognized value, NULL is returned, but no GLX + error is generated. + + The string returned for GLX_RENDERER_VENDOR_ID_MESA will have the same + format as the string that would be returned by glGetString of GL_VENDOR. + It may, however, have a different value. + + The string returned for GLX_RENDERER_DEVICE_ID_MESA will have the same + format as the string that would be returned by glGetString of GL_RENDERER. + It may, however, have a different value. + + + [Add to section section 3.3.7 "Rendering Contexts"] + + The attribute name GLX_RENDERER_ID_MESA specified the index of the render + against which the context should be created. The default value of + GLX_RENDER_ID_MESA is 0. + + + [Add to list of errors for glXCreateContextAttribsARB in section section + 3.3.7 "Rendering Contexts"] + + * If the value of GLX_RENDERER_ID_MESA specifies a non-existent + renderer, BadMatch is generated. + +Dependencies on GLX_EXT_create_context_es_profile and +GLX_EXT_create_context_es2_profile + + If neither extension is supported, remove all mention of + GLX_RENDERER_OPENGL_ES2_PROFILE_VERSION_MESA from the spec. + + If GLX_EXT_create_context_es_profile is not supported, remove all mention of + GLX_RENDERER_OPENGL_ES_PROFILE_VERSION_MESA from the spec. + +Issues + + 1) How should the difference between on-card and GART memory be exposed? + + UNRESOLVED. + + 2) How should memory limitations of unified memory architecture (UMA) + systems be exposed? + + UNRESOLVED. Some hardware has different per-process and global + limits for memory that can be accessed within a single draw call. + + 3) How should the renderer's API preference be advertised? + + UNRESOLVED. The common case for desktop renderers is to prefer + either core or compatibility. However, some renderers may actually + prefer an ES context. This leaves the application in a tough spot + if it can only support core or compatibility and the renderer says it + wants ES. + + 4) Should OpenGL ES 2.0 and OpenGL ES 3.0 be treated separately? + + RESOLVED. No. OpenGL ES 3.0 is backwards compatible with OpenGL ES + 2.0. Applications can detect OpenGL ES 3.0 support by querying + GLX_RENDERER_OPENGL_ES2_PROFILE_VERSION_MESA. + + 5) How can applications tell the difference between different hardware + renderers for the same device? For example, whether the renderer is the + open-source driver or the closed-source driver. + + RESOLVED. Assuming this extension is ever implemented outside Mesa, + applications can query GLX_RENDERER_VENDOR_ID_MESA from + glXQueryRendererStringMESA. This will almost certainly return + different strings for open-source and closed-source drivers. + + 6) What is the value of GLX_RENDERER_UNIFIED_MEMORY_ARCHITECTURE_MESA for + software renderers? + + UNRESOLVED. Video (display) memory and texture memory is not unified + for software implementations, so it seems reasonable for this to be + False. + + 7) How does an application determine the number of available renderers? + + UNRESOLVED. + + 8) What happens if a fbconfig is used to create context on a renderer + that cannot support it? For example, if a multisampled config is used + with a software renderer that does not support multisampling. + + RESOLVED. The language for glXCreateContextAttribsARB already covers + this case. Context creation will fail, and BadMatch is generated. + + 9) In addition to being able to query the supported versions, should + applications also be able to query the supported extensions? + + RESOLVED. No. Desktop OpenGL core profiles and OpenGL ES 3.0 have + moved away from the monolithic string returned by glGetString of + GL_EXTENSIONS. Providing the newer indexed query would require adding + a lot of extra infrastructure, and it would probably provide little + benefit to applications. + + 10) What combination of values for GLX_RENDERER_PREFERRED_PROFILE_MESA, + GLX_RENDERER_OPENGL_COMPATIBILITY_PROFILE_VERSION_MESA, and + GLX_RENDERER_OPENGL_CORE_PROFILE_VERSION_MESA should be returned + for a renderer that only supports OpenGL 3.1 without the + GL_ARB_compatibility extension? + + RESOLVED. The renderer will return GLX_CONTEXT_CORE_PROFILE_BIT_ARB + for GLX_RENDERER_PREFERRED_PROFILE_MESA. + + Further, the renderer will return <3,0> for + GLX_RENDERER_OPENGL_COMPATIBILITY_PROFILE_VERSION_MESA because OpenGL + 3.1 without GL_ARB_compatibility is not backwards compatible with + previous versions of OpenGL. The render will return <3,1> for + GLX_RENDERER_OPENGL_CORE_PROFILE_VERSION_MESA indicating that support + for OpenGL 3.1 is available. + + Even though there is no OpenGL 3.1 core profile, the values + returned for GLX_RENDERER_PREFERRED_PROFILE_MESA and + GLX_RENDERER_OPENGL_CORE_PROFILE_VERSION_MESA can be supplied + with the GLX_CONTEXT_PROFILE_MASK_ARB and + GLX_CONTEXT_{MAJOR,MINOR}_VERSION_ARB attributes of + glXCreateContextAttribsARB without error. If the requested + OpenGL version is less than 3.2, the + GLX_CONTEXT_PROFILE_MASK_ARB attribute is ignored by + glXCreateContextAttribsARB. + + 11) How can application learn about multi-GPU (e.g., SLI, CrossFireX, + etc.) configurations? + + UNRESOLVED. Based on ISV feedback, this is important information to + provide to the application. Given the variety of possible hardware + configurations (e.g., Hybrid CrossFireX) and different rendering + modes (e.g., split-frame rendering vs. alternate-frame rendering), + it's not clear how this information can be communicated. + + It is likely that this will be left to a layered extension. + + 12) Should capability queries similar to those in + GL_ARB_internalformat_query or GL_ARB_internalformat_query2 be added? + + RESOLVED. No. With the possible exception of the texture size + queries, it seems unlikely that applications would ever use this + information before creating a context. + + 13) Existing GL extensions (e.g., GL_ATI_meminfo and + GL_NVX_gpu_memory_info) allow easy queries after context creation. With + this extension it is a bit of a pain for a portable application to query + the information after context creation. + + RESOLVED. Add versions of the queries that implicitly take the + display, screen, and renderer from the currently bound context. + + 14) Why not make the queries from issue #13 GL functions (instead of GLX)? + + RESOLVED. It is fairly compelling for the post-creation queries to + just use glGetInteger and glGetString. However, the GL enums and + the GLX enums would have different names and would almost certainly + have different values. It seems like this would cause more problems + than it would solve. + + 15) Should the string queries be required to return the same values as + glGetString(GL_VENDOR) and glGetString(GL_RENDERER)? + + UNRESOLVED. This may be useful for applications that already do + device detection based on these strings. + + 16) What type should the value parameter of glXQueryRendererIntegerMESA + and glXQueryCurrentRendererIntegerMESA be? + + UNRESOLVED. Other similar GLX query functions just use int or + unsigned int, so that's what this extension uses for now. However, + an expeclitly sized value, such as uint32_t or uint64_t, seems + preferable. + + 17) What about SoCs and other systems that don't have PCI? + + RESOLVED. The GLX_RENDERER_VENDOR_ID_MESA and + GLX_RENDERER_DEVICE_ID_MESA integer queries may return 0xFFFFFFFF if a + PCI ID either does not exist or is not available. Implementations + should make every attempt to return as much information as is + possible. For example, if the implementation is running on a non-PCI + SoC with a Qualcomm GPU, GLX_RENDERER_VENDOR_ID_MESA should return + 0x168C, but GLX_RENDERER_DEVICE_ID_MESA will return 0x0000. + +Revision History + + Version 1, 2012/08/27 - Initial version + + Version 2, 2012/09/04 - Specify behavior of implementations that + do not support certain profiles. + Change wording of issue #8 to be more + clear. + Make some wording changes to issue #10 to + clarify the resolution a bit. + + Version 3, 2012/09/23 - Add issue #11 regarding multi-GPU systems. + + Version 4, 2013/02/01 - Add issue #12 regarding texture / renderbuffer + format queries. + + Version 5, 2013/02/14 - Add issues #13 and #14 regarding simpler queires + after the context is created and made current. + Add issue #15 regarding the string query. + Add issue #16 regarding the value type returned + by the Integer functions. + + Version 6, 2013/10/25 - Fix a typo. Update the list of functions to + which the new enums can be passed. The "Current" + versions were previously missing. + + Version 7, 2013/11/07 - Fix a couple more typos. Add issue #17 regarding + the PCI queries on systems that don't have PCI. diff --git a/mesalib/include/GL/glx.h b/mesalib/include/GL/glx.h index fa5a8eda9..62d0ede9e 100644 --- a/mesalib/include/GL/glx.h +++ b/mesalib/include/GL/glx.h @@ -467,7 +467,32 @@ extern void glXReleaseTexImageEXT(Display *dpy, GLXDrawable drawable, int buffer #endif /* GLX_EXT_texture_from_pixmap */ - +#ifndef GLX_MESA_query_renderer +#define GLX_MESA_query_renderer 1 + +#define GLX_RENDERER_VENDOR_ID_MESA 0x8183 +#define GLX_RENDERER_DEVICE_ID_MESA 0x8184 +#define GLX_RENDERER_VERSION_MESA 0x8185 +#define GLX_RENDERER_ACCELERATED_MESA 0x8186 +#define GLX_RENDERER_VIDEO_MEMORY_MESA 0x8187 +#define GLX_RENDERER_UNIFIED_MEMORY_ARCHITECTURE_MESA 0x8188 +#define GLX_RENDERER_PREFERRED_PROFILE_MESA 0x8189 +#define GLX_RENDERER_OPENGL_CORE_PROFILE_VERSION_MESA 0x818A +#define GLX_RENDERER_OPENGL_COMPATIBILITY_PROFILE_VERSION_MESA 0x818B +#define GLX_RENDERER_OPENGL_ES_PROFILE_VERSION_MESA 0x818C +#define GLX_RENDERER_OPENGL_ES2_PROFILE_VERSION_MESA 0x818D +#define GLX_RENDERER_ID_MESA 0x818E + +Bool glXQueryRendererIntegerMESA(Display *dpy, int screen, int renderer, int attribute, unsigned int *value); +Bool glXQueryCurrentRendererIntegerMESA(int attribute, unsigned int *value); +const char *glXQueryRendererStringMESA(Display *dpy, int screen, int renderer, int attribute); +const char *glXQueryCurrentRendererStringMESA(int attribute); + +typedef Bool (*PFNGLXQUERYRENDERERINTEGERMESAPROC) (Display *dpy, int screen, int renderer, int attribute, unsigned int *value); +typedef Bool (*PFNGLXQUERYCURRENTRENDERERINTEGERMESAPROC) (int attribute, unsigned int *value); +typedef const char *(*PFNGLXQUERYRENDERERSTRINGMESAPROC) (Display *dpy, int screen, int renderer, int attribute); +typedef const char *(*PFNGLXQUERYCURRENTRENDERERSTRINGMESAPROC) (int attribute); +#endif /* GLX_MESA_query_renderer */ /*** Should these go here, or in another header? */ /* diff --git a/mesalib/include/GL/internal/dri_interface.h b/mesalib/include/GL/internal/dri_interface.h index 48993b939..ed4325764 100644 --- a/mesalib/include/GL/internal/dri_interface.h +++ b/mesalib/include/GL/internal/dri_interface.h @@ -86,6 +86,10 @@ typedef struct __DRIdri2LoaderExtensionRec __DRIdri2LoaderExtension; typedef struct __DRI2flushExtensionRec __DRI2flushExtension; typedef struct __DRI2throttleExtensionRec __DRI2throttleExtension; + +typedef struct __DRIimageLoaderExtensionRec __DRIimageLoaderExtension; +typedef struct __DRIimageDriverExtensionRec __DRIimageDriverExtension; + /*@}*/ @@ -763,6 +767,40 @@ struct __DRIswrastExtensionRec { }; +/** Common DRI function definitions, shared among DRI2 and Image extensions + */ + +typedef __DRIscreen * +(*__DRIcreateNewScreen2Func)(int screen, int fd, + const __DRIextension **extensions, + const __DRIextension **driver_extensions, + const __DRIconfig ***driver_configs, + void *loaderPrivate); + +typedef __DRIdrawable * +(*__DRIcreateNewDrawableFunc)(__DRIscreen *screen, + const __DRIconfig *config, + void *loaderPrivate); + +typedef __DRIcontext * +(*__DRIcreateNewContextFunc)(__DRIscreen *screen, + const __DRIconfig *config, + __DRIcontext *shared, + void *loaderPrivate); + +typedef __DRIcontext * +(*__DRIcreateContextAttribsFunc)(__DRIscreen *screen, + int api, + const __DRIconfig *config, + __DRIcontext *shared, + unsigned num_attribs, + const uint32_t *attribs, + unsigned *error, + void *loaderPrivate); + +typedef unsigned int +(*__DRIgetAPIMaskFunc)(__DRIscreen *screen); + /** * DRI2 Loader extension. */ @@ -910,17 +948,11 @@ struct __DRIdri2ExtensionRec { const __DRIconfig ***driver_configs, void *loaderPrivate); - __DRIdrawable *(*createNewDrawable)(__DRIscreen *screen, - const __DRIconfig *config, - void *loaderPrivate); - - __DRIcontext *(*createNewContext)(__DRIscreen *screen, - const __DRIconfig *config, - __DRIcontext *shared, - void *loaderPrivate); + __DRIcreateNewDrawableFunc createNewDrawable; + __DRIcreateNewContextFunc createNewContext; /* Since version 2 */ - unsigned int (*getAPIMask)(__DRIscreen *screen); + __DRIgetAPIMaskFunc getAPIMask; __DRIcontext *(*createNewContextForAPI)(__DRIscreen *screen, int api, @@ -943,25 +975,14 @@ struct __DRIdri2ExtensionRec { * * \sa __DRIswrastExtensionRec::createContextAttribs */ - __DRIcontext *(*createContextAttribs)(__DRIscreen *screen, - int api, - const __DRIconfig *config, - __DRIcontext *shared, - unsigned num_attribs, - const uint32_t *attribs, - unsigned *error, - void *loaderPrivate); + __DRIcreateContextAttribsFunc createContextAttribs; /** * createNewScreen with the driver's extension list passed in. * * \since version 4 */ - __DRIscreen *(*createNewScreen2)(int screen, int fd, - const __DRIextension **loader_extensions, - const __DRIextension **driver_extensions, - const __DRIconfig ***driver_configs, - void *loaderPrivate); + __DRIcreateNewScreen2Func createNewScreen2; }; @@ -996,6 +1017,7 @@ struct __DRIdri2ExtensionRec { #define __DRI_IMAGE_FORMAT_NONE 0x1008 #define __DRI_IMAGE_FORMAT_XRGB2101010 0x1009 #define __DRI_IMAGE_FORMAT_ARGB2101010 0x100a +#define __DRI_IMAGE_FORMAT_SARGB8 0x100b #define __DRI_IMAGE_USE_SHARE 0x0001 #define __DRI_IMAGE_USE_SCANOUT 0x0002 @@ -1287,4 +1309,105 @@ typedef struct __DRIDriverVtableExtensionRec { const struct __DriverAPIRec *vtable; } __DRIDriverVtableExtension; +/** + * Query renderer driver extension + * + * This allows the window system layer (either EGL or GLX) to query aspects of + * hardware and driver support without creating a context. + */ +#define __DRI2_RENDERER_QUERY "DRI_RENDERER_QUERY" +#define __DRI2_RENDERER_QUERY_VERSION 1 + +#define __DRI2_RENDERER_VENDOR_ID 0x0000 +#define __DRI2_RENDERER_DEVICE_ID 0x0001 +#define __DRI2_RENDERER_VERSION 0x0002 +#define __DRI2_RENDERER_ACCELERATED 0x0003 +#define __DRI2_RENDERER_VIDEO_MEMORY 0x0004 +#define __DRI2_RENDERER_UNIFIED_MEMORY_ARCHITECTURE 0x0005 +#define __DRI2_RENDERER_PREFERRED_PROFILE 0x0006 +#define __DRI2_RENDERER_OPENGL_CORE_PROFILE_VERSION 0x0007 +#define __DRI2_RENDERER_OPENGL_COMPATIBILITY_PROFILE_VERSION 0x0008 +#define __DRI2_RENDERER_OPENGL_ES_PROFILE_VERSION 0x0009 +#define __DRI2_RENDERER_OPENGL_ES2_PROFILE_VERSION 0x000a + +typedef struct __DRI2rendererQueryExtensionRec __DRI2rendererQueryExtension; +struct __DRI2rendererQueryExtensionRec { + __DRIextension base; + + int (*queryInteger)(__DRIscreen *screen, int attribute, unsigned int *val); + int (*queryString)(__DRIscreen *screen, int attribute, const char **val); +}; + +/** + * Image Loader extension. Drivers use this to allocate color buffers + */ + +enum __DRIimageBufferMask { + __DRI_IMAGE_BUFFER_BACK = (1 << 0), + __DRI_IMAGE_BUFFER_FRONT = (1 << 1) +}; + +struct __DRIimageList { + uint32_t image_mask; + __DRIimage *back; + __DRIimage *front; +}; + +#define __DRI_IMAGE_LOADER "DRI_IMAGE_LOADER" +#define __DRI_IMAGE_LOADER_VERSION 1 + +struct __DRIimageLoaderExtensionRec { + __DRIextension base; + + /** + * Allocate color buffers. + * + * \param driDrawable + * \param width Width of allocated buffers + * \param height Height of allocated buffers + * \param format one of __DRI_IMAGE_FORMAT_* + * \param stamp Address of variable to be updated when + * getBuffers must be called again + * \param loaderPrivate The loaderPrivate for driDrawable + * \param buffer_mask Set of buffers to allocate + * \param buffers Returned buffers + */ + int (*getBuffers)(__DRIdrawable *driDrawable, + unsigned int format, + uint32_t *stamp, + void *loaderPrivate, + uint32_t buffer_mask, + struct __DRIimageList *buffers); + + /** + * Flush pending front-buffer rendering + * + * Any rendering that has been performed to the + * fake front will be flushed to the front + * + * \param driDrawable Drawable whose front-buffer is to be flushed + * \param loaderPrivate Loader's private data that was previously passed + * into __DRIdri2ExtensionRec::createNewDrawable + */ + void (*flushFrontBuffer)(__DRIdrawable *driDrawable, void *loaderPrivate); +}; + +/** + * DRI extension. + */ + +#define __DRI_IMAGE_DRIVER "DRI_IMAGE_DRIVER" +#define __DRI_IMAGE_DRIVER_VERSION 1 + +struct __DRIimageDriverExtensionRec { + __DRIextension base; + + /* Common DRI functions, shared with DRI2 */ + __DRIcreateNewScreen2Func createNewScreen2; + __DRIcreateNewDrawableFunc createNewDrawable; + __DRIcreateNewContextFunc createNewContext; + __DRIcreateContextAttribsFunc createContextAttribs; + __DRIgetAPIMaskFunc getAPIMask; +}; + #endif diff --git a/mesalib/src/gallium/SConscript b/mesalib/src/gallium/SConscript index 9a25ccafb..c68519df0 100644 --- a/mesalib/src/gallium/SConscript +++ b/mesalib/src/gallium/SConscript @@ -45,9 +45,6 @@ if not env['embedded']: if env['dri']: SConscript('state_trackers/dri/SConscript') - if env['dri'] and env['xorg']: - SConscript('state_trackers/xorg/SConscript') - if env['platform'] == 'windows': SConscript('state_trackers/wgl/SConscript') @@ -136,11 +133,6 @@ if not env['embedded']: 'targets/dri-i915/SConscript', ]) - if env['xorg'] and env['drm']: - SConscript([ - #'targets/xorg-i915/SConscript', - ]) - # # Unit tests & tools diff --git a/mesalib/src/gallium/auxiliary/util/u_format.c b/mesalib/src/gallium/auxiliary/util/u_format.c index 9ef3bb53f..6b602bf32 100644 --- a/mesalib/src/gallium/auxiliary/util/u_format.c +++ b/mesalib/src/gallium/auxiliary/util/u_format.c @@ -215,9 +215,8 @@ util_format_is_supported(enum pipe_format format, unsigned bind) * default MRD will be 1.0 / ((1 << 24) - 1). */ double -util_get_depth_format_mrd(enum pipe_format format) +util_get_depth_format_mrd(const struct util_format_description *desc) { - struct util_format_description *format_desc; /* * Depth buffer formats without a depth component OR scenarios * without a bound depth buffer default to D24. @@ -225,23 +224,20 @@ util_get_depth_format_mrd(enum pipe_format format) double mrd = 1.0 / ((1 << 24) - 1); unsigned depth_channel; - format_desc = (struct util_format_description *) - util_format_description(format); - - assert(format_desc); + assert(desc); /* * Some depth formats do not store the depth component in the first * channel, detect the format and adjust the depth channel. Get the * swizzled depth component channel. */ - depth_channel = format_desc->swizzle[0]; + depth_channel = desc->swizzle[0]; - if (format_desc->channel[depth_channel].type == UTIL_FORMAT_TYPE_UNSIGNED && - format_desc->channel[depth_channel].normalized) { + if (desc->channel[depth_channel].type == UTIL_FORMAT_TYPE_UNSIGNED && + desc->channel[depth_channel].normalized) { int depth_bits; - depth_bits = format_desc->channel[depth_channel].size; + depth_bits = desc->channel[depth_channel].size; mrd = 1.0 / ((1ULL << depth_bits) - 1); } diff --git a/mesalib/src/gallium/auxiliary/util/u_format.h b/mesalib/src/gallium/auxiliary/util/u_format.h index 369c3994a..0fbaf4cc1 100644 --- a/mesalib/src/gallium/auxiliary/util/u_format.h +++ b/mesalib/src/gallium/auxiliary/util/u_format.h @@ -545,6 +545,22 @@ util_format_is_depth_and_stencil(enum pipe_format format) } +/** + * Calculates the depth format type based upon the incoming format description. + */ +static INLINE unsigned +util_get_depth_format_type(const struct util_format_description *desc) +{ + unsigned depth_channel = desc->swizzle[0]; + if (desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS && + depth_channel != UTIL_FORMAT_SWIZZLE_NONE) { + return desc->channel[depth_channel].type; + } else { + return UTIL_FORMAT_TYPE_VOID; + } +} + + /** * Calculates the MRD for the depth format. MRD is used in depth bias * for UNORM and unbound depth buffers. When the depth buffer is floating @@ -552,7 +568,7 @@ util_format_is_depth_and_stencil(enum pipe_format format) * default MRD will be 1.0 / ((1 << 24) - 1). */ double -util_get_depth_format_mrd(enum pipe_format format); +util_get_depth_format_mrd(const struct util_format_description *desc); /** diff --git a/mesalib/src/gallium/auxiliary/util/u_math.h b/mesalib/src/gallium/auxiliary/util/u_math.h index f5c14ef8d..426d5daa7 100644 --- a/mesalib/src/gallium/auxiliary/util/u_math.h +++ b/mesalib/src/gallium/auxiliary/util/u_math.h @@ -245,6 +245,19 @@ union di { }; +/** + * Extract the IEEE float32 exponent. + */ +static INLINE signed +util_get_float32_exponent(float x) { + union fi f; + + f.f = x; + + return ((f.ui >> 23) & 0xff) - 127; +} + + /** * Fast version of 2^x * Identity: exp2(a + b) = exp2(a) * exp2(b) diff --git a/mesalib/src/glsl/Makefile.sources b/mesalib/src/glsl/Makefile.sources index 2aabc0585..744b0adcf 100644 --- a/mesalib/src/glsl/Makefile.sources +++ b/mesalib/src/glsl/Makefile.sources @@ -47,6 +47,7 @@ LIBGLSL_FILES = \ $(GLSL_SRCDIR)/ir_validate.cpp \ $(GLSL_SRCDIR)/ir_variable_refcount.cpp \ $(GLSL_SRCDIR)/linker.cpp \ + $(GLSL_SRCDIR)/link_atomics.cpp \ $(GLSL_SRCDIR)/link_functions.cpp \ $(GLSL_SRCDIR)/link_interface_blocks.cpp \ $(GLSL_SRCDIR)/link_uniforms.cpp \ diff --git a/mesalib/src/glsl/ast.h b/mesalib/src/glsl/ast.h index 97905c6a6..5c214b604 100644 --- a/mesalib/src/glsl/ast.h +++ b/mesalib/src/glsl/ast.h @@ -385,6 +385,12 @@ struct ast_type_qualifier { */ unsigned explicit_binding:1; + /** + * Flag set if GL_ARB_shader_atomic counter "offset" layout + * qualifier is used. + */ + unsigned explicit_offset:1; + /** \name Layout qualifiers for GL_AMD_conservative_depth */ /** \{ */ unsigned depth_any:1; @@ -447,6 +453,15 @@ struct ast_type_qualifier { */ int binding; + /** + * Offset specified via GL_ARB_shader_atomic_counter's "offset" + * keyword. + * + * \note + * This field is only valid if \c explicit_offset is set. + */ + int offset; + /** * Return true if and only if an interpolation qualifier is present. */ diff --git a/mesalib/src/glsl/ast_to_hir.cpp b/mesalib/src/glsl/ast_to_hir.cpp index f75e68ce1..76b256c73 100644 --- a/mesalib/src/glsl/ast_to_hir.cpp +++ b/mesalib/src/glsl/ast_to_hir.cpp @@ -1995,12 +1995,22 @@ validate_binding_qualifier(struct _mesa_glsl_parse_state *state, "exceeds the maximum number of texture image units " "(%d)", qual->binding, elements, limit); + return false; + } + } else if (var->type->contains_atomic()) { + assert(ctx->Const.MaxAtomicBufferBindings <= MAX_COMBINED_ATOMIC_BUFFERS); + if (unsigned(qual->binding) >= ctx->Const.MaxAtomicBufferBindings) { + _mesa_glsl_error(loc, state, "layout(binding = %d) exceeds the " + " maximum number of atomic counter buffer bindings" + "(%d)", qual->binding, + ctx->Const.MaxAtomicBufferBindings); + return false; } } else { _mesa_glsl_error(loc, state, "the \"binding\" qualifier only applies to uniform " - "blocks, samplers, or arrays of samplers"); + "blocks, samplers, atomic counters, or arrays thereof"); return false; } @@ -2300,6 +2310,29 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual, var->binding = qual->binding; } + if (var->type->contains_atomic()) { + if (var->mode == ir_var_uniform) { + if (var->explicit_binding) { + unsigned *offset = &state->atomic_counter_offsets[var->binding]; + + if (*offset % ATOMIC_COUNTER_SIZE) + _mesa_glsl_error(loc, state, + "misaligned atomic counter offset"); + + var->atomic.offset = *offset; + *offset += var->type->atomic_size(); + + } else { + _mesa_glsl_error(loc, state, + "atomic counters require explicit binding point"); + } + } else if (var->mode != ir_var_function_in) { + _mesa_glsl_error(loc, state, "atomic counters may only be declared as " + "function parameters or uniform-qualified " + "global variables"); + } + } + /* Does the declaration use the deprecated 'attribute' or 'varying' * keywords? */ @@ -2835,6 +2868,18 @@ ast_declarator_list::hir(exec_list *instructions, (void) this->type->specifier->hir(instructions, state); decl_type = this->type->glsl_type(& type_name, state); + + /* An offset-qualified atomic counter declaration sets the default + * offset for the next declaration within the same atomic counter + * buffer. + */ + if (decl_type && decl_type->contains_atomic()) { + if (type->qualifier.flags.q.explicit_binding && + type->qualifier.flags.q.explicit_offset) + state->atomic_counter_offsets[type->qualifier.binding] = + type->qualifier.offset; + } + if (this->declarations.is_empty()) { /* If there is no structure involved in the program text, there are two * possible scenarios: @@ -2864,6 +2909,11 @@ ast_declarator_list::hir(exec_list *instructions, _mesa_glsl_error(&loc, state, "invalid type `%s' in empty declaration", type_name); + } else if (decl_type->base_type == GLSL_TYPE_ATOMIC_UINT) { + /* Empty atomic counter declarations are allowed and useful + * to set the default offset qualifier. + */ + return NULL; } else if (this->type->qualifier.precision != ast_precision_none) { if (this->type->specifier->structure != NULL) { _mesa_glsl_error(&loc, state, @@ -4565,6 +4615,17 @@ ast_process_structure_or_interface_block(exec_list *instructions, "uniform in non-default uniform block contains sampler"); } + if (field_type->contains_atomic()) { + /* FINISHME: Add a spec quotation here once updated spec + * FINISHME: language is available. See Khronos bug #10903 + * FINISHME: on whether atomic counters are allowed in + * FINISHME: structures. + */ + YYLTYPE loc = decl_list->get_location(); + _mesa_glsl_error(&loc, state, "atomic counter in structure or " + "uniform block"); + } + const struct ast_type_qualifier *const qual = & decl_list->type->qualifier; if (qual->flags.q.std140 || diff --git a/mesalib/src/glsl/ast_type.cpp b/mesalib/src/glsl/ast_type.cpp index 8aabd95f9..2b088bf8b 100644 --- a/mesalib/src/glsl/ast_type.cpp +++ b/mesalib/src/glsl/ast_type.cpp @@ -72,7 +72,8 @@ ast_type_qualifier::has_layout() const || this->flags.q.packed || this->flags.q.explicit_location || this->flags.q.explicit_index - || this->flags.q.explicit_binding; + || this->flags.q.explicit_binding + || this->flags.q.explicit_offset; } bool @@ -121,13 +122,18 @@ ast_type_qualifier::merge_qualifier(YYLTYPE *loc, ubo_layout_mask.flags.q.packed = 1; ubo_layout_mask.flags.q.shared = 1; + ast_type_qualifier ubo_binding_mask; + ubo_binding_mask.flags.q.explicit_binding = 1; + ubo_binding_mask.flags.q.explicit_offset = 1; + /* Uniform block layout qualifiers get to overwrite each * other (rightmost having priority), while all other * qualifiers currently don't allow duplicates. */ if ((this->flags.i & q.flags.i & ~(ubo_mat_mask.flags.i | - ubo_layout_mask.flags.i)) != 0) { + ubo_layout_mask.flags.i | + ubo_binding_mask.flags.i)) != 0) { _mesa_glsl_error(loc, state, "duplicate layout qualifiers used"); return false; @@ -168,6 +174,9 @@ ast_type_qualifier::merge_qualifier(YYLTYPE *loc, if (q.flags.q.explicit_binding) this->binding = q.binding; + if (q.flags.q.explicit_offset) + this->offset = q.offset; + if (q.precision != ast_precision_none) this->precision = q.precision; diff --git a/mesalib/src/glsl/builtin_functions.cpp b/mesalib/src/glsl/builtin_functions.cpp index 3fa0cb5ad..8cb75e5ad 100644 --- a/mesalib/src/glsl/builtin_functions.cpp +++ b/mesalib/src/glsl/builtin_functions.cpp @@ -293,7 +293,8 @@ static bool fs_oes_derivatives(const _mesa_glsl_parse_state *state) { return state->target == fragment_shader && - (!state->es_shader || state->OES_standard_derivatives_enable); + (state->is_version(110, 300) || + state->OES_standard_derivatives_enable); } static bool diff --git a/mesalib/src/glsl/glsl_lexer.ll b/mesalib/src/glsl/glsl_lexer.ll index e24df8096..822d70d6b 100644 --- a/mesalib/src/glsl/glsl_lexer.ll +++ b/mesalib/src/glsl/glsl_lexer.ll @@ -337,6 +337,7 @@ samplerExternalOES { return IDENTIFIER; } +atomic_uint KEYWORD_WITH_ALT(420, 300, 420, 0, yyextra->ARB_shader_atomic_counters_enable, ATOMIC_UINT); struct return STRUCT; void return VOID_TOK; @@ -518,7 +519,6 @@ restrict KEYWORD(0, 300, 0, 0, RESTRICT); readonly KEYWORD(0, 300, 0, 0, READONLY); writeonly KEYWORD(0, 300, 0, 0, WRITEONLY); resource KEYWORD(0, 300, 0, 0, RESOURCE); -atomic_uint KEYWORD(0, 300, 0, 0, ATOMIC_UINT); patch KEYWORD(0, 300, 0, 0, PATCH); sample KEYWORD(0, 300, 0, 0, SAMPLE); subroutine KEYWORD(0, 300, 0, 0, SUBROUTINE); diff --git a/mesalib/src/glsl/glsl_parser.yy b/mesalib/src/glsl/glsl_parser.yy index 14420f8a3..ada3690f6 100644 --- a/mesalib/src/glsl/glsl_parser.yy +++ b/mesalib/src/glsl/glsl_parser.yy @@ -144,6 +144,7 @@ static bool match_layout_qualifier(const char *s1, const char *s2, %token SAMPLER2DMS ISAMPLER2DMS USAMPLER2DMS %token SAMPLER2DMSARRAY ISAMPLER2DMSARRAY USAMPLER2DMSARRAY %token SAMPLEREXTERNALOES +%token ATOMIC_UINT %token STRUCT VOID_TOK WHILE %token IDENTIFIER TYPE_IDENTIFIER NEW_IDENTIFIER %type any_identifier @@ -173,7 +174,7 @@ static bool match_layout_qualifier(const char *s1, const char *s2, %token HVEC2 HVEC3 HVEC4 DVEC2 DVEC3 DVEC4 FVEC2 FVEC3 FVEC4 %token SAMPLER3DRECT %token SIZEOF CAST NAMESPACE USING -%token COHERENT RESTRICT READONLY WRITEONLY RESOURCE ATOMIC_UINT PATCH SAMPLE +%token COHERENT RESTRICT READONLY WRITEONLY RESOURCE PATCH SAMPLE %token SUBROUTINE %token ERROR_TOK @@ -1324,12 +1325,19 @@ layout_qualifier_id: } } - if (state->ARB_shading_language_420pack_enable && + if ((state->ARB_shading_language_420pack_enable || + state->ARB_shader_atomic_counters_enable) && match_layout_qualifier("binding", $1, state) == 0) { $$.flags.q.explicit_binding = 1; $$.binding = $3; } + if (state->ARB_shader_atomic_counters_enable && + match_layout_qualifier("offset", $1, state) == 0) { + $$.flags.q.explicit_offset = 1; + $$.offset = $3; + } + if (match_layout_qualifier("max_vertices", $1, state) == 0) { $$.flags.q.max_vertices = 1; @@ -1703,6 +1711,7 @@ basic_type_specifier_nonarray: | SAMPLER2DMSARRAY { $$ = "sampler2DMSArray"; } | ISAMPLER2DMSARRAY { $$ = "isampler2DMSArray"; } | USAMPLER2DMSARRAY { $$ = "usampler2DMSArray"; } + | ATOMIC_UINT { $$ = "atomic_uint"; } ; precision_qualifier: diff --git a/mesalib/src/glsl/glsl_parser_extras.h b/mesalib/src/glsl/glsl_parser_extras.h index 345d7a018..d232bb3f6 100644 --- a/mesalib/src/glsl/glsl_parser_extras.h +++ b/mesalib/src/glsl/glsl_parser_extras.h @@ -373,6 +373,9 @@ struct _mesa_glsl_parse_state { * Unused for other shader types. */ unsigned gs_input_size; + + /** Atomic counter offsets by binding */ + unsigned atomic_counter_offsets[MAX_COMBINED_ATOMIC_BUFFERS]; }; # define YYLLOC_DEFAULT(Current, Rhs, N) \ diff --git a/mesalib/src/glsl/link_atomics.cpp b/mesalib/src/glsl/link_atomics.cpp new file mode 100644 index 000000000..2466bbd79 --- /dev/null +++ b/mesalib/src/glsl/link_atomics.cpp @@ -0,0 +1,277 @@ +/* + * 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. + */ + +#include "ir.h" +#include "ir_uniform.h" +#include "linker.h" +#include "program/hash_table.h" +#include "main/macros.h" + +namespace { + /* + * Atomic counter as seen by the program. + */ + struct active_atomic_counter { + unsigned id; + ir_variable *var; + }; + + /* + * Atomic counter buffer referenced by the program. There is a one + * to one correspondence between these and the objects that can be + * queried using glGetActiveAtomicCounterBufferiv(). + */ + struct active_atomic_buffer { + active_atomic_buffer() + : counters(0), num_counters(0), stage_references(), size(0) + {} + + ~active_atomic_buffer() + { + free(counters); + } + + void push_back(unsigned id, ir_variable *var) + { + counters = (active_atomic_counter *) + realloc(counters, sizeof(active_atomic_counter) * (num_counters + 1)); + + counters[num_counters].id = id; + counters[num_counters].var = var; + num_counters++; + } + + active_atomic_counter *counters; + unsigned num_counters; + unsigned stage_references[MESA_SHADER_TYPES]; + unsigned size; + }; + + int + cmp_actives(const void *a, const void *b) + { + const active_atomic_counter *const first = (active_atomic_counter *) a; + const active_atomic_counter *const second = (active_atomic_counter *) b; + + return int(first->var->atomic.offset) - int(second->var->atomic.offset); + } + + bool + check_atomic_counters_overlap(const ir_variable *x, const ir_variable *y) + { + return ((x->atomic.offset >= y->atomic.offset && + x->atomic.offset < y->atomic.offset + y->type->atomic_size()) || + (y->atomic.offset >= x->atomic.offset && + y->atomic.offset < x->atomic.offset + x->type->atomic_size())); + } + + active_atomic_buffer * + find_active_atomic_counters(struct gl_context *ctx, + struct gl_shader_program *prog, + unsigned *num_buffers) + { + active_atomic_buffer *const buffers = + new active_atomic_buffer[ctx->Const.MaxAtomicBufferBindings]; + + *num_buffers = 0; + + for (unsigned i = 0; i < MESA_SHADER_TYPES; ++i) { + struct gl_shader *sh = prog->_LinkedShaders[i]; + if (sh == NULL) + continue; + + foreach_list(node, sh->ir) { + ir_variable *var = ((ir_instruction *)node)->as_variable(); + + if (var && var->type->contains_atomic()) { + unsigned id; + bool found = prog->UniformHash->get(id, var->name); + assert(found); + active_atomic_buffer *buf = &buffers[var->binding]; + + /* If this is the first time the buffer is used, increment + * the counter of buffers used. + */ + if (buf->size == 0) + (*num_buffers)++; + + buf->push_back(id, var); + + buf->stage_references[i]++; + buf->size = MAX2(buf->size, var->atomic.offset + + var->type->atomic_size()); + } + } + } + + for (unsigned i = 0; i < ctx->Const.MaxAtomicBufferBindings; i++) { + if (buffers[i].size == 0) + continue; + + qsort(buffers[i].counters, buffers[i].num_counters, + sizeof(active_atomic_counter), + cmp_actives); + + for (unsigned j = 1; j < buffers[i].num_counters; j++) { + /* If an overlapping counter found, it must be a reference to the + * same counter from a different shader stage. + */ + if (check_atomic_counters_overlap(buffers[i].counters[j-1].var, + buffers[i].counters[j].var) + && strcmp(buffers[i].counters[j-1].var->name, + buffers[i].counters[j].var->name) != 0) { + linker_error(prog, "Atomic counter %s declared at offset %d " + "which is already in use.", + buffers[i].counters[j].var->name, + buffers[i].counters[j].var->atomic.offset); + } + } + } + return buffers; + } +} + +void +link_assign_atomic_counter_resources(struct gl_context *ctx, + struct gl_shader_program *prog) +{ + unsigned num_buffers; + active_atomic_buffer *abs = + find_active_atomic_counters(ctx, prog, &num_buffers); + + prog->AtomicBuffers = rzalloc_array(prog, gl_active_atomic_buffer, + num_buffers); + prog->NumAtomicBuffers = num_buffers; + + unsigned i = 0; + for (unsigned binding = 0; + binding < ctx->Const.MaxAtomicBufferBindings; + binding++) { + + /* If the binding was not used, skip. + */ + if (abs[binding].size == 0) + continue; + + active_atomic_buffer &ab = abs[binding]; + gl_active_atomic_buffer &mab = prog->AtomicBuffers[i]; + + /* Assign buffer-specific fields. */ + mab.Binding = binding; + mab.MinimumSize = ab.size; + mab.Uniforms = rzalloc_array(prog->AtomicBuffers, GLuint, + ab.num_counters); + mab.NumUniforms = ab.num_counters; + + /* Assign counter-specific fields. */ + for (unsigned j = 0; j < ab.num_counters; j++) { + ir_variable *const var = ab.counters[j].var; + const unsigned id = ab.counters[j].id; + gl_uniform_storage *const storage = &prog->UniformStorage[id]; + + mab.Uniforms[j] = id; + var->atomic.buffer_index = i; + storage->atomic_buffer_index = i; + storage->offset = var->atomic.offset; + storage->array_stride = (var->type->is_array() ? + var->type->element_type()->atomic_size() : 0); + } + + /* Assign stage-specific fields. */ + for (unsigned j = 0; j < MESA_SHADER_TYPES; ++j) + mab.StageReferences[j] = + (ab.stage_references[j] ? GL_TRUE : GL_FALSE); + + i++; + } + + delete [] abs; + assert(i == num_buffers); +} + +void +link_check_atomic_counter_resources(struct gl_context *ctx, + struct gl_shader_program *prog) +{ + STATIC_ASSERT(MESA_SHADER_TYPES == 3); + static const char *shader_names[MESA_SHADER_TYPES] = { + "vertex", "geometry", "fragment" + }; + const unsigned max_atomic_counters[MESA_SHADER_TYPES] = { + ctx->Const.VertexProgram.MaxAtomicCounters, + ctx->Const.GeometryProgram.MaxAtomicCounters, + ctx->Const.FragmentProgram.MaxAtomicCounters + }; + const unsigned max_atomic_buffers[MESA_SHADER_TYPES] = { + ctx->Const.VertexProgram.MaxAtomicBuffers, + ctx->Const.GeometryProgram.MaxAtomicBuffers, + ctx->Const.FragmentProgram.MaxAtomicBuffers + }; + unsigned num_buffers; + active_atomic_buffer *const abs = + find_active_atomic_counters(ctx, prog, &num_buffers); + unsigned atomic_counters[MESA_SHADER_TYPES] = {}; + unsigned atomic_buffers[MESA_SHADER_TYPES] = {}; + unsigned total_atomic_counters = 0; + unsigned total_atomic_buffers = 0; + + /* Sum the required resources. Note that this counts buffers and + * counters referenced by several shader stages multiple times + * against the combined limit -- That's the behavior the spec + * requires. + */ + for (unsigned i = 0; i < ctx->Const.MaxAtomicBufferBindings; i++) { + if (abs[i].size == 0) + continue; + + for (unsigned j = 0; j < MESA_SHADER_TYPES; ++j) { + const unsigned n = abs[i].stage_references[j]; + + if (n) { + atomic_counters[j] += n; + total_atomic_counters += n; + atomic_buffers[j]++; + total_atomic_buffers++; + } + } + } + + /* Check that they are within the supported limits. */ + for (unsigned i = 0; i < MESA_SHADER_TYPES; i++) { + if (atomic_counters[i] > max_atomic_counters[i]) + linker_error(prog, "Too many %s shader atomic counters", + shader_names[i]); + + if (atomic_buffers[i] > max_atomic_buffers[i]) + linker_error(prog, "Too many %s shader atomic counter buffers", + shader_names[i]); + } + + if (total_atomic_counters > ctx->Const.MaxCombinedAtomicCounters) + linker_error(prog, "Too many combined atomic counters"); + + if (total_atomic_buffers > ctx->Const.MaxCombinedAtomicBuffers) + linker_error(prog, "Too many combined atomic buffers"); + + delete [] abs; +} diff --git a/mesalib/src/glsl/linker.cpp b/mesalib/src/glsl/linker.cpp index 49bb142a8..1d53b6599 100644 --- a/mesalib/src/glsl/linker.cpp +++ b/mesalib/src/glsl/linker.cpp @@ -651,6 +651,14 @@ cross_validate_globals(struct gl_shader_program *prog, existing->explicit_binding = true; } + if (var->type->contains_atomic() && + var->atomic.offset != existing->atomic.offset) { + linker_error(prog, "offset specifications for %s " + "`%s' have differing values\n", + mode_string(var), var->name); + return; + } + /* Validate layout qualifiers for gl_FragDepth. * * From the AMD/ARB_conservative_depth specs: @@ -1485,8 +1493,12 @@ update_array_sizes(struct gl_shader_program *prog) /* GL_ARB_uniform_buffer_object says that std140 uniforms * will not be eliminated. Since we always do std140, just * don't resize arrays in UBOs. + * + * Atomic counters are supposed to get deterministic + * locations assigned based on the declaration ordering and + * sizes, array compaction would mess that up. */ - if (var->is_in_uniform_block()) + if (var->is_in_uniform_block() || var->type->contains_atomic()) continue; unsigned int size = var->max_array_access; @@ -1991,6 +2003,10 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) prog->UniformBlockStageIndex[i] = NULL; } + ralloc_free(prog->AtomicBuffers); + prog->AtomicBuffers = NULL; + prog->NumAtomicBuffers = 0; + /* Separate the shaders into groups based on their type. */ struct gl_shader **vert_shader_list; @@ -2342,9 +2358,12 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) update_array_sizes(prog); link_assign_uniform_locations(prog); + link_assign_atomic_counter_resources(ctx, prog); store_fragdepth_layout(prog); check_resources(ctx, prog); + link_check_atomic_counter_resources(ctx, prog); + if (!prog->LinkStatus) goto done; diff --git a/mesalib/src/glsl/linker.h b/mesalib/src/glsl/linker.h index 887cd33d1..7b1f6f9c5 100644 --- a/mesalib/src/glsl/linker.h +++ b/mesalib/src/glsl/linker.h @@ -69,6 +69,14 @@ validate_interstage_interface_blocks(struct gl_shader_program *prog, const gl_shader *producer, const gl_shader *consumer); +extern void +link_assign_atomic_counter_resources(struct gl_context *ctx, + struct gl_shader_program *prog); + +extern void +link_check_atomic_counter_resources(struct gl_context *ctx, + struct gl_shader_program *prog); + /** * Class for processing all of the leaf fields of a variable that corresponds * to a program resource. diff --git a/mesalib/src/mapi/glapi/Makefile.am b/mesalib/src/mapi/glapi/Makefile.am index 05c67a6d4..bf653a305 100644 --- a/mesalib/src/mapi/glapi/Makefile.am +++ b/mesalib/src/mapi/glapi/Makefile.am @@ -33,10 +33,11 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/mesa if HAVE_X86_ASM -GLAPI_ASM_SOURCES = $(X86_API) -endif if HAVE_X86_64_ASM GLAPI_ASM_SOURCES = $(X86_64_API) +else +GLAPI_ASM_SOURCES = $(X86_API) +endif endif if HAVE_SPARC_ASM GLAPI_ASM_SOURCES = $(SPARC_API) diff --git a/mesalib/src/mapi/glapi/gen/ARB_vertex_attrib_binding.xml b/mesalib/src/mapi/glapi/gen/ARB_vertex_attrib_binding.xml new file mode 100644 index 000000000..0ee6a3c00 --- /dev/null +++ b/mesalib/src/mapi/glapi/gen/ARB_vertex_attrib_binding.xml @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/mesalib/src/mapi/glapi/gen/Makefile.am b/mesalib/src/mapi/glapi/gen/Makefile.am index cbbf659dd..476d943dd 100644 --- a/mesalib/src/mapi/glapi/gen/Makefile.am +++ b/mesalib/src/mapi/glapi/gen/Makefile.am @@ -32,11 +32,11 @@ MESA_GLAPI_OUTPUTS = \ MESA_GLAPI_ASM_OUTPUTS = if HAVE_X86_ASM -MESA_GLAPI_ASM_OUTPUTS += $(MESA_GLAPI_DIR)/glapi_x86.S -endif - if HAVE_X86_64_ASM MESA_GLAPI_ASM_OUTPUTS += $(MESA_GLAPI_DIR)/glapi_x86-64.S +else +MESA_GLAPI_ASM_OUTPUTS += $(MESA_GLAPI_DIR)/glapi_x86.S +endif endif if HAVE_SPARC_ASM @@ -125,6 +125,7 @@ API_XML = \ ARB_texture_storage_multisample.xml \ ARB_texture_storage.xml \ ARB_vertex_array_object.xml \ + ARB_vertex_attrib_binding.xml \ AMD_draw_buffers_blend.xml \ AMD_performance_monitor.xml \ ARB_vertex_type_2_10_10_10_rev.xml \ diff --git a/mesalib/src/mapi/glapi/gen/gl_API.xml b/mesalib/src/mapi/glapi/gen/gl_API.xml index 69014c5d2..a2d914ac4 100644 --- a/mesalib/src/mapi/glapi/gen/gl_API.xml +++ b/mesalib/src/mapi/glapi/gen/gl_API.xml @@ -8458,7 +8458,11 @@ - + + + + + diff --git a/mesalib/src/mesa/.gitignore b/mesalib/src/mesa/.gitignore new file mode 100644 index 000000000..ca3130d9f --- /dev/null +++ b/mesalib/src/mesa/.gitignore @@ -0,0 +1,2 @@ +gen_matypes +matypes.h diff --git a/mesalib/src/mesa/Makefile.am b/mesalib/src/mesa/Makefile.am index a54b8ac1b..a60600e03 100644 --- a/mesalib/src/mesa/Makefile.am +++ b/mesalib/src/mesa/Makefile.am @@ -19,7 +19,7 @@ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. -SUBDIRS = x86 x86-64 . main/tests +SUBDIRS = . main/tests if HAVE_X11_DRIVER SUBDIRS += drivers/x11 @@ -81,7 +81,7 @@ main/get_hash.h: $(GLAPI)/gl_and_es_API.xml main/get_hash_params.py \ -f $< > $@.tmp; \ mv $@.tmp $@; -noinst_LTLIBRARIES = +noinst_LTLIBRARIES = $(ARCH_LIBS) if NEED_LIBMESA noinst_LTLIBRARIES += libmesa.la else @@ -98,12 +98,20 @@ AM_CXXFLAGS = $(LLVM_CFLAGS) $(VISIBILITY_CXXFLAGS) MESA_ASM_FILES_FOR_ARCH = if HAVE_X86_ASM -MESA_ASM_FILES_FOR_ARCH += $(X86_FILES) -AM_CPPFLAGS += -I$(builddir)/x86 -I$(srcdir)/x86 -endif +noinst_PROGRAMS = gen_matypes + +gen_matypes_SOURCES = x86/gen_matypes.c +BUILT_SOURCES += matypes.h + +ARCH_LIBS = libmesa_sse41.la + if HAVE_X86_64_ASM MESA_ASM_FILES_FOR_ARCH += $(X86_64_FILES) AM_CPPFLAGS += -I$(builddir)/x86-64 -I$(srcdir)/x86-64 +else +MESA_ASM_FILES_FOR_ARCH += $(X86_FILES) +AM_CPPFLAGS += -I$(builddir)/x86 -I$(srcdir)/x86 +endif endif if HAVE_SPARC_ASM MESA_ASM_FILES_FOR_ARCH += $(SPARC_FILES) @@ -117,6 +125,7 @@ libmesa_la_SOURCES = \ libmesa_la_LIBADD = \ $(top_builddir)/src/glsl/libglsl.la \ + $(ARCH_LIBS) \ $() libmesagallium_la_SOURCES = \ @@ -126,8 +135,13 @@ libmesagallium_la_SOURCES = \ libmesagallium_la_LIBADD = \ $(top_builddir)/src/glsl/libglsl.la \ + $(ARCH_LIBS) \ $() +libmesa_sse41_la_SOURCES = \ + main/streaming-load-memcpy.c +libmesa_sse41_la_CFLAGS = $(AM_CFLAGS) -msse4.1 + pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = gl.pc @@ -139,6 +153,15 @@ $(BUILDDIR)program/program_parse.tab.c $(BUILDDIR)program/program_parse.tab.h: p $(MKDIR_P) $(builddir)/program $(AM_V_GEN) $(YACC) -p "_mesa_program_" -v -d --output=$(BUILDDIR)program/program_parse.tab.c $< +if GEN_ASM_OFFSETS +matypes.h: $(gen_matypes_SOURCES) + $(AM_V_GEN)$(COMPILE) $< -DASM_OFFSETS -S -o - | \ + sed -n '/^->/{s:^->::;/[$$]/{s:^:#define :;s:[$$]::};p}' > $@ +else +matypes.h: gen_matypes + $(AM_V_GEN)./gen_matypes > $@ +endif + # Emacs tags tags: etags `find . -name \*.[ch]` $(top_srcdir)/include/GL/*.h diff --git a/mesalib/src/mesa/drivers/dri/common/dri_util.c b/mesalib/src/mesa/drivers/dri/common/dri_util.c index c28b0fc41..86cf24cb8 100644 --- a/mesalib/src/mesa/drivers/dri/common/dri_util.c +++ b/mesalib/src/mesa/drivers/dri/common/dri_util.c @@ -78,6 +78,8 @@ setupLoaderExtensions(__DRIscreen *psp, psp->dri2.useInvalidate = (__DRIuseInvalidateExtension *) extensions[i]; if (strcmp(extensions[i]->name, __DRI_SWRAST_LOADER) == 0) psp->swrast_loader = (__DRIswrastLoaderExtension *) extensions[i]; + if (strcmp(extensions[i]->name, __DRI_IMAGE_LOADER) == 0) + psp->image.loader = (__DRIimageLoaderExtension *) extensions[i]; } } @@ -106,10 +108,10 @@ const struct __DriverAPIRec *globalDriverAPI = &driDriverAPI; * Display. */ static __DRIscreen * -dri2CreateNewScreen2(int scrn, int fd, - const __DRIextension **extensions, - const __DRIextension **driver_extensions, - const __DRIconfig ***driver_configs, void *data) +driCreateNewScreen2(int scrn, int fd, + const __DRIextension **extensions, + const __DRIextension **driver_extensions, + const __DRIconfig ***driver_configs, void *data) { static const __DRIextension *emptyExtensionList[] = { NULL }; __DRIscreen *psp; @@ -190,7 +192,7 @@ dri2CreateNewScreen(int scrn, int fd, const __DRIextension **extensions, const __DRIconfig ***driver_configs, void *data) { - return dri2CreateNewScreen2(scrn, fd, extensions, NULL, + return driCreateNewScreen2(scrn, fd, extensions, NULL, driver_configs, data); } @@ -199,7 +201,7 @@ static __DRIscreen * driSWRastCreateNewScreen(int scrn, const __DRIextension **extensions, const __DRIconfig ***driver_configs, void *data) { - return dri2CreateNewScreen2(scrn, -1, extensions, NULL, + return driCreateNewScreen2(scrn, -1, extensions, NULL, driver_configs, data); } @@ -208,7 +210,7 @@ driSWRastCreateNewScreen2(int scrn, const __DRIextension **extensions, const __DRIextension **driver_extensions, const __DRIconfig ***driver_configs, void *data) { - return dri2CreateNewScreen2(scrn, -1, extensions, driver_extensions, + return driCreateNewScreen2(scrn, -1, extensions, driver_extensions, driver_configs, data); } @@ -291,13 +293,13 @@ validate_context_version(__DRIscreen *screen, /*@{*/ static __DRIcontext * -dri2CreateContextAttribs(__DRIscreen *screen, int api, - const __DRIconfig *config, - __DRIcontext *shared, - unsigned num_attribs, - const uint32_t *attribs, - unsigned *error, - void *data) +driCreateContextAttribs(__DRIscreen *screen, int api, + const __DRIconfig *config, + __DRIcontext *shared, + unsigned num_attribs, + const uint32_t *attribs, + unsigned *error, + void *data) { __DRIcontext *context; const struct gl_config *modes = (config != NULL) ? &config->modes : NULL; @@ -306,6 +308,7 @@ dri2CreateContextAttribs(__DRIscreen *screen, int api, unsigned major_version = 1; unsigned minor_version = 0; uint32_t flags = 0; + bool notify_reset = false; assert((num_attribs == 0) || (attribs != NULL)); @@ -344,6 +347,10 @@ dri2CreateContextAttribs(__DRIscreen *screen, int api, case __DRI_CTX_ATTRIB_FLAGS: flags = attribs[i * 2 + 1]; break; + case __DRI_CTX_ATTRIB_RESET_STRATEGY: + notify_reset = (attribs[i * 2 + 1] + != __DRI_CTX_RESET_NO_NOTIFICATION); + break; default: /* We can't create a context that satisfies the requirements of an * attribute that we don't understand. Return failure. @@ -424,7 +431,7 @@ dri2CreateContextAttribs(__DRIscreen *screen, int api, if (!screen->driver->CreateContext(mesa_api, modes, context, major_version, minor_version, - flags, error, shareCtx) ) { + flags, notify_reset, error, shareCtx)) { free(context); return NULL; } @@ -442,22 +449,22 @@ dri2CreateContextAttribs(__DRIscreen *screen, int api, } static __DRIcontext * -dri2CreateNewContextForAPI(__DRIscreen *screen, int api, - const __DRIconfig *config, - __DRIcontext *shared, void *data) +driCreateNewContextForAPI(__DRIscreen *screen, int api, + const __DRIconfig *config, + __DRIcontext *shared, void *data) { unsigned error; - return dri2CreateContextAttribs(screen, api, config, shared, 0, NULL, - &error, data); + return driCreateContextAttribs(screen, api, config, shared, 0, NULL, + &error, data); } static __DRIcontext * -dri2CreateNewContext(__DRIscreen *screen, const __DRIconfig *config, - __DRIcontext *shared, void *data) +driCreateNewContext(__DRIscreen *screen, const __DRIconfig *config, + __DRIcontext *shared, void *data) { - return dri2CreateNewContextForAPI(screen, __DRI_API_OPENGL, - config, shared, data); + return driCreateNewContextForAPI(screen, __DRI_API_OPENGL, + config, shared, data); } /** @@ -609,9 +616,9 @@ static void dri_put_drawable(__DRIdrawable *pdp) } static __DRIdrawable * -dri2CreateNewDrawable(__DRIscreen *screen, - const __DRIconfig *config, - void *data) +driCreateNewDrawable(__DRIscreen *screen, + const __DRIconfig *config, + void *data) { __DRIdrawable *pdraw; @@ -698,7 +705,7 @@ dri2ConfigQueryf(__DRIscreen *screen, const char *var, GLfloat *val) } static unsigned int -dri2GetAPIMask(__DRIscreen *screen) +driGetAPIMask(__DRIscreen *screen) { return screen->api_mask; } @@ -729,7 +736,7 @@ const __DRIcoreExtension driCoreExtension = { .createNewDrawable = NULL, .destroyDrawable = driDestroyDrawable, .swapBuffers = driSwapBuffers, /* swrast */ - .createNewContext = dri2CreateNewContext, /* swrast */ + .createNewContext = driCreateNewContext, /* swrast */ .copyContext = driCopyContext, .destroyContext = driDestroyContext, .bindContext = driBindContext, @@ -741,22 +748,22 @@ const __DRIdri2Extension driDRI2Extension = { .base = { __DRI_DRI2, 4 }, .createNewScreen = dri2CreateNewScreen, - .createNewDrawable = dri2CreateNewDrawable, - .createNewContext = dri2CreateNewContext, - .getAPIMask = dri2GetAPIMask, - .createNewContextForAPI = dri2CreateNewContextForAPI, + .createNewDrawable = driCreateNewDrawable, + .createNewContext = driCreateNewContext, + .getAPIMask = driGetAPIMask, + .createNewContextForAPI = driCreateNewContextForAPI, .allocateBuffer = dri2AllocateBuffer, .releaseBuffer = dri2ReleaseBuffer, - .createContextAttribs = dri2CreateContextAttribs, - .createNewScreen2 = dri2CreateNewScreen2, + .createContextAttribs = driCreateContextAttribs, + .createNewScreen2 = driCreateNewScreen2, }; const __DRIswrastExtension driSWRastExtension = { { __DRI_SWRAST, 4 }, driSWRastCreateNewScreen, - dri2CreateNewDrawable, - dri2CreateNewContextForAPI, - dri2CreateContextAttribs, + driCreateNewDrawable, + driCreateNewContextForAPI, + driCreateContextAttribs, driSWRastCreateNewScreen2, }; @@ -792,3 +799,76 @@ driUpdateFramebufferSize(struct gl_context *ctx, const __DRIdrawable *dPriv) assert(fb->Height == dPriv->h); } } + +uint32_t +driGLFormatToImageFormat(gl_format format) +{ + switch (format) { + case MESA_FORMAT_RGB565: + return __DRI_IMAGE_FORMAT_RGB565; + case MESA_FORMAT_XRGB8888: + return __DRI_IMAGE_FORMAT_XRGB8888; + case MESA_FORMAT_ARGB2101010: + return __DRI_IMAGE_FORMAT_ARGB2101010; + case MESA_FORMAT_XRGB2101010_UNORM: + return __DRI_IMAGE_FORMAT_XRGB2101010; + case MESA_FORMAT_ARGB8888: + return __DRI_IMAGE_FORMAT_ARGB8888; + case MESA_FORMAT_RGBA8888_REV: + return __DRI_IMAGE_FORMAT_ABGR8888; + case MESA_FORMAT_RGBX8888_REV: + return __DRI_IMAGE_FORMAT_XBGR8888; + case MESA_FORMAT_R8: + return __DRI_IMAGE_FORMAT_R8; + case MESA_FORMAT_GR88: + return __DRI_IMAGE_FORMAT_GR88; + case MESA_FORMAT_NONE: + return __DRI_IMAGE_FORMAT_NONE; + case MESA_FORMAT_SARGB8: + return __DRI_IMAGE_FORMAT_SARGB8; + default: + return 0; + } +} + +gl_format +driImageFormatToGLFormat(uint32_t image_format) +{ + switch (image_format) { + case __DRI_IMAGE_FORMAT_RGB565: + return MESA_FORMAT_RGB565; + case __DRI_IMAGE_FORMAT_XRGB8888: + return MESA_FORMAT_XRGB8888; + case __DRI_IMAGE_FORMAT_ARGB2101010: + return MESA_FORMAT_ARGB2101010; + case __DRI_IMAGE_FORMAT_XRGB2101010: + return MESA_FORMAT_XRGB2101010_UNORM; + case __DRI_IMAGE_FORMAT_ARGB8888: + return MESA_FORMAT_ARGB8888; + case __DRI_IMAGE_FORMAT_ABGR8888: + return MESA_FORMAT_RGBA8888_REV; + case __DRI_IMAGE_FORMAT_XBGR8888: + return MESA_FORMAT_RGBX8888_REV; + case __DRI_IMAGE_FORMAT_R8: + return MESA_FORMAT_R8; + case __DRI_IMAGE_FORMAT_GR88: + return MESA_FORMAT_GR88; + case __DRI_IMAGE_FORMAT_SARGB8: + return MESA_FORMAT_SARGB8; + case __DRI_IMAGE_FORMAT_NONE: + return MESA_FORMAT_NONE; + default: + return MESA_FORMAT_NONE; + } +} + +/** Image driver interface */ +const __DRIimageDriverExtension driImageDriverExtension = { + .base = { __DRI_IMAGE_DRIVER, __DRI_IMAGE_DRIVER_VERSION }, + + .createNewScreen2 = driCreateNewScreen2, + .createNewDrawable = driCreateNewDrawable, + .createNewContext = driCreateNewContext, + .getAPIMask = driGetAPIMask, + .createContextAttribs = driCreateContextAttribs, +}; diff --git a/mesalib/src/mesa/drivers/dri/common/dri_util.h b/mesalib/src/mesa/drivers/dri/common/dri_util.h index 5b56061e2..79a8564ad 100644 --- a/mesalib/src/mesa/drivers/dri/common/dri_util.h +++ b/mesalib/src/mesa/drivers/dri/common/dri_util.h @@ -57,6 +57,7 @@ #include #include "main/mtypes.h" #include "xmlconfig.h" +#include /** * Extensions. @@ -87,6 +88,7 @@ struct __DriverAPIRec { unsigned major_version, unsigned minor_version, uint32_t flags, + bool notify_reset, unsigned *error, void *sharedContextPrivate); @@ -174,6 +176,10 @@ struct __DRIscreenRec { __DRIuseInvalidateExtension *useInvalidate; } dri2; + struct { + __DRIimageLoaderExtension *loader; + } image; + driOptionCache optionInfo; driOptionCache optionCache; @@ -271,10 +277,18 @@ struct __DRIdrawableRec { } dri2; }; +extern uint32_t +driGLFormatToImageFormat(gl_format format); + +extern gl_format +driImageFormatToGLFormat(uint32_t image_format); + extern void dri2InvalidateDrawable(__DRIdrawable *drawable); extern void driUpdateFramebufferSize(struct gl_context *ctx, const __DRIdrawable *dPriv); +extern const __DRIimageDriverExtension driImageDriverExtension; + #endif /* _DRI_UTIL_H_ */ diff --git a/mesalib/src/mesa/drivers/dri/common/utils.c b/mesalib/src/mesa/drivers/dri/common/utils.c index f3780d9b6..b30fca903 100644 --- a/mesalib/src/mesa/drivers/dri/common/utils.c +++ b/mesalib/src/mesa/drivers/dri/common/utils.c @@ -37,6 +37,7 @@ #include "main/cpuinfo.h" #include "main/extensions.h" #include "utils.h" +#include "dri_util.h" unsigned @@ -477,3 +478,66 @@ driIndexConfigAttrib(const __DRIconfig *config, int index, return GL_FALSE; } + +/** + * Implement queries for values that are common across all Mesa drivers + * + * Currently only the following queries are supported by this function: + * + * - \c __DRI2_RENDERER_VERSION + * - \c __DRI2_RENDERER_OPENGL_CORE_PROFILE_VERSION + * - \c __DRI2_RENDERER_OPENGL_COMPATIBLITY_PROFILE_VERSION + * - \c __DRI2_RENDERER_ES_PROFILE_VERSION + * - \c __DRI2_RENDERER_ES2_PROFILE_VERSION + * + * \returns + * Zero if a recognized value of \c param is supplied, -1 otherwise. + */ +int +driQueryRendererIntegerCommon(__DRIscreen *psp, int param, int *value) +{ + switch (param) { + case __DRI2_RENDERER_VERSION: { + static const char *const ver = PACKAGE_VERSION; + char *endptr; + int v[3]; + + v[0] = strtol(ver, &endptr, 10); + assert(endptr[0] == '.'); + if (endptr[0] != '.') + return -1; + + v[1] = strtol(endptr + 1, &endptr, 10); + assert(endptr[0] == '.'); + if (endptr[0] != '.') + return -1; + + v[2] = strtol(endptr + 1, &endptr, 10); + + value[0] = v[0]; + value[1] = v[1]; + value[2] = v[2]; + return 0; + } + case __DRI2_RENDERER_OPENGL_CORE_PROFILE_VERSION: + value[0] = psp->max_gl_core_version / 10; + value[1] = psp->max_gl_core_version % 10; + return 0; + case __DRI2_RENDERER_OPENGL_COMPATIBILITY_PROFILE_VERSION: + value[0] = psp->max_gl_compat_version / 10; + value[1] = psp->max_gl_compat_version % 10; + return 0; + case __DRI2_RENDERER_OPENGL_ES_PROFILE_VERSION: + value[0] = psp->max_gl_es1_version / 10; + value[1] = psp->max_gl_es1_version % 10; + return 0; + case __DRI2_RENDERER_OPENGL_ES2_PROFILE_VERSION: + value[0] = psp->max_gl_es2_version / 10; + value[1] = psp->max_gl_es2_version % 10; + return 0; + default: + break; + } + + return -1; +} diff --git a/mesalib/src/mesa/drivers/dri/common/utils.h b/mesalib/src/mesa/drivers/dri/common/utils.h index e3b3940da..5d6ef879e 100644 --- a/mesalib/src/mesa/drivers/dri/common/utils.h +++ b/mesalib/src/mesa/drivers/dri/common/utils.h @@ -65,4 +65,7 @@ int driIndexConfigAttrib(const __DRIconfig *config, int index, unsigned int *attrib, unsigned int *value); +int +driQueryRendererIntegerCommon(__DRIscreen *psp, int param, int *value); + #endif /* DRI_DEBUG_H */ diff --git a/mesalib/src/mesa/main/api_arrayelt.c b/mesalib/src/mesa/main/api_arrayelt.c index ea0923837..6822465e8 100644 --- a/mesalib/src/mesa/main/api_arrayelt.c +++ b/mesalib/src/mesa/main/api_arrayelt.c @@ -35,6 +35,7 @@ */ #include "glheader.h" +#include "arrayobj.h" #include "api_arrayelt.h" #include "bufferobj.h" #include "context.h" @@ -1485,46 +1486,52 @@ _ae_update_state(struct gl_context *ctx) actx->nr_vbos = 0; + if (arrayObj->NewArrays) { + /* update the derived client arrays */ + _mesa_update_array_object_client_arrays(ctx, arrayObj); + arrayObj->NewArrays = 0; + } + /* conventional vertex arrays */ - if (arrayObj->VertexAttrib[VERT_ATTRIB_COLOR_INDEX].Enabled) { - aa->array = &arrayObj->VertexAttrib[VERT_ATTRIB_COLOR_INDEX]; + if (arrayObj->_VertexAttrib[VERT_ATTRIB_COLOR_INDEX].Enabled) { + aa->array = &arrayObj->_VertexAttrib[VERT_ATTRIB_COLOR_INDEX]; aa->offset = IndexFuncs[TYPE_IDX(aa->array->Type)]; check_vbo(actx, aa->array->BufferObj); aa++; } - if (arrayObj->VertexAttrib[VERT_ATTRIB_EDGEFLAG].Enabled) { - aa->array = &arrayObj->VertexAttrib[VERT_ATTRIB_EDGEFLAG]; + if (arrayObj->_VertexAttrib[VERT_ATTRIB_EDGEFLAG].Enabled) { + aa->array = &arrayObj->_VertexAttrib[VERT_ATTRIB_EDGEFLAG]; aa->offset = _gloffset_EdgeFlagv; check_vbo(actx, aa->array->BufferObj); aa++; } - if (arrayObj->VertexAttrib[VERT_ATTRIB_NORMAL].Enabled) { - aa->array = &arrayObj->VertexAttrib[VERT_ATTRIB_NORMAL]; + if (arrayObj->_VertexAttrib[VERT_ATTRIB_NORMAL].Enabled) { + aa->array = &arrayObj->_VertexAttrib[VERT_ATTRIB_NORMAL]; aa->offset = NormalFuncs[TYPE_IDX(aa->array->Type)]; check_vbo(actx, aa->array->BufferObj); aa++; } - if (arrayObj->VertexAttrib[VERT_ATTRIB_COLOR0].Enabled) { - aa->array = &arrayObj->VertexAttrib[VERT_ATTRIB_COLOR0]; + if (arrayObj->_VertexAttrib[VERT_ATTRIB_COLOR0].Enabled) { + aa->array = &arrayObj->_VertexAttrib[VERT_ATTRIB_COLOR0]; aa->offset = ColorFuncs[aa->array->Size-3][TYPE_IDX(aa->array->Type)]; check_vbo(actx, aa->array->BufferObj); aa++; } - if (arrayObj->VertexAttrib[VERT_ATTRIB_COLOR1].Enabled) { - aa->array = &arrayObj->VertexAttrib[VERT_ATTRIB_COLOR1]; + if (arrayObj->_VertexAttrib[VERT_ATTRIB_COLOR1].Enabled) { + aa->array = &arrayObj->_VertexAttrib[VERT_ATTRIB_COLOR1]; aa->offset = SecondaryColorFuncs[TYPE_IDX(aa->array->Type)]; check_vbo(actx, aa->array->BufferObj); aa++; } - if (arrayObj->VertexAttrib[VERT_ATTRIB_FOG].Enabled) { - aa->array = &arrayObj->VertexAttrib[VERT_ATTRIB_FOG]; + if (arrayObj->_VertexAttrib[VERT_ATTRIB_FOG].Enabled) { + aa->array = &arrayObj->_VertexAttrib[VERT_ATTRIB_FOG]; aa->offset = FogCoordFuncs[TYPE_IDX(aa->array->Type)]; check_vbo(actx, aa->array->BufferObj); aa++; } for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) { struct gl_client_array *attribArray = - &arrayObj->VertexAttrib[VERT_ATTRIB_TEX(i)]; + &arrayObj->_VertexAttrib[VERT_ATTRIB_TEX(i)]; if (attribArray->Enabled) { /* NOTE: we use generic glVertexAttribNV functions here. * If we ever remove GL_NV_vertex_program this will have to change. @@ -1543,7 +1550,7 @@ _ae_update_state(struct gl_context *ctx) /* generic vertex attribute arrays */ for (i = 1; i < VERT_ATTRIB_GENERIC_MAX; i++) { /* skip zero! */ struct gl_client_array *attribArray = - &arrayObj->VertexAttrib[VERT_ATTRIB_GENERIC(i)]; + &arrayObj->_VertexAttrib[VERT_ATTRIB_GENERIC(i)]; if (attribArray->Enabled) { GLint intOrNorm; at->array = attribArray; @@ -1570,18 +1577,18 @@ _ae_update_state(struct gl_context *ctx) } /* finally, vertex position */ - if (arrayObj->VertexAttrib[VERT_ATTRIB_GENERIC0].Enabled) { + if (arrayObj->_VertexAttrib[VERT_ATTRIB_GENERIC0].Enabled) { /* Use glVertex(v) instead of glVertexAttrib(0, v) to be sure it's * issued as the last (provoking) attribute). */ - aa->array = &arrayObj->VertexAttrib[VERT_ATTRIB_GENERIC0]; + aa->array = &arrayObj->_VertexAttrib[VERT_ATTRIB_GENERIC0]; assert(aa->array->Size >= 2); /* XXX fix someday? */ aa->offset = VertexFuncs[aa->array->Size-2][TYPE_IDX(aa->array->Type)]; check_vbo(actx, aa->array->BufferObj); aa++; } - else if (arrayObj->VertexAttrib[VERT_ATTRIB_POS].Enabled) { - aa->array = &arrayObj->VertexAttrib[VERT_ATTRIB_POS]; + else if (arrayObj->_VertexAttrib[VERT_ATTRIB_POS].Enabled) { + aa->array = &arrayObj->_VertexAttrib[VERT_ATTRIB_POS]; aa->offset = VertexFuncs[aa->array->Size-2][TYPE_IDX(aa->array->Type)]; check_vbo(actx, aa->array->BufferObj); aa++; diff --git a/mesalib/src/mesa/main/arrayobj.c b/mesalib/src/mesa/main/arrayobj.c index 5d50d29f8..dbf8fdc73 100644 --- a/mesalib/src/mesa/main/arrayobj.c +++ b/mesalib/src/mesa/main/arrayobj.c @@ -72,7 +72,7 @@ _mesa_lookup_arrayobj(struct gl_context *ctx, GLuint id) /** - * For all the vertex arrays in the array object, unbind any pointers + * For all the vertex binding points in the array object, unbind any pointers * to any buffer objects (VBOs). * This is done just prior to array object destruction. */ @@ -81,8 +81,11 @@ unbind_array_object_vbos(struct gl_context *ctx, struct gl_array_object *obj) { GLuint i; - for (i = 0; i < Elements(obj->VertexAttrib); i++) - _mesa_reference_buffer_object(ctx, &obj->VertexAttrib[i].BufferObj, NULL); + for (i = 0; i < Elements(obj->VertexBinding); i++) + _mesa_reference_buffer_object(ctx, &obj->VertexBinding[i].BufferObj, NULL); + + for (i = 0; i < Elements(obj->_VertexAttrib); i++) + _mesa_reference_buffer_object(ctx, &obj->_VertexAttrib[i].BufferObj, NULL); } @@ -181,20 +184,30 @@ _mesa_reference_array_object_(struct gl_context *ctx, static void init_array(struct gl_context *ctx, - struct gl_client_array *array, GLint size, GLint type) + struct gl_array_object *obj, GLuint index, GLint size, GLint type) { + struct gl_vertex_attrib_array *array = &obj->VertexAttrib[index]; + struct gl_vertex_buffer_binding *binding = &obj->VertexBinding[index]; + array->Size = size; array->Type = type; array->Format = GL_RGBA; /* only significant for GL_EXT_vertex_array_bgra */ array->Stride = 0; - array->StrideB = 0; array->Ptr = NULL; + array->RelativeOffset = 0; array->Enabled = GL_FALSE; array->Normalized = GL_FALSE; array->Integer = GL_FALSE; array->_ElementSize = size * _mesa_sizeof_type(type); + array->VertexBinding = index; + + binding->Offset = 0; + binding->Stride = array->_ElementSize; + binding->BufferObj = NULL; + binding->_BoundArrays = BITFIELD64_BIT(index); + /* Vertex array buffers */ - _mesa_reference_buffer_object(ctx, &array->BufferObj, + _mesa_reference_buffer_object(ctx, &binding->BufferObj, ctx->Shared->NullBufferObj); } @@ -215,31 +228,31 @@ _mesa_initialize_array_object( struct gl_context *ctx, obj->RefCount = 1; /* Init the individual arrays */ - for (i = 0; i < Elements(obj->VertexAttrib); i++) { + for (i = 0; i < Elements(obj->_VertexAttrib); i++) { switch (i) { case VERT_ATTRIB_WEIGHT: - init_array(ctx, &obj->VertexAttrib[VERT_ATTRIB_WEIGHT], 1, GL_FLOAT); + init_array(ctx, obj, VERT_ATTRIB_WEIGHT, 1, GL_FLOAT); break; case VERT_ATTRIB_NORMAL: - init_array(ctx, &obj->VertexAttrib[VERT_ATTRIB_NORMAL], 3, GL_FLOAT); + init_array(ctx, obj, VERT_ATTRIB_NORMAL, 3, GL_FLOAT); break; case VERT_ATTRIB_COLOR1: - init_array(ctx, &obj->VertexAttrib[VERT_ATTRIB_COLOR1], 3, GL_FLOAT); + init_array(ctx, obj, VERT_ATTRIB_COLOR1, 3, GL_FLOAT); break; case VERT_ATTRIB_FOG: - init_array(ctx, &obj->VertexAttrib[VERT_ATTRIB_FOG], 1, GL_FLOAT); + init_array(ctx, obj, VERT_ATTRIB_FOG, 1, GL_FLOAT); break; case VERT_ATTRIB_COLOR_INDEX: - init_array(ctx, &obj->VertexAttrib[VERT_ATTRIB_COLOR_INDEX], 1, GL_FLOAT); + init_array(ctx, obj, VERT_ATTRIB_COLOR_INDEX, 1, GL_FLOAT); break; case VERT_ATTRIB_EDGEFLAG: - init_array(ctx, &obj->VertexAttrib[VERT_ATTRIB_EDGEFLAG], 1, GL_BOOL); + init_array(ctx, obj, VERT_ATTRIB_EDGEFLAG, 1, GL_BOOL); break; case VERT_ATTRIB_POINT_SIZE: - init_array(ctx, &obj->VertexAttrib[VERT_ATTRIB_POINT_SIZE], 1, GL_FLOAT); + init_array(ctx, obj, VERT_ATTRIB_POINT_SIZE, 1, GL_FLOAT); break; default: - init_array(ctx, &obj->VertexAttrib[i], 4, GL_FLOAT); + init_array(ctx, obj, i, 4, GL_FLOAT); break; } } @@ -279,7 +292,7 @@ remove_array_object( struct gl_context *ctx, struct gl_array_object *obj ) /** * Helper for _mesa_update_array_object_max_element(). - * \return min(arrayObj->VertexAttrib[*]._MaxElement). + * \return min(arrayObj->_VertexAttrib[*]._MaxElement). */ static GLuint compute_max_element(struct gl_array_object *arrayObj, GLbitfield64 enabled) @@ -291,7 +304,7 @@ compute_max_element(struct gl_array_object *arrayObj, GLbitfield64 enabled) GLint attrib = ffsll(enabled) - 1; enabled ^= BITFIELD64_BIT(attrib); - client_array = &arrayObj->VertexAttrib[attrib]; + client_array = &arrayObj->_VertexAttrib[attrib]; assert(client_array->Enabled); _mesa_update_array_max_element(client_array); min = MIN2(min, client_array->_MaxElement); @@ -322,6 +335,32 @@ _mesa_update_array_object_max_element(struct gl_context *ctx, } +/** + * Updates the derived gl_client_arrays when a gl_vertex_attrib_array + * or a gl_vertex_buffer_binding has changed. + */ +void +_mesa_update_array_object_client_arrays(struct gl_context *ctx, struct gl_array_object *arrayObj) +{ + GLbitfield64 arrays = arrayObj->NewArrays; + + while (arrays) { + struct gl_client_array *client_array; + struct gl_vertex_attrib_array *attrib_array; + struct gl_vertex_buffer_binding *buffer_binding; + + GLint attrib = ffsll(arrays) - 1; + arrays ^= BITFIELD64_BIT(attrib); + + attrib_array = &arrayObj->VertexAttrib[attrib]; + buffer_binding = &arrayObj->VertexBinding[attrib_array->VertexBinding]; + client_array = &arrayObj->_VertexAttrib[attrib]; + + _mesa_update_client_array(ctx, client_array, attrib_array, buffer_binding); + } +} + + /**********************************************************************/ /* API Functions */ /**********************************************************************/ diff --git a/mesalib/src/mesa/main/arrayobj.h b/mesalib/src/mesa/main/arrayobj.h index 492ef3501..7c3720242 100644 --- a/mesalib/src/mesa/main/arrayobj.h +++ b/mesalib/src/mesa/main/arrayobj.h @@ -78,6 +78,11 @@ extern void _mesa_update_array_object_max_element(struct gl_context *ctx, struct gl_array_object *arrayObj); +extern void +_mesa_update_array_object_client_arrays(struct gl_context *ctx, + struct gl_array_object *arrayObj); + + /** Returns the bitmask of all enabled arrays in fixed function mode. * * In fixed function mode only the traditional fixed function arrays diff --git a/mesalib/src/mesa/main/attrib.c b/mesalib/src/mesa/main/attrib.c index ca617f744..c9332bd52 100644 --- a/mesalib/src/mesa/main/attrib.c +++ b/mesalib/src/mesa/main/attrib.c @@ -1369,8 +1369,11 @@ copy_array_object(struct gl_context *ctx, /* In theory must be the same anyway, but on recreate make sure it matches */ dest->ARBsemantics = src->ARBsemantics; - for (i = 0; i < Elements(src->VertexAttrib); i++) - _mesa_copy_client_array(ctx, &dest->VertexAttrib[i], &src->VertexAttrib[i]); + for (i = 0; i < Elements(src->_VertexAttrib); i++) { + _mesa_copy_client_array(ctx, &dest->_VertexAttrib[i], &src->_VertexAttrib[i]); + _mesa_copy_vertex_attrib_array(ctx, &dest->VertexAttrib[i], &src->VertexAttrib[i]); + _mesa_copy_vertex_buffer_binding(ctx, &dest->VertexBinding[i], &src->VertexBinding[i]); + } /* _Enabled must be the same than on push */ dest->_Enabled = src->_Enabled; diff --git a/mesalib/src/mesa/main/bufferobj.c b/mesalib/src/mesa/main/bufferobj.c index 1f5506157..b27f592e8 100644 --- a/mesalib/src/mesa/main/bufferobj.c +++ b/mesalib/src/mesa/main/bufferobj.c @@ -655,16 +655,17 @@ _mesa_free_buffer_objects( struct gl_context *ctx ) } } -static bool -handle_bind_buffer_gen(struct gl_context *ctx, - GLenum target, - GLuint buffer, - struct gl_buffer_object **buf_handle) +bool +_mesa_handle_bind_buffer_gen(struct gl_context *ctx, + GLenum target, + GLuint buffer, + struct gl_buffer_object **buf_handle, + const char *caller) { struct gl_buffer_object *buf = *buf_handle; if (!buf && ctx->API == API_OPENGL_CORE) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glBindBuffer(non-gen name)"); + _mesa_error(ctx, GL_INVALID_OPERATION, "%s(non-gen name)", caller); return false; } @@ -675,7 +676,7 @@ handle_bind_buffer_gen(struct gl_context *ctx, ASSERT(ctx->Driver.NewBufferObject); buf = ctx->Driver.NewBufferObject(ctx, buffer, target); if (!buf) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindBufferARB"); + _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", caller); return false; } _mesa_HashInsert(ctx->Shared->BufferObjects, buffer, buf); @@ -719,7 +720,8 @@ bind_buffer_object(struct gl_context *ctx, GLenum target, GLuint buffer) else { /* non-default buffer object */ newBufObj = _mesa_lookup_bufferobj(ctx, buffer); - if (!handle_bind_buffer_gen(ctx, target, buffer, &newBufObj)) + if (!_mesa_handle_bind_buffer_gen(ctx, target, buffer, + &newBufObj, "glBindBuffer")) return; } @@ -862,8 +864,8 @@ _mesa_DeleteBuffers(GLsizei n, const GLuint *ids) } /* unbind any vertex pointers bound to this buffer */ - for (j = 0; j < Elements(arrayObj->VertexAttrib); j++) { - unbind(ctx, &arrayObj->VertexAttrib[j].BufferObj, bufObj); + for (j = 0; j < Elements(arrayObj->VertexBinding); j++) { + unbind(ctx, &arrayObj->VertexBinding[j].BufferObj, bufObj); } if (ctx->Array.ArrayBufferObj == bufObj) { @@ -2181,7 +2183,8 @@ _mesa_BindBufferRange(GLenum target, GLuint index, } else { bufObj = _mesa_lookup_bufferobj(ctx, buffer); } - if (!handle_bind_buffer_gen(ctx, target, buffer, &bufObj)) + if (!_mesa_handle_bind_buffer_gen(ctx, target, buffer, + &bufObj, "glBindBufferRange")) return; if (!bufObj) { @@ -2227,7 +2230,8 @@ _mesa_BindBufferBase(GLenum target, GLuint index, GLuint buffer) } else { bufObj = _mesa_lookup_bufferobj(ctx, buffer); } - if (!handle_bind_buffer_gen(ctx, target, buffer, &bufObj)) + if (!_mesa_handle_bind_buffer_gen(ctx, target, buffer, + &bufObj, "glBindBufferBase")) return; if (!bufObj) { diff --git a/mesalib/src/mesa/main/bufferobj.h b/mesalib/src/mesa/main/bufferobj.h index 9b582f8c1..0b898a21b 100644 --- a/mesalib/src/mesa/main/bufferobj.h +++ b/mesalib/src/mesa/main/bufferobj.h @@ -28,7 +28,7 @@ #ifndef BUFFEROBJ_H #define BUFFEROBJ_H - +#include #include "mtypes.h" @@ -62,6 +62,13 @@ _mesa_init_buffer_objects( struct gl_context *ctx ); extern void _mesa_free_buffer_objects( struct gl_context *ctx ); +extern bool +_mesa_handle_bind_buffer_gen(struct gl_context *ctx, + GLenum target, + GLuint buffer, + struct gl_buffer_object **buf_handle, + const char *caller); + extern void _mesa_update_default_objects_buffer_objects(struct gl_context *ctx); diff --git a/mesalib/src/mesa/main/context.c b/mesalib/src/mesa/main/context.c index 6cdeed19b..d005d2370 100644 --- a/mesalib/src/mesa/main/context.c +++ b/mesalib/src/mesa/main/context.c @@ -678,6 +678,10 @@ _mesa_init_constants(struct gl_context *ctx) ctx->Const.MaxAtomicBufferSize = MAX_ATOMIC_COUNTERS * ATOMIC_COUNTER_SIZE; ctx->Const.MaxCombinedAtomicBuffers = MAX_COMBINED_ATOMIC_BUFFERS; ctx->Const.MaxCombinedAtomicCounters = MAX_ATOMIC_COUNTERS; + + /* GL_ARB_vertex_attrib_binding */ + ctx->Const.MaxVertexAttribRelativeOffset = 2047; + ctx->Const.MaxVertexAttribBindings = MAX_VERTEX_GENERIC_ATTRIBS; } @@ -804,7 +808,7 @@ init_attrib_groups(struct gl_context *ctx) ctx->NewState = _NEW_ALL; ctx->NewDriverState = ~0; ctx->ErrorValue = GL_NO_ERROR; - ctx->ResetStatus = GL_NO_ERROR; + ctx->ShareGroupReset = false; ctx->varying_vp_inputs = VERT_BIT_ALL; return GL_TRUE; diff --git a/mesalib/src/mesa/main/dd.h b/mesalib/src/mesa/main/dd.h index d7c432713..b5b874f47 100644 --- a/mesalib/src/mesa/main/dd.h +++ b/mesalib/src/mesa/main/dd.h @@ -890,6 +890,15 @@ struct dd_function_table { struct gl_texture_object *texObj, struct gl_texture_image *texImage, const GLvoid *vdpSurface, GLuint index); + + /** + * Query reset status for GL_ARB_robustness + * + * Per \c glGetGraphicsResetStatusARB, this function should return a + * non-zero value once after a reset. If a reset is non-atomic, the + * non-zero status should be returned for the duration of the reset. + */ + GLenum (*GetGraphicsResetStatus)(struct gl_context *ctx); }; diff --git a/mesalib/src/mesa/main/enable.c b/mesalib/src/mesa/main/enable.c index dd6a772f9..c047f5df2 100644 --- a/mesalib/src/mesa/main/enable.c +++ b/mesalib/src/mesa/main/enable.c @@ -135,6 +135,8 @@ client_state(struct gl_context *ctx, GLenum cap, GLboolean state) else arrayObj->_Enabled &= ~flag; + arrayObj->NewArrays |= flag; + if (ctx->Driver.Enable) { ctx->Driver.Enable( ctx, cap, state ); } diff --git a/mesalib/src/mesa/main/extensions.c b/mesalib/src/mesa/main/extensions.c index 48c4e9f1b..104618c23 100644 --- a/mesalib/src/mesa/main/extensions.c +++ b/mesalib/src/mesa/main/extensions.c @@ -165,9 +165,11 @@ static const struct extension extension_table[] = { { "GL_ARB_uniform_buffer_object", o(ARB_uniform_buffer_object), GL, 2009 }, { "GL_ARB_vertex_array_bgra", o(EXT_vertex_array_bgra), GL, 2008 }, { "GL_ARB_vertex_array_object", o(dummy_true), GL, 2006 }, + { "GL_ARB_vertex_attrib_binding", o(dummy_true), GL, 2012 }, { "GL_ARB_vertex_buffer_object", o(dummy_true), GLL, 2003 }, { "GL_ARB_vertex_program", o(ARB_vertex_program), GLL, 2002 }, { "GL_ARB_vertex_shader", o(ARB_vertex_shader), GL, 2002 }, + { "GL_ARB_vertex_type_10f_11f_11f_rev", o(ARB_vertex_type_10f_11f_11f_rev), GL, 2013 }, { "GL_ARB_vertex_type_2_10_10_10_rev", o(ARB_vertex_type_2_10_10_10_rev), GL, 2009 }, { "GL_ARB_window_pos", o(dummy_true), GLL, 2001 }, /* EXT extensions */ diff --git a/mesalib/src/mesa/main/get.c b/mesalib/src/mesa/main/get.c index 6a0de0c16..eee855007 100644 --- a/mesalib/src/mesa/main/get.c +++ b/mesalib/src/mesa/main/get.c @@ -550,7 +550,7 @@ static void find_custom_value(struct gl_context *ctx, const struct value_desc *d, union value *v) { struct gl_buffer_object **buffer_obj; - struct gl_client_array *array; + struct gl_vertex_attrib_array *array; GLuint unit, *p; switch (d->pname) { @@ -775,7 +775,7 @@ find_custom_value(struct gl_context *ctx, const struct value_desc *d, union valu break; case GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB: v->value_int = - ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_TEX(ctx->Array.ActiveTexture)].BufferObj->Name; + ctx->Array.ArrayObj->VertexBinding[VERT_ATTRIB_TEX(ctx->Array.ActiveTexture)].BufferObj->Name; break; case GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB: v->value_int = ctx->Array.ArrayObj->ElementArrayBufferObj->Name; @@ -819,7 +819,7 @@ find_custom_value(struct gl_context *ctx, const struct value_desc *d, union valu ctx->CurrentRenderbuffer ? ctx->CurrentRenderbuffer->Name : 0; break; case GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES: - v->value_int = ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_POINT_SIZE].BufferObj->Name; + v->value_int = ctx->Array.ArrayObj->VertexBinding[VERT_ATTRIB_POINT_SIZE].BufferObj->Name; break; case GL_FOG_COLOR: @@ -1740,6 +1740,30 @@ find_value_indexed(const char *func, GLenum pname, GLuint index, union value *v) goto invalid_value; v->value_int64 = ctx->AtomicBufferBindings[index].Size; return TYPE_INT64; + + case GL_VERTEX_BINDING_DIVISOR: + if (!_mesa_is_desktop_gl(ctx) || !ctx->Extensions.ARB_instanced_arrays) + goto invalid_enum; + if (index >= ctx->Const.VertexProgram.MaxAttribs) + goto invalid_value; + v->value_int = ctx->Array.ArrayObj->VertexBinding[VERT_ATTRIB_GENERIC(index)].InstanceDivisor; + return TYPE_INT; + + case GL_VERTEX_BINDING_OFFSET: + if (!_mesa_is_desktop_gl(ctx)) + goto invalid_enum; + if (index >= ctx->Const.VertexProgram.MaxAttribs) + goto invalid_value; + v->value_int = ctx->Array.ArrayObj->VertexBinding[VERT_ATTRIB_GENERIC(index)].Offset; + return TYPE_INT; + + case GL_VERTEX_BINDING_STRIDE: + if (!_mesa_is_desktop_gl(ctx)) + goto invalid_enum; + if (index >= ctx->Const.VertexProgram.MaxAttribs) + goto invalid_value; + v->value_int = ctx->Array.ArrayObj->VertexBinding[VERT_ATTRIB_GENERIC(index)].Stride; + return TYPE_INT; } invalid_enum: diff --git a/mesalib/src/mesa/main/get_hash_params.py b/mesalib/src/mesa/main/get_hash_params.py index 0851b7b70..c961feeee 100644 --- a/mesalib/src/mesa/main/get_hash_params.py +++ b/mesalib/src/mesa/main/get_hash_params.py @@ -221,9 +221,9 @@ descriptor=[ [ "SAMPLE_ALPHA_TO_ONE_ARB", "CONTEXT_BOOL(Multisample.SampleAlphaToOne), NO_EXTRA" ], # GL_ARB_vertex_buffer_object - [ "VERTEX_ARRAY_BUFFER_BINDING_ARB", "LOC_CUSTOM, TYPE_INT, offsetof(struct gl_array_object, VertexAttrib[VERT_ATTRIB_POS].BufferObj), NO_EXTRA" ], - [ "NORMAL_ARRAY_BUFFER_BINDING_ARB", "LOC_CUSTOM, TYPE_INT, offsetof(struct gl_array_object, VertexAttrib[VERT_ATTRIB_NORMAL].BufferObj), NO_EXTRA" ], - [ "COLOR_ARRAY_BUFFER_BINDING_ARB", "LOC_CUSTOM, TYPE_INT, offsetof(struct gl_array_object, VertexAttrib[VERT_ATTRIB_COLOR0].BufferObj), NO_EXTRA" ], + [ "VERTEX_ARRAY_BUFFER_BINDING_ARB", "LOC_CUSTOM, TYPE_INT, offsetof(struct gl_array_object, VertexBinding[VERT_ATTRIB_POS].BufferObj), NO_EXTRA" ], + [ "NORMAL_ARRAY_BUFFER_BINDING_ARB", "LOC_CUSTOM, TYPE_INT, offsetof(struct gl_array_object, VertexBinding[VERT_ATTRIB_NORMAL].BufferObj), NO_EXTRA" ], + [ "COLOR_ARRAY_BUFFER_BINDING_ARB", "LOC_CUSTOM, TYPE_INT, offsetof(struct gl_array_object, VertexBinding[VERT_ATTRIB_COLOR0].BufferObj), NO_EXTRA" ], [ "TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB", "LOC_CUSTOM, TYPE_INT, NO_OFFSET, NO_EXTRA" ], # GL_OES_point_sprite @@ -585,10 +585,10 @@ descriptor=[ [ "PRIMITIVE_RESTART_INDEX_NV", "CONTEXT_INT(Array.RestartIndex), extra_NV_primitive_restart" ], # GL_ARB_vertex_buffer_object - [ "INDEX_ARRAY_BUFFER_BINDING_ARB", "LOC_CUSTOM, TYPE_INT, offsetof(struct gl_array_object, VertexAttrib[VERT_ATTRIB_COLOR_INDEX].BufferObj), NO_EXTRA" ], - [ "EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB", "LOC_CUSTOM, TYPE_INT, offsetof(struct gl_array_object, VertexAttrib[VERT_ATTRIB_EDGEFLAG].BufferObj), NO_EXTRA" ], - [ "SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB", "LOC_CUSTOM, TYPE_INT, offsetof(struct gl_array_object, VertexAttrib[VERT_ATTRIB_COLOR1].BufferObj), NO_EXTRA" ], - [ "FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB", "LOC_CUSTOM, TYPE_INT, offsetof(struct gl_array_object, VertexAttrib[VERT_ATTRIB_FOG].BufferObj), NO_EXTRA" ], + [ "INDEX_ARRAY_BUFFER_BINDING_ARB", "LOC_CUSTOM, TYPE_INT, offsetof(struct gl_array_object, VertexBinding[VERT_ATTRIB_COLOR_INDEX].BufferObj), NO_EXTRA" ], + [ "EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB", "LOC_CUSTOM, TYPE_INT, offsetof(struct gl_array_object, VertexBinding[VERT_ATTRIB_EDGEFLAG].BufferObj), NO_EXTRA" ], + [ "SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB", "LOC_CUSTOM, TYPE_INT, offsetof(struct gl_array_object, VertexBinding[VERT_ATTRIB_COLOR1].BufferObj), NO_EXTRA" ], + [ "FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB", "LOC_CUSTOM, TYPE_INT, offsetof(struct gl_array_object, VertexBinding[VERT_ATTRIB_FOG].BufferObj), NO_EXTRA" ], # GL_ARB_vertex_program # == GL_VERTEX_PROGRAM_NV @@ -737,6 +737,10 @@ descriptor=[ [ "MAX_GEOMETRY_ATOMIC_COUNTERS", "CONTEXT_INT(Const.GeometryProgram.MaxAtomicCounters), extra_ARB_shader_atomic_counters_and_geometry_shader" ], [ "MAX_COMBINED_ATOMIC_COUNTER_BUFFERS", "CONTEXT_INT(Const.MaxCombinedAtomicBuffers), extra_ARB_shader_atomic_counters" ], [ "MAX_COMBINED_ATOMIC_COUNTERS", "CONTEXT_INT(Const.MaxCombinedAtomicCounters), extra_ARB_shader_atomic_counters" ], + +# GL_ARB_vertex_attrib_binding + [ "MAX_VERTEX_ATTRIB_RELATIVE_OFFSET", "CONTEXT_ENUM(Const.MaxVertexAttribRelativeOffset), NO_EXTRA" ], + [ "MAX_VERTEX_ATTRIB_BINDINGS", "CONTEXT_ENUM(Const.MaxVertexAttribBindings), NO_EXTRA" ], ]}, # Enums restricted to OpenGL Core profile diff --git a/mesalib/src/mesa/main/getstring.c b/mesalib/src/mesa/main/getstring.c index 0e075427f..d8189115a 100644 --- a/mesalib/src/mesa/main/getstring.c +++ b/mesalib/src/mesa/main/getstring.c @@ -23,7 +23,7 @@ */ - +#include #include "glheader.h" #include "context.h" #include "get.h" @@ -305,11 +305,50 @@ GLenum GLAPIENTRY _mesa_GetGraphicsResetStatusARB( void ) { GET_CURRENT_CONTEXT(ctx); - GLenum status = ctx->ResetStatus; + GLenum status = GL_NO_ERROR; + + /* The ARB_robustness specification says: + * + * "If the reset notification behavior is NO_RESET_NOTIFICATION_ARB, + * then the implementation will never deliver notification of reset + * events, and GetGraphicsResetStatusARB will always return NO_ERROR." + */ + if (ctx->Const.ResetStrategy == GL_NO_RESET_NOTIFICATION_ARB) { + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, + "glGetGraphicsResetStatusARB always returns GL_NO_ERROR " + "because reset notifictation was not requested at context " + "creation.\n"); + + return GL_NO_ERROR; + } - if (MESA_VERBOSE & VERBOSE_API) - _mesa_debug(ctx, "glGetGraphicsResetStatusARB" - "(always returns GL_NO_ERROR)\n"); + if (ctx->Driver.GetGraphicsResetStatus) { + /* Query the reset status of this context from the driver core. + */ + status = ctx->Driver.GetGraphicsResetStatus(ctx); + + _glthread_LOCK_MUTEX(ctx->Shared->Mutex); + + /* If this context has not been affected by a GPU reset, check to see if + * some other context in the share group has been affected by a reset. + * If another context saw a reset but this context did not, assume that + * this context was not guilty. + */ + if (status != GL_NO_ERROR) { + ctx->Shared->ShareGroupReset = true; + } else if (ctx->Shared->ShareGroupReset && !ctx->ShareGroupReset) { + status = GL_INNOCENT_CONTEXT_RESET_ARB; + } + + ctx->ShareGroupReset = ctx->Shared->ShareGroupReset; + _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); + } + + if (!ctx->Driver.GetGraphicsResetStatus && (MESA_VERBOSE & VERBOSE_API)) + _mesa_debug(ctx, + "glGetGraphicsResetStatusARB always returns GL_NO_ERROR " + "because the driver doesn't track reset status.\n"); return status; } diff --git a/mesalib/src/mesa/main/glformats.c b/mesalib/src/mesa/main/glformats.c index dfee6f196..740faa890 100644 --- a/mesalib/src/mesa/main/glformats.c +++ b/mesalib/src/mesa/main/glformats.c @@ -345,6 +345,11 @@ _mesa_bytes_per_vertex_attrib(GLint comps, GLenum type) return sizeof(GLuint); else return -1; + case GL_UNSIGNED_INT_10F_11F_11F_REV: + if (comps == 3) + return sizeof(GLuint); + else + return -1; default: return -1; } diff --git a/mesalib/src/mesa/main/mtypes.h b/mesalib/src/mesa/main/mtypes.h index b5c5583d6..ae96e2326 100644 --- a/mesalib/src/mesa/main/mtypes.h +++ b/mesalib/src/mesa/main/mtypes.h @@ -35,6 +35,7 @@ #include /* uint32_t */ +#include #include "main/glheader.h" #include "main/config.h" @@ -1473,6 +1474,44 @@ struct gl_client_array }; +/** + * Vertex attribute array as seen by the client. + * + * Contains the size, type, format and normalization flag, + * along with the index of a vertex buffer binding point. + * + * Note that the Stride field corresponds to VERTEX_ATTRIB_ARRAY_STRIDE + * and is only present for backwards compatibility reasons. + * Rendering always uses VERTEX_BINDING_STRIDE. + * The gl*Pointer() functions will set VERTEX_ATTRIB_ARRAY_STRIDE + * and VERTEX_BINDING_STRIDE to the same value, while + * glBindVertexBuffer() will only set VERTEX_BINDING_STRIDE. + */ +struct gl_vertex_attrib_array +{ + GLint Size; /**< Components per element (1,2,3,4) */ + GLenum Type; /**< Datatype: GL_FLOAT, GL_INT, etc */ + GLenum Format; /**< Default: GL_RGBA, but may be GL_BGRA */ + GLsizei Stride; /**< Stride as specified with gl*Pointer() */ + const GLubyte *Ptr; /**< Points to client array data. Not used when a VBO is bound */ + GLintptr RelativeOffset; /**< Offset of the first element relative to the binding offset */ + GLboolean Enabled; /**< Whether the array is enabled */ + GLboolean Normalized; /**< Fixed-point values are normalized when converted to floats */ + GLboolean Integer; /**< Fixed-point values are not converted to floats */ + GLuint _ElementSize; /**< Size of each element in bytes */ + GLuint VertexBinding; /**< Vertex buffer binding */ +}; + +struct gl_vertex_buffer_binding +{ + GLintptr Offset; /**< User-specified offset */ + GLsizei Stride; /**< User-specified stride */ + GLuint InstanceDivisor; /**< GL_ARB_instanced_arrays */ + struct gl_buffer_object *BufferObj; /**< GL_ARB_vertex_buffer_object */ + GLbitfield64 _BoundArrays; /**< Arrays bound to this binding point */ +}; + + /** * Collection of vertex arrays. Defined by the GL_APPLE_vertex_array_object * extension, but a nice encapsulation in any case. @@ -1507,12 +1546,21 @@ struct gl_array_object */ GLboolean EverBound; + /** Derived vertex attribute arrays */ + struct gl_client_array _VertexAttrib[VERT_ATTRIB_MAX]; + /** Vertex attribute arrays */ - struct gl_client_array VertexAttrib[VERT_ATTRIB_MAX]; + struct gl_vertex_attrib_array VertexAttrib[VERT_ATTRIB_MAX]; + + /** Vertex buffer bindings */ + struct gl_vertex_buffer_binding VertexBinding[VERT_ATTRIB_MAX]; /** Mask of VERT_BIT_* values indicating which arrays are enabled */ GLbitfield64 _Enabled; + /** Mask of VERT_BIT_* values indicating changed/dirty arrays */ + GLbitfield64 NewArrays; + /** * Min of all enabled arrays' _MaxElement. When arrays reside inside VBOs * we can determine the max legal (in bounds) glDrawElements array index. @@ -2765,6 +2813,17 @@ struct gl_shared_state /** GL_ARB_sampler_objects */ struct _mesa_HashTable *SamplerObjects; + + /** + * Some context in this share group was affected by a GPU reset + * + * On the next call to \c glGetGraphicsResetStatus, contexts that have not + * been affected by a GPU reset must also return + * \c GL_INNOCENT_CONTEXT_RESET_ARB. + * + * Once this field becomes true, it is never reset to false. + */ + bool ShareGroupReset; }; @@ -3213,6 +3272,10 @@ struct gl_constants GLuint MaxAtomicBufferSize; GLuint MaxCombinedAtomicBuffers; GLuint MaxCombinedAtomicCounters; + + /** GL_ARB_vertex_attrib_binding */ + GLint MaxVertexAttribRelativeOffset; + GLint MaxVertexAttribBindings; }; @@ -3291,6 +3354,7 @@ struct gl_extensions GLboolean ARB_uniform_buffer_object; GLboolean ARB_vertex_program; GLboolean ARB_vertex_shader; + GLboolean ARB_vertex_type_10f_11f_11f_rev; GLboolean ARB_vertex_type_2_10_10_10_rev; GLboolean EXT_blend_color; GLboolean EXT_blend_equation_separate; @@ -3851,9 +3915,6 @@ struct gl_context GLenum ErrorValue; /**< Last error code */ - /* GL_ARB_robustness */ - GLenum ResetStatus; - /** * Recognize and silence repeated error debug messages in buggy apps. */ @@ -3918,6 +3979,13 @@ struct gl_context const void *vdpGetProcAddress; struct set *vdpSurfaces; /*@}*/ + + /** + * Has this context observed a GPU reset in any context in the share group? + * + * Once this field becomes true, it is never reset to false. + */ + GLboolean ShareGroupReset; }; diff --git a/mesalib/src/mesa/main/state.c b/mesalib/src/mesa/main/state.c index 23926410b..33070b7e0 100644 --- a/mesalib/src/mesa/main/state.c +++ b/mesalib/src/mesa/main/state.c @@ -410,6 +410,9 @@ _mesa_update_state_locked( struct gl_context *ctx ) new_prog_state |= update_program( ctx ); } + if (new_state & _NEW_ARRAY) + _mesa_update_array_object_client_arrays(ctx, ctx->Array.ArrayObj); + if (ctx->Const.CheckArrayBounds && new_state & (_NEW_ARRAY | _NEW_PROGRAM | _NEW_BUFFER_OBJECT)) { _mesa_update_array_object_max_element(ctx, ctx->Array.ArrayObj); @@ -430,6 +433,7 @@ _mesa_update_state_locked( struct gl_context *ctx ) new_state = ctx->NewState | new_prog_state; ctx->NewState = 0; ctx->Driver.UpdateState(ctx, new_state); + ctx->Array.ArrayObj->NewArrays = 0x0; } diff --git a/mesalib/src/mesa/main/streaming-load-memcpy.c b/mesalib/src/mesa/main/streaming-load-memcpy.c new file mode 100644 index 000000000..d7147afdc --- /dev/null +++ b/mesalib/src/mesa/main/streaming-load-memcpy.c @@ -0,0 +1,85 @@ +/* + * 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. + * + * Authors: + * Eric Anholt + * Matt Turner + * + */ + +#include "main/macros.h" +#include "main/streaming-load-memcpy.h" +#include + +/* Copies memory from src to dst, using SSE 4.1's MOVNTDQA to get streaming + * read performance from uncached memory. + */ +void +_mesa_streaming_load_memcpy(void *restrict dst, void *restrict src, size_t len) +{ + char *restrict d = dst; + char *restrict s = src; + + /* If dst and src are not co-aligned, fallback to memcpy(). */ + if (((uintptr_t)d & 15) != ((uintptr_t)s & 15)) { + memcpy(d, s, len); + return; + } + + /* memcpy() the misaligned header. At the end of this if block, and + * are aligned to a 16-byte boundary or == 0. + */ + if ((uintptr_t)d & 15) { + uintptr_t bytes_before_alignment_boundary = 16 - ((uintptr_t)d & 15); + assert(bytes_before_alignment_boundary < 16); + + memcpy(d, s, MIN2(bytes_before_alignment_boundary, len)); + + d = (char *)ALIGN((uintptr_t)d, 16); + s = (char *)ALIGN((uintptr_t)s, 16); + len -= MIN2(bytes_before_alignment_boundary, len); + } + + while (len >= 64) { + __m128i *dst_cacheline = (__m128i *)d; + __m128i *src_cacheline = (__m128i *)s; + + __m128i temp1 = _mm_stream_load_si128(src_cacheline + 0); + __m128i temp2 = _mm_stream_load_si128(src_cacheline + 1); + __m128i temp3 = _mm_stream_load_si128(src_cacheline + 2); + __m128i temp4 = _mm_stream_load_si128(src_cacheline + 3); + + _mm_store_si128(dst_cacheline + 0, temp1); + _mm_store_si128(dst_cacheline + 1, temp2); + _mm_store_si128(dst_cacheline + 2, temp3); + _mm_store_si128(dst_cacheline + 3, temp4); + + d += 64; + s += 64; + len -= 64; + } + + /* memcpy() the tail. */ + if (len) { + memcpy(d, s, len); + } +} diff --git a/mesalib/src/mesa/main/streaming-load-memcpy.h b/mesalib/src/mesa/main/streaming-load-memcpy.h new file mode 100644 index 000000000..41eeeeca0 --- /dev/null +++ b/mesalib/src/mesa/main/streaming-load-memcpy.h @@ -0,0 +1,33 @@ +/* + * 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. + * + * Authors: + * Eric Anholt + * Matt Turner + * + */ + +/* Copies memory from src to dst, using SSE 4.1's MOVNTDQA to get streaming + * read performance from uncached memory. + */ +void +_mesa_streaming_load_memcpy(void *restrict dst, void *restrict src, size_t len); diff --git a/mesalib/src/mesa/main/varray.c b/mesalib/src/mesa/main/varray.c index dee476abb..d17d698d3 100644 --- a/mesalib/src/mesa/main/varray.c +++ b/mesalib/src/mesa/main/varray.c @@ -60,6 +60,7 @@ #define FIXED_GL_BIT 0x800 #define UNSIGNED_INT_2_10_10_10_REV_BIT 0x1000 #define INT_2_10_10_10_REV_BIT 0x2000 +#define UNSIGNED_INT_10F_11F_11F_REV_BIT 0x4000 /** Convert GL datatype enum into a _BIT value seen above */ @@ -96,6 +97,8 @@ type_to_bit(const struct gl_context *ctx, GLenum type) return UNSIGNED_INT_2_10_10_10_REV_BIT; case GL_INT_2_10_10_10_REV: return INT_2_10_10_10_REV_BIT; + case GL_UNSIGNED_INT_10F_11F_11F_REV: + return UNSIGNED_INT_10F_11F_11F_REV_BIT; default: return 0; } @@ -103,54 +106,110 @@ type_to_bit(const struct gl_context *ctx, GLenum type) /** - * Do error checking and update state for glVertex/Color/TexCoord/...Pointer - * functions. - * - * \param func name of calling function used for error reporting - * \param attrib the attribute array index to update - * \param legalTypes bitmask of *_BIT above indicating legal datatypes - * \param sizeMin min allowable size value - * \param sizeMax max allowable size value (may also be BGRA_OR_4) - * \param size components per element (1, 2, 3 or 4) - * \param type datatype of each component (GL_FLOAT, GL_INT, etc) - * \param stride stride between elements, in elements - * \param normalized are integer types converted to floats in [-1, 1]? - * \param integer integer-valued values (will not be normalized to [-1,1]) - * \param ptr the address (or offset inside VBO) of the array data + * Sets the VertexBinding field in the vertex attribute given by attribIndex. */ static void -update_array(struct gl_context *ctx, - const char *func, - GLuint attrib, GLbitfield legalTypesMask, - GLint sizeMin, GLint sizeMax, - GLint size, GLenum type, GLsizei stride, - GLboolean normalized, GLboolean integer, - const GLvoid *ptr) +vertex_attrib_binding(struct gl_context *ctx, GLuint attribIndex, + GLuint bindingIndex) { - struct gl_client_array *array; - GLbitfield typeBit; - GLsizei elementSize; - GLenum format = GL_RGBA; + struct gl_array_object *arrayObj = ctx->Array.ArrayObj; + struct gl_vertex_attrib_array *array = &arrayObj->VertexAttrib[attribIndex]; - /* Page 407 (page 423 of the PDF) of the OpenGL 3.0 spec says: - * - * "Client vertex arrays - all vertex array attribute pointers must - * refer to buffer objects (section 2.9.2). The default vertex array - * object (the name zero) is also deprecated. Calling - * VertexAttribPointer when no buffer object or no vertex array object - * is bound will generate an INVALID_OPERATION error..." - * - * The check for VBOs is handled below. - */ - if (ctx->API == API_OPENGL_CORE - && (ctx->Array.ArrayObj == ctx->Array.DefaultArrayObj)) { - _mesa_error(ctx, GL_INVALID_OPERATION, "%s(no array object bound)", - func); - return; + if (array->VertexBinding != bindingIndex) { + const GLbitfield64 array_bit = VERT_BIT(attribIndex); + + FLUSH_VERTICES(ctx, _NEW_ARRAY); + + arrayObj->VertexBinding[array->VertexBinding]._BoundArrays &= ~array_bit; + arrayObj->VertexBinding[bindingIndex]._BoundArrays |= array_bit; + + array->VertexBinding = bindingIndex; + + arrayObj->NewArrays |= array_bit; } +} + + +/** + * Binds a buffer object to the vertex buffer binding point given by index, + * and sets the Offset and Stride fields. + */ +static void +bind_vertex_buffer(struct gl_context *ctx, GLuint index, + struct gl_buffer_object *vbo, + GLintptr offset, GLsizei stride) +{ + struct gl_array_object *arrayObj = ctx->Array.ArrayObj; + struct gl_vertex_buffer_binding *binding = &arrayObj->VertexBinding[index]; + + if (binding->BufferObj != vbo || + binding->Offset != offset || + binding->Stride != stride) { + + FLUSH_VERTICES(ctx, _NEW_ARRAY); + + _mesa_reference_buffer_object(ctx, &binding->BufferObj, vbo); + + binding->Offset = offset; + binding->Stride = stride; + + arrayObj->NewArrays |= binding->_BoundArrays; + } +} + + +/** + * Sets the InstanceDivisor field in the vertex buffer binding point + * given by bindingIndex. + */ +static void +vertex_binding_divisor(struct gl_context *ctx, GLuint bindingIndex, + GLuint divisor) +{ + struct gl_array_object *arrayObj = ctx->Array.ArrayObj; + struct gl_vertex_buffer_binding *binding = + &arrayObj->VertexBinding[bindingIndex]; + + if (binding->InstanceDivisor != divisor) { + FLUSH_VERTICES(ctx, _NEW_ARRAY); + binding->InstanceDivisor = divisor; + arrayObj->NewArrays |= binding->_BoundArrays; + } +} + + +/** + * Does error checking and updates the format in an attrib array. + * + * Called by update_array() and VertexAttrib*Format(). + * + * \param func Name of calling function used for error reporting + * \param attrib The index of the attribute array + * \param legalTypes Bitmask of *_BIT above indicating legal datatypes + * \param sizeMin Min allowable size value + * \param sizeMax Max allowable size value (may also be BGRA_OR_4) + * \param size Components per element (1, 2, 3 or 4) + * \param type Datatype of each component (GL_FLOAT, GL_INT, etc) + * \param normalized Whether integer types are converted to floats in [-1, 1] + * \param integer Integer-valued values (will not be normalized to [-1, 1]) + * \param relativeOffset Offset of the first element relative to the binding offset. + */ +static bool +update_array_format(struct gl_context *ctx, + const char *func, + GLuint attrib, GLbitfield legalTypesMask, + GLint sizeMin, GLint sizeMax, + GLint size, GLenum type, + GLboolean normalized, GLboolean integer, + GLuint relativeOffset) +{ + struct gl_vertex_attrib_array *array; + GLbitfield typeBit; + GLuint elementSize; + GLenum format = GL_RGBA; if (_mesa_is_gles(ctx)) { - legalTypesMask &= ~(FIXED_GL_BIT | DOUBLE_BIT); + legalTypesMask &= ~(FIXED_GL_BIT | DOUBLE_BIT | UNSIGNED_INT_10F_11F_11F_REV_BIT); /* GL_INT and GL_UNSIGNED_INT data is not allowed in OpenGL ES until * 3.0. The 2_10_10_10 types are added in OpenGL ES 3.0 or @@ -180,13 +239,16 @@ update_array(struct gl_context *ctx, if (!ctx->Extensions.ARB_vertex_type_2_10_10_10_rev) legalTypesMask &= ~(UNSIGNED_INT_2_10_10_10_REV_BIT | INT_2_10_10_10_REV_BIT); + + if (!ctx->Extensions.ARB_vertex_type_10f_11f_11f_rev) + legalTypesMask &= ~UNSIGNED_INT_10F_11F_11F_REV_BIT; } typeBit = type_to_bit(ctx, type); if (typeBit == 0x0 || (typeBit & legalTypesMask) == 0x0) { _mesa_error(ctx, GL_INVALID_ENUM, "%s(type = %s)", func, _mesa_lookup_enum_by_nr(type)); - return; + return false; } /* Do size parameter checking. @@ -206,26 +268,26 @@ update_array(struct gl_context *ctx, * ... * • size is BGRA and normalized is FALSE;" */ - GLboolean bgra_error = GL_FALSE; + bool bgra_error = false; if (ctx->Extensions.ARB_vertex_type_2_10_10_10_rev) { if (type != GL_UNSIGNED_INT_2_10_10_10_REV && type != GL_INT_2_10_10_10_REV && type != GL_UNSIGNED_BYTE) - bgra_error = GL_TRUE; + bgra_error = true; } else if (type != GL_UNSIGNED_BYTE) - bgra_error = GL_TRUE; + bgra_error = true; if (bgra_error) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(size=GL_BGRA and type=%s)", func, _mesa_lookup_enum_by_nr(type)); - return; + return false; } if (!normalized) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(size=GL_BGRA and normalized=GL_FALSE)", func); - return; + return false; } format = GL_BGRA; @@ -233,18 +295,106 @@ update_array(struct gl_context *ctx, } else if (size < sizeMin || size > sizeMax || size > 4) { _mesa_error(ctx, GL_INVALID_VALUE, "%s(size=%d)", func, size); - return; + return false; } if (ctx->Extensions.ARB_vertex_type_2_10_10_10_rev && (type == GL_UNSIGNED_INT_2_10_10_10_REV || type == GL_INT_2_10_10_10_REV) && size != 4) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(size=%d)", func, size); - return; + return false; + } + + /* The ARB_vertex_attrib_binding_spec says: + * + * An INVALID_VALUE error is generated if is larger than + * the value of MAX_VERTEX_ATTRIB_RELATIVE_OFFSET. + */ + if (relativeOffset > ctx->Const.MaxVertexAttribRelativeOffset) { + _mesa_error(ctx, GL_INVALID_VALUE, + "%s(relativeOffset=%d > " + "GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET)", + func, relativeOffset); + return false; + } + + if (ctx->Extensions.ARB_vertex_type_10f_11f_11f_rev && + type == GL_UNSIGNED_INT_10F_11F_11F_REV && size != 3) { + _mesa_error(ctx, GL_INVALID_OPERATION, "%s(size=%d)", func, size); + return false; } ASSERT(size <= 4); + elementSize = _mesa_bytes_per_vertex_attrib(size, type); + assert(elementSize != -1); + + array = &ctx->Array.ArrayObj->VertexAttrib[attrib]; + array->Size = size; + array->Type = type; + array->Format = format; + array->Normalized = normalized; + array->Integer = integer; + array->RelativeOffset = relativeOffset; + array->_ElementSize = elementSize; + + ctx->Array.ArrayObj->NewArrays |= VERT_BIT(attrib); + ctx->NewState |= _NEW_ARRAY; + + return true; +} + + +/** + * Do error checking and update state for glVertex/Color/TexCoord/...Pointer + * functions. + * + * \param func name of calling function used for error reporting + * \param attrib the attribute array index to update + * \param legalTypes bitmask of *_BIT above indicating legal datatypes + * \param sizeMin min allowable size value + * \param sizeMax max allowable size value (may also be BGRA_OR_4) + * \param size components per element (1, 2, 3 or 4) + * \param type datatype of each component (GL_FLOAT, GL_INT, etc) + * \param stride stride between elements, in elements + * \param normalized are integer types converted to floats in [-1, 1]? + * \param integer integer-valued values (will not be normalized to [-1,1]) + * \param ptr the address (or offset inside VBO) of the array data + */ +static void +update_array(struct gl_context *ctx, + const char *func, + GLuint attrib, GLbitfield legalTypesMask, + GLint sizeMin, GLint sizeMax, + GLint size, GLenum type, GLsizei stride, + GLboolean normalized, GLboolean integer, + const GLvoid *ptr) +{ + struct gl_vertex_attrib_array *array; + GLsizei effectiveStride; + + /* Page 407 (page 423 of the PDF) of the OpenGL 3.0 spec says: + * + * "Client vertex arrays - all vertex array attribute pointers must + * refer to buffer objects (section 2.9.2). The default vertex array + * object (the name zero) is also deprecated. Calling + * VertexAttribPointer when no buffer object or no vertex array object + * is bound will generate an INVALID_OPERATION error..." + * + * The check for VBOs is handled below. + */ + if (ctx->API == API_OPENGL_CORE + && (ctx->Array.ArrayObj == ctx->Array.DefaultArrayObj)) { + _mesa_error(ctx, GL_INVALID_OPERATION, "%s(no array object bound)", + func); + return; + } + + if (!update_array_format(ctx, func, attrib, legalTypesMask, sizeMin, sizeMax, + size, type, normalized, integer, 0)) { + return; + } + if (stride < 0) { _mesa_error( ctx, GL_INVALID_VALUE, "%s(stride=%d)", func, stride ); return; @@ -268,24 +418,18 @@ update_array(struct gl_context *ctx, return; } - elementSize = _mesa_bytes_per_vertex_attrib(size, type); - assert(elementSize != -1); + /* Reset the vertex attrib binding */ + vertex_attrib_binding(ctx, attrib, attrib); + /* The Stride and Ptr fields are not set by update_array_format() */ array = &ctx->Array.ArrayObj->VertexAttrib[attrib]; - array->Size = size; - array->Type = type; - array->Format = format; array->Stride = stride; - array->StrideB = stride ? stride : elementSize; - array->Normalized = normalized; - array->Integer = integer; - array->Ptr = (const GLubyte *) ptr; - array->_ElementSize = elementSize; + array->Ptr = (const GLvoid *) ptr; - _mesa_reference_buffer_object(ctx, &array->BufferObj, - ctx->Array.ArrayBufferObj); - - ctx->NewState |= _NEW_ARRAY; + /* Update the vertex buffer binding */ + effectiveStride = stride != 0 ? stride : array->_ElementSize; + bind_vertex_buffer(ctx, attrib, ctx->Array.ArrayBufferObj, + (GLintptr) ptr, effectiveStride); } @@ -473,7 +617,8 @@ _mesa_VertexAttribPointer(GLuint index, GLint size, GLenum type, HALF_BIT | FLOAT_BIT | DOUBLE_BIT | FIXED_ES_BIT | FIXED_GL_BIT | UNSIGNED_INT_2_10_10_10_REV_BIT | - INT_2_10_10_10_REV_BIT); + INT_2_10_10_10_REV_BIT | + UNSIGNED_INT_10F_11F_11F_REV_BIT); GET_CURRENT_CONTEXT(ctx); if (index >= ctx->Const.VertexProgram.MaxAttribs) { @@ -530,13 +675,14 @@ _mesa_EnableVertexAttribArray(GLuint index) arrayObj = ctx->Array.ArrayObj; - ASSERT(VERT_ATTRIB_GENERIC(index) < Elements(arrayObj->VertexAttrib)); + ASSERT(VERT_ATTRIB_GENERIC(index) < Elements(arrayObj->_VertexAttrib)); if (!arrayObj->VertexAttrib[VERT_ATTRIB_GENERIC(index)].Enabled) { /* was disabled, now being enabled */ FLUSH_VERTICES(ctx, _NEW_ARRAY); arrayObj->VertexAttrib[VERT_ATTRIB_GENERIC(index)].Enabled = GL_TRUE; arrayObj->_Enabled |= VERT_BIT_GENERIC(index); + arrayObj->NewArrays |= VERT_BIT_GENERIC(index); } } @@ -555,13 +701,14 @@ _mesa_DisableVertexAttribArray(GLuint index) arrayObj = ctx->Array.ArrayObj; - ASSERT(VERT_ATTRIB_GENERIC(index) < Elements(arrayObj->VertexAttrib)); + ASSERT(VERT_ATTRIB_GENERIC(index) < Elements(arrayObj->_VertexAttrib)); if (arrayObj->VertexAttrib[VERT_ATTRIB_GENERIC(index)].Enabled) { /* was enabled, now being disabled */ FLUSH_VERTICES(ctx, _NEW_ARRAY); arrayObj->VertexAttrib[VERT_ATTRIB_GENERIC(index)].Enabled = GL_FALSE; arrayObj->_Enabled &= ~VERT_BIT_GENERIC(index); + arrayObj->NewArrays |= VERT_BIT_GENERIC(index); } } @@ -575,16 +722,17 @@ static GLuint get_vertex_array_attrib(struct gl_context *ctx, GLuint index, GLenum pname, const char *caller) { - const struct gl_client_array *array; + const struct gl_array_object *arrayObj = ctx->Array.ArrayObj; + const struct gl_vertex_attrib_array *array; if (index >= ctx->Const.VertexProgram.MaxAttribs) { _mesa_error(ctx, GL_INVALID_VALUE, "%s(index=%u)", caller, index); return 0; } - ASSERT(VERT_ATTRIB_GENERIC(index) < Elements(ctx->Array.ArrayObj->VertexAttrib)); + ASSERT(VERT_ATTRIB_GENERIC(index) < Elements(arrayObj->VertexAttrib)); - array = &ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_GENERIC(index)]; + array = &arrayObj->VertexAttrib[VERT_ATTRIB_GENERIC(index)]; switch (pname) { case GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB: @@ -598,7 +746,7 @@ get_vertex_array_attrib(struct gl_context *ctx, GLuint index, GLenum pname, case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB: return array->Normalized; case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB: - return array->BufferObj->Name; + return arrayObj->VertexBinding[array->VertexBinding].BufferObj->Name; case GL_VERTEX_ATTRIB_ARRAY_INTEGER: if ((_mesa_is_desktop_gl(ctx) && (ctx->Version >= 30 || ctx->Extensions.EXT_gpu_shader4)) @@ -609,7 +757,17 @@ get_vertex_array_attrib(struct gl_context *ctx, GLuint index, GLenum pname, case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ARB: if ((_mesa_is_desktop_gl(ctx) && ctx->Extensions.ARB_instanced_arrays) || _mesa_is_gles3(ctx)) { - return array->InstanceDivisor; + return arrayObj->VertexBinding[array->VertexBinding].InstanceDivisor; + } + goto error; + case GL_VERTEX_ATTRIB_BINDING: + if (_mesa_is_desktop_gl(ctx)) { + return array->VertexBinding - VERT_ATTRIB_GENERIC0; + } + goto error; + case GL_VERTEX_ATTRIB_RELATIVE_OFFSET: + if (_mesa_is_desktop_gl(ctx)) { + return array->RelativeOffset; } goto error; default: @@ -643,7 +801,7 @@ get_current_attrib(struct gl_context *ctx, GLuint index, const char *function) return NULL; } - ASSERT(VERT_ATTRIB_GENERIC(index) < Elements(ctx->Array.ArrayObj->VertexAttrib)); + ASSERT(VERT_ATTRIB_GENERIC(index) < Elements(ctx->Array.ArrayObj->_VertexAttrib)); FLUSH_CURRENT(ctx, 0); return ctx->Current.Attrib[VERT_ATTRIB_GENERIC(index)]; @@ -765,7 +923,7 @@ _mesa_GetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid **pointer) return; } - ASSERT(VERT_ATTRIB_GENERIC(index) < Elements(ctx->Array.ArrayObj->VertexAttrib)); + ASSERT(VERT_ATTRIB_GENERIC(index) < Elements(ctx->Array.ArrayObj->_VertexAttrib)); *pointer = (GLvoid *) ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_GENERIC(index)].Ptr; } @@ -1141,9 +1299,10 @@ _mesa_PrimitiveRestartIndex(GLuint index) void GLAPIENTRY _mesa_VertexAttribDivisor(GLuint index, GLuint divisor) { - struct gl_client_array *array; GET_CURRENT_CONTEXT(ctx); + const GLuint genericIndex = VERT_ATTRIB_GENERIC(index); + if (!ctx->Extensions.ARB_instanced_arrays) { _mesa_error(ctx, GL_INVALID_OPERATION, "glVertexAttribDivisor()"); return; @@ -1155,13 +1314,21 @@ _mesa_VertexAttribDivisor(GLuint index, GLuint divisor) return; } - ASSERT(VERT_ATTRIB_GENERIC(index) < Elements(ctx->Array.ArrayObj->VertexAttrib)); + ASSERT(genericIndex < Elements(ctx->Array.ArrayObj->VertexAttrib)); - array = &ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_GENERIC(index)]; - if (array->InstanceDivisor != divisor) { - FLUSH_VERTICES(ctx, _NEW_ARRAY); - array->InstanceDivisor = divisor; - } + /* The ARB_vertex_attrib_binding spec says: + * + * "The command + * + * void VertexAttribDivisor(uint index, uint divisor); + * + * is equivalent to (assuming no errors are generated): + * + * VertexAttribBinding(index, index); + * VertexBindingDivisor(index, divisor);" + */ + vertex_attrib_binding(ctx, genericIndex, genericIndex); + vertex_binding_divisor(ctx, genericIndex, divisor); } @@ -1190,6 +1357,329 @@ _mesa_primitive_restart_index(const struct gl_context *ctx, GLenum ib_type) } +/** + * GL_ARB_vertex_attrib_binding + */ +void GLAPIENTRY +_mesa_BindVertexBuffer(GLuint bindingIndex, GLuint buffer, GLintptr offset, + GLsizei stride) +{ + GET_CURRENT_CONTEXT(ctx); + const struct gl_array_object *arrayObj = ctx->Array.ArrayObj; + struct gl_buffer_object *vbo; + + ASSERT_OUTSIDE_BEGIN_END(ctx); + + /* The ARB_vertex_attrib_binding spec says: + * + * "An INVALID_OPERATION error is generated if no vertex array object + * is bound." + */ + if (ctx->API == API_OPENGL_CORE && + ctx->Array.ArrayObj == ctx->Array.DefaultArrayObj) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glBindVertexBuffer(No array object bound)"); + return; + } + + /* The ARB_vertex_attrib_binding spec says: + * + * "An INVALID_VALUE error is generated if is greater than + * the value of MAX_VERTEX_ATTRIB_BINDINGS." + */ + if (bindingIndex >= ctx->Const.MaxVertexAttribBindings) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glBindVertexBuffer(bindingindex=%u > " + "GL_MAX_VERTEX_ATTRIB_BINDINGS)", + bindingIndex); + return; + } + + /* The ARB_vertex_attrib_binding spec says: + * + * "The error INVALID_VALUE is generated if or + * are negative." + */ + if (offset < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glBindVertexBuffer(offset=%lld < 0)", (long long)offset); + return; + } + + if (stride < 0) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glBindVertexBuffer(stride=%d < 0)", stride); + return; + } + + if (buffer == arrayObj->VertexBinding[VERT_ATTRIB_GENERIC(bindingIndex)].BufferObj->Name) { + vbo = arrayObj->VertexBinding[VERT_ATTRIB_GENERIC(bindingIndex)].BufferObj; + } else if (buffer != 0) { + vbo = _mesa_lookup_bufferobj(ctx, buffer); + + /* From the GL_ARB_vertex_attrib_array spec: + * + * "[Core profile only:] + * An INVALID_OPERATION error is generated if buffer is not zero or a + * name returned from a previous call to GenBuffers, or if such a name + * has since been deleted with DeleteBuffers. + * + * Otherwise, we fall back to the same compat profile behavior as other + * object references (automatically gen it). + */ + if (!_mesa_handle_bind_buffer_gen(ctx, GL_ARRAY_BUFFER, buffer, + &vbo, "glBindVertexBuffer")) + return; + } else { + /* The ARB_vertex_attrib_binding spec says: + * + * "If is zero, any buffer object attached to this + * bindpoint is detached." + */ + vbo = ctx->Shared->NullBufferObj; + } + + bind_vertex_buffer(ctx, VERT_ATTRIB_GENERIC(bindingIndex), + vbo, offset, stride); +} + + +void GLAPIENTRY +_mesa_VertexAttribFormat(GLuint attribIndex, GLint size, GLenum type, + GLboolean normalized, GLuint relativeOffset) +{ + const GLbitfield legalTypes = (BYTE_BIT | UNSIGNED_BYTE_BIT | + SHORT_BIT | UNSIGNED_SHORT_BIT | + INT_BIT | UNSIGNED_INT_BIT | + HALF_BIT | FLOAT_BIT | DOUBLE_BIT | + FIXED_GL_BIT | + UNSIGNED_INT_2_10_10_10_REV_BIT | + INT_2_10_10_10_REV_BIT | + UNSIGNED_INT_10F_11F_11F_REV_BIT); + + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + /* The ARB_vertex_attrib_binding spec says: + * + * "An INVALID_OPERATION error is generated under any of the following + * conditions: + * - if no vertex array object is currently bound (see section 2.10); + * - ..." + */ + if (ctx->API == API_OPENGL_CORE && + ctx->Array.ArrayObj == ctx->Array.DefaultArrayObj) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glVertexAttribFormat(No array object bound)"); + return; + } + + /* The ARB_vertex_attrib_binding spec says: + * + * "The error INVALID_VALUE is generated if index is greater than or equal + * to the value of MAX_VERTEX_ATTRIBS." + */ + if (attribIndex >= ctx->Const.VertexProgram.MaxAttribs) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glVertexAttribFormat(attribindex=%u > " + "GL_MAX_VERTEX_ATTRIBS)", + attribIndex); + return; + } + + FLUSH_VERTICES(ctx, 0); + + update_array_format(ctx, "glVertexAttribFormat", + VERT_ATTRIB_GENERIC(attribIndex), + legalTypes, 1, BGRA_OR_4, size, type, normalized, + GL_FALSE, relativeOffset); +} + + +void GLAPIENTRY +_mesa_VertexAttribIFormat(GLuint attribIndex, GLint size, GLenum type, + GLuint relativeOffset) +{ + const GLbitfield legalTypes = (BYTE_BIT | UNSIGNED_BYTE_BIT | + SHORT_BIT | UNSIGNED_SHORT_BIT | + INT_BIT | UNSIGNED_INT_BIT); + + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + /* The ARB_vertex_attrib_binding spec says: + * + * "An INVALID_OPERATION error is generated under any of the following + * conditions: + * - if no vertex array object is currently bound (see section 2.10); + * - ..." + */ + if (ctx->API == API_OPENGL_CORE && + ctx->Array.ArrayObj == ctx->Array.DefaultArrayObj) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glVertexAttribIFormat(No array object bound)"); + return; + } + + /* The ARB_vertex_attrib_binding spec says: + * + * "The error INVALID_VALUE is generated if index is greater than + * or equal to the value of MAX_VERTEX_ATTRIBS." + */ + if (attribIndex >= ctx->Const.VertexProgram.MaxAttribs) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glVertexAttribIFormat(attribindex=%u > " + "GL_MAX_VERTEX_ATTRIBS)", + attribIndex); + return; + } + + FLUSH_VERTICES(ctx, 0); + + update_array_format(ctx, "glVertexAttribIFormat", + VERT_ATTRIB_GENERIC(attribIndex), + legalTypes, 1, 4, size, type, GL_FALSE, GL_TRUE, + relativeOffset); +} + + +void GLAPIENTRY +_mesa_VertexAttribLFormat(GLuint attribIndex, GLint size, GLenum type, + GLuint relativeOffset) +{ + const GLbitfield legalTypes = DOUBLE_BIT; + + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + /* Page 298 of the PDF of the OpenGL 4.3 (Core Profile) spec says: + * + * "An INVALID_OPERATION error is generated under any of the following + * conditions: + * • if no vertex array object is currently bound (see section 10.4); + * • ..." + * + * This language is missing from the extension spec, but we assume + * that this is an oversight. + */ + if (ctx->API == API_OPENGL_CORE && + ctx->Array.ArrayObj == ctx->Array.DefaultArrayObj) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glVertexAttribLFormat(No array object bound)"); + return; + } + + /* The ARB_vertex_attrib_binding spec says: + * + * "The error INVALID_VALUE is generated if is greater than + * or equal to the value of MAX_VERTEX_ATTRIBS." + */ + if (attribIndex >= ctx->Const.VertexProgram.MaxAttribs) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glVertexAttribLFormat(attribindex=%u > " + "GL_MAX_VERTEX_ATTRIBS)", + attribIndex); + return; + } + + FLUSH_VERTICES(ctx, 0); + + update_array_format(ctx, "glVertexAttribLFormat", + VERT_ATTRIB_GENERIC(attribIndex), + legalTypes, 1, 4, size, type, GL_FALSE, GL_FALSE, + relativeOffset); +} + + +void GLAPIENTRY +_mesa_VertexAttribBinding(GLuint attribIndex, GLuint bindingIndex) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + /* The ARB_vertex_attrib_binding spec says: + * + * "An INVALID_OPERATION error is generated if no vertex array object + * is bound." + */ + if (ctx->API == API_OPENGL_CORE && + ctx->Array.ArrayObj == ctx->Array.DefaultArrayObj) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glVertexAttribBinding(No array object bound)"); + return; + } + + /* The ARB_vertex_attrib_binding spec says: + * + * " must be less than the value of MAX_VERTEX_ATTRIBS and + * must be less than the value of + * MAX_VERTEX_ATTRIB_BINDINGS, otherwise the error INVALID_VALUE + * is generated." + */ + if (attribIndex >= ctx->Const.VertexProgram.MaxAttribs) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glVertexAttribBinding(attribindex=%u >= " + "GL_MAX_VERTEX_ATTRIBS)", + attribIndex); + return; + } + + if (bindingIndex >= ctx->Const.MaxVertexAttribBindings) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glVertexAttribBinding(bindingindex=%u >= " + "GL_MAX_VERTEX_ATTRIB_BINDINGS)", + bindingIndex); + return; + } + + ASSERT(VERT_ATTRIB_GENERIC(attribIndex) < + Elements(ctx->Array.ArrayObj->VertexAttrib)); + + vertex_attrib_binding(ctx, VERT_ATTRIB_GENERIC(attribIndex), + VERT_ATTRIB_GENERIC(bindingIndex)); +} + + +void GLAPIENTRY +_mesa_VertexBindingDivisor(GLuint bindingIndex, GLuint divisor) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + if (!ctx->Extensions.ARB_instanced_arrays) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glVertexBindingDivisor()"); + return; + } + + /* The ARB_vertex_attrib_binding spec says: + * + * "An INVALID_OPERATION error is generated if no vertex array object + * is bound." + */ + if (ctx->API == API_OPENGL_CORE && + ctx->Array.ArrayObj == ctx->Array.DefaultArrayObj) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glVertexBindingDivisor(No array object bound)"); + return; + } + + /* The ARB_vertex_attrib_binding spec says: + * + * "An INVALID_VALUE error is generated if is greater + * than or equal to the value of MAX_VERTEX_ATTRIB_BINDINGS." + */ + if (bindingIndex >= ctx->Const.MaxVertexAttribBindings) { + _mesa_error(ctx, GL_INVALID_VALUE, + "glVertexBindingDivisor(bindingindex=%u > " + "GL_MAX_VERTEX_ATTRIB_BINDINGS)", + bindingIndex); + return; + } + + vertex_binding_divisor(ctx, VERT_ATTRIB_GENERIC(bindingIndex), divisor); +} + + /** * Copy one client vertex array to another. */ @@ -1213,7 +1703,36 @@ _mesa_copy_client_array(struct gl_context *ctx, dst->_MaxElement = src->_MaxElement; } +void +_mesa_copy_vertex_attrib_array(struct gl_context *ctx, + struct gl_vertex_attrib_array *dst, + const struct gl_vertex_attrib_array *src) +{ + dst->Size = src->Size; + dst->Type = src->Type; + dst->Format = src->Format; + dst->VertexBinding = src->VertexBinding; + dst->RelativeOffset = src->RelativeOffset; + dst->Format = src->Format; + dst->Integer = src->Integer; + dst->Normalized = src->Normalized; + dst->Ptr = src->Ptr; + dst->Enabled = src->Enabled; + dst->_ElementSize = src->_ElementSize; +} +void +_mesa_copy_vertex_buffer_binding(struct gl_context *ctx, + struct gl_vertex_buffer_binding *dst, + const struct gl_vertex_buffer_binding *src) +{ + dst->Offset = src->Offset; + dst->Stride = src->Stride; + dst->InstanceDivisor = src->InstanceDivisor; + dst->_BoundArrays = src->_BoundArrays; + + _mesa_reference_buffer_object(ctx, &dst->BufferObj, src->BufferObj); +} /** * Print vertex array's fields. @@ -1245,18 +1764,18 @@ _mesa_print_arrays(struct gl_context *ctx) _mesa_update_array_object_max_element(ctx, arrayObj); printf("Array Object %u\n", arrayObj->Name); - if (arrayObj->VertexAttrib[VERT_ATTRIB_POS].Enabled) - print_array("Vertex", -1, &arrayObj->VertexAttrib[VERT_ATTRIB_POS]); - if (arrayObj->VertexAttrib[VERT_ATTRIB_NORMAL].Enabled) - print_array("Normal", -1, &arrayObj->VertexAttrib[VERT_ATTRIB_NORMAL]); - if (arrayObj->VertexAttrib[VERT_ATTRIB_COLOR0].Enabled) - print_array("Color", -1, &arrayObj->VertexAttrib[VERT_ATTRIB_COLOR0]); + if (arrayObj->_VertexAttrib[VERT_ATTRIB_POS].Enabled) + print_array("Vertex", -1, &arrayObj->_VertexAttrib[VERT_ATTRIB_POS]); + if (arrayObj->_VertexAttrib[VERT_ATTRIB_NORMAL].Enabled) + print_array("Normal", -1, &arrayObj->_VertexAttrib[VERT_ATTRIB_NORMAL]); + if (arrayObj->_VertexAttrib[VERT_ATTRIB_COLOR0].Enabled) + print_array("Color", -1, &arrayObj->_VertexAttrib[VERT_ATTRIB_COLOR0]); for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) - if (arrayObj->VertexAttrib[VERT_ATTRIB_TEX(i)].Enabled) - print_array("TexCoord", i, &arrayObj->VertexAttrib[VERT_ATTRIB_TEX(i)]); + if (arrayObj->_VertexAttrib[VERT_ATTRIB_TEX(i)].Enabled) + print_array("TexCoord", i, &arrayObj->_VertexAttrib[VERT_ATTRIB_TEX(i)]); for (i = 0; i < VERT_ATTRIB_GENERIC_MAX; i++) - if (arrayObj->VertexAttrib[VERT_ATTRIB_GENERIC(i)].Enabled) - print_array("Attrib", i, &arrayObj->VertexAttrib[VERT_ATTRIB_GENERIC(i)]); + if (arrayObj->_VertexAttrib[VERT_ATTRIB_GENERIC(i)].Enabled) + print_array("Attrib", i, &arrayObj->_VertexAttrib[VERT_ATTRIB_GENERIC(i)]); printf(" _MaxElement = %u\n", arrayObj->_MaxElement); } diff --git a/mesalib/src/mesa/main/varray.h b/mesalib/src/mesa/main/varray.h index 7e611e8c7..8a9487c6e 100644 --- a/mesalib/src/mesa/main/varray.h +++ b/mesalib/src/mesa/main/varray.h @@ -29,6 +29,7 @@ #include "glheader.h" +#include "bufferobj.h" struct gl_client_array; struct gl_context; @@ -50,8 +51,10 @@ _mesa_update_array_max_element(struct gl_client_array *array) GLsizeiptrARB bufSize = (GLsizeiptrARB) array->BufferObj->Size; if (offset < bufSize) { - array->_MaxElement = (bufSize - offset + array->StrideB - - array->_ElementSize) / array->StrideB; + const GLuint stride = array->StrideB ? + array->StrideB : array->_ElementSize; + array->_MaxElement = (bufSize - offset + stride + - array->_ElementSize) / stride; } else { array->_MaxElement = 0; @@ -64,6 +67,44 @@ _mesa_update_array_max_element(struct gl_client_array *array) } +/** + * Returns a pointer to the vertex attribute data in a client array, + * or the offset into the vertex buffer for an array that resides in + * a vertex buffer. + */ +static inline const GLubyte * +_mesa_vertex_attrib_address(struct gl_vertex_attrib_array *array, + struct gl_vertex_buffer_binding *binding) +{ + return (binding->BufferObj->Name == 0 ? + array->Ptr : + (const GLubyte *)(binding->Offset + array->RelativeOffset)); +} + +/** + * Sets the fields in a gl_client_array to values derived from a + * gl_vertex_attrib_array and a gl_vertex_buffer_binding. + */ +static inline void +_mesa_update_client_array(struct gl_context *ctx, + struct gl_client_array *dst, + struct gl_vertex_attrib_array *src, + struct gl_vertex_buffer_binding *binding) +{ + dst->Size = src->Size; + dst->Type = src->Type; + dst->Format = src->Format; + dst->Stride = src->Stride; + dst->StrideB = binding->Stride; + dst->Ptr = _mesa_vertex_attrib_address(src, binding); + dst->Enabled = src->Enabled; + dst->Normalized = src->Normalized; + dst->Integer = src->Integer; + dst->InstanceDivisor = binding->InstanceDivisor; + dst->_ElementSize = src->_ElementSize; + _mesa_reference_buffer_object(ctx, &dst->BufferObj, binding->BufferObj); +} + extern void GLAPIENTRY _mesa_VertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *ptr); @@ -250,11 +291,43 @@ _mesa_VertexAttribDivisor(GLuint index, GLuint divisor); extern unsigned _mesa_primitive_restart_index(const struct gl_context *ctx, GLenum ib_type); +extern void GLAPIENTRY +_mesa_BindVertexBuffer(GLuint bindingIndex, GLuint buffer, GLintptr offset, + GLsizei stride); + +extern void GLAPIENTRY +_mesa_VertexAttribFormat(GLuint attribIndex, GLint size, GLenum type, + GLboolean normalized, GLuint relativeOffset); + +extern void GLAPIENTRY +_mesa_VertexAttribIFormat(GLuint attribIndex, GLint size, GLenum type, + GLuint relativeOffset); + +extern void GLAPIENTRY +_mesa_VertexAttribLFormat(GLuint attribIndex, GLint size, GLenum type, + GLuint relativeOffset); + +extern void GLAPIENTRY +_mesa_VertexAttribBinding(GLuint attribIndex, GLuint bindingIndex); + +extern void GLAPIENTRY +_mesa_VertexBindingDivisor(GLuint bindingIndex, GLuint divisor); + + extern void _mesa_copy_client_array(struct gl_context *ctx, struct gl_client_array *dst, struct gl_client_array *src); +extern void +_mesa_copy_vertex_attrib_array(struct gl_context *ctx, + struct gl_vertex_attrib_array *dst, + const struct gl_vertex_attrib_array *src); + +extern void +_mesa_copy_vertex_buffer_binding(struct gl_context *ctx, + struct gl_vertex_buffer_binding *dst, + const struct gl_vertex_buffer_binding *src); extern void _mesa_print_arrays(struct gl_context *ctx); diff --git a/mesalib/src/mesa/state_tracker/st_atom_array.c b/mesalib/src/mesa/state_tracker/st_atom_array.c index 87a0a17f1..76a94bcf8 100644 --- a/mesalib/src/mesa/state_tracker/st_atom_array.c +++ b/mesalib/src/mesa/state_tracker/st_atom_array.c @@ -214,7 +214,8 @@ st_pipe_vertex_format(GLenum type, GLuint size, GLenum format, assert((type >= GL_BYTE && type <= GL_DOUBLE) || type == GL_FIXED || type == GL_HALF_FLOAT || type == GL_INT_2_10_10_10_REV || - type == GL_UNSIGNED_INT_2_10_10_10_REV); + type == GL_UNSIGNED_INT_2_10_10_10_REV || + type == GL_UNSIGNED_INT_10F_11F_11F_REV); assert(size >= 1); assert(size <= 4); assert(format == GL_RGBA || format == GL_BGRA); @@ -251,6 +252,14 @@ st_pipe_vertex_format(GLenum type, GLuint size, GLenum format, } } + if (type == GL_UNSIGNED_INT_10F_11F_11F_REV) { + assert(size == 3); + assert(!integer); + assert(format == GL_RGBA); + + return PIPE_FORMAT_R11G11B10_FLOAT; + } + if (format == GL_BGRA) { /* this is an odd-ball case */ assert(type == GL_UNSIGNED_BYTE); diff --git a/mesalib/src/mesa/state_tracker/st_extensions.c b/mesalib/src/mesa/state_tracker/st_extensions.c index 97c5d55e1..e8d0902d9 100644 --- a/mesalib/src/mesa/state_tracker/st_extensions.c +++ b/mesalib/src/mesa/state_tracker/st_extensions.c @@ -507,6 +507,8 @@ void st_init_extensions(struct st_context *st) PIPE_FORMAT_B10G10R10A2_USCALED, PIPE_FORMAT_R10G10B10A2_SSCALED, PIPE_FORMAT_B10G10R10A2_SSCALED } }, + { { o(ARB_vertex_type_10f_11f_11f_rev) }, + { PIPE_FORMAT_R11G11B10_FLOAT } }, }; static const struct st_extension_format_mapping tbo_rgb32[] = { diff --git a/mesalib/src/mesa/vbo/vbo_attrib_tmp.h b/mesalib/src/mesa/vbo/vbo_attrib_tmp.h index bbc020539..358d12d15 100644 --- a/mesalib/src/mesa/vbo/vbo_attrib_tmp.h +++ b/mesalib/src/mesa/vbo/vbo_attrib_tmp.h @@ -25,6 +25,8 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. **************************************************************************/ +#include "util/u_format_r11g11b10f.h" + /* float */ #define ATTR1FV( A, V ) ATTR( A, 1, GL_FLOAT, (V)[0], 0, 0, 1 ) #define ATTR2FV( A, V ) ATTR( A, 2, GL_FLOAT, (V)[0], (V)[1], 0, 1 ) @@ -205,6 +207,10 @@ static inline float conv_i2_to_norm_float(const struct gl_context *ctx, int i2) } else { \ ATTRI10_##val((attr), (arg)); \ } \ + } else if ((type) == GL_UNSIGNED_INT_10F_11F_11F_REV) { \ + float res[4]; \ + r11g11b10f_to_float3((arg), res); \ + ATTR##val##FV((attr), res); \ } else \ ERROR(GL_INVALID_VALUE); \ } while(0) @@ -835,12 +841,26 @@ TAG(VertexAttrib4fvNV)(GLuint index, const GLfloat * v) ATTR4FV(index, v); } + #define ERROR_IF_NOT_PACKED_TYPE(ctx, type, func) \ if (type != GL_INT_2_10_10_10_REV && type != GL_UNSIGNED_INT_2_10_10_10_REV) { \ _mesa_error(ctx, GL_INVALID_ENUM, "%s(type)", func); \ return; \ } +/* Extended version of ERROR_IF_NOT_PACKED_TYPE which also + * accepts GL_UNSIGNED_INT_10F_11F_11F_REV. + * + * Only used for VertexAttribP[123]ui[v]; VertexAttribP4* cannot use this type, + * and neither can legacy vertex attribs. + */ +#define ERROR_IF_NOT_PACKED_TYPE_EXT(ctx, type, func) \ + if (type != GL_INT_2_10_10_10_REV && type != GL_UNSIGNED_INT_2_10_10_10_REV && \ + type != GL_UNSIGNED_INT_10F_11F_11F_REV) { \ + _mesa_error(ctx, GL_INVALID_ENUM, "%s(type)", func); \ + return; \ + } + static void GLAPIENTRY TAG(VertexP2ui)(GLenum type, GLuint value) { @@ -1094,7 +1114,7 @@ TAG(VertexAttribP1ui)(GLuint index, GLenum type, GLboolean normalized, GLuint value) { GET_CURRENT_CONTEXT(ctx); - ERROR_IF_NOT_PACKED_TYPE(ctx, type, "glVertexAttribP1ui"); + ERROR_IF_NOT_PACKED_TYPE_EXT(ctx, type, "glVertexAttribP1ui"); ATTR_UI_INDEX(ctx, 1, type, normalized, index, value); } @@ -1103,7 +1123,7 @@ TAG(VertexAttribP2ui)(GLuint index, GLenum type, GLboolean normalized, GLuint value) { GET_CURRENT_CONTEXT(ctx); - ERROR_IF_NOT_PACKED_TYPE(ctx, type, "glVertexAttribP2ui"); + ERROR_IF_NOT_PACKED_TYPE_EXT(ctx, type, "glVertexAttribP2ui"); ATTR_UI_INDEX(ctx, 2, type, normalized, index, value); } @@ -1112,7 +1132,7 @@ TAG(VertexAttribP3ui)(GLuint index, GLenum type, GLboolean normalized, GLuint value) { GET_CURRENT_CONTEXT(ctx); - ERROR_IF_NOT_PACKED_TYPE(ctx, type, "glVertexAttribP3ui"); + ERROR_IF_NOT_PACKED_TYPE_EXT(ctx, type, "glVertexAttribP3ui"); ATTR_UI_INDEX(ctx, 3, type, normalized, index, value); } @@ -1130,7 +1150,7 @@ TAG(VertexAttribP1uiv)(GLuint index, GLenum type, GLboolean normalized, const GLuint *value) { GET_CURRENT_CONTEXT(ctx); - ERROR_IF_NOT_PACKED_TYPE(ctx, type, "glVertexAttribP1uiv"); + ERROR_IF_NOT_PACKED_TYPE_EXT(ctx, type, "glVertexAttribP1uiv"); ATTR_UI_INDEX(ctx, 1, type, normalized, index, *value); } @@ -1139,7 +1159,7 @@ TAG(VertexAttribP2uiv)(GLuint index, GLenum type, GLboolean normalized, const GLuint *value) { GET_CURRENT_CONTEXT(ctx); - ERROR_IF_NOT_PACKED_TYPE(ctx, type, "glVertexAttribP2uiv"); + ERROR_IF_NOT_PACKED_TYPE_EXT(ctx, type, "glVertexAttribP2uiv"); ATTR_UI_INDEX(ctx, 2, type, normalized, index, *value); } @@ -1148,7 +1168,7 @@ TAG(VertexAttribP3uiv)(GLuint index, GLenum type, GLboolean normalized, const GLuint *value) { GET_CURRENT_CONTEXT(ctx); - ERROR_IF_NOT_PACKED_TYPE(ctx, type, "glVertexAttribP3uiv"); + ERROR_IF_NOT_PACKED_TYPE_EXT(ctx, type, "glVertexAttribP3uiv"); ATTR_UI_INDEX(ctx, 3, type, normalized, index, *value); } diff --git a/mesalib/src/mesa/vbo/vbo_exec_array.c b/mesalib/src/mesa/vbo/vbo_exec_array.c index f25a9dec3..d72382376 100644 --- a/mesalib/src/mesa/vbo/vbo_exec_array.c +++ b/mesalib/src/mesa/vbo/vbo_exec_array.c @@ -318,8 +318,8 @@ check_draw_elements_data(struct gl_context *ctx, GLsizei count, GLenum elemType, } /* check element j of each enabled array */ - for (k = 0; k < Elements(arrayObj->VertexAttrib); k++) { - check_array_data(ctx, &arrayObj->VertexAttrib[k], k, j); + for (k = 0; k < Elements(arrayObj->_VertexAttrib); k++) { + check_array_data(ctx, &arrayObj->_VertexAttrib[k], k, j); } } @@ -327,8 +327,8 @@ check_draw_elements_data(struct gl_context *ctx, GLsizei count, GLenum elemType, ctx->Driver.UnmapBuffer(ctx, ctx->Array.ArrayObj->ElementArrayBufferObj); } - for (k = 0; k < Elements(arrayObj->VertexAttrib); k++) { - unmap_array_buffer(ctx, &arrayObj->VertexAttrib[k]); + for (k = 0; k < Elements(arrayObj->_VertexAttrib); k++) { + unmap_array_buffer(ctx, &arrayObj->_VertexAttrib[k]); } } @@ -368,7 +368,7 @@ print_draw_arrays(struct gl_context *ctx, exec->array.inputs[i]->Size, stride, /*exec->array.inputs[i]->Enabled,*/ - arrayObj->VertexAttrib[VERT_ATTRIB_FF(i)].Enabled, + arrayObj->_VertexAttrib[VERT_ATTRIB_FF(i)].Enabled, exec->array.inputs[i]->Ptr, bufName); @@ -405,7 +405,7 @@ recalculate_input_bindings(struct gl_context *ctx) { struct vbo_context *vbo = vbo_context(ctx); struct vbo_exec_context *exec = &vbo->exec; - struct gl_client_array *vertexAttrib = ctx->Array.ArrayObj->VertexAttrib; + struct gl_client_array *vertexAttrib = ctx->Array.ArrayObj->_VertexAttrib; const struct gl_client_array **inputs = &exec->array.inputs[0]; GLbitfield64 const_inputs = 0x0; GLuint i; diff --git a/mesalib/src/mesa/x86/.gitignore b/mesalib/src/mesa/x86/.gitignore deleted file mode 100644 index ca3130d9f..000000000 --- a/mesalib/src/mesa/x86/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -gen_matypes -matypes.h diff --git a/mesalib/src/mesa/x86/Makefile.am b/mesalib/src/mesa/x86/Makefile.am deleted file mode 100644 index 167857684..000000000 --- a/mesalib/src/mesa/x86/Makefile.am +++ /dev/null @@ -1,49 +0,0 @@ -# Copyright © 2012 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. - -if HAVE_X86_ASM - -AM_CPPFLAGS = \ - -I$(top_srcdir)/include \ - -I$(top_srcdir)/src/mesa \ - -I$(top_srcdir)/src/mapi \ - $(DEFINES) - -noinst_PROGRAMS = gen_matypes - -gen_matypes_SOURCES = gen_matypes.c -BUILT_SOURCES = matypes.h -CLEANFILES = matypes.h - -if GEN_ASM_OFFSETS - -matypes.h: $(gen_matypes_SOURCES) - $(AM_V_GEN)$(COMPILE) $< -DASM_OFFSETS -S -o - | \ - sed -n '/^->/{s:^->::;/[$$]/{s:^:#define :;s:[$$]::};p}' > $@ - -else - -matypes.h: gen_matypes - $(AM_V_GEN)./gen_matypes > $@ - -endif - -endif -- cgit v1.2.3 From 09e94a8e392e8fe6fd89ddefbf3897a92e525b5b Mon Sep 17 00:00:00 2001 From: marha Date: Fri, 8 Nov 2013 11:28:34 +0100 Subject: Added presentproto-1.0 --- X11/extensions/presentproto.h | 242 +++++++++++++ X11/extensions/presentproto.pc.in | 9 + X11/extensions/presentproto.txt | 745 ++++++++++++++++++++++++++++++++++++++ X11/extensions/presenttokens.h | 91 +++++ packages.txt | 1 + 5 files changed, 1088 insertions(+) create mode 100644 X11/extensions/presentproto.h create mode 100644 X11/extensions/presentproto.pc.in create mode 100644 X11/extensions/presentproto.txt create mode 100644 X11/extensions/presenttokens.h diff --git a/X11/extensions/presentproto.h b/X11/extensions/presentproto.h new file mode 100644 index 000000000..8303a942f --- /dev/null +++ b/X11/extensions/presentproto.h @@ -0,0 +1,242 @@ +/* + * 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_PROTO_H_ +#define _PRESENT_PROTO_H_ + +#include + +#define Region CARD32 +#define XSyncFence CARD32 +#define EventID CARD32 + +typedef struct { + Window window B32; + CARD32 serial B32; +} xPresentNotify; +#define sz_xPresentNotify 8 + +typedef struct { + CARD8 reqType; + CARD8 presentReqType; + CARD16 length B16; + CARD32 majorVersion B32; + CARD32 minorVersion B32; +} xPresentQueryVersionReq; +#define sz_xPresentQueryVersionReq 12 + +typedef struct { + BYTE type; /* X_Reply */ + BYTE pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 majorVersion B32; + CARD32 minorVersion B32; + CARD32 pad2 B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; +} xPresentQueryVersionReply; +#define sz_xPresentQueryVersionReply 32 + +typedef struct { + CARD8 reqType; + CARD8 presentReqType; + CARD16 length B16; + Window window B32; + + Pixmap pixmap B32; + CARD32 serial B32; + + Region valid B32; + Region update B32; + + INT16 x_off B16; + INT16 y_off B16; + CARD32 target_crtc B32; + + XSyncFence wait_fence B32; + XSyncFence idle_fence B32; + + CARD32 options B32; + CARD32 pad1 B32; + + CARD64 target_msc; + CARD64 divisor; + CARD64 remainder; + /* followed by a LISTofPRESENTNOTIFY */ +} xPresentPixmapReq; +#define sz_xPresentPixmapReq 72 + +typedef struct { + CARD8 reqType; + CARD8 presentReqType; + CARD16 length B16; + Window window B32; + + CARD32 serial B32; + CARD32 pad0 B32; + + CARD64 target_msc; + CARD64 divisor; + CARD64 remainder; +} xPresentNotifyMSCReq; +#define sz_xPresentNotifyMSCReq 40 + +typedef struct { + CARD8 reqType; + CARD8 presentReqType; + CARD16 length B16; + CARD32 eid B32; + CARD32 window B32; + CARD32 eventMask B32; +} xPresentSelectInputReq; +#define sz_xPresentSelectInputReq 16 + +typedef struct { + CARD8 reqType; + CARD8 presentReqType; + CARD16 length B16; + CARD32 target B32; +} xPresentQueryCapabilitiesReq; +#define sz_xPresentQueryCapabilitiesReq 8 + +typedef struct { + BYTE type; /* X_Reply */ + BYTE pad1; + CARD16 sequenceNumber B16; + CARD32 length B32; + CARD32 capabilities B32; + CARD32 pad3 B32; + CARD32 pad4 B32; + CARD32 pad5 B32; + CARD32 pad6 B32; + CARD32 pad7 B32; +} xPresentQueryCapabilitiesReply; +#define sz_xPresentQueryCapabilitiesReply 32 + +/* + * Events + * + * All Present events are X Generic Events + */ + +typedef struct { + CARD8 type; + CARD8 extension; + CARD16 sequenceNumber B16; + CARD32 length; + CARD16 evtype B16; + CARD16 pad2; + CARD32 eid B32; + CARD32 window B32; + INT16 x B16; + INT16 y B16; + CARD16 width B16; + CARD16 height B16; + INT16 off_x B16; + INT16 off_y B16; + + CARD16 pixmap_width B16; + CARD16 pixmap_height B16; + CARD32 pixmap_flags B32; +} xPresentConfigureNotify; +#define sz_xPresentConfigureNotify 40 + +typedef struct { + CARD8 type; + CARD8 extension; + CARD16 sequenceNumber B16; + CARD32 length; + CARD16 evtype B16; + CARD8 kind; + CARD8 mode; + CARD32 eid B32; + Window window B32; + CARD32 serial B32; + CARD64 ust; + + CARD64 msc; +} xPresentCompleteNotify; +#define sz_xPresentCompleteNotify 40 + +typedef struct { + CARD8 type; + CARD8 extension; + CARD16 sequenceNumber B16; + CARD32 length; + CARD16 evtype B16; + CARD16 pad2 B16; + CARD32 eid B32; + Window window B32; + CARD32 serial B32; + Pixmap pixmap B32; + CARD32 idle_fence B32; +} xPresentIdleNotify; +#define sz_xPresentIdleNotify 32 + +typedef struct { + CARD8 type; + CARD8 extension; + CARD16 sequenceNumber B16; + CARD32 length; + CARD16 evtype B16; + CARD8 update_window; + CARD8 pad1; + CARD32 eid B32; + Window event_window B32; + Window window B32; + Pixmap pixmap B32; + CARD32 serial B32; + + /* 32-byte boundary */ + + Region valid_region B32; + Region update_region B32; + + xRectangle valid_rect; + + xRectangle update_rect; + + INT16 x_off B16; + INT16 y_off B16; + CARD32 target_crtc B32; + + XSyncFence wait_fence B32; + XSyncFence idle_fence B32; + + CARD32 options B32; + CARD32 pad2 B32; + + CARD64 target_msc; + CARD64 divisor; + CARD64 remainder; + +} xPresentRedirectNotify; + +#define sz_xPresentRedirectNotify 104 + +#undef Region +#undef XSyncFence +#undef EventID + +#endif diff --git a/X11/extensions/presentproto.pc.in b/X11/extensions/presentproto.pc.in new file mode 100644 index 000000000..5d328e0a4 --- /dev/null +++ b/X11/extensions/presentproto.pc.in @@ -0,0 +1,9 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: PresentProto +Description: Present extension headers +Version: @PACKAGE_VERSION@ +Cflags: -I${includedir} diff --git a/X11/extensions/presentproto.txt b/X11/extensions/presentproto.txt new file mode 100644 index 000000000..2edcf8166 --- /dev/null +++ b/X11/extensions/presentproto.txt @@ -0,0 +1,745 @@ + The Present Extension + Version 1.0 + 2013-6-6 + + Keith Packard + keithp@keithp.com + Intel Corporation + +1. Introduction + +The Present extension provides a way for applications to update their +window contents from a pixmap in a well defined fashion, synchronizing +with the display refresh and potentially using a more efficient +mechanism than copying the contents of the source pixmap. + +1.1. Acknowledgments + +Eric Anholt +Owen Taylor +James Jones + + ❄ ❄ ❄ ❄ ❄ ❄ ❄ + +2. Data Types + +PRESENTEVENTID { XID } + + Defines a unique event delivery target for Present + events. Multiple event IDs can be allocated to provide + multiple distinct event delivery contexts. + +PRESENTNOTIFY { + window: WINDOW + serial: CARD32 + } + + A list of these is passed to PresentPixmap; when the indicated + PresentPixmap completes, PresentCompletNotify events will be + delivered both to the PresentPixmap window/serial parameter as + well as each of the entries in the list of PRESENTNOTIFY parameter. + +PRESENTEVENTTYPE { PresentConfigureNotify, + PresentCompleteNotify, + PresentIdleNotify, + PresentRedirectNotify } + +PRESENTEVENTMASK { PresentConfigureNotifyMask, + PresentCompleteNotifyMask, + PresentIdleNotifyMask, + PresentSubredirectNotifyMask } + +PRESENTOPTION { PresentOptionAsync, + PresentOptionCopy, + PresentOptionUST } + +PRESENTCAPABILITY { PresentCapabilityAsync, + PresentCapabilityFence, + PresentCapabilityUST } + +PRESENTCOMPLETEKIND { PresentCompleteKindPixmap, + PresentCompleteKindMSCNotify } + +PRESENTCOMPLETEMODE { PresentCompleteModeCopy, + PresentCompleteModeFlip, + PresentCompleteModeSkip } + +The Present extension also uses the Sync extension Fence data type to +provide synchronization for pixmaps. + + ❄ ❄ ❄ ❄ ❄ ❄ ❄ + +3. Errors + +EventID + A value for an EventID argument does not name a defined EventID + + ❄ ❄ ❄ ❄ ❄ ❄ ❄ + +5. Events + +ConfigureNotify events inform clients about window configuration +changes which can affect the allocation of window-related buffers. + +CompleteNotify events inform clients about the completion of a pending +PresentPixmap request. + +IdleNotify events inform clients when pixmaps are available for re-use. + +RedirectNotify events inform clients about other clients PresentPixmap +requests. + + ❄ ❄ ❄ ❄ ❄ ❄ ❄ + +6. Extension Initialization + +The name of this extension is "Present" + +┌─── + PresentQueryVersion + client-major-version: CARD32 + client-minor-version: CARD32 + ▶ + major-version: CARD32 + minor-version: CARD32 +└─── + + The client sends the highest supported version to the server + and the server sends the highest version it supports, but no + higher than the requested version. Major versions changes can + introduce incompatibilities in existing functionality, minor + version changes introduce only backward compatible changes. + It is the clients responsibility to ensure that the server + supports a version which is compatible with its expectations. + + Backwards compatible changes included addition of new + requests. + + ❄ ❄ ❄ ❄ ❄ ❄ ❄ + +7. Extension Requests + +┌─── + PresentPixmap + window: WINDOW + pixmap: PIXMAP + serial: CARD32 + valid-area: REGION or None + update-area: REGION or None + x-off, y-off: INT16 + target-crtc: CRTC or None + wait-fence: FENCE + idle-fence: FENCE + options: SETofPRESENTOPTION + target-msc: CARD64 + divisor: CARD64 + remainder: CARD64 + notifies: LISTofPRESENTNOTIFY +└─── + Errors: Window, Pixmap, Match + + Provides new content for the specified window, to be made + visible at the specified time (defined by 'target-msc', 'divisor' + and 'remainder'). If the depth of 'pixmap' and 'window' do not + match, a Match error will be generated. + + 'serial' is an arbitrary client-specified value which will + be returned in the associated PresentCompleteNotify event so + that the client can associate the event and request. + + 'valid-area' defines the portion of 'pixmap' which contains + valid window contents, or None if the pixmap contains valid + contents for the whole window. + + 'update-area' defines the subset of the window to be updated, + or None if the whole window is to be updated. + + PresentPixmap may use any region of 'pixmap' which contains + 'update-area' and which is contained by 'valid-area'. In other + words, areas inside 'update-area' will be presented from + 'pixmap', areas outside 'valid-area' will not be presented + from 'pixmap' and areas inside 'valid-area' but outside + 'update-area' may or may not be presented at the discretion of + the X server. + + 'x-off' and 'y-off' define the location in the window where + the 0,0 location of the pixmap will be presented. valid-area + and update-area are relative to the pixmap. + + PresentPixmap will block until 'wait-fence' is triggered. + + When the X server has finished using 'pixmap' for this + operation, it will send a PresentIdleNotify event and arrange + for any 'idle-fence' to be triggered. This may be at any time + following the PresentPixmap request -- the contents may be + immediately copied to another buffer, copied just in time for + the vblank interrupt or the pixmap may be used directly for + display (in which case it will be busy until some future + PresentPixmap operation). + + If 'idle-fence' is not None, then the client guarantees to the + X server that it will wait for that fence to be signalled + before it uses the pixmap again. If 'idle-fence' is None, then + the X server must arrange for the pixmap to be re-usable by + the client as soon as the PresentIdleNotify event has been + received. Note that if PresentCapabilityFence is set for the + associated CRTC, then clients should use fences to improve + overall systme performance. If PresentCapabilityFence is not + set, then using fences offers no benefit, but also no cost. + + If 'target-msc' is greater than the current msc for 'window', + the presentation will occur at (or after) the 'target-msc' + field. Otherwise, the presentation will occur after the next + field where msc % 'divisor' == 'remainder'. + + If 'target-crtc' is None, then the X server will choose a + suitable CRTC for synchronization. + + If 'options' contains PresentOptionAsync, and the 'target-msc' + is less than or equal to the current msc for 'window', then + the operation will be performed as soon as possible, not + necessarily waiting for the next vertical blank interval. + + If 'options' contains PresentOptionCopy, then 'pixmap' will be + idle, and 'idle-fence' triggered as soon as the operation occurs. + + If 'options' contains PresentOptionUST, then target-msc, + divisor and remainder will all be interpreted as UST values + instead of MSC values and the frame update will be scheduled + for the specified UST time, If the target-crtc supports + PresentCapabilityUST, then the swap time will be as close to + the target time as the driver can manage. Otherwise, the + server will take the target UST time and convert it to a + suitable target MSC value. + + After the presentation occurs, a PresentCompleteNotify event + with kind PresentCompleteKindPixmap will be generated, both to + 'window' as well as all members of 'notifies'. + + If 'window' is destroyed before the presentation occurs, then + the presentation action will not be completed. + + PresentPixmap holds a reference to 'pixmap' until the + presentation occurs, so 'pixmap' may be immediately freed + after the request executes, even if that is before the + presentation occurs. + + If 'idle-fence' is destroyed before the presentation occurs, + then idle-fence will not be signaled but the presentation will + occur normally. + + If 'wait-fence' is destroyed before it becomes triggered, then + the presentation operation will no longer wait for it and will + occur when the other conditions are satisfied. + +┌─── + PresentNotifyMSC + window: WINDOW + serial: CARD32 + target-msc: CARD64 + divisor: CARD64 + remainder: CARD64 +└─── + Errors: Window + + Delivers a PresentCompleteNotifyEvent with kind + PresentCompleteKindNotifyMSC after the time specified by + 'target-msc', 'divisor' and 'remainder'). + + 'serial' is an arbitrary client-specified value which will be + returned in the event so that the client can associate the + event and request. + + If 'target-msc' is greater than the current msc for 'window', + the event will be delivered at (or after) the 'target-msc' + field. Otherwise, the event delivery will occur after the next + field where msc % 'divisor' == 'remainder'. + + If 'window' is destroyed before the event is delivered, then + the event delivery will not be completed. + +┌─── + PresentSelectInput + event-id: PRESENTEVENTID + window: WINDOW + eventMask: SETofPRESENTEVENT +└─── + Errors: Window, Value, Match, IDchoice, Access + + Selects the set of Present events to be delivered for the + specified window and event context. PresentSelectInput can + create, modifiy or delete event contexts. An event context is + associated with a specific window; using an existing event + context with a different window generates a Match error. + + If eventContext specifies an existing event context, then if + eventMask is empty, PresentSelectInput deletes the specified + context, otherwise the specified event context is changed to + select a different set of events. + + If eventContext is an unused XID, then if eventMask is empty + no operation is performed. Otherwise, a new event context is + created selecting the specified events. + + Specifying PresentSubredirectNotify Mask causes PresentPixmap + requests on any child of 'window' from other clients to + generate PresentRedirectNotify events to 'window' instead of + actually performing the operation. However, only one client at + a time can select for PresentRedirect on a window. An attempt + to violate this restriction results in an Access error. + +┌─── + PresentQueryCapabilities + target: CRTC or WINDOW + ▶ + capabilities: SETofPRESENTCAPABILITY +└─── + Errors: Window, CRTC + + Returns the supported capabilities for the target CRTC. If + 'target' is a CRTC, then it is used as the target CRTC. If + 'target' is a WINDOW, then the target CRTC is selected by the + X server from among the CRTCs on the screen specified by the window. + + PresentCapabilityAsync means that the target device can flip + the scanout buffer mid-frame instead of waiting for a vertical + blank interval. The precise latency between the flip request + and the actual scanout transition is not defined by this + specification, but is intended to be no more than a few + scanlines. + + PresentCapabilityFence means that the target device can take + advantage of SyncFences in the Present operations to improve + GPU throughput. The driver must operate correctly in the + absense of fences, but may have reduced performance. Using + fences for drivers not advertising this capability should have + no performance impact. + + PresentCapabilityUST means that the target device can scanout + the image at an arbitrary UST time value, and is not driven by + a periodic scanout timer. Applications specifying UST times + for PresentPixmap can expect that their image will appear to + the user within a short amount of time from that specified in + the request. The precise accuracy of the scanout time is not + defined by the extension, but is expected to be on the order + of milliseconds or less. + + ❄ ❄ ❄ ❄ ❄ ❄ ❄ + +8. Extension Events + +┌─── + PresentConfigureNotify + type: CARD8 XGE event type (35) + extension: CARD8 Present extension request number + sequence-number: CARD16 + length: CARD32 2 + evtype: CARD16 Present_ConfigureNotify + eventID: PRESENTEVENTID + window: WINDOW + x: INT16 + y: INT16 + width: CARD16 + height: CARD16 + off_x: INT16 + off_y: INT16 + pixmap_width: CARD16 + pixmap_height: CARD16 + pixmap_flags: CARD32 +└─── + + PresentConfigureNotify events are sent when the window + configuration changes if PresentSelectInput has requested + it. PresentConfigureNotify events are XGE events and so do not + have a unique event type. + + 'x' and 'y' are the parent-relative location of 'window'. + +┌─── + PresentCompleteNotify + type: CARD8 XGE event type (35) + extension: CARD8 Present extension request number + sequence-number: CARD16 + length: CARD32 2 + evtype: PRESENTEVENTTYPE PresentCompleteNotify + eventID: PRESENTEVENTID + window: WINDOW + kind: PRESENTCOMPLETEKIND + mode: PRESENTCOMPLETEMODE + serial: CARD32 + ust: CARD64 + msc: CARD64 +└─── + + CompleteNotify events are delivered when a PresentPixmap or + PresentNotifyMSC operation has completed. + + 'kind' is PresentCompleteKindPixmap when generated by a + PresentPixmap operation completion or + PresentCompleteKindNotifyMsc when generated by a + PresentNotifyMSC operation completion. + + 'mode' is PresentCompleteModeCopy when the source pixmap + contents are taken from the pixmap and the pixmap is idle + immediately after the presentation completes. 'mode' is + PresentCompleteModeFlip when the pixmap remains in-use even + after the presentation completes. It will become idle no later + than when the next PresentPixmap operation targeting the same + window by any client completes. If the presentation operation + was skipped because some later operation made it irrelevant, + then 'mode' will be PresentCompleteModeSkip. + + 'serial' is the value provided in the generating PresentPixmap + request. + + 'msc' and 'ust' indicate the frame count and system time when + the presentation actually occurred. + +┌─── + PresentIdleNotify + type: CARD8 XGE event type (35) + extension: CARD8 Present extension request number + sequence-number: CARD16 + length: CARD32 0 + evtype: PRESENTEVENTTYPE PresentIdleNotify + eventID: PRESENTEVENTID + window: WINDOW + serial: CARD32 + pixmap: PIXMAP + idle-fence: FENCE +└─── + + IdleNotify events are delivered when a pixmap used in a + PresentPixmap operation may be re-used by the client. + + 'window' is the window from the PresentPixmap to which this + event is delivered. + + 'serial' is the value provided in the associated PresentPixmap + request. + + 'pixmap' is the pixmap which is ready for re-use. + + 'idle-fence' is the fence which was provided in the + originating PresentPixmap request and is used to synchronize + rendering between the client and the X server's use of the + buffer. If not None, then the client must wait for the fence + to be signaled before using the pixmap. + +┌─── + PresentRedirectNotify + type: CARD8 XGE event type (35) + extension: CARD8 Present extension request number + sequence-number: CARD16 + length: CARD32 17 + 2 n + evtype: CARD16 Present_RedirectNotify + update-window: BOOL + + eventID: PRESENTEVENTID + event-window: WINDOW + window: WINDOW + pixmap: PIXMAP + serial: CARD32 + + valid-area: REGION + update-area: REGION + valid-rect: RECTANGLE + update-rect: RECTANGLE + x-off, y-off: INT16 + target-crtc: CRTC + wait-fence: FENCE + idle-fence: FENCE + options: SETofPRESENTOPTION + target-msc: CARD64 + divisor: CARD64 + remainder: CARD64 + notifies: LISTofPRESENTNOTIFY +└─── + + RedirectNotify events are delivered when the client has + selected for SubredirectNotify the parent of the target + window. All of the values provided to the PresentPixmap + request are provided. If the client simply passes these + parameters back to the X server, the effect will be as if the + original client executed the request. + + If 'update-window' is TRUE, then there are clients who have + requested composite automatic redirect on the window and who + presumably expect the window buffer to eventually contain + the application provided contents. The compositing manager + should at least occasionally update the window buffer with + suitable contents. The precise update interval is left to the + discretion of the client receiving this event. + + ❄ ❄ ❄ ❄ ❄ ❄ ❄ + +9. Extension Versioning + + 1.0: First published version + + ❄ ❄ ❄ ❄ ❄ ❄ ❄ + + +10. Relationship with other extensions + +As an extension designed to support other extensions, there is +naturally some interactions with other extensions. + +10.1 GLX + +GLX is both an application interface and an X extension. OpenGL +applications using the GLX API will use the GLX extension and may use +the Present extension to display application contents. + +10.2 DRI3 + +The DRI3 extension provides a way to share direct rendered pixel data +with the X server as X pixmaps. When used in conjunction with Present, +they provide a complete direct rendering solution for OpenGL or other +APIs. + +10.3 DRI2 + +Present provides similar functionality to the DRI2SwapBuffers and +requests, however Present uses X pixmaps to refer to the new window +contents instead of the DRI2 buffer attachments. + +Present and DRI3 are designed in conjunction to replace DRI2 + +10.4 XvMC / Xv + +It might be nice to be able to use YUV formatted objects as Present +sources. + + ❄ ❄ ❄ ❄ ❄ ❄ ❄ + +Appendix A. Protocol Encoding + +Syntactic Conventions + +This document uses the same syntactic conventions as the core X +protocol encoding document. + + +A.1 Common Types +┌─── + PresentEventType + 0 PresentConfigureNotify + 1 PresentCompleteNotify + 2 PresentIdleNotify + 3 PresentRedirectNotify +└─── + +┌─── + PresentEventMask + 1 PresentConfigureNotifyMask + 2 PresentCompleteNotifyMask + 4 PresentIdleNotifyMask + 8 PresentRedirectNotifyMask +└─── + +┌─── + PresentOption + 1 PresentOptionAsync + 2 PresentOptionCopy; + 4 PresentOptionUST +└─── + +┌─── + PresentCapability + 1 PresentCapabilityAsync + 2 PresentCapabilityFence + 4 PresentCapabilityUST +└─── + +┌─── + PresentCompleteKind + 0 PresentCompleteKindPixmap + 1 PresentCompleteKindMSCNotify +└─── + +┌─── + PresentCompleteMode + 0 PresentCompleteModeCopy + 1 PresentCompleteModeFlip + 2 PresentCompleteModeSkip +└─── + +┌─── + PresentNotify + 4 Window window + 4 CARD32 serial +└─── + +A.2 Protocol Requests + +┌─── + PresentQueryVersion + 1 CARD8 major opcode + 1 0 Present opcode + 2 3 length + 4 CARD32 major version + 4 CARD32 minor version + ▶ + 1 1 Reply + 1 unused + 2 CARD16 sequence number + 4 0 reply length + 4 CARD32 major version + 4 CARD32 minor version + 16 unused +└─── + +┌─── + PresentPixmap + 1 CARD8 major opcode + 1 1 Present opcode + 2 18+2n length + 4 Window window + 4 Pixmap pixmap + 4 CARD32 serial + 4 Region valid-area + 4 Region update-area + 2 INT16 x-off + 2 INT16 y-off + 4 CRTC target-crtc + 4 SyncFence wait-fence + 4 SyncFence idle-fence + 4 CARD32 options + 4 unused + 8 CARD64 target-msc + 8 CARD64 divisor + 8 CARD64 remainder + 8n LISTofPresentNotify notifies +└─── + +┌─── + PresentNotifyMSC + 1 CARD8 major opcode + 1 2 Present opcode + 2 10 length + 4 Window window + 4 CARD32 serial + 4 unused + 8 CARD64 target-msc + 8 CARD64 divisor + 8 CARD64 remainder +└─── + +┌─── + PresentSelectInput + 1 CARD8 major opcode + 1 3 Present opcode + 2 4 length + 4 EventID event-id + 4 Window window + 4 SETofPRESENTEVENTMASK event-mask +└─── + +┌─── + PresentQueryCapabilities + 1 CARD8 major opcode + 1 4 Present opcode + 2 2 length + 4 CRTC or Window target + ▶ + 1 1 Reply + 1 unused + 2 CARD16 sequence number + 4 0 reply length + 4 SETofPRESENTCAPABILITY capabilities +└─── + +A.3 Protocol Events + +┌─── + PresentConfigureNotify + 1 35 XGE + 1 CARD8 Present extension opcode + 2 CARD16 sequence number + 4 2 length + 2 0 PresentConfigureNotify + 2 unused + 4 CARD32 event id + 4 Window window + 2 INT16 x + 2 INT16 y + 2 CARD16 width + 2 CARD16 height + 2 INT16 off x + 2 INT16 off y + + 2 CARD16 pixmap width + 2 CARD16 pixmap height + 4 CARD32 pixmap flags +└─── + +┌─── + PresentCompleteNotify + 1 35 XGE + 1 CARD8 Present extension opcode + 2 CARD16 sequence number + 4 2 length + 2 1 PresentCompleteNotify + 1 CARD8 kind + 1 CARD8 mode + 4 CARD32 event id + 4 Window window + 4 CARD32 serial + 8 CARD64 ust + + 8 CARD64 msc +└─── + +┌─── + PresentIdleNotify + 1 35 XGE + 1 CARD8 Present extension opcode + 2 CARD16 sequence number + 4 0 length + 2 2 PresentIdleNotify + 2 unused + 4 CARD32 event id + 4 Window window + 4 CARD32 serial + 4 Pixmap pixmap + 4 SyncFence idle-fence +└─── + +┌─── + PresentRedirectNotify + 1 35 XGE + 1 CARD8 Present extension opcode + 2 CARD16 sequence number + 4 18+2n length + 2 3 PresentRedirectNotify + 1 BOOL update-window + 1 unused + 4 CARD32 event id + 4 Window event-window + 4 Window window + 4 Pixmap pixmap + 4 CARD32 serial + + 4 Region valid-area + 4 Region update-area + 8 Rectangle valid-rect + 8 Rectangle update-rect + 2 INT16 x-off + 2 INT16 y-off + 4 CRTC target-crtc + 4 SyncFence wait-fence + 4 SyncFence idle-fence + 4 CARD32 options + 4 unused + 8 CARD64 target-msc + 8 CARD64 divisor + 8 CARD64 remainder + 8n LISTofPRESENTNOTIFY notifies +└─── + +A.4 Protocol Errors + +The DRI3 extension defines no errors. + + ❄ ❄ ❄ ❄ ❄ ❄ ❄ diff --git a/X11/extensions/presenttokens.h b/X11/extensions/presenttokens.h new file mode 100644 index 000000000..807dbcfa5 --- /dev/null +++ b/X11/extensions/presenttokens.h @@ -0,0 +1,91 @@ +/* + * 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_TOKENS_H_ +#define _PRESENT_TOKENS_H_ + +#define PRESENT_NAME "Present" +#define PRESENT_MAJOR 1 +#define PRESENT_MINOR 0 + +#define PresentNumberErrors 0 +#define PresentNumberEvents 0 + +/* Requests */ +#define X_PresentQueryVersion 0 +#define X_PresentPixmap 1 +#define X_PresentNotifyMSC 2 +#define X_PresentSelectInput 3 +#define X_PresentQueryCapabilities 4 + +#define PresentNumberRequests 5 + +/* Present operation options */ +#define PresentOptionNone 0 +#define PresentOptionAsync (1 << 0) +#define PresentOptionCopy (1 << 1) +#define PresentOptionUST (1 << 2) + +#define PresentAllOptions (PresentOptionAsync | \ + PresentOptionCopy | \ + PresentOptionUST) + +/* Present capabilities */ + +#define PresentCapabilityNone 0 +#define PresentCapabilityAsync 1 +#define PresentCapabilityFence 2 +#define PresentCapabilityUST 4 + +#define PresentAllCapabilities (PresentCapabilityAsync | \ + PresentCapabilityFence | \ + PresentCapabilityUST) + +/* Events */ +#define PresentConfigureNotify 0 +#define PresentCompleteNotify 1 +#define PresentIdleNotify 2 +#define PresentRedirectNotify 3 + +/* Event Masks */ +#define PresentConfigureNotifyMask 1 +#define PresentCompleteNotifyMask 2 +#define PresentIdleNotifyMask 4 +#define PresentRedirectNotifyMask 8 + +#define PresentAllEvents (PresentConfigureNotifyMask | \ + PresentCompleteNotifyMask | \ + PresentIdleNotifyMask | \ + PresentRedirectNotifyMask) + +/* Complete Kinds */ + +#define PresentCompleteKindPixmap 0 +#define PresentCompleteKindNotifyMSC 1 + +/* Complete Modes */ + +#define PresentCompleteModeCopy 0 +#define PresentCompleteModeFlip 1 +#define PresentCompleteModeSkip 2 + +#endif diff --git a/packages.txt b/packages.txt index f0f66f826..4eae1625c 100644 --- a/packages.txt +++ b/packages.txt @@ -68,6 +68,7 @@ mesa git version mkfontscale git version openssl-1.0.1e pixman git version +presentproto-1.0 pthreads-w32 cvs version randrproto git version recordproto-1.14.2 -- cgit v1.2.3