xserver: Branch 'master' - 36 commits

Keith Packard keithp at kemper.freedesktop.org
Tue Nov 25 23:19:10 PST 2008


 acinclude.m4                   |   60 ++++-
 configure.ac                   |   12 -
 hw/xfree86/dri/Makefile.am     |    5 
 hw/xfree86/dri/dri.c           |   19 +
 hw/xfree86/dri/dristruct.h     |    2 
 hw/xfree86/loader/xf86sym.c    |    3 
 hw/xfree86/modes/xf86Crtc.c    |  106 ++++++++-
 hw/xfree86/modes/xf86Crtc.h    |   33 ++
 hw/xfree86/modes/xf86Cursors.c |   35 +--
 hw/xfree86/modes/xf86RandR12.c |   62 ++++-
 hw/xfree86/modes/xf86RandR12.h |    1 
 hw/xfree86/modes/xf86Rename.h  |    1 
 hw/xfree86/modes/xf86Rotate.c  |  469 ++++++++++++++---------------------------
 randr/Makefile.am              |    6 
 randr/mirandr.c                |    2 
 randr/randrstr.h               |   66 +++++
 randr/rrcrtc.c                 |  320 +++++++++++++++++++++++++--
 randr/rrdispatch.c             |    5 
 randr/rrinfo.c                 |    2 
 randr/rrproperty.c             |    4 
 randr/rrsdispatch.c            |   23 ++
 randr/rrtransform.c            |  260 ++++++++++++++++++++++
 randr/rrtransform.h            |   75 ++++++
 render/Makefile.am             |    1 
 render/filter.c                |   82 +++++--
 render/matrix.c                |   88 +++++++
 render/mipict.c                |    2 
 render/picture.c               |   64 -----
 render/picturestr.h            |   48 +++-
 29 files changed, 1354 insertions(+), 502 deletions(-)

New commits:
commit f3edc1fb0210149f35eab4e413700b5c4ac48214
Author: Keith Packard <keithp at keithp.com>
Date:   Tue Nov 25 23:15:35 2008 -0800

    New version of dolt

diff --git a/acinclude.m4 b/acinclude.m4
index 833b557..efece2a 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -7,15 +7,12 @@ dnl
 dnl To use dolt, invoke the DOLT macro immediately after the libtool macros.
 dnl Optionally, copy this file into acinclude.m4, to avoid the need to have it
 dnl installed when running autoconf on your project.
-dnl
-dnl git snapshot: d91f2b4e9041538400e2703a2a6fbeecdb8ee27d
+
 AC_DEFUN([DOLT], [
 AC_REQUIRE([AC_CANONICAL_HOST])
 # dolt, a replacement for libtool
 # Josh Triplett <josh at freedesktop.org>
 AC_PATH_PROG(DOLT_BASH, bash)
-AC_MSG_CHECKING([if libtool sucks])
-AC_MSG_RESULT([yup, it does])
 AC_MSG_CHECKING([if dolt supports this host])
 dolt_supported=yes
 if test x$DOLT_BASH = x; then
@@ -25,9 +22,16 @@ if test x$GCC != xyes; then
     dolt_supported=no
 fi
 case $host in
-i?86-*-linux*|x86_64-*-linux*|powerpc-*-linux*) ;;
-amd64-*-freebsd*|i?86-*-freebsd*|ia64-*-freebsd*) ;;
-*) dolt_supported=no ;;
+i?86-*-linux*|x86_64-*-linux*|powerpc-*-linux* \
+|amd64-*-freebsd*|i?86-*-freebsd*|ia64-*-freebsd*)
+    pic_options='-fPIC'
+    ;;
+i?86-apple-darwin*)
+    pic_options='-fno-common'
+    ;;
+*)
+    dolt_supported=no
+    ;;
 esac
 if test x$dolt_supported = xno ; then
     AC_MSG_RESULT([no, falling back to libtool])
@@ -75,7 +79,9 @@ if test ! -d "$libobjdir" ; then
 fi
 pic_object="$libobjdir/$objbase.o"
 args@<:@$objarg@:>@="$pic_object"
-"${args@<:@@@:>@}" -fPIC -DPIC || exit $?
+__DOLTCOMPILE__EOF__
+    cat <<__DOLTCOMPILE__EOF__ >>doltcompile
+"\${args@<:@@@:>@}" $pic_options -DPIC || exit \$?
 __DOLTCOMPILE__EOF__
     fi
 
@@ -107,7 +113,7 @@ __DOLTCOMPILE__EOF__
 
     if test x$enable_shared = xyes; then
         cat <<'__DOLTCOMPILE__EOF__' >>doltcompile
-echo "pic_object='$pic_object'"
+echo "pic_object='.libs/${objbase}.o'"
 __DOLTCOMPILE__EOF__
     else
         cat <<'__DOLTCOMPILE__EOF__' >>doltcompile
@@ -117,7 +123,7 @@ __DOLTCOMPILE__EOF__
 
     if test x$enable_static = xyes; then
         cat <<'__DOLTCOMPILE__EOF__' >>doltcompile
-echo "non_pic_object='$non_pic_object'"
+echo "non_pic_object='${objbase}.o'"
 __DOLTCOMPILE__EOF__
     else
         cat <<'__DOLTCOMPILE__EOF__' >>doltcompile
@@ -133,15 +139,43 @@ dnl Done writing out doltcompile; substitute it for libtool compilation.
     chmod +x doltcompile
     LTCOMPILE='$(top_builddir)/doltcompile $(COMPILE)'
     LTCXXCOMPILE='$(top_builddir)/doltcompile $(CXXCOMPILE)'
+
+dnl automake ignores LTCOMPILE and LTCXXCOMPILE when it has separate CFLAGS for
+dnl a target, so write out a libtool wrapper to handle that case.
+dnl Note that doltlibtool does not handle inferred tags or option arguments
+dnl without '=', because automake does not use them.
+    cat <<__DOLTLIBTOOL__EOF__ > doltlibtool
+#!$DOLT_BASH
+__DOLTLIBTOOL__EOF__
+    cat <<'__DOLTLIBTOOL__EOF__' >>doltlibtool
+top_builddir_slash="${0%%doltlibtool}"
+: ${top_builddir_slash:=./}
+args=()
+modeok=false
+tagok=false
+for arg in "$[]@"; do
+    case "$arg" in
+        --mode=compile) modeok=true ;;
+        --tag=CC|--tag=CXX) tagok=true ;;
+        *) args+=("$arg")
+    esac
+done
+if $modeok && $tagok ; then
+    . ${top_builddir_slash}doltcompile "${args@<:@@@:>@}"
+else
+    exec ${top_builddir_slash}libtool "$[]@"
+fi
+__DOLTLIBTOOL__EOF__
+
+dnl Done writing out doltlibtool; substitute it for libtool.
+    chmod +x doltlibtool
+    LIBTOOL='$(top_builddir)/doltlibtool'
 fi
 AC_SUBST(LTCOMPILE)
 AC_SUBST(LTCXXCOMPILE)
 # end dolt
 ])
 
-
-
-
 # ===========================================================================
 #             http://autoconf-archive.cryp.to/ac_define_dir.html
 # ===========================================================================
commit 4715f079b9c61362755c95c1ebf89c97cc6fff2b
Merge: 9ffc671... ed597f1...
Author: Keith Packard <keithp at keithp.com>
Date:   Tue Nov 25 22:19:08 2008 -0800

    Merge commit 'origin/master'

commit 9ffc6719390df8fdd0a5295a7a7a0eaea792be45
Author: Keith Packard <keithp at keithp.com>
Date:   Mon Nov 24 13:08:48 2008 -0800

    Move matrix operations from X server to pixman 0.13.2
    
    pixman 0.13.2 now holds all of the matrix operations. This leaves
    the protocol conversion routines and some ABI stubs in place
    
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/configure.ac b/configure.ac
index 79f9b25..200c141 100644
--- a/configure.ac
+++ b/configure.ac
@@ -665,7 +665,7 @@ XEXTXORG_LIB='$(top_builddir)/Xext/libXextbuiltin.la'
 
 dnl Core modules for most extensions, et al.
 REQUIRED_MODULES="[randrproto >= 1.2] [renderproto >= 0.9.3] [fixesproto >= 4.0] [damageproto >= 1.1] xcmiscproto [xextproto >= 7.0.3] [xproto >= 7.0.13] [xtrans >= 1.2.2] bigreqsproto resourceproto fontsproto [inputproto >= 1.9.99.6] [kbproto >= 1.0.3]"
-REQUIRED_LIBS="xfont xau fontenc [pixman-1 >= 0.9.5]"
+REQUIRED_LIBS="xfont xau fontenc [pixman-1 >= 0.13.2]"
 
 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
@@ -1181,7 +1181,7 @@ AC_MSG_RESULT([$XVFB])
 AM_CONDITIONAL(XVFB, [test "x$XVFB" = xyes])
 
 if test "x$XVFB" = xyes; then
-	XVFB_LIBS="$FB_LIB $FIXES_LIB $XEXT_LIB $CONFIG_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RENDER_LIB $RANDR_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB"
+	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])
@@ -1228,7 +1228,7 @@ if test "x$XORG" = xyes; then
 	XORG_OSINCS='-I$(top_srcdir)/hw/xfree86/os-support -I$(top_srcdir)/hw/xfree86/os-support/bus -I$(top_srcdir)/os'
 	XORG_INCS="$XORG_DDXINCS $XORG_OSINCS"
 	XORG_CFLAGS="$XORGSERVER_CFLAGS -DHAVE_XORG_CONFIG_H"
-	XORG_LIBS="$COMPOSITE_LIB $FIXES_LIB $XEXTXORG_LIB $GLX_LIBS $RENDER_LIB $RANDR_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $SELINUX_LIB"
+	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 $SELINUX_LIB"
 
 	PKG_CHECK_MODULES([PCIACCESS], [pciaccess >= 0.8.0])
 	SAVE_LIBS=$LIBS
@@ -1536,7 +1536,7 @@ 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 $FB_LIB $FIXES_LIB $XEXT_LIB $CONFIG_LIB $DBE_LIB $RECORD_LIB $RENDER_LIB $RANDR_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $XPSTUBS_LIB"
+	DARWIN_LIBS="$MI_LIB $OS_LIB $DIX_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],[:])
@@ -1714,7 +1714,7 @@ if test "$KDRIVE" = yes; then
     
     KDRIVE_CFLAGS="$XSERVER_CFLAGS -DHAVE_KDRIVE_CONFIG_H $TSLIB_CFLAGS"
 
-    KDRIVE_PURE_LIBS="$FB_LIB $MI_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RENDER_LIB $RANDR_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $OS_LIB"
+    KDRIVE_PURE_LIBS="$FB_LIB $MI_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $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.a'
     case $host_os in
 	*linux*)
