diff options
126 files changed, 5280 insertions, 373 deletions
diff --git a/X11/xtrans/Xtrans.c b/X11/xtrans/Xtrans.c index 0799f0468..7c7967f5d 100644 --- a/X11/xtrans/Xtrans.c +++ b/X11/xtrans/Xtrans.c @@ -866,17 +866,22 @@ TRANS(Write) (XtransConnInfo ciptr, char *buf, int size) } int -TRANS(Readv) (XtransConnInfo ciptr, struct iovec *buf, int size) +TRANS(Writev) (XtransConnInfo ciptr, struct iovec *buf, int size) { - return ciptr->transptr->Readv (ciptr, buf, size); + return ciptr->transptr->Writev (ciptr, buf, size); } int -TRANS(Writev) (XtransConnInfo ciptr, struct iovec *buf, int size) +TRANS(SendFd) (XtransConnInfo ciptr, int fd, int do_close) +{ + return ciptr->transptr->SendFd(ciptr, fd, do_close); +} +int +TRANS(RecvFd) (XtransConnInfo ciptr) { - return ciptr->transptr->Writev (ciptr, buf, size); + return ciptr->transptr->RecvFd(ciptr); } int diff --git a/X11/xtrans/Xtrans.h b/X11/xtrans/Xtrans.h index 2945b2aba..53b8b627d 100644 --- a/X11/xtrans/Xtrans.h +++ b/X11/xtrans/Xtrans.h @@ -344,18 +344,16 @@ int TRANS(Write)( int /* size */ ); -int TRANS(Readv)( - XtransConnInfo, /* ciptr */ - struct iovec *, /* buf */ - int /* size */ -); - int TRANS(Writev)( XtransConnInfo, /* ciptr */ struct iovec *, /* buf */ int /* size */ ); +int TRANS(SendFd) (XtransConnInfo ciptr, int fd, int do_close); + +int TRANS(RecvFd) (XtransConnInfo ciptr); + int TRANS(Disconnect)( XtransConnInfo /* ciptr */ ); diff --git a/X11/xtrans/Xtransint.h b/X11/xtrans/Xtransint.h index 3bce8dc6b..dd886db87 100644 --- a/X11/xtrans/Xtransint.h +++ b/X11/xtrans/Xtransint.h @@ -72,6 +72,8 @@ from The Open Group. # define XTRANSDEBUG 1 #endif +#define XTRANS_SEND_FDS 1 + #ifdef WIN32 # define _WILLWINSOCK_ #endif @@ -123,6 +125,16 @@ from The Open Group. #define X_TCP_PORT 6000 #endif +#if XTRANS_SEND_FDS + +struct _XtransConnFd { + struct _XtransConnFd *next; + int fd; + int do_close; +}; + +#endif + struct _XtransConnInfo { struct _Xtransport *transptr; int index; @@ -135,6 +147,8 @@ struct _XtransConnInfo { int addrlen; char *peeraddr; int peeraddrlen; + struct _XtransConnFd *recv_fds; + struct _XtransConnFd *send_fds; }; #define XTRANS_OPEN_COTS_CLIENT 1 @@ -275,6 +289,16 @@ typedef struct _Xtransport { int /* size */ ); + int (*SendFd)( + XtransConnInfo, /* connection */ + int, /* fd */ + int /* do_close */ + ); + + int (*RecvFd)( + XtransConnInfo /* connection */ + ); + int (*Disconnect)( XtransConnInfo /* connection */ ); diff --git a/X11/xtrans/Xtranssock.c b/X11/xtrans/Xtranssock.c index 24269b241..23150b259 100644 --- a/X11/xtrans/Xtranssock.c +++ b/X11/xtrans/Xtranssock.c @@ -2097,47 +2097,176 @@ TRANS(SocketBytesReadable) (XtransConnInfo ciptr, BytesReadable_t *pend) #endif /* WIN32 */ } +#if XTRANS_SEND_FDS + +static void +appendFd(struct _XtransConnFd **prev, int fd, int do_close) +{ + struct _XtransConnFd *cf, *new; + + new = malloc (sizeof (struct _XtransConnFd)); + if (!new) { + /* XXX mark connection as broken */ + close(fd); + return; + } + new->next = 0; + new->fd = fd; + new->do_close = do_close; + /* search to end of list */ + for (; (cf = *prev); prev = &(cf->next)); + *prev = new; +} static int -TRANS(SocketRead) (XtransConnInfo ciptr, char *buf, int size) +removeFd(struct _XtransConnFd **prev) +{ + struct _XtransConnFd *cf; + int fd; + + if ((cf = *prev)) { + *prev = cf->next; + fd = cf->fd; + free(cf); + } else + fd = -1; + return fd; +} +static void +discardFd(struct _XtransConnFd **prev, struct _XtransConnFd *upto, int do_close) { - prmsg (2,"SocketRead(%d,%p,%d)\n", ciptr->fd, buf, size); + struct _XtransConnFd *cf, *next; -#if defined(WIN32) - { - int ret = recv ((SOCKET)ciptr->fd, buf, size, 0); -#ifdef WIN32 - if (ret == SOCKET_ERROR) errno = WSAGetLastError(); -#endif - return ret; + for (cf = *prev; cf != upto; cf = next) { + next = cf->next; + if (do_close || cf->do_close) + close(cf->fd); + free(cf); } -#else - return read (ciptr->fd, buf, size); -#endif /* WIN32 */ + *prev = upto; } +static void +cleanupFds(XtransConnInfo ciptr) +{ + /* Clean up the send list but don't close the fds */ + discardFd(&ciptr->send_fds, NULL, 0); + /* Clean up the recv list and *do* close the fds */ + discardFd(&ciptr->recv_fds, NULL, 1); +} static int -TRANS(SocketWrite) (XtransConnInfo ciptr, char *buf, int size) +nFd(struct _XtransConnFd **prev) +{ + struct _XtransConnFd *cf; + int n = 0; + + for (cf = *prev; cf; cf = cf->next) + n++; + return n; +} + +static int +TRANS(SocketRecvFd) (XtransConnInfo ciptr) +{ + prmsg (2, "SocketRecvFd(%d)\n", ciptr->fd); + return removeFd(&ciptr->recv_fds); +} +static int +TRANS(SocketSendFd) (XtransConnInfo ciptr, int fd, int do_close) { - prmsg (2,"SocketWrite(%d,%p,%d)\n", ciptr->fd, buf, size); + appendFd(&ciptr->send_fds, fd, do_close); + return 0; +} + +static int +TRANS(SocketRecvFdInvalid)(XtransConnInfo ciptr) +{ + errno = EINVAL; + return -1; +} + +static int +TRANS(SocketSendFdInvalid)(XtransConnInfo ciptr, int fd, int do_close) +{ + errno = EINVAL; + return -1; +} + +#define MAX_FDS 128 + +struct fd_pass { + struct cmsghdr cmsghdr; + int fd[MAX_FDS]; +}; + +static inline void init_msg_recv(struct msghdr *msg, struct iovec *iov, int niov, struct fd_pass *pass, int nfd) { + msg->msg_name = NULL; + msg->msg_namelen = 0; + msg->msg_iov = iov; + msg->msg_iovlen = niov; + msg->msg_control = pass; + msg->msg_controllen = sizeof (struct cmsghdr) + nfd * sizeof (int); +} + +static inline void init_msg_send(struct msghdr *msg, struct iovec *iov, int niov, struct fd_pass *pass, int nfd) { + init_msg_recv(msg, iov, niov, pass, nfd); + pass->cmsghdr.cmsg_len = msg->msg_controllen; + pass->cmsghdr.cmsg_level = SOL_SOCKET; + pass->cmsghdr.cmsg_type = SCM_RIGHTS; +} + +#endif /* XTRANS_SEND_FDS */ + +static int +TRANS(SocketRead) (XtransConnInfo ciptr, char *buf, int size) + +{ + prmsg (2,"SocketRead(%d,%p,%d)\n", ciptr->fd, buf, size); #if defined(WIN32) { - int ret = send ((SOCKET)ciptr->fd, buf, size, 0); + int ret = recv ((SOCKET)ciptr->fd, buf, size, 0); #ifdef WIN32 if (ret == SOCKET_ERROR) errno = WSAGetLastError(); #endif return ret; } #else - return write (ciptr->fd, buf, size); +#if XTRANS_SEND_FDS + { + struct msghdr msg; + struct iovec iov; + struct fd_pass pass; + + iov.iov_base = buf; + iov.iov_len = size; + + init_msg_recv(&msg, &iov, 1, &pass, MAX_FDS); + size = recvmsg(ciptr->fd, &msg, 0); + if (size >= 0 && msg.msg_controllen > sizeof (struct cmsghdr)) { + if (pass.cmsghdr.cmsg_level == SOL_SOCKET && + pass.cmsghdr.cmsg_type == SCM_RIGHTS && + !((msg.msg_flags & MSG_TRUNC) || + (msg.msg_flags & MSG_CTRUNC))) + { + int nfd = (msg.msg_controllen - sizeof (struct cmsghdr)) / sizeof (int); + int *fd = (int *) CMSG_DATA(&pass.cmsghdr); + int i; + for (i = 0; i < nfd; i++) + appendFd(&ciptr->recv_fds, fd[i], 0); + } + } + return size; + } +#else + return read(ciptr->fd, buf, size); +#endif /* XTRANS_SEND_FDS */ #endif /* WIN32 */ } - static int TRANS(SocketReadv) (XtransConnInfo ciptr, struct iovec *buf, int size) @@ -2154,11 +2283,65 @@ TRANS(SocketWritev) (XtransConnInfo ciptr, struct iovec *buf, int size) { prmsg (2,"SocketWritev(%d,%p,%d)\n", ciptr->fd, buf, size); +#if XTRANS_SEND_FDS + if (ciptr->send_fds) + { + struct msghdr msg; + struct fd_pass pass; + int nfd; + struct _XtransConnFd *cf; + int i; + + nfd = nFd(&ciptr->send_fds); + cf = ciptr->send_fds; + + /* Set up fds */ + for (i = 0; i < nfd; i++) { + pass.fd[i] = cf->fd; + cf = cf->next; + } + + init_msg_send(&msg, buf, size, &pass, nfd); + i = sendmsg(ciptr->fd, &msg, 0); + if (i > 0) + discardFd(&ciptr->send_fds, cf, 0); + return i; + } +#endif return WRITEV (ciptr, buf, size); } static int +TRANS(SocketWrite) (XtransConnInfo ciptr, char *buf, int size) + +{ + prmsg (2,"SocketWrite(%d,%p,%d)\n", ciptr->fd, buf, size); + +#if defined(WIN32) + { + int ret = send ((SOCKET)ciptr->fd, buf, size, 0); +#ifdef WIN32 + if (ret == SOCKET_ERROR) errno = WSAGetLastError(); +#endif + return ret; + } +#else +#if XTRANS_SEND_FDS + if (ciptr->send_fds) + { + struct iovec iov; + + iov.iov_base = buf; + iov.iov_len = size; + return TRANS(SocketWritev)(ciptr, &iov, 1); + } +#endif /* XTRANS_SEND_FDS */ + return write (ciptr->fd, buf, size); +#endif /* WIN32 */ +} + +static int TRANS(SocketDisconnect) (XtransConnInfo ciptr) { @@ -2211,6 +2394,9 @@ TRANS(SocketUNIXClose) (XtransConnInfo ciptr) prmsg (2,"SocketUNIXClose(%p,%d)\n", ciptr, ciptr->fd); +#if XTRANS_SEND_FDS + cleanupFds(ciptr); +#endif ret = close(ciptr->fd); if (ciptr->flags @@ -2239,6 +2425,9 @@ TRANS(SocketUNIXCloseForCloning) (XtransConnInfo ciptr) prmsg (2,"SocketUNIXCloseForCloning(%p,%d)\n", ciptr, ciptr->fd); +#if XTRANS_SEND_FDS + cleanupFds(ciptr); +#endif ret = close(ciptr->fd); return ret; @@ -2293,6 +2482,8 @@ Xtransport TRANS(SocketTCPFuncs) = { TRANS(SocketWrite), TRANS(SocketReadv), TRANS(SocketWritev), + TRANS(SocketSendFdInvalid), + TRANS(SocketRecvFdInvalid), TRANS(SocketDisconnect), TRANS(SocketINETClose), TRANS(SocketINETClose), @@ -2333,6 +2524,8 @@ Xtransport TRANS(SocketINETFuncs) = { TRANS(SocketWrite), TRANS(SocketReadv), TRANS(SocketWritev), + TRANS(SocketSendFdInvalid), + TRANS(SocketRecvFdInvalid), TRANS(SocketDisconnect), TRANS(SocketINETClose), TRANS(SocketINETClose), @@ -2374,6 +2567,8 @@ Xtransport TRANS(SocketINET6Funcs) = { TRANS(SocketWrite), TRANS(SocketReadv), TRANS(SocketWritev), + TRANS(SocketSendFdInvalid), + TRANS(SocketRecvFdInvalid), TRANS(SocketDisconnect), TRANS(SocketINETClose), TRANS(SocketINETClose), @@ -2422,6 +2617,8 @@ Xtransport TRANS(SocketLocalFuncs) = { TRANS(SocketWrite), TRANS(SocketReadv), TRANS(SocketWritev), + TRANS(SocketSendFd), + TRANS(SocketRecvFd), TRANS(SocketDisconnect), TRANS(SocketUNIXClose), TRANS(SocketUNIXCloseForCloning), @@ -2476,6 +2673,8 @@ Xtransport TRANS(SocketUNIXFuncs) = { TRANS(SocketWrite), TRANS(SocketReadv), TRANS(SocketWritev), + TRANS(SocketSendFd), + TRANS(SocketRecvFd), TRANS(SocketDisconnect), TRANS(SocketUNIXClose), TRANS(SocketUNIXCloseForCloning), diff --git a/X11/xtrans/configure.ac b/X11/xtrans/configure.ac index cc3c006ae..8c3aa3ded 100644 --- a/X11/xtrans/configure.ac +++ b/X11/xtrans/configure.ac @@ -21,7 +21,7 @@ # Initialize Autoconf AC_PREREQ([2.60]) -AC_INIT([xtrans], [1.2.7], +AC_INIT([xtrans], [1.3.0], [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], [xtrans]) AC_CONFIG_SRCDIR([Makefile.am]) diff --git a/fontconfig/fonts.dtd b/fontconfig/fonts.dtd index 4c38e77f0..479f2c0fb 100644 --- a/fontconfig/fonts.dtd +++ b/fontconfig/fonts.dtd @@ -140,7 +140,7 @@ if 'target' is 'font', execute the match on the result of a font selection. --> -<!ELEMENT match (test*, edit*)+> +<!ELEMENT match (test|edit)+> <!ATTLIST match target (pattern|font|scan) "pattern"> diff --git a/fontconfig/src/fcxml.c b/fontconfig/src/fcxml.c index 8ff10b6e6..bd95580aa 100644 --- a/fontconfig/src/fcxml.c +++ b/fontconfig/src/fcxml.c @@ -2566,6 +2566,11 @@ FcParseMatch (FcConfigParse *parse) } FcVStackPopAndDestroy (parse); } + if (!rule) + { + FcConfigMessage (parse, FcSevereWarning, "No <test> nor <edit> elements in <match>"); + return; + } if (!FcConfigAddRule (parse->config, rule, kind)) FcConfigMessage (parse, FcSevereError, "out of memory"); } diff --git a/mesalib/configure.ac b/mesalib/configure.ac index f94c9b979..0a250471e 100644 --- a/mesalib/configure.ac +++ b/mesalib/configure.ac @@ -1771,7 +1771,7 @@ if test "x$with_gallium_drivers" != x; then PKG_CHECK_MODULES([RADEON], [libdrm_radeon >= $LIBDRM_RADEON_REQUIRED]) gallium_require_llvm "Gallium R300" GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS r300" - gallium_check_st "radeon/drm" "r300/dri" "" "" "r300/xvmc" "r300/vdpau" + gallium_check_st "radeon/drm" "r300/dri" "" "" "" "" DRICOMMON_NEED_LIBDRM=yes ;; xr600) @@ -1789,7 +1789,7 @@ if test "x$with_gallium_drivers" != x; then if test "x$enable_opencl" = xyes; then LLVM_COMPONENTS="${LLVM_COMPONENTS} bitreader asmparser" fi - gallium_check_st "radeon/drm" "r600/dri" "r600/xorg" "" "r600/xvmc" "r600/vdpau" + gallium_check_st "radeon/drm" "r600/dri" "" "" "r600/xvmc" "r600/vdpau" DRICOMMON_NEED_LIBDRM=yes ;; xradeonsi) @@ -1798,7 +1798,7 @@ if test "x$with_gallium_drivers" != x; then gallium_require_drm_loader GALLIUM_DRIVERS_DIRS="$GALLIUM_DRIVERS_DIRS radeonsi" radeon_llvm_check - gallium_check_st "radeon/drm" "radeonsi/dri" "radeonsi/xorg" "" "" "radeonsi/vdpau" "" + gallium_check_st "radeon/drm" "radeonsi/dri" "" "" "" "radeonsi/vdpau" "" DRICOMMON_NEED_LIBDRM=yes ;; xnouveau) @@ -1828,16 +1828,6 @@ if test "x$with_gallium_drivers" != x; then if test "x$enable_dri" = xyes; then GALLIUM_TARGET_DIRS="$GALLIUM_TARGET_DIRS dri-swrast" fi - if test "x$enable_vdpau" = xyes; then - GALLIUM_TARGET_DIRS="$GALLIUM_TARGET_DIRS vdpau-softpipe" - fi - if test "x$enable_xvmc" = xyes; then - GALLIUM_TARGET_DIRS="$GALLIUM_TARGET_DIRS xvmc-softpipe" - fi - if test "x$enable_vdpau" = xyes -o "x$enable_xvmc" = xyes; then - NEED_WINSYS_XLIB=yes - GALLIUM_WINSYS_DIRS="$GALLIUM_WINSYS_DIRS sw/xlib" - fi ;; *) AC_MSG_ERROR([Unknown Gallium driver: $driver]) @@ -2044,23 +2034,17 @@ AC_CONFIG_FILES([Makefile src/gallium/targets/pipe-loader/Makefile src/gallium/targets/radeonsi/dri/Makefile src/gallium/targets/radeonsi/vdpau/Makefile - src/gallium/targets/radeonsi/xorg/Makefile src/gallium/targets/r300/dri/Makefile - src/gallium/targets/r300/vdpau/Makefile - src/gallium/targets/r300/xvmc/Makefile src/gallium/targets/r600/dri/Makefile src/gallium/targets/r600/vdpau/Makefile - src/gallium/targets/r600/xorg/Makefile src/gallium/targets/r600/xvmc/Makefile src/gallium/targets/libgl-xlib/Makefile src/gallium/targets/vdpau-nouveau/Makefile - src/gallium/targets/vdpau-softpipe/Makefile src/gallium/targets/xa-vmwgfx/Makefile src/gallium/targets/xa-vmwgfx/xatracker.pc src/gallium/targets/xorg-i915/Makefile src/gallium/targets/xorg-nouveau/Makefile src/gallium/targets/xvmc-nouveau/Makefile - src/gallium/targets/xvmc-softpipe/Makefile src/gallium/tests/trivial/Makefile src/gallium/tests/unit/Makefile src/gallium/winsys/Makefile diff --git a/mesalib/docs/relnotes/10.0.html b/mesalib/docs/relnotes/10.0.html index ef550d154..5ff53398e 100644 --- a/mesalib/docs/relnotes/10.0.html +++ b/mesalib/docs/relnotes/10.0.html @@ -49,6 +49,7 @@ Note: some of the new features are only available with certain drivers. <li>GL_ARB_texture_gather on i965.</li> <li>GL_ARB_texture_query_levels on i965.</li> <li>GL_ARB_texture_mirror_clamp_to_edge.</li> +<li>GL_ARB_transform_feedback2, GL_ARB_transform_feedback3, and GL_ARB_transform_feedback_instanced on i965/Gen7 (with appropriate kernel support).</li> <li>GL_KHR_debug</li> </ul> diff --git a/mesalib/src/glsl/Makefile.sources b/mesalib/src/glsl/Makefile.sources index 2f7bfa163..2aabc0585 100644 --- a/mesalib/src/glsl/Makefile.sources +++ b/mesalib/src/glsl/Makefile.sources @@ -83,6 +83,7 @@ LIBGLSL_FILES = \ $(GLSL_SRCDIR)/opt_constant_variable.cpp \ $(GLSL_SRCDIR)/opt_copy_propagation.cpp \ $(GLSL_SRCDIR)/opt_copy_propagation_elements.cpp \ + $(GLSL_SRCDIR)/opt_cse.cpp \ $(GLSL_SRCDIR)/opt_dead_builtin_varyings.cpp \ $(GLSL_SRCDIR)/opt_dead_code.cpp \ $(GLSL_SRCDIR)/opt_dead_code_local.cpp \ diff --git a/mesalib/src/glsl/builtin_variables.cpp b/mesalib/src/glsl/builtin_variables.cpp index 7a3505ace..4d441045a 100644 --- a/mesalib/src/glsl/builtin_variables.cpp +++ b/mesalib/src/glsl/builtin_variables.cpp @@ -30,6 +30,9 @@ #include "program/prog_statevars.h" #include "program/prog_instruction.h" +static struct gl_builtin_uniform_element gl_NumSamples_elements[] = { + {NULL, {STATE_NUM_SAMPLES, 0, 0}, SWIZZLE_XXXX} +}; static struct gl_builtin_uniform_element gl_DepthRange_elements[] = { {"near", {STATE_DEPTH_RANGE, 0, 0}, SWIZZLE_XXXX}, @@ -236,6 +239,7 @@ static struct gl_builtin_uniform_element gl_NormalMatrix_elements[] = { #define STATEVAR(name) {#name, name ## _elements, Elements(name ## _elements)} static const struct gl_builtin_uniform_desc _mesa_builtin_uniform_desc[] = { + STATEVAR(gl_NumSamples), STATEVAR(gl_DepthRange), STATEVAR(gl_ClipPlane), STATEVAR(gl_Point), @@ -662,6 +666,7 @@ builtin_variable_generator::generate_constants() void builtin_variable_generator::generate_uniforms() { + add_uniform(int_t, "gl_NumSamples"); add_uniform(type("gl_DepthRangeParameters"), "gl_DepthRange"); add_uniform(array(vec4_t, VERT_ATTRIB_MAX), "gl_CurrentAttribVertMESA"); add_uniform(array(vec4_t, VARYING_SLOT_MAX), "gl_CurrentAttribFragMESA"); @@ -838,6 +843,19 @@ builtin_variable_generator::generate_fs_special_vars() if (state->AMD_shader_stencil_export_warn) var->warn_extension = "GL_AMD_shader_stencil_export"; } + + if (state->ARB_sample_shading_enable) { + add_system_value(SYSTEM_VALUE_SAMPLE_ID, int_t, "gl_SampleID"); + add_system_value(SYSTEM_VALUE_SAMPLE_POS, vec2_t, "gl_SamplePosition"); + /* From the ARB_sample_shading specification: + * "The number of elements in the array is ceil(<s>/32), where + * <s> is the maximum number of color samples supported by the + * implementation." + * Since no drivers expose more than 32x MSAA, we can simply set + * the array size to 1 rather than computing it. + */ + add_output(FRAG_RESULT_SAMPLE_MASK, array(int_t, 1), "gl_SampleMask"); + } } diff --git a/mesalib/src/glsl/glcpp/glcpp-parse.y b/mesalib/src/glsl/glcpp/glcpp-parse.y index 86f3cd5aa..7edc27488 100644 --- a/mesalib/src/glsl/glcpp/glcpp-parse.y +++ b/mesalib/src/glsl/glcpp/glcpp-parse.y @@ -1249,6 +1249,9 @@ glcpp_parser_create (const struct gl_extensions *extensions, int api) if (extensions->ARB_shading_language_420pack) add_builtin_define(parser, "GL_ARB_shading_language_420pack", 1); + if (extensions->ARB_sample_shading) + add_builtin_define(parser, "GL_ARB_sample_shading", 1); + if (extensions->EXT_shader_integer_mix) add_builtin_define(parser, "GL_EXT_shader_integer_mix", 1); diff --git a/mesalib/src/glsl/glsl_parser_extras.cpp b/mesalib/src/glsl/glsl_parser_extras.cpp index 77e8816c4..d922db9db 100644 --- a/mesalib/src/glsl/glsl_parser_extras.cpp +++ b/mesalib/src/glsl/glsl_parser_extras.cpp @@ -540,6 +540,7 @@ static const _mesa_glsl_extension _mesa_glsl_supported_extensions[] = { EXT(EXT_shader_integer_mix, true, true, EXT_shader_integer_mix), EXT(ARB_texture_gather, true, false, ARB_texture_gather), EXT(ARB_shader_atomic_counters, true, false, ARB_shader_atomic_counters), + EXT(ARB_sample_shading, true, false, ARB_sample_shading), }; #undef EXT @@ -1604,6 +1605,7 @@ do_common_optimization(exec_list *ir, bool linked, else progress = do_constant_variable_unlinked(ir) || progress; progress = do_constant_folding(ir) || progress; + progress = do_cse(ir) || progress; progress = do_algebraic(ir) || progress; progress = do_lower_jumps(ir) || progress; progress = do_vec_index_to_swizzle(ir) || progress; diff --git a/mesalib/src/glsl/glsl_parser_extras.h b/mesalib/src/glsl/glsl_parser_extras.h index f22dac355..345d7a018 100644 --- a/mesalib/src/glsl/glsl_parser_extras.h +++ b/mesalib/src/glsl/glsl_parser_extras.h @@ -350,6 +350,8 @@ struct _mesa_glsl_parse_state { bool AMD_vertex_shader_layer_warn; bool ARB_shading_language_420pack_enable; bool ARB_shading_language_420pack_warn; + bool ARB_sample_shading_enable; + bool ARB_sample_shading_warn; bool EXT_shader_integer_mix_enable; bool EXT_shader_integer_mix_warn; bool ARB_shader_atomic_counters_enable; diff --git a/mesalib/src/glsl/glsl_types.h b/mesalib/src/glsl/glsl_types.h index fdb1f3a6e..96eee5e64 100644 --- a/mesalib/src/glsl/glsl_types.h +++ b/mesalib/src/glsl/glsl_types.h @@ -459,7 +459,7 @@ struct glsl_type { */ bool contains_atomic() const { - return atomic_size(); + return atomic_size() > 0; } /** diff --git a/mesalib/src/glsl/ir.h b/mesalib/src/glsl/ir.h index 5b30fe59b..2f06fb9ea 100644 --- a/mesalib/src/glsl/ir.h +++ b/mesalib/src/glsl/ir.h @@ -133,6 +133,7 @@ public: virtual class ir_return * as_return() { return NULL; } virtual class ir_if * as_if() { return NULL; } virtual class ir_swizzle * as_swizzle() { return NULL; } + virtual class ir_texture * as_texture() { return NULL; } virtual class ir_constant * as_constant() { return NULL; } virtual class ir_discard * as_discard() { return NULL; } virtual class ir_jump * as_jump() { return NULL; } @@ -1731,6 +1732,11 @@ public: v->visit(this); } + virtual ir_texture *as_texture() + { + return this; + } + virtual ir_visitor_status accept(ir_hierarchical_visitor *); /** diff --git a/mesalib/src/glsl/ir_optimization.h b/mesalib/src/glsl/ir_optimization.h index 074686c5d..3ca9f5744 100644 --- a/mesalib/src/glsl/ir_optimization.h +++ b/mesalib/src/glsl/ir_optimization.h @@ -77,6 +77,7 @@ bool do_constant_variable_unlinked(exec_list *instructions); bool do_copy_propagation(exec_list *instructions); bool do_copy_propagation_elements(exec_list *instructions); bool do_constant_propagation(exec_list *instructions); +bool do_cse(exec_list *instructions); void do_dead_builtin_varyings(struct gl_context *ctx, gl_shader *producer, gl_shader *consumer, unsigned num_tfeedback_decls, diff --git a/mesalib/src/glsl/opt_cse.cpp b/mesalib/src/glsl/opt_cse.cpp new file mode 100644 index 000000000..c0fdb23e6 --- /dev/null +++ b/mesalib/src/glsl/opt_cse.cpp @@ -0,0 +1,599 @@ +/* + * Copyright © 2013 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +/** + * \file opt_cse.cpp + * + * constant subexpression elimination at the GLSL IR level. + * + * Compare to brw_fs_cse.cpp for a more complete CSE implementation. This one + * is generic and handles texture operations, but it's rather simple currently + * and doesn't support modification of variables in the available expressions + * list, so it can't do variables other than uniforms or shader inputs. + */ + +#include "ir.h" +#include "ir_visitor.h" +#include "ir_rvalue_visitor.h" +#include "ir_basic_block.h" +#include "ir_optimization.h" +#include "ir_builder.h" +#include "glsl_types.h" + +using namespace ir_builder; + +static bool debug = false; + +namespace { + +/** + * This is the record of an available expression for common subexpression + * elimination. + */ +class ae_entry : public exec_node +{ +public: + ae_entry(ir_instruction *base_ir, ir_rvalue **val) + : val(val), base_ir(base_ir) + { + assert(val); + assert(*val); + assert(base_ir); + + var = NULL; + } + + /** + * The pointer to the expression that we might be able to reuse + * + * Note the double pointer -- this is the place in the base_ir expression + * tree that we would rewrite to move the expression out to a new variable + * assignment. + */ + ir_rvalue **val; + + /** + * Root instruction in the basic block where the expression appeared. + * + * This is used so that we can insert the new variable declaration into the + * instruction stream (since *val is just somewhere in base_ir's expression + * tree). + */ + ir_instruction *base_ir; + + /** + * The variable that the expression has been stored in, if it's been CSEd + * once already. + */ + ir_variable *var; +}; + +class cse_visitor : public ir_rvalue_visitor { +public: + cse_visitor(exec_list *validate_instructions) + : validate_instructions(validate_instructions) + { + progress = false; + mem_ctx = ralloc_context(NULL); + this->ae = new(mem_ctx) exec_list; + } + ~cse_visitor() + { + ralloc_free(mem_ctx); + } + + virtual ir_visitor_status visit_enter(ir_function_signature *ir); + virtual ir_visitor_status visit_enter(ir_loop *ir); + virtual ir_visitor_status visit_enter(ir_if *ir); + virtual ir_visitor_status visit_enter(ir_call *ir); + virtual void handle_rvalue(ir_rvalue **rvalue); + + bool progress; + +private: + void *mem_ctx; + + ir_rvalue *try_cse(ir_rvalue *rvalue); + void add_to_ae(ir_rvalue **rvalue); + + /** List of ae_entry: The available expressions to reuse */ + exec_list *ae; + + /** + * The whole shader, so that we can validate_ir_tree in debug mode. + * + * This proved quite useful when trying to get the tree manipulation + * right. + */ + exec_list *validate_instructions; +}; + +/** + * Visitor to walk an expression tree to check that all variables referenced + * are constants. + */ +class is_cse_candidate_visitor : public ir_hierarchical_visitor +{ +public: + + is_cse_candidate_visitor() + : ok(true) + { + } + + virtual ir_visitor_status visit(ir_dereference_variable *ir); + + bool ok; +}; + + +class contains_rvalue_visitor : public ir_rvalue_visitor +{ +public: + + contains_rvalue_visitor(ir_rvalue *val) + : val(val) + { + found = false; + } + + virtual void handle_rvalue(ir_rvalue **rvalue); + + bool found; + +private: + ir_rvalue *val; +}; + +} /* unnamed namespace */ + +static void +dump_ae(exec_list *ae) +{ + int i = 0; + + printf("CSE: AE contents:\n"); + foreach_list(node, ae) { + ae_entry *entry = (ae_entry *)node; + + printf("CSE: AE %2d (%p): ", i, entry); + (*entry->val)->print(); + printf("\n"); + + if (entry->var) + printf("CSE: in var %p:\n", entry->var); + + i++; + } +} + +ir_visitor_status +is_cse_candidate_visitor::visit(ir_dereference_variable *ir) +{ + /* Currently, since we don't handle kills of the ae based on variables + * getting assigned, we can only handle constant variables. + */ + if (ir->var->read_only) { + return visit_continue; + } else { + ok = false; + return visit_stop; + } +} + +void +contains_rvalue_visitor::handle_rvalue(ir_rvalue **rvalue) +{ + if (*rvalue == val) + found = true; +} + +static bool +contains_rvalue(ir_rvalue *haystack, ir_rvalue *needle) +{ + contains_rvalue_visitor v(needle); + haystack->accept(&v); + return v.found; +} + +static bool +is_cse_candidate(ir_rvalue *ir) +{ + /* Our temporary variable assignment generation isn't ready to handle + * anything bigger than a vector. + */ + if (!ir->type->is_vector() && !ir->type->is_scalar()) + return false; + + /* Only handle expressions and textures currently. We may want to extend + * to variable-index array dereferences at some point. + */ + switch (ir->ir_type) { + case ir_type_expression: + case ir_type_texture: + break; + default: + return false; + } + + is_cse_candidate_visitor v; + + ir->accept(&v); + + return v.ok; +} + +static bool +equals(ir_rvalue *a, ir_rvalue *b); + +static bool +equals(ir_constant *a, ir_constant *b) +{ + if (!a || !b) + return false; + + if (a->type != b->type) + return false; + + for (unsigned i = 0; i < a->type->components(); i++) { + if (a->value.u[i] != b->value.u[i]) + return false; + } + + return true; +} + +static bool +equals(ir_dereference_variable *a, ir_dereference_variable *b) +{ + if (!a || !b) + return false; + + return a->var == b->var; +} + +static bool +equals(ir_dereference_array *a, ir_dereference_array *b) +{ + if (!a || !b) + return false; + + if (!equals(a->array, b->array)) + return false; + + if (!equals(a->array_index, b->array_index)) + return false; + + return true; +} + +static bool +equals(ir_swizzle *a, ir_swizzle *b) +{ + if (!a || !b) + return false; + + if (a->type != b->type) + return false; + + if (a->mask.x != b->mask.x || + a->mask.y != b->mask.y || + a->mask.z != b->mask.z || + a->mask.w != b->mask.w) { + return false; + } + + return equals(a->val, b->val); +} + +static bool +equals(ir_texture *a, ir_texture *b) +{ + if (!a || !b) + return false; + + if (a->type != b->type) + return false; + + if (a->op != b->op) + return false; + + if (!equals(a->coordinate, b->coordinate)) + return false; + + if (!equals(a->projector, b->projector)) + return false; + + if (!equals(a->shadow_comparitor, b->shadow_comparitor)) + return false; + + if (!equals(a->offset, b->offset)) + return false; + + if (!equals(a->sampler, b->sampler)) + return false; + + switch (a->op) { + case ir_tex: + case ir_lod: + case ir_query_levels: + break; + case ir_txb: + if (!equals(a->lod_info.bias, b->lod_info.bias)) + return false; + break; + case ir_txl: + case ir_txf: + case ir_txs: + if (!equals(a->lod_info.lod, b->lod_info.lod)) + return false; + break; + case ir_txd: + if (!equals(a->lod_info.grad.dPdx, b->lod_info.grad.dPdx) || + !equals(a->lod_info.grad.dPdy, b->lod_info.grad.dPdy)) + return false; + case ir_txf_ms: + if (!equals(a->lod_info.sample_index, b->lod_info.sample_index)) + return false; + break; + case ir_tg4: + if (!equals(a->lod_info.component, b->lod_info.component)) + return false; + default: + assert(!"Unrecognized texture op"); + } + + return true; +} + +static bool +equals(ir_expression *a, ir_expression *b) +{ + if (!a || !b) + return false; + + if (a->type != b->type) + return false; + + if (a->operation != b->operation) + return false; + + for (unsigned i = 0; i < a->get_num_operands(); i++) { + if (!equals(a->operands[i], b->operands[i])) + return false; + } + + return true; +} + +static bool +equals(ir_rvalue *a, ir_rvalue *b) +{ + if (!a || !b) + return !a && !b; + + if (a->type != b->type) + return false; + + switch (a->ir_type) { + case ir_type_texture: + return equals(a->as_texture(), b->as_texture()); + + case ir_type_constant: + return equals(a->as_constant(), b->as_constant()); + + case ir_type_expression: + return equals(a->as_expression(), b->as_expression()); + + case ir_type_dereference_variable: + return equals(a->as_dereference_variable(), b->as_dereference_variable()); + + case ir_type_dereference_array: + return equals(a->as_dereference_array(), b->as_dereference_array()); + + case ir_type_swizzle: + return equals(a->as_swizzle(), b->as_swizzle()); + + default: + return false; + } +} + +/** + * Tries to find and return a reference to a previous computation of a given + * expression. + * + * Walk the list of available expressions checking if any of them match the + * rvalue, and if so, move the previous copy of the expression to a temporary + * and return a reference of the temporary. + */ +ir_rvalue * +cse_visitor::try_cse(ir_rvalue *rvalue) +{ + foreach_list(node, ae) { + ae_entry *entry = (ae_entry *)node; + + if (debug) { + printf("Comparing to AE %p: ", entry); + (*entry->val)->print(); + printf("\n"); + } + + if (!equals(rvalue, *entry->val)) + continue; + + if (debug) { + printf("CSE: Replacing: "); + (*entry->val)->print(); + printf("\n"); + printf("CSE: with: "); + rvalue->print(); + printf("\n"); + } + + if (!entry->var) { + ir_instruction *base_ir = entry->base_ir; + + ir_variable *var = new(rvalue) ir_variable(rvalue->type, + "cse", + ir_var_auto); + + /* Write the previous expression result into a new variable. */ + base_ir->insert_before(var); + ir_assignment *assignment = assign(var, *entry->val); + base_ir->insert_before(assignment); + + /* Replace the expression in the original tree with a deref of the + * variable, but keep tracking the expression for further reuse. + */ + *entry->val = new(rvalue) ir_dereference_variable(var); + entry->val = &assignment->rhs; + + entry->var = var; + + /* Update the base_irs in the AE list. We have to be sure that + * they're correct -- expressions from our base_ir that weren't moved + * need to stay in this base_ir (so that later consumption of them + * puts new variables between our new variable and our base_ir), but + * expressions from our base_ir that we *did* move need base_ir + * updated so that any further elimination from inside gets its new + * assignments put before our new assignment. + */ + foreach_list(fixup_node, ae) { + ae_entry *fixup_entry = (ae_entry *)fixup_node; + if (contains_rvalue(assignment->rhs, *fixup_entry->val)) + fixup_entry->base_ir = assignment; + } + + if (debug) + dump_ae(ae); + } + + /* Replace the expression in our current tree with the variable. */ + return new(rvalue) ir_dereference_variable(entry->var); + } + + return NULL; +} + +/** Add the rvalue to the list of available expressions for CSE. */ +void +cse_visitor::add_to_ae(ir_rvalue **rvalue) +{ + if (debug) { + printf("CSE: Add to AE: "); + (*rvalue)->print(); + printf("\n"); + } + + ae->push_tail(new(mem_ctx) ae_entry(base_ir, rvalue)); + + if (debug) + dump_ae(ae); +} + +void +cse_visitor::handle_rvalue(ir_rvalue **rvalue) +{ + if (!*rvalue) + return; + + if (debug) { + printf("CSE: handle_rvalue "); + (*rvalue)->print(); + printf("\n"); + } + + if (!is_cse_candidate(*rvalue)) + return; + + ir_rvalue *new_rvalue = try_cse(*rvalue); + if (new_rvalue) { + *rvalue = new_rvalue; + progress = true; + + if (debug) + validate_ir_tree(validate_instructions); + } else { + add_to_ae(rvalue); + } +} + +ir_visitor_status +cse_visitor::visit_enter(ir_if *ir) +{ + handle_rvalue(&ir->condition); + + ae->make_empty(); + visit_list_elements(this, &ir->then_instructions); + + ae->make_empty(); + visit_list_elements(this, &ir->else_instructions); + + ae->make_empty(); + return visit_continue_with_parent; +} + +ir_visitor_status +cse_visitor::visit_enter(ir_function_signature *ir) +{ + ae->make_empty(); + visit_list_elements(this, &ir->body); + + ae->make_empty(); + return visit_continue_with_parent; +} + +ir_visitor_status +cse_visitor::visit_enter(ir_loop *ir) +{ + ae->make_empty(); + visit_list_elements(this, &ir->body_instructions); + + ae->make_empty(); + return visit_continue_with_parent; +} + +ir_visitor_status +cse_visitor::visit_enter(ir_call *ir) +{ + /* Because call is an exec_list of ir_rvalues, handle_rvalue gets passed a + * pointer to the (ir_rvalue *) on the stack. Since we save those pointers + * in the AE list, we can't let handle_rvalue get called. + */ + return visit_continue_with_parent; +} + +/** + * Does a (uniform-value) constant subexpression elimination pass on the code + * present in the instruction stream. + */ +bool +do_cse(exec_list *instructions) +{ + cse_visitor v(instructions); + + visit_list_elements(&v, instructions); + + return v.progress; +} diff --git a/mesalib/src/glsl/standalone_scaffolding.cpp b/mesalib/src/glsl/standalone_scaffolding.cpp index 7a1cf6877..cbff6d182 100644 --- a/mesalib/src/glsl/standalone_scaffolding.cpp +++ b/mesalib/src/glsl/standalone_scaffolding.cpp @@ -97,6 +97,7 @@ void initialize_context_to_defaults(struct gl_context *ctx, gl_api api) ctx->Extensions.ARB_explicit_attrib_location = true; ctx->Extensions.ARB_fragment_coord_conventions = true; ctx->Extensions.ARB_gpu_shader5 = true; + ctx->Extensions.ARB_sample_shading = true; ctx->Extensions.ARB_shader_bit_encoding = true; ctx->Extensions.ARB_shader_stencil_export = true; ctx->Extensions.ARB_shader_texture_lod = true; diff --git a/mesalib/src/mapi/glapi/gen/ARB_sample_shading.xml b/mesalib/src/mapi/glapi/gen/ARB_sample_shading.xml new file mode 100644 index 000000000..cc8296a47 --- /dev/null +++ b/mesalib/src/mapi/glapi/gen/ARB_sample_shading.xml @@ -0,0 +1,19 @@ +<?xml version="1.0"?> +<!DOCTYPE OpenGLAPI SYSTEM "gl_API.dtd"> + +<!-- Note: no GLX protocol info yet. --> + +<OpenGLAPI> + +<category name="GL_ARB_sample_shading" number="70"> + + <enum name="SAMPLE_SHADING_ARB" value="0x8C36"/> + <enum name="MIN_SAMPLE_SHADING_VALUE_ARB" value="0x8C37"/> + + <function name="MinSampleShadingARB" alias="MinSampleShading"> + <param name="value" type="GLfloat"/> + </function> + +</category> + +</OpenGLAPI> diff --git a/mesalib/src/mapi/glapi/gen/GL4x.xml b/mesalib/src/mapi/glapi/gen/GL4x.xml new file mode 100644 index 000000000..6706278ce --- /dev/null +++ b/mesalib/src/mapi/glapi/gen/GL4x.xml @@ -0,0 +1,21 @@ +<?xml version="1.0"?> +<!DOCTYPE OpenGLAPI SYSTEM "gl_API.dtd"> + +<!-- Note: no GLX protocol info yet. --> + +<OpenGLAPI> + +<category name="4.0"> + <enum name="SAMPLE_SHADING" value="0x8C36"/> + <enum name="MIN_SAMPLE_SHADING_VALUE" value="0x8C37"/> + + <function name="MinSampleShading" offset="assign"> + <param name="value" type="GLfloat"/> + </function> +</category> + +<category name="4.3"> + +</category> + +</OpenGLAPI> diff --git a/mesalib/src/mapi/glapi/gen/Makefile.am b/mesalib/src/mapi/glapi/gen/Makefile.am index 390245216..cbbf659dd 100644 --- a/mesalib/src/mapi/glapi/gen/Makefile.am +++ b/mesalib/src/mapi/glapi/gen/Makefile.am @@ -108,6 +108,7 @@ API_XML = \ ARB_invalidate_subdata.xml \ ARB_map_buffer_range.xml \ ARB_robustness.xml \ + ARB_sample_shading.xml \ ARB_sampler_objects.xml \ ARB_seamless_cube_map.xml \ ARB_shader_atomic_counters.xml \ @@ -144,7 +145,9 @@ API_XML = \ NV_texture_barrier.xml \ NV_vdpau_interop.xml \ OES_EGL_image.xml \ - GL3x.xml + GL3x.xml \ + GL4x.xml + COMMON = $(API_XML) \ diff --git a/mesalib/src/mapi/glapi/gen/gl_API.xml b/mesalib/src/mapi/glapi/gen/gl_API.xml index 45d69b40a..69014c5d2 100644 --- a/mesalib/src/mapi/glapi/gen/gl_API.xml +++ b/mesalib/src/mapi/glapi/gen/gl_API.xml @@ -8187,7 +8187,7 @@ <xi:include href="ARB_draw_buffers_blend.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/> <xi:include href="AMD_draw_buffers_blend.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/> -<!-- 70. GL_ARB_sample_shading --> +<xi:include href="ARB_sample_shading.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/> <xi:include href="ARB_texture_cube_map_array.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/> <xi:include href="ARB_texture_gather.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/> <!-- 73. GL_ARB_texture_query_lod --> @@ -13122,4 +13122,6 @@ <xi:include href="NV_vdpau_interop.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/> +<xi:include href="GL4x.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/> + </OpenGLAPI> diff --git a/mesalib/src/mesa/drivers/common/meta.c b/mesalib/src/mesa/drivers/common/meta.c index 798efa680..aa50dde73 100644 --- a/mesalib/src/mesa/drivers/common/meta.c +++ b/mesalib/src/mesa/drivers/common/meta.c @@ -1729,10 +1729,10 @@ blitframebuffer_texture(struct gl_context *ctx, } else { assert(target == GL_TEXTURE_RECTANGLE_ARB); - s0 = srcX0; - s1 = srcX1; - t0 = srcY0; - t1 = srcY1; + s0 = (float) srcX0; + s1 = (float) srcX1; + t0 = (float) srcY0; + t1 = (float) srcY1; } /* setup vertex positions */ @@ -2825,7 +2825,7 @@ _mesa_meta_DrawPixels(struct gl_context *ctx, _mesa_StencilMask(mask); _mesa_ProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 0, - 255.0 / mask, 0.5, 0.0, 0.0); + 255.0f / mask, 0.5f, 0.0f, 0.0f); _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4); } @@ -3184,7 +3184,7 @@ setup_texture_coords(GLenum faceTarget, r = (slice + 0.5f) / depth; } else if (faceTarget == GL_TEXTURE_2D_ARRAY) - r = slice; + r = (float) slice; else r = 0.0F; coords0[0] = 0.0F; /* s */ @@ -3204,28 +3204,28 @@ setup_texture_coords(GLenum faceTarget, coords0[0] = 0.0F; /* s */ coords0[1] = 0.0F; /* t */ coords0[2] = 0.0F; /* r */ - coords1[0] = width; + coords1[0] = (float) width; coords1[1] = 0.0F; coords1[2] = 0.0F; - coords2[0] = width; - coords2[1] = height; + coords2[0] = (float) width; + coords2[1] = (float) height; coords2[2] = 0.0F; coords3[0] = 0.0F; - coords3[1] = height; + coords3[1] = (float) height; coords3[2] = 0.0F; break; case GL_TEXTURE_1D_ARRAY: coords0[0] = 0.0F; /* s */ - coords0[1] = slice; /* t */ + coords0[1] = (float) slice; /* t */ coords0[2] = 0.0F; /* r */ coords1[0] = 1.0f; - coords1[1] = slice; + coords1[1] = (float) slice; coords1[2] = 0.0F; coords2[0] = 1.0F; - coords2[1] = slice; + coords2[1] = (float) slice; coords2[2] = 0.0F; coords3[0] = 0.0F; - coords3[1] = slice; + coords3[1] = (float) slice; coords3[2] = 0.0F; break; diff --git a/mesalib/src/mesa/main/dd.h b/mesalib/src/mesa/main/dd.h index 501192199..d7c432713 100644 --- a/mesalib/src/mesa/main/dd.h +++ b/mesalib/src/mesa/main/dd.h @@ -843,6 +843,14 @@ struct dd_function_table { struct gl_transform_feedback_object *obj); /** + * Return the number of vertices written to a stream during the last + * Begin/EndTransformFeedback block. + */ + GLsizei (*GetTransformFeedbackVertexCount)(struct gl_context *ctx, + struct gl_transform_feedback_object *obj, + GLuint stream); + + /** * \name GL_NV_texture_barrier interface */ void (*TextureBarrier)(struct gl_context *ctx); diff --git a/mesalib/src/mesa/main/enable.c b/mesalib/src/mesa/main/enable.c index 5e2fd80d2..dd6a772f9 100644 --- a/mesalib/src/mesa/main/enable.c +++ b/mesalib/src/mesa/main/enable.c @@ -802,6 +802,17 @@ _mesa_set_enable(struct gl_context *ctx, GLenum cap, GLboolean state) ctx->Multisample.SampleCoverageInvert = state; break; + /* GL_ARB_sample_shading */ + case GL_SAMPLE_SHADING: + if (!_mesa_is_desktop_gl(ctx)) + goto invalid_enum_error; + CHECK_EXTENSION(ARB_sample_shading, cap); + if (ctx->Multisample.SampleShading == state) + return; + FLUSH_VERTICES(ctx, _NEW_MULTISAMPLE); + ctx->Multisample.SampleShading = state; + break; + /* GL_IBM_rasterpos_clip */ case GL_RASTER_POSITION_UNCLIPPED_IBM: if (ctx->API != API_OPENGL_COMPAT) @@ -1594,6 +1605,13 @@ _mesa_IsEnabled( GLenum cap ) CHECK_EXTENSION(ARB_texture_multisample); return ctx->Multisample.SampleMask; + /* ARB_sample_shading */ + case GL_SAMPLE_SHADING: + if (!_mesa_is_desktop_gl(ctx)) + goto invalid_enum_error; + CHECK_EXTENSION(ARB_sample_shading); + return ctx->Multisample.SampleShading; + default: goto invalid_enum_error; } diff --git a/mesalib/src/mesa/main/extensions.c b/mesalib/src/mesa/main/extensions.c index 285ec377c..48c4e9f1b 100644 --- a/mesalib/src/mesa/main/extensions.c +++ b/mesalib/src/mesa/main/extensions.c @@ -118,6 +118,7 @@ static const struct extension extension_table[] = { { "GL_ARB_point_sprite", o(ARB_point_sprite), GL, 2003 }, { "GL_ARB_provoking_vertex", o(EXT_provoking_vertex), GL, 2009 }, { "GL_ARB_robustness", o(dummy_true), GL, 2010 }, + { "GL_ARB_sample_shading", o(ARB_sample_shading), GL, 2009 }, { "GL_ARB_sampler_objects", o(dummy_true), GL, 2009 }, { "GL_ARB_seamless_cube_map", o(ARB_seamless_cube_map), GL, 2009 }, { "GL_ARB_shader_atomic_counters", o(ARB_shader_atomic_counters), GL, 2011 }, diff --git a/mesalib/src/mesa/main/get.c b/mesalib/src/mesa/main/get.c index 6e72ff5c2..6a0de0c16 100644 --- a/mesalib/src/mesa/main/get.c +++ b/mesalib/src/mesa/main/get.c @@ -131,6 +131,7 @@ enum value_extra { EXTRA_VERSION_30, EXTRA_VERSION_31, EXTRA_VERSION_32, + EXTRA_VERSION_40, EXTRA_API_GL, EXTRA_API_GL_CORE, EXTRA_API_ES2, @@ -391,6 +392,7 @@ extra_NV_primitive_restart[] = { static const int extra_version_30[] = { EXTRA_VERSION_30, EXTRA_END }; static const int extra_version_31[] = { EXTRA_VERSION_31, EXTRA_END }; static const int extra_version_32[] = { EXTRA_VERSION_32, EXTRA_END }; +static const int extra_version_40[] = { EXTRA_VERSION_40, EXTRA_END }; static const int extra_gl30_es3[] = { EXTRA_VERSION_30, @@ -410,6 +412,12 @@ static const int extra_gl32_ARB_geometry_shader4[] = { EXTRA_END }; +static const int extra_gl40_ARB_sample_shading[] = { + EXTRA_VERSION_40, + EXT(ARB_sample_shading), + EXTRA_END +}; + static const int extra_ARB_vertex_program_api_es2[] = { EXT(ARB_vertex_program), diff --git a/mesalib/src/mesa/main/get_hash_params.py b/mesalib/src/mesa/main/get_hash_params.py index 9f79f3406..0851b7b70 100644 --- a/mesalib/src/mesa/main/get_hash_params.py +++ b/mesalib/src/mesa/main/get_hash_params.py @@ -83,6 +83,9 @@ descriptor=[ [ "SAMPLE_BUFFERS_ARB", "BUFFER_INT(Visual.sampleBuffers), extra_new_buffers" ], [ "SAMPLES_ARB", "BUFFER_INT(Visual.samples), extra_new_buffers" ], +# GL_ARB_sample_shading + [ "MIN_SAMPLE_SHADING_VALUE_ARB", "CONTEXT_FLOAT(Multisample.MinSampleShadingValue), extra_gl40_ARB_sample_shading" ], + # GL_SGIS_generate_mipmap [ "GENERATE_MIPMAP_HINT_SGIS", "CONTEXT_ENUM(Hint.GenerateMipmap), NO_EXTRA" ], diff --git a/mesalib/src/mesa/main/mtypes.h b/mesalib/src/mesa/main/mtypes.h index a1a5eb4bf..b5c5583d6 100644 --- a/mesalib/src/mesa/main/mtypes.h +++ b/mesalib/src/mesa/main/mtypes.h @@ -274,6 +274,11 @@ typedef enum #define VARYING_BIT_VAR(V) BITFIELD64_BIT(VARYING_SLOT_VAR0 + (V)) /*@}*/ +/** + * Bitflags for system values. + */ +#define SYSTEM_BIT_SAMPLE_ID BITFIELD64_BIT(SYSTEM_VALUE_SAMPLE_ID) +#define SYSTEM_BIT_SAMPLE_POS BITFIELD64_BIT(SYSTEM_VALUE_SAMPLE_POS) /** * Determine if the given gl_varying_slot appears in the fragment shader. @@ -306,12 +311,13 @@ typedef enum * register is written. No FRAG_RESULT_DATAn will be written. */ FRAG_RESULT_COLOR = 2, + FRAG_RESULT_SAMPLE_MASK = 3, /* FRAG_RESULT_DATAn are the per-render-target (GLSL gl_FragData[n] * or ARB_fragment_program fragment.color[n]) color results. If * any are written, FRAG_RESULT_COLOR will not be written. */ - FRAG_RESULT_DATA0 = 3, + FRAG_RESULT_DATA0 = 4, FRAG_RESULT_MAX = (FRAG_RESULT_DATA0 + MAX_DRAW_BUFFERS) } gl_frag_result; @@ -872,6 +878,8 @@ struct gl_multisample_attrib GLboolean SampleCoverage; GLfloat SampleCoverageValue; GLboolean SampleCoverageInvert; + GLboolean SampleShading; + GLfloat MinSampleShadingValue; /* ARB_texture_multisample / GL3.2 additions */ GLboolean SampleMask; @@ -1902,6 +1910,8 @@ typedef enum SYSTEM_VALUE_FRONT_FACE, /**< Fragment shader only (not done yet) */ SYSTEM_VALUE_VERTEX_ID, /**< Vertex shader only */ SYSTEM_VALUE_INSTANCE_ID, /**< Vertex shader only */ + SYSTEM_VALUE_SAMPLE_ID, /**< Fragment shader only */ + SYSTEM_VALUE_SAMPLE_POS, /**< Fragment shader only */ SYSTEM_VALUE_MAX /**< Number of values */ } gl_system_value; @@ -3156,6 +3166,12 @@ struct gl_constants */ GLboolean PrimitiveRestartInSoftware; + /** + * Always use the GetTransformFeedbackVertexCount() driver hook, rather + * than passing the transform feedback object to the drawing function. + */ + GLboolean AlwaysUseGetTransformFeedbackVertexCount; + /** GL_ARB_map_buffer_alignment */ GLuint MinMapBufferAlignment; @@ -3239,6 +3255,7 @@ struct gl_extensions GLboolean ARB_occlusion_query; GLboolean ARB_occlusion_query2; GLboolean ARB_point_sprite; + GLboolean ARB_sample_shading; GLboolean ARB_seamless_cube_map; GLboolean ARB_shader_atomic_counters; GLboolean ARB_shader_bit_encoding; diff --git a/mesalib/src/mesa/main/multisample.c b/mesalib/src/mesa/main/multisample.c index bd97c5096..599cdee74 100644 --- a/mesalib/src/mesa/main/multisample.c +++ b/mesalib/src/mesa/main/multisample.c @@ -119,6 +119,24 @@ _mesa_SampleMaski(GLuint index, GLbitfield mask) ctx->Multisample.SampleMaskValue = mask; } +/** + * Called via glMinSampleShadingARB + */ +void GLAPIENTRY +_mesa_MinSampleShading(GLclampf value) +{ + GET_CURRENT_CONTEXT(ctx); + + if (!ctx->Extensions.ARB_sample_shading || !_mesa_is_desktop_gl(ctx)) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glMinSampleShading"); + return; + } + + FLUSH_VERTICES(ctx, 0); + + ctx->Multisample.MinSampleShadingValue = CLAMP(value, 0.0, 1.0); + ctx->NewState |= _NEW_MULTISAMPLE; +} /** * Helper for checking a requested sample count against the limit diff --git a/mesalib/src/mesa/main/multisample.h b/mesalib/src/mesa/main/multisample.h index 66848d269..7441d3ee9 100644 --- a/mesalib/src/mesa/main/multisample.h +++ b/mesalib/src/mesa/main/multisample.h @@ -44,6 +44,8 @@ _mesa_GetMultisamplefv(GLenum pname, GLuint index, GLfloat* val); extern void GLAPIENTRY _mesa_SampleMaski(GLuint index, GLbitfield mask); +extern void GLAPIENTRY +_mesa_MinSampleShading(GLclampf value); extern GLenum _mesa_check_sample_count(struct gl_context *ctx, GLenum target, diff --git a/mesalib/src/mesa/main/performance_monitor.c b/mesalib/src/mesa/main/performance_monitor.c index 8dfa8261e..17cae5183 100644 --- a/mesalib/src/mesa/main/performance_monitor.c +++ b/mesalib/src/mesa/main/performance_monitor.c @@ -127,7 +127,7 @@ _mesa_GetPerfMonitorGroupsAMD(GLint *numGroups, GLsizei groupsSize, if (groupsSize > 0 && groups != NULL) { unsigned i; - unsigned n = MIN2(groupsSize, ctx->PerfMonitor.NumGroups); + unsigned n = MIN2((GLuint) groupsSize, ctx->PerfMonitor.NumGroups); /* We just use the index in the Groups array as the ID. */ for (i = 0; i < n; i++) @@ -156,7 +156,7 @@ _mesa_GetPerfMonitorCountersAMD(GLuint group, GLint *numCounters, if (counters != NULL) { unsigned i; - unsigned n = MIN2(group_obj->NumCounters, countersSize); + unsigned n = MIN2(group_obj->NumCounters, (GLuint) countersSize); for (i = 0; i < n; i++) { /* We just use the index in the Counters array as the ID. */ counters[i] = i; @@ -379,7 +379,7 @@ _mesa_SelectPerfMonitorCountersAMD(GLuint monitor, GLboolean enable, GLuint *counterList) { GET_CURRENT_CONTEXT(ctx); - unsigned i; + int i; struct gl_perf_monitor_object *m; const struct gl_perf_monitor_group *group_obj; diff --git a/mesalib/src/mesa/main/transformfeedback.c b/mesalib/src/mesa/main/transformfeedback.c index bc9b52ab9..76d213b16 100644 --- a/mesalib/src/mesa/main/transformfeedback.c +++ b/mesalib/src/mesa/main/transformfeedback.c @@ -205,17 +205,27 @@ _mesa_free_transform_feedback(struct gl_context *ctx) } +/** Initialize the fields of a gl_transform_feedback_object. */ +void +_mesa_init_transform_feedback_object(struct gl_transform_feedback_object *obj, + GLuint name) +{ + if (!obj) + return; + + obj->Name = name; + obj->RefCount = 1; + obj->EverBound = GL_FALSE; +} + + /** Default fallback for ctx->Driver.NewTransformFeedback() */ static struct gl_transform_feedback_object * new_transform_feedback(struct gl_context *ctx, GLuint name) { struct gl_transform_feedback_object *obj; obj = CALLOC_STRUCT(gl_transform_feedback_object); - if (obj) { - obj->Name = name; - obj->RefCount = 1; - obj->EverBound = GL_FALSE; - } + _mesa_init_transform_feedback_object(obj, name); return obj; } diff --git a/mesalib/src/mesa/main/transformfeedback.h b/mesalib/src/mesa/main/transformfeedback.h index 0ffaab508..7aecd66a7 100644 --- a/mesalib/src/mesa/main/transformfeedback.h +++ b/mesalib/src/mesa/main/transformfeedback.h @@ -91,6 +91,9 @@ _mesa_GetTransformFeedbackVarying(GLuint program, GLuint index, /*** GL_ARB_transform_feedback2 ***/ +extern void +_mesa_init_transform_feedback_object(struct gl_transform_feedback_object *obj, + GLuint name); struct gl_transform_feedback_object * _mesa_lookup_transform_feedback_object(struct gl_context *ctx, GLuint name); diff --git a/mesalib/src/mesa/main/uniforms.c b/mesalib/src/mesa/main/uniforms.c index 2e847fe31..17e24f678 100644 --- a/mesalib/src/mesa/main/uniforms.c +++ b/mesalib/src/mesa/main/uniforms.c @@ -853,7 +853,7 @@ _mesa_GetActiveAtomicCounterBufferiv(GLuint program, GLuint bufferIndex, GET_CURRENT_CONTEXT(ctx); struct gl_shader_program *shProg; struct gl_active_atomic_buffer *ab; - int i; + GLuint i; if (!ctx->Extensions.ARB_shader_atomic_counters) { _mesa_error(ctx, GL_INVALID_OPERATION, diff --git a/mesalib/src/mesa/main/vdpau.c b/mesalib/src/mesa/main/vdpau.c index e21a26b43..359757607 100644 --- a/mesalib/src/mesa/main/vdpau.c +++ b/mesalib/src/mesa/main/vdpau.c @@ -324,7 +324,7 @@ void GLAPIENTRY _mesa_VDPAUMapSurfacesNV(GLsizei numSurfaces, const GLintptr *surfaces) { GET_CURRENT_CONTEXT(ctx); - int i, j; + int i; if (!ctx->vdpDevice || !ctx->vdpGetProcAddress || !ctx->vdpSurfaces) { _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUUnmapSurfacesNV"); @@ -348,6 +348,7 @@ _mesa_VDPAUMapSurfacesNV(GLsizei numSurfaces, const GLintptr *surfaces) for (i = 0; i < numSurfaces; ++i) { struct vdp_surface *surf = (struct vdp_surface *)surfaces[i]; unsigned numTextureNames = surf->output ? 1 : 4; + unsigned j; for (j = 0; j < numTextureNames; ++j) { struct gl_texture_object *tex = surf->textures[j]; @@ -377,7 +378,7 @@ void GLAPIENTRY _mesa_VDPAUUnmapSurfacesNV(GLsizei numSurfaces, const GLintptr *surfaces) { GET_CURRENT_CONTEXT(ctx); - int i, j; + int i; if (!ctx->vdpDevice || !ctx->vdpGetProcAddress || !ctx->vdpSurfaces) { _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUUnmapSurfacesNV"); @@ -401,6 +402,7 @@ _mesa_VDPAUUnmapSurfacesNV(GLsizei numSurfaces, const GLintptr *surfaces) for (i = 0; i < numSurfaces; ++i) { struct vdp_surface *surf = (struct vdp_surface *)surfaces[i]; unsigned numTextureNames = surf->output ? 1 : 4; + unsigned j; for (j = 0; j < numTextureNames; ++j) { struct gl_texture_object *tex = surf->textures[j]; diff --git a/mesalib/src/mesa/program/prog_print.c b/mesalib/src/mesa/program/prog_print.c index cf852132d..fa9063f5b 100644 --- a/mesalib/src/mesa/program/prog_print.c +++ b/mesalib/src/mesa/program/prog_print.c @@ -311,6 +311,7 @@ arb_output_attrib_string(GLint index, GLenum progType) "result.depth", /* FRAG_RESULT_DEPTH */ "result.(one)", /* FRAG_RESULT_STENCIL */ "result.color", /* FRAG_RESULT_COLOR */ + "result.samplemask", /* FRAG_RESULT_SAMPLE_MASK */ "result.color[0]", /* FRAG_RESULT_DATA0 (named for GLSL's gl_FragData) */ "result.color[1]", "result.color[2]", diff --git a/mesalib/src/mesa/program/prog_statevars.c b/mesalib/src/mesa/program/prog_statevars.c index 145c07c67..f6fd53576 100644 --- a/mesalib/src/mesa/program/prog_statevars.c +++ b/mesalib/src/mesa/program/prog_statevars.c @@ -349,6 +349,9 @@ _mesa_fetch_state(struct gl_context *ctx, const gl_state_index state[], } } return; + case STATE_NUM_SAMPLES: + ((int *)value)[0] = ctx->DrawBuffer->Visual.samples; + return; case STATE_DEPTH_RANGE: value[0] = ctx->Viewport.Near; /* near */ value[1] = ctx->Viewport.Far; /* far */ @@ -665,6 +668,9 @@ _mesa_program_state_flags(const gl_state_index state[STATE_LENGTH]) case STATE_PROGRAM_MATRIX: return _NEW_TRACK_MATRIX; + case STATE_NUM_SAMPLES: + return _NEW_BUFFERS; + case STATE_DEPTH_RANGE: return _NEW_VIEWPORT; @@ -852,6 +858,9 @@ append_token(char *dst, gl_state_index k) case STATE_TEXENV_COLOR: append(dst, "texenv"); break; + case STATE_NUM_SAMPLES: + append(dst, "numsamples"); + break; case STATE_DEPTH_RANGE: append(dst, "depth.range"); break; @@ -1027,6 +1036,8 @@ _mesa_program_state_string(const gl_state_index state[STATE_LENGTH]) break; case STATE_FOG_COLOR: break; + case STATE_NUM_SAMPLES: + break; case STATE_DEPTH_RANGE: break; case STATE_FRAGMENT_PROGRAM: diff --git a/mesalib/src/mesa/program/prog_statevars.h b/mesalib/src/mesa/program/prog_statevars.h index ec22b7376..23a9f48c3 100644 --- a/mesalib/src/mesa/program/prog_statevars.h +++ b/mesalib/src/mesa/program/prog_statevars.h @@ -103,6 +103,8 @@ typedef enum gl_state_index_ { STATE_TEXENV_COLOR, + STATE_NUM_SAMPLES, /* An integer, not a float like the other state vars */ + STATE_DEPTH_RANGE, STATE_VERTEX_PROGRAM, diff --git a/mesalib/src/mesa/program/program.c b/mesalib/src/mesa/program/program.c index 093d37297..a102ec17a 100644 --- a/mesalib/src/mesa/program/program.c +++ b/mesalib/src/mesa/program/program.c @@ -32,6 +32,7 @@ #include "main/glheader.h" #include "main/context.h" #include "main/hash.h" +#include "main/macros.h" #include "program.h" #include "prog_cache.h" #include "prog_parameter.h" @@ -1024,3 +1025,34 @@ _mesa_postprocess_program(struct gl_context *ctx, struct gl_program *prog) } } + +/* Gets the minimum number of shader invocations per fragment. + * This function is useful to determine if we need to do per + * sample shading or per fragment shading. + */ +GLint +_mesa_get_min_invocations_per_fragment(struct gl_context *ctx, + const struct gl_fragment_program *prog) +{ + /* From ARB_sample_shading specification: + * "Using gl_SampleID in a fragment shader causes the entire shader + * to be evaluated per-sample." + * + * "Using gl_SamplePosition in a fragment shader causes the entire + * shader to be evaluated per-sample." + * + * "If MULTISAMPLE or SAMPLE_SHADING_ARB is disabled, sample shading + * has no effect." + */ + if (ctx->Multisample.Enabled) { + if (prog->Base.SystemValuesRead & (SYSTEM_BIT_SAMPLE_ID | + SYSTEM_BIT_SAMPLE_POS)) + return MAX2(ctx->DrawBuffer->Visual.samples, 1); + else if (ctx->Multisample.SampleShading) + return MAX2(ceil(ctx->Multisample.MinSampleShadingValue * + ctx->DrawBuffer->Visual.samples), 1); + else + return 1; + } + return 1; +} diff --git a/mesalib/src/mesa/program/program.h b/mesalib/src/mesa/program/program.h index 34965ab99..353ccab47 100644 --- a/mesalib/src/mesa/program/program.h +++ b/mesalib/src/mesa/program/program.h @@ -187,6 +187,9 @@ _mesa_valid_register_index(const struct gl_context *ctx, extern void _mesa_postprocess_program(struct gl_context *ctx, struct gl_program *prog); +extern GLint +_mesa_get_min_invocations_per_fragment(struct gl_context *ctx, + const struct gl_fragment_program *prog); static inline GLuint _mesa_program_target_to_index(GLenum v) diff --git a/mesalib/src/mesa/state_tracker/st_cb_xformfb.c b/mesalib/src/mesa/state_tracker/st_cb_xformfb.c index e1a7a88a1..e824fe9b3 100644 --- a/mesalib/src/mesa/state_tracker/st_cb_xformfb.c +++ b/mesalib/src/mesa/state_tracker/st_cb_xformfb.c @@ -74,8 +74,8 @@ st_new_transform_feedback(struct gl_context *ctx, GLuint name) if (!obj) return NULL; - obj->base.Name = name; - obj->base.RefCount = 1; + _mesa_init_transform_feedback_object(&obj->base, name); + return &obj->base; } diff --git a/mesalib/src/mesa/state_tracker/st_draw.h b/mesalib/src/mesa/state_tracker/st_draw.h index 3313fc8c7..394473b20 100644 --- a/mesalib/src/mesa/state_tracker/st_draw.h +++ b/mesalib/src/mesa/state_tracker/st_draw.h @@ -77,7 +77,7 @@ st_feedback_draw_vbo(struct gl_context *ctx, static INLINE unsigned pointer_to_offset(const void *ptr) { - return (unsigned) (((unsigned long) ptr) & 0xffffffffUL); + return (unsigned) (((GLsizeiptr) ptr) & 0xffffffffUL); } diff --git a/mesalib/src/mesa/swrast/s_texfetch_tmp.h b/mesalib/src/mesa/swrast/s_texfetch_tmp.h index 7a687532d..e2521b50c 100644 --- a/mesalib/src/mesa/swrast/s_texfetch_tmp.h +++ b/mesalib/src/mesa/swrast/s_texfetch_tmp.h @@ -1537,7 +1537,7 @@ static void FETCH(f_z24_s8)( const struct swrast_texture_image *texImage, /* only return Z, not stencil data */ const GLuint *src = TEXEL_ADDR(GLuint, texImage, i, j, k, 1); const GLdouble scale = 1.0 / (GLdouble) 0xffffff; - texel[0] = ((*src) >> 8) * scale; + texel[0] = (GLfloat) (((*src) >> 8) * scale); ASSERT(texImage->Base.TexFormat == MESA_FORMAT_Z24_S8 || texImage->Base.TexFormat == MESA_FORMAT_Z24_X8); ASSERT(texel[0] >= 0.0F); @@ -1555,7 +1555,7 @@ static void FETCH(f_s8_z24)( const struct swrast_texture_image *texImage, /* only return Z, not stencil data */ const GLuint *src = TEXEL_ADDR(GLuint, texImage, i, j, k, 1); const GLdouble scale = 1.0 / (GLdouble) 0xffffff; - texel[0] = ((*src) & 0x00ffffff) * scale; + texel[0] = (GLfloat) (((*src) & 0x00ffffff) * scale); ASSERT(texImage->Base.TexFormat == MESA_FORMAT_S8_Z24 || texImage->Base.TexFormat == MESA_FORMAT_X8_Z24); ASSERT(texel[0] >= 0.0F); diff --git a/mesalib/src/mesa/vbo/vbo_attrib_tmp.h b/mesalib/src/mesa/vbo/vbo_attrib_tmp.h index 02c283da4..bbc020539 100644 --- a/mesalib/src/mesa/vbo/vbo_attrib_tmp.h +++ b/mesalib/src/mesa/vbo/vbo_attrib_tmp.h @@ -140,7 +140,7 @@ static inline float conv_i10_to_norm_float(const struct gl_context *ctx, int i10 (ctx->API == API_OPENGL_CORE && ctx->Version >= 42)) { /* Equation 2.3 above. */ float f = ((float) val.x) / 511.0F; - return MAX2(f, -1.0); + return MAX2(f, -1.0f); } else { /* Equation 2.2 above. */ return (2.0F * (float)val.x + 1.0F) * (1.0F / 1023.0F); @@ -156,7 +156,7 @@ static inline float conv_i2_to_norm_float(const struct gl_context *ctx, int i2) (ctx->API == API_OPENGL_CORE && ctx->Version >= 42)) { /* Equation 2.3 above. */ float f = (float) val.x; - return MAX2(f, -1.0); + return MAX2(f, -1.0f); } else { /* Equation 2.2 above. */ return (2.0F * (float)val.x + 1.0F) * (1.0F / 3.0F); diff --git a/mesalib/src/mesa/vbo/vbo_exec_array.c b/mesalib/src/mesa/vbo/vbo_exec_array.c index 1670409d4..f25a9dec3 100644 --- a/mesalib/src/mesa/vbo/vbo_exec_array.c +++ b/mesalib/src/mesa/vbo/vbo_exec_array.c @@ -1464,6 +1464,16 @@ vbo_draw_transform_feedback(struct gl_context *ctx, GLenum mode, return; } + if (ctx->Driver.GetTransformFeedbackVertexCount && + (ctx->Const.AlwaysUseGetTransformFeedbackVertexCount || + (ctx->Const.PrimitiveRestartInSoftware && + ctx->Array._PrimitiveRestart) || + !vbo_all_varyings_in_vbos(exec->array.inputs))) { + GLsizei n = ctx->Driver.GetTransformFeedbackVertexCount(ctx, obj, stream); + vbo_draw_arrays(ctx, mode, 0, n, numInstances, 0); + return; + } + vbo_bind_arrays(ctx); /* init most fields to zero */ diff --git a/pixman/configure.ac b/pixman/configure.ac index 8a3b62268..5e512be8e 100644 --- a/pixman/configure.ac +++ b/pixman/configure.ac @@ -54,7 +54,7 @@ AC_PREREQ([2.57]) m4_define([pixman_major], 0) m4_define([pixman_minor], 31) -m4_define([pixman_micro], 1) +m4_define([pixman_micro], 3) m4_define([pixman_version],[pixman_major.pixman_minor.pixman_micro]) @@ -1044,6 +1044,22 @@ fi AC_MSG_RESULT($support_for_float128) +dnl ===================================== +dnl __builtin_clz + +support_for_builtin_clz=no + +AC_MSG_CHECKING(for __builtin_clz) +AC_LINK_IFELSE([AC_LANG_SOURCE([[ +unsigned int x = 11; int main (void) { return __builtin_clz(x); } +]])], support_for_builtin_clz=yes) + +if test x$support_for_builtin_clz = xyes; then + AC_DEFINE([HAVE_BUILTIN_CLZ], [], [Whether the compiler supports __builtin_clz]) +fi + +AC_MSG_RESULT($support_for_builtin_clz) + dnl ================== dnl libpng diff --git a/pixman/pixman/pixman-matrix.c b/pixman/pixman/pixman-matrix.c index 89b96826b..4032c137a 100644 --- a/pixman/pixman/pixman-matrix.c +++ b/pixman/pixman/pixman-matrix.c @@ -37,7 +37,7 @@ static force_inline int count_leading_zeros (uint32_t x) { -#ifdef __GNUC__ +#ifdef HAVE_BUILTIN_CLZ return __builtin_clz (x); #else int n = 0; diff --git a/pixman/pixman/pixman.h b/pixman/pixman/pixman.h index 7ff9fb52a..509ba5e53 100644 --- a/pixman/pixman/pixman.h +++ b/pixman/pixman/pixman.h @@ -1030,7 +1030,7 @@ struct pixman_triangle #define pixman_trapezoid_valid(t) \ ((t)->left.p1.y != (t)->left.p2.y && \ (t)->right.p1.y != (t)->right.p2.y && \ - (int) ((t)->bottom - (t)->top) > 0) + ((t)->bottom > (t)->top)) struct pixman_span_fix { diff --git a/pixman/test/trap-crasher.c b/pixman/test/trap-crasher.c index 4e4cac297..77be1c98b 100644 --- a/pixman/test/trap-crasher.c +++ b/pixman/test/trap-crasher.c @@ -5,7 +5,7 @@ int main() { pixman_image_t *dst; - pixman_trapezoid_t traps[1] = { + pixman_trapezoid_t traps[] = { { 2147483646, 2147483647, @@ -18,6 +18,18 @@ main() { 0, 2147483647 } } }, + { + 32768, + - 2147483647, + { + { 0, 0 }, + { 0, 2147483647 } + }, + { + { 65536, 0 }, + { 0, 2147483647 } + } + }, }; dst = pixman_image_create_bits (PIXMAN_a8, 1, 1, NULL, -1); diff --git a/xkbcomp/action.c b/xkbcomp/action.c index 3b82e647e..4623c0caf 100644 --- a/xkbcomp/action.c +++ b/xkbcomp/action.c @@ -41,7 +41,7 @@ static ExprDef constFalse; /***====================================================================***/ static Bool -stringToAction(char *str, unsigned *type_rtrn) +stringToAction(const char *str, unsigned *type_rtrn) { if (str == NULL) return False; @@ -134,7 +134,7 @@ stringToAction(char *str, unsigned *type_rtrn) } static Bool -stringToField(char *str, unsigned *field_rtrn) +stringToField(const char *str, unsigned *field_rtrn) { if (str == NULL) @@ -1397,8 +1397,8 @@ HandleActionDef(ExprDef * def, int SetActionField(XkbDescPtr xkb, - char *elem, - char *field, + const char *elem, + const char *field, ExprDef * array_ndx, ExprDef * value, ActionInfo ** info_rtrn) { ActionInfo *new, *old; diff --git a/xkbcomp/action.h b/xkbcomp/action.h index 2fb7a5eb9..983b06e20 100644 --- a/xkbcomp/action.h +++ b/xkbcomp/action.h @@ -72,8 +72,8 @@ extern int HandleActionDef(ExprDef * /* def */ , ); extern int SetActionField(XkbDescPtr /* xkb */ , - char * /* elem */ , - char * /* field */ , + const char * /* elem */ , + const char * /* field */ , ExprDef * /* index */ , ExprDef * /* value */ , ActionInfo ** /* info_rtrn */ diff --git a/xkbcomp/compat.c b/xkbcomp/compat.c index f4d82a6de..82fd4e666 100644 --- a/xkbcomp/compat.c +++ b/xkbcomp/compat.c @@ -494,7 +494,7 @@ static LookupEntry useModMapValues[] = { static int SetInterpField(SymInterpInfo * si, XkbDescPtr xkb, - char *field, + const char *field, ExprDef * arrayNdx, ExprDef * value, CompatInfo * info) { int ok = 1; diff --git a/xkbcomp/expr.c b/xkbcomp/expr.c index 96fd95675..e0f957c15 100644 --- a/xkbcomp/expr.c +++ b/xkbcomp/expr.c @@ -292,7 +292,7 @@ ExprResolveModIndex(ExprDef * expr, IdentLookupFunc lookup, XPointer lookupPriv) { int ok = 0; - char *bogus = NULL; + const char *bogus = NULL; switch (expr->op) { @@ -382,7 +382,7 @@ ExprResolveBoolean(ExprDef * expr, IdentLookupFunc lookup, XPointer lookupPriv) { int ok = 0; - char *bogus = NULL; + const char *bogus = NULL; switch (expr->op) { @@ -715,7 +715,7 @@ ExprResolveString(ExprDef * expr, ExprResult leftRtrn, rightRtrn; ExprDef *left; ExprDef *right; - char *bogus = NULL; + const char *bogus = NULL; switch (expr->op) { @@ -729,7 +729,7 @@ ExprResolveString(ExprDef * expr, val_rtrn->str = XkbAtomGetString(NULL, expr->value.str); if (val_rtrn->str == NULL) { - static char *empty = ""; + static const char *empty = ""; val_rtrn->str = empty; } return True; @@ -767,7 +767,7 @@ ExprResolveString(ExprDef * expr, new = (char *) uAlloc(len); if (new) { - sprintf(new, "%s%s", leftRtrn.str, rightRtrn.str); + snprintf(new, len, "%s%s", leftRtrn.str, rightRtrn.str); val_rtrn->str = new; return True; } @@ -822,7 +822,7 @@ ExprResolveKeyName(ExprDef * expr, int ok = 0; ExprDef *left; ExprResult leftRtrn; - char *bogus = NULL; + const char *bogus = NULL; switch (expr->op) { @@ -941,7 +941,7 @@ ExprResolveMask(ExprDef * expr, int ok = 0; ExprResult leftRtrn, rightRtrn; ExprDef *left, *right; - char *bogus = NULL; + const char *bogus = NULL; switch (expr->op) { diff --git a/xkbcomp/geometry.c b/xkbcomp/geometry.c index 7f65c3af4..2daa213ac 100644 --- a/xkbcomp/geometry.c +++ b/xkbcomp/geometry.c @@ -258,9 +258,9 @@ ddText(Display * dpy, DoodadInfo * di) } if (di->section) { - sprintf(buf, "%s in section %s", - XkbAtomText(dpy, di->name, XkbMessage), scText(dpy, - di->section)); + snprintf(buf, sizeof(buf), "%s in section %s", + XkbAtomText(dpy, di->name, XkbMessage), + scText(dpy, di->section)); return buf; } return XkbAtomText(dpy, di->name, XkbMessage); @@ -967,7 +967,7 @@ AddDoodad(SectionInfo * si, GeometryInfo * info, DoodadInfo * new) } static DoodadInfo * -FindDfltDoodadByTypeName(char *name, SectionInfo * si, GeometryInfo * info) +FindDfltDoodadByTypeName(const char *name, SectionInfo *si, GeometryInfo *info) { DoodadInfo *dflt; unsigned type; @@ -1408,7 +1408,7 @@ HandleIncludeGeometry(IncludeStmt * stmt, XkbDescPtr xkb, GeometryInfo * info, static int SetShapeField(ShapeInfo * si, - char *field, + const char *field, ExprDef * arrayNdx, ExprDef * value, GeometryInfo * info) { ExprResult tmp; @@ -1440,7 +1440,7 @@ SetShapeField(ShapeInfo * si, static int SetShapeDoodadField(DoodadInfo * di, - char *field, + const char *field, ExprDef * arrayNdx, ExprDef * value, SectionInfo * si, GeometryInfo * info) { @@ -1510,14 +1510,14 @@ SetShapeDoodadField(DoodadInfo * di, static int SetTextDoodadField(DoodadInfo * di, - char *field, + const char *field, ExprDef * arrayNdx, ExprDef * value, SectionInfo * si, GeometryInfo * info) { ExprResult tmp; unsigned def; unsigned type; - char *typeName = "text doodad"; + const char *typeName = "text doodad"; union { Atom *str; @@ -1660,7 +1660,7 @@ SetTextDoodadField(DoodadInfo * di, static int SetIndicatorDoodadField(DoodadInfo * di, - char *field, + const char *field, ExprDef * arrayNdx, ExprDef * value, SectionInfo * si, GeometryInfo * info) @@ -1705,12 +1705,12 @@ SetIndicatorDoodadField(DoodadInfo * di, static int SetLogoDoodadField(DoodadInfo * di, - char *field, + const char *field, ExprDef * arrayNdx, ExprDef * value, SectionInfo * si, GeometryInfo * info) { ExprResult tmp; - char *typeName = "logo doodad"; + const char *typeName = "logo doodad"; if ((!uStrCaseCmp(field, "corner")) || (!uStrCaseCmp(field, "cornerradius"))) @@ -1786,7 +1786,7 @@ SetLogoDoodadField(DoodadInfo * di, static int SetDoodadField(DoodadInfo * di, - char *field, + const char *field, ExprDef * arrayNdx, ExprDef * value, SectionInfo * si, GeometryInfo * info) { @@ -1889,7 +1889,7 @@ SetDoodadField(DoodadInfo * di, static int SetSectionField(SectionInfo * si, - char *field, + const char *field, ExprDef * arrayNdx, ExprDef * value, GeometryInfo * info) { unsigned short *pField; @@ -1977,7 +1977,7 @@ SetSectionField(SectionInfo * si, static int SetRowField(RowInfo * row, - char *field, + const char *field, ExprDef * arrayNdx, ExprDef * value, GeometryInfo * info) { ExprResult tmp; @@ -2841,7 +2841,7 @@ HandleGeometryFile(XkbFile * file, XkbDescPtr xkb, unsigned merge, GeometryInfo * info) { ParseCommon *stmt; - char *failWhat; + const char *failWhat; if (merge == MergeDefault) merge = MergeAugment; @@ -3273,7 +3273,7 @@ FontFromParts(Atom fontTok, Atom setWidthTok, Atom varTok, int size, Atom encodingTok) { int totalSize; - char *font, *weight, *slant, *setWidth, *variant, *encoding; + const char *font, *weight, *slant, *setWidth, *variant, *encoding; char *rtrn; font = (fontTok != None ? XkbAtomGetString(NULL, fontTok) : DFLT_FONT); @@ -3297,8 +3297,8 @@ FontFromParts(Atom fontTok, rtrn = uCalloc(totalSize, 1); if (rtrn) { - sprintf(rtrn, FONT_TEMPLATE, font, weight, slant, setWidth, variant, - size, encoding); + snprintf(rtrn, totalSize, FONT_TEMPLATE, font, weight, slant, + setWidth, variant, size, encoding); } return rtrn; } diff --git a/xkbcomp/indicators.c b/xkbcomp/indicators.c index d4a362fb8..421ad583d 100644 --- a/xkbcomp/indicators.c +++ b/xkbcomp/indicators.c @@ -200,7 +200,7 @@ static LookupEntry groupComponentNames[] = { int SetIndicatorMapField(LEDInfo * led, XkbDescPtr xkb, - char *field, ExprDef * arrayNdx, ExprDef * value) + const char *field, ExprDef *arrayNdx, ExprDef *value) { ExprResult rtrn; Bool ok; diff --git a/xkbcomp/indicators.h b/xkbcomp/indicators.h index 35ae38a4c..8e7884d7c 100644 --- a/xkbcomp/indicators.h +++ b/xkbcomp/indicators.h @@ -62,7 +62,7 @@ extern LEDInfo *AddIndicatorMap(LEDInfo * /* oldLEDs */ , extern int SetIndicatorMapField(LEDInfo * /* led */ , XkbDescPtr /* xkb */ , - char * /* field */ , + const char * /* field */ , ExprDef * /* arrayNdx */ , ExprDef * /* value */ ); diff --git a/xkbcomp/keytypes.c b/xkbcomp/keytypes.c index da55d755d..375ca3e0d 100644 --- a/xkbcomp/keytypes.c +++ b/xkbcomp/keytypes.c @@ -879,7 +879,7 @@ SetLevelName(KeyTypeInfo * type, ExprDef * arrayNdx, ExprDef * value) static Bool SetKeyTypeField(KeyTypeInfo * type, XkbDescPtr xkb, - char *field, + const char *field, ExprDef * arrayNdx, ExprDef * value, KeyTypesInfo * info) { ExprResult tmp; diff --git a/xkbcomp/listing.c b/xkbcomp/listing.c index 11de88a83..c7f5ef83b 100644 --- a/xkbcomp/listing.c +++ b/xkbcomp/listing.c @@ -302,18 +302,19 @@ AddDirectory(char *head, char *ptrn, char *rest, char *map) { char *tmp, *filename; struct stat sbuf; + size_t tmpsize; filename = FileName(file); if (!filename || filename[0] == '.') continue; if (ptrn && (!XkbNameMatchesPattern(filename, ptrn))) continue; - tmp = - (char *) uAlloc((head ? strlen(head) : 0) + strlen(filename) + 2); + tmpsize = (head ? strlen(head) : 0) + strlen(filename) + 2; + tmp = uAlloc(tmpsize); if (!tmp) continue; - sprintf(tmp, "%s%s%s", (head ? head : ""), (head ? "/" : ""), - filename); + snprintf(tmp, tmpsize, "%s%s%s", + (head ? head : ""), (head ? "/" : ""), filename); if (stat(tmp, &sbuf) < 0) { uFree(tmp); diff --git a/xkbcomp/symbols.c b/xkbcomp/symbols.c index 5547999b5..d43ba9ffb 100644 --- a/xkbcomp/symbols.c +++ b/xkbcomp/symbols.c @@ -928,7 +928,7 @@ GetGroupIndex(KeyInfo * key, static Bool AddSymbolsToKey(KeyInfo * key, XkbDescPtr xkb, - char *field, + const char *field, ExprDef * arrayNdx, ExprDef * value, SymbolsInfo * info) { unsigned ndx, nSyms; @@ -982,7 +982,7 @@ AddSymbolsToKey(KeyInfo * key, static Bool AddActionsToKey(KeyInfo * key, XkbDescPtr xkb, - char *field, + const char *field, ExprDef * arrayNdx, ExprDef * value, SymbolsInfo * info) { register int i; @@ -1118,7 +1118,7 @@ static LookupEntry rgEntries[] = { static Bool SetSymbolsField(KeyInfo * key, XkbDescPtr xkb, - char *field, + const char *field, ExprDef * arrayNdx, ExprDef * value, SymbolsInfo * info) { Bool ok = True; @@ -1235,7 +1235,7 @@ SetSymbolsField(KeyInfo * key, uStrCasePrefix("permanentoverlay", field)) { Bool permanent = False; - char *which; + const char *which; int overlayNdx; if (uStrCasePrefix("permanent", field)) { diff --git a/xkbcomp/utils.c b/xkbcomp/utils.c index 55efbe11f..541c33e14 100644 --- a/xkbcomp/utils.c +++ b/xkbcomp/utils.c @@ -88,65 +88,6 @@ uFree(Opaque ptr) } /***====================================================================***/ -/*** FUNCTION ENTRY TRACKING ***/ -/***====================================================================***/ - -static FILE *entryFile = NULL; -int uEntryLevel; - -Boolean -uSetEntryFile(char *name) -{ - if ((entryFile != NULL) && (entryFile != stderr)) - { - fprintf(entryFile, "switching to %s\n", name ? name : "stderr"); - fclose(entryFile); - } - if (name != NullString) - entryFile = fopen(name, "w"); - else - entryFile = stderr; - if (entryFile == NULL) - { - entryFile = stderr; - return (False); - } - return (True); -} - -void -uEntry(int l, char *s, ...) -{ - int i; - va_list args; - - for (i = 0; i < uEntryLevel; i++) - { - putc(' ', entryFile); - } - va_start(args, s); - vfprintf(entryFile, s, args); - va_end(args); - uEntryLevel += l; -} - -void -uExit(int l, char *rtVal) -{ - int i; - - uEntryLevel -= l; - if (uEntryLevel < 0) - uEntryLevel = 0; - for (i = 0; i < uEntryLevel; i++) - { - putc(' ', entryFile); - } - fprintf(entryFile, "---> %p\n", rtVal); - return; -} - -/***====================================================================***/ /*** PRINT FUNCTIONS ***/ /***====================================================================***/ diff --git a/xkbcomp/utils.h b/xkbcomp/utils.h index b00067d6e..81f5893b6 100644 --- a/xkbcomp/utils.h +++ b/xkbcomp/utils.h @@ -219,15 +219,6 @@ uInformation(const char * /* s */ , ... /***====================================================================***/ -#ifdef ASSERTIONS_ON -#define uASSERT(where,why) \ - {if (!(why)) uFatalError("assertion botched in %s ( why )\n",where);} -#else -#define uASSERT(where,why) -#endif - -/***====================================================================***/ - #ifndef DEBUG_VAR #define DEBUG_VAR debugFlags #endif @@ -277,64 +268,4 @@ extern #define uDEBUG_NOI5(f,s,a,b,c,d,e) #endif - extern Boolean uSetEntryFile(char *name); - extern void uEntry(int /* l */ , - char * /* s */ , ... - ) _X_ATTRIBUTE_PRINTF(2, 3); - - extern void uExit(int l, char *rtVal); -#ifdef ENTRY_TRACKING_ON -#define ENTRY_BIT 0x10 -#define LOW_ENTRY_BIT 0x1000 -#define ENTER (DEBUG_VAR&ENTRY_BIT) -#define FLAG(fLag) (DEBUG_VAR&(fLag)) - - extern int uEntryLevel; - -#define uENTRY(s) { if (ENTER) uEntry(1,s);} -#define uENTRY1(s,a) { if (ENTER) uEntry(1,s,a);} -#define uENTRY2(s,a,b) { if (ENTER) uEntry(1,s,a,b);} -#define uENTRY3(s,a,b,c) { if (ENTER) uEntry(1,s,a,b,c);} -#define uENTRY4(s,a,b,c,d) { if (ENTER) uEntry(1,s,a,b,c,d);} -#define uENTRY5(s,a,b,c,d,e) { if (ENTER) uEntry(1,s,a,b,c,d,e);} -#define uENTRY6(s,a,b,c,d,e,f) { if (ENTER) uEntry(1,s,a,b,c,d,e,f);} -#define uENTRY7(s,a,b,c,d,e,f,g) { if (ENTER) uEntry(1,s,a,b,c,d,e,f,g);} -#define uRETURN(v) { if (ENTER) uEntryLevel--; return(v); } -#define uVOIDRETURN { if (ENTER) uEntryLevel--; return; } - -#define uFLAG_ENTRY(w,s) { if (FLAG(w)) uEntry(0,s);} -#define uFLAG_ENTRY1(w,s,a) { if (FLAG(w)) uEntry(0,s,a);} -#define uFLAG_ENTRY2(w,s,a,b) { if (FLAG(w)) uEntry(0,s,a,b);} -#define uFLAG_ENTRY3(w,s,a,b,c) { if (FLAG(w)) uEntry(0,s,a,b,c);} -#define uFLAG_ENTRY4(w,s,a,b,c,d) { if (FLAG(w)) uEntry(0,s,a,b,c,d);} -#define uFLAG_ENTRY5(w,s,a,b,c,d,e) { if (FLAG(w)) uEntry(0,s,a,b,c,d,e);} -#define uFLAG_ENTRY6(w,s,a,b,c,d,e,f) { if (FLAG(w)) uEntry(0,s,a,b,c,d,e,f);} -#define uFLAG_ENTRY7(w,s,a,b,c,d,e,f,g) { if(FLAG(w))uEntry(0,s,a,b,c,d,e,f,g);} -#define uFLAG_RETURN(v) { return(v);} -#define uFLAG_VOIDRETURN { return; } -#else -#define uENTRY(s) -#define uENTRY1(s,a) -#define uENTRY2(s,a1,a2) -#define uENTRY3(s,a1,a2,a3) -#define uENTRY4(s,a1,a2,a3,a4) -#define uENTRY5(s,a1,a2,a3,a4,a5) -#define uENTRY6(s,a1,a2,a3,a4,a5,a6) -#define uENTRY7(s,a1,a2,a3,a4,a5,a6,a7) -#define uRETURN(v) { return(v); } -#define uVOIDRETURN { return; } - -#define uFLAG_ENTRY(f,s) -#define uFLAG_ENTRY1(f,s,a) -#define uFLAG_ENTRY2(f,s,a,b) -#define uFLAG_ENTRY3(f,s,a,b,c) -#define uFLAG_ENTRY4(f,s,a,b,c,d) -#define uFLAG_ENTRY5(f,s,a,b,c,d,e) -#define uFLAG_ENTRY6(f,s,a,b,c,d,e,g) -#define uFLAG_ENTRY7(f,s,a,b,c,d,e,g,h) -#define uFLAG_RETURN(v) { return(v);} -#define uFLAG_VOIDRETURN { return; } -#endif - - #endif /* UTILS_H */ diff --git a/xkbcomp/xkbcomp.c b/xkbcomp/xkbcomp.c index fb5dec2fc..956e79c0f 100644 --- a/xkbcomp/xkbcomp.c +++ b/xkbcomp/xkbcomp.c @@ -745,7 +745,7 @@ parseArgs(int argc, char *argv[]) ACTION("Exiting\n"); exit(1); } - sprintf(outputFile, "stdin.%s", fileTypeExt[outputFormat]); + snprintf(outputFile, len, "stdin.%s", fileTypeExt[outputFormat]); } else if ((outputFile == NULL) && (inputFile != NULL)) { @@ -773,7 +773,7 @@ parseArgs(int argc, char *argv[]) } ext = strrchr(base, '.'); if (ext == NULL) - sprintf(outputFile, "%s.%s", base, fileTypeExt[outputFormat]); + snprintf(outputFile, len, "%s.%s", base, fileTypeExt[outputFormat]); else { strcpy(outputFile, base); @@ -881,7 +881,6 @@ main(int argc, char *argv[]) Status status; scan_set_file(stdin); - uSetEntryFile(NullString); uSetDebugFile(NullString); uSetErrorFile(NullString); diff --git a/xorg-server/Makefile.am b/xorg-server/Makefile.am index 7be4271d4..5bf760b2e 100644 --- a/xorg-server/Makefile.am +++ b/xorg-server/Makefile.am @@ -17,6 +17,14 @@ if RECORD RECORD_DIR=record endif +if DRI3 +DRI3_DIR=dri3 +endif + +if PRESENT +PRESENT_DIR=present +endif + SUBDIRS = \ doc \ man \ @@ -38,6 +46,8 @@ SUBDIRS = \ damageext \ $(COMPOSITE_DIR) \ $(GLX_DIR) \ + $(PRESENT_DIR) \ + $(DRI3_DIR) \ exa \ config \ hw \ @@ -91,6 +101,8 @@ DIST_SUBDIRS = \ glx \ exa \ config \ + dri3 \ + present \ hw \ test diff --git a/xorg-server/Xext/shm.c b/xorg-server/Xext/shm.c index 55960907b..1a70260fb 100644 --- a/xorg-server/Xext/shm.c +++ b/xorg-server/Xext/shm.c @@ -53,6 +53,7 @@ in this Software without prior written authorization from The Open Group. #include "xace.h" #include <X11/extensions/shmproto.h> #include <X11/Xfuncproto.h> +#include <sys/mman.h> #include "protocol-versions.h" /* Needed for Solaris cross-zone shared memory extension */ @@ -89,15 +90,6 @@ in this Software without prior written authorization from The Open Group. #include "extinit.h" -typedef struct _ShmDesc { - struct _ShmDesc *next; - int shmid; - int refcnt; - char *addr; - Bool writable; - unsigned long size; -} ShmDescRec, *ShmDescPtr; - typedef struct _ShmScrPrivateRec { CloseScreenProcPtr CloseScreen; ShmFuncsPtr shmFuncs; @@ -391,8 +383,10 @@ ProcShmAttach(ClientPtr client) client->errorValue = stuff->readOnly; return BadValue; } - for (shmdesc = Shmsegs; - shmdesc && (shmdesc->shmid != stuff->shmid); shmdesc = shmdesc->next); + for (shmdesc = Shmsegs; shmdesc; shmdesc = shmdesc->next) { + if (!shmdesc->is_fd && shmdesc->shmid == stuff->shmid) + break; + } if (shmdesc) { if (!stuff->readOnly && !shmdesc->writable) return BadAccess; @@ -402,6 +396,7 @@ ProcShmAttach(ClientPtr client) shmdesc = malloc(sizeof(ShmDescRec)); if (!shmdesc) return BadAlloc; + shmdesc->is_fd = FALSE; shmdesc->addr = shmat(stuff->shmid, 0, stuff->readOnly ? SHM_RDONLY : 0); if ((shmdesc->addr == ((char *) -1)) || SHMSTAT(stuff->shmid, &buf)) { @@ -440,7 +435,10 @@ ShmDetachSegment(pointer value, /* must conform to DeleteType */ if (--shmdesc->refcnt) return TRUE; - shmdt(shmdesc->addr); + if (shmdesc->is_fd) + munmap(shmdesc->addr, shmdesc->size); + else + shmdt(shmdesc->addr); for (prev = &Shmsegs; *prev != shmdesc; prev = &(*prev)->next); *prev = shmdesc->next; free(shmdesc); @@ -1097,6 +1095,122 @@ ProcShmCreatePixmap(ClientPtr client) } static int +ProcShmAttachFd(ClientPtr client) +{ + int fd; + ShmDescPtr shmdesc; + REQUEST(xShmAttachFdReq); + struct stat statb; + + SetReqFds(client, 1); + REQUEST_SIZE_MATCH(xShmAttachFdReq); + LEGAL_NEW_RESOURCE(stuff->shmseg, client); + if ((stuff->readOnly != xTrue) && (stuff->readOnly != xFalse)) { + client->errorValue = stuff->readOnly; + return BadValue; + } + fd = ReadFdFromClient(client); + if (fd < 0) + return BadMatch; + + if (fstat(fd, &statb) < 0 || statb.st_size == 0) { + close(fd); + return BadMatch; + } + + shmdesc = malloc(sizeof(ShmDescRec)); + if (!shmdesc) { + close(fd); + return BadAlloc; + } + shmdesc->is_fd = TRUE; + shmdesc->addr = mmap(NULL, statb.st_size, + stuff->readOnly ? PROT_READ : PROT_READ|PROT_WRITE, + MAP_SHARED, + fd, 0); + + close(fd); + if ((shmdesc->addr == ((char *) -1))) { + free(shmdesc); + return BadAccess; + } + + shmdesc->refcnt = 1; + shmdesc->writable = !stuff->readOnly; + shmdesc->size = statb.st_size; + shmdesc->next = Shmsegs; + Shmsegs = shmdesc; + + if (!AddResource(stuff->shmseg, ShmSegType, (pointer) shmdesc)) + return BadAlloc; + return Success; +} + +static int +ProcShmCreateSegment(ClientPtr client) +{ + int fd; + ShmDescPtr shmdesc; + REQUEST(xShmCreateSegmentReq); + xShmCreateSegmentReply rep = { + .type = X_Reply, + .nfd = 1, + .sequenceNumber = client->sequence, + .length = 0, + }; + char template[] = "/tmp/shm-XXXXXX"; + + REQUEST_SIZE_MATCH(xShmCreateSegmentReq); + if ((stuff->readOnly != xTrue) && (stuff->readOnly != xFalse)) { + client->errorValue = stuff->readOnly; + return BadValue; + } + fd = mkstemp(template); + if (fd < 0) + return BadAlloc; + unlink(template); + if (ftruncate(fd, stuff->size) < 0) { + close(fd); + return BadAlloc; + } + shmdesc = malloc(sizeof(ShmDescRec)); + if (!shmdesc) { + close(fd); + return BadAlloc; + } + shmdesc->is_fd = TRUE; + shmdesc->addr = mmap(NULL, stuff->size, + stuff->readOnly ? PROT_READ : PROT_READ|PROT_WRITE, + MAP_SHARED, + fd, 0); + + if ((shmdesc->addr == ((char *) -1))) { + close(fd); + free(shmdesc); + return BadAccess; + } + + shmdesc->refcnt = 1; + shmdesc->writable = !stuff->readOnly; + shmdesc->size = stuff->size; + shmdesc->next = Shmsegs; + Shmsegs = shmdesc; + + if (!AddResource(stuff->shmseg, ShmSegType, (pointer) shmdesc)) { + close(fd); + return BadAlloc; + } + + if (WriteFdToClient(client, fd, TRUE) < 0) { + FreeResource(stuff->shmseg, RT_NONE); + close(fd); + return BadAlloc; + } + WriteToClient(client, sizeof (xShmCreateSegmentReply), &rep); + return Success; +} + +static int ProcShmDispatch(ClientPtr client) { REQUEST(xReq); @@ -1125,6 +1239,10 @@ ProcShmDispatch(ClientPtr client) return ProcPanoramiXShmCreatePixmap(client); #endif return ProcShmCreatePixmap(client); + case X_ShmAttachFd: + return ProcShmAttachFd(client); + case X_ShmCreateSegment: + return ProcShmCreateSegment(client); default: return BadRequest; } @@ -1226,6 +1344,28 @@ SProcShmCreatePixmap(ClientPtr client) } static int +SProcShmAttachFd(ClientPtr client) +{ + REQUEST(xShmAttachFdReq); + SetReqFds(client, 1); + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xShmAttachFdReq); + swapl(&stuff->shmseg); + return ProcShmAttachFd(client); +} + +static int +SProcShmCreateSegment(ClientPtr client) +{ + REQUEST(xShmCreateSegmentReq); + swaps(&stuff->length); + REQUEST_SIZE_MATCH(xShmCreateSegmentReq); + swapl(&stuff->shmseg); + swapl(&stuff->size); + return ProcShmCreateSegment(client); +} + +static int SProcShmDispatch(ClientPtr client) { REQUEST(xReq); @@ -1242,6 +1382,10 @@ SProcShmDispatch(ClientPtr client) return SProcShmGetImage(client); case X_ShmCreatePixmap: return SProcShmCreatePixmap(client); + case X_ShmAttachFd: + return SProcShmAttachFd(client); + case X_ShmCreateSegment: + return SProcShmCreateSegment(client); default: return BadRequest; } diff --git a/xorg-server/Xext/shmint.h b/xorg-server/Xext/shmint.h index fa6941c90..db35fbbbe 100644 --- a/xorg-server/Xext/shmint.h +++ b/xorg-server/Xext/shmint.h @@ -56,6 +56,16 @@ typedef struct _ShmFuncs { void (*PutImage) (XSHM_PUT_IMAGE_ARGS); } ShmFuncs, *ShmFuncsPtr; +typedef struct _ShmDesc { + struct _ShmDesc *next; + int shmid; + int refcnt; + char *addr; + Bool is_fd; + Bool writable; + unsigned long size; +} ShmDescRec, *ShmDescPtr; + extern _X_EXPORT void ShmRegisterFuncs(ScreenPtr pScreen, ShmFuncsPtr funcs); diff --git a/xorg-server/Xext/sync.c b/xorg-server/Xext/sync.c index b2ee92e37..a04c38388 100644 --- a/xorg-server/Xext/sync.c +++ b/xorg-server/Xext/sync.c @@ -141,7 +141,7 @@ SyncCheckWarnIsCounter(const SyncObject * pSync, const char *warning) * interested in the counter. The two functions below are used to * delete and add triggers on this list. */ -static void +void SyncDeleteTriggerFromSyncObject(SyncTrigger * pTrigger) { SyncTriggerList *pCur; @@ -184,7 +184,7 @@ SyncDeleteTriggerFromSyncObject(SyncTrigger * pTrigger) } } -static int +int SyncAddTriggerToSyncObject(SyncTrigger * pTrigger) { SyncTriggerList *pCur; @@ -916,6 +916,34 @@ SyncCreate(ClientPtr client, XID id, unsigned char type) return pSync; } +int +SyncCreateFenceFromFD(ClientPtr client, DrawablePtr pDraw, XID id, int fd, BOOL initially_triggered) +{ + SyncFence *pFence; + int status; + + pFence = (SyncFence *) SyncCreate(client, id, SYNC_FENCE); + if (!pFence) + return BadAlloc; + + status = miSyncInitFenceFromFD(pDraw, pFence, fd, initially_triggered); + if (status != Success) { + miSyncDestroyFence(pFence); + return status; + } + + if (!AddResource(id, RTFence, (pointer) pFence)) + return BadAlloc; + + return Success; +} + +int +SyncFDFromFence(ClientPtr client, DrawablePtr pDraw, SyncFence *pFence) +{ + return miSyncFDFromFence(pDraw, pFence); +} + static SyncCounter * SyncCreateCounter(ClientPtr client, XSyncCounter id, CARD64 initialvalue) { @@ -2654,7 +2682,16 @@ IdleTimeBlockHandler(pointer pCounter, struct timeval **wt, pointer LastSelectMa IdleTimeQueryValue(counter, &idle); counter->value = idle; /* push, so CheckTrigger works */ - if (less && XSyncValueLessOrEqual(idle, *less)) { + /** + * There's an indefinite amount of time between ProcessInputEvents() + * where the idle time is reset and the time we actually get here. idle + * may be past the lower bracket if we dawdled with the events, so + * check for whether we did reset and bomb out of select immediately. + */ + if (less && XSyncValueGreaterThan(idle, *less) && + LastEventTimeWasReset(priv->deviceid)) { + AdjustWaitForDelay(wt, 0); + } else if (less && XSyncValueLessOrEqual(idle, *less)) { /* * We've been idle for less than the threshold value, and someone * wants to know about that, but now we need to know whether they diff --git a/xorg-server/Xext/syncsrv.h b/xorg-server/Xext/syncsrv.h index c68229f46..45fca04da 100644 --- a/xorg-server/Xext/syncsrv.h +++ b/xorg-server/Xext/syncsrv.h @@ -136,4 +136,17 @@ extern void SyncDestroySystemCounter(pointer pCounter); extern SyncCounter *SyncInitDeviceIdleTime(DeviceIntPtr dev); extern void SyncRemoveDeviceIdleTime(SyncCounter *counter); + +int +SyncCreateFenceFromFD(ClientPtr client, DrawablePtr pDraw, XID id, int fd, BOOL initially_triggered); + +int +SyncFDFromFence(ClientPtr client, DrawablePtr pDraw, SyncFence *fence); + +void +SyncDeleteTriggerFromSyncObject(SyncTrigger * pTrigger); + +int +SyncAddTriggerToSyncObject(SyncTrigger * pTrigger); + #endif /* _SYNCSRV_H_ */ diff --git a/xorg-server/Xext/xvdisp.c b/xorg-server/Xext/xvdisp.c index 787729387..613867a6b 100644 --- a/xorg-server/Xext/xvdisp.c +++ b/xorg-server/Xext/xvdisp.c @@ -43,6 +43,7 @@ SOFTWARE. #include "xvdix.h" #ifdef MITSHM #include <X11/extensions/shmproto.h> +#include "shmint.h" #endif #include "xvdisp.h" @@ -949,18 +950,6 @@ ProcXvPutImage(ClientPtr client) } #ifdef MITSHM -/* redefined here since it's not in any header file */ -typedef struct _ShmDesc { - struct _ShmDesc *next; - int shmid; - int refcnt; - char *addr; - Bool writable; - unsigned long size; -} ShmDescRec, *ShmDescPtr; - -extern RESTYPE ShmSegType; -extern int ShmCompletionCode; static int ProcXvShmPutImage(ClientPtr client) diff --git a/xorg-server/configure.ac b/xorg-server/configure.ac index d29f1706a..0d855f250 100644 --- a/xorg-server/configure.ac +++ b/xorg-server/configure.ac @@ -26,9 +26,9 @@ dnl dnl Process this file with autoconf to create configure. AC_PREREQ(2.60) -AC_INIT([xorg-server], 1.14.99.3, [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], xorg-server) -RELEASE_DATE="2013-10-18" -RELEASE_NAME="Bundaberg" +AC_INIT([xorg-server], 1.14.99.901, [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], xorg-server) +RELEASE_DATE="2013-10-31" +RELEASE_NAME="Bom Retiro" AC_CONFIG_SRCDIR([Makefile.am]) AM_INIT_AUTOMAKE([foreign dist-bzip2]) @@ -228,10 +228,6 @@ dnl AGPGART headers AC_CHECK_HEADERS([linux/agpgart.h sys/agpio.h sys/agpgart.h], AGP=yes) AM_CONDITIONAL(AGP, [test "x$AGP" = xyes]) -dnl APM header -AC_CHECK_HEADERS([linux/apm_bios.h], LNXAPM=yes) -AM_CONDITIONAL(LNXAPM, [test "x$LNXAPM" = xyes]) - dnl fbdev header AC_CHECK_HEADERS([linux/fb.h], FBDEV=yes) AM_CONDITIONAL(FBDEVHW, [test "x$FBDEV" = xyes]) @@ -300,7 +296,7 @@ AC_CHECK_HEADER([machine/apmvar.h],[ AM_CONDITIONAL(BSD_APM, [test "x$ac_cv_BSD_APM" = xyes]) AM_CONDITIONAL(BSD_KQUEUE_APM, [test "x$ac_cv_BSD_KQUEUE_APM" = xyes]) -dnl glibc backtrace support check (hw/xfree86/common/xf86Events.c) +dnl glibc backtrace support check AC_CHECK_HEADER([execinfo.h],[ AC_CHECK_LIB(c, backtrace, [ AC_DEFINE(HAVE_BACKTRACE, 1, [Has backtrace support]) @@ -613,6 +609,8 @@ AC_ARG_ENABLE(xdm-auth-1, AS_HELP_STRING([--disable-xdm-auth-1], [Build XDM- AC_ARG_ENABLE(glx, AS_HELP_STRING([--disable-glx], [Build GLX extension (default: enabled)]), [GLX=$enableval], [GLX=yes]) AC_ARG_ENABLE(dri, AS_HELP_STRING([--enable-dri], [Build DRI extension (default: auto)]), [DRI=$enableval]) AC_ARG_ENABLE(dri2, AS_HELP_STRING([--enable-dri2], [Build DRI2 extension (default: auto)]), [DRI2=$enableval], [DRI2=auto]) +AC_ARG_ENABLE(dri3, AS_HELP_STRING([--enable-dri3], [Build DRI3 extension (default: auto)]), [DRI3=$enableval], [DRI3=auto]) +AC_ARG_ENABLE(present, AS_HELP_STRING([--disable-present], [Build Present extension (default: enabled)]), [PRESENT=$enableval], [PRESENT=yes]) AC_ARG_ENABLE(xinerama, AS_HELP_STRING([--disable-xinerama], [Build Xinerama extension (default: enabled)]), [XINERAMA=$enableval], [XINERAMA=yes]) AC_ARG_ENABLE(xf86vidmode, AS_HELP_STRING([--disable-xf86vidmode], [Build XF86VidMode extension (default: auto)]), [XF86VIDMODE=$enableval], [XF86VIDMODE=auto]) AC_ARG_ENABLE(xace, AS_HELP_STRING([--disable-xace], [Build X-ACE extension (default: enabled)]), [XACE=$enableval], [XACE=yes]) @@ -635,6 +633,8 @@ AC_ARG_ENABLE(windowswm, AS_HELP_STRING([--enable-windowswm], [Build XWin w AC_ARG_ENABLE(libdrm, AS_HELP_STRING([--enable-libdrm], [Build Xorg with libdrm support (default: enabled)]), [DRM=$enableval],[DRM=yes]) AC_ARG_ENABLE(clientids, AS_HELP_STRING([--disable-clientids], [Build Xorg with client ID tracking (default: enabled)]), [CLIENTIDS=$enableval], [CLIENTIDS=yes]) AC_ARG_ENABLE(pciaccess, AS_HELP_STRING([--enable-pciaccess], [Build Xorg with pciaccess library (default: enabled)]), [PCI=$enableval], [PCI=yes]) +AC_ARG_ENABLE(linux_acpi, AC_HELP_STRING([--disable-linux-acpi], [Disable building ACPI support on Linux (if available).]), [enable_linux_acpi=$enableval], [enable_linux_acpi=yes]) +AC_ARG_ENABLE(linux_apm, AC_HELP_STRING([--disable-linux-apm], [Disable building APM support on Linux (if available).]), [enable_linux_apm=$enableval], [enable_linux_apm=yes]) dnl DDXes. AC_ARG_ENABLE(xorg, AS_HELP_STRING([--enable-xorg], [Build Xorg server (default: auto)]), [XORG=$enableval], [XORG=auto]) @@ -715,6 +715,7 @@ case $host_os in CONFIG_UDEV_KMS=no DGA=no DRI2=no + DRI3=no INT10MODULE=no PCI=no VGAHW=no @@ -732,6 +733,7 @@ case $host_os in VBE=no DRM=no DRI2=no + DRI3=no if test x$XQUARTZ = xauto; then AC_CACHE_CHECK([whether to build Xquartz],xorg_cv_Carbon_framework,[ @@ -781,6 +783,7 @@ SCRNSAVERPROTO="scrnsaverproto >= 1.1" RESOURCEPROTO="resourceproto >= 1.2.0" DRIPROTO="xf86driproto >= 2.1.0" DRI2PROTO="dri2proto >= 2.8" +DRI3PROTO="dri3proto >= 1.0" XINERAMAPROTO="xineramaproto" BIGFONTPROTO="xf86bigfontproto >= 1.2.0" DGAPROTO="xf86dgaproto >= 2.0.99.1" @@ -803,6 +806,7 @@ DAMAGEPROTO="damageproto >= 1.1" XCMISCPROTO="xcmiscproto >= 1.2.0" BIGREQSPROTO="bigreqsproto >= 1.1.0" XTRANS="xtrans >= 1.2.2" +PRESENTPROTO="presentproto >= 1.0" dnl List of libraries that require a specific version LIBAPPLEWM="applewm >= 1.4" @@ -1113,7 +1117,22 @@ case "$DRI2,$HAVE_DRI2PROTO" in esac AM_CONDITIONAL(DRI2, test "x$DRI2" = xyes) -if test "x$DRI" = xyes || test "x$DRI2" = xyes || test "x$CONFIG_UDEV_KMS" = xyes; then +PKG_CHECK_MODULES([DRI3PROTO], $DRI3PROTO, + [HAVE_DRI3PROTO=yes], [HAVE_DRI3PROTO=no]) +case "$DRI3,$HAVE_DRI3PROTO" in + yes,no) + AC_MSG_ERROR([DRI3 requested, but dri3proto not found.]) + ;; + yes,yes | auto,yes) + AC_DEFINE(DRI3, 1, [Build DRI3 extension]) + DRI3=yes + DRI3_LIB='$(top_builddir)/dri3/libdri3.la' + SDK_REQUIRED_MODULES="$SDK_REQUIRED_MODULES $DRI3PROTO" + ;; +esac +AM_CONDITIONAL(DRI3, test "x$DRI3" = xyes) + +if test "x$DRI" = xyes || test "x$DRI2" = xyes || test "x$DRI3" = xyes || test "x$CONFIG_UDEV_KMS" = xyes; then if test "x$DRM" = xyes; then AC_DEFINE(WITH_LIBDRM, 1, [Building with libdrm support]) PKG_CHECK_MODULES([LIBDRM], $LIBDRM) @@ -1141,6 +1160,14 @@ if test "x$DRI2" = xyes; then fi AM_CONDITIONAL(DRI2_AIGLX, test "x$DRI2_AIGLX" = xyes) +AM_CONDITIONAL(PRESENT, [test "x$PRESENT" = xyes]) +if test "x$PRESENT" = xyes; then + AC_DEFINE(PRESENT, 1, [Support Present extension]) + REQUIRED_MODULES="$REQUIRED_MODULES $PRESENTPROTO" + SDK_REQUIRED_MODULES="$SDK_REQUIRED_MODULES $PRESENTPROTO" + PRESENT_INC='-I$(top_srcdir)/present' + PRESENT_LIB='$(top_builddir)/present/libpresent.la' +fi AM_CONDITIONAL(XINERAMA, [test "x$XINERAMA" = xyes]) if test "x$XINERAMA" = xyes; then @@ -1306,6 +1333,7 @@ if test "x$XDMAUTH" = xyes; then XDMCP_MODULES="xdmcp" fi fi +REQUIRED_LIBS="$REQUIRED_LIBS xshmfence" AC_DEFINE_DIR(COMPILEDDEFAULTFONTPATH, FONTPATH, [Default font path]) AC_DEFINE_DIR(SERVER_MISC_CONFIG_PATH, SERVERCONFIG, [Server miscellaneous config path]) @@ -1564,7 +1592,7 @@ AC_EGREP_CPP([I_AM_SVR4],[ AC_DEFINE([SVR4],1,[Define to 1 on systems derived from System V Release 4]) AC_MSG_RESULT([yes])], AC_MSG_RESULT([no])) -XSERVER_CFLAGS="$XSERVER_CFLAGS $CORE_INCS $XEXT_INC $COMPOSITE_INC $DAMAGE_INC $FIXES_INC $XI_INC $MI_INC $MIEXT_SYNC_INC $MIEXT_SHADOW_INC $MIEXT_LAYER_INC $MIEXT_DAMAGE_INC $RENDER_INC $RANDR_INC $FB_INC $DBE_INC" +XSERVER_CFLAGS="$XSERVER_CFLAGS $CORE_INCS $XEXT_INC $COMPOSITE_INC $DAMAGE_INC $FIXES_INC $XI_INC $MI_INC $MIEXT_SYNC_INC $MIEXT_SHADOW_INC $MIEXT_LAYER_INC $MIEXT_DAMAGE_INC $RENDER_INC $RANDR_INC $FB_INC $DBE_INC $PRESENT_INC" dnl --------------------------------------------------------------------------- dnl DDX section. @@ -1577,7 +1605,7 @@ AC_MSG_RESULT([$XVFB]) AM_CONDITIONAL(XVFB, [test "x$XVFB" = xyes]) if test "x$XVFB" = xyes; then - XVFB_LIBS="$FB_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB" + XVFB_LIBS="$FB_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $DRI3_LIB $PRESENT_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB" XVFB_SYS_LIBS="$XVFBMODULES_LIBS $GLX_SYS_LIBS" AC_SUBST([XVFB_LIBS]) AC_SUBST([XVFB_SYS_LIBS]) @@ -1598,7 +1626,7 @@ if test "x$XNEST" = xyes; then if test "x$have_xnest" = xno; then AC_MSG_ERROR([Xnest build explicitly requested, but required modules not found.]) fi - XNEST_LIBS="$FB_LIB $FIXES_LIB $MI_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $MAIN_LIB $DIX_LIB $OS_LIB" + XNEST_LIBS="$FB_LIB $FIXES_LIB $MI_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $DRI3_LIB $PRESENT_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $MAIN_LIB $DIX_LIB $OS_LIB" XNEST_SYS_LIBS="$XNESTMODULES_LIBS $GLX_SYS_LIBS" AC_SUBST([XNEST_LIBS]) AC_SUBST([XNEST_SYS_LIBS]) @@ -1623,7 +1651,7 @@ if test "x$XORG" = xyes; then XORG_OSINCS='-I$(top_srcdir)/hw/xfree86/os-support -I$(top_srcdir)/hw/xfree86/os-support/bus -I$(top_srcdir)/os' XORG_INCS="$XORG_DDXINCS $XORG_OSINCS" XORG_CFLAGS="$XORGSERVER_CFLAGS -DHAVE_XORG_CONFIG_H" - XORG_LIBS="$COMPOSITE_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $XI_LIB $XKB_LIB" + XORG_LIBS="$COMPOSITE_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $DRI3_LIB $PRESENT_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $XI_LIB $XKB_LIB" dnl ================================================================== dnl symbol visibility @@ -1705,9 +1733,6 @@ if test "x$XORG" = xyes; then case $host_os in linux*) - if test "x$LNXAPM" = xyes; then - XORG_CFLAGS="$XORG_CFLAGS -DXF86PM" - fi XORG_OS_SUBDIR="linux" linux_acpi="no" case $host_cpu in @@ -1715,11 +1740,16 @@ if test "x$XORG" = xyes; then linux_alpha=yes ;; i*86|amd64*|x86_64*|ia64*) - linux_acpi="yes" + linux_acpi=$enable_linux_acpi ;; *) ;; esac + dnl APM header + AC_CHECK_HEADERS([linux/apm_bios.h], [linux_apm=$enable_linux_apm]) + if test "x$linux_apm" = xyes -o "x$linux_acpi" = xyes; then + AC_DEFINE(XF86PM, 1, [Support APM/ACPI power management in the server]) + fi ;; freebsd* | kfreebsd*-gnu | dragonfly*) XORG_OS_SUBDIR="bsd" @@ -1882,6 +1912,7 @@ AM_CONDITIONAL([XORG_BUS_BSDPCI], [test "x$xorg_bus_bsdpci" = xyes]) AM_CONDITIONAL([XORG_BUS_SPARC], [test "x$xorg_bus_sparc" = xyes]) AM_CONDITIONAL([LINUX_ALPHA], [test "x$linux_alpha" = xyes]) AM_CONDITIONAL([LNXACPI], [test "x$linux_acpi" = xyes]) +AM_CONDITIONAL([LNXAPM], [test "x$linux_apm" = xyes]) AM_CONDITIONAL([SOLARIS_ASM_INLINE], [test "x$solaris_asm_inline" = xyes]) AM_CONDITIONAL([SOLARIS_VT], [test "x$solaris_vt" = xyes]) AM_CONDITIONAL([DGA], [test "x$DGA" = xyes]) @@ -2036,7 +2067,7 @@ if test "x$DMX" = xyes; then fi DMX_INCLUDES="$XEXT_INC $RENDER_INC $RECORD_INC" XDMX_CFLAGS="$DMXMODULES_CFLAGS" - XDMX_LIBS="$FB_LIB $MI_LIB $XEXT_LIB $RENDER_LIB $RECORD_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $MIEXT_SYNC_LIB $MIEXT_SHADOW_LIB $MIEXT_DAMAGE_LIB $COMPOSITE_LIB $DAMAGE_LIB $MAIN_LIB $DIX_LIB $CONFIG_LIB $OS_LIB $FIXES_LIB" + XDMX_LIBS="$FB_LIB $MI_LIB $XEXT_LIB $RENDER_LIB $RECORD_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $DRI3_LIB $PRESENT_LIB $MIEXT_SYNC_LIB $MIEXT_SHADOW_LIB $MIEXT_DAMAGE_LIB $COMPOSITE_LIB $DAMAGE_LIB $MAIN_LIB $DIX_LIB $CONFIG_LIB $OS_LIB $FIXES_LIB" XDMX_SYS_LIBS="$DMXMODULES_LIBS" AC_SUBST([XDMX_CFLAGS]) AC_SUBST([XDMX_LIBS]) @@ -2145,7 +2176,7 @@ if test "$KDRIVE" = yes; then KDRIVE_CFLAGS="$XSERVER_CFLAGS -DHAVE_KDRIVE_CONFIG_H $TSLIB_CFLAGS" - KDRIVE_PURE_LIBS="$FB_LIB $MI_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $OS_LIB" + KDRIVE_PURE_LIBS="$FB_LIB $MI_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $DRI3_LIB $PRESENT_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $OS_LIB" KDRIVE_LIB='$(top_builddir)/hw/kdrive/src/libkdrive.la' case $host_os in *linux*) @@ -2267,6 +2298,8 @@ Xext/Makefile Xi/Makefile xfixes/Makefile exa/Makefile +dri3/Makefile +present/Makefile hw/Makefile hw/xfree86/Makefile hw/xfree86/common/Makefile diff --git a/xorg-server/dix/region.c b/xorg-server/dix/region.c index 737d2a861..15f3d01a5 100644 --- a/xorg-server/dix/region.c +++ b/xorg-server/dix/region.c @@ -255,6 +255,21 @@ RegionDestroy(RegionPtr pReg) free(pReg); } +RegionPtr +RegionDuplicate(RegionPtr pOld) +{ + RegionPtr pNew; + + pNew = RegionCreate(&pOld->extents, 0); + if (!pNew) + return NULL; + if (!RegionCopy(pNew, pOld)) { + RegionDestroy(pNew); + return NULL; + } + return pNew; +} + void RegionPrint(RegionPtr rgn) { diff --git a/xorg-server/dri3/Makefile.am b/xorg-server/dri3/Makefile.am new file mode 100644 index 000000000..e47a734e0 --- /dev/null +++ b/xorg-server/dri3/Makefile.am @@ -0,0 +1,13 @@ +noinst_LTLIBRARIES = libdri3.la +AM_CFLAGS = \ + -DHAVE_XORG_CONFIG_H \ + @DIX_CFLAGS@ @XORG_CFLAGS@ + +libdri3_la_SOURCES = \ + dri3.h \ + dri3_priv.h \ + dri3.c \ + dri3_request.c \ + dri3_screen.c + +sdk_HEADERS = dri3.h diff --git a/xorg-server/dri3/dri3.c b/xorg-server/dri3/dri3.c new file mode 100644 index 000000000..2bca7ae9b --- /dev/null +++ b/xorg-server/dri3/dri3.c @@ -0,0 +1,87 @@ +/* + * Copyright © 2013 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include "dri3_priv.h" + +int dri3_request; +DevPrivateKeyRec dri3_screen_private_key; +DevPrivateKeyRec dri3_window_private_key; + +static Bool +dri3_close_screen(ScreenPtr screen) +{ + dri3_screen_priv_ptr screen_priv = dri3_screen_priv(screen); + + unwrap(screen_priv, screen, CloseScreen); + + free(screen_priv); + return (*screen->CloseScreen) (screen); +} + +Bool +dri3_screen_init(ScreenPtr screen, dri3_screen_info_ptr info) +{ + if (!dixRegisterPrivateKey(&dri3_screen_private_key, PRIVATE_SCREEN, 0)) + return FALSE; + + if (!dri3_screen_priv(screen)) { + dri3_screen_priv_ptr screen_priv = calloc(1, sizeof (dri3_screen_priv_rec)); + if (!screen_priv) + return FALSE; + + wrap(screen_priv, screen, CloseScreen, dri3_close_screen); + + screen_priv->info = info; + + dixSetPrivate(&screen->devPrivates, &dri3_screen_private_key, screen_priv); + } + + return TRUE; +} + +void +dri3_extension_init(void) +{ + ExtensionEntry *extension; + int i; + + extension = AddExtension(DRI3_NAME, DRI3NumberEvents, DRI3NumberErrors, + proc_dri3_dispatch, sproc_dri3_dispatch, + NULL, StandardMinorOpcode); + if (!extension) + goto bail; + + dri3_request = extension->base; + + for (i = 0; i < screenInfo.numScreens; i++) { + if (!dri3_screen_init(screenInfo.screens[i], NULL)) + goto bail; + } + return; + +bail: + FatalError("Cannot initialize DRI3 extension"); +} diff --git a/xorg-server/dri3/dri3.h b/xorg-server/dri3/dri3.h new file mode 100644 index 000000000..7774c8757 --- /dev/null +++ b/xorg-server/dri3/dri3.h @@ -0,0 +1,59 @@ +/* + * Copyright © 2013 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifndef _DRI3_H_ +#define _DRI3_H_ + +#include <X11/extensions/dri3proto.h> +#include <randrstr.h> + +#define DRI3_SCREEN_INFO_VERSION 0 + +typedef int (*dri3_open_proc)(ScreenPtr screen, + RRProviderPtr provider, + int *fd); + +typedef PixmapPtr (*dri3_pixmap_from_fd_proc) (ScreenPtr screen, + int fd, + CARD16 width, + CARD16 height, + CARD16 stride, + CARD8 depth, + CARD8 bpp); + +typedef int (*dri3_fd_from_pixmap_proc) (ScreenPtr screen, + PixmapPtr pixmap, + CARD16 *stride, + CARD32 *size); + +typedef struct dri3_screen_info { + uint32_t version; + + dri3_open_proc open; + dri3_pixmap_from_fd_proc pixmap_from_fd; + dri3_fd_from_pixmap_proc fd_from_pixmap; +} dri3_screen_info_rec, *dri3_screen_info_ptr; + +extern _X_EXPORT Bool +dri3_screen_init(ScreenPtr screen, dri3_screen_info_ptr info); + +#endif /* _DRI3_H_ */ diff --git a/xorg-server/dri3/dri3_event.c b/xorg-server/dri3/dri3_event.c new file mode 100644 index 000000000..02f0f6579 --- /dev/null +++ b/xorg-server/dri3/dri3_event.c @@ -0,0 +1,163 @@ +/* + * Copyright © 2013 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include "dri3_priv.h" + +RESTYPE dri3_event_type; + +static int +dri3_free_event(pointer data, XID id) +{ + dri3_event_ptr dri3_event = (dri3_event_ptr) data; + dri3_window_priv_ptr window_priv = dri3_window_priv(dri3_event->window); + dri3_event_ptr *previous, current; + + for (previous = &window_priv->events; (current = *previous); previous = ¤t->next) { + if (current == dri3_event) { + *previous = dri3_event->next; + break; + } + } + free((pointer) dri3_event); + return 1; + +} + +void +dri3_free_events(WindowPtr window) +{ + dri3_window_priv_ptr window_priv = dri3_window_priv(window); + dri3_event_ptr event; + + if (!window_priv) + return; + + while ((event = window_priv->events)) + FreeResource(event->id, RT_NONE); +} + +static void +dri3_event_swap(xGenericEvent *from, xGenericEvent *to) +{ + *to = *from; + swaps(&to->sequenceNumber); + swapl(&to->length); + swaps(&to->evtype); + switch (from->evtype) { + case DRI3_ConfigureNotify: { + xDRI3ConfigureNotify *c = (xDRI3ConfigureNotify *) to; + + swapl(&c->eid); + swapl(&c->window); + swaps(&c->x); + swaps(&c->y); + swaps(&c->width); + swaps(&c->height); + swaps(&c->off_x); + swaps(&c->off_y); + swaps(&c->pixmap_width); + swaps(&c->pixmap_height); + swapl(&c->pixmap_flags); + break; + } + } +} + +void +dri3_send_config_notify(WindowPtr window, int x, int y, int w, int h, int bw, WindowPtr sibling) +{ + dri3_window_priv_ptr window_priv = dri3_window_priv(window); + + if (window_priv) { + xDRI3ConfigureNotify cn = { + .type = GenericEvent, + .extension = dri3_request, + .length = (sizeof(xDRI3ConfigureNotify) - 32) >> 2, + .evtype = DRI3_ConfigureNotify, + .eid = 0, + .window = window->drawable.id, + .x = x, + .y = y, + .width = w, + .height = h, + .off_x = 0, + .off_y = 0, + .pixmap_width = w, + .pixmap_height = h, + .pixmap_flags = 0 + }; + dri3_event_ptr event; + dri3_screen_priv_ptr screen_priv = dri3_screen_priv(window->drawable.pScreen); + + if (screen_priv->info && screen_priv->info->driver_config) + screen_priv->info->driver_config(window, &cn); + + for (event = window_priv->events; event; event = event->next) { + if (event->mask & (1 << DRI3ConfigureNotify)) { + cn.eid = event->id; + WriteEventsToClient(event->client, 1, (xEvent *) &cn); + } + } + } +} + +int +dri3_select_input(ClientPtr client, XID eid, WindowPtr window, CARD32 mask) +{ + dri3_window_priv_ptr window_priv = dri3_window_priv(window); + dri3_event_ptr event; + + if (!window_priv) + return BadAlloc; + + event = calloc (1, sizeof (dri3_event_rec)); + if (!event) + return BadAlloc; + + event->client = client; + event->window = window; + event->id = eid; + event->mask = mask; + + event->next = window_priv->events; + window_priv->events = event; + + if (!AddResource(event->id, dri3_event_type, (pointer) event)) + return BadAlloc; + + return Success; +} + +Bool +dri3_event_init(void) +{ + dri3_event_type = CreateNewResourceType(dri3_free_event, "DRI3Event"); + if (!dri3_event_type) + return FALSE; + + GERegisterExtension(dri3_request, dri3_event_swap); + return TRUE; +} diff --git a/xorg-server/dri3/dri3_priv.h b/xorg-server/dri3/dri3_priv.h new file mode 100644 index 000000000..e2fed839b --- /dev/null +++ b/xorg-server/dri3/dri3_priv.h @@ -0,0 +1,80 @@ +/* + * Copyright © 2013 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifndef _DRI3PRIV_H_ +#define _DRI3PRIV_H_ + +#include <X11/X.h> +#include "scrnintstr.h" +#include "misc.h" +#include "list.h" +#include "windowstr.h" +#include "dixstruct.h" +#include <randrstr.h> +#include "dri3.h" + +extern int dri3_request; + +extern DevPrivateKeyRec dri3_screen_private_key; + +typedef struct dri3_screen_priv { + CloseScreenProcPtr CloseScreen; + ConfigNotifyProcPtr ConfigNotify; + DestroyWindowProcPtr DestroyWindow; + + dri3_screen_info_ptr info; +} dri3_screen_priv_rec, *dri3_screen_priv_ptr; + +#define wrap(priv,real,mem,func) {\ + priv->mem = real->mem; \ + real->mem = func; \ +} + +#define unwrap(priv,real,mem) {\ + real->mem = priv->mem; \ +} + +static inline dri3_screen_priv_ptr +dri3_screen_priv(ScreenPtr screen) +{ + return (dri3_screen_priv_ptr)dixLookupPrivate(&(screen)->devPrivates, &dri3_screen_private_key); +} + +int +proc_dri3_dispatch(ClientPtr client); + +int +sproc_dri3_dispatch(ClientPtr client); + +/* DDX interface */ + +int +dri3_open(ClientPtr client, ScreenPtr screen, RRProviderPtr provider, int *fd); + +int +dri3_pixmap_from_fd(PixmapPtr *ppixmap, ScreenPtr screen, int fd, + CARD16 width, CARD16 height, CARD16 stride, CARD8 depth, CARD8 bpp); + +int +dri3_fd_from_pixmap(int *pfd, PixmapPtr pixmap, CARD16 *stride, CARD32 *size); + +#endif /* _DRI3PRIV_H_ */ diff --git a/xorg-server/dri3/dri3_request.c b/xorg-server/dri3/dri3_request.c new file mode 100644 index 000000000..3ebb9d509 --- /dev/null +++ b/xorg-server/dri3/dri3_request.c @@ -0,0 +1,394 @@ +/* + * Copyright © 2013 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include "dri3_priv.h" +#include <syncsrv.h> +#include <unistd.h> +#include <xace.h> +#include "../Xext/syncsdk.h" + +static int +proc_dri3_query_version(ClientPtr client) +{ + REQUEST(xDRI3QueryVersionReq); + xDRI3QueryVersionReply rep = { + .type = X_Reply, + .sequenceNumber = client->sequence, + .length = 0, + .majorVersion = DRI3_MAJOR, + .minorVersion = DRI3_MINOR + }; + + REQUEST_SIZE_MATCH(xDRI3QueryVersionReq); + (void) stuff; + if (client->swapped) { + swaps(&rep.sequenceNumber); + swapl(&rep.length); + swapl(&rep.majorVersion); + swapl(&rep.minorVersion); + } + WriteToClient(client, sizeof(rep), &rep); + return Success; +} + +static int +proc_dri3_open(ClientPtr client) +{ + REQUEST(xDRI3OpenReq); + xDRI3OpenReply rep = { + .type = X_Reply, + .nfd = 1, + .sequenceNumber = client->sequence, + .length = 0, + }; + RRProviderPtr provider; + DrawablePtr drawable; + ScreenPtr screen; + int fd; + int status; + + REQUEST_SIZE_MATCH(xDRI3OpenReq); + + status = dixLookupDrawable(&drawable, stuff->drawable, client, 0, DixReadAccess); + if (status != Success) + return status; + + if (stuff->provider == None) + provider = NULL; + else if (!RRProviderType) { + return BadMatch; + } else { + VERIFY_RR_PROVIDER(stuff->provider, provider, DixReadAccess); + if (drawable->pScreen != provider->pScreen) + return BadMatch; + } + screen = drawable->pScreen; + + status = dri3_open(client, screen, provider, &fd); + if (status != Success) + return status; + + if (client->swapped) { + swaps(&rep.sequenceNumber); + swapl(&rep.length); + } + + if (WriteFdToClient(client, fd, TRUE) < 0) { + close(fd); + return BadAlloc; + } + + WriteToClient(client, sizeof (rep), &rep); + + return Success; +} + +static int +proc_dri3_pixmap_from_buffer(ClientPtr client) +{ + REQUEST(xDRI3PixmapFromBufferReq); + int fd; + DrawablePtr drawable; + PixmapPtr pixmap; + int rc; + + SetReqFds(client, 1); + REQUEST_SIZE_MATCH(xDRI3PixmapFromBufferReq); + LEGAL_NEW_RESOURCE(stuff->pixmap, client); + rc = dixLookupDrawable(&drawable, stuff->drawable, client, M_ANY, DixGetAttrAccess); + if (rc != Success) { + client->errorValue = stuff->drawable; + return rc; + } + + if (!stuff->width || !stuff->height) { + client->errorValue = 0; + return BadValue; + } + + if (stuff->width > 32767 || stuff->height > 32767) + return BadAlloc; + + if (stuff->depth != 1) { + DepthPtr depth = drawable->pScreen->allowedDepths; + int i; + for (i = 0; i < drawable->pScreen->numDepths; i++, depth++) + if (depth->depth == stuff->depth) + break; + if (i == drawable->pScreen->numDepths) { + client->errorValue = stuff->depth; + return BadValue; + } + } + + fd = ReadFdFromClient(client); + if (fd < 0) + return BadValue; + + rc = dri3_pixmap_from_fd(&pixmap, + drawable->pScreen, fd, + stuff->width, stuff->height, + stuff->stride, stuff->depth, + stuff->bpp); + close (fd); + if (rc != Success) + return rc; + + pixmap->drawable.id = stuff->pixmap; + + /* security creation/labeling check */ + rc = XaceHook(XACE_RESOURCE_ACCESS, client, stuff->pixmap, RT_PIXMAP, + pixmap, RT_NONE, NULL, DixCreateAccess); + + if (rc != Success) { + (*drawable->pScreen->DestroyPixmap) (pixmap); + return rc; + } + if (AddResource(stuff->pixmap, RT_PIXMAP, (pointer) pixmap)) + return Success; + + return Success; +} + +static int +proc_dri3_buffer_from_pixmap(ClientPtr client) +{ + REQUEST(xDRI3BufferFromPixmapReq); + xDRI3BufferFromPixmapReply rep = { + .type = X_Reply, + .nfd = 1, + .sequenceNumber = client->sequence, + .length = 0, + }; + int rc; + int fd; + PixmapPtr pixmap; + + REQUEST_SIZE_MATCH(xDRI3BufferFromPixmapReq); + rc = dixLookupResourceByType((pointer *) &pixmap, stuff->pixmap, RT_PIXMAP, + client, DixWriteAccess); + if (rc != Success) { + client->errorValue = stuff->pixmap; + return rc; + } + + rep.width = pixmap->drawable.width; + rep.height = pixmap->drawable.height; + rep.depth = pixmap->drawable.depth; + rep.bpp = pixmap->drawable.bitsPerPixel; + + rc = dri3_fd_from_pixmap(&fd, pixmap, &rep.stride, &rep.size); + if (rc != Success) + return rc; + + if (client->swapped) { + swaps(&rep.sequenceNumber); + swapl(&rep.length); + swapl(&rep.size); + swaps(&rep.width); + swaps(&rep.height); + swaps(&rep.stride); + } + if (WriteFdToClient(client, fd, TRUE) < 0) { + close(fd); + return BadAlloc; + } + + WriteToClient(client, sizeof(rep), &rep); + + return client->noClientException; +} + +static int +proc_dri3_fence_from_fd(ClientPtr client) +{ + REQUEST(xDRI3FenceFromFDReq); + DrawablePtr drawable; + int fd; + int status; + + SetReqFds(client, 1); + REQUEST_SIZE_MATCH(xDRI3FenceFromFDReq); + LEGAL_NEW_RESOURCE(stuff->fence, client); + + status = dixLookupDrawable(&drawable, stuff->drawable, client, M_ANY, DixGetAttrAccess); + if (status != Success) + return status; + + fd = ReadFdFromClient(client); + if (fd < 0) + return BadValue; + + status = SyncCreateFenceFromFD(client, drawable, stuff->fence, + fd, stuff->initially_triggered); + + return status; +} + +static int +proc_dri3_fd_from_fence(ClientPtr client) +{ + REQUEST(xDRI3FDFromFenceReq); + xDRI3FDFromFenceReply rep = { + .type = X_Reply, + .nfd = 1, + .sequenceNumber = client->sequence, + .length = 0, + }; + DrawablePtr drawable; + int fd; + int status; + SyncFence *fence; + + REQUEST_SIZE_MATCH(xDRI3FDFromFenceReq); + + status = dixLookupDrawable(&drawable, stuff->drawable, client, M_ANY, DixGetAttrAccess); + if (status != Success) + return status; + status = SyncVerifyFence(&fence, stuff->fence, client, DixWriteAccess); + if (status != Success) + return status; + + fd = SyncFDFromFence(client, drawable, fence); + if (fd < 0) + return BadMatch; + + if (client->swapped) { + swaps(&rep.sequenceNumber); + swapl(&rep.length); + } + if (WriteFdToClient(client, fd, FALSE) < 0) + return BadAlloc; + + WriteToClient(client, sizeof(rep), &rep); + + return client->noClientException; +} + +int (*proc_dri3_vector[DRI3NumberRequests]) (ClientPtr) = { + proc_dri3_query_version, /* 0 */ + proc_dri3_open, /* 1 */ + proc_dri3_pixmap_from_buffer, /* 2 */ + proc_dri3_buffer_from_pixmap, /* 3 */ + proc_dri3_fence_from_fd, /* 4 */ + proc_dri3_fd_from_fence, /* 5 */ +}; + +int +proc_dri3_dispatch(ClientPtr client) +{ + REQUEST(xReq); + if (stuff->data >= DRI3NumberRequests || !proc_dri3_vector[stuff->data]) + return BadRequest; + return (*proc_dri3_vector[stuff->data]) (client); +} + +static int +sproc_dri3_query_version(ClientPtr client) +{ + REQUEST(xDRI3QueryVersionReq); + + swaps(&stuff->length); + swapl(&stuff->majorVersion); + swapl(&stuff->minorVersion); + return (*proc_dri3_vector[stuff->dri3ReqType]) (client); +} + +static int +sproc_dri3_open(ClientPtr client) +{ + REQUEST(xDRI3OpenReq); + + swaps(&stuff->length); + swapl(&stuff->drawable); + swapl(&stuff->provider); + return (*proc_dri3_vector[stuff->dri3ReqType]) (client); +} + +static int +sproc_dri3_pixmap_from_buffer(ClientPtr client) +{ + REQUEST(xDRI3PixmapFromBufferReq); + + swaps(&stuff->length); + swapl(&stuff->pixmap); + swapl(&stuff->drawable); + swapl(&stuff->size); + swaps(&stuff->width); + swaps(&stuff->height); + swaps(&stuff->stride); + return (*proc_dri3_vector[stuff->dri3ReqType]) (client); +} + +static int +sproc_dri3_buffer_from_pixmap(ClientPtr client) +{ + REQUEST(xDRI3BufferFromPixmapReq); + + swaps(&stuff->length); + swapl(&stuff->pixmap); + return (*proc_dri3_vector[stuff->dri3ReqType]) (client); +} + +static int +sproc_dri3_fence_from_fd(ClientPtr client) +{ + REQUEST(xDRI3FenceFromFDReq); + + swaps(&stuff->length); + swapl(&stuff->drawable); + swapl(&stuff->fence); + return (*proc_dri3_vector[stuff->dri3ReqType]) (client); +} + +static int +sproc_dri3_fd_from_fence(ClientPtr client) +{ + REQUEST(xDRI3FDFromFenceReq); + + swaps(&stuff->length); + swapl(&stuff->drawable); + swapl(&stuff->fence); + return (*proc_dri3_vector[stuff->dri3ReqType]) (client); +} + +int (*sproc_dri3_vector[DRI3NumberRequests]) (ClientPtr) = { + sproc_dri3_query_version, /* 0 */ + sproc_dri3_open, /* 1 */ + sproc_dri3_pixmap_from_buffer, /* 2 */ + sproc_dri3_buffer_from_pixmap, /* 3 */ + sproc_dri3_fence_from_fd, /* 4 */ + sproc_dri3_fd_from_fence, /* 5 */ +}; + +int +sproc_dri3_dispatch(ClientPtr client) +{ + REQUEST(xReq); + if (stuff->data >= DRI3NumberRequests || !sproc_dri3_vector[stuff->data]) + return BadRequest; + return (*sproc_dri3_vector[stuff->data]) (client); +} diff --git a/xorg-server/dri3/dri3_screen.c b/xorg-server/dri3/dri3_screen.c new file mode 100644 index 000000000..cf2735b8d --- /dev/null +++ b/xorg-server/dri3/dri3_screen.c @@ -0,0 +1,80 @@ +/* + * Copyright © 2013 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include "dri3_priv.h" +#include <syncsdk.h> +#include <misync.h> +#include <misyncshm.h> +#include <randrstr.h> + +int +dri3_open(ClientPtr client, ScreenPtr screen, RRProviderPtr provider, int *fd) +{ + dri3_screen_priv_ptr ds = dri3_screen_priv(screen); + dri3_screen_info_ptr info = ds->info; + int rc; + + if (!info || !info->open) + return BadMatch; + + rc = (*info->open) (screen, provider, fd); + if (rc != Success) + return rc; + + return Success; +} + +int +dri3_pixmap_from_fd(PixmapPtr *ppixmap, ScreenPtr screen, int fd, + CARD16 width, CARD16 height, CARD16 stride, CARD8 depth, CARD8 bpp) +{ + dri3_screen_priv_ptr ds = dri3_screen_priv(screen); + dri3_screen_info_ptr info = ds->info; + PixmapPtr pixmap; + + pixmap = (*info->pixmap_from_fd) (screen, fd, width, height, stride, depth, bpp); + if (!pixmap) + return BadAlloc; + + *ppixmap = pixmap; + return Success; +} + +int +dri3_fd_from_pixmap(int *pfd, PixmapPtr pixmap, CARD16 *stride, CARD32 *size) +{ + ScreenPtr screen = pixmap->drawable.pScreen; + dri3_screen_priv_ptr ds = dri3_screen_priv(screen); + dri3_screen_info_ptr info = ds->info; + int fd; + + fd = (*info->fd_from_pixmap)(screen, pixmap, stride, size); + if (fd < 0) + return BadAlloc; + *pfd = fd; + return Success; +} + diff --git a/xorg-server/dri3/dri3int.h b/xorg-server/dri3/dri3int.h new file mode 100644 index 000000000..7f53eba45 --- /dev/null +++ b/xorg-server/dri3/dri3int.h @@ -0,0 +1,26 @@ +/* + * Copyright © 2011 Daniel Stone + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Author: Daniel Stone <daniel@fooishbar.org> + */ + +extern Bool DRI2ModuleSetup(void); diff --git a/xorg-server/glx/glxcmds.c b/xorg-server/glx/glxcmds.c index 64ebf9ecd..efa4aecb2 100644 --- a/xorg-server/glx/glxcmds.c +++ b/xorg-server/glx/glxcmds.c @@ -1118,7 +1118,8 @@ DoGetFBConfigs(__GLXclientState * cl, unsigned screen) WRITE_PAIR(GLX_BIND_TO_MIPMAP_TEXTURE_EXT, modes->bindToMipmapTexture); WRITE_PAIR(GLX_BIND_TO_TEXTURE_TARGETS_EXT, modes->bindToTextureTargets); - WRITE_PAIR(GLX_Y_INVERTED_EXT, modes->yInverted); + /* can't report honestly until mesa is fixed */ + WRITE_PAIR(GLX_Y_INVERTED_EXT, GLX_DONT_CARE); if (modes->drawableType & GLX_PBUFFER_BIT) { WRITE_PAIR(GLX_MAX_PBUFFER_WIDTH, modes->maxPbufferWidth); WRITE_PAIR(GLX_MAX_PBUFFER_HEIGHT, modes->maxPbufferHeight); diff --git a/xorg-server/glx/glxdricommon.c b/xorg-server/glx/glxdricommon.c index 48f0bce21..1022c0075 100644 --- a/xorg-server/glx/glxdricommon.c +++ b/xorg-server/glx/glxdricommon.c @@ -178,6 +178,7 @@ createModeFromConfig(const __DRIcoreExtension * core, config->config.visualType = visualType; config->config.renderType = renderType; config->config.drawableType = drawableType; + config->config.yInverted = GL_TRUE; return &config->config; } diff --git a/xorg-server/hw/dmx/dmxextension.c b/xorg-server/hw/dmx/dmxextension.c index d7296ae2d..c6c6a8e6d 100644 --- a/xorg-server/hw/dmx/dmxextension.c +++ b/xorg-server/hw/dmx/dmxextension.c @@ -68,6 +68,9 @@ * _any_ header files. */ extern FontPtr defaultFont; +/* Hack to get Present to build (present requires RandR) */ +RESTYPE RRCrtcType; + /** This routine provides information to the DMX protocol extension * about a particular screen. */ Bool diff --git a/xorg-server/hw/dmx/dmxinit.c b/xorg-server/hw/dmx/dmxinit.c index 65416ed26..bd868a092 100644 --- a/xorg-server/hw/dmx/dmxinit.c +++ b/xorg-server/hw/dmx/dmxinit.c @@ -109,6 +109,8 @@ Bool dmxGLXSyncSwap = FALSE; Bool dmxGLXFinishSwap = FALSE; #endif +RESTYPE RRProviderType = 0; + Bool dmxIgnoreBadFontPaths = FALSE; Bool dmxAddRemoveScreens = FALSE; diff --git a/xorg-server/hw/kdrive/ephyr/hostx.c b/xorg-server/hw/kdrive/ephyr/hostx.c index 5fa33b9db..ee9ae455c 100644 --- a/xorg-server/hw/kdrive/ephyr/hostx.c +++ b/xorg-server/hw/kdrive/ephyr/hostx.c @@ -695,9 +695,6 @@ hostx_screen_init(KdScreenInfo *screen, malloc(scrpriv->ximg->stride * buffer_height); } - *bytes_per_line = scrpriv->ximg->stride; - *bits_per_pixel = scrpriv->ximg->bpp; - if (scrpriv->win_pre_existing == None && !EphyrWantResize) { /* Ask the WM to keep our size static */ xcb_size_hints_t size_hints = {0}; @@ -717,13 +714,21 @@ hostx_screen_init(KdScreenInfo *screen, scrpriv->win_height = height; if (host_depth_matches_server(scrpriv)) { + *bytes_per_line = scrpriv->ximg->stride; + *bits_per_pixel = scrpriv->ximg->bpp; + EPHYR_DBG("Host matches server"); return scrpriv->ximg->data; } else { - EPHYR_DBG("server bpp %i", scrpriv->server_depth >> 3); - scrpriv->fb_data = - malloc(width * buffer_height * (scrpriv->server_depth >> 3)); + int bytes_per_pixel = scrpriv->server_depth >> 3; + int stride = (width * bytes_per_pixel + 0x3) & ~0x3; + + *bytes_per_line = stride; + *bits_per_pixel = scrpriv->server_depth; + + EPHYR_DBG("server bpp %i", bytes_per_pixel); + scrpriv->fb_data = malloc (stride * buffer_height); return scrpriv->fb_data; } } @@ -762,15 +767,14 @@ hostx_paint_rect(KdScreenInfo *screen, if (!host_depth_matches_server(scrpriv)) { int x, y, idx, bytes_per_pixel = (scrpriv->server_depth >> 3); + int stride = (scrpriv->win_width * bytes_per_pixel + 0x3) & ~0x3; unsigned char r, g, b; unsigned long host_pixel; EPHYR_DBG("Unmatched host depth scrpriv=%p\n", scrpriv); for (y = sy; y < sy + height; y++) for (x = sx; x < sx + width; x++) { - idx = - (scrpriv->win_width * y * bytes_per_pixel) + - (x * bytes_per_pixel); + idx = y * stride + x * bytes_per_pixel; switch (scrpriv->server_depth) { case 16: diff --git a/xorg-server/hw/xfree86/Makefile.am b/xorg-server/hw/xfree86/Makefile.am index 59cfb5f6f..eea16a851 100644 --- a/xorg-server/hw/xfree86/Makefile.am +++ b/xorg-server/hw/xfree86/Makefile.am @@ -41,7 +41,7 @@ nodist_Xorg_SOURCES = sdksyms.c AM_CFLAGS = $(DIX_CFLAGS) @XORG_CFLAGS@ AM_CPPFLAGS = $(XORG_INCS) -I$(srcdir)/parser -I$(top_srcdir)/miext/cw \ -I$(srcdir)/ddc -I$(srcdir)/i2c -I$(srcdir)/modes -I$(srcdir)/ramdac \ - -I$(srcdir)/dri -I$(srcdir)/dri2 + -I$(srcdir)/dri -I$(srcdir)/dri2 -I$(top_srcdir)/dri3 LOCAL_LIBS = \ $(MAIN_LIB) \ @@ -59,6 +59,8 @@ LOCAL_LIBS = \ dixmods/libxorgxkb.la \ $(DRI_LIB) \ $(DRI2_LIB) \ + $(top_builddir)/dri3/libdri3.la \ + $(top_builddir)/miext/sync/libsync.la \ $(top_builddir)/mi/libmi.la \ $(top_builddir)/os/libos.la Xorg_LDADD = \ diff --git a/xorg-server/hw/xfree86/common/xf86Configure.c b/xorg-server/hw/xfree86/common/xf86Configure.c index 6c5e35919..91e8df93d 100644 --- a/xorg-server/hw/xfree86/common/xf86Configure.c +++ b/xorg-server/hw/xfree86/common/xf86Configure.c @@ -123,12 +123,14 @@ xf86AddBusDeviceToConfigure(const char *driver, BusType bus, void *busData, switch (bus) { #ifdef XSERVER_LIBPCIACCESS case BUS_PCI: + DevToConfig[i].pVideo = busData; xf86PciConfigureNewDev(busData, DevToConfig[i].pVideo, &DevToConfig[i].GDev, &chipset); break; #endif #if (defined(__sparc__) || defined(__sparc)) && !defined(__OpenBSD__) case BUS_SBUS: + DevToConfig[i].sVideo = busData; xf86SbusConfigureNewDev(busData, DevToConfig[i].sVideo, &DevToConfig[i].GDev); break; diff --git a/xorg-server/hw/xfree86/common/xf86DPMS.c b/xorg-server/hw/xfree86/common/xf86DPMS.c index 3f1e142c7..881cb2773 100644 --- a/xorg-server/hw/xfree86/common/xf86DPMS.c +++ b/xorg-server/hw/xfree86/common/xf86DPMS.c @@ -36,6 +36,7 @@ #include <X11/X.h> #include "os.h" #include "globals.h" +#include "windowstr.h" #include "xf86.h" #include "xf86Priv.h" #ifdef DPMSExtension @@ -159,7 +160,13 @@ DPMSSet(ClientPtr client, int level) return Success; if (level != DPMSModeOn) { - rc = dixSaveScreens(client, SCREEN_SAVER_FORCER, ScreenSaverActive); + if (xf86IsUnblank(screenIsSaved)) { + rc = dixSaveScreens(client, SCREEN_SAVER_FORCER, ScreenSaverActive); + if (rc != Success) + return rc; + } + } else if (!xf86IsUnblank(screenIsSaved)) { + rc = dixSaveScreens(client, SCREEN_SAVER_FORCER, ScreenSaverReset); if (rc != Success) return rc; } diff --git a/xorg-server/hw/xfree86/common/xf86Events.c b/xorg-server/hw/xfree86/common/xf86Events.c index 7a949fd74..d0b14314b 100644 --- a/xorg-server/hw/xfree86/common/xf86Events.c +++ b/xorg-server/hw/xfree86/common/xf86Events.c @@ -116,6 +116,7 @@ typedef struct x_IHRec { InputHandlerProc ihproc; pointer data; Bool enabled; + Bool is_input; struct x_IHRec *next; } IHRec, *IHPtr; @@ -446,8 +447,12 @@ xf86VTSwitch(void) * Keep the order: Disable Device > LeaveVT * EnterVT > EnableDevice */ - for (ih = InputHandlers; ih; ih = ih->next) - xf86DisableInputHandler(ih); + for (ih = InputHandlers; ih; ih = ih->next) { + if (ih->is_input) + xf86DisableInputHandler(ih); + else + xf86DisableGeneralHandler(ih); + } for (pInfo = xf86InputDevs; pInfo; pInfo = pInfo->next) { if (pInfo->dev) { if (!pInfo->dev->enabled) @@ -496,9 +501,12 @@ xf86VTSwitch(void) pInfo->flags &= ~XI86_DEVICE_DISABLED; pInfo = pInfo->next; } - for (ih = InputHandlers; ih; ih = ih->next) - xf86EnableInputHandler(ih); - + for (ih = InputHandlers; ih; ih = ih->next) { + if (ih->is_input) + xf86EnableInputHandler(ih); + else + xf86EnableGeneralHandler(ih); + } OsReleaseSIGIO(); } @@ -558,9 +566,12 @@ xf86VTSwitch(void) pInfo = pInfo->next; } - for (ih = InputHandlers; ih; ih = ih->next) - xf86EnableInputHandler(ih); - + for (ih = InputHandlers; ih; ih = ih->next) { + if (ih->is_input) + xf86EnableInputHandler(ih); + else + xf86EnableGeneralHandler(ih); + } #ifdef XSERVER_PLATFORM_BUS /* check for any new output devices */ xf86platformVTProbe(); @@ -600,8 +611,10 @@ xf86AddInputHandler(int fd, InputHandlerProc proc, pointer data) { IHPtr ih = addInputHandler(fd, proc, data); - if (ih) + if (ih) { AddEnabledDevice(fd); + ih->is_input = TRUE; + } return ih; } diff --git a/xorg-server/hw/xfree86/common/xf86RandR.c b/xorg-server/hw/xfree86/common/xf86RandR.c index 5606bee4b..2418731dc 100644 --- a/xorg-server/hw/xfree86/common/xf86RandR.c +++ b/xorg-server/hw/xfree86/common/xf86RandR.c @@ -214,13 +214,15 @@ xf86RandRSetMode(ScreenPtr pScreen, */ xf86ReconfigureLayout(); - /* - * Make sure the whole screen is visible - */ - xf86SetViewport(pScreen, pScreen->width, pScreen->height); - xf86SetViewport(pScreen, 0, 0); - if (pRoot && scrp->vtSema) - (*scrp->EnableDisableFBAccess) (scrp, TRUE); + if (scrp->vtSema) { + /* + * Make sure the whole screen is visible + */ + xf86SetViewport (pScreen, pScreen->width, pScreen->height); + xf86SetViewport (pScreen, 0, 0); + if (pRoot) + (*scrp->EnableDisableFBAccess) (scrp, TRUE); + } return ret; } diff --git a/xorg-server/hw/xfree86/modes/xf86Crtc.c b/xorg-server/hw/xfree86/modes/xf86Crtc.c index 35845e875..2a02c8507 100644 --- a/xorg-server/hw/xfree86/modes/xf86Crtc.c +++ b/xorg-server/hw/xfree86/modes/xf86Crtc.c @@ -3045,10 +3045,22 @@ handle_detailed_physical_size(struct detailed_monitor_section if (det_mon->type == DT && det_mon->section.d_timings.h_size != 0 && det_mon->section.d_timings.v_size != 0) { - - p->output->mm_width = det_mon->section.d_timings.h_size; - p->output->mm_height = det_mon->section.d_timings.v_size; - p->ret = TRUE; + /* some sanity checking for aspect ratio: + assume any h / v (or v / h) > 2.4 to be bogus. + This would even include cinemascope */ + if (((det_mon->section.d_timings.h_size * 5) < + (det_mon->section.d_timings.v_size * 12)) && + ((det_mon->section.d_timings.v_size * 5) < + (det_mon->section.d_timings.h_size * 12))) { + p->output->mm_width = det_mon->section.d_timings.h_size; + p->output->mm_height = det_mon->section.d_timings.v_size; + p->ret = TRUE; + } else + xf86DrvMsg(p->output->scrn->scrnIndex, X_WARNING, + "Output %s: Strange aspect ratio (%i/%i), " + "consider adding a quirk\n", p->output->name, + det_mon->section.d_timings.h_size, + det_mon->section.d_timings.v_size); } } diff --git a/xorg-server/hw/xfree86/sdksyms.sh b/xorg-server/hw/xfree86/sdksyms.sh index 48b48b5db..7c9734c07 100644 --- a/xorg-server/hw/xfree86/sdksyms.sh +++ b/xorg-server/hw/xfree86/sdksyms.sh @@ -99,6 +99,7 @@ cat > sdksyms.c << EOF # include "dri2.h" #endif +# include "dri3.h" /* hw/xfree86/vgahw/Makefile.am -- module */ /* diff --git a/xorg-server/hw/xquartz/bundle/Info.plist.cpp b/xorg-server/hw/xquartz/bundle/Info.plist.cpp index b0106c6da..b99e417aa 100644 --- a/xorg-server/hw/xquartz/bundle/Info.plist.cpp +++ b/xorg-server/hw/xquartz/bundle/Info.plist.cpp @@ -19,9 +19,9 @@ <key>CFBundlePackageType</key> <string>APPL</string> <key>CFBundleShortVersionString</key> - <string>2.7.4</string> + <string>2.7.6</string> <key>CFBundleVersion</key> - <string>2.7.4</string> + <string>2.7.6</string> <key>CFBundleSignature</key> <string>x11a</string> <key>CSResourcesFileMapped</key> diff --git a/xorg-server/include/dix-config.h.in b/xorg-server/include/dix-config.h.in index a643dfcc8..397ee967a 100644 --- a/xorg-server/include/dix-config.h.in +++ b/xorg-server/include/dix-config.h.in @@ -39,6 +39,9 @@ /* Build DPMS extension */ #undef DPMSExtension +/* Build DRI3 extension */ +#undef DRI3 + /* Build GLX extension */ #undef GLXEXT @@ -252,6 +255,9 @@ /* Internal define for Xinerama */ #undef PANORAMIX +/* Support Present extension */ +#undef PRESENT + /* Overall prefix */ #undef PROJECTROOT diff --git a/xorg-server/include/dixstruct.h b/xorg-server/include/dixstruct.h index 7711cde99..456e63360 100644 --- a/xorg-server/include/dixstruct.h +++ b/xorg-server/include/dixstruct.h @@ -110,8 +110,16 @@ typedef struct _Client { DeviceIntPtr clientPtr; ClientIdPtr clientIds; + int req_fds; } ClientRec; +static inline void +SetReqFds(ClientPtr client, int req_fds) { + if (client->req_fds != 0 && req_fds != client->req_fds) + LogMessage(X_ERROR, "Mismatching number of request fds %d != %d\n", req_fds, client->req_fds); + client->req_fds = req_fds; +} + /* * Scheduling interface */ diff --git a/xorg-server/include/extinit.h b/xorg-server/include/extinit.h index 6d67bf2e5..fa5f29378 100644 --- a/xorg-server/include/extinit.h +++ b/xorg-server/include/extinit.h @@ -176,4 +176,14 @@ extern void XvExtensionInit(void); extern void XvMCExtensionInit(void); #endif +#if defined(DRI3) +#include <X11/extensions/dri3proto.h> +extern void dri3_extension_init(void); +#endif + +#if defined(PRESENT) +#include <X11/extensions/presentproto.h> +#include "presentext.h" +#endif + #endif diff --git a/xorg-server/include/misc.h b/xorg-server/include/misc.h index 0c67f11fe..17de71041 100644 --- a/xorg-server/include/misc.h +++ b/xorg-server/include/misc.h @@ -305,6 +305,35 @@ __builtin_constant_p(int x) } #endif +/* byte swap a 64-bit value */ +static inline void +swap_uint64(uint64_t *x) +{ + char n; + + n = ((char *) x)[0]; + ((char *) x)[0] = ((char *) x)[7]; + ((char *) x)[7] = n; + + n = ((char *) x)[1]; + ((char *) x)[1] = ((char *) x)[6]; + ((char *) x)[6] = n; + + n = ((char *) x)[2]; + ((char *) x)[2] = ((char *) x)[5]; + ((char *) x)[5] = n; + + n = ((char *) x)[3]; + ((char *) x)[3] = ((char *) x)[4]; + ((char *) x)[4] = n; +} + +#define swapll(x) do { \ + if (sizeof(*(x)) != 8) \ + wrong_size(); \ + swap_uint64((uint64_t *)(x)); \ + } while (0) + /* byte swap a 32-bit value */ static inline void swap_uint32(uint32_t * x) diff --git a/xorg-server/include/os.h b/xorg-server/include/os.h index c7108a5d3..11b219845 100644 --- a/xorg-server/include/os.h +++ b/xorg-server/include/os.h @@ -98,6 +98,10 @@ extern _X_EXPORT int WaitForSomething(int * /*pClientsReady */ extern _X_EXPORT int ReadRequestFromClient(ClientPtr /*client */ ); +extern _X_EXPORT int ReadFdFromClient(ClientPtr client); + +extern _X_EXPORT int WriteFdToClient(ClientPtr client, int fd, Bool do_close); + extern _X_EXPORT Bool InsertFakeRequest(ClientPtr /*client */ , char * /*data */ , int /*count */ ); @@ -165,6 +169,7 @@ extern void ListenOnOpenFD(int /* fd */ , int /* noxauth */ ); #endif extern _X_EXPORT CARD32 GetTimeInMillis(void); +extern _X_EXPORT CARD64 GetTimeInMicros(void); extern _X_EXPORT void AdjustWaitForDelay(pointer /*waitTime */ , unsigned long /*newdelay */ ); diff --git a/xorg-server/include/regionstr.h b/xorg-server/include/regionstr.h index 805257b3f..4a0725d62 100644 --- a/xorg-server/include/regionstr.h +++ b/xorg-server/include/regionstr.h @@ -213,6 +213,8 @@ extern _X_EXPORT RegionPtr RegionCreate(BoxPtr /*rect */ , extern _X_EXPORT void RegionDestroy(RegionPtr /*pReg */ ); +extern _X_EXPORT RegionPtr RegionDuplicate(RegionPtr /* pOld */); + static inline Bool RegionCopy(RegionPtr dst, RegionPtr src) { diff --git a/xorg-server/include/xorg-config.h.in b/xorg-server/include/xorg-config.h.in index 0df31aeb2..487d7addb 100644 --- a/xorg-server/include/xorg-config.h.in +++ b/xorg-server/include/xorg-config.h.in @@ -142,4 +142,7 @@ /* Define to 1 if you have the `seteuid' function. */ #undef HAVE_SETEUID +/* Support APM/ACPI power management in the server */ +#undef XF86PM + #endif /* _XORG_CONFIG_H_ */ diff --git a/xorg-server/include/xorg-server.h.in b/xorg-server/include/xorg-server.h.in index 81935be5c..1281b3e5e 100644 --- a/xorg-server/include/xorg-server.h.in +++ b/xorg-server/include/xorg-server.h.in @@ -28,6 +28,9 @@ /* Build DPMS extension */ #undef DPMSExtension +/* Build DRI3 extension */ +#undef DRI3 + /* Build GLX extension */ #undef GLXEXT @@ -67,6 +70,9 @@ /* Internal define for Xinerama */ #undef PANORAMIX +/* Support Present extension */ +#undef PRESENT + /* Support RANDR extension */ #undef RANDR diff --git a/xorg-server/mi/miinitext.c b/xorg-server/mi/miinitext.c index 145da38e9..636618282 100644 --- a/xorg-server/mi/miinitext.c +++ b/xorg-server/mi/miinitext.c @@ -287,6 +287,10 @@ static ExtensionModule staticExtensions[] = { #ifdef DPMSExtension {DPMSExtensionInit, DPMSExtensionName, &noDPMSExtension}, #endif + {present_extension_init, PRESENT_NAME, NULL}, +#ifdef DRI3 + {dri3_extension_init, DRI3_NAME, NULL}, +#endif #ifdef RES {ResExtensionInit, XRES_NAME, &noResExtension}, #endif diff --git a/xorg-server/miext/damage/damage.c b/xorg-server/miext/damage/damage.c index cc0299143..173fe5070 100644 --- a/xorg-server/miext/damage/damage.c +++ b/xorg-server/miext/damage/damage.c @@ -382,10 +382,7 @@ damageValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable) drawableDamage(pDrawable); DAMAGE_GC_FUNC_PROLOGUE(pGC); (*pGC->funcs->ValidateGC) (pGC, changes, pDrawable); - if (pDamage) - pGCPriv->ops = pGC->ops; /* so it's not NULL, so FUNC_EPILOGUE does work */ - else - pGCPriv->ops = NULL; + pGCPriv->ops = pGC->ops; /* just so it's not NULL */ DAMAGE_GC_FUNC_EPILOGUE(pGC); } diff --git a/xorg-server/miext/sync/Makefile.am b/xorg-server/miext/sync/Makefile.am index 9aa1ba5d5..e25ceacb0 100644 --- a/xorg-server/miext/sync/Makefile.am +++ b/xorg-server/miext/sync/Makefile.am @@ -5,10 +5,11 @@ AM_CFLAGS = $(DIX_CFLAGS) AM_CPPFLAGS = if XORG -sdk_HEADERS = misync.h misyncstr.h +sdk_HEADERS = misync.h misyncstr.h misyncshm.h endif libsync_la_SOURCES = \ misync.c \ misync.h \ + misyncshm.c \ misyncstr.h diff --git a/xorg-server/miext/sync/misync.c b/xorg-server/miext/sync/misync.c index b6914d18d..3d03d1b59 100644 --- a/xorg-server/miext/sync/misync.c +++ b/xorg-server/miext/sync/misync.c @@ -29,20 +29,7 @@ #include "misync.h" #include "misyncstr.h" -static DevPrivateKeyRec syncScreenPrivateKeyRec; -static DevPrivateKey syncScreenPrivateKey = &syncScreenPrivateKeyRec; - -#define SYNC_SCREEN_PRIV(pScreen) \ - (SyncScreenPrivPtr) dixLookupPrivate(&pScreen->devPrivates, \ - syncScreenPrivateKey) - -typedef struct _syncScreenPriv { - /* Wrappable sync-specific screen functions */ - SyncScreenFuncsRec funcs; - - /* Wrapped screen functions */ - CloseScreenProcPtr CloseScreen; -} SyncScreenPrivRec, *SyncScreenPrivPtr; +DevPrivateKeyRec miSyncScreenPrivateKey; /* Default implementations of the sync screen functions */ void @@ -62,25 +49,25 @@ miSyncScreenDestroyFence(ScreenPtr pScreen, SyncFence * pFence) } /* Default implementations of the per-object functions */ -static void +void miSyncFenceSetTriggered(SyncFence * pFence) { pFence->triggered = TRUE; } -static void +void miSyncFenceReset(SyncFence * pFence) { pFence->triggered = FALSE; } -static Bool +Bool miSyncFenceCheckTriggered(SyncFence * pFence) { return pFence->triggered; } -static void +void miSyncFenceAddTrigger(SyncTrigger * pTrigger) { (void) pTrigger; @@ -88,7 +75,7 @@ miSyncFenceAddTrigger(SyncTrigger * pTrigger) return; } -static void +void miSyncFenceDeleteTrigger(SyncTrigger * pTrigger) { (void) pTrigger; @@ -182,15 +169,15 @@ miSyncSetup(ScreenPtr pScreen) &miSyncScreenDestroyFence }; - if (!dixPrivateKeyRegistered(syncScreenPrivateKey)) { - if (!dixRegisterPrivateKey(syncScreenPrivateKey, PRIVATE_SCREEN, + if (!dixPrivateKeyRegistered(&miSyncScreenPrivateKey)) { + if (!dixRegisterPrivateKey(&miSyncScreenPrivateKey, PRIVATE_SCREEN, sizeof(SyncScreenPrivRec))) return FALSE; } pScreenPriv = SYNC_SCREEN_PRIV(pScreen); - if (pScreenPriv->funcs.CreateFence) { + if (!pScreenPriv->funcs.CreateFence) { pScreenPriv->funcs = miSyncScreenFuncs; /* Wrap CloseScreen to clean up */ diff --git a/xorg-server/miext/sync/misync.h b/xorg-server/miext/sync/misync.h index deebb82bc..f63ec2b82 100644 --- a/xorg-server/miext/sync/misync.h +++ b/xorg-server/miext/sync/misync.h @@ -76,4 +76,25 @@ extern _X_EXPORT SyncScreenFuncsPtr miSyncGetScreenFuncs(ScreenPtr pScreen); extern _X_EXPORT Bool miSyncSetup(ScreenPtr pScreen); +Bool +miSyncFenceCheckTriggered(SyncFence * pFence); + +void +miSyncFenceSetTriggered(SyncFence * pFence); + +void +miSyncFenceReset(SyncFence * pFence); + +void +miSyncFenceAddTrigger(SyncTrigger * pTrigger); + +void +miSyncFenceDeleteTrigger(SyncTrigger * pTrigger); + +int +miSyncInitFenceFromFD(DrawablePtr pDraw, SyncFence *pFence, int fd, BOOL initially_triggered); + +int +miSyncFDFromFence(DrawablePtr pDraw, SyncFence *pFence); + #endif /* _MISYNC_H_ */ diff --git a/xorg-server/miext/sync/misyncshm.c b/xorg-server/miext/sync/misyncshm.c new file mode 100644 index 000000000..ddd15ae49 --- /dev/null +++ b/xorg-server/miext/sync/misyncshm.c @@ -0,0 +1,176 @@ +/* + * Copyright © 2013 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include "scrnintstr.h" +#include "misync.h" +#include "misyncstr.h" +#include "misyncshm.h" +#include "pixmapstr.h" +#include <sys/mman.h> +#include <unistd.h> +#include <X11/xshmfence.h> + +static DevPrivateKeyRec syncShmFencePrivateKey; + +typedef struct _SyncShmFencePrivate { + int32_t *fence; + int fd; +} SyncShmFencePrivateRec, *SyncShmFencePrivatePtr; + +#define SYNC_FENCE_PRIV(pFence) \ + (SyncShmFencePrivatePtr) dixLookupPrivate(&pFence->devPrivates, &syncShmFencePrivateKey) + +static void +miSyncShmFenceSetTriggered(SyncFence * pFence) +{ + SyncShmFencePrivatePtr pPriv = SYNC_FENCE_PRIV(pFence); + + if (pPriv->fence) + xshmfence_trigger(pPriv->fence); + miSyncFenceSetTriggered(pFence); +} + +static void +miSyncShmFenceReset(SyncFence * pFence) +{ + SyncShmFencePrivatePtr pPriv = SYNC_FENCE_PRIV(pFence); + + if (pPriv->fence) + xshmfence_reset(pPriv->fence); + miSyncFenceReset(pFence); +} + +static Bool +miSyncShmFenceCheckTriggered(SyncFence * pFence) +{ + SyncShmFencePrivatePtr pPriv = SYNC_FENCE_PRIV(pFence); + + if (pPriv->fence) + return xshmfence_query(pPriv->fence); + else + return miSyncFenceCheckTriggered(pFence); +} + +static void +miSyncShmFenceAddTrigger(SyncTrigger * pTrigger) +{ + miSyncFenceAddTrigger(pTrigger); +} + +static void +miSyncShmFenceDeleteTrigger(SyncTrigger * pTrigger) +{ + miSyncFenceDeleteTrigger(pTrigger); +} + +static const SyncFenceFuncsRec miSyncShmFenceFuncs = { + &miSyncShmFenceSetTriggered, + &miSyncShmFenceReset, + &miSyncShmFenceCheckTriggered, + &miSyncShmFenceAddTrigger, + &miSyncShmFenceDeleteTrigger +}; + +static void +miSyncShmScreenCreateFence(ScreenPtr pScreen, SyncFence * pFence, + Bool initially_triggered) +{ + SyncShmFencePrivatePtr pPriv = SYNC_FENCE_PRIV(pFence); + + pPriv->fence = NULL; + miSyncScreenCreateFence(pScreen, pFence, initially_triggered); + pFence->funcs = miSyncShmFenceFuncs; +} + +static void +miSyncShmScreenDestroyFence(ScreenPtr pScreen, SyncFence * pFence) +{ + SyncShmFencePrivatePtr pPriv = SYNC_FENCE_PRIV(pFence); + + if (pPriv->fence) { + xshmfence_trigger(pPriv->fence); + xshmfence_unmap_shm(pPriv->fence); + close(pPriv->fd); + } + miSyncScreenDestroyFence(pScreen, pFence); +} + +int +miSyncInitFenceFromFD(DrawablePtr pDraw, SyncFence *pFence, int fd, BOOL initially_triggered) + +{ + SyncShmFencePrivatePtr pPriv = SYNC_FENCE_PRIV(pFence); + + miSyncInitFence(pDraw->pScreen, pFence, initially_triggered); + + pPriv->fence = xshmfence_map_shm(fd); + if (pPriv->fence) { + pPriv->fd = fd; + return Success; + } + else + close(fd); + return BadValue; +} + +int +miSyncFDFromFence(DrawablePtr pDraw, SyncFence *pFence) +{ + SyncShmFencePrivatePtr pPriv = SYNC_FENCE_PRIV(pFence); + + if (!pPriv->fence) { + pPriv->fd = xshmfence_alloc_shm(); + if (pPriv->fd < 0) + return -1; + pPriv->fence = xshmfence_map_shm(pPriv->fd); + if (!pPriv->fence) { + close (pPriv->fd); + return -1; + } + } + return pPriv->fd; +} + +_X_EXPORT Bool miSyncShmScreenInit(ScreenPtr pScreen) +{ + SyncScreenFuncsPtr funcs; + + if (!miSyncSetup(pScreen)) + return FALSE; + + if (!dixPrivateKeyRegistered(&syncShmFencePrivateKey)) { + if (!dixRegisterPrivateKey(&syncShmFencePrivateKey, PRIVATE_SYNC_FENCE, + sizeof(SyncShmFencePrivateRec))) + return FALSE; + } + + funcs = miSyncGetScreenFuncs(pScreen); + + funcs->CreateFence = miSyncShmScreenCreateFence; + funcs->DestroyFence = miSyncShmScreenDestroyFence; + return TRUE; +} + diff --git a/xorg-server/miext/sync/misyncshm.h b/xorg-server/miext/sync/misyncshm.h new file mode 100644 index 000000000..4edbb50c3 --- /dev/null +++ b/xorg-server/miext/sync/misyncshm.h @@ -0,0 +1,28 @@ +/* + * Copyright © 2013 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifndef _MISYNCSHM_H_ +#define _MISYNCSYM_H_ + +extern _X_EXPORT Bool miSyncShmScreenInit(ScreenPtr pScreen); + +#endif /* _MISYNCSHM_H_ */ diff --git a/xorg-server/miext/sync/misyncstr.h b/xorg-server/miext/sync/misyncstr.h index e19256fee..b5bf6fd91 100644 --- a/xorg-server/miext/sync/misyncstr.h +++ b/xorg-server/miext/sync/misyncstr.h @@ -29,6 +29,7 @@ #define _MISYNCSTR_H_ #include "dix.h" +#include "scrnintstr.h" #include <X11/extensions/syncconst.h> #define CARD64 XSyncValue /* XXX temporary! need real 64 bit values for Alpha */ @@ -79,4 +80,18 @@ typedef struct _SyncTriggerList { struct _SyncTriggerList *next; } SyncTriggerList; +extern DevPrivateKeyRec miSyncScreenPrivateKey; + +#define SYNC_SCREEN_PRIV(pScreen) \ + (SyncScreenPrivPtr) dixLookupPrivate(&pScreen->devPrivates, \ + &miSyncScreenPrivateKey) + +typedef struct _syncScreenPriv { + /* Wrappable sync-specific screen functions */ + SyncScreenFuncsRec funcs; + + /* Wrapped screen functions */ + CloseScreenProcPtr CloseScreen; +} SyncScreenPrivRec, *SyncScreenPrivPtr; + #endif /* _MISYNCSTR_H_ */ diff --git a/xorg-server/os/backtrace.c b/xorg-server/os/backtrace.c index 426f9b15b..3d1195b86 100644 --- a/xorg-server/os/backtrace.c +++ b/xorg-server/os/backtrace.c @@ -114,14 +114,15 @@ xorg_backtrace(void) void xorg_backtrace(void) { - void *array[64]; + const int BT_SIZE = 64; + void *array[BT_SIZE]; const char *mod; int size, i; Dl_info info; ErrorFSigSafe("\n"); ErrorFSigSafe("Backtrace:\n"); - size = backtrace(array, 64); + size = backtrace(array, BT_SIZE); for (i = 0; i < size; i++) { int rc = dladdr(array[i], &info); diff --git a/xorg-server/os/connection.c b/xorg-server/os/connection.c index 6cd8bcf43..162e1d93e 100644 --- a/xorg-server/os/connection.c +++ b/xorg-server/os/connection.c @@ -923,7 +923,7 @@ ErrorConnMax(XtransConnInfo trans_conn) iov[0].iov_len = sz_xConnSetupPrefix; iov[0].iov_base = (char *) &csp; iov[1].iov_len = csp.lengthReason; - iov[1].iov_base = NOROOM; + iov[1].iov_base = (void *) NOROOM; iov[2].iov_len = (4 - (csp.lengthReason & 3)) & 3; iov[2].iov_base = pad; (void) _XSERVTransWritev(trans_conn, iov, 3); diff --git a/xorg-server/os/io.c b/xorg-server/os/io.c index 380036664..a20faa56f 100644 --- a/xorg-server/os/io.c +++ b/xorg-server/os/io.c @@ -259,6 +259,12 @@ ReadRequestFromClient(ClientPtr client) oc->input = oci; } + /* Discard any unused file descriptors */ + while (client->req_fds > 0) { + int req_fd = ReadFdFromClient(client); + if (req_fd >= 0) + close(req_fd); + } /* advance to start of next request */ oci->bufptr += oci->lenLastReq; @@ -485,6 +491,29 @@ ReadRequestFromClient(ClientPtr client) return needed; } +int +ReadFdFromClient(ClientPtr client) +{ + int fd = -1; + + if (client->req_fds > 0) { + OsCommPtr oc = (OsCommPtr) client->osPrivate; + + --client->req_fds; + fd = _XSERVTransRecvFd(oc->trans_conn); + } else + LogMessage(X_ERROR, "Request asks for FD without setting req_fds\n"); + return fd; +} + +int +WriteFdToClient(ClientPtr client, int fd, Bool do_close) +{ + OsCommPtr oc = (OsCommPtr) client->osPrivate; + + return _XSERVTransSendFd(oc->trans_conn, fd, do_close); +} + /***************************************************************** * InsertFakeRequest * Splice a consed up (possibly partial) request in as the next request. diff --git a/xorg-server/os/utils.c b/xorg-server/os/utils.c index 97c3125e6..995f62a37 100644 --- a/xorg-server/os/utils.c +++ b/xorg-server/os/utils.c @@ -430,6 +430,11 @@ GetTimeInMillis(void) { return GetTickCount(); } +CARD64 +GetTimeInMicros(void) +{ + return (CARD64) GetTickCount() * 1000; +} #else CARD32 GetTimeInMillis(void) @@ -460,6 +465,28 @@ GetTimeInMillis(void) X_GETTIMEOFDAY(&tv); return (tv.tv_sec * 1000) + (tv.tv_usec / 1000); } + +CARD64 +GetTimeInMicros(void) +{ + struct timeval tv; +#ifdef MONOTONIC_CLOCK + struct timespec tp; + static clockid_t clockid; + + if (!clockid) { + if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0) + clockid = CLOCK_MONOTONIC; + else + clockid = ~0L; + } + if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0) + return (CARD64) tp.tv_sec * (CARD64)1000000 + tp.tv_nsec / 1000; +#endif + + X_GETTIMEOFDAY(&tv); + return (CARD64) tv.tv_sec * (CARD64)1000000000 + (CARD64) tv.tv_usec * 1000; +} #endif void diff --git a/xorg-server/os/xstrans.c b/xorg-server/os/xstrans.c index 6348a6511..2bc79e7ae 100644 --- a/xorg-server/os/xstrans.c +++ b/xorg-server/os/xstrans.c @@ -5,9 +5,11 @@ #include <X11/Xfuncproto.h> /* ErrorF is used by xtrans */ +#ifndef HAVE_DIX_CONFIG_H extern _X_EXPORT void ErrorF(const char *f, ...) _X_ATTRIBUTE_PRINTF(1, 2); +#endif #define TRANS_REOPEN #define TRANS_SERVER diff --git a/xorg-server/present/Makefile.am b/xorg-server/present/Makefile.am new file mode 100644 index 000000000..7fea6699f --- /dev/null +++ b/xorg-server/present/Makefile.am @@ -0,0 +1,17 @@ +noinst_LTLIBRARIES = libpresent.la +AM_CFLAGS = \ + -DHAVE_XORG_CONFIG_H \ + @DIX_CFLAGS@ @XORG_CFLAGS@ + +libpresent_la_SOURCES = \ + present.h \ + present.c \ + present_event.c \ + present_fake.c \ + present_fence.c \ + present_notify.c \ + present_priv.h \ + present_request.c \ + present_screen.c + +sdk_HEADERS = present.h presentext.h diff --git a/xorg-server/present/present.c b/xorg-server/present/present.c new file mode 100644 index 000000000..4c97ce40c --- /dev/null +++ b/xorg-server/present/present.c @@ -0,0 +1,775 @@ +/* + * Copyright © 2013 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include "present_priv.h" +#include <gcstruct.h> +#include <misync.h> +#include <misyncstr.h> +#ifdef MONOTONIC_CLOCK +#include <time.h> +#endif + +static uint64_t present_event_id; +static struct xorg_list present_exec_queue; +static struct xorg_list present_flip_queue; + +#if 0 +#define DebugPresent(x) ErrorF x +#else +#define DebugPresent(x) +#endif + +/* + * Copies the update region from a pixmap to the target drawable + */ +static void +present_copy_region(DrawablePtr drawable, + PixmapPtr pixmap, + RegionPtr update, + int16_t x_off, + int16_t y_off) +{ + ScreenPtr screen = drawable->pScreen; + GCPtr gc; + + gc = GetScratchGC(drawable->depth, screen); + if (update) { + ChangeGCVal changes[2]; + + changes[0].val = x_off; + changes[1].val = y_off; + ChangeGC(serverClient, gc, + GCClipXOrigin|GCClipYOrigin, + changes); + (*gc->funcs->ChangeClip)(gc, CT_REGION, update, 0); + } + ValidateGC(drawable, gc); + (*gc->ops->CopyArea)(&pixmap->drawable, + drawable, + gc, + 0, 0, + pixmap->drawable.width, pixmap->drawable.height, + x_off, y_off); + if (update) + (*gc->funcs->ChangeClip)(gc, CT_NONE, NULL, 0); + FreeScratchGC(gc); +} + +static Bool +present_check_flip(RRCrtcPtr crtc, + WindowPtr window, + PixmapPtr pixmap, + Bool sync_flip, + RegionPtr valid, + int16_t x_off, + int16_t y_off) +{ + ScreenPtr screen = window->drawable.pScreen; + WindowPtr root = screen->root; + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + + if (!screen_priv) + return FALSE; + + if (!screen_priv->info) + return FALSE; + + if (!crtc) + return FALSE; + + /* Check to see if the driver supports flips at all */ + if (!screen_priv->info->flip) + return FALSE; + + /* Can't pend a flip while unflipping */ + if (screen_priv->unflip_event_id) { + return FALSE; + } + + /* Can't have two pending flips at the same time */ + if (screen_priv->flip_pending) { + return FALSE; + } + + /* Make sure the window hasn't been redirected with Composite */ + if (screen->GetWindowPixmap(window) != screen->GetScreenPixmap(screen)) + return FALSE; + + /* Check for full-screen window */ + if (!RegionEqual(&window->clipList, &root->winSize)) { + return FALSE; + } + + /* Source pixmap must align with window exactly */ + if (x_off || y_off) { + return FALSE; + } + + /* Make sure the area marked as valid fills the screen */ + if (valid && !RegionEqual(valid, &root->winSize)) { + return FALSE; + } + + /* Does the window match the pixmap exactly? */ + if (window->drawable.x != 0 || window->drawable.y != 0 || +#ifdef COMPOSITE + window->drawable.x != pixmap->screen_x || window->drawable.y != pixmap->screen_y || +#endif + window->drawable.width != pixmap->drawable.width || + window->drawable.height != pixmap->drawable.height) { + return FALSE; + } + + /* Ask the driver for permission */ + if (screen_priv->info->check_flip) { + if (!(*screen_priv->info->check_flip) (crtc, window, pixmap, sync_flip)) { + return FALSE; + } + } + + return TRUE; +} + +static Bool +present_flip(RRCrtcPtr crtc, + uint64_t event_id, + uint64_t target_msc, + PixmapPtr pixmap, + Bool sync_flip) +{ + ScreenPtr screen = crtc->pScreen; + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + + return (*screen_priv->info->flip) (crtc, event_id, target_msc, pixmap, sync_flip); +} + +static void +present_vblank_notify(present_vblank_ptr vblank, CARD8 kind, CARD8 mode, uint64_t ust, uint64_t crtc_msc) +{ + int n; + + present_send_complete_notify(vblank->window, kind, mode, vblank->serial, ust, crtc_msc - vblank->msc_offset); + for (n = 0; n < vblank->num_notifies; n++) { + WindowPtr window = vblank->notifies[n].window; + CARD32 serial = vblank->notifies[n].serial; + + if (window) + present_send_complete_notify(window, kind, mode, serial, ust, crtc_msc - vblank->msc_offset); + } +} + +static void +present_pixmap_idle(PixmapPtr pixmap, WindowPtr window, CARD32 serial, struct present_fence *present_fence) +{ + present_fence_set_triggered(present_fence); + present_send_idle_notify(window, serial, pixmap, present_fence); +} + +RRCrtcPtr +present_get_crtc(WindowPtr window) +{ + ScreenPtr screen = window->drawable.pScreen; + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + + if (!screen_priv) + return NULL; + + if (!screen_priv->info) + return NULL; + + return (*screen_priv->info->get_crtc)(window); +} + +uint32_t +present_query_capabilities(RRCrtcPtr crtc) +{ + present_screen_priv_ptr screen_priv; + + if (!crtc) + return 0; + + screen_priv = present_screen_priv(crtc->pScreen); + + if (!screen_priv) + return 0; + + if (!screen_priv->info) + return 0; + + return screen_priv->info->capabilities; +} + +static int +present_get_ust_msc(WindowPtr window, RRCrtcPtr crtc, uint64_t *ust, uint64_t *msc) +{ + ScreenPtr screen = window->drawable.pScreen; + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + + if (crtc == NULL) + return present_fake_get_ust_msc(screen, ust, msc); + else + return (*screen_priv->info->get_ust_msc)(crtc, ust, msc); +} + +static void +present_flush(WindowPtr window) +{ + ScreenPtr screen = window->drawable.pScreen; + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + + if (!screen_priv) + return; + + if (!screen_priv->info) + return; + + (*screen_priv->info->flush) (window); +} + +static int +present_queue_vblank(ScreenPtr screen, + RRCrtcPtr crtc, + uint64_t event_id, + uint64_t msc) +{ + Bool ret; + + if (crtc == NULL) + ret = present_fake_queue_vblank(screen, event_id, msc); + else + { + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + ret = (*screen_priv->info->queue_vblank) (crtc, event_id, msc); + } + return ret; +} + +static uint64_t +present_window_to_crtc_msc(WindowPtr window, RRCrtcPtr crtc, uint64_t window_msc, uint64_t new_msc) +{ + present_window_priv_ptr window_priv = present_get_window_priv(window, TRUE); + + if (crtc != window_priv->crtc) { + uint64_t old_ust, old_msc; + + /* The old CRTC may have been turned off, in which case + * we'll just use whatever previous MSC we'd seen from this CRTC + */ + + if (present_get_ust_msc(window, window_priv->crtc, &old_ust, &old_msc) != Success) + old_msc = window_priv->msc; + + window_priv->msc_offset += new_msc - old_msc; + window_priv->crtc = crtc; + } + + return window_msc + window_priv->msc_offset; +} + +static void +present_flip_idle(ScreenPtr screen) +{ + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + + if (screen_priv->flip_pixmap) { + present_pixmap_idle(screen_priv->flip_pixmap, screen_priv->flip_window, + screen_priv->flip_serial, screen_priv->flip_idle_fence); + present_fence_destroy(screen_priv->flip_idle_fence); + dixDestroyPixmap(screen_priv->flip_pixmap, screen_priv->flip_pixmap->drawable.id); + screen_priv->flip_crtc = NULL; + screen_priv->flip_window = NULL; + screen_priv->flip_serial = 0; + screen_priv->flip_pixmap = NULL; + screen_priv->flip_idle_fence = NULL; + } +} + +static void +present_unflip(ScreenPtr screen) +{ + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + + assert (!screen_priv->unflip_event_id); + assert (!screen_priv->flip_pending); + + /* Update the screen pixmap with the current flip pixmap contents + */ + if (screen_priv->flip_pixmap) { + present_copy_region(&screen->GetScreenPixmap(screen)->drawable, + screen_priv->flip_pixmap, + NULL, 0, 0); + } + screen_priv->unflip_event_id = ++present_event_id; + DebugPresent(("u %lld\n", screen_priv->unflip_event_id)); + (*screen_priv->info->unflip) (screen, screen_priv->unflip_event_id); +} + +static void +present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc); + +static void +present_flip_notify(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc) +{ + WindowPtr window = vblank->window; + ScreenPtr screen = window->drawable.pScreen; + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + + DebugPresent(("\tn %p %8lld: %08lx -> %08lx\n", vblank, vblank->target_msc, + vblank->pixmap ? vblank->pixmap->drawable.id : 0, + vblank->window->drawable.id)); + + assert (vblank == screen_priv->flip_pending); + + present_flip_idle(screen); + + /* Transfer reference for pixmap and fence from vblank to screen_priv */ + screen_priv->flip_crtc = vblank->crtc; + screen_priv->flip_window = vblank->window; + screen_priv->flip_serial = vblank->serial; + screen_priv->flip_pixmap = vblank->pixmap; + screen_priv->flip_idle_fence = vblank->idle_fence; + + vblank->pixmap = NULL; + vblank->idle_fence = NULL; + + screen_priv->flip_pending = NULL; + + if (vblank->abort_flip) + present_unflip(screen); + + if (!vblank->window_destroyed) + present_vblank_notify(vblank, PresentCompleteKindPixmap, PresentCompleteModeFlip, ust, crtc_msc); + present_vblank_destroy(vblank); +} + +void +present_event_notify(uint64_t event_id, uint64_t ust, uint64_t msc) +{ + present_vblank_ptr vblank, tmp; + int s; + + xorg_list_for_each_entry_safe(vblank, tmp, &present_exec_queue, event_queue) { + if (vblank->event_id == event_id) { + xorg_list_del(&vblank->event_queue); + present_execute(vblank, ust, msc); + return; + } + } + xorg_list_for_each_entry_safe(vblank, tmp, &present_flip_queue, event_queue) { + if (vblank->event_id == event_id) { + xorg_list_del(&vblank->event_queue); + present_flip_notify(vblank, ust, msc); + return; + } + } + + for (s = 0; s < screenInfo.numScreens; s++) { + ScreenPtr screen = screenInfo.screens[s]; + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + + if (event_id == screen_priv->unflip_event_id) { + DebugPresent(("\tun %lld\n", event_id)); + screen_priv->unflip_event_id = 0; + present_flip_idle(screen); + } + } +} + +/* + * 'window' is being reconfigured. Check to see if it is involved + * in flipping and clean up as necessary + */ +void +present_check_flip_window (WindowPtr window) +{ + ScreenPtr screen = window->drawable.pScreen; + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + present_window_priv_ptr window_priv = present_window_priv(window); + present_vblank_ptr flip_pending = screen_priv->flip_pending; + present_vblank_ptr vblank; + + /* If this window hasn't ever been used with Present, it can't be + * flipping + */ + if (!window_priv) + return; + + if (screen_priv->unflip_event_id) + return; + + if (flip_pending) { + /* + * Check pending flip + */ + if (flip_pending->window == window) { + if (!present_check_flip(flip_pending->crtc, window, flip_pending->pixmap, + flip_pending->sync_flip, NULL, 0, 0)) + flip_pending->abort_flip = TRUE; + } + } else { + /* + * Check current flip + */ + if (window == screen_priv->flip_window) { + if (!present_check_flip(screen_priv->flip_crtc, window, screen_priv->flip_pixmap, FALSE, NULL, 0, 0)) + present_unflip(screen); + } + } + + /* Now check any queued vblanks */ + xorg_list_for_each_entry(vblank, &window_priv->vblank, window_list) { + if (vblank->flip && !present_check_flip(vblank->crtc, window, vblank->pixmap, FALSE, NULL, 0, 0)) + vblank->flip = FALSE; + } +} + +/* + * Once the required MSC has been reached, execute the pending request. + * + * For requests to actually present something, either blt contents to + * the screen or queue a frame buffer swap. + * + * For requests to just get the current MSC/UST combo, skip that part and + * go straight to event delivery + */ + +static void +present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc) +{ + WindowPtr window = vblank->window; + present_screen_priv_ptr screen_priv = present_screen_priv(window->drawable.pScreen); + + if (vblank->wait_fence) { + /* XXX check fence, queue if not ready */ + } + + xorg_list_del(&vblank->event_queue); + if (vblank->pixmap) { + + if (vblank->flip && screen_priv->flip_pending == NULL && !screen_priv->unflip_event_id) { + + DebugPresent(("\tf %p %8lld: %08lx -> %08lx\n", vblank, crtc_msc, vblank->pixmap->drawable.id, vblank->window->drawable.id)); + /* Prepare to flip by removing from the window/screen lists + * and sticking it into the flip_pending field + */ + screen_priv->flip_pending = vblank; + xorg_list_del(&vblank->window_list); + + xorg_list_add(&vblank->event_queue, &present_flip_queue); + /* Try to flip + */ + if (present_flip(vblank->crtc, vblank->event_id, vblank->target_msc, vblank->pixmap, vblank->sync_flip)) + return; + + xorg_list_del(&vblank->event_queue); + /* Oops, flip failed. Clear the flip_pending field + */ + screen_priv->flip_pending = NULL; + vblank->flip = FALSE; + } + DebugPresent(("\tc %p %8lld: %08lx -> %08lx\n", vblank, crtc_msc, vblank->pixmap->drawable.id, vblank->window->drawable.id)); + if (screen_priv->flip_pending) { + + /* Check pending flip + */ + if (window == screen_priv->flip_pending->window) + screen_priv->flip_pending->abort_flip = TRUE; + } else if (!screen_priv->unflip_event_id) { + + /* Check current flip + */ + if (window == screen_priv->flip_window) + present_unflip(window->drawable.pScreen); + } + present_copy_region(&window->drawable, vblank->pixmap, vblank->update, vblank->x_off, vblank->y_off); + + /* present_copy_region sticks the region into a scratch GC, + * which is then freed, freeing the region + */ + vblank->update = NULL; + present_flush(window); + + present_pixmap_idle(vblank->pixmap, vblank->window, vblank->serial, vblank->idle_fence); + } + present_vblank_notify(vblank, vblank->kind, PresentCompleteModeCopy, ust, crtc_msc); + present_vblank_destroy(vblank); +} + +int +present_pixmap(WindowPtr window, + PixmapPtr pixmap, + CARD32 serial, + RegionPtr valid, + RegionPtr update, + int16_t x_off, + int16_t y_off, + RRCrtcPtr target_crtc, + SyncFence *wait_fence, + SyncFence *idle_fence, + uint32_t options, + uint64_t window_msc, + uint64_t divisor, + uint64_t remainder, + present_notify_ptr notifies, + int num_notifies) +{ + uint64_t ust; + uint64_t target_msc; + uint64_t crtc_msc; + int ret; + present_vblank_ptr vblank; + ScreenPtr screen = window->drawable.pScreen; + present_window_priv_ptr window_priv = present_get_window_priv(window, TRUE); + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + + if (!window_priv) + return BadAlloc; + + if (!target_crtc) { + /* Update the CRTC if we have a pixmap or we don't have a CRTC + */ + if (!pixmap) + target_crtc = window_priv->crtc; + + if (!target_crtc) + target_crtc = present_get_crtc(window); + } + + present_get_ust_msc(window, target_crtc, &ust, &crtc_msc); + + target_msc = present_window_to_crtc_msc(window, target_crtc, window_msc, crtc_msc); + + /* Stash the current MSC away in case we need it later + */ + window_priv->msc = crtc_msc; + + /* Adjust target_msc to match modulus + */ + if (crtc_msc >= target_msc) { + if (divisor != 0) { + target_msc = crtc_msc - (crtc_msc % divisor) + remainder; + if (target_msc <= crtc_msc) + target_msc += divisor; + } else + target_msc = crtc_msc; + } + + /* + * Look for a matching presentation already on the list and + * don't bother doing the previous one if this one will overwrite it + * in the same frame + */ + + if (!update) { + xorg_list_for_each_entry(vblank, &window_priv->vblank, window_list) { + + if (!vblank->pixmap) + continue; + + if (vblank->crtc != target_crtc || vblank->target_msc != target_msc) + continue; + + present_pixmap_idle(vblank->pixmap, vblank->window, vblank->serial, vblank->idle_fence); + present_fence_destroy(vblank->idle_fence); + dixDestroyPixmap(vblank->pixmap, vblank->pixmap->drawable.id); + + vblank->pixmap = NULL; + vblank->idle_fence = NULL; + } + } + + vblank = calloc (1, sizeof (present_vblank_rec)); + if (!vblank) + return BadAlloc; + + xorg_list_append(&vblank->window_list, &window_priv->vblank); + xorg_list_init(&vblank->event_queue); + + vblank->screen = screen; + vblank->window = window; + vblank->pixmap = pixmap; + vblank->event_id = ++present_event_id; + if (pixmap) { + vblank->kind = PresentCompleteKindPixmap; + pixmap->refcnt++; + } else + vblank->kind = PresentCompleteKindNotifyMSC; + + vblank->serial = serial; + + if (valid) { + vblank->valid = RegionDuplicate(valid); + if (!vblank->valid) + goto no_mem; + } + if (update) { + vblank->update = RegionDuplicate(update); + if (!vblank->update) + goto no_mem; + } + + vblank->x_off = x_off; + vblank->y_off = y_off; + vblank->target_msc = target_msc; + vblank->crtc = target_crtc; + vblank->msc_offset = window_priv->msc_offset; + vblank->notifies = notifies; + vblank->num_notifies = num_notifies; + + if (!screen_priv->info || !(screen_priv->info->capabilities & PresentCapabilityAsync)) + vblank->sync_flip = TRUE; + + if (pixmap && present_check_flip (target_crtc, window, pixmap, vblank->sync_flip, valid, x_off, y_off)) { + vblank->flip = TRUE; + if (vblank->sync_flip) + target_msc--; + } + + if (idle_fence) { + vblank->idle_fence = present_fence_create(idle_fence); + if (!vblank->idle_fence) + goto no_mem; + } + + if (pixmap) + DebugPresent(("q %p %8lld: %08lx -> %08lx (crtc %d)\n", + vblank, target_msc, vblank->pixmap->drawable.id, vblank->window->drawable.id, target_crtc ? 1 : 0)); + + xorg_list_add(&vblank->event_queue, &present_exec_queue); + if (target_msc >= crtc_msc) { + ret = present_queue_vblank(screen, target_crtc, vblank->event_id, target_msc); + if (ret != Success) { + xorg_list_del(&vblank->event_queue); + goto failure; + } + } else + present_execute(vblank, ust, crtc_msc); + + return Success; + +no_mem: + ret = BadAlloc; +failure: + vblank->notifies = NULL; + present_vblank_destroy(vblank); + return ret; +} + +void +present_abort_vblank(ScreenPtr screen, RRCrtcPtr crtc, uint64_t event_id, uint64_t msc) +{ + present_vblank_ptr vblank, tmp; + + if (crtc == NULL) + present_fake_abort_vblank(screen, event_id, msc); + else + { + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + + (*screen_priv->info->abort_vblank) (crtc, event_id, msc); + } + + xorg_list_for_each_entry_safe(vblank, tmp, &present_exec_queue, event_queue) { + if (vblank->event_id == event_id) { + xorg_list_del(&vblank->event_queue); + return; + } + } + xorg_list_for_each_entry_safe(vblank, tmp, &present_flip_queue, event_queue) { + if (vblank->event_id == event_id) { + xorg_list_del(&vblank->event_queue); + return; + } + } +} + +int +present_notify_msc(WindowPtr window, + CARD32 serial, + uint64_t target_msc, + uint64_t divisor, + uint64_t remainder) +{ + return present_pixmap(window, + NULL, + serial, + NULL, NULL, + 0, 0, + NULL, + NULL, NULL, + 0, + target_msc, divisor, remainder, NULL, 0); +} + +void +present_flip_destroy(ScreenPtr screen) +{ + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + + /* XXX this needs to be synchronous for server reset */ + + /* Do the actual cleanup once the flip has been performed by the hardware */ + if (screen_priv->flip_pending) + screen_priv->flip_pending->abort_flip = TRUE; +} + +void +present_vblank_destroy(present_vblank_ptr vblank) +{ + /* Remove vblank from window and screen lists */ + xorg_list_del(&vblank->window_list); + + DebugPresent(("\td %p %8lld: %08lx -> %08lx\n", vblank, vblank->target_msc, + vblank->pixmap ? vblank->pixmap->drawable.id : 0, + vblank->window->drawable.id)); + + /* Drop pixmap reference */ + if (vblank->pixmap) + dixDestroyPixmap(vblank->pixmap, vblank->pixmap->drawable.id); + + /* Free regions */ + if (vblank->valid) + RegionDestroy(vblank->valid); + if (vblank->update) + RegionDestroy(vblank->update); + + if (vblank->idle_fence) + present_fence_destroy(vblank->idle_fence); + + if (vblank->notifies) + present_destroy_notifies(vblank->notifies, vblank->num_notifies); + + free(vblank); +} + +Bool +present_init(void) +{ + xorg_list_init(&present_exec_queue); + xorg_list_init(&present_flip_queue); + present_fake_queue_init(); + return TRUE; +} diff --git a/xorg-server/present/present.h b/xorg-server/present/present.h new file mode 100644 index 000000000..6a451fb23 --- /dev/null +++ b/xorg-server/present/present.h @@ -0,0 +1,118 @@ +/* + * Copyright © 2013 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifndef _PRESENT_H_ +#define _PRESENT_H_ + +#include <X11/extensions/presentproto.h> +#include "randrstr.h" +#include "presentext.h" + +typedef struct present_vblank present_vblank_rec, *present_vblank_ptr; + +/* Return the current CRTC for 'window'. + */ +typedef RRCrtcPtr (*present_get_crtc_ptr) (WindowPtr window); + +/* Return the current ust/msc for 'crtc' + */ +typedef int (*present_get_ust_msc_ptr) (RRCrtcPtr crtc, uint64_t *ust, uint64_t *msc); + +/* Queue callback on 'crtc' for time 'msc'. Call present_event_notify with 'event_id' + * at or after 'msc'. Return false if it didn't happen (which might occur if 'crtc' + * is not currently generating vblanks). + */ +typedef Bool (*present_queue_vblank_ptr) (RRCrtcPtr crtc, + uint64_t event_id, + uint64_t msc); + +/* Abort pending vblank. The extension is no longer interested in + * 'event_id' which was to be notified at 'msc'. If possible, the + * driver is free to de-queue the notification. + */ +typedef void (*present_abort_vblank_ptr) (RRCrtcPtr crtc, uint64_t event_id, uint64_t msc); + +/* Flush pending drawing on 'window' to the hardware. + */ +typedef void (*present_flush_ptr) (WindowPtr window); + +/* Check if 'pixmap' is suitable for flipping to 'window'. + */ +typedef Bool (*present_check_flip_ptr) (RRCrtcPtr crtc, WindowPtr window, PixmapPtr pixmap, Bool sync_flip); + +/* Flip pixmap, return false if it didn't happen. + * + * 'crtc' is to be used for any necessary synchronization. + * + * 'sync_flip' requests that the flip be performed at the next + * vertical blank interval to avoid tearing artifacts. If false, the + * flip should be performed as soon as possible. + * + * present_event_notify should be called with 'event_id' when the flip + * occurs + */ +typedef Bool (*present_flip_ptr) (RRCrtcPtr crtc, + uint64_t event_id, + uint64_t target_msc, + PixmapPtr pixmap, + Bool sync_flip); + +/* "unflip" back to the regular screen scanout buffer + * + * present_event_notify should be called with 'event_id' when the unflip occurs. + */ +typedef void (*present_unflip_ptr) (ScreenPtr screen, + uint64_t event_id); + +#define PRESENT_SCREEN_INFO_VERSION 0 + +typedef struct present_screen_info { + uint32_t version; + + present_get_crtc_ptr get_crtc; + present_get_ust_msc_ptr get_ust_msc; + present_queue_vblank_ptr queue_vblank; + present_abort_vblank_ptr abort_vblank; + present_flush_ptr flush; + uint32_t capabilities; + present_check_flip_ptr check_flip; + present_flip_ptr flip; + present_unflip_ptr unflip; + +} present_screen_info_rec, *present_screen_info_ptr; + +/* + * Called when 'event_id' occurs. 'ust' and 'msc' indicate when the + * event actually happened + */ +extern _X_EXPORT void +present_event_notify(uint64_t event_id, uint64_t ust, uint64_t msc); + +/* 'crtc' has been turned off, so any pending events will never occur. + */ +extern _X_EXPORT void +present_event_abandon(RRCrtcPtr crtc); + +extern _X_EXPORT Bool +present_screen_init(ScreenPtr screen, present_screen_info_ptr info); + +#endif /* _PRESENT_H_ */ diff --git a/xorg-server/present/present_event.c b/xorg-server/present/present_event.c new file mode 100644 index 000000000..a30bc8286 --- /dev/null +++ b/xorg-server/present/present_event.c @@ -0,0 +1,239 @@ +/* + * Copyright © 2013 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include "present_priv.h" + +#include "present_priv.h" + +RESTYPE present_event_type; + +static int +present_free_event(pointer data, XID id) +{ + present_event_ptr present_event = (present_event_ptr) data; + present_window_priv_ptr window_priv = present_window_priv(present_event->window); + present_event_ptr *previous, current; + + for (previous = &window_priv->events; (current = *previous); previous = ¤t->next) { + if (current == present_event) { + *previous = present_event->next; + break; + } + } + free((pointer) present_event); + return 1; + +} + +void +present_free_events(WindowPtr window) +{ + present_window_priv_ptr window_priv = present_window_priv(window); + present_event_ptr event; + + if (!window_priv) + return; + + while ((event = window_priv->events)) + FreeResource(event->id, RT_NONE); +} + +static void +present_event_swap(xGenericEvent *from, xGenericEvent *to) +{ + *to = *from; + swaps(&to->sequenceNumber); + swapl(&to->length); + swaps(&to->evtype); + switch (from->evtype) { + case PresentConfigureNotify: { + xPresentConfigureNotify *c = (xPresentConfigureNotify *) to; + + swapl(&c->eid); + swapl(&c->window); + swaps(&c->x); + swaps(&c->y); + swaps(&c->width); + swaps(&c->height); + swaps(&c->off_x); + swaps(&c->off_y); + swaps(&c->pixmap_width); + swaps(&c->pixmap_height); + swapl(&c->pixmap_flags); + break; + } + case PresentCompleteNotify: + { + xPresentCompleteNotify *c = (xPresentCompleteNotify *) to; + swapl(&c->eid); + swapl(&c->window); + swapl(&c->serial); + swapll(&c->ust); + swapll(&c->msc); + } + case PresentIdleNotify: + { + xPresentIdleNotify *c = (xPresentIdleNotify *) to; + swapl(&c->eid); + swapl(&c->window); + swapl(&c->serial); + swapl(&c->idle_fence); + } + } +} + +void +present_send_config_notify(WindowPtr window, int x, int y, int w, int h, int bw, WindowPtr sibling) +{ + present_window_priv_ptr window_priv = present_window_priv(window); + + if (window_priv) { + xPresentConfigureNotify cn = { + .type = GenericEvent, + .extension = present_request, + .length = (sizeof(xPresentConfigureNotify) - 32) >> 2, + .evtype = PresentConfigureNotify, + .eid = 0, + .window = window->drawable.id, + .x = x, + .y = y, + .width = w, + .height = h, + .off_x = 0, + .off_y = 0, + .pixmap_width = w, + .pixmap_height = h, + .pixmap_flags = 0 + }; + present_event_ptr event; + + for (event = window_priv->events; event; event = event->next) { + if (event->mask & (1 << PresentConfigureNotify)) { + cn.eid = event->id; + WriteEventsToClient(event->client, 1, (xEvent *) &cn); + } + } + } +} + +void +present_send_complete_notify(WindowPtr window, CARD8 kind, CARD8 mode, CARD32 serial, uint64_t ust, uint64_t msc) +{ + present_window_priv_ptr window_priv = present_window_priv(window); + + if (window_priv) { + xPresentCompleteNotify cn = { + .type = GenericEvent, + .extension = present_request, + .length = (sizeof(xPresentCompleteNotify) - 32) >> 2, + .evtype = PresentCompleteNotify, + .kind = kind, + .mode = mode, + .eid = 0, + .window = window->drawable.id, + .serial = serial, + .ust = ust, + .msc = msc, + }; + present_event_ptr event; + + for (event = window_priv->events; event; event = event->next) { + if (event->mask & PresentCompleteNotifyMask) { + cn.eid = event->id; + WriteEventsToClient(event->client, 1, (xEvent *) &cn); + } + } + } +} + +void +present_send_idle_notify(WindowPtr window, CARD32 serial, PixmapPtr pixmap, struct present_fence *idle_fence) +{ + present_window_priv_ptr window_priv = present_window_priv(window); + + if (window_priv) { + xPresentIdleNotify in = { + .type = GenericEvent, + .extension = present_request, + .length = (sizeof(xPresentIdleNotify) - 32) >> 2, + .evtype = PresentIdleNotify, + .eid = 0, + .window = window->drawable.id, + .serial = serial, + .pixmap = pixmap->drawable.id, + .idle_fence = present_fence_id(idle_fence) + }; + present_event_ptr event; + + for (event = window_priv->events; event; event = event->next) { + if (event->mask & PresentIdleNotifyMask) { + in.eid = event->id; + WriteEventsToClient(event->client, 1, (xEvent *) &in); + } + } + } +} + +int +present_select_input(ClientPtr client, XID eid, WindowPtr window, CARD32 mask) +{ + present_window_priv_ptr window_priv = present_get_window_priv(window, mask != 0); + present_event_ptr event; + + if (!window_priv) { + if (mask) + return BadAlloc; + return Success; + } + + event = calloc (1, sizeof (present_event_rec)); + if (!event) + return BadAlloc; + + event->client = client; + event->window = window; + event->id = eid; + event->mask = mask; + + event->next = window_priv->events; + window_priv->events = event; + + if (!AddResource(event->id, present_event_type, (pointer) event)) + return BadAlloc; + + return Success; +} + +Bool +present_event_init(void) +{ + present_event_type = CreateNewResourceType(present_free_event, "PresentEvent"); + if (!present_event_type) + return FALSE; + + GERegisterExtension(present_request, present_event_swap); + return TRUE; +} diff --git a/xorg-server/present/present_fake.c b/xorg-server/present/present_fake.c new file mode 100644 index 000000000..a67759254 --- /dev/null +++ b/xorg-server/present/present_fake.c @@ -0,0 +1,140 @@ +/* + * Copyright © 2013 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include "present_priv.h" +#include "list.h" + +static struct xorg_list fake_vblank_queue; + +typedef struct present_fake_vblank { + struct xorg_list list; + uint64_t event_id; + OsTimerPtr timer; + ScreenPtr screen; +} present_fake_vblank_rec, *present_fake_vblank_ptr; + +int +present_fake_get_ust_msc(ScreenPtr screen, uint64_t *ust, uint64_t *msc) +{ + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + + *ust = GetTimeInMicros(); + *msc = *ust / screen_priv->fake_interval; + return Success; +} + +static void +present_fake_notify(ScreenPtr screen, uint64_t event_id) +{ + uint64_t ust, msc; + + present_fake_get_ust_msc(screen, &ust, &msc); + present_event_notify(event_id, ust, msc); +} + +static CARD32 +present_fake_do_timer(OsTimerPtr timer, + CARD32 time, + pointer arg) +{ + present_fake_vblank_ptr fake_vblank = arg; + + present_fake_notify(fake_vblank->screen, fake_vblank->event_id); + xorg_list_del(&fake_vblank->list); + free(fake_vblank); + return 0; +} + +void +present_fake_abort_vblank(ScreenPtr screen, uint64_t event_id, uint64_t msc) +{ + present_fake_vblank_ptr fake_vblank, tmp; + + xorg_list_for_each_entry_safe(fake_vblank, tmp, &fake_vblank_queue, list) { + if (fake_vblank->event_id == event_id) { + TimerCancel(fake_vblank->timer); + xorg_list_del(&fake_vblank->list); + free (fake_vblank); + break; + } + } +} + +int +present_fake_queue_vblank(ScreenPtr screen, + uint64_t event_id, + uint64_t msc) +{ + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + uint64_t ust = msc * screen_priv->fake_interval; + uint64_t now = GetTimeInMicros(); + INT32 delay = ((int64_t) (ust - now)) / 1000; + present_fake_vblank_ptr fake_vblank; + + if (delay <= 0) { + present_fake_notify(screen, event_id); + return Success; + } + + fake_vblank = calloc (1, sizeof (present_fake_vblank_rec)); + if (!fake_vblank) + return BadAlloc; + + fake_vblank->screen = screen; + fake_vblank->event_id = event_id; + fake_vblank->timer = TimerSet(NULL, 0, delay, present_fake_do_timer, fake_vblank); + if (!fake_vblank->timer) { + free(fake_vblank); + return BadAlloc; + } + + xorg_list_add(&fake_vblank->list, &fake_vblank_queue); + + return Success; +} + +void +present_fake_screen_init(ScreenPtr screen) +{ + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + + /* For screens with hardware vblank support, the fake code + * will be used for off-screen windows and while screens are blanked, + * in which case we want a slow interval here + * + * Otherwise, pretend that the screen runs at 60Hz + */ + if (screen_priv->info && screen_priv->info->get_crtc) + screen_priv->fake_interval = 1000000; + else + screen_priv->fake_interval = 16667; +} + +void +present_fake_queue_init(void) +{ + xorg_list_init(&fake_vblank_queue); +} diff --git a/xorg-server/present/present_fence.c b/xorg-server/present/present_fence.c new file mode 100644 index 000000000..db5efcaad --- /dev/null +++ b/xorg-server/present/present_fence.c @@ -0,0 +1,112 @@ +/* + * Copyright © 2013 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include "present_priv.h" +#include <gcstruct.h> +#include <misync.h> +#include <misyncstr.h> + +/* + * Wraps SyncFence objects so we can add a SyncTrigger to find out + * when the SyncFence gets destroyed and clean up appropriately + */ + +struct present_fence { + SyncTrigger trigger; + SyncFence *fence; +}; + +/* + * SyncTrigger callbacks + */ +static Bool +present_fence_sync_check_trigger(SyncTrigger *trigger, XSyncValue oldval) +{ + return FALSE; +} + +static void +present_fence_sync_trigger_fired(SyncTrigger *trigger) +{ +} + +static void +present_fence_sync_counter_destroyed(SyncTrigger *trigger) +{ + struct present_fence *present_fence = container_of(trigger, struct present_fence, trigger); + + present_fence->fence = NULL; +} + +struct present_fence * +present_fence_create(SyncFence *fence) +{ + struct present_fence *present_fence; + + present_fence = calloc (1, sizeof (struct present_fence)); + if (!present_fence) + return NULL; + + present_fence->fence = fence; + present_fence->trigger.pSync = (SyncObject *) fence; + present_fence->trigger.CheckTrigger = present_fence_sync_check_trigger; + present_fence->trigger.TriggerFired = present_fence_sync_trigger_fired; + present_fence->trigger.CounterDestroyed = present_fence_sync_counter_destroyed; + + if (SyncAddTriggerToSyncObject(&present_fence->trigger) != Success) { + free (present_fence); + return NULL; + } + return present_fence; +} + +void +present_fence_destroy(struct present_fence *present_fence) +{ + if (present_fence) { + if (present_fence->fence) + SyncDeleteTriggerFromSyncObject(&present_fence->trigger); + free(present_fence); + } +} + +void +present_fence_set_triggered(struct present_fence *present_fence) +{ + if (present_fence) + if (present_fence->fence) + (*present_fence->fence->funcs.SetTriggered) (present_fence->fence); +} + +XID +present_fence_id(struct present_fence *present_fence) +{ + if (!present_fence) + return None; + if (!present_fence->fence) + return None; + return present_fence->fence->sync.id; +} diff --git a/xorg-server/present/present_notify.c b/xorg-server/present/present_notify.c new file mode 100644 index 000000000..e272e08dc --- /dev/null +++ b/xorg-server/present/present_notify.c @@ -0,0 +1,114 @@ +/* + * Copyright © 2013 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include "present_priv.h" + +/* + * Mark all pending notifies for 'window' as invalid when + * the window is destroyed + */ + +void +present_clear_window_notifies(WindowPtr window) +{ + present_notify_ptr notify; + present_window_priv_ptr window_priv = present_window_priv(window); + + if (!window_priv) + return; + + xorg_list_for_each_entry(notify, &window_priv->notifies, window_list) { + notify->window = NULL; + } +} + +/* + * 'notify' is being freed; remove it from the window's notify list + */ + +void +present_free_window_notify(present_notify_ptr notify) +{ + xorg_list_del(¬ify->window_list); +} + +/* + * 'notify' is new; add it to the specified window + */ + +int +present_add_window_notify(present_notify_ptr notify) +{ + WindowPtr window = notify->window; + present_window_priv_ptr window_priv = present_get_window_priv(window, TRUE); + + if (!window_priv) + return BadAlloc; + + xorg_list_add(¬ify->window_list, &window_priv->notifies); + return Success; +} + +int +present_create_notifies(ClientPtr client, int num_notifies, xPresentNotify *x_notifies, present_notify_ptr *p_notifies) +{ + present_notify_ptr notifies; + int i; + int added = 0; + int status; + + notifies = calloc (num_notifies, sizeof (present_notify_rec)); + if (!notifies) + return BadAlloc; + + for (i = 0; i < num_notifies; i++) { + status = dixLookupWindow(¬ifies[i].window, x_notifies[i].window, client, DixGetAttrAccess); + if (status != Success) + goto bail; + + notifies[i].serial = x_notifies[i].serial; + status = present_add_window_notify(¬ifies[i]); + if (status != Success) + goto bail; + + added = i; + } + return Success; + +bail: + present_destroy_notifies(notifies, added); + return status; +} + +void +present_destroy_notifies(present_notify_ptr notifies, int num_notifies) +{ + int i; + for (i = 0; i < num_notifies; i++) + present_free_window_notify(¬ifies[i]); + + free(notifies); +} diff --git a/xorg-server/present/present_priv.h b/xorg-server/present/present_priv.h new file mode 100644 index 000000000..a92b62a2d --- /dev/null +++ b/xorg-server/present/present_priv.h @@ -0,0 +1,288 @@ +/* + * Copyright © 2013 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifndef _PRESENT_PRIV_H_ +#define _PRESENT_PRIV_H_ + +#include <X11/X.h> +#include "scrnintstr.h" +#include "misc.h" +#include "list.h" +#include "windowstr.h" +#include "dixstruct.h" +#include "present.h" +#include <syncsdk.h> +#include <syncsrv.h> +#include <xfixes.h> +#include <randrstr.h> + +extern int present_request; + +extern DevPrivateKeyRec present_screen_private_key; + +typedef struct present_fence *present_fence_ptr; + +typedef struct present_notify present_notify_rec, *present_notify_ptr; + +struct present_notify { + struct xorg_list window_list; + WindowPtr window; + CARD32 serial; +}; + +struct present_vblank { + struct xorg_list window_list; + struct xorg_list event_queue; + ScreenPtr screen; + WindowPtr window; + PixmapPtr pixmap; + RegionPtr valid; + RegionPtr update; + RRCrtcPtr crtc; + uint32_t serial; + int16_t x_off; + int16_t y_off; + CARD16 kind; + uint64_t event_id; + uint64_t target_msc; + uint64_t msc_offset; + present_fence_ptr idle_fence; + present_fence_ptr wait_fence; + present_notify_ptr notifies; + int num_notifies; + Bool flip; + Bool sync_flip; + Bool abort_flip; + + Bool window_destroyed; +}; + +typedef struct present_screen_priv { + CloseScreenProcPtr CloseScreen; + ConfigNotifyProcPtr ConfigNotify; + DestroyWindowProcPtr DestroyWindow; + ClipNotifyProcPtr ClipNotify; + + present_vblank_ptr flip_pending; + uint64_t unflip_event_id; + + uint32_t fake_interval; + + /* Currently active flipped pixmap and fence */ + RRCrtcPtr flip_crtc; + WindowPtr flip_window; + uint32_t flip_serial; + PixmapPtr flip_pixmap; + present_fence_ptr flip_idle_fence; + + present_screen_info_ptr info; +} present_screen_priv_rec, *present_screen_priv_ptr; + +#define wrap(priv,real,mem,func) {\ + priv->mem = real->mem; \ + real->mem = func; \ +} + +#define unwrap(priv,real,mem) {\ + real->mem = priv->mem; \ +} + +static inline present_screen_priv_ptr +present_screen_priv(ScreenPtr screen) +{ + return (present_screen_priv_ptr)dixLookupPrivate(&(screen)->devPrivates, &present_screen_private_key); +} + +/* + * Each window has a list of clients and event masks + */ +typedef struct present_event *present_event_ptr; + +typedef struct present_event { + present_event_ptr next; + ClientPtr client; + WindowPtr window; + XID id; + int mask; +} present_event_rec; + +typedef struct present_window_priv { + present_event_ptr events; + RRCrtcPtr crtc; /* Last reported CRTC from get_ust_msc */ + uint64_t msc_offset; + uint64_t msc; /* Last reported MSC from the current crtc */ + struct xorg_list vblank; + struct xorg_list notifies; +} present_window_priv_rec, *present_window_priv_ptr; + +extern DevPrivateKeyRec present_window_private_key; + +static inline present_window_priv_ptr +present_window_priv(WindowPtr window) +{ + return (present_window_priv_ptr)dixGetPrivate(&(window)->devPrivates, &present_window_private_key); +} + +present_window_priv_ptr +present_get_window_priv(WindowPtr window, Bool create); + +extern RESTYPE present_event_type; + +/* + * present.c + */ +int +present_pixmap(WindowPtr window, + PixmapPtr pixmap, + CARD32 serial, + RegionPtr valid, + RegionPtr update, + int16_t x_off, + int16_t y_off, + RRCrtcPtr target_crtc, + SyncFence *wait_fence, + SyncFence *idle_fence, + uint32_t options, + uint64_t target_msc, + uint64_t divisor, + uint64_t remainder, + present_notify_ptr notifies, + int num_notifies); + +int +present_notify_msc(WindowPtr window, + CARD32 serial, + uint64_t target_msc, + uint64_t divisor, + uint64_t remainder); + +void +present_abort_vblank(ScreenPtr screen, RRCrtcPtr crtc, uint64_t event_id, uint64_t msc); + +void +present_vblank_destroy(present_vblank_ptr vblank); + +void +present_flip_destroy(ScreenPtr screen); + +void +present_check_flip_window(WindowPtr window); + +RRCrtcPtr +present_get_crtc(WindowPtr window); + +uint32_t +present_query_capabilities(RRCrtcPtr crtc); + +Bool +present_init(void); + +/* + * present_event.c + */ + +void +present_free_events(WindowPtr window); + +void +present_send_config_notify(WindowPtr window, int x, int y, int w, int h, int bw, WindowPtr sibling); + +void +present_send_complete_notify(WindowPtr window, CARD8 kind, CARD8 mode, CARD32 serial, uint64_t ust, uint64_t msc); + +void +present_send_idle_notify(WindowPtr window, CARD32 serial, PixmapPtr pixmap, present_fence_ptr idle_fence); + +int +present_select_input(ClientPtr client, + CARD32 eid, + WindowPtr window, + CARD32 event_mask); + +Bool +present_event_init(void); + +/* + * present_fake.c + */ +int +present_fake_get_ust_msc(ScreenPtr screen, uint64_t *ust, uint64_t *msc); + +int +present_fake_queue_vblank(ScreenPtr screen, uint64_t event_id, uint64_t msc); + +void +present_fake_abort_vblank(ScreenPtr screen, uint64_t event_id, uint64_t msc); + +void +present_fake_screen_init(ScreenPtr screen); + +void +present_fake_queue_init(void); + +/* + * present_fence.c + */ +struct present_fence * +present_fence_create(SyncFence *sync_fence); + +void +present_fence_destroy(struct present_fence *present_fence); + +void +present_fence_set_triggered(struct present_fence *present_fence); + +XID +present_fence_id(struct present_fence *present_fence); + +/* + * present_notify.c + */ +void +present_clear_window_notifies(WindowPtr window); + +void +present_free_window_notify(present_notify_ptr notify); + +int +present_add_window_notify(present_notify_ptr notify); + +int +present_create_notifies(ClientPtr client, int num_notifies, xPresentNotify *x_notifies, present_notify_ptr *p_notifies); + +void +present_destroy_notifies(present_notify_ptr notifies, int num_notifies); + +/* + * present_request.c + */ +int +proc_present_dispatch(ClientPtr client); + +int +sproc_present_dispatch(ClientPtr client); + +/* + * present_screen.c + */ + +#endif /* _PRESENT_PRIV_H_ */ diff --git a/xorg-server/present/present_request.c b/xorg-server/present/present_request.c new file mode 100644 index 000000000..095fa2daf --- /dev/null +++ b/xorg-server/present/present_request.c @@ -0,0 +1,330 @@ +/* + * Copyright © 2013 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include "present_priv.h" +#include "randrstr.h" + +static int +proc_present_query_version(ClientPtr client) +{ + REQUEST(xPresentQueryVersionReq); + xPresentQueryVersionReply rep = { + .type = X_Reply, + .sequenceNumber = client->sequence, + .length = 0, + .majorVersion = PRESENT_MAJOR, + .minorVersion = PRESENT_MINOR + }; + + REQUEST_SIZE_MATCH(xPresentQueryVersionReq); + (void) stuff; + if (client->swapped) { + swaps(&rep.sequenceNumber); + swapl(&rep.length); + swapl(&rep.majorVersion); + swapl(&rep.minorVersion); + } + WriteToClient(client, sizeof(rep), &rep); + return Success; +} + +#define VERIFY_FENCE_OR_NONE(fence_ptr, fence_id, client, access) do { \ + if ((fence_id) == None) \ + (fence_ptr) = NULL; \ + else { \ + int __rc__ = SyncVerifyFence(&fence_ptr, fence_id, client, access); \ + if (__rc__ != Success) \ + return __rc__; \ + } \ + } while (0) + +#define VERIFY_CRTC_OR_NONE(crtc_ptr, crtc_id, client, access) do { \ + if ((crtc_id) == None) \ + (crtc_ptr) = NULL; \ + else { \ + VERIFY_RR_CRTC(crtc_id, crtc_ptr, access); \ + } \ + } while (0) + +static int +proc_present_pixmap(ClientPtr client) +{ + REQUEST(xPresentPixmapReq); + WindowPtr window; + PixmapPtr pixmap; + RegionPtr valid = NULL; + RegionPtr update = NULL; + SyncFence *wait_fence; + SyncFence *idle_fence; + RRCrtcPtr target_crtc; + int ret; + int nnotifies; + present_notify_ptr notifies = NULL; + + REQUEST_AT_LEAST_SIZE(xPresentPixmapReq); + ret = dixLookupWindow(&window, stuff->window, client, DixWriteAccess); + if (ret != Success) + return ret; + ret = dixLookupResourceByType((pointer *) &pixmap, stuff->pixmap, RT_PIXMAP, client, DixReadAccess); + if (ret != Success) + return ret; + + if (window->drawable.depth != pixmap->drawable.depth) + return BadMatch; + + VERIFY_REGION_OR_NONE(valid, stuff->valid, client, DixReadAccess); + VERIFY_REGION_OR_NONE(update, stuff->update, client, DixReadAccess); + + VERIFY_CRTC_OR_NONE(target_crtc, stuff->target_crtc, client, DixReadAccess); + + VERIFY_FENCE_OR_NONE(wait_fence, stuff->wait_fence, client, DixReadAccess); + VERIFY_FENCE_OR_NONE(idle_fence, stuff->idle_fence, client, DixWriteAccess); + + if (stuff->options & ~(PresentAllOptions)) { + client->errorValue = stuff->options; + return BadValue; + } + + /* + * Check to see if remainder is sane + */ + if (stuff->divisor == 0) { + if (stuff->remainder != 0) { + client->errorValue = (CARD32) stuff->remainder; + return BadValue; + } + } else { + if (stuff->remainder >= stuff->divisor) { + client->errorValue = (CARD32) stuff->remainder; + return BadValue; + } + } + + nnotifies = (client->req_len << 2) - sizeof (xPresentPixmapReq); + if (nnotifies % sizeof (xPresentNotify)) + return BadLength; + + nnotifies /= sizeof (xPresentNotify); + if (nnotifies) { + ret = present_create_notifies(client, nnotifies, (xPresentNotify *) (stuff + 1), ¬ifies); + if (ret != Success) + return ret; + } + + ret = present_pixmap(window, pixmap, stuff->serial, valid, update, + stuff->x_off, stuff->y_off, target_crtc, + wait_fence, idle_fence, stuff->options, + stuff->target_msc, stuff->divisor, stuff->remainder, notifies, nnotifies); + if (ret != Success) + present_destroy_notifies(notifies, nnotifies); + return ret; +} + +static int +proc_present_notify_msc(ClientPtr client) +{ + REQUEST(xPresentNotifyMSCReq); + WindowPtr window; + int rc; + + REQUEST_SIZE_MATCH(xPresentNotifyMSCReq); + rc = dixLookupWindow(&window, stuff->window, client, DixReadAccess); + if (rc != Success) + return rc; + + /* + * Check to see if remainder is sane + */ + if (stuff->divisor == 0) { + if (stuff->remainder != 0) { + client->errorValue = (CARD32) stuff->remainder; + return BadValue; + } + } else { + if (stuff->remainder >= stuff->divisor) { + client->errorValue = (CARD32) stuff->remainder; + return BadValue; + } + } + + return present_notify_msc(window, stuff->serial, + stuff->target_msc, stuff->divisor, stuff->remainder); +} + +static int +proc_present_select_input (ClientPtr client) +{ + REQUEST(xPresentSelectInputReq); + WindowPtr window; + int rc; + + REQUEST_SIZE_MATCH(xPresentSelectInputReq); + + LEGAL_NEW_RESOURCE(stuff->eid, client); + + rc = dixLookupWindow(&window, stuff->window, client, DixGetAttrAccess); + if (rc != Success) + return rc; + + if (stuff->eventMask & ~PresentAllEvents) { + client->errorValue = stuff->eventMask; + return BadValue; + } + return present_select_input(client, stuff->eid, window, stuff->eventMask); +} + +static int +proc_present_query_capabilities (ClientPtr client) +{ + REQUEST(xPresentQueryCapabilitiesReq); + xPresentQueryCapabilitiesReply rep = { + .type = X_Reply, + .sequenceNumber = client->sequence, + .length = 0, + }; + WindowPtr window; + RRCrtcPtr crtc = NULL; + int r; + + r = dixLookupWindow(&window, stuff->target, client, DixGetAttrAccess); + switch (r) { + case Success: + crtc = present_get_crtc(window); + break; + case BadWindow: + VERIFY_RR_CRTC(stuff->target, crtc, DixGetAttrAccess); + break; + default: + return r; + } + + rep.capabilities = present_query_capabilities(crtc); + + if (client->swapped) { + swaps(&rep.sequenceNumber); + swapl(&rep.length); + swapl(&rep.capabilities); + } + WriteToClient(client, sizeof(rep), &rep); + return Success; +} + +int (*proc_present_vector[PresentNumberRequests]) (ClientPtr) = { + proc_present_query_version, /* 0 */ + proc_present_pixmap, /* 1 */ + proc_present_notify_msc, /* 2 */ + proc_present_select_input, /* 3 */ + proc_present_query_capabilities, /* 4 */ +}; + +int +proc_present_dispatch(ClientPtr client) +{ + REQUEST(xReq); + if (stuff->data >= PresentNumberRequests || !proc_present_vector[stuff->data]) + return BadRequest; + return (*proc_present_vector[stuff->data]) (client); +} + +static int +sproc_present_query_version(ClientPtr client) +{ + REQUEST(xPresentQueryVersionReq); + + swaps(&stuff->length); + swapl(&stuff->majorVersion); + swapl(&stuff->minorVersion); + return (*proc_present_vector[stuff->presentReqType]) (client); +} + +static int +sproc_present_pixmap(ClientPtr client) +{ + REQUEST(xPresentPixmapReq); + + swaps(&stuff->length); + swapl(&stuff->window); + swapl(&stuff->pixmap); + swapl(&stuff->valid); + swapl(&stuff->update); + swaps(&stuff->x_off); + swaps(&stuff->y_off); + swapll(&stuff->target_msc); + swapll(&stuff->divisor); + swapll(&stuff->remainder); + swapl(&stuff->idle_fence); + return (*proc_present_vector[stuff->presentReqType]) (client); +} + +static int +sproc_present_notify_msc(ClientPtr client) +{ + REQUEST(xPresentNotifyMSCReq); + + swaps(&stuff->length); + swapl(&stuff->window); + swapll(&stuff->target_msc); + swapll(&stuff->divisor); + swapll(&stuff->remainder); + return (*proc_present_vector[stuff->presentReqType]) (client); +} + +static int +sproc_present_select_input (ClientPtr client) +{ + REQUEST(xPresentSelectInputReq); + + swaps(&stuff->length); + swapl(&stuff->window); + swapl(&stuff->eventMask); + return (*proc_present_vector[stuff->presentReqType]) (client); +} + +static int +sproc_present_query_capabilities (ClientPtr client) +{ + REQUEST(xPresentQueryCapabilitiesReq); + swaps(&stuff->length); + swapl(&stuff->target); + return (*proc_present_vector[stuff->presentReqType]) (client); +} + +int (*sproc_present_vector[PresentNumberRequests]) (ClientPtr) = { + sproc_present_query_version, /* 0 */ + sproc_present_pixmap, /* 1 */ + sproc_present_notify_msc, /* 2 */ + sproc_present_select_input, /* 3 */ + sproc_present_query_capabilities, /* 4 */ +}; + +int +sproc_present_dispatch(ClientPtr client) +{ + REQUEST(xReq); + if (stuff->data >= PresentNumberRequests || !sproc_present_vector[stuff->data]) + return BadRequest; + return (*sproc_present_vector[stuff->data]) (client); +} diff --git a/xorg-server/present/present_screen.c b/xorg-server/present/present_screen.c new file mode 100644 index 000000000..50b2b2d23 --- /dev/null +++ b/xorg-server/present/present_screen.c @@ -0,0 +1,231 @@ +/* + * Copyright © 2013 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#include "present_priv.h" + +int present_request; +DevPrivateKeyRec present_screen_private_key; +DevPrivateKeyRec present_window_private_key; + +/* + * Get a pointer to a present window private, creating if necessary + */ +present_window_priv_ptr +present_get_window_priv(WindowPtr window, Bool create) +{ + present_window_priv_ptr window_priv = present_window_priv(window); + + if (!create || window_priv != NULL) + return window_priv; + window_priv = calloc (1, sizeof (present_window_priv_rec)); + if (!window_priv) + return NULL; + xorg_list_init(&window_priv->vblank); + xorg_list_init(&window_priv->notifies); + dixSetPrivate(&window->devPrivates, &present_window_private_key, window_priv); + return window_priv; +} + +/* + * Hook the close screen function to clean up our screen private + */ +static Bool +present_close_screen(ScreenPtr screen) +{ + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + + present_flip_destroy(screen); + + unwrap(screen_priv, screen, CloseScreen); + (*screen->CloseScreen) (screen); + free(screen_priv); + return TRUE; +} + +/* + * Free any queued presentations for this window + */ +static void +present_free_window_vblank(WindowPtr window) +{ + present_window_priv_ptr window_priv = present_window_priv(window); + present_vblank_ptr vblank, tmp; + + xorg_list_for_each_entry_safe(vblank, tmp, &window_priv->vblank, window_list) { + present_abort_vblank(window->drawable.pScreen, vblank->crtc, vblank->event_id, vblank->target_msc); + present_vblank_destroy(vblank); + } +} + +/* + * Clean up any pending or current flips for this window + */ +static void +present_clear_window_flip(WindowPtr window) +{ + ScreenPtr screen = window->drawable.pScreen; + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + present_vblank_ptr flip_pending = screen_priv->flip_pending; + + if (flip_pending && flip_pending->window == window) { + assert (flip_pending->abort_flip); + flip_pending->window_destroyed = TRUE; + } + if (screen_priv->flip_window == window) + screen_priv->flip_window = NULL; +} + +/* + * Hook the close window function to clean up our window private + */ +static Bool +present_destroy_window(WindowPtr window) +{ + Bool ret; + ScreenPtr screen = window->drawable.pScreen; + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + present_window_priv_ptr window_priv = present_window_priv(window); + + if (window_priv) { + present_clear_window_notifies(window); + present_free_events(window); + present_free_window_vblank(window); + present_clear_window_flip(window); + free(window_priv); + } + unwrap(screen_priv, screen, DestroyWindow); + if (screen->DestroyWindow) + ret = screen->DestroyWindow (window); + else + ret = TRUE; + wrap(screen_priv, screen, DestroyWindow, present_destroy_window); + return ret; +} + +/* + * Hook the config notify screen function to deliver present config notify events + */ +static int +present_config_notify(WindowPtr window, + int x, int y, int w, int h, int bw, + WindowPtr sibling) +{ + int ret; + ScreenPtr screen = window->drawable.pScreen; + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + + present_send_config_notify(window, x, y, w, h, bw, sibling); + + unwrap(screen_priv, screen, ConfigNotify); + if (screen->ConfigNotify) + ret = screen->ConfigNotify (window, x, y, w, h, bw, sibling); + else + ret = 0; + wrap(screen_priv, screen, ConfigNotify, present_config_notify); + return ret; +} + +/* + * Hook the clip notify screen function to un-flip as necessary + */ + +static void +present_clip_notify(WindowPtr window, int dx, int dy) +{ + ScreenPtr screen = window->drawable.pScreen; + present_screen_priv_ptr screen_priv = present_screen_priv(screen); + + present_check_flip_window(window); + unwrap(screen_priv, screen, ClipNotify) + if (screen->ClipNotify) + screen->ClipNotify (window, dx, dy); + wrap(screen_priv, screen, ClipNotify, present_clip_notify); +} + +/* + * Initialize a screen for use with present + */ +int +present_screen_init(ScreenPtr screen, present_screen_info_ptr info) +{ + if (!dixRegisterPrivateKey(&present_screen_private_key, PRIVATE_SCREEN, 0)) + return FALSE; + + if (!dixRegisterPrivateKey(&present_window_private_key, PRIVATE_WINDOW, 0)) + return FALSE; + + if (!present_screen_priv(screen)) { + present_screen_priv_ptr screen_priv = calloc(1, sizeof (present_screen_priv_rec)); + if (!screen_priv) + return FALSE; + + wrap(screen_priv, screen, CloseScreen, present_close_screen); + wrap(screen_priv, screen, DestroyWindow, present_destroy_window); + wrap(screen_priv, screen, ConfigNotify, present_config_notify); + wrap(screen_priv, screen, ClipNotify, present_clip_notify); + + screen_priv->info = info; + + dixSetPrivate(&screen->devPrivates, &present_screen_private_key, screen_priv); + + present_fake_screen_init(screen); + } + + return TRUE; +} + +/* + * Initialize the present extension + */ +void +present_extension_init(void) +{ + ExtensionEntry *extension; + int i; + + extension = AddExtension(PRESENT_NAME, PresentNumberEvents, PresentNumberErrors, + proc_present_dispatch, sproc_present_dispatch, + NULL, StandardMinorOpcode); + if (!extension) + goto bail; + + present_request = extension->base; + + if (!present_init()) + goto bail; + + if (!present_event_init()) + goto bail; + + for (i = 0; i < screenInfo.numScreens; i++) { + if (!present_screen_init(screenInfo.screens[i], NULL)) + goto bail; + } + return; + +bail: + FatalError("Cannot initialize Present extension"); +} diff --git a/xorg-server/present/presentext.h b/xorg-server/present/presentext.h new file mode 100644 index 000000000..f177f55dc --- /dev/null +++ b/xorg-server/present/presentext.h @@ -0,0 +1,29 @@ +/* + * Copyright © 2013 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifndef _PRESENTEXT_H_ +#define _PRESENTEXT_H_ + +extern _X_EXPORT void +present_extension_init(void); + +#endif /* _PRESENTEXT_H_ */ diff --git a/xorg-server/test/Makefile.am b/xorg-server/test/Makefile.am index eff0c9d81..e59c412ee 100644 --- a/xorg-server/test/Makefile.am +++ b/xorg-server/test/Makefile.am @@ -19,7 +19,7 @@ AM_CPPFLAGS += -I$(top_srcdir)/hw/xfree86/parser \ -I$(top_srcdir)/hw/xfree86/ddc \ -I$(top_srcdir)/hw/xfree86/i2c -I$(top_srcdir)/hw/xfree86/modes \ -I$(top_srcdir)/hw/xfree86/ramdac -I$(top_srcdir)/hw/xfree86/dri \ - -I$(top_srcdir)/hw/xfree86/dri2 + -I$(top_srcdir)/hw/xfree86/dri2 -I$(top_srcdir)/dri3 endif TEST_LDADD=libxservertest.la $(XORG_SYS_LIBS) $(XSERVER_SYS_LIBS) $(GLX_SYS_LIBS) @@ -64,6 +64,10 @@ if DRI2 libxservertest_la_LIBADD += $(top_builddir)/hw/xfree86/dri2/libdri2.la endif +if DRI3 +libxservertest_la_LIBADD += $(top_builddir)/dri3/libdri3.la +endif + else nodist_libxservertest_la_SOURCES = \ ddxstubs.c \ @@ -105,6 +109,11 @@ libxservertest_la_LIBADD += \ $(top_builddir)/record/librecord.la endif +if DRI3 +libxservertest_la_LIBADD += \ + $(top_builddir)/dri3/libdri3.la +endif + if XQUARTZ libxservertest_la_LIBADD += \ $(top_builddir)/miext/rootless/librootless.la |