From 4787c5a8db870b0cff2326bd750c4d96c7d84e51 Mon Sep 17 00:00:00 2001 From: marha Date: Tue, 18 May 2010 12:10:10 +0000 Subject: svn merge -r603:HEAD "^/branches/released" . --- xorg-server/configure.ac | 4495 +++++++++-------- xorg-server/dix/colormap.c | 5523 +++++++++++---------- xorg-server/dix/gc.c | 2317 ++++----- xorg-server/hw/xfree86/common/Makefile.am | 1 + xorg-server/hw/xfree86/dri2/dri2.c | 2278 ++++----- xorg-server/hw/xquartz/X11Application.m | 28 +- xorg-server/hw/xquartz/mach-startup/bundle-main.c | 5 + xorg-server/os/log.c | 1241 ++--- 8 files changed, 7958 insertions(+), 7930 deletions(-) diff --git a/xorg-server/configure.ac b/xorg-server/configure.ac index 959ed48a8..1c7875ee3 100644 --- a/xorg-server/configure.ac +++ b/xorg-server/configure.ac @@ -1,2248 +1,2247 @@ -dnl Copyright © 2003-2007 Keith Packard, Daniel Stone -dnl -dnl Permission is hereby granted, free of charge, to any person obtaining a -dnl copy of this software and associated documentation files (the "Software"), -dnl to deal in the Software without restriction, including without limitation -dnl the rights to use, copy, modify, merge, publish, distribute, sublicense, -dnl and/or sell copies of the Software, and to permit persons to whom the -dnl Software is furnished to do so, subject to the following conditions: -dnl -dnl The above copyright notice and this permission notice (including the next -dnl paragraph) shall be included in all copies or substantial portions of the -dnl Software. -dnl -dnl THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -dnl IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -dnl FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -dnl THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -dnl LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -dnl FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -dnl DEALINGS IN THE SOFTWARE. -dnl -dnl Authors: Keith Packard -dnl Daniel Stone -dnl an unwitting cast of miscellaneous others -dnl -dnl Process this file with autoconf to create configure. - -AC_PREREQ(2.57) -AC_INIT([xorg-server], 1.8.99.0, [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], xorg-server) -RELEASE_DATE="unreleased" -AC_CONFIG_SRCDIR([Makefile.am]) -AM_INIT_AUTOMAKE([foreign dist-bzip2]) -AM_MAINTAINER_MODE - -# Require xorg-macros: XORG_DEFAULT_OPTIONS -m4_ifndef([XORG_MACROS_VERSION], - [m4_fatal([must install xorg-macros 1.6 or later before running autoconf/autogen])]) -XORG_MACROS_VERSION(1.6) -XORG_DEFAULT_OPTIONS -XORG_WITH_DOXYGEN(1.6.1) - -m4_ifndef([XORG_FONT_MACROS_VERSION], [m4_fatal([must install fontutil 1.1 or later before running autoconf/autogen])]) -XORG_FONT_MACROS_VERSION(1.1) - -dnl this gets generated by autoheader, and thus contains all the defines. we -dnl don't ever actually use it, internally. -AC_CONFIG_HEADERS(include/do-not-use-config.h) -dnl xorg-server.h is an external header, designed to be included by loadable -dnl drivers. -AC_CONFIG_HEADERS(include/xorg-server.h) -dnl dix-config.h covers most of the DIX (i.e. everything but the DDX, not just -dnl dix/). -AC_CONFIG_HEADERS(include/dix-config.h) -dnl xorg-config.h covers the Xorg DDX. -AC_CONFIG_HEADERS(include/xorg-config.h) -dnl xkb-config.h covers XKB for the Xorg and Xnest DDXs. -AC_CONFIG_HEADERS(include/xkb-config.h) -dnl xwin-config.h covers the XWin DDX. -AC_CONFIG_HEADERS(include/xwin-config.h) -dnl kdrive-config.h covers the kdrive DDX -AC_CONFIG_HEADERS(include/kdrive-config.h) -dnl version-config.h covers the version numbers so they can be bumped without -dnl forcing an entire recompile.x -AC_CONFIG_HEADERS(include/version-config.h) - -AC_PROG_CC -AM_PROG_AS -AC_PROG_INSTALL -AC_PROG_LN_S -AC_LIBTOOL_WIN32_DLL -AC_DISABLE_STATIC -AC_PROG_LIBTOOL -DOLT -AC_PROG_MAKE_SET -PKG_PROG_PKG_CONFIG -AC_PROG_LEX -AC_PROG_YACC -AC_SYS_LARGEFILE -XORG_PROG_RAWCPP -AC_PROG_SED - -# Quoted so that make will expand $(CWARNFLAGS) in makefiles to allow -# easier overrides at build time. -XSERVER_CFLAGS='$(CWARNFLAGS)' - -dnl Check for dtrace program (needed to build Xserver dtrace probes) -dnl Also checks for , since some Linux distros have an -dnl ISDN trace program named dtrace -AC_ARG_WITH(dtrace, AS_HELP_STRING([--with-dtrace=PATH], - [Enable dtrace probes (default: enabled if dtrace found)]), - [WDTRACE=$withval], [WDTRACE=auto]) -if test "x$WDTRACE" = "xyes" -o "x$WDTRACE" = "xauto" ; then - AC_PATH_PROG(DTRACE, [dtrace], [not_found], [$PATH:/usr/sbin]) - if test "x$DTRACE" = "xnot_found" ; then - if test "x$WDTRACE" = "xyes" ; then - AC_MSG_FAILURE([dtrace requested but not found]) - fi - WDTRACE="no" - else - AC_CHECK_HEADER(sys/sdt.h, [HAS_SDT_H="yes"], [HAS_SDT_H="no"]) - if test "x$WDTRACE" = "xauto" -a "x$HAS_SDT_H" = "xno" ; then - WDTRACE="no" - fi - fi -fi -if test "x$WDTRACE" != "xno" ; then - AC_DEFINE(XSERVER_DTRACE, 1, - [Define to 1 if the DTrace Xserver provider probes should be built in.]) - -# Solaris/OpenSolaris require dtrace -G to build dtrace probe information into -# object files, and require linking with those as relocatable objects, not .a -# archives. MacOS X handles all this in the normal compiler toolchain, and on -# some releases (like Tiger), will error out on dtrace -G. For now, other -# platforms with Dtrace ports are assumed to support -G (the FreeBSD and Linux -# ports appear to, based on my web searches, but have not yet been tested). - case $host_os in - darwin*) SPECIAL_DTRACE_OBJECTS=no ;; - *) SPECIAL_DTRACE_OBJECTS=yes ;; - esac -fi -AM_CONDITIONAL(XSERVER_DTRACE, [test "x$WDTRACE" != "xno"]) -AM_CONDITIONAL(SPECIAL_DTRACE_OBJECTS, [test "x$SPECIAL_DTRACE_OBJECTS" = "xyes"]) - -AC_HEADER_DIRENT -AC_HEADER_STDC -AC_CHECK_HEADERS([fcntl.h stdlib.h string.h unistd.h dlfcn.h stropts.h fnmatch.h]) - -dnl Checks for typedefs, structures, and compiler characteristics. -AC_C_CONST -AC_C_BIGENDIAN([ENDIAN="X_BIG_ENDIAN"], [ENDIAN="X_LITTLE_ENDIAN"]) - -AC_CHECK_SIZEOF([unsigned long]) -if test "$ac_cv_sizeof_unsigned_long" = 8; then - AC_DEFINE(_XSERVER64, 1, [Define to 1 if unsigned long is 64 bits.]) -fi - -AC_TYPE_PID_T - -# Checks for headers/macros for byte swapping -# Known variants: -# bswap_16, bswap_32, bswap_64 (glibc) -# __swap16, __swap32, __swap64 (OpenBSD) -# bswap16, bswap32, bswap64 (other BSD's) -# and a fallback to local macros if none of the above are found - -# if is found, assume it's the correct version -AC_CHECK_HEADERS([byteswap.h]) - -# if is found, have to check which version -AC_CHECK_HEADER([sys/endian.h], [HAVE_SYS_ENDIAN_H="yes"], [HAVE_SYS_ENDIAN_H="no"]) - -if test "x$HAVE_SYS_ENDIAN_H" = "xyes" ; then - AC_MSG_CHECKING([for __swap16 variant of byteswapping macros]) - AC_LINK_IFELSE([AC_LANG_PROGRAM([ -#include -#include - ], [ -int a = 1, b; -b = __swap16(a); - ]) -], [SYS_ENDIAN__SWAP='yes'], [SYS_ENDIAN__SWAP='no']) - AC_MSG_RESULT([$SYS_ENDIAN__SWAP]) - - AC_MSG_CHECKING([for bswap16 variant of byteswapping macros]) - AC_LINK_IFELSE([AC_LANG_PROGRAM([ -#include -#include - ], [ -int a = 1, b; -b = bswap16(a); - ]) -], [SYS_ENDIAN_BSWAP='yes'], [SYS_ENDIAN_BSWAP='no']) - AC_MSG_RESULT([$SYS_ENDIAN_BSWAP]) - - if test "$SYS_ENDIAN_BSWAP" = "yes" ; then - USE_SYS_ENDIAN_H=yes - BSWAP=bswap - else - if test "$SYS_ENDIAN__SWAP" = "yes" ; then - USE_SYS_ENDIAN_H=yes - BSWAP=__swap - else - USE_SYS_ENDIAN_H=no - fi - fi - - if test "$USE_SYS_ENDIAN_H" = "yes" ; then - AC_DEFINE([USE_SYS_ENDIAN_H], 1, - [Define to use byteswap macros from ]) - AC_DEFINE_UNQUOTED([bswap_16], ${BSWAP}16, - [Define to 16-bit byteswap macro]) - AC_DEFINE_UNQUOTED([bswap_32], ${BSWAP}32, - [Define to 32-bit byteswap macro]) - AC_DEFINE_UNQUOTED([bswap_64], ${BSWAP}64, - [Define to 64-bit byteswap macro]) - fi -fi - -dnl Check to see if dlopen is in default libraries (like Solaris, which -dnl has it in libc), or if libdl is needed to get it. -AC_CHECK_FUNC([dlopen], [], - AC_CHECK_LIB([dl], [dlopen], DLOPEN_LIBS="-ldl")) -AC_SUBST(DLOPEN_LIBS) - -dnl Checks for library functions. -AC_FUNC_VPRINTF -AC_CHECK_FUNCS([geteuid getuid link memmove memset mkstemp strchr strrchr \ - strtol getopt getopt_long vsnprintf walkcontext backtrace \ - getisax getzoneid shmctl64 strcasestr ffs]) -AC_FUNC_ALLOCA -dnl Old HAS_* names used in os/*.c. -AC_CHECK_FUNC([getdtablesize], - AC_DEFINE(HAS_GETDTABLESIZE, 1, [Have the 'getdtablesize' function.])) -AC_CHECK_FUNC([getifaddrs], - AC_DEFINE(HAS_GETIFADDRS, 1, [Have the 'getifaddrs' function.])) -AC_CHECK_FUNC([getpeereid], - AC_DEFINE(HAS_GETPEEREID, 1, [Have the 'getpeereid' function.])) -AC_CHECK_FUNC([getpeerucred], - AC_DEFINE(HAS_GETPEERUCRED, 1, [Have the 'getpeerucred' function.])) -AC_CHECK_FUNC([strlcat], HAVE_STRLCAT=yes, HAVE_STRLCAT=no) -AM_CONDITIONAL(NEED_STRLCAT, [test x$HAVE_STRLCAT = xno]) -AC_CHECK_FUNC([strlcpy], AC_DEFINE(HAS_STRLCPY, 1, [Have the 'strlcpy' function])) - -AM_CONDITIONAL(NEED_VSNPRINTF, [test x$HAVE_VSNPRINTF = xno]) - -dnl Check for mmap support for Xvfb -AC_CHECK_FUNC([mmap], AC_DEFINE(HAS_MMAP, 1, [Have the 'mmap' function.])) - -dnl Find the math libary -AC_CHECK_LIB(m, sqrt) -AC_CHECK_LIB(m, cbrt, AC_DEFINE(HAVE_CBRT, 1, [Have the 'cbrt' function])) - -AC_CHECK_HEADERS([ndbm.h dbm.h rpcsvc/dbm.h]) - -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]) - -dnl MTRR header -AC_CHECK_HEADERS([asm/mtrr.h], ac_cv_asm_mtrr_h=yes) -if test "x$ac_cv_asm_mtrr_h" = xyes; then - HAVE_MTRR=yes -fi - -dnl BSD MTRR header -AC_CHECK_HEADERS([sys/memrange.h], ac_cv_memrange_h=yes) -if test "x$ac_cv_memrange_h" = xyes; then - HAVE_MTRR=yes -fi - -if test "x$HAVE_MTRR" = xyes; then - AC_DEFINE(HAS_MTRR_SUPPORT, 1, [MTRR support available]) -fi - -dnl A NetBSD MTRR header -AC_CHECK_HEADERS([machine/mtrr.h], ac_cv_machine_mtrr_h=yes) -if test "x$ac_cv_machine_mtrr_h" = xyes; then - AC_DEFINE(HAS_MTRR_BUILTIN, 1, [Define to 1 if NetBSD built-in MTRR - support is available]) -fi - -dnl FreeBSD kldload support (sys/linker.h) -AC_CHECK_HEADERS([sys/linker.h], - [ac_cv_sys_linker_h=yes], - [ac_cv_sys_linker_h=no], - [#include ]) -AM_CONDITIONAL(FREEBSD_KLDLOAD, [test "x$ac_cv_sys_linker_h" = xyes]) - -AC_CACHE_CHECK([for SYSV IPC], - ac_cv_sysv_ipc, - [AC_TRY_LINK([ -#include -#include -#include -],[ -{ - int id; - id = shmget(IPC_PRIVATE, 512, SHM_W | SHM_R); - if (id < 0) return -1; - return shmctl(id, IPC_RMID, 0); -}], - [ac_cv_sysv_ipc=yes], - [ac_cv_sysv_ipc=no])]) -if test "x$ac_cv_sysv_ipc" = xyes; then - AC_DEFINE(HAVE_SYSV_IPC, 1, [Define to 1 if SYSV IPC is available]) -fi - -dnl OpenBSD /dev/xf86 aperture driver -if test -c /dev/xf86 ; then - AC_DEFINE(HAS_APERTURE_DRV, 1, [System has /dev/xf86 aperture driver]) -fi - -dnl BSD APM support -AC_CHECK_HEADER([machine/apmvar.h],[ - AC_CHECK_HEADER([sys/event.h], - ac_cv_BSD_KQUEUE_APM=yes, - ac_cv_BSD_APM=yes)]) - -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) -AC_CHECK_HEADER([execinfo.h],[ - AC_CHECK_LIB(c, backtrace, [ - AC_DEFINE(HAVE_BACKTRACE, 1, [Has backtrace support]) - AC_DEFINE(HAVE_EXECINFO_H, 1, [Have execinfo.h]) - ])] -) - -dnl ARM needs additional compiler flags for proper backtraces if GCC is -dnl used. Compile a dummy program with the -mapcs-frame option. If it -dnl succeeds, we know that we are building for ARM with GCC. -old_CFLAGS="$CFLAGS" -CFLAGS="-mapcs-frame" -AC_COMPILE_IFELSE( - AC_LANG_PROGRAM([[ ]]), - ARM_BACKTRACE_CFLAGS="$CFLAGS", - ARM_BACKTRACE_CFLAGS="" -) -CFLAGS="$old_CFLAGS" -AC_SUBST(ARM_BACKTRACE_CFLAGS) - -dnl --------------------------------------------------------------------------- -dnl Bus options and CPU capabilities. Replaces logic in -dnl hw/xfree86/os-support/bus/Makefile.am, among others. -dnl --------------------------------------------------------------------------- -DEFAULT_INT10="x86emu" - -dnl Override defaults as needed for specific platforms: - -case $host_cpu in - alpha*) - ALPHA_VIDEO=yes - case $host_os in - *freebsd*) SYS_LIBS=-lio ;; - *netbsd*) AC_DEFINE(USE_ALPHA_PIO, 1, [NetBSD PIO alpha IO]) ;; - esac - GLX_ARCH_DEFINES="-D__GLX_ALIGN64 -mieee" - ;; - arm*) - ARM_VIDEO=yes - ;; - i*86) - I386_VIDEO=yes - case $host_os in - *freebsd*) AC_DEFINE(USE_DEV_IO) ;; - *dragonfly*) AC_DEFINE(USE_DEV_IO) ;; - *netbsd*) AC_DEFINE(USE_I386_IOPL) - SYS_LIBS=-li386 - ;; - *openbsd*) AC_DEFINE(USE_I386_IOPL) - SYS_LIBS=-li386 - ;; - esac - ;; - powerpc*) - PPC_VIDEO=yes - case $host_os in - *freebsd*) DEFAULT_INT10=stub ;; - esac - ;; - sparc*) - SPARC64_VIDEO=yes - BSD_ARCH_SOURCES="sparc64_video.c ioperm_noop.c" - GLX_ARCH_DEFINES="-D__GLX_ALIGN64" - ;; - x86_64*|amd64*) - I386_VIDEO=yes - case $host_os in - *freebsd*) AC_DEFINE(USE_DEV_IO, 1, [BSD /dev/io]) ;; - *dragonfly*) AC_DEFINE(USE_DEV_IO, 1, [BSD /dev/io]) ;; - *netbsd*) AC_DEFINE(USE_I386_IOPL, 1, [BSD i386 iopl]) - SYS_LIBS=-lx86_64 - ;; - *openbsd*) AC_DEFINE(USE_AMD64_IOPL, 1, [BSD AMD64 iopl]) - SYS_LIBS=-lamd64 - ;; - esac - GLX_ARCH_DEFINES="-D__GLX_ALIGN64" - ;; - ia64*) - GLX_ARCH_DEFINES="-D__GLX_ALIGN64" - ;; - s390*) - GLX_ARCH_DEFINES="-D__GLX_ALIGN64" - ;; -esac -AC_SUBST(GLX_ARCH_DEFINES) - -dnl BSD *_video.c selection -AM_CONDITIONAL(ALPHA_VIDEO, [test "x$ALPHA_VIDEO" = xyes]) -AM_CONDITIONAL(ARM_VIDEO, [test "x$ARM_VIDEO" = xyes]) -AM_CONDITIONAL(I386_VIDEO, [test "x$I386_VIDEO" = xyes]) -AM_CONDITIONAL(PPC_VIDEO, [test "x$PPC_VIDEO" = xyes]) -AM_CONDITIONAL(SPARC64_VIDEO, [test "x$SPARC64_VIDEO" = xyes]) - -DRI=no -USE_SIGIO_BY_DEFAULT="yes" -dnl it would be nice to autodetect these *CONS_SUPPORTs -case $host_os in - *freebsd* | *dragonfly*) - case $host_os in - kfreebsd*-gnu) ;; - *) AC_DEFINE(CSRG_BASED, 1, [System is BSD-like]) ;; - esac - AC_DEFINE(PCCONS_SUPPORT, 1, [System has PC console]) - AC_DEFINE(PCVT_SUPPORT, 1, [System has PCVT console]) - AC_DEFINE(SYSCONS_SUPPORT, 1, [System has syscons console]) - DRI=yes - ;; - *netbsd*) - AC_DEFINE(CSRG_BASED, 1, [System is BSD-like]) - AC_DEFINE(PCCONS_SUPPORT, 1, [System has PC console]) - AC_DEFINE(PCVT_SUPPORT, 1, [System has PCVT console]) - AC_DEFINE(WSCONS_SUPPORT, 1, [System has wscons console]) - DRI=yes - ;; - *openbsd*) - AC_DEFINE(CSRG_BASED, 1, [System is BSD-like]) - AC_DEFINE(PCVT_SUPPORT, 1, [System has PC console]) - AC_DEFINE(WSCONS_SUPPORT, 1, [System has wscons console]) - ;; - *linux*) - DRI=yes - ;; - *solaris*) - PKG_CHECK_EXISTS(libdrm, DRI=yes, DRI=no) - # Disable use of SIGIO by default until some system bugs are - # fixed - see Sun/OpenSolaris bug id 6879897 - USE_SIGIO_BY_DEFAULT="no" - ;; - darwin*) - AC_DEFINE(CSRG_BASED, 1, [System is BSD-like]) - ;; - cygwin*) - CFLAGS="$CFLAGS -DFD_SETSIZE=256" - ;; -esac - -dnl augment XORG_RELEASE_VERSION for our snapshot number and to expose the -dnl major number -PVMAJOR=`echo $PACKAGE_VERSION | cut -d . -f 1` -PVS=`echo $PACKAGE_VERSION | cut -d . -f 4 | cut -d - -f 1` -if test "x$PVS" = "x"; then - PVS="0" -fi - -VENDOR_RELEASE="((($PVMAJOR) * 10000000) + (($PVM) * 100000) + (($PVP) * 1000) + $PVS)" -VENDOR_MAN_VERSION="Version ${PACKAGE_VERSION}" - -VENDOR_NAME="The X.Org Foundation" -VENDOR_NAME_SHORT="X.Org" -VENDOR_WEB="http://wiki.x.org" - -m4_ifdef([AS_HELP_STRING], , [m4_define([AS_HELP_STRING], m4_defn([AC_HELP_STRING]))]) - -dnl Build options. -AC_ARG_ENABLE(werror, AS_HELP_STRING([--enable-werror], - [Obsolete - use --enable-strict-compilation instead]), - AC_MSG_ERROR([--enable-werror has been replaced by --enable-strict-compilation])) - -AC_ARG_ENABLE(debug, AS_HELP_STRING([--enable-debug], - [Enable debugging (default: disabled)]), - [DEBUGGING=$enableval], [DEBUGGING=no]) -AC_ARG_ENABLE(unit-tests, AS_HELP_STRING([--enable-unit-tests], - [Enable unit-tests (default: auto)]), - [UNITTESTS=$enableval], [UNITTESTS=auto]) -AC_ARG_ENABLE(use-sigio-by-default, AS_HELP_STRING([--enable-use-sigio-by-default] - [Enable SIGIO input handlers by default (default: $USE_SIGIO_BY_DEFAULT)]), - [USE_SIGIO_BY_DEFAULT=$enableval], []) -AC_ARG_WITH(int10, AS_HELP_STRING([--with-int10=BACKEND], [int10 backend: vm86, x86emu or stub]), - [INT10="$withval"], - [INT10="$DEFAULT_INT10"]) -AC_ARG_WITH(vendor-name, AS_HELP_STRING([--with-vendor-name=VENDOR], - [Vendor string reported by the server]), - [ VENDOR_NAME="$withval" ], []) -AC_ARG_WITH(vendor-name-short, AS_HELP_STRING([--with-vendor-name-short=VENDOR], - [Short version of vendor string reported by the server]), - [ VENDOR_NAME_SHORT="$withval" ], []) -AC_ARG_WITH(vendor-web, AS_HELP_STRING([--with-vendor-web=URL], - [Vendor web address reported by the server]), - [ VENDOR_WEB="$withval" ], []) -AC_ARG_WITH(module-dir, AS_HELP_STRING([--with-module-dir=DIR], - [Directory where modules are installed (default: $libdir/xorg/modules)]), - [ moduledir="$withval" ], - [ moduledir="${libdir}/xorg/modules" ]) -AC_ARG_WITH(log-dir, AS_HELP_STRING([--with-log-dir=DIR], - [Directory where log files are kept (default: $localstatedir/log)]), - [ logdir="$withval" ], - [ logdir="$localstatedir/log" ]) -AC_ARG_WITH(builder-addr, AS_HELP_STRING([--with-builder-addr=ADDRESS], - [Builder address (default: xorg@lists.freedesktop.org)]), - [ BUILDERADDR="$withval" ], - [ BUILDERADDR="xorg@lists.freedesktop.org" ]) -AC_ARG_WITH(os-name, AS_HELP_STRING([--with-os-name=OSNAME], [Name of OS (default: output of "uname -srm")]), - [ OSNAME="$withval" ], - [ OSNAME=`uname -srm` ]) -AC_ARG_WITH(os-vendor, AS_HELP_STRING([--with-os-vendor=OSVENDOR], [Name of OS vendor]), - [ OSVENDOR="$withval" ], - [ OSVENDOR="" ]) -AC_ARG_WITH(builderstring, AS_HELP_STRING([--with-builderstring=BUILDERSTRING], [Additional builder string]), - [ BUILDERSTRING="$withval" ] - [ ]) - -dnl Determine font path -XORG_FONTROOTDIR -XORG_FONTSUBDIR(FONTMISCDIR, fontmiscdir, misc) -XORG_FONTSUBDIR(FONTOTFDIR, fontotfdir, OTF) -XORG_FONTSUBDIR(FONTTTFDIR, fontttfdir, TTF) -XORG_FONTSUBDIR(FONTTYPE1DIR, fonttype1dir, Type1) -XORG_FONTSUBDIR(FONT75DPIDIR, font75dpidir, 75dpi) -XORG_FONTSUBDIR(FONT100DPIDIR, font100dpidir, 100dpi) - -dnl Uses --default-font-path if set, otherwise checks for /etc/X11/fontpath.d, -dnl otherwise uses standard subdirectories of FONTROOTDIR. When cross -dnl compiling, assume default font path uses standard FONTROOTDIR directories. -DEFAULT_FONT_PATH="${FONTMISCDIR}/,${FONTTTFDIR}/,${FONTOTFDIR}/,${FONTTYPE1DIR}/,${FONT100DPIDIR}/,${FONT75DPIDIR}/" -if test "$cross_compiling" != yes; then - AC_CHECK_FILE([${sysconfdir}/X11/fontpath.d], - [DEFAULT_FONT_PATH='catalogue:${sysconfdir}/X11/fontpath.d'], - [case $host_os in - darwin*) DEFAULT_FONT_PATH="${DEFAULT_FONT_PATH},/Library/Fonts,/System/Library/Fonts" ;; - esac]) -fi -AC_ARG_WITH(default-font-path, AS_HELP_STRING([--with-default-font-path=PATH], [Comma separated list of font dirs]), - [ FONTPATH="$withval" ], - [ FONTPATH="${DEFAULT_FONT_PATH}" ]) - -AC_MSG_CHECKING([for default font path]) -AC_MSG_RESULT([$FONTPATH]) - -AC_ARG_WITH(xkb-path, AS_HELP_STRING([--with-xkb-path=PATH], [Path to XKB base dir (default: ${datadir}/X11/xkb)]), - [ XKBPATH="$withval" ], - [ XKBPATH="${datadir}/X11/xkb" ]) -AC_ARG_WITH(xkb-output, AS_HELP_STRING([--with-xkb-output=PATH], [Path to XKB output dir (default: ${datadir}/X11/xkb/compiled)]), - [ XKBOUTPUT="$withval" ], - [ XKBOUTPUT="compiled" ]) -AC_ARG_WITH(default-xkb-rules, AS_HELP_STRING([--with-default-xkb-rules=RULES], - [Keyboard ruleset (default: base/evdev)]), - [ XKB_DFLT_RULES="$withval" ], - [ XKB_DFLT_RULES="" ]) -AC_ARG_WITH(default-xkb-model, AS_HELP_STRING([--with-default-xkb-model=MODEL], - [Keyboard model (default: pc105)]), - [ XKB_DFLT_MODEL="$withval" ], - [ XKB_DFLT_MODEL="pc105" ]) -AC_ARG_WITH(default-xkb-layout, AS_HELP_STRING([--with-default-xkb-layout=LAYOUT], - [Keyboard layout (default: us)]), - [ XKB_DFLT_LAYOUT="$withval" ], - [ XKB_DFLT_LAYOUT="us" ]) -AC_ARG_WITH(default-xkb-variant, AS_HELP_STRING([--with-default-xkb-variant=VARIANT], - [Keyboard variant (default: (none))]), - [ XKB_DFLT_VARIANT="$withval" ], - [ XKB_DFLT_VARIANT="" ]) -AC_ARG_WITH(default-xkb-options, AS_HELP_STRING([--with-default-xkb-options=OPTIONS], - [Keyboard layout options (default: (none))]), - [ XKB_DFLT_OPTIONS="$withval" ], - [ XKB_DFLT_OPTIONS="" ]) -AC_ARG_WITH(serverconfig-path, AS_HELP_STRING([--with-serverconfig-path=PATH], - [Directory where ancillary server config files are installed (default: ${libdir}/xorg)]), - [ SERVERCONFIG="$withval" ], - [ SERVERCONFIG="${libdir}/xorg" ]) -AC_ARG_WITH(apple-applications-dir,AS_HELP_STRING([--with-apple-applications-dir=PATH], [Path to the Applications directory (default: /Applications/Utilities)]), - [ APPLE_APPLICATIONS_DIR="${withval}" ], - [ APPLE_APPLICATIONS_DIR="/Applications/Utilities" ]) -AC_SUBST([APPLE_APPLICATIONS_DIR]) -AC_ARG_WITH(apple-application-name,AS_HELP_STRING([--with-apple-application-name=NAME], [Name for the .app (default: X11)]), - [ APPLE_APPLICATION_NAME="${withval}" ], - [ APPLE_APPLICATION_NAME="X11" ]) -AC_SUBST([APPLE_APPLICATION_NAME]) -AC_ARG_WITH(launchd-id-prefix, AS_HELP_STRING([--with-launchd-id-prefix=PATH], [Prefix to use for launchd identifiers (default: org.x)]), - [ LAUNCHD_ID_PREFIX="${withval}" ], - [ LAUNCHD_ID_PREFIX="org.x" ]) -AC_SUBST([LAUNCHD_ID_PREFIX]) -AC_DEFINE_UNQUOTED(LAUNCHD_ID_PREFIX, "$LAUNCHD_ID_PREFIX", [Prefix to use for launchd identifiers]) -AC_ARG_ENABLE(sparkle,AS_HELP_STRING([--enable-sparkle], [Enable updating of X11.app using the Sparkle Framework (default: disabled)]), - [ XQUARTZ_SPARKLE="${enableval}" ], - [ XQUARTZ_SPARKLE="no" ]) -AC_SUBST([XQUARTZ_SPARKLE]) -AC_ARG_ENABLE(builddocs, AS_HELP_STRING([--enable-builddocs], [Build docs (default: disabled)]), - [BUILDDOCS=$enableval], - [BUILDDOCS=no]) -AC_ARG_ENABLE(install-libxf86config, - AS_HELP_STRING([--enable-install-libxf86config], - [Install libxf86config (default: disabled)]), - [INSTALL_LIBXF86CONFIG=$enableval], - [INSTALL_LIBXF86CONFIG=no]) -AC_ARG_ENABLE(visibility, AC_HELP_STRING([--enable-visibility], [Enable symbol visibility (default: auto)]), - [SYMBOL_VISIBILITY=$enableval], - [SYMBOL_VISIBILITY=auto]) -AC_ARG_ENABLE(pc98, AC_HELP_STRING([--enable-pc98], [Enable PC98 support in Xorg (default: auto)]), - [SUPPORT_PC98=$enableval], - [SUPPORT_PC98=auto]) - -dnl GLX build options -AC_ARG_WITH(dri-driver-path, AS_HELP_STRING([--with-dri-driver-path=PATH], [Path to DRI drivers (default: ${libdir}/dri)]), - [ DRI_DRIVER_PATH="$withval" ], - [ DRI_DRIVER_PATH="${libdir}/dri" ]) -AC_ARG_ENABLE(aiglx, AS_HELP_STRING([--enable-aiglx], [Build accelerated indirect GLX (default: enabled)]), - [AIGLX=$enableval], - [AIGLX=yes]) -AC_ARG_ENABLE(glx-tls, AS_HELP_STRING([--enable-glx-tls], [Build GLX with TLS support (default: disabled)]), - [GLX_USE_TLS=$enableval], - [GLX_USE_TLS=no]) - -dnl Extensions. -AC_ARG_ENABLE(registry, AS_HELP_STRING([--disable-registry], [Build string registry module (default: enabled)]), [XREGISTRY=$enableval], [XREGISTRY=yes]) -AC_ARG_ENABLE(composite, AS_HELP_STRING([--disable-composite], [Build Composite extension (default: enabled)]), [COMPOSITE=$enableval], [COMPOSITE=yes]) -AC_ARG_ENABLE(mitshm, AS_HELP_STRING([--disable-shm], [Build SHM extension (default: enabled)]), [MITSHM=$enableval], [MITSHM=yes]) -AC_ARG_ENABLE(xres, AS_HELP_STRING([--disable-xres], [Build XRes extension (default: enabled)]), [RES=$enableval], [RES=yes]) -AC_ARG_ENABLE(record, AS_HELP_STRING([--disable-record], [Build Record extension (default: enabled)]), [RECORD=$enableval], [RECORD=yes]) -AC_ARG_ENABLE(xv, AS_HELP_STRING([--disable-xv], [Build Xv extension (default: enabled)]), [XV=$enableval], [XV=yes]) -AC_ARG_ENABLE(xvmc, AS_HELP_STRING([--disable-xvmc], [Build XvMC extension (default: enabled)]), [XVMC=$enableval], [XVMC=yes]) -AC_ARG_ENABLE(dga, AS_HELP_STRING([--disable-dga], [Build DGA extension (default: auto)]), [DGA=$enableval], [DGA=auto]) -AC_ARG_ENABLE(screensaver, AS_HELP_STRING([--disable-screensaver], [Build ScreenSaver extension (default: enabled)]), [SCREENSAVER=$enableval], [SCREENSAVER=yes]) -AC_ARG_ENABLE(xdmcp, AS_HELP_STRING([--disable-xdmcp], [Build XDMCP extension (default: auto)]), [XDMCP=$enableval], [XDMCP=auto]) -AC_ARG_ENABLE(xdm-auth-1, AS_HELP_STRING([--disable-xdm-auth-1], [Build XDM-Auth-1 extension (default: auto)]), [XDMAUTH=$enableval], [XDMAUTH=auto]) -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(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]) -AC_ARG_ENABLE(xselinux, AS_HELP_STRING([--enable-xselinux], [Build SELinux extension (default: disabled)]), [XSELINUX=$enableval], [XSELINUX=no]) -AC_ARG_ENABLE(xcsecurity, AS_HELP_STRING([--enable-xcsecurity], [Build Security extension (default: disabled)]), [XCSECURITY=$enableval], [XCSECURITY=no]) -AC_ARG_ENABLE(xcalibrate, AS_HELP_STRING([--enable-xcalibrate], [Build XCalibrate extension (default: disabled)]), [XCALIBRATE=$enableval], [XCALIBRATE=no]) -AC_ARG_ENABLE(tslib, AS_HELP_STRING([--enable-tslib], [Build kdrive tslib touchscreen support (default: disabled)]), [TSLIB=$enableval], [TSLIB=no]) -AC_ARG_ENABLE(dbe, AS_HELP_STRING([--disable-dbe], [Build DBE extension (default: enabled)]), [DBE=$enableval], [DBE=yes]) -AC_ARG_ENABLE(xf86bigfont, AS_HELP_STRING([--enable-xf86bigfont], [Build XF86 Big Font extension (default: disabled)]), [XF86BIGFONT=$enableval], [XF86BIGFONT=no]) -AC_ARG_ENABLE(dpms, AS_HELP_STRING([--disable-dpms], [Build DPMS extension (default: enabled)]), [DPMSExtension=$enableval], [DPMSExtension=yes]) -AC_ARG_ENABLE(config-udev, AS_HELP_STRING([--enable-config-udev], [Build udev support (default: auto)]), [CONFIG_UDEV=$enableval], [CONFIG_UDEV=auto]) -AC_ARG_ENABLE(config-dbus, AS_HELP_STRING([--enable-config-dbus], [Build D-BUS API support (default: no)]), [CONFIG_DBUS_API=$enableval], [CONFIG_DBUS_API=no]) -AC_ARG_ENABLE(config-hal, AS_HELP_STRING([--disable-config-hal], [Build HAL support (default: auto)]), [CONFIG_HAL=$enableval], [CONFIG_HAL=auto]) -AC_ARG_ENABLE(xfree86-utils, AS_HELP_STRING([--enable-xfree86-utils], [Build xfree86 DDX utilities (default: enabled)]), [XF86UTILS=$enableval], [XF86UTILS=yes]) -AC_ARG_ENABLE(xaa, AS_HELP_STRING([--enable-xaa], [Build XAA (default: enabled)]), [XAA=$enableval], [XAA=yes]) -AC_ARG_ENABLE(vgahw, AS_HELP_STRING([--enable-vgahw], [Build Xorg with vga access (default: enabled)]), [VGAHW=$enableval], [VGAHW=yes]) -AC_ARG_ENABLE(vbe, AS_HELP_STRING([--enable-vbe], [Build Xorg with VBE module (default: enabled)]), [VBE=$enableval], [VBE=yes]) -AC_ARG_ENABLE(int10-module, AS_HELP_STRING([--enable-int10-module], [Build Xorg with int10 module (default: enabled)]), [INT10MODULE=$enableval], [INT10MODULE=yes]) -AC_ARG_ENABLE(windowswm, AS_HELP_STRING([--enable-windowswm], [Build XWin with WindowsWM extension (default: no)]), [WINDOWSWM=$enableval], [WINDOWSWM=no]) - -dnl DDXes. -AC_ARG_ENABLE(xorg, AS_HELP_STRING([--enable-xorg], [Build Xorg server (default: auto)]), [XORG=$enableval], [XORG=auto]) -AC_ARG_ENABLE(dmx, AS_HELP_STRING([--enable-dmx], [Build DMX server (default: auto)]), [DMX=$enableval], [DMX=auto]) -AC_ARG_ENABLE(xvfb, AS_HELP_STRING([--enable-xvfb], [Build Xvfb server (default: yes)]), [XVFB=$enableval], [XVFB=yes]) -AC_ARG_ENABLE(xnest, AS_HELP_STRING([--enable-xnest], [Build Xnest server (default: auto)]), [XNEST=$enableval], [XNEST=auto]) -AC_ARG_ENABLE(xquartz, AS_HELP_STRING([--enable-xquartz], [Build Xquartz server for OS-X (default: auto)]), [XQUARTZ=$enableval], [XQUARTZ=auto]) -AC_ARG_ENABLE(standalone-xpbproxy, AS_HELP_STRING([--enable-standalone-xpbproxy], [Build a standalone xpbproxy (in addition to the one integrated into Xquartz as a separate thread) (default: no)]), [STANDALONE_XPBPROXY=$enableval], [STANDALONE_XPBPROXY=no]) -AC_ARG_ENABLE(xwin, AS_HELP_STRING([--enable-xwin], [Build XWin server (default: auto)]), [XWIN=$enableval], [XWIN=auto]) -dnl kdrive and its subsystems -AC_ARG_ENABLE(kdrive, AS_HELP_STRING([--enable-kdrive], [Build kdrive servers (default: no)]), [KDRIVE=$enableval], [KDRIVE=no]) -AC_ARG_ENABLE(xephyr, AS_HELP_STRING([--enable-xephyr], [Build the kdrive Xephyr server (default: auto)]), [XEPHYR=$enableval], [XEPHYR=auto]) -AC_ARG_ENABLE(xfake, AS_HELP_STRING([--enable-xfake], [Build the kdrive 'fake' server (default: auto)]), [XFAKE=$enableval], [XFAKE=auto]) -AC_ARG_ENABLE(xfbdev, AS_HELP_STRING([--enable-xfbdev], [Build the kdrive framebuffer device server (default: auto)]), [XFBDEV=$enableval], [XFBDEV=auto]) -dnl kdrive options -AC_ARG_ENABLE(kdrive-kbd, AS_HELP_STRING([--enable-kdrive-kbd], [Build kbd driver for kdrive (default: auto)]), [KDRIVE_KBD=$enableval], [KDRIVE_KBD=auto]) -AC_ARG_ENABLE(kdrive-mouse, AC_HELP_STRING([--enable-kdrive-mouse], [Build mouse driver for kdrive (default: auto)]), [KDRIVE_MOUSE=$enableval], [KDRIVE_MOUSE=auto]) -AC_ARG_ENABLE(kdrive-evdev, AC_HELP_STRING([--enable-kdrive-evdev], [Build evdev driver for kdrive (default: auto)]), [KDRIVE_EVDEV=$enableval], [KDRIVE_EVDEV=auto]) - - -dnl chown/chmod to be setuid root as part of build -dnl Replaces InstallXserverSetUID in imake -AC_ARG_ENABLE(install-setuid, - AS_HELP_STRING([--enable-install-setuid], - [Install Xorg server as owned by root with setuid bit (default: auto)]), - [SETUID=$enableval], [SETUID=auto]) -AC_MSG_CHECKING([to see if we can install the Xorg server as root]) -if test "x$SETUID" = "xauto" ; then - case $host_os in - cygwin*) SETUID="no" ;; - darwin*) SETUID="no" ;; - *) - case $host_cpu in - sparc) SETUID="no" ;; - *) SETUID="yes" ;; - esac - esac - if test "x$SETUID" = xyes; then - touch testfile - chown root testfile > /dev/null 2>&1 || SETUID="no" - rm -f testfile - fi -fi -AC_MSG_RESULT([$SETUID]) -AM_CONDITIONAL(INSTALL_SETUID, [test "x$SETUID" = "xyes"]) - -dnl Issue an error if xtrans.m4 was not found and XTRANS_CONNECTION_FLAGS macro -dnl was not expanded, since xorg-server with no transport types is rather useless. -dnl -dnl If you're seeing an error here, be sure you installed the lib/xtrans module -dnl first and if it's not in the default location, that you set the ACLOCAL -dnl environment variable to find it, such as: -dnl ACLOCAL="aclocal -I ${PREFIX}/share/aclocal" -m4_pattern_forbid([^XTRANS_CONNECTION_FLAGS$]) - -# Transport selection macro from xtrans.m4 -XTRANS_CONNECTION_FLAGS - -# Secure RPC detection macro from xtrans.m4 -XTRANS_SECURE_RPC_FLAGS -AM_CONDITIONAL(SECURE_RPC, [test "x$SECURE_RPC" = xyes]) - -AM_CONDITIONAL(INT10_VM86, [test "x$INT10" = xvm86]) -AM_CONDITIONAL(INT10_X86EMU, [test "x$INT10" = xx86emu]) -AM_CONDITIONAL(INT10_STUB, [test "x$INT10" = xstub]) -if test "x$INT10" = xyes; then - dnl VM86 headers - AC_CHECK_HEADERS([sys/vm86.h sys/io.h]) -fi - -dnl Handle building documentation -AM_CONDITIONAL(BUILDDOCS, test "x$BUILDDOCS" = xyes) - -dnl Only build sgml docs when linuxdoc is available and -dnl def.ents has been installed -XORG_CHECK_LINUXDOC - -dnl Handle installing libxf86config -AM_CONDITIONAL(INSTALL_LIBXF86CONFIG, [test "x$INSTALL_LIBXF86CONFIG" = xyes]) - -dnl DDX Detection... Yes, it's ugly to have it here... but we need to -dnl handle this early on so that we don't require unsupported extensions -case $host_os in - cygwin*) - DGA=no - DRI2=no - XF86VIDMODE=no - XSELINUX=no - XV=no - ;; - darwin*) - DRI2=no - - if test x$XQUARTZ = xauto; then - AC_CACHE_CHECK([whether to build Xquartz],xorg_cv_Carbon_framework,[ - save_LDFLAGS=$LDFLAGS - LDFLAGS="$LDFLAGS -framework Carbon" - AC_LINK_IFELSE([char FSFindFolder(); int main() { FSFindFolder(); return 0;}], - [xorg_cv_Carbon_framework=yes], - [xorg_cv_Carbon_framework=no]) - LDFLAGS=$save_LDFLAGS]) - - if test "X$xorg_cv_Carbon_framework" = Xyes; then - XQUARTZ=yes - else - XQUARTZ=no - fi - fi - - if test "x$XQUARTZ" = xyes ; then - XQUARTZ=yes - XVFB=no - XNEST=no - - COMPOSITE=no - DGA=no - DPMSExtension=no - XF86VIDMODE=no - fi - ;; - *) XQUARTZ=no ;; -esac - -dnl --------------------------------------------------------------------------- -dnl Extension section -dnl --------------------------------------------------------------------------- -XEXT_INC='-I$(top_srcdir)/Xext' -XEXT_LIB='$(top_builddir)/Xext/libXext.la' -XEXTXORG_LIB='$(top_builddir)/Xext/libXextbuiltin.la' - -dnl Optional modules -VIDEOPROTO="videoproto" -COMPOSITEPROTO="compositeproto >= 0.4" -RECORDPROTO="recordproto >= 1.13.99.1" -SCRNSAVERPROTO="scrnsaverproto >= 1.1" -RESOURCEPROTO="resourceproto" -DRIPROTO="xf86driproto >= 2.1.0" -DRI2PROTO="dri2proto >= 2.3" -XINERAMAPROTO="xineramaproto" -BIGFONTPROTO="xf86bigfontproto >= 1.2.0" -XCALIBRATEPROTO="xcalibrateproto" -DGAPROTO="xf86dgaproto >= 2.0.99.1" -GLPROTO="glproto >= 1.4.10" -DMXPROTO="dmxproto >= 2.2.99.1" -VIDMODEPROTO="xf86vidmodeproto >= 2.2.99.1" -WINDOWSWMPROTO="windowswmproto" -APPLEWMPROTO="applewmproto >= 1.4" - -dnl Core modules for most extensions, et al. -REQUIRED_MODULES="[randrproto >= 1.2.99.3] [renderproto >= 0.11] [fixesproto >= 4.1] [damageproto >= 1.1] [xcmiscproto >= 1.2.0] [xextproto >= 7.0.99.3] [xproto >= 7.0.13] [xtrans >= 1.2.2] [bigreqsproto >= 1.1.0] fontsproto [inputproto >= 1.9.99.902] [kbproto >= 1.0.3]" -REQUIRED_LIBS="xfont xau [pixman-1 >= 0.15.20]" - -dnl List of libraries that require a specific version -LIBAPPLEWM="applewm >= 1.4" -LIBDMX="dmx >= 1.0.99.1" -LIBDRI="dri >= 7.8.0" -LIBDRM="libdrm >= 2.3.0" -LIBGL="gl >= 7.1.0" -LIBXEXT="xext >= 1.0.99.4" -LIBXI="xi >= 1.2.99.1" -LIBXTST="xtst >= 1.0.99.2" -LIBPCIACCESS="pciaccess >= 0.8.0" -LIBGLIB="glib-2.0 >= 2.16" -LIBUDEV="libudev >= 143" -LIBSELINUX="libselinux >= 2.0.86" - -if test "x$CONFIG_UDEV" = xyes && - { test "x$CONFIG_DBUS_API" = xyes || test "x$CONFIG_HAL" = xyes; }; then - AC_MSG_ERROR([Hotplugging through both libudev and dbus/hal not allowed]) -fi - -PKG_CHECK_MODULES(UDEV, $LIBUDEV, [HAVE_LIBUDEV=yes], [HAVE_LIBUDEV=no]) -if test "x$CONFIG_UDEV" = xauto; then - CONFIG_UDEV="$HAVE_LIBUDEV" -fi -AM_CONDITIONAL(CONFIG_UDEV, [test "x$CONFIG_UDEV" = xyes]) -if test "x$CONFIG_UDEV" = xyes; then - CONFIG_DBUS_API=no - CONFIG_HAL=no - if ! test "x$HAVE_LIBUDEV" = xyes; then - AC_MSG_ERROR([udev configuration API requested, but libudev is not installed]) - fi - AC_DEFINE(CONFIG_UDEV, 1, [Use libudev for input hotplug]) -fi - -dnl HAVE_DBUS is true if we actually have the D-Bus library, whereas -dnl CONFIG_DBUS_API is true if we want to enable the D-Bus config -dnl API. -PKG_CHECK_MODULES(DBUS, dbus-1, [HAVE_DBUS=yes], [HAVE_DBUS=no]) -if test "x$HAVE_DBUS" = xyes; then - AC_DEFINE(HAVE_DBUS, 1, [Have D-Bus support]) -fi -AM_CONDITIONAL(HAVE_DBUS, [test "x$HAVE_DBUS" = xyes]) - -if test "x$CONFIG_DBUS_API" = xauto; then - CONFIG_DBUS_API="$HAVE_DBUS" -fi -if test "x$CONFIG_DBUS_API" = xyes; then - if ! test "x$HAVE_DBUS" = xyes; then - AC_MSG_ERROR([D-Bus configuration API requested, but D-Bus is not installed.]) - fi - - AC_DEFINE(CONFIG_DBUS_API, 1, [Use the D-Bus input configuration API]) - CONFIG_NEED_DBUS="yes" -fi -AM_CONDITIONAL(CONFIG_DBUS_API, [test "x$CONFIG_DBUS_API" = xyes]) - -PKG_CHECK_MODULES(HAL, hal, [HAVE_HAL=yes], [HAVE_HAL=no]) -if test "x$CONFIG_HAL" = xauto; then - CONFIG_HAL="$HAVE_HAL" -fi -if test "x$CONFIG_HAL" = xyes; then - if ! test "x$HAVE_HAL" = xyes; then - AC_MSG_ERROR([HAL hotplug API requested, but HAL is not installed.]) - fi - - AC_DEFINE(CONFIG_HAL, 1, [Use the HAL hotplug API]) - CONFIG_NEED_DBUS="yes" -fi -AM_CONDITIONAL(CONFIG_HAL, [test "x$CONFIG_HAL" = xyes]) - -if test "x$CONFIG_NEED_DBUS" = xyes; then - AC_DEFINE(CONFIG_NEED_DBUS, 1, [Use D-Bus for input hotplug]) -fi -AM_CONDITIONAL(CONFIG_NEED_DBUS, [test "x$CONFIG_NEED_DBUS" = xyes]) -CONFIG_LIB='$(top_builddir)/config/libconfig.la' - -if test "x$USE_SIGIO_BY_DEFAULT" = xyes; then - USE_SIGIO_BY_DEFAULT_VALUE=TRUE -else - USE_SIGIO_BY_DEFAULT_VALUE=FALSE -fi -AC_DEFINE_UNQUOTED([USE_SIGIO_BY_DEFAULT], [$USE_SIGIO_BY_DEFAULT_VALUE], - [Use SIGIO handlers for input device events by default]) - -AC_MSG_CHECKING([for glibc...]) -AC_PREPROC_IFELSE([ -#include -#ifndef __GLIBC__ -#error -#endif -], glibc=yes, glibc=no) -AC_MSG_RESULT([$glibc]) - -AC_CHECK_FUNCS([clock_gettime], [have_clock_gettime=yes], - [AC_CHECK_LIB([rt], [clock_gettime], [have_clock_gettime=-lrt], - [have_clock_gettime=no])]) - -AC_MSG_CHECKING([for a useful monotonic clock ...]) - -if ! test "x$have_clock_gettime" = xno; then - if ! test "x$have_clock_gettime" = xyes; then - CLOCK_LIBS="$have_clock_gettime" - else - CLOCK_LIBS="" - fi - - LIBS_SAVE="$LIBS" - LIBS="$CLOCK_LIBS" - CPPFLAGS_SAVE="$CPPFLAGS" - - if test x"$glibc" = xyes; then - CPPFLAGS="$CPPFLAGS -D_POSIX_C_SOURCE=200112L" - fi - - AC_RUN_IFELSE([ -#include - -int main(int argc, char *argv[[]]) { - struct timespec tp; - - if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0) - return 0; - else - return 1; -} - ], [MONOTONIC_CLOCK=yes], [MONOTONIC_CLOCK=no], - [MONOTONIC_CLOCK="cross compiling"]) - - LIBS="$LIBS_SAVE" - CPPFLAGS="$CPPFLAGS_SAVE" -else - MONOTONIC_CLOCK=no -fi - -AC_MSG_RESULT([$MONOTONIC_CLOCK]) - -if test "x$MONOTONIC_CLOCK" = xyes; then - AC_DEFINE(MONOTONIC_CLOCK, 1, [Have monotonic clock from clock_gettime()]) - LIBS="$LIBS $CLOCK_LIBS" -fi - -AM_CONDITIONAL(XV, [test "x$XV" = xyes]) -if test "x$XV" = xyes; then - AC_DEFINE(XV, 1, [Support Xv extension]) - AC_DEFINE(XvExtension, 1, [Build Xv extension]) - REQUIRED_MODULES="$REQUIRED_MODULES $VIDEOPROTO" -else - XVMC=no -fi - -AM_CONDITIONAL(XVMC, [test "x$XVMC" = xyes]) -if test "x$XVMC" = xyes; then - AC_DEFINE(XvMCExtension, 1, [Build XvMC extension]) -fi - -AM_CONDITIONAL(XREGISTRY, [test "x$XREGISTRY" = xyes]) -if test "x$XREGISTRY" = xyes; then - AC_DEFINE(XREGISTRY, 1, [Build registry module]) -fi - -AM_CONDITIONAL(COMPOSITE, [test "x$COMPOSITE" = xyes]) -if test "x$COMPOSITE" = xyes; then - AC_DEFINE(COMPOSITE, 1, [Support Composite Extension]) - REQUIRED_MODULES="$REQUIRED_MODULES $COMPOSITEPROTO" - COMPOSITE_LIB='$(top_builddir)/composite/libcomposite.la' - COMPOSITE_INC='-I$(top_srcdir)/composite' -fi - -AM_CONDITIONAL(MITSHM, [test "x$MITSHM" = xyes]) -if test "x$MITSHM" = xyes; then - AC_DEFINE(MITSHM, 1, [Support MIT-SHM extension]) - AC_DEFINE(HAS_SHM, 1, [Support SHM]) -fi - -AM_CONDITIONAL(RECORD, [test "x$RECORD" = xyes]) -if test "x$RECORD" = xyes; then - AC_DEFINE(XRECORD, 1, [Support Record extension]) - REQUIRED_MODULES="$REQUIRED_MODULES $RECORDPROTO" - RECORD_LIB='$(top_builddir)/record/librecord.la' -fi - -AM_CONDITIONAL(SCREENSAVER, [test "x$SCREENSAVER" = xyes]) -if test "x$SCREENSAVER" = xyes; then - AC_DEFINE(SCREENSAVER, 1, [Support MIT-SCREEN-SAVER extension]) - REQUIRED_MODULES="$REQUIRED_MODULES $SCRNSAVERPROTO" -fi - -AM_CONDITIONAL(RES, [test "x$RES" = xyes]) -if test "x$RES" = xyes; then - AC_DEFINE(RES, 1, [Support X resource extension]) - REQUIRED_MODULES="$REQUIRED_MODULES $RESOURCEPROTO" -fi - -if test "x$GLX" = xyes; then - PKG_CHECK_MODULES([XLIB], [x11]) - PKG_CHECK_MODULES([GL], $GLPROTO $LIBGL) - AC_SUBST(XLIB_CFLAGS) - AC_DEFINE(GLXEXT, 1, [Build GLX extension]) - GLX_LIBS='$(top_builddir)/glx/libglx.la' - GLX_SYS_LIBS="$GLX_SYS_LIBS" -else - GLX=no -fi -AM_CONDITIONAL(GLX, test "x$GLX" = xyes) - -if test "x$AIGLX" = xyes -a "x$GLX" = xyes -a "x$DRI" = xyes; then - AC_DEFINE(AIGLX, 1, [Build AIGLX loader]) -else - AIGLX=no -fi -AM_CONDITIONAL(AIGLX, test "x$AIGLX" = xyes) - -if test "x$GLX_USE_TLS" = xyes -a "x$AIGLX" = xyes; then - GLX_DEFINES="-DGLX_USE_TLS -DPTHREADS" - GLX_SYS_LIBS="$GLX_SYS_LIBS -lpthread" -fi -AC_SUBST([GLX_DEFINES]) - -AM_CONDITIONAL(DRI, test "x$DRI" = xyes) -if test "x$DRI" = xyes; then - AC_DEFINE(XF86DRI, 1, [Build DRI extension]) - PKG_CHECK_MODULES([DRIPROTO], [$DRIPROTO]) - PKG_CHECK_MODULES([DRI], $GLPROTO $LIBDRI) - AC_SUBST(DRIPROTO_CFLAGS) -fi - -PKG_CHECK_MODULES([DRI2PROTO], $DRI2PROTO, - [HAVE_DRI2PROTO=yes], [HAVE_DRI2PROTO=no]) -case "$DRI2,$HAVE_DRI2PROTO" in - yes,no) - AC_MSG_ERROR([DRI2 requested, but dri2proto not found.]) - ;; - yes,yes | auto,yes) - AC_DEFINE(DRI2, 1, [Build DRI2 extension]) - DRI2=yes - ;; -esac -AM_CONDITIONAL(DRI2, test "x$DRI2" = xyes) - -if test "x$DRI" = xyes || test "x$DRI2" = xyes; then - PKG_CHECK_MODULES([LIBDRM], $LIBDRM) - AC_SUBST(LIBDRM_CFLAGS) - AC_SUBST(LIBDRM_LIBS) -fi - -if test "x$DRI2" = xyes; then - save_CFLAGS=$CFLAGS - CFLAGS="$GL_CFLAGS $LIBDRM_CFLAGS" - AC_COMPILE_IFELSE([AC_LANG_SOURCE([[#include -#include -#ifndef __DRI_DRI2 -#error DRI2 extension not available. -#endif]])], - [HAVE_DRI2EXTENSION=yes], - [HAVE_DRI2EXTENSION=no]) - CFLAGS=$save_CFLAGS - if test "x$HAVE_DRI2EXTENSION" = xyes; then - AC_DEFINE(DRI2_AIGLX, 1, [Build DRI2 AIGLX loader]) - DRI2_AIGLX=yes - else - AC_MSG_NOTICE([DRI2 AIGLX disabled, __DRI_DRI2 not defined in dri_interface.h.]) - DRI2_AIGLX=no - fi -fi -AM_CONDITIONAL(DRI2_AIGLX, test "x$DRI2_AIGLX" = xyes) - - -AM_CONDITIONAL(XINERAMA, [test "x$XINERAMA" = xyes]) -if test "x$XINERAMA" = xyes; then - AC_DEFINE(XINERAMA, 1, [Support Xinerama extension]) - AC_DEFINE(PANORAMIX, 1, [Internal define for Xinerama]) - REQUIRED_MODULES="$REQUIRED_MODULES $XINERAMAPROTO" -fi - -AM_CONDITIONAL(XACE, [test "x$XACE" = xyes]) -if test "x$XACE" = xyes; then - AC_DEFINE(XACE, 1, [Build X-ACE extension]) -fi - -AM_CONDITIONAL(XSELINUX, [test "x$XSELINUX" = xyes]) -if test "x$XSELINUX" = xyes; then - if test "x$XACE" != xyes; then - AC_MSG_ERROR([cannot build SELinux extension without X-ACE]) - fi - AC_CHECK_HEADERS([libaudit.h], [], AC_MSG_ERROR([SELinux extension requires audit system headers])) - AC_CHECK_LIB(audit, audit_open, [], AC_MSG_ERROR([SELinux extension requires audit system library])) - PKG_CHECK_MODULES([SELINUX], $LIBSELINUX) - SELINUX_LIBS="$SELINUX_LIBS -laudit" - AC_DEFINE(XSELINUX, 1, [Build SELinux extension]) -fi - -AM_CONDITIONAL(XCSECURITY, [test "x$XCSECURITY" = xyes]) -if test "x$XCSECURITY" = xyes; then - if test "x$XACE" != xyes; then - AC_MSG_ERROR([cannot build Security extension without X-ACE]) - fi - AC_DEFINE(XCSECURITY, 1, [Build Security extension]) -fi - -AM_CONDITIONAL(DBE, [test "x$DBE" = xyes]) -if test "x$DBE" = xyes; then - AC_DEFINE(DBE, 1, [Support DBE extension]) - DBE_LIB='$(top_builddir)/dbe/libdbe.la' -fi - -AM_CONDITIONAL(XF86BIGFONT, [test "x$XF86BIGFONT" = xyes]) -if test "x$XF86BIGFONT" = xyes; then - AC_DEFINE(XF86BIGFONT, 1, [Support XF86 Big font extension]) - REQUIRED_MODULES="$REQUIRED_MODULES $BIGFONTPROTO" -fi - -AM_CONDITIONAL(DPMSExtension, [test "x$DPMSExtension" = xyes]) -if test "x$DPMSExtension" = xyes; then - AC_DEFINE(DPMSExtension, 1, [Support DPMS extension]) -fi - -if test "x$XCALIBRATE" = xyes && test "$KDRIVE" = yes; then - AC_DEFINE(XCALIBRATE, 1, [Build XCalibrate extension]) - REQUIRED_MODULES="$REQUIRED_MODULES $XCALIBRATEPROTO" -else - XCALIBRATE=no -fi -AM_CONDITIONAL(XCALIBRATE, [test "x$XCALIBRATE" = xyes]) - -AC_DEFINE(RENDER, 1, [Support RENDER extension]) -RENDER_LIB='$(top_builddir)/render/librender.la' -RENDER_INC='-I$(top_srcdir)/render' - -AC_DEFINE(RANDR, 1, [Support RANDR extension]) -RANDR_LIB='$(top_builddir)/randr/librandr.la' -RANDR_INC='-I$(top_srcdir)/randr' - -AC_DEFINE(XFIXES,1,[Support XFixes extension]) -FIXES_LIB='$(top_builddir)/xfixes/libxfixes.la' -FIXES_INC='-I$(top_srcdir)/xfixes' - -AC_DEFINE(DAMAGE,1,[Support Damage extension]) -DAMAGE_LIB='$(top_builddir)/damageext/libdamageext.la' -DAMAGE_INC='-I$(top_srcdir)/damageext' -MIEXT_DAMAGE_LIB='$(top_builddir)/miext/damage/libdamage.la' -MIEXT_DAMAGE_INC='-I$(top_srcdir)/miext/damage' - -# XINPUT extension is integral part of the server -AC_DEFINE(XINPUT, 1, [Support X Input extension]) -XI_LIB='$(top_builddir)/Xi/libXi.la' -XI_INC='-I$(top_srcdir)/Xi' - -AM_CONDITIONAL(XF86UTILS, test "x$XF86UTILS" = xyes) -AM_CONDITIONAL(XAA, test "x$XAA" = xyes) -AM_CONDITIONAL(VGAHW, test "x$VGAHW" = xyes) -AM_CONDITIONAL(VBE, test "x$VBE" = xyes) -AM_CONDITIONAL(INT10MODULE, test "x$INT10MODULE" = xyes) - -AC_DEFINE(SHAPE, 1, [Support SHAPE extension]) - -AC_DEFINE_DIR(XKB_BASE_DIRECTORY, XKBPATH, [Path to XKB data]) -AC_ARG_WITH(xkb-bin-directory, - AS_HELP_STRING([--with-xkb-bin-directory=DIR], [Directory containing xkbcomp program]), - [XKB_BIN_DIRECTORY="$withval"], - [XKB_BIN_DIRECTORY="$bindir"]) - -AC_DEFINE_DIR(XKB_BIN_DIRECTORY, XKB_BIN_DIRECTORY, [Path to XKB bin dir]) - -dnl Make sure XKM_OUTPUT_DIR is an absolute path -XKBOUTPUT_FIRSTCHAR=`echo $XKBOUTPUT | cut -b 1` -if [[ x$XKBOUTPUT_FIRSTCHAR != x/ -a x$XKBOUTPUT_FIRSTCHAR != 'x$' ]] ; then - XKBOUTPUT="$XKB_BASE_DIRECTORY/$XKBOUTPUT" -fi - -dnl XKM_OUTPUT_DIR (used in code) must end in / or file names get hosed -dnl XKB_COMPILED_DIR (used in Makefiles) must not or install-sh gets confused - -XKBOUTPUT=`echo $XKBOUTPUT/ | $SED 's|/*$|/|'` -XKB_COMPILED_DIR=`echo $XKBOUTPUT | $SED 's|/*$||'` -AC_DEFINE_DIR(XKM_OUTPUT_DIR, XKBOUTPUT, [Path to XKB output dir]) -AC_SUBST(XKB_COMPILED_DIR) - -if test "x$XKB_DFLT_RULES" = x; then - case $host_os in - linux*) - dnl doesn't take AutoAddDevices into account, but whatever. - if test "x$CONFIG_HAL" = xyes; then - XKB_DFLT_RULES="evdev" - else - XKB_DFLT_RULES="base" - fi - ;; - *) - XKB_DFLT_RULES="base" - ;; - esac -fi -AC_DEFINE_UNQUOTED(XKB_DFLT_RULES, ["$XKB_DFLT_RULES"], [Default XKB ruleset]) -AC_DEFINE_UNQUOTED(XKB_DFLT_MODEL, ["$XKB_DFLT_MODEL"], [Default XKB model]) -AC_DEFINE_UNQUOTED(XKB_DFLT_LAYOUT, ["$XKB_DFLT_LAYOUT"], [Default XKB layout]) -AC_DEFINE_UNQUOTED(XKB_DFLT_VARIANT, ["$XKB_DFLT_VARIANT"], [Default XKB variant]) -AC_DEFINE_UNQUOTED(XKB_DFLT_OPTIONS, ["$XKB_DFLT_OPTIONS"], [Default XKB options]) - -XKB_LIB='$(top_builddir)/xkb/libxkb.la' -XKB_STUB_LIB='$(top_builddir)/xkb/libxkbstubs.la' -REQUIRED_MODULES="$REQUIRED_MODULES xkbfile" - -AC_CHECK_FUNC(strcasecmp, [], AC_DEFINE([NEED_STRCASECMP], 1, - [Do not have 'strcasecmp'.])) -AC_CHECK_FUNC(strncasecmp, [], AC_DEFINE([NEED_STRNCASECMP], 1, - [Do not have 'strncasecmp'.])) -AC_CHECK_FUNC(strcasestr, [], AC_DEFINE([NEED_STRCASESTR], 1, - [Do not have 'strcasestr'.])) - -PKG_CHECK_MODULES([XDMCP], [xdmcp], [have_libxdmcp="yes"], [have_libxdmcp="no"]) -if test "x$have_libxdmcp" = xyes; then - AC_CHECK_LIB(Xdmcp, XdmcpWrap, [have_xdmcpwrap="yes"], [have_xdmcpwrap="no"], [$XDMCP_LIBS]) -fi -if test "x$XDMCP" = xauto; then - if test "x$have_libxdmcp" = xyes; then - XDMCP=yes - else - XDMCP=no - fi -fi -if test "x$XDMAUTH" = xauto; then - if test "x$have_libxdmcp" = xyes && test "x$have_xdmcpwrap" = xyes; then - XDMAUTH=yes - else - XDMAUTH=no - fi -fi - -AM_CONDITIONAL(XDMCP, [test "x$XDMCP" = xyes]) -if test "x$XDMCP" = xyes; then - AC_DEFINE(XDMCP, 1, [Support XDM Control Protocol]) - REQUIRED_LIBS="$REQUIRED_LIBS xdmcp" - XDMCP_MODULES="xdmcp" -fi - -AM_CONDITIONAL(XDMAUTH, [test "x$XDMAUTH" = xyes]) -if test "x$XDMAUTH" = xyes; then - AC_DEFINE(HASXDMAUTH,1,[Support XDM-AUTH*-1]) - if ! test "x$XDMCP" = xyes; then - REQUIRED_LIBS="$REQUIRED_LIBS xdmcp" - XDMCP_MODULES="xdmcp" - fi -fi - -AC_DEFINE_DIR(COMPILEDDEFAULTFONTPATH, FONTPATH, [Default font path]) -AC_DEFINE_DIR(PCI_TXT_IDS_PATH, PCI_TXT_IDS_DIR, [Default PCI text file ID path]) -AC_DEFINE_DIR(SERVER_MISC_CONFIG_PATH, SERVERCONFIG, [Server miscellaneous config path]) -AC_DEFINE_DIR(BASE_FONT_PATH, FONTROOTDIR, [Default base font path]) -AC_DEFINE_DIR(DRI_DRIVER_PATH, DRI_DRIVER_PATH, [Default DRI driver path]) -AC_DEFINE_UNQUOTED(XVENDORNAME, ["$VENDOR_NAME"], [Vendor name]) -AC_DEFINE_UNQUOTED(XVENDORNAMESHORT, ["$VENDOR_NAME_SHORT"], [Short vendor name]) -AC_DEFINE_UNQUOTED(XORG_DATE, ["$RELEASE_DATE"], [Vendor release]) -AC_DEFINE_UNQUOTED(XORG_MAN_VERSION, ["$VENDOR_MAN_VERSION"], [Vendor man version]) -AC_DEFINE_UNQUOTED(BUILDERADDR, ["$BUILDERADDR"], [Builder address]) - -if test -z "$OSNAME"; then - OSNAME="UNKNOWN" -fi - -AC_DEFINE_UNQUOTED(OSNAME, ["$OSNAME"], [Operating System Name]) -AC_DEFINE_UNQUOTED(OSVENDOR, ["$OSVENDOR"], [Operating System Vendor]) -AC_DEFINE_UNQUOTED(BUILDERSTRING, ["$BUILDERSTRING"], [Builder string]) - -AC_SUBST([VENDOR_NAME_SHORT]) -AC_DEFINE_UNQUOTED(VENDOR_NAME, ["$VENDOR_NAME"], [Vendor name]) -AC_DEFINE_UNQUOTED(VENDOR_NAME_SHORT, ["$VENDOR_NAME_SHORT"], [Vendor name]) -AC_DEFINE_UNQUOTED(VENDOR_RELEASE, [$VENDOR_RELEASE], [Vendor release]) -AC_DEFINE_UNQUOTED(VENDOR_MAN_VERSION, ["$VENDOR_MAN_VERSION"], [Vendor man version]) - -AC_DEFINE(NO_LIBCWRAPPER, 1, [Define to 1 if modules should avoid the libcwrapper]) - -if test "x$DEBUGGING" = xyes; then - AC_DEFINE(DEBUG, 1, [Enable debugging code]) -fi -AM_CONDITIONAL(DEBUG, [test "x$DEBUGGING" = xyes]) - -# If unittests aren't explicitly disabled, check for required support -if test "x$UNITTESTS" != xno ; then - PKG_CHECK_MODULES([GLIB], $LIBGLIB, - [HAVE_GLIB=yes], [HAVE_GLIB=no]) - - # Check if linker supports -wrap, passed via compiler flags - # When cross-compiling, reports no, since unit tests run from - # "make check", so would be running on build machine, not target - AC_MSG_CHECKING([whether the linker supports -wrap]) - save_LDFLAGS="$LDFLAGS" - LDFLAGS="$LDFLAGS -Wl,-wrap,exit" - AC_RUN_IFELSE([AC_LANG_PROGRAM([[ - void __wrap_exit (int s) - { - __real_exit (0); - }]], - [[exit (1);]])], - [linker_can_wrap="yes"], - [linker_can_wrap="no"], - [linker_can_wrap="no"]) - AC_MSG_RESULT([$linker_can_wrap]) - LDFLAGS="$save_LDFLAGS" -fi - -if test "x$UNITTESTS" = xauto; then - if test "x$HAVE_GLIB" = xyes && test "x$linker_can_wrap" = xyes; then - UNITTESTS=yes - else - UNITTESTS=no - fi -fi -if test "x$UNITTESTS" = xyes; then - if test "x$HAVE_GLIB" = xno; then - AC_MSG_ERROR([glib required to build unit tests]) - fi - if test "x$linker_can_wrap" = xno; then - AC_MSG_ERROR([ld -wrap support required to build unit tests]) - fi - AC_DEFINE(UNITTESTS, 1, [Enable unit tests]) - AC_SUBST([GLIB_LIBS]) - AC_SUBST([GLIB_CFLAGS]) -fi -AM_CONDITIONAL(UNITTESTS, [test "x$UNITTESTS" = xyes]) - -AC_DEFINE(XTEST, 1, [Support XTest extension]) -AC_DEFINE(XSYNC, 1, [Support XSync extension]) -AC_DEFINE(XCMISC, 1, [Support XCMisc extension]) -AC_DEFINE(BIGREQS, 1, [Support BigRequests extension]) - -if test "x$SPECIAL_DTRACE_OBJECTS" = "xyes" ; then - DIX_LIB='$(top_builddir)/dix/dix.O' - OS_LIB='$(top_builddir)/os/os.O $(SHA1_LIBS)' -else - DIX_LIB='$(top_builddir)/dix/libdix.la' - OS_LIB='$(top_builddir)/os/libos.la' -fi -AC_SUBST([DIX_LIB]) -AC_SUBST([OS_LIB]) - -MAIN_LIB='$(top_builddir)/dix/libmain.la' -AC_SUBST([MAIN_LIB]) - -MI_LIB='$(top_builddir)/mi/libmi.la' -MI_EXT_LIB='$(top_builddir)/mi/libmiext.la' -MI_INC='-I$(top_srcdir)/mi' -FB_LIB='$(top_builddir)/fb/libfb.la' -FB_INC='-I$(top_srcdir)/fb' -MIEXT_SHADOW_INC='-I$(top_srcdir)/miext/shadow' -MIEXT_SHADOW_LIB='$(top_builddir)/miext/shadow/libshadow.la' -CORE_INCS='-I$(top_srcdir)/include -I$(top_builddir)/include' - -# SHA1 hashing -AC_ARG_WITH([sha1], - [AS_HELP_STRING([--with-sha1=libc|libmd|libgcrypt|libcrypto|libsha1|CommonCrypto], - [choose SHA1 implementation])]) -AC_CHECK_FUNC([SHA1Init], [HAVE_SHA1_IN_LIBC=yes]) -if test "x$with_sha1" = x && test "x$HAVE_SHA1_IN_LIBC" = xyes; then - with_sha1=libc -fi -if test "x$with_sha1" = xlibc && test "x$HAVE_SHA1_IN_LIBC" != xyes; then - AC_MSG_ERROR([libc requested but not found]) -fi -if test "x$with_sha1" = xlibc; then - AC_DEFINE([HAVE_SHA1_IN_LIBC], [1], - [Use libc SHA1 functions]) - SHA1_LIBS="" -fi -AC_CHECK_FUNC([CC_SHA1_Init], [HAVE_SHA1_IN_COMMONCRYPTO=yes]) -if test "x$with_sha1" = x && test "x$HAVE_SHA1_IN_COMMONCRYPTO" = xyes; then - with_sha1=CommonCrypto -fi -if test "x$with_sha1" = xCommonCrypto && test "x$HAVE_SHA1_IN_COMMONCRYPTO" != xyes; then - AC_MSG_ERROR([CommonCrypto requested but not found]) -fi -if test "x$with_sha1" = xCommonCrypto; then - AC_DEFINE([HAVE_SHA1_IN_COMMONCRYPTO], [1], - [Use CommonCrypto SHA1 functions]) - SHA1_LIBS="" -fi -AC_CHECK_LIB([md], [SHA1Init], [HAVE_LIBMD=yes]) -if test "x$with_sha1" = x && test "x$HAVE_LIBMD" = xyes; then - with_sha1=libmd -fi -if test "x$with_sha1" = xlibmd && test "x$HAVE_LIBMD" != xyes; then - AC_MSG_ERROR([libmd requested but not found]) -fi -if test "x$with_sha1" = xlibmd; then - AC_DEFINE([HAVE_SHA1_IN_LIBMD], [1], - [Use libmd SHA1 functions]) - SHA1_LIBS=-lmd -fi -AC_CHECK_LIB([sha1], [sha1_begin], [HAVE_LIBSHA1=yes]) -if test "x$with_sha1" = x && test "x$HAVE_LIBSHA1" = xyes; then - with_sha1=libsha1 -fi -if test "x$with_sha1" = xlibsha1 && test "x$HAVE_LIBSHA1" != xyes; then - AC_MSG_ERROR([libsha1 requested but not found]) -fi -if test "x$with_sha1" = xlibsha1; then - AC_DEFINE([HAVE_SHA1_IN_LIBSHA1], [1], - [Use libsha1 for SHA1]) - SHA1_LIBS=-lsha1 -fi -AC_CHECK_LIB([gcrypt], [gcry_md_open], [HAVE_LIBGCRYPT=yes]) -if test "x$with_sha1" = x && test "x$HAVE_LIBGCRYPT" = xyes; then - with_sha1=libgcrypt -fi -if test "x$with_sha1" = xlibgcrypt && test "x$HAVE_LIBGCRYPT" != xyes; then - AC_MSG_ERROR([libgcrypt requested but not found]) -fi -if test "x$with_sha1" = xlibgcrypt; then - AC_DEFINE([HAVE_SHA1_IN_LIBGCRYPT], [1], - [Use libgcrypt SHA1 functions]) - SHA1_LIBS=-lgcrypt -fi -# We don't need all of the OpenSSL libraries, just libcrypto -AC_CHECK_LIB([crypto], [SHA1_Init], [HAVE_LIBCRYPTO=yes]) -PKG_CHECK_MODULES([OPENSSL], [openssl], [HAVE_OPENSSL_PKC=yes], - [HAVE_OPENSSL_PKC=no]) -if test "x$HAVE_LIBCRYPTO" = xyes || test "x$HAVE_OPENSSL_PKC" = xyes; then - if test "x$with_sha1" = x; then - with_sha1=libcrypto - fi -else - if test "x$with_sha1" = xlibcrypto; then - AC_MSG_ERROR([OpenSSL libcrypto requested but not found]) - fi -fi -if test "x$with_sha1" = xlibcrypto; then - if test "x$HAVE_LIBCRYPTO" = xyes; then - SHA1_LIBS=-lcrypto - else - SHA1_LIBS="$OPENSSL_LIBS" - SHA1_CFLAGS="$OPENSSL_CFLAGS" - fi -fi -AC_MSG_CHECKING([for SHA1 implementation]) -if test "x$with_sha1" = x; then - AC_MSG_ERROR([No suitable SHA1 implementation found]) -fi -AC_MSG_RESULT([$with_sha1]) -AC_SUBST(SHA1_LIBS) -AC_SUBST(SHA1_CFLAGS) - -PKG_CHECK_MODULES([XSERVERCFLAGS], [$REQUIRED_MODULES $REQUIRED_LIBS]) -PKG_CHECK_MODULES([XSERVERLIBS], [$REQUIRED_LIBS]) - -# Autotools has some unfortunate issues with library handling. In order to -# get a server to rebuild when a dependency in the tree is changed, it must -# be listed in SERVERNAME_DEPENDENCIES. However, no system libraries may be -# listed there, or some versions of autotools will break (especially if a -L -# is required to find the library). So, we keep two sets of libraries -# detected: NAMESPACE_LIBS for in-tree libraries to be linked against, which -# will go into the _DEPENDENCIES and _LDADD of the server, and -# NAMESPACE_SYS_LIBS which will go into only the _LDADD. The -# NAMESPACEMODULES_LIBS detected from pkgconfig should always go in -# NAMESPACE_SYS_LIBS. -# -# XSERVER_LIBS is the set of in-tree libraries which all servers require. -# XSERVER_SYS_LIBS is the set of out-of-tree libraries which all servers -# require. -# -XSERVER_CFLAGS="${XSERVER_CFLAGS} ${XSERVERCFLAGS_CFLAGS}" -XSERVER_LIBS="$DIX_LIB $CONFIG_LIB $MI_LIB $OS_LIB" -XSERVER_SYS_LIBS="${XSERVERLIBS_LIBS} ${SYS_LIBS} ${LIBS}" -AC_SUBST([XSERVER_LIBS]) -AC_SUBST([XSERVER_SYS_LIBS]) - -UTILS_SYS_LIBS="${SYS_LIBS}" -AC_SUBST([UTILS_SYS_LIBS]) - -# The Xorg binary needs to export symbols so that they can be used from modules -# Some platforms require extra flags to do this. libtool should set the -# necessary flags for each platform when -export-dynamic is passed to it. -LD_EXPORT_SYMBOLS_FLAG="-export-dynamic" -AC_SUBST([LD_EXPORT_SYMBOLS_FLAG]) - -dnl Imake defines SVR4 on SVR4 systems, and many files check for it, so -dnl we need to replicate that here until those can all be fixed -AC_MSG_CHECKING([if SVR4 needs to be defined]) -AC_EGREP_CPP([I_AM_SVR4],[ -#if defined(SVR4) || defined(__svr4__) || defined(__SVR4) - I_AM_SVR4 -#endif -],[ -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_SHADOW_INC $MIEXT_LAYER_INC $MIEXT_DAMAGE_INC $RENDER_INC $RANDR_INC $FB_INC" - -dnl --------------------------------------------------------------------------- -dnl DDX section. -dnl --------------------------------------------------------------------------- - -dnl Xvfb DDX - -AC_MSG_CHECKING([whether to build Xvfb DDX]) -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 $CONFIG_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_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]) -fi - - -dnl Xnest DDX - -PKG_CHECK_MODULES(XNESTMODULES, [xfont $LIBXEXT x11 xau $XDMCP_MODULES], [have_xnest=yes], [have_xnest=no]) -AC_MSG_CHECKING([whether to build Xnest DDX]) -if test "x$XNEST" = xauto; then - XNEST="$have_xnest" -fi -AC_MSG_RESULT([$XNEST]) -AM_CONDITIONAL(XNEST, [test "x$XNEST" = xyes]) - -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_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $DIX_LIB $MAIN_LIB $OS_LIB $CONFIG_LIB" - XNEST_SYS_LIBS="$XNESTMODULES_LIBS $GLX_SYS_LIBS" - AC_SUBST([XNEST_LIBS]) - AC_SUBST([XNEST_SYS_LIBS]) -fi - - -dnl Xorg DDX - -AC_MSG_CHECKING([whether to build Xorg DDX]) -if test "x$XORG" = xauto; then - XORG="yes" - case $host_os in - cygwin*) XORG="no" ;; - darwin*) XORG="no" ;; - esac -fi -AC_MSG_RESULT([$XORG]) - -xorg_bus_linuxpci=no -xorg_bus_bsdpci=no -xorg_bus_sparc=no - -if test "x$XORG" = xyes; then - XORG_DDXINCS='-I$(top_srcdir)/hw/xfree86 -I$(top_srcdir)/hw/xfree86/include -I$(top_srcdir)/hw/xfree86/common' - 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 $XEXTXORG_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB" - - dnl ================================================================== - dnl symbol visibility - symbol_visibility= - have_visibility=disabled - if test x$SYMBOL_VISIBILITY != xno; then - AC_MSG_CHECKING(for symbol visibility support) - if test x$GCC = xyes; then - VISIBILITY_CFLAGS="-fvisibility=hidden" - else - AC_CHECK_DECL([__SUNPRO_C], [SUNCC="yes"], [SUNCC="no"]) - if test x$SUNCC = xyes; then - VISIBILITY_CFLAGS="-xldscope=hidden" - else - have_visibility=no - fi - fi - if test x$have_visibility != xno; then - save_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS $VISIBILITY_CFLAGS" - AC_TRY_COMPILE( - [#include - extern _X_HIDDEN int hidden_int; - extern _X_EXPORT int public_int; - extern _X_HIDDEN int hidden_int_func(void); - extern _X_EXPORT int public_int_func(void);], - [], - have_visibility=yes, - have_visibility=no) - CFLAGS=$save_CFLAGS - fi - AC_MSG_RESULT([$have_visibility]) - if test x$have_visibility != xno; then - symbol_visibility=$VISIBILITY_CFLAGS - XORG_CFLAGS="$XORG_CFLAGS $VISIBILITY_CFLAGS" - XSERVER_CFLAGS="$XSERVER_CFLAGS $VISIBILITY_CFLAGS" - fi - fi - dnl added to xorg-server.pc - AC_SUBST([symbol_visibility]) - dnl =================================================================== - - PKG_CHECK_MODULES([PCIACCESS], $LIBPCIACCESS) - SAVE_LIBS=$LIBS - SAVE_CFLAGS=$CFLAGS - CFLAGS=$PCIACCESS_CFLAGS - LIBS=$PCIACCESS_LIBS - AC_CHECK_FUNCS([pci_system_init_dev_mem]) - AC_CHECK_FUNCS([pci_device_enable]) - AC_CHECK_FUNCS([pci_device_is_boot_vga]) - AC_CHECK_FUNCS([pci_device_vgaarb_init]) - LIBS=$SAVE_LIBS - CFLAGS=$SAVE_CFLAGS - XORG_SYS_LIBS="$XORG_SYS_LIBS $PCIACCESS_LIBS $GLX_SYS_LIBS" - XORG_CFLAGS="$XORG_CFLAGS $PCIACCESS_CFLAGS" - - case $host_os in - linux*) - if test "x$LNXAPM" = xyes; then - XORG_CFLAGS="$XORG_CFLAGS -DXF86PM" - fi - XORG_OS="linux" - XORG_OS_SUBDIR="linux" - xorg_bus_linuxpci="yes" - linux_acpi="no" - case $host_cpu in - ia64*) - linux_ia64=yes - linux_acpi="yes" - ;; - alpha*) - linux_alpha=yes - ;; - i*86|amd64*|x86_64*) - linux_acpi="yes" - ;; - *) - ;; - esac - ;; - freebsd* | kfreebsd*-gnu | dragonfly*) - XORG_OS="freebsd" - XORG_OS_SUBDIR="bsd" - xorg_bus_bsdpci="yes" - ;; - netbsd*) - XORG_OS="netbsd" - XORG_OS_SUBDIR="bsd" - xorg_bus_bsdpci="yes" - ;; - openbsd*) - if test "x$ac_cv_BSD_APM" = xyes \ - -o "x$ac_cv_BSD_KQUEUE_APM" = xyes; then - XORG_CFLAGS="$XORG_CFLAGS -DXF86PM" - fi - XORG_OS="openbsd" - XORG_OS_SUBDIR="bsd" - xorg_bus_bsdpci="yes" - ;; - solaris*) - XORG_OS="solaris" - XORG_OS_SUBDIR="solaris" - XORG_CFLAGS="$XORG_CFLAGS -DXF86PM" - # Use the same stubs as BSD for old functions, since we now - # use libpciaccess for PCI - xorg_bus_bsdpci="yes" - AC_CHECK_HEADERS([sys/kd.h]) - AC_CHECK_HEADERS([sys/vt.h], [solaris_vt=yes], [solaris_vt=no]) - # Check for minimum supported release - AC_MSG_CHECKING([Solaris version]) - OS_MINOR=`echo ${host_os}|$SED -e 's/^.*solaris2\.//' -e s'/\..*$//'` - if test "${OS_MINOR}" -ge 7 ; then - AC_MSG_RESULT(Solaris ${OS_MINOR}) - else - AC_MSG_RESULT(Solaris `echo ${host_os}|$SED -e 's/^.*solaris//`) - fi - if test "${OS_MINOR}" -lt 8 ; then - AC_MSG_ERROR([This release no longer supports Solaris versions older than Solaris 8.]) - fi - AC_CHECK_DECL([__SUNPRO_C], [SUNCC="yes"], [SUNCC="no"]) - if test "x$SUNCC" = "xyes"; then - solaris_asm_inline="yes" - fi - AC_CHECK_DECL([_LP64], [SOLARIS_64="yes"], [SOLARIS_64="no"]) - - case $host_cpu in - sparc*) - SOLARIS_INOUT_ARCH="sparcv8plus" - ;; - i*86) - if test x$SOLARIS_64 = xyes ; then - SOLARIS_INOUT_ARCH="amd64" - else - SOLARIS_INOUT_ARCH="ia32" - fi - ;; - *) - AC_MSG_ERROR([Unsupported Solaris platform. Only SPARC & x86 \ - are supported on Solaris in this release. If you are \ - interested in porting Xorg to your platform, please email \ - xorg@lists.freedesktop.org.]) ;; - esac - AC_SUBST([SOLARIS_INOUT_ARCH]) - if test x$solaris_asm_inline = xyes ; then - SOLARIS_ASM_CFLAGS='$(top_srcdir)/hw/xfree86/os-support/solaris/solaris-$(SOLARIS_INOUT_ARCH).il' - XORG_CFLAGS="${XORG_CFLAGS} "'$(SOLARIS_ASM_CFLAGS)' - fi - AC_SUBST([SOLARIS_ASM_CFLAGS]) - if test "x$SUPPORT_PC98" = xauto; then - SUPPORT_PC98="no" - fi - ;; - gnu*) - XORG_OS="gnu" - XORG_OS_SUBDIR="hurd" - # Use the same stubs as BSD for old functions, since we now - # use libpciaccess for PCI - xorg_bus_bsdpci="yes" - ;; - *) - XORG_OS="unknown" - XORG_OS_SUBDIR="unknown" - AC_MSG_ERROR([m4_text_wrap(m4_join([ ], - [Your OS is unknown. Xorg currently only supports Linux,], - [Free/Open/Net/DragonFlyBSD, Solaris/OpenSolaris, & GNU Hurd.], - [If you are interested in porting Xorg to your platform,], - [please email xorg@lists.freedesktop.org.]))]) - ;; - esac - - case $host_cpu in - sparc*) - xorg_bus_sparc="yes" - ;; - i*86) - if test "x$SUPPORT_PC98" = xauto; then - SUPPORT_PC98="yes" - fi - ;; - esac - - if test "x$SUPPORT_PC98" = xauto; then - SUPPORT_PC98="no" - fi - if test "x$SUPPORT_PC98" = xyes; then - AC_DEFINE(SUPPORT_PC98, 1, [Support PC98]) - fi - if test "x$XORG_OS_PCI" = x ; then - XORG_OS_PCI=$XORG_OS - fi - if test "x$DGA" = xauto; then - PKG_CHECK_MODULES(DGA, $DGAPROTO, [DGA=yes], [DGA=no]) - fi - if test "x$DGA" = xyes; then - XORG_MODULES="$XORG_MODULES $DGAPROTO" - PKG_CHECK_MODULES(DGA, $DGAPROTO) - AC_DEFINE(DGA, 1, [Support DGA extension]) - AC_DEFINE(XFreeXDGA, 1, [Build XDGA support]) - fi - - if test "x$XF86VIDMODE" = xauto; then - PKG_CHECK_MODULES(XF86VIDMODE, $VIDMODEPROTO, [XF86VIDMODE=yes], [XF86VIDMODE=no]) - fi - if test "x$XF86VIDMODE" = xyes; then - XORG_MODULES="$XORG_MODULES $VIDMODEPROTO" - PKG_CHECK_MODULES(XF86VIDMODE, $VIDMODEPROTO) - AC_DEFINE(XF86VIDMODE, 1, [Support XFree86 Video Mode extension]) - fi - - if test -n "$XORG_MODULES"; then - PKG_CHECK_MODULES(XORG_MODULES, [$XORG_MODULES]) - XORG_CFLAGS="$XORG_CFLAGS $XORG_MODULES_CFLAGS" - XORG_SYS_LIBS="$XORG_SYS_LIBS $XORG_MODULES_LIBS" - fi - - AC_SUBST([XORG_LIBS]) - AC_SUBST([XORG_SYS_LIBS]) - AC_SUBST([XORG_INCS]) - AC_SUBST([XORG_OS]) - AC_SUBST([XORG_OS_SUBDIR]) - - AC_PATH_PROG(PERL, perl, no) - dnl unlikely as this may be ... - if test "x$PERL" = xno; then - AC_MSG_ERROR([Perl is required to build the XFree86/Xorg DDX.]) - fi - AC_SUBST(PERL) - - AC_SUBST([XORG_CFLAGS]) - - dnl these only go in xorg-config.h - XF86CONFIGFILE="xorg.conf" - XF86CONFIGDIR="xorg.conf.d" - AC_SUBST(XF86CONFIGDIR) - CONFIGFILE="$sysconfdir/$XF86CONFIGFILE" - LOGPREFIX="$logdir/Xorg." - AC_DEFINE(XORG_SERVER, 1, [Building Xorg server]) - AC_DEFINE(XORGSERVER, 1, [Building Xorg server]) - AC_DEFINE(XFree86Server, 1, [Building XFree86 server]) - AC_DEFINE(XFree86LOADER, 1, [Building loadable XFree86 server]) - AC_DEFINE_UNQUOTED(XORG_VERSION_CURRENT, [$VENDOR_RELEASE], [Current Xorg version]) - AC_DEFINE(NEED_XF86_TYPES, 1, [Need XFree86 typedefs]) - AC_DEFINE(NEED_XF86_PROTOTYPES, 1, [Need XFree86 helper functions]) - AC_DEFINE(__XSERVERNAME__, "Xorg", [Name of X server]) - AC_DEFINE_DIR(__XCONFIGFILE__, XF86CONFIGFILE, [Name of configuration file]) - AC_DEFINE_DIR(XF86CONFIGFILE, XF86CONFIGFILE, [Name of configuration file]) - AC_DEFINE_DIR(__XCONFIGDIR__, XF86CONFIGDIR, [Name of configuration directory]) - AC_DEFINE_DIR(DEFAULT_MODULE_PATH, moduledir, [Default module search path]) - AC_DEFINE_DIR(DEFAULT_LIBRARY_PATH, libdir, [Default library install path]) - AC_DEFINE_DIR(DEFAULT_LOGPREFIX, LOGPREFIX, [Default log location]) - AC_DEFINE_UNQUOTED(__VENDORDWEBSUPPORT__, ["$VENDOR_WEB"], [Vendor web address for support]) - AC_DEFINE(XSERVER_LIBPCIACCESS, 1, [Use libpciaccess for all pci manipulation]) - if test "x$VGAHW" = xyes; then - AC_DEFINE(WITH_VGAHW, 1, [Building vgahw module]) - fi - - driverdir="$moduledir/drivers" - AC_SUBST([moduledir]) - AC_SUBST([driverdir]) - sdkdir="$includedir/xorg" - extdir="$includedir/X11/extensions" - sysconfigdir="$datadir/X11/$XF86CONFIGDIR" - AC_SUBST([sdkdir]) - AC_SUBST([extdir]) - AC_SUBST([sysconfigdir]) - AC_SUBST([logdir]) - - # stuff the ABI versions into the pc file too - extract_abi() { - grep ^.define.*${1}_VERSION ${srcdir}/hw/xfree86/common/xf86Module.h | tr '(),' ' .' | awk '{ print $4$5 }' - } - abi_ansic=`extract_abi ANSIC` - abi_videodrv=`extract_abi VIDEODRV` - abi_xinput=`extract_abi XINPUT` - abi_extension=`extract_abi EXTENSION` - AC_SUBST([abi_ansic]) - AC_SUBST([abi_videodrv]) - AC_SUBST([abi_xinput]) - AC_SUBST([abi_extension]) -fi -AM_CONDITIONAL([XORG], [test "x$XORG" = xyes]) -AM_CONDITIONAL([XORG_BUS_LINUXPCI], [test "x$xorg_bus_linuxpci" = xyes]) -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_IA64], [test "x$linux_ia64" = xyes]) -AM_CONDITIONAL([LINUX_ALPHA], [test "x$linux_alpha" = xyes]) -AM_CONDITIONAL([LNXACPI], [test "x$linux_acpi" = 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]) -AM_CONDITIONAL([XF86VIDMODE], [test "x$XF86VIDMODE" = xyes]) - -dnl XWin DDX - -AC_MSG_CHECKING([whether to build XWin DDX]) -if test "x$XWIN" = xauto; then - case $host_os in - cygwin*) XWIN="yes" ;; - mingw*) XWIN="yes" ;; - *) XWIN="no" ;; - esac -fi -AC_MSG_RESULT([$XWIN]) - -if test "x$XWIN" = xyes; then - AC_DEFINE_DIR(SYSCONFDIR, sysconfdir, [Location of system.XWinrc]) - AC_DEFINE_DIR(DEFAULT_LOGDIR, logdir, [Default log location]) - AC_DEFINE_UNQUOTED(XORG_VERSION_CURRENT, [$VENDOR_RELEASE], [Current Xorg version]) - AC_DEFINE_UNQUOTED(__VENDORDWEBSUPPORT__, ["$VENDOR_WEB"], [Vendor web address for support]) - AC_CHECK_TOOL(WINDRES, windres) - - PKG_CHECK_MODULES([XWINMODULES],[x11 xdmcp xau xfont]) - - if test "x$WINDOWSWM" = xauto; then - PKG_CHECK_EXISTS($WINDOWSWMPROTO, [WINDOWSWM=yes], [WINDOWSWM=no]) - fi - if test "x$WINDOWSWM" = xyes ; then - PKG_CHECK_MODULES(WINDOWSWM, $WINDOWSWMPROTO) - XWINMODULES_CFLAGS="$XWINMODULES_CFLAGS $WINDOWSWM_CFLAGS" - AC_DEFINE(ROOTLESS,1,[Build Rootless code]) - fi - - case $host_os in - cygwin*) - XWIN_SERVER_NAME=XWin - AC_DEFINE(HAS_DEVWINDOWS,1,[Cygwin has /dev/windows for signaling new win32 messages]) - ;; - mingw*) - XWIN_SERVER_NAME=Xming - AC_DEFINE(RELOCATE_PROJECTROOT,1,[Make PROJECT_ROOT relative to the xserver location]) - AC_DEFINE(HAS_WINSOCK,1,[Use Windows sockets]) - XWIN_SYS_LIBS=-lwinsock2 - ;; - esac - XWIN_LIBS="$FB_LIB $MI_LIB $FIXES_LIB $XEXT_LIB $CONFIG_LIB $RANDR_LIB $RENDER_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $OS_LIB" - XWIN_SYS_LIBS="$XWIN_SYS_LIBS $XWINMODULES_LIBS" - AC_SUBST(XWIN_LIBS) - AC_SUBST(XWIN_SERVER_NAME) - AC_SUBST(XWIN_SYS_LIBS) - - if test "x$DEBUGGING" = xyes; then - AC_DEFINE(CYGDEBUG, 1, [Simple debug messages]) - AC_DEFINE(CYGWINDOWING_DEBUG, 1, [Debug messages for window handling]) - AC_DEFINE(CYGMULTIWINDOW_DEBUG, 1, [Debug window manager]) - fi - - AC_DEFINE(DDXOSVERRORF, 1, [Use OsVendorVErrorF]) - AC_DEFINE(DDXBEFORERESET, 1, [Use ddxBeforeReset ]) -fi -AM_CONDITIONAL(XWIN, [test "x$XWIN" = xyes]) -AM_CONDITIONAL(XWIN_MULTIWINDOW, [test "x$XWIN" = xyes]) -AM_CONDITIONAL(XWIN_MULTIWINDOWEXTWM, [test "x$XWIN" = xyes && test "x$WINDOWSWM" = xyes]) -AM_CONDITIONAL(XWIN_CLIPBOARD, [test "x$XWIN" = xyes]) -AM_CONDITIONAL(XWIN_GLX_WINDOWS, [test "x$XWIN" = xyes && false]) -AM_CONDITIONAL(XWIN_NATIVEGDI, [test "x$XWIN" = xyes && false]) -AM_CONDITIONAL(XWIN_PRIMARYFB, [test "x$XWIN" = xyes && false]) -AM_CONDITIONAL(XWIN_RANDR, [test "x$XWIN" = xyes]) -AM_CONDITIONAL(XWIN_XV, [test "x$XWIN" = xyes && test "x$XV" = xyes]) - -dnl Darwin / OS X DDX -if test "x$XQUARTZ" = xyes; then - AC_DEFINE(XQUARTZ,1,[Have Quartz]) - AC_DEFINE(ROOTLESS,1,[Build Rootless code]) - - DARWIN_LIBS="$MI_LIB $OS_LIB $DIX_LIB $MAIN_LIB $FB_LIB $FIXES_LIB $XEXT_LIB $CONFIG_LIB $DBE_LIB $RECORD_LIB $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $XPSTUBS_LIB" - AC_SUBST([DARWIN_LIBS]) - - AC_CHECK_LIB([Xplugin],[xp_init],[:]) - - CFLAGS="${CFLAGS} -DROOTLESS_WORKAROUND -DROOTLESS_SAFEALPHA -DNO_ALLOCA" - - PKG_CHECK_MODULES(XPBPROXY, $APPLEWMPROTO $LIBAPPLEWM xfixes x11) - - if test "x$XQUARTZ_SPARKLE" = xyes ; then - AC_DEFINE(XQUARTZ_SPARKLE,1,[Support application updating through sparkle.]) - fi - - if test "x$STANDALONE_XPBPROXY" = xyes ; then - AC_DEFINE(STANDALONE_XPBPROXY,1,[Build a standalone xpbproxy]) - fi -fi - -# Support for objc in autotools is minimal and not documented. -OBJC='$(CC)' -OBJCLD='$(CCLD)' -OBJCLINK='$(LINK)' -OBJCFLAGS='$(CFLAGS)' -AC_SUBST([OBJC]) -AC_SUBST([OBJCCLD]) -AC_SUBST([OBJCLINK]) -AC_SUBST([OBJCFLAGS]) -# internal, undocumented automake func follows :( -_AM_DEPENDENCIES([OBJC]) -AM_CONDITIONAL(XQUARTZ, [test "x$XQUARTZ" = xyes]) -AM_CONDITIONAL(XQUARTZ_SPARKLE, [test "x$XQUARTZ_SPARKLE" != "xno"]) -AM_CONDITIONAL(STANDALONE_XPBPROXY, [test "x$STANDALONE_XPBPROXY" = xyes]) - -dnl DMX DDX -PKG_CHECK_MODULES( - [DMXMODULES], - [xmuu $LIBXEXT x11 xrender xfixes xfont $LIBXI $DMXPROTO xau $XDMCP_MODULES], - [PKG_CHECK_MODULES( - [XDMXCONFIG_DEP], - [xaw7 xmu xt xpm x11], - [have_dmx=yes], - [have_dmx=no])], - [have_dmx=no]) -AC_MSG_CHECKING([whether to build Xdmx DDX]) -if test "x$DMX" = xauto; then - DMX="$have_dmx" - case $host_os in - cygwin*) DMX="no" ;; - darwin*) DMX="no" ;; - esac -fi -AC_MSG_RESULT([$DMX]) -AM_CONDITIONAL(DMX, [test "x$DMX" = xyes]) - -if test "x$DMX" = xyes; then - if test "x$have_dmx" = xno; then - AC_MSG_ERROR([Xdmx build explicitly requested, but required - modules not found.]) - fi - DMX_INCLUDES="$XEXT_INC $RENDER_INC $RECORD_INC" - XDMX_CFLAGS="$DMXMODULES_CFLAGS" - XDMX_LIBS="$FB_LIB $MI_LIB $RENDER_LIB $RECORD_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $MIEXT_SHADOW_LIB $MIEXT_DAMAGE_LIB $XEXT_LIB $MAIN_LIB $DIX_LIB $CONFIG_LIB $OS_LIB $FIXES_LIB" - XDMX_SYS_LIBS="$DMXMODULES_LIBS" - AC_SUBST([XDMX_CFLAGS]) - AC_SUBST([XDMX_LIBS]) - AC_SUBST([XDMX_SYS_LIBS]) - -dnl USB sources in DMX require - AC_CHECK_HEADER([linux/input.h], DMX_BUILD_USB="yes", - DMX_BUILD_USB="no") -dnl Linux sources in DMX require - AC_CHECK_HEADER([linux/keyboard.h], DMX_BUILD_LNX="yes", - DMX_BUILD_LNX="no") - AC_SUBST(XDMXCONFIG_DEP_CFLAGS) - AC_SUBST(XDMXCONFIG_DEP_LIBS) - PKG_CHECK_MODULES([DMXEXAMPLES_DEP], [$LIBDMX $LIBXEXT x11]) - AC_SUBST(DMXEXAMPLES_DEP_LIBS) - PKG_CHECK_MODULES([DMXXMUEXAMPLES_DEP], [$LIBDMX xmu $LIBXEXT x11]) - AC_SUBST(DMXXMUEXAMPLES_DEP_LIBS) - PKG_CHECK_MODULES([DMXXIEXAMPLES_DEP], [$LIBDMX $LIBXI $LIBXEXT x11]) - AC_SUBST(DMXXIEXAMPLES_DEP_LIBS) - PKG_CHECK_MODULES([XTSTEXAMPLES_DEP], [$LIBXTST $LIBXEXT x11]) - AC_SUBST(XTSTEXAMPLES_DEP_LIBS) - PKG_CHECK_MODULES([XRESEXAMPLES_DEP], [xres $LIBXEXT x11]) - AC_SUBST(XRESEXAMPLES_DEP_LIBS) - PKG_CHECK_MODULES([X11EXAMPLES_DEP], [$LIBXEXT x11]) - AC_SUBST(X11EXAMPLES_DEP_LIBS) - -fi -AM_CONDITIONAL([DMX_BUILD_LNX], [test "x$DMX_BUILD_LNX" = xyes]) -AM_CONDITIONAL([DMX_BUILD_USB], [test "x$DMX_BUILD_USB" = xyes]) - -dnl kdrive DDX - -XEPHYR_LIBS= -XEPHYR_INCS= - -AM_CONDITIONAL(KDRIVE, [test x$KDRIVE = xyes]) - -if test "$KDRIVE" = yes; then - AC_DEFINE(KDRIVESERVER,1,[Build Kdrive X server]) - AC_DEFINE(KDRIVEDDXACTIONS,,[Build kdrive ddx]) - - AC_CHECK_HEADERS([linux/fb.h]) - if test "$ac_cv_header_linux_fb_h" = yes && test "x$XFBDEV" = xauto; then - XFBDEV=yes - fi - - if test "x$XFBDEV" = xyes; then - KDRIVEFBDEVLIB=yes - AC_DEFINE(KDRIVEFBDEV, 1, [Build fbdev-based kdrive server]) - fi - - - PKG_CHECK_MODULES([TSLIB], [tslib-0.0], [HAVE_TSLIB="yes"], [HAVE_TSLIB="no"]) - if test "x$HAVE_TSLIB" = xno; then - AC_CHECK_LIB(ts, ts_open, [HAVE_TSLIB="yes"]) - fi - - if test "xTSLIB" = xauto; then - TSLIB="$HAVE_TSLIB" - fi - - if test "x$TSLIB" = xyes; then - if ! test "x$HAVE_TSLIB" = xyes; then - AC_MSG_ERROR([tslib must be installed to build the tslib driver. See http://tslib.berlios.de/]) - else - AC_DEFINE(TSLIB, 1, [Have tslib support]) - fi - fi - - if test "x$KDRIVE_KBD" = xyes; then - AC_DEFINE(KDRIVE_KBD, 1, [Enable KDrive kbd driver]) - fi - if test "x$KDRIVE_EVDEV" = xyes; then - AC_DEFINE(KDRIVE_EVDEV, 1, [Enable KDrive evdev driver]) - fi - if test "x$KDRIVE_MOUSE" = xyes; then - AC_DEFINE(KDRIVE_MOUSE, 1, [Enable KDrive mouse driver]) - fi - - XEPHYR_REQUIRED_LIBS="x11 $LIBXEXT xfont xau xdmcp" - if test "x$XV" = xyes; then - XEPHYR_REQUIRED_LIBS="$XEPHYR_REQUIRED_LIBS xv" - fi - if test "x$DRI" = xyes && test "x$GLX" = xyes; then - XEPHYR_REQUIRED_LIBS="$XEPHYR_REQUIRED_LIBS $LIBGL libdrm" - fi - - PKG_CHECK_MODULES(XEPHYR, $XEPHYR_REQUIRED_LIBS, [xephyr="yes"], [xephyr="no"]) - if test "x$XEPHYR" = xauto; then - XEPHYR=$xephyr - fi - - # Xephyr needs nanosleep() which is in librt on Solaris - AC_CHECK_FUNC([nanosleep], [], - AC_CHECK_LIB([rt], [nanosleep], XEPHYR_LIBS="$XEPHYR_LIBS -lrt")) - - # damage shadow extension glx (NOTYET) fb mi - KDRIVE_INC='-I$(top_srcdir)/hw/kdrive/src' - KDRIVE_PURE_INCS="$KDRIVE_INC $MIEXT_DAMAGE_INC $MIEXT_SHADOW_INC $XEXT_INC $FB_INC $MI_INC" - KDRIVE_OS_INC='-I$(top_srcdir)/hw/kdrive/linux' - KDRIVE_INCS="$KDRIVE_PURE_INCS $KDRIVE_OS_INC" - - 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_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*) - KDRIVE_OS_LIB='$(top_builddir)/hw/kdrive/linux/liblinux.la' - KDRIVELINUX=yes - if test "x$KDRIVE_EVDEV" = xauto; then - KDRIVE_EVDEV=yes - fi - if test "x$KDRIVE_KBD" = xauto; then - KDRIVE_KBD=yes - fi - if test "x$KDRIVE_MOUSE" = xauto; then - KDRIVE_MOUSE=yes - fi - ;; - *) - if test "x$KDRIVE_EVDEV" = xauto; then - KDRIVE_EVDEV=no - fi - if test "x$KDRIVE_KBD" = xauto; then - KDRIVE_KBD=no - fi - if test "x$KDRIVE_MOUSE" = xauto; then - KDRIVE_MOUSE=no - fi - ;; - esac - KDRIVE_STUB_LIB='$(top_builddir)/hw/kdrive/src/libkdrivestubs.la' - KDRIVE_LOCAL_LIBS="$MAIN_LIB $DIX_LIB $KDRIVE_LIB $KDRIVE_STUB_LIB $CONFIG_LIB" - KDRIVE_LOCAL_LIBS="$KDRIVE_LOCAL_LIBS $FB_LIB $MI_LIB $KDRIVE_PURE_LIBS" - KDRIVE_LOCAL_LIBS="$KDRIVE_LOCAL_LIBS $KDRIVE_OS_LIB $OS_LIB" - KDRIVE_LIBS="$TSLIB_LIBS $KDRIVE_LOCAL_LIBS $XSERVER_SYS_LIBS $GLX_SYS_LIBS $DLOPEN_LIBS" - - AC_SUBST([XEPHYR_LIBS]) - AC_SUBST([XEPHYR_INCS]) -fi -AC_SUBST([KDRIVE_INCS]) -AC_SUBST([KDRIVE_PURE_INCS]) -AC_SUBST([KDRIVE_CFLAGS]) -AC_SUBST([KDRIVE_PURE_LIBS]) -AC_SUBST([KDRIVE_LOCAL_LIBS]) -AC_SUBST([KDRIVE_LIBS]) -AM_CONDITIONAL(KDRIVELINUX, [test "x$KDRIVELINUX" = xyes]) -AM_CONDITIONAL(KDRIVE_EVDEV, [test "x$KDRIVE_EVDEV" = xyes]) -AM_CONDITIONAL(KDRIVE_KBD, [test "x$KDRIVE_KBD" = xyes]) -AM_CONDITIONAL(KDRIVE_MOUSE, [test "x$KDRIVE_MOUSE" = xyes]) -AM_CONDITIONAL(TSLIB, [test "x$HAVE_TSLIB" = xyes]) -AM_CONDITIONAL(KDRIVEFBDEV, [test "x$XFBDEV" = xyes]) -AM_CONDITIONAL(XEPHYR, [test "x$KDRIVE" = xyes && test "x$XEPHYR" = xyes]) -AM_CONDITIONAL(BUILD_KDRIVEFBDEVLIB, [test "x$KDRIVE" = xyes && test "x$KDRIVEFBDEVLIB" = xyes]) -AM_CONDITIONAL(XFAKESERVER, [test "x$KDRIVE" = xyes && test "x$XFAKE" = xyes]) - -dnl and the rest of these are generic, so they're in config.h -dnl -dnl though, thanks to the passing of some significant amount of time, the -dnl above is probably a complete fallacy, and you should not rely on it. -dnl but this is still actually better than imake, honest. -daniels - -AC_TRY_COMPILE([ -#include -#ifndef __GLIBC__ -#error not glibc -#endif -], [], [AC_DEFINE(_GNU_SOURCE, 1, - [ Enable GNU and other extensions to the C environment for glibc])]) - -AC_DEFINE_DIR(PROJECTROOT, prefix, [Overall prefix]) - -BUILD_DATE="`date +'%Y%m%d'`" -AC_SUBST([BUILD_DATE]) -BUILD_TIME="`date +'1%H%M%S'`" -AC_SUBST([BUILD_TIME]) - -DIX_CFLAGS="-DHAVE_DIX_CONFIG_H $XSERVER_CFLAGS" - -AC_SUBST([DIX_CFLAGS]) - -AC_SUBST([libdir]) -AC_SUBST([exec_prefix]) -AC_SUBST([prefix]) - -AC_OUTPUT([ -Makefile -glx/Makefile -include/Makefile -composite/Makefile -damageext/Makefile -dbe/Makefile -dix/Makefile -doc/Makefile -fb/Makefile -record/Makefile -config/Makefile -mi/Makefile -miext/Makefile -miext/damage/Makefile -miext/shadow/Makefile -miext/cw/Makefile -miext/rootless/Makefile -os/Makefile -randr/Makefile -render/Makefile -xkb/Makefile -Xext/Makefile -Xi/Makefile -xfixes/Makefile -exa/Makefile -hw/Makefile -hw/xfree86/Makefile -hw/xfree86/common/Makefile -hw/xfree86/common/xf86Build.h -hw/xfree86/ddc/Makefile -hw/xfree86/dixmods/Makefile -hw/xfree86/dixmods/extmod/Makefile -hw/xfree86/doc/Makefile -hw/xfree86/doc/devel/Makefile -hw/xfree86/doc/man/Makefile -hw/xfree86/doc/sgml/Makefile -hw/xfree86/dri/Makefile -hw/xfree86/dri2/Makefile -hw/xfree86/exa/Makefile -hw/xfree86/fbdevhw/Makefile -hw/xfree86/i2c/Makefile -hw/xfree86/int10/Makefile -hw/xfree86/loader/Makefile -hw/xfree86/modes/Makefile -hw/xfree86/os-support/Makefile -hw/xfree86/os-support/bsd/Makefile -hw/xfree86/os-support/bus/Makefile -hw/xfree86/os-support/hurd/Makefile -hw/xfree86/os-support/misc/Makefile -hw/xfree86/os-support/linux/Makefile -hw/xfree86/os-support/sco/Makefile -hw/xfree86/os-support/solaris/Makefile -hw/xfree86/os-support/sysv/Makefile -hw/xfree86/parser/Makefile -hw/xfree86/ramdac/Makefile -hw/xfree86/shadowfb/Makefile -hw/xfree86/vbe/Makefile -hw/xfree86/vgahw/Makefile -hw/xfree86/x86emu/Makefile -hw/xfree86/xaa/Makefile -hw/xfree86/xf8_16bpp/Makefile -hw/xfree86/utils/Makefile -hw/xfree86/utils/cvt/Makefile -hw/xfree86/utils/gtf/Makefile -hw/dmx/config/Makefile -hw/dmx/doc/Makefile -hw/dmx/examples/Makefile -hw/dmx/input/Makefile -hw/dmx/glxProxy/Makefile -hw/dmx/Makefile -hw/vfb/Makefile -hw/xnest/Makefile -hw/xwin/Makefile -hw/xwin/glx/Makefile -hw/xquartz/Makefile -hw/xquartz/GL/Makefile -hw/xquartz/bundle/Makefile -hw/xquartz/doc/Makefile -hw/xquartz/mach-startup/Makefile -hw/xquartz/pbproxy/Makefile -hw/xquartz/xpr/Makefile -hw/kdrive/Makefile -hw/kdrive/ephyr/Makefile -hw/kdrive/fake/Makefile -hw/kdrive/fbdev/Makefile -hw/kdrive/linux/Makefile -hw/kdrive/src/Makefile -test/Makefile -test/xi2/Makefile -xorg-server.pc -]) +dnl Copyright © 2003-2007 Keith Packard, Daniel Stone +dnl +dnl Permission is hereby granted, free of charge, to any person obtaining a +dnl copy of this software and associated documentation files (the "Software"), +dnl to deal in the Software without restriction, including without limitation +dnl the rights to use, copy, modify, merge, publish, distribute, sublicense, +dnl and/or sell copies of the Software, and to permit persons to whom the +dnl Software is furnished to do so, subject to the following conditions: +dnl +dnl The above copyright notice and this permission notice (including the next +dnl paragraph) shall be included in all copies or substantial portions of the +dnl Software. +dnl +dnl THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +dnl IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +dnl FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +dnl THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +dnl LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +dnl FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +dnl DEALINGS IN THE SOFTWARE. +dnl +dnl Authors: Keith Packard +dnl Daniel Stone +dnl an unwitting cast of miscellaneous others +dnl +dnl Process this file with autoconf to create configure. + +AC_PREREQ(2.57) +AC_INIT([xorg-server], 1.8.99.0, [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], xorg-server) +RELEASE_DATE="unreleased" +AC_CONFIG_SRCDIR([Makefile.am]) +AM_INIT_AUTOMAKE([foreign dist-bzip2]) +AM_MAINTAINER_MODE + +# Require xorg-macros: XORG_DEFAULT_OPTIONS +m4_ifndef([XORG_MACROS_VERSION], + [m4_fatal([must install xorg-macros 1.6 or later before running autoconf/autogen])]) +XORG_MACROS_VERSION(1.6) +XORG_DEFAULT_OPTIONS +XORG_WITH_DOXYGEN(1.6.1) + +m4_ifndef([XORG_FONT_MACROS_VERSION], [m4_fatal([must install fontutil 1.1 or later before running autoconf/autogen])]) +XORG_FONT_MACROS_VERSION(1.1) + +dnl this gets generated by autoheader, and thus contains all the defines. we +dnl don't ever actually use it, internally. +AC_CONFIG_HEADERS(include/do-not-use-config.h) +dnl xorg-server.h is an external header, designed to be included by loadable +dnl drivers. +AC_CONFIG_HEADERS(include/xorg-server.h) +dnl dix-config.h covers most of the DIX (i.e. everything but the DDX, not just +dnl dix/). +AC_CONFIG_HEADERS(include/dix-config.h) +dnl xorg-config.h covers the Xorg DDX. +AC_CONFIG_HEADERS(include/xorg-config.h) +dnl xkb-config.h covers XKB for the Xorg and Xnest DDXs. +AC_CONFIG_HEADERS(include/xkb-config.h) +dnl xwin-config.h covers the XWin DDX. +AC_CONFIG_HEADERS(include/xwin-config.h) +dnl kdrive-config.h covers the kdrive DDX +AC_CONFIG_HEADERS(include/kdrive-config.h) +dnl version-config.h covers the version numbers so they can be bumped without +dnl forcing an entire recompile.x +AC_CONFIG_HEADERS(include/version-config.h) + +AC_PROG_CC +AM_PROG_AS +AC_PROG_INSTALL +AC_PROG_LN_S +AC_LIBTOOL_WIN32_DLL +AC_DISABLE_STATIC +AC_PROG_LIBTOOL +DOLT +AC_PROG_MAKE_SET +PKG_PROG_PKG_CONFIG +AC_PROG_LEX +AC_PROG_YACC +AC_SYS_LARGEFILE +XORG_PROG_RAWCPP +AC_PROG_SED + +# Quoted so that make will expand $(CWARNFLAGS) in makefiles to allow +# easier overrides at build time. +XSERVER_CFLAGS='$(CWARNFLAGS)' + +dnl Check for dtrace program (needed to build Xserver dtrace probes) +dnl Also checks for , since some Linux distros have an +dnl ISDN trace program named dtrace +AC_ARG_WITH(dtrace, AS_HELP_STRING([--with-dtrace=PATH], + [Enable dtrace probes (default: enabled if dtrace found)]), + [WDTRACE=$withval], [WDTRACE=auto]) +if test "x$WDTRACE" = "xyes" -o "x$WDTRACE" = "xauto" ; then + AC_PATH_PROG(DTRACE, [dtrace], [not_found], [$PATH:/usr/sbin]) + if test "x$DTRACE" = "xnot_found" ; then + if test "x$WDTRACE" = "xyes" ; then + AC_MSG_FAILURE([dtrace requested but not found]) + fi + WDTRACE="no" + else + AC_CHECK_HEADER(sys/sdt.h, [HAS_SDT_H="yes"], [HAS_SDT_H="no"]) + if test "x$WDTRACE" = "xauto" -a "x$HAS_SDT_H" = "xno" ; then + WDTRACE="no" + fi + fi +fi +if test "x$WDTRACE" != "xno" ; then + AC_DEFINE(XSERVER_DTRACE, 1, + [Define to 1 if the DTrace Xserver provider probes should be built in.]) + +# Solaris/OpenSolaris require dtrace -G to build dtrace probe information into +# object files, and require linking with those as relocatable objects, not .a +# archives. MacOS X handles all this in the normal compiler toolchain, and on +# some releases (like Tiger), will error out on dtrace -G. For now, other +# platforms with Dtrace ports are assumed to support -G (the FreeBSD and Linux +# ports appear to, based on my web searches, but have not yet been tested). + case $host_os in + darwin*) SPECIAL_DTRACE_OBJECTS=no ;; + *) SPECIAL_DTRACE_OBJECTS=yes ;; + esac +fi +AM_CONDITIONAL(XSERVER_DTRACE, [test "x$WDTRACE" != "xno"]) +AM_CONDITIONAL(SPECIAL_DTRACE_OBJECTS, [test "x$SPECIAL_DTRACE_OBJECTS" = "xyes"]) + +AC_HEADER_DIRENT +AC_HEADER_STDC +AC_CHECK_HEADERS([fcntl.h stdlib.h string.h unistd.h dlfcn.h stropts.h fnmatch.h]) + +dnl Checks for typedefs, structures, and compiler characteristics. +AC_C_CONST +AC_C_BIGENDIAN([ENDIAN="X_BIG_ENDIAN"], [ENDIAN="X_LITTLE_ENDIAN"]) + +AC_CHECK_SIZEOF([unsigned long]) +if test "$ac_cv_sizeof_unsigned_long" = 8; then + AC_DEFINE(_XSERVER64, 1, [Define to 1 if unsigned long is 64 bits.]) +fi + +AC_TYPE_PID_T + +# Checks for headers/macros for byte swapping +# Known variants: +# bswap_16, bswap_32, bswap_64 (glibc) +# __swap16, __swap32, __swap64 (OpenBSD) +# bswap16, bswap32, bswap64 (other BSD's) +# and a fallback to local macros if none of the above are found + +# if is found, assume it's the correct version +AC_CHECK_HEADERS([byteswap.h]) + +# if is found, have to check which version +AC_CHECK_HEADER([sys/endian.h], [HAVE_SYS_ENDIAN_H="yes"], [HAVE_SYS_ENDIAN_H="no"]) + +if test "x$HAVE_SYS_ENDIAN_H" = "xyes" ; then + AC_MSG_CHECKING([for __swap16 variant of byteswapping macros]) + AC_LINK_IFELSE([AC_LANG_PROGRAM([ +#include +#include + ], [ +int a = 1, b; +b = __swap16(a); + ]) +], [SYS_ENDIAN__SWAP='yes'], [SYS_ENDIAN__SWAP='no']) + AC_MSG_RESULT([$SYS_ENDIAN__SWAP]) + + AC_MSG_CHECKING([for bswap16 variant of byteswapping macros]) + AC_LINK_IFELSE([AC_LANG_PROGRAM([ +#include +#include + ], [ +int a = 1, b; +b = bswap16(a); + ]) +], [SYS_ENDIAN_BSWAP='yes'], [SYS_ENDIAN_BSWAP='no']) + AC_MSG_RESULT([$SYS_ENDIAN_BSWAP]) + + if test "$SYS_ENDIAN_BSWAP" = "yes" ; then + USE_SYS_ENDIAN_H=yes + BSWAP=bswap + else + if test "$SYS_ENDIAN__SWAP" = "yes" ; then + USE_SYS_ENDIAN_H=yes + BSWAP=__swap + else + USE_SYS_ENDIAN_H=no + fi + fi + + if test "$USE_SYS_ENDIAN_H" = "yes" ; then + AC_DEFINE([USE_SYS_ENDIAN_H], 1, + [Define to use byteswap macros from ]) + AC_DEFINE_UNQUOTED([bswap_16], ${BSWAP}16, + [Define to 16-bit byteswap macro]) + AC_DEFINE_UNQUOTED([bswap_32], ${BSWAP}32, + [Define to 32-bit byteswap macro]) + AC_DEFINE_UNQUOTED([bswap_64], ${BSWAP}64, + [Define to 64-bit byteswap macro]) + fi +fi + +dnl Check to see if dlopen is in default libraries (like Solaris, which +dnl has it in libc), or if libdl is needed to get it. +AC_CHECK_FUNC([dlopen], [], + AC_CHECK_LIB([dl], [dlopen], DLOPEN_LIBS="-ldl")) +AC_SUBST(DLOPEN_LIBS) + +dnl Checks for library functions. +AC_FUNC_VPRINTF +AC_CHECK_FUNCS([geteuid getuid link memmove memset mkstemp strchr strrchr \ + strtol getopt getopt_long vsnprintf walkcontext backtrace \ + getisax getzoneid shmctl64 strcasestr ffs]) +AC_FUNC_ALLOCA +dnl Old HAS_* names used in os/*.c. +AC_CHECK_FUNC([getdtablesize], + AC_DEFINE(HAS_GETDTABLESIZE, 1, [Have the 'getdtablesize' function.])) +AC_CHECK_FUNC([getifaddrs], + AC_DEFINE(HAS_GETIFADDRS, 1, [Have the 'getifaddrs' function.])) +AC_CHECK_FUNC([getpeereid], + AC_DEFINE(HAS_GETPEEREID, 1, [Have the 'getpeereid' function.])) +AC_CHECK_FUNC([getpeerucred], + AC_DEFINE(HAS_GETPEERUCRED, 1, [Have the 'getpeerucred' function.])) +AC_CHECK_FUNC([strlcat], HAVE_STRLCAT=yes, HAVE_STRLCAT=no) +AM_CONDITIONAL(NEED_STRLCAT, [test x$HAVE_STRLCAT = xno]) +AC_CHECK_FUNC([strlcpy], AC_DEFINE(HAS_STRLCPY, 1, [Have the 'strlcpy' function])) + +AM_CONDITIONAL(NEED_VSNPRINTF, [test x$HAVE_VSNPRINTF = xno]) + +dnl Check for mmap support for Xvfb +AC_CHECK_FUNC([mmap], AC_DEFINE(HAS_MMAP, 1, [Have the 'mmap' function.])) + +dnl Find the math libary +AC_CHECK_LIB(m, sqrt) +AC_CHECK_LIB(m, cbrt, AC_DEFINE(HAVE_CBRT, 1, [Have the 'cbrt' function])) + +AC_CHECK_HEADERS([ndbm.h dbm.h rpcsvc/dbm.h]) + +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]) + +dnl MTRR header +AC_CHECK_HEADERS([asm/mtrr.h], ac_cv_asm_mtrr_h=yes) +if test "x$ac_cv_asm_mtrr_h" = xyes; then + HAVE_MTRR=yes +fi + +dnl BSD MTRR header +AC_CHECK_HEADERS([sys/memrange.h], ac_cv_memrange_h=yes) +if test "x$ac_cv_memrange_h" = xyes; then + HAVE_MTRR=yes +fi + +if test "x$HAVE_MTRR" = xyes; then + AC_DEFINE(HAS_MTRR_SUPPORT, 1, [MTRR support available]) +fi + +dnl A NetBSD MTRR header +AC_CHECK_HEADERS([machine/mtrr.h], ac_cv_machine_mtrr_h=yes) +if test "x$ac_cv_machine_mtrr_h" = xyes; then + AC_DEFINE(HAS_MTRR_BUILTIN, 1, [Define to 1 if NetBSD built-in MTRR + support is available]) +fi + +dnl FreeBSD kldload support (sys/linker.h) +AC_CHECK_HEADERS([sys/linker.h], + [ac_cv_sys_linker_h=yes], + [ac_cv_sys_linker_h=no], + [#include ]) +AM_CONDITIONAL(FREEBSD_KLDLOAD, [test "x$ac_cv_sys_linker_h" = xyes]) + +AC_CACHE_CHECK([for SYSV IPC], + ac_cv_sysv_ipc, + [AC_TRY_LINK([ +#include +#include +#include +],[ +{ + int id; + id = shmget(IPC_PRIVATE, 512, SHM_W | SHM_R); + if (id < 0) return -1; + return shmctl(id, IPC_RMID, 0); +}], + [ac_cv_sysv_ipc=yes], + [ac_cv_sysv_ipc=no])]) +if test "x$ac_cv_sysv_ipc" = xyes; then + AC_DEFINE(HAVE_SYSV_IPC, 1, [Define to 1 if SYSV IPC is available]) +fi + +dnl OpenBSD /dev/xf86 aperture driver +if test -c /dev/xf86 ; then + AC_DEFINE(HAS_APERTURE_DRV, 1, [System has /dev/xf86 aperture driver]) +fi + +dnl BSD APM support +AC_CHECK_HEADER([machine/apmvar.h],[ + AC_CHECK_HEADER([sys/event.h], + ac_cv_BSD_KQUEUE_APM=yes, + ac_cv_BSD_APM=yes)]) + +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) +AC_CHECK_HEADER([execinfo.h],[ + AC_CHECK_LIB(c, backtrace, [ + AC_DEFINE(HAVE_BACKTRACE, 1, [Has backtrace support]) + AC_DEFINE(HAVE_EXECINFO_H, 1, [Have execinfo.h]) + ])] +) + +dnl ARM needs additional compiler flags for proper backtraces if GCC is +dnl used. Compile a dummy program with the -mapcs-frame option. If it +dnl succeeds, we know that we are building for ARM with GCC. +old_CFLAGS="$CFLAGS" +CFLAGS="-mapcs-frame" +AC_COMPILE_IFELSE( + AC_LANG_PROGRAM([[ ]]), + ARM_BACKTRACE_CFLAGS="$CFLAGS", + ARM_BACKTRACE_CFLAGS="" +) +CFLAGS="$old_CFLAGS" +AC_SUBST(ARM_BACKTRACE_CFLAGS) + +dnl --------------------------------------------------------------------------- +dnl Bus options and CPU capabilities. Replaces logic in +dnl hw/xfree86/os-support/bus/Makefile.am, among others. +dnl --------------------------------------------------------------------------- +DEFAULT_INT10="x86emu" + +dnl Override defaults as needed for specific platforms: + +case $host_cpu in + alpha*) + ALPHA_VIDEO=yes + case $host_os in + *freebsd*) SYS_LIBS=-lio ;; + *netbsd*) AC_DEFINE(USE_ALPHA_PIO, 1, [NetBSD PIO alpha IO]) ;; + esac + GLX_ARCH_DEFINES="-D__GLX_ALIGN64 -mieee" + ;; + arm*) + ARM_VIDEO=yes + ;; + i*86) + I386_VIDEO=yes + case $host_os in + *freebsd*) AC_DEFINE(USE_DEV_IO) ;; + *dragonfly*) AC_DEFINE(USE_DEV_IO) ;; + *netbsd*) AC_DEFINE(USE_I386_IOPL) + SYS_LIBS=-li386 + ;; + *openbsd*) AC_DEFINE(USE_I386_IOPL) + SYS_LIBS=-li386 + ;; + esac + ;; + powerpc*) + PPC_VIDEO=yes + case $host_os in + *freebsd*) DEFAULT_INT10=stub ;; + esac + ;; + sparc*) + SPARC64_VIDEO=yes + BSD_ARCH_SOURCES="sparc64_video.c ioperm_noop.c" + GLX_ARCH_DEFINES="-D__GLX_ALIGN64" + ;; + x86_64*|amd64*) + I386_VIDEO=yes + case $host_os in + *freebsd*) AC_DEFINE(USE_DEV_IO, 1, [BSD /dev/io]) ;; + *dragonfly*) AC_DEFINE(USE_DEV_IO, 1, [BSD /dev/io]) ;; + *netbsd*) AC_DEFINE(USE_I386_IOPL, 1, [BSD i386 iopl]) + SYS_LIBS=-lx86_64 + ;; + *openbsd*) AC_DEFINE(USE_AMD64_IOPL, 1, [BSD AMD64 iopl]) + SYS_LIBS=-lamd64 + ;; + esac + GLX_ARCH_DEFINES="-D__GLX_ALIGN64" + ;; + ia64*) + GLX_ARCH_DEFINES="-D__GLX_ALIGN64" + ;; + s390*) + GLX_ARCH_DEFINES="-D__GLX_ALIGN64" + ;; +esac +AC_SUBST(GLX_ARCH_DEFINES) + +dnl BSD *_video.c selection +AM_CONDITIONAL(ALPHA_VIDEO, [test "x$ALPHA_VIDEO" = xyes]) +AM_CONDITIONAL(ARM_VIDEO, [test "x$ARM_VIDEO" = xyes]) +AM_CONDITIONAL(I386_VIDEO, [test "x$I386_VIDEO" = xyes]) +AM_CONDITIONAL(PPC_VIDEO, [test "x$PPC_VIDEO" = xyes]) +AM_CONDITIONAL(SPARC64_VIDEO, [test "x$SPARC64_VIDEO" = xyes]) + +DRI=no +USE_SIGIO_BY_DEFAULT="yes" +dnl it would be nice to autodetect these *CONS_SUPPORTs +case $host_os in + *freebsd* | *dragonfly*) + case $host_os in + kfreebsd*-gnu) ;; + *) AC_DEFINE(CSRG_BASED, 1, [System is BSD-like]) ;; + esac + AC_DEFINE(PCCONS_SUPPORT, 1, [System has PC console]) + AC_DEFINE(PCVT_SUPPORT, 1, [System has PCVT console]) + AC_DEFINE(SYSCONS_SUPPORT, 1, [System has syscons console]) + DRI=yes + ;; + *netbsd*) + AC_DEFINE(CSRG_BASED, 1, [System is BSD-like]) + AC_DEFINE(PCCONS_SUPPORT, 1, [System has PC console]) + AC_DEFINE(PCVT_SUPPORT, 1, [System has PCVT console]) + AC_DEFINE(WSCONS_SUPPORT, 1, [System has wscons console]) + DRI=yes + ;; + *openbsd*) + AC_DEFINE(CSRG_BASED, 1, [System is BSD-like]) + AC_DEFINE(PCVT_SUPPORT, 1, [System has PC console]) + AC_DEFINE(WSCONS_SUPPORT, 1, [System has wscons console]) + ;; + *linux*) + DRI=yes + ;; + *solaris*) + PKG_CHECK_EXISTS(libdrm, DRI=yes, DRI=no) + # Disable use of SIGIO by default until some system bugs are + # fixed - see Sun/OpenSolaris bug id 6879897 + USE_SIGIO_BY_DEFAULT="no" + ;; + darwin*) + AC_DEFINE(CSRG_BASED, 1, [System is BSD-like]) + ;; + cygwin*) + CFLAGS="$CFLAGS -DFD_SETSIZE=256" + ;; +esac + +dnl augment XORG_RELEASE_VERSION for our snapshot number and to expose the +dnl major number +PVMAJOR=`echo $PACKAGE_VERSION | cut -d . -f 1` +PVS=`echo $PACKAGE_VERSION | cut -d . -f 4 | cut -d - -f 1` +if test "x$PVS" = "x"; then + PVS="0" +fi + +VENDOR_RELEASE="((($PVMAJOR) * 10000000) + (($PVM) * 100000) + (($PVP) * 1000) + $PVS)" +VENDOR_MAN_VERSION="Version ${PACKAGE_VERSION}" + +VENDOR_NAME="The X.Org Foundation" +VENDOR_NAME_SHORT="X.Org" +VENDOR_WEB="http://wiki.x.org" + +m4_ifdef([AS_HELP_STRING], , [m4_define([AS_HELP_STRING], m4_defn([AC_HELP_STRING]))]) + +dnl Build options. +AC_ARG_ENABLE(werror, AS_HELP_STRING([--enable-werror], + [Obsolete - use --enable-strict-compilation instead]), + AC_MSG_ERROR([--enable-werror has been replaced by --enable-strict-compilation])) + +AC_ARG_ENABLE(debug, AS_HELP_STRING([--enable-debug], + [Enable debugging (default: disabled)]), + [DEBUGGING=$enableval], [DEBUGGING=no]) +AC_ARG_ENABLE(unit-tests, AS_HELP_STRING([--enable-unit-tests], + [Enable unit-tests (default: auto)]), + [UNITTESTS=$enableval], [UNITTESTS=auto]) +AC_ARG_ENABLE(use-sigio-by-default, AS_HELP_STRING([--enable-use-sigio-by-default] + [Enable SIGIO input handlers by default (default: $USE_SIGIO_BY_DEFAULT)]), + [USE_SIGIO_BY_DEFAULT=$enableval], []) +AC_ARG_WITH(int10, AS_HELP_STRING([--with-int10=BACKEND], [int10 backend: vm86, x86emu or stub]), + [INT10="$withval"], + [INT10="$DEFAULT_INT10"]) +AC_ARG_WITH(vendor-name, AS_HELP_STRING([--with-vendor-name=VENDOR], + [Vendor string reported by the server]), + [ VENDOR_NAME="$withval" ], []) +AC_ARG_WITH(vendor-name-short, AS_HELP_STRING([--with-vendor-name-short=VENDOR], + [Short version of vendor string reported by the server]), + [ VENDOR_NAME_SHORT="$withval" ], []) +AC_ARG_WITH(vendor-web, AS_HELP_STRING([--with-vendor-web=URL], + [Vendor web address reported by the server]), + [ VENDOR_WEB="$withval" ], []) +AC_ARG_WITH(module-dir, AS_HELP_STRING([--with-module-dir=DIR], + [Directory where modules are installed (default: $libdir/xorg/modules)]), + [ moduledir="$withval" ], + [ moduledir="${libdir}/xorg/modules" ]) +AC_ARG_WITH(log-dir, AS_HELP_STRING([--with-log-dir=DIR], + [Directory where log files are kept (default: $localstatedir/log)]), + [ logdir="$withval" ], + [ logdir="$localstatedir/log" ]) +AC_ARG_WITH(builder-addr, AS_HELP_STRING([--with-builder-addr=ADDRESS], + [Builder address (default: xorg@lists.freedesktop.org)]), + [ BUILDERADDR="$withval" ], + [ BUILDERADDR="xorg@lists.freedesktop.org" ]) +AC_ARG_WITH(os-name, AS_HELP_STRING([--with-os-name=OSNAME], [Name of OS (default: output of "uname -srm")]), + [ OSNAME="$withval" ], + [ OSNAME=`uname -srm` ]) +AC_ARG_WITH(os-vendor, AS_HELP_STRING([--with-os-vendor=OSVENDOR], [Name of OS vendor]), + [ OSVENDOR="$withval" ], + [ OSVENDOR="" ]) +AC_ARG_WITH(builderstring, AS_HELP_STRING([--with-builderstring=BUILDERSTRING], [Additional builder string]), + [ BUILDERSTRING="$withval" ] + [ ]) + +dnl Determine font path +XORG_FONTROOTDIR +XORG_FONTSUBDIR(FONTMISCDIR, fontmiscdir, misc) +XORG_FONTSUBDIR(FONTOTFDIR, fontotfdir, OTF) +XORG_FONTSUBDIR(FONTTTFDIR, fontttfdir, TTF) +XORG_FONTSUBDIR(FONTTYPE1DIR, fonttype1dir, Type1) +XORG_FONTSUBDIR(FONT75DPIDIR, font75dpidir, 75dpi) +XORG_FONTSUBDIR(FONT100DPIDIR, font100dpidir, 100dpi) + +dnl Uses --default-font-path if set, otherwise checks for /etc/X11/fontpath.d, +dnl otherwise uses standard subdirectories of FONTROOTDIR. When cross +dnl compiling, assume default font path uses standard FONTROOTDIR directories. +DEFAULT_FONT_PATH="${FONTMISCDIR}/,${FONTTTFDIR}/,${FONTOTFDIR}/,${FONTTYPE1DIR}/,${FONT100DPIDIR}/,${FONT75DPIDIR}/" +if test "$cross_compiling" != yes; then + AC_CHECK_FILE([${sysconfdir}/X11/fontpath.d], + [DEFAULT_FONT_PATH='catalogue:${sysconfdir}/X11/fontpath.d'], + [case $host_os in + darwin*) DEFAULT_FONT_PATH="${DEFAULT_FONT_PATH},/Library/Fonts,/System/Library/Fonts" ;; + esac]) +fi +AC_ARG_WITH(default-font-path, AS_HELP_STRING([--with-default-font-path=PATH], [Comma separated list of font dirs]), + [ FONTPATH="$withval" ], + [ FONTPATH="${DEFAULT_FONT_PATH}" ]) + +AC_MSG_CHECKING([for default font path]) +AC_MSG_RESULT([$FONTPATH]) + +AC_ARG_WITH(xkb-path, AS_HELP_STRING([--with-xkb-path=PATH], [Path to XKB base dir (default: ${datadir}/X11/xkb)]), + [ XKBPATH="$withval" ], + [ XKBPATH="${datadir}/X11/xkb" ]) +AC_ARG_WITH(xkb-output, AS_HELP_STRING([--with-xkb-output=PATH], [Path to XKB output dir (default: ${datadir}/X11/xkb/compiled)]), + [ XKBOUTPUT="$withval" ], + [ XKBOUTPUT="compiled" ]) +AC_ARG_WITH(default-xkb-rules, AS_HELP_STRING([--with-default-xkb-rules=RULES], + [Keyboard ruleset (default: base/evdev)]), + [ XKB_DFLT_RULES="$withval" ], + [ XKB_DFLT_RULES="" ]) +AC_ARG_WITH(default-xkb-model, AS_HELP_STRING([--with-default-xkb-model=MODEL], + [Keyboard model (default: pc105)]), + [ XKB_DFLT_MODEL="$withval" ], + [ XKB_DFLT_MODEL="pc105" ]) +AC_ARG_WITH(default-xkb-layout, AS_HELP_STRING([--with-default-xkb-layout=LAYOUT], + [Keyboard layout (default: us)]), + [ XKB_DFLT_LAYOUT="$withval" ], + [ XKB_DFLT_LAYOUT="us" ]) +AC_ARG_WITH(default-xkb-variant, AS_HELP_STRING([--with-default-xkb-variant=VARIANT], + [Keyboard variant (default: (none))]), + [ XKB_DFLT_VARIANT="$withval" ], + [ XKB_DFLT_VARIANT="" ]) +AC_ARG_WITH(default-xkb-options, AS_HELP_STRING([--with-default-xkb-options=OPTIONS], + [Keyboard layout options (default: (none))]), + [ XKB_DFLT_OPTIONS="$withval" ], + [ XKB_DFLT_OPTIONS="" ]) +AC_ARG_WITH(serverconfig-path, AS_HELP_STRING([--with-serverconfig-path=PATH], + [Directory where ancillary server config files are installed (default: ${libdir}/xorg)]), + [ SERVERCONFIG="$withval" ], + [ SERVERCONFIG="${libdir}/xorg" ]) +AC_ARG_WITH(apple-applications-dir,AS_HELP_STRING([--with-apple-applications-dir=PATH], [Path to the Applications directory (default: /Applications/Utilities)]), + [ APPLE_APPLICATIONS_DIR="${withval}" ], + [ APPLE_APPLICATIONS_DIR="/Applications/Utilities" ]) +AC_SUBST([APPLE_APPLICATIONS_DIR]) +AC_ARG_WITH(apple-application-name,AS_HELP_STRING([--with-apple-application-name=NAME], [Name for the .app (default: X11)]), + [ APPLE_APPLICATION_NAME="${withval}" ], + [ APPLE_APPLICATION_NAME="X11" ]) +AC_SUBST([APPLE_APPLICATION_NAME]) +AC_ARG_WITH(launchd-id-prefix, AS_HELP_STRING([--with-launchd-id-prefix=PATH], [Prefix to use for launchd identifiers (default: org.x)]), + [ LAUNCHD_ID_PREFIX="${withval}" ], + [ LAUNCHD_ID_PREFIX="org.x" ]) +AC_SUBST([LAUNCHD_ID_PREFIX]) +AC_DEFINE_UNQUOTED(LAUNCHD_ID_PREFIX, "$LAUNCHD_ID_PREFIX", [Prefix to use for launchd identifiers]) +AC_ARG_ENABLE(sparkle,AS_HELP_STRING([--enable-sparkle], [Enable updating of X11.app using the Sparkle Framework (default: disabled)]), + [ XQUARTZ_SPARKLE="${enableval}" ], + [ XQUARTZ_SPARKLE="no" ]) +AC_SUBST([XQUARTZ_SPARKLE]) +AC_ARG_ENABLE(builddocs, AS_HELP_STRING([--enable-builddocs], [Build docs (default: disabled)]), + [BUILDDOCS=$enableval], + [BUILDDOCS=no]) +AC_ARG_ENABLE(install-libxf86config, + AS_HELP_STRING([--enable-install-libxf86config], + [Install libxf86config (default: disabled)]), + [INSTALL_LIBXF86CONFIG=$enableval], + [INSTALL_LIBXF86CONFIG=no]) +AC_ARG_ENABLE(visibility, AC_HELP_STRING([--enable-visibility], [Enable symbol visibility (default: auto)]), + [SYMBOL_VISIBILITY=$enableval], + [SYMBOL_VISIBILITY=auto]) +AC_ARG_ENABLE(pc98, AC_HELP_STRING([--enable-pc98], [Enable PC98 support in Xorg (default: auto)]), + [SUPPORT_PC98=$enableval], + [SUPPORT_PC98=auto]) + +dnl GLX build options +AC_ARG_WITH(dri-driver-path, AS_HELP_STRING([--with-dri-driver-path=PATH], [Path to DRI drivers (default: ${libdir}/dri)]), + [ DRI_DRIVER_PATH="$withval" ], + [ DRI_DRIVER_PATH="${libdir}/dri" ]) +AC_ARG_ENABLE(aiglx, AS_HELP_STRING([--enable-aiglx], [Build accelerated indirect GLX (default: enabled)]), + [AIGLX=$enableval], + [AIGLX=yes]) +AC_ARG_ENABLE(glx-tls, AS_HELP_STRING([--enable-glx-tls], [Build GLX with TLS support (default: disabled)]), + [GLX_USE_TLS=$enableval], + [GLX_USE_TLS=no]) + +dnl Extensions. +AC_ARG_ENABLE(registry, AS_HELP_STRING([--disable-registry], [Build string registry module (default: enabled)]), [XREGISTRY=$enableval], [XREGISTRY=yes]) +AC_ARG_ENABLE(composite, AS_HELP_STRING([--disable-composite], [Build Composite extension (default: enabled)]), [COMPOSITE=$enableval], [COMPOSITE=yes]) +AC_ARG_ENABLE(mitshm, AS_HELP_STRING([--disable-shm], [Build SHM extension (default: enabled)]), [MITSHM=$enableval], [MITSHM=yes]) +AC_ARG_ENABLE(xres, AS_HELP_STRING([--disable-xres], [Build XRes extension (default: enabled)]), [RES=$enableval], [RES=yes]) +AC_ARG_ENABLE(record, AS_HELP_STRING([--disable-record], [Build Record extension (default: enabled)]), [RECORD=$enableval], [RECORD=yes]) +AC_ARG_ENABLE(xv, AS_HELP_STRING([--disable-xv], [Build Xv extension (default: enabled)]), [XV=$enableval], [XV=yes]) +AC_ARG_ENABLE(xvmc, AS_HELP_STRING([--disable-xvmc], [Build XvMC extension (default: enabled)]), [XVMC=$enableval], [XVMC=yes]) +AC_ARG_ENABLE(dga, AS_HELP_STRING([--disable-dga], [Build DGA extension (default: auto)]), [DGA=$enableval], [DGA=auto]) +AC_ARG_ENABLE(screensaver, AS_HELP_STRING([--disable-screensaver], [Build ScreenSaver extension (default: enabled)]), [SCREENSAVER=$enableval], [SCREENSAVER=yes]) +AC_ARG_ENABLE(xdmcp, AS_HELP_STRING([--disable-xdmcp], [Build XDMCP extension (default: auto)]), [XDMCP=$enableval], [XDMCP=auto]) +AC_ARG_ENABLE(xdm-auth-1, AS_HELP_STRING([--disable-xdm-auth-1], [Build XDM-Auth-1 extension (default: auto)]), [XDMAUTH=$enableval], [XDMAUTH=auto]) +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(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]) +AC_ARG_ENABLE(xselinux, AS_HELP_STRING([--enable-xselinux], [Build SELinux extension (default: disabled)]), [XSELINUX=$enableval], [XSELINUX=no]) +AC_ARG_ENABLE(xcsecurity, AS_HELP_STRING([--enable-xcsecurity], [Build Security extension (default: disabled)]), [XCSECURITY=$enableval], [XCSECURITY=no]) +AC_ARG_ENABLE(xcalibrate, AS_HELP_STRING([--enable-xcalibrate], [Build XCalibrate extension (default: disabled)]), [XCALIBRATE=$enableval], [XCALIBRATE=no]) +AC_ARG_ENABLE(tslib, AS_HELP_STRING([--enable-tslib], [Build kdrive tslib touchscreen support (default: disabled)]), [TSLIB=$enableval], [TSLIB=no]) +AC_ARG_ENABLE(dbe, AS_HELP_STRING([--disable-dbe], [Build DBE extension (default: enabled)]), [DBE=$enableval], [DBE=yes]) +AC_ARG_ENABLE(xf86bigfont, AS_HELP_STRING([--enable-xf86bigfont], [Build XF86 Big Font extension (default: disabled)]), [XF86BIGFONT=$enableval], [XF86BIGFONT=no]) +AC_ARG_ENABLE(dpms, AS_HELP_STRING([--disable-dpms], [Build DPMS extension (default: enabled)]), [DPMSExtension=$enableval], [DPMSExtension=yes]) +AC_ARG_ENABLE(config-udev, AS_HELP_STRING([--enable-config-udev], [Build udev support (default: auto)]), [CONFIG_UDEV=$enableval], [CONFIG_UDEV=auto]) +AC_ARG_ENABLE(config-dbus, AS_HELP_STRING([--enable-config-dbus], [Build D-BUS API support (default: no)]), [CONFIG_DBUS_API=$enableval], [CONFIG_DBUS_API=no]) +AC_ARG_ENABLE(config-hal, AS_HELP_STRING([--disable-config-hal], [Build HAL support (default: auto)]), [CONFIG_HAL=$enableval], [CONFIG_HAL=auto]) +AC_ARG_ENABLE(xfree86-utils, AS_HELP_STRING([--enable-xfree86-utils], [Build xfree86 DDX utilities (default: enabled)]), [XF86UTILS=$enableval], [XF86UTILS=yes]) +AC_ARG_ENABLE(xaa, AS_HELP_STRING([--enable-xaa], [Build XAA (default: enabled)]), [XAA=$enableval], [XAA=yes]) +AC_ARG_ENABLE(vgahw, AS_HELP_STRING([--enable-vgahw], [Build Xorg with vga access (default: enabled)]), [VGAHW=$enableval], [VGAHW=yes]) +AC_ARG_ENABLE(vbe, AS_HELP_STRING([--enable-vbe], [Build Xorg with VBE module (default: enabled)]), [VBE=$enableval], [VBE=yes]) +AC_ARG_ENABLE(int10-module, AS_HELP_STRING([--enable-int10-module], [Build Xorg with int10 module (default: enabled)]), [INT10MODULE=$enableval], [INT10MODULE=yes]) +AC_ARG_ENABLE(windowswm, AS_HELP_STRING([--enable-windowswm], [Build XWin with WindowsWM extension (default: no)]), [WINDOWSWM=$enableval], [WINDOWSWM=no]) + +dnl DDXes. +AC_ARG_ENABLE(xorg, AS_HELP_STRING([--enable-xorg], [Build Xorg server (default: auto)]), [XORG=$enableval], [XORG=auto]) +AC_ARG_ENABLE(dmx, AS_HELP_STRING([--enable-dmx], [Build DMX server (default: auto)]), [DMX=$enableval], [DMX=auto]) +AC_ARG_ENABLE(xvfb, AS_HELP_STRING([--enable-xvfb], [Build Xvfb server (default: yes)]), [XVFB=$enableval], [XVFB=yes]) +AC_ARG_ENABLE(xnest, AS_HELP_STRING([--enable-xnest], [Build Xnest server (default: auto)]), [XNEST=$enableval], [XNEST=auto]) +AC_ARG_ENABLE(xquartz, AS_HELP_STRING([--enable-xquartz], [Build Xquartz server for OS-X (default: auto)]), [XQUARTZ=$enableval], [XQUARTZ=auto]) +AC_ARG_ENABLE(standalone-xpbproxy, AS_HELP_STRING([--enable-standalone-xpbproxy], [Build a standalone xpbproxy (in addition to the one integrated into Xquartz as a separate thread) (default: no)]), [STANDALONE_XPBPROXY=$enableval], [STANDALONE_XPBPROXY=no]) +AC_ARG_ENABLE(xwin, AS_HELP_STRING([--enable-xwin], [Build XWin server (default: auto)]), [XWIN=$enableval], [XWIN=auto]) +dnl kdrive and its subsystems +AC_ARG_ENABLE(kdrive, AS_HELP_STRING([--enable-kdrive], [Build kdrive servers (default: no)]), [KDRIVE=$enableval], [KDRIVE=no]) +AC_ARG_ENABLE(xephyr, AS_HELP_STRING([--enable-xephyr], [Build the kdrive Xephyr server (default: auto)]), [XEPHYR=$enableval], [XEPHYR=auto]) +AC_ARG_ENABLE(xfake, AS_HELP_STRING([--enable-xfake], [Build the kdrive 'fake' server (default: auto)]), [XFAKE=$enableval], [XFAKE=auto]) +AC_ARG_ENABLE(xfbdev, AS_HELP_STRING([--enable-xfbdev], [Build the kdrive framebuffer device server (default: auto)]), [XFBDEV=$enableval], [XFBDEV=auto]) +dnl kdrive options +AC_ARG_ENABLE(kdrive-kbd, AS_HELP_STRING([--enable-kdrive-kbd], [Build kbd driver for kdrive (default: auto)]), [KDRIVE_KBD=$enableval], [KDRIVE_KBD=auto]) +AC_ARG_ENABLE(kdrive-mouse, AC_HELP_STRING([--enable-kdrive-mouse], [Build mouse driver for kdrive (default: auto)]), [KDRIVE_MOUSE=$enableval], [KDRIVE_MOUSE=auto]) +AC_ARG_ENABLE(kdrive-evdev, AC_HELP_STRING([--enable-kdrive-evdev], [Build evdev driver for kdrive (default: auto)]), [KDRIVE_EVDEV=$enableval], [KDRIVE_EVDEV=auto]) + + +dnl chown/chmod to be setuid root as part of build +dnl Replaces InstallXserverSetUID in imake +AC_ARG_ENABLE(install-setuid, + AS_HELP_STRING([--enable-install-setuid], + [Install Xorg server as owned by root with setuid bit (default: auto)]), + [SETUID=$enableval], [SETUID=auto]) +AC_MSG_CHECKING([to see if we can install the Xorg server as root]) +if test "x$SETUID" = "xauto" ; then + case $host_os in + cygwin*) SETUID="no" ;; + darwin*) SETUID="no" ;; + *) + case $host_cpu in + sparc) SETUID="no" ;; + *) SETUID="yes" ;; + esac + esac + if test "x$SETUID" = xyes; then + touch testfile + chown root testfile > /dev/null 2>&1 || SETUID="no" + rm -f testfile + fi +fi +AC_MSG_RESULT([$SETUID]) +AM_CONDITIONAL(INSTALL_SETUID, [test "x$SETUID" = "xyes"]) + +dnl Issue an error if xtrans.m4 was not found and XTRANS_CONNECTION_FLAGS macro +dnl was not expanded, since xorg-server with no transport types is rather useless. +dnl +dnl If you're seeing an error here, be sure you installed the lib/xtrans module +dnl first and if it's not in the default location, that you set the ACLOCAL +dnl environment variable to find it, such as: +dnl ACLOCAL="aclocal -I ${PREFIX}/share/aclocal" +m4_pattern_forbid([^XTRANS_CONNECTION_FLAGS$]) + +# Transport selection macro from xtrans.m4 +XTRANS_CONNECTION_FLAGS + +# Secure RPC detection macro from xtrans.m4 +XTRANS_SECURE_RPC_FLAGS +AM_CONDITIONAL(SECURE_RPC, [test "x$SECURE_RPC" = xyes]) + +AM_CONDITIONAL(INT10_VM86, [test "x$INT10" = xvm86]) +AM_CONDITIONAL(INT10_X86EMU, [test "x$INT10" = xx86emu]) +AM_CONDITIONAL(INT10_STUB, [test "x$INT10" = xstub]) +if test "x$INT10" = xyes; then + dnl VM86 headers + AC_CHECK_HEADERS([sys/vm86.h sys/io.h]) +fi + +dnl Handle building documentation +AM_CONDITIONAL(BUILDDOCS, test "x$BUILDDOCS" = xyes) + +dnl Only build sgml docs when linuxdoc is available and +dnl def.ents has been installed +XORG_CHECK_LINUXDOC + +dnl Handle installing libxf86config +AM_CONDITIONAL(INSTALL_LIBXF86CONFIG, [test "x$INSTALL_LIBXF86CONFIG" = xyes]) + +dnl DDX Detection... Yes, it's ugly to have it here... but we need to +dnl handle this early on so that we don't require unsupported extensions +case $host_os in + cygwin*) + DGA=no + DRI2=no + XF86VIDMODE=no + XSELINUX=no + XV=no + ;; + darwin*) + DRI2=no + + if test x$XQUARTZ = xauto; then + AC_CACHE_CHECK([whether to build Xquartz],xorg_cv_Carbon_framework,[ + save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS -framework Carbon" + AC_LINK_IFELSE([char FSFindFolder(); int main() { FSFindFolder(); return 0;}], + [xorg_cv_Carbon_framework=yes], + [xorg_cv_Carbon_framework=no]) + LDFLAGS=$save_LDFLAGS]) + + if test "X$xorg_cv_Carbon_framework" = Xyes; then + XQUARTZ=yes + else + XQUARTZ=no + fi + fi + + if test "x$XQUARTZ" = xyes ; then + XQUARTZ=yes + XVFB=no + XNEST=no + + COMPOSITE=no + DGA=no + DPMSExtension=no + XF86VIDMODE=no + fi + ;; + *) XQUARTZ=no ;; +esac + +dnl --------------------------------------------------------------------------- +dnl Extension section +dnl --------------------------------------------------------------------------- +XEXT_INC='-I$(top_srcdir)/Xext' +XEXT_LIB='$(top_builddir)/Xext/libXext.la' +XEXTXORG_LIB='$(top_builddir)/Xext/libXextbuiltin.la' + +dnl Optional modules +VIDEOPROTO="videoproto" +COMPOSITEPROTO="compositeproto >= 0.4" +RECORDPROTO="recordproto >= 1.13.99.1" +SCRNSAVERPROTO="scrnsaverproto >= 1.1" +RESOURCEPROTO="resourceproto" +DRIPROTO="xf86driproto >= 2.1.0" +DRI2PROTO="dri2proto >= 2.3" +XINERAMAPROTO="xineramaproto" +BIGFONTPROTO="xf86bigfontproto >= 1.2.0" +XCALIBRATEPROTO="xcalibrateproto" +DGAPROTO="xf86dgaproto >= 2.0.99.1" +GLPROTO="glproto >= 1.4.10" +DMXPROTO="dmxproto >= 2.2.99.1" +VIDMODEPROTO="xf86vidmodeproto >= 2.2.99.1" +WINDOWSWMPROTO="windowswmproto" +APPLEWMPROTO="applewmproto >= 1.4" + +dnl Core modules for most extensions, et al. +REQUIRED_MODULES="[randrproto >= 1.2.99.3] [renderproto >= 0.11] [fixesproto >= 4.1] [damageproto >= 1.1] [xcmiscproto >= 1.2.0] [xextproto >= 7.0.99.3] [xproto >= 7.0.13] [xtrans >= 1.2.2] [bigreqsproto >= 1.1.0] fontsproto [inputproto >= 1.9.99.902] [kbproto >= 1.0.3]" +REQUIRED_LIBS="xfont xau [pixman-1 >= 0.15.20]" + +dnl List of libraries that require a specific version +LIBAPPLEWM="applewm >= 1.4" +LIBDMX="dmx >= 1.0.99.1" +LIBDRI="dri >= 7.8.0" +LIBDRM="libdrm >= 2.3.0" +LIBGL="gl >= 7.1.0" +LIBXEXT="xext >= 1.0.99.4" +LIBXI="xi >= 1.2.99.1" +LIBXTST="xtst >= 1.0.99.2" +LIBPCIACCESS="pciaccess >= 0.8.0" +LIBGLIB="glib-2.0 >= 2.16" +LIBUDEV="libudev >= 143" +LIBSELINUX="libselinux >= 2.0.86" + +if test "x$CONFIG_UDEV" = xyes && + { test "x$CONFIG_DBUS_API" = xyes || test "x$CONFIG_HAL" = xyes; }; then + AC_MSG_ERROR([Hotplugging through both libudev and dbus/hal not allowed]) +fi + +PKG_CHECK_MODULES(UDEV, $LIBUDEV, [HAVE_LIBUDEV=yes], [HAVE_LIBUDEV=no]) +if test "x$CONFIG_UDEV" = xauto; then + CONFIG_UDEV="$HAVE_LIBUDEV" +fi +AM_CONDITIONAL(CONFIG_UDEV, [test "x$CONFIG_UDEV" = xyes]) +if test "x$CONFIG_UDEV" = xyes; then + CONFIG_DBUS_API=no + CONFIG_HAL=no + if ! test "x$HAVE_LIBUDEV" = xyes; then + AC_MSG_ERROR([udev configuration API requested, but libudev is not installed]) + fi + AC_DEFINE(CONFIG_UDEV, 1, [Use libudev for input hotplug]) +fi + +dnl HAVE_DBUS is true if we actually have the D-Bus library, whereas +dnl CONFIG_DBUS_API is true if we want to enable the D-Bus config +dnl API. +PKG_CHECK_MODULES(DBUS, dbus-1, [HAVE_DBUS=yes], [HAVE_DBUS=no]) +if test "x$HAVE_DBUS" = xyes; then + AC_DEFINE(HAVE_DBUS, 1, [Have D-Bus support]) +fi +AM_CONDITIONAL(HAVE_DBUS, [test "x$HAVE_DBUS" = xyes]) + +if test "x$CONFIG_DBUS_API" = xauto; then + CONFIG_DBUS_API="$HAVE_DBUS" +fi +if test "x$CONFIG_DBUS_API" = xyes; then + if ! test "x$HAVE_DBUS" = xyes; then + AC_MSG_ERROR([D-Bus configuration API requested, but D-Bus is not installed.]) + fi + + AC_DEFINE(CONFIG_DBUS_API, 1, [Use the D-Bus input configuration API]) + CONFIG_NEED_DBUS="yes" +fi +AM_CONDITIONAL(CONFIG_DBUS_API, [test "x$CONFIG_DBUS_API" = xyes]) + +PKG_CHECK_MODULES(HAL, hal, [HAVE_HAL=yes], [HAVE_HAL=no]) +if test "x$CONFIG_HAL" = xauto; then + CONFIG_HAL="$HAVE_HAL" +fi +if test "x$CONFIG_HAL" = xyes; then + if ! test "x$HAVE_HAL" = xyes; then + AC_MSG_ERROR([HAL hotplug API requested, but HAL is not installed.]) + fi + + AC_DEFINE(CONFIG_HAL, 1, [Use the HAL hotplug API]) + CONFIG_NEED_DBUS="yes" +fi +AM_CONDITIONAL(CONFIG_HAL, [test "x$CONFIG_HAL" = xyes]) + +if test "x$CONFIG_NEED_DBUS" = xyes; then + AC_DEFINE(CONFIG_NEED_DBUS, 1, [Use D-Bus for input hotplug]) +fi +AM_CONDITIONAL(CONFIG_NEED_DBUS, [test "x$CONFIG_NEED_DBUS" = xyes]) + +if test "x$USE_SIGIO_BY_DEFAULT" = xyes; then + USE_SIGIO_BY_DEFAULT_VALUE=TRUE +else + USE_SIGIO_BY_DEFAULT_VALUE=FALSE +fi +AC_DEFINE_UNQUOTED([USE_SIGIO_BY_DEFAULT], [$USE_SIGIO_BY_DEFAULT_VALUE], + [Use SIGIO handlers for input device events by default]) + +AC_MSG_CHECKING([for glibc...]) +AC_PREPROC_IFELSE([ +#include +#ifndef __GLIBC__ +#error +#endif +], glibc=yes, glibc=no) +AC_MSG_RESULT([$glibc]) + +AC_CHECK_FUNCS([clock_gettime], [have_clock_gettime=yes], + [AC_CHECK_LIB([rt], [clock_gettime], [have_clock_gettime=-lrt], + [have_clock_gettime=no])]) + +AC_MSG_CHECKING([for a useful monotonic clock ...]) + +if ! test "x$have_clock_gettime" = xno; then + if ! test "x$have_clock_gettime" = xyes; then + CLOCK_LIBS="$have_clock_gettime" + else + CLOCK_LIBS="" + fi + + LIBS_SAVE="$LIBS" + LIBS="$CLOCK_LIBS" + CPPFLAGS_SAVE="$CPPFLAGS" + + if test x"$glibc" = xyes; then + CPPFLAGS="$CPPFLAGS -D_POSIX_C_SOURCE=200112L" + fi + + AC_RUN_IFELSE([ +#include + +int main(int argc, char *argv[[]]) { + struct timespec tp; + + if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0) + return 0; + else + return 1; +} + ], [MONOTONIC_CLOCK=yes], [MONOTONIC_CLOCK=no], + [MONOTONIC_CLOCK="cross compiling"]) + + LIBS="$LIBS_SAVE" + CPPFLAGS="$CPPFLAGS_SAVE" +else + MONOTONIC_CLOCK=no +fi + +AC_MSG_RESULT([$MONOTONIC_CLOCK]) + +if test "x$MONOTONIC_CLOCK" = xyes; then + AC_DEFINE(MONOTONIC_CLOCK, 1, [Have monotonic clock from clock_gettime()]) + LIBS="$LIBS $CLOCK_LIBS" +fi + +AM_CONDITIONAL(XV, [test "x$XV" = xyes]) +if test "x$XV" = xyes; then + AC_DEFINE(XV, 1, [Support Xv extension]) + AC_DEFINE(XvExtension, 1, [Build Xv extension]) + REQUIRED_MODULES="$REQUIRED_MODULES $VIDEOPROTO" +else + XVMC=no +fi + +AM_CONDITIONAL(XVMC, [test "x$XVMC" = xyes]) +if test "x$XVMC" = xyes; then + AC_DEFINE(XvMCExtension, 1, [Build XvMC extension]) +fi + +AM_CONDITIONAL(XREGISTRY, [test "x$XREGISTRY" = xyes]) +if test "x$XREGISTRY" = xyes; then + AC_DEFINE(XREGISTRY, 1, [Build registry module]) +fi + +AM_CONDITIONAL(COMPOSITE, [test "x$COMPOSITE" = xyes]) +if test "x$COMPOSITE" = xyes; then + AC_DEFINE(COMPOSITE, 1, [Support Composite Extension]) + REQUIRED_MODULES="$REQUIRED_MODULES $COMPOSITEPROTO" + COMPOSITE_LIB='$(top_builddir)/composite/libcomposite.la' + COMPOSITE_INC='-I$(top_srcdir)/composite' +fi + +AM_CONDITIONAL(MITSHM, [test "x$MITSHM" = xyes]) +if test "x$MITSHM" = xyes; then + AC_DEFINE(MITSHM, 1, [Support MIT-SHM extension]) + AC_DEFINE(HAS_SHM, 1, [Support SHM]) +fi + +AM_CONDITIONAL(RECORD, [test "x$RECORD" = xyes]) +if test "x$RECORD" = xyes; then + AC_DEFINE(XRECORD, 1, [Support Record extension]) + REQUIRED_MODULES="$REQUIRED_MODULES $RECORDPROTO" + RECORD_LIB='$(top_builddir)/record/librecord.la' +fi + +AM_CONDITIONAL(SCREENSAVER, [test "x$SCREENSAVER" = xyes]) +if test "x$SCREENSAVER" = xyes; then + AC_DEFINE(SCREENSAVER, 1, [Support MIT-SCREEN-SAVER extension]) + REQUIRED_MODULES="$REQUIRED_MODULES $SCRNSAVERPROTO" +fi + +AM_CONDITIONAL(RES, [test "x$RES" = xyes]) +if test "x$RES" = xyes; then + AC_DEFINE(RES, 1, [Support X resource extension]) + REQUIRED_MODULES="$REQUIRED_MODULES $RESOURCEPROTO" +fi + +if test "x$GLX" = xyes; then + PKG_CHECK_MODULES([XLIB], [x11]) + PKG_CHECK_MODULES([GL], $GLPROTO $LIBGL) + AC_SUBST(XLIB_CFLAGS) + AC_DEFINE(GLXEXT, 1, [Build GLX extension]) + GLX_LIBS='$(top_builddir)/glx/libglx.la' + GLX_SYS_LIBS="$GLX_SYS_LIBS" +else + GLX=no +fi +AM_CONDITIONAL(GLX, test "x$GLX" = xyes) + +if test "x$AIGLX" = xyes -a "x$GLX" = xyes -a "x$DRI" = xyes; then + AC_DEFINE(AIGLX, 1, [Build AIGLX loader]) +else + AIGLX=no +fi +AM_CONDITIONAL(AIGLX, test "x$AIGLX" = xyes) + +if test "x$GLX_USE_TLS" = xyes -a "x$AIGLX" = xyes; then + GLX_DEFINES="-DGLX_USE_TLS -DPTHREADS" + GLX_SYS_LIBS="$GLX_SYS_LIBS -lpthread" +fi +AC_SUBST([GLX_DEFINES]) + +AM_CONDITIONAL(DRI, test "x$DRI" = xyes) +if test "x$DRI" = xyes; then + AC_DEFINE(XF86DRI, 1, [Build DRI extension]) + PKG_CHECK_MODULES([DRIPROTO], [$DRIPROTO]) + PKG_CHECK_MODULES([DRI], $GLPROTO $LIBDRI) + AC_SUBST(DRIPROTO_CFLAGS) +fi + +PKG_CHECK_MODULES([DRI2PROTO], $DRI2PROTO, + [HAVE_DRI2PROTO=yes], [HAVE_DRI2PROTO=no]) +case "$DRI2,$HAVE_DRI2PROTO" in + yes,no) + AC_MSG_ERROR([DRI2 requested, but dri2proto not found.]) + ;; + yes,yes | auto,yes) + AC_DEFINE(DRI2, 1, [Build DRI2 extension]) + DRI2=yes + ;; +esac +AM_CONDITIONAL(DRI2, test "x$DRI2" = xyes) + +if test "x$DRI" = xyes || test "x$DRI2" = xyes; then + PKG_CHECK_MODULES([LIBDRM], $LIBDRM) + AC_SUBST(LIBDRM_CFLAGS) + AC_SUBST(LIBDRM_LIBS) +fi + +if test "x$DRI2" = xyes; then + save_CFLAGS=$CFLAGS + CFLAGS="$GL_CFLAGS $LIBDRM_CFLAGS" + AC_COMPILE_IFELSE([AC_LANG_SOURCE([[#include +#include +#ifndef __DRI_DRI2 +#error DRI2 extension not available. +#endif]])], + [HAVE_DRI2EXTENSION=yes], + [HAVE_DRI2EXTENSION=no]) + CFLAGS=$save_CFLAGS + if test "x$HAVE_DRI2EXTENSION" = xyes; then + AC_DEFINE(DRI2_AIGLX, 1, [Build DRI2 AIGLX loader]) + DRI2_AIGLX=yes + else + AC_MSG_NOTICE([DRI2 AIGLX disabled, __DRI_DRI2 not defined in dri_interface.h.]) + DRI2_AIGLX=no + fi +fi +AM_CONDITIONAL(DRI2_AIGLX, test "x$DRI2_AIGLX" = xyes) + + +AM_CONDITIONAL(XINERAMA, [test "x$XINERAMA" = xyes]) +if test "x$XINERAMA" = xyes; then + AC_DEFINE(XINERAMA, 1, [Support Xinerama extension]) + AC_DEFINE(PANORAMIX, 1, [Internal define for Xinerama]) + REQUIRED_MODULES="$REQUIRED_MODULES $XINERAMAPROTO" +fi + +AM_CONDITIONAL(XACE, [test "x$XACE" = xyes]) +if test "x$XACE" = xyes; then + AC_DEFINE(XACE, 1, [Build X-ACE extension]) +fi + +AM_CONDITIONAL(XSELINUX, [test "x$XSELINUX" = xyes]) +if test "x$XSELINUX" = xyes; then + if test "x$XACE" != xyes; then + AC_MSG_ERROR([cannot build SELinux extension without X-ACE]) + fi + AC_CHECK_HEADERS([libaudit.h], [], AC_MSG_ERROR([SELinux extension requires audit system headers])) + AC_CHECK_LIB(audit, audit_open, [], AC_MSG_ERROR([SELinux extension requires audit system library])) + PKG_CHECK_MODULES([SELINUX], $LIBSELINUX) + SELINUX_LIBS="$SELINUX_LIBS -laudit" + AC_DEFINE(XSELINUX, 1, [Build SELinux extension]) +fi + +AM_CONDITIONAL(XCSECURITY, [test "x$XCSECURITY" = xyes]) +if test "x$XCSECURITY" = xyes; then + if test "x$XACE" != xyes; then + AC_MSG_ERROR([cannot build Security extension without X-ACE]) + fi + AC_DEFINE(XCSECURITY, 1, [Build Security extension]) +fi + +AM_CONDITIONAL(DBE, [test "x$DBE" = xyes]) +if test "x$DBE" = xyes; then + AC_DEFINE(DBE, 1, [Support DBE extension]) + DBE_LIB='$(top_builddir)/dbe/libdbe.la' +fi + +AM_CONDITIONAL(XF86BIGFONT, [test "x$XF86BIGFONT" = xyes]) +if test "x$XF86BIGFONT" = xyes; then + AC_DEFINE(XF86BIGFONT, 1, [Support XF86 Big font extension]) + REQUIRED_MODULES="$REQUIRED_MODULES $BIGFONTPROTO" +fi + +AM_CONDITIONAL(DPMSExtension, [test "x$DPMSExtension" = xyes]) +if test "x$DPMSExtension" = xyes; then + AC_DEFINE(DPMSExtension, 1, [Support DPMS extension]) +fi + +if test "x$XCALIBRATE" = xyes && test "$KDRIVE" = yes; then + AC_DEFINE(XCALIBRATE, 1, [Build XCalibrate extension]) + REQUIRED_MODULES="$REQUIRED_MODULES $XCALIBRATEPROTO" +else + XCALIBRATE=no +fi +AM_CONDITIONAL(XCALIBRATE, [test "x$XCALIBRATE" = xyes]) + +AC_DEFINE(RENDER, 1, [Support RENDER extension]) +RENDER_LIB='$(top_builddir)/render/librender.la' +RENDER_INC='-I$(top_srcdir)/render' + +AC_DEFINE(RANDR, 1, [Support RANDR extension]) +RANDR_LIB='$(top_builddir)/randr/librandr.la' +RANDR_INC='-I$(top_srcdir)/randr' + +AC_DEFINE(XFIXES,1,[Support XFixes extension]) +FIXES_LIB='$(top_builddir)/xfixes/libxfixes.la' +FIXES_INC='-I$(top_srcdir)/xfixes' + +AC_DEFINE(DAMAGE,1,[Support Damage extension]) +DAMAGE_LIB='$(top_builddir)/damageext/libdamageext.la' +DAMAGE_INC='-I$(top_srcdir)/damageext' +MIEXT_DAMAGE_LIB='$(top_builddir)/miext/damage/libdamage.la' +MIEXT_DAMAGE_INC='-I$(top_srcdir)/miext/damage' + +# XINPUT extension is integral part of the server +AC_DEFINE(XINPUT, 1, [Support X Input extension]) +XI_LIB='$(top_builddir)/Xi/libXi.la' +XI_INC='-I$(top_srcdir)/Xi' + +AM_CONDITIONAL(XF86UTILS, test "x$XF86UTILS" = xyes) +AM_CONDITIONAL(XAA, test "x$XAA" = xyes) +AM_CONDITIONAL(VGAHW, test "x$VGAHW" = xyes) +AM_CONDITIONAL(VBE, test "x$VBE" = xyes) +AM_CONDITIONAL(INT10MODULE, test "x$INT10MODULE" = xyes) + +AC_DEFINE(SHAPE, 1, [Support SHAPE extension]) + +AC_DEFINE_DIR(XKB_BASE_DIRECTORY, XKBPATH, [Path to XKB data]) +AC_ARG_WITH(xkb-bin-directory, + AS_HELP_STRING([--with-xkb-bin-directory=DIR], [Directory containing xkbcomp program]), + [XKB_BIN_DIRECTORY="$withval"], + [XKB_BIN_DIRECTORY="$bindir"]) + +AC_DEFINE_DIR(XKB_BIN_DIRECTORY, XKB_BIN_DIRECTORY, [Path to XKB bin dir]) + +dnl Make sure XKM_OUTPUT_DIR is an absolute path +XKBOUTPUT_FIRSTCHAR=`echo $XKBOUTPUT | cut -b 1` +if [[ x$XKBOUTPUT_FIRSTCHAR != x/ -a x$XKBOUTPUT_FIRSTCHAR != 'x$' ]] ; then + XKBOUTPUT="$XKB_BASE_DIRECTORY/$XKBOUTPUT" +fi + +dnl XKM_OUTPUT_DIR (used in code) must end in / or file names get hosed +dnl XKB_COMPILED_DIR (used in Makefiles) must not or install-sh gets confused + +XKBOUTPUT=`echo $XKBOUTPUT/ | $SED 's|/*$|/|'` +XKB_COMPILED_DIR=`echo $XKBOUTPUT | $SED 's|/*$||'` +AC_DEFINE_DIR(XKM_OUTPUT_DIR, XKBOUTPUT, [Path to XKB output dir]) +AC_SUBST(XKB_COMPILED_DIR) + +if test "x$XKB_DFLT_RULES" = x; then + case $host_os in + linux*) + dnl doesn't take AutoAddDevices into account, but whatever. + if test "x$CONFIG_HAL" = xyes; then + XKB_DFLT_RULES="evdev" + else + XKB_DFLT_RULES="base" + fi + ;; + *) + XKB_DFLT_RULES="base" + ;; + esac +fi +AC_DEFINE_UNQUOTED(XKB_DFLT_RULES, ["$XKB_DFLT_RULES"], [Default XKB ruleset]) +AC_DEFINE_UNQUOTED(XKB_DFLT_MODEL, ["$XKB_DFLT_MODEL"], [Default XKB model]) +AC_DEFINE_UNQUOTED(XKB_DFLT_LAYOUT, ["$XKB_DFLT_LAYOUT"], [Default XKB layout]) +AC_DEFINE_UNQUOTED(XKB_DFLT_VARIANT, ["$XKB_DFLT_VARIANT"], [Default XKB variant]) +AC_DEFINE_UNQUOTED(XKB_DFLT_OPTIONS, ["$XKB_DFLT_OPTIONS"], [Default XKB options]) + +XKB_LIB='$(top_builddir)/xkb/libxkb.la' +XKB_STUB_LIB='$(top_builddir)/xkb/libxkbstubs.la' +REQUIRED_MODULES="$REQUIRED_MODULES xkbfile" + +AC_CHECK_FUNC(strcasecmp, [], AC_DEFINE([NEED_STRCASECMP], 1, + [Do not have 'strcasecmp'.])) +AC_CHECK_FUNC(strncasecmp, [], AC_DEFINE([NEED_STRNCASECMP], 1, + [Do not have 'strncasecmp'.])) +AC_CHECK_FUNC(strcasestr, [], AC_DEFINE([NEED_STRCASESTR], 1, + [Do not have 'strcasestr'.])) + +PKG_CHECK_MODULES([XDMCP], [xdmcp], [have_libxdmcp="yes"], [have_libxdmcp="no"]) +if test "x$have_libxdmcp" = xyes; then + AC_CHECK_LIB(Xdmcp, XdmcpWrap, [have_xdmcpwrap="yes"], [have_xdmcpwrap="no"], [$XDMCP_LIBS]) +fi +if test "x$XDMCP" = xauto; then + if test "x$have_libxdmcp" = xyes; then + XDMCP=yes + else + XDMCP=no + fi +fi +if test "x$XDMAUTH" = xauto; then + if test "x$have_libxdmcp" = xyes && test "x$have_xdmcpwrap" = xyes; then + XDMAUTH=yes + else + XDMAUTH=no + fi +fi + +AM_CONDITIONAL(XDMCP, [test "x$XDMCP" = xyes]) +if test "x$XDMCP" = xyes; then + AC_DEFINE(XDMCP, 1, [Support XDM Control Protocol]) + REQUIRED_LIBS="$REQUIRED_LIBS xdmcp" + XDMCP_MODULES="xdmcp" +fi + +AM_CONDITIONAL(XDMAUTH, [test "x$XDMAUTH" = xyes]) +if test "x$XDMAUTH" = xyes; then + AC_DEFINE(HASXDMAUTH,1,[Support XDM-AUTH*-1]) + if ! test "x$XDMCP" = xyes; then + REQUIRED_LIBS="$REQUIRED_LIBS xdmcp" + XDMCP_MODULES="xdmcp" + fi +fi + +AC_DEFINE_DIR(COMPILEDDEFAULTFONTPATH, FONTPATH, [Default font path]) +AC_DEFINE_DIR(PCI_TXT_IDS_PATH, PCI_TXT_IDS_DIR, [Default PCI text file ID path]) +AC_DEFINE_DIR(SERVER_MISC_CONFIG_PATH, SERVERCONFIG, [Server miscellaneous config path]) +AC_DEFINE_DIR(BASE_FONT_PATH, FONTROOTDIR, [Default base font path]) +AC_DEFINE_DIR(DRI_DRIVER_PATH, DRI_DRIVER_PATH, [Default DRI driver path]) +AC_DEFINE_UNQUOTED(XVENDORNAME, ["$VENDOR_NAME"], [Vendor name]) +AC_DEFINE_UNQUOTED(XVENDORNAMESHORT, ["$VENDOR_NAME_SHORT"], [Short vendor name]) +AC_DEFINE_UNQUOTED(XORG_DATE, ["$RELEASE_DATE"], [Vendor release]) +AC_DEFINE_UNQUOTED(XORG_MAN_VERSION, ["$VENDOR_MAN_VERSION"], [Vendor man version]) +AC_DEFINE_UNQUOTED(BUILDERADDR, ["$BUILDERADDR"], [Builder address]) + +if test -z "$OSNAME"; then + OSNAME="UNKNOWN" +fi + +AC_DEFINE_UNQUOTED(OSNAME, ["$OSNAME"], [Operating System Name]) +AC_DEFINE_UNQUOTED(OSVENDOR, ["$OSVENDOR"], [Operating System Vendor]) +AC_DEFINE_UNQUOTED(BUILDERSTRING, ["$BUILDERSTRING"], [Builder string]) + +AC_SUBST([VENDOR_NAME_SHORT]) +AC_DEFINE_UNQUOTED(VENDOR_NAME, ["$VENDOR_NAME"], [Vendor name]) +AC_DEFINE_UNQUOTED(VENDOR_NAME_SHORT, ["$VENDOR_NAME_SHORT"], [Vendor name]) +AC_DEFINE_UNQUOTED(VENDOR_RELEASE, [$VENDOR_RELEASE], [Vendor release]) +AC_DEFINE_UNQUOTED(VENDOR_MAN_VERSION, ["$VENDOR_MAN_VERSION"], [Vendor man version]) + +AC_DEFINE(NO_LIBCWRAPPER, 1, [Define to 1 if modules should avoid the libcwrapper]) + +if test "x$DEBUGGING" = xyes; then + AC_DEFINE(DEBUG, 1, [Enable debugging code]) +fi +AM_CONDITIONAL(DEBUG, [test "x$DEBUGGING" = xyes]) + +# If unittests aren't explicitly disabled, check for required support +if test "x$UNITTESTS" != xno ; then + PKG_CHECK_MODULES([GLIB], $LIBGLIB, + [HAVE_GLIB=yes], [HAVE_GLIB=no]) + + # Check if linker supports -wrap, passed via compiler flags + # When cross-compiling, reports no, since unit tests run from + # "make check", so would be running on build machine, not target + AC_MSG_CHECKING([whether the linker supports -wrap]) + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS -Wl,-wrap,exit" + AC_RUN_IFELSE([AC_LANG_PROGRAM([[ + void __wrap_exit (int s) + { + __real_exit (0); + }]], + [[exit (1);]])], + [linker_can_wrap="yes"], + [linker_can_wrap="no"], + [linker_can_wrap="no"]) + AC_MSG_RESULT([$linker_can_wrap]) + LDFLAGS="$save_LDFLAGS" +fi + +if test "x$UNITTESTS" = xauto; then + if test "x$HAVE_GLIB" = xyes && test "x$linker_can_wrap" = xyes; then + UNITTESTS=yes + else + UNITTESTS=no + fi +fi +if test "x$UNITTESTS" = xyes; then + if test "x$HAVE_GLIB" = xno; then + AC_MSG_ERROR([glib required to build unit tests]) + fi + if test "x$linker_can_wrap" = xno; then + AC_MSG_ERROR([ld -wrap support required to build unit tests]) + fi + AC_DEFINE(UNITTESTS, 1, [Enable unit tests]) + AC_SUBST([GLIB_LIBS]) + AC_SUBST([GLIB_CFLAGS]) +fi +AM_CONDITIONAL(UNITTESTS, [test "x$UNITTESTS" = xyes]) + +AC_DEFINE(XTEST, 1, [Support XTest extension]) +AC_DEFINE(XSYNC, 1, [Support XSync extension]) +AC_DEFINE(XCMISC, 1, [Support XCMisc extension]) +AC_DEFINE(BIGREQS, 1, [Support BigRequests extension]) + +if test "x$SPECIAL_DTRACE_OBJECTS" = "xyes" ; then + DIX_LIB='$(top_builddir)/dix/dix.O' + OS_LIB='$(top_builddir)/os/os.O $(SHA1_LIBS)' +else + DIX_LIB='$(top_builddir)/dix/libdix.la' + OS_LIB='$(top_builddir)/os/libos.la' +fi +AC_SUBST([DIX_LIB]) +AC_SUBST([OS_LIB]) + +MAIN_LIB='$(top_builddir)/dix/libmain.la' +AC_SUBST([MAIN_LIB]) + +MI_LIB='$(top_builddir)/mi/libmi.la' +MI_EXT_LIB='$(top_builddir)/mi/libmiext.la' +MI_INC='-I$(top_srcdir)/mi' +FB_LIB='$(top_builddir)/fb/libfb.la' +FB_INC='-I$(top_srcdir)/fb' +MIEXT_SHADOW_INC='-I$(top_srcdir)/miext/shadow' +MIEXT_SHADOW_LIB='$(top_builddir)/miext/shadow/libshadow.la' +CORE_INCS='-I$(top_srcdir)/include -I$(top_builddir)/include' + +# SHA1 hashing +AC_ARG_WITH([sha1], + [AS_HELP_STRING([--with-sha1=libc|libmd|libgcrypt|libcrypto|libsha1|CommonCrypto], + [choose SHA1 implementation])]) +AC_CHECK_FUNC([SHA1Init], [HAVE_SHA1_IN_LIBC=yes]) +if test "x$with_sha1" = x && test "x$HAVE_SHA1_IN_LIBC" = xyes; then + with_sha1=libc +fi +if test "x$with_sha1" = xlibc && test "x$HAVE_SHA1_IN_LIBC" != xyes; then + AC_MSG_ERROR([libc requested but not found]) +fi +if test "x$with_sha1" = xlibc; then + AC_DEFINE([HAVE_SHA1_IN_LIBC], [1], + [Use libc SHA1 functions]) + SHA1_LIBS="" +fi +AC_CHECK_FUNC([CC_SHA1_Init], [HAVE_SHA1_IN_COMMONCRYPTO=yes]) +if test "x$with_sha1" = x && test "x$HAVE_SHA1_IN_COMMONCRYPTO" = xyes; then + with_sha1=CommonCrypto +fi +if test "x$with_sha1" = xCommonCrypto && test "x$HAVE_SHA1_IN_COMMONCRYPTO" != xyes; then + AC_MSG_ERROR([CommonCrypto requested but not found]) +fi +if test "x$with_sha1" = xCommonCrypto; then + AC_DEFINE([HAVE_SHA1_IN_COMMONCRYPTO], [1], + [Use CommonCrypto SHA1 functions]) + SHA1_LIBS="" +fi +AC_CHECK_LIB([md], [SHA1Init], [HAVE_LIBMD=yes]) +if test "x$with_sha1" = x && test "x$HAVE_LIBMD" = xyes; then + with_sha1=libmd +fi +if test "x$with_sha1" = xlibmd && test "x$HAVE_LIBMD" != xyes; then + AC_MSG_ERROR([libmd requested but not found]) +fi +if test "x$with_sha1" = xlibmd; then + AC_DEFINE([HAVE_SHA1_IN_LIBMD], [1], + [Use libmd SHA1 functions]) + SHA1_LIBS=-lmd +fi +AC_CHECK_LIB([sha1], [sha1_begin], [HAVE_LIBSHA1=yes]) +if test "x$with_sha1" = x && test "x$HAVE_LIBSHA1" = xyes; then + with_sha1=libsha1 +fi +if test "x$with_sha1" = xlibsha1 && test "x$HAVE_LIBSHA1" != xyes; then + AC_MSG_ERROR([libsha1 requested but not found]) +fi +if test "x$with_sha1" = xlibsha1; then + AC_DEFINE([HAVE_SHA1_IN_LIBSHA1], [1], + [Use libsha1 for SHA1]) + SHA1_LIBS=-lsha1 +fi +AC_CHECK_LIB([gcrypt], [gcry_md_open], [HAVE_LIBGCRYPT=yes]) +if test "x$with_sha1" = x && test "x$HAVE_LIBGCRYPT" = xyes; then + with_sha1=libgcrypt +fi +if test "x$with_sha1" = xlibgcrypt && test "x$HAVE_LIBGCRYPT" != xyes; then + AC_MSG_ERROR([libgcrypt requested but not found]) +fi +if test "x$with_sha1" = xlibgcrypt; then + AC_DEFINE([HAVE_SHA1_IN_LIBGCRYPT], [1], + [Use libgcrypt SHA1 functions]) + SHA1_LIBS=-lgcrypt +fi +# We don't need all of the OpenSSL libraries, just libcrypto +AC_CHECK_LIB([crypto], [SHA1_Init], [HAVE_LIBCRYPTO=yes]) +PKG_CHECK_MODULES([OPENSSL], [openssl], [HAVE_OPENSSL_PKC=yes], + [HAVE_OPENSSL_PKC=no]) +if test "x$HAVE_LIBCRYPTO" = xyes || test "x$HAVE_OPENSSL_PKC" = xyes; then + if test "x$with_sha1" = x; then + with_sha1=libcrypto + fi +else + if test "x$with_sha1" = xlibcrypto; then + AC_MSG_ERROR([OpenSSL libcrypto requested but not found]) + fi +fi +if test "x$with_sha1" = xlibcrypto; then + if test "x$HAVE_LIBCRYPTO" = xyes; then + SHA1_LIBS=-lcrypto + else + SHA1_LIBS="$OPENSSL_LIBS" + SHA1_CFLAGS="$OPENSSL_CFLAGS" + fi +fi +AC_MSG_CHECKING([for SHA1 implementation]) +if test "x$with_sha1" = x; then + AC_MSG_ERROR([No suitable SHA1 implementation found]) +fi +AC_MSG_RESULT([$with_sha1]) +AC_SUBST(SHA1_LIBS) +AC_SUBST(SHA1_CFLAGS) + +PKG_CHECK_MODULES([XSERVERCFLAGS], [$REQUIRED_MODULES $REQUIRED_LIBS]) +PKG_CHECK_MODULES([XSERVERLIBS], [$REQUIRED_LIBS]) + +# Autotools has some unfortunate issues with library handling. In order to +# get a server to rebuild when a dependency in the tree is changed, it must +# be listed in SERVERNAME_DEPENDENCIES. However, no system libraries may be +# listed there, or some versions of autotools will break (especially if a -L +# is required to find the library). So, we keep two sets of libraries +# detected: NAMESPACE_LIBS for in-tree libraries to be linked against, which +# will go into the _DEPENDENCIES and _LDADD of the server, and +# NAMESPACE_SYS_LIBS which will go into only the _LDADD. The +# NAMESPACEMODULES_LIBS detected from pkgconfig should always go in +# NAMESPACE_SYS_LIBS. +# +# XSERVER_LIBS is the set of in-tree libraries which all servers require. +# XSERVER_SYS_LIBS is the set of out-of-tree libraries which all servers +# require. +# +XSERVER_CFLAGS="${XSERVER_CFLAGS} ${XSERVERCFLAGS_CFLAGS}" +XSERVER_LIBS="$DIX_LIB $MI_LIB $OS_LIB" +XSERVER_SYS_LIBS="${XSERVERLIBS_LIBS} ${SYS_LIBS} ${LIBS}" +AC_SUBST([XSERVER_LIBS]) +AC_SUBST([XSERVER_SYS_LIBS]) + +UTILS_SYS_LIBS="${SYS_LIBS}" +AC_SUBST([UTILS_SYS_LIBS]) + +# The Xorg binary needs to export symbols so that they can be used from modules +# Some platforms require extra flags to do this. libtool should set the +# necessary flags for each platform when -export-dynamic is passed to it. +LD_EXPORT_SYMBOLS_FLAG="-export-dynamic" +AC_SUBST([LD_EXPORT_SYMBOLS_FLAG]) + +dnl Imake defines SVR4 on SVR4 systems, and many files check for it, so +dnl we need to replicate that here until those can all be fixed +AC_MSG_CHECKING([if SVR4 needs to be defined]) +AC_EGREP_CPP([I_AM_SVR4],[ +#if defined(SVR4) || defined(__svr4__) || defined(__SVR4) + I_AM_SVR4 +#endif +],[ +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_SHADOW_INC $MIEXT_LAYER_INC $MIEXT_DAMAGE_INC $RENDER_INC $RANDR_INC $FB_INC" + +dnl --------------------------------------------------------------------------- +dnl DDX section. +dnl --------------------------------------------------------------------------- + +dnl Xvfb DDX + +AC_MSG_CHECKING([whether to build Xvfb DDX]) +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_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]) +fi + + +dnl Xnest DDX + +PKG_CHECK_MODULES(XNESTMODULES, [xfont $LIBXEXT x11 xau $XDMCP_MODULES], [have_xnest=yes], [have_xnest=no]) +AC_MSG_CHECKING([whether to build Xnest DDX]) +if test "x$XNEST" = xauto; then + XNEST="$have_xnest" +fi +AC_MSG_RESULT([$XNEST]) +AM_CONDITIONAL(XNEST, [test "x$XNEST" = xyes]) + +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_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $DIX_LIB $MAIN_LIB $OS_LIB" + XNEST_SYS_LIBS="$XNESTMODULES_LIBS $GLX_SYS_LIBS" + AC_SUBST([XNEST_LIBS]) + AC_SUBST([XNEST_SYS_LIBS]) +fi + + +dnl Xorg DDX + +AC_MSG_CHECKING([whether to build Xorg DDX]) +if test "x$XORG" = xauto; then + XORG="yes" + case $host_os in + cygwin*) XORG="no" ;; + darwin*) XORG="no" ;; + esac +fi +AC_MSG_RESULT([$XORG]) + +xorg_bus_linuxpci=no +xorg_bus_bsdpci=no +xorg_bus_sparc=no + +if test "x$XORG" = xyes; then + XORG_DDXINCS='-I$(top_srcdir)/hw/xfree86 -I$(top_srcdir)/hw/xfree86/include -I$(top_srcdir)/hw/xfree86/common' + 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 $XEXTXORG_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB" + + dnl ================================================================== + dnl symbol visibility + symbol_visibility= + have_visibility=disabled + if test x$SYMBOL_VISIBILITY != xno; then + AC_MSG_CHECKING(for symbol visibility support) + if test x$GCC = xyes; then + VISIBILITY_CFLAGS="-fvisibility=hidden" + else + AC_CHECK_DECL([__SUNPRO_C], [SUNCC="yes"], [SUNCC="no"]) + if test x$SUNCC = xyes; then + VISIBILITY_CFLAGS="-xldscope=hidden" + else + have_visibility=no + fi + fi + if test x$have_visibility != xno; then + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $VISIBILITY_CFLAGS" + AC_TRY_COMPILE( + [#include + extern _X_HIDDEN int hidden_int; + extern _X_EXPORT int public_int; + extern _X_HIDDEN int hidden_int_func(void); + extern _X_EXPORT int public_int_func(void);], + [], + have_visibility=yes, + have_visibility=no) + CFLAGS=$save_CFLAGS + fi + AC_MSG_RESULT([$have_visibility]) + if test x$have_visibility != xno; then + symbol_visibility=$VISIBILITY_CFLAGS + XORG_CFLAGS="$XORG_CFLAGS $VISIBILITY_CFLAGS" + XSERVER_CFLAGS="$XSERVER_CFLAGS $VISIBILITY_CFLAGS" + fi + fi + dnl added to xorg-server.pc + AC_SUBST([symbol_visibility]) + dnl =================================================================== + + PKG_CHECK_MODULES([PCIACCESS], $LIBPCIACCESS) + SAVE_LIBS=$LIBS + SAVE_CFLAGS=$CFLAGS + CFLAGS=$PCIACCESS_CFLAGS + LIBS=$PCIACCESS_LIBS + AC_CHECK_FUNCS([pci_system_init_dev_mem]) + AC_CHECK_FUNCS([pci_device_enable]) + AC_CHECK_FUNCS([pci_device_is_boot_vga]) + AC_CHECK_FUNCS([pci_device_vgaarb_init]) + LIBS=$SAVE_LIBS + CFLAGS=$SAVE_CFLAGS + XORG_SYS_LIBS="$XORG_SYS_LIBS $PCIACCESS_LIBS $GLX_SYS_LIBS" + XORG_CFLAGS="$XORG_CFLAGS $PCIACCESS_CFLAGS" + + case $host_os in + linux*) + if test "x$LNXAPM" = xyes; then + XORG_CFLAGS="$XORG_CFLAGS -DXF86PM" + fi + XORG_OS="linux" + XORG_OS_SUBDIR="linux" + xorg_bus_linuxpci="yes" + linux_acpi="no" + case $host_cpu in + ia64*) + linux_ia64=yes + linux_acpi="yes" + ;; + alpha*) + linux_alpha=yes + ;; + i*86|amd64*|x86_64*) + linux_acpi="yes" + ;; + *) + ;; + esac + ;; + freebsd* | kfreebsd*-gnu | dragonfly*) + XORG_OS="freebsd" + XORG_OS_SUBDIR="bsd" + xorg_bus_bsdpci="yes" + ;; + netbsd*) + XORG_OS="netbsd" + XORG_OS_SUBDIR="bsd" + xorg_bus_bsdpci="yes" + ;; + openbsd*) + if test "x$ac_cv_BSD_APM" = xyes \ + -o "x$ac_cv_BSD_KQUEUE_APM" = xyes; then + XORG_CFLAGS="$XORG_CFLAGS -DXF86PM" + fi + XORG_OS="openbsd" + XORG_OS_SUBDIR="bsd" + xorg_bus_bsdpci="yes" + ;; + solaris*) + XORG_OS="solaris" + XORG_OS_SUBDIR="solaris" + XORG_CFLAGS="$XORG_CFLAGS -DXF86PM" + # Use the same stubs as BSD for old functions, since we now + # use libpciaccess for PCI + xorg_bus_bsdpci="yes" + AC_CHECK_HEADERS([sys/kd.h]) + AC_CHECK_HEADERS([sys/vt.h], [solaris_vt=yes], [solaris_vt=no]) + # Check for minimum supported release + AC_MSG_CHECKING([Solaris version]) + OS_MINOR=`echo ${host_os}|$SED -e 's/^.*solaris2\.//' -e s'/\..*$//'` + if test "${OS_MINOR}" -ge 7 ; then + AC_MSG_RESULT(Solaris ${OS_MINOR}) + else + AC_MSG_RESULT(Solaris `echo ${host_os}|$SED -e 's/^.*solaris//`) + fi + if test "${OS_MINOR}" -lt 8 ; then + AC_MSG_ERROR([This release no longer supports Solaris versions older than Solaris 8.]) + fi + AC_CHECK_DECL([__SUNPRO_C], [SUNCC="yes"], [SUNCC="no"]) + if test "x$SUNCC" = "xyes"; then + solaris_asm_inline="yes" + fi + AC_CHECK_DECL([_LP64], [SOLARIS_64="yes"], [SOLARIS_64="no"]) + + case $host_cpu in + sparc*) + SOLARIS_INOUT_ARCH="sparcv8plus" + ;; + i*86) + if test x$SOLARIS_64 = xyes ; then + SOLARIS_INOUT_ARCH="amd64" + else + SOLARIS_INOUT_ARCH="ia32" + fi + ;; + *) + AC_MSG_ERROR([Unsupported Solaris platform. Only SPARC & x86 \ + are supported on Solaris in this release. If you are \ + interested in porting Xorg to your platform, please email \ + xorg@lists.freedesktop.org.]) ;; + esac + AC_SUBST([SOLARIS_INOUT_ARCH]) + if test x$solaris_asm_inline = xyes ; then + SOLARIS_ASM_CFLAGS='$(top_srcdir)/hw/xfree86/os-support/solaris/solaris-$(SOLARIS_INOUT_ARCH).il' + XORG_CFLAGS="${XORG_CFLAGS} "'$(SOLARIS_ASM_CFLAGS)' + fi + AC_SUBST([SOLARIS_ASM_CFLAGS]) + if test "x$SUPPORT_PC98" = xauto; then + SUPPORT_PC98="no" + fi + ;; + gnu*) + XORG_OS="gnu" + XORG_OS_SUBDIR="hurd" + # Use the same stubs as BSD for old functions, since we now + # use libpciaccess for PCI + xorg_bus_bsdpci="yes" + ;; + *) + XORG_OS="unknown" + XORG_OS_SUBDIR="unknown" + AC_MSG_ERROR([m4_text_wrap(m4_join([ ], + [Your OS is unknown. Xorg currently only supports Linux,], + [Free/Open/Net/DragonFlyBSD, Solaris/OpenSolaris, & GNU Hurd.], + [If you are interested in porting Xorg to your platform,], + [please email xorg@lists.freedesktop.org.]))]) + ;; + esac + + case $host_cpu in + sparc*) + xorg_bus_sparc="yes" + ;; + i*86) + if test "x$SUPPORT_PC98" = xauto; then + SUPPORT_PC98="yes" + fi + ;; + esac + + if test "x$SUPPORT_PC98" = xauto; then + SUPPORT_PC98="no" + fi + if test "x$SUPPORT_PC98" = xyes; then + AC_DEFINE(SUPPORT_PC98, 1, [Support PC98]) + fi + if test "x$XORG_OS_PCI" = x ; then + XORG_OS_PCI=$XORG_OS + fi + if test "x$DGA" = xauto; then + PKG_CHECK_MODULES(DGA, $DGAPROTO, [DGA=yes], [DGA=no]) + fi + if test "x$DGA" = xyes; then + XORG_MODULES="$XORG_MODULES $DGAPROTO" + PKG_CHECK_MODULES(DGA, $DGAPROTO) + AC_DEFINE(DGA, 1, [Support DGA extension]) + AC_DEFINE(XFreeXDGA, 1, [Build XDGA support]) + fi + + if test "x$XF86VIDMODE" = xauto; then + PKG_CHECK_MODULES(XF86VIDMODE, $VIDMODEPROTO, [XF86VIDMODE=yes], [XF86VIDMODE=no]) + fi + if test "x$XF86VIDMODE" = xyes; then + XORG_MODULES="$XORG_MODULES $VIDMODEPROTO" + PKG_CHECK_MODULES(XF86VIDMODE, $VIDMODEPROTO) + AC_DEFINE(XF86VIDMODE, 1, [Support XFree86 Video Mode extension]) + fi + + if test -n "$XORG_MODULES"; then + PKG_CHECK_MODULES(XORG_MODULES, [$XORG_MODULES]) + XORG_CFLAGS="$XORG_CFLAGS $XORG_MODULES_CFLAGS" + XORG_SYS_LIBS="$XORG_SYS_LIBS $XORG_MODULES_LIBS" + fi + + AC_SUBST([XORG_LIBS]) + AC_SUBST([XORG_SYS_LIBS]) + AC_SUBST([XORG_INCS]) + AC_SUBST([XORG_OS]) + AC_SUBST([XORG_OS_SUBDIR]) + + AC_PATH_PROG(PERL, perl, no) + dnl unlikely as this may be ... + if test "x$PERL" = xno; then + AC_MSG_ERROR([Perl is required to build the XFree86/Xorg DDX.]) + fi + AC_SUBST(PERL) + + AC_SUBST([XORG_CFLAGS]) + + dnl these only go in xorg-config.h + XF86CONFIGFILE="xorg.conf" + XF86CONFIGDIR="xorg.conf.d" + AC_SUBST(XF86CONFIGDIR) + CONFIGFILE="$sysconfdir/$XF86CONFIGFILE" + LOGPREFIX="$logdir/Xorg." + AC_DEFINE(XORG_SERVER, 1, [Building Xorg server]) + AC_DEFINE(XORGSERVER, 1, [Building Xorg server]) + AC_DEFINE(XFree86Server, 1, [Building XFree86 server]) + AC_DEFINE(XFree86LOADER, 1, [Building loadable XFree86 server]) + AC_DEFINE_UNQUOTED(XORG_VERSION_CURRENT, [$VENDOR_RELEASE], [Current Xorg version]) + AC_DEFINE(NEED_XF86_TYPES, 1, [Need XFree86 typedefs]) + AC_DEFINE(NEED_XF86_PROTOTYPES, 1, [Need XFree86 helper functions]) + AC_DEFINE(__XSERVERNAME__, "Xorg", [Name of X server]) + AC_DEFINE_DIR(__XCONFIGFILE__, XF86CONFIGFILE, [Name of configuration file]) + AC_DEFINE_DIR(XF86CONFIGFILE, XF86CONFIGFILE, [Name of configuration file]) + AC_DEFINE_DIR(__XCONFIGDIR__, XF86CONFIGDIR, [Name of configuration directory]) + AC_DEFINE_DIR(DEFAULT_MODULE_PATH, moduledir, [Default module search path]) + AC_DEFINE_DIR(DEFAULT_LIBRARY_PATH, libdir, [Default library install path]) + AC_DEFINE_DIR(DEFAULT_LOGPREFIX, LOGPREFIX, [Default log location]) + AC_DEFINE_UNQUOTED(__VENDORDWEBSUPPORT__, ["$VENDOR_WEB"], [Vendor web address for support]) + AC_DEFINE(XSERVER_LIBPCIACCESS, 1, [Use libpciaccess for all pci manipulation]) + if test "x$VGAHW" = xyes; then + AC_DEFINE(WITH_VGAHW, 1, [Building vgahw module]) + fi + + driverdir="$moduledir/drivers" + AC_SUBST([moduledir]) + AC_SUBST([driverdir]) + sdkdir="$includedir/xorg" + extdir="$includedir/X11/extensions" + sysconfigdir="$datadir/X11/$XF86CONFIGDIR" + AC_SUBST([sdkdir]) + AC_SUBST([extdir]) + AC_SUBST([sysconfigdir]) + AC_SUBST([logdir]) + + # stuff the ABI versions into the pc file too + extract_abi() { + grep ^.define.*${1}_VERSION ${srcdir}/hw/xfree86/common/xf86Module.h | tr '(),' ' .' | awk '{ print $4$5 }' + } + abi_ansic=`extract_abi ANSIC` + abi_videodrv=`extract_abi VIDEODRV` + abi_xinput=`extract_abi XINPUT` + abi_extension=`extract_abi EXTENSION` + AC_SUBST([abi_ansic]) + AC_SUBST([abi_videodrv]) + AC_SUBST([abi_xinput]) + AC_SUBST([abi_extension]) +fi +AM_CONDITIONAL([XORG], [test "x$XORG" = xyes]) +AM_CONDITIONAL([XORG_BUS_LINUXPCI], [test "x$xorg_bus_linuxpci" = xyes]) +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_IA64], [test "x$linux_ia64" = xyes]) +AM_CONDITIONAL([LINUX_ALPHA], [test "x$linux_alpha" = xyes]) +AM_CONDITIONAL([LNXACPI], [test "x$linux_acpi" = 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]) +AM_CONDITIONAL([XF86VIDMODE], [test "x$XF86VIDMODE" = xyes]) + +dnl XWin DDX + +AC_MSG_CHECKING([whether to build XWin DDX]) +if test "x$XWIN" = xauto; then + case $host_os in + cygwin*) XWIN="yes" ;; + mingw*) XWIN="yes" ;; + *) XWIN="no" ;; + esac +fi +AC_MSG_RESULT([$XWIN]) + +if test "x$XWIN" = xyes; then + AC_DEFINE_DIR(SYSCONFDIR, sysconfdir, [Location of system.XWinrc]) + AC_DEFINE_DIR(DEFAULT_LOGDIR, logdir, [Default log location]) + AC_DEFINE_UNQUOTED(XORG_VERSION_CURRENT, [$VENDOR_RELEASE], [Current Xorg version]) + AC_DEFINE_UNQUOTED(__VENDORDWEBSUPPORT__, ["$VENDOR_WEB"], [Vendor web address for support]) + AC_CHECK_TOOL(WINDRES, windres) + + PKG_CHECK_MODULES([XWINMODULES],[x11 xdmcp xau xfont]) + + if test "x$WINDOWSWM" = xauto; then + PKG_CHECK_EXISTS($WINDOWSWMPROTO, [WINDOWSWM=yes], [WINDOWSWM=no]) + fi + if test "x$WINDOWSWM" = xyes ; then + PKG_CHECK_MODULES(WINDOWSWM, $WINDOWSWMPROTO) + XWINMODULES_CFLAGS="$XWINMODULES_CFLAGS $WINDOWSWM_CFLAGS" + AC_DEFINE(ROOTLESS,1,[Build Rootless code]) + fi + + case $host_os in + cygwin*) + XWIN_SERVER_NAME=XWin + AC_DEFINE(HAS_DEVWINDOWS,1,[Cygwin has /dev/windows for signaling new win32 messages]) + ;; + mingw*) + XWIN_SERVER_NAME=Xming + AC_DEFINE(RELOCATE_PROJECTROOT,1,[Make PROJECT_ROOT relative to the xserver location]) + AC_DEFINE(HAS_WINSOCK,1,[Use Windows sockets]) + XWIN_SYS_LIBS=-lwinsock2 + ;; + esac + XWIN_LIBS="$FB_LIB $MI_LIB $FIXES_LIB $XEXT_LIB $RANDR_LIB $RENDER_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $OS_LIB" + XWIN_SYS_LIBS="$XWIN_SYS_LIBS $XWINMODULES_LIBS" + AC_SUBST(XWIN_LIBS) + AC_SUBST(XWIN_SERVER_NAME) + AC_SUBST(XWIN_SYS_LIBS) + + if test "x$DEBUGGING" = xyes; then + AC_DEFINE(CYGDEBUG, 1, [Simple debug messages]) + AC_DEFINE(CYGWINDOWING_DEBUG, 1, [Debug messages for window handling]) + AC_DEFINE(CYGMULTIWINDOW_DEBUG, 1, [Debug window manager]) + fi + + AC_DEFINE(DDXOSVERRORF, 1, [Use OsVendorVErrorF]) + AC_DEFINE(DDXBEFORERESET, 1, [Use ddxBeforeReset ]) +fi +AM_CONDITIONAL(XWIN, [test "x$XWIN" = xyes]) +AM_CONDITIONAL(XWIN_MULTIWINDOW, [test "x$XWIN" = xyes]) +AM_CONDITIONAL(XWIN_MULTIWINDOWEXTWM, [test "x$XWIN" = xyes && test "x$WINDOWSWM" = xyes]) +AM_CONDITIONAL(XWIN_CLIPBOARD, [test "x$XWIN" = xyes]) +AM_CONDITIONAL(XWIN_GLX_WINDOWS, [test "x$XWIN" = xyes && false]) +AM_CONDITIONAL(XWIN_NATIVEGDI, [test "x$XWIN" = xyes && false]) +AM_CONDITIONAL(XWIN_PRIMARYFB, [test "x$XWIN" = xyes && false]) +AM_CONDITIONAL(XWIN_RANDR, [test "x$XWIN" = xyes]) +AM_CONDITIONAL(XWIN_XV, [test "x$XWIN" = xyes && test "x$XV" = xyes]) + +dnl Darwin / OS X DDX +if test "x$XQUARTZ" = xyes; then + AC_DEFINE(XQUARTZ,1,[Have Quartz]) + AC_DEFINE(ROOTLESS,1,[Build Rootless code]) + + DARWIN_LIBS="$MI_LIB $OS_LIB $DIX_LIB $MAIN_LIB $FB_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $XPSTUBS_LIB" + AC_SUBST([DARWIN_LIBS]) + + AC_CHECK_LIB([Xplugin],[xp_init],[:]) + + CFLAGS="${CFLAGS} -DROOTLESS_WORKAROUND -DROOTLESS_SAFEALPHA -DNO_ALLOCA" + + PKG_CHECK_MODULES(XPBPROXY, $APPLEWMPROTO $LIBAPPLEWM xfixes x11) + + if test "x$XQUARTZ_SPARKLE" = xyes ; then + AC_DEFINE(XQUARTZ_SPARKLE,1,[Support application updating through sparkle.]) + fi + + if test "x$STANDALONE_XPBPROXY" = xyes ; then + AC_DEFINE(STANDALONE_XPBPROXY,1,[Build a standalone xpbproxy]) + fi +fi + +# Support for objc in autotools is minimal and not documented. +OBJC='$(CC)' +OBJCLD='$(CCLD)' +OBJCLINK='$(LINK)' +OBJCFLAGS='$(CFLAGS)' +AC_SUBST([OBJC]) +AC_SUBST([OBJCCLD]) +AC_SUBST([OBJCLINK]) +AC_SUBST([OBJCFLAGS]) +# internal, undocumented automake func follows :( +_AM_DEPENDENCIES([OBJC]) +AM_CONDITIONAL(XQUARTZ, [test "x$XQUARTZ" = xyes]) +AM_CONDITIONAL(XQUARTZ_SPARKLE, [test "x$XQUARTZ_SPARKLE" != "xno"]) +AM_CONDITIONAL(STANDALONE_XPBPROXY, [test "x$STANDALONE_XPBPROXY" = xyes]) + +dnl DMX DDX +PKG_CHECK_MODULES( + [DMXMODULES], + [xmuu $LIBXEXT x11 xrender xfixes xfont $LIBXI $DMXPROTO xau $XDMCP_MODULES], + [PKG_CHECK_MODULES( + [XDMXCONFIG_DEP], + [xaw7 xmu xt xpm x11], + [have_dmx=yes], + [have_dmx=no])], + [have_dmx=no]) +AC_MSG_CHECKING([whether to build Xdmx DDX]) +if test "x$DMX" = xauto; then + DMX="$have_dmx" + case $host_os in + cygwin*) DMX="no" ;; + darwin*) DMX="no" ;; + esac +fi +AC_MSG_RESULT([$DMX]) +AM_CONDITIONAL(DMX, [test "x$DMX" = xyes]) + +if test "x$DMX" = xyes; then + if test "x$have_dmx" = xno; then + AC_MSG_ERROR([Xdmx build explicitly requested, but required + modules not found.]) + fi + DMX_INCLUDES="$XEXT_INC $RENDER_INC $RECORD_INC" + XDMX_CFLAGS="$DMXMODULES_CFLAGS" + XDMX_LIBS="$FB_LIB $MI_LIB $RENDER_LIB $RECORD_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $MIEXT_SHADOW_LIB $MIEXT_DAMAGE_LIB $XEXT_LIB $MAIN_LIB $DIX_LIB $OS_LIB $FIXES_LIB" + XDMX_SYS_LIBS="$DMXMODULES_LIBS" + AC_SUBST([XDMX_CFLAGS]) + AC_SUBST([XDMX_LIBS]) + AC_SUBST([XDMX_SYS_LIBS]) + +dnl USB sources in DMX require + AC_CHECK_HEADER([linux/input.h], DMX_BUILD_USB="yes", + DMX_BUILD_USB="no") +dnl Linux sources in DMX require + AC_CHECK_HEADER([linux/keyboard.h], DMX_BUILD_LNX="yes", + DMX_BUILD_LNX="no") + AC_SUBST(XDMXCONFIG_DEP_CFLAGS) + AC_SUBST(XDMXCONFIG_DEP_LIBS) + PKG_CHECK_MODULES([DMXEXAMPLES_DEP], [$LIBDMX $LIBXEXT x11]) + AC_SUBST(DMXEXAMPLES_DEP_LIBS) + PKG_CHECK_MODULES([DMXXMUEXAMPLES_DEP], [$LIBDMX xmu $LIBXEXT x11]) + AC_SUBST(DMXXMUEXAMPLES_DEP_LIBS) + PKG_CHECK_MODULES([DMXXIEXAMPLES_DEP], [$LIBDMX $LIBXI $LIBXEXT x11]) + AC_SUBST(DMXXIEXAMPLES_DEP_LIBS) + PKG_CHECK_MODULES([XTSTEXAMPLES_DEP], [$LIBXTST $LIBXEXT x11]) + AC_SUBST(XTSTEXAMPLES_DEP_LIBS) + PKG_CHECK_MODULES([XRESEXAMPLES_DEP], [xres $LIBXEXT x11]) + AC_SUBST(XRESEXAMPLES_DEP_LIBS) + PKG_CHECK_MODULES([X11EXAMPLES_DEP], [$LIBXEXT x11]) + AC_SUBST(X11EXAMPLES_DEP_LIBS) + +fi +AM_CONDITIONAL([DMX_BUILD_LNX], [test "x$DMX_BUILD_LNX" = xyes]) +AM_CONDITIONAL([DMX_BUILD_USB], [test "x$DMX_BUILD_USB" = xyes]) + +dnl kdrive DDX + +XEPHYR_LIBS= +XEPHYR_INCS= + +AM_CONDITIONAL(KDRIVE, [test x$KDRIVE = xyes]) + +if test "$KDRIVE" = yes; then + AC_DEFINE(KDRIVESERVER,1,[Build Kdrive X server]) + AC_DEFINE(KDRIVEDDXACTIONS,,[Build kdrive ddx]) + + AC_CHECK_HEADERS([linux/fb.h]) + if test "$ac_cv_header_linux_fb_h" = yes && test "x$XFBDEV" = xauto; then + XFBDEV=yes + fi + + if test "x$XFBDEV" = xyes; then + KDRIVEFBDEVLIB=yes + AC_DEFINE(KDRIVEFBDEV, 1, [Build fbdev-based kdrive server]) + fi + + + PKG_CHECK_MODULES([TSLIB], [tslib-0.0], [HAVE_TSLIB="yes"], [HAVE_TSLIB="no"]) + if test "x$HAVE_TSLIB" = xno; then + AC_CHECK_LIB(ts, ts_open, [HAVE_TSLIB="yes"]) + fi + + if test "xTSLIB" = xauto; then + TSLIB="$HAVE_TSLIB" + fi + + if test "x$TSLIB" = xyes; then + if ! test "x$HAVE_TSLIB" = xyes; then + AC_MSG_ERROR([tslib must be installed to build the tslib driver. See http://tslib.berlios.de/]) + else + AC_DEFINE(TSLIB, 1, [Have tslib support]) + fi + fi + + if test "x$KDRIVE_KBD" = xyes; then + AC_DEFINE(KDRIVE_KBD, 1, [Enable KDrive kbd driver]) + fi + if test "x$KDRIVE_EVDEV" = xyes; then + AC_DEFINE(KDRIVE_EVDEV, 1, [Enable KDrive evdev driver]) + fi + if test "x$KDRIVE_MOUSE" = xyes; then + AC_DEFINE(KDRIVE_MOUSE, 1, [Enable KDrive mouse driver]) + fi + + XEPHYR_REQUIRED_LIBS="x11 $LIBXEXT xfont xau xdmcp" + if test "x$XV" = xyes; then + XEPHYR_REQUIRED_LIBS="$XEPHYR_REQUIRED_LIBS xv" + fi + if test "x$DRI" = xyes && test "x$GLX" = xyes; then + XEPHYR_REQUIRED_LIBS="$XEPHYR_REQUIRED_LIBS $LIBGL libdrm" + fi + + PKG_CHECK_MODULES(XEPHYR, $XEPHYR_REQUIRED_LIBS, [xephyr="yes"], [xephyr="no"]) + if test "x$XEPHYR" = xauto; then + XEPHYR=$xephyr + fi + + # Xephyr needs nanosleep() which is in librt on Solaris + AC_CHECK_FUNC([nanosleep], [], + AC_CHECK_LIB([rt], [nanosleep], XEPHYR_LIBS="$XEPHYR_LIBS -lrt")) + + # damage shadow extension glx (NOTYET) fb mi + KDRIVE_INC='-I$(top_srcdir)/hw/kdrive/src' + KDRIVE_PURE_INCS="$KDRIVE_INC $MIEXT_DAMAGE_INC $MIEXT_SHADOW_INC $XEXT_INC $FB_INC $MI_INC" + KDRIVE_OS_INC='-I$(top_srcdir)/hw/kdrive/linux' + KDRIVE_INCS="$KDRIVE_PURE_INCS $KDRIVE_OS_INC" + + 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_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*) + KDRIVE_OS_LIB='$(top_builddir)/hw/kdrive/linux/liblinux.la' + KDRIVELINUX=yes + if test "x$KDRIVE_EVDEV" = xauto; then + KDRIVE_EVDEV=yes + fi + if test "x$KDRIVE_KBD" = xauto; then + KDRIVE_KBD=yes + fi + if test "x$KDRIVE_MOUSE" = xauto; then + KDRIVE_MOUSE=yes + fi + ;; + *) + if test "x$KDRIVE_EVDEV" = xauto; then + KDRIVE_EVDEV=no + fi + if test "x$KDRIVE_KBD" = xauto; then + KDRIVE_KBD=no + fi + if test "x$KDRIVE_MOUSE" = xauto; then + KDRIVE_MOUSE=no + fi + ;; + esac + KDRIVE_STUB_LIB='$(top_builddir)/hw/kdrive/src/libkdrivestubs.la' + KDRIVE_LOCAL_LIBS="$MAIN_LIB $DIX_LIB $KDRIVE_LIB $KDRIVE_STUB_LIB" + KDRIVE_LOCAL_LIBS="$KDRIVE_LOCAL_LIBS $FB_LIB $MI_LIB $KDRIVE_PURE_LIBS" + KDRIVE_LOCAL_LIBS="$KDRIVE_LOCAL_LIBS $KDRIVE_OS_LIB $OS_LIB" + KDRIVE_LIBS="$TSLIB_LIBS $KDRIVE_LOCAL_LIBS $XSERVER_SYS_LIBS $GLX_SYS_LIBS $DLOPEN_LIBS" + + AC_SUBST([XEPHYR_LIBS]) + AC_SUBST([XEPHYR_INCS]) +fi +AC_SUBST([KDRIVE_INCS]) +AC_SUBST([KDRIVE_PURE_INCS]) +AC_SUBST([KDRIVE_CFLAGS]) +AC_SUBST([KDRIVE_PURE_LIBS]) +AC_SUBST([KDRIVE_LOCAL_LIBS]) +AC_SUBST([KDRIVE_LIBS]) +AM_CONDITIONAL(KDRIVELINUX, [test "x$KDRIVELINUX" = xyes]) +AM_CONDITIONAL(KDRIVE_EVDEV, [test "x$KDRIVE_EVDEV" = xyes]) +AM_CONDITIONAL(KDRIVE_KBD, [test "x$KDRIVE_KBD" = xyes]) +AM_CONDITIONAL(KDRIVE_MOUSE, [test "x$KDRIVE_MOUSE" = xyes]) +AM_CONDITIONAL(TSLIB, [test "x$HAVE_TSLIB" = xyes]) +AM_CONDITIONAL(KDRIVEFBDEV, [test "x$XFBDEV" = xyes]) +AM_CONDITIONAL(XEPHYR, [test "x$KDRIVE" = xyes && test "x$XEPHYR" = xyes]) +AM_CONDITIONAL(BUILD_KDRIVEFBDEVLIB, [test "x$KDRIVE" = xyes && test "x$KDRIVEFBDEVLIB" = xyes]) +AM_CONDITIONAL(XFAKESERVER, [test "x$KDRIVE" = xyes && test "x$XFAKE" = xyes]) + +dnl and the rest of these are generic, so they're in config.h +dnl +dnl though, thanks to the passing of some significant amount of time, the +dnl above is probably a complete fallacy, and you should not rely on it. +dnl but this is still actually better than imake, honest. -daniels + +AC_TRY_COMPILE([ +#include +#ifndef __GLIBC__ +#error not glibc +#endif +], [], [AC_DEFINE(_GNU_SOURCE, 1, + [ Enable GNU and other extensions to the C environment for glibc])]) + +AC_DEFINE_DIR(PROJECTROOT, prefix, [Overall prefix]) + +BUILD_DATE="`date +'%Y%m%d'`" +AC_SUBST([BUILD_DATE]) +BUILD_TIME="`date +'1%H%M%S'`" +AC_SUBST([BUILD_TIME]) + +DIX_CFLAGS="-DHAVE_DIX_CONFIG_H $XSERVER_CFLAGS" + +AC_SUBST([DIX_CFLAGS]) + +AC_SUBST([libdir]) +AC_SUBST([exec_prefix]) +AC_SUBST([prefix]) + +AC_OUTPUT([ +Makefile +glx/Makefile +include/Makefile +composite/Makefile +damageext/Makefile +dbe/Makefile +dix/Makefile +doc/Makefile +fb/Makefile +record/Makefile +config/Makefile +mi/Makefile +miext/Makefile +miext/damage/Makefile +miext/shadow/Makefile +miext/cw/Makefile +miext/rootless/Makefile +os/Makefile +randr/Makefile +render/Makefile +xkb/Makefile +Xext/Makefile +Xi/Makefile +xfixes/Makefile +exa/Makefile +hw/Makefile +hw/xfree86/Makefile +hw/xfree86/common/Makefile +hw/xfree86/common/xf86Build.h +hw/xfree86/ddc/Makefile +hw/xfree86/dixmods/Makefile +hw/xfree86/dixmods/extmod/Makefile +hw/xfree86/doc/Makefile +hw/xfree86/doc/devel/Makefile +hw/xfree86/doc/man/Makefile +hw/xfree86/doc/sgml/Makefile +hw/xfree86/dri/Makefile +hw/xfree86/dri2/Makefile +hw/xfree86/exa/Makefile +hw/xfree86/fbdevhw/Makefile +hw/xfree86/i2c/Makefile +hw/xfree86/int10/Makefile +hw/xfree86/loader/Makefile +hw/xfree86/modes/Makefile +hw/xfree86/os-support/Makefile +hw/xfree86/os-support/bsd/Makefile +hw/xfree86/os-support/bus/Makefile +hw/xfree86/os-support/hurd/Makefile +hw/xfree86/os-support/misc/Makefile +hw/xfree86/os-support/linux/Makefile +hw/xfree86/os-support/sco/Makefile +hw/xfree86/os-support/solaris/Makefile +hw/xfree86/os-support/sysv/Makefile +hw/xfree86/parser/Makefile +hw/xfree86/ramdac/Makefile +hw/xfree86/shadowfb/Makefile +hw/xfree86/vbe/Makefile +hw/xfree86/vgahw/Makefile +hw/xfree86/x86emu/Makefile +hw/xfree86/xaa/Makefile +hw/xfree86/xf8_16bpp/Makefile +hw/xfree86/utils/Makefile +hw/xfree86/utils/cvt/Makefile +hw/xfree86/utils/gtf/Makefile +hw/dmx/config/Makefile +hw/dmx/doc/Makefile +hw/dmx/examples/Makefile +hw/dmx/input/Makefile +hw/dmx/glxProxy/Makefile +hw/dmx/Makefile +hw/vfb/Makefile +hw/xnest/Makefile +hw/xwin/Makefile +hw/xwin/glx/Makefile +hw/xquartz/Makefile +hw/xquartz/GL/Makefile +hw/xquartz/bundle/Makefile +hw/xquartz/doc/Makefile +hw/xquartz/mach-startup/Makefile +hw/xquartz/pbproxy/Makefile +hw/xquartz/xpr/Makefile +hw/kdrive/Makefile +hw/kdrive/ephyr/Makefile +hw/kdrive/fake/Makefile +hw/kdrive/fbdev/Makefile +hw/kdrive/linux/Makefile +hw/kdrive/src/Makefile +test/Makefile +test/xi2/Makefile +xorg-server.pc +]) diff --git a/xorg-server/dix/colormap.c b/xorg-server/dix/colormap.c index 8bd41ce67..e22c35cb8 100644 --- a/xorg-server/dix/colormap.c +++ b/xorg-server/dix/colormap.c @@ -1,2761 +1,2762 @@ -/*********************************************************** - -Copyright 1987, 1998 The Open Group - -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. - -The above copyright notice and this permission notice 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 -OPEN GROUP 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. - -Except as contained in this notice, the name of The Open Group shall not be -used in advertising or otherwise to promote the sale, use or other dealings -in this Software without prior written authorization from The Open Group. - - -Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -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 Digital not be -used in advertising or publicity pertaining to distribution of the -software without specific, written prior permission. - -DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL -DIGITAL 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 -#endif - -#include -#include -#include -#include -#include -#include "misc.h" -#include "dix.h" -#include "colormapst.h" -#include "os.h" -#include "scrnintstr.h" -#include "resource.h" -#include "windowstr.h" -#include "privates.h" -#include "xace.h" - -#ifdef _MSC_VER -#define UpdateColors thisUpdateColors -#endif - -static Pixel FindBestPixel( - EntryPtr /*pentFirst*/, - int /*size*/, - xrgb * /*prgb*/, - int /*channel*/ -); - -static int AllComp( - EntryPtr /*pent*/, - xrgb * /*prgb*/ -); - -static int RedComp( - EntryPtr /*pent*/, - xrgb * /*prgb*/ -); - -static int GreenComp( - EntryPtr /*pent*/, - xrgb * /*prgb*/ -); - -static int BlueComp( - EntryPtr /*pent*/, - xrgb * /*prgb*/ -); - -static void FreePixels( - ColormapPtr /*pmap*/, - int /*client*/ -); - -static void CopyFree( - int /*channel*/, - int /*client*/, - ColormapPtr /*pmapSrc*/, - ColormapPtr /*pmapDst*/ -); - -static void FreeCell( - ColormapPtr /*pmap*/, - Pixel /*i*/, - int /*channel*/ -); - -static void UpdateColors( - ColormapPtr /*pmap*/ -); - -static int AllocDirect( - int /*client*/, - ColormapPtr /*pmap*/, - int /*c*/, - int /*r*/, - int /*g*/, - int /*b*/, - Bool /*contig*/, - Pixel * /*pixels*/, - Pixel * /*prmask*/, - Pixel * /*pgmask*/, - Pixel * /*pbmask*/ -); - -static int AllocPseudo( - int /*client*/, - ColormapPtr /*pmap*/, - int /*c*/, - int /*r*/, - Bool /*contig*/, - Pixel * /*pixels*/, - Pixel * /*pmask*/, - Pixel ** /*pppixFirst*/ -); - -static Bool AllocCP( - ColormapPtr /*pmap*/, - EntryPtr /*pentFirst*/, - int /*count*/, - int /*planes*/, - Bool /*contig*/, - Pixel * /*pixels*/, - Pixel * /*pMask*/ -); - -static Bool AllocShared( - ColormapPtr /*pmap*/, - Pixel * /*ppix*/, - int /*c*/, - int /*r*/, - int /*g*/, - int /*b*/, - Pixel /*rmask*/, - Pixel /*gmask*/, - Pixel /*bmask*/, - Pixel * /*ppixFirst*/ -); - -static int FreeCo( - ColormapPtr /*pmap*/, - int /*client*/, - int /*color*/, - int /*npixIn*/, - Pixel * /*ppixIn*/, - Pixel /*mask*/ -); - -static int TellNoMap( - WindowPtr /*pwin*/, - Colormap * /*pmid*/ -); - -static void FindColorInRootCmap ( - ColormapPtr /* pmap */, - EntryPtr /* pentFirst */, - int /* size */, - xrgb* /* prgb */, - Pixel* /* pPixel */, - int /* channel */, - ColorCompareProcPtr /* comp */ -); - -#define NUMRED(vis) ((vis->redMask >> vis->offsetRed) + 1) -#define NUMGREEN(vis) ((vis->greenMask >> vis->offsetGreen) + 1) -#define NUMBLUE(vis) ((vis->blueMask >> vis->offsetBlue) + 1) -#if COMPOSITE -#define ALPHAMASK(vis) ((vis)->nplanes < 32 ? 0 : \ - (CARD32) ~((vis)->redMask|(vis)->greenMask|(vis)->blueMask)) -#else -#define ALPHAMASK(vis) 0 -#endif - -#define RGBMASK(vis) (vis->redMask | vis->greenMask | vis->blueMask | ALPHAMASK(vis)) - -/* GetNextBitsOrBreak(bits, mask, base) -- - * (Suggestion: First read the macro, then read this explanation. - * - * Either generate the next value to OR in to a pixel or break out of this - * while loop - * - * This macro is used when we're trying to generate all 2^n combinations of - * bits in mask. What we're doing here is counting in binary, except that - * the bits we use to count may not be contiguous. This macro will be - * called 2^n times, returning a different value in bits each time. Then - * it will cause us to break out of a surrounding loop. (It will always be - * called from within a while loop.) - * On call: mask is the value we want to find all the combinations for - * base has 1 bit set where the least significant bit of mask is set - * - * For example,if mask is 01010, base should be 0010 and we count like this: - * 00010 (see this isn't so hard), - * then we add base to bits and get 0100. (bits & ~mask) is (0100 & 0100) so - * we add that to bits getting (0100 + 0100) = - * 01000 for our next value. - * then we add 0010 to get - * 01010 and we're done (easy as 1, 2, 3) - */ -#define GetNextBitsOrBreak(bits, mask, base) \ - if((bits) == (mask)) \ - break; \ - (bits) += (base); \ - while((bits) & ~(mask)) \ - (bits) += ((bits) & ~(mask)); -/* ID of server as client */ -#define SERVER_ID 0 - -typedef struct _colorResource -{ - Colormap mid; - int client; -} colorResource; - -/* Invariants: - * refcnt == 0 means entry is empty - * refcnt > 0 means entry is useable by many clients, so it can't be changed - * refcnt == AllocPrivate means entry owned by one client only - * fShared should only be set if refcnt == AllocPrivate, and only in red map - */ - - -/** - * Create and initialize the color map - * - * \param mid resource to use for this colormap - * \param alloc 1 iff all entries are allocated writable - */ -int -CreateColormap (Colormap mid, ScreenPtr pScreen, VisualPtr pVisual, - ColormapPtr *ppcmap, int alloc, int client) -{ - int class, size; - unsigned long sizebytes; - ColormapPtr pmap; - EntryPtr pent; - int i; - Pixel *ppix, **pptr; - - class = pVisual->class; - if(!(class & DynamicClass) && (alloc != AllocNone) && (client != SERVER_ID)) - return (BadMatch); - - size = pVisual->ColormapEntries; - sizebytes = (size * sizeof(Entry)) + - (MAXCLIENTS * sizeof(Pixel *)) + - (MAXCLIENTS * sizeof(int)); - if ((class | DynamicClass) == DirectColor) - sizebytes *= 3; - sizebytes += sizeof(ColormapRec); - pmap = malloc(sizebytes); - if (!pmap) - return (BadAlloc); -#if defined(_XSERVER64) - pmap->pad0 = 0; - pmap->pad1 = 0; -#if (X_BYTE_ORDER == X_LITTLE_ENDIAN) - pmap->pad2 = 0; -#endif -#endif - pmap->red = (EntryPtr)((char *)pmap + sizeof(ColormapRec)); - sizebytes = size * sizeof(Entry); - pmap->clientPixelsRed = (Pixel **)((char *)pmap->red + sizebytes); - pmap->numPixelsRed = (int *)((char *)pmap->clientPixelsRed + - (MAXCLIENTS * sizeof(Pixel *))); - pmap->mid = mid; - pmap->flags = 0; /* start out with all flags clear */ - if(mid == pScreen->defColormap) - pmap->flags |= IsDefault; - pmap->pScreen = pScreen; - pmap->pVisual = pVisual; - pmap->class = class; - if ((class | DynamicClass) == DirectColor) - size = NUMRED(pVisual); - pmap->freeRed = size; - bzero ((char *) pmap->red, (int)sizebytes); - bzero((char *) pmap->numPixelsRed, MAXCLIENTS * sizeof(int)); - for (pptr = &pmap->clientPixelsRed[MAXCLIENTS]; --pptr >= pmap->clientPixelsRed; ) - *pptr = (Pixel *)NULL; - if (alloc == AllocAll) - { - if (class & DynamicClass) - pmap->flags |= AllAllocated; - for (pent = &pmap->red[size - 1]; pent >= pmap->red; pent--) - pent->refcnt = AllocPrivate; - pmap->freeRed = 0; - ppix = malloc(size * sizeof(Pixel)); - if (!ppix) - { - free(pmap); - return (BadAlloc); - } - pmap->clientPixelsRed[client] = ppix; - for(i = 0; i < size; i++) - ppix[i] = i; - pmap->numPixelsRed[client] = size; - } - - if ((class | DynamicClass) == DirectColor) - { - pmap->freeGreen = NUMGREEN(pVisual); - pmap->green = (EntryPtr)((char *)pmap->numPixelsRed + - (MAXCLIENTS * sizeof(int))); - pmap->clientPixelsGreen = (Pixel **)((char *)pmap->green + sizebytes); - pmap->numPixelsGreen = (int *)((char *)pmap->clientPixelsGreen + - (MAXCLIENTS * sizeof(Pixel *))); - pmap->freeBlue = NUMBLUE(pVisual); - pmap->blue = (EntryPtr)((char *)pmap->numPixelsGreen + - (MAXCLIENTS * sizeof(int))); - pmap->clientPixelsBlue = (Pixel **)((char *)pmap->blue + sizebytes); - pmap->numPixelsBlue = (int *)((char *)pmap->clientPixelsBlue + - (MAXCLIENTS * sizeof(Pixel *))); - - bzero ((char *) pmap->green, (int)sizebytes); - bzero ((char *) pmap->blue, (int)sizebytes); - - memmove((char *) pmap->clientPixelsGreen, - (char *) pmap->clientPixelsRed, - MAXCLIENTS * sizeof(Pixel *)); - memmove((char *) pmap->clientPixelsBlue, - (char *) pmap->clientPixelsRed, - MAXCLIENTS * sizeof(Pixel *)); - bzero((char *) pmap->numPixelsGreen, MAXCLIENTS * sizeof(int)); - bzero((char *) pmap->numPixelsBlue, MAXCLIENTS * sizeof(int)); - - /* If every cell is allocated, mark its refcnt */ - if (alloc == AllocAll) - { - size = pmap->freeGreen; - for(pent = &pmap->green[size-1]; pent >= pmap->green; pent--) - pent->refcnt = AllocPrivate; - pmap->freeGreen = 0; - ppix = malloc(size * sizeof(Pixel)); - if (!ppix) - { - free(pmap->clientPixelsRed[client]); - free(pmap); - return(BadAlloc); - } - pmap->clientPixelsGreen[client] = ppix; - for(i = 0; i < size; i++) - ppix[i] = i; - pmap->numPixelsGreen[client] = size; - - size = pmap->freeBlue; - for(pent = &pmap->blue[size-1]; pent >= pmap->blue; pent--) - pent->refcnt = AllocPrivate; - pmap->freeBlue = 0; - ppix = malloc(size * sizeof(Pixel)); - if (!ppix) - { - free(pmap->clientPixelsGreen[client]); - free(pmap->clientPixelsRed[client]); - free(pmap); - return(BadAlloc); - } - pmap->clientPixelsBlue[client] = ppix; - for(i = 0; i < size; i++) - ppix[i] = i; - pmap->numPixelsBlue[client] = size; - } - } - pmap->devPrivates = NULL; - pmap->flags |= BeingCreated; - - if (!AddResource(mid, RT_COLORMAP, (pointer)pmap)) - return (BadAlloc); - - /* - * Security creation/labeling check - */ - i = XaceHook(XACE_RESOURCE_ACCESS, clients[client], mid, RT_COLORMAP, - pmap, RT_NONE, NULL, DixCreateAccess); - if (i != Success) { - FreeResource(mid, RT_NONE); - return i; - } - - /* If the device wants a chance to initialize the colormap in any way, - * this is it. In specific, if this is a Static colormap, this is the - * time to fill in the colormap's values */ - if (!(*pScreen->CreateColormap)(pmap)) - { - FreeResource (mid, RT_NONE); - return BadAlloc; - } - pmap->flags &= ~BeingCreated; - *ppcmap = pmap; - return (Success); -} - -/** - * - * \param value must conform to DeleteType - */ -int -FreeColormap (pointer value, XID mid) -{ - int i; - EntryPtr pent; - ColormapPtr pmap = (ColormapPtr)value; - - if(CLIENT_ID(mid) != SERVER_ID) - { - (*pmap->pScreen->UninstallColormap) (pmap); - WalkTree(pmap->pScreen, (VisitWindowProcPtr)TellNoMap, (pointer) &mid); - } - - /* This is the device's chance to undo anything it needs to, especially - * to free any storage it allocated */ - (*pmap->pScreen->DestroyColormap)(pmap); - - if(pmap->clientPixelsRed) - { - for(i = 0; i < MAXCLIENTS; i++) - free(pmap->clientPixelsRed[i]); - } - - if ((pmap->class == PseudoColor) || (pmap->class == GrayScale)) - { - for(pent = &pmap->red[pmap->pVisual->ColormapEntries - 1]; - pent >= pmap->red; - pent--) - { - if(pent->fShared) - { - if (--pent->co.shco.red->refcnt == 0) - free(pent->co.shco.red); - if (--pent->co.shco.green->refcnt == 0) - free(pent->co.shco.green); - if (--pent->co.shco.blue->refcnt == 0) - free(pent->co.shco.blue); - } - } - } - if((pmap->class | DynamicClass) == DirectColor) - { - for(i = 0; i < MAXCLIENTS; i++) - { - free(pmap->clientPixelsGreen[i]); - free(pmap->clientPixelsBlue[i]); - } - } - - dixFreePrivates(pmap->devPrivates); - free(pmap); - return(Success); -} - -/* Tell window that pmid has disappeared */ -static int -TellNoMap (WindowPtr pwin, Colormap *pmid) -{ - xEvent xE; - - if (wColormap(pwin) == *pmid) - { - /* This should be call to DeliverEvent */ - xE.u.u.type = ColormapNotify; - xE.u.colormap.window = pwin->drawable.id; - xE.u.colormap.colormap = None; - xE.u.colormap.new = TRUE; - xE.u.colormap.state = ColormapUninstalled; -#ifdef PANORAMIX - if(noPanoramiXExtension || !pwin->drawable.pScreen->myNum) -#endif - DeliverEvents(pwin, &xE, 1, (WindowPtr)NULL); - if (pwin->optional) { - pwin->optional->colormap = None; - CheckWindowOptionalNeed (pwin); - } - } - - return (WT_WALKCHILDREN); -} - -/* Tell window that pmid got uninstalled */ -int -TellLostMap (WindowPtr pwin, pointer value) -{ - Colormap *pmid = (Colormap *)value; - xEvent xE; - -#ifdef PANORAMIX - if(!noPanoramiXExtension && pwin->drawable.pScreen->myNum) - return WT_STOPWALKING; -#endif - if (wColormap(pwin) == *pmid) - { - /* This should be call to DeliverEvent */ - xE.u.u.type = ColormapNotify; - xE.u.colormap.window = pwin->drawable.id; - xE.u.colormap.colormap = *pmid; - xE.u.colormap.new = FALSE; - xE.u.colormap.state = ColormapUninstalled; - DeliverEvents(pwin, &xE, 1, (WindowPtr)NULL); - } - - return (WT_WALKCHILDREN); -} - -/* Tell window that pmid got installed */ -int -TellGainedMap (WindowPtr pwin, pointer value) -{ - Colormap *pmid = (Colormap *)value; - xEvent xE; - -#ifdef PANORAMIX - if(!noPanoramiXExtension && pwin->drawable.pScreen->myNum) - return WT_STOPWALKING; -#endif - if (wColormap (pwin) == *pmid) - { - /* This should be call to DeliverEvent */ - xE.u.u.type = ColormapNotify; - xE.u.colormap.window = pwin->drawable.id; - xE.u.colormap.colormap = *pmid; - xE.u.colormap.new = FALSE; - xE.u.colormap.state = ColormapInstalled; - DeliverEvents(pwin, &xE, 1, (WindowPtr)NULL); - } - - return (WT_WALKCHILDREN); -} - - -int -CopyColormapAndFree (Colormap mid, ColormapPtr pSrc, int client) -{ - ColormapPtr pmap = (ColormapPtr) NULL; - int result, alloc, size; - Colormap midSrc; - ScreenPtr pScreen; - VisualPtr pVisual; - - pScreen = pSrc->pScreen; - pVisual = pSrc->pVisual; - midSrc = pSrc->mid; - alloc = ((pSrc->flags & AllAllocated) && CLIENT_ID(midSrc) == client) ? - AllocAll : AllocNone; - size = pVisual->ColormapEntries; - - /* If the create returns non-0, it failed */ - result = CreateColormap (mid, pScreen, pVisual, &pmap, alloc, client); - if(result != Success) - return(result); - if(alloc == AllocAll) - { - memmove((char *)pmap->red, (char *)pSrc->red, size * sizeof(Entry)); - if((pmap->class | DynamicClass) == DirectColor) - { - memmove((char *)pmap->green, (char *)pSrc->green, size * sizeof(Entry)); - memmove((char *)pmap->blue, (char *)pSrc->blue, size * sizeof(Entry)); - } - pSrc->flags &= ~AllAllocated; - FreePixels(pSrc, client); - UpdateColors(pmap); - return(Success); - } - - CopyFree(REDMAP, client, pSrc, pmap); - if ((pmap->class | DynamicClass) == DirectColor) - { - CopyFree(GREENMAP, client, pSrc, pmap); - CopyFree(BLUEMAP, client, pSrc, pmap); - } - if (pmap->class & DynamicClass) - UpdateColors(pmap); - /* XXX should worry about removing any RT_CMAPENTRY resource */ - return(Success); -} - -/* Helper routine for freeing large numbers of cells from a map */ -static void -CopyFree (int channel, int client, ColormapPtr pmapSrc, ColormapPtr pmapDst) -{ - int z, npix; - EntryPtr pentSrcFirst, pentDstFirst; - EntryPtr pentSrc, pentDst; - Pixel *ppix; - int nalloc; - - switch(channel) - { - default: /* so compiler can see that everything gets initialized */ - case REDMAP: - ppix = (pmapSrc->clientPixelsRed)[client]; - npix = (pmapSrc->numPixelsRed)[client]; - pentSrcFirst = pmapSrc->red; - pentDstFirst = pmapDst->red; - break; - case GREENMAP: - ppix = (pmapSrc->clientPixelsGreen)[client]; - npix = (pmapSrc->numPixelsGreen)[client]; - pentSrcFirst = pmapSrc->green; - pentDstFirst = pmapDst->green; - break; - case BLUEMAP: - ppix = (pmapSrc->clientPixelsBlue)[client]; - npix = (pmapSrc->numPixelsBlue)[client]; - pentSrcFirst = pmapSrc->blue; - pentDstFirst = pmapDst->blue; - break; - } - nalloc = 0; - if (pmapSrc->class & DynamicClass) - { - for(z = npix; --z >= 0; ppix++) - { - /* Copy entries */ - pentSrc = pentSrcFirst + *ppix; - pentDst = pentDstFirst + *ppix; - if (pentDst->refcnt > 0) - { - pentDst->refcnt++; - } - else - { - *pentDst = *pentSrc; - nalloc++; - if (pentSrc->refcnt > 0) - pentDst->refcnt = 1; - else - pentSrc->fShared = FALSE; - } - FreeCell(pmapSrc, *ppix, channel); - } - } - - /* Note that FreeCell has already fixed pmapSrc->free{Color} */ - switch(channel) - { - case REDMAP: - pmapDst->freeRed -= nalloc; - (pmapDst->clientPixelsRed)[client] = - (pmapSrc->clientPixelsRed)[client]; - (pmapSrc->clientPixelsRed)[client] = (Pixel *) NULL; - (pmapDst->numPixelsRed)[client] = (pmapSrc->numPixelsRed)[client]; - (pmapSrc->numPixelsRed)[client] = 0; - break; - case GREENMAP: - pmapDst->freeGreen -= nalloc; - (pmapDst->clientPixelsGreen)[client] = - (pmapSrc->clientPixelsGreen)[client]; - (pmapSrc->clientPixelsGreen)[client] = (Pixel *) NULL; - (pmapDst->numPixelsGreen)[client] = (pmapSrc->numPixelsGreen)[client]; - (pmapSrc->numPixelsGreen)[client] = 0; - break; - case BLUEMAP: - pmapDst->freeBlue -= nalloc; - pmapDst->clientPixelsBlue[client] = pmapSrc->clientPixelsBlue[client]; - pmapSrc->clientPixelsBlue[client] = (Pixel *) NULL; - pmapDst->numPixelsBlue[client] = pmapSrc->numPixelsBlue[client]; - pmapSrc->numPixelsBlue[client] = 0; - break; - } -} - -/* Free the ith entry in a color map. Must handle freeing of - * colors allocated through AllocColorPlanes */ -static void -FreeCell (ColormapPtr pmap, Pixel i, int channel) -{ - EntryPtr pent; - int *pCount; - - - switch (channel) - { - default: /* so compiler can see that everything gets initialized */ - case PSEUDOMAP: - case REDMAP: - pent = (EntryPtr) &pmap->red[i]; - pCount = &pmap->freeRed; - break; - case GREENMAP: - pent = (EntryPtr) &pmap->green[i]; - pCount = &pmap->freeGreen; - break; - case BLUEMAP: - pent = (EntryPtr) &pmap->blue[i]; - pCount = &pmap->freeBlue; - break; - } - /* If it's not privately allocated and it's not time to free it, just - * decrement the count */ - if (pent->refcnt > 1) - pent->refcnt--; - else - { - /* If the color type is shared, find the sharedcolor. If decremented - * refcnt is 0, free the shared cell. */ - if (pent->fShared) - { - if(--pent->co.shco.red->refcnt == 0) - free(pent->co.shco.red); - if(--pent->co.shco.green->refcnt == 0) - free(pent->co.shco.green); - if(--pent->co.shco.blue->refcnt == 0) - free(pent->co.shco.blue); - pent->fShared = FALSE; - } - pent->refcnt = 0; - *pCount += 1; - } -} - -static void -UpdateColors (ColormapPtr pmap) -{ - xColorItem *defs; - xColorItem *pdef; - EntryPtr pent; - VisualPtr pVisual; - int i, n, size; - - pVisual = pmap->pVisual; - size = pVisual->ColormapEntries; - defs = malloc(size * sizeof(xColorItem)); - if (!defs) - return; - n = 0; - pdef = defs; - if (pmap->class == DirectColor) - { - for (i = 0; i < size; i++) - { - if (!pmap->red[i].refcnt && - !pmap->green[i].refcnt && - !pmap->blue[i].refcnt) - continue; - pdef->pixel = ((Pixel)i << pVisual->offsetRed) | - ((Pixel)i << pVisual->offsetGreen) | - ((Pixel)i << pVisual->offsetBlue); - pdef->red = pmap->red[i].co.local.red; - pdef->green = pmap->green[i].co.local.green; - pdef->blue = pmap->blue[i].co.local.blue; - pdef->flags = DoRed|DoGreen|DoBlue; - pdef++; - n++; - } - } - else - { - for (i = 0, pent = pmap->red; i < size; i++, pent++) - { - if (!pent->refcnt) - continue; - pdef->pixel = i; - if(pent->fShared) - { - pdef->red = pent->co.shco.red->color; - pdef->green = pent->co.shco.green->color; - pdef->blue = pent->co.shco.blue->color; - } - else - { - pdef->red = pent->co.local.red; - pdef->green = pent->co.local.green; - pdef->blue = pent->co.local.blue; - } - pdef->flags = DoRed|DoGreen|DoBlue; - pdef++; - n++; - } - } - if (n) - (*pmap->pScreen->StoreColors)(pmap, n, defs); - free(defs); -} - -/* Get a read-only color from a ColorMap (probably slow for large maps) - * Returns by changing the value in pred, pgreen, pblue and pPix - */ -int -AllocColor (ColormapPtr pmap, - unsigned short *pred, unsigned short *pgreen, unsigned short *pblue, - Pixel *pPix, int client) -{ - Pixel pixR, pixG, pixB; - int entries; - xrgb rgb; - int class; - VisualPtr pVisual; - int npix; - Pixel *ppix; - - pVisual = pmap->pVisual; - (*pmap->pScreen->ResolveColor) (pred, pgreen, pblue, pVisual); - rgb.red = *pred; - rgb.green = *pgreen; - rgb.blue = *pblue; - class = pmap->class; - entries = pVisual->ColormapEntries; - - /* If the colormap is being created, then we want to be able to change - * the colormap, even if it's a static type. Otherwise, we'd never be - * able to initialize static colormaps - */ - if(pmap->flags & BeingCreated) - class |= DynamicClass; - - /* If this is one of the static storage classes, and we're not initializing - * it, the best we can do is to find the closest color entry to the - * requested one and return that. - */ - switch (class) { - case StaticColor: - case StaticGray: - /* Look up all three components in the same pmap */ - *pPix = pixR = FindBestPixel(pmap->red, entries, &rgb, PSEUDOMAP); - *pred = pmap->red[pixR].co.local.red; - *pgreen = pmap->red[pixR].co.local.green; - *pblue = pmap->red[pixR].co.local.blue; - npix = pmap->numPixelsRed[client]; - ppix = (Pixel *) realloc(pmap->clientPixelsRed[client], - (npix + 1) * sizeof(Pixel)); - if (!ppix) - return (BadAlloc); - ppix[npix] = pixR; - pmap->clientPixelsRed[client] = ppix; - pmap->numPixelsRed[client]++; - break; - - case TrueColor: - /* Look up each component in its own map, then OR them together */ - pixR = FindBestPixel(pmap->red, NUMRED(pVisual), &rgb, REDMAP); - pixG = FindBestPixel(pmap->green, NUMGREEN(pVisual), &rgb, GREENMAP); - pixB = FindBestPixel(pmap->blue, NUMBLUE(pVisual), &rgb, BLUEMAP); - *pPix = (pixR << pVisual->offsetRed) | - (pixG << pVisual->offsetGreen) | - (pixB << pVisual->offsetBlue) | - ALPHAMASK(pVisual); - - *pred = pmap->red[pixR].co.local.red; - *pgreen = pmap->green[pixG].co.local.green; - *pblue = pmap->blue[pixB].co.local.blue; - npix = pmap->numPixelsRed[client]; - ppix = (Pixel *) realloc(pmap->clientPixelsRed[client], - (npix + 1) * sizeof(Pixel)); - if (!ppix) - return (BadAlloc); - ppix[npix] = pixR; - pmap->clientPixelsRed[client] = ppix; - npix = pmap->numPixelsGreen[client]; - ppix = (Pixel *) realloc(pmap->clientPixelsGreen[client], - (npix + 1) * sizeof(Pixel)); - if (!ppix) - return (BadAlloc); - ppix[npix] = pixG; - pmap->clientPixelsGreen[client] = ppix; - npix = pmap->numPixelsBlue[client]; - ppix = (Pixel *) realloc(pmap->clientPixelsBlue[client], - (npix + 1) * sizeof(Pixel)); - if (!ppix) - return (BadAlloc); - ppix[npix] = pixB; - pmap->clientPixelsBlue[client] = ppix; - pmap->numPixelsRed[client]++; - pmap->numPixelsGreen[client]++; - pmap->numPixelsBlue[client]++; - break; - - case GrayScale: - case PseudoColor: - if (pmap->mid != pmap->pScreen->defColormap && - pmap->pVisual->vid == pmap->pScreen->rootVisual) - { - ColormapPtr prootmap; - dixLookupResourceByType((pointer *)&prootmap, pmap->pScreen->defColormap, - RT_COLORMAP, clients[client], DixReadAccess); - - if (pmap->class == prootmap->class) - FindColorInRootCmap (prootmap, prootmap->red, entries, &rgb, - pPix, PSEUDOMAP, AllComp); - } - if (FindColor(pmap, pmap->red, entries, &rgb, pPix, PSEUDOMAP, - client, AllComp) != Success) - return (BadAlloc); - break; - - case DirectColor: - if (pmap->mid != pmap->pScreen->defColormap && - pmap->pVisual->vid == pmap->pScreen->rootVisual) - { - ColormapPtr prootmap; - dixLookupResourceByType((pointer *)&prootmap, pmap->pScreen->defColormap, - RT_COLORMAP, clients[client], DixReadAccess); - - if (pmap->class == prootmap->class) - { - pixR = (*pPix & pVisual->redMask) >> pVisual->offsetRed; - FindColorInRootCmap (prootmap, prootmap->red, entries, &rgb, - &pixR, REDMAP, RedComp); - pixG = (*pPix & pVisual->greenMask) >> pVisual->offsetGreen; - FindColorInRootCmap (prootmap, prootmap->green, entries, &rgb, - &pixG, GREENMAP, GreenComp); - pixB = (*pPix & pVisual->blueMask) >> pVisual->offsetBlue; - FindColorInRootCmap (prootmap, prootmap->blue, entries, &rgb, - &pixB, BLUEMAP, BlueComp); - *pPix = pixR | pixG | pixB; - } - } - - pixR = (*pPix & pVisual->redMask) >> pVisual->offsetRed; - if (FindColor(pmap, pmap->red, NUMRED(pVisual), &rgb, &pixR, REDMAP, - client, RedComp) != Success) - return (BadAlloc); - pixG = (*pPix & pVisual->greenMask) >> pVisual->offsetGreen; - if (FindColor(pmap, pmap->green, NUMGREEN(pVisual), &rgb, &pixG, - GREENMAP, client, GreenComp) != Success) - { - (void)FreeCo(pmap, client, REDMAP, 1, &pixR, (Pixel)0); - return (BadAlloc); - } - pixB = (*pPix & pVisual->blueMask) >> pVisual->offsetBlue; - if (FindColor(pmap, pmap->blue, NUMBLUE(pVisual), &rgb, &pixB, BLUEMAP, - client, BlueComp) != Success) - { - (void)FreeCo(pmap, client, GREENMAP, 1, &pixG, (Pixel)0); - (void)FreeCo(pmap, client, REDMAP, 1, &pixR, (Pixel)0); - return (BadAlloc); - } - *pPix = pixR | pixG | pixB | ALPHAMASK(pVisual); - - break; - } - - /* if this is the client's first pixel in this colormap, tell the - * resource manager that the client has pixels in this colormap which - * should be freed when the client dies */ - if ((pmap->numPixelsRed[client] == 1) && - (CLIENT_ID(pmap->mid) != client) && - !(pmap->flags & BeingCreated)) - { - colorResource *pcr; - - pcr = malloc(sizeof(colorResource)); - if (!pcr) - { - (void)FreeColors(pmap, client, 1, pPix, (Pixel)0); - return (BadAlloc); - } - pcr->mid = pmap->mid; - pcr->client = client; - if (!AddResource(FakeClientID(client), RT_CMAPENTRY, (pointer)pcr)) - return (BadAlloc); - } - return (Success); -} - -/* - * FakeAllocColor -- fake an AllocColor request by - * returning a free pixel if availible, otherwise returning - * the closest matching pixel. This is used by the mi - * software sprite code to recolor cursors. A nice side-effect - * is that this routine will never return failure. - */ - -void -FakeAllocColor (ColormapPtr pmap, xColorItem *item) -{ - Pixel pixR, pixG, pixB; - Pixel temp; - int entries; - xrgb rgb; - int class; - VisualPtr pVisual; - - pVisual = pmap->pVisual; - rgb.red = item->red; - rgb.green = item->green; - rgb.blue = item->blue; - (*pmap->pScreen->ResolveColor) (&rgb.red, &rgb.green, &rgb.blue, pVisual); - class = pmap->class; - entries = pVisual->ColormapEntries; - - switch (class) { - case GrayScale: - case PseudoColor: - temp = 0; - item->pixel = 0; - if (FindColor(pmap, pmap->red, entries, &rgb, &temp, PSEUDOMAP, - -1, AllComp) == Success) { - item->pixel = temp; - break; - } - /* fall through ... */ - case StaticColor: - case StaticGray: - item->pixel = FindBestPixel(pmap->red, entries, &rgb, PSEUDOMAP); - break; - - case DirectColor: - /* Look up each component in its own map, then OR them together */ - pixR = (item->pixel & pVisual->redMask) >> pVisual->offsetRed; - pixG = (item->pixel & pVisual->greenMask) >> pVisual->offsetGreen; - pixB = (item->pixel & pVisual->blueMask) >> pVisual->offsetBlue; - if (FindColor(pmap, pmap->red, NUMRED(pVisual), &rgb, &pixR, REDMAP, - -1, RedComp) != Success) - pixR = FindBestPixel(pmap->red, NUMRED(pVisual), &rgb, REDMAP) - << pVisual->offsetRed; - if (FindColor(pmap, pmap->green, NUMGREEN(pVisual), &rgb, &pixG, - GREENMAP, -1, GreenComp) != Success) - pixG = FindBestPixel(pmap->green, NUMGREEN(pVisual), &rgb, - GREENMAP) << pVisual->offsetGreen; - if (FindColor(pmap, pmap->blue, NUMBLUE(pVisual), &rgb, &pixB, BLUEMAP, - -1, BlueComp) != Success) - pixB = FindBestPixel(pmap->blue, NUMBLUE(pVisual), &rgb, BLUEMAP) - << pVisual->offsetBlue; - item->pixel = pixR | pixG | pixB; - break; - - case TrueColor: - /* Look up each component in its own map, then OR them together */ - pixR = FindBestPixel(pmap->red, NUMRED(pVisual), &rgb, REDMAP); - pixG = FindBestPixel(pmap->green, NUMGREEN(pVisual), &rgb, GREENMAP); - pixB = FindBestPixel(pmap->blue, NUMBLUE(pVisual), &rgb, BLUEMAP); - item->pixel = (pixR << pVisual->offsetRed) | - (pixG << pVisual->offsetGreen) | - (pixB << pVisual->offsetBlue); - break; - } -} - -/* free a pixel value obtained from FakeAllocColor */ -void -FakeFreeColor(ColormapPtr pmap, Pixel pixel) -{ - VisualPtr pVisual; - Pixel pixR, pixG, pixB; - - switch (pmap->class) { - case GrayScale: - case PseudoColor: - if (pmap->red[pixel].refcnt == AllocTemporary) - pmap->red[pixel].refcnt = 0; - break; - case DirectColor: - pVisual = pmap->pVisual; - pixR = (pixel & pVisual->redMask) >> pVisual->offsetRed; - pixG = (pixel & pVisual->greenMask) >> pVisual->offsetGreen; - pixB = (pixel & pVisual->blueMask) >> pVisual->offsetBlue; - if (pmap->red[pixR].refcnt == AllocTemporary) - pmap->red[pixR].refcnt = 0; - if (pmap->green[pixG].refcnt == AllocTemporary) - pmap->green[pixG].refcnt = 0; - if (pmap->blue[pixB].refcnt == AllocTemporary) - pmap->blue[pixB].refcnt = 0; - break; - } -} - -typedef unsigned short BigNumUpper; -typedef unsigned long BigNumLower; - -#define BIGNUMLOWERBITS 24 -#define BIGNUMUPPERBITS 16 -#define BIGNUMLOWER (1 << BIGNUMLOWERBITS) -#define BIGNUMUPPER (1 << BIGNUMUPPERBITS) -#define UPPERPART(i) ((i) >> BIGNUMLOWERBITS) -#define LOWERPART(i) ((i) & (BIGNUMLOWER - 1)) - -typedef struct _bignum { - BigNumUpper upper; - BigNumLower lower; -} BigNumRec, *BigNumPtr; - -#define BigNumGreater(x,y) (((x)->upper > (y)->upper) ||\ - ((x)->upper == (y)->upper && (x)->lower > (y)->lower)) - -#define UnsignedToBigNum(u,r) (((r)->upper = UPPERPART(u)), \ - ((r)->lower = LOWERPART(u))) - -#define MaxBigNum(r) (((r)->upper = BIGNUMUPPER-1), \ - ((r)->lower = BIGNUMLOWER-1)) - -static void -BigNumAdd (BigNumPtr x, BigNumPtr y, BigNumPtr r) -{ - BigNumLower lower, carry = 0; - - lower = x->lower + y->lower; - if (lower >= BIGNUMLOWER) { - lower -= BIGNUMLOWER; - carry = 1; - } - r->lower = lower; - r->upper = x->upper + y->upper + carry; -} - -static Pixel -FindBestPixel(EntryPtr pentFirst, int size, xrgb *prgb, int channel) -{ - EntryPtr pent; - Pixel pixel, final; - long dr, dg, db; - unsigned long sq; - BigNumRec minval, sum, temp; - - final = 0; - MaxBigNum(&minval); - /* look for the minimal difference */ - for (pent = pentFirst, pixel = 0; pixel < size; pent++, pixel++) - { - dr = dg = db = 0; - switch(channel) - { - case PSEUDOMAP: - dg = (long) pent->co.local.green - prgb->green; - db = (long) pent->co.local.blue - prgb->blue; - case REDMAP: - dr = (long) pent->co.local.red - prgb->red; - break; - case GREENMAP: - dg = (long) pent->co.local.green - prgb->green; - break; - case BLUEMAP: - db = (long) pent->co.local.blue - prgb->blue; - break; - } - sq = dr * dr; - UnsignedToBigNum (sq, &sum); - sq = dg * dg; - UnsignedToBigNum (sq, &temp); - BigNumAdd (&sum, &temp, &sum); - sq = db * db; - UnsignedToBigNum (sq, &temp); - BigNumAdd (&sum, &temp, &sum); - if (BigNumGreater (&minval, &sum)) - { - final = pixel; - minval = sum; - } - } - return(final); -} - -static void -FindColorInRootCmap (ColormapPtr pmap, EntryPtr pentFirst, int size, - xrgb *prgb, Pixel *pPixel, int channel, - ColorCompareProcPtr comp) -{ - EntryPtr pent; - Pixel pixel; - int count; - - if ((pixel = *pPixel) >= size) - pixel = 0; - for (pent = pentFirst + pixel, count = size; --count >= 0; pent++, pixel++) - { - if (pent->refcnt > 0 && (*comp) (pent, prgb)) - { - switch (channel) - { - case REDMAP: - pixel <<= pmap->pVisual->offsetRed; - break; - case GREENMAP: - pixel <<= pmap->pVisual->offsetGreen; - break; - case BLUEMAP: - pixel <<= pmap->pVisual->offsetBlue; - break; - default: /* PSEUDOMAP */ - break; - } - *pPixel = pixel; - } - } -} - -/* Tries to find a color in pmap that exactly matches the one requested in prgb - * if it can't it allocates one. - * Starts looking at pentFirst + *pPixel, so if you want a specific pixel, - * load *pPixel with that value, otherwise set it to 0 - */ -int -FindColor (ColormapPtr pmap, EntryPtr pentFirst, int size, xrgb *prgb, - Pixel *pPixel, int channel, int client, - ColorCompareProcPtr comp) -{ - EntryPtr pent; - Bool foundFree; - Pixel pixel, Free = 0; - int npix, count, *nump = NULL; - Pixel **pixp = NULL, *ppix; - xColorItem def; - - foundFree = FALSE; - - if((pixel = *pPixel) >= size) - pixel = 0; - /* see if there is a match, and also look for a free entry */ - for (pent = pentFirst + pixel, count = size; --count >= 0; ) - { - if (pent->refcnt > 0) - { - if ((*comp) (pent, prgb)) - { - if (client >= 0) - pent->refcnt++; - *pPixel = pixel; - switch(channel) - { - case REDMAP: - *pPixel <<= pmap->pVisual->offsetRed; - case PSEUDOMAP: - break; - case GREENMAP: - *pPixel <<= pmap->pVisual->offsetGreen; - break; - case BLUEMAP: - *pPixel <<= pmap->pVisual->offsetBlue; - break; - } - goto gotit; - } - } - else if (!foundFree && pent->refcnt == 0) - { - Free = pixel; - foundFree = TRUE; - /* If we're initializing the colormap, then we are looking for - * the first free cell we can find, not to minimize the number - * of entries we use. So don't look any further. */ - if(pmap->flags & BeingCreated) - break; - } - pixel++; - if(pixel >= size) - { - pent = pentFirst; - pixel = 0; - } - else - pent++; - } - - /* If we got here, we didn't find a match. If we also didn't find - * a free entry, we're out of luck. Otherwise, we'll usurp a free - * entry and fill it in */ - if (!foundFree) - return (BadAlloc); - pent = pentFirst + Free; - pent->fShared = FALSE; - pent->refcnt = (client >= 0) ? 1 : AllocTemporary; - - switch (channel) - { - case PSEUDOMAP: - pent->co.local.red = prgb->red; - pent->co.local.green = prgb->green; - pent->co.local.blue = prgb->blue; - def.red = prgb->red; - def.green = prgb->green; - def.blue = prgb->blue; - def.flags = (DoRed|DoGreen|DoBlue); - if (client >= 0) - pmap->freeRed--; - def.pixel = Free; - break; - - case REDMAP: - pent->co.local.red = prgb->red; - def.red = prgb->red; - def.green = pmap->green[0].co.local.green; - def.blue = pmap->blue[0].co.local.blue; - def.flags = DoRed; - if (client >= 0) - pmap->freeRed--; - def.pixel = Free << pmap->pVisual->offsetRed; - break; - - case GREENMAP: - pent->co.local.green = prgb->green; - def.red = pmap->red[0].co.local.red; - def.green = prgb->green; - def.blue = pmap->blue[0].co.local.blue; - def.flags = DoGreen; - if (client >= 0) - pmap->freeGreen--; - def.pixel = Free << pmap->pVisual->offsetGreen; - break; - - case BLUEMAP: - pent->co.local.blue = prgb->blue; - def.red = pmap->red[0].co.local.red; - def.green = pmap->green[0].co.local.green; - def.blue = prgb->blue; - def.flags = DoBlue; - if (client >= 0) - pmap->freeBlue--; - def.pixel = Free << pmap->pVisual->offsetBlue; - break; - } - (*pmap->pScreen->StoreColors) (pmap, 1, &def); - pixel = Free; - *pPixel = def.pixel; - -gotit: - if (pmap->flags & BeingCreated || client == -1) - return(Success); - /* Now remember the pixel, for freeing later */ - switch (channel) - { - case PSEUDOMAP: - case REDMAP: - nump = pmap->numPixelsRed; - pixp = pmap->clientPixelsRed; - break; - - case GREENMAP: - nump = pmap->numPixelsGreen; - pixp = pmap->clientPixelsGreen; - break; - - case BLUEMAP: - nump = pmap->numPixelsBlue; - pixp = pmap->clientPixelsBlue; - break; - } - npix = nump[client]; - ppix = (Pixel *) realloc(pixp[client], (npix + 1) * sizeof(Pixel)); - if (!ppix) - { - pent->refcnt--; - if (!pent->fShared) - switch (channel) - { - case PSEUDOMAP: - case REDMAP: - pmap->freeRed++; - break; - case GREENMAP: - pmap->freeGreen++; - break; - case BLUEMAP: - pmap->freeBlue++; - break; - } - return(BadAlloc); - } - ppix[npix] = pixel; - pixp[client] = ppix; - nump[client]++; - - return(Success); -} - -/* Comparison functions -- passed to FindColor to determine if an - * entry is already the color we're looking for or not */ -static int -AllComp (EntryPtr pent, xrgb *prgb) -{ - if((pent->co.local.red == prgb->red) && - (pent->co.local.green == prgb->green) && - (pent->co.local.blue == prgb->blue) ) - return (1); - return (0); -} - -static int -RedComp (EntryPtr pent, xrgb *prgb) -{ - if (pent->co.local.red == prgb->red) - return (1); - return (0); -} - -static int -GreenComp (EntryPtr pent, xrgb *prgb) -{ - if (pent->co.local.green == prgb->green) - return (1); - return (0); -} - -static int -BlueComp (EntryPtr pent, xrgb *prgb) -{ - if (pent->co.local.blue == prgb->blue) - return (1); - return (0); -} - - -/* Read the color value of a cell */ - -int -QueryColors (ColormapPtr pmap, int count, Pixel *ppixIn, xrgb *prgbList, ClientPtr client) -{ - Pixel *ppix, pixel; - xrgb *prgb; - VisualPtr pVisual; - EntryPtr pent; - Pixel i; - int errVal = Success; - - pVisual = pmap->pVisual; - if ((pmap->class | DynamicClass) == DirectColor) - { - int numred, numgreen, numblue; - Pixel rgbbad; - - numred = NUMRED(pVisual); - numgreen = NUMGREEN(pVisual); - numblue = NUMBLUE(pVisual); - rgbbad = ~RGBMASK(pVisual); - for( ppix = ppixIn, prgb = prgbList; --count >= 0; ppix++, prgb++) - { - pixel = *ppix; - if (pixel & rgbbad) { - client->errorValue = pixel; - errVal = BadValue; - continue; - } - i = (pixel & pVisual->redMask) >> pVisual->offsetRed; - if (i >= numred) - { - client->errorValue = pixel; - errVal = BadValue; - continue; - } - prgb->red = pmap->red[i].co.local.red; - i = (pixel & pVisual->greenMask) >> pVisual->offsetGreen; - if (i >= numgreen) - { - client->errorValue = pixel; - errVal = BadValue; - continue; - } - prgb->green = pmap->green[i].co.local.green; - i = (pixel & pVisual->blueMask) >> pVisual->offsetBlue; - if (i >= numblue) - { - client->errorValue = pixel; - errVal = BadValue; - continue; - } - prgb->blue = pmap->blue[i].co.local.blue; - } - } - else - { - for( ppix = ppixIn, prgb = prgbList; --count >= 0; ppix++, prgb++) - { - pixel = *ppix; - if (pixel >= pVisual->ColormapEntries) - { - client->errorValue = pixel; - errVal = BadValue; - } - else - { - pent = (EntryPtr)&pmap->red[pixel]; - if (pent->fShared) - { - prgb->red = pent->co.shco.red->color; - prgb->green = pent->co.shco.green->color; - prgb->blue = pent->co.shco.blue->color; - } - else - { - prgb->red = pent->co.local.red; - prgb->green = pent->co.local.green; - prgb->blue = pent->co.local.blue; - } - } - } - } - return (errVal); -} - -static void -FreePixels(ColormapPtr pmap, int client) -{ - Pixel *ppix, *ppixStart; - int n; - int class; - - class = pmap->class; - ppixStart = pmap->clientPixelsRed[client]; - if (class & DynamicClass) - { - n = pmap->numPixelsRed[client]; - for (ppix = ppixStart; --n >= 0; ) - { - FreeCell(pmap, *ppix, REDMAP); - ppix++; - } - } - - free(ppixStart); - pmap->clientPixelsRed[client] = (Pixel *) NULL; - pmap->numPixelsRed[client] = 0; - if ((class | DynamicClass) == DirectColor) - { - ppixStart = pmap->clientPixelsGreen[client]; - if (class & DynamicClass) - for (ppix = ppixStart, n = pmap->numPixelsGreen[client]; --n >= 0;) - FreeCell(pmap, *ppix++, GREENMAP); - free(ppixStart); - pmap->clientPixelsGreen[client] = (Pixel *) NULL; - pmap->numPixelsGreen[client] = 0; - - ppixStart = pmap->clientPixelsBlue[client]; - if (class & DynamicClass) - for (ppix = ppixStart, n = pmap->numPixelsBlue[client]; --n >= 0; ) - FreeCell(pmap, *ppix++, BLUEMAP); - free(ppixStart); - pmap->clientPixelsBlue[client] = (Pixel *) NULL; - pmap->numPixelsBlue[client] = 0; - } -} - -/** - * Frees all of a client's colors and cells. - * - * \param value must conform to DeleteType - * \unused fakeid - */ -int -FreeClientPixels (pointer value, XID fakeid) -{ - pointer pmap; - colorResource *pcr = value; - int rc; - - rc = dixLookupResourceByType(&pmap, pcr->mid, RT_COLORMAP, serverClient, - DixRemoveAccess); - if (rc == Success) - FreePixels((ColormapPtr)pmap, pcr->client); - free(pcr); - return Success; -} - -int -AllocColorCells (int client, ColormapPtr pmap, int colors, int planes, - Bool contig, Pixel *ppix, Pixel *masks) -{ - Pixel rmask, gmask, bmask, *ppixFirst, r, g, b; - int n, class; - int ok; - int oldcount; - colorResource *pcr = (colorResource *)NULL; - - class = pmap->class; - if (!(class & DynamicClass)) - return (BadAlloc); /* Shouldn't try on this type */ - oldcount = pmap->numPixelsRed[client]; - if (pmap->class == DirectColor) - oldcount += pmap->numPixelsGreen[client] + pmap->numPixelsBlue[client]; - if (!oldcount && (CLIENT_ID(pmap->mid) != client)) - { - pcr = malloc(sizeof(colorResource)); - if (!pcr) - return (BadAlloc); - } - - if (pmap->class == DirectColor) - { - ok = AllocDirect (client, pmap, colors, planes, planes, planes, - contig, ppix, &rmask, &gmask, &bmask); - if(ok == Success) - { - for (r = g = b = 1, n = planes; --n >= 0; r += r, g += g, b += b) - { - while(!(rmask & r)) - r += r; - while(!(gmask & g)) - g += g; - while(!(bmask & b)) - b += b; - *masks++ = r | g | b; - } - } - } - else - { - ok = AllocPseudo (client, pmap, colors, planes, contig, ppix, &rmask, - &ppixFirst); - if(ok == Success) - { - for (r = 1, n = planes; --n >= 0; r += r) - { - while(!(rmask & r)) - r += r; - *masks++ = r; - } - } - } - - /* if this is the client's first pixels in this colormap, tell the - * resource manager that the client has pixels in this colormap which - * should be freed when the client dies */ - if ((ok == Success) && pcr) - { - pcr->mid = pmap->mid; - pcr->client = client; - if (!AddResource(FakeClientID(client), RT_CMAPENTRY, (pointer)pcr)) - ok = BadAlloc; - } else if (pcr) - free(pcr); - - return (ok); -} - - -int -AllocColorPlanes (int client, ColormapPtr pmap, int colors, - int r, int g, int b, Bool contig, Pixel *pixels, - Pixel *prmask, Pixel *pgmask, Pixel *pbmask) -{ - int ok; - Pixel mask, *ppixFirst; - Pixel shift; - int i; - int class; - int oldcount; - colorResource *pcr = (colorResource *)NULL; - - class = pmap->class; - if (!(class & DynamicClass)) - return (BadAlloc); /* Shouldn't try on this type */ - oldcount = pmap->numPixelsRed[client]; - if (class == DirectColor) - oldcount += pmap->numPixelsGreen[client] + pmap->numPixelsBlue[client]; - if (!oldcount && (CLIENT_ID(pmap->mid) != client)) - { - pcr = malloc(sizeof(colorResource)); - if (!pcr) - return (BadAlloc); - } - - if (class == DirectColor) - { - ok = AllocDirect (client, pmap, colors, r, g, b, contig, pixels, - prmask, pgmask, pbmask); - } - else - { - /* Allocate the proper pixels */ - /* XXX This is sort of bad, because of contig is set, we force all - * r + g + b bits to be contiguous. Should only force contiguity - * per mask - */ - ok = AllocPseudo (client, pmap, colors, r + g + b, contig, pixels, - &mask, &ppixFirst); - - if(ok == Success) - { - /* now split that mask into three */ - *prmask = *pgmask = *pbmask = 0; - shift = 1; - for (i = r; --i >= 0; shift += shift) - { - while (!(mask & shift)) - shift += shift; - *prmask |= shift; - } - for (i = g; --i >= 0; shift += shift) - { - while (!(mask & shift)) - shift += shift; - *pgmask |= shift; - } - for (i = b; --i >= 0; shift += shift) - { - while (!(mask & shift)) - shift += shift; - *pbmask |= shift; - } - - /* set up the shared color cells */ - if (!AllocShared(pmap, pixels, colors, r, g, b, - *prmask, *pgmask, *pbmask, ppixFirst)) - { - (void)FreeColors(pmap, client, colors, pixels, mask); - ok = BadAlloc; - } - } - } - - /* if this is the client's first pixels in this colormap, tell the - * resource manager that the client has pixels in this colormap which - * should be freed when the client dies */ - if ((ok == Success) && pcr) - { - pcr->mid = pmap->mid; - pcr->client = client; - if (!AddResource(FakeClientID(client), RT_CMAPENTRY, (pointer)pcr)) - ok = BadAlloc; - } else if (pcr) - free(pcr); - - return (ok); -} - -static int -AllocDirect (int client, ColormapPtr pmap, int c, int r, int g, int b, Bool contig, - Pixel *pixels, Pixel *prmask, Pixel *pgmask, Pixel *pbmask) -{ - Pixel *ppixRed, *ppixGreen, *ppixBlue; - Pixel *ppix, *pDst, *p; - int npix, npixR, npixG, npixB; - Bool okR, okG, okB; - Pixel *rpix = 0, *gpix = 0, *bpix = 0; - - npixR = c << r; - npixG = c << g; - npixB = c << b; - if ((r >= 32) || (g >= 32) || (b >= 32) || - (npixR > pmap->freeRed) || (npixR < c) || - (npixG > pmap->freeGreen) || (npixG < c) || - (npixB > pmap->freeBlue) || (npixB < c)) - return BadAlloc; - - /* start out with empty pixels */ - for(p = pixels; p < pixels + c; p++) - *p = 0; - - ppixRed = malloc(npixR * sizeof(Pixel)); - ppixGreen = malloc(npixG * sizeof(Pixel)); - ppixBlue = malloc(npixB * sizeof(Pixel)); - if (!ppixRed || !ppixGreen || !ppixBlue) - { - if (ppixBlue) free(ppixBlue); - if (ppixGreen) free(ppixGreen); - if (ppixRed) free(ppixRed); - return(BadAlloc); - } - - okR = AllocCP(pmap, pmap->red, c, r, contig, ppixRed, prmask); - okG = AllocCP(pmap, pmap->green, c, g, contig, ppixGreen, pgmask); - okB = AllocCP(pmap, pmap->blue, c, b, contig, ppixBlue, pbmask); - - if (okR && okG && okB) - { - rpix = (Pixel *) realloc(pmap->clientPixelsRed[client], - (pmap->numPixelsRed[client] + (c << r)) * - sizeof(Pixel)); - if (rpix) - pmap->clientPixelsRed[client] = rpix; - gpix = (Pixel *) realloc(pmap->clientPixelsGreen[client], - (pmap->numPixelsGreen[client] + (c << g)) * - sizeof(Pixel)); - if (gpix) - pmap->clientPixelsGreen[client] = gpix; - bpix = (Pixel *) realloc(pmap->clientPixelsBlue[client], - (pmap->numPixelsBlue[client] + (c << b)) * - sizeof(Pixel)); - if (bpix) - pmap->clientPixelsBlue[client] = bpix; - } - - if (!okR || !okG || !okB || !rpix || !gpix || !bpix) - { - if (okR) - for(ppix = ppixRed, npix = npixR; --npix >= 0; ppix++) - pmap->red[*ppix].refcnt = 0; - if (okG) - for(ppix = ppixGreen, npix = npixG; --npix >= 0; ppix++) - pmap->green[*ppix].refcnt = 0; - if (okB) - for(ppix = ppixBlue, npix = npixB; --npix >= 0; ppix++) - pmap->blue[*ppix].refcnt = 0; - free(ppixBlue); - free(ppixGreen); - free(ppixRed); - return(BadAlloc); - } - - *prmask <<= pmap->pVisual->offsetRed; - *pgmask <<= pmap->pVisual->offsetGreen; - *pbmask <<= pmap->pVisual->offsetBlue; - - ppix = rpix + pmap->numPixelsRed[client]; - for (pDst = pixels, p = ppixRed; p < ppixRed + npixR; p++) - { - *ppix++ = *p; - if(p < ppixRed + c) - *pDst++ |= *p << pmap->pVisual->offsetRed; - } - pmap->numPixelsRed[client] += npixR; - pmap->freeRed -= npixR; - - ppix = gpix + pmap->numPixelsGreen[client]; - for (pDst = pixels, p = ppixGreen; p < ppixGreen + npixG; p++) - { - *ppix++ = *p; - if(p < ppixGreen + c) - *pDst++ |= *p << pmap->pVisual->offsetGreen; - } - pmap->numPixelsGreen[client] += npixG; - pmap->freeGreen -= npixG; - - ppix = bpix + pmap->numPixelsBlue[client]; - for (pDst = pixels, p = ppixBlue; p < ppixBlue + npixB; p++) - { - *ppix++ = *p; - if(p < ppixBlue + c) - *pDst++ |= *p << pmap->pVisual->offsetBlue; - } - pmap->numPixelsBlue[client] += npixB; - pmap->freeBlue -= npixB; - - - for (pDst = pixels; pDst < pixels + c; pDst++) - *pDst |= ALPHAMASK(pmap->pVisual); - - free(ppixBlue); - free(ppixGreen); - free(ppixRed); - - return (Success); -} - -static int -AllocPseudo (int client, ColormapPtr pmap, int c, int r, Bool contig, - Pixel *pixels, Pixel *pmask, Pixel **pppixFirst) -{ - Pixel *ppix, *p, *pDst, *ppixTemp; - int npix; - Bool ok; - - npix = c << r; - if ((r >= 32) || (npix > pmap->freeRed) || (npix < c)) - return(BadAlloc); - if(!(ppixTemp = malloc(npix * sizeof(Pixel)))) - return(BadAlloc); - ok = AllocCP(pmap, pmap->red, c, r, contig, ppixTemp, pmask); - - if (ok) - { - - /* all the allocated pixels are added to the client pixel list, - * but only the unique ones are returned to the client */ - ppix = (Pixel *)realloc(pmap->clientPixelsRed[client], - (pmap->numPixelsRed[client] + npix) * sizeof(Pixel)); - if (!ppix) - { - for (p = ppixTemp; p < ppixTemp + npix; p++) - pmap->red[*p].refcnt = 0; - return (BadAlloc); - } - pmap->clientPixelsRed[client] = ppix; - ppix += pmap->numPixelsRed[client]; - *pppixFirst = ppix; - pDst = pixels; - for (p = ppixTemp; p < ppixTemp + npix; p++) - { - *ppix++ = *p; - if(p < ppixTemp + c) - *pDst++ = *p; - } - pmap->numPixelsRed[client] += npix; - pmap->freeRed -= npix; - } - free(ppixTemp); - return (ok ? Success : BadAlloc); -} - -/* Allocates count << planes pixels from colormap pmap for client. If - * contig, then the plane mask is made of consecutive bits. Returns - * all count << pixels in the array pixels. The first count of those - * pixels are the unique pixels. *pMask has the mask to Or with the - * unique pixels to get the rest of them. - * - * Returns True iff all pixels could be allocated - * All cells allocated will have refcnt set to AllocPrivate and shared to FALSE - * (see AllocShared for why we care) - */ -static Bool -AllocCP (ColormapPtr pmap, EntryPtr pentFirst, int count, int planes, - Bool contig, Pixel *pixels, Pixel *pMask) -{ - EntryPtr ent; - Pixel pixel, base, entries, maxp, save; - int dplanes, found; - Pixel *ppix; - Pixel mask; - Pixel finalmask; - - dplanes = pmap->pVisual->nplanes; - - /* Easy case. Allocate pixels only */ - if (planes == 0) - { - /* allocate writable entries */ - ppix = pixels; - ent = pentFirst; - pixel = 0; - while (--count >= 0) - { - /* Just find count unallocated cells */ - while (ent->refcnt) - { - ent++; - pixel++; - } - ent->refcnt = AllocPrivate; - *ppix++ = pixel; - ent->fShared = FALSE; - } - *pMask = 0; - return (TRUE); - } - else if (planes > dplanes) - { - return (FALSE); - } - - /* General case count pixels * 2 ^ planes cells to be allocated */ - - /* make room for new pixels */ - ent = pentFirst; - - /* first try for contiguous planes, since it's fastest */ - for (mask = (((Pixel)1) << planes) - 1, base = 1, dplanes -= (planes - 1); - --dplanes >= 0; - mask += mask, base += base) - { - ppix = pixels; - found = 0; - pixel = 0; - entries = pmap->pVisual->ColormapEntries - mask; - while (pixel < entries) - { - save = pixel; - maxp = pixel + mask + base; - /* check if all are free */ - while (pixel != maxp && ent[pixel].refcnt == 0) - pixel += base; - if (pixel == maxp) - { - /* this one works */ - *ppix++ = save; - found++; - if (found == count) - { - /* found enough, allocate them all */ - while (--count >= 0) - { - pixel = pixels[count]; - maxp = pixel + mask; - while (1) - { - ent[pixel].refcnt = AllocPrivate; - ent[pixel].fShared = FALSE; - if (pixel == maxp) - break; - pixel += base; - *ppix++ = pixel; - } - } - *pMask = mask; - return (TRUE); - } - } - pixel = save + 1; - if (pixel & mask) - pixel += mask; - } - } - - dplanes = pmap->pVisual->nplanes; - if (contig || planes == 1 || dplanes < 3) - return (FALSE); - - /* this will be very slow for large maps, need a better algorithm */ - - /* - we can generate the smallest and largest numbers that fits in dplanes - bits and contain exactly planes bits set as follows. First, we need to - check that it is possible to generate such a mask at all. - (Non-contiguous masks need one more bit than contiguous masks). Then - the smallest such mask consists of the rightmost planes-1 bits set, then - a zero, then a one in position planes + 1. The formula is - (3 << (planes-1)) -1 - The largest such masks consists of the leftmost planes-1 bits set, then - a zero, then a one bit in position dplanes-planes-1. If dplanes is - smaller than 32 (the number of bits in a word) then the formula is: - (1<>> - - */ - - finalmask = - (((((Pixel)1)<<(planes-1)) - 1) << (dplanes-planes+1)) + - (((Pixel)1)<<(dplanes-planes-1)); - for (mask = (((Pixel)3) << (planes -1)) - 1; mask <= finalmask; mask++) - { - /* next 3 magic statements count number of ones (HAKMEM #169) */ - pixel = (mask >> 1) & 033333333333; - pixel = mask - pixel - ((pixel >> 1) & 033333333333); - if ((((pixel + (pixel >> 3)) & 030707070707) % 077) != planes) - continue; - ppix = pixels; - found = 0; - entries = pmap->pVisual->ColormapEntries - mask; - base = lowbit (mask); - for (pixel = 0; pixel < entries; pixel++) - { - if (pixel & mask) - continue; - maxp = 0; - /* check if all are free */ - while (ent[pixel + maxp].refcnt == 0) - { - GetNextBitsOrBreak(maxp, mask, base); - } - if ((maxp < mask) || (ent[pixel + mask].refcnt != 0)) - continue; - /* this one works */ - *ppix++ = pixel; - found++; - if (found < count) - continue; - /* found enough, allocate them all */ - while (--count >= 0) - { - pixel = (pixels)[count]; - maxp = 0; - while (1) - { - ent[pixel + maxp].refcnt = AllocPrivate; - ent[pixel + maxp].fShared = FALSE; - GetNextBitsOrBreak(maxp, mask, base); - *ppix++ = pixel + maxp; - } - } - - *pMask = mask; - return (TRUE); - } - } - return (FALSE); -} - -/** - * - * \param ppixFirst First of the client's new pixels - */ -static Bool -AllocShared (ColormapPtr pmap, Pixel *ppix, int c, int r, int g, int b, - Pixel rmask, Pixel gmask, Pixel bmask, Pixel *ppixFirst) -{ - Pixel *pptr, *cptr; - int npix, z, npixClientNew, npixShared; - Pixel basemask, base, bits, common; - SHAREDCOLOR *pshared, **ppshared, **psharedList; - - npixClientNew = c << (r + g + b); - npixShared = (c << r) + (c << g) + (c << b); - psharedList = malloc(npixShared * sizeof(SHAREDCOLOR *)); - if (!psharedList) - return FALSE; - ppshared = psharedList; - for (z = npixShared; --z >= 0; ) - { - if (!(ppshared[z] = malloc(sizeof(SHAREDCOLOR)))) - { - for (z++ ; z < npixShared; z++) - free(ppshared[z]); - return FALSE; - } - } - for(pptr = ppix, npix = c; --npix >= 0; pptr++) - { - basemask = ~(gmask | bmask); - common = *pptr & basemask; - if (rmask) - { - bits = 0; - base = lowbit (rmask); - while(1) - { - pshared = *ppshared++; - pshared->refcnt = 1 << (g + b); - for (cptr = ppixFirst, z = npixClientNew; --z >= 0; cptr++) - { - if ((*cptr & basemask) == (common | bits)) - { - pmap->red[*cptr].fShared = TRUE; - pmap->red[*cptr].co.shco.red = pshared; - } - } - GetNextBitsOrBreak(bits, rmask, base); - } - } - else - { - pshared = *ppshared++; - pshared->refcnt = 1 << (g + b); - for (cptr = ppixFirst, z = npixClientNew; --z >= 0; cptr++) - { - if ((*cptr & basemask) == common) - { - pmap->red[*cptr].fShared = TRUE; - pmap->red[*cptr].co.shco.red = pshared; - } - } - } - basemask = ~(rmask | bmask); - common = *pptr & basemask; - if (gmask) - { - bits = 0; - base = lowbit (gmask); - while(1) - { - pshared = *ppshared++; - pshared->refcnt = 1 << (r + b); - for (cptr = ppixFirst, z = npixClientNew; --z >= 0; cptr++) - { - if ((*cptr & basemask) == (common | bits)) - { - pmap->red[*cptr].co.shco.green = pshared; - } - } - GetNextBitsOrBreak(bits, gmask, base); - } - } - else - { - pshared = *ppshared++; - pshared->refcnt = 1 << (g + b); - for (cptr = ppixFirst, z = npixClientNew; --z >= 0; cptr++) - { - if ((*cptr & basemask) == common) - { - pmap->red[*cptr].co.shco.green = pshared; - } - } - } - basemask = ~(rmask | gmask); - common = *pptr & basemask; - if (bmask) - { - bits = 0; - base = lowbit (bmask); - while(1) - { - pshared = *ppshared++; - pshared->refcnt = 1 << (r + g); - for (cptr = ppixFirst, z = npixClientNew; --z >= 0; cptr++) - { - if ((*cptr & basemask) == (common | bits)) - { - pmap->red[*cptr].co.shco.blue = pshared; - } - } - GetNextBitsOrBreak(bits, bmask, base); - } - } - else - { - pshared = *ppshared++; - pshared->refcnt = 1 << (g + b); - for (cptr = ppixFirst, z = npixClientNew; --z >= 0; cptr++) - { - if ((*cptr & basemask) == common) - { - pmap->red[*cptr].co.shco.blue = pshared; - } - } - } - } - free(psharedList); - return TRUE; -} - - -/** FreeColors - * Free colors and/or cells (probably slow for large numbers) - */ -int -FreeColors (ColormapPtr pmap, int client, int count, Pixel *pixels, Pixel mask) -{ - int rval, result, class; - Pixel rmask; - - class = pmap->class; - if (pmap->flags & AllAllocated) - return(BadAccess); - if ((class | DynamicClass) == DirectColor) - { - rmask = mask & RGBMASK(pmap->pVisual); - result = FreeCo(pmap, client, REDMAP, count, pixels, - mask & pmap->pVisual->redMask); - /* If any of the three calls fails, we must report that, if more - * than one fails, it's ok that we report the last one */ - rval = FreeCo(pmap, client, GREENMAP, count, pixels, - mask & pmap->pVisual->greenMask); - if(rval != Success) - result = rval; - rval = FreeCo(pmap, client, BLUEMAP, count, pixels, - mask & pmap->pVisual->blueMask); - if(rval != Success) - result = rval; - } - else - { - rmask = mask & ((((Pixel)1) << pmap->pVisual->nplanes) - 1); - result = FreeCo(pmap, client, PSEUDOMAP, count, pixels, rmask); - } - if ((mask != rmask) && count) - { - clients[client]->errorValue = *pixels | mask; - result = BadValue; - } - /* XXX should worry about removing any RT_CMAPENTRY resource */ - return (result); -} - -/** - * Helper for FreeColors -- frees all combinations of *newpixels and mask bits - * which the client has allocated in channel colormap cells of pmap. - * doesn't change newpixels if it doesn't need to - * - * \param pmap which colormap head - * \param color which sub-map, eg, RED, BLUE, PSEUDO - * \param npixIn number of pixels passed in - * \param ppixIn number of base pixels - * \param mask mask client gave us - */ -static int -FreeCo (ColormapPtr pmap, int client, int color, int npixIn, Pixel *ppixIn, Pixel mask) -{ - Pixel *ppixClient, pixTest; - int npixClient, npixNew, npix; - Pixel bits, base, cmask, rgbbad; - Pixel *pptr, *cptr; - int n, zapped; - int errVal = Success; - int offset, numents; - - if (npixIn == 0) - return (errVal); - bits = 0; - zapped = 0; - base = lowbit (mask); - - switch(color) - { - case REDMAP: - cmask = pmap->pVisual->redMask; - rgbbad = ~RGBMASK(pmap->pVisual); - offset = pmap->pVisual->offsetRed; - numents = (cmask >> offset) + 1; - ppixClient = pmap->clientPixelsRed[client]; - npixClient = pmap->numPixelsRed[client]; - break; - case GREENMAP: - cmask = pmap->pVisual->greenMask; - rgbbad = ~RGBMASK(pmap->pVisual); - offset = pmap->pVisual->offsetGreen; - numents = (cmask >> offset) + 1; - ppixClient = pmap->clientPixelsGreen[client]; - npixClient = pmap->numPixelsGreen[client]; - break; - case BLUEMAP: - cmask = pmap->pVisual->blueMask; - rgbbad = ~RGBMASK(pmap->pVisual); - offset = pmap->pVisual->offsetBlue; - numents = (cmask >> offset) + 1; - ppixClient = pmap->clientPixelsBlue[client]; - npixClient = pmap->numPixelsBlue[client]; - break; - default: /* so compiler can see that everything gets initialized */ - case PSEUDOMAP: - cmask = ~((Pixel)0); - rgbbad = 0; - offset = 0; - numents = pmap->pVisual->ColormapEntries; - ppixClient = pmap->clientPixelsRed[client]; - npixClient = pmap->numPixelsRed[client]; - break; - } - - - /* zap all pixels which match */ - while (1) - { - /* go through pixel list */ - for (pptr = ppixIn, n = npixIn; --n >= 0; pptr++) - { - pixTest = ((*pptr | bits) & cmask) >> offset; - if ((pixTest >= numents) || (*pptr & rgbbad)) - { - clients[client]->errorValue = *pptr | bits; - errVal = BadValue; - continue; - } - - /* find match in client list */ - for (cptr = ppixClient, npix = npixClient; - --npix >= 0 && *cptr != pixTest; - cptr++) ; - - if (npix >= 0) - { - if (pmap->class & DynamicClass) - { - FreeCell(pmap, pixTest, color); - } - *cptr = ~((Pixel)0); - zapped++; - } - else - errVal = BadAccess; - } - /* generate next bits value */ - GetNextBitsOrBreak(bits, mask, base); - } - - /* delete freed pixels from client pixel list */ - if (zapped) - { - npixNew = npixClient - zapped; - if (npixNew) - { - /* Since the list can only get smaller, we can do a copy in - * place and then realloc to a smaller size */ - pptr = cptr = ppixClient; - - /* If we have all the new pixels, we don't have to examine the - * rest of the old ones */ - for(npix = 0; npix < npixNew; cptr++) - { - if (*cptr != ~((Pixel)0)) - { - *pptr++ = *cptr; - npix++; - } - } - pptr = (Pixel *)realloc(ppixClient, npixNew * sizeof(Pixel)); - if (pptr) - ppixClient = pptr; - npixClient = npixNew; - } - else - { - npixClient = 0; - free(ppixClient); - ppixClient = (Pixel *)NULL; - } - switch(color) - { - case PSEUDOMAP: - case REDMAP: - pmap->clientPixelsRed[client] = ppixClient; - pmap->numPixelsRed[client] = npixClient; - break; - case GREENMAP: - pmap->clientPixelsGreen[client] = ppixClient; - pmap->numPixelsGreen[client] = npixClient; - break; - case BLUEMAP: - pmap->clientPixelsBlue[client] = ppixClient; - pmap->numPixelsBlue[client] = npixClient; - break; - } - } - return (errVal); -} - - - -/* Redefine color values */ -int -StoreColors (ColormapPtr pmap, int count, xColorItem *defs, ClientPtr client) -{ - Pixel pix; - xColorItem *pdef; - EntryPtr pent, pentT, pentLast; - VisualPtr pVisual; - SHAREDCOLOR *pred, *pgreen, *pblue; - int n, ChgRed, ChgGreen, ChgBlue, idef; - int class, errVal = Success; - int ok; - - - class = pmap->class; - if(!(class & DynamicClass) && !(pmap->flags & BeingCreated)) - { - return(BadAccess); - } - pVisual = pmap->pVisual; - - idef = 0; - if((class | DynamicClass) == DirectColor) - { - int numred, numgreen, numblue; - Pixel rgbbad; - - numred = NUMRED(pVisual); - numgreen = NUMGREEN(pVisual); - numblue = NUMBLUE(pVisual); - rgbbad = ~RGBMASK(pVisual); - for (pdef = defs, n = 0; n < count; pdef++, n++) - { - ok = TRUE; - (*pmap->pScreen->ResolveColor) - (&pdef->red, &pdef->green, &pdef->blue, pmap->pVisual); - - if (pdef->pixel & rgbbad) - { - errVal = BadValue; - client->errorValue = pdef->pixel; - continue; - } - pix = (pdef->pixel & pVisual->redMask) >> pVisual->offsetRed; - if (pix >= numred) - { - errVal = BadValue; - ok = FALSE; - } - else if (pmap->red[pix].refcnt != AllocPrivate) - { - errVal = BadAccess; - ok = FALSE; - } - else if (pdef->flags & DoRed) - { - pmap->red[pix].co.local.red = pdef->red; - } - else - { - pdef->red = pmap->red[pix].co.local.red; - } - - pix = (pdef->pixel & pVisual->greenMask) >> pVisual->offsetGreen; - if (pix >= numgreen) - { - errVal = BadValue; - ok = FALSE; - } - else if (pmap->green[pix].refcnt != AllocPrivate) - { - errVal = BadAccess; - ok = FALSE; - } - else if (pdef->flags & DoGreen) - { - pmap->green[pix].co.local.green = pdef->green; - } - else - { - pdef->green = pmap->green[pix].co.local.green; - } - - pix = (pdef->pixel & pVisual->blueMask) >> pVisual->offsetBlue; - if (pix >= numblue) - { - errVal = BadValue; - ok = FALSE; - } - else if (pmap->blue[pix].refcnt != AllocPrivate) - { - errVal = BadAccess; - ok = FALSE; - } - else if (pdef->flags & DoBlue) - { - pmap->blue[pix].co.local.blue = pdef->blue; - } - else - { - pdef->blue = pmap->blue[pix].co.local.blue; - } - /* If this is an o.k. entry, then it gets added to the list - * to be sent to the hardware. If not, skip it. Once we've - * skipped one, we have to copy all the others. - */ - if(ok) - { - if(idef != n) - defs[idef] = defs[n]; - idef++; - } else - client->errorValue = pdef->pixel; - } - } - else - { - for (pdef = defs, n = 0; n < count; pdef++, n++) - { - - ok = TRUE; - if (pdef->pixel >= pVisual->ColormapEntries) - { - client->errorValue = pdef->pixel; - errVal = BadValue; - ok = FALSE; - } - else if (pmap->red[pdef->pixel].refcnt != AllocPrivate) - { - errVal = BadAccess; - ok = FALSE; - } - - /* If this is an o.k. entry, then it gets added to the list - * to be sent to the hardware. If not, skip it. Once we've - * skipped one, we have to copy all the others. - */ - if(ok) - { - if(idef != n) - defs[idef] = defs[n]; - idef++; - } - else - continue; - - (*pmap->pScreen->ResolveColor) - (&pdef->red, &pdef->green, &pdef->blue, pmap->pVisual); - - pent = &pmap->red[pdef->pixel]; - - if(pdef->flags & DoRed) - { - if(pent->fShared) - { - pent->co.shco.red->color = pdef->red; - if (pent->co.shco.red->refcnt > 1) - ok = FALSE; - } - else - pent->co.local.red = pdef->red; - } - else - { - if(pent->fShared) - pdef->red = pent->co.shco.red->color; - else - pdef->red = pent->co.local.red; - } - if(pdef->flags & DoGreen) - { - if(pent->fShared) - { - pent->co.shco.green->color = pdef->green; - if (pent->co.shco.green->refcnt > 1) - ok = FALSE; - } - else - pent->co.local.green = pdef->green; - } - else - { - if(pent->fShared) - pdef->green = pent->co.shco.green->color; - else - pdef->green = pent->co.local.green; - } - if(pdef->flags & DoBlue) - { - if(pent->fShared) - { - pent->co.shco.blue->color = pdef->blue; - if (pent->co.shco.blue->refcnt > 1) - ok = FALSE; - } - else - pent->co.local.blue = pdef->blue; - } - else - { - if(pent->fShared) - pdef->blue = pent->co.shco.blue->color; - else - pdef->blue = pent->co.local.blue; - } - - if(!ok) - { - /* have to run through the colormap and change anybody who - * shares this value */ - pred = pent->co.shco.red; - pgreen = pent->co.shco.green; - pblue = pent->co.shco.blue; - ChgRed = pdef->flags & DoRed; - ChgGreen = pdef->flags & DoGreen; - ChgBlue = pdef->flags & DoBlue; - pentLast = pmap->red + pVisual->ColormapEntries; - - for(pentT = pmap->red; pentT < pentLast; pentT++) - { - if(pentT->fShared && (pentT != pent)) - { - xColorItem defChg; - - /* There are, alas, devices in this world too dumb - * to read their own hardware colormaps. Sick, but - * true. So we're going to be really nice and load - * the xColorItem with the proper value for all the - * fields. We will only set the flags for those - * fields that actually change. Smart devices can - * arrange to change only those fields. Dumb devices - * can rest assured that we have provided for them, - * and can change all three fields */ - - defChg.flags = 0; - if(ChgRed && pentT->co.shco.red == pred) - { - defChg.flags |= DoRed; - } - if(ChgGreen && pentT->co.shco.green == pgreen) - { - defChg.flags |= DoGreen; - } - if(ChgBlue && pentT->co.shco.blue == pblue) - { - defChg.flags |= DoBlue; - } - if(defChg.flags != 0) - { - defChg.pixel = pentT - pmap->red; - defChg.red = pentT->co.shco.red->color; - defChg.green = pentT->co.shco.green->color; - defChg.blue = pentT->co.shco.blue->color; - (*pmap->pScreen->StoreColors) (pmap, 1, &defChg); - } - } - } - - } - } - } - /* Note that we use idef, the count of acceptable entries, and not - * count, the count of proposed entries */ - if (idef != 0) - ( *pmap->pScreen->StoreColors) (pmap, idef, defs); - return (errVal); -} - -int -IsMapInstalled(Colormap map, WindowPtr pWin) -{ - Colormap *pmaps; - int imap, nummaps, found; - - pmaps = malloc(pWin->drawable.pScreen->maxInstalledCmaps*sizeof(Colormap)); - if(!pmaps) - return(FALSE); - nummaps = (*pWin->drawable.pScreen->ListInstalledColormaps) - (pWin->drawable.pScreen, pmaps); - found = FALSE; - for(imap = 0; imap < nummaps; imap++) - { - if(pmaps[imap] == map) - { - found = TRUE; - break; - } - } - free(pmaps); - return (found); -} - -struct colormap_lookup_data { - ScreenPtr pScreen; - VisualPtr visuals; -}; - -static void _colormap_find_resource(pointer value, XID id, - pointer cdata) -{ - struct colormap_lookup_data *cmap_data = cdata; - VisualPtr visuals = cmap_data->visuals; - ScreenPtr pScreen = cmap_data->pScreen; - ColormapPtr cmap = value; - int j; - - if (pScreen != cmap->pScreen) - return; - - j = cmap->pVisual - pScreen->visuals; - cmap->pVisual = &visuals[j]; -} - -/* something has realloced the visuals, instead of breaking - ABI fix it up here - glx and compsite did this wrong */ -Bool -ResizeVisualArray(ScreenPtr pScreen, int new_visual_count, - DepthPtr depth) -{ - struct colormap_lookup_data cdata; - int numVisuals; - VisualPtr visuals; - XID *vids, vid; - int first_new_vid, first_new_visual, i; - - first_new_vid = depth->numVids; - first_new_visual = pScreen->numVisuals; - - vids = realloc(depth->vids, (depth->numVids + new_visual_count) * sizeof(XID)); - if (!vids) - return FALSE; - - /* its realloced now no going back if we fail the next one */ - depth->vids = vids; - - numVisuals = pScreen->numVisuals + new_visual_count; - visuals = realloc(pScreen->visuals, numVisuals * sizeof(VisualRec)); - if (!visuals) { - return FALSE; - } - - cdata.visuals = visuals; - cdata.pScreen = pScreen; - FindClientResourcesByType(serverClient, RT_COLORMAP, _colormap_find_resource, &cdata); - - pScreen->visuals = visuals; - - for (i = 0; i < new_visual_count; i++) { - vid = FakeClientID(0); - pScreen->visuals[first_new_visual + i].vid = vid; - vids[first_new_vid + i] = vid; - } - - depth->numVids += new_visual_count; - pScreen->numVisuals += new_visual_count; - - return TRUE; -} +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +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. + +The above copyright notice and this permission notice 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 +OPEN GROUP 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. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 +#endif + +#include +#include +#include +#include +#include +#include "misc.h" +#include "dix.h" +#include "dixstruct.h" +#include "colormapst.h" +#include "os.h" +#include "scrnintstr.h" +#include "resource.h" +#include "windowstr.h" +#include "privates.h" +#include "xace.h" + +#ifdef _MSC_VER +#define UpdateColors thisUpdateColors +#endif + +static Pixel FindBestPixel( + EntryPtr /*pentFirst*/, + int /*size*/, + xrgb * /*prgb*/, + int /*channel*/ +); + +static int AllComp( + EntryPtr /*pent*/, + xrgb * /*prgb*/ +); + +static int RedComp( + EntryPtr /*pent*/, + xrgb * /*prgb*/ +); + +static int GreenComp( + EntryPtr /*pent*/, + xrgb * /*prgb*/ +); + +static int BlueComp( + EntryPtr /*pent*/, + xrgb * /*prgb*/ +); + +static void FreePixels( + ColormapPtr /*pmap*/, + int /*client*/ +); + +static void CopyFree( + int /*channel*/, + int /*client*/, + ColormapPtr /*pmapSrc*/, + ColormapPtr /*pmapDst*/ +); + +static void FreeCell( + ColormapPtr /*pmap*/, + Pixel /*i*/, + int /*channel*/ +); + +static void UpdateColors( + ColormapPtr /*pmap*/ +); + +static int AllocDirect( + int /*client*/, + ColormapPtr /*pmap*/, + int /*c*/, + int /*r*/, + int /*g*/, + int /*b*/, + Bool /*contig*/, + Pixel * /*pixels*/, + Pixel * /*prmask*/, + Pixel * /*pgmask*/, + Pixel * /*pbmask*/ +); + +static int AllocPseudo( + int /*client*/, + ColormapPtr /*pmap*/, + int /*c*/, + int /*r*/, + Bool /*contig*/, + Pixel * /*pixels*/, + Pixel * /*pmask*/, + Pixel ** /*pppixFirst*/ +); + +static Bool AllocCP( + ColormapPtr /*pmap*/, + EntryPtr /*pentFirst*/, + int /*count*/, + int /*planes*/, + Bool /*contig*/, + Pixel * /*pixels*/, + Pixel * /*pMask*/ +); + +static Bool AllocShared( + ColormapPtr /*pmap*/, + Pixel * /*ppix*/, + int /*c*/, + int /*r*/, + int /*g*/, + int /*b*/, + Pixel /*rmask*/, + Pixel /*gmask*/, + Pixel /*bmask*/, + Pixel * /*ppixFirst*/ +); + +static int FreeCo( + ColormapPtr /*pmap*/, + int /*client*/, + int /*color*/, + int /*npixIn*/, + Pixel * /*ppixIn*/, + Pixel /*mask*/ +); + +static int TellNoMap( + WindowPtr /*pwin*/, + Colormap * /*pmid*/ +); + +static void FindColorInRootCmap ( + ColormapPtr /* pmap */, + EntryPtr /* pentFirst */, + int /* size */, + xrgb* /* prgb */, + Pixel* /* pPixel */, + int /* channel */, + ColorCompareProcPtr /* comp */ +); + +#define NUMRED(vis) ((vis->redMask >> vis->offsetRed) + 1) +#define NUMGREEN(vis) ((vis->greenMask >> vis->offsetGreen) + 1) +#define NUMBLUE(vis) ((vis->blueMask >> vis->offsetBlue) + 1) +#if COMPOSITE +#define ALPHAMASK(vis) ((vis)->nplanes < 32 ? 0 : \ + (CARD32) ~((vis)->redMask|(vis)->greenMask|(vis)->blueMask)) +#else +#define ALPHAMASK(vis) 0 +#endif + +#define RGBMASK(vis) (vis->redMask | vis->greenMask | vis->blueMask | ALPHAMASK(vis)) + +/* GetNextBitsOrBreak(bits, mask, base) -- + * (Suggestion: First read the macro, then read this explanation. + * + * Either generate the next value to OR in to a pixel or break out of this + * while loop + * + * This macro is used when we're trying to generate all 2^n combinations of + * bits in mask. What we're doing here is counting in binary, except that + * the bits we use to count may not be contiguous. This macro will be + * called 2^n times, returning a different value in bits each time. Then + * it will cause us to break out of a surrounding loop. (It will always be + * called from within a while loop.) + * On call: mask is the value we want to find all the combinations for + * base has 1 bit set where the least significant bit of mask is set + * + * For example,if mask is 01010, base should be 0010 and we count like this: + * 00010 (see this isn't so hard), + * then we add base to bits and get 0100. (bits & ~mask) is (0100 & 0100) so + * we add that to bits getting (0100 + 0100) = + * 01000 for our next value. + * then we add 0010 to get + * 01010 and we're done (easy as 1, 2, 3) + */ +#define GetNextBitsOrBreak(bits, mask, base) \ + if((bits) == (mask)) \ + break; \ + (bits) += (base); \ + while((bits) & ~(mask)) \ + (bits) += ((bits) & ~(mask)); +/* ID of server as client */ +#define SERVER_ID 0 + +typedef struct _colorResource +{ + Colormap mid; + int client; +} colorResource; + +/* Invariants: + * refcnt == 0 means entry is empty + * refcnt > 0 means entry is useable by many clients, so it can't be changed + * refcnt == AllocPrivate means entry owned by one client only + * fShared should only be set if refcnt == AllocPrivate, and only in red map + */ + + +/** + * Create and initialize the color map + * + * \param mid resource to use for this colormap + * \param alloc 1 iff all entries are allocated writable + */ +int +CreateColormap (Colormap mid, ScreenPtr pScreen, VisualPtr pVisual, + ColormapPtr *ppcmap, int alloc, int client) +{ + int class, size; + unsigned long sizebytes; + ColormapPtr pmap; + EntryPtr pent; + int i; + Pixel *ppix, **pptr; + + class = pVisual->class; + if(!(class & DynamicClass) && (alloc != AllocNone) && (client != SERVER_ID)) + return (BadMatch); + + size = pVisual->ColormapEntries; + sizebytes = (size * sizeof(Entry)) + + (MAXCLIENTS * sizeof(Pixel *)) + + (MAXCLIENTS * sizeof(int)); + if ((class | DynamicClass) == DirectColor) + sizebytes *= 3; + sizebytes += sizeof(ColormapRec); + pmap = malloc(sizebytes); + if (!pmap) + return (BadAlloc); +#if defined(_XSERVER64) + pmap->pad0 = 0; + pmap->pad1 = 0; +#if (X_BYTE_ORDER == X_LITTLE_ENDIAN) + pmap->pad2 = 0; +#endif +#endif + pmap->red = (EntryPtr)((char *)pmap + sizeof(ColormapRec)); + sizebytes = size * sizeof(Entry); + pmap->clientPixelsRed = (Pixel **)((char *)pmap->red + sizebytes); + pmap->numPixelsRed = (int *)((char *)pmap->clientPixelsRed + + (MAXCLIENTS * sizeof(Pixel *))); + pmap->mid = mid; + pmap->flags = 0; /* start out with all flags clear */ + if(mid == pScreen->defColormap) + pmap->flags |= IsDefault; + pmap->pScreen = pScreen; + pmap->pVisual = pVisual; + pmap->class = class; + if ((class | DynamicClass) == DirectColor) + size = NUMRED(pVisual); + pmap->freeRed = size; + bzero ((char *) pmap->red, (int)sizebytes); + bzero((char *) pmap->numPixelsRed, MAXCLIENTS * sizeof(int)); + for (pptr = &pmap->clientPixelsRed[MAXCLIENTS]; --pptr >= pmap->clientPixelsRed; ) + *pptr = (Pixel *)NULL; + if (alloc == AllocAll) + { + if (class & DynamicClass) + pmap->flags |= AllAllocated; + for (pent = &pmap->red[size - 1]; pent >= pmap->red; pent--) + pent->refcnt = AllocPrivate; + pmap->freeRed = 0; + ppix = malloc(size * sizeof(Pixel)); + if (!ppix) + { + free(pmap); + return (BadAlloc); + } + pmap->clientPixelsRed[client] = ppix; + for(i = 0; i < size; i++) + ppix[i] = i; + pmap->numPixelsRed[client] = size; + } + + if ((class | DynamicClass) == DirectColor) + { + pmap->freeGreen = NUMGREEN(pVisual); + pmap->green = (EntryPtr)((char *)pmap->numPixelsRed + + (MAXCLIENTS * sizeof(int))); + pmap->clientPixelsGreen = (Pixel **)((char *)pmap->green + sizebytes); + pmap->numPixelsGreen = (int *)((char *)pmap->clientPixelsGreen + + (MAXCLIENTS * sizeof(Pixel *))); + pmap->freeBlue = NUMBLUE(pVisual); + pmap->blue = (EntryPtr)((char *)pmap->numPixelsGreen + + (MAXCLIENTS * sizeof(int))); + pmap->clientPixelsBlue = (Pixel **)((char *)pmap->blue + sizebytes); + pmap->numPixelsBlue = (int *)((char *)pmap->clientPixelsBlue + + (MAXCLIENTS * sizeof(Pixel *))); + + bzero ((char *) pmap->green, (int)sizebytes); + bzero ((char *) pmap->blue, (int)sizebytes); + + memmove((char *) pmap->clientPixelsGreen, + (char *) pmap->clientPixelsRed, + MAXCLIENTS * sizeof(Pixel *)); + memmove((char *) pmap->clientPixelsBlue, + (char *) pmap->clientPixelsRed, + MAXCLIENTS * sizeof(Pixel *)); + bzero((char *) pmap->numPixelsGreen, MAXCLIENTS * sizeof(int)); + bzero((char *) pmap->numPixelsBlue, MAXCLIENTS * sizeof(int)); + + /* If every cell is allocated, mark its refcnt */ + if (alloc == AllocAll) + { + size = pmap->freeGreen; + for(pent = &pmap->green[size-1]; pent >= pmap->green; pent--) + pent->refcnt = AllocPrivate; + pmap->freeGreen = 0; + ppix = malloc(size * sizeof(Pixel)); + if (!ppix) + { + free(pmap->clientPixelsRed[client]); + free(pmap); + return(BadAlloc); + } + pmap->clientPixelsGreen[client] = ppix; + for(i = 0; i < size; i++) + ppix[i] = i; + pmap->numPixelsGreen[client] = size; + + size = pmap->freeBlue; + for(pent = &pmap->blue[size-1]; pent >= pmap->blue; pent--) + pent->refcnt = AllocPrivate; + pmap->freeBlue = 0; + ppix = malloc(size * sizeof(Pixel)); + if (!ppix) + { + free(pmap->clientPixelsGreen[client]); + free(pmap->clientPixelsRed[client]); + free(pmap); + return(BadAlloc); + } + pmap->clientPixelsBlue[client] = ppix; + for(i = 0; i < size; i++) + ppix[i] = i; + pmap->numPixelsBlue[client] = size; + } + } + pmap->devPrivates = NULL; + pmap->flags |= BeingCreated; + + if (!AddResource(mid, RT_COLORMAP, (pointer)pmap)) + return (BadAlloc); + + /* + * Security creation/labeling check + */ + i = XaceHook(XACE_RESOURCE_ACCESS, clients[client], mid, RT_COLORMAP, + pmap, RT_NONE, NULL, DixCreateAccess); + if (i != Success) { + FreeResource(mid, RT_NONE); + return i; + } + + /* If the device wants a chance to initialize the colormap in any way, + * this is it. In specific, if this is a Static colormap, this is the + * time to fill in the colormap's values */ + if (!(*pScreen->CreateColormap)(pmap)) + { + FreeResource (mid, RT_NONE); + return BadAlloc; + } + pmap->flags &= ~BeingCreated; + *ppcmap = pmap; + return (Success); +} + +/** + * + * \param value must conform to DeleteType + */ +int +FreeColormap (pointer value, XID mid) +{ + int i; + EntryPtr pent; + ColormapPtr pmap = (ColormapPtr)value; + + if(CLIENT_ID(mid) != SERVER_ID) + { + (*pmap->pScreen->UninstallColormap) (pmap); + WalkTree(pmap->pScreen, (VisitWindowProcPtr)TellNoMap, (pointer) &mid); + } + + /* This is the device's chance to undo anything it needs to, especially + * to free any storage it allocated */ + (*pmap->pScreen->DestroyColormap)(pmap); + + if(pmap->clientPixelsRed) + { + for(i = 0; i < MAXCLIENTS; i++) + free(pmap->clientPixelsRed[i]); + } + + if ((pmap->class == PseudoColor) || (pmap->class == GrayScale)) + { + for(pent = &pmap->red[pmap->pVisual->ColormapEntries - 1]; + pent >= pmap->red; + pent--) + { + if(pent->fShared) + { + if (--pent->co.shco.red->refcnt == 0) + free(pent->co.shco.red); + if (--pent->co.shco.green->refcnt == 0) + free(pent->co.shco.green); + if (--pent->co.shco.blue->refcnt == 0) + free(pent->co.shco.blue); + } + } + } + if((pmap->class | DynamicClass) == DirectColor) + { + for(i = 0; i < MAXCLIENTS; i++) + { + free(pmap->clientPixelsGreen[i]); + free(pmap->clientPixelsBlue[i]); + } + } + + dixFreePrivates(pmap->devPrivates); + free(pmap); + return(Success); +} + +/* Tell window that pmid has disappeared */ +static int +TellNoMap (WindowPtr pwin, Colormap *pmid) +{ + xEvent xE; + + if (wColormap(pwin) == *pmid) + { + /* This should be call to DeliverEvent */ + xE.u.u.type = ColormapNotify; + xE.u.colormap.window = pwin->drawable.id; + xE.u.colormap.colormap = None; + xE.u.colormap.new = TRUE; + xE.u.colormap.state = ColormapUninstalled; +#ifdef PANORAMIX + if(noPanoramiXExtension || !pwin->drawable.pScreen->myNum) +#endif + DeliverEvents(pwin, &xE, 1, (WindowPtr)NULL); + if (pwin->optional) { + pwin->optional->colormap = None; + CheckWindowOptionalNeed (pwin); + } + } + + return (WT_WALKCHILDREN); +} + +/* Tell window that pmid got uninstalled */ +int +TellLostMap (WindowPtr pwin, pointer value) +{ + Colormap *pmid = (Colormap *)value; + xEvent xE; + +#ifdef PANORAMIX + if(!noPanoramiXExtension && pwin->drawable.pScreen->myNum) + return WT_STOPWALKING; +#endif + if (wColormap(pwin) == *pmid) + { + /* This should be call to DeliverEvent */ + xE.u.u.type = ColormapNotify; + xE.u.colormap.window = pwin->drawable.id; + xE.u.colormap.colormap = *pmid; + xE.u.colormap.new = FALSE; + xE.u.colormap.state = ColormapUninstalled; + DeliverEvents(pwin, &xE, 1, (WindowPtr)NULL); + } + + return (WT_WALKCHILDREN); +} + +/* Tell window that pmid got installed */ +int +TellGainedMap (WindowPtr pwin, pointer value) +{ + Colormap *pmid = (Colormap *)value; + xEvent xE; + +#ifdef PANORAMIX + if(!noPanoramiXExtension && pwin->drawable.pScreen->myNum) + return WT_STOPWALKING; +#endif + if (wColormap (pwin) == *pmid) + { + /* This should be call to DeliverEvent */ + xE.u.u.type = ColormapNotify; + xE.u.colormap.window = pwin->drawable.id; + xE.u.colormap.colormap = *pmid; + xE.u.colormap.new = FALSE; + xE.u.colormap.state = ColormapInstalled; + DeliverEvents(pwin, &xE, 1, (WindowPtr)NULL); + } + + return (WT_WALKCHILDREN); +} + + +int +CopyColormapAndFree (Colormap mid, ColormapPtr pSrc, int client) +{ + ColormapPtr pmap = (ColormapPtr) NULL; + int result, alloc, size; + Colormap midSrc; + ScreenPtr pScreen; + VisualPtr pVisual; + + pScreen = pSrc->pScreen; + pVisual = pSrc->pVisual; + midSrc = pSrc->mid; + alloc = ((pSrc->flags & AllAllocated) && CLIENT_ID(midSrc) == client) ? + AllocAll : AllocNone; + size = pVisual->ColormapEntries; + + /* If the create returns non-0, it failed */ + result = CreateColormap (mid, pScreen, pVisual, &pmap, alloc, client); + if(result != Success) + return(result); + if(alloc == AllocAll) + { + memmove((char *)pmap->red, (char *)pSrc->red, size * sizeof(Entry)); + if((pmap->class | DynamicClass) == DirectColor) + { + memmove((char *)pmap->green, (char *)pSrc->green, size * sizeof(Entry)); + memmove((char *)pmap->blue, (char *)pSrc->blue, size * sizeof(Entry)); + } + pSrc->flags &= ~AllAllocated; + FreePixels(pSrc, client); + UpdateColors(pmap); + return(Success); + } + + CopyFree(REDMAP, client, pSrc, pmap); + if ((pmap->class | DynamicClass) == DirectColor) + { + CopyFree(GREENMAP, client, pSrc, pmap); + CopyFree(BLUEMAP, client, pSrc, pmap); + } + if (pmap->class & DynamicClass) + UpdateColors(pmap); + /* XXX should worry about removing any RT_CMAPENTRY resource */ + return(Success); +} + +/* Helper routine for freeing large numbers of cells from a map */ +static void +CopyFree (int channel, int client, ColormapPtr pmapSrc, ColormapPtr pmapDst) +{ + int z, npix; + EntryPtr pentSrcFirst, pentDstFirst; + EntryPtr pentSrc, pentDst; + Pixel *ppix; + int nalloc; + + switch(channel) + { + default: /* so compiler can see that everything gets initialized */ + case REDMAP: + ppix = (pmapSrc->clientPixelsRed)[client]; + npix = (pmapSrc->numPixelsRed)[client]; + pentSrcFirst = pmapSrc->red; + pentDstFirst = pmapDst->red; + break; + case GREENMAP: + ppix = (pmapSrc->clientPixelsGreen)[client]; + npix = (pmapSrc->numPixelsGreen)[client]; + pentSrcFirst = pmapSrc->green; + pentDstFirst = pmapDst->green; + break; + case BLUEMAP: + ppix = (pmapSrc->clientPixelsBlue)[client]; + npix = (pmapSrc->numPixelsBlue)[client]; + pentSrcFirst = pmapSrc->blue; + pentDstFirst = pmapDst->blue; + break; + } + nalloc = 0; + if (pmapSrc->class & DynamicClass) + { + for(z = npix; --z >= 0; ppix++) + { + /* Copy entries */ + pentSrc = pentSrcFirst + *ppix; + pentDst = pentDstFirst + *ppix; + if (pentDst->refcnt > 0) + { + pentDst->refcnt++; + } + else + { + *pentDst = *pentSrc; + nalloc++; + if (pentSrc->refcnt > 0) + pentDst->refcnt = 1; + else + pentSrc->fShared = FALSE; + } + FreeCell(pmapSrc, *ppix, channel); + } + } + + /* Note that FreeCell has already fixed pmapSrc->free{Color} */ + switch(channel) + { + case REDMAP: + pmapDst->freeRed -= nalloc; + (pmapDst->clientPixelsRed)[client] = + (pmapSrc->clientPixelsRed)[client]; + (pmapSrc->clientPixelsRed)[client] = (Pixel *) NULL; + (pmapDst->numPixelsRed)[client] = (pmapSrc->numPixelsRed)[client]; + (pmapSrc->numPixelsRed)[client] = 0; + break; + case GREENMAP: + pmapDst->freeGreen -= nalloc; + (pmapDst->clientPixelsGreen)[client] = + (pmapSrc->clientPixelsGreen)[client]; + (pmapSrc->clientPixelsGreen)[client] = (Pixel *) NULL; + (pmapDst->numPixelsGreen)[client] = (pmapSrc->numPixelsGreen)[client]; + (pmapSrc->numPixelsGreen)[client] = 0; + break; + case BLUEMAP: + pmapDst->freeBlue -= nalloc; + pmapDst->clientPixelsBlue[client] = pmapSrc->clientPixelsBlue[client]; + pmapSrc->clientPixelsBlue[client] = (Pixel *) NULL; + pmapDst->numPixelsBlue[client] = pmapSrc->numPixelsBlue[client]; + pmapSrc->numPixelsBlue[client] = 0; + break; + } +} + +/* Free the ith entry in a color map. Must handle freeing of + * colors allocated through AllocColorPlanes */ +static void +FreeCell (ColormapPtr pmap, Pixel i, int channel) +{ + EntryPtr pent; + int *pCount; + + + switch (channel) + { + default: /* so compiler can see that everything gets initialized */ + case PSEUDOMAP: + case REDMAP: + pent = (EntryPtr) &pmap->red[i]; + pCount = &pmap->freeRed; + break; + case GREENMAP: + pent = (EntryPtr) &pmap->green[i]; + pCount = &pmap->freeGreen; + break; + case BLUEMAP: + pent = (EntryPtr) &pmap->blue[i]; + pCount = &pmap->freeBlue; + break; + } + /* If it's not privately allocated and it's not time to free it, just + * decrement the count */ + if (pent->refcnt > 1) + pent->refcnt--; + else + { + /* If the color type is shared, find the sharedcolor. If decremented + * refcnt is 0, free the shared cell. */ + if (pent->fShared) + { + if(--pent->co.shco.red->refcnt == 0) + free(pent->co.shco.red); + if(--pent->co.shco.green->refcnt == 0) + free(pent->co.shco.green); + if(--pent->co.shco.blue->refcnt == 0) + free(pent->co.shco.blue); + pent->fShared = FALSE; + } + pent->refcnt = 0; + *pCount += 1; + } +} + +static void +UpdateColors (ColormapPtr pmap) +{ + xColorItem *defs; + xColorItem *pdef; + EntryPtr pent; + VisualPtr pVisual; + int i, n, size; + + pVisual = pmap->pVisual; + size = pVisual->ColormapEntries; + defs = malloc(size * sizeof(xColorItem)); + if (!defs) + return; + n = 0; + pdef = defs; + if (pmap->class == DirectColor) + { + for (i = 0; i < size; i++) + { + if (!pmap->red[i].refcnt && + !pmap->green[i].refcnt && + !pmap->blue[i].refcnt) + continue; + pdef->pixel = ((Pixel)i << pVisual->offsetRed) | + ((Pixel)i << pVisual->offsetGreen) | + ((Pixel)i << pVisual->offsetBlue); + pdef->red = pmap->red[i].co.local.red; + pdef->green = pmap->green[i].co.local.green; + pdef->blue = pmap->blue[i].co.local.blue; + pdef->flags = DoRed|DoGreen|DoBlue; + pdef++; + n++; + } + } + else + { + for (i = 0, pent = pmap->red; i < size; i++, pent++) + { + if (!pent->refcnt) + continue; + pdef->pixel = i; + if(pent->fShared) + { + pdef->red = pent->co.shco.red->color; + pdef->green = pent->co.shco.green->color; + pdef->blue = pent->co.shco.blue->color; + } + else + { + pdef->red = pent->co.local.red; + pdef->green = pent->co.local.green; + pdef->blue = pent->co.local.blue; + } + pdef->flags = DoRed|DoGreen|DoBlue; + pdef++; + n++; + } + } + if (n) + (*pmap->pScreen->StoreColors)(pmap, n, defs); + free(defs); +} + +/* Get a read-only color from a ColorMap (probably slow for large maps) + * Returns by changing the value in pred, pgreen, pblue and pPix + */ +int +AllocColor (ColormapPtr pmap, + unsigned short *pred, unsigned short *pgreen, unsigned short *pblue, + Pixel *pPix, int client) +{ + Pixel pixR, pixG, pixB; + int entries; + xrgb rgb; + int class; + VisualPtr pVisual; + int npix; + Pixel *ppix; + + pVisual = pmap->pVisual; + (*pmap->pScreen->ResolveColor) (pred, pgreen, pblue, pVisual); + rgb.red = *pred; + rgb.green = *pgreen; + rgb.blue = *pblue; + class = pmap->class; + entries = pVisual->ColormapEntries; + + /* If the colormap is being created, then we want to be able to change + * the colormap, even if it's a static type. Otherwise, we'd never be + * able to initialize static colormaps + */ + if(pmap->flags & BeingCreated) + class |= DynamicClass; + + /* If this is one of the static storage classes, and we're not initializing + * it, the best we can do is to find the closest color entry to the + * requested one and return that. + */ + switch (class) { + case StaticColor: + case StaticGray: + /* Look up all three components in the same pmap */ + *pPix = pixR = FindBestPixel(pmap->red, entries, &rgb, PSEUDOMAP); + *pred = pmap->red[pixR].co.local.red; + *pgreen = pmap->red[pixR].co.local.green; + *pblue = pmap->red[pixR].co.local.blue; + npix = pmap->numPixelsRed[client]; + ppix = (Pixel *) realloc(pmap->clientPixelsRed[client], + (npix + 1) * sizeof(Pixel)); + if (!ppix) + return (BadAlloc); + ppix[npix] = pixR; + pmap->clientPixelsRed[client] = ppix; + pmap->numPixelsRed[client]++; + break; + + case TrueColor: + /* Look up each component in its own map, then OR them together */ + pixR = FindBestPixel(pmap->red, NUMRED(pVisual), &rgb, REDMAP); + pixG = FindBestPixel(pmap->green, NUMGREEN(pVisual), &rgb, GREENMAP); + pixB = FindBestPixel(pmap->blue, NUMBLUE(pVisual), &rgb, BLUEMAP); + *pPix = (pixR << pVisual->offsetRed) | + (pixG << pVisual->offsetGreen) | + (pixB << pVisual->offsetBlue) | + ALPHAMASK(pVisual); + + *pred = pmap->red[pixR].co.local.red; + *pgreen = pmap->green[pixG].co.local.green; + *pblue = pmap->blue[pixB].co.local.blue; + npix = pmap->numPixelsRed[client]; + ppix = (Pixel *) realloc(pmap->clientPixelsRed[client], + (npix + 1) * sizeof(Pixel)); + if (!ppix) + return (BadAlloc); + ppix[npix] = pixR; + pmap->clientPixelsRed[client] = ppix; + npix = pmap->numPixelsGreen[client]; + ppix = (Pixel *) realloc(pmap->clientPixelsGreen[client], + (npix + 1) * sizeof(Pixel)); + if (!ppix) + return (BadAlloc); + ppix[npix] = pixG; + pmap->clientPixelsGreen[client] = ppix; + npix = pmap->numPixelsBlue[client]; + ppix = (Pixel *) realloc(pmap->clientPixelsBlue[client], + (npix + 1) * sizeof(Pixel)); + if (!ppix) + return (BadAlloc); + ppix[npix] = pixB; + pmap->clientPixelsBlue[client] = ppix; + pmap->numPixelsRed[client]++; + pmap->numPixelsGreen[client]++; + pmap->numPixelsBlue[client]++; + break; + + case GrayScale: + case PseudoColor: + if (pmap->mid != pmap->pScreen->defColormap && + pmap->pVisual->vid == pmap->pScreen->rootVisual) + { + ColormapPtr prootmap; + dixLookupResourceByType((pointer *)&prootmap, pmap->pScreen->defColormap, + RT_COLORMAP, clients[client], DixReadAccess); + + if (pmap->class == prootmap->class) + FindColorInRootCmap (prootmap, prootmap->red, entries, &rgb, + pPix, PSEUDOMAP, AllComp); + } + if (FindColor(pmap, pmap->red, entries, &rgb, pPix, PSEUDOMAP, + client, AllComp) != Success) + return (BadAlloc); + break; + + case DirectColor: + if (pmap->mid != pmap->pScreen->defColormap && + pmap->pVisual->vid == pmap->pScreen->rootVisual) + { + ColormapPtr prootmap; + dixLookupResourceByType((pointer *)&prootmap, pmap->pScreen->defColormap, + RT_COLORMAP, clients[client], DixReadAccess); + + if (pmap->class == prootmap->class) + { + pixR = (*pPix & pVisual->redMask) >> pVisual->offsetRed; + FindColorInRootCmap (prootmap, prootmap->red, entries, &rgb, + &pixR, REDMAP, RedComp); + pixG = (*pPix & pVisual->greenMask) >> pVisual->offsetGreen; + FindColorInRootCmap (prootmap, prootmap->green, entries, &rgb, + &pixG, GREENMAP, GreenComp); + pixB = (*pPix & pVisual->blueMask) >> pVisual->offsetBlue; + FindColorInRootCmap (prootmap, prootmap->blue, entries, &rgb, + &pixB, BLUEMAP, BlueComp); + *pPix = pixR | pixG | pixB; + } + } + + pixR = (*pPix & pVisual->redMask) >> pVisual->offsetRed; + if (FindColor(pmap, pmap->red, NUMRED(pVisual), &rgb, &pixR, REDMAP, + client, RedComp) != Success) + return (BadAlloc); + pixG = (*pPix & pVisual->greenMask) >> pVisual->offsetGreen; + if (FindColor(pmap, pmap->green, NUMGREEN(pVisual), &rgb, &pixG, + GREENMAP, client, GreenComp) != Success) + { + (void)FreeCo(pmap, client, REDMAP, 1, &pixR, (Pixel)0); + return (BadAlloc); + } + pixB = (*pPix & pVisual->blueMask) >> pVisual->offsetBlue; + if (FindColor(pmap, pmap->blue, NUMBLUE(pVisual), &rgb, &pixB, BLUEMAP, + client, BlueComp) != Success) + { + (void)FreeCo(pmap, client, GREENMAP, 1, &pixG, (Pixel)0); + (void)FreeCo(pmap, client, REDMAP, 1, &pixR, (Pixel)0); + return (BadAlloc); + } + *pPix = pixR | pixG | pixB | ALPHAMASK(pVisual); + + break; + } + + /* if this is the client's first pixel in this colormap, tell the + * resource manager that the client has pixels in this colormap which + * should be freed when the client dies */ + if ((pmap->numPixelsRed[client] == 1) && + (CLIENT_ID(pmap->mid) != client) && + !(pmap->flags & BeingCreated)) + { + colorResource *pcr; + + pcr = malloc(sizeof(colorResource)); + if (!pcr) + { + (void)FreeColors(pmap, client, 1, pPix, (Pixel)0); + return (BadAlloc); + } + pcr->mid = pmap->mid; + pcr->client = client; + if (!AddResource(FakeClientID(client), RT_CMAPENTRY, (pointer)pcr)) + return (BadAlloc); + } + return (Success); +} + +/* + * FakeAllocColor -- fake an AllocColor request by + * returning a free pixel if availible, otherwise returning + * the closest matching pixel. This is used by the mi + * software sprite code to recolor cursors. A nice side-effect + * is that this routine will never return failure. + */ + +void +FakeAllocColor (ColormapPtr pmap, xColorItem *item) +{ + Pixel pixR, pixG, pixB; + Pixel temp; + int entries; + xrgb rgb; + int class; + VisualPtr pVisual; + + pVisual = pmap->pVisual; + rgb.red = item->red; + rgb.green = item->green; + rgb.blue = item->blue; + (*pmap->pScreen->ResolveColor) (&rgb.red, &rgb.green, &rgb.blue, pVisual); + class = pmap->class; + entries = pVisual->ColormapEntries; + + switch (class) { + case GrayScale: + case PseudoColor: + temp = 0; + item->pixel = 0; + if (FindColor(pmap, pmap->red, entries, &rgb, &temp, PSEUDOMAP, + -1, AllComp) == Success) { + item->pixel = temp; + break; + } + /* fall through ... */ + case StaticColor: + case StaticGray: + item->pixel = FindBestPixel(pmap->red, entries, &rgb, PSEUDOMAP); + break; + + case DirectColor: + /* Look up each component in its own map, then OR them together */ + pixR = (item->pixel & pVisual->redMask) >> pVisual->offsetRed; + pixG = (item->pixel & pVisual->greenMask) >> pVisual->offsetGreen; + pixB = (item->pixel & pVisual->blueMask) >> pVisual->offsetBlue; + if (FindColor(pmap, pmap->red, NUMRED(pVisual), &rgb, &pixR, REDMAP, + -1, RedComp) != Success) + pixR = FindBestPixel(pmap->red, NUMRED(pVisual), &rgb, REDMAP) + << pVisual->offsetRed; + if (FindColor(pmap, pmap->green, NUMGREEN(pVisual), &rgb, &pixG, + GREENMAP, -1, GreenComp) != Success) + pixG = FindBestPixel(pmap->green, NUMGREEN(pVisual), &rgb, + GREENMAP) << pVisual->offsetGreen; + if (FindColor(pmap, pmap->blue, NUMBLUE(pVisual), &rgb, &pixB, BLUEMAP, + -1, BlueComp) != Success) + pixB = FindBestPixel(pmap->blue, NUMBLUE(pVisual), &rgb, BLUEMAP) + << pVisual->offsetBlue; + item->pixel = pixR | pixG | pixB; + break; + + case TrueColor: + /* Look up each component in its own map, then OR them together */ + pixR = FindBestPixel(pmap->red, NUMRED(pVisual), &rgb, REDMAP); + pixG = FindBestPixel(pmap->green, NUMGREEN(pVisual), &rgb, GREENMAP); + pixB = FindBestPixel(pmap->blue, NUMBLUE(pVisual), &rgb, BLUEMAP); + item->pixel = (pixR << pVisual->offsetRed) | + (pixG << pVisual->offsetGreen) | + (pixB << pVisual->offsetBlue); + break; + } +} + +/* free a pixel value obtained from FakeAllocColor */ +void +FakeFreeColor(ColormapPtr pmap, Pixel pixel) +{ + VisualPtr pVisual; + Pixel pixR, pixG, pixB; + + switch (pmap->class) { + case GrayScale: + case PseudoColor: + if (pmap->red[pixel].refcnt == AllocTemporary) + pmap->red[pixel].refcnt = 0; + break; + case DirectColor: + pVisual = pmap->pVisual; + pixR = (pixel & pVisual->redMask) >> pVisual->offsetRed; + pixG = (pixel & pVisual->greenMask) >> pVisual->offsetGreen; + pixB = (pixel & pVisual->blueMask) >> pVisual->offsetBlue; + if (pmap->red[pixR].refcnt == AllocTemporary) + pmap->red[pixR].refcnt = 0; + if (pmap->green[pixG].refcnt == AllocTemporary) + pmap->green[pixG].refcnt = 0; + if (pmap->blue[pixB].refcnt == AllocTemporary) + pmap->blue[pixB].refcnt = 0; + break; + } +} + +typedef unsigned short BigNumUpper; +typedef unsigned long BigNumLower; + +#define BIGNUMLOWERBITS 24 +#define BIGNUMUPPERBITS 16 +#define BIGNUMLOWER (1 << BIGNUMLOWERBITS) +#define BIGNUMUPPER (1 << BIGNUMUPPERBITS) +#define UPPERPART(i) ((i) >> BIGNUMLOWERBITS) +#define LOWERPART(i) ((i) & (BIGNUMLOWER - 1)) + +typedef struct _bignum { + BigNumUpper upper; + BigNumLower lower; +} BigNumRec, *BigNumPtr; + +#define BigNumGreater(x,y) (((x)->upper > (y)->upper) ||\ + ((x)->upper == (y)->upper && (x)->lower > (y)->lower)) + +#define UnsignedToBigNum(u,r) (((r)->upper = UPPERPART(u)), \ + ((r)->lower = LOWERPART(u))) + +#define MaxBigNum(r) (((r)->upper = BIGNUMUPPER-1), \ + ((r)->lower = BIGNUMLOWER-1)) + +static void +BigNumAdd (BigNumPtr x, BigNumPtr y, BigNumPtr r) +{ + BigNumLower lower, carry = 0; + + lower = x->lower + y->lower; + if (lower >= BIGNUMLOWER) { + lower -= BIGNUMLOWER; + carry = 1; + } + r->lower = lower; + r->upper = x->upper + y->upper + carry; +} + +static Pixel +FindBestPixel(EntryPtr pentFirst, int size, xrgb *prgb, int channel) +{ + EntryPtr pent; + Pixel pixel, final; + long dr, dg, db; + unsigned long sq; + BigNumRec minval, sum, temp; + + final = 0; + MaxBigNum(&minval); + /* look for the minimal difference */ + for (pent = pentFirst, pixel = 0; pixel < size; pent++, pixel++) + { + dr = dg = db = 0; + switch(channel) + { + case PSEUDOMAP: + dg = (long) pent->co.local.green - prgb->green; + db = (long) pent->co.local.blue - prgb->blue; + case REDMAP: + dr = (long) pent->co.local.red - prgb->red; + break; + case GREENMAP: + dg = (long) pent->co.local.green - prgb->green; + break; + case BLUEMAP: + db = (long) pent->co.local.blue - prgb->blue; + break; + } + sq = dr * dr; + UnsignedToBigNum (sq, &sum); + sq = dg * dg; + UnsignedToBigNum (sq, &temp); + BigNumAdd (&sum, &temp, &sum); + sq = db * db; + UnsignedToBigNum (sq, &temp); + BigNumAdd (&sum, &temp, &sum); + if (BigNumGreater (&minval, &sum)) + { + final = pixel; + minval = sum; + } + } + return(final); +} + +static void +FindColorInRootCmap (ColormapPtr pmap, EntryPtr pentFirst, int size, + xrgb *prgb, Pixel *pPixel, int channel, + ColorCompareProcPtr comp) +{ + EntryPtr pent; + Pixel pixel; + int count; + + if ((pixel = *pPixel) >= size) + pixel = 0; + for (pent = pentFirst + pixel, count = size; --count >= 0; pent++, pixel++) + { + if (pent->refcnt > 0 && (*comp) (pent, prgb)) + { + switch (channel) + { + case REDMAP: + pixel <<= pmap->pVisual->offsetRed; + break; + case GREENMAP: + pixel <<= pmap->pVisual->offsetGreen; + break; + case BLUEMAP: + pixel <<= pmap->pVisual->offsetBlue; + break; + default: /* PSEUDOMAP */ + break; + } + *pPixel = pixel; + } + } +} + +/* Tries to find a color in pmap that exactly matches the one requested in prgb + * if it can't it allocates one. + * Starts looking at pentFirst + *pPixel, so if you want a specific pixel, + * load *pPixel with that value, otherwise set it to 0 + */ +int +FindColor (ColormapPtr pmap, EntryPtr pentFirst, int size, xrgb *prgb, + Pixel *pPixel, int channel, int client, + ColorCompareProcPtr comp) +{ + EntryPtr pent; + Bool foundFree; + Pixel pixel, Free = 0; + int npix, count, *nump = NULL; + Pixel **pixp = NULL, *ppix; + xColorItem def; + + foundFree = FALSE; + + if((pixel = *pPixel) >= size) + pixel = 0; + /* see if there is a match, and also look for a free entry */ + for (pent = pentFirst + pixel, count = size; --count >= 0; ) + { + if (pent->refcnt > 0) + { + if ((*comp) (pent, prgb)) + { + if (client >= 0) + pent->refcnt++; + *pPixel = pixel; + switch(channel) + { + case REDMAP: + *pPixel <<= pmap->pVisual->offsetRed; + case PSEUDOMAP: + break; + case GREENMAP: + *pPixel <<= pmap->pVisual->offsetGreen; + break; + case BLUEMAP: + *pPixel <<= pmap->pVisual->offsetBlue; + break; + } + goto gotit; + } + } + else if (!foundFree && pent->refcnt == 0) + { + Free = pixel; + foundFree = TRUE; + /* If we're initializing the colormap, then we are looking for + * the first free cell we can find, not to minimize the number + * of entries we use. So don't look any further. */ + if(pmap->flags & BeingCreated) + break; + } + pixel++; + if(pixel >= size) + { + pent = pentFirst; + pixel = 0; + } + else + pent++; + } + + /* If we got here, we didn't find a match. If we also didn't find + * a free entry, we're out of luck. Otherwise, we'll usurp a free + * entry and fill it in */ + if (!foundFree) + return (BadAlloc); + pent = pentFirst + Free; + pent->fShared = FALSE; + pent->refcnt = (client >= 0) ? 1 : AllocTemporary; + + switch (channel) + { + case PSEUDOMAP: + pent->co.local.red = prgb->red; + pent->co.local.green = prgb->green; + pent->co.local.blue = prgb->blue; + def.red = prgb->red; + def.green = prgb->green; + def.blue = prgb->blue; + def.flags = (DoRed|DoGreen|DoBlue); + if (client >= 0) + pmap->freeRed--; + def.pixel = Free; + break; + + case REDMAP: + pent->co.local.red = prgb->red; + def.red = prgb->red; + def.green = pmap->green[0].co.local.green; + def.blue = pmap->blue[0].co.local.blue; + def.flags = DoRed; + if (client >= 0) + pmap->freeRed--; + def.pixel = Free << pmap->pVisual->offsetRed; + break; + + case GREENMAP: + pent->co.local.green = prgb->green; + def.red = pmap->red[0].co.local.red; + def.green = prgb->green; + def.blue = pmap->blue[0].co.local.blue; + def.flags = DoGreen; + if (client >= 0) + pmap->freeGreen--; + def.pixel = Free << pmap->pVisual->offsetGreen; + break; + + case BLUEMAP: + pent->co.local.blue = prgb->blue; + def.red = pmap->red[0].co.local.red; + def.green = pmap->green[0].co.local.green; + def.blue = prgb->blue; + def.flags = DoBlue; + if (client >= 0) + pmap->freeBlue--; + def.pixel = Free << pmap->pVisual->offsetBlue; + break; + } + (*pmap->pScreen->StoreColors) (pmap, 1, &def); + pixel = Free; + *pPixel = def.pixel; + +gotit: + if (pmap->flags & BeingCreated || client == -1) + return(Success); + /* Now remember the pixel, for freeing later */ + switch (channel) + { + case PSEUDOMAP: + case REDMAP: + nump = pmap->numPixelsRed; + pixp = pmap->clientPixelsRed; + break; + + case GREENMAP: + nump = pmap->numPixelsGreen; + pixp = pmap->clientPixelsGreen; + break; + + case BLUEMAP: + nump = pmap->numPixelsBlue; + pixp = pmap->clientPixelsBlue; + break; + } + npix = nump[client]; + ppix = (Pixel *) realloc(pixp[client], (npix + 1) * sizeof(Pixel)); + if (!ppix) + { + pent->refcnt--; + if (!pent->fShared) + switch (channel) + { + case PSEUDOMAP: + case REDMAP: + pmap->freeRed++; + break; + case GREENMAP: + pmap->freeGreen++; + break; + case BLUEMAP: + pmap->freeBlue++; + break; + } + return(BadAlloc); + } + ppix[npix] = pixel; + pixp[client] = ppix; + nump[client]++; + + return(Success); +} + +/* Comparison functions -- passed to FindColor to determine if an + * entry is already the color we're looking for or not */ +static int +AllComp (EntryPtr pent, xrgb *prgb) +{ + if((pent->co.local.red == prgb->red) && + (pent->co.local.green == prgb->green) && + (pent->co.local.blue == prgb->blue) ) + return (1); + return (0); +} + +static int +RedComp (EntryPtr pent, xrgb *prgb) +{ + if (pent->co.local.red == prgb->red) + return (1); + return (0); +} + +static int +GreenComp (EntryPtr pent, xrgb *prgb) +{ + if (pent->co.local.green == prgb->green) + return (1); + return (0); +} + +static int +BlueComp (EntryPtr pent, xrgb *prgb) +{ + if (pent->co.local.blue == prgb->blue) + return (1); + return (0); +} + + +/* Read the color value of a cell */ + +int +QueryColors (ColormapPtr pmap, int count, Pixel *ppixIn, xrgb *prgbList, ClientPtr client) +{ + Pixel *ppix, pixel; + xrgb *prgb; + VisualPtr pVisual; + EntryPtr pent; + Pixel i; + int errVal = Success; + + pVisual = pmap->pVisual; + if ((pmap->class | DynamicClass) == DirectColor) + { + int numred, numgreen, numblue; + Pixel rgbbad; + + numred = NUMRED(pVisual); + numgreen = NUMGREEN(pVisual); + numblue = NUMBLUE(pVisual); + rgbbad = ~RGBMASK(pVisual); + for( ppix = ppixIn, prgb = prgbList; --count >= 0; ppix++, prgb++) + { + pixel = *ppix; + if (pixel & rgbbad) { + client->errorValue = pixel; + errVal = BadValue; + continue; + } + i = (pixel & pVisual->redMask) >> pVisual->offsetRed; + if (i >= numred) + { + client->errorValue = pixel; + errVal = BadValue; + continue; + } + prgb->red = pmap->red[i].co.local.red; + i = (pixel & pVisual->greenMask) >> pVisual->offsetGreen; + if (i >= numgreen) + { + client->errorValue = pixel; + errVal = BadValue; + continue; + } + prgb->green = pmap->green[i].co.local.green; + i = (pixel & pVisual->blueMask) >> pVisual->offsetBlue; + if (i >= numblue) + { + client->errorValue = pixel; + errVal = BadValue; + continue; + } + prgb->blue = pmap->blue[i].co.local.blue; + } + } + else + { + for( ppix = ppixIn, prgb = prgbList; --count >= 0; ppix++, prgb++) + { + pixel = *ppix; + if (pixel >= pVisual->ColormapEntries) + { + client->errorValue = pixel; + errVal = BadValue; + } + else + { + pent = (EntryPtr)&pmap->red[pixel]; + if (pent->fShared) + { + prgb->red = pent->co.shco.red->color; + prgb->green = pent->co.shco.green->color; + prgb->blue = pent->co.shco.blue->color; + } + else + { + prgb->red = pent->co.local.red; + prgb->green = pent->co.local.green; + prgb->blue = pent->co.local.blue; + } + } + } + } + return (errVal); +} + +static void +FreePixels(ColormapPtr pmap, int client) +{ + Pixel *ppix, *ppixStart; + int n; + int class; + + class = pmap->class; + ppixStart = pmap->clientPixelsRed[client]; + if (class & DynamicClass) + { + n = pmap->numPixelsRed[client]; + for (ppix = ppixStart; --n >= 0; ) + { + FreeCell(pmap, *ppix, REDMAP); + ppix++; + } + } + + free(ppixStart); + pmap->clientPixelsRed[client] = (Pixel *) NULL; + pmap->numPixelsRed[client] = 0; + if ((class | DynamicClass) == DirectColor) + { + ppixStart = pmap->clientPixelsGreen[client]; + if (class & DynamicClass) + for (ppix = ppixStart, n = pmap->numPixelsGreen[client]; --n >= 0;) + FreeCell(pmap, *ppix++, GREENMAP); + free(ppixStart); + pmap->clientPixelsGreen[client] = (Pixel *) NULL; + pmap->numPixelsGreen[client] = 0; + + ppixStart = pmap->clientPixelsBlue[client]; + if (class & DynamicClass) + for (ppix = ppixStart, n = pmap->numPixelsBlue[client]; --n >= 0; ) + FreeCell(pmap, *ppix++, BLUEMAP); + free(ppixStart); + pmap->clientPixelsBlue[client] = (Pixel *) NULL; + pmap->numPixelsBlue[client] = 0; + } +} + +/** + * Frees all of a client's colors and cells. + * + * \param value must conform to DeleteType + * \unused fakeid + */ +int +FreeClientPixels (pointer value, XID fakeid) +{ + pointer pmap; + colorResource *pcr = value; + int rc; + + rc = dixLookupResourceByType(&pmap, pcr->mid, RT_COLORMAP, serverClient, + DixRemoveAccess); + if (rc == Success) + FreePixels((ColormapPtr)pmap, pcr->client); + free(pcr); + return Success; +} + +int +AllocColorCells (int client, ColormapPtr pmap, int colors, int planes, + Bool contig, Pixel *ppix, Pixel *masks) +{ + Pixel rmask, gmask, bmask, *ppixFirst, r, g, b; + int n, class; + int ok; + int oldcount; + colorResource *pcr = (colorResource *)NULL; + + class = pmap->class; + if (!(class & DynamicClass)) + return (BadAlloc); /* Shouldn't try on this type */ + oldcount = pmap->numPixelsRed[client]; + if (pmap->class == DirectColor) + oldcount += pmap->numPixelsGreen[client] + pmap->numPixelsBlue[client]; + if (!oldcount && (CLIENT_ID(pmap->mid) != client)) + { + pcr = malloc(sizeof(colorResource)); + if (!pcr) + return (BadAlloc); + } + + if (pmap->class == DirectColor) + { + ok = AllocDirect (client, pmap, colors, planes, planes, planes, + contig, ppix, &rmask, &gmask, &bmask); + if(ok == Success) + { + for (r = g = b = 1, n = planes; --n >= 0; r += r, g += g, b += b) + { + while(!(rmask & r)) + r += r; + while(!(gmask & g)) + g += g; + while(!(bmask & b)) + b += b; + *masks++ = r | g | b; + } + } + } + else + { + ok = AllocPseudo (client, pmap, colors, planes, contig, ppix, &rmask, + &ppixFirst); + if(ok == Success) + { + for (r = 1, n = planes; --n >= 0; r += r) + { + while(!(rmask & r)) + r += r; + *masks++ = r; + } + } + } + + /* if this is the client's first pixels in this colormap, tell the + * resource manager that the client has pixels in this colormap which + * should be freed when the client dies */ + if ((ok == Success) && pcr) + { + pcr->mid = pmap->mid; + pcr->client = client; + if (!AddResource(FakeClientID(client), RT_CMAPENTRY, (pointer)pcr)) + ok = BadAlloc; + } else if (pcr) + free(pcr); + + return (ok); +} + + +int +AllocColorPlanes (int client, ColormapPtr pmap, int colors, + int r, int g, int b, Bool contig, Pixel *pixels, + Pixel *prmask, Pixel *pgmask, Pixel *pbmask) +{ + int ok; + Pixel mask, *ppixFirst; + Pixel shift; + int i; + int class; + int oldcount; + colorResource *pcr = (colorResource *)NULL; + + class = pmap->class; + if (!(class & DynamicClass)) + return (BadAlloc); /* Shouldn't try on this type */ + oldcount = pmap->numPixelsRed[client]; + if (class == DirectColor) + oldcount += pmap->numPixelsGreen[client] + pmap->numPixelsBlue[client]; + if (!oldcount && (CLIENT_ID(pmap->mid) != client)) + { + pcr = malloc(sizeof(colorResource)); + if (!pcr) + return (BadAlloc); + } + + if (class == DirectColor) + { + ok = AllocDirect (client, pmap, colors, r, g, b, contig, pixels, + prmask, pgmask, pbmask); + } + else + { + /* Allocate the proper pixels */ + /* XXX This is sort of bad, because of contig is set, we force all + * r + g + b bits to be contiguous. Should only force contiguity + * per mask + */ + ok = AllocPseudo (client, pmap, colors, r + g + b, contig, pixels, + &mask, &ppixFirst); + + if(ok == Success) + { + /* now split that mask into three */ + *prmask = *pgmask = *pbmask = 0; + shift = 1; + for (i = r; --i >= 0; shift += shift) + { + while (!(mask & shift)) + shift += shift; + *prmask |= shift; + } + for (i = g; --i >= 0; shift += shift) + { + while (!(mask & shift)) + shift += shift; + *pgmask |= shift; + } + for (i = b; --i >= 0; shift += shift) + { + while (!(mask & shift)) + shift += shift; + *pbmask |= shift; + } + + /* set up the shared color cells */ + if (!AllocShared(pmap, pixels, colors, r, g, b, + *prmask, *pgmask, *pbmask, ppixFirst)) + { + (void)FreeColors(pmap, client, colors, pixels, mask); + ok = BadAlloc; + } + } + } + + /* if this is the client's first pixels in this colormap, tell the + * resource manager that the client has pixels in this colormap which + * should be freed when the client dies */ + if ((ok == Success) && pcr) + { + pcr->mid = pmap->mid; + pcr->client = client; + if (!AddResource(FakeClientID(client), RT_CMAPENTRY, (pointer)pcr)) + ok = BadAlloc; + } else if (pcr) + free(pcr); + + return (ok); +} + +static int +AllocDirect (int client, ColormapPtr pmap, int c, int r, int g, int b, Bool contig, + Pixel *pixels, Pixel *prmask, Pixel *pgmask, Pixel *pbmask) +{ + Pixel *ppixRed, *ppixGreen, *ppixBlue; + Pixel *ppix, *pDst, *p; + int npix, npixR, npixG, npixB; + Bool okR, okG, okB; + Pixel *rpix = 0, *gpix = 0, *bpix = 0; + + npixR = c << r; + npixG = c << g; + npixB = c << b; + if ((r >= 32) || (g >= 32) || (b >= 32) || + (npixR > pmap->freeRed) || (npixR < c) || + (npixG > pmap->freeGreen) || (npixG < c) || + (npixB > pmap->freeBlue) || (npixB < c)) + return BadAlloc; + + /* start out with empty pixels */ + for(p = pixels; p < pixels + c; p++) + *p = 0; + + ppixRed = malloc(npixR * sizeof(Pixel)); + ppixGreen = malloc(npixG * sizeof(Pixel)); + ppixBlue = malloc(npixB * sizeof(Pixel)); + if (!ppixRed || !ppixGreen || !ppixBlue) + { + if (ppixBlue) free(ppixBlue); + if (ppixGreen) free(ppixGreen); + if (ppixRed) free(ppixRed); + return(BadAlloc); + } + + okR = AllocCP(pmap, pmap->red, c, r, contig, ppixRed, prmask); + okG = AllocCP(pmap, pmap->green, c, g, contig, ppixGreen, pgmask); + okB = AllocCP(pmap, pmap->blue, c, b, contig, ppixBlue, pbmask); + + if (okR && okG && okB) + { + rpix = (Pixel *) realloc(pmap->clientPixelsRed[client], + (pmap->numPixelsRed[client] + (c << r)) * + sizeof(Pixel)); + if (rpix) + pmap->clientPixelsRed[client] = rpix; + gpix = (Pixel *) realloc(pmap->clientPixelsGreen[client], + (pmap->numPixelsGreen[client] + (c << g)) * + sizeof(Pixel)); + if (gpix) + pmap->clientPixelsGreen[client] = gpix; + bpix = (Pixel *) realloc(pmap->clientPixelsBlue[client], + (pmap->numPixelsBlue[client] + (c << b)) * + sizeof(Pixel)); + if (bpix) + pmap->clientPixelsBlue[client] = bpix; + } + + if (!okR || !okG || !okB || !rpix || !gpix || !bpix) + { + if (okR) + for(ppix = ppixRed, npix = npixR; --npix >= 0; ppix++) + pmap->red[*ppix].refcnt = 0; + if (okG) + for(ppix = ppixGreen, npix = npixG; --npix >= 0; ppix++) + pmap->green[*ppix].refcnt = 0; + if (okB) + for(ppix = ppixBlue, npix = npixB; --npix >= 0; ppix++) + pmap->blue[*ppix].refcnt = 0; + free(ppixBlue); + free(ppixGreen); + free(ppixRed); + return(BadAlloc); + } + + *prmask <<= pmap->pVisual->offsetRed; + *pgmask <<= pmap->pVisual->offsetGreen; + *pbmask <<= pmap->pVisual->offsetBlue; + + ppix = rpix + pmap->numPixelsRed[client]; + for (pDst = pixels, p = ppixRed; p < ppixRed + npixR; p++) + { + *ppix++ = *p; + if(p < ppixRed + c) + *pDst++ |= *p << pmap->pVisual->offsetRed; + } + pmap->numPixelsRed[client] += npixR; + pmap->freeRed -= npixR; + + ppix = gpix + pmap->numPixelsGreen[client]; + for (pDst = pixels, p = ppixGreen; p < ppixGreen + npixG; p++) + { + *ppix++ = *p; + if(p < ppixGreen + c) + *pDst++ |= *p << pmap->pVisual->offsetGreen; + } + pmap->numPixelsGreen[client] += npixG; + pmap->freeGreen -= npixG; + + ppix = bpix + pmap->numPixelsBlue[client]; + for (pDst = pixels, p = ppixBlue; p < ppixBlue + npixB; p++) + { + *ppix++ = *p; + if(p < ppixBlue + c) + *pDst++ |= *p << pmap->pVisual->offsetBlue; + } + pmap->numPixelsBlue[client] += npixB; + pmap->freeBlue -= npixB; + + + for (pDst = pixels; pDst < pixels + c; pDst++) + *pDst |= ALPHAMASK(pmap->pVisual); + + free(ppixBlue); + free(ppixGreen); + free(ppixRed); + + return (Success); +} + +static int +AllocPseudo (int client, ColormapPtr pmap, int c, int r, Bool contig, + Pixel *pixels, Pixel *pmask, Pixel **pppixFirst) +{ + Pixel *ppix, *p, *pDst, *ppixTemp; + int npix; + Bool ok; + + npix = c << r; + if ((r >= 32) || (npix > pmap->freeRed) || (npix < c)) + return(BadAlloc); + if(!(ppixTemp = malloc(npix * sizeof(Pixel)))) + return(BadAlloc); + ok = AllocCP(pmap, pmap->red, c, r, contig, ppixTemp, pmask); + + if (ok) + { + + /* all the allocated pixels are added to the client pixel list, + * but only the unique ones are returned to the client */ + ppix = (Pixel *)realloc(pmap->clientPixelsRed[client], + (pmap->numPixelsRed[client] + npix) * sizeof(Pixel)); + if (!ppix) + { + for (p = ppixTemp; p < ppixTemp + npix; p++) + pmap->red[*p].refcnt = 0; + return (BadAlloc); + } + pmap->clientPixelsRed[client] = ppix; + ppix += pmap->numPixelsRed[client]; + *pppixFirst = ppix; + pDst = pixels; + for (p = ppixTemp; p < ppixTemp + npix; p++) + { + *ppix++ = *p; + if(p < ppixTemp + c) + *pDst++ = *p; + } + pmap->numPixelsRed[client] += npix; + pmap->freeRed -= npix; + } + free(ppixTemp); + return (ok ? Success : BadAlloc); +} + +/* Allocates count << planes pixels from colormap pmap for client. If + * contig, then the plane mask is made of consecutive bits. Returns + * all count << pixels in the array pixels. The first count of those + * pixels are the unique pixels. *pMask has the mask to Or with the + * unique pixels to get the rest of them. + * + * Returns True iff all pixels could be allocated + * All cells allocated will have refcnt set to AllocPrivate and shared to FALSE + * (see AllocShared for why we care) + */ +static Bool +AllocCP (ColormapPtr pmap, EntryPtr pentFirst, int count, int planes, + Bool contig, Pixel *pixels, Pixel *pMask) +{ + EntryPtr ent; + Pixel pixel, base, entries, maxp, save; + int dplanes, found; + Pixel *ppix; + Pixel mask; + Pixel finalmask; + + dplanes = pmap->pVisual->nplanes; + + /* Easy case. Allocate pixels only */ + if (planes == 0) + { + /* allocate writable entries */ + ppix = pixels; + ent = pentFirst; + pixel = 0; + while (--count >= 0) + { + /* Just find count unallocated cells */ + while (ent->refcnt) + { + ent++; + pixel++; + } + ent->refcnt = AllocPrivate; + *ppix++ = pixel; + ent->fShared = FALSE; + } + *pMask = 0; + return (TRUE); + } + else if (planes > dplanes) + { + return (FALSE); + } + + /* General case count pixels * 2 ^ planes cells to be allocated */ + + /* make room for new pixels */ + ent = pentFirst; + + /* first try for contiguous planes, since it's fastest */ + for (mask = (((Pixel)1) << planes) - 1, base = 1, dplanes -= (planes - 1); + --dplanes >= 0; + mask += mask, base += base) + { + ppix = pixels; + found = 0; + pixel = 0; + entries = pmap->pVisual->ColormapEntries - mask; + while (pixel < entries) + { + save = pixel; + maxp = pixel + mask + base; + /* check if all are free */ + while (pixel != maxp && ent[pixel].refcnt == 0) + pixel += base; + if (pixel == maxp) + { + /* this one works */ + *ppix++ = save; + found++; + if (found == count) + { + /* found enough, allocate them all */ + while (--count >= 0) + { + pixel = pixels[count]; + maxp = pixel + mask; + while (1) + { + ent[pixel].refcnt = AllocPrivate; + ent[pixel].fShared = FALSE; + if (pixel == maxp) + break; + pixel += base; + *ppix++ = pixel; + } + } + *pMask = mask; + return (TRUE); + } + } + pixel = save + 1; + if (pixel & mask) + pixel += mask; + } + } + + dplanes = pmap->pVisual->nplanes; + if (contig || planes == 1 || dplanes < 3) + return (FALSE); + + /* this will be very slow for large maps, need a better algorithm */ + + /* + we can generate the smallest and largest numbers that fits in dplanes + bits and contain exactly planes bits set as follows. First, we need to + check that it is possible to generate such a mask at all. + (Non-contiguous masks need one more bit than contiguous masks). Then + the smallest such mask consists of the rightmost planes-1 bits set, then + a zero, then a one in position planes + 1. The formula is + (3 << (planes-1)) -1 + The largest such masks consists of the leftmost planes-1 bits set, then + a zero, then a one bit in position dplanes-planes-1. If dplanes is + smaller than 32 (the number of bits in a word) then the formula is: + (1<>> + + */ + + finalmask = + (((((Pixel)1)<<(planes-1)) - 1) << (dplanes-planes+1)) + + (((Pixel)1)<<(dplanes-planes-1)); + for (mask = (((Pixel)3) << (planes -1)) - 1; mask <= finalmask; mask++) + { + /* next 3 magic statements count number of ones (HAKMEM #169) */ + pixel = (mask >> 1) & 033333333333; + pixel = mask - pixel - ((pixel >> 1) & 033333333333); + if ((((pixel + (pixel >> 3)) & 030707070707) % 077) != planes) + continue; + ppix = pixels; + found = 0; + entries = pmap->pVisual->ColormapEntries - mask; + base = lowbit (mask); + for (pixel = 0; pixel < entries; pixel++) + { + if (pixel & mask) + continue; + maxp = 0; + /* check if all are free */ + while (ent[pixel + maxp].refcnt == 0) + { + GetNextBitsOrBreak(maxp, mask, base); + } + if ((maxp < mask) || (ent[pixel + mask].refcnt != 0)) + continue; + /* this one works */ + *ppix++ = pixel; + found++; + if (found < count) + continue; + /* found enough, allocate them all */ + while (--count >= 0) + { + pixel = (pixels)[count]; + maxp = 0; + while (1) + { + ent[pixel + maxp].refcnt = AllocPrivate; + ent[pixel + maxp].fShared = FALSE; + GetNextBitsOrBreak(maxp, mask, base); + *ppix++ = pixel + maxp; + } + } + + *pMask = mask; + return (TRUE); + } + } + return (FALSE); +} + +/** + * + * \param ppixFirst First of the client's new pixels + */ +static Bool +AllocShared (ColormapPtr pmap, Pixel *ppix, int c, int r, int g, int b, + Pixel rmask, Pixel gmask, Pixel bmask, Pixel *ppixFirst) +{ + Pixel *pptr, *cptr; + int npix, z, npixClientNew, npixShared; + Pixel basemask, base, bits, common; + SHAREDCOLOR *pshared, **ppshared, **psharedList; + + npixClientNew = c << (r + g + b); + npixShared = (c << r) + (c << g) + (c << b); + psharedList = malloc(npixShared * sizeof(SHAREDCOLOR *)); + if (!psharedList) + return FALSE; + ppshared = psharedList; + for (z = npixShared; --z >= 0; ) + { + if (!(ppshared[z] = malloc(sizeof(SHAREDCOLOR)))) + { + for (z++ ; z < npixShared; z++) + free(ppshared[z]); + return FALSE; + } + } + for(pptr = ppix, npix = c; --npix >= 0; pptr++) + { + basemask = ~(gmask | bmask); + common = *pptr & basemask; + if (rmask) + { + bits = 0; + base = lowbit (rmask); + while(1) + { + pshared = *ppshared++; + pshared->refcnt = 1 << (g + b); + for (cptr = ppixFirst, z = npixClientNew; --z >= 0; cptr++) + { + if ((*cptr & basemask) == (common | bits)) + { + pmap->red[*cptr].fShared = TRUE; + pmap->red[*cptr].co.shco.red = pshared; + } + } + GetNextBitsOrBreak(bits, rmask, base); + } + } + else + { + pshared = *ppshared++; + pshared->refcnt = 1 << (g + b); + for (cptr = ppixFirst, z = npixClientNew; --z >= 0; cptr++) + { + if ((*cptr & basemask) == common) + { + pmap->red[*cptr].fShared = TRUE; + pmap->red[*cptr].co.shco.red = pshared; + } + } + } + basemask = ~(rmask | bmask); + common = *pptr & basemask; + if (gmask) + { + bits = 0; + base = lowbit (gmask); + while(1) + { + pshared = *ppshared++; + pshared->refcnt = 1 << (r + b); + for (cptr = ppixFirst, z = npixClientNew; --z >= 0; cptr++) + { + if ((*cptr & basemask) == (common | bits)) + { + pmap->red[*cptr].co.shco.green = pshared; + } + } + GetNextBitsOrBreak(bits, gmask, base); + } + } + else + { + pshared = *ppshared++; + pshared->refcnt = 1 << (g + b); + for (cptr = ppixFirst, z = npixClientNew; --z >= 0; cptr++) + { + if ((*cptr & basemask) == common) + { + pmap->red[*cptr].co.shco.green = pshared; + } + } + } + basemask = ~(rmask | gmask); + common = *pptr & basemask; + if (bmask) + { + bits = 0; + base = lowbit (bmask); + while(1) + { + pshared = *ppshared++; + pshared->refcnt = 1 << (r + g); + for (cptr = ppixFirst, z = npixClientNew; --z >= 0; cptr++) + { + if ((*cptr & basemask) == (common | bits)) + { + pmap->red[*cptr].co.shco.blue = pshared; + } + } + GetNextBitsOrBreak(bits, bmask, base); + } + } + else + { + pshared = *ppshared++; + pshared->refcnt = 1 << (g + b); + for (cptr = ppixFirst, z = npixClientNew; --z >= 0; cptr++) + { + if ((*cptr & basemask) == common) + { + pmap->red[*cptr].co.shco.blue = pshared; + } + } + } + } + free(psharedList); + return TRUE; +} + + +/** FreeColors + * Free colors and/or cells (probably slow for large numbers) + */ +int +FreeColors (ColormapPtr pmap, int client, int count, Pixel *pixels, Pixel mask) +{ + int rval, result, class; + Pixel rmask; + + class = pmap->class; + if (pmap->flags & AllAllocated) + return(BadAccess); + if ((class | DynamicClass) == DirectColor) + { + rmask = mask & RGBMASK(pmap->pVisual); + result = FreeCo(pmap, client, REDMAP, count, pixels, + mask & pmap->pVisual->redMask); + /* If any of the three calls fails, we must report that, if more + * than one fails, it's ok that we report the last one */ + rval = FreeCo(pmap, client, GREENMAP, count, pixels, + mask & pmap->pVisual->greenMask); + if(rval != Success) + result = rval; + rval = FreeCo(pmap, client, BLUEMAP, count, pixels, + mask & pmap->pVisual->blueMask); + if(rval != Success) + result = rval; + } + else + { + rmask = mask & ((((Pixel)1) << pmap->pVisual->nplanes) - 1); + result = FreeCo(pmap, client, PSEUDOMAP, count, pixels, rmask); + } + if ((mask != rmask) && count) + { + clients[client]->errorValue = *pixels | mask; + result = BadValue; + } + /* XXX should worry about removing any RT_CMAPENTRY resource */ + return (result); +} + +/** + * Helper for FreeColors -- frees all combinations of *newpixels and mask bits + * which the client has allocated in channel colormap cells of pmap. + * doesn't change newpixels if it doesn't need to + * + * \param pmap which colormap head + * \param color which sub-map, eg, RED, BLUE, PSEUDO + * \param npixIn number of pixels passed in + * \param ppixIn number of base pixels + * \param mask mask client gave us + */ +static int +FreeCo (ColormapPtr pmap, int client, int color, int npixIn, Pixel *ppixIn, Pixel mask) +{ + Pixel *ppixClient, pixTest; + int npixClient, npixNew, npix; + Pixel bits, base, cmask, rgbbad; + Pixel *pptr, *cptr; + int n, zapped; + int errVal = Success; + int offset, numents; + + if (npixIn == 0) + return (errVal); + bits = 0; + zapped = 0; + base = lowbit (mask); + + switch(color) + { + case REDMAP: + cmask = pmap->pVisual->redMask; + rgbbad = ~RGBMASK(pmap->pVisual); + offset = pmap->pVisual->offsetRed; + numents = (cmask >> offset) + 1; + ppixClient = pmap->clientPixelsRed[client]; + npixClient = pmap->numPixelsRed[client]; + break; + case GREENMAP: + cmask = pmap->pVisual->greenMask; + rgbbad = ~RGBMASK(pmap->pVisual); + offset = pmap->pVisual->offsetGreen; + numents = (cmask >> offset) + 1; + ppixClient = pmap->clientPixelsGreen[client]; + npixClient = pmap->numPixelsGreen[client]; + break; + case BLUEMAP: + cmask = pmap->pVisual->blueMask; + rgbbad = ~RGBMASK(pmap->pVisual); + offset = pmap->pVisual->offsetBlue; + numents = (cmask >> offset) + 1; + ppixClient = pmap->clientPixelsBlue[client]; + npixClient = pmap->numPixelsBlue[client]; + break; + default: /* so compiler can see that everything gets initialized */ + case PSEUDOMAP: + cmask = ~((Pixel)0); + rgbbad = 0; + offset = 0; + numents = pmap->pVisual->ColormapEntries; + ppixClient = pmap->clientPixelsRed[client]; + npixClient = pmap->numPixelsRed[client]; + break; + } + + + /* zap all pixels which match */ + while (1) + { + /* go through pixel list */ + for (pptr = ppixIn, n = npixIn; --n >= 0; pptr++) + { + pixTest = ((*pptr | bits) & cmask) >> offset; + if ((pixTest >= numents) || (*pptr & rgbbad)) + { + clients[client]->errorValue = *pptr | bits; + errVal = BadValue; + continue; + } + + /* find match in client list */ + for (cptr = ppixClient, npix = npixClient; + --npix >= 0 && *cptr != pixTest; + cptr++) ; + + if (npix >= 0) + { + if (pmap->class & DynamicClass) + { + FreeCell(pmap, pixTest, color); + } + *cptr = ~((Pixel)0); + zapped++; + } + else + errVal = BadAccess; + } + /* generate next bits value */ + GetNextBitsOrBreak(bits, mask, base); + } + + /* delete freed pixels from client pixel list */ + if (zapped) + { + npixNew = npixClient - zapped; + if (npixNew) + { + /* Since the list can only get smaller, we can do a copy in + * place and then realloc to a smaller size */ + pptr = cptr = ppixClient; + + /* If we have all the new pixels, we don't have to examine the + * rest of the old ones */ + for(npix = 0; npix < npixNew; cptr++) + { + if (*cptr != ~((Pixel)0)) + { + *pptr++ = *cptr; + npix++; + } + } + pptr = (Pixel *)realloc(ppixClient, npixNew * sizeof(Pixel)); + if (pptr) + ppixClient = pptr; + npixClient = npixNew; + } + else + { + npixClient = 0; + free(ppixClient); + ppixClient = (Pixel *)NULL; + } + switch(color) + { + case PSEUDOMAP: + case REDMAP: + pmap->clientPixelsRed[client] = ppixClient; + pmap->numPixelsRed[client] = npixClient; + break; + case GREENMAP: + pmap->clientPixelsGreen[client] = ppixClient; + pmap->numPixelsGreen[client] = npixClient; + break; + case BLUEMAP: + pmap->clientPixelsBlue[client] = ppixClient; + pmap->numPixelsBlue[client] = npixClient; + break; + } + } + return (errVal); +} + + + +/* Redefine color values */ +int +StoreColors (ColormapPtr pmap, int count, xColorItem *defs, ClientPtr client) +{ + Pixel pix; + xColorItem *pdef; + EntryPtr pent, pentT, pentLast; + VisualPtr pVisual; + SHAREDCOLOR *pred, *pgreen, *pblue; + int n, ChgRed, ChgGreen, ChgBlue, idef; + int class, errVal = Success; + int ok; + + + class = pmap->class; + if(!(class & DynamicClass) && !(pmap->flags & BeingCreated)) + { + return(BadAccess); + } + pVisual = pmap->pVisual; + + idef = 0; + if((class | DynamicClass) == DirectColor) + { + int numred, numgreen, numblue; + Pixel rgbbad; + + numred = NUMRED(pVisual); + numgreen = NUMGREEN(pVisual); + numblue = NUMBLUE(pVisual); + rgbbad = ~RGBMASK(pVisual); + for (pdef = defs, n = 0; n < count; pdef++, n++) + { + ok = TRUE; + (*pmap->pScreen->ResolveColor) + (&pdef->red, &pdef->green, &pdef->blue, pmap->pVisual); + + if (pdef->pixel & rgbbad) + { + errVal = BadValue; + client->errorValue = pdef->pixel; + continue; + } + pix = (pdef->pixel & pVisual->redMask) >> pVisual->offsetRed; + if (pix >= numred) + { + errVal = BadValue; + ok = FALSE; + } + else if (pmap->red[pix].refcnt != AllocPrivate) + { + errVal = BadAccess; + ok = FALSE; + } + else if (pdef->flags & DoRed) + { + pmap->red[pix].co.local.red = pdef->red; + } + else + { + pdef->red = pmap->red[pix].co.local.red; + } + + pix = (pdef->pixel & pVisual->greenMask) >> pVisual->offsetGreen; + if (pix >= numgreen) + { + errVal = BadValue; + ok = FALSE; + } + else if (pmap->green[pix].refcnt != AllocPrivate) + { + errVal = BadAccess; + ok = FALSE; + } + else if (pdef->flags & DoGreen) + { + pmap->green[pix].co.local.green = pdef->green; + } + else + { + pdef->green = pmap->green[pix].co.local.green; + } + + pix = (pdef->pixel & pVisual->blueMask) >> pVisual->offsetBlue; + if (pix >= numblue) + { + errVal = BadValue; + ok = FALSE; + } + else if (pmap->blue[pix].refcnt != AllocPrivate) + { + errVal = BadAccess; + ok = FALSE; + } + else if (pdef->flags & DoBlue) + { + pmap->blue[pix].co.local.blue = pdef->blue; + } + else + { + pdef->blue = pmap->blue[pix].co.local.blue; + } + /* If this is an o.k. entry, then it gets added to the list + * to be sent to the hardware. If not, skip it. Once we've + * skipped one, we have to copy all the others. + */ + if(ok) + { + if(idef != n) + defs[idef] = defs[n]; + idef++; + } else + client->errorValue = pdef->pixel; + } + } + else + { + for (pdef = defs, n = 0; n < count; pdef++, n++) + { + + ok = TRUE; + if (pdef->pixel >= pVisual->ColormapEntries) + { + client->errorValue = pdef->pixel; + errVal = BadValue; + ok = FALSE; + } + else if (pmap->red[pdef->pixel].refcnt != AllocPrivate) + { + errVal = BadAccess; + ok = FALSE; + } + + /* If this is an o.k. entry, then it gets added to the list + * to be sent to the hardware. If not, skip it. Once we've + * skipped one, we have to copy all the others. + */ + if(ok) + { + if(idef != n) + defs[idef] = defs[n]; + idef++; + } + else + continue; + + (*pmap->pScreen->ResolveColor) + (&pdef->red, &pdef->green, &pdef->blue, pmap->pVisual); + + pent = &pmap->red[pdef->pixel]; + + if(pdef->flags & DoRed) + { + if(pent->fShared) + { + pent->co.shco.red->color = pdef->red; + if (pent->co.shco.red->refcnt > 1) + ok = FALSE; + } + else + pent->co.local.red = pdef->red; + } + else + { + if(pent->fShared) + pdef->red = pent->co.shco.red->color; + else + pdef->red = pent->co.local.red; + } + if(pdef->flags & DoGreen) + { + if(pent->fShared) + { + pent->co.shco.green->color = pdef->green; + if (pent->co.shco.green->refcnt > 1) + ok = FALSE; + } + else + pent->co.local.green = pdef->green; + } + else + { + if(pent->fShared) + pdef->green = pent->co.shco.green->color; + else + pdef->green = pent->co.local.green; + } + if(pdef->flags & DoBlue) + { + if(pent->fShared) + { + pent->co.shco.blue->color = pdef->blue; + if (pent->co.shco.blue->refcnt > 1) + ok = FALSE; + } + else + pent->co.local.blue = pdef->blue; + } + else + { + if(pent->fShared) + pdef->blue = pent->co.shco.blue->color; + else + pdef->blue = pent->co.local.blue; + } + + if(!ok) + { + /* have to run through the colormap and change anybody who + * shares this value */ + pred = pent->co.shco.red; + pgreen = pent->co.shco.green; + pblue = pent->co.shco.blue; + ChgRed = pdef->flags & DoRed; + ChgGreen = pdef->flags & DoGreen; + ChgBlue = pdef->flags & DoBlue; + pentLast = pmap->red + pVisual->ColormapEntries; + + for(pentT = pmap->red; pentT < pentLast; pentT++) + { + if(pentT->fShared && (pentT != pent)) + { + xColorItem defChg; + + /* There are, alas, devices in this world too dumb + * to read their own hardware colormaps. Sick, but + * true. So we're going to be really nice and load + * the xColorItem with the proper value for all the + * fields. We will only set the flags for those + * fields that actually change. Smart devices can + * arrange to change only those fields. Dumb devices + * can rest assured that we have provided for them, + * and can change all three fields */ + + defChg.flags = 0; + if(ChgRed && pentT->co.shco.red == pred) + { + defChg.flags |= DoRed; + } + if(ChgGreen && pentT->co.shco.green == pgreen) + { + defChg.flags |= DoGreen; + } + if(ChgBlue && pentT->co.shco.blue == pblue) + { + defChg.flags |= DoBlue; + } + if(defChg.flags != 0) + { + defChg.pixel = pentT - pmap->red; + defChg.red = pentT->co.shco.red->color; + defChg.green = pentT->co.shco.green->color; + defChg.blue = pentT->co.shco.blue->color; + (*pmap->pScreen->StoreColors) (pmap, 1, &defChg); + } + } + } + + } + } + } + /* Note that we use idef, the count of acceptable entries, and not + * count, the count of proposed entries */ + if (idef != 0) + ( *pmap->pScreen->StoreColors) (pmap, idef, defs); + return (errVal); +} + +int +IsMapInstalled(Colormap map, WindowPtr pWin) +{ + Colormap *pmaps; + int imap, nummaps, found; + + pmaps = malloc(pWin->drawable.pScreen->maxInstalledCmaps*sizeof(Colormap)); + if(!pmaps) + return(FALSE); + nummaps = (*pWin->drawable.pScreen->ListInstalledColormaps) + (pWin->drawable.pScreen, pmaps); + found = FALSE; + for(imap = 0; imap < nummaps; imap++) + { + if(pmaps[imap] == map) + { + found = TRUE; + break; + } + } + free(pmaps); + return (found); +} + +struct colormap_lookup_data { + ScreenPtr pScreen; + VisualPtr visuals; +}; + +static void _colormap_find_resource(pointer value, XID id, + pointer cdata) +{ + struct colormap_lookup_data *cmap_data = cdata; + VisualPtr visuals = cmap_data->visuals; + ScreenPtr pScreen = cmap_data->pScreen; + ColormapPtr cmap = value; + int j; + + if (pScreen != cmap->pScreen) + return; + + j = cmap->pVisual - pScreen->visuals; + cmap->pVisual = &visuals[j]; +} + +/* something has realloced the visuals, instead of breaking + ABI fix it up here - glx and compsite did this wrong */ +Bool +ResizeVisualArray(ScreenPtr pScreen, int new_visual_count, + DepthPtr depth) +{ + struct colormap_lookup_data cdata; + int numVisuals; + VisualPtr visuals; + XID *vids, vid; + int first_new_vid, first_new_visual, i; + + first_new_vid = depth->numVids; + first_new_visual = pScreen->numVisuals; + + vids = realloc(depth->vids, (depth->numVids + new_visual_count) * sizeof(XID)); + if (!vids) + return FALSE; + + /* its realloced now no going back if we fail the next one */ + depth->vids = vids; + + numVisuals = pScreen->numVisuals + new_visual_count; + visuals = realloc(pScreen->visuals, numVisuals * sizeof(VisualRec)); + if (!visuals) { + return FALSE; + } + + cdata.visuals = visuals; + cdata.pScreen = pScreen; + FindClientResourcesByType(serverClient, RT_COLORMAP, _colormap_find_resource, &cdata); + + pScreen->visuals = visuals; + + for (i = 0; i < new_visual_count; i++) { + vid = FakeClientID(0); + pScreen->visuals[first_new_visual + i].vid = vid; + vids[first_new_vid + i] = vid; + } + + depth->numVids += new_visual_count; + pScreen->numVisuals += new_visual_count; + + return TRUE; +} diff --git a/xorg-server/dix/gc.c b/xorg-server/dix/gc.c index b738d4112..6281f25cd 100644 --- a/xorg-server/dix/gc.c +++ b/xorg-server/dix/gc.c @@ -1,1158 +1,1159 @@ -/*********************************************************** - -Copyright 1987, 1998 The Open Group - -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. - -The above copyright notice and this permission notice 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 -OPEN GROUP 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. - -Except as contained in this notice, the name of The Open Group shall not be -used in advertising or otherwise to promote the sale, use or other dealings -in this Software without prior written authorization from The Open Group. - - -Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -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 Digital not be -used in advertising or publicity pertaining to distribution of the -software without specific, written prior permission. - -DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL -DIGITAL 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 -#endif - -#include -#include -#include -#include "misc.h" -#include "resource.h" -#include "gcstruct.h" -#include "pixmapstr.h" -#include "dixfontstr.h" -#include "scrnintstr.h" -#include "region.h" - -#include "privates.h" -#include "dix.h" -#include "xace.h" -#include - -extern FontPtr defaultFont; - -static Bool CreateDefaultTile(GCPtr pGC); - -static unsigned char DefaultDash[2] = {4, 4}; - -void -ValidateGC(DrawablePtr pDraw, GC *pGC) -{ - (*pGC->funcs->ValidateGC) (pGC, pGC->stateChanges, pDraw); - pGC->stateChanges = 0; - pGC->serialNumber = pDraw->serialNumber; -} - - -/* - * ChangeGC/ChangeGCXIDs: - * - * The client performing the gc change must be passed so that access - * checks can be performed on any tiles, stipples, or fonts that are - * specified. ddxen can call this too; they should normally pass - * NullClient for the client since any access checking should have - * already been done at a higher level. - * - * If you have any XIDs, you must use ChangeGCXIDs: - * - * CARD32 v[2]; - * v[0] = FillTiled; - * v[1] = pid; - * ChangeGCXIDs(client, pGC, GCFillStyle|GCTile, v); - * - * However, if you need to pass a pointer to a pixmap or font, you must - * use ChangeGC: - * - * ChangeGCVal v[2]; - * v[0].val = FillTiled; - * v[1].ptr = pPixmap; - * ChangeGC(client, pGC, GCFillStyle|GCTile, v); - * - * If you have neither XIDs nor pointers, you can use either function, - * but ChangeGC will do less work. - * - * ChangeGCVal v[2]; - * v[0].val = foreground; - * v[1].val = background; - * ChangeGC(client, pGC, GCForeground|GCBackground, v); - */ - -#define NEXTVAL(_type, _var) { \ - _var = (_type)(pUnion->val); pUnion++; \ - } - -#define NEXT_PTR(_type, _var) { \ - _var = (_type)pUnion->ptr; pUnion++; } - -int -ChangeGC(ClientPtr client, GC *pGC, BITS32 mask, ChangeGCValPtr pUnion) -{ - BITS32 index2; - int error = 0; - PixmapPtr pPixmap; - BITS32 maskQ; - - assert(pUnion); - pGC->serialNumber |= GC_CHANGE_SERIAL_BIT; - - maskQ = mask; /* save these for when we walk the GCque */ - while (mask && !error) - { - index2 = (BITS32) lowbit (mask); - mask &= ~index2; - pGC->stateChanges |= index2; - switch (index2) - { - case GCFunction: - { - CARD8 newalu; - NEXTVAL(CARD8, newalu); - if (newalu <= GXset) - pGC->alu = newalu; - else - { - if (client) - client->errorValue = newalu; - error = BadValue; - } - break; - } - case GCPlaneMask: - NEXTVAL(unsigned long, pGC->planemask); - break; - case GCForeground: - NEXTVAL(unsigned long, pGC->fgPixel); - /* - * this is for CreateGC - */ - if (!pGC->tileIsPixel && !pGC->tile.pixmap) - { - pGC->tileIsPixel = TRUE; - pGC->tile.pixel = pGC->fgPixel; - } - break; - case GCBackground: - NEXTVAL(unsigned long, pGC->bgPixel); - break; - case GCLineWidth: /* ??? line width is a CARD16 */ - NEXTVAL(CARD16, pGC->lineWidth); - break; - case GCLineStyle: - { - unsigned int newlinestyle; - NEXTVAL(unsigned int, newlinestyle); - if (newlinestyle <= LineDoubleDash) - pGC->lineStyle = newlinestyle; - else - { - if (client) - client->errorValue = newlinestyle; - error = BadValue; - } - break; - } - case GCCapStyle: - { - unsigned int newcapstyle; - NEXTVAL(unsigned int, newcapstyle); - if (newcapstyle <= CapProjecting) - pGC->capStyle = newcapstyle; - else - { - if (client) - client->errorValue = newcapstyle; - error = BadValue; - } - break; - } - case GCJoinStyle: - { - unsigned int newjoinstyle; - NEXTVAL(unsigned int, newjoinstyle); - if (newjoinstyle <= JoinBevel) - pGC->joinStyle = newjoinstyle; - else - { - if (client) - client->errorValue = newjoinstyle; - error = BadValue; - } - break; - } - case GCFillStyle: - { - unsigned int newfillstyle; - NEXTVAL(unsigned int, newfillstyle); - if (newfillstyle <= FillOpaqueStippled) - pGC->fillStyle = newfillstyle; - else - { - if (client) - client->errorValue = newfillstyle; - error = BadValue; - } - break; - } - case GCFillRule: - { - unsigned int newfillrule; - NEXTVAL(unsigned int, newfillrule); - if (newfillrule <= WindingRule) - pGC->fillRule = newfillrule; - else - { - if (client) - client->errorValue = newfillrule; - error = BadValue; - } - break; - } - case GCTile: - NEXT_PTR(PixmapPtr, pPixmap); - if ((pPixmap->drawable.depth != pGC->depth) || - (pPixmap->drawable.pScreen != pGC->pScreen)) - { - error = BadMatch; - } - else - { - pPixmap->refcnt++; - if (!pGC->tileIsPixel) - (* pGC->pScreen->DestroyPixmap)(pGC->tile.pixmap); - pGC->tileIsPixel = FALSE; - pGC->tile.pixmap = pPixmap; - } - break; - case GCStipple: - NEXT_PTR(PixmapPtr, pPixmap); - if ((pPixmap->drawable.depth != 1) || - (pPixmap->drawable.pScreen != pGC->pScreen)) - { - error = BadMatch; - } - else - { - pPixmap->refcnt++; - if (pGC->stipple) - (* pGC->pScreen->DestroyPixmap)(pGC->stipple); - pGC->stipple = pPixmap; - } - break; - case GCTileStipXOrigin: - NEXTVAL(INT16, pGC->patOrg.x); - break; - case GCTileStipYOrigin: - NEXTVAL(INT16, pGC->patOrg.y); - break; - case GCFont: - { - FontPtr pFont; - NEXT_PTR(FontPtr, pFont); - pFont->refcnt++; - if (pGC->font) - CloseFont(pGC->font, (Font)0); - pGC->font = pFont; - break; - } - case GCSubwindowMode: - { - unsigned int newclipmode; - NEXTVAL(unsigned int, newclipmode); - if (newclipmode <= IncludeInferiors) - pGC->subWindowMode = newclipmode; - else - { - if (client) - client->errorValue = newclipmode; - error = BadValue; - } - break; - } - case GCGraphicsExposures: - { - unsigned int newge; - NEXTVAL(unsigned int, newge); - if (newge <= xTrue) - pGC->graphicsExposures = newge; - else - { - if (client) - client->errorValue = newge; - error = BadValue; - } - break; - } - case GCClipXOrigin: - NEXTVAL(INT16, pGC->clipOrg.x); - break; - case GCClipYOrigin: - NEXTVAL(INT16, pGC->clipOrg.y); - break; - case GCClipMask: - NEXT_PTR(PixmapPtr, pPixmap); - if (pPixmap) - { - if ((pPixmap->drawable.depth != 1) || - (pPixmap->drawable.pScreen != pGC->pScreen)) - { - error = BadMatch; - break; - } - pPixmap->refcnt++; - } - (*pGC->funcs->ChangeClip)(pGC, pPixmap ? CT_PIXMAP : CT_NONE, - (pointer)pPixmap, 0); - break; - case GCDashOffset: - NEXTVAL(INT16, pGC->dashOffset); - break; - case GCDashList: - { - CARD8 newdash; - NEXTVAL(CARD8, newdash); - if (newdash == 4) - { - if (pGC->dash != DefaultDash) - { - free(pGC->dash); - pGC->numInDashList = 2; - pGC->dash = DefaultDash; - } - } - else if (newdash != 0) - { - unsigned char *dash; - - dash = malloc(2 * sizeof(unsigned char)); - if (dash) - { - if (pGC->dash != DefaultDash) - free(pGC->dash); - pGC->numInDashList = 2; - pGC->dash = dash; - dash[0] = newdash; - dash[1] = newdash; - } - else - error = BadAlloc; - } - else - { - if (client) - client->errorValue = newdash; - error = BadValue; - } - break; - } - case GCArcMode: - { - unsigned int newarcmode; - NEXTVAL(unsigned int, newarcmode); - if (newarcmode <= ArcPieSlice) - pGC->arcMode = newarcmode; - else - { - if (client) - client->errorValue = newarcmode; - error = BadValue; - } - break; - } - default: - if (client) - client->errorValue = maskQ; - error = BadValue; - break; - } - } /* end while mask && !error */ - - if (pGC->fillStyle == FillTiled && pGC->tileIsPixel) - { - if (!CreateDefaultTile (pGC)) - { - pGC->fillStyle = FillSolid; - error = BadAlloc; - } - } - (*pGC->funcs->ChangeGC)(pGC, maskQ); - return error; -} - -#undef NEXTVAL -#undef NEXT_PTR - -static const struct { - BITS32 mask; - RESTYPE type; - Mask access_mode; -} xidfields[] = { - { GCTile, RT_PIXMAP, DixReadAccess }, - { GCStipple, RT_PIXMAP, DixReadAccess }, - { GCFont, RT_FONT, DixUseAccess }, - { GCClipMask, RT_PIXMAP, DixReadAccess }, -}; - -int -ChangeGCXIDs(ClientPtr client, GC *pGC, BITS32 mask, CARD32 *pC32) -{ - ChangeGCVal vals[GCLastBit + 1]; - int i; - if (mask & ~GCAllBits) - { - client->errorValue = mask; - return BadValue; - } - for (i = Ones(mask); i--; ) - vals[i].val = pC32[i]; - for (i = 0; i < sizeof(xidfields) / sizeof(*xidfields); ++i) - { - int offset, rc; - if (!(mask & xidfields[i].mask)) - continue; - offset = Ones(mask & (xidfields[i].mask - 1)); - if (xidfields[i].mask == GCClipMask && vals[offset].val == None) - { - vals[offset].ptr = NullPixmap; - continue; - } - rc = dixLookupResourceByType(&vals[offset].ptr, vals[offset].val, - xidfields[i].type, client, xidfields[i].access_mode); - if (rc != Success) - { - client->errorValue = vals[offset].val; - if (rc == BadValue) - rc = (xidfields[i].type == RT_PIXMAP) ? BadPixmap : BadFont; - return rc; - } - } - return ChangeGC(client, pGC, mask, vals); -} - -/* CreateGC(pDrawable, mask, pval, pStatus) - creates a default GC for the given drawable, using mask to fill - in any non-default values. - Returns a pointer to the new GC on success, NULL otherwise. - returns status of non-default fields in pStatus -BUG: - should check for failure to create default tile - -*/ -GCPtr -CreateGC(DrawablePtr pDrawable, BITS32 mask, XID *pval, int *pStatus, - XID gcid, ClientPtr client) -{ - GCPtr pGC; - - pGC = malloc(sizeof(GC)); - if (!pGC) - { - *pStatus = BadAlloc; - return (GCPtr)NULL; - } - - pGC->pScreen = pDrawable->pScreen; - pGC->depth = pDrawable->depth; - pGC->alu = GXcopy; /* dst <- src */ - pGC->planemask = ~0; - pGC->serialNumber = GC_CHANGE_SERIAL_BIT; - pGC->funcs = 0; - pGC->devPrivates = NULL; - pGC->fgPixel = 0; - pGC->bgPixel = 1; - pGC->lineWidth = 0; - pGC->lineStyle = LineSolid; - pGC->capStyle = CapButt; - pGC->joinStyle = JoinMiter; - pGC->fillStyle = FillSolid; - pGC->fillRule = EvenOddRule; - pGC->arcMode = ArcPieSlice; - pGC->tile.pixel = 0; - pGC->tile.pixmap = NullPixmap; - if (mask & GCForeground) - { - /* - * magic special case -- ChangeGC checks for this condition - * and snags the Foreground value to create a pseudo default-tile - */ - pGC->tileIsPixel = FALSE; - } - else - { - pGC->tileIsPixel = TRUE; - } - - pGC->patOrg.x = 0; - pGC->patOrg.y = 0; - pGC->subWindowMode = ClipByChildren; - pGC->graphicsExposures = TRUE; - pGC->clipOrg.x = 0; - pGC->clipOrg.y = 0; - pGC->clientClipType = CT_NONE; - pGC->clientClip = (pointer)NULL; - pGC->numInDashList = 2; - pGC->dash = DefaultDash; - pGC->dashOffset = 0; - pGC->lastWinOrg.x = 0; - pGC->lastWinOrg.y = 0; - - /* use the default font and stipple */ - pGC->font = defaultFont; - defaultFont->refcnt++; - pGC->stipple = pGC->pScreen->PixmapPerDepth[0]; - pGC->stipple->refcnt++; - - /* security creation/labeling check */ - *pStatus = XaceHook(XACE_RESOURCE_ACCESS, client, gcid, RT_GC, pGC, - RT_NONE, NULL, DixCreateAccess|DixSetAttrAccess); - if (*pStatus != Success) - goto out; - - pGC->stateChanges = GCAllBits; - if (!(*pGC->pScreen->CreateGC)(pGC)) - *pStatus = BadAlloc; - else if (mask) - *pStatus = ChangeGCXIDs(client, pGC, mask, pval); - else - *pStatus = Success; - -out: - if (*pStatus != Success) - { - if (!pGC->tileIsPixel && !pGC->tile.pixmap) - pGC->tileIsPixel = TRUE; /* undo special case */ - FreeGC(pGC, (XID)0); - pGC = (GCPtr)NULL; - } - - return (pGC); -} - -static Bool -CreateDefaultTile (GCPtr pGC) -{ - ChangeGCVal tmpval[3]; - PixmapPtr pTile; - GCPtr pgcScratch; - xRectangle rect; - CARD16 w, h; - - w = 1; - h = 1; - (*pGC->pScreen->QueryBestSize)(TileShape, &w, &h, pGC->pScreen); - pTile = (PixmapPtr) - (*pGC->pScreen->CreatePixmap)(pGC->pScreen, - w, h, pGC->depth, 0); - pgcScratch = GetScratchGC(pGC->depth, pGC->pScreen); - if (!pTile || !pgcScratch) - { - if (pTile) - (*pTile->drawable.pScreen->DestroyPixmap)(pTile); - if (pgcScratch) - FreeScratchGC(pgcScratch); - return FALSE; - } - tmpval[0].val = GXcopy; - tmpval[1].val = pGC->tile.pixel; - tmpval[2].val = FillSolid; - (void)ChangeGC(NullClient, pgcScratch, GCFunction | GCForeground | GCFillStyle, tmpval); - ValidateGC((DrawablePtr)pTile, pgcScratch); - rect.x = 0; - rect.y = 0; - rect.width = w; - rect.height = h; - (*pgcScratch->ops->PolyFillRect)((DrawablePtr)pTile, pgcScratch, 1, &rect); - /* Always remember to free the scratch graphics context after use. */ - FreeScratchGC(pgcScratch); - - pGC->tileIsPixel = FALSE; - pGC->tile.pixmap = pTile; - return TRUE; -} - -int -CopyGC(GC *pgcSrc, GC *pgcDst, BITS32 mask) -{ - BITS32 index2; - BITS32 maskQ; - int error = 0; - - if (pgcSrc == pgcDst) - return Success; - pgcDst->serialNumber |= GC_CHANGE_SERIAL_BIT; - pgcDst->stateChanges |= mask; - maskQ = mask; - while (mask) - { - index2 = (BITS32) lowbit (mask); - mask &= ~index2; - switch (index2) - { - case GCFunction: - pgcDst->alu = pgcSrc->alu; - break; - case GCPlaneMask: - pgcDst->planemask = pgcSrc->planemask; - break; - case GCForeground: - pgcDst->fgPixel = pgcSrc->fgPixel; - break; - case GCBackground: - pgcDst->bgPixel = pgcSrc->bgPixel; - break; - case GCLineWidth: - pgcDst->lineWidth = pgcSrc->lineWidth; - break; - case GCLineStyle: - pgcDst->lineStyle = pgcSrc->lineStyle; - break; - case GCCapStyle: - pgcDst->capStyle = pgcSrc->capStyle; - break; - case GCJoinStyle: - pgcDst->joinStyle = pgcSrc->joinStyle; - break; - case GCFillStyle: - pgcDst->fillStyle = pgcSrc->fillStyle; - break; - case GCFillRule: - pgcDst->fillRule = pgcSrc->fillRule; - break; - case GCTile: - { - if (EqualPixUnion(pgcDst->tileIsPixel, - pgcDst->tile, - pgcSrc->tileIsPixel, - pgcSrc->tile)) - { - break; - } - if (!pgcDst->tileIsPixel) - (* pgcDst->pScreen->DestroyPixmap)(pgcDst->tile.pixmap); - pgcDst->tileIsPixel = pgcSrc->tileIsPixel; - pgcDst->tile = pgcSrc->tile; - if (!pgcDst->tileIsPixel) - pgcDst->tile.pixmap->refcnt++; - break; - } - case GCStipple: - { - if (pgcDst->stipple == pgcSrc->stipple) - break; - if (pgcDst->stipple) - (* pgcDst->pScreen->DestroyPixmap)(pgcDst->stipple); - pgcDst->stipple = pgcSrc->stipple; - if (pgcDst->stipple) - pgcDst->stipple->refcnt ++; - break; - } - case GCTileStipXOrigin: - pgcDst->patOrg.x = pgcSrc->patOrg.x; - break; - case GCTileStipYOrigin: - pgcDst->patOrg.y = pgcSrc->patOrg.y; - break; - case GCFont: - if (pgcDst->font == pgcSrc->font) - break; - if (pgcDst->font) - CloseFont(pgcDst->font, (Font)0); - if ((pgcDst->font = pgcSrc->font) != NullFont) - (pgcDst->font)->refcnt++; - break; - case GCSubwindowMode: - pgcDst->subWindowMode = pgcSrc->subWindowMode; - break; - case GCGraphicsExposures: - pgcDst->graphicsExposures = pgcSrc->graphicsExposures; - break; - case GCClipXOrigin: - pgcDst->clipOrg.x = pgcSrc->clipOrg.x; - break; - case GCClipYOrigin: - pgcDst->clipOrg.y = pgcSrc->clipOrg.y; - break; - case GCClipMask: - (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc); - break; - case GCDashOffset: - pgcDst->dashOffset = pgcSrc->dashOffset; - break; - case GCDashList: - if (pgcSrc->dash == DefaultDash) - { - if (pgcDst->dash != DefaultDash) - { - free(pgcDst->dash); - pgcDst->numInDashList = pgcSrc->numInDashList; - pgcDst->dash = pgcSrc->dash; - } - } - else - { - unsigned char *dash; - unsigned int i; - - dash = malloc(pgcSrc->numInDashList * sizeof(unsigned char)); - if (dash) - { - if (pgcDst->dash != DefaultDash) - free(pgcDst->dash); - pgcDst->numInDashList = pgcSrc->numInDashList; - pgcDst->dash = dash; - for (i=0; inumInDashList; i++) - dash[i] = pgcSrc->dash[i]; - } - else - error = BadAlloc; - } - break; - case GCArcMode: - pgcDst->arcMode = pgcSrc->arcMode; - break; - default: - FatalError ("CopyGC: Unhandled mask!\n"); - } - } - if (pgcDst->fillStyle == FillTiled && pgcDst->tileIsPixel) - { - if (!CreateDefaultTile (pgcDst)) - { - pgcDst->fillStyle = FillSolid; - error = BadAlloc; - } - } - (*pgcDst->funcs->CopyGC) (pgcSrc, maskQ, pgcDst); - return error; -} - -/** - * does the diX part of freeing the characteristics in the GC. - * - * \param value must conform to DeleteType - */ -int -FreeGC(pointer value, XID gid) -{ - GCPtr pGC = (GCPtr)value; - - CloseFont(pGC->font, (Font)0); - (* pGC->funcs->DestroyClip)(pGC); - - if (!pGC->tileIsPixel) - (* pGC->pScreen->DestroyPixmap)(pGC->tile.pixmap); - if (pGC->stipple) - (* pGC->pScreen->DestroyPixmap)(pGC->stipple); - - (*pGC->funcs->DestroyGC) (pGC); - if (pGC->dash != DefaultDash) - free(pGC->dash); - dixFreePrivates(pGC->devPrivates); - free(pGC); - return(Success); -} - -/* CreateScratchGC(pScreen, depth) - like CreateGC, but doesn't do the default tile or stipple, -since we can't create them without already having a GC. any code -using the tile or stipple has to set them explicitly anyway, -since the state of the scratch gc is unknown. This is OK -because ChangeGC() has to be able to deal with NULL tiles and -stipples anyway (in case the CreateGC() call has provided a -value for them -- we can't set the default tile until the -client-supplied attributes are installed, since the fgPixel -is what fills the default tile. (maybe this comment should -go with CreateGC() or ChangeGC().) -*/ - -GCPtr -CreateScratchGC(ScreenPtr pScreen, unsigned depth) -{ - GCPtr pGC; - - pGC = malloc(sizeof(GC)); - if (!pGC) - return (GCPtr)NULL; - - pGC->pScreen = pScreen; - pGC->depth = depth; - pGC->alu = GXcopy; /* dst <- src */ - pGC->planemask = ~0; - pGC->serialNumber = 0; - pGC->devPrivates = NULL; - pGC->fgPixel = 0; - pGC->bgPixel = 1; - pGC->lineWidth = 0; - pGC->lineStyle = LineSolid; - pGC->capStyle = CapButt; - pGC->joinStyle = JoinMiter; - pGC->fillStyle = FillSolid; - pGC->fillRule = EvenOddRule; - pGC->arcMode = ArcPieSlice; - pGC->font = defaultFont; - if ( pGC->font) /* necessary, because open of default font could fail */ - pGC->font->refcnt++; - pGC->tileIsPixel = TRUE; - pGC->tile.pixel = 0; - pGC->tile.pixmap = NullPixmap; - pGC->stipple = NullPixmap; - pGC->patOrg.x = 0; - pGC->patOrg.y = 0; - pGC->subWindowMode = ClipByChildren; - pGC->graphicsExposures = TRUE; - pGC->clipOrg.x = 0; - pGC->clipOrg.y = 0; - pGC->clientClipType = CT_NONE; - pGC->dashOffset = 0; - pGC->numInDashList = 2; - pGC->dash = DefaultDash; - pGC->lastWinOrg.x = 0; - pGC->lastWinOrg.y = 0; - - pGC->stateChanges = GCAllBits; - if (!(*pScreen->CreateGC)(pGC)) - { - FreeGC(pGC, (XID)0); - pGC = (GCPtr)NULL; - } - return pGC; -} - -void -FreeGCperDepth(int screenNum) -{ - int i; - ScreenPtr pScreen; - GCPtr *ppGC; - - pScreen = screenInfo.screens[screenNum]; - ppGC = pScreen->GCperDepth; - - for (i = 0; i <= pScreen->numDepths; i++) - (void)FreeGC(ppGC[i], (XID)0); - pScreen->rgf = ~0L; -} - - -Bool -CreateGCperDepth(int screenNum) -{ - int i; - ScreenPtr pScreen; - DepthPtr pDepth; - GCPtr *ppGC; - - pScreen = screenInfo.screens[screenNum]; - pScreen->rgf = 0; - ppGC = pScreen->GCperDepth; - /* do depth 1 separately because it's not included in list */ - if (!(ppGC[0] = CreateScratchGC(pScreen, 1))) - return FALSE; - ppGC[0]->graphicsExposures = FALSE; - /* Make sure we don't overflow GCperDepth[] */ - if( pScreen->numDepths > MAXFORMATS ) - return FALSE; - - pDepth = pScreen->allowedDepths; - for (i=0; inumDepths; i++, pDepth++) - { - if (!(ppGC[i+1] = CreateScratchGC(pScreen, pDepth->depth))) - { - for (; i >= 0; i--) - (void)FreeGC(ppGC[i], (XID)0); - return FALSE; - } - ppGC[i+1]->graphicsExposures = FALSE; - } - return TRUE; -} - -Bool -CreateDefaultStipple(int screenNum) -{ - ScreenPtr pScreen; - ChangeGCVal tmpval[3]; - xRectangle rect; - CARD16 w, h; - GCPtr pgcScratch; - - pScreen = screenInfo.screens[screenNum]; - - w = 16; - h = 16; - (* pScreen->QueryBestSize)(StippleShape, &w, &h, pScreen); - if (!(pScreen->PixmapPerDepth[0] = - (*pScreen->CreatePixmap)(pScreen, w, h, 1, 0))) - return FALSE; - /* fill stipple with 1 */ - tmpval[0].val = GXcopy; - tmpval[1].val = 1; - tmpval[2].val = FillSolid; - pgcScratch = GetScratchGC(1, pScreen); - if (!pgcScratch) - { - (*pScreen->DestroyPixmap)(pScreen->PixmapPerDepth[0]); - return FALSE; - } - (void)ChangeGC(NullClient, pgcScratch, GCFunction|GCForeground|GCFillStyle, tmpval); - ValidateGC((DrawablePtr)pScreen->PixmapPerDepth[0], pgcScratch); - rect.x = 0; - rect.y = 0; - rect.width = w; - rect.height = h; - (*pgcScratch->ops->PolyFillRect)((DrawablePtr)pScreen->PixmapPerDepth[0], - pgcScratch, 1, &rect); - FreeScratchGC(pgcScratch); - return TRUE; -} - -void -FreeDefaultStipple(int screenNum) -{ - ScreenPtr pScreen = screenInfo.screens[screenNum]; - (*pScreen->DestroyPixmap)(pScreen->PixmapPerDepth[0]); -} - -int -SetDashes(GCPtr pGC, unsigned offset, unsigned ndash, unsigned char *pdash) -{ - long i; - unsigned char *p, *indash; - BITS32 maskQ = 0; - - i = ndash; - p = pdash; - while (i--) - { - if (!*p++) - { - /* dash segment must be > 0 */ - return BadValue; - } - } - - if (ndash & 1) - p = malloc(2 * ndash * sizeof(unsigned char)); - else - p = malloc(ndash * sizeof(unsigned char)); - if (!p) - return BadAlloc; - - pGC->serialNumber |= GC_CHANGE_SERIAL_BIT; - if (offset != pGC->dashOffset) - { - pGC->dashOffset = offset; - pGC->stateChanges |= GCDashOffset; - maskQ |= GCDashOffset; - } - - if (pGC->dash != DefaultDash) - free(pGC->dash); - pGC->numInDashList = ndash; - pGC->dash = p; - if (ndash & 1) - { - pGC->numInDashList += ndash; - indash = pdash; - i = ndash; - while (i--) - *p++ = *indash++; - } - while(ndash--) - *p++ = *pdash++; - pGC->stateChanges |= GCDashList; - maskQ |= GCDashList; - - if (pGC->funcs->ChangeGC) - (*pGC->funcs->ChangeGC) (pGC, maskQ); - return Success; -} - -int -VerifyRectOrder(int nrects, xRectangle *prects, int ordering) -{ - xRectangle *prectP, *prectN; - int i; - - switch(ordering) - { - case Unsorted: - return CT_UNSORTED; - case YSorted: - if(nrects > 1) - { - for(i = 1, prectP = prects, prectN = prects + 1; - i < nrects; - i++, prectP++, prectN++) - if(prectN->y < prectP->y) - return -1; - } - return CT_YSORTED; - case YXSorted: - if(nrects > 1) - { - for(i = 1, prectP = prects, prectN = prects + 1; - i < nrects; - i++, prectP++, prectN++) - if((prectN->y < prectP->y) || - ( (prectN->y == prectP->y) && - (prectN->x < prectP->x) ) ) - return -1; - } - return CT_YXSORTED; - case YXBanded: - if(nrects > 1) - { - for(i = 1, prectP = prects, prectN = prects + 1; - i < nrects; - i++, prectP++, prectN++) - if((prectN->y != prectP->y && - prectN->y < prectP->y + (int) prectP->height) || - ((prectN->y == prectP->y) && - (prectN->height != prectP->height || - prectN->x < prectP->x + (int) prectP->width))) - return -1; - } - return CT_YXBANDED; - } - return -1; -} - -int -SetClipRects(GCPtr pGC, int xOrigin, int yOrigin, int nrects, - xRectangle *prects, int ordering) -{ - int newct, size; - xRectangle *prectsNew; - - newct = VerifyRectOrder(nrects, prects, ordering); - if (newct < 0) - return(BadMatch); - size = nrects * sizeof(xRectangle); - prectsNew = malloc(size); - if (!prectsNew && size) - return BadAlloc; - - pGC->serialNumber |= GC_CHANGE_SERIAL_BIT; - pGC->clipOrg.x = xOrigin; - pGC->stateChanges |= GCClipXOrigin; - - pGC->clipOrg.y = yOrigin; - pGC->stateChanges |= GCClipYOrigin; - - if (size) - memmove((char *)prectsNew, (char *)prects, size); - (*pGC->funcs->ChangeClip)(pGC, newct, (pointer)prectsNew, nrects); - if (pGC->funcs->ChangeGC) - (*pGC->funcs->ChangeGC) (pGC, GCClipXOrigin|GCClipYOrigin|GCClipMask); - return Success; -} - - -/* - sets reasonable defaults - if we can get a pre-allocated one, use it and mark it as used. - if we can't, create one out of whole cloth (The Velveteen GC -- if - you use it often enough it will become real.) -*/ -GCPtr -GetScratchGC(unsigned depth, ScreenPtr pScreen) -{ - int i; - GCPtr pGC; - - for (i=0; i<=pScreen->numDepths; i++) - if ( pScreen->GCperDepth[i]->depth == depth && - !(pScreen->rgf & (1L << (i+1))) - ) - { - pScreen->rgf |= (1L << (i+1)); - pGC = (pScreen->GCperDepth[i]); - - pGC->alu = GXcopy; - pGC->planemask = ~0; - pGC->serialNumber = 0; - pGC->fgPixel = 0; - pGC->bgPixel = 1; - pGC->lineWidth = 0; - pGC->lineStyle = LineSolid; - pGC->capStyle = CapButt; - pGC->joinStyle = JoinMiter; - pGC->fillStyle = FillSolid; - pGC->fillRule = EvenOddRule; - pGC->arcMode = ArcChord; - pGC->patOrg.x = 0; - pGC->patOrg.y = 0; - pGC->subWindowMode = ClipByChildren; - pGC->graphicsExposures = FALSE; - pGC->clipOrg.x = 0; - pGC->clipOrg.y = 0; - if (pGC->clientClipType != CT_NONE) - (*pGC->funcs->ChangeClip) (pGC, CT_NONE, NULL, 0); - pGC->stateChanges = GCAllBits; - return pGC; - } - /* if we make it this far, need to roll our own */ - pGC = CreateScratchGC(pScreen, depth); - if (pGC) - pGC->graphicsExposures = FALSE; - return pGC; -} - -/* - if the gc to free is in the table of pre-existing ones, -mark it as available. - if not, free it for real -*/ -void -FreeScratchGC(GCPtr pGC) -{ - ScreenPtr pScreen = pGC->pScreen; - int i; - - for (i=0; i<=pScreen->numDepths; i++) - { - if ( pScreen->GCperDepth[i] == pGC) - { - pScreen->rgf &= ~(1L << (i+1)); - return; - } - } - (void)FreeGC(pGC, (GContext)0); -} +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +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. + +The above copyright notice and this permission notice 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 +OPEN GROUP 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. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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 +#endif + +#include +#include +#include +#include "misc.h" +#include "resource.h" +#include "gcstruct.h" +#include "pixmapstr.h" +#include "dixfontstr.h" +#include "scrnintstr.h" +#include "region.h" +#include "dixstruct.h" + +#include "privates.h" +#include "dix.h" +#include "xace.h" +#include + +extern FontPtr defaultFont; + +static Bool CreateDefaultTile(GCPtr pGC); + +static unsigned char DefaultDash[2] = {4, 4}; + +void +ValidateGC(DrawablePtr pDraw, GC *pGC) +{ + (*pGC->funcs->ValidateGC) (pGC, pGC->stateChanges, pDraw); + pGC->stateChanges = 0; + pGC->serialNumber = pDraw->serialNumber; +} + + +/* + * ChangeGC/ChangeGCXIDs: + * + * The client performing the gc change must be passed so that access + * checks can be performed on any tiles, stipples, or fonts that are + * specified. ddxen can call this too; they should normally pass + * NullClient for the client since any access checking should have + * already been done at a higher level. + * + * If you have any XIDs, you must use ChangeGCXIDs: + * + * CARD32 v[2]; + * v[0] = FillTiled; + * v[1] = pid; + * ChangeGCXIDs(client, pGC, GCFillStyle|GCTile, v); + * + * However, if you need to pass a pointer to a pixmap or font, you must + * use ChangeGC: + * + * ChangeGCVal v[2]; + * v[0].val = FillTiled; + * v[1].ptr = pPixmap; + * ChangeGC(client, pGC, GCFillStyle|GCTile, v); + * + * If you have neither XIDs nor pointers, you can use either function, + * but ChangeGC will do less work. + * + * ChangeGCVal v[2]; + * v[0].val = foreground; + * v[1].val = background; + * ChangeGC(client, pGC, GCForeground|GCBackground, v); + */ + +#define NEXTVAL(_type, _var) { \ + _var = (_type)(pUnion->val); pUnion++; \ + } + +#define NEXT_PTR(_type, _var) { \ + _var = (_type)pUnion->ptr; pUnion++; } + +int +ChangeGC(ClientPtr client, GC *pGC, BITS32 mask, ChangeGCValPtr pUnion) +{ + BITS32 index2; + int error = 0; + PixmapPtr pPixmap; + BITS32 maskQ; + + assert(pUnion); + pGC->serialNumber |= GC_CHANGE_SERIAL_BIT; + + maskQ = mask; /* save these for when we walk the GCque */ + while (mask && !error) + { + index2 = (BITS32) lowbit (mask); + mask &= ~index2; + pGC->stateChanges |= index2; + switch (index2) + { + case GCFunction: + { + CARD8 newalu; + NEXTVAL(CARD8, newalu); + if (newalu <= GXset) + pGC->alu = newalu; + else + { + if (client) + client->errorValue = newalu; + error = BadValue; + } + break; + } + case GCPlaneMask: + NEXTVAL(unsigned long, pGC->planemask); + break; + case GCForeground: + NEXTVAL(unsigned long, pGC->fgPixel); + /* + * this is for CreateGC + */ + if (!pGC->tileIsPixel && !pGC->tile.pixmap) + { + pGC->tileIsPixel = TRUE; + pGC->tile.pixel = pGC->fgPixel; + } + break; + case GCBackground: + NEXTVAL(unsigned long, pGC->bgPixel); + break; + case GCLineWidth: /* ??? line width is a CARD16 */ + NEXTVAL(CARD16, pGC->lineWidth); + break; + case GCLineStyle: + { + unsigned int newlinestyle; + NEXTVAL(unsigned int, newlinestyle); + if (newlinestyle <= LineDoubleDash) + pGC->lineStyle = newlinestyle; + else + { + if (client) + client->errorValue = newlinestyle; + error = BadValue; + } + break; + } + case GCCapStyle: + { + unsigned int newcapstyle; + NEXTVAL(unsigned int, newcapstyle); + if (newcapstyle <= CapProjecting) + pGC->capStyle = newcapstyle; + else + { + if (client) + client->errorValue = newcapstyle; + error = BadValue; + } + break; + } + case GCJoinStyle: + { + unsigned int newjoinstyle; + NEXTVAL(unsigned int, newjoinstyle); + if (newjoinstyle <= JoinBevel) + pGC->joinStyle = newjoinstyle; + else + { + if (client) + client->errorValue = newjoinstyle; + error = BadValue; + } + break; + } + case GCFillStyle: + { + unsigned int newfillstyle; + NEXTVAL(unsigned int, newfillstyle); + if (newfillstyle <= FillOpaqueStippled) + pGC->fillStyle = newfillstyle; + else + { + if (client) + client->errorValue = newfillstyle; + error = BadValue; + } + break; + } + case GCFillRule: + { + unsigned int newfillrule; + NEXTVAL(unsigned int, newfillrule); + if (newfillrule <= WindingRule) + pGC->fillRule = newfillrule; + else + { + if (client) + client->errorValue = newfillrule; + error = BadValue; + } + break; + } + case GCTile: + NEXT_PTR(PixmapPtr, pPixmap); + if ((pPixmap->drawable.depth != pGC->depth) || + (pPixmap->drawable.pScreen != pGC->pScreen)) + { + error = BadMatch; + } + else + { + pPixmap->refcnt++; + if (!pGC->tileIsPixel) + (* pGC->pScreen->DestroyPixmap)(pGC->tile.pixmap); + pGC->tileIsPixel = FALSE; + pGC->tile.pixmap = pPixmap; + } + break; + case GCStipple: + NEXT_PTR(PixmapPtr, pPixmap); + if ((pPixmap->drawable.depth != 1) || + (pPixmap->drawable.pScreen != pGC->pScreen)) + { + error = BadMatch; + } + else + { + pPixmap->refcnt++; + if (pGC->stipple) + (* pGC->pScreen->DestroyPixmap)(pGC->stipple); + pGC->stipple = pPixmap; + } + break; + case GCTileStipXOrigin: + NEXTVAL(INT16, pGC->patOrg.x); + break; + case GCTileStipYOrigin: + NEXTVAL(INT16, pGC->patOrg.y); + break; + case GCFont: + { + FontPtr pFont; + NEXT_PTR(FontPtr, pFont); + pFont->refcnt++; + if (pGC->font) + CloseFont(pGC->font, (Font)0); + pGC->font = pFont; + break; + } + case GCSubwindowMode: + { + unsigned int newclipmode; + NEXTVAL(unsigned int, newclipmode); + if (newclipmode <= IncludeInferiors) + pGC->subWindowMode = newclipmode; + else + { + if (client) + client->errorValue = newclipmode; + error = BadValue; + } + break; + } + case GCGraphicsExposures: + { + unsigned int newge; + NEXTVAL(unsigned int, newge); + if (newge <= xTrue) + pGC->graphicsExposures = newge; + else + { + if (client) + client->errorValue = newge; + error = BadValue; + } + break; + } + case GCClipXOrigin: + NEXTVAL(INT16, pGC->clipOrg.x); + break; + case GCClipYOrigin: + NEXTVAL(INT16, pGC->clipOrg.y); + break; + case GCClipMask: + NEXT_PTR(PixmapPtr, pPixmap); + if (pPixmap) + { + if ((pPixmap->drawable.depth != 1) || + (pPixmap->drawable.pScreen != pGC->pScreen)) + { + error = BadMatch; + break; + } + pPixmap->refcnt++; + } + (*pGC->funcs->ChangeClip)(pGC, pPixmap ? CT_PIXMAP : CT_NONE, + (pointer)pPixmap, 0); + break; + case GCDashOffset: + NEXTVAL(INT16, pGC->dashOffset); + break; + case GCDashList: + { + CARD8 newdash; + NEXTVAL(CARD8, newdash); + if (newdash == 4) + { + if (pGC->dash != DefaultDash) + { + free(pGC->dash); + pGC->numInDashList = 2; + pGC->dash = DefaultDash; + } + } + else if (newdash != 0) + { + unsigned char *dash; + + dash = malloc(2 * sizeof(unsigned char)); + if (dash) + { + if (pGC->dash != DefaultDash) + free(pGC->dash); + pGC->numInDashList = 2; + pGC->dash = dash; + dash[0] = newdash; + dash[1] = newdash; + } + else + error = BadAlloc; + } + else + { + if (client) + client->errorValue = newdash; + error = BadValue; + } + break; + } + case GCArcMode: + { + unsigned int newarcmode; + NEXTVAL(unsigned int, newarcmode); + if (newarcmode <= ArcPieSlice) + pGC->arcMode = newarcmode; + else + { + if (client) + client->errorValue = newarcmode; + error = BadValue; + } + break; + } + default: + if (client) + client->errorValue = maskQ; + error = BadValue; + break; + } + } /* end while mask && !error */ + + if (pGC->fillStyle == FillTiled && pGC->tileIsPixel) + { + if (!CreateDefaultTile (pGC)) + { + pGC->fillStyle = FillSolid; + error = BadAlloc; + } + } + (*pGC->funcs->ChangeGC)(pGC, maskQ); + return error; +} + +#undef NEXTVAL +#undef NEXT_PTR + +static const struct { + BITS32 mask; + RESTYPE type; + Mask access_mode; +} xidfields[] = { + { GCTile, RT_PIXMAP, DixReadAccess }, + { GCStipple, RT_PIXMAP, DixReadAccess }, + { GCFont, RT_FONT, DixUseAccess }, + { GCClipMask, RT_PIXMAP, DixReadAccess }, +}; + +int +ChangeGCXIDs(ClientPtr client, GC *pGC, BITS32 mask, CARD32 *pC32) +{ + ChangeGCVal vals[GCLastBit + 1]; + int i; + if (mask & ~GCAllBits) + { + client->errorValue = mask; + return BadValue; + } + for (i = Ones(mask); i--; ) + vals[i].val = pC32[i]; + for (i = 0; i < sizeof(xidfields) / sizeof(*xidfields); ++i) + { + int offset, rc; + if (!(mask & xidfields[i].mask)) + continue; + offset = Ones(mask & (xidfields[i].mask - 1)); + if (xidfields[i].mask == GCClipMask && vals[offset].val == None) + { + vals[offset].ptr = NullPixmap; + continue; + } + rc = dixLookupResourceByType(&vals[offset].ptr, vals[offset].val, + xidfields[i].type, client, xidfields[i].access_mode); + if (rc != Success) + { + client->errorValue = vals[offset].val; + if (rc == BadValue) + rc = (xidfields[i].type == RT_PIXMAP) ? BadPixmap : BadFont; + return rc; + } + } + return ChangeGC(client, pGC, mask, vals); +} + +/* CreateGC(pDrawable, mask, pval, pStatus) + creates a default GC for the given drawable, using mask to fill + in any non-default values. + Returns a pointer to the new GC on success, NULL otherwise. + returns status of non-default fields in pStatus +BUG: + should check for failure to create default tile + +*/ +GCPtr +CreateGC(DrawablePtr pDrawable, BITS32 mask, XID *pval, int *pStatus, + XID gcid, ClientPtr client) +{ + GCPtr pGC; + + pGC = malloc(sizeof(GC)); + if (!pGC) + { + *pStatus = BadAlloc; + return (GCPtr)NULL; + } + + pGC->pScreen = pDrawable->pScreen; + pGC->depth = pDrawable->depth; + pGC->alu = GXcopy; /* dst <- src */ + pGC->planemask = ~0; + pGC->serialNumber = GC_CHANGE_SERIAL_BIT; + pGC->funcs = 0; + pGC->devPrivates = NULL; + pGC->fgPixel = 0; + pGC->bgPixel = 1; + pGC->lineWidth = 0; + pGC->lineStyle = LineSolid; + pGC->capStyle = CapButt; + pGC->joinStyle = JoinMiter; + pGC->fillStyle = FillSolid; + pGC->fillRule = EvenOddRule; + pGC->arcMode = ArcPieSlice; + pGC->tile.pixel = 0; + pGC->tile.pixmap = NullPixmap; + if (mask & GCForeground) + { + /* + * magic special case -- ChangeGC checks for this condition + * and snags the Foreground value to create a pseudo default-tile + */ + pGC->tileIsPixel = FALSE; + } + else + { + pGC->tileIsPixel = TRUE; + } + + pGC->patOrg.x = 0; + pGC->patOrg.y = 0; + pGC->subWindowMode = ClipByChildren; + pGC->graphicsExposures = TRUE; + pGC->clipOrg.x = 0; + pGC->clipOrg.y = 0; + pGC->clientClipType = CT_NONE; + pGC->clientClip = (pointer)NULL; + pGC->numInDashList = 2; + pGC->dash = DefaultDash; + pGC->dashOffset = 0; + pGC->lastWinOrg.x = 0; + pGC->lastWinOrg.y = 0; + + /* use the default font and stipple */ + pGC->font = defaultFont; + defaultFont->refcnt++; + pGC->stipple = pGC->pScreen->PixmapPerDepth[0]; + pGC->stipple->refcnt++; + + /* security creation/labeling check */ + *pStatus = XaceHook(XACE_RESOURCE_ACCESS, client, gcid, RT_GC, pGC, + RT_NONE, NULL, DixCreateAccess|DixSetAttrAccess); + if (*pStatus != Success) + goto out; + + pGC->stateChanges = GCAllBits; + if (!(*pGC->pScreen->CreateGC)(pGC)) + *pStatus = BadAlloc; + else if (mask) + *pStatus = ChangeGCXIDs(client, pGC, mask, pval); + else + *pStatus = Success; + +out: + if (*pStatus != Success) + { + if (!pGC->tileIsPixel && !pGC->tile.pixmap) + pGC->tileIsPixel = TRUE; /* undo special case */ + FreeGC(pGC, (XID)0); + pGC = (GCPtr)NULL; + } + + return (pGC); +} + +static Bool +CreateDefaultTile (GCPtr pGC) +{ + ChangeGCVal tmpval[3]; + PixmapPtr pTile; + GCPtr pgcScratch; + xRectangle rect; + CARD16 w, h; + + w = 1; + h = 1; + (*pGC->pScreen->QueryBestSize)(TileShape, &w, &h, pGC->pScreen); + pTile = (PixmapPtr) + (*pGC->pScreen->CreatePixmap)(pGC->pScreen, + w, h, pGC->depth, 0); + pgcScratch = GetScratchGC(pGC->depth, pGC->pScreen); + if (!pTile || !pgcScratch) + { + if (pTile) + (*pTile->drawable.pScreen->DestroyPixmap)(pTile); + if (pgcScratch) + FreeScratchGC(pgcScratch); + return FALSE; + } + tmpval[0].val = GXcopy; + tmpval[1].val = pGC->tile.pixel; + tmpval[2].val = FillSolid; + (void)ChangeGC(NullClient, pgcScratch, GCFunction | GCForeground | GCFillStyle, tmpval); + ValidateGC((DrawablePtr)pTile, pgcScratch); + rect.x = 0; + rect.y = 0; + rect.width = w; + rect.height = h; + (*pgcScratch->ops->PolyFillRect)((DrawablePtr)pTile, pgcScratch, 1, &rect); + /* Always remember to free the scratch graphics context after use. */ + FreeScratchGC(pgcScratch); + + pGC->tileIsPixel = FALSE; + pGC->tile.pixmap = pTile; + return TRUE; +} + +int +CopyGC(GC *pgcSrc, GC *pgcDst, BITS32 mask) +{ + BITS32 index2; + BITS32 maskQ; + int error = 0; + + if (pgcSrc == pgcDst) + return Success; + pgcDst->serialNumber |= GC_CHANGE_SERIAL_BIT; + pgcDst->stateChanges |= mask; + maskQ = mask; + while (mask) + { + index2 = (BITS32) lowbit (mask); + mask &= ~index2; + switch (index2) + { + case GCFunction: + pgcDst->alu = pgcSrc->alu; + break; + case GCPlaneMask: + pgcDst->planemask = pgcSrc->planemask; + break; + case GCForeground: + pgcDst->fgPixel = pgcSrc->fgPixel; + break; + case GCBackground: + pgcDst->bgPixel = pgcSrc->bgPixel; + break; + case GCLineWidth: + pgcDst->lineWidth = pgcSrc->lineWidth; + break; + case GCLineStyle: + pgcDst->lineStyle = pgcSrc->lineStyle; + break; + case GCCapStyle: + pgcDst->capStyle = pgcSrc->capStyle; + break; + case GCJoinStyle: + pgcDst->joinStyle = pgcSrc->joinStyle; + break; + case GCFillStyle: + pgcDst->fillStyle = pgcSrc->fillStyle; + break; + case GCFillRule: + pgcDst->fillRule = pgcSrc->fillRule; + break; + case GCTile: + { + if (EqualPixUnion(pgcDst->tileIsPixel, + pgcDst->tile, + pgcSrc->tileIsPixel, + pgcSrc->tile)) + { + break; + } + if (!pgcDst->tileIsPixel) + (* pgcDst->pScreen->DestroyPixmap)(pgcDst->tile.pixmap); + pgcDst->tileIsPixel = pgcSrc->tileIsPixel; + pgcDst->tile = pgcSrc->tile; + if (!pgcDst->tileIsPixel) + pgcDst->tile.pixmap->refcnt++; + break; + } + case GCStipple: + { + if (pgcDst->stipple == pgcSrc->stipple) + break; + if (pgcDst->stipple) + (* pgcDst->pScreen->DestroyPixmap)(pgcDst->stipple); + pgcDst->stipple = pgcSrc->stipple; + if (pgcDst->stipple) + pgcDst->stipple->refcnt ++; + break; + } + case GCTileStipXOrigin: + pgcDst->patOrg.x = pgcSrc->patOrg.x; + break; + case GCTileStipYOrigin: + pgcDst->patOrg.y = pgcSrc->patOrg.y; + break; + case GCFont: + if (pgcDst->font == pgcSrc->font) + break; + if (pgcDst->font) + CloseFont(pgcDst->font, (Font)0); + if ((pgcDst->font = pgcSrc->font) != NullFont) + (pgcDst->font)->refcnt++; + break; + case GCSubwindowMode: + pgcDst->subWindowMode = pgcSrc->subWindowMode; + break; + case GCGraphicsExposures: + pgcDst->graphicsExposures = pgcSrc->graphicsExposures; + break; + case GCClipXOrigin: + pgcDst->clipOrg.x = pgcSrc->clipOrg.x; + break; + case GCClipYOrigin: + pgcDst->clipOrg.y = pgcSrc->clipOrg.y; + break; + case GCClipMask: + (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc); + break; + case GCDashOffset: + pgcDst->dashOffset = pgcSrc->dashOffset; + break; + case GCDashList: + if (pgcSrc->dash == DefaultDash) + { + if (pgcDst->dash != DefaultDash) + { + free(pgcDst->dash); + pgcDst->numInDashList = pgcSrc->numInDashList; + pgcDst->dash = pgcSrc->dash; + } + } + else + { + unsigned char *dash; + unsigned int i; + + dash = malloc(pgcSrc->numInDashList * sizeof(unsigned char)); + if (dash) + { + if (pgcDst->dash != DefaultDash) + free(pgcDst->dash); + pgcDst->numInDashList = pgcSrc->numInDashList; + pgcDst->dash = dash; + for (i=0; inumInDashList; i++) + dash[i] = pgcSrc->dash[i]; + } + else + error = BadAlloc; + } + break; + case GCArcMode: + pgcDst->arcMode = pgcSrc->arcMode; + break; + default: + FatalError ("CopyGC: Unhandled mask!\n"); + } + } + if (pgcDst->fillStyle == FillTiled && pgcDst->tileIsPixel) + { + if (!CreateDefaultTile (pgcDst)) + { + pgcDst->fillStyle = FillSolid; + error = BadAlloc; + } + } + (*pgcDst->funcs->CopyGC) (pgcSrc, maskQ, pgcDst); + return error; +} + +/** + * does the diX part of freeing the characteristics in the GC. + * + * \param value must conform to DeleteType + */ +int +FreeGC(pointer value, XID gid) +{ + GCPtr pGC = (GCPtr)value; + + CloseFont(pGC->font, (Font)0); + (* pGC->funcs->DestroyClip)(pGC); + + if (!pGC->tileIsPixel) + (* pGC->pScreen->DestroyPixmap)(pGC->tile.pixmap); + if (pGC->stipple) + (* pGC->pScreen->DestroyPixmap)(pGC->stipple); + + (*pGC->funcs->DestroyGC) (pGC); + if (pGC->dash != DefaultDash) + free(pGC->dash); + dixFreePrivates(pGC->devPrivates); + free(pGC); + return(Success); +} + +/* CreateScratchGC(pScreen, depth) + like CreateGC, but doesn't do the default tile or stipple, +since we can't create them without already having a GC. any code +using the tile or stipple has to set them explicitly anyway, +since the state of the scratch gc is unknown. This is OK +because ChangeGC() has to be able to deal with NULL tiles and +stipples anyway (in case the CreateGC() call has provided a +value for them -- we can't set the default tile until the +client-supplied attributes are installed, since the fgPixel +is what fills the default tile. (maybe this comment should +go with CreateGC() or ChangeGC().) +*/ + +GCPtr +CreateScratchGC(ScreenPtr pScreen, unsigned depth) +{ + GCPtr pGC; + + pGC = malloc(sizeof(GC)); + if (!pGC) + return (GCPtr)NULL; + + pGC->pScreen = pScreen; + pGC->depth = depth; + pGC->alu = GXcopy; /* dst <- src */ + pGC->planemask = ~0; + pGC->serialNumber = 0; + pGC->devPrivates = NULL; + pGC->fgPixel = 0; + pGC->bgPixel = 1; + pGC->lineWidth = 0; + pGC->lineStyle = LineSolid; + pGC->capStyle = CapButt; + pGC->joinStyle = JoinMiter; + pGC->fillStyle = FillSolid; + pGC->fillRule = EvenOddRule; + pGC->arcMode = ArcPieSlice; + pGC->font = defaultFont; + if ( pGC->font) /* necessary, because open of default font could fail */ + pGC->font->refcnt++; + pGC->tileIsPixel = TRUE; + pGC->tile.pixel = 0; + pGC->tile.pixmap = NullPixmap; + pGC->stipple = NullPixmap; + pGC->patOrg.x = 0; + pGC->patOrg.y = 0; + pGC->subWindowMode = ClipByChildren; + pGC->graphicsExposures = TRUE; + pGC->clipOrg.x = 0; + pGC->clipOrg.y = 0; + pGC->clientClipType = CT_NONE; + pGC->dashOffset = 0; + pGC->numInDashList = 2; + pGC->dash = DefaultDash; + pGC->lastWinOrg.x = 0; + pGC->lastWinOrg.y = 0; + + pGC->stateChanges = GCAllBits; + if (!(*pScreen->CreateGC)(pGC)) + { + FreeGC(pGC, (XID)0); + pGC = (GCPtr)NULL; + } + return pGC; +} + +void +FreeGCperDepth(int screenNum) +{ + int i; + ScreenPtr pScreen; + GCPtr *ppGC; + + pScreen = screenInfo.screens[screenNum]; + ppGC = pScreen->GCperDepth; + + for (i = 0; i <= pScreen->numDepths; i++) + (void)FreeGC(ppGC[i], (XID)0); + pScreen->rgf = ~0L; +} + + +Bool +CreateGCperDepth(int screenNum) +{ + int i; + ScreenPtr pScreen; + DepthPtr pDepth; + GCPtr *ppGC; + + pScreen = screenInfo.screens[screenNum]; + pScreen->rgf = 0; + ppGC = pScreen->GCperDepth; + /* do depth 1 separately because it's not included in list */ + if (!(ppGC[0] = CreateScratchGC(pScreen, 1))) + return FALSE; + ppGC[0]->graphicsExposures = FALSE; + /* Make sure we don't overflow GCperDepth[] */ + if( pScreen->numDepths > MAXFORMATS ) + return FALSE; + + pDepth = pScreen->allowedDepths; + for (i=0; inumDepths; i++, pDepth++) + { + if (!(ppGC[i+1] = CreateScratchGC(pScreen, pDepth->depth))) + { + for (; i >= 0; i--) + (void)FreeGC(ppGC[i], (XID)0); + return FALSE; + } + ppGC[i+1]->graphicsExposures = FALSE; + } + return TRUE; +} + +Bool +CreateDefaultStipple(int screenNum) +{ + ScreenPtr pScreen; + ChangeGCVal tmpval[3]; + xRectangle rect; + CARD16 w, h; + GCPtr pgcScratch; + + pScreen = screenInfo.screens[screenNum]; + + w = 16; + h = 16; + (* pScreen->QueryBestSize)(StippleShape, &w, &h, pScreen); + if (!(pScreen->PixmapPerDepth[0] = + (*pScreen->CreatePixmap)(pScreen, w, h, 1, 0))) + return FALSE; + /* fill stipple with 1 */ + tmpval[0].val = GXcopy; + tmpval[1].val = 1; + tmpval[2].val = FillSolid; + pgcScratch = GetScratchGC(1, pScreen); + if (!pgcScratch) + { + (*pScreen->DestroyPixmap)(pScreen->PixmapPerDepth[0]); + return FALSE; + } + (void)ChangeGC(NullClient, pgcScratch, GCFunction|GCForeground|GCFillStyle, tmpval); + ValidateGC((DrawablePtr)pScreen->PixmapPerDepth[0], pgcScratch); + rect.x = 0; + rect.y = 0; + rect.width = w; + rect.height = h; + (*pgcScratch->ops->PolyFillRect)((DrawablePtr)pScreen->PixmapPerDepth[0], + pgcScratch, 1, &rect); + FreeScratchGC(pgcScratch); + return TRUE; +} + +void +FreeDefaultStipple(int screenNum) +{ + ScreenPtr pScreen = screenInfo.screens[screenNum]; + (*pScreen->DestroyPixmap)(pScreen->PixmapPerDepth[0]); +} + +int +SetDashes(GCPtr pGC, unsigned offset, unsigned ndash, unsigned char *pdash) +{ + long i; + unsigned char *p, *indash; + BITS32 maskQ = 0; + + i = ndash; + p = pdash; + while (i--) + { + if (!*p++) + { + /* dash segment must be > 0 */ + return BadValue; + } + } + + if (ndash & 1) + p = malloc(2 * ndash * sizeof(unsigned char)); + else + p = malloc(ndash * sizeof(unsigned char)); + if (!p) + return BadAlloc; + + pGC->serialNumber |= GC_CHANGE_SERIAL_BIT; + if (offset != pGC->dashOffset) + { + pGC->dashOffset = offset; + pGC->stateChanges |= GCDashOffset; + maskQ |= GCDashOffset; + } + + if (pGC->dash != DefaultDash) + free(pGC->dash); + pGC->numInDashList = ndash; + pGC->dash = p; + if (ndash & 1) + { + pGC->numInDashList += ndash; + indash = pdash; + i = ndash; + while (i--) + *p++ = *indash++; + } + while(ndash--) + *p++ = *pdash++; + pGC->stateChanges |= GCDashList; + maskQ |= GCDashList; + + if (pGC->funcs->ChangeGC) + (*pGC->funcs->ChangeGC) (pGC, maskQ); + return Success; +} + +int +VerifyRectOrder(int nrects, xRectangle *prects, int ordering) +{ + xRectangle *prectP, *prectN; + int i; + + switch(ordering) + { + case Unsorted: + return CT_UNSORTED; + case YSorted: + if(nrects > 1) + { + for(i = 1, prectP = prects, prectN = prects + 1; + i < nrects; + i++, prectP++, prectN++) + if(prectN->y < prectP->y) + return -1; + } + return CT_YSORTED; + case YXSorted: + if(nrects > 1) + { + for(i = 1, prectP = prects, prectN = prects + 1; + i < nrects; + i++, prectP++, prectN++) + if((prectN->y < prectP->y) || + ( (prectN->y == prectP->y) && + (prectN->x < prectP->x) ) ) + return -1; + } + return CT_YXSORTED; + case YXBanded: + if(nrects > 1) + { + for(i = 1, prectP = prects, prectN = prects + 1; + i < nrects; + i++, prectP++, prectN++) + if((prectN->y != prectP->y && + prectN->y < prectP->y + (int) prectP->height) || + ((prectN->y == prectP->y) && + (prectN->height != prectP->height || + prectN->x < prectP->x + (int) prectP->width))) + return -1; + } + return CT_YXBANDED; + } + return -1; +} + +int +SetClipRects(GCPtr pGC, int xOrigin, int yOrigin, int nrects, + xRectangle *prects, int ordering) +{ + int newct, size; + xRectangle *prectsNew; + + newct = VerifyRectOrder(nrects, prects, ordering); + if (newct < 0) + return(BadMatch); + size = nrects * sizeof(xRectangle); + prectsNew = malloc(size); + if (!prectsNew && size) + return BadAlloc; + + pGC->serialNumber |= GC_CHANGE_SERIAL_BIT; + pGC->clipOrg.x = xOrigin; + pGC->stateChanges |= GCClipXOrigin; + + pGC->clipOrg.y = yOrigin; + pGC->stateChanges |= GCClipYOrigin; + + if (size) + memmove((char *)prectsNew, (char *)prects, size); + (*pGC->funcs->ChangeClip)(pGC, newct, (pointer)prectsNew, nrects); + if (pGC->funcs->ChangeGC) + (*pGC->funcs->ChangeGC) (pGC, GCClipXOrigin|GCClipYOrigin|GCClipMask); + return Success; +} + + +/* + sets reasonable defaults + if we can get a pre-allocated one, use it and mark it as used. + if we can't, create one out of whole cloth (The Velveteen GC -- if + you use it often enough it will become real.) +*/ +GCPtr +GetScratchGC(unsigned depth, ScreenPtr pScreen) +{ + int i; + GCPtr pGC; + + for (i=0; i<=pScreen->numDepths; i++) + if ( pScreen->GCperDepth[i]->depth == depth && + !(pScreen->rgf & (1L << (i+1))) + ) + { + pScreen->rgf |= (1L << (i+1)); + pGC = (pScreen->GCperDepth[i]); + + pGC->alu = GXcopy; + pGC->planemask = ~0; + pGC->serialNumber = 0; + pGC->fgPixel = 0; + pGC->bgPixel = 1; + pGC->lineWidth = 0; + pGC->lineStyle = LineSolid; + pGC->capStyle = CapButt; + pGC->joinStyle = JoinMiter; + pGC->fillStyle = FillSolid; + pGC->fillRule = EvenOddRule; + pGC->arcMode = ArcChord; + pGC->patOrg.x = 0; + pGC->patOrg.y = 0; + pGC->subWindowMode = ClipByChildren; + pGC->graphicsExposures = FALSE; + pGC->clipOrg.x = 0; + pGC->clipOrg.y = 0; + if (pGC->clientClipType != CT_NONE) + (*pGC->funcs->ChangeClip) (pGC, CT_NONE, NULL, 0); + pGC->stateChanges = GCAllBits; + return pGC; + } + /* if we make it this far, need to roll our own */ + pGC = CreateScratchGC(pScreen, depth); + if (pGC) + pGC->graphicsExposures = FALSE; + return pGC; +} + +/* + if the gc to free is in the table of pre-existing ones, +mark it as available. + if not, free it for real +*/ +void +FreeScratchGC(GCPtr pGC) +{ + ScreenPtr pScreen = pGC->pScreen; + int i; + + for (i=0; i<=pScreen->numDepths; i++) + { + if ( pScreen->GCperDepth[i] == pGC) + { + pScreen->rgf &= ~(1L << (i+1)); + return; + } + } + (void)FreeGC(pGC, (GContext)0); +} diff --git a/xorg-server/hw/xfree86/common/Makefile.am b/xorg-server/hw/xfree86/common/Makefile.am index ad27210cd..821a2b500 100644 --- a/xorg-server/hw/xfree86/common/Makefile.am +++ b/xorg-server/hw/xfree86/common/Makefile.am @@ -41,6 +41,7 @@ libcommon_la_SOURCES = xf86Configure.c xf86ShowOpts.c xf86Bus.c xf86Config.c \ xf86Mode.c xorgHelper.c \ $(XVSOURCES) $(BUSSOURCES) $(RANDRSOURCES) nodist_libcommon_la_SOURCES = xf86DefModeSet.c xf86Build.h +libcommon_la_LIBADD = $(top_builddir)/config/libconfig.la INCLUDES = $(XORG_INCS) -I$(srcdir)/../ddc -I$(srcdir)/../i2c \ -I$(srcdir)/../loader -I$(srcdir)/../parser \ diff --git a/xorg-server/hw/xfree86/dri2/dri2.c b/xorg-server/hw/xfree86/dri2/dri2.c index 64be079ca..29c917f21 100644 --- a/xorg-server/hw/xfree86/dri2/dri2.c +++ b/xorg-server/hw/xfree86/dri2/dri2.c @@ -1,1138 +1,1140 @@ -/* - * Copyright © 2007, 2008 Red Hat, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Soft- - * ware"), to deal in the Software without restriction, including without - * limitation the rights to use, copy, modify, merge, publish, distribute, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, provided that the above copyright - * notice(s) and this permission notice appear in all copies of the Soft- - * ware and that both the above copyright notice(s) and this permission - * notice appear in supporting documentation. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- - * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY - * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN - * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE- - * QUENTIAL 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 PERFOR- - * MANCE OF THIS SOFTWARE. - * - * Except as contained in this notice, the name of a copyright holder shall - * not be used in advertising or otherwise to promote the sale, use or - * other dealings in this Software without prior written authorization of - * the copyright holder. - * - * Authors: - * Kristian Høgsberg (krh@redhat.com) - */ - -#ifdef HAVE_XORG_CONFIG_H -#include -#endif - -#include -#include -#include "xf86Module.h" -#include "list.h" -#include "scrnintstr.h" -#include "windowstr.h" -#include "dixstruct.h" -#include "dri2.h" -#include "xf86VGAarbiter.h" - -#include "xf86.h" - -CARD8 dri2_major; /* version of DRI2 supported by DDX */ -CARD8 dri2_minor; - -static int dri2ScreenPrivateKeyIndex; -static DevPrivateKey dri2ScreenPrivateKey = &dri2ScreenPrivateKeyIndex; -static int dri2WindowPrivateKeyIndex; -static DevPrivateKey dri2WindowPrivateKey = &dri2WindowPrivateKeyIndex; -static int dri2PixmapPrivateKeyIndex; -static DevPrivateKey dri2PixmapPrivateKey = &dri2PixmapPrivateKeyIndex; -static RESTYPE dri2DrawableRes; - -typedef struct _DRI2Screen *DRI2ScreenPtr; - -typedef struct _DRI2Drawable { - DRI2ScreenPtr dri2_screen; - DrawablePtr drawable; - struct list reference_list; - int width; - int height; - DRI2BufferPtr *buffers; - int bufferCount; - unsigned int swapsPending; - ClientPtr blockedClient; - Bool blockedOnMsc; - int swap_interval; - CARD64 swap_count; - int64_t target_sbc; /* -1 means no SBC wait outstanding */ - CARD64 last_swap_target; /* most recently queued swap target */ - CARD64 last_swap_msc; /* msc at completion of most recent swap */ - CARD64 last_swap_ust; /* ust at completion of most recent swap */ - int swap_limit; /* for N-buffering */ -} DRI2DrawableRec, *DRI2DrawablePtr; - -typedef struct _DRI2Screen { - ScreenPtr screen; - int refcnt; - unsigned int numDrivers; - const char **driverNames; - const char *deviceName; - int fd; - unsigned int lastSequence; - - DRI2CreateBufferProcPtr CreateBuffer; - DRI2DestroyBufferProcPtr DestroyBuffer; - DRI2CopyRegionProcPtr CopyRegion; - DRI2ScheduleSwapProcPtr ScheduleSwap; - DRI2GetMSCProcPtr GetMSC; - DRI2ScheduleWaitMSCProcPtr ScheduleWaitMSC; - - HandleExposuresProcPtr HandleExposures; - - ConfigNotifyProcPtr ConfigNotify; -} DRI2ScreenRec; - -static DRI2ScreenPtr -DRI2GetScreen(ScreenPtr pScreen) -{ - return dixLookupPrivate(&pScreen->devPrivates, dri2ScreenPrivateKey); -} - -static DRI2DrawablePtr -DRI2GetDrawable(DrawablePtr pDraw) -{ - WindowPtr pWin; - PixmapPtr pPixmap; - - if (pDraw->type == DRAWABLE_WINDOW) { - pWin = (WindowPtr) pDraw; - return dixLookupPrivate(&pWin->devPrivates, dri2WindowPrivateKey); - } else { - pPixmap = (PixmapPtr) pDraw; - return dixLookupPrivate(&pPixmap->devPrivates, dri2PixmapPrivateKey); - } -} - -static DRI2DrawablePtr -DRI2AllocateDrawable(DrawablePtr pDraw) -{ - DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen); - DRI2DrawablePtr pPriv; - CARD64 ust; - WindowPtr pWin; - PixmapPtr pPixmap; - - pPriv = malloc(sizeof *pPriv); - if (pPriv == NULL) - return NULL; - - pPriv->dri2_screen = ds; - pPriv->drawable = pDraw; - pPriv->width = pDraw->width; - pPriv->height = pDraw->height; - pPriv->buffers = NULL; - pPriv->bufferCount = 0; - pPriv->swapsPending = 0; - pPriv->blockedClient = NULL; - pPriv->blockedOnMsc = FALSE; - pPriv->swap_count = 0; - pPriv->target_sbc = -1; - pPriv->swap_interval = 1; - /* Initialize last swap target from DDX if possible */ - if (!ds->GetMSC || !(*ds->GetMSC)(pDraw, &ust, &pPriv->last_swap_target)) - pPriv->last_swap_target = 0; - - pPriv->swap_limit = 1; /* default to double buffering */ - pPriv->last_swap_msc = 0; - pPriv->last_swap_ust = 0; - list_init(&pPriv->reference_list); - - if (pDraw->type == DRAWABLE_WINDOW) { - pWin = (WindowPtr) pDraw; - dixSetPrivate(&pWin->devPrivates, dri2WindowPrivateKey, pPriv); - } else { - pPixmap = (PixmapPtr) pDraw; - dixSetPrivate(&pPixmap->devPrivates, dri2PixmapPrivateKey, pPriv); - } - - return pPriv; -} - -typedef struct DRI2DrawableRefRec { - XID id; - XID dri2_id; - DRI2InvalidateProcPtr invalidate; - void *priv; - struct list link; -} DRI2DrawableRefRec, *DRI2DrawableRefPtr; - -static DRI2DrawableRefPtr -DRI2LookupDrawableRef(DRI2DrawablePtr pPriv, XID id) -{ - DRI2DrawableRefPtr ref; - - list_for_each_entry(ref, &pPriv->reference_list, link) { - if (ref->id == id) - return ref; - } - - return NULL; -} - -static int -DRI2AddDrawableRef(DRI2DrawablePtr pPriv, XID id, XID dri2_id, - DRI2InvalidateProcPtr invalidate, void *priv) -{ - DRI2DrawableRefPtr ref; - - ref = malloc(sizeof *ref); - if (ref == NULL) - return BadAlloc; - - if (!AddResource(dri2_id, dri2DrawableRes, pPriv)) - return BadAlloc; - if (!DRI2LookupDrawableRef(pPriv, id)) - if (!AddResource(id, dri2DrawableRes, pPriv)) - return BadAlloc; - - ref->id = id; - ref->dri2_id = dri2_id; - ref->invalidate = invalidate; - ref->priv = priv; - list_add(&ref->link, &pPriv->reference_list); - - return Success; -} - -int -DRI2CreateDrawable(ClientPtr client, DrawablePtr pDraw, XID id, - DRI2InvalidateProcPtr invalidate, void *priv) -{ - DRI2DrawablePtr pPriv; - XID dri2_id; - int rc; - - pPriv = DRI2GetDrawable(pDraw); - if (pPriv == NULL) - pPriv = DRI2AllocateDrawable(pDraw); - if (pPriv == NULL) - return BadAlloc; - - dri2_id = FakeClientID(client->index); - rc = DRI2AddDrawableRef(pPriv, id, dri2_id, invalidate, priv); - if (rc != Success) - return rc; - - return Success; -} - -static int DRI2DrawableGone(pointer p, XID id) -{ - DRI2DrawablePtr pPriv = p; - DRI2ScreenPtr ds = pPriv->dri2_screen; - DRI2DrawableRefPtr ref, next; - WindowPtr pWin; - PixmapPtr pPixmap; - DrawablePtr pDraw; - int i; - - list_for_each_entry_safe(ref, next, &pPriv->reference_list, link) { - if (ref->dri2_id == id) { - list_del(&ref->link); - /* If this was the last ref under this X drawable XID, - * unregister the X drawable resource. */ - if (!DRI2LookupDrawableRef(pPriv, ref->id)) - FreeResourceByType(ref->id, dri2DrawableRes, TRUE); - free(ref); - break; - } - - if (ref->id == id) { - list_del(&ref->link); - FreeResourceByType(ref->dri2_id, dri2DrawableRes, TRUE); - free(ref); - } - } - - if (!list_is_empty(&pPriv->reference_list)) - return Success; - - pDraw = pPriv->drawable; - if (pDraw->type == DRAWABLE_WINDOW) { - pWin = (WindowPtr) pDraw; - dixSetPrivate(&pWin->devPrivates, dri2WindowPrivateKey, NULL); - } else { - pPixmap = (PixmapPtr) pDraw; - dixSetPrivate(&pPixmap->devPrivates, dri2PixmapPrivateKey, NULL); - } - - if (pPriv->buffers != NULL) { - for (i = 0; i < pPriv->bufferCount; i++) - (*ds->DestroyBuffer)(pDraw, pPriv->buffers[i]); - - free(pPriv->buffers); - } - - free(pPriv); - - return Success; -} - -static int -find_attachment(DRI2DrawablePtr pPriv, unsigned attachment) -{ - int i; - - if (pPriv->buffers == NULL) { - return -1; - } - - for (i = 0; i < pPriv->bufferCount; i++) { - if ((pPriv->buffers[i] != NULL) - && (pPriv->buffers[i]->attachment == attachment)) { - return i; - } - } - - return -1; -} - -static Bool -allocate_or_reuse_buffer(DrawablePtr pDraw, DRI2ScreenPtr ds, - DRI2DrawablePtr pPriv, - unsigned int attachment, unsigned int format, - int dimensions_match, DRI2BufferPtr *buffer) -{ - int old_buf = find_attachment(pPriv, attachment); - - if ((old_buf < 0) - || !dimensions_match - || (pPriv->buffers[old_buf]->format != format)) { - *buffer = (*ds->CreateBuffer)(pDraw, attachment, format); - return TRUE; - - } else { - *buffer = pPriv->buffers[old_buf]; - pPriv->buffers[old_buf] = NULL; - return FALSE; - } -} - -static void -update_dri2_drawable_buffers(DRI2DrawablePtr pPriv, DrawablePtr pDraw, - DRI2BufferPtr *buffers, int *out_count, int *width, int *height) -{ - DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen); - int i; - - if (pPriv->buffers != NULL) { - for (i = 0; i < pPriv->bufferCount; i++) { - if (pPriv->buffers[i] != NULL) { - (*ds->DestroyBuffer)(pDraw, pPriv->buffers[i]); - } - } - - free(pPriv->buffers); - } - - pPriv->buffers = buffers; - pPriv->bufferCount = *out_count; - pPriv->width = pDraw->width; - pPriv->height = pDraw->height; - *width = pPriv->width; - *height = pPriv->height; -} - -static DRI2BufferPtr * -do_get_buffers(DrawablePtr pDraw, int *width, int *height, - unsigned int *attachments, int count, int *out_count, - int has_format) -{ - DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen); - DRI2DrawablePtr pPriv = DRI2GetDrawable(pDraw); - DRI2BufferPtr *buffers; - int need_real_front = 0; - int need_fake_front = 0; - int have_fake_front = 0; - int front_format = 0; - int dimensions_match; - int buffers_changed = 0; - int i; - - if (!pPriv) { - *width = pDraw->width; - *height = pDraw->height; - *out_count = 0; - return NULL; - } - - dimensions_match = (pDraw->width == pPriv->width) - && (pDraw->height == pPriv->height); - - buffers = malloc((count + 1) * sizeof(buffers[0])); - - for (i = 0; i < count; i++) { - const unsigned attachment = *(attachments++); - const unsigned format = (has_format) ? *(attachments++) : 0; - - if (allocate_or_reuse_buffer(pDraw, ds, pPriv, attachment, - format, dimensions_match, - &buffers[i])) - buffers_changed = 1; - - if (buffers[i] == NULL) - goto err_out; - - /* If the drawable is a window and the front-buffer is requested, - * silently add the fake front-buffer to the list of requested - * attachments. The counting logic in the loop accounts for the case - * where the client requests both the fake and real front-buffer. - */ - if (attachment == DRI2BufferBackLeft) { - need_real_front++; - front_format = format; - } - - if (attachment == DRI2BufferFrontLeft) { - need_real_front--; - front_format = format; - - if (pDraw->type == DRAWABLE_WINDOW) { - need_fake_front++; - } - } - - if (pDraw->type == DRAWABLE_WINDOW) { - if (attachment == DRI2BufferFakeFrontLeft) { - need_fake_front--; - have_fake_front = 1; - } - } - } - - if (need_real_front > 0) { - if (allocate_or_reuse_buffer(pDraw, ds, pPriv, DRI2BufferFrontLeft, - front_format, dimensions_match, - &buffers[i++])) - buffers_changed = 1; - - if (buffers[i] == NULL) - goto err_out; - } - - if (need_fake_front > 0) { - if (allocate_or_reuse_buffer(pDraw, ds, pPriv, DRI2BufferFakeFrontLeft, - front_format, dimensions_match, - &buffers[i++])) - buffers_changed = 1; - - if (buffers[i] == NULL) - goto err_out; - - have_fake_front = 1; - } - - *out_count = i; - - update_dri2_drawable_buffers(pPriv, pDraw, buffers, out_count, width, height); - - /* If the client is getting a fake front-buffer, pre-fill it with the - * contents of the real front-buffer. This ensures correct operation of - * applications that call glXWaitX before calling glDrawBuffer. - */ - if (have_fake_front && buffers_changed) { - BoxRec box; - RegionRec region; - - box.x1 = 0; - box.y1 = 0; - box.x2 = pPriv->width; - box.y2 = pPriv->height; - REGION_INIT(pDraw->pScreen, ®ion, &box, 0); - - DRI2CopyRegion(pDraw, ®ion, DRI2BufferFakeFrontLeft, - DRI2BufferFrontLeft); - } - - return pPriv->buffers; - -err_out: - - *out_count = 0; - - for (i = 0; i < count; i++) { - if (buffers[i] != NULL) - (*ds->DestroyBuffer)(pDraw, buffers[i]); - } - - free(buffers); - buffers = NULL; - - update_dri2_drawable_buffers(pPriv, pDraw, buffers, out_count, width, height); - - return buffers; -} - -DRI2BufferPtr * -DRI2GetBuffers(DrawablePtr pDraw, int *width, int *height, - unsigned int *attachments, int count, int *out_count) -{ - return do_get_buffers(pDraw, width, height, attachments, count, - out_count, FALSE); -} - -DRI2BufferPtr * -DRI2GetBuffersWithFormat(DrawablePtr pDraw, int *width, int *height, - unsigned int *attachments, int count, int *out_count) -{ - return do_get_buffers(pDraw, width, height, attachments, count, - out_count, TRUE); -} - -static void -DRI2InvalidateDrawable(DrawablePtr pDraw) -{ - DRI2DrawablePtr pPriv = DRI2GetDrawable(pDraw); - DRI2DrawableRefPtr ref; - - if (!pPriv) - return; - - list_for_each_entry(ref, &pPriv->reference_list, link) - ref->invalidate(pDraw, ref->priv); -} - -/* - * In the direct rendered case, we throttle the clients that have more - * than their share of outstanding swaps (and thus busy buffers) when a - * new GetBuffers request is received. In the AIGLX case, we allow the - * client to get the new buffers, but throttle when the next GLX request - * comes in (see __glXDRIcontextWait()). - */ -Bool -DRI2ThrottleClient(ClientPtr client, DrawablePtr pDraw) -{ - DRI2DrawablePtr pPriv; - - pPriv = DRI2GetDrawable(pDraw); - if (pPriv == NULL) - return FALSE; - - /* Throttle to swap limit */ - if ((pPriv->swapsPending >= pPriv->swap_limit) && - !pPriv->blockedClient) { - ResetCurrentRequest(client); - client->sequence--; - IgnoreClient(client); - pPriv->blockedClient = client; - return TRUE; - } - - return FALSE; -} - -static void -__DRI2BlockClient(ClientPtr client, DRI2DrawablePtr pPriv) -{ - if (pPriv->blockedClient == NULL) { - IgnoreClient(client); - pPriv->blockedClient = client; - } -} - -void -DRI2BlockClient(ClientPtr client, DrawablePtr pDraw) -{ - DRI2DrawablePtr pPriv; - - pPriv = DRI2GetDrawable(pDraw); - if (pPriv == NULL) - return; - - __DRI2BlockClient(client, pPriv); - pPriv->blockedOnMsc = TRUE; -} - -int -DRI2CopyRegion(DrawablePtr pDraw, RegionPtr pRegion, - unsigned int dest, unsigned int src) -{ - DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen); - DRI2DrawablePtr pPriv; - DRI2BufferPtr pDestBuffer, pSrcBuffer; - int i; - - pPriv = DRI2GetDrawable(pDraw); - if (pPriv == NULL) - return BadDrawable; - - pDestBuffer = NULL; - pSrcBuffer = NULL; - for (i = 0; i < pPriv->bufferCount; i++) - { - if (pPriv->buffers[i]->attachment == dest) - pDestBuffer = (DRI2BufferPtr) pPriv->buffers[i]; - if (pPriv->buffers[i]->attachment == src) - pSrcBuffer = (DRI2BufferPtr) pPriv->buffers[i]; - } - if (pSrcBuffer == NULL || pDestBuffer == NULL) - return BadValue; - - (*ds->CopyRegion)(pDraw, pRegion, pDestBuffer, pSrcBuffer); - - return Success; -} - -/* Can this drawable be page flipped? */ -Bool -DRI2CanFlip(DrawablePtr pDraw) -{ - ScreenPtr pScreen = pDraw->pScreen; - WindowPtr pWin, pRoot; - PixmapPtr pWinPixmap, pRootPixmap; - - if (pDraw->type == DRAWABLE_PIXMAP) - return TRUE; - - pRoot = WindowTable[pScreen->myNum]; - pRootPixmap = pScreen->GetWindowPixmap(pRoot); - - pWin = (WindowPtr) pDraw; - pWinPixmap = pScreen->GetWindowPixmap(pWin); - if (pRootPixmap != pWinPixmap) - return FALSE; - if (!REGION_EQUAL(pScreen, &pWin->clipList, &pRoot->winSize)) - return FALSE; - - return TRUE; -} - -/* Can we do a pixmap exchange instead of a blit? */ -Bool -DRI2CanExchange(DrawablePtr pDraw) -{ - return FALSE; -} - -void -DRI2WaitMSCComplete(ClientPtr client, DrawablePtr pDraw, int frame, - unsigned int tv_sec, unsigned int tv_usec) -{ - DRI2DrawablePtr pPriv; - - pPriv = DRI2GetDrawable(pDraw); - if (pPriv == NULL) - return; - - ProcDRI2WaitMSCReply(client, ((CARD64)tv_sec * 1000000) + tv_usec, - frame, pPriv->swap_count); - - if (pPriv->blockedClient) - AttendClient(pPriv->blockedClient); - - pPriv->blockedClient = NULL; - pPriv->blockedOnMsc = FALSE; -} - -static void -DRI2WakeClient(ClientPtr client, DrawablePtr pDraw, int frame, - unsigned int tv_sec, unsigned int tv_usec) -{ - ScreenPtr pScreen = pDraw->pScreen; - DRI2DrawablePtr pPriv; - - pPriv = DRI2GetDrawable(pDraw); - if (pPriv == NULL) { - xf86DrvMsg(pScreen->myNum, X_ERROR, - "[DRI2] %s: bad drawable\n", __func__); - return; - } - - /* - * Swap completed. - * Wake the client iff: - * - it was waiting on SBC - * - was blocked due to GLX make current - * - was blocked due to swap throttling - * - is not blocked due to an MSC wait - */ - if (pPriv->target_sbc != -1 && - pPriv->target_sbc <= pPriv->swap_count) { - ProcDRI2WaitMSCReply(client, ((CARD64)tv_sec * 1000000) + tv_usec, - frame, pPriv->swap_count); - pPriv->target_sbc = -1; - - AttendClient(pPriv->blockedClient); - pPriv->blockedClient = NULL; - } else if (pPriv->target_sbc == -1 && !pPriv->blockedOnMsc) { - if (pPriv->blockedClient) { - AttendClient(pPriv->blockedClient); - pPriv->blockedClient = NULL; - } - } -} - -void -DRI2SwapComplete(ClientPtr client, DrawablePtr pDraw, int frame, - unsigned int tv_sec, unsigned int tv_usec, int type, - DRI2SwapEventPtr swap_complete, void *swap_data) -{ - ScreenPtr pScreen = pDraw->pScreen; - DRI2DrawablePtr pPriv; - CARD64 ust = 0; - BoxRec box; - RegionRec region; - - pPriv = DRI2GetDrawable(pDraw); - if (pPriv == NULL) { - xf86DrvMsg(pScreen->myNum, X_ERROR, - "[DRI2] %s: bad drawable\n", __func__); - return; - } - - pPriv->swapsPending--; - pPriv->swap_count++; - - box.x1 = 0; - box.y1 = 0; - box.x2 = pDraw->width; - box.y2 = pDraw->height; - REGION_INIT(pScreen, ®ion, &box, 0); - DRI2CopyRegion(pDraw, ®ion, DRI2BufferFakeFrontLeft, - DRI2BufferFrontLeft); - - ust = ((CARD64)tv_sec * 1000000) + tv_usec; - if (swap_complete) - swap_complete(client, swap_data, type, ust, frame, pPriv->swap_count); - - pPriv->last_swap_msc = frame; - pPriv->last_swap_ust = ust; - - DRI2WakeClient(client, pDraw, frame, tv_sec, tv_usec); -} - -Bool -DRI2WaitSwap(ClientPtr client, DrawablePtr pDrawable) -{ - DRI2DrawablePtr pPriv = DRI2GetDrawable(pDrawable); - - /* If we're currently waiting for a swap on this drawable, reset - * the request and suspend the client. We only support one - * blocked client per drawable. */ - if ((pPriv->swapsPending) && - pPriv->blockedClient == NULL) { - ResetCurrentRequest(client); - client->sequence--; - __DRI2BlockClient(client, pPriv); - return TRUE; - } - - return FALSE; -} - -int -DRI2SwapBuffers(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc, - CARD64 divisor, CARD64 remainder, CARD64 *swap_target, - DRI2SwapEventPtr func, void *data) -{ - ScreenPtr pScreen = pDraw->pScreen; - DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen); - DRI2DrawablePtr pPriv; - DRI2BufferPtr pDestBuffer = NULL, pSrcBuffer = NULL; - int ret, i; - - pPriv = DRI2GetDrawable(pDraw); - if (pPriv == NULL) { - xf86DrvMsg(pScreen->myNum, X_ERROR, - "[DRI2] %s: bad drawable\n", __func__); - return BadDrawable; - } - - for (i = 0; i < pPriv->bufferCount; i++) { - if (pPriv->buffers[i]->attachment == DRI2BufferFrontLeft) - pDestBuffer = (DRI2BufferPtr) pPriv->buffers[i]; - if (pPriv->buffers[i]->attachment == DRI2BufferBackLeft) - pSrcBuffer = (DRI2BufferPtr) pPriv->buffers[i]; - } - if (pSrcBuffer == NULL || pDestBuffer == NULL) { - xf86DrvMsg(pScreen->myNum, X_ERROR, - "[DRI2] %s: drawable has no back or front?\n", __func__); - return BadDrawable; - } - - /* Old DDX or no swap interval, just blit */ - if (!ds->ScheduleSwap || !pPriv->swap_interval) { - BoxRec box; - RegionRec region; - - box.x1 = 0; - box.y1 = 0; - box.x2 = pDraw->width; - box.y2 = pDraw->height; - REGION_INIT(pScreen, ®ion, &box, 0); - - pPriv->swapsPending++; - - (*ds->CopyRegion)(pDraw, ®ion, pDestBuffer, pSrcBuffer); - DRI2SwapComplete(client, pDraw, target_msc, 0, 0, DRI2_BLIT_COMPLETE, - func, data); - return Success; - } - - /* - * In the simple glXSwapBuffers case, all params will be 0, and we just - * need to schedule a swap for the last swap target + the swap interval. - */ - if (target_msc == 0 && divisor == 0 && remainder == 0) { - /* - * Swap target for this swap is last swap target + swap interval since - * we have to account for the current swap count, interval, and the - * number of pending swaps. - */ - *swap_target = pPriv->last_swap_target + pPriv->swap_interval; - } else { - /* glXSwapBuffersMscOML could have a 0 target_msc, honor it */ - *swap_target = target_msc; - } - - pPriv->swapsPending++; - ret = (*ds->ScheduleSwap)(client, pDraw, pDestBuffer, pSrcBuffer, - swap_target, divisor, remainder, func, data); - if (!ret) { - pPriv->swapsPending--; /* didn't schedule */ - xf86DrvMsg(pScreen->myNum, X_ERROR, - "[DRI2] %s: driver failed to schedule swap\n", __func__); - return BadDrawable; - } - - pPriv->last_swap_target = *swap_target; - - /* According to spec, return expected swapbuffers count SBC after this swap - * will complete. - */ - *swap_target = pPriv->swap_count + pPriv->swapsPending; - - DRI2InvalidateDrawable(pDraw); - - return Success; -} - -void -DRI2SwapInterval(DrawablePtr pDrawable, int interval) -{ - ScreenPtr pScreen = pDrawable->pScreen; - DRI2DrawablePtr pPriv = DRI2GetDrawable(pDrawable); - - if (pPriv == NULL) { - xf86DrvMsg(pScreen->myNum, X_ERROR, - "[DRI2] %s: bad drawable\n", __func__); - return; - } - - /* fixme: check against arbitrary max? */ - pPriv->swap_interval = interval; -} - -int -DRI2GetMSC(DrawablePtr pDraw, CARD64 *ust, CARD64 *msc, CARD64 *sbc) -{ - ScreenPtr pScreen = pDraw->pScreen; - DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen); - DRI2DrawablePtr pPriv; - Bool ret; - - pPriv = DRI2GetDrawable(pDraw); - if (pPriv == NULL) { - xf86DrvMsg(pScreen->myNum, X_ERROR, - "[DRI2] %s: bad drawable\n", __func__); - return BadDrawable; - } - - if (!ds->GetMSC) { - *ust = 0; - *msc = 0; - *sbc = pPriv->swap_count; - return Success; - } - - /* - * Spec needs to be updated to include unmapped or redirected - * drawables - */ - - ret = (*ds->GetMSC)(pDraw, ust, msc); - if (!ret) - return BadDrawable; - - *sbc = pPriv->swap_count; - - return Success; -} - -int -DRI2WaitMSC(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc, - CARD64 divisor, CARD64 remainder) -{ - DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen); - DRI2DrawablePtr pPriv; - Bool ret; - - pPriv = DRI2GetDrawable(pDraw); - if (pPriv == NULL) - return BadDrawable; - - /* Old DDX just completes immediately */ - if (!ds->ScheduleWaitMSC) { - DRI2WaitMSCComplete(client, pDraw, target_msc, 0, 0); - - return Success; - } - - ret = (*ds->ScheduleWaitMSC)(client, pDraw, target_msc, divisor, remainder); - if (!ret) - return BadDrawable; - - return Success; -} - -int -DRI2WaitSBC(ClientPtr client, DrawablePtr pDraw, CARD64 target_sbc, - CARD64 *ust, CARD64 *msc, CARD64 *sbc) -{ - DRI2DrawablePtr pPriv; - - pPriv = DRI2GetDrawable(pDraw); - if (pPriv == NULL) - return BadDrawable; - - /* target_sbc == 0 means to block until all pending swaps are - * finished. Recalculate target_sbc to get that behaviour. - */ - if (target_sbc == 0) - target_sbc = pPriv->swap_count + pPriv->swapsPending; - - /* If current swap count already >= target_sbc, - * return immediately with (ust, msc, sbc) triplet of - * most recent completed swap. - */ - if (pPriv->swap_count >= target_sbc) { - *sbc = pPriv->swap_count; - *msc = pPriv->last_swap_msc; - *ust = pPriv->last_swap_ust; - return Success; - } - - pPriv->target_sbc = target_sbc; - __DRI2BlockClient(client, pPriv); - - return Success; -} - -Bool -DRI2HasSwapControl(ScreenPtr pScreen) -{ - DRI2ScreenPtr ds = DRI2GetScreen(pScreen); - - return (ds->ScheduleSwap && ds->GetMSC); -} - -Bool -DRI2Connect(ScreenPtr pScreen, unsigned int driverType, int *fd, - const char **driverName, const char **deviceName) -{ - DRI2ScreenPtr ds = DRI2GetScreen(pScreen); - - if (ds == NULL || driverType >= ds->numDrivers || - !ds->driverNames[driverType]) - return FALSE; - - *fd = ds->fd; - *driverName = ds->driverNames[driverType]; - *deviceName = ds->deviceName; - - return TRUE; -} - -Bool -DRI2Authenticate(ScreenPtr pScreen, drm_magic_t magic) -{ - DRI2ScreenPtr ds = DRI2GetScreen(pScreen); - - if (ds == NULL || drmAuthMagic(ds->fd, magic)) - return FALSE; - - return TRUE; -} - -static void -DRI2ConfigNotify(WindowPtr pWin, int x, int y, int w, int h, int bw, - WindowPtr pSib) -{ - DrawablePtr pDraw = (DrawablePtr)pWin; - ScreenPtr pScreen = pDraw->pScreen; - DRI2ScreenPtr ds = DRI2GetScreen(pScreen); - DRI2DrawablePtr dd = DRI2GetDrawable(pDraw); - - if (ds->ConfigNotify) { - pScreen->ConfigNotify = ds->ConfigNotify; - - (*pScreen->ConfigNotify)(pWin, x, y, w, h, bw, pSib); - - ds->ConfigNotify = pScreen->ConfigNotify; - pScreen->ConfigNotify = DRI2ConfigNotify; - } - - if (!dd || (dd->width == w && dd->height == h)) - return; - - DRI2InvalidateDrawable(pDraw); -} - -Bool -DRI2ScreenInit(ScreenPtr pScreen, DRI2InfoPtr info) -{ - DRI2ScreenPtr ds; - const char* driverTypeNames[] = { - "DRI", /* DRI2DriverDRI */ - "VDPAU", /* DRI2DriverVDPAU */ - }; - unsigned int i; - CARD8 cur_minor; - - if (info->version < 3) - return FALSE; - - if (!xf86VGAarbiterAllowDRI(pScreen)) { - xf86DrvMsg(pScreen->myNum, X_WARNING, - "[DRI2] Direct rendering is not supported when VGA arb is necessary for the device\n"); - return FALSE; - } - - ds = calloc(1, sizeof *ds); - if (!ds) - return FALSE; - - ds->screen = pScreen; - ds->fd = info->fd; - ds->deviceName = info->deviceName; - dri2_major = 1; - - ds->CreateBuffer = info->CreateBuffer; - ds->DestroyBuffer = info->DestroyBuffer; - ds->CopyRegion = info->CopyRegion; - - if (info->version >= 4) { - ds->ScheduleSwap = info->ScheduleSwap; - ds->ScheduleWaitMSC = info->ScheduleWaitMSC; - ds->GetMSC = info->GetMSC; - cur_minor = 3; - } else { - cur_minor = 1; - } - - /* Initialize minor if needed and set to minimum provied by DDX */ - if (!dri2_minor || dri2_minor > cur_minor) - dri2_minor = cur_minor; - - if (info->version == 3 || info->numDrivers == 0) { - /* Driver too old: use the old-style driverName field */ - ds->numDrivers = 1; - ds->driverNames = malloc(sizeof(*ds->driverNames)); - if (!ds->driverNames) { - free(ds); - return FALSE; - } - ds->driverNames[0] = info->driverName; - } else { - ds->numDrivers = info->numDrivers; - ds->driverNames = malloc(info->numDrivers * sizeof(*ds->driverNames)); - if (!ds->driverNames) { - free(ds); - return FALSE; - } - memcpy(ds->driverNames, info->driverNames, - info->numDrivers * sizeof(*ds->driverNames)); - } - - dixSetPrivate(&pScreen->devPrivates, dri2ScreenPrivateKey, ds); - - ds->ConfigNotify = pScreen->ConfigNotify; - pScreen->ConfigNotify = DRI2ConfigNotify; - - xf86DrvMsg(pScreen->myNum, X_INFO, "[DRI2] Setup complete\n"); - for (i = 0; i < sizeof(driverTypeNames) / sizeof(driverTypeNames[0]); i++) { - if (i < ds->numDrivers && ds->driverNames[i]) { - xf86DrvMsg(pScreen->myNum, X_INFO, "[DRI2] %s driver: %s\n", - driverTypeNames[i], ds->driverNames[i]); - } - } - - return TRUE; -} - -void -DRI2CloseScreen(ScreenPtr pScreen) -{ - DRI2ScreenPtr ds = DRI2GetScreen(pScreen); - - free(ds->driverNames); - free(ds); - dixSetPrivate(&pScreen->devPrivates, dri2ScreenPrivateKey, NULL); -} - -extern ExtensionModule dri2ExtensionModule; - -static pointer -DRI2Setup(pointer module, pointer opts, int *errmaj, int *errmin) -{ - static Bool setupDone = FALSE; - - dri2DrawableRes = CreateNewResourceType(DRI2DrawableGone, "DRI2Drawable"); - - if (!setupDone) - { - setupDone = TRUE; - LoadExtension(&dri2ExtensionModule, FALSE); - } - else - { - if (errmaj) - *errmaj = LDR_ONCEONLY; - } - - return (pointer) 1; -} - -static XF86ModuleVersionInfo DRI2VersRec = -{ - "dri2", - MODULEVENDORSTRING, - MODINFOSTRING1, - MODINFOSTRING2, - XORG_VERSION_CURRENT, - 1, 2, 0, - ABI_CLASS_EXTENSION, - ABI_EXTENSION_VERSION, - MOD_CLASS_NONE, - { 0, 0, 0, 0 } -}; - -_X_EXPORT XF86ModuleData dri2ModuleData = { &DRI2VersRec, DRI2Setup, NULL }; - -void -DRI2Version(int *major, int *minor) -{ - if (major != NULL) - *major = DRI2VersRec.majorversion; - - if (minor != NULL) - *minor = DRI2VersRec.minorversion; -} +/* + * Copyright © 2007, 2008 Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Soft- + * ware"), to deal in the Software without restriction, including without + * limitation the rights to use, copy, modify, merge, publish, distribute, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, provided that the above copyright + * notice(s) and this permission notice appear in all copies of the Soft- + * ware and that both the above copyright notice(s) and this permission + * notice appear in supporting documentation. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- + * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY + * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN + * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE- + * QUENTIAL 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 PERFOR- + * MANCE OF THIS SOFTWARE. + * + * Except as contained in this notice, the name of a copyright holder shall + * not be used in advertising or otherwise to promote the sale, use or + * other dealings in this Software without prior written authorization of + * the copyright holder. + * + * Authors: + * Kristian Høgsberg (krh@redhat.com) + */ + +#ifdef HAVE_XORG_CONFIG_H +#include +#endif + +#include +#include +#include "xf86Module.h" +#include "list.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "dixstruct.h" +#include "dri2.h" +#include "xf86VGAarbiter.h" + +#include "xf86.h" + +CARD8 dri2_major; /* version of DRI2 supported by DDX */ +CARD8 dri2_minor; + +static int dri2ScreenPrivateKeyIndex; +static DevPrivateKey dri2ScreenPrivateKey = &dri2ScreenPrivateKeyIndex; +static int dri2WindowPrivateKeyIndex; +static DevPrivateKey dri2WindowPrivateKey = &dri2WindowPrivateKeyIndex; +static int dri2PixmapPrivateKeyIndex; +static DevPrivateKey dri2PixmapPrivateKey = &dri2PixmapPrivateKeyIndex; +static RESTYPE dri2DrawableRes; + +typedef struct _DRI2Screen *DRI2ScreenPtr; + +typedef struct _DRI2Drawable { + DRI2ScreenPtr dri2_screen; + DrawablePtr drawable; + struct list reference_list; + int width; + int height; + DRI2BufferPtr *buffers; + int bufferCount; + unsigned int swapsPending; + ClientPtr blockedClient; + Bool blockedOnMsc; + int swap_interval; + CARD64 swap_count; + int64_t target_sbc; /* -1 means no SBC wait outstanding */ + CARD64 last_swap_target; /* most recently queued swap target */ + CARD64 last_swap_msc; /* msc at completion of most recent swap */ + CARD64 last_swap_ust; /* ust at completion of most recent swap */ + int swap_limit; /* for N-buffering */ +} DRI2DrawableRec, *DRI2DrawablePtr; + +typedef struct _DRI2Screen { + ScreenPtr screen; + int refcnt; + unsigned int numDrivers; + const char **driverNames; + const char *deviceName; + int fd; + unsigned int lastSequence; + + DRI2CreateBufferProcPtr CreateBuffer; + DRI2DestroyBufferProcPtr DestroyBuffer; + DRI2CopyRegionProcPtr CopyRegion; + DRI2ScheduleSwapProcPtr ScheduleSwap; + DRI2GetMSCProcPtr GetMSC; + DRI2ScheduleWaitMSCProcPtr ScheduleWaitMSC; + + HandleExposuresProcPtr HandleExposures; + + ConfigNotifyProcPtr ConfigNotify; +} DRI2ScreenRec; + +static DRI2ScreenPtr +DRI2GetScreen(ScreenPtr pScreen) +{ + return dixLookupPrivate(&pScreen->devPrivates, dri2ScreenPrivateKey); +} + +static DRI2DrawablePtr +DRI2GetDrawable(DrawablePtr pDraw) +{ + WindowPtr pWin; + PixmapPtr pPixmap; + + if (pDraw->type == DRAWABLE_WINDOW) { + pWin = (WindowPtr) pDraw; + return dixLookupPrivate(&pWin->devPrivates, dri2WindowPrivateKey); + } else { + pPixmap = (PixmapPtr) pDraw; + return dixLookupPrivate(&pPixmap->devPrivates, dri2PixmapPrivateKey); + } +} + +static DRI2DrawablePtr +DRI2AllocateDrawable(DrawablePtr pDraw) +{ + DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen); + DRI2DrawablePtr pPriv; + CARD64 ust; + WindowPtr pWin; + PixmapPtr pPixmap; + + pPriv = malloc(sizeof *pPriv); + if (pPriv == NULL) + return NULL; + + pPriv->dri2_screen = ds; + pPriv->drawable = pDraw; + pPriv->width = pDraw->width; + pPriv->height = pDraw->height; + pPriv->buffers = NULL; + pPriv->bufferCount = 0; + pPriv->swapsPending = 0; + pPriv->blockedClient = NULL; + pPriv->blockedOnMsc = FALSE; + pPriv->swap_count = 0; + pPriv->target_sbc = -1; + pPriv->swap_interval = 1; + /* Initialize last swap target from DDX if possible */ + if (!ds->GetMSC || !(*ds->GetMSC)(pDraw, &ust, &pPriv->last_swap_target)) + pPriv->last_swap_target = 0; + + pPriv->swap_limit = 1; /* default to double buffering */ + pPriv->last_swap_msc = 0; + pPriv->last_swap_ust = 0; + list_init(&pPriv->reference_list); + + if (pDraw->type == DRAWABLE_WINDOW) { + pWin = (WindowPtr) pDraw; + dixSetPrivate(&pWin->devPrivates, dri2WindowPrivateKey, pPriv); + } else { + pPixmap = (PixmapPtr) pDraw; + dixSetPrivate(&pPixmap->devPrivates, dri2PixmapPrivateKey, pPriv); + } + + return pPriv; +} + +typedef struct DRI2DrawableRefRec { + XID id; + XID dri2_id; + DRI2InvalidateProcPtr invalidate; + void *priv; + struct list link; +} DRI2DrawableRefRec, *DRI2DrawableRefPtr; + +static DRI2DrawableRefPtr +DRI2LookupDrawableRef(DRI2DrawablePtr pPriv, XID id) +{ + DRI2DrawableRefPtr ref; + + list_for_each_entry(ref, &pPriv->reference_list, link) { + if (ref->id == id) + return ref; + } + + return NULL; +} + +static int +DRI2AddDrawableRef(DRI2DrawablePtr pPriv, XID id, XID dri2_id, + DRI2InvalidateProcPtr invalidate, void *priv) +{ + DRI2DrawableRefPtr ref; + + ref = malloc(sizeof *ref); + if (ref == NULL) + return BadAlloc; + + if (!AddResource(dri2_id, dri2DrawableRes, pPriv)) + return BadAlloc; + if (!DRI2LookupDrawableRef(pPriv, id)) + if (!AddResource(id, dri2DrawableRes, pPriv)) + return BadAlloc; + + ref->id = id; + ref->dri2_id = dri2_id; + ref->invalidate = invalidate; + ref->priv = priv; + list_add(&ref->link, &pPriv->reference_list); + + return Success; +} + +int +DRI2CreateDrawable(ClientPtr client, DrawablePtr pDraw, XID id, + DRI2InvalidateProcPtr invalidate, void *priv) +{ + DRI2DrawablePtr pPriv; + XID dri2_id; + int rc; + + pPriv = DRI2GetDrawable(pDraw); + if (pPriv == NULL) + pPriv = DRI2AllocateDrawable(pDraw); + if (pPriv == NULL) + return BadAlloc; + + dri2_id = FakeClientID(client->index); + rc = DRI2AddDrawableRef(pPriv, id, dri2_id, invalidate, priv); + if (rc != Success) + return rc; + + return Success; +} + +static int DRI2DrawableGone(pointer p, XID id) +{ + DRI2DrawablePtr pPriv = p; + DRI2ScreenPtr ds = pPriv->dri2_screen; + DRI2DrawableRefPtr ref, next; + WindowPtr pWin; + PixmapPtr pPixmap; + DrawablePtr pDraw; + int i; + + list_for_each_entry_safe(ref, next, &pPriv->reference_list, link) { + if (ref->dri2_id == id) { + list_del(&ref->link); + /* If this was the last ref under this X drawable XID, + * unregister the X drawable resource. */ + if (!DRI2LookupDrawableRef(pPriv, ref->id)) + FreeResourceByType(ref->id, dri2DrawableRes, TRUE); + free(ref); + break; + } + + if (ref->id == id) { + list_del(&ref->link); + FreeResourceByType(ref->dri2_id, dri2DrawableRes, TRUE); + free(ref); + } + } + + if (!list_is_empty(&pPriv->reference_list)) + return Success; + + pDraw = pPriv->drawable; + if (pDraw->type == DRAWABLE_WINDOW) { + pWin = (WindowPtr) pDraw; + dixSetPrivate(&pWin->devPrivates, dri2WindowPrivateKey, NULL); + } else { + pPixmap = (PixmapPtr) pDraw; + dixSetPrivate(&pPixmap->devPrivates, dri2PixmapPrivateKey, NULL); + } + + if (pPriv->buffers != NULL) { + for (i = 0; i < pPriv->bufferCount; i++) + (*ds->DestroyBuffer)(pDraw, pPriv->buffers[i]); + + free(pPriv->buffers); + } + + free(pPriv); + + return Success; +} + +static int +find_attachment(DRI2DrawablePtr pPriv, unsigned attachment) +{ + int i; + + if (pPriv->buffers == NULL) { + return -1; + } + + for (i = 0; i < pPriv->bufferCount; i++) { + if ((pPriv->buffers[i] != NULL) + && (pPriv->buffers[i]->attachment == attachment)) { + return i; + } + } + + return -1; +} + +static Bool +allocate_or_reuse_buffer(DrawablePtr pDraw, DRI2ScreenPtr ds, + DRI2DrawablePtr pPriv, + unsigned int attachment, unsigned int format, + int dimensions_match, DRI2BufferPtr *buffer) +{ + int old_buf = find_attachment(pPriv, attachment); + + if ((old_buf < 0) + || !dimensions_match + || (pPriv->buffers[old_buf]->format != format)) { + *buffer = (*ds->CreateBuffer)(pDraw, attachment, format); + return TRUE; + + } else { + *buffer = pPriv->buffers[old_buf]; + pPriv->buffers[old_buf] = NULL; + return FALSE; + } +} + +static void +update_dri2_drawable_buffers(DRI2DrawablePtr pPriv, DrawablePtr pDraw, + DRI2BufferPtr *buffers, int *out_count, int *width, int *height) +{ + DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen); + int i; + + if (pPriv->buffers != NULL) { + for (i = 0; i < pPriv->bufferCount; i++) { + if (pPriv->buffers[i] != NULL) { + (*ds->DestroyBuffer)(pDraw, pPriv->buffers[i]); + } + } + + free(pPriv->buffers); + } + + pPriv->buffers = buffers; + pPriv->bufferCount = *out_count; + pPriv->width = pDraw->width; + pPriv->height = pDraw->height; + *width = pPriv->width; + *height = pPriv->height; +} + +static DRI2BufferPtr * +do_get_buffers(DrawablePtr pDraw, int *width, int *height, + unsigned int *attachments, int count, int *out_count, + int has_format) +{ + DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen); + DRI2DrawablePtr pPriv = DRI2GetDrawable(pDraw); + DRI2BufferPtr *buffers; + int need_real_front = 0; + int need_fake_front = 0; + int have_fake_front = 0; + int front_format = 0; + int dimensions_match; + int buffers_changed = 0; + int i; + + if (!pPriv) { + *width = pDraw->width; + *height = pDraw->height; + *out_count = 0; + return NULL; + } + + dimensions_match = (pDraw->width == pPriv->width) + && (pDraw->height == pPriv->height); + + buffers = malloc((count + 1) * sizeof(buffers[0])); + + for (i = 0; i < count; i++) { + const unsigned attachment = *(attachments++); + const unsigned format = (has_format) ? *(attachments++) : 0; + + if (allocate_or_reuse_buffer(pDraw, ds, pPriv, attachment, + format, dimensions_match, + &buffers[i])) + buffers_changed = 1; + + if (buffers[i] == NULL) + goto err_out; + + /* If the drawable is a window and the front-buffer is requested, + * silently add the fake front-buffer to the list of requested + * attachments. The counting logic in the loop accounts for the case + * where the client requests both the fake and real front-buffer. + */ + if (attachment == DRI2BufferBackLeft) { + need_real_front++; + front_format = format; + } + + if (attachment == DRI2BufferFrontLeft) { + need_real_front--; + front_format = format; + + if (pDraw->type == DRAWABLE_WINDOW) { + need_fake_front++; + } + } + + if (pDraw->type == DRAWABLE_WINDOW) { + if (attachment == DRI2BufferFakeFrontLeft) { + need_fake_front--; + have_fake_front = 1; + } + } + } + + if (need_real_front > 0) { + if (allocate_or_reuse_buffer(pDraw, ds, pPriv, DRI2BufferFrontLeft, + front_format, dimensions_match, + &buffers[i])) + buffers_changed = 1; + + if (buffers[i] == NULL) + goto err_out; + i++; + } + + if (need_fake_front > 0) { + if (allocate_or_reuse_buffer(pDraw, ds, pPriv, DRI2BufferFakeFrontLeft, + front_format, dimensions_match, + &buffers[i])) + buffers_changed = 1; + + if (buffers[i] == NULL) + goto err_out; + + i++; + have_fake_front = 1; + } + + *out_count = i; + + update_dri2_drawable_buffers(pPriv, pDraw, buffers, out_count, width, height); + + /* If the client is getting a fake front-buffer, pre-fill it with the + * contents of the real front-buffer. This ensures correct operation of + * applications that call glXWaitX before calling glDrawBuffer. + */ + if (have_fake_front && buffers_changed) { + BoxRec box; + RegionRec region; + + box.x1 = 0; + box.y1 = 0; + box.x2 = pPriv->width; + box.y2 = pPriv->height; + REGION_INIT(pDraw->pScreen, ®ion, &box, 0); + + DRI2CopyRegion(pDraw, ®ion, DRI2BufferFakeFrontLeft, + DRI2BufferFrontLeft); + } + + return pPriv->buffers; + +err_out: + + *out_count = 0; + + for (i = 0; i < count; i++) { + if (buffers[i] != NULL) + (*ds->DestroyBuffer)(pDraw, buffers[i]); + } + + free(buffers); + buffers = NULL; + + update_dri2_drawable_buffers(pPriv, pDraw, buffers, out_count, width, height); + + return buffers; +} + +DRI2BufferPtr * +DRI2GetBuffers(DrawablePtr pDraw, int *width, int *height, + unsigned int *attachments, int count, int *out_count) +{ + return do_get_buffers(pDraw, width, height, attachments, count, + out_count, FALSE); +} + +DRI2BufferPtr * +DRI2GetBuffersWithFormat(DrawablePtr pDraw, int *width, int *height, + unsigned int *attachments, int count, int *out_count) +{ + return do_get_buffers(pDraw, width, height, attachments, count, + out_count, TRUE); +} + +static void +DRI2InvalidateDrawable(DrawablePtr pDraw) +{ + DRI2DrawablePtr pPriv = DRI2GetDrawable(pDraw); + DRI2DrawableRefPtr ref; + + if (!pPriv) + return; + + list_for_each_entry(ref, &pPriv->reference_list, link) + ref->invalidate(pDraw, ref->priv); +} + +/* + * In the direct rendered case, we throttle the clients that have more + * than their share of outstanding swaps (and thus busy buffers) when a + * new GetBuffers request is received. In the AIGLX case, we allow the + * client to get the new buffers, but throttle when the next GLX request + * comes in (see __glXDRIcontextWait()). + */ +Bool +DRI2ThrottleClient(ClientPtr client, DrawablePtr pDraw) +{ + DRI2DrawablePtr pPriv; + + pPriv = DRI2GetDrawable(pDraw); + if (pPriv == NULL) + return FALSE; + + /* Throttle to swap limit */ + if ((pPriv->swapsPending >= pPriv->swap_limit) && + !pPriv->blockedClient) { + ResetCurrentRequest(client); + client->sequence--; + IgnoreClient(client); + pPriv->blockedClient = client; + return TRUE; + } + + return FALSE; +} + +static void +__DRI2BlockClient(ClientPtr client, DRI2DrawablePtr pPriv) +{ + if (pPriv->blockedClient == NULL) { + IgnoreClient(client); + pPriv->blockedClient = client; + } +} + +void +DRI2BlockClient(ClientPtr client, DrawablePtr pDraw) +{ + DRI2DrawablePtr pPriv; + + pPriv = DRI2GetDrawable(pDraw); + if (pPriv == NULL) + return; + + __DRI2BlockClient(client, pPriv); + pPriv->blockedOnMsc = TRUE; +} + +int +DRI2CopyRegion(DrawablePtr pDraw, RegionPtr pRegion, + unsigned int dest, unsigned int src) +{ + DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen); + DRI2DrawablePtr pPriv; + DRI2BufferPtr pDestBuffer, pSrcBuffer; + int i; + + pPriv = DRI2GetDrawable(pDraw); + if (pPriv == NULL) + return BadDrawable; + + pDestBuffer = NULL; + pSrcBuffer = NULL; + for (i = 0; i < pPriv->bufferCount; i++) + { + if (pPriv->buffers[i]->attachment == dest) + pDestBuffer = (DRI2BufferPtr) pPriv->buffers[i]; + if (pPriv->buffers[i]->attachment == src) + pSrcBuffer = (DRI2BufferPtr) pPriv->buffers[i]; + } + if (pSrcBuffer == NULL || pDestBuffer == NULL) + return BadValue; + + (*ds->CopyRegion)(pDraw, pRegion, pDestBuffer, pSrcBuffer); + + return Success; +} + +/* Can this drawable be page flipped? */ +Bool +DRI2CanFlip(DrawablePtr pDraw) +{ + ScreenPtr pScreen = pDraw->pScreen; + WindowPtr pWin, pRoot; + PixmapPtr pWinPixmap, pRootPixmap; + + if (pDraw->type == DRAWABLE_PIXMAP) + return TRUE; + + pRoot = WindowTable[pScreen->myNum]; + pRootPixmap = pScreen->GetWindowPixmap(pRoot); + + pWin = (WindowPtr) pDraw; + pWinPixmap = pScreen->GetWindowPixmap(pWin); + if (pRootPixmap != pWinPixmap) + return FALSE; + if (!REGION_EQUAL(pScreen, &pWin->clipList, &pRoot->winSize)) + return FALSE; + + return TRUE; +} + +/* Can we do a pixmap exchange instead of a blit? */ +Bool +DRI2CanExchange(DrawablePtr pDraw) +{ + return FALSE; +} + +void +DRI2WaitMSCComplete(ClientPtr client, DrawablePtr pDraw, int frame, + unsigned int tv_sec, unsigned int tv_usec) +{ + DRI2DrawablePtr pPriv; + + pPriv = DRI2GetDrawable(pDraw); + if (pPriv == NULL) + return; + + ProcDRI2WaitMSCReply(client, ((CARD64)tv_sec * 1000000) + tv_usec, + frame, pPriv->swap_count); + + if (pPriv->blockedClient) + AttendClient(pPriv->blockedClient); + + pPriv->blockedClient = NULL; + pPriv->blockedOnMsc = FALSE; +} + +static void +DRI2WakeClient(ClientPtr client, DrawablePtr pDraw, int frame, + unsigned int tv_sec, unsigned int tv_usec) +{ + ScreenPtr pScreen = pDraw->pScreen; + DRI2DrawablePtr pPriv; + + pPriv = DRI2GetDrawable(pDraw); + if (pPriv == NULL) { + xf86DrvMsg(pScreen->myNum, X_ERROR, + "[DRI2] %s: bad drawable\n", __func__); + return; + } + + /* + * Swap completed. + * Wake the client iff: + * - it was waiting on SBC + * - was blocked due to GLX make current + * - was blocked due to swap throttling + * - is not blocked due to an MSC wait + */ + if (pPriv->target_sbc != -1 && + pPriv->target_sbc <= pPriv->swap_count) { + ProcDRI2WaitMSCReply(client, ((CARD64)tv_sec * 1000000) + tv_usec, + frame, pPriv->swap_count); + pPriv->target_sbc = -1; + + AttendClient(pPriv->blockedClient); + pPriv->blockedClient = NULL; + } else if (pPriv->target_sbc == -1 && !pPriv->blockedOnMsc) { + if (pPriv->blockedClient) { + AttendClient(pPriv->blockedClient); + pPriv->blockedClient = NULL; + } + } +} + +void +DRI2SwapComplete(ClientPtr client, DrawablePtr pDraw, int frame, + unsigned int tv_sec, unsigned int tv_usec, int type, + DRI2SwapEventPtr swap_complete, void *swap_data) +{ + ScreenPtr pScreen = pDraw->pScreen; + DRI2DrawablePtr pPriv; + CARD64 ust = 0; + BoxRec box; + RegionRec region; + + pPriv = DRI2GetDrawable(pDraw); + if (pPriv == NULL) { + xf86DrvMsg(pScreen->myNum, X_ERROR, + "[DRI2] %s: bad drawable\n", __func__); + return; + } + + pPriv->swapsPending--; + pPriv->swap_count++; + + box.x1 = 0; + box.y1 = 0; + box.x2 = pDraw->width; + box.y2 = pDraw->height; + REGION_INIT(pScreen, ®ion, &box, 0); + DRI2CopyRegion(pDraw, ®ion, DRI2BufferFakeFrontLeft, + DRI2BufferFrontLeft); + + ust = ((CARD64)tv_sec * 1000000) + tv_usec; + if (swap_complete) + swap_complete(client, swap_data, type, ust, frame, pPriv->swap_count); + + pPriv->last_swap_msc = frame; + pPriv->last_swap_ust = ust; + + DRI2WakeClient(client, pDraw, frame, tv_sec, tv_usec); +} + +Bool +DRI2WaitSwap(ClientPtr client, DrawablePtr pDrawable) +{ + DRI2DrawablePtr pPriv = DRI2GetDrawable(pDrawable); + + /* If we're currently waiting for a swap on this drawable, reset + * the request and suspend the client. We only support one + * blocked client per drawable. */ + if ((pPriv->swapsPending) && + pPriv->blockedClient == NULL) { + ResetCurrentRequest(client); + client->sequence--; + __DRI2BlockClient(client, pPriv); + return TRUE; + } + + return FALSE; +} + +int +DRI2SwapBuffers(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc, + CARD64 divisor, CARD64 remainder, CARD64 *swap_target, + DRI2SwapEventPtr func, void *data) +{ + ScreenPtr pScreen = pDraw->pScreen; + DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen); + DRI2DrawablePtr pPriv; + DRI2BufferPtr pDestBuffer = NULL, pSrcBuffer = NULL; + int ret, i; + + pPriv = DRI2GetDrawable(pDraw); + if (pPriv == NULL) { + xf86DrvMsg(pScreen->myNum, X_ERROR, + "[DRI2] %s: bad drawable\n", __func__); + return BadDrawable; + } + + for (i = 0; i < pPriv->bufferCount; i++) { + if (pPriv->buffers[i]->attachment == DRI2BufferFrontLeft) + pDestBuffer = (DRI2BufferPtr) pPriv->buffers[i]; + if (pPriv->buffers[i]->attachment == DRI2BufferBackLeft) + pSrcBuffer = (DRI2BufferPtr) pPriv->buffers[i]; + } + if (pSrcBuffer == NULL || pDestBuffer == NULL) { + xf86DrvMsg(pScreen->myNum, X_ERROR, + "[DRI2] %s: drawable has no back or front?\n", __func__); + return BadDrawable; + } + + /* Old DDX or no swap interval, just blit */ + if (!ds->ScheduleSwap || !pPriv->swap_interval) { + BoxRec box; + RegionRec region; + + box.x1 = 0; + box.y1 = 0; + box.x2 = pDraw->width; + box.y2 = pDraw->height; + REGION_INIT(pScreen, ®ion, &box, 0); + + pPriv->swapsPending++; + + (*ds->CopyRegion)(pDraw, ®ion, pDestBuffer, pSrcBuffer); + DRI2SwapComplete(client, pDraw, target_msc, 0, 0, DRI2_BLIT_COMPLETE, + func, data); + return Success; + } + + /* + * In the simple glXSwapBuffers case, all params will be 0, and we just + * need to schedule a swap for the last swap target + the swap interval. + */ + if (target_msc == 0 && divisor == 0 && remainder == 0) { + /* + * Swap target for this swap is last swap target + swap interval since + * we have to account for the current swap count, interval, and the + * number of pending swaps. + */ + *swap_target = pPriv->last_swap_target + pPriv->swap_interval; + } else { + /* glXSwapBuffersMscOML could have a 0 target_msc, honor it */ + *swap_target = target_msc; + } + + pPriv->swapsPending++; + ret = (*ds->ScheduleSwap)(client, pDraw, pDestBuffer, pSrcBuffer, + swap_target, divisor, remainder, func, data); + if (!ret) { + pPriv->swapsPending--; /* didn't schedule */ + xf86DrvMsg(pScreen->myNum, X_ERROR, + "[DRI2] %s: driver failed to schedule swap\n", __func__); + return BadDrawable; + } + + pPriv->last_swap_target = *swap_target; + + /* According to spec, return expected swapbuffers count SBC after this swap + * will complete. + */ + *swap_target = pPriv->swap_count + pPriv->swapsPending; + + DRI2InvalidateDrawable(pDraw); + + return Success; +} + +void +DRI2SwapInterval(DrawablePtr pDrawable, int interval) +{ + ScreenPtr pScreen = pDrawable->pScreen; + DRI2DrawablePtr pPriv = DRI2GetDrawable(pDrawable); + + if (pPriv == NULL) { + xf86DrvMsg(pScreen->myNum, X_ERROR, + "[DRI2] %s: bad drawable\n", __func__); + return; + } + + /* fixme: check against arbitrary max? */ + pPriv->swap_interval = interval; +} + +int +DRI2GetMSC(DrawablePtr pDraw, CARD64 *ust, CARD64 *msc, CARD64 *sbc) +{ + ScreenPtr pScreen = pDraw->pScreen; + DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen); + DRI2DrawablePtr pPriv; + Bool ret; + + pPriv = DRI2GetDrawable(pDraw); + if (pPriv == NULL) { + xf86DrvMsg(pScreen->myNum, X_ERROR, + "[DRI2] %s: bad drawable\n", __func__); + return BadDrawable; + } + + if (!ds->GetMSC) { + *ust = 0; + *msc = 0; + *sbc = pPriv->swap_count; + return Success; + } + + /* + * Spec needs to be updated to include unmapped or redirected + * drawables + */ + + ret = (*ds->GetMSC)(pDraw, ust, msc); + if (!ret) + return BadDrawable; + + *sbc = pPriv->swap_count; + + return Success; +} + +int +DRI2WaitMSC(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc, + CARD64 divisor, CARD64 remainder) +{ + DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen); + DRI2DrawablePtr pPriv; + Bool ret; + + pPriv = DRI2GetDrawable(pDraw); + if (pPriv == NULL) + return BadDrawable; + + /* Old DDX just completes immediately */ + if (!ds->ScheduleWaitMSC) { + DRI2WaitMSCComplete(client, pDraw, target_msc, 0, 0); + + return Success; + } + + ret = (*ds->ScheduleWaitMSC)(client, pDraw, target_msc, divisor, remainder); + if (!ret) + return BadDrawable; + + return Success; +} + +int +DRI2WaitSBC(ClientPtr client, DrawablePtr pDraw, CARD64 target_sbc, + CARD64 *ust, CARD64 *msc, CARD64 *sbc) +{ + DRI2DrawablePtr pPriv; + + pPriv = DRI2GetDrawable(pDraw); + if (pPriv == NULL) + return BadDrawable; + + /* target_sbc == 0 means to block until all pending swaps are + * finished. Recalculate target_sbc to get that behaviour. + */ + if (target_sbc == 0) + target_sbc = pPriv->swap_count + pPriv->swapsPending; + + /* If current swap count already >= target_sbc, + * return immediately with (ust, msc, sbc) triplet of + * most recent completed swap. + */ + if (pPriv->swap_count >= target_sbc) { + *sbc = pPriv->swap_count; + *msc = pPriv->last_swap_msc; + *ust = pPriv->last_swap_ust; + return Success; + } + + pPriv->target_sbc = target_sbc; + __DRI2BlockClient(client, pPriv); + + return Success; +} + +Bool +DRI2HasSwapControl(ScreenPtr pScreen) +{ + DRI2ScreenPtr ds = DRI2GetScreen(pScreen); + + return (ds->ScheduleSwap && ds->GetMSC); +} + +Bool +DRI2Connect(ScreenPtr pScreen, unsigned int driverType, int *fd, + const char **driverName, const char **deviceName) +{ + DRI2ScreenPtr ds = DRI2GetScreen(pScreen); + + if (ds == NULL || driverType >= ds->numDrivers || + !ds->driverNames[driverType]) + return FALSE; + + *fd = ds->fd; + *driverName = ds->driverNames[driverType]; + *deviceName = ds->deviceName; + + return TRUE; +} + +Bool +DRI2Authenticate(ScreenPtr pScreen, drm_magic_t magic) +{ + DRI2ScreenPtr ds = DRI2GetScreen(pScreen); + + if (ds == NULL || drmAuthMagic(ds->fd, magic)) + return FALSE; + + return TRUE; +} + +static void +DRI2ConfigNotify(WindowPtr pWin, int x, int y, int w, int h, int bw, + WindowPtr pSib) +{ + DrawablePtr pDraw = (DrawablePtr)pWin; + ScreenPtr pScreen = pDraw->pScreen; + DRI2ScreenPtr ds = DRI2GetScreen(pScreen); + DRI2DrawablePtr dd = DRI2GetDrawable(pDraw); + + if (ds->ConfigNotify) { + pScreen->ConfigNotify = ds->ConfigNotify; + + (*pScreen->ConfigNotify)(pWin, x, y, w, h, bw, pSib); + + ds->ConfigNotify = pScreen->ConfigNotify; + pScreen->ConfigNotify = DRI2ConfigNotify; + } + + if (!dd || (dd->width == w && dd->height == h)) + return; + + DRI2InvalidateDrawable(pDraw); +} + +Bool +DRI2ScreenInit(ScreenPtr pScreen, DRI2InfoPtr info) +{ + DRI2ScreenPtr ds; + const char* driverTypeNames[] = { + "DRI", /* DRI2DriverDRI */ + "VDPAU", /* DRI2DriverVDPAU */ + }; + unsigned int i; + CARD8 cur_minor; + + if (info->version < 3) + return FALSE; + + if (!xf86VGAarbiterAllowDRI(pScreen)) { + xf86DrvMsg(pScreen->myNum, X_WARNING, + "[DRI2] Direct rendering is not supported when VGA arb is necessary for the device\n"); + return FALSE; + } + + ds = calloc(1, sizeof *ds); + if (!ds) + return FALSE; + + ds->screen = pScreen; + ds->fd = info->fd; + ds->deviceName = info->deviceName; + dri2_major = 1; + + ds->CreateBuffer = info->CreateBuffer; + ds->DestroyBuffer = info->DestroyBuffer; + ds->CopyRegion = info->CopyRegion; + + if (info->version >= 4) { + ds->ScheduleSwap = info->ScheduleSwap; + ds->ScheduleWaitMSC = info->ScheduleWaitMSC; + ds->GetMSC = info->GetMSC; + cur_minor = 3; + } else { + cur_minor = 1; + } + + /* Initialize minor if needed and set to minimum provied by DDX */ + if (!dri2_minor || dri2_minor > cur_minor) + dri2_minor = cur_minor; + + if (info->version == 3 || info->numDrivers == 0) { + /* Driver too old: use the old-style driverName field */ + ds->numDrivers = 1; + ds->driverNames = malloc(sizeof(*ds->driverNames)); + if (!ds->driverNames) { + free(ds); + return FALSE; + } + ds->driverNames[0] = info->driverName; + } else { + ds->numDrivers = info->numDrivers; + ds->driverNames = malloc(info->numDrivers * sizeof(*ds->driverNames)); + if (!ds->driverNames) { + free(ds); + return FALSE; + } + memcpy(ds->driverNames, info->driverNames, + info->numDrivers * sizeof(*ds->driverNames)); + } + + dixSetPrivate(&pScreen->devPrivates, dri2ScreenPrivateKey, ds); + + ds->ConfigNotify = pScreen->ConfigNotify; + pScreen->ConfigNotify = DRI2ConfigNotify; + + xf86DrvMsg(pScreen->myNum, X_INFO, "[DRI2] Setup complete\n"); + for (i = 0; i < sizeof(driverTypeNames) / sizeof(driverTypeNames[0]); i++) { + if (i < ds->numDrivers && ds->driverNames[i]) { + xf86DrvMsg(pScreen->myNum, X_INFO, "[DRI2] %s driver: %s\n", + driverTypeNames[i], ds->driverNames[i]); + } + } + + return TRUE; +} + +void +DRI2CloseScreen(ScreenPtr pScreen) +{ + DRI2ScreenPtr ds = DRI2GetScreen(pScreen); + + free(ds->driverNames); + free(ds); + dixSetPrivate(&pScreen->devPrivates, dri2ScreenPrivateKey, NULL); +} + +extern ExtensionModule dri2ExtensionModule; + +static pointer +DRI2Setup(pointer module, pointer opts, int *errmaj, int *errmin) +{ + static Bool setupDone = FALSE; + + dri2DrawableRes = CreateNewResourceType(DRI2DrawableGone, "DRI2Drawable"); + + if (!setupDone) + { + setupDone = TRUE; + LoadExtension(&dri2ExtensionModule, FALSE); + } + else + { + if (errmaj) + *errmaj = LDR_ONCEONLY; + } + + return (pointer) 1; +} + +static XF86ModuleVersionInfo DRI2VersRec = +{ + "dri2", + MODULEVENDORSTRING, + MODINFOSTRING1, + MODINFOSTRING2, + XORG_VERSION_CURRENT, + 1, 2, 0, + ABI_CLASS_EXTENSION, + ABI_EXTENSION_VERSION, + MOD_CLASS_NONE, + { 0, 0, 0, 0 } +}; + +_X_EXPORT XF86ModuleData dri2ModuleData = { &DRI2VersRec, DRI2Setup, NULL }; + +void +DRI2Version(int *major, int *minor) +{ + if (major != NULL) + *major = DRI2VersRec.majorversion; + + if (minor != NULL) + *minor = DRI2VersRec.minorversion; +} diff --git a/xorg-server/hw/xquartz/X11Application.m b/xorg-server/hw/xquartz/X11Application.m index c9a0d669f..805ed9933 100644 --- a/xorg-server/hw/xquartz/X11Application.m +++ b/xorg-server/hw/xquartz/X11Application.m @@ -1030,20 +1030,32 @@ static inline int ensure_flag(int flags, int device_independent, int device_depe if(isMouseOrTabletEvent) { static NSPoint lastpt; NSWindow *window = [e window]; - NSRect screen = [[[NSScreen screens] objectAtIndex:0] frame];; - + NSRect screen = [[[NSScreen screens] objectAtIndex:0] frame]; + BOOL hasUntrustedPointerDelta; + + // NSEvents for tablets are not consistent wrt deltaXY between events, so we cannot rely on that + // Thus tablets will be subject to the warp-pointer bug worked around by the delta, but tablets + // are not normally used in cases where that bug would present itself, so this is a fair tradeoff + // deltaX and deltaY are incorrect for NSMouseMoved, NSTabletPointEventSubtype + // http://xquartz.macosforge.org/trac/ticket/288 + hasUntrustedPointerDelta = isTabletEvent; + + // The deltaXY for middle click events also appear erroneous after fast user switching + // deltaX and deltaY are incorrect for NSOtherMouseDown and NSOtherMouseUp after FUS + // http://xquartz.macosforge.org/trac/ticket/389 + hasUntrustedPointerDelta = hasUntrustedPointerDelta || [e type] == NSOtherMouseDown || [e type] == NSOtherMouseUp; + + // The deltaXY for scroll events correspond to the scroll delta, not the pointer delta + // deltaXY for wheel events are being sent as mouse movement + hasUntrustedPointerDelta = hasUntrustedPointerDelta || [e type] == NSScrollWheel; + if (window != nil) { NSRect frame = [window frame]; location = [e locationInWindow]; location.x += frame.origin.x; location.y += frame.origin.y; lastpt = location; - } else if(isTabletEvent) { - // NSEvents for tablets are not consistent wrt deltaXY between events, so we cannot rely on that - // Thus tablets will be subject to the warp-pointer bug worked around by the delta, but tablets - // are not normally used in cases where that bug would present itself, so this is a fair tradeoff - // deltaX and deltaY are incorrect for NSMouseMoved, NSTabletPointEventSubtype - // http://xquartz.macosforge.org/trac/ticket/288 + } else if(hasUntrustedPointerDelta) { location = [e locationInWindow]; lastpt = location; } else { diff --git a/xorg-server/hw/xquartz/mach-startup/bundle-main.c b/xorg-server/hw/xquartz/mach-startup/bundle-main.c index 42aa757ea..63a185fc8 100644 --- a/xorg-server/hw/xquartz/mach-startup/bundle-main.c +++ b/xorg-server/hw/xquartz/mach-startup/bundle-main.c @@ -75,7 +75,12 @@ extern int noPanoramiXExtension; static char __crashreporter_info_buff__[4096] = {0}; static const char *__crashreporter_info__ = &__crashreporter_info_buff__[0]; +#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 +// This is actually a toolchain requirement, but I'm not sure the correct check, +// but it should be fine to just only include it for Leopard and later. This line +// just tells the linker to never strip this symbol (such as for space optimization) asm (".desc ___crashreporter_info__, 0x10"); +#endif static const char *__crashreporter_info__base = "X.Org X Server " XSERVER_VERSION " Build Date: " BUILD_DATE; diff --git a/xorg-server/os/log.c b/xorg-server/os/log.c index a377be7e8..42a4efefa 100644 --- a/xorg-server/os/log.c +++ b/xorg-server/os/log.c @@ -1,617 +1,624 @@ -/* - -Copyright 1987, 1998 The Open Group - -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. - -The above copyright notice and this permission notice 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 OPEN GROUP 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. - -Except as contained in this notice, the name of The Open Group shall -not be used in advertising or otherwise to promote the sale, use or -other dealings in this Software without prior written authorization -from The Open Group. - - -Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts, -Copyright 1994 Quarterdeck Office Systems. - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -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 names of Digital and -Quarterdeck not be used in advertising or publicity pertaining to -distribution of the software without specific, written prior -permission. - -DIGITAL AND QUARTERDECK DISCLAIM ALL WARRANTIES WITH REGARD TO THIS -SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS, IN NO EVENT SHALL DIGITAL 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. - -*/ - -/* - * Copyright (c) 1997-2003 by The XFree86 Project, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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. - * - * Except as contained in this notice, the name of the copyright holder(s) - * and author(s) shall not be used in advertising or otherwise to promote - * the sale, use or other dealings in this Software without prior written - * authorization from the copyright holder(s) and author(s). - */ - - -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include /* for malloc() */ -#include - -#include "input.h" -#include "site.h" -#include "opaque.h" - -#ifdef WIN32 -#include -#ifndef _MSC_VER -#define getpid(x) _getpid(x) -#endif -#endif - -#ifdef _MSC_VER -#define S_ISREG(m) (((m)&_S_IFMT) == _S_IFREG) -#endif - -#ifdef XF86BIGFONT -#include "xf86bigfontsrv.h" -#endif - -#ifdef DDXOSVERRORF -void (*OsVendorVErrorFProc)(const char *, va_list args) = NULL; -#endif - -static FILE *logFile = NULL; -static Bool logFlush = FALSE; -static Bool logSync = FALSE; -static int logVerbosity = DEFAULT_LOG_VERBOSITY; -static int logFileVerbosity = DEFAULT_LOG_FILE_VERBOSITY; - -/* Buffer to information logged before the log file is opened. */ -static char *saveBuffer = NULL; -static int bufferSize = 0, bufferUnused = 0, bufferPos = 0; -static Bool needBuffer = TRUE; - -#ifdef __APPLE__ -static char __crashreporter_info_buff__[4096] = {0}; -static const char *__crashreporter_info__ = &__crashreporter_info_buff__[0]; -asm (".desc ___crashreporter_info__, 0x10"); -#endif - -/* Prefix strings for log messages. */ -#ifndef X_UNKNOWN_STRING -#define X_UNKNOWN_STRING "(\?\?)" -#endif -#ifndef X_PROBE_STRING -#define X_PROBE_STRING "(--)" -#endif -#ifndef X_CONFIG_STRING -#define X_CONFIG_STRING "(**)" -#endif -#ifndef X_DEFAULT_STRING -#define X_DEFAULT_STRING "(==)" -#endif -#ifndef X_CMDLINE_STRING -#define X_CMDLINE_STRING "(++)" -#endif -#ifndef X_NOTICE_STRING -#define X_NOTICE_STRING "(!!)" -#endif -#ifndef X_ERROR_STRING -#define X_ERROR_STRING "(EE)" -#endif -#ifndef X_WARNING_STRING -#define X_WARNING_STRING "(WW)" -#endif -#ifndef X_INFO_STRING -#define X_INFO_STRING "(II)" -#endif -#ifndef X_NOT_IMPLEMENTED_STRING -#define X_NOT_IMPLEMENTED_STRING "(NI)" -#endif - -/* - * LogInit is called to start logging to a file. It is also called (with - * NULL arguments) when logging to a file is not wanted. It must always be - * called, otherwise log messages will continue to accumulate in a buffer. - * - * %s, if present in the fname or backup strings, is expanded to the display - * string. - */ - -const char * -LogInit(const char *fname, const char *backup) -{ - char *logFileName = NULL; - - if (fname && *fname) { - /* malloc() can't be used yet. */ - logFileName = malloc(strlen(fname) + strlen(display) + 1); - if (!logFileName) - FatalError("Cannot allocate space for the log file name\n"); - sprintf(logFileName, fname, display); - - if (backup && *backup) { - struct stat buf; - - if (!stat(logFileName, &buf) && S_ISREG(buf.st_mode)) { - char *suffix; - char *oldLog; - - oldLog = malloc(strlen(logFileName) + strlen(backup) + - strlen(display) + 1); - suffix = malloc(strlen(backup) + strlen(display) + 1); - if (!oldLog || !suffix) - FatalError("Cannot allocate space for the log file name\n"); - sprintf(suffix, backup, display); - sprintf(oldLog, "%s%s", logFileName, suffix); - free(suffix); - if (rename(logFileName, oldLog) == -1) { - FatalError("Cannot move old log file \"%s\" to \"%s\"\n", - logFileName, oldLog); - } - free(oldLog); - } - } - if ((logFile = fopen(logFileName, "w")) == NULL) - FatalError("Cannot open log file \"%s\"\n", logFileName); - setvbuf(logFile, NULL, _IONBF, 0); - - /* Flush saved log information. */ - if (saveBuffer && bufferSize > 0) { - fwrite(saveBuffer, bufferPos, 1, logFile); - fflush(logFile); -#ifndef WIN32 - fsync(fileno(logFile)); -#endif - } - } - - /* - * Unconditionally free the buffer, and flag that the buffer is no longer - * needed. - */ - if (saveBuffer && bufferSize > 0) { - free(saveBuffer); /* Must be free(), not free() */ - saveBuffer = NULL; - bufferSize = 0; - } - needBuffer = FALSE; - - return logFileName; -} - -void -LogClose(void) -{ - if (logFile) { - fclose(logFile); - logFile = NULL; - } -} - -Bool -LogSetParameter(LogParameter param, int value) -{ - switch (param) { - case XLOG_FLUSH: - logFlush = value ? TRUE : FALSE; - return TRUE; - case XLOG_SYNC: - logSync = value ? TRUE : FALSE; - return TRUE; - case XLOG_VERBOSITY: - logVerbosity = value; - return TRUE; - case XLOG_FILE_VERBOSITY: - logFileVerbosity = value; - return TRUE; - default: - return FALSE; - } -} - -/* This function does the actual log message writes. */ - -void -LogVWrite(int verb, const char *f, va_list args) -{ - char tmpBuffer[1024]; - int len = 0; - static Bool newline = TRUE; - - if (newline) { - sprintf(tmpBuffer, "[%10.3f] ", GetTimeInMillis() / 1000.0); - len = strlen(tmpBuffer); - if (logFile) - fwrite(tmpBuffer, len, 1, logFile); - } - - /* - * Since a va_list can only be processed once, write the string to a - * buffer, and then write the buffer out to the appropriate output - * stream(s). - */ - if (verb < 0 || logFileVerbosity >= verb || logVerbosity >= verb) { - vsnprintf(tmpBuffer, sizeof(tmpBuffer)-1, f, args); - tmpBuffer[sizeof(tmpBuffer)-1]=0; - len = strlen(tmpBuffer); - } - newline = (tmpBuffer[len-1] == '\n'); - if ((verb < 0 || logVerbosity >= verb) && len > 0) - fwrite(tmpBuffer, len, 1, stderr); - if ((verb < 0 || logFileVerbosity >= verb) && len > 0) { - if (logFile) { - fwrite(tmpBuffer, len, 1, logFile); - if (logFlush) { - fflush(logFile); -#ifndef WIN32 - if (logSync) - fsync(fileno(logFile)); -#endif - } - } else if (needBuffer) { - /* - * Note, this code is used before OsInit() has been called, so - * malloc() and friends can't be used. - */ - if (len > bufferUnused) { - bufferSize += 1024; - bufferUnused += 1024; - if (saveBuffer) - saveBuffer = realloc(saveBuffer, bufferSize); - else - saveBuffer = malloc(bufferSize); - if (!saveBuffer) - FatalError("realloc() failed while saving log messages\n"); - } - bufferUnused -= len; - memcpy(saveBuffer + bufferPos, tmpBuffer, len); - bufferPos += len; - } - } -} - -void -LogWrite(int verb, const char *f, ...) -{ - va_list args; - - va_start(args, f); - LogVWrite(verb, f, args); - va_end(args); -} - -void -LogVMessageVerb(MessageType type, int verb, const char *format, va_list args) -{ - const char *s = X_UNKNOWN_STRING; - char tmpBuf[1024]; - - /* Ignore verbosity for X_ERROR */ - if (logVerbosity >= verb || logFileVerbosity >= verb || type == X_ERROR) { - switch (type) { - case X_PROBED: - s = X_PROBE_STRING; - break; - case X_CONFIG: - s = X_CONFIG_STRING; - break; - case X_DEFAULT: - s = X_DEFAULT_STRING; - break; - case X_CMDLINE: - s = X_CMDLINE_STRING; - break; - case X_NOTICE: - s = X_NOTICE_STRING; - break; - case X_ERROR: - s = X_ERROR_STRING; - if (verb > 0) - verb = 0; - break; - case X_WARNING: - s = X_WARNING_STRING; - break; - case X_INFO: - s = X_INFO_STRING; - break; - case X_NOT_IMPLEMENTED: - s = X_NOT_IMPLEMENTED_STRING; - break; - case X_UNKNOWN: - s = X_UNKNOWN_STRING; - break; - case X_NONE: - s = NULL; - break; - } - - /* if s is not NULL we need a space before format */ - snprintf(tmpBuf, sizeof(tmpBuf), "%s%s%s", s ? s : "", - s ? " " : "", - format); - LogVWrite(verb, tmpBuf, args); - } -} - -/* Log message with verbosity level specified. */ -void -LogMessageVerb(MessageType type, int verb, const char *format, ...) -{ - va_list ap; - - va_start(ap, format); - LogVMessageVerb(type, verb, format, ap); - va_end(ap); -} - -/* Log a message with the standard verbosity level of 1. */ -void -LogMessage(MessageType type, const char *format, ...) -{ - va_list ap; - - va_start(ap, format); - LogVMessageVerb(type, 1, format, ap); - va_end(ap); -} - -void -AbortServer(void) _X_NORETURN; - -void -AbortServer(void) -{ -#ifdef XF86BIGFONT - XF86BigfontCleanup(); -#endif - CloseWellKnownConnections(); - OsCleanup(TRUE); - CloseDownDevices(); - AbortDDX(); - fflush(stderr); - if (CoreDump) - OsAbort(); - exit (1); -} - -#define AUDIT_PREFIX "AUDIT: %s: %ld: " -#ifndef AUDIT_TIMEOUT -#define AUDIT_TIMEOUT ((CARD32)(120 * 1000)) /* 2 mn */ -#endif - -static int nrepeat = 0; -static int oldlen = -1; -static OsTimerPtr auditTimer = NULL; - -void -FreeAuditTimer(void) -{ - if (auditTimer != NULL) { - /* Force output of pending messages */ - TimerForce(auditTimer); - TimerFree(auditTimer); - auditTimer = NULL; - } -} - -static char * -AuditPrefix(void) -{ - time_t tm; - char *autime, *s; - char *tmpBuf; - int len; - - time(&tm); - autime = ctime(&tm); - if ((s = strchr(autime, '\n'))) - *s = '\0'; - len = strlen(AUDIT_PREFIX) + strlen(autime) + 10 + 1; - tmpBuf = malloc(len); - if (!tmpBuf) - return NULL; - snprintf(tmpBuf, len, AUDIT_PREFIX, autime, (unsigned long)getpid()); - return tmpBuf; -} - -void -AuditF(const char * f, ...) -{ - va_list args; - - va_start(args, f); - - VAuditF(f, args); - va_end(args); -} - -static CARD32 -AuditFlush(OsTimerPtr timer, CARD32 now, pointer arg) -{ - char *prefix; - - if (nrepeat > 0) { - prefix = AuditPrefix(); - ErrorF("%slast message repeated %d times\n", - prefix != NULL ? prefix : "", nrepeat); - nrepeat = 0; - if (prefix != NULL) - free(prefix); - return AUDIT_TIMEOUT; - } else { - /* if the timer expires without anything to print, flush the message */ - oldlen = -1; - return 0; - } -} - -void -VAuditF(const char *f, va_list args) -{ - char *prefix; - char buf[1024]; - int len; - static char oldbuf[1024]; - - prefix = AuditPrefix(); - len = vsnprintf(buf, sizeof(buf), f, args); - - if (len == oldlen && strcmp(buf, oldbuf) == 0) { - /* Message already seen */ - nrepeat++; - } else { - /* new message */ - if (auditTimer != NULL) - TimerForce(auditTimer); - ErrorF("%s%s", prefix != NULL ? prefix : "", buf); - strlcpy(oldbuf, buf, sizeof(oldbuf)); - oldlen = len; - nrepeat = 0; - auditTimer = TimerSet(auditTimer, 0, AUDIT_TIMEOUT, AuditFlush, NULL); - } - if (prefix != NULL) - free(prefix); -} - -void -FatalError(const char *f, ...) -{ - va_list args; - static Bool beenhere = FALSE; - - if (beenhere) - ErrorF("\nFatalError re-entered, aborting\n"); - else - ErrorF("\nFatal server error:\n"); - - va_start(args, f); -#ifdef __APPLE__ - (void)vsnprintf(__crashreporter_info_buff__, sizeof(__crashreporter_info_buff__), f, args); -#endif - VErrorF(f, args); - va_end(args); - ErrorF("\n"); - if (!beenhere) - OsVendorFatalError(); - if (!beenhere) { - beenhere = TRUE; - AbortServer(); - } else - OsAbort(); - /*NOTREACHED*/ -} - -void -VErrorF(const char *f, va_list args) -{ -#ifdef DDXOSVERRORF - if (OsVendorVErrorFProc) - OsVendorVErrorFProc(f, args); - else - LogVWrite(-1, f, args); -#else - LogVWrite(-1, f, args); -#endif -} - -void -ErrorF(const char * f, ...) -{ - va_list args; - - va_start(args, f); - VErrorF(f, args); - va_end(args); -} - -/* A perror() workalike. */ - -void -Error(char *str) -{ - char *err = NULL; - int saveErrno = errno; - - if (str) { - err = malloc(strlen(strerror(saveErrno)) + strlen(str) + 2 + 1); - if (!err) - return; - sprintf(err, "%s: ", str); - strcat(err, strerror(saveErrno)); - LogWrite(-1, "%s", err); - free(err); - } else - LogWrite(-1, "%s", strerror(saveErrno)); -} - -void -LogPrintMarkers(void) -{ - /* Show what the message marker symbols mean. */ - LogWrite(0, "Markers: "); - LogMessageVerb(X_PROBED, 0, "probed, "); - LogMessageVerb(X_CONFIG, 0, "from config file, "); - LogMessageVerb(X_DEFAULT, 0, "default setting,\n\t"); - LogMessageVerb(X_CMDLINE, 0, "from command line, "); - LogMessageVerb(X_NOTICE, 0, "notice, "); - LogMessageVerb(X_INFO, 0, "informational,\n\t"); - LogMessageVerb(X_WARNING, 0, "warning, "); - LogMessageVerb(X_ERROR, 0, "error, "); - LogMessageVerb(X_NOT_IMPLEMENTED, 0, "not implemented, "); - LogMessageVerb(X_UNKNOWN, 0, "unknown.\n"); -} - +/* + +Copyright 1987, 1998 The Open Group + +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. + +The above copyright notice and this permission notice 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 OPEN GROUP 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. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts, +Copyright 1994 Quarterdeck Office Systems. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +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 names of Digital and +Quarterdeck not be used in advertising or publicity pertaining to +distribution of the software without specific, written prior +permission. + +DIGITAL AND QUARTERDECK DISCLAIM ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS, IN NO EVENT SHALL DIGITAL 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. + +*/ + +/* + * Copyright (c) 1997-2003 by The XFree86 Project, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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. + * + * Except as contained in this notice, the name of the copyright holder(s) + * and author(s) shall not be used in advertising or otherwise to promote + * the sale, use or other dealings in this Software without prior written + * authorization from the copyright holder(s) and author(s). + */ + + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include /* for malloc() */ +#include + +#include "input.h" +#include "site.h" +#include "opaque.h" + +#ifdef WIN32 +#include +#ifndef _MSC_VER +#define getpid(x) _getpid(x) +#endif +#endif + +#ifdef _MSC_VER +#define S_ISREG(m) (((m)&_S_IFMT) == _S_IFREG) +#endif + +#ifdef XF86BIGFONT +#include "xf86bigfontsrv.h" +#endif + +#ifdef DDXOSVERRORF +void (*OsVendorVErrorFProc)(const char *, va_list args) = NULL; +#endif + +static FILE *logFile = NULL; +static Bool logFlush = FALSE; +static Bool logSync = FALSE; +static int logVerbosity = DEFAULT_LOG_VERBOSITY; +static int logFileVerbosity = DEFAULT_LOG_FILE_VERBOSITY; + +/* Buffer to information logged before the log file is opened. */ +static char *saveBuffer = NULL; +static int bufferSize = 0, bufferUnused = 0, bufferPos = 0; +static Bool needBuffer = TRUE; + +#ifdef __APPLE__ +#include + +static char __crashreporter_info_buff__[4096] = {0}; +static const char *__crashreporter_info__ = &__crashreporter_info_buff__[0]; +#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 +// This is actually a toolchain requirement, but I'm not sure the correct check, +// but it should be fine to just only include it for Leopard and later. This line +// just tells the linker to never strip this symbol (such as for space optimization) +asm (".desc ___crashreporter_info__, 0x10"); +#endif +#endif + +/* Prefix strings for log messages. */ +#ifndef X_UNKNOWN_STRING +#define X_UNKNOWN_STRING "(\?\?)" +#endif +#ifndef X_PROBE_STRING +#define X_PROBE_STRING "(--)" +#endif +#ifndef X_CONFIG_STRING +#define X_CONFIG_STRING "(**)" +#endif +#ifndef X_DEFAULT_STRING +#define X_DEFAULT_STRING "(==)" +#endif +#ifndef X_CMDLINE_STRING +#define X_CMDLINE_STRING "(++)" +#endif +#ifndef X_NOTICE_STRING +#define X_NOTICE_STRING "(!!)" +#endif +#ifndef X_ERROR_STRING +#define X_ERROR_STRING "(EE)" +#endif +#ifndef X_WARNING_STRING +#define X_WARNING_STRING "(WW)" +#endif +#ifndef X_INFO_STRING +#define X_INFO_STRING "(II)" +#endif +#ifndef X_NOT_IMPLEMENTED_STRING +#define X_NOT_IMPLEMENTED_STRING "(NI)" +#endif + +/* + * LogInit is called to start logging to a file. It is also called (with + * NULL arguments) when logging to a file is not wanted. It must always be + * called, otherwise log messages will continue to accumulate in a buffer. + * + * %s, if present in the fname or backup strings, is expanded to the display + * string. + */ + +const char * +LogInit(const char *fname, const char *backup) +{ + char *logFileName = NULL; + + if (fname && *fname) { + /* malloc() can't be used yet. */ + logFileName = malloc(strlen(fname) + strlen(display) + 1); + if (!logFileName) + FatalError("Cannot allocate space for the log file name\n"); + sprintf(logFileName, fname, display); + + if (backup && *backup) { + struct stat buf; + + if (!stat(logFileName, &buf) && S_ISREG(buf.st_mode)) { + char *suffix; + char *oldLog; + + oldLog = malloc(strlen(logFileName) + strlen(backup) + + strlen(display) + 1); + suffix = malloc(strlen(backup) + strlen(display) + 1); + if (!oldLog || !suffix) + FatalError("Cannot allocate space for the log file name\n"); + sprintf(suffix, backup, display); + sprintf(oldLog, "%s%s", logFileName, suffix); + free(suffix); + if (rename(logFileName, oldLog) == -1) { + FatalError("Cannot move old log file \"%s\" to \"%s\"\n", + logFileName, oldLog); + } + free(oldLog); + } + } + if ((logFile = fopen(logFileName, "w")) == NULL) + FatalError("Cannot open log file \"%s\"\n", logFileName); + setvbuf(logFile, NULL, _IONBF, 0); + + /* Flush saved log information. */ + if (saveBuffer && bufferSize > 0) { + fwrite(saveBuffer, bufferPos, 1, logFile); + fflush(logFile); +#ifndef WIN32 + fsync(fileno(logFile)); +#endif + } + } + + /* + * Unconditionally free the buffer, and flag that the buffer is no longer + * needed. + */ + if (saveBuffer && bufferSize > 0) { + free(saveBuffer); /* Must be free(), not free() */ + saveBuffer = NULL; + bufferSize = 0; + } + needBuffer = FALSE; + + return logFileName; +} + +void +LogClose(void) +{ + if (logFile) { + fclose(logFile); + logFile = NULL; + } +} + +Bool +LogSetParameter(LogParameter param, int value) +{ + switch (param) { + case XLOG_FLUSH: + logFlush = value ? TRUE : FALSE; + return TRUE; + case XLOG_SYNC: + logSync = value ? TRUE : FALSE; + return TRUE; + case XLOG_VERBOSITY: + logVerbosity = value; + return TRUE; + case XLOG_FILE_VERBOSITY: + logFileVerbosity = value; + return TRUE; + default: + return FALSE; + } +} + +/* This function does the actual log message writes. */ + +void +LogVWrite(int verb, const char *f, va_list args) +{ + char tmpBuffer[1024]; + int len = 0; + static Bool newline = TRUE; + + if (newline) { + sprintf(tmpBuffer, "[%10.3f] ", GetTimeInMillis() / 1000.0); + len = strlen(tmpBuffer); + if (logFile) + fwrite(tmpBuffer, len, 1, logFile); + } + + /* + * Since a va_list can only be processed once, write the string to a + * buffer, and then write the buffer out to the appropriate output + * stream(s). + */ + if (verb < 0 || logFileVerbosity >= verb || logVerbosity >= verb) { + vsnprintf(tmpBuffer, sizeof(tmpBuffer)-1, f, args); + tmpBuffer[sizeof(tmpBuffer)-1]=0; + len = strlen(tmpBuffer); + } + newline = (tmpBuffer[len-1] == '\n'); + if ((verb < 0 || logVerbosity >= verb) && len > 0) + fwrite(tmpBuffer, len, 1, stderr); + if ((verb < 0 || logFileVerbosity >= verb) && len > 0) { + if (logFile) { + fwrite(tmpBuffer, len, 1, logFile); + if (logFlush) { + fflush(logFile); +#ifndef WIN32 + if (logSync) + fsync(fileno(logFile)); +#endif + } + } else if (needBuffer) { + /* + * Note, this code is used before OsInit() has been called, so + * malloc() and friends can't be used. + */ + if (len > bufferUnused) { + bufferSize += 1024; + bufferUnused += 1024; + if (saveBuffer) + saveBuffer = realloc(saveBuffer, bufferSize); + else + saveBuffer = malloc(bufferSize); + if (!saveBuffer) + FatalError("realloc() failed while saving log messages\n"); + } + bufferUnused -= len; + memcpy(saveBuffer + bufferPos, tmpBuffer, len); + bufferPos += len; + } + } +} + +void +LogWrite(int verb, const char *f, ...) +{ + va_list args; + + va_start(args, f); + LogVWrite(verb, f, args); + va_end(args); +} + +void +LogVMessageVerb(MessageType type, int verb, const char *format, va_list args) +{ + const char *s = X_UNKNOWN_STRING; + char tmpBuf[1024]; + + /* Ignore verbosity for X_ERROR */ + if (logVerbosity >= verb || logFileVerbosity >= verb || type == X_ERROR) { + switch (type) { + case X_PROBED: + s = X_PROBE_STRING; + break; + case X_CONFIG: + s = X_CONFIG_STRING; + break; + case X_DEFAULT: + s = X_DEFAULT_STRING; + break; + case X_CMDLINE: + s = X_CMDLINE_STRING; + break; + case X_NOTICE: + s = X_NOTICE_STRING; + break; + case X_ERROR: + s = X_ERROR_STRING; + if (verb > 0) + verb = 0; + break; + case X_WARNING: + s = X_WARNING_STRING; + break; + case X_INFO: + s = X_INFO_STRING; + break; + case X_NOT_IMPLEMENTED: + s = X_NOT_IMPLEMENTED_STRING; + break; + case X_UNKNOWN: + s = X_UNKNOWN_STRING; + break; + case X_NONE: + s = NULL; + break; + } + + /* if s is not NULL we need a space before format */ + snprintf(tmpBuf, sizeof(tmpBuf), "%s%s%s", s ? s : "", + s ? " " : "", + format); + LogVWrite(verb, tmpBuf, args); + } +} + +/* Log message with verbosity level specified. */ +void +LogMessageVerb(MessageType type, int verb, const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + LogVMessageVerb(type, verb, format, ap); + va_end(ap); +} + +/* Log a message with the standard verbosity level of 1. */ +void +LogMessage(MessageType type, const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + LogVMessageVerb(type, 1, format, ap); + va_end(ap); +} + +void +AbortServer(void) _X_NORETURN; + +void +AbortServer(void) +{ +#ifdef XF86BIGFONT + XF86BigfontCleanup(); +#endif + CloseWellKnownConnections(); + OsCleanup(TRUE); + CloseDownDevices(); + AbortDDX(); + fflush(stderr); + if (CoreDump) + OsAbort(); + exit (1); +} + +#define AUDIT_PREFIX "AUDIT: %s: %ld: " +#ifndef AUDIT_TIMEOUT +#define AUDIT_TIMEOUT ((CARD32)(120 * 1000)) /* 2 mn */ +#endif + +static int nrepeat = 0; +static int oldlen = -1; +static OsTimerPtr auditTimer = NULL; + +void +FreeAuditTimer(void) +{ + if (auditTimer != NULL) { + /* Force output of pending messages */ + TimerForce(auditTimer); + TimerFree(auditTimer); + auditTimer = NULL; + } +} + +static char * +AuditPrefix(void) +{ + time_t tm; + char *autime, *s; + char *tmpBuf; + int len; + + time(&tm); + autime = ctime(&tm); + if ((s = strchr(autime, '\n'))) + *s = '\0'; + len = strlen(AUDIT_PREFIX) + strlen(autime) + 10 + 1; + tmpBuf = malloc(len); + if (!tmpBuf) + return NULL; + snprintf(tmpBuf, len, AUDIT_PREFIX, autime, (unsigned long)getpid()); + return tmpBuf; +} + +void +AuditF(const char * f, ...) +{ + va_list args; + + va_start(args, f); + + VAuditF(f, args); + va_end(args); +} + +static CARD32 +AuditFlush(OsTimerPtr timer, CARD32 now, pointer arg) +{ + char *prefix; + + if (nrepeat > 0) { + prefix = AuditPrefix(); + ErrorF("%slast message repeated %d times\n", + prefix != NULL ? prefix : "", nrepeat); + nrepeat = 0; + if (prefix != NULL) + free(prefix); + return AUDIT_TIMEOUT; + } else { + /* if the timer expires without anything to print, flush the message */ + oldlen = -1; + return 0; + } +} + +void +VAuditF(const char *f, va_list args) +{ + char *prefix; + char buf[1024]; + int len; + static char oldbuf[1024]; + + prefix = AuditPrefix(); + len = vsnprintf(buf, sizeof(buf), f, args); + + if (len == oldlen && strcmp(buf, oldbuf) == 0) { + /* Message already seen */ + nrepeat++; + } else { + /* new message */ + if (auditTimer != NULL) + TimerForce(auditTimer); + ErrorF("%s%s", prefix != NULL ? prefix : "", buf); + strlcpy(oldbuf, buf, sizeof(oldbuf)); + oldlen = len; + nrepeat = 0; + auditTimer = TimerSet(auditTimer, 0, AUDIT_TIMEOUT, AuditFlush, NULL); + } + if (prefix != NULL) + free(prefix); +} + +void +FatalError(const char *f, ...) +{ + va_list args; + static Bool beenhere = FALSE; + + if (beenhere) + ErrorF("\nFatalError re-entered, aborting\n"); + else + ErrorF("\nFatal server error:\n"); + + va_start(args, f); +#ifdef __APPLE__ + (void)vsnprintf(__crashreporter_info_buff__, sizeof(__crashreporter_info_buff__), f, args); +#endif + VErrorF(f, args); + va_end(args); + ErrorF("\n"); + if (!beenhere) + OsVendorFatalError(); + if (!beenhere) { + beenhere = TRUE; + AbortServer(); + } else + OsAbort(); + /*NOTREACHED*/ +} + +void +VErrorF(const char *f, va_list args) +{ +#ifdef DDXOSVERRORF + if (OsVendorVErrorFProc) + OsVendorVErrorFProc(f, args); + else + LogVWrite(-1, f, args); +#else + LogVWrite(-1, f, args); +#endif +} + +void +ErrorF(const char * f, ...) +{ + va_list args; + + va_start(args, f); + VErrorF(f, args); + va_end(args); +} + +/* A perror() workalike. */ + +void +Error(char *str) +{ + char *err = NULL; + int saveErrno = errno; + + if (str) { + err = malloc(strlen(strerror(saveErrno)) + strlen(str) + 2 + 1); + if (!err) + return; + sprintf(err, "%s: ", str); + strcat(err, strerror(saveErrno)); + LogWrite(-1, "%s", err); + free(err); + } else + LogWrite(-1, "%s", strerror(saveErrno)); +} + +void +LogPrintMarkers(void) +{ + /* Show what the message marker symbols mean. */ + LogWrite(0, "Markers: "); + LogMessageVerb(X_PROBED, 0, "probed, "); + LogMessageVerb(X_CONFIG, 0, "from config file, "); + LogMessageVerb(X_DEFAULT, 0, "default setting,\n\t"); + LogMessageVerb(X_CMDLINE, 0, "from command line, "); + LogMessageVerb(X_NOTICE, 0, "notice, "); + LogMessageVerb(X_INFO, 0, "informational,\n\t"); + LogMessageVerb(X_WARNING, 0, "warning, "); + LogMessageVerb(X_ERROR, 0, "error, "); + LogMessageVerb(X_NOT_IMPLEMENTED, 0, "not implemented, "); + LogMessageVerb(X_UNKNOWN, 0, "unknown.\n"); +} + -- cgit v1.2.3