diff --git a/hw/xfree86/modes/xf86Crtc.c b/hw/xfree86/modes/xf86Crtc.c
index 7dce1ab..fe9d7b0 100644
--- a/hw/xfree86/modes/xf86Crtc.c
+++ b/hw/xfree86/modes/xf86Crtc.c
@@ -103,9 +103,9 @@ xf86CrtcCreate (ScrnInfoPtr		scrn,
 #endif
     crtc->rotation = RR_Rotate_0;
     crtc->desiredRotation = RR_Rotate_0;
-    PictureTransformInitIdentity (&crtc->crtc_to_framebuffer);
-    pict_f_transform_init_identity (&crtc->f_crtc_to_framebuffer);
-    pict_f_transform_init_identity (&crtc->f_framebuffer_to_crtc);
+    pixman_transform_init_identity (&crtc->crtc_to_framebuffer);
+    pixman_f_transform_init_identity (&crtc->f_crtc_to_framebuffer);
+    pixman_f_transform_init_identity (&crtc->f_framebuffer_to_crtc);
     crtc->filter = NULL;
     crtc->params = NULL;
     crtc->nparams = 0;
diff --git a/hw/xfree86/modes/xf86Cursors.c b/hw/xfree86/modes/xf86Cursors.c
index cd4f9e8..a58b001 100644
--- a/hw/xfree86/modes/xf86Cursors.c
+++ b/hw/xfree86/modes/xf86Cursors.c
@@ -329,7 +329,7 @@ xf86_crtc_set_cursor_position (xf86CrtcPtr crtc, int x, int y)
 	struct pict_f_vector   v;
 
 	v.v[0] = x + ScreenPriv->HotX; v.v[1] = y + ScreenPriv->HotY; v.v[2] = 1;
-	pict_f_transform_point (&crtc->f_framebuffer_to_crtc, &v);
+	pixman_f_transform_point (&crtc->f_framebuffer_to_crtc, &v);
 	x = floor (v.v[0] + 0.5);
 	y = floor (v.v[1] + 0.5);
 	/*
diff --git a/hw/xfree86/modes/xf86Rotate.c b/hw/xfree86/modes/xf86Rotate.c
index 865d59c..07189a5 100644
--- a/hw/xfree86/modes/xf86Rotate.c
+++ b/hw/xfree86/modes/xf86Rotate.c
@@ -122,7 +122,7 @@ xf86RotateCrtcRedisplay (xf86CrtcPtr crtc, RegionPtr region)
 	dst_box.x2 += crtc->filter_width >> 1;
 	dst_box.y1 -= crtc->filter_height >> 1;
 	dst_box.y2 += crtc->filter_height >> 1;
-	pict_f_transform_bounds (&crtc->f_framebuffer_to_crtc, &dst_box);
+	pixman_f_transform_bounds (&crtc->f_framebuffer_to_crtc, &dst_box);
 	CompositePicture (PictOpSrc,
 			  src, NULL, dst,
 			  dst_box.x1, dst_box.y1, 0, 0, dst_box.x1, dst_box.y1,
@@ -177,7 +177,7 @@ xf86CrtcDamageShadow (xf86CrtcPtr crtc)
     damage_box.x2 = crtc->mode.HDisplay;
     damage_box.y1 = 0;
     damage_box.y2 = crtc->mode.VDisplay;
-    if (!PictureTransformBounds (&damage_box, &crtc->crtc_to_framebuffer))
+    if (!pixman_transform_bounds (&crtc->crtc_to_framebuffer, &damage_box))
     {
 	damage_box.x1 = 0;
 	damage_box.y1 = 0;
@@ -375,7 +375,7 @@ xf86CrtcFitsScreen (xf86CrtcPtr crtc, struct pict_f_transform *crtc_to_fb)
     b.x2 = crtc->mode.HDisplay;
     b.y2 = crtc->mode.VDisplay;
     if (crtc_to_fb)
-	pict_f_transform_bounds (crtc_to_fb, &b);
+	pixman_f_transform_bounds (crtc_to_fb, &b);
     else {
 	b.x1 += crtc->x;
 	b.y1 += crtc->y;
@@ -532,7 +532,7 @@ xf86CrtcRotate (xf86CrtcPtr crtc)
     crtc->bounds.x2 = crtc->mode.HDisplay;
     crtc->bounds.y1 = 0;
     crtc->bounds.y2 = crtc->mode.VDisplay;
-    pict_f_transform_bounds (&f_crtc_to_fb, &crtc->bounds);
+    pixman_f_transform_bounds (&f_crtc_to_fb, &crtc->bounds);
 
     /* All done */
     return TRUE;
diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
index c431637..5d270ce 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -91,9 +91,9 @@ RRCrtcCreate (ScreenPtr pScreen, void *devPrivate)
     crtc->devPrivate = devPrivate;
     RRTransformInit (&crtc->client_pending_transform);
     RRTransformInit (&crtc->client_current_transform);
-    PictureTransformInitIdentity (&crtc->transform);
-    pict_f_transform_init_identity (&crtc->f_transform);
-    pict_f_transform_init_identity (&crtc->f_inverse);
+    pixman_transform_init_identity (&crtc->transform);
+    pixman_f_transform_init_identity (&crtc->f_transform);
+    pixman_f_transform_init_identity (&crtc->f_inverse);
 
     if (!AddResource (crtc->id, RRCrtcType, (pointer) crtc))
 	return NULL;
@@ -395,7 +395,7 @@ RRCrtcGetTransform (RRCrtcPtr crtc)
 {
     RRTransformPtr  transform = &crtc->client_pending_transform;
 
-    if (PictureTransformIsIdentity (&transform->transform))
+    if (pixman_transform_is_identity (&transform->transform))
 	return NULL;
     return transform;
 }
@@ -508,7 +508,7 @@ RRModeGetScanoutSize (RRModePtr mode, PictTransformPtr transform,
     box.x2 = mode->mode.width;
     box.y2 = mode->mode.height;
 
-    PictureTransformBounds (&box, transform);
+    pixman_transform_bounds (transform, &box);
     *width = box.x2 - box.x1;
     *height = box.y2 - box.y1;
 }
@@ -558,8 +558,8 @@ RRCrtcGammaSetSize (RRCrtcPtr	crtc,
 int
 RRCrtcTransformSet (RRCrtcPtr		crtc,
 		    PictTransformPtr	transform,
-		    struct pict_f_transform *f_transform,
-		    struct pict_f_transform *f_inverse,
+		    struct pixman_f_transform *f_transform,
+		    struct pixman_f_transform *f_inverse,
 		    char		*filter_name,
 		    int			filter_len,
 		    xFixed		*params,
@@ -909,7 +909,7 @@ ProcRRSetCrtcConfig (ClientPtr client)
 	    int source_width;
 	    int	source_height;
 	    PictTransform transform;
-	    struct pict_f_transform f_transform, f_inverse;
+	    struct pixman_f_transform f_transform, f_inverse;
 
 	    RRTransformCompute (stuff->x, stuff->y,
 				mode->mode.width, mode->mode.height,
@@ -1011,7 +1011,7 @@ ProcRRGetCrtcGamma (ClientPtr client)
     RRCrtcPtr			crtc;
     int				n;
     unsigned long		len;
-    char			*extra;
+    char			*extra = NULL;
     
     REQUEST_SIZE_MATCH(xRRGetCrtcGammaReq);
     crtc = LookupCrtc (client, stuff->crtc, DixReadAccess);
@@ -1083,7 +1083,7 @@ ProcRRSetCrtcTransform (ClientPtr client)
     REQUEST(xRRSetCrtcTransformReq);
     RRCrtcPtr		    crtc;
     PictTransform	    transform;
-    struct pict_f_transform f_transform, f_inverse;
+    struct pixman_f_transform f_transform, f_inverse;
     char		    *filter;
     int			    nbytes;
     xFixed		    *params;
@@ -1095,8 +1095,8 @@ ProcRRSetCrtcTransform (ClientPtr client)
 	return RRErrorBase + BadRRCrtc;
 
     PictTransform_from_xRenderTransform (&transform, &stuff->transform);
-    pict_f_transform_from_pixman_transform (&f_transform, &transform);
-    if (!pict_f_transform_invert (&f_inverse, &f_transform))
+    pixman_f_transform_from_pixman_transform (&f_transform, &transform);
+    if (!pixman_f_transform_invert (&f_inverse, &f_transform))
 	return BadMatch;
 
     filter = (char *) (stuff + 1);
diff --git a/randr/rrproperty.c b/randr/rrproperty.c
index 9bc7254..6ca7cc9 100644
--- a/randr/rrproperty.c
+++ b/randr/rrproperty.c
@@ -461,7 +461,7 @@ ProcRRQueryOutputProperty (ClientPtr client)
     xRRQueryOutputPropertyReply	    rep;
     RROutputPtr			    output;
     RRPropertyPtr		    prop;
-    char *extra;
+    char *extra = NULL;
     
     REQUEST_SIZE_MATCH(xRRQueryOutputPropertyReq);
 
@@ -613,7 +613,7 @@ ProcRRGetOutputProperty (ClientPtr client)
     unsigned long		n, len, ind;
     RROutputPtr			output;
     xRRGetOutputPropertyReply	reply;
-    char			*extra;
+    char			*extra = NULL;
 
     REQUEST_SIZE_MATCH(xRRGetOutputPropertyReq);
     if (stuff->delete)
diff --git a/randr/rrtransform.c b/randr/rrtransform.c
index 836a7ae..a901df4 100644
--- a/randr/rrtransform.c
+++ b/randr/rrtransform.c
@@ -26,9 +26,9 @@
 void
 RRTransformInit (RRTransformPtr transform)
 {
-    PictureTransformInitIdentity (&transform->transform);
-    pict_f_transform_init_identity (&transform->f_transform);
-    pict_f_transform_init_identity (&transform->f_inverse);
+    pixman_transform_init_identity (&transform->transform);
+    pixman_f_transform_init_identity (&transform->f_transform);
+    pixman_f_transform_init_identity (&transform->f_inverse);
     transform->filter = NULL;
     transform->params = NULL;
     transform->nparams = 0;
@@ -44,9 +44,9 @@ RRTransformFini (RRTransformPtr transform)
 Bool
 RRTransformEqual (RRTransformPtr a, RRTransformPtr b)
 {
-    if (a && PictureTransformIsIdentity (&a->transform))
+    if (a && pixman_transform_is_identity (&a->transform))
 	a = NULL;
-    if (b && PictureTransformIsIdentity (&b->transform))
+    if (b && pixman_transform_is_identity (&b->transform))
 	b = NULL;
     if (a == NULL && b == NULL)
 	return TRUE;
@@ -95,7 +95,7 @@ RRTransformSetFilter (RRTransformPtr	dst,
 Bool
 RRTransformCopy (RRTransformPtr dst, RRTransformPtr src)
 {
-    if (src && PictureTransformIsIdentity (&src->transform))
+    if (src && pixman_transform_is_identity (&src->transform))
 	src = NULL;
 
     if (src)
@@ -111,9 +111,9 @@ RRTransformCopy (RRTransformPtr dst, RRTransformPtr src)
     {
 	if (!RRTransformSetFilter (dst, NULL, NULL, 0, 0, 0))
 	    return FALSE;
-	PictureTransformInitIdentity (&dst->transform);
-	pict_f_transform_init_identity (&dst->f_transform);
-	pict_f_transform_init_identity (&dst->f_inverse);
+	pixman_transform_init_identity (&dst->transform);
+	pixman_f_transform_init_identity (&dst->f_transform);
+	pixman_f_transform_init_identity (&dst->f_inverse);
     }
     return TRUE;
 }
@@ -136,20 +136,20 @@ RRTransformCompute (int			    x,
 		    RRTransformPtr	    rr_transform,
 
 		    PictTransformPtr	    transform,
-		    struct pict_f_transform *f_transform,
-		    struct pict_f_transform *f_inverse)
+		    struct pixman_f_transform *f_transform,
+		    struct pixman_f_transform *f_inverse)
 {
     PictTransform	    t_transform, inverse;
-    struct pict_f_transform tf_transform, tf_inverse;
+    struct pixman_f_transform tf_transform, tf_inverse;
 
     if (!transform) transform = &t_transform;
     if (!f_transform) f_transform = &tf_transform;
     if (!f_inverse) f_inverse = &tf_inverse;
 
-    PictureTransformInitIdentity (transform);
-    PictureTransformInitIdentity (&inverse);
-    pict_f_transform_init_identity (f_transform);
-    pict_f_transform_init_identity (f_inverse);
+    pixman_transform_init_identity (transform);
+    pixman_transform_init_identity (&inverse);
+    pixman_f_transform_init_identity (f_transform);
+    pixman_f_transform_init_identity (f_inverse);
     if (rotation != RR_Rotate_0)
     {
 	double	f_rot_cos, f_rot_sin, f_rot_dx, f_rot_dy;
@@ -186,10 +186,10 @@ RRTransformCompute (int			    x,
 	    break;
 	}
 	
-	PictureTransformRotate (transform, &inverse, rot_cos, rot_sin);
-	PictureTransformTranslate (transform, &inverse, rot_dx, rot_dy);
-	pict_f_transform_rotate (f_transform, f_inverse, f_rot_cos, f_rot_sin);
-	pict_f_transform_translate (f_transform, f_inverse, f_rot_dx, f_rot_dy);
+	pixman_transform_rotate (transform, &inverse, rot_cos, rot_sin);
+	pixman_transform_translate (transform, &inverse, rot_dx, rot_dy);
+	pixman_f_transform_rotate (f_transform, f_inverse, f_rot_cos, f_rot_sin);
+	pixman_f_transform_translate (f_transform, f_inverse, f_rot_dx, f_rot_dy);
 
 	/* reflection */
 	f_scale_x = 1;
@@ -225,35 +225,35 @@ RRTransformCompute (int			    x,
 	    }
 	}
 	
-	PictureTransformScale (transform, &inverse, scale_x, scale_y);
-	pict_f_transform_scale (f_transform, f_inverse, f_scale_x, f_scale_y);
-	PictureTransformTranslate (transform, &inverse, scale_dx, scale_dy);
-	pict_f_transform_translate (f_transform, f_inverse, f_scale_dx, f_scale_dy);
+	pixman_transform_scale (transform, &inverse, scale_x, scale_y);
+	pixman_f_transform_scale (f_transform, f_inverse, f_scale_x, f_scale_y);
+	pixman_transform_translate (transform, &inverse, scale_dx, scale_dy);
+	pixman_f_transform_translate (f_transform, f_inverse, f_scale_dx, f_scale_dy);
     }
     
 #ifdef RANDR_12_INTERFACE
     if (rr_transform)
     {
-        PictureTransformMultiply (transform, transform, &rr_transform->transform);
-	pict_f_transform_multiply (f_transform, f_transform, &rr_transform->f_transform);
-	pict_f_transform_multiply (f_inverse, &rr_transform->f_inverse, f_inverse);
+        pixman_transform_multiply (transform, transform, &rr_transform->transform);
+	pixman_f_transform_multiply (f_transform, f_transform, &rr_transform->f_transform);
+	pixman_f_transform_multiply (f_inverse, &rr_transform->f_inverse, f_inverse);
     }
 #endif
     /*
      * Compute the class of the resulting transform
      */
-    if (PictureTransformIsIdentity (transform))
+    if (pixman_transform_is_identity (transform))
     {
-	PictureTransformInitTranslate (transform, F ( x), F ( y));
+	pixman_transform_init_translate (transform, F ( x), F ( y));
 
-	pict_f_transform_init_translate (f_transform, F( x), F( y));
-	pict_f_transform_init_translate (f_inverse,   F(-x), F(-y));
+	pixman_f_transform_init_translate (f_transform, F( x), F( y));
+	pixman_f_transform_init_translate (f_inverse,   F(-x), F(-y));
 	return FALSE;
     }
     else
     {
-	PictureTransformTranslate (&inverse, transform, x, y);
-	pict_f_transform_translate (f_inverse, f_transform, x, y);
+	pixman_transform_translate (&inverse, transform, x, y);
+	pixman_f_transform_translate (f_inverse, f_transform, x, y);
 	return TRUE;
     }
 }
diff --git a/render/matrix.c b/render/matrix.c
index 560ee94..3b55eb9 100644
--- a/render/matrix.c
+++ b/render/matrix.c
@@ -39,314 +39,6 @@
 #include "servermd.h"
 #include "picturestr.h"
 
-#define F(x)	IntToxFixed(x)
-
-_X_EXPORT void
-PictureTransformInitIdentity (PictTransformPtr matrix)
-{
-    int	i;
-    memset (matrix, '\0', sizeof (PictTransform));
-    for (i = 0; i < 3; i++)
-	matrix->matrix[i][i] = F(1);
-}
-
-typedef xFixed_32_32	xFixed_34_30;
-
-_X_EXPORT Bool
-PictureTransformPoint3d (PictTransformPtr transform,
-                         PictVectorPtr	vector)
-{
-    PictVector	    result;
-    int		    i, j;
-    xFixed_32_32    partial;
-    xFixed_48_16    v;
-
-    for (j = 0; j < 3; j++)
-    {
-	v = 0;
-	for (i = 0; i < 3; i++)
-	{
-	    partial = ((xFixed_48_16) transform->matrix[j][i] *
-		       (xFixed_48_16) vector->vector[i]);
-	    v += partial >> 16;
-	}
-	if (v > MAX_FIXED_48_16 || v < MIN_FIXED_48_16)
-	    return FALSE;
-	result.vector[j] = (xFixed) v;
-    }
-    *vector = result;
-    if (!result.vector[2])
-	return FALSE;
-    return TRUE;
-}
-
-_X_EXPORT Bool
-PictureTransformPoint (PictTransformPtr transform,
-		       PictVectorPtr	vector)
-{
-    int		    i, j;
-    xFixed_32_32    partial;
-    xFixed_34_30    v[3];
-    xFixed_48_16    quo;
-
-    for (j = 0; j < 3; j++)
-    {
-	v[j] = 0;
-	for (i = 0; i < 3; i++)
-	{
-	    partial = ((xFixed_32_32) transform->matrix[j][i] * 
-		       (xFixed_32_32) vector->vector[i]);
-	    v[j] += partial >> 2;
-	}
-    }
-    if (!v[2])
-	return FALSE;
-    for (j = 0; j < 2; j++)
-    {
-	quo = v[j] / (v[2] >> 16);
-	if (quo > MAX_FIXED_48_16 || quo < MIN_FIXED_48_16)
-	    return FALSE;
-	vector->vector[j] = (xFixed) quo;
-    }
-    vector->vector[2] = xFixed1;
-    return TRUE;
-}
-
-_X_EXPORT Bool
-PictureTransformMultiply (PictTransformPtr dst, PictTransformPtr l, PictTransformPtr r)
-{
-    PictTransform   d;
-    int		    dx, dy;
-    int		    o;
-
-    for (dy = 0; dy < 3; dy++)
-	for (dx = 0; dx < 3; dx++)
-	{
-	    xFixed_48_16    v;
-	    xFixed_32_32    partial;
-	    v = 0;
-	    for (o = 0; o < 3; o++)
-	    {
-		partial = (xFixed_32_32) l->matrix[dy][o] * (xFixed_32_32) r->matrix[o][dx];
-		v += partial >> 16;
-	    }
-	    if (v > MAX_FIXED_48_16 || v < MIN_FIXED_48_16)
-		return FALSE;
-	    d.matrix[dy][dx] = (xFixed) v;
-	}
-    *dst = d;
-    return TRUE;
-}
-
-_X_EXPORT void
-PictureTransformInitScale (PictTransformPtr t, xFixed sx, xFixed sy)
-{
-    memset (t, '\0', sizeof (PictTransform));
-    t->matrix[0][0] = sx;
-    t->matrix[1][1] = sy;
-    t->matrix[2][2] = F (1);
-}
-
-static xFixed
-fixed_inverse (xFixed x)
-{
-    return (xFixed) ((((xFixed_48_16) F(1)) * F(1)) / x);
-}
-
-_X_EXPORT Bool
-PictureTransformScale (PictTransformPtr forward,
-		       PictTransformPtr reverse,
-		       xFixed sx, xFixed sy)
-{
-    PictTransform   t;
-    
-    if (sx == 0 || sy == 0)
-	return FALSE;
-
-    PictureTransformInitScale (&t, sx, sy);
-    if (!PictureTransformMultiply (forward, &t, forward))
-	return FALSE;
-    PictureTransformInitScale (&t, fixed_inverse (sx), fixed_inverse (sy));
-    if (!PictureTransformMultiply (reverse, reverse, &t))
-	return FALSE;
-    return TRUE;
-}
-
-_X_EXPORT void
-PictureTransformInitRotate (PictTransformPtr t, xFixed c, xFixed s)
-{
-    memset (t, '\0', sizeof (PictTransform));
-    t->matrix[0][0] = c;
-    t->matrix[0][1] = -s;
-    t->matrix[1][0] = s;
-    t->matrix[1][1] = c;
-    t->matrix[2][2] = F (1);
-}
-
-_X_EXPORT Bool
-PictureTransformRotate (PictTransformPtr forward,
-			PictTransformPtr reverse,
-			xFixed c, xFixed s)
-{
-    PictTransform   t;
-    PictureTransformInitRotate (&t, c, s);
-    if (!PictureTransformMultiply (forward, &t, forward))
-	return FALSE;
-    
-    PictureTransformInitRotate (&t, c, -s);
-    if (!PictureTransformMultiply (reverse, reverse, &t))
-	return FALSE;
-    return TRUE;
-}
-
-_X_EXPORT void
-PictureTransformInitTranslate (PictTransformPtr t, xFixed tx, xFixed ty)
-{
-    memset (t, '\0', sizeof (PictTransform));
-    t->matrix[0][0] = F (1);
-    t->matrix[0][2] = tx;
-    t->matrix[1][1] = F (1);
-    t->matrix[1][2] = ty;
-    t->matrix[2][2] = F (1);
-}
-
-_X_EXPORT Bool
-PictureTransformTranslate (PictTransformPtr forward,
-			   PictTransformPtr reverse,
-			   xFixed tx, xFixed ty)
-{
-    PictTransform   t;
-    PictureTransformInitTranslate (&t, tx, ty);
-    if (!PictureTransformMultiply (forward, &t, forward))
-	return FALSE;
-
-    PictureTransformInitTranslate (&t, -tx, -ty);
-    if (!PictureTransformMultiply (reverse, reverse, &t))
-	return FALSE;
-    return TRUE;
-}
-
-_X_EXPORT Bool
-PictureTransformBounds (BoxPtr b, PictTransformPtr matrix)
-{
-    PictVector	v[4];
-    int		i;
-    int		x1, y1, x2, y2;
-
-    v[0].vector[0] = F (b->x1);    v[0].vector[1] = F (b->y1);	v[0].vector[2] = F(1);
-    v[1].vector[0] = F (b->x2);    v[1].vector[1] = F (b->y1);	v[1].vector[2] = F(1);
-    v[2].vector[0] = F (b->x2);    v[2].vector[1] = F (b->y2);	v[2].vector[2] = F(1);
-    v[3].vector[0] = F (b->x1);    v[3].vector[1] = F (b->y2);	v[3].vector[2] = F(1);
-    for (i = 0; i < 4; i++)
-    {
-	if (!PictureTransformPoint (matrix, &v[i]))
-	    return FALSE;
-	x1 = xFixedToInt (v[i].vector[0]);
-	y1 = xFixedToInt (v[i].vector[1]);
-	x2 = xFixedToInt (xFixedCeil (v[i].vector[0]));
-	y2 = xFixedToInt (xFixedCeil (v[i].vector[1]));
-	if (i == 0)
-	{
-	    b->x1 = x1; b->y1 = y1;
-	    b->x2 = x2; b->y2 = y2;
-	}
-	else
-	{
-	    if (x1 < b->x1) b->x1 = x1;
-	    if (y1 < b->y1) b->y1 = y1;
-	    if (x2 > b->x2) b->x2 = x2;
-	    if (y2 > b->y2) b->y2 = y2;
-	}
-    }
-    return TRUE;
-}
-
-_X_EXPORT Bool
-PictureTransformInvert (PictTransformPtr dst, const PictTransformPtr src)
-{
-    struct pict_f_transform m, r;
-
-    pict_f_transform_from_pixman_transform (&m, src);
-    if (!pict_f_transform_invert (&r, &m))
-	return FALSE;
-    if (!pixman_transform_from_pict_f_transform (dst, &r))
-	return FALSE;
-    return TRUE;
-}
-
-static Bool
-within_epsilon (xFixed a, xFixed b, xFixed epsilon)
-{
-    xFixed  t = a - b;
-    if (t < 0) t = -t;
-    return t <= epsilon;
-}
-
-#define epsilon	(xFixed) (2)
-
-#define IsSame(a,b) (within_epsilon (a, b, epsilon))
-#define IsZero(a)   (within_epsilon (a, 0, epsilon))
-#define IsOne(a)    (within_epsilon (a, F(1), epsilon))
-#define IsUnit(a)   (within_epsilon (a, F( 1), epsilon) || \
-		     within_epsilon (a, F(-1), epsilon) || \
-		     IsZero (a))
-#define IsInt(a)    (IsZero (xFixedFrac(a)))
-		     
-_X_EXPORT Bool
-PictureTransformIsIdentity(PictTransform *t)
-{
-    return (IsSame (t->matrix[0][0], t->matrix[1][1]) &&
-	    IsSame (t->matrix[0][0], t->matrix[2][2]) &&
-	    !IsZero (t->matrix[0][0]) &&
-	    IsZero (t->matrix[0][1]) &&
-	    IsZero (t->matrix[0][2]) &&
-	    IsZero (t->matrix[1][0]) &&
-	    IsZero (t->matrix[1][2]) &&
-	    IsZero (t->matrix[2][0]) &&
-	    IsZero (t->matrix[2][1]));
-}
-
-_X_EXPORT Bool
-PictureTransformIsScale(PictTransform *t)
-{
-    return (!IsZero (t->matrix[0][0]) &&
-	     IsZero (t->matrix[0][1]) &&
-	     IsZero (t->matrix[0][2]) &&
-	    
-	     IsZero (t->matrix[1][0]) &&
-	    !IsZero (t->matrix[1][1]) &&
-	     IsZero (t->matrix[1][2]) &&
-	    
-	     IsZero (t->matrix[2][0]) &&
-	     IsZero (t->matrix[2][1]) &&
-	    !IsZero (t->matrix[2][2]));
-}
-
-_X_EXPORT Bool
-PictureTransformIsIntTranslate(PictTransform *t)
-{
-    return ( IsOne  (t->matrix[0][0]) &&
-	     IsZero (t->matrix[0][1]) &&
-	     IsInt  (t->matrix[0][2]) &&
-	    
-	     IsZero (t->matrix[1][0]) &&
-	     IsOne  (t->matrix[1][1]) &&
-	     IsInt  (t->matrix[1][2]) &&
-	    
-	     IsZero (t->matrix[2][0]) &&
-	     IsZero (t->matrix[2][1]) &&
-	     IsOne  (t->matrix[2][2]));
-}
-
-_X_EXPORT Bool
-PictureTransformIsInverse (PictTransform *a, PictTransform *b)
-{
-    PictTransform   t;
-
-    PictureTransformMultiply (&t, a, b);
-    return PictureTransformIsIdentity (&t);
-}
-
 _X_EXPORT void
 PictTransform_from_xRenderTransform (PictTransformPtr pict,
 				     xRenderTransform *render)
@@ -364,7 +56,7 @@ PictTransform_from_xRenderTransform (PictTransformPtr pict,
     pict->matrix[2][2] = render->matrix33;
 }
 
-void
+_X_EXPORT void
 xRenderTransform_from_PictTransform (xRenderTransform *render,
 				     PictTransformPtr pict)
 {
@@ -381,251 +73,16 @@ xRenderTransform_from_PictTransform (xRenderTransform *render,
     render->matrix33 = pict->matrix[2][2];
 }
 
-/*
- * Floating point matrix interfaces
- */
-
-_X_EXPORT void
-pict_f_transform_from_pixman_transform (struct pict_f_transform *ft,
-					struct pixman_transform	*t)
-{
-    int	i, j;
-
-    for (j = 0; j < 3; j++)
-	for (i = 0; i < 3; i++)
-	    ft->m[j][i] = pixman_fixed_to_double (t->matrix[j][i]);
-}
-
 _X_EXPORT Bool
-pixman_transform_from_pict_f_transform (struct pixman_transform	*t,
-					struct pict_f_transform	*ft)
-{
-    int	i, j;
-
-    for (j = 0; j < 3; j++)
-	for (i = 0; i < 3; i++)
-	{
-	    double  d = ft->m[j][i];
-	    if (d < -32767.0 || d > 32767.0)
-		return FALSE;
-	    d = d * 65536.0 + 0.5;
-	    t->matrix[j][i] = (xFixed) floor (d);
-	}
-    return TRUE;
-}
-
-static const int	a[3] = { 3, 3, 2 };
-static const int	b[3] = { 2, 1, 1 };
-
-_X_EXPORT Bool
-pict_f_transform_invert (struct pict_f_transform *r,
-			 struct pict_f_transform *m)
-{
-    double  det;
-    int	    i, j;
-    static int	a[3] = { 2, 2, 1 };
-    static int	b[3] = { 1, 0, 0 };
-
-    det = 0;
-    for (i = 0; i < 3; i++) {
-	double	p;
-	int	ai = a[i];
-	int	bi = b[i];
-	p = m->m[i][0] * (m->m[ai][2] * m->m[bi][1] - m->m[ai][1] * m->m[bi][2]);
-	if (i == 1)
-	    p = -p;
-	det += p;
-    }
-    if (det == 0)
-	return FALSE;
-    det = 1/det;
-    for (j = 0; j < 3; j++) {
-	for (i = 0; i < 3; i++) {
-	    double  p;
-	    int	    ai = a[i];
-	    int	    aj = a[j];
-	    int	    bi = b[i];
-	    int	    bj = b[j];
-
-	    p = m->m[ai][aj] * m->m[bi][bj] - m->m[ai][bj] * m->m[bi][aj];
-	    if (((i + j) & 1) != 0)
-		p = -p;
-	    r->m[j][i] = det * p;
-	}
-    }
-    return TRUE;
-}
-
-_X_EXPORT Bool
-pict_f_transform_point (struct pict_f_transform *t,
-			struct pict_f_vector	*v)
-{
-    struct pict_f_vector    result;
-    int			    i, j;
-    double		    a;
-
-    for (j = 0; j < 3; j++)
-    {
-	a = 0;
-	for (i = 0; i < 3; i++)
-	    a += t->m[j][i] * v->v[i];
-	result.v[j] = a;
-    }
-    if (!result.v[2])
-	return FALSE;
-    for (j = 0; j < 2; j++)
-	v->v[j] = result.v[j] / result.v[2];
-    v->v[2] = 1;
-    return TRUE;
-}
-
-_X_EXPORT void
-pict_f_transform_point_3d (struct pict_f_transform *t,
-			   struct pict_f_vector	*v)
-{
-    struct pict_f_vector    result;
-    int			    i, j;
-    double		    a;
-
-    for (j = 0; j < 3; j++)
-    {
-	a = 0;
-	for (i = 0; i < 3; i++)
-	    a += t->m[j][i] * v->v[i];
-	result.v[j] = a;
-    }
-    *v = result;
-}
-
-_X_EXPORT void
-pict_f_transform_multiply (struct pict_f_transform *dst,
-			   struct pict_f_transform *l, struct pict_f_transform *r)
-{
-    struct pict_f_transform d;
-    int			    dx, dy;
-    int			    o;
-
-    for (dy = 0; dy < 3; dy++)
-	for (dx = 0; dx < 3; dx++)
-	{
-	    double v = 0;
-	    for (o = 0; o < 3; o++)
-		v += l->m[dy][o] * r->m[o][dx];
-	    d.m[dy][dx] = v;
-	}
-    *dst = d;
-}
-
-_X_EXPORT void
-pict_f_transform_init_scale (struct pict_f_transform *t, double sx, double sy)
-{
-    t->m[0][0] = sx;	t->m[0][1] = 0;	    t->m[0][2] = 0;
-    t->m[1][0] = 0;	t->m[1][1] = sy;    t->m[1][2] = 0;
-    t->m[2][0] = 0;	t->m[2][1] = 0;	    t->m[2][2] = 1;
-}
-
-_X_EXPORT Bool
-pict_f_transform_scale (struct pict_f_transform *forward,
-			struct pict_f_transform *reverse,
-			double sx, double sy)
-{
-    struct pict_f_transform t;
-
-    if (sx == 0 || sy == 0)
-	return FALSE;
-
-    pict_f_transform_init_scale (&t, sx, sy);
-    pict_f_transform_multiply (forward, &t, forward);
-    pict_f_transform_init_scale (&t, 1/sx, 1/sy);
-    pict_f_transform_multiply (reverse, reverse, &t);
-    return TRUE;
-}
-
-_X_EXPORT void
-pict_f_transform_init_rotate (struct pict_f_transform *t, double c, double s)
-{
-    t->m[0][0] = c;	t->m[0][1] = -s;    t->m[0][2] = 0;
-    t->m[1][0] = s;	t->m[1][1] = c;	    t->m[1][2] = 0;
-    t->m[2][0] = 0;	t->m[2][1] = 0;	    t->m[2][2] = 1;
-}
-
-_X_EXPORT Bool
-pict_f_transform_rotate (struct pict_f_transform *forward,
-			 struct pict_f_transform *reverse,
-			 double c, double s)
-{
-    struct pict_f_transform t;
-
-    pict_f_transform_init_rotate (&t, c, s);
-    pict_f_transform_multiply (forward, &t, forward);
-    pict_f_transform_init_rotate (&t, c, -s);
-    pict_f_transform_multiply (reverse, reverse, &t);
-    return TRUE;
-}
-
-_X_EXPORT void
-pict_f_transform_init_translate (struct pict_f_transform *t, double tx, double ty)
+PictureTransformPoint (PictTransformPtr transform,
+		       PictVectorPtr	vector)
 {
-    t->m[0][0] = 1;	t->m[0][1] = 0;	    t->m[0][2] = tx;
-    t->m[1][0] = 0;	t->m[1][1] = 1;	    t->m[1][2] = ty;
-    t->m[2][0] = 0;	t->m[2][1] = 0;	    t->m[2][2] = 1;
+	return pixman_transform_point(transform, vector);
 }
 
 _X_EXPORT Bool
-pict_f_transform_translate (struct pict_f_transform *forward,
-			    struct pict_f_transform *reverse,
-			    double tx, double ty)
-{
-    struct pict_f_transform t;
-
-    pict_f_transform_init_translate (&t, tx, ty);
-    pict_f_transform_multiply (forward, &t, forward);
-    pict_f_transform_init_translate (&t, -tx, -ty);
-    pict_f_transform_multiply (reverse, reverse, &t);
-    return TRUE;
-}
-
-_X_EXPORT Bool
-pict_f_transform_bounds (struct pict_f_transform *t, BoxPtr b)
-{
-    struct pict_f_vector    v[4];
-    int			    i;
-    int			    x1, y1, x2, y2;
-
-    v[0].v[0] = b->x1;    v[0].v[1] = b->y1;	v[0].v[2] = 1;
-    v[1].v[0] = b->x2;    v[1].v[1] = b->y1;	v[1].v[2] = 1;
-    v[2].v[0] = b->x2;    v[2].v[1] = b->y2;	v[2].v[2] = 1;
-    v[3].v[0] = b->x1;    v[3].v[1] = b->y2;	v[3].v[2] = 1;
-    for (i = 0; i < 4; i++)
-    {
-	if (!pict_f_transform_point (t, &v[i]))
-	    return FALSE;
-	x1 = floor (v[i].v[0]);
-	y1 = floor (v[i].v[1]);
-	x2 = ceil (v[i].v[0]);
-	y2 = ceil (v[i].v[1]);
-	if (i == 0)
-	{
-	    b->x1 = x1; b->y1 = y1;
-	    b->x2 = x2; b->y2 = y2;
-	}
-	else
-	{
-	    if (x1 < b->x1) b->x1 = x1;
-	    if (y1 < b->y1) b->y1 = y1;
-	    if (x2 > b->x2) b->x2 = x2;
-	    if (y2 > b->y2) b->y2 = y2;
-	}
-    }
-    return TRUE;
-}
-
-_X_EXPORT void
-pict_f_transform_init_identity (struct pict_f_transform *t)
+PictureTransformPoint3d (PictTransformPtr transform,
+                         PictVectorPtr	vector)
 {
-    int	i, j;
-
-    for (j = 0; j < 3; j++)
-	for (i = 0; i < 3; i++)
-	    t->m[j][i] = i == j ? 1 : 0;
+	return pixman_transform_point_3d(transform, vector);
 }
diff --git a/render/mipict.c b/render/mipict.c
index 87dccbb..2fadd8c 100644
--- a/render/mipict.c
+++ b/render/mipict.c
@@ -379,7 +379,7 @@ miCompositeSourceValidate (PicturePtr	pPicture,
 		t.vector[0] = IntToxFixed (points[i].x);
 		t.vector[1] = IntToxFixed (points[i].y);
 		t.vector[2] = xFixed1;
-		if (PictureTransformPoint (pPicture->transform, &t))
+		if (pixman_transform_point (pPicture->transform, &t))
 		{
 		    int	tx = xFixedToInt (t.vector[0]);
 		    int ty = xFixedToInt (t.vector[1]);
diff --git a/render/picturestr.h b/render/picturestr.h
index ab5dc16..4d788fc 100644
--- a/render/picturestr.h
+++ b/render/picturestr.h
@@ -56,13 +56,8 @@ typedef struct _PictFormat {
 typedef struct pixman_vector PictVector, *PictVectorPtr;
 typedef struct pixman_transform PictTransform, *PictTransformPtr;
 
-struct pict_f_vector {
-    double  v[3];
-};
-
-struct pict_f_transform {
-    double  m[3][3];
-};
+#define pict_f_vector pixman_f_vector
+#define pict_f_transform pixman_f_transform
 
 #define PICT_GRADIENT_STOPTABLE_SIZE 1024
 #define SourcePictTypeSolidFill 0
@@ -685,62 +680,6 @@ void PanoramiXRenderReset (void);
 /*
  * matrix.c
  */
-void
-PictureTransformInitIdentity (PictTransformPtr matrix);
-
-Bool
-PictureTransformPoint3d (PictTransformPtr transform,
-                         PictVectorPtr	vector);
-
-Bool
-PictureTransformPoint (PictTransformPtr transform,
-		       PictVectorPtr	vector);
-
-Bool
-PictureTransformMultiply (PictTransformPtr dst,
-			  PictTransformPtr l, PictTransformPtr r);
-
-void
-PictureTransformInitScale (PictTransformPtr t, xFixed sx, xFixed sy);
-
-Bool
-PictureTransformScale (PictTransformPtr forward,
-		       PictTransformPtr reverse,
-		       xFixed sx, xFixed sy);
-
-void
-PictureTransformInitRotate (PictTransformPtr t, xFixed c, xFixed s);
-
-Bool
-PictureTransformRotate (PictTransformPtr forward,
-			PictTransformPtr reverse,
-			xFixed c, xFixed s);
-
-void
-PictureTransformInitTranslate (PictTransformPtr t, xFixed tx, xFixed ty);
-
-Bool
-PictureTransformTranslate (PictTransformPtr forward,
-			   PictTransformPtr reverse,
-			   xFixed tx, xFixed ty);
-
-Bool
-PictureTransformBounds (BoxPtr b, PictTransformPtr matrix);
-
-Bool
-PictureTransformInvert (PictTransformPtr dst, const PictTransformPtr src);
-
-Bool
-PictureTransformIsIdentity(PictTransform *t);
-
-Bool
-PictureTransformIsScale(PictTransform *t);
-
-Bool
-PictureTransformIsIntTranslate (PictTransform *t);
-
-Bool
-PictureTransformIsInverse(PictTransform *t, PictTransform *i);
 
 void
 PictTransform_from_xRenderTransform (PictTransformPtr pict,
@@ -750,59 +689,12 @@ void
 xRenderTransform_from_PictTransform (xRenderTransform *render,
 				     PictTransformPtr pict);
 
-void
-pict_f_transform_from_pixman_transform (struct pict_f_transform *ft,
-					struct pixman_transform	*t);
-
-Bool
-pixman_transform_from_pict_f_transform (struct pixman_transform	*t,
-					struct pict_f_transform	*ft);
-
-Bool
-pict_f_transform_invert (struct pict_f_transform *r,
-			 struct pict_f_transform *m);
-
-
-Bool
-pict_f_transform_point (struct pict_f_transform *t,
-			struct pict_f_vector	*v);
-
-void
-pict_f_transform_point_3d (struct pict_f_transform *t,
-			   struct pict_f_vector	*v);
-
-void
-pict_f_transform_multiply (struct pict_f_transform *dst,
-			   struct pict_f_transform *l, struct pict_f_transform *r);
-
-void
-pict_f_transform_init_scale (struct pict_f_transform *t, double sx, double sy);
-
-Bool
-pict_f_transform_scale (struct pict_f_transform *forward,
-			struct pict_f_transform *reverse,
-			double sx, double sy);
-
-void
-pict_f_transform_init_rotate (struct pict_f_transform *t, double c, double s);
-
-Bool
-pict_f_transform_rotate (struct pict_f_transform *forward,
-			 struct pict_f_transform *reverse,
-			 double c, double s);
-
-void
-pict_f_transform_init_translate (struct pict_f_transform *t, double tx, double ty);
-
 Bool
-pict_f_transform_translate (struct pict_f_transform *forward,
-			    struct pict_f_transform *reverse,
-			    double tx, double ty);
+PictureTransformPoint (PictTransformPtr transform,
+		       PictVectorPtr	vector);
 
 Bool
-pict_f_transform_bounds (struct pict_f_transform *t, BoxPtr b);
-
-void
-pict_f_transform_init_identity (struct pict_f_transform *t);
+PictureTransformPoint3d (PictTransformPtr transform,
+                         PictVectorPtr	vector);
 
 #endif /* _PICTURESTR_H_ */
commit c4b9ab6bf56139fdd8c7c584a6f523c6766cddd6
Author: Keith Packard <keithp at keithp.com>
Date:   Tue Apr 29 08:29:42 2008 -0700

    Handle transform failure when computing shadow damage area.
    
    PictureTransformBounds can fail, when this happens, damage the entire screen
    so that the shadow gets repainted correctly.

diff --git a/hw/xfree86/modes/xf86Rotate.c b/hw/xfree86/modes/xf86Rotate.c
index 75f4a55..865d59c 100644
--- a/hw/xfree86/modes/xf86Rotate.c
+++ b/hw/xfree86/modes/xf86Rotate.c
@@ -135,25 +135,6 @@ xf86RotateCrtcRedisplay (xf86CrtcPtr crtc, RegionPtr region)
 }
 
 static void
-xf86CrtcDamageShadow (xf86CrtcPtr crtc)
-{
-    ScrnInfoPtr	pScrn = crtc->scrn;
-    BoxRec	damage_box;
-    RegionRec   damage_region;
-    ScreenPtr	pScreen = pScrn->pScreen;
-
-    damage_box.x1 = 0;
-    damage_box.x2 = crtc->mode.HDisplay;
-    damage_box.y1 = 0;
-    damage_box.y2 = crtc->mode.VDisplay;
-    PictureTransformBounds (&damage_box, &crtc->crtc_to_framebuffer);
-    REGION_INIT (pScreen, &damage_region, &damage_box, 1);
-    DamageRegionAppend(&(*pScreen->GetScreenPixmap)(pScreen)->drawable,
-			&damage_region);
-    REGION_UNINIT (pScreen, &damage_region);
-}
-
-static void
 xf86CrtcShadowClear (xf86CrtcPtr crtc)
 {
     PixmapPtr		dst_pixmap = crtc->rotatedPixmap;
@@ -185,6 +166,36 @@ xf86CrtcShadowClear (xf86CrtcPtr crtc)
 }
 
 static void
+xf86CrtcDamageShadow (xf86CrtcPtr crtc)
+{
+    ScrnInfoPtr	pScrn = crtc->scrn;
+    BoxRec	damage_box;
+    RegionRec   damage_region;
+    ScreenPtr	pScreen = pScrn->pScreen;
+
+    damage_box.x1 = 0;
+    damage_box.x2 = crtc->mode.HDisplay;
+    damage_box.y1 = 0;
+    damage_box.y2 = crtc->mode.VDisplay;
+    if (!PictureTransformBounds (&damage_box, &crtc->crtc_to_framebuffer))
+    {
+	damage_box.x1 = 0;
+	damage_box.y1 = 0;
+	damage_box.x2 = pScreen->width;
+	damage_box.y2 = pScreen->height;
+    }
+    if (damage_box.x1 < 0) damage_box.x1 = 0;
+    if (damage_box.y1 < 0) damage_box.y1 = 0;
+    if (damage_box.x2 > pScreen->width) damage_box.x2 = pScreen->width;
+    if (damage_box.y2 > pScreen->height) damage_box.y2 = pScreen->height;
+    REGION_INIT (pScreen, &damage_region, &damage_box, 1);
+    DamageRegionAppend (&(*pScreen->GetScreenPixmap)(pScreen)->drawable,
+			&damage_region);
+    REGION_UNINIT (pScreen, &damage_region);
+    xf86CrtcShadowClear (crtc);
+}
+
+static void
 xf86RotatePrepare (ScreenPtr pScreen)
 {
     ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
diff --git a/render/matrix.c b/render/matrix.c
index 603281e..560ee94 100644
--- a/render/matrix.c
+++ b/render/matrix.c
@@ -84,7 +84,6 @@ _X_EXPORT Bool
 PictureTransformPoint (PictTransformPtr transform,
 		       PictVectorPtr	vector)
 {
-    PictVector	    result;
     int		    i, j;
     xFixed_32_32    partial;
     xFixed_34_30    v[3];
@@ -227,7 +226,7 @@ PictureTransformTranslate (PictTransformPtr forward,
     return TRUE;
 }
 
-_X_EXPORT void
+_X_EXPORT Bool
 PictureTransformBounds (BoxPtr b, PictTransformPtr matrix)
 {
     PictVector	v[4];
@@ -240,7 +239,8 @@ PictureTransformBounds (BoxPtr b, PictTransformPtr matrix)
     v[3].vector[0] = F (b->x1);    v[3].vector[1] = F (b->y2);	v[3].vector[2] = F(1);
     for (i = 0; i < 4; i++)
     {
-	PictureTransformPoint (matrix, &v[i]);
+	if (!PictureTransformPoint (matrix, &v[i]))
+	    return FALSE;
 	x1 = xFixedToInt (v[i].vector[0]);
 	y1 = xFixedToInt (v[i].vector[1]);
 	x2 = xFixedToInt (xFixedCeil (v[i].vector[0]));
@@ -258,6 +258,7 @@ PictureTransformBounds (BoxPtr b, PictTransformPtr matrix)
 	    if (y2 > b->y2) b->y2 = y2;
 	}
     }
+    return TRUE;
 }
 
 _X_EXPORT Bool
diff --git a/render/picturestr.h b/render/picturestr.h
index 4a7b6e7..ab5dc16 100644
--- a/render/picturestr.h
+++ b/render/picturestr.h
@@ -724,7 +724,7 @@ PictureTransformTranslate (PictTransformPtr forward,
 			   PictTransformPtr reverse,
 			   xFixed tx, xFixed ty);
 
-void
+Bool
 PictureTransformBounds (BoxPtr b, PictTransformPtr matrix);
 
 Bool
commit 9c7679240ad90367693a462e288308b3fdc08f26
Author: Keith Packard <keithp at keithp.com>
Date:   Sun Mar 30 19:05:07 2008 -0700

    [randr] don't try to compute crtc transform when no mode is set.
    
    Dereferencing the NULL mode pointer would cause a crash. As these transform
    matrices won't be used while the CRTC is disabled, just leave their values
    alone.

diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
index c237f03..c431637 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -233,7 +233,7 @@ RRCrtcNotify (RRCrtcPtr	    crtc,
 	RRTransformCopy (&crtc->client_current_transform, transform);
 	RRCrtcChanged (crtc, TRUE);
     }
-    if (crtc->changed)
+    if (crtc->changed && mode)
     {
 	RRTransformCompute (x, y,
 			    mode->mode.width, mode->mode.height,
commit 315b6d0a425d0257f226ee7032aca3ca31665e59
Author: Keith Packard <keithp at keithp.com>
Date:   Thu Mar 27 11:46:39 2008 -0700

    Update RandR global transform when driver notifies of transform change.
    
    Need to compute and save the global transform when the driver changes it.

diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
index 1b6350e..c237f03 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -233,6 +233,15 @@ RRCrtcNotify (RRCrtcPtr	    crtc,
 	RRTransformCopy (&crtc->client_current_transform, transform);
 	RRCrtcChanged (crtc, TRUE);
     }
+    if (crtc->changed)
+    {
+	RRTransformCompute (x, y,
+			    mode->mode.width, mode->mode.height,
+			    rotation,
+			    &crtc->client_current_transform,
+			    &crtc->transform, &crtc->f_transform,
+			    &crtc->f_inverse);
+    }
     return TRUE;
 }
 
commit 5d9282fde919c936816a85c2a9c5734dc9d57cc2
Author: Keith Packard <keithp at keithp.com>
Date:   Thu Mar 27 11:45:53 2008 -0700

    Export rrtransform.h as needed by randrstr.h
    
    When the transform management was moved from randrstr.h, the associated
    header file became necessary to build drivers. Include it as a part of the
    sdk headers.

diff --git a/randr/Makefile.am b/randr/Makefile.am
index 3d16ede..1f1bea0 100644
--- a/randr/Makefile.am
+++ b/randr/Makefile.am
@@ -5,7 +5,7 @@ AM_CFLAGS = $(DIX_CFLAGS)
 XINERAMA_SRCS = rrxinerama.c
 
 if XORG
-sdk_HEADERS = randrstr.h
+sdk_HEADERS = randrstr.h rrtransform.h
 endif
 
 librandr_la_SOURCES =	\
commit 7236fd9dd4e9f5c4cb5bafa5c2a18cff12a0444c
Author: Keith Packard <keithp at keithp.com>
Date:   Fri Mar 21 03:16:09 2008 -0700

    Be careful about copying transforms around; they have allocated memory.

diff --git a/hw/xfree86/modes/xf86Crtc.c b/hw/xfree86/modes/xf86Crtc.c
index d24fc86..7dce1ab 100644
--- a/hw/xfree86/modes/xf86Crtc.c
+++ b/hw/xfree86/modes/xf86Crtc.c
@@ -271,7 +271,10 @@ xf86CrtcSetModeTransform (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotati
     saved_x = crtc->x;
     saved_y = crtc->y;
     saved_rotation = crtc->rotation;
-    saved_transform = crtc->transform;
+    if (crtc->transformPresent) {
+	RRTransformInit (&saved_transform);
+	RRTransformCopy (&saved_transform, &crtc->transform);
+    }
     saved_transform_present = crtc->transformPresent;
 
     /* Update crtc values up front so the driver can rely on them for mode
@@ -283,7 +286,6 @@ xf86CrtcSetModeTransform (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotati
     crtc->rotation = rotation;
     if (transform) {
 	RRTransformCopy (&crtc->transform, transform);
-	crtc->transform = *transform;
 	crtc->transformPresent = TRUE;
     } else
 	crtc->transformPresent = FALSE;
@@ -380,7 +382,8 @@ done:
 	crtc->y = saved_y;
 	crtc->rotation = saved_rotation;
 	crtc->mode = saved_mode;
-	crtc->transform = saved_transform;
+	if (saved_transform_present)
+	    RRTransformCopy (&crtc->transform, &saved_transform);
 	crtc->transformPresent = saved_transform_present;
     }
 
commit 7e69e364d2ef146d8ec3651d04bdd6d641017449
Author: Keith Packard <keithp at keithp.com>
Date:   Fri Mar 21 03:15:00 2008 -0700

    Fix rotated/reflected cursor positions.
    
    Doing projective transforms required repositioning the cursor using the
    hotspot, but that requires relocating the upper left corner in terms of said
    hotspot.

diff --git a/hw/xfree86/modes/xf86Cursors.c b/hw/xfree86/modes/xf86Cursors.c
index 4065789..cd4f9e8 100644
--- a/hw/xfree86/modes/xf86Cursors.c
+++ b/hw/xfree86/modes/xf86Cursors.c
@@ -330,23 +330,23 @@ xf86_crtc_set_cursor_position (xf86CrtcPtr crtc, int x, int y)
 
 	v.v[0] = x + ScreenPriv->HotX; v.v[1] = y + ScreenPriv->HotY; v.v[2] = 1;
 	pict_f_transform_point (&crtc->f_framebuffer_to_crtc, &v);
-	x = floor (v.v[0] + 0.5) - ScreenPriv->HotX;
-	y = floor (v.v[1] + 0.5) - ScreenPriv->HotY;
+	x = floor (v.v[0] + 0.5);
+	y = floor (v.v[1] + 0.5);
+	/*
+	 * Transform position of cursor upper left corner
+	 */
+	xf86_crtc_rotate_coord_back (crtc->rotation,
+				     cursor_info->MaxWidth,
+				     cursor_info->MaxHeight,
+				     ScreenPriv->HotX, ScreenPriv->HotY, &dx, &dy);
+	x -= dx;
+	y -= dy;
    }
     else
     {
 	x -= crtc->x;
 	y -= crtc->y;
     }
-    /*
-     * Transform position of cursor upper left corner
-     */
-    xf86_crtc_rotate_coord_back (crtc->rotation,
-				 cursor_info->MaxWidth,
-				 cursor_info->MaxHeight,
-				 0, 0, &dx, &dy);
-    x -= dx;
-    y -= dy;
 
     /*
      * Disable the cursor when it is outside the viewport
commit 93179c214fc6ed88f72955a11c69ae0a47316d8c
Author: Keith Packard <keithp at keithp.com>
Date:   Fri Mar 21 03:14:47 2008 -0700

    rrtransform needs randrstr to get RANDR_INTERFACE defines

diff --git a/randr/rrtransform.c b/randr/rrtransform.c
index f9934d7..836a7ae 100644
--- a/randr/rrtransform.c
+++ b/randr/rrtransform.c
@@ -20,6 +20,7 @@
  * OF THIS SOFTWARE.
  */
 
+#include "randrstr.h"
 #include "rrtransform.h"
 
 void
commit 7c61db66a470a8306e346ed8bf8934f014dada42
Author: Keith Packard <keithp at keithp.com>
Date:   Fri Mar 21 02:39:49 2008 -0700

    Create rrtransform.[ch]. Add RRTransform argument to RRCrtcNotify.
    
    Instead of using a separate function to notify DIX about transform changes,
    add the transform to RRCrtcNotify so that the whole Crtc state changes
    atomically.

diff --git a/hw/xfree86/modes/xf86Crtc.c b/hw/xfree86/modes/xf86Crtc.c
index bccda0e..d24fc86 100644
--- a/hw/xfree86/modes/xf86Crtc.c
+++ b/hw/xfree86/modes/xf86Crtc.c
@@ -282,6 +282,7 @@ xf86CrtcSetModeTransform (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotati
     crtc->y = y;
     crtc->rotation = rotation;
     if (transform) {
+	RRTransformCopy (&crtc->transform, transform);
 	crtc->transform = *transform;
 	crtc->transformPresent = TRUE;
     } else
@@ -367,10 +368,6 @@ xf86CrtcSetModeTransform (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotati
 	if (output->crtc == crtc)
 	    output->funcs->commit(output);
     }
-#ifdef RANDR_12_INTERFACE
-    if (crtc->randr_crtc)
-	RRCrtcSetTransform (crtc->randr_crtc, transform);
-#endif
 
     /* XXX free adjustedmode */
     ret = TRUE;
diff --git a/hw/xfree86/modes/xf86RandR12.c b/hw/xfree86/modes/xf86RandR12.c
index 49add63..9d7750f 100644
--- a/hw/xfree86/modes/xf86RandR12.c
+++ b/hw/xfree86/modes/xf86RandR12.c
@@ -715,7 +715,9 @@ xf86RandR12CrtcNotify (RRCrtcPtr	randr_crtc)
 	}
     }
     ret = RRCrtcNotify (randr_crtc, randr_mode, x, y,
-			rotation, numOutputs, randr_outputs);
+			rotation, 
+			crtc->transformPresent ? &crtc->transform : NULL,
+			numOutputs, randr_outputs);
     xfree(randr_outputs);
     return ret;
 }
diff --git a/hw/xfree86/modes/xf86Rotate.c b/hw/xfree86/modes/xf86Rotate.c
index 7d35c34..75f4a55 100644
--- a/hw/xfree86/modes/xf86Rotate.c
+++ b/hw/xfree86/modes/xf86Rotate.c
@@ -395,7 +395,7 @@ xf86CrtcRotate (xf86CrtcPtr crtc)
     if (crtc->transformPresent)
 	transform = &crtc->transform;
 
-    if (!RRComputeTransform (crtc->x, crtc->y,
+    if (!RRTransformCompute (crtc->x, crtc->y,
 			     crtc->mode.HDisplay, crtc->mode.VDisplay,
 			     crtc->rotation,
 			     transform,
diff --git a/randr/Makefile.am b/randr/Makefile.am
index 20b0f72..3d16ede 100644
--- a/randr/Makefile.am
+++ b/randr/Makefile.am
@@ -20,7 +20,9 @@ librandr_la_SOURCES =	\
 	rrpointer.c	\
 	rrproperty.c	\
 	rrscreen.c	\
-	rrsdispatch.c
+	rrsdispatch.c	\
+	rrtransform.h	\
+	rrtransform.c
 
 if XINERAMA
 librandr_la_SOURCES += ${XINERAMA_SRCS}
diff --git a/randr/mirandr.c b/randr/mirandr.c
index 7777853..05375e4 100644
--- a/randr/mirandr.c
+++ b/randr/mirandr.c
@@ -159,7 +159,7 @@ miRandRInit (ScreenPtr pScreen)
 	return FALSE;
     if (!RROutputSetConnection (output, RR_Connected))
 	return FALSE;
-    RRCrtcNotify (crtc, mode, 0, 0, RR_Rotate_0, 1, &output);
+    RRCrtcNotify (crtc, mode, 0, 0, RR_Rotate_0, NULL, 1, &output);
 #endif
     return TRUE;
 }
diff --git a/randr/randrstr.h b/randr/randrstr.h
index d4cfa67..822e377 100644
--- a/randr/randrstr.h
+++ b/randr/randrstr.h
@@ -43,6 +43,7 @@
 #include "pixmapstr.h"
 #include "extnsionst.h"
 #include "servermd.h"
+#include "rrtransform.h"
 #include <X11/extensions/randr.h>
 #include <X11/extensions/randrproto.h>
 #ifdef RENDER
@@ -78,7 +79,6 @@ typedef struct _rrPropertyValue	RRPropertyValueRec, *RRPropertyValuePtr;
 typedef struct _rrProperty	RRPropertyRec, *RRPropertyPtr;
 typedef struct _rrCrtc		RRCrtcRec, *RRCrtcPtr;
 typedef struct _rrOutput	RROutputRec, *RROutputPtr;
-typedef struct _rrTransform	RRTransformRec, *RRTransformPtr;
 
 struct _rrMode {
     int		    refcnt;
@@ -105,17 +105,6 @@ struct _rrProperty {
     RRPropertyValueRec	current, pending;
 };
 
-struct _rrTransform {
-    PictTransform   transform;
-    struct pict_f_transform f_transform;
-    struct pict_f_transform f_inverse;
-    PictFilterPtr   filter;
-    xFixed	    *params;
-    int		    nparams;
-    int		    width;
-    int		    height;
-};
-
 struct _rrCrtc {
     RRCrtc	    id;
     ScreenPtr	    pScreen;
@@ -557,6 +546,7 @@ RRCrtcNotify (RRCrtcPtr	    crtc,
 	      int	    x,
 	      int	    y,
 	      Rotation	    rotation,
+	      RRTransformPtr transform,
 	      int	    numOutputs,
 	      RROutputPtr   *outputs);
 
@@ -618,7 +608,7 @@ RRCrtcGetScanoutSize(RRCrtcPtr crtc, int *width, int *height);
  * Return TRUE if the resulting transform is not a simple translation.
  */
 Bool
-RRComputeTransform (int			    x,
+RRTransformCompute (int			    x,
 		    int			    y,
 		    int			    width,
 		    int			    height,
@@ -636,12 +626,6 @@ RRTransformPtr
 RRCrtcGetTransform (RRCrtcPtr crtc);
 
 /*
- * Mark the pending transform as current
- */
-void
-RRCrtcSetTransform (RRCrtcPtr crtc, RRTransformPtr transform);
-
-/*
  * Check whether the pending and current transforms are the same
  */
 Bool
diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
index 091517a..1b6350e 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -48,69 +48,6 @@ RRCrtcChanged (RRCrtcPtr crtc, Bool layoutChanged)
     }
 }
 
-static void
-RRTransformInit (RRTransformPtr transform)
-{
-    PictureTransformInitIdentity (&transform->transform);
-    pict_f_transform_init_identity (&transform->f_transform);
-    pict_f_transform_init_identity (&transform->f_inverse);
-    transform->filter = NULL;
-    transform->params = NULL;
-    transform->nparams = 0;
-}
-
-static Bool
-RRTransformSetFilter (RRTransformPtr	dst,
-		      PictFilterPtr	filter,
-		      xFixed		*params,
-		      int		nparams,
-		      int		width,
-		      int		height)
-{
-    xFixed  *new_params;
-
-    if (nparams)
-    {
-	new_params = xalloc (nparams * sizeof (xFixed));
-	if (!new_params)
-	    return FALSE;
-	memcpy (new_params, params, nparams * sizeof (xFixed));
-    }
-    else
-	new_params = NULL;
-    if (dst->params)
-	xfree (dst->params);
-    dst->filter = filter;
-    dst->params = new_params;
-    dst->nparams = nparams;
-    dst->width = width;
-    dst->height = height;
-    return TRUE;
-}
-
-static Bool
-RRTransformCopy (RRTransformPtr dst, RRTransformPtr src)
-{
-    if (src)
-    {
-	if (!RRTransformSetFilter (dst, src->filter,
-				   src->params, src->nparams, src->width, src->height))
-	    return FALSE;
-	dst->transform = src->transform;
-	dst->f_transform = src->f_transform;
-	dst->f_inverse = src->f_inverse;
-    }
-    else
-    {
-	if (!RRTransformSetFilter (dst, NULL, NULL, 0, 0, 0))
-	    return FALSE;
-	PictureTransformInitIdentity (&dst->transform);
-	pict_f_transform_init_identity (&dst->f_transform);
-	pict_f_transform_init_identity (&dst->f_inverse);
-    }
-    return TRUE;
-}
-
 /*
  * Create a CRTC
  */
@@ -196,6 +133,7 @@ RRCrtcNotify (RRCrtcPtr	    crtc,
 	      int	    x,
 	      int	    y,
 	      Rotation	    rotation,
+	      RRTransformPtr transform,
 	      int	    numOutputs,
 	      RROutputPtr   *outputs)
 {
@@ -291,6 +229,10 @@ RRCrtcNotify (RRCrtcPtr	    crtc,
 	crtc->rotation = rotation;
 	RRCrtcChanged (crtc, TRUE);
     }
+    if (!RRTransformEqual (transform, &crtc->client_current_transform)) {
+	RRTransformCopy (&crtc->client_current_transform, transform);
+	RRCrtcChanged (crtc, TRUE);
+    }
     return TRUE;
 }
 
@@ -391,7 +333,7 @@ RRCrtcSet (RRCrtcPtr    crtc,
 
 		if (!mode)
 		{
-		    RRCrtcNotify (crtc, NULL, x, y, rotation, 0, NULL);
+		    RRCrtcNotify (crtc, NULL, x, y, rotation, NULL, 0, NULL);
 		    ret = TRUE;
 		}
 		else
@@ -417,7 +359,7 @@ RRCrtcSet (RRCrtcPtr    crtc,
 		     */
 		    if (ret)
 		    {
-			RRCrtcNotify (crtc, mode, x, y, rotation, 1, outputs);
+			RRCrtcNotify (crtc, mode, x, y, rotation, NULL, 1, outputs);
 			RRScreenSizeNotify (pScreen);
 		    }
 		}
@@ -450,27 +392,6 @@ RRCrtcGetTransform (RRCrtcPtr crtc)
 }
 
 /*
- * Called when driver applies a transform to a crtc
- */
-void
-RRCrtcSetTransform (RRCrtcPtr crtc, RRTransformPtr transform)
-{
-    if (!crtc->mode)
-	return;
-
-    RRTransformCopy (&crtc->client_current_transform, transform);
-
-    RRComputeTransform (crtc->x, crtc->y,
-			crtc->mode->mode.width,
-			crtc->mode->mode.height,
-			crtc->rotation,
-			transform,
-			&crtc->transform,
-			&crtc->f_transform,
-			&crtc->f_inverse);
-}
-
-/*
  * Check whether the pending and current transforms are the same
  */
 Bool
@@ -674,141 +595,6 @@ RRCrtcTransformSet (RRCrtcPtr		crtc,
     return Success;
 }
 
-#define F(x)	IntToxFixed(x)
-
-/*
- * Compute the complete transformation matrix including
- * client-specified transform, rotation/reflection values and the crtc 
- * offset.
- *
- * Return TRUE if the resulting transform is not a simple translation.
- */
-Bool
-RRComputeTransform (int			    x,
-		    int			    y,
-		    int			    width,
-		    int			    height,
-		    Rotation		    rotation,
-		    RRTransformPtr	    rr_transform,
-
-		    PictTransformPtr	    transform,
-		    struct pict_f_transform *f_transform,
-		    struct pict_f_transform *f_inverse)
-{
-    PictTransform	    inverse;
-
-    PictureTransformInitIdentity (transform);
-    PictureTransformInitIdentity (&inverse);
-    pict_f_transform_init_identity (f_transform);
-    pict_f_transform_init_identity (f_inverse);
-    if (rotation != RR_Rotate_0)
-    {
-	double	f_rot_cos, f_rot_sin, f_rot_dx, f_rot_dy;
-	double	f_scale_x, f_scale_y, f_scale_dx, f_scale_dy;
-	xFixed	rot_cos, rot_sin, rot_dx, rot_dy;
-	xFixed	scale_x, scale_y, scale_dx, scale_dy;
-
-	/* rotation */
-	switch (rotation & 0xf) {
-	default:
-	case RR_Rotate_0:
-	    f_rot_cos = 1;	    f_rot_sin = 0;
-	    f_rot_dx  = 0;	    f_rot_dy  = 0;
-	    rot_cos = F ( 1);	    rot_sin = F ( 0);
-	    rot_dx  = F ( 0);	    rot_dy  = F ( 0);
-	    break;
-	case RR_Rotate_90:
-	    f_rot_cos = 0;	    f_rot_sin = 1;
-	    f_rot_dx  = height;	    f_rot_dy  = 0;
-	    rot_cos = F ( 0);	    rot_sin = F ( 1);
-	    rot_dx =  F ( height);  rot_dy  = F (0);
-	    break;
-	case RR_Rotate_180:
-	    f_rot_cos = -1;	    f_rot_sin = 0;
-	    f_rot_dx  = width;	    f_rot_dy  = height;
-	    rot_cos = F (-1);	    rot_sin = F ( 0);
-	    rot_dx  = F (width);   rot_dy  = F ( height);
-	    break;
-	case RR_Rotate_270:
-	    f_rot_cos = 0;	    f_rot_sin = -1;
-	    f_rot_dx  = 0;	    f_rot_dy  = width;
-	    rot_cos = F ( 0);	    rot_sin = F (-1);
-	    rot_dx  = F ( 0);	    rot_dy  = F ( width);
-	    break;
-	}
-	
-	PictureTransformRotate (&inverse, transform, rot_cos, rot_sin);
-	PictureTransformTranslate (&inverse, transform, rot_dx, rot_dy);
-	pict_f_transform_rotate (f_inverse, f_transform, f_rot_cos, f_rot_sin);
-	pict_f_transform_translate (f_inverse, f_transform, f_rot_dx, f_rot_dy);
-
-	/* reflection */
-	f_scale_x = 1;
-	f_scale_dx = 0;
-	f_scale_y = 1;
-	f_scale_dy = 0;
-	scale_x = F (1);
-	scale_dx = 0;
-	scale_y = F (1);
-	scale_dy = 0;
-	if (rotation & RR_Reflect_X)
-	{
-	    f_scale_x = -1;
-	    scale_x = F(-1);
-	    if (rotation & (RR_Rotate_0|RR_Rotate_180)) {
-		f_scale_dx = width;
-		scale_dx = F(width);
-	    } else {
-		f_scale_dx = height;
-		scale_dx = F(height);
-	    }
-	}
-	if (rotation & RR_Reflect_Y)
-	{
-	    f_scale_y = -1;
-	    scale_y = F(-1);
-	    if (rotation & (RR_Rotate_0|RR_Rotate_180)) {
-		f_scale_dy = height;
-		scale_dy = F(height);
-	    } else {
-		f_scale_dy = width;
-		scale_dy = F(width);
-	    }
-	}
-	
-	PictureTransformScale (&inverse, transform, scale_x, scale_y);
-	pict_f_transform_scale (f_inverse, f_transform, f_scale_x, f_scale_y);
-	PictureTransformTranslate (&inverse, transform, scale_dx, scale_dy);
-	pict_f_transform_translate (f_inverse, f_transform, f_scale_dx, f_scale_dy);
-    }
-    
-#ifdef RANDR_12_INTERFACE
-    if (rr_transform)
-    {
-        PictureTransformMultiply (transform, transform, &rr_transform->transform);
-	pict_f_transform_multiply (f_transform, f_transform, &rr_transform->f_transform);
-	pict_f_transform_multiply (f_inverse, &rr_transform->f_inverse, f_inverse);
-    }
-#endif
-    /*
-     * Compute the class of the resulting transform
-     */
-    if (PictureTransformIsIdentity (transform))
-    {
-	PictureTransformInitTranslate (transform, F ( x), F ( y));
-
-	pict_f_transform_init_translate (f_transform, F( x), F( y));
-	pict_f_transform_init_translate (f_inverse,   F(-x), F(-y));
-	return FALSE;
-    }
-    else
-    {
-	PictureTransformTranslate (&inverse, transform, x, y);
-	pict_f_transform_translate (f_inverse, f_transform, x, y);
-	return TRUE;
-    }
-}
-
 /*
  * Initialize crtc type
  */
@@ -1116,7 +902,7 @@ ProcRRSetCrtcConfig (ClientPtr client)
 	    PictTransform transform;
 	    struct pict_f_transform f_transform, f_inverse;
 
-	    RRComputeTransform (stuff->x, stuff->y,
+	    RRTransformCompute (stuff->x, stuff->y,
 				mode->mode.width, mode->mode.height,
 				rotation,
 				&crtc->client_pending_transform,
diff --git a/randr/rrinfo.c b/randr/rrinfo.c
index 7e77d39..38314de 100644
--- a/randr/rrinfo.c
+++ b/randr/rrinfo.c
@@ -170,7 +170,7 @@ RRScanOldConfig (ScreenPtr pScreen, Rotation rotations)
     /* notice current mode */
     if (newMode)
 	RRCrtcNotify (crtc, newMode, 0, 0, pScrPriv->rotation,
-		      1, &output);
+		      NULL, 1, &output);
 }
 #endif
 
diff --git a/randr/rrtransform.c b/randr/rrtransform.c
new file mode 100644
index 0000000..f9934d7
--- /dev/null
+++ b/randr/rrtransform.c
@@ -0,0 +1,259 @@
+/*
+ * Copyright © 2007 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#include "rrtransform.h"
+
+void
+RRTransformInit (RRTransformPtr transform)
+{
+    PictureTransformInitIdentity (&transform->transform);
+    pict_f_transform_init_identity (&transform->f_transform);
+    pict_f_transform_init_identity (&transform->f_inverse);
+    transform->filter = NULL;
+    transform->params = NULL;
+    transform->nparams = 0;
+}
+
+void
+RRTransformFini (RRTransformPtr transform)
+{
+    if (transform->params)
+	xfree (transform->params);
+}
+
+Bool
+RRTransformEqual (RRTransformPtr a, RRTransformPtr b)
+{
+    if (a && PictureTransformIsIdentity (&a->transform))
+	a = NULL;
+    if (b && PictureTransformIsIdentity (&b->transform))
+	b = NULL;
+    if (a == NULL && b == NULL)
+	return TRUE;
+    if (a == NULL || b == NULL)
+	return FALSE;
+    if (memcmp (&a->transform, &b->transform, sizeof (a->transform)) != 0)
+	return FALSE;
+    if (a->filter != b->filter)
+	return FALSE;
+    if (a->nparams != b->nparams)
+	return FALSE;
+    if (memcmp (a->params, b->params, a->nparams * sizeof (xFixed)) != 0)
+	return FALSE;
+    return TRUE;
+}
+
+Bool
+RRTransformSetFilter (RRTransformPtr	dst,
+		      PictFilterPtr	filter,
+		      xFixed		*params,
+		      int		nparams,
+		      int		width,
+		      int		height)
+{
+    xFixed  *new_params;
+
+    if (nparams)
+    {
+	new_params = xalloc (nparams * sizeof (xFixed));
+	if (!new_params)
+	    return FALSE;
+	memcpy (new_params, params, nparams * sizeof (xFixed));
+    }
+    else
+	new_params = NULL;
+    if (dst->params)
+	xfree (dst->params);
+    dst->filter = filter;
+    dst->params = new_params;
+    dst->nparams = nparams;
+    dst->width = width;
+    dst->height = height;
+    return TRUE;
+}
+
+Bool
+RRTransformCopy (RRTransformPtr dst, RRTransformPtr src)
+{
+    if (src && PictureTransformIsIdentity (&src->transform))
+	src = NULL;
+
+    if (src)
+    {
+	if (!RRTransformSetFilter (dst, src->filter,
+				   src->params, src->nparams, src->width, src->height))
+	    return FALSE;
+	dst->transform = src->transform;
+	dst->f_transform = src->f_transform;
+	dst->f_inverse = src->f_inverse;
+    }
+    else
+    {
+	if (!RRTransformSetFilter (dst, NULL, NULL, 0, 0, 0))
+	    return FALSE;
+	PictureTransformInitIdentity (&dst->transform);
+	pict_f_transform_init_identity (&dst->f_transform);
+	pict_f_transform_init_identity (&dst->f_inverse);
+    }
+    return TRUE;
+}
+
+#define F(x)	IntToxFixed(x)
+
+/*
+ * Compute the complete transformation matrix including
+ * client-specified transform, rotation/reflection values and the crtc 
+ * offset.
+ *
+ * Return TRUE if the resulting transform is not a simple translation.
+ */
+Bool
+RRTransformCompute (int			    x,
+		    int			    y,
+		    int			    width,
+		    int			    height,
+		    Rotation		    rotation,
+		    RRTransformPtr	    rr_transform,
+
+		    PictTransformPtr	    transform,
+		    struct pict_f_transform *f_transform,
+		    struct pict_f_transform *f_inverse)
+{
+    PictTransform	    t_transform, inverse;
+    struct pict_f_transform tf_transform, tf_inverse;
+
+    if (!transform) transform = &t_transform;
+    if (!f_transform) f_transform = &tf_transform;
+    if (!f_inverse) f_inverse = &tf_inverse;
+
+    PictureTransformInitIdentity (transform);
+    PictureTransformInitIdentity (&inverse);
+    pict_f_transform_init_identity (f_transform);
+    pict_f_transform_init_identity (f_inverse);
+    if (rotation != RR_Rotate_0)
+    {
+	double	f_rot_cos, f_rot_sin, f_rot_dx, f_rot_dy;
+	double	f_scale_x, f_scale_y, f_scale_dx, f_scale_dy;
+	xFixed	rot_cos, rot_sin, rot_dx, rot_dy;
+	xFixed	scale_x, scale_y, scale_dx, scale_dy;
+
+	/* rotation */
+	switch (rotation & 0xf) {
+	default:
+	case RR_Rotate_0:
+	    f_rot_cos = 1;	    f_rot_sin = 0;
+	    f_rot_dx  = 0;	    f_rot_dy  = 0;
+	    rot_cos = F ( 1);	    rot_sin = F ( 0);
+	    rot_dx  = F ( 0);	    rot_dy  = F ( 0);
+	    break;
+	case RR_Rotate_90:
+	    f_rot_cos = 0;	    f_rot_sin = 1;
+	    f_rot_dx  = height;	    f_rot_dy  = 0;
+	    rot_cos = F ( 0);	    rot_sin = F ( 1);
+	    rot_dx =  F ( height);  rot_dy  = F (0);
+	    break;
+	case RR_Rotate_180:
+	    f_rot_cos = -1;	    f_rot_sin = 0;
+	    f_rot_dx  = width;	    f_rot_dy  = height;
+	    rot_cos = F (-1);	    rot_sin = F ( 0);
+	    rot_dx  = F (width);   rot_dy  = F ( height);
+	    break;
+	case RR_Rotate_270:
+	    f_rot_cos = 0;	    f_rot_sin = -1;
+	    f_rot_dx  = 0;	    f_rot_dy  = width;
+	    rot_cos = F ( 0);	    rot_sin = F (-1);
+	    rot_dx  = F ( 0);	    rot_dy  = F ( width);
+	    break;
+	}
+	
+	PictureTransformRotate (transform, &inverse, rot_cos, rot_sin);
+	PictureTransformTranslate (transform, &inverse, rot_dx, rot_dy);
+	pict_f_transform_rotate (f_transform, f_inverse, f_rot_cos, f_rot_sin);
+	pict_f_transform_translate (f_transform, f_inverse, f_rot_dx, f_rot_dy);
+
+	/* reflection */
+	f_scale_x = 1;
+	f_scale_dx = 0;
+	f_scale_y = 1;
+	f_scale_dy = 0;
+	scale_x = F (1);
+	scale_dx = 0;
+	scale_y = F (1);
+	scale_dy = 0;
+	if (rotation & RR_Reflect_X)
+	{
+	    f_scale_x = -1;
+	    scale_x = F(-1);
+	    if (rotation & (RR_Rotate_0|RR_Rotate_180)) {
+		f_scale_dx = width;
+		scale_dx = F(width);
+	    } else {
+		f_scale_dx = height;
+		scale_dx = F(height);
+	    }
+	}
+	if (rotation & RR_Reflect_Y)
+	{
+	    f_scale_y = -1;
+	    scale_y = F(-1);
+	    if (rotation & (RR_Rotate_0|RR_Rotate_180)) {
+		f_scale_dy = height;
+		scale_dy = F(height);
+	    } else {
+		f_scale_dy = width;
+		scale_dy = F(width);
+	    }
+	}
+	
+	PictureTransformScale (transform, &inverse, scale_x, scale_y);
+	pict_f_transform_scale (f_transform, f_inverse, f_scale_x, f_scale_y);
+	PictureTransformTranslate (transform, &inverse, scale_dx, scale_dy);
+	pict_f_transform_translate (f_transform, f_inverse, f_scale_dx, f_scale_dy);
+    }
+    
+#ifdef RANDR_12_INTERFACE
+    if (rr_transform)
+    {
+        PictureTransformMultiply (transform, transform, &rr_transform->transform);
+	pict_f_transform_multiply (f_transform, f_transform, &rr_transform->f_transform);
+	pict_f_transform_multiply (f_inverse, &rr_transform->f_inverse, f_inverse);
+    }
+#endif
+    /*
+     * Compute the class of the resulting transform
+     */
+    if (PictureTransformIsIdentity (transform))
+    {
+	PictureTransformInitTranslate (transform, F ( x), F ( y));
+
+	pict_f_transform_init_translate (f_transform, F( x), F( y));
+	pict_f_transform_init_translate (f_inverse,   F(-x), F(-y));
+	return FALSE;
+    }
+    else
+    {
+	PictureTransformTranslate (&inverse, transform, x, y);
+	pict_f_transform_translate (f_inverse, f_transform, x, y);
+	return TRUE;
+    }
+}
+
diff --git a/randr/rrtransform.h b/randr/rrtransform.h
new file mode 100644
index 0000000..92d3ee7
--- /dev/null
+++ b/randr/rrtransform.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright © 2007 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#ifndef _RRTRANSFORM_H_
+#define _RRTRANSFORM_H_
+
+#include <X11/extensions/randr.h>
+#include "picturestr.h"
+
+typedef struct _rrTransform	RRTransformRec, *RRTransformPtr;
+
+struct _rrTransform {
+    PictTransform   transform;
+    struct pict_f_transform f_transform;
+    struct pict_f_transform f_inverse;
+    PictFilterPtr   filter;
+    xFixed	    *params;
+    int		    nparams;
+    int		    width;
+    int		    height;
+};
+
+void
+RRTransformInit (RRTransformPtr transform);
+
+void
+RRTransformFini (RRTransformPtr transform);
+
+Bool
+RRTransformEqual (RRTransformPtr a, RRTransformPtr b);
+
+Bool
+RRTransformSetFilter (RRTransformPtr	dst,
+		      PictFilterPtr	filter,
+		      xFixed		*params,
+		      int		nparams,
+		      int		width,
+		      int		height);
+
+Bool
+RRTransformCopy (RRTransformPtr dst, RRTransformPtr src);
+
+Bool
+RRTransformCompute (int			    x,
+		    int			    y,
+		    int			    width,
+		    int			    height,
+		    Rotation		    rotation,
+		    RRTransformPtr	    rr_transform,
+
+		    PictTransformPtr	    transform,
+		    struct pict_f_transform *f_transform,
+		    struct pict_f_transform *f_inverse);
+
+
+#endif /* _RRTRANSFORM_H_ */
commit fa6a1df209bd74da1d545982cca437afc2198cc1
Author: Keith Packard <keithp at keithp.com>
Date:   Fri Mar 21 02:35:28 2008 -0700

    Avoid overflow in PictureTransformPoint. Fix PictureTransformIsIdentity.
    
    PictureTransformPoint computes homogeneous coordinates internally, but fails
    to handle intermediate values larger than 16.16. Use 64 bit intermediate
    values while computing the final result at 16.16 and only complain if that
    result is too large.
    
    PictureTransformIsIdentity was completely wrong -- it was not checking for
    identity transforms at all.

diff --git a/render/matrix.c b/render/matrix.c
index a4cde4f..603281e 100644
--- a/render/matrix.c
+++ b/render/matrix.c
@@ -50,6 +50,8 @@ PictureTransformInitIdentity (PictTransformPtr matrix)
 	matrix->matrix[i][i] = F(1);
 }
 
+typedef xFixed_32_32	xFixed_34_30;
+
 _X_EXPORT Bool
 PictureTransformPoint3d (PictTransformPtr transform,
                          PictVectorPtr	vector)
@@ -78,7 +80,6 @@ PictureTransformPoint3d (PictTransformPtr transform,
     return TRUE;
 }
 
-
 _X_EXPORT Bool
 PictureTransformPoint (PictTransformPtr transform,
 		       PictVectorPtr	vector)
@@ -86,30 +87,27 @@ PictureTransformPoint (PictTransformPtr transform,
     PictVector	    result;
     int		    i, j;
     xFixed_32_32    partial;
-    xFixed_48_16    v;
+    xFixed_34_30    v[3];
+    xFixed_48_16    quo;
 
     for (j = 0; j < 3; j++)
     {
-	v = 0;
+	v[j] = 0;
 	for (i = 0; i < 3; i++)
 	{
-	    partial = ((xFixed_48_16) transform->matrix[j][i] * 
-		       (xFixed_48_16) vector->vector[i]);
-	    v += partial >> 16;
+	    partial = ((xFixed_32_32) transform->matrix[j][i] * 
+		       (xFixed_32_32) vector->vector[i]);
+	    v[j] += partial >> 2;
 	}
-	if (v > MAX_FIXED_48_16 || v < MIN_FIXED_48_16)
-	    return FALSE;
-	result.vector[j] = (xFixed) v;
     }
-    if (!result.vector[2])
+    if (!v[2])
 	return FALSE;
     for (j = 0; j < 2; j++)
     {
-	partial = (xFixed_48_16) result.vector[j] << 16;
-	v = partial / result.vector[2];
-	if (v > MAX_FIXED_48_16 || v < MIN_FIXED_48_16)
+	quo = v[j] / (v[2] >> 16);
+	if (quo > MAX_FIXED_48_16 || quo < MIN_FIXED_48_16)
 	    return FALSE;
-	vector->vector[j] = (xFixed) v;
+	vector->vector[j] = (xFixed) quo;
     }
     vector->vector[2] = xFixed1;
     return TRUE;
@@ -296,29 +294,15 @@ within_epsilon (xFixed a, xFixed b, xFixed epsilon)
 _X_EXPORT Bool
 PictureTransformIsIdentity(PictTransform *t)
 {
-    return (IsUnit (t->matrix[0][0]) &&
-	    IsUnit (t->matrix[0][1]) &&
-            IsInt  (t->matrix[0][2]) &&
-	    IsUnit (t->matrix[1][0]) &&
-	    IsUnit (t->matrix[1][1]) &&
-            IsInt  (t->matrix[1][2]) &&
-            IsZero (t->matrix[2][0]) &&
-            IsZero (t->matrix[2][1]) &&
-	    IsOne  (t->matrix[2][2]));
-}
-
-_X_EXPORT Bool
-PictureTransformIsUnit(PictTransform *t)
-{
-    return (IsSame (t->matrix[0][0],t->matrix[1][1]) &&
+    return (IsSame (t->matrix[0][0], t->matrix[1][1]) &&
 	    IsSame (t->matrix[0][0], t->matrix[2][2]) &&
-            !IsZero (t->matrix[0][0]) &&
+	    !IsZero (t->matrix[0][0]) &&
 	    IsZero (t->matrix[0][1]) &&
-            IsZero (t->matrix[0][2]) &&
-            IsZero (t->matrix[1][0]) &&
-            IsZero (t->matrix[1][2]) &&
-            IsZero (t->matrix[2][0]) &&
-            IsZero (t->matrix[2][1]));
+	    IsZero (t->matrix[0][2]) &&
+	    IsZero (t->matrix[1][0]) &&
+	    IsZero (t->matrix[1][2]) &&
+	    IsZero (t->matrix[2][0]) &&
+	    IsZero (t->matrix[2][1]));
 }
 
 _X_EXPORT Bool
@@ -334,11 +318,11 @@ PictureTransformIsScale(PictTransform *t)
 	    
 	     IsZero (t->matrix[2][0]) &&
 	     IsZero (t->matrix[2][1]) &&
-	     IsOne (t->matrix[2][2]));
+	    !IsZero (t->matrix[2][2]));
 }
 
 _X_EXPORT Bool
-PictureTransformIsTranslate(PictTransform *t)
+PictureTransformIsIntTranslate(PictTransform *t)
 {
     return ( IsOne  (t->matrix[0][0]) &&
 	     IsZero (t->matrix[0][1]) &&
diff --git a/render/picturestr.h b/render/picturestr.h
index b18f316..4a7b6e7 100644
--- a/render/picturestr.h
+++ b/render/picturestr.h
@@ -734,13 +734,10 @@ Bool
 PictureTransformIsIdentity(PictTransform *t);
 
 Bool
-PictureTransformIsUnit(PictTransform *t);
-
-Bool
 PictureTransformIsScale(PictTransform *t);
 
 Bool
-PictureTransformIsTranslate (PictTransform *t);
+PictureTransformIsIntTranslate (PictTransform *t);
 
 Bool
 PictureTransformIsInverse(PictTransform *t, PictTransform *i);
commit 6fe9c15731be5f5afabacb3aa3ed71b840f4238b
Author: Keith Packard <keithp at keithp.com>
Date:   Wed Mar 19 12:15:39 2008 -0700

    Allow drivers to set crtc transforms.
    
    Track curent transform down in the mode setting code so that it may be set
    separately from RandR.

diff --git a/hw/xfree86/modes/xf86Crtc.c b/hw/xfree86/modes/xf86Crtc.c
index 9f11037..bccda0e 100644
--- a/hw/xfree86/modes/xf86Crtc.c
+++ b/hw/xfree86/modes/xf86Crtc.c
@@ -237,8 +237,8 @@ xf86CrtcSetScreenSubpixelOrder (ScreenPtr pScreen)
  * Sets the given video mode on the given crtc
  */
 _X_EXPORT Bool
-xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation,
-		 int x, int y)
+xf86CrtcSetModeTransform (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation,
+			  RRTransformPtr transform, int x, int y)
 {
     ScrnInfoPtr		scrn = crtc->scrn;
     xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
@@ -249,6 +249,8 @@ xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation,
     DisplayModeRec	saved_mode;
     int			saved_x, saved_y;
     Rotation		saved_rotation;
+    RRTransformRec	saved_transform;
+    Bool		saved_transform_present;
 
     if (crtc->funcs->set_mode_major)
 	return crtc->funcs->set_mode_major(crtc, mode, rotation, x, y);
@@ -269,6 +271,9 @@ xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation,
     saved_x = crtc->x;
     saved_y = crtc->y;
     saved_rotation = crtc->rotation;
+    saved_transform = crtc->transform;
+    saved_transform_present = crtc->transformPresent;
+
     /* Update crtc values up front so the driver can rely on them for mode
      * setting.
      */
@@ -276,6 +281,11 @@ xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation,
     crtc->x = x;
     crtc->y = y;
     crtc->rotation = rotation;
+    if (transform) {
+	crtc->transform = *transform;
+	crtc->transformPresent = TRUE;
+    } else
+	crtc->transformPresent = FALSE;
 
     /* Shift offsets that move us out of virtual size */
     if (x + mode->HDisplay > xf86_config->maxWidth ||
@@ -322,9 +332,8 @@ xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation,
 	goto done;
     }
 
-    if (!xf86CrtcRotate (crtc, mode, rotation)) {
+    if (!xf86CrtcRotate (crtc))
 	goto done;
-    }
 
     /* Prepare the outputs and CRTCs before setting the mode. */
     for (i = 0; i < xf86_config->num_output; i++) {
@@ -356,17 +365,11 @@ xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation,
     {
 	xf86OutputPtr output = xf86_config->output[i];
 	if (output->crtc == crtc)
-	{
 	    output->funcs->commit(output);
-#ifdef RANDR_12_INTERFACE
-	    if (output->randr_output)
-		RRPostPendingProperties (output->randr_output);
-#endif
-	}
     }
 #ifdef RANDR_12_INTERFACE
     if (crtc->randr_crtc)
-	RRCrtcPostPendingTransform (crtc->randr_crtc);
+	RRCrtcSetTransform (crtc->randr_crtc, transform);
 #endif
 
     /* XXX free adjustedmode */
@@ -380,6 +383,8 @@ done:
 	crtc->y = saved_y;
 	crtc->rotation = saved_rotation;
 	crtc->mode = saved_mode;
+	crtc->transform = saved_transform;
+	crtc->transformPresent = saved_transform_present;
     }
 
     if (didLock)
@@ -388,6 +393,17 @@ done:
     return ret;
 }
 
+/**
+ * Sets the given video mode on the given crtc, but without providing
+ * a transform
+ */
+_X_EXPORT Bool
+xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation,
+		 int x, int y)
+{
+    return xf86CrtcSetModeTransform (crtc, mode, rotation, NULL, x, y);
+}
+
 /*
  * Output functions
  */
@@ -740,12 +756,12 @@ xf86CrtcScreenInit (ScreenPtr screen)
 	xf86RandR12SetRotations (screen, RR_Rotate_0 | RR_Rotate_90 |
 				 RR_Rotate_180 | RR_Rotate_270 |
 				 RR_Reflect_X | RR_Reflect_Y);
-	xf86RandR12SetTransform (screen, TRUE);
+	xf86RandR12SetTransformSupport (screen, TRUE);
     }
     else
     {
 	xf86RandR12SetRotations (screen, RR_Rotate_0);
-	xf86RandR12SetTransform (screen, FALSE);
+	xf86RandR12SetTransformSupport (screen, FALSE);
     }
     
     /* Wrap CreateScreenResources so we can initialize the RandR code */
@@ -2236,6 +2252,7 @@ xf86InitialConfiguration (ScrnInfoPtr scrn, Bool canGrow)
 	    crtc->desiredRotation = output->initial_rotation;
 	    crtc->desiredX = output->initial_x;
 	    crtc->desiredY = output->initial_y;
+	    crtc->desiredTransformPresent = FALSE;
 	    crtc->enabled = TRUE;
 	    crtc->x = output->initial_x;
 	    crtc->y = output->initial_y;
@@ -2367,6 +2384,7 @@ xf86SetDesiredModes (ScrnInfoPtr scrn)
 	xf86CrtcPtr	crtc = config->crtc[c];
 	xf86OutputPtr	output = NULL;
 	int		o;
+	RRTransformPtr	transform;
 
 	/* Skip disabled CRTCs */
 	if (!crtc->enabled)
@@ -2397,12 +2415,17 @@ xf86SetDesiredModes (ScrnInfoPtr scrn)
 		return FALSE;
 	    crtc->desiredMode = *mode;
 	    crtc->desiredRotation = RR_Rotate_0;
+	    crtc->desiredTransformPresent = FALSE;
 	    crtc->desiredX = 0;
 	    crtc->desiredY = 0;
 	}
 
-	if (!xf86CrtcSetMode (crtc, &crtc->desiredMode, crtc->desiredRotation,
-			      crtc->desiredX, crtc->desiredY))
+	if (crtc->desiredTransformPresent)
+	    transform = &crtc->desiredTransform;
+	else
+	    transform = NULL;
+	if (!xf86CrtcSetModeTransform (crtc, &crtc->desiredMode, crtc->desiredRotation,
+				       transform, crtc->desiredX, crtc->desiredY))
 	    return FALSE;
     }
 
@@ -2531,12 +2554,13 @@ xf86SetSingleMode (ScrnInfoPtr pScrn, DisplayModePtr desired, Rotation rotation)
 	    crtc->enabled = FALSE;
 	    continue;
 	}
-	if (!xf86CrtcSetMode (crtc, crtc_mode, rotation, 0, 0))
+	if (!xf86CrtcSetModeTransform (crtc, crtc_mode, rotation, NULL, 0, 0))
 	    ok = FALSE;
 	else
 	{
 	    crtc->desiredMode = *crtc_mode;
 	    crtc->desiredRotation = rotation;
+	    crtc->desiredTransformPresent = FALSE;
 	    crtc->desiredX = 0;
 	    crtc->desiredY = 0;
 	}
diff --git a/hw/xfree86/modes/xf86Crtc.h b/hw/xfree86/modes/xf86Crtc.h
index 026ec78..4b6f7d2 100644
--- a/hw/xfree86/modes/xf86Crtc.h
+++ b/hw/xfree86/modes/xf86Crtc.h
@@ -313,6 +313,10 @@ struct _xf86Crtc {
     int		    filter_width;
     int		    filter_height;
     Bool	    transform_in_use;
+    RRTransformRec  transform;
+    Bool	    transformPresent;
+    RRTransformRec  desiredTransform;
+    Bool	    desiredTransformPresent;
     /**
      * Bounding box in screen space
      */
@@ -665,6 +669,11 @@ xf86CrtcDestroy (xf86CrtcPtr		crtc);
 /**
  * Sets the given video mode on the given crtc
  */
+
+Bool
+xf86CrtcSetModeTransform (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation,
+			  RRTransformPtr transform, int x, int y);
+
 Bool
 xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation,
 		 int x, int y);
@@ -673,7 +682,7 @@ xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation,
  * Assign crtc rotation during mode set
  */
 Bool
-xf86CrtcRotate (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation);
+xf86CrtcRotate (xf86CrtcPtr crtc);
 
 /*
  * free shadow memory allocated for all crtcs
diff --git a/hw/xfree86/modes/xf86RandR12.c b/hw/xfree86/modes/xf86RandR12.c
index f247a88..49add63 100644
--- a/hw/xfree86/modes/xf86RandR12.c
+++ b/hw/xfree86/modes/xf86RandR12.c
@@ -569,7 +569,7 @@ xf86RandR12SetRotations (ScreenPtr pScreen, Rotation rotations)
 }
 
 _X_EXPORT void
-xf86RandR12SetTransform (ScreenPtr pScreen, Bool transforms)
+xf86RandR12SetTransformSupport (ScreenPtr pScreen, Bool transforms)
 {
     XF86RandRInfoPtr	randrp;
 #if RANDR_13_INTERFACE
@@ -588,7 +588,7 @@ xf86RandR12SetTransform (ScreenPtr pScreen, Bool transforms)
     for (c = 0; c < config->num_crtc; c++) {
 	xf86CrtcPtr    crtc = config->crtc[c];
 
-	RRCrtcSetTransform (crtc->randr_crtc, transforms);
+	RRCrtcSetTransformSupport (crtc->randr_crtc, transforms);
     }
 #endif
 }
@@ -751,18 +751,19 @@ xf86RandRModeConvert (ScrnInfoPtr	scrn,
 }
 
 static Bool
-xf86RandR12CrtcSet (ScreenPtr	pScreen,
-		  RRCrtcPtr	randr_crtc,
-		  RRModePtr	randr_mode,
-		  int		x,
-		  int		y,
-		  Rotation	rotation,
-		  int		num_randr_outputs,
-		  RROutputPtr	*randr_outputs)
+xf86RandR12CrtcSet (ScreenPtr	    pScreen,
+		    RRCrtcPtr	    randr_crtc,
+		    RRModePtr	    randr_mode,
+		    int		    x,
+		    int		    y,
+		    Rotation	    rotation,
+		    int		    num_randr_outputs,
+		    RROutputPtr	    *randr_outputs)
 {
     ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
     xf86CrtcConfigPtr   config = XF86_CRTC_CONFIG_PTR(pScrn);
     xf86CrtcPtr		crtc = randr_crtc->devPrivate;
+    RRTransformPtr	transform;
     Bool		changed = FALSE;
     int			o, ro;
     xf86CrtcPtr		*save_crtcs;
@@ -780,7 +781,11 @@ xf86RandR12CrtcSet (ScreenPtr	pScreen,
     if (rotation != crtc->rotation)
 	changed = TRUE;
 
-    if (RRCrtcPendingTransform (randr_crtc))
+    transform = RRCrtcGetTransform (randr_crtc);
+    if ((transform != NULL) != crtc->transformPresent)
+	changed = TRUE;
+    else if (transform && memcmp (&transform->transform, &crtc->transform.transform,
+				  sizeof (transform->transform)) != 0)
 	changed = TRUE;
 
     if (x != crtc->x || y != crtc->y)
@@ -820,9 +825,10 @@ xf86RandR12CrtcSet (ScreenPtr	pScreen,
 	if (randr_mode)
 	{
 	    DisplayModeRec  mode;
+	    RRTransformPtr  transform = RRCrtcGetTransform (randr_crtc);
 
 	    xf86RandRModeConvert (pScrn, randr_mode, &mode);
-	    if (!xf86CrtcSetMode (crtc, &mode, rotation, x, y))
+	    if (!xf86CrtcSetModeTransform (crtc, &mode, rotation, transform, x, y))
 	    {
 		crtc->enabled = save_enabled;
 		for (o = 0; o < config->num_output; o++)
@@ -838,6 +844,12 @@ xf86RandR12CrtcSet (ScreenPtr	pScreen,
 	     */
 	    crtc->desiredMode = mode;
 	    crtc->desiredRotation = rotation;
+	    if (transform) {
+		crtc->desiredTransform = *transform;
+		crtc->desiredTransformPresent = TRUE;
+	    } else
+		crtc->desiredTransformPresent = FALSE;
+
 	    crtc->desiredX = x;
 	    crtc->desiredY = y;
 	}
diff --git a/hw/xfree86/modes/xf86RandR12.h b/hw/xfree86/modes/xf86RandR12.h
index c361b47..17a2dcc 100644
--- a/hw/xfree86/modes/xf86RandR12.h
+++ b/hw/xfree86/modes/xf86RandR12.h
@@ -31,7 +31,7 @@
 Bool xf86RandR12CreateScreenResources (ScreenPtr pScreen);
 Bool xf86RandR12Init(ScreenPtr pScreen);
 void xf86RandR12SetRotations (ScreenPtr pScreen, Rotation rotation);
-void xf86RandR12SetTransform (ScreenPtr pScreen, Bool transforms);
+void xf86RandR12SetTransformSupport (ScreenPtr pScreen, Bool transforms);
 Bool xf86RandR12SetConfig(ScreenPtr pScreen, Rotation rotation, int rate,
 			RRScreenSizePtr pSize);
 Rotation xf86RandR12GetRotation(ScreenPtr pScreen);
diff --git a/hw/xfree86/modes/xf86Rename.h b/hw/xfree86/modes/xf86Rename.h
index b8c1d70..e3418ca 100644
--- a/hw/xfree86/modes/xf86Rename.h
+++ b/hw/xfree86/modes/xf86Rename.h
@@ -38,6 +38,7 @@
 #define xf86CrtcInUse XF86NAME(xf86CrtcInUse)
 #define xf86CrtcRotate XF86NAME(xf86CrtcRotate)
 #define xf86CrtcScreenInit XF86NAME(xf86CrtcScreenInit)
+#define xf86CrtcSetModeTransform XF86NAME(xf86CrtcSetModeTransform)
 #define xf86CrtcSetMode XF86NAME(xf86CrtcSetMode)
 #define xf86CrtcSetSizeRange XF86NAME(xf86CrtcSetSizeRange)
 #define xf86CVTMode XF86NAME(xf86CVTMode)
diff --git a/hw/xfree86/modes/xf86Rotate.c b/hw/xfree86/modes/xf86Rotate.c
index efbacec..7d35c34 100644
--- a/hw/xfree86/modes/xf86Rotate.c
+++ b/hw/xfree86/modes/xf86Rotate.c
@@ -349,8 +349,35 @@ xf86RotateCloseScreen (ScreenPtr screen)
 	xf86RotateDestroy (xf86_config->crtc[c]);
 }
 
+static Bool
+xf86CrtcFitsScreen (xf86CrtcPtr crtc, struct pict_f_transform *crtc_to_fb)
+{
+    ScrnInfoPtr		pScrn = crtc->scrn;
+    /* if this is called during ScreenInit() we don't have pScrn->pScreen yet */
+    ScreenPtr		pScreen = screenInfo.screens[pScrn->scrnIndex];
+    BoxRec		b;
+
+    if (!pScreen)
+	return TRUE;
+    b.x1 = 0;
+    b.y1 = 0;
+    b.x2 = crtc->mode.HDisplay;
+    b.y2 = crtc->mode.VDisplay;
+    if (crtc_to_fb)
+	pict_f_transform_bounds (crtc_to_fb, &b);
+    else {
+	b.x1 += crtc->x;
+	b.y1 += crtc->y;
+	b.x2 += crtc->x;
+	b.y2 += crtc->y;
+    }
+
+    return (0 <= b.x1 && b.x2 <= pScreen->width &&
+	    0 <= b.y1 && b.y2 <= pScreen->height);
+}
+
 _X_EXPORT Bool
-xf86CrtcRotate (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation)
+xf86CrtcRotate (xf86CrtcPtr crtc)
 {
     ScrnInfoPtr		pScrn = crtc->scrn;
     xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
@@ -364,20 +391,19 @@ xf86CrtcRotate (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation)
     int			new_width = 0;
     int			new_height = 0;
     RRTransformPtr	transform = NULL;
-    
-#ifdef RANDR_12_INTERFACE
-    if (crtc->randr_crtc)
-	transform = RRCrtcGetTransform (crtc->randr_crtc);
-#endif
-    if (!transform ||
-	!RRComputeTransform (crtc->x, crtc->y,
+
+    if (crtc->transformPresent)
+	transform = &crtc->transform;
+
+    if (!RRComputeTransform (crtc->x, crtc->y,
 			     crtc->mode.HDisplay, crtc->mode.VDisplay,
-			     rotation,
+			     crtc->rotation,
 			     transform,
 
 			     &crtc_to_fb,
 			     &f_crtc_to_fb,
-			     &f_fb_to_crtc))
+			     &f_fb_to_crtc) &&
+	xf86CrtcFitsScreen (crtc, &f_crtc_to_fb))
     {
 	/*
 	 * If the untranslated transformation is the identity,
@@ -400,8 +426,8 @@ xf86CrtcRotate (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation)
 	 * matches the mode, not the pre-rotated copy in the
 	 * frame buffer
 	 */
-	int	    width = mode->HDisplay;
-	int	    height = mode->VDisplay;
+	int	    width = crtc->mode.HDisplay;
+	int	    height = crtc->mode.VDisplay;
 	void	    *shadowData = crtc->rotatedData;
 	PixmapPtr   shadow = crtc->rotatedPixmap;
 	int	    old_width = shadow ? shadow->drawable.width : 0;
diff --git a/randr/randrstr.h b/randr/randrstr.h
index 5ac983d..d4cfa67 100644
--- a/randr/randrstr.h
+++ b/randr/randrstr.h
@@ -545,7 +545,7 @@ RRCrtcSetRotations (RRCrtcPtr crtc, Rotation rotations);
  * Set whether transforms are allowed on a CRTC
  */
 void
-RRCrtcSetTransform (RRCrtcPtr crtc, Bool transforms);
+RRCrtcSetTransformSupport (RRCrtcPtr crtc, Bool transforms);
 
 /*
  * Notify the extension that the Crtc has been reconfigured,
@@ -639,7 +639,7 @@ RRCrtcGetTransform (RRCrtcPtr crtc);
  * Mark the pending transform as current
  */
 void
-RRCrtcPostPendingTransform (RRCrtcPtr crtc);
+RRCrtcSetTransform (RRCrtcPtr crtc, RRTransformPtr transform);
 
 /*
  * Check whether the pending and current transforms are the same
diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
index d7ea6f2..091517a 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -91,12 +91,23 @@ RRTransformSetFilter (RRTransformPtr	dst,
 static Bool
 RRTransformCopy (RRTransformPtr dst, RRTransformPtr src)
 {
-    if (!RRTransformSetFilter (dst, src->filter,
-			       src->params, src->nparams, src->width, src->height))
-	return FALSE;
-    dst->transform = src->transform;
-    dst->f_transform = src->f_transform;
-    dst->f_inverse = src->f_inverse;
+    if (src)
+    {
+	if (!RRTransformSetFilter (dst, src->filter,
+				   src->params, src->nparams, src->width, src->height))
+	    return FALSE;
+	dst->transform = src->transform;
+	dst->f_transform = src->f_transform;
+	dst->f_inverse = src->f_inverse;
+    }
+    else
+    {
+	if (!RRTransformSetFilter (dst, NULL, NULL, 0, 0, 0))
+	    return FALSE;
+	PictureTransformInitIdentity (&dst->transform);
+	pict_f_transform_init_identity (&dst->f_transform);
+	pict_f_transform_init_identity (&dst->f_inverse);
+    }
     return TRUE;
 }
 
@@ -170,7 +181,7 @@ RRCrtcSetRotations (RRCrtcPtr crtc, Rotation rotations)
  * Set whether transforms are allowed on a CRTC
  */
 void
-RRCrtcSetTransform (RRCrtcPtr crtc, Bool transforms)
+RRCrtcSetTransformSupport (RRCrtcPtr crtc, Bool transforms)
 {
     crtc->transforms = transforms;
 }
@@ -439,21 +450,21 @@ RRCrtcGetTransform (RRCrtcPtr crtc)
 }
 
 /*
- * Mark the pending transform as current
+ * Called when driver applies a transform to a crtc
  */
 void
-RRCrtcPostPendingTransform (RRCrtcPtr crtc)
+RRCrtcSetTransform (RRCrtcPtr crtc, RRTransformPtr transform)
 {
     if (!crtc->mode)
 	return;
 
-    RRTransformCopy (&crtc->client_current_transform,
-		     &crtc->client_pending_transform);
+    RRTransformCopy (&crtc->client_current_transform, transform);
+
     RRComputeTransform (crtc->x, crtc->y,
 			crtc->mode->mode.width,
 			crtc->mode->mode.height,
 			crtc->rotation,
-			&crtc->client_current_transform,
+			transform,
 			&crtc->transform,
 			&crtc->f_transform,
 			&crtc->f_inverse);
@@ -1091,23 +1102,25 @@ ProcRRSetCrtcConfig (ClientPtr client)
 	}
     
 #ifdef RANDR_12_INTERFACE
-#if 0
 	/*
 	 * Check screen size bounds if the DDX provides a 1.2 interface
 	 * for setting screen size. Else, assume the CrtcSet sets
-	 * the size along with the mode
+	 * the size along with the mode. If the driver supports transforms,
+	 * then it must allow crtcs to display a subset of the screen, so
+	 * only do this check for drivers without transform support.
 	 */
-	if (pScrPriv->rrScreenSetSize)
+	if (pScrPriv->rrScreenSetSize && !crtc->transforms)
 	{
 	    int source_width;
 	    int	source_height;
-	    PictTransform transform, inverse;
+	    PictTransform transform;
+	    struct pict_f_transform f_transform, f_inverse;
 
-	    RRComputeTransform (mode, stuff->rotation,
-				stuff->x, stuff->y,
-				&crtc->client_pending_transform.transform,
-				&crtc->client_pending_transform.inverse,
-				&transform, &inverse);
+	    RRComputeTransform (stuff->x, stuff->y,
+				mode->mode.width, mode->mode.height,
+				rotation,
+				&crtc->client_pending_transform,
+				&transform, &f_transform, &f_inverse);
 
 	    RRModeGetScanoutSize (mode, &transform, &source_width, &source_height);
 	    if (stuff->x + source_width > pScreen->width)
@@ -1127,7 +1140,6 @@ ProcRRSetCrtcConfig (ClientPtr client)
 	    }
 	}
 #endif
-#endif
     }
     
     /*
commit 49db14e4ac26070ed86088419483888dda18b603
Author: Keith Packard <keithp at keithp.com>
Date:   Wed Mar 19 00:46:35 2008 -0700

    Handle RandR transform matrices in floating point.
    
    RandR matrix computations lose too much precision in fixed point;
    computations using the inverted matrix can be as much as 10 pixels off.
    Convert them to double precision values and pass those around. These API
    changes are fairly heavyweight; the official Render interface remains fixed
    point, so the fixed point matrix comes along for the ride everywhere.

diff --git a/hw/xfree86/modes/xf86Crtc.c b/hw/xfree86/modes/xf86Crtc.c
index 65c0030..9f11037 100644
--- a/hw/xfree86/modes/xf86Crtc.c
+++ b/hw/xfree86/modes/xf86Crtc.c
@@ -104,7 +104,8 @@ xf86CrtcCreate (ScrnInfoPtr		scrn,
     crtc->rotation = RR_Rotate_0;
     crtc->desiredRotation = RR_Rotate_0;
     PictureTransformInitIdentity (&crtc->crtc_to_framebuffer);
-    PictureTransformInitIdentity (&crtc->framebuffer_to_crtc);
+    pict_f_transform_init_identity (&crtc->f_crtc_to_framebuffer);
+    pict_f_transform_init_identity (&crtc->f_framebuffer_to_crtc);
     crtc->filter = NULL;
     crtc->params = NULL;
     crtc->nparams = 0;
diff --git a/hw/xfree86/modes/xf86Crtc.h b/hw/xfree86/modes/xf86Crtc.h
index d093b1a..026ec78 100644
--- a/hw/xfree86/modes/xf86Crtc.h
+++ b/hw/xfree86/modes/xf86Crtc.h
@@ -305,7 +305,8 @@ struct _xf86Crtc {
      * Current transformation matrix
      */
     PictTransform   crtc_to_framebuffer;
-    PictTransform   framebuffer_to_crtc;
+    struct pict_f_transform f_crtc_to_framebuffer;
+    struct pict_f_transform f_framebuffer_to_crtc;
     PictFilterPtr   filter;
     xFixed	    *params;
     int		    nparams;
diff --git a/hw/xfree86/modes/xf86Cursors.c b/hw/xfree86/modes/xf86Cursors.c
index 7bf9265..4065789 100644
--- a/hw/xfree86/modes/xf86Cursors.c
+++ b/hw/xfree86/modes/xf86Cursors.c
@@ -326,15 +326,13 @@ xf86_crtc_set_cursor_position (xf86CrtcPtr crtc, int x, int y)
 	xf86CursorScreenPtr ScreenPriv =
 	    (xf86CursorScreenPtr)dixLookupPrivate(&screen->devPrivates,
 						  xf86CursorScreenKey);
-	PictVector	v;
-	x += ScreenPriv->HotX;
-	y += ScreenPriv->HotY;
-	v.vector[0] = IntToxFixed (x); v.vector[1] = IntToxFixed (y); v.vector[2] = IntToxFixed(1);
-	PictureTransformPoint (&crtc->framebuffer_to_crtc, &v);
-	x = xFixedToInt (v.vector[0]); y = xFixedToInt (v.vector[1]);
-	x -= ScreenPriv->HotX;
-	y -= ScreenPriv->HotY;
-    }
+	struct pict_f_vector   v;
+
+	v.v[0] = x + ScreenPriv->HotX; v.v[1] = y + ScreenPriv->HotY; v.v[2] = 1;
+	pict_f_transform_point (&crtc->f_framebuffer_to_crtc, &v);
+	x = floor (v.v[0] + 0.5) - ScreenPriv->HotX;
+	y = floor (v.v[1] + 0.5) - ScreenPriv->HotY;
+   }
     else
     {
 	x -= crtc->x;
diff --git a/hw/xfree86/modes/xf86Rotate.c b/hw/xfree86/modes/xf86Rotate.c
index 7b49afa..efbacec 100644
--- a/hw/xfree86/modes/xf86Rotate.c
+++ b/hw/xfree86/modes/xf86Rotate.c
@@ -122,7 +122,7 @@ xf86RotateCrtcRedisplay (xf86CrtcPtr crtc, RegionPtr region)
 	dst_box.x2 += crtc->filter_width >> 1;
 	dst_box.y1 -= crtc->filter_height >> 1;
 	dst_box.y2 += crtc->filter_height >> 1;
-	PictureTransformBounds (&dst_box, &crtc->framebuffer_to_crtc);
+	pict_f_transform_bounds (&crtc->f_framebuffer_to_crtc, &dst_box);
 	CompositePicture (PictOpSrc,
 			  src, NULL, dst,
 			  dst_box.x1, dst_box.y1, 0, 0, dst_box.x1, dst_box.y1,
@@ -165,6 +165,8 @@ xf86CrtcShadowClear (xf86CrtcPtr crtc)
     xRectangle		rect;
     int			error;
 
+    if (!dst_pixmap)
+	return;
     dst = CreatePicture (None,
 			 &dst_pixmap->drawable,
 			 format,
@@ -199,7 +201,6 @@ xf86RotatePrepare (ScreenPtr pScreen)
 							     crtc->rotatedData,
 							     crtc->mode.HDisplay,
 							     crtc->mode.VDisplay);
-	    xf86CrtcShadowClear (crtc);
 	    if (!xf86_config->rotation_damage_registered)
 	    {
 		/* Hook damage to screen pixmap */
@@ -355,109 +356,33 @@ xf86CrtcRotate (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation)
     xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
     /* if this is called during ScreenInit() we don't have pScrn->pScreen yet */
     ScreenPtr		pScreen = screenInfo.screens[pScrn->scrnIndex];
-    PictTransform	crtc_to_fb, fb_to_crtc;
+    PictTransform	crtc_to_fb;
+    struct pict_f_transform f_crtc_to_fb, f_fb_to_crtc;
     xFixed		*new_params = NULL;
     int			new_nparams = 0;
     PictFilterPtr	new_filter = NULL;
     int			new_width = 0;
     int			new_height = 0;
-    
-    PictureTransformInitIdentity (&crtc_to_fb);
-    PictureTransformInitIdentity (&fb_to_crtc);
-    if (rotation != RR_Rotate_0)
-    {
-	xFixed	rot_cos, rot_sin, rot_dx, rot_dy;
-	xFixed	scale_x, scale_y, scale_dx, scale_dy;
-	int	mode_w = crtc->mode.HDisplay;
-	int	mode_h = crtc->mode.VDisplay;
-	
-	/* rotation */
-	switch (rotation & 0xf) {
-	default:
-	case RR_Rotate_0:
-	    rot_cos = F ( 1);	    rot_sin = F ( 0);
-	    rot_dx  = F ( 0);	    rot_dy  = F ( 0);
-	    break;
-	case RR_Rotate_90:
-	    rot_cos = F ( 0);	    rot_sin = F ( 1);
-	    rot_dx =  F ( mode_h);  rot_dy  = F (0);
-	    break;
-	case RR_Rotate_180:
-	    rot_cos = F (-1);	    rot_sin = F ( 0);
-	    rot_dx  = F (mode_w);   rot_dy  = F ( mode_h);
-	    break;
-	case RR_Rotate_270:
-	    rot_cos = F ( 0);	    rot_sin = F (-1);
-	    rot_dx  = F ( 0);	    rot_dy  = F ( mode_w);
-	    break;
-	}
-	
-	PictureTransformRotate (&crtc_to_fb, &fb_to_crtc, rot_cos, rot_sin);
-	PictureTransformTranslate (&crtc_to_fb, &fb_to_crtc, rot_dx, rot_dy);
-
-	/* reflection */
-	scale_x = F (1);
-	scale_dx = 0;
-	scale_y = F (1);
-	scale_dy = 0;
-	if (rotation & RR_Reflect_X)
-	{
-	    scale_x = F(-1);
-	    if (rotation & (RR_Rotate_0|RR_Rotate_180))
-		scale_dx = F(mode_w);
-	    else
-		scale_dx = F(mode_h);
-	}
-	if (rotation & RR_Reflect_Y)
-	{
-	    scale_y = F(-1);
-	    if (rotation & (RR_Rotate_0|RR_Rotate_180))
-		scale_dy = F(mode_h);
-	    else
-		scale_dy = F(mode_w);
-	}
-	
-	PictureTransformScale (&crtc_to_fb, &fb_to_crtc, scale_x, scale_y);
-	PictureTransformTranslate (&crtc_to_fb, &fb_to_crtc, scale_dx, scale_dy);
-    }
+    RRTransformPtr	transform = NULL;
     
 #ifdef RANDR_12_INTERFACE
     if (crtc->randr_crtc)
-    {
-
-	RRTransformPtr	transform = RRCrtcGetTransform (crtc->randr_crtc);
-	if (transform)
-	{
-	    if (transform->nparams) {
-		new_params = xalloc (transform->nparams * sizeof (xFixed));
-		if (new_params) {
-		    memcpy (new_params, transform->params,
-			    transform->nparams * sizeof (xFixed));
-		    new_nparams = transform->nparams;
-		    new_filter = transform->filter;
-		}
-	    } else
-		new_filter = transform->filter;
-	    if (new_filter)
-	    {
-		new_width = new_filter->width;
-		new_height = new_filter->height;
-	    }
-	    PictureTransformMultiply (&crtc_to_fb, &transform->transform, &crtc_to_fb);
-	    PictureTransformMultiply (&fb_to_crtc, &fb_to_crtc, &transform->inverse);
-	}
-    }
+	transform = RRCrtcGetTransform (crtc->randr_crtc);
 #endif
-    /*
-     * If the untranslated transformation is the identity,
-     * disable the shadow buffer
-     */
-    if (PictureTransformIsIdentity (&crtc_to_fb))
+    if (!transform ||
+	!RRComputeTransform (crtc->x, crtc->y,
+			     crtc->mode.HDisplay, crtc->mode.VDisplay,
+			     rotation,
+			     transform,
+
+			     &crtc_to_fb,
+			     &f_crtc_to_fb,
+			     &f_fb_to_crtc))
     {
-	PictureTransformInitTranslate (&crtc_to_fb,
-				       F (-crtc->x), F (-crtc->y));
-	PictureTransformInitTranslate (&fb_to_crtc,
-				       F ( crtc->x), F ( crtc->y));
+	/*
+	 * If the untranslated transformation is the identity,
+	 * disable the shadow buffer
+	 */
 	xf86RotateDestroy (crtc);
 	crtc->transform_in_use = FALSE;
 	if (new_params)
@@ -470,24 +395,18 @@ xf86CrtcRotate (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation)
     }
     else
     {
-	int width, height, old_width, old_height;
-	void *shadowData;
-	PixmapPtr shadow;
-
-	PictureTransformTranslate (&crtc_to_fb, &fb_to_crtc, F(crtc->x), F(crtc->y));
-
-	/* 
+	/*
 	 * these are the size of the shadow pixmap, which
 	 * matches the mode, not the pre-rotated copy in the
 	 * frame buffer
 	 */
-	width = mode->HDisplay;
-	height = mode->VDisplay;
-	shadowData = crtc->rotatedData;
-	shadow = crtc->rotatedPixmap;
-	old_width = shadow ? shadow->drawable.width : 0;
-	old_height = shadow ? shadow->drawable.height : 0;
-	
+	int	    width = mode->HDisplay;
+	int	    height = mode->VDisplay;
+	void	    *shadowData = crtc->rotatedData;
+	PixmapPtr   shadow = crtc->rotatedPixmap;
+	int	    old_width = shadow ? shadow->drawable.width : 0;
+	int	    old_height = shadow ? shadow->drawable.height : 0;
+
 	/* Allocate memory for rotation */
 	if (old_width != width || old_height != height)
 	{
@@ -522,6 +441,27 @@ xf86CrtcRotate (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation)
 	    xf86_config->BlockHandler = pScreen->BlockHandler;
 	    pScreen->BlockHandler = xf86RotateBlockHandler;
 	}
+#ifdef RANDR_12_INTERFACE
+	if (transform)
+	{
+	    if (transform->nparams) {
+		new_params = xalloc (transform->nparams * sizeof (xFixed));
+		if (new_params) {
+		    memcpy (new_params, transform->params,
+			    transform->nparams * sizeof (xFixed));
+		    new_nparams = transform->nparams;
+		    new_filter = transform->filter;
+		}
+	    } else
+		new_filter = transform->filter;
+	    if (new_filter)
+	    {
+		new_width = new_filter->width;
+		new_height = new_filter->height;
+	    }
+	}
+#endif
+
 	if (0)
 	{
     bail2:
@@ -537,14 +477,13 @@ xf86CrtcRotate (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation)
 								  NULL,
 								  old_width,
 								  old_height);
-	    if (new_params)
-		xfree (new_params);
 	    return FALSE;
 	}
 	crtc->transform_in_use = TRUE;
     }
     crtc->crtc_to_framebuffer = crtc_to_fb;
-    crtc->framebuffer_to_crtc = fb_to_crtc;
+    crtc->f_crtc_to_framebuffer = f_crtc_to_fb;
+    crtc->f_framebuffer_to_crtc = f_fb_to_crtc;
     if (crtc->params)
 	xfree (crtc->params);
     crtc->params = new_params;
@@ -556,8 +495,8 @@ xf86CrtcRotate (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation)
     crtc->bounds.x2 = crtc->mode.HDisplay;
     crtc->bounds.y1 = 0;
     crtc->bounds.y2 = crtc->mode.VDisplay;
-    PictureTransformBounds (&crtc->bounds, &crtc_to_fb);
-    
+    pict_f_transform_bounds (&f_crtc_to_fb, &crtc->bounds);
+
     /* All done */
     return TRUE;
 }
diff --git a/randr/randrstr.h b/randr/randrstr.h
index 792c3d6..5ac983d 100644
--- a/randr/randrstr.h
+++ b/randr/randrstr.h
@@ -107,7 +107,8 @@ struct _rrProperty {
 
 struct _rrTransform {
     PictTransform   transform;
-    PictTransform   inverse;
+    struct pict_f_transform f_transform;
+    struct pict_f_transform f_inverse;
     PictFilterPtr   filter;
     xFixed	    *params;
     int		    nparams;
@@ -134,7 +135,8 @@ struct _rrCrtc {
     RRTransformRec  client_pending_transform;
     RRTransformRec  client_current_transform;
     PictTransform   transform;
-    PictTransform   inverse;
+    struct pict_f_transform f_transform;
+    struct pict_f_transform f_inverse;
 };
 
 struct _rrOutput {
@@ -616,14 +618,16 @@ RRCrtcGetScanoutSize(RRCrtcPtr crtc, int *width, int *height);
  * Return TRUE if the resulting transform is not a simple translation.
  */
 Bool
-RRComputeTransform (RRModePtr		mode,
-		    Rotation		rotation,
-		    int			x,
-		    int			y,
-		    PictTransformPtr	client_transform,
-		    PictTransformPtr	client_inverse,
-		    PictTransformPtr    transform,
-		    PictTransformPtr    inverse);
+RRComputeTransform (int			    x,
+		    int			    y,
+		    int			    width,
+		    int			    height,
+		    Rotation		    rotation,
+		    RRTransformPtr	    rr_transform,
+
+		    PictTransformPtr	    transform,
+		    struct pict_f_transform *f_transform,
+		    struct pict_f_transform *f_inverse);
 
 /*
  * Return crtc transform
@@ -657,7 +661,8 @@ RRCrtcDestroy (RRCrtcPtr crtc);
 int
 RRCrtcTransformSet (RRCrtcPtr		crtc,
 		    PictTransformPtr	transform,
-		    PictTransformPtr	inverse,
+		    struct pict_f_transform *f_transform,
+		    struct pict_f_transform *f_inverse,
 		    char		*filter,
 		    int			filter_len,
 		    xFixed		*params,
diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
index e0fafce..d7ea6f2 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -52,7 +52,8 @@ static void
 RRTransformInit (RRTransformPtr transform)
 {
     PictureTransformInitIdentity (&transform->transform);
-    PictureTransformInitIdentity (&transform->inverse);
+    pict_f_transform_init_identity (&transform->f_transform);
+    pict_f_transform_init_identity (&transform->f_inverse);
     transform->filter = NULL;
     transform->params = NULL;
     transform->nparams = 0;
@@ -94,7 +95,8 @@ RRTransformCopy (RRTransformPtr dst, RRTransformPtr src)
 			       src->params, src->nparams, src->width, src->height))
 	return FALSE;
     dst->transform = src->transform;
-    dst->inverse = src->inverse;
+    dst->f_transform = src->f_transform;
+    dst->f_inverse = src->f_inverse;
     return TRUE;
 }
 
@@ -142,7 +144,8 @@ RRCrtcCreate (ScreenPtr pScreen, void *devPrivate)
     RRTransformInit (&crtc->client_pending_transform);
     RRTransformInit (&crtc->client_current_transform);
     PictureTransformInitIdentity (&crtc->transform);
-    PictureTransformInitIdentity (&crtc->inverse);
+    pict_f_transform_init_identity (&crtc->f_transform);
+    pict_f_transform_init_identity (&crtc->f_inverse);
 
     if (!AddResource (crtc->id, RRCrtcType, (pointer) crtc))
 	return NULL;
@@ -441,13 +444,19 @@ RRCrtcGetTransform (RRCrtcPtr crtc)
 void
 RRCrtcPostPendingTransform (RRCrtcPtr crtc)
 {
+    if (!crtc->mode)
+	return;
+
     RRTransformCopy (&crtc->client_current_transform,
 		     &crtc->client_pending_transform);
-    RRComputeTransform (crtc->mode, crtc->rotation, crtc->x, crtc->y,
-			&crtc->client_current_transform.transform,
-			&crtc->client_current_transform.inverse,
+    RRComputeTransform (crtc->x, crtc->y,
+			crtc->mode->mode.width,
+			crtc->mode->mode.height,
+			crtc->rotation,
+			&crtc->client_current_transform,
 			&crtc->transform,
-			&crtc->inverse);
+			&crtc->f_transform,
+			&crtc->f_inverse);
 }
 
 /*
@@ -608,7 +617,8 @@ RRCrtcGammaSetSize (RRCrtcPtr	crtc,
 int
 RRCrtcTransformSet (RRCrtcPtr		crtc,
 		    PictTransformPtr	transform,
-		    PictTransformPtr	inverse,
+		    struct pict_f_transform *f_transform,
+		    struct pict_f_transform *f_inverse,
 		    char		*filter_name,
 		    int			filter_len,
 		    xFixed		*params,
@@ -648,7 +658,8 @@ RRCrtcTransformSet (RRCrtcPtr		crtc,
 	return BadAlloc;
 
     crtc->client_pending_transform.transform = *transform;
-    crtc->client_pending_transform.inverse = *inverse;
+    crtc->client_pending_transform.f_transform = *f_transform;
+    crtc->client_pending_transform.f_inverse = *f_inverse;
     return Success;
 }
 
@@ -662,78 +673,110 @@ RRCrtcTransformSet (RRCrtcPtr		crtc,
  * Return TRUE if the resulting transform is not a simple translation.
  */
 Bool
-RRComputeTransform (RRModePtr		mode,
-		    Rotation		rotation,
-		    int			x,
-		    int			y,
-		    PictTransformPtr	client_transform,
-		    PictTransformPtr	client_inverse,
-		    PictTransformPtr    transform,
-		    PictTransformPtr    inverse)
+RRComputeTransform (int			    x,
+		    int			    y,
+		    int			    width,
+		    int			    height,
+		    Rotation		    rotation,
+		    RRTransformPtr	    rr_transform,
+
+		    PictTransformPtr	    transform,
+		    struct pict_f_transform *f_transform,
+		    struct pict_f_transform *f_inverse)
 {
+    PictTransform	    inverse;
+
     PictureTransformInitIdentity (transform);
-    PictureTransformInitIdentity (inverse);
+    PictureTransformInitIdentity (&inverse);
+    pict_f_transform_init_identity (f_transform);
+    pict_f_transform_init_identity (f_inverse);
     if (rotation != RR_Rotate_0)
     {
+	double	f_rot_cos, f_rot_sin, f_rot_dx, f_rot_dy;
+	double	f_scale_x, f_scale_y, f_scale_dx, f_scale_dy;
 	xFixed	rot_cos, rot_sin, rot_dx, rot_dy;
 	xFixed	scale_x, scale_y, scale_dx, scale_dy;
-	int	mode_w = mode->mode.width;
-	int	mode_h = mode->mode.height;
-	
+
 	/* rotation */
 	switch (rotation & 0xf) {
 	default:
 	case RR_Rotate_0:
+	    f_rot_cos = 1;	    f_rot_sin = 0;
+	    f_rot_dx  = 0;	    f_rot_dy  = 0;
 	    rot_cos = F ( 1);	    rot_sin = F ( 0);
 	    rot_dx  = F ( 0);	    rot_dy  = F ( 0);
 	    break;
 	case RR_Rotate_90:
+	    f_rot_cos = 0;	    f_rot_sin = 1;
+	    f_rot_dx  = height;	    f_rot_dy  = 0;
 	    rot_cos = F ( 0);	    rot_sin = F ( 1);
-	    rot_dx =  F ( mode_h);  rot_dy  = F (0);
+	    rot_dx =  F ( height);  rot_dy  = F (0);
 	    break;
 	case RR_Rotate_180:
+	    f_rot_cos = -1;	    f_rot_sin = 0;
+	    f_rot_dx  = width;	    f_rot_dy  = height;
 	    rot_cos = F (-1);	    rot_sin = F ( 0);
-	    rot_dx  = F (mode_w);   rot_dy  = F ( mode_h);
+	    rot_dx  = F (width);   rot_dy  = F ( height);
 	    break;
 	case RR_Rotate_270:
+	    f_rot_cos = 0;	    f_rot_sin = -1;
+	    f_rot_dx  = 0;	    f_rot_dy  = width;
 	    rot_cos = F ( 0);	    rot_sin = F (-1);
-	    rot_dx  = F ( 0);	    rot_dy  = F ( mode_w);
+	    rot_dx  = F ( 0);	    rot_dy  = F ( width);
 	    break;
 	}
 	
-	PictureTransformRotate (inverse, transform, rot_cos, rot_sin);
-	PictureTransformTranslate (inverse, transform, rot_dx, rot_dy);
+	PictureTransformRotate (&inverse, transform, rot_cos, rot_sin);
+	PictureTransformTranslate (&inverse, transform, rot_dx, rot_dy);
+	pict_f_transform_rotate (f_inverse, f_transform, f_rot_cos, f_rot_sin);
+	pict_f_transform_translate (f_inverse, f_transform, f_rot_dx, f_rot_dy);
 
 	/* reflection */
+	f_scale_x = 1;
+	f_scale_dx = 0;
+	f_scale_y = 1;
+	f_scale_dy = 0;
 	scale_x = F (1);
 	scale_dx = 0;
 	scale_y = F (1);
 	scale_dy = 0;
 	if (rotation & RR_Reflect_X)
 	{
+	    f_scale_x = -1;
 	    scale_x = F(-1);
-	    if (rotation & (RR_Rotate_0|RR_Rotate_180))
-		scale_dx = F(mode_w);
-	    else
-		scale_dx = F(mode_h);
+	    if (rotation & (RR_Rotate_0|RR_Rotate_180)) {
+		f_scale_dx = width;
+		scale_dx = F(width);
+	    } else {
+		f_scale_dx = height;
+		scale_dx = F(height);
+	    }
 	}
 	if (rotation & RR_Reflect_Y)
 	{
+	    f_scale_y = -1;
 	    scale_y = F(-1);
-	    if (rotation & (RR_Rotate_0|RR_Rotate_180))
-		scale_dy = F(mode_h);
-	    else
-		scale_dy = F(mode_w);
+	    if (rotation & (RR_Rotate_0|RR_Rotate_180)) {
+		f_scale_dy = height;
+		scale_dy = F(height);
+	    } else {
+		f_scale_dy = width;
+		scale_dy = F(width);
+	    }
 	}
 	
-	PictureTransformScale (inverse, transform, scale_x, scale_y);
-	PictureTransformTranslate (inverse, transform, scale_dx, scale_dy);
+	PictureTransformScale (&inverse, transform, scale_x, scale_y);
+	pict_f_transform_scale (f_inverse, f_transform, f_scale_x, f_scale_y);
+	PictureTransformTranslate (&inverse, transform, scale_dx, scale_dy);
+	pict_f_transform_translate (f_inverse, f_transform, f_scale_dx, f_scale_dy);
     }
     
 #ifdef RANDR_12_INTERFACE
+    if (rr_transform)
     {
-        PictureTransformMultiply (inverse, client_inverse, inverse);
-        PictureTransformMultiply (transform, transform, client_transform);
+        PictureTransformMultiply (transform, transform, &rr_transform->transform);
+	pict_f_transform_multiply (f_transform, f_transform, &rr_transform->f_transform);
+	pict_f_transform_multiply (f_inverse, &rr_transform->f_inverse, f_inverse);
     }
 #endif
     /*
@@ -741,13 +784,16 @@ RRComputeTransform (RRModePtr		mode,
      */
     if (PictureTransformIsIdentity (transform))
     {
-	PictureTransformInitTranslate (inverse,   F (-x), F (-y));
 	PictureTransformInitTranslate (transform, F ( x), F ( y));
+
+	pict_f_transform_init_translate (f_transform, F( x), F( y));
+	pict_f_transform_init_translate (f_inverse,   F(-x), F(-y));
 	return FALSE;
     }
     else
     {
-	PictureTransformTranslate (inverse, transform, x, y);
+	PictureTransformTranslate (&inverse, transform, x, y);
+	pict_f_transform_translate (f_inverse, f_transform, x, y);
 	return TRUE;
     }
 }
@@ -1045,6 +1091,7 @@ ProcRRSetCrtcConfig (ClientPtr client)
 	}
     
 #ifdef RANDR_12_INTERFACE
+#if 0
 	/*
 	 * Check screen size bounds if the DDX provides a 1.2 interface
 	 * for setting screen size. Else, assume the CrtcSet sets
@@ -1080,6 +1127,7 @@ ProcRRSetCrtcConfig (ClientPtr client)
 	    }
 	}
 #endif
+#endif
     }
     
     /*
@@ -1227,7 +1275,8 @@ ProcRRSetCrtcTransform (ClientPtr client)
 {
     REQUEST(xRRSetCrtcTransformReq);
     RRCrtcPtr		    crtc;
-    PictTransform	    transform, inverse;
+    PictTransform	    transform;
+    struct pict_f_transform f_transform, f_inverse;
     char		    *filter;
     int			    nbytes;
     xFixed		    *params;
@@ -1239,7 +1288,8 @@ ProcRRSetCrtcTransform (ClientPtr client)
 	return RRErrorBase + BadRRCrtc;
 
     PictTransform_from_xRenderTransform (&transform, &stuff->transform);
-    if (!PictureTransformInvert (&inverse, &transform))
+    pict_f_transform_from_pixman_transform (&f_transform, &transform);
+    if (!pict_f_transform_invert (&f_inverse, &f_transform))
 	return BadMatch;
 
     filter = (char *) (stuff + 1);
@@ -1249,7 +1299,7 @@ ProcRRSetCrtcTransform (ClientPtr client)
     if (nparams < 0)
 	return BadLength;
 
-    return RRCrtcTransformSet (crtc, &transform, &inverse,
+    return RRCrtcTransformSet (crtc, &transform, &f_transform, &f_inverse,
 			       filter, nbytes, params, nparams);
 }
 
diff --git a/render/matrix.c b/render/matrix.c
index 0d5d962..a4cde4f 100644
--- a/render/matrix.c
+++ b/render/matrix.c
@@ -262,83 +262,15 @@ PictureTransformBounds (BoxPtr b, PictTransformPtr matrix)
     }
 }
 
-static const int	a[3] = { 3, 3, 2 };
-static const int	b[3] = { 2, 1, 1 };
-
-static void
-to_doubles (double m[3][3], const PictTransformPtr t)
-{
-    int	i, j;
-
-    for (j = 0; j < 3; j++)
-	for (i = 0; i < 3; i++)
-	    m[j][i] = pixman_fixed_to_double (t->matrix[j][i]);
-}
-
-static Bool
-from_doubles (PictTransformPtr t, double m[3][3])
-{
-    int	i, j;
-
-    for (j = 0; j < 3; j++)
-	for (i = 0; i < 3; i++)
-	{
-	    double  d = m[j][i];
-	    if (d < -32767.0 || d > 32767.0)
-		return FALSE;
-	    d = d * 65536.0 + 0.5;
-	    t->matrix[j][i] = (xFixed) floor (d);
-	}
-    return TRUE;
-}
-
-static Bool
-invert (double r[3][3], double m[3][3])
-{
-    double  det;
-    int	    i, j;
-    static int	a[3] = { 2, 2, 1 };
-    static int	b[3] = { 1, 0, 0 };
-
-    det = 0;
-    for (i = 0; i < 3; i++) {
-	double	p;
-	int	ai = a[i];
-	int	bi = b[i];
-	p = m[i][0] * (m[ai][2] * m[bi][1] - m[ai][1] * m[bi][2]);
-	if (i == 1)
-	    p = -p;
-	det += p;
-    }
-    if (det == 0)
-	return FALSE;
-    det = 1/det;
-    for (j = 0; j < 3; j++) {
-	for (i = 0; i < 3; i++) {
-	    double  p;
-	    int	    ai = a[i];
-	    int	    aj = a[j];
-	    int	    bi = b[i];
-	    int	    bj = b[j];
-
-	    p = m[ai][aj] * m[bi][bj] - m[ai][bj] * m[bi][aj];
-	    if (((i + j) & 1) != 0)
-		p = -p;
-	    r[j][i] = det * p;
-	}
-    }
-    return TRUE;
-}
-
 _X_EXPORT Bool
 PictureTransformInvert (PictTransformPtr dst, const PictTransformPtr src)
 {
-    double  m[3][3], r[3][3];
+    struct pict_f_transform m, r;
 
-    to_doubles (m, src);
-    if (!invert (r, m))
+    pict_f_transform_from_pixman_transform (&m, src);
+    if (!pict_f_transform_invert (&r, &m))
 	return FALSE;
-    if (!from_doubles (dst, r))
+    if (!pixman_transform_from_pict_f_transform (dst, &r))
 	return FALSE;
     return TRUE;
 }
@@ -464,3 +396,251 @@ xRenderTransform_from_PictTransform (xRenderTransform *render,
     render->matrix33 = pict->matrix[2][2];
 }
 
+/*
+ * Floating point matrix interfaces
+ */
+
+_X_EXPORT void
+pict_f_transform_from_pixman_transform (struct pict_f_transform *ft,
+					struct pixman_transform	*t)
+{
+    int	i, j;
+
+    for (j = 0; j < 3; j++)
+	for (i = 0; i < 3; i++)
+	    ft->m[j][i] = pixman_fixed_to_double (t->matrix[j][i]);
+}
+
+_X_EXPORT Bool
+pixman_transform_from_pict_f_transform (struct pixman_transform	*t,
+					struct pict_f_transform	*ft)
+{
+    int	i, j;
+
+    for (j = 0; j < 3; j++)
+	for (i = 0; i < 3; i++)
+	{
+	    double  d = ft->m[j][i];
+	    if (d < -32767.0 || d > 32767.0)
+		return FALSE;
+	    d = d * 65536.0 + 0.5;
+	    t->matrix[j][i] = (xFixed) floor (d);
+	}
+    return TRUE;
+}
+
+static const int	a[3] = { 3, 3, 2 };
+static const int	b[3] = { 2, 1, 1 };
+
+_X_EXPORT Bool
+pict_f_transform_invert (struct pict_f_transform *r,
+			 struct pict_f_transform *m)
+{
+    double  det;
+    int	    i, j;
+    static int	a[3] = { 2, 2, 1 };
+    static int	b[3] = { 1, 0, 0 };
+
+    det = 0;
+    for (i = 0; i < 3; i++) {
+	double	p;
+	int	ai = a[i];
+	int	bi = b[i];
+	p = m->m[i][0] * (m->m[ai][2] * m->m[bi][1] - m->m[ai][1] * m->m[bi][2]);
+	if (i == 1)
+	    p = -p;
+	det += p;
+    }
+    if (det == 0)
+	return FALSE;
+    det = 1/det;
+    for (j = 0; j < 3; j++) {
+	for (i = 0; i < 3; i++) {
+	    double  p;
+	    int	    ai = a[i];
+	    int	    aj = a[j];
+	    int	    bi = b[i];
+	    int	    bj = b[j];
+
+	    p = m->m[ai][aj] * m->m[bi][bj] - m->m[ai][bj] * m->m[bi][aj];
+	    if (((i + j) & 1) != 0)
+		p = -p;
+	    r->m[j][i] = det * p;
+	}
+    }
+    return TRUE;
+}
+
+_X_EXPORT Bool
+pict_f_transform_point (struct pict_f_transform *t,
+			struct pict_f_vector	*v)
+{
+    struct pict_f_vector    result;
+    int			    i, j;
+    double		    a;
+
+    for (j = 0; j < 3; j++)
+    {
+	a = 0;
+	for (i = 0; i < 3; i++)
+	    a += t->m[j][i] * v->v[i];
+	result.v[j] = a;
+    }
+    if (!result.v[2])
+	return FALSE;
+    for (j = 0; j < 2; j++)
+	v->v[j] = result.v[j] / result.v[2];
+    v->v[2] = 1;
+    return TRUE;
+}
+
+_X_EXPORT void
+pict_f_transform_point_3d (struct pict_f_transform *t,
+			   struct pict_f_vector	*v)
+{
+    struct pict_f_vector    result;
+    int			    i, j;
+    double		    a;
+
+    for (j = 0; j < 3; j++)
+    {
+	a = 0;
+	for (i = 0; i < 3; i++)
+	    a += t->m[j][i] * v->v[i];
+	result.v[j] = a;
+    }
+    *v = result;
+}
+
+_X_EXPORT void
+pict_f_transform_multiply (struct pict_f_transform *dst,
+			   struct pict_f_transform *l, struct pict_f_transform *r)
+{
+    struct pict_f_transform d;
+    int			    dx, dy;
+    int			    o;
+
+    for (dy = 0; dy < 3; dy++)
+	for (dx = 0; dx < 3; dx++)
+	{
+	    double v = 0;
+	    for (o = 0; o < 3; o++)
+		v += l->m[dy][o] * r->m[o][dx];
+	    d.m[dy][dx] = v;
+	}
+    *dst = d;
+}
+
+_X_EXPORT void
+pict_f_transform_init_scale (struct pict_f_transform *t, double sx, double sy)
+{
+    t->m[0][0] = sx;	t->m[0][1] = 0;	    t->m[0][2] = 0;
+    t->m[1][0] = 0;	t->m[1][1] = sy;    t->m[1][2] = 0;
+    t->m[2][0] = 0;	t->m[2][1] = 0;	    t->m[2][2] = 1;
+}
+
+_X_EXPORT Bool
+pict_f_transform_scale (struct pict_f_transform *forward,
+			struct pict_f_transform *reverse,
+			double sx, double sy)
+{
+    struct pict_f_transform t;
+
+    if (sx == 0 || sy == 0)
+	return FALSE;
+
+    pict_f_transform_init_scale (&t, sx, sy);
+    pict_f_transform_multiply (forward, &t, forward);
+    pict_f_transform_init_scale (&t, 1/sx, 1/sy);
+    pict_f_transform_multiply (reverse, reverse, &t);
+    return TRUE;
+}
+
+_X_EXPORT void
+pict_f_transform_init_rotate (struct pict_f_transform *t, double c, double s)
+{
+    t->m[0][0] = c;	t->m[0][1] = -s;    t->m[0][2] = 0;
+    t->m[1][0] = s;	t->m[1][1] = c;	    t->m[1][2] = 0;
+    t->m[2][0] = 0;	t->m[2][1] = 0;	    t->m[2][2] = 1;
+}
+
+_X_EXPORT Bool
+pict_f_transform_rotate (struct pict_f_transform *forward,
+			 struct pict_f_transform *reverse,
+			 double c, double s)
+{
+    struct pict_f_transform t;
+
+    pict_f_transform_init_rotate (&t, c, s);
+    pict_f_transform_multiply (forward, &t, forward);
+    pict_f_transform_init_rotate (&t, c, -s);
+    pict_f_transform_multiply (reverse, reverse, &t);
+    return TRUE;
+}
+
+_X_EXPORT void
+pict_f_transform_init_translate (struct pict_f_transform *t, double tx, double ty)
+{
+    t->m[0][0] = 1;	t->m[0][1] = 0;	    t->m[0][2] = tx;
+    t->m[1][0] = 0;	t->m[1][1] = 1;	    t->m[1][2] = ty;
+    t->m[2][0] = 0;	t->m[2][1] = 0;	    t->m[2][2] = 1;
+}
+
+_X_EXPORT Bool
+pict_f_transform_translate (struct pict_f_transform *forward,
+			    struct pict_f_transform *reverse,
+			    double tx, double ty)
+{
+    struct pict_f_transform t;
+
+    pict_f_transform_init_translate (&t, tx, ty);
+    pict_f_transform_multiply (forward, &t, forward);
+    pict_f_transform_init_translate (&t, -tx, -ty);
+    pict_f_transform_multiply (reverse, reverse, &t);
+    return TRUE;
+}
+
+_X_EXPORT Bool
+pict_f_transform_bounds (struct pict_f_transform *t, BoxPtr b)
+{
+    struct pict_f_vector    v[4];
+    int			    i;
+    int			    x1, y1, x2, y2;
+
+    v[0].v[0] = b->x1;    v[0].v[1] = b->y1;	v[0].v[2] = 1;
+    v[1].v[0] = b->x2;    v[1].v[1] = b->y1;	v[1].v[2] = 1;
+    v[2].v[0] = b->x2;    v[2].v[1] = b->y2;	v[2].v[2] = 1;
+    v[3].v[0] = b->x1;    v[3].v[1] = b->y2;	v[3].v[2] = 1;
+    for (i = 0; i < 4; i++)
+    {
+	if (!pict_f_transform_point (t, &v[i]))
+	    return FALSE;
+	x1 = floor (v[i].v[0]);
+	y1 = floor (v[i].v[1]);
+	x2 = ceil (v[i].v[0]);
+	y2 = ceil (v[i].v[1]);
+	if (i == 0)
+	{
+	    b->x1 = x1; b->y1 = y1;
+	    b->x2 = x2; b->y2 = y2;
+	}
+	else
+	{
+	    if (x1 < b->x1) b->x1 = x1;
+	    if (y1 < b->y1) b->y1 = y1;
+	    if (x2 > b->x2) b->x2 = x2;
+	    if (y2 > b->y2) b->y2 = y2;
+	}
+    }
+    return TRUE;
+}
+
+_X_EXPORT void
+pict_f_transform_init_identity (struct pict_f_transform *t)
+{
+    int	i, j;
+
+    for (j = 0; j < 3; j++)
+	for (i = 0; i < 3; i++)
+	    t->m[j][i] = i == j ? 1 : 0;
+}
diff --git a/render/picturestr.h b/render/picturestr.h
index 658e221..b18f316 100644
--- a/render/picturestr.h
+++ b/render/picturestr.h
@@ -56,6 +56,14 @@ typedef struct _PictFormat {
 typedef struct pixman_vector PictVector, *PictVectorPtr;
 typedef struct pixman_transform PictTransform, *PictTransformPtr;
 
+struct pict_f_vector {
+    double  v[3];
+};
+
+struct pict_f_transform {
+    double  m[3][3];
+};
+
 #define PICT_GRADIENT_STOPTABLE_SIZE 1024
 #define SourcePictTypeSolidFill 0
 #define SourcePictTypeLinear 1
@@ -745,4 +753,59 @@ void
 xRenderTransform_from_PictTransform (xRenderTransform *render,
 				     PictTransformPtr pict);
 
+void
+pict_f_transform_from_pixman_transform (struct pict_f_transform *ft,
+					struct pixman_transform	*t);
+
+Bool
+pixman_transform_from_pict_f_transform (struct pixman_transform	*t,
+					struct pict_f_transform	*ft);
+
+Bool
+pict_f_transform_invert (struct pict_f_transform *r,
+			 struct pict_f_transform *m);
+
+
+Bool
+pict_f_transform_point (struct pict_f_transform *t,
+			struct pict_f_vector	*v);
+
+void
+pict_f_transform_point_3d (struct pict_f_transform *t,
+			   struct pict_f_vector	*v);
+
+void
+pict_f_transform_multiply (struct pict_f_transform *dst,
+			   struct pict_f_transform *l, struct pict_f_transform *r);
+
+void
+pict_f_transform_init_scale (struct pict_f_transform *t, double sx, double sy);
+
+Bool
+pict_f_transform_scale (struct pict_f_transform *forward,
+			struct pict_f_transform *reverse,
+			double sx, double sy);
+
+void
+pict_f_transform_init_rotate (struct pict_f_transform *t, double c, double s);
+
+Bool
+pict_f_transform_rotate (struct pict_f_transform *forward,
+			 struct pict_f_transform *reverse,
+			 double c, double s);
+
+void
+pict_f_transform_init_translate (struct pict_f_transform *t, double tx, double ty);
+
+Bool
+pict_f_transform_translate (struct pict_f_transform *forward,
+			    struct pict_f_transform *reverse,
+			    double tx, double ty);
+
+Bool
+pict_f_transform_bounds (struct pict_f_transform *t, BoxPtr b);
+
+void
+pict_f_transform_init_identity (struct pict_f_transform *t);
+
 #endif /* _PICTURESTR_H_ */
commit 6f734aecaec4f5c6152c3ebca197ef65bb4523da
Author: Keith Packard <keithp at keithp.com>
Date:   Tue Mar 18 16:06:06 2008 -0700

    Eliminate inverse matrix from randr transform protocol
    
    It is easier, and potentially more precise, to compute the inverse in the
    server where everything can eventually be kept in floating point form.

diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
index 6559d51..e0fafce 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -1341,14 +1341,12 @@ ProcRRGetCrtcTransform (ClientPtr client)
     reply->hasTransforms = crtc->transforms;
 
     transform_encode (client, &reply->pendingTransform, &pending->transform);
-    transform_encode (client, &reply->pendingInverse, &pending->inverse);
     extra += transform_filter_encode (client, extra,
 				      &reply->pendingNbytesFilter,
 				      &reply->pendingNparamsFilter,
 				      pending);
 
     transform_encode (client, &reply->currentTransform, &current->transform);
-    transform_encode (client, &reply->currentInverse, &current->inverse);
     extra += transform_filter_encode (client, extra,
 				      &reply->currentNbytesFilter,
 				      &reply->currentNparamsFilter,
commit 197aa784694992f6bcfd194932309e440334c237
Author: Keith Packard <keithp at keithp.com>
Date:   Tue Mar 18 15:35:44 2008 -0700

    Report whether transforms are support from driver through extension to client
    
    Add APIs to xf86RandR12 support and randr extension to record whether the
    driver supports transforms, report that value in the RRGetCrtcTransform
    reply.

diff --git a/hw/xfree86/modes/xf86Crtc.c b/hw/xfree86/modes/xf86Crtc.c
index 57b0140..65c0030 100644
--- a/hw/xfree86/modes/xf86Crtc.c
+++ b/hw/xfree86/modes/xf86Crtc.c
@@ -735,11 +735,17 @@ xf86CrtcScreenInit (ScreenPtr screen)
 	    break;
     }
     if (c == config->num_crtc)
+    {
 	xf86RandR12SetRotations (screen, RR_Rotate_0 | RR_Rotate_90 |
 				 RR_Rotate_180 | RR_Rotate_270 |
 				 RR_Reflect_X | RR_Reflect_Y);
+	xf86RandR12SetTransform (screen, TRUE);
+    }
     else
+    {
 	xf86RandR12SetRotations (screen, RR_Rotate_0);
+	xf86RandR12SetTransform (screen, FALSE);
+    }
     
     /* Wrap CreateScreenResources so we can initialize the RandR code */
     config->CreateScreenResources = screen->CreateScreenResources;
diff --git a/hw/xfree86/modes/xf86RandR12.c b/hw/xfree86/modes/xf86RandR12.c
index 6e14bd7..f247a88 100644
--- a/hw/xfree86/modes/xf86RandR12.c
+++ b/hw/xfree86/modes/xf86RandR12.c
@@ -569,6 +569,31 @@ xf86RandR12SetRotations (ScreenPtr pScreen, Rotation rotations)
 }
 
 _X_EXPORT void
+xf86RandR12SetTransform (ScreenPtr pScreen, Bool transforms)
+{
+    XF86RandRInfoPtr	randrp;
+#if RANDR_13_INTERFACE
+    ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
+    int			c;
+    xf86CrtcConfigPtr   config = XF86_CRTC_CONFIG_PTR(pScrn);
+#endif
+
+#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(7,0,0,0,0)
+    if (xf86RandR12Key == NULL)
+	return;
+#endif
+
+    randrp = XF86RANDRINFO(pScreen);
+#if RANDR_13_INTERFACE
+    for (c = 0; c < config->num_crtc; c++) {
+	xf86CrtcPtr    crtc = config->crtc[c];
+
+	RRCrtcSetTransform (crtc->randr_crtc, transforms);
+    }
+#endif
+}
+
+_X_EXPORT void
 xf86RandR12GetOriginalVirtualSize(ScrnInfoPtr pScrn, int *x, int *y)
 {
     ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex];
diff --git a/hw/xfree86/modes/xf86RandR12.h b/hw/xfree86/modes/xf86RandR12.h
index 4fd855c..c361b47 100644
--- a/hw/xfree86/modes/xf86RandR12.h
+++ b/hw/xfree86/modes/xf86RandR12.h
@@ -31,6 +31,7 @@
 Bool xf86RandR12CreateScreenResources (ScreenPtr pScreen);
 Bool xf86RandR12Init(ScreenPtr pScreen);
 void xf86RandR12SetRotations (ScreenPtr pScreen, Rotation rotation);
+void xf86RandR12SetTransform (ScreenPtr pScreen, Bool transforms);
 Bool xf86RandR12SetConfig(ScreenPtr pScreen, Rotation rotation, int rate,
 			RRScreenSizePtr pSize);
 Rotation xf86RandR12GetRotation(ScreenPtr pScreen);
diff --git a/randr/randrstr.h b/randr/randrstr.h
index 17d0a8b..792c3d6 100644
--- a/randr/randrstr.h
+++ b/randr/randrstr.h
@@ -130,6 +130,7 @@ struct _rrCrtc {
     CARD16	    *gammaBlue;
     CARD16	    *gammaGreen;
     void	    *devPrivate;
+    Bool	    transforms;
     RRTransformRec  client_pending_transform;
     RRTransformRec  client_current_transform;
     PictTransform   transform;
@@ -539,6 +540,12 @@ void
 RRCrtcSetRotations (RRCrtcPtr crtc, Rotation rotations);
 
 /*
+ * Set whether transforms are allowed on a CRTC
+ */
+void
+RRCrtcSetTransform (RRCrtcPtr crtc, Bool transforms);
+
+/*
  * Notify the extension that the Crtc has been reconfigured,
  * the driver calls this whenever it has updated the mode
  */
diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
index b8b9ec0..6559d51 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -164,6 +164,15 @@ RRCrtcSetRotations (RRCrtcPtr crtc, Rotation rotations)
 }
 
 /*
+ * Set whether transforms are allowed on a CRTC
+ */
+void
+RRCrtcSetTransform (RRCrtcPtr crtc, Bool transforms)
+{
+    crtc->transforms = transforms;
+}
+
+/*
  * Notify the extension that the Crtc has been reconfigured,
  * the driver calls this whenever it has updated the mode
  */
@@ -608,6 +617,9 @@ RRCrtcTransformSet (RRCrtcPtr		crtc,
     PictFilterPtr   filter = NULL;
     int		    width = 0, height = 0;
 
+    if (!crtc->transforms)
+	return BadValue;
+
     if (filter_len)
     {
 	filter = PictureFindFilter (crtc->pScreen,
@@ -1326,8 +1338,7 @@ ProcRRGetCrtcTransform (ClientPtr client)
     reply->sequenceNumber = client->sequence;
     reply->length = (CrtcTransformExtra + nextra) >> 2;
 
-    /* XXX deal with DDXen that can't do transforms */
-    reply->hasTransforms = xTrue;
+    reply->hasTransforms = crtc->transforms;
 
     transform_encode (client, &reply->pendingTransform, &pending->transform);
     transform_encode (client, &reply->pendingInverse, &pending->inverse);
commit e86c34663ef97e946a1129450105efa89a123af6
Author: Keith Packard <keithp at keithp.com>
Date:   Tue Mar 18 15:25:31 2008 -0700

    Clear shadow pixmaps before using them.
    
    This eliminates some ugly flashing, as well as clearing the borders when the
    shadow will not be completely painted.

diff --git a/hw/xfree86/modes/xf86Rotate.c b/hw/xfree86/modes/xf86Rotate.c
index dc9ad11..7b49afa 100644
--- a/hw/xfree86/modes/xf86Rotate.c
+++ b/hw/xfree86/modes/xf86Rotate.c
@@ -154,6 +154,35 @@ xf86CrtcDamageShadow (xf86CrtcPtr crtc)
 }
 
 static void
+xf86CrtcShadowClear (xf86CrtcPtr crtc)
+{
+    PixmapPtr		dst_pixmap = crtc->rotatedPixmap;
+    ScrnInfoPtr		scrn = crtc->scrn;
+    ScreenPtr		screen = scrn->pScreen;
+    PicturePtr		dst;
+    PictFormatPtr	format = compWindowFormat (WindowTable[screen->myNum]);
+    static xRenderColor black = { 0, 0, 0, 0 };
+    xRectangle		rect;
+    int			error;
+
+    dst = CreatePicture (None,
+			 &dst_pixmap->drawable,
+			 format,
+			 0L,
+			 NULL,
+			 serverClient,
+			 &error);
+    if (!dst)
+	return;
+    rect.x = 0;
+    rect.y = 0;
+    rect.width = dst_pixmap->drawable.width;
+    rect.height = dst_pixmap->drawable.height;
+    CompositeRects (PictOpSrc, dst, &black, 1, &rect);
+    FreePicture (dst, None);
+}
+
+static void
 xf86RotatePrepare (ScreenPtr pScreen)
 {
     ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
@@ -170,6 +199,7 @@ xf86RotatePrepare (ScreenPtr pScreen)
 							     crtc->rotatedData,
 							     crtc->mode.HDisplay,
 							     crtc->mode.VDisplay);
+	    xf86CrtcShadowClear (crtc);
 	    if (!xf86_config->rotation_damage_registered)
 	    {
 		/* Hook damage to screen pixmap */
commit 97ab0c6eff870b52c0383b63a78cec49059b2545
Author: Keith Packard <keithp at keithp.com>
Date:   Tue Mar 18 15:15:40 2008 -0700

    When converting from double to fixed, round carefully.
    
    This reduces the matrix representation error after inverting a
    transformation matrix (although it doesn't eliminate it entirely).
    
    Perhaps we should extend Render to include 64-bit floating point transforms...

diff --git a/render/matrix.c b/render/matrix.c
index 6e50205..0d5d962 100644
--- a/render/matrix.c
+++ b/render/matrix.c
@@ -72,9 +72,9 @@ PictureTransformPoint3d (PictTransformPtr transform,
 	    return FALSE;
 	result.vector[j] = (xFixed) v;
     }
+    *vector = result;
     if (!result.vector[2])
 	return FALSE;
-    *vector = result;
     return TRUE;
 }
 
@@ -286,7 +286,8 @@ from_doubles (PictTransformPtr t, double m[3][3])
 	    double  d = m[j][i];
 	    if (d < -32767.0 || d > 32767.0)
 		return FALSE;
-	    t->matrix[j][i] = pixman_double_to_fixed (d);
+	    d = d * 65536.0 + 0.5;
+	    t->matrix[j][i] = (xFixed) floor (d);
 	}
     return TRUE;
 }
@@ -294,7 +295,7 @@ from_doubles (PictTransformPtr t, double m[3][3])
 static Bool
 invert (double r[3][3], double m[3][3])
 {
-    double  det, norm;
+    double  det;
     int	    i, j;
     static int	a[3] = { 2, 2, 1 };
     static int	b[3] = { 1, 0, 0 };
commit 6d3a9e40a4b9ec455af11cce31e4aa616c93db32
Author: Keith Packard <keithp at keithp.com>
Date:   Mon Mar 17 23:04:49 2008 -0700

    Compute matrix inversion instead of using wire version in RRCrtcTransformSet
    
    It doesn't make sense to have the client invert this matrix when the server
    can do so reasonably efficiently. This avoids weird fixed point rounding
    errors when testing the transform against its inverse. Now to fix the
    protocol.

diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
index b715884..b8b9ec0 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -608,8 +608,6 @@ RRCrtcTransformSet (RRCrtcPtr		crtc,
     PictFilterPtr   filter = NULL;
     int		    width = 0, height = 0;
 
-    if (!PictureTransformIsInverse (transform, inverse))
-	return BadMatch;
     if (filter_len)
     {
 	filter = PictureFindFilter (crtc->pScreen,
@@ -1229,7 +1227,8 @@ ProcRRSetCrtcTransform (ClientPtr client)
 	return RRErrorBase + BadRRCrtc;
 
     PictTransform_from_xRenderTransform (&transform, &stuff->transform);
-    PictTransform_from_xRenderTransform (&inverse, &stuff->inverse);
+    if (!PictureTransformInvert (&inverse, &transform))
+	return BadMatch;
 
     filter = (char *) (stuff + 1);
     nbytes = stuff->nbytesFilter;
commit 160252d94f04acc95f0a4e0f884ff565a5aa0744
Author: Keith Packard <keithp at keithp.com>
Date:   Mon Mar 17 23:03:56 2008 -0700

    Add matrix inversion function (uses doubles)
    
    The obvious matrix inversion function, coded using doubles to avoid fiddling
    with fixed point precision adventures.

diff --git a/render/matrix.c b/render/matrix.c
index a976304..6e50205 100644
--- a/render/matrix.c
+++ b/render/matrix.c
@@ -262,6 +262,86 @@ PictureTransformBounds (BoxPtr b, PictTransformPtr matrix)
     }
 }
 
+static const int	a[3] = { 3, 3, 2 };
+static const int	b[3] = { 2, 1, 1 };
+
+static void
+to_doubles (double m[3][3], const PictTransformPtr t)
+{
+    int	i, j;
+
+    for (j = 0; j < 3; j++)
+	for (i = 0; i < 3; i++)
+	    m[j][i] = pixman_fixed_to_double (t->matrix[j][i]);
+}
+
+static Bool
+from_doubles (PictTransformPtr t, double m[3][3])
+{
+    int	i, j;
+
+    for (j = 0; j < 3; j++)
+	for (i = 0; i < 3; i++)
+	{
+	    double  d = m[j][i];
+	    if (d < -32767.0 || d > 32767.0)
+		return FALSE;
+	    t->matrix[j][i] = pixman_double_to_fixed (d);
+	}
+    return TRUE;
+}
+
+static Bool
+invert (double r[3][3], double m[3][3])
+{
+    double  det, norm;
+    int	    i, j;
+    static int	a[3] = { 2, 2, 1 };
+    static int	b[3] = { 1, 0, 0 };
+
+    det = 0;
+    for (i = 0; i < 3; i++) {
+	double	p;
+	int	ai = a[i];
+	int	bi = b[i];
+	p = m[i][0] * (m[ai][2] * m[bi][1] - m[ai][1] * m[bi][2]);
+	if (i == 1)
+	    p = -p;
+	det += p;
+    }
+    if (det == 0)
+	return FALSE;
+    det = 1/det;
+    for (j = 0; j < 3; j++) {
+	for (i = 0; i < 3; i++) {
+	    double  p;
+	    int	    ai = a[i];
+	    int	    aj = a[j];
+	    int	    bi = b[i];
+	    int	    bj = b[j];
+
+	    p = m[ai][aj] * m[bi][bj] - m[ai][bj] * m[bi][aj];
+	    if (((i + j) & 1) != 0)
+		p = -p;
+	    r[j][i] = det * p;
+	}
+    }
+    return TRUE;
+}
+
+_X_EXPORT Bool
+PictureTransformInvert (PictTransformPtr dst, const PictTransformPtr src)
+{
+    double  m[3][3], r[3][3];
+
+    to_doubles (m, src);
+    if (!invert (r, m))
+	return FALSE;
+    if (!from_doubles (dst, r))
+	return FALSE;
+    return TRUE;
+}
+
 static Bool
 within_epsilon (xFixed a, xFixed b, xFixed epsilon)
 {
diff --git a/render/picturestr.h b/render/picturestr.h
index 60be68a..658e221 100644
--- a/render/picturestr.h
+++ b/render/picturestr.h
@@ -720,6 +720,9 @@ void
 PictureTransformBounds (BoxPtr b, PictTransformPtr matrix);
 
 Bool
+PictureTransformInvert (PictTransformPtr dst, const PictTransformPtr src);
+
+Bool
 PictureTransformIsIdentity(PictTransform *t);
 
 Bool
commit 8fd82c88e3f2060fda4ba30376900ece77668c63
Author: Keith Packard <keithp at keithp.com>
Date:   Mon Mar 17 16:14:43 2008 -0700

    Adjust transformed cursor position to account for hotspot

diff --git a/hw/xfree86/modes/xf86Cursors.c b/hw/xfree86/modes/xf86Cursors.c
index a7ed5c4..7bf9265 100644
--- a/hw/xfree86/modes/xf86Cursors.c
+++ b/hw/xfree86/modes/xf86Cursors.c
@@ -37,6 +37,7 @@
 #include "xf86Crtc.h"
 #include "xf86Modes.h"
 #include "xf86RandR12.h"
+#include "xf86CursorPriv.h"
 #include "X11/extensions/render.h"
 #define DPMS_SERVER
 #include "X11/extensions/dpms.h"
@@ -321,10 +322,18 @@ xf86_crtc_set_cursor_position (xf86CrtcPtr crtc, int x, int y)
      */
     if (crtc->transform_in_use)
     {
+	ScreenPtr	screen = scrn->pScreen;
+	xf86CursorScreenPtr ScreenPriv =
+	    (xf86CursorScreenPtr)dixLookupPrivate(&screen->devPrivates,
+						  xf86CursorScreenKey);
 	PictVector	v;
+	x += ScreenPriv->HotX;
+	y += ScreenPriv->HotY;
 	v.vector[0] = IntToxFixed (x); v.vector[1] = IntToxFixed (y); v.vector[2] = IntToxFixed(1);
 	PictureTransformPoint (&crtc->framebuffer_to_crtc, &v);
 	x = xFixedToInt (v.vector[0]); y = xFixedToInt (v.vector[1]);
+	x -= ScreenPriv->HotX;
+	y -= ScreenPriv->HotY;
     }
     else
     {
commit eb222e64128034df8361d5a82d4f4aa1318923ce
Author: Keith Packard <keithp at keithp.com>
Date:   Mon Mar 17 16:14:15 2008 -0700

    Actually use filter kernel size to expand transform redisplay box

diff --git a/hw/xfree86/modes/xf86Rotate.c b/hw/xfree86/modes/xf86Rotate.c
index bf6976a..dc9ad11 100644
--- a/hw/xfree86/modes/xf86Rotate.c
+++ b/hw/xfree86/modes/xf86Rotate.c
@@ -118,10 +118,10 @@ xf86RotateCrtcRedisplay (xf86CrtcPtr crtc, RegionPtr region)
 	BoxRec	dst_box;
 
 	dst_box = *b;
-	dst_box.x1 -= crtc->filter_width >> 2;
-	dst_box.x2 += crtc->filter_width >> 2;
-	dst_box.y1 -= crtc->filter_width >> 2;
-	dst_box.y2 += crtc->filter_width >> 2;
+	dst_box.x1 -= crtc->filter_width >> 1;
+	dst_box.x2 += crtc->filter_width >> 1;
+	dst_box.y1 -= crtc->filter_height >> 1;
+	dst_box.y2 += crtc->filter_height >> 1;
 	PictureTransformBounds (&dst_box, &crtc->framebuffer_to_crtc);
 	CompositePicture (PictOpSrc,
 			  src, NULL, dst,
@@ -408,6 +408,11 @@ xf86CrtcRotate (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation)
 		}
 	    } else
 		new_filter = transform->filter;
+	    if (new_filter)
+	    {
+		new_width = new_filter->width;
+		new_height = new_filter->height;
+	    }
 	    PictureTransformMultiply (&crtc_to_fb, &transform->transform, &crtc_to_fb);
 	    PictureTransformMultiply (&fb_to_crtc, &fb_to_crtc, &transform->inverse);
 	}
commit 3fdb963f6e8287edeb4c5bc7bbadbc02eb8bb910
Author: Keith Packard <keithp at keithp.com>
Date:   Mon Mar 17 16:13:25 2008 -0700

    Correct bilinear filter kernel size (should be 2x2)

diff --git a/render/filter.c b/render/filter.c
index b5bcf02..21eedca 100644
--- a/render/filter.c
+++ b/render/filter.c
@@ -252,7 +252,7 @@ PictureSetDefaultFilters (ScreenPtr pScreen)
 	    return FALSE;
     if (PictureAddFilter (pScreen, FilterNearest, 0, 1, 1) < 0)
 	return FALSE;
-    if (PictureAddFilter (pScreen, FilterBilinear, 0, 4, 4) < 0)
+    if (PictureAddFilter (pScreen, FilterBilinear, 0, 2, 2) < 0)
 	return FALSE;
 
     if (!PictureSetFilterAlias (pScreen, FilterNearest, FilterFast))
commit ee6326a6b89b2d223f6e1eaf02aac1fe8aebfaf6
Author: Keith Packard <keithp at keithp.com>
Date:   Mon Mar 17 15:22:06 2008 -0700

    Handle filter widths in xf86Rotate

diff --git a/hw/xfree86/modes/xf86Crtc.h b/hw/xfree86/modes/xf86Crtc.h
index a5bb11b..d093b1a 100644
--- a/hw/xfree86/modes/xf86Crtc.h
+++ b/hw/xfree86/modes/xf86Crtc.h
@@ -309,6 +309,8 @@ struct _xf86Crtc {
     PictFilterPtr   filter;
     xFixed	    *params;
     int		    nparams;
+    int		    filter_width;
+    int		    filter_height;
     Bool	    transform_in_use;
     /**
      * Bounding box in screen space
diff --git a/hw/xfree86/modes/xf86Rotate.c b/hw/xfree86/modes/xf86Rotate.c
index f201ae3..bf6976a 100644
--- a/hw/xfree86/modes/xf86Rotate.c
+++ b/hw/xfree86/modes/xf86Rotate.c
@@ -118,6 +118,10 @@ xf86RotateCrtcRedisplay (xf86CrtcPtr crtc, RegionPtr region)
 	BoxRec	dst_box;
 
 	dst_box = *b;
+	dst_box.x1 -= crtc->filter_width >> 2;
+	dst_box.x2 += crtc->filter_width >> 2;
+	dst_box.y1 -= crtc->filter_width >> 2;
+	dst_box.y2 += crtc->filter_width >> 2;
 	PictureTransformBounds (&dst_box, &crtc->framebuffer_to_crtc);
 	CompositePicture (PictOpSrc,
 			  src, NULL, dst,
@@ -322,6 +326,11 @@ xf86CrtcRotate (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation)
     /* if this is called during ScreenInit() we don't have pScrn->pScreen yet */
     ScreenPtr		pScreen = screenInfo.screens[pScrn->scrnIndex];
     PictTransform	crtc_to_fb, fb_to_crtc;
+    xFixed		*new_params = NULL;
+    int			new_nparams = 0;
+    PictFilterPtr	new_filter = NULL;
+    int			new_width = 0;
+    int			new_height = 0;
     
     PictureTransformInitIdentity (&crtc_to_fb);
     PictureTransformInitIdentity (&fb_to_crtc);
@@ -385,9 +394,6 @@ xf86CrtcRotate (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation)
 #ifdef RANDR_12_INTERFACE
     if (crtc->randr_crtc)
     {
-	xFixed		*new_params = NULL;
-	int		new_nparams = 0;
-	PictFilterPtr   new_filter = NULL;
 
 	RRTransformPtr	transform = RRCrtcGetTransform (crtc->randr_crtc);
 	if (transform)
@@ -405,11 +411,6 @@ xf86CrtcRotate (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation)
 	    PictureTransformMultiply (&crtc_to_fb, &transform->transform, &crtc_to_fb);
 	    PictureTransformMultiply (&fb_to_crtc, &fb_to_crtc, &transform->inverse);
 	}
-	if (crtc->params)
-	    xfree (crtc->params);
-	crtc->params = new_params;
-	crtc->nparams = new_nparams;
-	crtc->filter = new_filter;
     }
 #endif
     /*
@@ -418,12 +419,19 @@ xf86CrtcRotate (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation)
      */
     if (PictureTransformIsIdentity (&crtc_to_fb))
     {
-	crtc->transform_in_use = FALSE;
-	PictureTransformInitTranslate (&crtc->crtc_to_framebuffer, 
+	PictureTransformInitTranslate (&crtc_to_fb,
 				       F (-crtc->x), F (-crtc->y));
-	PictureTransformInitTranslate (&crtc->framebuffer_to_crtc,
+	PictureTransformInitTranslate (&fb_to_crtc,
 				       F ( crtc->x), F ( crtc->y));
 	xf86RotateDestroy (crtc);
+	crtc->transform_in_use = FALSE;
+	if (new_params)
+	    xfree (new_params);
+	new_params = NULL;
+	new_nparams = 0;
+	new_filter = NULL;
+	new_width = 0;
+	new_height = 0;
     }
     else
     {
@@ -494,17 +502,26 @@ xf86CrtcRotate (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation)
 								  NULL,
 								  old_width,
 								  old_height);
+	    if (new_params)
+		xfree (new_params);
 	    return FALSE;
 	}
 	crtc->transform_in_use = TRUE;
-	crtc->crtc_to_framebuffer = crtc_to_fb;
-	crtc->framebuffer_to_crtc = fb_to_crtc;
-	crtc->bounds.x1 = 0;
-	crtc->bounds.x2 = crtc->mode.HDisplay;
-	crtc->bounds.y1 = 0;
-	crtc->bounds.y2 = crtc->mode.VDisplay;
-	PictureTransformBounds (&crtc->bounds, &crtc_to_fb);
     }
+    crtc->crtc_to_framebuffer = crtc_to_fb;
+    crtc->framebuffer_to_crtc = fb_to_crtc;
+    if (crtc->params)
+	xfree (crtc->params);
+    crtc->params = new_params;
+    crtc->nparams = new_nparams;
+    crtc->filter = new_filter;
+    crtc->filter_width = new_width;
+    crtc->filter_height = new_height;
+    crtc->bounds.x1 = 0;
+    crtc->bounds.x2 = crtc->mode.HDisplay;
+    crtc->bounds.y1 = 0;
+    crtc->bounds.y2 = crtc->mode.VDisplay;
+    PictureTransformBounds (&crtc->bounds, &crtc_to_fb);
     
     /* All done */
     return TRUE;
commit ddc8466137d229fdc100cc403f492c7d61a1ba89
Author: Keith Packard <keithp at keithp.com>
Date:   Mon Mar 17 15:21:26 2008 -0700

    Initialize and cleanup new filter fields in xf86Crtc.

diff --git a/hw/xfree86/modes/xf86Crtc.c b/hw/xfree86/modes/xf86Crtc.c
index a7e7af6..57b0140 100644
--- a/hw/xfree86/modes/xf86Crtc.c
+++ b/hw/xfree86/modes/xf86Crtc.c
@@ -103,6 +103,16 @@ xf86CrtcCreate (ScrnInfoPtr		scrn,
 #endif
     crtc->rotation = RR_Rotate_0;
     crtc->desiredRotation = RR_Rotate_0;
+    PictureTransformInitIdentity (&crtc->crtc_to_framebuffer);
+    PictureTransformInitIdentity (&crtc->framebuffer_to_crtc);
+    crtc->filter = NULL;
+    crtc->params = NULL;
+    crtc->nparams = 0;
+    crtc->filter_width = 0;
+    crtc->filter_height = 0;
+    crtc->transform_in_use = FALSE;
+    memset (&crtc->bounds, '\0', sizeof (crtc->bounds));
+
     if (xf86_config->crtc)
 	crtcs = xrealloc (xf86_config->crtc,
 			  (xf86_config->num_crtc + 1) * sizeof (xf86CrtcPtr));
@@ -134,6 +144,8 @@ xf86CrtcDestroy (xf86CrtcPtr crtc)
 	    xf86_config->num_crtc--;
 	    break;
 	}
+    if (crtc->params)
+	xfree (crtc->params);
     xfree (crtc);
 }
 
commit 16c093afd4f6b30d889cacdc994b0024f9bd83d5
Author: Keith Packard <keithp at keithp.com>
Date:   Mon Mar 17 15:20:52 2008 -0700

    Pass filter kernel size through transforms

diff --git a/randr/randrstr.h b/randr/randrstr.h
index cdaebe9..17d0a8b 100644
--- a/randr/randrstr.h
+++ b/randr/randrstr.h
@@ -111,6 +111,8 @@ struct _rrTransform {
     PictFilterPtr   filter;
     xFixed	    *params;
     int		    nparams;
+    int		    width;
+    int		    height;
 };
 
 struct _rrCrtc {
diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
index bae17c5..b715884 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -62,7 +62,9 @@ static Bool
 RRTransformSetFilter (RRTransformPtr	dst,
 		      PictFilterPtr	filter,
 		      xFixed		*params,
-		      int		nparams)
+		      int		nparams,
+		      int		width,
+		      int		height)
 {
     xFixed  *new_params;
 
@@ -80,6 +82,8 @@ RRTransformSetFilter (RRTransformPtr	dst,
     dst->filter = filter;
     dst->params = new_params;
     dst->nparams = nparams;
+    dst->width = width;
+    dst->height = height;
     return TRUE;
 }
 
@@ -87,7 +91,7 @@ static Bool
 RRTransformCopy (RRTransformPtr dst, RRTransformPtr src)
 {
     if (!RRTransformSetFilter (dst, src->filter,
-			       src->params, src->nparams))
+			       src->params, src->nparams, src->width, src->height))
 	return FALSE;
     dst->transform = src->transform;
     dst->inverse = src->inverse;
@@ -602,6 +606,7 @@ RRCrtcTransformSet (RRCrtcPtr		crtc,
 		    int			nparams)
 {
     PictFilterPtr   filter = NULL;
+    int		    width = 0, height = 0;
 
     if (!PictureTransformIsInverse (transform, inverse))
 	return BadMatch;
@@ -615,9 +620,13 @@ RRCrtcTransformSet (RRCrtcPtr		crtc,
 	if (filter->ValidateParams)
 	{
 	    if (!filter->ValidateParams (crtc->pScreen, filter->id,
-					 params, nparams))
+					 params, nparams, &width, &height))
 		return BadMatch;
 	}
+	else {
+	    width = filter->width;
+	    height = filter->height;
+	}
     }
     else
     {
@@ -625,7 +634,7 @@ RRCrtcTransformSet (RRCrtcPtr		crtc,
 	    return BadMatch;
     }
     if (!RRTransformSetFilter (&crtc->client_pending_transform,
-			       filter, params, nparams))
+			       filter, params, nparams, width, height))
 	return BadAlloc;
 
     crtc->client_pending_transform.transform = *transform;
@@ -1037,12 +1046,11 @@ ProcRRSetCrtcConfig (ClientPtr client)
 	    int	source_height;
 	    PictTransform transform, inverse;
 
-	    if (!RRComputeTransform (mode, stuff->rotation,
-				     stuff->x, stuff->y,
-				     &crtc->client_pending_transform.transform,
-				     &crtc->client_pending_transform.inverse,
-				     &transform, &inverse))
-		return BadMatch;
+	    RRComputeTransform (mode, stuff->rotation,
+				stuff->x, stuff->y,
+				&crtc->client_pending_transform.transform,
+				&crtc->client_pending_transform.inverse,
+				&transform, &inverse);
 
 	    RRModeGetScanoutSize (mode, &transform, &source_width, &source_height);
 	    if (stuff->x + source_width > pScreen->width)
commit 1df02d7ddd44f84bcaefd6583af1a9141cb3c78b
Author: Keith Packard <keithp at keithp.com>
Date:   Mon Mar 17 15:19:17 2008 -0700

    Add kernel size to Render filters.
    
    This width/height value lets filter users know how far the filter spreads
    into the source image.

diff --git a/render/filter.c b/render/filter.c
index e499fc4..b5bcf02 100644
--- a/render/filter.c
+++ b/render/filter.c
@@ -126,7 +126,9 @@ PictureFreeFilterIds (void)
 _X_EXPORT int
 PictureAddFilter (ScreenPtr			    pScreen,
 		  char				    *filter,
-		  PictFilterValidateParamsProcPtr   ValidateParams)
+		  PictFilterValidateParamsProcPtr   ValidateParams,
+		  int				    width,
+		  int				    height)
 {
     PictureScreenPtr    ps = GetPictureScreen(pScreen);
     int			id = PictureGetFilterId (filter, -1,  TRUE);
@@ -152,6 +154,8 @@ PictureAddFilter (ScreenPtr			    pScreen,
     ps->filters[i].name = PictureGetFilterName (id);
     ps->filters[i].id = id;
     ps->filters[i].ValidateParams = ValidateParams;
+    ps->filters[i].width = width;
+    ps->filters[i].height = height;
     return id;
 }
 
@@ -216,18 +220,26 @@ static Bool
 convolutionFilterValidateParams (ScreenPtr pScreen,
                                  int	   filter,
                                  xFixed	   *params,
-                                 int	   nparams)
+                                 int	   nparams,
+				 int       *width,
+				 int	   *height)
 {
+    int	w, h;
     if (nparams < 3)
         return FALSE;
 
     if (xFixedFrac (params[0]) || xFixedFrac (params[1]))
         return FALSE;
 
+    w = xFixedToInt (params[0]);
+    h = xFixedToInt (params[1]);
+
     nparams -= 2;
-    if ((xFixedToInt (params[0]) * xFixedToInt (params[1])) > nparams)
+    if (w * h > nparams)
         return FALSE;
 
+    *width = w;
+    *height = h;
     return TRUE;
 }
 
@@ -238,9 +250,9 @@ PictureSetDefaultFilters (ScreenPtr pScreen)
     if (!filterNames)
 	if (!PictureSetDefaultIds ())
 	    return FALSE;
-    if (PictureAddFilter (pScreen, FilterNearest, 0) < 0)
+    if (PictureAddFilter (pScreen, FilterNearest, 0, 1, 1) < 0)
 	return FALSE;
-    if (PictureAddFilter (pScreen, FilterBilinear, 0) < 0)
+    if (PictureAddFilter (pScreen, FilterBilinear, 0, 4, 4) < 0)
 	return FALSE;
 
     if (!PictureSetFilterAlias (pScreen, FilterNearest, FilterFast))
@@ -250,7 +262,7 @@ PictureSetDefaultFilters (ScreenPtr pScreen)
     if (!PictureSetFilterAlias (pScreen, FilterBilinear, FilterBest))
 	return FALSE;
 
-    if (PictureAddFilter (pScreen, FilterConvolution, convolutionFilterValidateParams) < 0)
+    if (PictureAddFilter (pScreen, FilterConvolution, convolutionFilterValidateParams, 0, 0) < 0)
         return FALSE;
 
     return TRUE;
@@ -314,7 +326,8 @@ SetPicturePictFilter (PicturePtr pPicture, PictFilterPtr pFilter,
 
     if (pFilter->ValidateParams)
     {
-	if (!(*pFilter->ValidateParams) (pScreen, pFilter->id, params, nparams))
+	int width, height;
+	if (!(*pFilter->ValidateParams) (pScreen, pFilter->id, params, nparams, &width, &height))
 	    return BadMatch;
     }
     else if (nparams)
diff --git a/render/picturestr.h b/render/picturestr.h
index 8a926ce..60be68a 100644
--- a/render/picturestr.h
+++ b/render/picturestr.h
@@ -185,11 +185,13 @@ typedef struct _Picture {
 } PictureRec;
 
 typedef Bool (*PictFilterValidateParamsProcPtr) (ScreenPtr pScreen, int id,
-						 xFixed *params, int nparams);
+						 xFixed *params, int nparams,
+						 int *width, int *height);
 typedef struct {
     char			    *name;
     int				    id;
     PictFilterValidateParamsProcPtr ValidateParams;
+    int				    width, height;
 } PictFilterRec, *PictFilterPtr;
 
 #define PictFilterNearest	0
@@ -458,7 +460,9 @@ PictureGetFilterName (int id);
 int
 PictureAddFilter (ScreenPtr			    pScreen,
 		  char				    *filter,
-		  PictFilterValidateParamsProcPtr   ValidateParams);
+		  PictFilterValidateParamsProcPtr   ValidateParams,
+		  int				    width,
+		  int				    height);
 
 Bool
 PictureSetFilterAlias (ScreenPtr pScreen, char *filter, char *alias);
commit 40f3dff6b350fe0be55ebf7dbca88a0ef8f6380f
Author: Keith Packard <keithp at keithp.com>
Date:   Mon Mar 17 13:57:47 2008 -0700

    Use transform when computing scanout size of modes
    
    Report transformed crtc sizes through RandR and Xinerama. Test screen size
    against transformed mode sizes when configuring the Crtc.

diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
index e3ba4f8..bae17c5 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -528,30 +528,35 @@ RRCrtcGammaNotify (RRCrtcPtr	crtc)
     return TRUE;    /* not much going on here */
 }
 
-/**
- * Returns the width/height that the crtc scans out from the framebuffer
- */
-void
-RRCrtcGetScanoutSize(RRCrtcPtr crtc, int *width, int *height)
+static void
+RRModeGetScanoutSize (RRModePtr mode, PictTransformPtr transform,
+		      int *width, int *height)
 {
-    if (crtc->mode == NULL) {
+    BoxRec  box;
+
+    if (mode == NULL) {
 	*width = 0;
 	*height = 0;
 	return;
     }
 
-    switch (crtc->rotation & 0xf) {
-    case RR_Rotate_0:
-    case RR_Rotate_180:
-	*width = crtc->mode->mode.width;
-	*height = crtc->mode->mode.height;
-	break;
-    case RR_Rotate_90:
-    case RR_Rotate_270:
-	*width = crtc->mode->mode.height;
-	*height = crtc->mode->mode.width;
-	break;
-    }
+    box.x1 = 0;
+    box.y1 = 0;
+    box.x2 = mode->mode.width;
+    box.y2 = mode->mode.height;
+
+    PictureTransformBounds (&box, transform);
+    *width = box.x2 - box.x1;
+    *height = box.y2 - box.y1;
+}
+
+/**
+ * Returns the width/height that the crtc scans out from the framebuffer
+ */
+void
+RRCrtcGetScanoutSize(RRCrtcPtr crtc, int *width, int *height)
+{
+    return RRModeGetScanoutSize (crtc->mode, &crtc->transform, width, height);
 }
 
 /*
@@ -1028,14 +1033,18 @@ ProcRRSetCrtcConfig (ClientPtr client)
 	 */
 	if (pScrPriv->rrScreenSetSize)
 	{
-	    int source_width = mode->mode.width;
-	    int	source_height = mode->mode.height;
+	    int source_width;
+	    int	source_height;
+	    PictTransform transform, inverse;
+
+	    if (!RRComputeTransform (mode, stuff->rotation,
+				     stuff->x, stuff->y,
+				     &crtc->client_pending_transform.transform,
+				     &crtc->client_pending_transform.inverse,
+				     &transform, &inverse))
+		return BadMatch;
 
-	    if ((rotation & 0xf) == RR_Rotate_90 || (rotation & 0xf) == RR_Rotate_270)
-	    {
-		source_width = mode->mode.height;
-		source_height = mode->mode.width;
-	    }
+	    RRModeGetScanoutSize (mode, &transform, &source_width, &source_height);
 	    if (stuff->x + source_width > pScreen->width)
 	    {
 		client->errorValue = stuff->x;
@@ -1246,7 +1255,6 @@ transform_filter_encode (ClientPtr client, char *output,
 			 CARD16	*nparamsFilter,
 			 RRTransformPtr transform)
 {
-    char    *output_orig = output;
     int	    nbytes, nparams;
     int	    n;
 
@@ -1260,17 +1268,17 @@ transform_filter_encode (ClientPtr client, char *output,
     *nbytesFilter = nbytes;
     *nparamsFilter = nparams;
     memcpy (output, transform->filter->name, nbytes);
-    output += nbytes;
     while ((nbytes & 3) != 0)
-	*output++ = 0;
-    memcpy (output, transform->params, nparams * sizeof (xFixed));
+	output[nbytes++] = 0;
+    memcpy (output + nbytes, transform->params, nparams * sizeof (xFixed));
     if (client->swapped) {
 	swaps (nbytesFilter, n);
 	swaps (nparamsFilter, n);
-	SwapLongs ((CARD32 *) output, nparams * sizeof (xFixed));
+	SwapLongs ((CARD32 *) (output + nbytes),
+		   nparams * sizeof (xFixed));
     }
-    output += nparams * sizeof (xFixed);
-    return output - output_orig;
+    nbytes += nparams * sizeof (xFixed);
+    return nbytes;
 }
 
 static void
commit f50349e1930e620cacdf27a6f8585fcb9cb5199a
Author: Keith Packard <keithp at keithp.com>
Date:   Sat Mar 15 00:36:45 2008 -0700

    [RANDR] Support filters in CRTC transforms.
    
    Create new RRTransform datatype to hold all of the transform related
    information, use that in lots of places to pass filters around.

diff --git a/hw/xfree86/modes/xf86Crtc.h b/hw/xfree86/modes/xf86Crtc.h
index ef8589e..a5bb11b 100644
--- a/hw/xfree86/modes/xf86Crtc.h
+++ b/hw/xfree86/modes/xf86Crtc.h
@@ -306,6 +306,9 @@ struct _xf86Crtc {
      */
     PictTransform   crtc_to_framebuffer;
     PictTransform   framebuffer_to_crtc;
+    PictFilterPtr   filter;
+    xFixed	    *params;
+    int		    nparams;
     Bool	    transform_in_use;
     /**
      * Bounding box in screen space
diff --git a/hw/xfree86/modes/xf86Rotate.c b/hw/xfree86/modes/xf86Rotate.c
index 7967e5b..f201ae3 100644
--- a/hw/xfree86/modes/xf86Rotate.c
+++ b/hw/xfree86/modes/xf86Rotate.c
@@ -109,6 +109,9 @@ xf86RotateCrtcRedisplay (xf86CrtcPtr crtc, RegionPtr region)
     error = SetPictureTransform (src, &crtc->crtc_to_framebuffer);
     if (error)
 	return;
+    if (crtc->transform_in_use && crtc->filter)
+	SetPicturePictFilter (src, crtc->filter,
+			      crtc->params, crtc->nparams);
 
     while (n--)
     {
@@ -380,13 +383,33 @@ xf86CrtcRotate (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation)
     }
     
 #ifdef RANDR_12_INTERFACE
+    if (crtc->randr_crtc)
     {
-	PictTransform	user_forward, user_reverse;
-	if (crtc->randr_crtc && RRCrtcGetTransform (crtc->randr_crtc, &user_forward, &user_reverse))
+	xFixed		*new_params = NULL;
+	int		new_nparams = 0;
+	PictFilterPtr   new_filter = NULL;
+
+	RRTransformPtr	transform = RRCrtcGetTransform (crtc->randr_crtc);
+	if (transform)
 	{
-	    PictureTransformMultiply (&crtc_to_fb, &user_forward, &crtc_to_fb);
-	    PictureTransformMultiply (&fb_to_crtc, &fb_to_crtc, &user_reverse);
+	    if (transform->nparams) {
+		new_params = xalloc (transform->nparams * sizeof (xFixed));
+		if (new_params) {
+		    memcpy (new_params, transform->params,
+			    transform->nparams * sizeof (xFixed));
+		    new_nparams = transform->nparams;
+		    new_filter = transform->filter;
+		}
+	    } else
+		new_filter = transform->filter;
+	    PictureTransformMultiply (&crtc_to_fb, &transform->transform, &crtc_to_fb);
+	    PictureTransformMultiply (&fb_to_crtc, &fb_to_crtc, &transform->inverse);
 	}
+	if (crtc->params)
+	    xfree (crtc->params);
+	crtc->params = new_params;
+	crtc->nparams = new_nparams;
+	crtc->filter = new_filter;
     }
 #endif
     /*
diff --git a/randr/randrstr.h b/randr/randrstr.h
index 320e9f7..cdaebe9 100644
--- a/randr/randrstr.h
+++ b/randr/randrstr.h
@@ -78,6 +78,7 @@ typedef struct _rrPropertyValue	RRPropertyValueRec, *RRPropertyValuePtr;
 typedef struct _rrProperty	RRPropertyRec, *RRPropertyPtr;
 typedef struct _rrCrtc		RRCrtcRec, *RRCrtcPtr;
 typedef struct _rrOutput	RROutputRec, *RROutputPtr;
+typedef struct _rrTransform	RRTransformRec, *RRTransformPtr;
 
 struct _rrMode {
     int		    refcnt;
@@ -104,6 +105,14 @@ struct _rrProperty {
     RRPropertyValueRec	current, pending;
 };
 
+struct _rrTransform {
+    PictTransform   transform;
+    PictTransform   inverse;
+    PictFilterPtr   filter;
+    xFixed	    *params;
+    int		    nparams;
+};
+
 struct _rrCrtc {
     RRCrtc	    id;
     ScreenPtr	    pScreen;
@@ -119,10 +128,8 @@ struct _rrCrtc {
     CARD16	    *gammaBlue;
     CARD16	    *gammaGreen;
     void	    *devPrivate;
-    PictTransform   client_pending_transform;
-    PictTransform   client_pending_inverse;
-    PictTransform   client_current_transform;
-    PictTransform   client_current_inverse;
+    RRTransformRec  client_pending_transform;
+    RRTransformRec  client_current_transform;
     PictTransform   transform;
     PictTransform   inverse;
 };
@@ -612,10 +619,8 @@ RRComputeTransform (RRModePtr		mode,
 /*
  * Return crtc transform
  */
-Bool
-RRCrtcGetTransform (RRCrtcPtr crtc,
-		    PictTransformPtr crtc_to_fb,
-		    PictTransformPtr fb_to_crtc);
+RRTransformPtr
+RRCrtcGetTransform (RRCrtcPtr crtc);
 
 /*
  * Mark the pending transform as current
@@ -643,7 +648,11 @@ RRCrtcDestroy (RRCrtcPtr crtc);
 int
 RRCrtcTransformSet (RRCrtcPtr		crtc,
 		    PictTransformPtr	transform,
-		    PictTransformPtr	inverse);
+		    PictTransformPtr	inverse,
+		    char		*filter,
+		    int			filter_len,
+		    xFixed		*params,
+		    int			nparams);
 
 /*
  * Initialize crtc type
diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
index 0cb8638..e3ba4f8 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -48,6 +48,52 @@ RRCrtcChanged (RRCrtcPtr crtc, Bool layoutChanged)
     }
 }
 
+static void
+RRTransformInit (RRTransformPtr transform)
+{
+    PictureTransformInitIdentity (&transform->transform);
+    PictureTransformInitIdentity (&transform->inverse);
+    transform->filter = NULL;
+    transform->params = NULL;
+    transform->nparams = 0;
+}
+
+static Bool
+RRTransformSetFilter (RRTransformPtr	dst,
+		      PictFilterPtr	filter,
+		      xFixed		*params,
+		      int		nparams)
+{
+    xFixed  *new_params;
+
+    if (nparams)
+    {
+	new_params = xalloc (nparams * sizeof (xFixed));
+	if (!new_params)
+	    return FALSE;
+	memcpy (new_params, params, nparams * sizeof (xFixed));
+    }
+    else
+	new_params = NULL;
+    if (dst->params)
+	xfree (dst->params);
+    dst->filter = filter;
+    dst->params = new_params;
+    dst->nparams = nparams;
+    return TRUE;
+}
+
+static Bool
+RRTransformCopy (RRTransformPtr dst, RRTransformPtr src)
+{
+    if (!RRTransformSetFilter (dst, src->filter,
+			       src->params, src->nparams))
+	return FALSE;
+    dst->transform = src->transform;
+    dst->inverse = src->inverse;
+    return TRUE;
+}
+
 /*
  * Create a CRTC
  */
@@ -89,10 +135,8 @@ RRCrtcCreate (ScreenPtr pScreen, void *devPrivate)
     crtc->gammaRed = crtc->gammaBlue = crtc->gammaGreen = NULL;
     crtc->changed = FALSE;
     crtc->devPrivate = devPrivate;
-    PictureTransformInitIdentity (&crtc->client_pending_transform);
-    PictureTransformInitIdentity (&crtc->client_pending_inverse);
-    PictureTransformInitIdentity (&crtc->client_current_transform);
-    PictureTransformInitIdentity (&crtc->client_current_inverse);
+    RRTransformInit (&crtc->client_pending_transform);
+    RRTransformInit (&crtc->client_current_transform);
     PictureTransformInitIdentity (&crtc->transform);
     PictureTransformInitIdentity (&crtc->inverse);
 
@@ -368,14 +412,14 @@ RRCrtcSet (RRCrtcPtr    crtc,
 /*
  * Return crtc transform
  */
-Bool
-RRCrtcGetTransform (RRCrtcPtr crtc,
-		    PictTransformPtr crtc_to_fb,
-		    PictTransformPtr fb_to_crtc)
+RRTransformPtr
+RRCrtcGetTransform (RRCrtcPtr crtc)
 {
-    *crtc_to_fb = crtc->client_pending_transform;
-    *fb_to_crtc = crtc->client_pending_inverse;
-    return !PictureTransformIsIdentity (crtc_to_fb);
+    RRTransformPtr  transform = &crtc->client_pending_transform;
+
+    if (PictureTransformIsIdentity (&transform->transform))
+	return NULL;
+    return transform;
 }
 
 /*
@@ -384,11 +428,11 @@ RRCrtcGetTransform (RRCrtcPtr crtc,
 void
 RRCrtcPostPendingTransform (RRCrtcPtr crtc)
 {
-    crtc->client_current_transform = crtc->client_pending_transform;
-    crtc->client_current_inverse = crtc->client_pending_inverse;
+    RRTransformCopy (&crtc->client_current_transform,
+		     &crtc->client_pending_transform);
     RRComputeTransform (crtc->mode, crtc->rotation, crtc->x, crtc->y,
-			&crtc->client_current_transform,
-			&crtc->client_current_inverse,
+			&crtc->client_current_transform.transform,
+			&crtc->client_current_transform.inverse,
 			&crtc->transform,
 			&crtc->inverse);
 }
@@ -399,8 +443,8 @@ RRCrtcPostPendingTransform (RRCrtcPtr crtc)
 Bool
 RRCrtcPendingTransform (RRCrtcPtr crtc)
 {
-    return memcmp (&crtc->client_current_transform,
-		   &crtc->client_pending_transform,
+    return memcmp (&crtc->client_current_transform.transform,
+		   &crtc->client_pending_transform.transform,
 		   sizeof (PictTransform)) != 0;
 }
 
@@ -546,12 +590,41 @@ RRCrtcGammaSetSize (RRCrtcPtr	crtc,
 int
 RRCrtcTransformSet (RRCrtcPtr		crtc,
 		    PictTransformPtr	transform,
-		    PictTransformPtr	inverse)
+		    PictTransformPtr	inverse,
+		    char		*filter_name,
+		    int			filter_len,
+		    xFixed		*params,
+		    int			nparams)
 {
+    PictFilterPtr   filter = NULL;
+
     if (!PictureTransformIsInverse (transform, inverse))
 	return BadMatch;
-    crtc->client_pending_transform = *transform;
-    crtc->client_pending_inverse = *inverse;
+    if (filter_len)
+    {
+	filter = PictureFindFilter (crtc->pScreen,
+				    filter_name,
+				    filter_len);
+	if (!filter)
+	    return BadName;
+	if (filter->ValidateParams)
+	{
+	    if (!filter->ValidateParams (crtc->pScreen, filter->id,
+					 params, nparams))
+		return BadMatch;
+	}
+    }
+    else
+    {
+	if (nparams)
+	    return BadMatch;
+    }
+    if (!RRTransformSetFilter (&crtc->client_pending_transform,
+			       filter, params, nparams))
+	return BadAlloc;
+
+    crtc->client_pending_transform.transform = *transform;
+    crtc->client_pending_transform.inverse = *inverse;
     return Success;
 }
 
@@ -1128,8 +1201,12 @@ ProcRRSetCrtcTransform (ClientPtr client)
     REQUEST(xRRSetCrtcTransformReq);
     RRCrtcPtr		    crtc;
     PictTransform	    transform, inverse;
+    char		    *filter;
+    int			    nbytes;
+    xFixed		    *params;
+    int			    nparams;
 
-    REQUEST_SIZE_MATCH (xRRSetCrtcTransformReq);
+    REQUEST_AT_LEAST_SIZE(xRRSetCrtcTransformReq);
     crtc = LookupCrtc (client, stuff->crtc, DixWriteAccess);
     if (!crtc)
 	return RRErrorBase + BadRRCrtc;
@@ -1137,42 +1214,124 @@ ProcRRSetCrtcTransform (ClientPtr client)
     PictTransform_from_xRenderTransform (&transform, &stuff->transform);
     PictTransform_from_xRenderTransform (&inverse, &stuff->inverse);
 
-    return RRCrtcTransformSet (crtc, &transform, &inverse);
+    filter = (char *) (stuff + 1);
+    nbytes = stuff->nbytesFilter;
+    params = (xFixed *) (filter + ((nbytes + 3) & ~3));
+    nparams = ((xFixed *) stuff + client->req_len) - params;
+    if (nparams < 0)
+	return BadLength;
+
+    return RRCrtcTransformSet (crtc, &transform, &inverse,
+			       filter, nbytes, params, nparams);
 }
 
 
 #define CrtcTransformExtra	(SIZEOF(xRRGetCrtcTransformReply) - 32)
 				
+static int
+transform_filter_length (RRTransformPtr transform)
+{
+    int	nbytes, nparams;
+
+    if (transform->filter == NULL)
+	return 0;
+    nbytes = strlen (transform->filter->name);
+    nparams = transform->nparams;
+    return ((nbytes + 3) & ~3) + (nparams * sizeof (xFixed));
+}
+
+static int
+transform_filter_encode (ClientPtr client, char *output,
+			 CARD16	*nbytesFilter,
+			 CARD16	*nparamsFilter,
+			 RRTransformPtr transform)
+{
+    char    *output_orig = output;
+    int	    nbytes, nparams;
+    int	    n;
+
+    if (transform->filter == NULL) {
+	*nbytesFilter = 0;
+	*nparamsFilter = 0;
+	return 0;
+    }
+    nbytes = strlen (transform->filter->name);
+    nparams = transform->nparams;
+    *nbytesFilter = nbytes;
+    *nparamsFilter = nparams;
+    memcpy (output, transform->filter->name, nbytes);
+    output += nbytes;
+    while ((nbytes & 3) != 0)
+	*output++ = 0;
+    memcpy (output, transform->params, nparams * sizeof (xFixed));
+    if (client->swapped) {
+	swaps (nbytesFilter, n);
+	swaps (nparamsFilter, n);
+	SwapLongs ((CARD32 *) output, nparams * sizeof (xFixed));
+    }
+    output += nparams * sizeof (xFixed);
+    return output - output_orig;
+}
+
+static void
+transform_encode (ClientPtr client, xRenderTransform *wire, PictTransform *pict)
+{
+    xRenderTransform_from_PictTransform (wire, pict);
+    if (client->swapped)
+	SwapLongs ((CARD32 *) wire, sizeof (xRenderTransform));
+}
+
 int
 ProcRRGetCrtcTransform (ClientPtr client)
 {
     REQUEST(xRRGetCrtcTransformReq);
-    xRRGetCrtcTransformReply	reply;
+    xRRGetCrtcTransformReply	*reply;
     RRCrtcPtr			crtc;
-    int				n;
+    int				n, nextra;
+    RRTransformPtr		current, pending;
+    char			*extra;
 
     REQUEST_SIZE_MATCH (xRRGetCrtcTransformReq);
     crtc = LookupCrtc (client, stuff->crtc, DixWriteAccess);
     if (!crtc)
 	return RRErrorBase + BadRRCrtc;
 
-    reply.type = X_Reply;
-    reply.sequenceNumber = client->sequence;
-    reply.length = CrtcTransformExtra >> 2;
-    
-    xRenderTransform_from_PictTransform (&reply.pendingTransform,
-					 &crtc->client_pending_transform);
-    xRenderTransform_from_PictTransform (&reply.pendingInverse,
-					 &crtc->client_pending_inverse);
-    xRenderTransform_from_PictTransform (&reply.currentTransform,
-					 &crtc->client_current_transform);
-    xRenderTransform_from_PictTransform (&reply.currentInverse,
-					 &crtc->client_current_inverse);
+    pending = &crtc->client_pending_transform;
+    current = &crtc->client_current_transform;
+
+    nextra = (transform_filter_length (pending) +
+	      transform_filter_length (current));
+
+    reply = xalloc (sizeof (xRRGetCrtcTransformReply) + nextra);
+    if (!reply)
+	return BadAlloc;
+
+    extra = (char *) (reply + 1);
+    reply->type = X_Reply;
+    reply->sequenceNumber = client->sequence;
+    reply->length = (CrtcTransformExtra + nextra) >> 2;
+
+    /* XXX deal with DDXen that can't do transforms */
+    reply->hasTransforms = xTrue;
+
+    transform_encode (client, &reply->pendingTransform, &pending->transform);
+    transform_encode (client, &reply->pendingInverse, &pending->inverse);
+    extra += transform_filter_encode (client, extra,
+				      &reply->pendingNbytesFilter,
+				      &reply->pendingNparamsFilter,
+				      pending);
+
+    transform_encode (client, &reply->currentTransform, &current->transform);
+    transform_encode (client, &reply->currentInverse, &current->inverse);
+    extra += transform_filter_encode (client, extra,
+				      &reply->currentNbytesFilter,
+				      &reply->currentNparamsFilter,
+				      current);
+
     if (client->swapped) {
-	swaps (&reply.sequenceNumber, n);
-	swapl (&reply.length, n);
-	SwapLongs ((CARD32 *) &reply.pendingTransform, 40);
+	swaps (&reply->sequenceNumber, n);
+	swapl (&reply->length, n);
     }
-    WriteToClient (client, sizeof (xRRGetCrtcTransformReply), (char *) &reply);
+    WriteToClient (client, sizeof (xRRGetCrtcTransformReply) + nextra, (char *) reply);
     return client->noClientException;
 }
commit acda790e430b2a18c7c35379f6e538f3d01ff221
Author: Keith Packard <keithp at keithp.com>
Date:   Fri Mar 14 13:46:30 2008 -0700

    [render] Split out filter finding from filter setting.
    
    To prepare for RandR using filters in transforms, split out
    code paths so that the RandR code can validate the filter name and
    parameters during the transform set operation so that use of the filter
    later will not have unreportable errors.

diff --git a/render/filter.c b/render/filter.c
index aa3eb1a..e499fc4 100644
--- a/render/filter.c
+++ b/render/filter.c
@@ -213,7 +213,7 @@ PictureFindFilter (ScreenPtr pScreen, char *name, int len)
 }
 
 static Bool
-convolutionFilterValidateParams (PicturePtr pPicture,
+convolutionFilterValidateParams (ScreenPtr pScreen,
                                  int	   filter,
                                  xFixed	   *params,
                                  int	   nparams)
@@ -270,29 +270,51 @@ int
 SetPictureFilter (PicturePtr pPicture, char *name, int len, xFixed *params, int nparams)
 {
     PictFilterPtr	pFilter;
-    xFixed		*new_params;
-    int			i, s, result;
+    ScreenPtr		pScreen;
 
-    pFilter = PictureFindFilter (screenInfo.screens[0], name, len);
+    if (pPicture->pDrawable != NULL)
+	pScreen = pPicture->pDrawable->pScreen;
+    else
+	pScreen = screenInfo.screens[0];
+
+    pFilter = PictureFindFilter (pScreen, name, len);
+
+    if (!pFilter)
+	return BadName;
 
-    if (pPicture->pDrawable == NULL) {
+    if (pPicture->pDrawable == NULL)
+    {
+	int s;
 	/* For source pictures, the picture isn't tied to a screen.  So, ensure
 	 * that all screens can handle a filter we set for the picture.
 	 */
-	for (s = 0; s < screenInfo.numScreens; s++) {
-	    if (PictureFindFilter (screenInfo.screens[s], name, len)->id !=
-		pFilter->id)
-	    {
+	for (s = 1; s < screenInfo.numScreens; s++)
+	{
+	    PictFilterPtr   pScreenFilter;
+	    pScreenFilter = PictureFindFilter (screenInfo.screens[s],
+					       name, len);
+	    if (!pScreenFilter || pScreenFilter->id != pFilter->id)
 		return BadMatch;
-	    }
 	}
     }
+    return SetPicturePictFilter (pPicture, pFilter, params, nparams);
+}
+
+int
+SetPicturePictFilter (PicturePtr pPicture, PictFilterPtr pFilter,
+		      xFixed *params, int nparams)
+{
+    ScreenPtr	pScreen;
+    int		i;
+
+    if (pPicture->pDrawable)
+	pScreen = pPicture->pDrawable->pScreen;
+    else
+	pScreen = screenInfo.screens[0];
 
-    if (!pFilter)
-	return BadName;
     if (pFilter->ValidateParams)
     {
-	if (!(*pFilter->ValidateParams) (pPicture, pFilter->id, params, nparams))
+	if (!(*pFilter->ValidateParams) (pScreen, pFilter->id, params, nparams))
 	    return BadMatch;
     }
     else if (nparams)
@@ -300,7 +322,7 @@ SetPictureFilter (PicturePtr pPicture, char *name, int len, xFixed *params, int
 
     if (nparams != pPicture->filter_nparams)
     {
-	new_params = xalloc (nparams * sizeof (xFixed));
+	xFixed *new_params = xalloc (nparams * sizeof (xFixed));
 	if (!new_params && nparams)
 	    return BadAlloc;
 	xfree (pPicture->filter_params);
@@ -311,9 +333,10 @@ SetPictureFilter (PicturePtr pPicture, char *name, int len, xFixed *params, int
 	pPicture->filter_params[i] = params[i];
     pPicture->filter = pFilter->id;
 
-    if (pPicture->pDrawable) {
-	ScreenPtr pScreen = pPicture->pDrawable->pScreen;
-	PictureScreenPtr ps = GetPictureScreen(pScreen);
+    if (pPicture->pDrawable)
+    {
+	PictureScreenPtr    ps = GetPictureScreen(pScreen);
+	int		    result;
 
 	result = (*ps->ChangePictureFilter) (pPicture, pPicture->filter,
 					     params, nparams);
diff --git a/render/picturestr.h b/render/picturestr.h
index 93d86bd..8a926ce 100644
--- a/render/picturestr.h
+++ b/render/picturestr.h
@@ -184,7 +184,7 @@ typedef struct _Picture {
     SourcePictPtr   pSourcePict;
 } PictureRec;
 
-typedef Bool (*PictFilterValidateParamsProcPtr) (PicturePtr pPicture, int id,
+typedef Bool (*PictFilterValidateParamsProcPtr) (ScreenPtr pScreen, int id,
 						 xFixed *params, int nparams);
 typedef struct {
     char			    *name;
@@ -473,7 +473,12 @@ PictFilterPtr
 PictureFindFilter (ScreenPtr pScreen, char *name, int len);
 
 int
-SetPictureFilter (PicturePtr pPicture, char *name, int len, xFixed *params, int nparams);
+SetPicturePictFilter (PicturePtr pPicture, PictFilterPtr pFilter,
+		      xFixed *params, int nparams);
+
+int
+SetPictureFilter (PicturePtr pPicture, char *name, int len,
+		  xFixed *params, int nparams);
 
 Bool
 PictureFinishInit (void);
commit e3d6f279d5c305dfb81ca109fbfb665870712d2f
Author: Keith Packard <keithp at keithp.com>
Date:   Thu Mar 13 21:31:12 2008 -0700

    Wire up RandR CRTC transform protocol, bump server to RandR 1.3
    
    This involved removing a pile of matrix code from the DDX,
    as well as moving a bit of transform logic from DDX to DIX.

diff --git a/hw/xfree86/modes/xf86Crtc.c b/hw/xfree86/modes/xf86Crtc.c
index a71f5c7..a7e7af6 100644
--- a/hw/xfree86/modes/xf86Crtc.c
+++ b/hw/xfree86/modes/xf86Crtc.c
@@ -351,6 +351,10 @@ xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation,
 #endif
 	}
     }
+#ifdef RANDR_12_INTERFACE
+    if (crtc->randr_crtc)
+	RRCrtcPostPendingTransform (crtc->randr_crtc);
+#endif
 
     /* XXX free adjustedmode */
     ret = TRUE;
diff --git a/hw/xfree86/modes/xf86RandR12.c b/hw/xfree86/modes/xf86RandR12.c
index 2ae8ea7..6e14bd7 100644
--- a/hw/xfree86/modes/xf86RandR12.c
+++ b/hw/xfree86/modes/xf86RandR12.c
@@ -755,6 +755,9 @@ xf86RandR12CrtcSet (ScreenPtr	pScreen,
     if (rotation != crtc->rotation)
 	changed = TRUE;
 
+    if (RRCrtcPendingTransform (randr_crtc))
+	changed = TRUE;
+
     if (x != crtc->x || y != crtc->y)
 	changed = TRUE;
     for (o = 0; o < config->num_output; o++) 
diff --git a/hw/xfree86/modes/xf86Rotate.c b/hw/xfree86/modes/xf86Rotate.c
index 5ab2bf8..7967e5b 100644
--- a/hw/xfree86/modes/xf86Rotate.c
+++ b/hw/xfree86/modes/xf86Rotate.c
@@ -70,205 +70,9 @@ compWindowFormat (WindowPtr pWin)
 
 #define F(x)	IntToxFixed(x)
 
-static void
-PictureTransformIdentity (PictTransformPtr matrix)
-{
-    int	i;
-    memset (matrix, '\0', sizeof (PictTransform));
-    for (i = 0; i < 3; i++)
-	matrix->matrix[i][i] = F(1);
-}
-
-static Bool
-PictureTransformMultiply (PictTransformPtr dst, PictTransformPtr l, PictTransformPtr r)
-{
-    PictTransform   d;
-    int		    dx, dy;
-    int		    o;
-
-    for (dy = 0; dy < 3; dy++)
-	for (dx = 0; dx < 3; dx++)
-	{
-	    xFixed_48_16    v;
-	    xFixed_32_32    partial;
-	    v = 0;
-	    for (o = 0; o < 3; o++)
-	    {
-		partial = (xFixed_32_32) l->matrix[dy][o] * (xFixed_32_32) r->matrix[o][dx];
-		v += partial >> 16;
-	    }
-	    if (v > MAX_FIXED_48_16 || v < MIN_FIXED_48_16)
-		return FALSE;
-	    d.matrix[dy][dx] = (xFixed) v;
-	}
-    *dst = d;
-    return TRUE;
-}
-
-static void
-PictureTransformInitScale (PictTransformPtr t, xFixed sx, xFixed sy)
-{
-    memset (t, '\0', sizeof (PictTransform));
-    t->matrix[0][0] = sx;
-    t->matrix[1][1] = sy;
-    t->matrix[2][2] = F (1);
-}
-
-static xFixed
-fixed_inverse (xFixed x)
-{
-    return (xFixed) ((((xFixed_48_16) F(1)) * F(1)) / x);
-}
-
-static Bool
-PictureTransformScale (PictTransformPtr forward,
-		       PictTransformPtr reverse,
-		       xFixed sx, xFixed sy)
-{
-    PictTransform   t;
-    
-    PictureTransformInitScale (&t, sx, sy);
-    if (!PictureTransformMultiply (forward, &t, forward))
-	return FALSE;
-    PictureTransformInitScale (&t, fixed_inverse (sx), fixed_inverse (sy));
-    if (!PictureTransformMultiply (reverse, reverse, &t))
-	return FALSE;
-    return TRUE;
-}
-
-static void
-PictureTransformInitRotate (PictTransformPtr t, xFixed c, xFixed s)
-{
-    memset (t, '\0', sizeof (PictTransform));
-    t->matrix[0][0] = c;
-    t->matrix[0][1] = -s;
-    t->matrix[1][0] = s;
-    t->matrix[1][1] = c;
-    t->matrix[2][2] = F (1);
-}
-
-static Bool
-PictureTransformRotate (PictTransformPtr forward,
-			PictTransformPtr reverse,
-			xFixed c, xFixed s)
-{
-    PictTransform   t;
-    PictureTransformInitRotate (&t, c, s);
-    if (!PictureTransformMultiply (forward, &t, forward))
-	return FALSE;
-    
-    PictureTransformInitRotate (&t, c, -s);
-    if (!PictureTransformMultiply (reverse, reverse, &t))
-	return FALSE;
-    return TRUE;
-}
-
-static void
-PictureTransformInitTranslate (PictTransformPtr t, xFixed tx, xFixed ty)
-{
-    memset (t, '\0', sizeof (PictTransform));
-    t->matrix[0][0] = F (1);
-    t->matrix[0][2] = tx;
-    t->matrix[1][1] = F (1);
-    t->matrix[1][2] = ty;
-    t->matrix[2][2] = F (1);
-}
-
-static Bool
-PictureTransformTranslate (PictTransformPtr forward,
-			   PictTransformPtr reverse,
-			   xFixed tx, xFixed ty)
-{
-    PictTransform   t;
-    PictureTransformInitTranslate (&t, tx, ty);
-    if (!PictureTransformMultiply (forward, &t, forward))
-	return FALSE;
-    
-    PictureTransformInitTranslate (&t, -tx, -ty);
-    if (!PictureTransformMultiply (reverse, reverse, &t))
-	return FALSE;
-    return TRUE;
-}
-
-static void
-PictureTransformBounds (BoxPtr b, PictTransformPtr matrix)
-{
-    PictVector	v[4];
-    int		i;
-    int		x1, y1, x2, y2;
-
-    v[0].vector[0] = F (b->x1);    v[0].vector[1] = F (b->y1);	v[0].vector[2] = F(1);
-    v[1].vector[0] = F (b->x2);    v[1].vector[1] = F (b->y1);	v[1].vector[2] = F(1);
-    v[2].vector[0] = F (b->x2);    v[2].vector[1] = F (b->y2);	v[2].vector[2] = F(1);
-    v[3].vector[0] = F (b->x1);    v[3].vector[1] = F (b->y2);	v[3].vector[2] = F(1);
-    for (i = 0; i < 4; i++)
-    {
-	PictureTransformPoint (matrix, &v[i]);
-	x1 = xFixedToInt (v[i].vector[0]);
-	y1 = xFixedToInt (v[i].vector[1]);
-	x2 = xFixedToInt (xFixedCeil (v[i].vector[0]));
-	y2 = xFixedToInt (xFixedCeil (v[i].vector[1]));
-	if (i == 0)
-	{
-	    b->x1 = x1; b->y1 = y1;
-	    b->x2 = x2; b->y2 = y2;
-	}
-	else
-	{
-	    if (x1 < b->x1) b->x1 = x1;
-	    if (y1 < b->y1) b->y1 = y1;
-	    if (x2 > b->x2) b->x2 = x2;
-	    if (y2 > b->y2) b->y2 = y2;
-	}
-    }
-}
-
-static Bool
-PictureTransformIsIdentity(PictTransform *t)
-{
-    return ((t->matrix[0][0] == t->matrix[1][1]) &&
-            (t->matrix[0][0] == t->matrix[2][2]) &&
-            (t->matrix[0][0] != 0) &&
-            (t->matrix[0][1] == 0) &&
-            (t->matrix[0][2] == 0) &&
-            (t->matrix[1][0] == 0) &&
-            (t->matrix[1][2] == 0) &&
-            (t->matrix[2][0] == 0) &&
-            (t->matrix[2][1] == 0));
-}
-
 #define toF(x)	((float) (x) / 65536.0f)
 
 static void
-PictureTransformErrorF (PictTransform *t)
-{
-    ErrorF ("{ { %f %f %f } { %f %f %f } { %f %f %f } }",
-	    toF(t->matrix[0][0]), toF(t->matrix[0][1]), toF(t->matrix[0][2]), 
-	    toF(t->matrix[1][0]), toF(t->matrix[1][1]), toF(t->matrix[1][2]), 
-	    toF(t->matrix[2][0]), toF(t->matrix[2][1]), toF(t->matrix[2][2]));
-}
-
-static Bool
-PictureTransformIsInverse (char *where, PictTransform *a, PictTransform *b)
-{
-    PictTransform   t;
-
-    PictureTransformMultiply (&t, a, b);
-    if (!PictureTransformIsIdentity (&t))
-    {
-	ErrorF ("%s: ", where);
-	PictureTransformErrorF (a);
-	ErrorF (" * ");
-	PictureTransformErrorF (b);
-	ErrorF (" = ");
-	PictureTransformErrorF (&t);
-	ErrorF ("\n");
-	return FALSE;
-    }
-    return TRUE;
-}
-
-static void
 xf86RotateCrtcRedisplay (xf86CrtcPtr crtc, RegionPtr region)
 {
     ScrnInfoPtr		scrn = crtc->scrn;
@@ -516,9 +320,8 @@ xf86CrtcRotate (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation)
     ScreenPtr		pScreen = screenInfo.screens[pScrn->scrnIndex];
     PictTransform	crtc_to_fb, fb_to_crtc;
     
-    PictureTransformIdentity (&crtc_to_fb);
-    PictureTransformIdentity (&fb_to_crtc);
-    PictureTransformIsInverse ("identity", &crtc_to_fb, &fb_to_crtc);
+    PictureTransformInitIdentity (&crtc_to_fb);
+    PictureTransformInitIdentity (&fb_to_crtc);
     if (rotation != RR_Rotate_0)
     {
 	xFixed	rot_cos, rot_sin, rot_dx, rot_dy;
@@ -548,10 +351,7 @@ xf86CrtcRotate (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation)
 	}
 	
 	PictureTransformRotate (&crtc_to_fb, &fb_to_crtc, rot_cos, rot_sin);
-	PictureTransformIsInverse ("rotate", &crtc_to_fb, &fb_to_crtc);
-
 	PictureTransformTranslate (&crtc_to_fb, &fb_to_crtc, rot_dx, rot_dy);
-	PictureTransformIsInverse ("rotate translate", &crtc_to_fb, &fb_to_crtc);
 
 	/* reflection */
 	scale_x = F (1);
@@ -576,19 +376,14 @@ xf86CrtcRotate (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation)
 	}
 	
 	PictureTransformScale (&crtc_to_fb, &fb_to_crtc, scale_x, scale_y);
-	PictureTransformIsInverse ("scale", &crtc_to_fb, &fb_to_crtc);
-
 	PictureTransformTranslate (&crtc_to_fb, &fb_to_crtc, scale_dx, scale_dy);
-	PictureTransformIsInverse ("scale translate", &crtc_to_fb, &fb_to_crtc);
-
     }
     
 #ifdef RANDR_12_INTERFACE
     {
 	PictTransform	user_forward, user_reverse;
-	if (RRCrtcGetTransform (crtc->randr_crtc, &user_forward, &user_reverse))
+	if (crtc->randr_crtc && RRCrtcGetTransform (crtc->randr_crtc, &user_forward, &user_reverse))
 	{
-	    PictureTransformIsInverse ("user", &user_forward, &user_reverse);
 	    PictureTransformMultiply (&crtc_to_fb, &user_forward, &crtc_to_fb);
 	    PictureTransformMultiply (&fb_to_crtc, &fb_to_crtc, &user_reverse);
 	}
@@ -614,7 +409,6 @@ xf86CrtcRotate (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation)
 	PixmapPtr shadow;
 
 	PictureTransformTranslate (&crtc_to_fb, &fb_to_crtc, F(crtc->x), F(crtc->y));
-	PictureTransformIsInverse ("offset", &crtc_to_fb, &fb_to_crtc);
 
 	/* 
 	 * these are the size of the shadow pixmap, which
diff --git a/randr/randrstr.h b/randr/randrstr.h
index 4692ddf..320e9f7 100644
--- a/randr/randrstr.h
+++ b/randr/randrstr.h
@@ -119,6 +119,12 @@ struct _rrCrtc {
     CARD16	    *gammaBlue;
     CARD16	    *gammaGreen;
     void	    *devPrivate;
+    PictTransform   client_pending_transform;
+    PictTransform   client_pending_inverse;
+    PictTransform   client_current_transform;
+    PictTransform   client_current_inverse;
+    PictTransform   transform;
+    PictTransform   inverse;
 };
 
 struct _rrOutput {
@@ -587,6 +593,23 @@ void
 RRCrtcGetScanoutSize(RRCrtcPtr crtc, int *width, int *height);
 
 /*
+ * Compute the complete transformation matrix including
+ * client-specified transform, rotation/reflection values and the crtc 
+ * offset.
+ *
+ * Return TRUE if the resulting transform is not a simple translation.
+ */
+Bool
+RRComputeTransform (RRModePtr		mode,
+		    Rotation		rotation,
+		    int			x,
+		    int			y,
+		    PictTransformPtr	client_transform,
+		    PictTransformPtr	client_inverse,
+		    PictTransformPtr    transform,
+		    PictTransformPtr    inverse);
+
+/*
  * Return crtc transform
  */
 Bool
@@ -601,11 +624,27 @@ void
 RRCrtcPostPendingTransform (RRCrtcPtr crtc);
 
 /*
+ * Check whether the pending and current transforms are the same
+ */
+Bool
+RRCrtcPendingTransform (RRCrtcPtr crtc);
+
+/*
  * Destroy a Crtc at shutdown
  */
 void
 RRCrtcDestroy (RRCrtcPtr crtc);
 
+
+/*
+ * Set the pending CRTC transformation
+ */
+
+int
+RRCrtcTransformSet (RRCrtcPtr		crtc,
+		    PictTransformPtr	transform,
+		    PictTransformPtr	inverse);
+
 /*
  * Initialize crtc type
  */
@@ -631,6 +670,12 @@ ProcRRGetCrtcGamma (ClientPtr client);
 int
 ProcRRSetCrtcGamma (ClientPtr client);
 
+int
+ProcRRSetCrtcTransform (ClientPtr client);
+
+int
+ProcRRGetCrtcTransform (ClientPtr client);
+
 /* rrdispatch.c */
 Bool
 RRClientKnowsRates (ClientPtr	pClient);
diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
index 38b3452..0cb8638 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -89,6 +89,12 @@ RRCrtcCreate (ScreenPtr pScreen, void *devPrivate)
     crtc->gammaRed = crtc->gammaBlue = crtc->gammaGreen = NULL;
     crtc->changed = FALSE;
     crtc->devPrivate = devPrivate;
+    PictureTransformInitIdentity (&crtc->client_pending_transform);
+    PictureTransformInitIdentity (&crtc->client_pending_inverse);
+    PictureTransformInitIdentity (&crtc->client_current_transform);
+    PictureTransformInitIdentity (&crtc->client_current_inverse);
+    PictureTransformInitIdentity (&crtc->transform);
+    PictureTransformInitIdentity (&crtc->inverse);
 
     if (!AddResource (crtc->id, RRCrtcType, (pointer) crtc))
 	return NULL;
@@ -290,7 +296,8 @@ RRCrtcSet (RRCrtcPtr    crtc,
 	crtc->rotation == rotation &&
 	crtc->numOutputs == numOutputs &&
 	!memcmp (crtc->outputs, outputs, numOutputs * sizeof (RROutputPtr)) &&
-	!RRCrtcPendingProperties (crtc))
+	!RRCrtcPendingProperties (crtc) &&
+	!RRCrtcPendingTransform (crtc))
     {
 	ret = TRUE;
     }
@@ -366,7 +373,9 @@ RRCrtcGetTransform (RRCrtcPtr crtc,
 		    PictTransformPtr crtc_to_fb,
 		    PictTransformPtr fb_to_crtc)
 {
-    return FALSE;
+    *crtc_to_fb = crtc->client_pending_transform;
+    *fb_to_crtc = crtc->client_pending_inverse;
+    return !PictureTransformIsIdentity (crtc_to_fb);
 }
 
 /*
@@ -375,6 +384,24 @@ RRCrtcGetTransform (RRCrtcPtr crtc,
 void
 RRCrtcPostPendingTransform (RRCrtcPtr crtc)
 {
+    crtc->client_current_transform = crtc->client_pending_transform;
+    crtc->client_current_inverse = crtc->client_pending_inverse;
+    RRComputeTransform (crtc->mode, crtc->rotation, crtc->x, crtc->y,
+			&crtc->client_current_transform,
+			&crtc->client_current_inverse,
+			&crtc->transform,
+			&crtc->inverse);
+}
+
+/*
+ * Check whether the pending and current transforms are the same
+ */
+Bool
+RRCrtcPendingTransform (RRCrtcPtr crtc)
+{
+    return memcmp (&crtc->client_current_transform,
+		   &crtc->client_pending_transform,
+		   sizeof (PictTransform)) != 0;
 }
 
 /*
@@ -513,6 +540,122 @@ RRCrtcGammaSetSize (RRCrtcPtr	crtc,
 }
 
 /*
+ * Set the pending CRTC transformation
+ */
+
+int
+RRCrtcTransformSet (RRCrtcPtr		crtc,
+		    PictTransformPtr	transform,
+		    PictTransformPtr	inverse)
+{
+    if (!PictureTransformIsInverse (transform, inverse))
+	return BadMatch;
+    crtc->client_pending_transform = *transform;
+    crtc->client_pending_inverse = *inverse;
+    return Success;
+}
+
+#define F(x)	IntToxFixed(x)
+
+/*
+ * Compute the complete transformation matrix including
+ * client-specified transform, rotation/reflection values and the crtc 
+ * offset.
+ *
+ * Return TRUE if the resulting transform is not a simple translation.
+ */
+Bool
+RRComputeTransform (RRModePtr		mode,
+		    Rotation		rotation,
+		    int			x,
+		    int			y,
+		    PictTransformPtr	client_transform,
+		    PictTransformPtr	client_inverse,
+		    PictTransformPtr    transform,
+		    PictTransformPtr    inverse)
+{
+    PictureTransformInitIdentity (transform);
+    PictureTransformInitIdentity (inverse);
+    if (rotation != RR_Rotate_0)
+    {
+	xFixed	rot_cos, rot_sin, rot_dx, rot_dy;
+	xFixed	scale_x, scale_y, scale_dx, scale_dy;
+	int	mode_w = mode->mode.width;
+	int	mode_h = mode->mode.height;
+	
+	/* rotation */
+	switch (rotation & 0xf) {
+	default:
+	case RR_Rotate_0:
+	    rot_cos = F ( 1);	    rot_sin = F ( 0);
+	    rot_dx  = F ( 0);	    rot_dy  = F ( 0);
+	    break;
+	case RR_Rotate_90:
+	    rot_cos = F ( 0);	    rot_sin = F ( 1);
+	    rot_dx =  F ( mode_h);  rot_dy  = F (0);
+	    break;
+	case RR_Rotate_180:
+	    rot_cos = F (-1);	    rot_sin = F ( 0);
+	    rot_dx  = F (mode_w);   rot_dy  = F ( mode_h);
+	    break;
+	case RR_Rotate_270:
+	    rot_cos = F ( 0);	    rot_sin = F (-1);
+	    rot_dx  = F ( 0);	    rot_dy  = F ( mode_w);
+	    break;
+	}
+	
+	PictureTransformRotate (inverse, transform, rot_cos, rot_sin);
+	PictureTransformTranslate (inverse, transform, rot_dx, rot_dy);
+
+	/* reflection */
+	scale_x = F (1);
+	scale_dx = 0;
+	scale_y = F (1);
+	scale_dy = 0;
+	if (rotation & RR_Reflect_X)
+	{
+	    scale_x = F(-1);
+	    if (rotation & (RR_Rotate_0|RR_Rotate_180))
+		scale_dx = F(mode_w);
+	    else
+		scale_dx = F(mode_h);
+	}
+	if (rotation & RR_Reflect_Y)
+	{
+	    scale_y = F(-1);
+	    if (rotation & (RR_Rotate_0|RR_Rotate_180))
+		scale_dy = F(mode_h);
+	    else
+		scale_dy = F(mode_w);
+	}
+	
+	PictureTransformScale (inverse, transform, scale_x, scale_y);
+	PictureTransformTranslate (inverse, transform, scale_dx, scale_dy);
+    }
+    
+#ifdef RANDR_12_INTERFACE
+    {
+        PictureTransformMultiply (inverse, client_inverse, inverse);
+        PictureTransformMultiply (transform, transform, client_transform);
+    }
+#endif
+    /*
+     * Compute the class of the resulting transform
+     */
+    if (PictureTransformIsIdentity (transform))
+    {
+	PictureTransformInitTranslate (inverse,   F (-x), F (-y));
+	PictureTransformInitTranslate (transform, F ( x), F ( y));
+	return FALSE;
+    }
+    else
+    {
+	PictureTransformTranslate (inverse, transform, x, y);
+	return TRUE;
+    }
+}
+
+/*
  * Initialize crtc type
  */
 Bool
@@ -977,3 +1120,59 @@ ProcRRSetCrtcGamma (ClientPtr client)
     return Success;
 }
 
+/* Version 1.3 additions */
+
+int
+ProcRRSetCrtcTransform (ClientPtr client)
+{
+    REQUEST(xRRSetCrtcTransformReq);
+    RRCrtcPtr		    crtc;
+    PictTransform	    transform, inverse;
+
+    REQUEST_SIZE_MATCH (xRRSetCrtcTransformReq);
+    crtc = LookupCrtc (client, stuff->crtc, DixWriteAccess);
+    if (!crtc)
+	return RRErrorBase + BadRRCrtc;
+
+    PictTransform_from_xRenderTransform (&transform, &stuff->transform);
+    PictTransform_from_xRenderTransform (&inverse, &stuff->inverse);
+
+    return RRCrtcTransformSet (crtc, &transform, &inverse);
+}
+
+
+#define CrtcTransformExtra	(SIZEOF(xRRGetCrtcTransformReply) - 32)
+				
+int
+ProcRRGetCrtcTransform (ClientPtr client)
+{
+    REQUEST(xRRGetCrtcTransformReq);
+    xRRGetCrtcTransformReply	reply;
+    RRCrtcPtr			crtc;
+    int				n;
+
+    REQUEST_SIZE_MATCH (xRRGetCrtcTransformReq);
+    crtc = LookupCrtc (client, stuff->crtc, DixWriteAccess);
+    if (!crtc)
+	return RRErrorBase + BadRRCrtc;
+
+    reply.type = X_Reply;
+    reply.sequenceNumber = client->sequence;
+    reply.length = CrtcTransformExtra >> 2;
+    
+    xRenderTransform_from_PictTransform (&reply.pendingTransform,
+					 &crtc->client_pending_transform);
+    xRenderTransform_from_PictTransform (&reply.pendingInverse,
+					 &crtc->client_pending_inverse);
+    xRenderTransform_from_PictTransform (&reply.currentTransform,
+					 &crtc->client_current_transform);
+    xRenderTransform_from_PictTransform (&reply.currentInverse,
+					 &crtc->client_current_inverse);
+    if (client->swapped) {
+	swaps (&reply.sequenceNumber, n);
+	swapl (&reply.length, n);
+	SwapLongs ((CARD32 *) &reply.pendingTransform, 40);
+    }
+    WriteToClient (client, sizeof (xRRGetCrtcTransformReply), (char *) &reply);
+    return client->noClientException;
+}
diff --git a/randr/rrdispatch.c b/randr/rrdispatch.c
index 72c68e3..20b471c 100644
--- a/randr/rrdispatch.c
+++ b/randr/rrdispatch.c
@@ -23,7 +23,7 @@
 #include "randrstr.h"
 
 #define SERVER_RANDR_MAJOR	1
-#define SERVER_RANDR_MINOR	2
+#define SERVER_RANDR_MINOR	3
 
 Bool
 RRClientKnowsRates (ClientPtr	pClient)
@@ -211,5 +211,8 @@ int (*ProcRandrVector[RRNumberRequests])(ClientPtr) = {
     ProcRRGetCrtcGammaSize,	/* 22 */
     ProcRRGetCrtcGamma,		/* 23 */
     ProcRRSetCrtcGamma,		/* 24 */
+/* V1.3 additions */
+    ProcRRSetCrtcTransform,	/* 25 */
+    ProcRRGetCrtcTransform,	/* 26 */
 };
 
diff --git a/randr/rrsdispatch.c b/randr/rrsdispatch.c
index 5037b9e..66a0e16 100644
--- a/randr/rrsdispatch.c
+++ b/randr/rrsdispatch.c
@@ -364,6 +364,26 @@ SProcRRSetCrtcGamma (ClientPtr client)
     return (*ProcRandrVector[stuff->randrReqType]) (client);
 }
 
+static int
+SProcRRSetCrtcTransform (ClientPtr client)
+{
+    REQUEST(xRRSetCrtcTransformReq);
+    
+    REQUEST_SIZE_MATCH(xRRSetCrtcTransformReq);
+    (void) stuff;
+    return BadImplementation; 
+}
+
+static int
+SProcRRGetCrtcTransform (ClientPtr client)
+{
+    REQUEST(xRRGetCrtcTransformReq);
+    
+    REQUEST_SIZE_MATCH(xRRGetCrtcTransformReq);
+    (void) stuff;
+    return BadImplementation; 
+}
+
 int (*SProcRandrVector[RRNumberRequests])(ClientPtr) = {
     SProcRRQueryVersion,	/* 0 */
 /* we skip 1 to make old clients fail pretty immediately */
@@ -394,5 +414,8 @@ int (*SProcRandrVector[RRNumberRequests])(ClientPtr) = {
     SProcRRGetCrtcGammaSize,	/* 22 */
     SProcRRGetCrtcGamma,	/* 23 */
     SProcRRSetCrtcGamma,	/* 24 */
+/* V1.3 additions */
+    SProcRRSetCrtcTransform,	/* 25 */
+    SProcRRGetCrtcTransform,	/* 26 */
 };
 
commit ff9d1cd843a9b0aba69a3d788b21d5f6af702590
Author: Keith Packard <keithp at keithp.com>
Date:   Thu Mar 13 21:30:18 2008 -0700

    Add funcs to convert between protocol and pixman matrices

diff --git a/render/matrix.c b/render/matrix.c
index bd584cb..a976304 100644
--- a/render/matrix.c
+++ b/render/matrix.c
@@ -222,7 +222,7 @@ PictureTransformTranslate (PictTransformPtr forward,
     PictureTransformInitTranslate (&t, tx, ty);
     if (!PictureTransformMultiply (forward, &t, forward))
 	return FALSE;
-    
+
     PictureTransformInitTranslate (&t, -tx, -ty);
     if (!PictureTransformMultiply (reverse, reverse, &t))
 	return FALSE;
@@ -349,3 +349,37 @@ PictureTransformIsInverse (PictTransform *a, PictTransform *b)
     return PictureTransformIsIdentity (&t);
 }
 
+_X_EXPORT void
+PictTransform_from_xRenderTransform (PictTransformPtr pict,
+				     xRenderTransform *render)
+{
+    pict->matrix[0][0] = render->matrix11;
+    pict->matrix[0][1] = render->matrix12;
+    pict->matrix[0][2] = render->matrix13;
+
+    pict->matrix[1][0] = render->matrix21;
+    pict->matrix[1][1] = render->matrix22;
+    pict->matrix[1][2] = render->matrix23;
+
+    pict->matrix[2][0] = render->matrix31;
+    pict->matrix[2][1] = render->matrix32;
+    pict->matrix[2][2] = render->matrix33;
+}
+
+void
+xRenderTransform_from_PictTransform (xRenderTransform *render,
+				     PictTransformPtr pict)
+{
+    render->matrix11 = pict->matrix[0][0];
+    render->matrix12 = pict->matrix[0][1];
+    render->matrix13 = pict->matrix[0][2];
+
+    render->matrix21 = pict->matrix[1][0];
+    render->matrix22 = pict->matrix[1][1];
+    render->matrix23 = pict->matrix[1][2];
+
+    render->matrix31 = pict->matrix[2][0];
+    render->matrix32 = pict->matrix[2][1];
+    render->matrix33 = pict->matrix[2][2];
+}
+
diff --git a/render/picturestr.h b/render/picturestr.h
index f7a0664..93d86bd 100644
--- a/render/picturestr.h
+++ b/render/picturestr.h
@@ -720,12 +720,17 @@ Bool
 PictureTransformIsScale(PictTransform *t);
 
 Bool
-PictureTransformIsScale(PictTransform *t);
-
-Bool
 PictureTransformIsTranslate (PictTransform *t);
 
 Bool
 PictureTransformIsInverse(PictTransform *t, PictTransform *i);
 
+void
+PictTransform_from_xRenderTransform (PictTransformPtr pict,
+				     xRenderTransform *render);
+
+void
+xRenderTransform_from_PictTransform (xRenderTransform *render,
+				     PictTransformPtr pict);
+
 #endif /* _PICTURESTR_H_ */
commit c2f254da694731ea573aa8bbc2707c083743f2d4
Author: Keith Packard <keithp at keithp.com>
Date:   Thu Mar 13 21:29:19 2008 -0700

    Randr now depends on Render for matrices

diff --git a/configure.ac b/configure.ac
index 6286a6c..79f9b25 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1199,7 +1199,7 @@ AC_MSG_RESULT([$XNEST])
 AM_CONDITIONAL(XNEST, [test "x$XNEST" = xyes])
 
 if test "x$XNEST" = xyes; then
-	XNEST_LIBS="$FB_LIB $FIXES_LIB $MI_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RENDER_LIB $RANDR_LIB $DAMAGE_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $DIX_LIB $OS_LIB $CONFIG_LIB"
+	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 $OS_LIB $CONFIG_LIB"
 	XNEST_SYS_LIBS="$XNESTMODULES_LIBS $GLX_SYS_LIBS"
 	AC_SUBST([XNEST_LIBS])
 	AC_SUBST([XNEST_SYS_LIBS])
commit f547650328287545a7a4d96df8d6a6c606dd95a9
Author: Keith Packard <keithp at keithp.com>
Date:   Thu Mar 13 14:50:13 2008 -0700

    Export a bunch of matrix operations from render.
    
    The render extension uses many matrix operations internally, this change
    exposes those functions to other parts of the server, drivers and
    extensions. The change is motivated by the 'transform' additions to the
    RandR extension but will likely be useful elsewhere.

diff --git a/render/Makefile.am b/render/Makefile.am
index e53c7c7..216c613 100644
--- a/render/Makefile.am
+++ b/render/Makefile.am
@@ -6,6 +6,7 @@ librender_la_SOURCES =	\
 	animcur.c	\
 	filter.c	\
 	glyph.c		\
+	matrix.c	\
 	miindex.c	\
 	mipict.c	\
 	mirect.c	\
diff --git a/render/matrix.c b/render/matrix.c
new file mode 100644
index 0000000..bd584cb
--- /dev/null
+++ b/render/matrix.c
@@ -0,0 +1,351 @@
+/*
+ * Copyright © 2007 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include "misc.h"
+#include "scrnintstr.h"
+#include "os.h"
+#include "regionstr.h"
+#include "validate.h"
+#include "windowstr.h"
+#include "input.h"
+#include "resource.h"
+#include "colormapst.h"
+#include "cursorstr.h"
+#include "dixstruct.h"
+#include "gcstruct.h"
+#include "servermd.h"
+#include "picturestr.h"
+
+#define F(x)	IntToxFixed(x)
+
+_X_EXPORT void
+PictureTransformInitIdentity (PictTransformPtr matrix)
+{
+    int	i;
+    memset (matrix, '\0', sizeof (PictTransform));
+    for (i = 0; i < 3; i++)
+	matrix->matrix[i][i] = F(1);
+}
+
+_X_EXPORT Bool
+PictureTransformPoint3d (PictTransformPtr transform,
+                         PictVectorPtr	vector)
+{
+    PictVector	    result;
+    int		    i, j;
+    xFixed_32_32    partial;
+    xFixed_48_16    v;
+
+    for (j = 0; j < 3; j++)
+    {
+	v = 0;
+	for (i = 0; i < 3; i++)
+	{
+	    partial = ((xFixed_48_16) transform->matrix[j][i] *
+		       (xFixed_48_16) vector->vector[i]);
+	    v += partial >> 16;
+	}
+	if (v > MAX_FIXED_48_16 || v < MIN_FIXED_48_16)
+	    return FALSE;
+	result.vector[j] = (xFixed) v;
+    }
+    if (!result.vector[2])
+	return FALSE;
+    *vector = result;
+    return TRUE;
+}
+
+
+_X_EXPORT Bool
+PictureTransformPoint (PictTransformPtr transform,
+		       PictVectorPtr	vector)
+{
+    PictVector	    result;
+    int		    i, j;
+    xFixed_32_32    partial;
+    xFixed_48_16    v;
+
+    for (j = 0; j < 3; j++)
+    {
+	v = 0;
+	for (i = 0; i < 3; i++)
+	{
+	    partial = ((xFixed_48_16) transform->matrix[j][i] * 
+		       (xFixed_48_16) vector->vector[i]);
+	    v += partial >> 16;
+	}
+	if (v > MAX_FIXED_48_16 || v < MIN_FIXED_48_16)
+	    return FALSE;
+	result.vector[j] = (xFixed) v;
+    }
+    if (!result.vector[2])
+	return FALSE;
+    for (j = 0; j < 2; j++)
+    {
+	partial = (xFixed_48_16) result.vector[j] << 16;
+	v = partial / result.vector[2];
+	if (v > MAX_FIXED_48_16 || v < MIN_FIXED_48_16)
+	    return FALSE;
+	vector->vector[j] = (xFixed) v;
+    }
+    vector->vector[2] = xFixed1;
+    return TRUE;
+}
+
+_X_EXPORT Bool
+PictureTransformMultiply (PictTransformPtr dst, PictTransformPtr l, PictTransformPtr r)
+{
+    PictTransform   d;
+    int		    dx, dy;
+    int		    o;
+
+    for (dy = 0; dy < 3; dy++)
+	for (dx = 0; dx < 3; dx++)
+	{
+	    xFixed_48_16    v;
+	    xFixed_32_32    partial;
+	    v = 0;
+	    for (o = 0; o < 3; o++)
+	    {
+		partial = (xFixed_32_32) l->matrix[dy][o] * (xFixed_32_32) r->matrix[o][dx];
+		v += partial >> 16;
+	    }
+	    if (v > MAX_FIXED_48_16 || v < MIN_FIXED_48_16)
+		return FALSE;
+	    d.matrix[dy][dx] = (xFixed) v;
+	}
+    *dst = d;
+    return TRUE;
+}
+
+_X_EXPORT void
+PictureTransformInitScale (PictTransformPtr t, xFixed sx, xFixed sy)
+{
+    memset (t, '\0', sizeof (PictTransform));
+    t->matrix[0][0] = sx;
+    t->matrix[1][1] = sy;
+    t->matrix[2][2] = F (1);
+}
+
+static xFixed
+fixed_inverse (xFixed x)
+{
+    return (xFixed) ((((xFixed_48_16) F(1)) * F(1)) / x);
+}
+
+_X_EXPORT Bool
+PictureTransformScale (PictTransformPtr forward,
+		       PictTransformPtr reverse,
+		       xFixed sx, xFixed sy)
+{
+    PictTransform   t;
+    
+    if (sx == 0 || sy == 0)
+	return FALSE;
+
+    PictureTransformInitScale (&t, sx, sy);
+    if (!PictureTransformMultiply (forward, &t, forward))
+	return FALSE;
+    PictureTransformInitScale (&t, fixed_inverse (sx), fixed_inverse (sy));
+    if (!PictureTransformMultiply (reverse, reverse, &t))
+	return FALSE;
+    return TRUE;
+}
+
+_X_EXPORT void
+PictureTransformInitRotate (PictTransformPtr t, xFixed c, xFixed s)
+{
+    memset (t, '\0', sizeof (PictTransform));
+    t->matrix[0][0] = c;
+    t->matrix[0][1] = -s;
+    t->matrix[1][0] = s;
+    t->matrix[1][1] = c;
+    t->matrix[2][2] = F (1);
+}
+
+_X_EXPORT Bool
+PictureTransformRotate (PictTransformPtr forward,
+			PictTransformPtr reverse,
+			xFixed c, xFixed s)
+{
+    PictTransform   t;
+    PictureTransformInitRotate (&t, c, s);
+    if (!PictureTransformMultiply (forward, &t, forward))
+	return FALSE;
+    
+    PictureTransformInitRotate (&t, c, -s);
+    if (!PictureTransformMultiply (reverse, reverse, &t))
+	return FALSE;
+    return TRUE;
+}
+
+_X_EXPORT void
+PictureTransformInitTranslate (PictTransformPtr t, xFixed tx, xFixed ty)
+{
+    memset (t, '\0', sizeof (PictTransform));
+    t->matrix[0][0] = F (1);
+    t->matrix[0][2] = tx;
+    t->matrix[1][1] = F (1);
+    t->matrix[1][2] = ty;
+    t->matrix[2][2] = F (1);
+}
+
+_X_EXPORT Bool
+PictureTransformTranslate (PictTransformPtr forward,
+			   PictTransformPtr reverse,
+			   xFixed tx, xFixed ty)
+{
+    PictTransform   t;
+    PictureTransformInitTranslate (&t, tx, ty);
+    if (!PictureTransformMultiply (forward, &t, forward))
+	return FALSE;
+    
+    PictureTransformInitTranslate (&t, -tx, -ty);
+    if (!PictureTransformMultiply (reverse, reverse, &t))
+	return FALSE;
+    return TRUE;
+}
+
+_X_EXPORT void
+PictureTransformBounds (BoxPtr b, PictTransformPtr matrix)
+{
+    PictVector	v[4];
+    int		i;
+    int		x1, y1, x2, y2;
+
+    v[0].vector[0] = F (b->x1);    v[0].vector[1] = F (b->y1);	v[0].vector[2] = F(1);
+    v[1].vector[0] = F (b->x2);    v[1].vector[1] = F (b->y1);	v[1].vector[2] = F(1);
+    v[2].vector[0] = F (b->x2);    v[2].vector[1] = F (b->y2);	v[2].vector[2] = F(1);
+    v[3].vector[0] = F (b->x1);    v[3].vector[1] = F (b->y2);	v[3].vector[2] = F(1);
+    for (i = 0; i < 4; i++)
+    {
+	PictureTransformPoint (matrix, &v[i]);
+	x1 = xFixedToInt (v[i].vector[0]);
+	y1 = xFixedToInt (v[i].vector[1]);
+	x2 = xFixedToInt (xFixedCeil (v[i].vector[0]));
+	y2 = xFixedToInt (xFixedCeil (v[i].vector[1]));
+	if (i == 0)
+	{
+	    b->x1 = x1; b->y1 = y1;
+	    b->x2 = x2; b->y2 = y2;
+	}
+	else
+	{
+	    if (x1 < b->x1) b->x1 = x1;
+	    if (y1 < b->y1) b->y1 = y1;
+	    if (x2 > b->x2) b->x2 = x2;
+	    if (y2 > b->y2) b->y2 = y2;
+	}
+    }
+}
+
+static Bool
+within_epsilon (xFixed a, xFixed b, xFixed epsilon)
+{
+    xFixed  t = a - b;
+    if (t < 0) t = -t;
+    return t <= epsilon;
+}
+
+#define epsilon	(xFixed) (2)
+
+#define IsSame(a,b) (within_epsilon (a, b, epsilon))
+#define IsZero(a)   (within_epsilon (a, 0, epsilon))
+#define IsOne(a)    (within_epsilon (a, F(1), epsilon))
+#define IsUnit(a)   (within_epsilon (a, F( 1), epsilon) || \
+		     within_epsilon (a, F(-1), epsilon) || \
+		     IsZero (a))
+#define IsInt(a)    (IsZero (xFixedFrac(a)))
+		     
+_X_EXPORT Bool
+PictureTransformIsIdentity(PictTransform *t)
+{
+    return (IsUnit (t->matrix[0][0]) &&
+	    IsUnit (t->matrix[0][1]) &&
+            IsInt  (t->matrix[0][2]) &&
+	    IsUnit (t->matrix[1][0]) &&
+	    IsUnit (t->matrix[1][1]) &&
+            IsInt  (t->matrix[1][2]) &&
+            IsZero (t->matrix[2][0]) &&
+            IsZero (t->matrix[2][1]) &&
+	    IsOne  (t->matrix[2][2]));
+}
+
+_X_EXPORT Bool
+PictureTransformIsUnit(PictTransform *t)
+{
+    return (IsSame (t->matrix[0][0],t->matrix[1][1]) &&
+	    IsSame (t->matrix[0][0], t->matrix[2][2]) &&
+            !IsZero (t->matrix[0][0]) &&
+	    IsZero (t->matrix[0][1]) &&
+            IsZero (t->matrix[0][2]) &&
+            IsZero (t->matrix[1][0]) &&
+            IsZero (t->matrix[1][2]) &&
+            IsZero (t->matrix[2][0]) &&
+            IsZero (t->matrix[2][1]));
+}
+
+_X_EXPORT Bool
+PictureTransformIsScale(PictTransform *t)
+{
+    return (!IsZero (t->matrix[0][0]) &&
+	     IsZero (t->matrix[0][1]) &&
+	     IsZero (t->matrix[0][2]) &&
+	    
+	     IsZero (t->matrix[1][0]) &&
+	    !IsZero (t->matrix[1][1]) &&
+	     IsZero (t->matrix[1][2]) &&
+	    
+	     IsZero (t->matrix[2][0]) &&
+	     IsZero (t->matrix[2][1]) &&
+	     IsOne (t->matrix[2][2]));
+}
+
+_X_EXPORT Bool
+PictureTransformIsTranslate(PictTransform *t)
+{
+    return ( IsOne  (t->matrix[0][0]) &&
+	     IsZero (t->matrix[0][1]) &&
+	     IsInt  (t->matrix[0][2]) &&
+	    
+	     IsZero (t->matrix[1][0]) &&
+	     IsOne  (t->matrix[1][1]) &&
+	     IsInt  (t->matrix[1][2]) &&
+	    
+	     IsZero (t->matrix[2][0]) &&
+	     IsZero (t->matrix[2][1]) &&
+	     IsOne  (t->matrix[2][2]));
+}
+
+_X_EXPORT Bool
+PictureTransformIsInverse (PictTransform *a, PictTransform *b)
+{
+    PictTransform   t;
+
+    PictureTransformMultiply (&t, a, b);
+    return PictureTransformIsIdentity (&t);
+}
+
diff --git a/render/picture.c b/render/picture.c
index fc2bf43..d672ebc 100644
--- a/render/picture.c
+++ b/render/picture.c
@@ -1780,67 +1780,3 @@ AddTraps (PicturePtr	pPicture,
     (*ps->AddTraps) (pPicture, xOff, yOff, ntrap, traps);
 }
 
-_X_EXPORT Bool
-PictureTransformPoint3d (PictTransformPtr transform,
-                         PictVectorPtr	vector)
-{
-    PictVector	    result;
-    int		    i, j;
-    xFixed_32_32    partial;
-    xFixed_48_16    v;
-
-    for (j = 0; j < 3; j++)
-    {
-	v = 0;
-	for (i = 0; i < 3; i++)
-	{
-	    partial = ((xFixed_48_16) transform->matrix[j][i] *
-		       (xFixed_48_16) vector->vector[i]);
-	    v += partial >> 16;
-	}
-	if (v > MAX_FIXED_48_16 || v < MIN_FIXED_48_16)
-	    return FALSE;
-	result.vector[j] = (xFixed) v;
-    }
-    if (!result.vector[2])
-	return FALSE;
-    *vector = result;
-    return TRUE;
-}
-
-
-_X_EXPORT Bool
-PictureTransformPoint (PictTransformPtr transform,
-		       PictVectorPtr	vector)
-{
-    PictVector	    result;
-    int		    i, j;
-    xFixed_32_32    partial;
-    xFixed_48_16    v;
-
-    for (j = 0; j < 3; j++)
-    {
-	v = 0;
-	for (i = 0; i < 3; i++)
-	{
-	    partial = ((xFixed_48_16) transform->matrix[j][i] * 
-		       (xFixed_48_16) vector->vector[i]);
-	    v += partial >> 16;
-	}
-	if (v > MAX_FIXED_48_16 || v < MIN_FIXED_48_16)
-	    return FALSE;
-	result.vector[j] = (xFixed) v;
-    }
-    if (!result.vector[2])
-	return FALSE;
-    for (j = 0; j < 2; j++)
-    {
-	partial = (xFixed_48_16) result.vector[j] << 16;
-	v = partial / result.vector[2];
-	if (v > MAX_FIXED_48_16 || v < MIN_FIXED_48_16)
-	    return FALSE;
-	vector->vector[j] = (xFixed) v;
-    }
-    vector->vector[2] = xFixed1;
-    return TRUE;
-}
diff --git a/render/picturestr.h b/render/picturestr.h
index 1ce16be..f7a0664 100644
--- a/render/picturestr.h
+++ b/render/picturestr.h
@@ -602,14 +602,6 @@ CompositeTriFan (CARD8		op,
 		 int		npoints,
 		 xPointFixed	*points);
 
-Bool
-PictureTransformPoint (PictTransformPtr transform,
-		       PictVectorPtr	vector);
-
-Bool
-PictureTransformPoint3d (PictTransformPtr transform,
-                         PictVectorPtr	vector);
-
 CARD32
 PictureGradientColor (PictGradientStopPtr stop1,
 		      PictGradientStopPtr stop2,
@@ -673,4 +665,67 @@ void PanoramiXRenderInit (void);
 void PanoramiXRenderReset (void);
 #endif
 
+/*
+ * matrix.c
+ */
+void
+PictureTransformInitIdentity (PictTransformPtr matrix);
+
+Bool
+PictureTransformPoint3d (PictTransformPtr transform,
+                         PictVectorPtr	vector);
+
+Bool
+PictureTransformPoint (PictTransformPtr transform,
+		       PictVectorPtr	vector);
+
+Bool
+PictureTransformMultiply (PictTransformPtr dst,
+			  PictTransformPtr l, PictTransformPtr r);
+
+void
+PictureTransformInitScale (PictTransformPtr t, xFixed sx, xFixed sy);
+
+Bool
+PictureTransformScale (PictTransformPtr forward,
+		       PictTransformPtr reverse,
+		       xFixed sx, xFixed sy);
+
+void
+PictureTransformInitRotate (PictTransformPtr t, xFixed c, xFixed s);
+
+Bool
+PictureTransformRotate (PictTransformPtr forward,
+			PictTransformPtr reverse,
+			xFixed c, xFixed s);
+
+void
+PictureTransformInitTranslate (PictTransformPtr t, xFixed tx, xFixed ty);
+
+Bool
+PictureTransformTranslate (PictTransformPtr forward,
+			   PictTransformPtr reverse,
+			   xFixed tx, xFixed ty);
+
+void
+PictureTransformBounds (BoxPtr b, PictTransformPtr matrix);
+
+Bool
+PictureTransformIsIdentity(PictTransform *t);
+
+Bool
+PictureTransformIsUnit(PictTransform *t);
+
+Bool
+PictureTransformIsScale(PictTransform *t);
+
+Bool
+PictureTransformIsScale(PictTransform *t);
+
+Bool
+PictureTransformIsTranslate (PictTransform *t);
+
+Bool
+PictureTransformIsInverse(PictTransform *t, PictTransform *i);
+
 #endif /* _PICTURESTR_H_ */
commit e063162e80e51ed4368874b3af7ba690ea280d9e
Author: Keith Packard <keithp at keithp.com>
Date:   Thu Mar 13 14:26:01 2008 -0700

    Add projective transforms to RandR DIX/DDX API.
    
    New RRCrtcGetTransform function in DIX that DDX can use to get the pending
    transform. The DDX code should be complete; the DIX code is just a stub at
    this point.

diff --git a/hw/xfree86/modes/xf86Rotate.c b/hw/xfree86/modes/xf86Rotate.c
index 12bd754..5ab2bf8 100644
--- a/hw/xfree86/modes/xf86Rotate.c
+++ b/hw/xfree86/modes/xf86Rotate.c
@@ -261,7 +261,7 @@ PictureTransformIsInverse (char *where, PictTransform *a, PictTransform *b)
 	ErrorF (" * ");
 	PictureTransformErrorF (b);
 	ErrorF (" = ");
-	PictureTransformErrorF (a);
+	PictureTransformErrorF (&t);
 	ErrorF ("\n");
 	return FALSE;
     }
@@ -331,10 +331,11 @@ xf86CrtcDamageShadow (xf86CrtcPtr crtc)
     RegionRec   damage_region;
     ScreenPtr	pScreen = pScrn->pScreen;
 
-    damage_box.x1 = crtc->x;
-    damage_box.x2 = crtc->x + xf86ModeWidth (&crtc->mode, crtc->rotation);
-    damage_box.y1 = crtc->y;
-    damage_box.y2 = crtc->y + xf86ModeHeight (&crtc->mode, crtc->rotation);
+    damage_box.x1 = 0;
+    damage_box.x2 = crtc->mode.HDisplay;
+    damage_box.y1 = 0;
+    damage_box.y2 = crtc->mode.VDisplay;
+    PictureTransformBounds (&damage_box, &crtc->crtc_to_framebuffer);
     REGION_INIT (pScreen, &damage_region, &damage_box, 1);
     DamageRegionAppend(&(*pScreen->GetScreenPixmap)(pScreen)->drawable,
 			&damage_region);
@@ -401,7 +402,7 @@ xf86RotateRedisplay(ScreenPtr pScreen)
 	{
 	    xf86CrtcPtr	    crtc = xf86_config->crtc[c];
 
-	    if (crtc->rotation != RR_Rotate_0 && crtc->enabled)
+	    if (crtc->transform_in_use && crtc->enabled)
 	    {
 		RegionRec   crtc_damage;
 
@@ -582,6 +583,17 @@ xf86CrtcRotate (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation)
 
     }
     
+#ifdef RANDR_12_INTERFACE
+    {
+	PictTransform	user_forward, user_reverse;
+	if (RRCrtcGetTransform (crtc->randr_crtc, &user_forward, &user_reverse))
+	{
+	    PictureTransformIsInverse ("user", &user_forward, &user_reverse);
+	    PictureTransformMultiply (&crtc_to_fb, &user_forward, &crtc_to_fb);
+	    PictureTransformMultiply (&fb_to_crtc, &fb_to_crtc, &user_reverse);
+	}
+    }
+#endif
     /*
      * If the untranslated transformation is the identity,
      * disable the shadow buffer
diff --git a/randr/randrstr.h b/randr/randrstr.h
index bd7c7c5..4692ddf 100644
--- a/randr/randrstr.h
+++ b/randr/randrstr.h
@@ -587,6 +587,20 @@ void
 RRCrtcGetScanoutSize(RRCrtcPtr crtc, int *width, int *height);
 
 /*
+ * Return crtc transform
+ */
+Bool
+RRCrtcGetTransform (RRCrtcPtr crtc,
+		    PictTransformPtr crtc_to_fb,
+		    PictTransformPtr fb_to_crtc);
+
+/*
+ * Mark the pending transform as current
+ */
+void
+RRCrtcPostPendingTransform (RRCrtcPtr crtc);
+
+/*
  * Destroy a Crtc at shutdown
  */
 void
diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
index ec65a04..38b3452 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -359,6 +359,25 @@ RRCrtcSet (RRCrtcPtr    crtc,
 }
 
 /*
+ * Return crtc transform
+ */
+Bool
+RRCrtcGetTransform (RRCrtcPtr crtc,
+		    PictTransformPtr crtc_to_fb,
+		    PictTransformPtr fb_to_crtc)
+{
+    return FALSE;
+}
+
+/*
+ * Mark the pending transform as current
+ */
+void
+RRCrtcPostPendingTransform (RRCrtcPtr crtc)
+{
+}
+
+/*
  * Destroy a Crtc at shutdown
  */
 void
commit 9c7ac47b871a71e42d2f6933749ca462f1a65b40
Author: Keith Packard <keithp at keithp.com>
Date:   Tue Nov 4 00:10:08 2008 -0800

    Notify DRI when crtc regions change
    
    Drivers that care about crtc positions on the screen to ensure that vblank
    works correctly need to be notified when crtcs are changed.
    
    Provide a hook in the mode setting code that is invoked whenever any
    configuration is done to the screen.
    
    Use this new hook in the DRI code so that DRI clients are notified and
    receive updated information.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/hw/xfree86/dri/Makefile.am b/hw/xfree86/dri/Makefile.am
index e17cea7..3ec30be 100644
--- a/hw/xfree86/dri/Makefile.am
+++ b/hw/xfree86/dri/Makefile.am
@@ -1,6 +1,11 @@
 libdri_la_LTLIBRARIES = libdri.la
 libdri_la_CFLAGS = -I$(top_srcdir)/hw/xfree86/common \
                    -I$(top_srcdir)/hw/xfree86/os-support \
+                   -I$(top_srcdir)/hw/xfree86/modes \
+                   -I$(top_srcdir)/hw/xfree86/ddc \
+                   -I$(top_srcdir)/hw/xfree86/i2c \
+                   -I$(top_srcdir)/hw/xfree86/parser \
+                   -I$(top_srcdir)/hw/xfree86/ramdac \
                    -I$(top_srcdir)/hw/xfree86/os-support/bus \
                    -I$(top_srcdir)/glx \
                    -I$(top_srcdir)/GL/include \
diff --git a/hw/xfree86/dri/dri.c b/hw/xfree86/dri/dri.c
index 3713659..1a3e091 100644
--- a/hw/xfree86/dri/dri.c
+++ b/hw/xfree86/dri/dri.c
@@ -302,6 +302,18 @@ DRIOpenDRMMaster(ScrnInfoPtr pScrn,
     return FALSE;
 }
 
+static void
+DRIClipNotifyAllDrawables(ScreenPtr pScreen);
+
+static void
+dri_crtc_notify(ScreenPtr pScreen)
+{
+    DRIScreenPrivPtr  pDRIPriv = DRI_SCREEN_PRIV(pScreen);
+    DRIClipNotifyAllDrawables(pScreen);
+    xf86_unwrap_crtc_notify(pScreen, pDRIPriv->xf86_crtc_notify);
+    xf86_crtc_notify(pScreen);
+    pDRIPriv->xf86_crtc_notify = xf86_wrap_crtc_notify(pScreen, dri_crtc_notify);
+}
 
 Bool
 DRIScreenInit(ScreenPtr pScreen, DRIInfoPtr pDRIInfo, int *pDRMFD)
@@ -605,6 +617,9 @@ DRIFinishScreenInit(ScreenPtr pScreen)
     pDRIPriv->DestroyWindow             = pScreen->DestroyWindow;
     pScreen->DestroyWindow              = DRIDestroyWindow;
 
+    pDRIPriv->xf86_crtc_notify = xf86_wrap_crtc_notify(pScreen,
+						       dri_crtc_notify);
+						       
     if (pDRIInfo->wrap.CopyWindow) {
 	pDRIPriv->wrap.CopyWindow       = pScreen->CopyWindow;
 	pScreen->CopyWindow             = pDRIInfo->wrap.CopyWindow;
@@ -658,6 +673,9 @@ DRICloseScreen(ScreenPtr pScreen)
 		pScreen->DestroyWindow          = pDRIPriv->DestroyWindow;
 		pDRIPriv->DestroyWindow         = NULL;
 	    }
+
+	    xf86_unwrap_crtc_notify(pScreen, pDRIPriv->xf86_crtc_notify);
+
 	    if (pDRIInfo->wrap.CopyWindow) {
 		pScreen->CopyWindow             = pDRIPriv->wrap.CopyWindow;
 		pDRIPriv->wrap.CopyWindow       = NULL;
@@ -671,6 +689,7 @@ DRICloseScreen(ScreenPtr pScreen)
 		pScrn->AdjustFrame              = pDRIPriv->wrap.AdjustFrame;
 		pDRIPriv->wrap.AdjustFrame      = NULL;
 	    }
+	    
 	    pDRIPriv->wrapped = FALSE;
 	}
 
diff --git a/hw/xfree86/dri/dristruct.h b/hw/xfree86/dri/dristruct.h
index ae970d8..fc929c2 100644
--- a/hw/xfree86/dri/dristruct.h
+++ b/hw/xfree86/dri/dristruct.h
@@ -35,6 +35,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define DRI_STRUCT_H
 
 #include "xf86drm.h"
+#include "xf86Crtc.h"
 
 
 #define DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin) ((DRIDrawablePrivPtr) \
@@ -106,6 +107,7 @@ typedef struct _DRIScreenPrivRec
     XF86DRILSAREAPtr    pLSAREA;      /* Mapped pointer to SAREA containing lock */
     int*                pLockRefCount;
     int*                pLockingContext;
+    xf86_crtc_notify_proc_ptr	xf86_crtc_notify;
 } DRIScreenPrivRec, *DRIScreenPrivPtr;
 
 
diff --git a/hw/xfree86/loader/xf86sym.c b/hw/xfree86/loader/xf86sym.c
index f2b7e93..2346356 100644
--- a/hw/xfree86/loader/xf86sym.c
+++ b/hw/xfree86/loader/xf86sym.c
@@ -914,6 +914,9 @@ _X_HIDDEN void *xfree86LookupTab[] = {
     SYMFUNC(xf86_hide_cursors)
     SYMFUNC(xf86_cursors_fini)
     SYMFUNC(xf86_crtc_clip_video_helper)
+    SYMFUNC(xf86_wrap_crtc_notify)
+    SYMFUNC(xf86_unwrap_crtc_notify)
+    SYMFUNC(xf86_crtc_notify)
 
     SYMFUNC(xf86DoEDID_DDC1)
     SYMFUNC(xf86DoEDID_DDC2)
diff --git a/hw/xfree86/modes/xf86Crtc.c b/hw/xfree86/modes/xf86Crtc.c
index 251b800..a71f5c7 100644
--- a/hw/xfree86/modes/xf86Crtc.c
+++ b/hw/xfree86/modes/xf86Crtc.c
@@ -2609,6 +2609,8 @@ xf86DisableUnusedFunctions(ScrnInfoPtr pScrn)
 	    memset(&crtc->mode, 0, sizeof(crtc->mode));
 	}
     }
+    if (pScrn->pScreen)
+	xf86_crtc_notify(pScrn->pScreen);
 }
 
 #ifdef RANDR_12_INTERFACE
@@ -2863,3 +2865,34 @@ xf86_crtc_clip_video_helper(ScrnInfoPtr pScrn,
 
     return ret;
 }
+
+xf86_crtc_notify_proc_ptr
+xf86_wrap_crtc_notify (ScreenPtr screen, xf86_crtc_notify_proc_ptr new)
+{
+    ScrnInfoPtr		scrn = xf86Screens[screen->myNum];
+    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(scrn);
+    xf86_crtc_notify_proc_ptr	old;
+    
+    old = config->xf86_crtc_notify;
+    config->xf86_crtc_notify = new;
+    return old;
+}
+
+void
+xf86_unwrap_crtc_notify(ScreenPtr screen, xf86_crtc_notify_proc_ptr old)
+{
+    ScrnInfoPtr		scrn = xf86Screens[screen->myNum];
+    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(scrn);
+
+    config->xf86_crtc_notify = old;
+}
+
+void
+xf86_crtc_notify(ScreenPtr screen)
+{
+    ScrnInfoPtr		scrn = xf86Screens[screen->myNum];
+    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(scrn);
+    
+    if (config->xf86_crtc_notify)
+	config->xf86_crtc_notify(screen);
+}
diff --git a/hw/xfree86/modes/xf86Crtc.h b/hw/xfree86/modes/xf86Crtc.h
index 83b1f13..ef8589e 100644
--- a/hw/xfree86/modes/xf86Crtc.h
+++ b/hw/xfree86/modes/xf86Crtc.h
@@ -569,6 +569,8 @@ typedef struct _xf86CrtcConfigFuncs {
 	      int		height);
 } xf86CrtcConfigFuncsRec, *xf86CrtcConfigFuncsPtr;
 
+typedef void (*xf86_crtc_notify_proc_ptr) (ScreenPtr pScreen);
+
 typedef struct _xf86CrtcConfig {
     int			num_output;
     xf86OutputPtr	*output;
@@ -621,6 +623,9 @@ typedef struct _xf86CrtcConfig {
     /* wrap screen BlockHandler for rotation */
     ScreenBlockHandlerProcPtr	BlockHandler;
 
+    /* callback when crtc configuration changes */
+    xf86_crtc_notify_proc_ptr  xf86_crtc_notify;
+
 } xf86CrtcConfigRec, *xf86CrtcConfigPtr;
 
 extern int xf86CrtcConfigPrivateIndex;
@@ -838,4 +843,13 @@ xf86_crtc_clip_video_helper(ScrnInfoPtr pScrn,
 			    INT32	width,
 			    INT32	height);
     
+xf86_crtc_notify_proc_ptr
+xf86_wrap_crtc_notify (ScreenPtr pScreen, xf86_crtc_notify_proc_ptr new);
+
+void
+xf86_unwrap_crtc_notify(ScreenPtr pScreen, xf86_crtc_notify_proc_ptr old);
+
+void
+xf86_crtc_notify(ScreenPtr pScreen);
+
 #endif /* _XF86CRTC_H_ */


More information about the xorg-commit mailing list