xserver: Branch 'master' - 13 commits

Keith Packard keithp at kemper.freedesktop.org
Mon Dec 6 20:40:28 PST 2010


 Xext/sync.c                    |    4 
 configure.ac                   |    2 
 hw/xfree86/common/xf86Helper.c |    6 
 hw/xfree86/modes/xf86Crtc.c    |  139 ++++++----
 hw/xfree86/modes/xf86Crtc.h    |  119 ++++++++
 hw/xfree86/modes/xf86Cursors.c |    4 
 hw/xfree86/modes/xf86RandR12.c |  387 ++++++++++++++++++++++------
 hw/xfree86/modes/xf86Rotate.c  |   44 +++
 include/protocol-versions.h    |    2 
 randr/Makefile.am              |    6 
 randr/mirrcrtc.c               |  174 ++++++++++++
 randr/randr.c                  |   15 +
 randr/randrstr.h               |  207 +++++++++++++--
 randr/rrcrtc.c                 |  562 ++++++++++++++++++++++++++++++++++++-----
 randr/rrdispatch.c             |    6 
 randr/rrinfo.c                 |    2 
 randr/rrpixmap.c               |  154 +++++++++++
 randr/rrscreen.c               |   32 ++
 randr/rrsdispatch.c            |  132 +++++++++
 randr/rrsprite.c               |  104 +++++++
 randr/rrtransform.c            |   64 ++++
 randr/rrtransform.h            |   15 -
 22 files changed, 1943 insertions(+), 237 deletions(-)

New commits:
commit 435361bd73b9fc733f093d81af6b839953e35176
Author: Keith Packard <keithp at keithp.com>
Date:   Mon Dec 6 20:38:14 2010 -0800

    sync: syncObject may be None in SyncInitTrigger
    
    And often is, especially when called from ProcSyncCreateAlarm.
    Crashing in this case seems unwise.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/Xext/sync.c b/Xext/sync.c
index ce00755..ab8f20d 100644
--- a/Xext/sync.c
+++ b/Xext/sync.c
@@ -296,7 +296,7 @@ SyncInitTrigger(ClientPtr client, SyncTrigger *pTrigger, XID syncObject,
 
     /* if system counter, ask it what the current value is */
 
-    if (SYNC_COUNTER == pSync->type)
+    if (pSync && SYNC_COUNTER == pSync->type)
     {
 	pCounter = (SyncCounter *)pSync;
 
@@ -320,7 +320,7 @@ SyncInitTrigger(ClientPtr client, SyncTrigger *pTrigger, XID syncObject,
     if (changes & XSyncCATestType)
     {
 
-	if (SYNC_FENCE == pSync->type)
+	if (pSync && SYNC_FENCE == pSync->type)
 	{
 	    pTrigger->CheckTrigger = SyncCheckTriggerFence;
 	}
commit 0d01b66df9081ef48843b3bad81c56bb2cd1ae69
Author: Keith Packard <keithp at keithp.com>
Date:   Sun Dec 5 23:35:28 2010 -0800

    randr: handle RRSetCrtcConfigs request with zero configs
    
    Need to actually return a reply in this case.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Aaron Plattner <aplattner at nvidia.com>

diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
index 0fc8188..5fe6900 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -1750,9 +1750,6 @@ ProcRRSetCrtcConfigs (ClientPtr client)
     screen_config.mm_width = stuff->widthInMillimeters;
     screen_config.mm_height = stuff->heightInMillimeters;
 
-    if (num_configs == 0)
-	return Success;
-
     output_ids = (RROutput *) (x_configs + num_configs);
 
     /*
@@ -1760,7 +1757,7 @@ ProcRRSetCrtcConfigs (ClientPtr client)
      * server crtc configurations
      */
     configs = calloc(num_configs, sizeof (RRCrtcConfigRec));
-    if (!configs)
+    if (num_configs > 0 && configs == NULL)
 	return BadAlloc;
     for (i = 0; i < num_configs; i++) {
 	rc = RRConvertCrtcConfig(client, screen, &screen_config,
@@ -1773,7 +1770,8 @@ ProcRRSetCrtcConfigs (ClientPtr client)
 	output_ids += x_configs[i].nOutput;
     }
 
-    if (!RRSetCrtcConfigs (screen, &screen_config, configs, num_configs))
+    if (num_configs &&
+	!RRSetCrtcConfigs (screen, &screen_config, configs, num_configs))
     {
 	rep.status = RRSetConfigFailed;
 	goto sendReply;
commit b0f4bd61f0caf80f3be9a176f1f7a707bc6628d8
Author: Keith Packard <keithp at keithp.com>
Date:   Sun Dec 5 21:53:25 2010 -0800

    ProcRRSetCrtcConfigs uses 'configs' without being initialized
    
    If the client sends invalid data for this request, the server
    will jump to 'sendReply' and call RRFreeCrtcConfigs, passing it the
    uninitialized 'configs' and 'num_configs' values.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Aaron Plattner <aplattner at nvidia.com>

diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
index 97aa3d7..0fc8188 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -1682,9 +1682,9 @@ ProcRRSetCrtcConfigs (ClientPtr client)
     rrScrPrivPtr	    scr_priv;
     xRRCrtcConfig	    *x_configs;
     RRScreenConfigRec	    screen_config;
-    RRCrtcConfigPtr	    configs;
+    RRCrtcConfigPtr	    configs = NULL;
     RROutput		    *output_ids;
-    int			    num_configs;
+    int			    num_configs = 0;
     int			    rc, i;
     int			    extra_len;
     int			    num_output_ids;
commit 752c368421c1c824752cf467fba9318d75d2ca2c
Author: Keith Packard <keithp at keithp.com>
Date:   Sun Dec 5 20:57:47 2010 -0800

    Separate out screen size and screen pixmap sizes in RRScreenSizeSet
    
    This provides for separate sizes for the screen scanout and rendering
    buffer and the application-visible screen size.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Aaron Plattner <aplattner at nvidia.com>

diff --git a/hw/xfree86/common/xf86Helper.c b/hw/xfree86/common/xf86Helper.c
index ea0acbf..01f9864 100644
--- a/hw/xfree86/common/xf86Helper.c
+++ b/hw/xfree86/common/xf86Helper.c
@@ -1038,7 +1038,12 @@ xf86SetRootClip (ScreenPtr pScreen, Bool enable)
 	RegionInit(&pWin->winSize, &box, 1);
 	RegionInit(&pWin->borderSize, &box, 1);
 	if (WasViewable)
+	{
+	    PixmapPtr	pPixmap = (*pScreen->GetScreenPixmap) (pScreen);
+	    box.x2 = pPixmap->drawable.width;
+	    box.y2 = pPixmap->drawable.height;
 	    RegionReset(&pWin->borderClip, &box);
+	}
 	pWin->drawable.width = pScreen->width;
 	pWin->drawable.height = pScreen->height;
         RegionBreak(&pWin->clipList);
@@ -1116,7 +1121,6 @@ xf86EnableDisableFBAccess(int scrnIndex, Bool enable)
 	 */
 	if (!xf86Resetting)
 	    xf86SetRootClip (pScreen, TRUE);
-
     }
     else
     {
diff --git a/hw/xfree86/modes/xf86RandR12.c b/hw/xfree86/modes/xf86RandR12.c
index dfe2cc3..407bf35 100644
--- a/hw/xfree86/modes/xf86RandR12.c
+++ b/hw/xfree86/modes/xf86RandR12.c
@@ -659,10 +659,12 @@ xf86RandR12SetConfig (ScreenPtr		pScreen,
 
 static Bool
 xf86RandR12ScreenSetSize (ScreenPtr	pScreen,
-			CARD16		width,
-			CARD16		height,
-			CARD32		mmWidth,
-			CARD32		mmHeight)
+			  CARD16	width,
+			  CARD16	height,
+			  CARD16	pixWidth,
+			  CARD16	pixHeight,
+			  CARD32	mmWidth,
+			  CARD32	mmHeight)
 {
     XF86RandRInfoPtr	randrp = XF86RANDRINFO(pScreen);
     ScrnInfoPtr		pScrn = XF86SCRNINFO(pScreen);
@@ -670,6 +672,8 @@ xf86RandR12ScreenSetSize (ScreenPtr	pScreen,
     WindowPtr		pRoot = pScreen->root;
     PixmapPtr		pScrnPix;
     Bool		ret = FALSE;
+    Bool		pixSizeChanged = FALSE;
+    Bool		winSizeChanged = FALSE;
     int                 c;
 
     if (xf86RandR12Key) {
@@ -677,46 +681,85 @@ xf86RandR12ScreenSetSize (ScreenPtr	pScreen,
         {
 	    randrp->virtualX = pScrn->virtualX;
 	    randrp->virtualY = pScrn->virtualY;
+	    pixSizeChanged = TRUE;
         }
     }
-    if (pRoot && pScrn->vtSema)
-	(*pScrn->EnableDisableFBAccess) (pScreen->myNum, FALSE);
 
-    /* Let the driver update virtualX and virtualY */
-    if (!(*config->funcs->resize)(pScrn, width, height))
-	goto finish;
+    pScrnPix = (*pScreen->GetScreenPixmap)(pScreen);
+    if (pixWidth != pScrnPix->drawable.width ||
+	pixHeight != pScrnPix->drawable.height)
+	pixSizeChanged = TRUE;
+
+    if (width != pScreen->width || height != pScreen->height)
+	winSizeChanged = TRUE;
+
+    if (pixSizeChanged)
+    {
+	if (pRoot && pScrn->vtSema)
+	    (*pScrn->EnableDisableFBAccess) (pScreen->myNum, FALSE);
+
+	/* Let the driver update virtualX and virtualY */
+	if (!(*config->funcs->resize)(pScrn, pixWidth, pixHeight))
+	    goto finish;
+    }
 
     ret = TRUE;
-    /* Update panning information */
-    for (c = 0; c < config->num_crtc; c++) {
-	xf86CrtcPtr crtc = config->crtc[c];
-	if (crtc->panningTotalArea.x2 > crtc->panningTotalArea.x1 ||
-	    crtc->panningTotalArea.y2 > crtc->panningTotalArea.y1) {
-	    if (crtc->panningTotalArea.x2 > crtc->panningTrackingArea.x1)
-		crtc->panningTotalArea.x2 += width  - pScreen->width;
-	    if (crtc->panningTotalArea.y2 > crtc->panningTrackingArea.y1)
-		crtc->panningTotalArea.y2 += height - pScreen->height;
-	    if (crtc->panningTrackingArea.x2 > crtc->panningTrackingArea.x1)
-		crtc->panningTrackingArea.x2 += width  - pScreen->width;
-	    if (crtc->panningTrackingArea.y2 > crtc->panningTrackingArea.y1)
-		crtc->panningTrackingArea.y2 += height - pScreen->height;
-	    xf86RandR13VerifyPanningArea (crtc, width, height);
-	    xf86RandR13Pan (crtc, randrp->pointerX, randrp->pointerY);
+
+    if (winSizeChanged)
+    {
+	/* Update panning information */
+	for (c = 0; c < config->num_crtc; c++) {
+	    xf86CrtcPtr crtc = config->crtc[c];
+	    if (crtc->panningTotalArea.x2 > crtc->panningTotalArea.x1 ||
+		crtc->panningTotalArea.y2 > crtc->panningTotalArea.y1) {
+		if (crtc->panningTotalArea.x2 > crtc->panningTrackingArea.x1)
+		    crtc->panningTotalArea.x2 += width  - pScreen->width;
+		if (crtc->panningTotalArea.y2 > crtc->panningTrackingArea.y1)
+		    crtc->panningTotalArea.y2 += height - pScreen->height;
+		if (crtc->panningTrackingArea.x2 > crtc->panningTrackingArea.x1)
+		    crtc->panningTrackingArea.x2 += width  - pScreen->width;
+		if (crtc->panningTrackingArea.y2 > crtc->panningTrackingArea.y1)
+		    crtc->panningTrackingArea.y2 += height - pScreen->height;
+		xf86RandR13VerifyPanningArea (crtc, width, height);
+		xf86RandR13Pan (crtc, randrp->pointerX, randrp->pointerY);
+	    }
 	}
     }
 
     pScrnPix = (*pScreen->GetScreenPixmap)(pScreen);
-    pScreen->width = pScrnPix->drawable.width = width;
-    pScreen->height = pScrnPix->drawable.height = height;
+    pScreen->width = width;
+    pScreen->height = height;
+    if (pRoot)
+    {
+	BoxRec	box;
+
+	pRoot->drawable.width = width;
+	pRoot->drawable.height = height;
+	box.x1 = 0;
+	box.y1 = 0;
+	box.x2 = width;
+	box.y2 = height;
+	RegionInit(&pRoot->winSize, &box, 1);
+	RegionInit(&pRoot->borderSize, &box, 1);
+    }
+    pScrnPix->drawable.width = pixWidth;
+    pScrnPix->drawable.height = pixHeight;
     randrp->mmWidth = pScreen->mmWidth = mmWidth;
     randrp->mmHeight = pScreen->mmHeight = mmHeight;
 
-    xf86SetViewport (pScreen, pScreen->width-1, pScreen->height-1);
-    xf86SetViewport (pScreen, 0, 0);
+    if (winSizeChanged)
+    {
+	xf86SetViewport (pScreen, pScreen->width-1, pScreen->height-1);
+	xf86SetViewport (pScreen, 0, 0);
+    }
 
 finish:
-    if (pRoot && pScrn->vtSema)
-	(*pScrn->EnableDisableFBAccess) (pScreen->myNum, TRUE);
+    if (pixSizeChanged)
+    {
+	if (pRoot && pScrn->vtSema)
+	    (*pScrn->EnableDisableFBAccess) (pScreen->myNum, TRUE);
+    }
+
 #if RANDR_12_INTERFACE
     if (xf86RandR12Key && pScreen->root && ret)
 	RRScreenSizeNotify (pScreen);
@@ -818,6 +861,8 @@ xf86RandR12CreateScreenResources (ScreenPtr pScreen)
 	xf86RandR12ScreenSetSize (pScreen,
 				  width,
 				  height,
+				  width,
+				  height,
 				  mmWidth,
 				  mmHeight);
     }
diff --git a/randr/mirrcrtc.c b/randr/mirrcrtc.c
index d493a0e..a9ee6b4 100644
--- a/randr/mirrcrtc.c
+++ b/randr/mirrcrtc.c
@@ -28,11 +28,6 @@ miRRSetScreenConfig(ScreenPtr screen,
 {
     RRScreenConfigRec	old_screen_config;
 
-    /* XXX deal with separate pixmap/screen sizes */
-    if (screen_config->screen_pixmap_width != screen_config->screen_width ||
-	screen_config->screen_pixmap_height != screen_config->screen_height)
-	return FALSE;
-
     RRScreenCurrentConfig(screen, &old_screen_config);
 
     /* Check and see if nothing has changed */
@@ -47,6 +42,8 @@ miRRSetScreenConfig(ScreenPtr screen,
     return RRScreenSizeSet(screen,
 			   screen_config->screen_width,
 			   screen_config->screen_height,
+			   screen_config->screen_pixmap_width,
+			   screen_config->screen_pixmap_height,
 			   screen_config->mm_width,
 			   screen_config->mm_height);
 }
diff --git a/randr/randrstr.h b/randr/randrstr.h
index 8240824..7c553f2 100644
--- a/randr/randrstr.h
+++ b/randr/randrstr.h
@@ -191,6 +191,8 @@ struct _rrOutput {
 typedef Bool (*RRScreenSetSizeProcPtr) (ScreenPtr	pScreen,
 					CARD16		width,
 					CARD16		height,
+					CARD16		pixWidth,
+					CARD16		pixHeight,
 					CARD32		mmWidth,
 					CARD32		mmHeight);
 					
@@ -478,6 +480,8 @@ extern _X_EXPORT Bool
 RRScreenSizeSet (ScreenPtr  pScreen,
 		 CARD16	    width,
 		 CARD16	    height,
+		 CARD16	    pixWidth,
+		 CARD16	    pixHeight,
 		 CARD32	    mmWidth,
 		 CARD32	    mmHeight);
 
diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
index 0b2bc28..97aa3d7 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -435,10 +435,9 @@ RRCrtcCurrentConfig(RRCrtcPtr crtc,
     crtc_config->sprite_position_f_transform = crtc->client_sprite_f_position_transform;
     crtc_config->sprite_image_f_transform = crtc->client_sprite_f_image_transform;
 
-    /* XXX add pixmap stuff */
-    crtc_config->pixmap = NULL;
-    crtc_config->pixmap_x = 0;
-    crtc_config->pixmap_y = 0;
+    crtc_config->pixmap = crtc->scanoutPixmap;
+    crtc_config->pixmap_x = crtc->x;
+    crtc_config->pixmap_y = crtc->y;
     return TRUE;
 }
 
@@ -1510,6 +1509,8 @@ RRConvertCrtcConfig(ClientPtr client, ScreenPtr screen,
 
     if (x->pixmap == None)
 	pixmap = NULL;
+    else if (x->pixmap == RR_CurrentScanoutPixmap)
+	pixmap = crtc->scanoutPixmap;
     else
     {
 	rc = dixLookupResourceByType((pointer *) &pixmap, x->pixmap,
diff --git a/randr/rrscreen.c b/randr/rrscreen.c
index 0c52347..292163f 100644
--- a/randr/rrscreen.c
+++ b/randr/rrscreen.c
@@ -168,6 +168,8 @@ Bool
 RRScreenSizeSet (ScreenPtr  pScreen,
 		 CARD16	    width,
 		 CARD16	    height,
+		 CARD16	    pixWidth,
+		 CARD16	    pixHeight,
 		 CARD32	    mmWidth,
 		 CARD32	    mmHeight)
 {
@@ -178,6 +180,7 @@ RRScreenSizeSet (ScreenPtr  pScreen,
     {
 	return (*pScrPriv->rrScreenSetSize) (pScreen,
 					     width, height,
+					     pixWidth, pixHeight,
 					     mmWidth, mmHeight);
     }
 #endif
@@ -318,6 +321,7 @@ ProcRRSetScreenSize (ClientPtr client)
     }
     if (!RRScreenSizeSet (pScreen, 
 			  stuff->width, stuff->height,
+			  stuff->width, stuff->height,
 			  stuff->widthInMillimeters,
 			  stuff->heightInMillimeters))
     {
@@ -949,7 +953,7 @@ ProcRRSetScreenConfig (ClientPtr client)
 		goto sendReply;
 	    }
 	}
-	if (!RRScreenSizeSet (pScreen, width, height,
+	if (!RRScreenSizeSet (pScreen, width, height, width, height,
 			      pScreen->mmWidth, pScreen->mmHeight))
 	{
 	    rep.status = RRSetConfigFailed;
commit a88d70fb20a2bc3152b84adff4380857e6cfadf5
Author: Keith Packard <keithp at keithp.com>
Date:   Sun Dec 5 20:55:46 2010 -0800

    Set sprite transforms from RRSetCrtcConfigs
    
    These were getting ignored.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Aaron Plattner <aplattner at nvidia.com>

diff --git a/hw/xfree86/modes/xf86RandR12.c b/hw/xfree86/modes/xf86RandR12.c
index b0eabdd..dfe2cc3 100644
--- a/hw/xfree86/modes/xf86RandR12.c
+++ b/hw/xfree86/modes/xf86RandR12.c
@@ -1819,8 +1819,8 @@ xf86RRConvertCrtcConfig(xf86CrtcSetConfigPtr	xf86_config,
 	return FALSE;
     for (o = 0; o < rr_config->numOutputs; o++)
 	xf86_config->outputs[o] = rr_config->outputs[o]->devPrivate;
-    xf86_config->sprite_position_transform = rr_config->sprite_position_transform;
-    xf86_config->sprite_image_transform = rr_config->sprite_image_transform;
+    xf86_config->sprite_position_transform = rr_config->sprite_position_f_transform;
+    xf86_config->sprite_image_transform = rr_config->sprite_image_f_transform;
     xf86_config->pixmap = rr_config->pixmap;
     xf86_config->pixmap_x = rr_config->pixmap_x;
     xf86_config->pixmap_y = rr_config->pixmap_y;
diff --git a/randr/mirrcrtc.c b/randr/mirrcrtc.c
index cc76797..d493a0e 100644
--- a/randr/mirrcrtc.c
+++ b/randr/mirrcrtc.c
@@ -60,14 +60,21 @@ miRRSetCrtcConfig(RRCrtcConfigPtr crtc_config)
 	x = crtc_config->pixmap_x;
 	y = crtc_config->pixmap_y;
     }
-    return RRCrtcSet(crtc_config->crtc,
-		     crtc_config->mode,
-		     x,
-		     y,
-		     crtc_config->rotation,
-		     crtc_config->numOutputs,
-		     crtc_config->outputs,
-		     crtc_config->pixmap);
+    if (!RRCrtcSet(crtc_config->crtc,
+		   crtc_config->mode,
+		   x,
+		   y,
+		   crtc_config->rotation,
+		   crtc_config->numOutputs,
+		   crtc_config->outputs,
+		   crtc_config->pixmap))
+	return FALSE;
+    RRCrtcSpriteTransformSet(crtc_config->crtc,
+			     &crtc_config->sprite_position_transform,
+			     &crtc_config->sprite_image_transform,
+			     &crtc_config->sprite_position_f_transform,
+			     &crtc_config->sprite_image_f_transform);
+    return TRUE;
 }
 
 Bool
diff --git a/randr/randrstr.h b/randr/randrstr.h
index c231972..8240824 100644
--- a/randr/randrstr.h
+++ b/randr/randrstr.h
@@ -154,8 +154,10 @@ struct _rrCrtcConfig {
     Rotation			rotation;
     int				numOutputs;
     RROutputPtr			*outputs;
-    struct pict_f_transform	sprite_position_transform;
-    struct pict_f_transform	sprite_image_transform;
+    PictTransform		sprite_position_transform;
+    PictTransform		sprite_image_transform;
+    struct pict_f_transform	sprite_position_f_transform;
+    struct pict_f_transform	sprite_image_f_transform;
     PixmapPtr			pixmap;
     int				pixmap_x, pixmap_y;
 };
diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
index 12982a8..0b2bc28 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -430,8 +430,10 @@ RRCrtcCurrentConfig(RRCrtcPtr crtc,
     if (!crtc_config->outputs)
 	return FALSE;
     memcpy(crtc_config->outputs, crtc->outputs, crtc->numOutputs * sizeof (RROutputPtr));
-    crtc_config->sprite_position_transform = crtc->client_sprite_f_position_transform;
-    crtc_config->sprite_image_transform = crtc->client_sprite_f_image_transform;
+    crtc_config->sprite_position_transform = crtc->client_sprite_position_transform;
+    crtc_config->sprite_image_transform = crtc->client_sprite_image_transform;
+    crtc_config->sprite_position_f_transform = crtc->client_sprite_f_position_transform;
+    crtc_config->sprite_image_f_transform = crtc->client_sprite_f_image_transform;
 
     /* XXX add pixmap stuff */
     crtc_config->pixmap = NULL;
@@ -718,8 +720,8 @@ RRScreenCoversCrtc(RRScreenConfigPtr screen_config,
 			crtc_config->mode->mode.width, crtc_config->mode->mode.height,
 			crtc_config->rotation,
 			client_transform,
-			&crtc_config->sprite_position_transform,
-			&crtc_config->sprite_image_transform,
+			&crtc_config->sprite_position_f_transform,
+			&crtc_config->sprite_image_f_transform,
 			NULL, &f_transform, NULL, NULL, NULL, NULL);
 
     RRModeGetScanoutSize (crtc_config->mode, &f_transform,
@@ -1469,15 +1471,6 @@ ProcRRGetCrtcTransform (ClientPtr client)
     return Success;
 }
 
-static void
-pixman_f_transform_from_xRenderTransform(struct pixman_f_transform *f_transform,
-					 xRenderTransform *x_transform)
-{
-    struct pixman_transform	transform;
-    PictTransform_from_xRenderTransform(&transform, x_transform);
-    pixman_f_transform_from_pixman_transform(f_transform, &transform);
-}
-
 static int
 RRConvertCrtcConfig(ClientPtr client, ScreenPtr screen,
 		    RRScreenConfigPtr screen_config,
@@ -1594,10 +1587,14 @@ RRConvertCrtcConfig(ClientPtr client, ScreenPtr screen,
     config->rotation = x->rotation;
     config->numOutputs = x->nOutput;
     config->outputs = outputs;
-    pixman_f_transform_from_xRenderTransform(&config->sprite_position_transform,
+    PictTransform_from_xRenderTransform(&config->sprite_position_transform,
 					     &x->spritePositionTransform);
-    pixman_f_transform_from_xRenderTransform(&config->sprite_image_transform,
+    PictTransform_from_xRenderTransform(&config->sprite_image_transform,
 					     &x->spriteImageTransform);
+    pixman_f_transform_from_pixman_transform(&config->sprite_position_f_transform,
+					     &config->sprite_position_transform);
+    pixman_f_transform_from_pixman_transform(&config->sprite_image_f_transform,
+					     &config->sprite_image_transform);
     config->pixmap = pixmap;
     config->pixmap_x = x->xPixmap;
     config->pixmap_y = x->yPixmap;
commit 96b4d4787bf82edd9d06eb9a6e94bc45412c7df2
Author: Keith Packard <keithp at keithp.com>
Date:   Sun Dec 5 20:49:19 2010 -0800

    DIX is responsible for ref counting scanout pixmaps.
    
    Remove some extra ref counting inside hw/xfree86/modes
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Aaron Plattner <aplattner at nvidia.com>

diff --git a/hw/xfree86/modes/xf86Crtc.c b/hw/xfree86/modes/xf86Crtc.c
index 5bf12f0..08d384f 100644
--- a/hw/xfree86/modes/xf86Crtc.c
+++ b/hw/xfree86/modes/xf86Crtc.c
@@ -414,10 +414,6 @@ done:
 	crtc->active = TRUE;
 	if (scrn->pScreen)
 	    xf86CrtcSetScreenSubpixelOrder (scrn->pScreen);
-	if (crtc->scanoutPixmap)
-	    ++crtc->scanoutPixmap->refcnt;
-	if (saved_scanout_pixmap)
-	    (*scrn->pScreen->DestroyPixmap)(saved_scanout_pixmap);
 	if (scrn->ModeSet)
 	    scrn->ModeSet(scrn);
     } else {
commit afb6ebf1d5829346c40fe1053c9f50afe926e6c6
Author: Keith Packard <keithp at keithp.com>
Date:   Fri Dec 3 13:04:37 2010 -0800

    randr: Hook up the new RandR 1.4 functionality
    
    This bumps the supported RandR protocol version and adds the dispatch
    hooks needed to call the new functions
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Aaron Plattner <aplattner at nvidia.com>

diff --git a/include/protocol-versions.h b/include/protocol-versions.h
index 1d33bdd..c8c7f5f 100644
--- a/include/protocol-versions.h
+++ b/include/protocol-versions.h
@@ -65,7 +65,7 @@
 
 /* RandR */
 #define SERVER_RANDR_MAJOR_VERSION		1
-#define SERVER_RANDR_MINOR_VERSION		3
+#define SERVER_RANDR_MINOR_VERSION		4
 
 /* Record */
 #define SERVER_RECORD_MAJOR_VERSION		1
diff --git a/randr/rrdispatch.c b/randr/rrdispatch.c
index ebfda57..aed746b 100644
--- a/randr/rrdispatch.c
+++ b/randr/rrdispatch.c
@@ -224,5 +224,11 @@ int (*ProcRandrVector[RRNumberRequests])(ClientPtr) = {
     ProcRRSetPanning,		/* 29 */
     ProcRRSetOutputPrimary,	/* 30 */
     ProcRRGetOutputPrimary,	/* 31 */
+/* V1.4 additions */
+    ProcRRQueryScanoutPixmaps,	/* 32 */
+    ProcRRCreateScanoutPixmap,	/* 33 */
+    ProcRRSetCrtcSpriteTransform,/* 34 */
+    ProcRRGetCrtcSpriteTransform,/* 35 */
+    ProcRRSetCrtcConfigs,	 /* 36 */
 };
 
diff --git a/randr/rrsdispatch.c b/randr/rrsdispatch.c
index e16090a..c848f91 100644
--- a/randr/rrsdispatch.c
+++ b/randr/rrsdispatch.c
@@ -461,6 +461,132 @@ SProcRRGetOutputPrimary (ClientPtr client)
     return ProcRandrVector[stuff->randrReqType](client);
 }
 
+static int
+SProcRRQueryScanoutPixmaps (ClientPtr client)
+{
+    int n;
+    REQUEST(xRRQueryScanoutPixmapsReq);
+
+    REQUEST_SIZE_MATCH(xRRQueryScanoutPixmapsReq);
+    swaps(&stuff->length, n);
+    swapl(&stuff->drawable, n);
+    return ProcRandrVector[stuff->randrReqType](client);
+}
+
+static int
+SProcRRCreateScanoutPixmap (ClientPtr client)
+{
+    int n;
+    REQUEST(xRRCreateScanoutPixmapReq);
+
+    REQUEST_SIZE_MATCH(xRRCreateScanoutPixmapReq);
+    swaps(&stuff->length, n);
+    swapl(&stuff->pid, n);
+    swapl(&stuff->drawable, n);
+    swaps(&stuff->width, n);
+    swaps(&stuff->height, n);
+    swapl(&stuff->format, n);
+    swaps(&stuff->rotations, n);
+    return ProcRandrVector[stuff->randrReqType](client);
+}
+
+static void
+swap_transform(xRenderTransform *t)
+{
+    int n;
+    swapl(&t->matrix11, n);
+    swapl(&t->matrix12, n);
+    swapl(&t->matrix13, n);
+    swapl(&t->matrix21, n);
+    swapl(&t->matrix22, n);
+    swapl(&t->matrix23, n);
+    swapl(&t->matrix31, n);
+    swapl(&t->matrix32, n);
+    swapl(&t->matrix33, n);
+}
+
+static int
+SProcRRSetCrtcSpriteTransform (ClientPtr client)
+{
+    int n;
+    REQUEST(xRRSetCrtcSpriteTransformReq);
+
+    REQUEST_SIZE_MATCH(xRRSetCrtcSpriteTransformReq);
+    swaps(&stuff->length, n);
+    swapl(&stuff->crtc, n);
+    swap_transform(&stuff->positionTransform);
+    swap_transform(&stuff->imageTransform);
+    return ProcRandrVector[stuff->randrReqType](client);
+}
+
+static int
+SProcRRGetCrtcSpriteTransform (ClientPtr client)
+{
+    int n;
+    REQUEST(xRRGetCrtcSpriteTransformReq);
+
+    REQUEST_SIZE_MATCH(xRRGetCrtcSpriteTransformReq);
+    swaps(&stuff->length, n);
+    swapl(&stuff->crtc, n);
+    return ProcRandrVector[stuff->randrReqType](client);
+}
+
+static int
+SProcRRSetCrtcConfigs (ClientPtr client)
+{
+    int n;
+    REQUEST(xRRSetCrtcConfigsReq);
+    int c;
+    int extra_len;
+    int num_configs;
+    int num_output_ids;
+    xRRCrtcConfig *x_configs;
+
+    REQUEST_AT_LEAST_SIZE(xRRSetCrtcConfigsReq);
+    swaps(&stuff->length, n);
+    swapl(&stuff->drawable, n);
+    swaps(&stuff->screenPixmapWidth, n);
+    swaps(&stuff->screenPixmapHeight, n);
+    swaps(&stuff->screenWidth, n);
+    swaps(&stuff->screenHeight, n);
+    swapl(&stuff->widthInMillimeters, n);
+    swapl(&stuff->heightInMillimeters, n);
+    swaps(&stuff->nConfigs, n);
+
+    extra_len = client->req_len - bytes_to_int32(sizeof(xRRSetCrtcConfigsReq));
+
+    num_configs = stuff->nConfigs;
+
+    /* Check request length against number of configs specified */
+    if (num_configs * (sizeof (xRRCrtcConfig) >> 2) > extra_len)
+	return BadLength;
+
+    x_configs = (xRRCrtcConfig *) (stuff + 1);
+    for (c = 0; c < num_configs; c++) {
+	swapl(&x_configs->crtc, n);
+	swaps(&x_configs->x, n);
+	swaps(&x_configs->y, n);
+	swapl(&x_configs->mode, n);
+	swaps(&x_configs->rotation, n);
+	swaps(&x_configs->nOutput, n);
+	swap_transform(&x_configs->spritePositionTransform);
+	swap_transform(&x_configs->spriteImageTransform);
+	swapl(&x_configs->pixmap, n);
+	swaps(&x_configs->xPixmap, n);
+	swaps(&x_configs->yPixmap, n);
+	x_configs++;
+    }
+
+    /* Let the other dispatch function deal with verifying that
+     * the right number of output ids are present, just
+     * swap whatever is here
+     */
+    num_output_ids = extra_len - (num_configs * (sizeof (xRRCrtcConfig)) >> 2);
+    SwapLongs((CARD32 *) x_configs, num_output_ids);
+
+    return ProcRandrVector[stuff->randrReqType](client);
+}
+
 int (*SProcRandrVector[RRNumberRequests])(ClientPtr) = {
     SProcRRQueryVersion,	/* 0 */
 /* we skip 1 to make old clients fail pretty immediately */
@@ -499,5 +625,11 @@ int (*SProcRandrVector[RRNumberRequests])(ClientPtr) = {
     SProcRRSetPanning,		/* 29 */
     SProcRRSetOutputPrimary,	/* 30 */
     SProcRRGetOutputPrimary,	/* 31 */
+/* V1.4 additions */
+    SProcRRQueryScanoutPixmaps,	/* 32 */
+    SProcRRCreateScanoutPixmap,	/* 33 */
+    SProcRRSetCrtcSpriteTransform,/* 34 */
+    SProcRRGetCrtcSpriteTransform,/* 35 */
+    SProcRRSetCrtcConfigs,	/* 36 */
 };
 
commit 82612045e11f2b882ae132e184a9629f43f1c424
Author: Keith Packard <keithp at keithp.com>
Date:   Fri Dec 3 13:00:46 2010 -0800

    randr: Add per-crtc pixmaps
    
    This adds new driver hooks to allocate scanout pixmaps and
    changes the mode setting APIs to pass the new scanout pixmaps
    along from DIX. DIX is responsible for reference counting the pixmaps
    by tracking them through RRCrtcNotify.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Aaron Plattner <aplattner at nvidia.com>

diff --git a/hw/xfree86/modes/xf86Crtc.c b/hw/xfree86/modes/xf86Crtc.c
index 3fccaea..5bf12f0 100644
--- a/hw/xfree86/modes/xf86Crtc.c
+++ b/hw/xfree86/modes/xf86Crtc.c
@@ -82,6 +82,17 @@ xf86CrtcSetSizeRange (ScrnInfoPtr scrn,
     config->maxHeight = maxHeight;
 }
 
+void
+xf86CrtcSetScanoutFormats(ScrnInfoPtr		scrn,
+			  int			num_formats,
+			  xf86CrtcScanoutFormat	*formats)
+{
+    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(scrn);
+
+    config->num_scanout_formats = num_formats;
+    config->scanout_formats = formats;
+}
+
 /*
  * Crtc functions
  */
@@ -265,6 +276,7 @@ xf86CrtcSet(xf86CrtcPtr crtc, xf86CrtcSetRec *set)
     Rotation		saved_rotation;
     RRTransformRec	saved_transform;
     Bool		saved_transform_present;
+    PixmapPtr		saved_scanout_pixmap;
 
     crtc->enabled = xf86CrtcInUse (crtc);
 
@@ -284,6 +296,7 @@ xf86CrtcSet(xf86CrtcPtr crtc, xf86CrtcSetRec *set)
     saved_x = crtc->x;
     saved_y = crtc->y;
     saved_rotation = crtc->rotation;
+    saved_scanout_pixmap = crtc->scanoutPixmap;
     if (crtc->transformPresent) {
 	RRTransformInit (&saved_transform);
 	RRTransformCopy (&saved_transform, &crtc->transform);
@@ -301,6 +314,8 @@ xf86CrtcSet(xf86CrtcPtr crtc, xf86CrtcSetRec *set)
     }
     if (set->flags & XF86CrtcSetRotation)
 	crtc->rotation = set->rotation;
+    if (set->flags & XF86CrtcSetScanoutPixmap)
+	crtc->scanoutPixmap = set->scanout_pixmap;
 
     if (set->flags & XF86CrtcSetTransform) {
 	if (set->transform) {
@@ -399,6 +414,10 @@ done:
 	crtc->active = TRUE;
 	if (scrn->pScreen)
 	    xf86CrtcSetScreenSubpixelOrder (scrn->pScreen);
+	if (crtc->scanoutPixmap)
+	    ++crtc->scanoutPixmap->refcnt;
+	if (saved_scanout_pixmap)
+	    (*scrn->pScreen->DestroyPixmap)(saved_scanout_pixmap);
 	if (scrn->ModeSet)
 	    scrn->ModeSet(scrn);
     } else {
@@ -409,6 +428,7 @@ done:
 	if (saved_transform_present)
 	    RRTransformCopy (&crtc->transform, &saved_transform);
 	crtc->transformPresent = saved_transform_present;
+	crtc->scanoutPixmap = saved_scanout_pixmap;
     }
 
     if (adjusted_mode) {
diff --git a/hw/xfree86/modes/xf86Crtc.h b/hw/xfree86/modes/xf86Crtc.h
index c2e8131..9a520fc 100644
--- a/hw/xfree86/modes/xf86Crtc.h
+++ b/hw/xfree86/modes/xf86Crtc.h
@@ -79,6 +79,7 @@ typedef enum _xf86CrtcSetFlags {
     XF86CrtcSetTransform = 8,		/* transform */
     XF86CrtcSetRotation = 16,		/* rotation */
     XF86CrtcSetProperty = 32,		/* output property */
+    XF86CrtcSetScanoutPixmap = 64,	/* scanout pixmap */
 } xf86CrtcSetFlags;
 
 typedef struct _xf86CrtcSet {
@@ -87,6 +88,7 @@ typedef struct _xf86CrtcSet {
     Rotation		rotation;
     RRTransformPtr	transform;
     int			x, y;
+    PixmapPtr		scanout_pixmap;
 } xf86CrtcSetRec;
 
 typedef struct _xf86CrtcFuncs {
@@ -277,6 +279,7 @@ struct _xf86Crtc {
     Rotation	    rotation;
     PixmapPtr	    rotatedPixmap;
     void	    *rotatedData;
+    PixmapPtr	    scanoutPixmap;
     
     /**
      * Position on screen
@@ -670,6 +673,14 @@ typedef struct _xf86CrtcSetConfig {
     int				pixmap_x, pixmap_y;
 } xf86CrtcSetConfigRec, *xf86CrtcSetConfigPtr;
 
+typedef struct _xf86CrtcScanoutFormat {
+    int		    depth;
+    int		    bitsPerPixel;
+    int		    maxWidth, maxHeight;
+    Rotation	    rotations;
+    PictFormatShort format;
+} xf86CrtcScanoutFormat;
+
 typedef struct _xf86CrtcConfigFuncs {
     /**
      * Requests that the driver resize the screen.
@@ -693,6 +704,17 @@ typedef struct _xf86CrtcConfigFuncs {
 		   RRScreenConfigPtr	screen_config,
 		   xf86CrtcSetConfigPtr	crtc_configs,
 		   int			num_configs);
+
+    /**
+     * Create a scanout pixmap
+     */
+    PixmapPtr
+    (*create_scanout_pixmap)(ScrnInfoPtr		scrn,
+			     int			width,
+			     int			height,
+			     Rotation			rotations,
+			     xf86CrtcScanoutFormat	*format);
+
 } xf86CrtcConfigFuncsRec, *xf86CrtcConfigFuncsPtr;
 
 typedef void (*xf86_crtc_notify_proc_ptr) (ScreenPtr pScreen);
@@ -752,6 +774,11 @@ typedef struct _xf86CrtcConfig {
     /* callback when crtc configuration changes */
     xf86_crtc_notify_proc_ptr  xf86_crtc_notify;
 
+    /*
+     * Supported scanout pixmap formats
+     */
+    int			num_scanout_formats;
+    xf86CrtcScanoutFormat	*scanout_formats;
 } xf86CrtcConfigRec, *xf86CrtcConfigPtr;
 
 extern _X_EXPORT int xf86CrtcConfigPrivateIndex;
@@ -797,6 +824,11 @@ xf86CrtcSetSizeRange (ScrnInfoPtr scrn,
 		      int minWidth, int minHeight,
 		      int maxWidth, int maxHeight);
 
+extern _X_EXPORT void
+xf86CrtcSetScanoutFormats (ScrnInfoPtr			scrn,
+			   int				num_formats,
+			   xf86CrtcScanoutFormat	*formats);
+
 /*
  * Crtc functions
  */
diff --git a/hw/xfree86/modes/xf86RandR12.c b/hw/xfree86/modes/xf86RandR12.c
index e3330f4..b0eabdd 100644
--- a/hw/xfree86/modes/xf86RandR12.c
+++ b/hw/xfree86/modes/xf86RandR12.c
@@ -1083,7 +1083,7 @@ xf86RandR12CrtcNotify (RRCrtcPtr	randr_crtc)
     ret = RRCrtcNotify (randr_crtc, randr_mode, x, y,
 			rotation,
 			crtc->transformPresent ? &crtc->transform : NULL,
-			numOutputs, randr_outputs);
+			numOutputs, randr_outputs, crtc->scanoutPixmap);
     free(randr_outputs);
     return ret;
 }
@@ -1126,7 +1126,8 @@ xf86RandR12CrtcSet (ScreenPtr	    pScreen,
 		    int		    y,
 		    Rotation	    rotation,
 		    int		    num_randr_outputs,
-		    RROutputPtr	    *randr_outputs)
+		    RROutputPtr	    *randr_outputs,
+		    PixmapPtr	    scanout_pixmap)
 {
     XF86RandRInfoPtr	randrp = XF86RANDRINFO(pScreen);
     ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
@@ -1157,6 +1158,9 @@ xf86RandR12CrtcSet (ScreenPtr	    pScreen,
 				  sizeof (transform->transform)) != 0)
 	flags |= XF86CrtcSetTransform;
 
+    if (scanout_pixmap != crtc->scanoutPixmap)
+	flags |= XF86CrtcSetScanoutPixmap;
+
     if (x != crtc->x || y != crtc->y)
 	flags |= XF86CrtcSetOrigin;
     for (o = 0; o < config->num_output; o++)
@@ -1203,6 +1207,7 @@ xf86RandR12CrtcSet (ScreenPtr	    pScreen,
 	    set.transform = transform;
 	    set.x = x;
 	    set.y = y;
+	    set.scanout_pixmap = scanout_pixmap;
 	    set.flags = flags;
 	    if (!xf86CrtcSet(crtc, &set))
 	    {
@@ -1732,6 +1737,54 @@ xf86RandR12ChangeGamma(int scrnIndex, Gamma gamma)
     return Success;
 }
 
+static RRScanoutPixmapInfo *
+xf86RRQueryScanoutPixmaps(ScreenPtr screen, int *n_info)
+{
+    ScrnInfoPtr		scrn = xf86Screens[screen->myNum];
+    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(scrn);
+    RRScanoutPixmapInfo	*info;
+    int			f;
+
+    info = calloc(config->num_scanout_formats, sizeof (RRScanoutPixmapInfo));
+    if (config->num_scanout_formats && !info) {
+	*n_info = 0;
+	return NULL;
+    }
+    for (f = 0; f < config->num_scanout_formats; f++) {
+	info[f].maxWidth = config->scanout_formats[f].maxWidth;
+	info[f].maxHeight = config->scanout_formats[f].maxHeight;
+	info[f].depth = config->scanout_formats[f].depth;
+	info[f].rotations = config->scanout_formats[f].rotations;
+	info[f].format = PictureMatchFormat (screen, info[f].depth,
+					     config->scanout_formats[f].format);
+    }
+    *n_info = config->num_scanout_formats;
+    return info;
+}
+
+static PixmapPtr
+xf86RRCreateScanoutPixmap(ScreenPtr screen,
+			  int width, int height, int depth,
+			  Rotation rotations,
+			  PictFormatPtr format)
+{
+    ScrnInfoPtr		scrn = xf86Screens[screen->myNum];
+    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(scrn);
+    int			f;
+
+    if (!config->funcs->create_scanout_pixmap)
+	return NullPixmap;
+
+    for (f = 0; f < config->num_scanout_formats; f++)
+	if (config->scanout_formats[f].depth == depth &&
+	    (config->scanout_formats[f].format & 0xffffff) == format->format) {
+	    return (*config->funcs->create_scanout_pixmap) (scrn, width, height,
+							    rotations,
+							    &config->scanout_formats[f]);
+	}
+    return NullPixmap;
+}
+
 static void
 xf86RandR14SetCrtcSpriteTransform(ScreenPtr		pScreen,
 				  RRCrtcPtr		randr_crtc,
@@ -1893,17 +1946,17 @@ xf86RandR12Init12 (ScreenPtr pScreen)
     rp->rrCrtcGetGamma = xf86RandR12CrtcGetGamma;
     rp->rrOutputSetProperty = xf86RandR12OutputSetProperty;
     rp->rrOutputValidateMode = xf86RandR12OutputValidateMode;
-#if RANDR_13_INTERFACE
     rp->rrOutputGetProperty = xf86RandR13OutputGetProperty;
     rp->rrGetPanning = xf86RandR13GetPanning;
     rp->rrSetPanning = xf86RandR13SetPanning;
-#endif
     rp->rrModeDestroy = xf86RandR12ModeDestroy;
     rp->rrSetConfig = NULL;
     pScrn->PointerMoved = xf86RandR12PointerMoved;
     pScrn->ChangeGamma = xf86RandR12ChangeGamma;
     rp->rrSetCrtcSpriteTransform = xf86RandR14SetCrtcSpriteTransform;
     rp->rrSetCrtcConfigs = xf86RRSetCrtcConfigs;
+    rp->rrQueryScanoutPixmaps = xf86RRQueryScanoutPixmaps;
+    rp->rrCreateScanoutPixmap = xf86RRCreateScanoutPixmap;
 
     randrp->orig_EnterVT = pScrn->EnterVT;
     pScrn->EnterVT = xf86RandR12EnterVT;
diff --git a/randr/Makefile.am b/randr/Makefile.am
index a1c88dc..b7664c6 100644
--- a/randr/Makefile.am
+++ b/randr/Makefile.am
@@ -16,6 +16,7 @@ librandr_la_SOURCES =	\
 	rrinfo.c	\
 	rrmode.c	\
 	rroutput.c	\
+	rrpixmap.c	\
 	rrpointer.c	\
 	rrproperty.c	\
 	rrscreen.c	\
diff --git a/randr/mirrcrtc.c b/randr/mirrcrtc.c
index b1e2c9f..cc76797 100644
--- a/randr/mirrcrtc.c
+++ b/randr/mirrcrtc.c
@@ -66,7 +66,8 @@ miRRSetCrtcConfig(RRCrtcConfigPtr crtc_config)
 		     y,
 		     crtc_config->rotation,
 		     crtc_config->numOutputs,
-		     crtc_config->outputs);
+		     crtc_config->outputs,
+		     crtc_config->pixmap);
 }
 
 Bool
diff --git a/randr/randr.c b/randr/randr.c
index 6077705..c22657e 100644
--- a/randr/randr.c
+++ b/randr/randr.c
@@ -98,6 +98,7 @@ RRCloseScreen (int i, ScreenPtr pScreen)
     
     free(pScrPriv->crtcs);
     free(pScrPriv->outputs);
+    free(pScrPriv->scanout_info);
     free(pScrPriv);
     RRNScreens -= 1;	/* ok, one fewer screen with RandR running */
     return (*pScreen->CloseScreen) (i, pScreen);    
@@ -248,6 +249,8 @@ Bool RRScreenInit(ScreenPtr pScreen)
     pScrPriv->rrCrtcSet = NULL;
     pScrPriv->rrCrtcSetGamma = NULL;
 #endif
+    pScrPriv->scanout_info = NULL;
+    pScrPriv->n_scanout_info = 0;
 #if RANDR_10_INTERFACE    
     pScrPriv->rrSetConfig = 0;
     pScrPriv->rotations = RR_Rotate_0;
@@ -482,6 +485,18 @@ RRVerticalRefresh (xRRModeInfo *mode)
     return (CARD16) refresh;
 }
 
+RRScanoutPixmapInfo *
+RRQueryScanoutPixmapInfo(ScreenPtr screen, int *n_info)
+{
+    rrScrPriv(screen);
+
+    if (!pScrPriv->scanout_info && pScrPriv->rrQueryScanoutPixmaps)
+	pScrPriv->scanout_info = pScrPriv->rrQueryScanoutPixmaps(screen,
+								 &pScrPriv->n_scanout_info);
+    *n_info = pScrPriv->n_scanout_info;
+    return pScrPriv->scanout_info;
+}
+
 static int
 ProcRRDispatch (ClientPtr client)
 {
diff --git a/randr/randrstr.h b/randr/randrstr.h
index 2fe9602..c231972 100644
--- a/randr/randrstr.h
+++ b/randr/randrstr.h
@@ -123,6 +123,7 @@ struct _rrCrtc {
     CARD16	    *gammaGreen;
     void	    *devPrivate;
     Bool	    transforms;
+    PixmapPtr	    scanoutPixmap;
     RRTransformRec  client_pending_transform;
     RRTransformRec  client_current_transform;
     PictTransform   client_sprite_position_transform;
@@ -198,7 +199,8 @@ typedef Bool (*RRCrtcSetProcPtr) (ScreenPtr		pScreen,
 				  int			y,
 				  Rotation		rotation,
 				  int			numOutputs,
-				  RROutputPtr		*outputs);
+				  RROutputPtr		*outputs,
+				  PixmapPtr		scanout_pixmap);
 
 typedef Bool (*RRCrtcSetGammaProcPtr) (ScreenPtr	pScreen,
 				       RRCrtcPtr	crtc);
@@ -264,6 +266,20 @@ typedef Bool (*RRSetConfigProcPtr) (ScreenPtr		pScreen,
 
 #endif
 	
+typedef struct {
+    PictFormatPtr	format;
+    int			maxWidth, maxHeight;
+    int			depth;
+    Rotation		rotations;
+} RRScanoutPixmapInfo;
+
+typedef RRScanoutPixmapInfo *(*RRQueryScanoutPixmapsPtr) (ScreenPtr pScreen,
+							  int *num_info);
+
+typedef PixmapPtr (*RRCreateScanoutPixmapPtr) (ScreenPtr pScreen,
+					       int width, int height, int depth,
+					       Rotation rotations,
+					       PictFormatPtr format);
 
 typedef void (*RRSetCrtcSpriteTransformPtr) (ScreenPtr pScreen,
 					     RRCrtcPtr randr_crtc,
@@ -303,6 +319,8 @@ typedef struct _rrScrPriv {
     RRGetPanningProcPtr	rrGetPanning;
     RRSetPanningProcPtr	rrSetPanning;
 #endif
+    RRQueryScanoutPixmapsPtr	rrQueryScanoutPixmaps;
+    RRCreateScanoutPixmapPtr	rrCreateScanoutPixmap;
     RRSetCrtcSpriteTransformPtr	rrSetCrtcSpriteTransform;
     RRGetCrtcSpriteTransformPtr	rrGetCrtcSpriteTransform;
     RRSetCrtcConfigsPtr rrSetCrtcConfigs;
@@ -333,6 +351,8 @@ typedef struct _rrScrPriv {
     /* Last known pointer position */
     RRCrtcPtr		    pointerCrtc;
 
+    RRScanoutPixmapInfo	    *scanout_info;
+    int			    n_scanout_info;
 #ifdef RANDR_10_INTERFACE
     /*
      * Configuration information
@@ -347,6 +367,7 @@ typedef struct _rrScrPriv {
     int			    rate;
     int			    size;
 #endif
+
 } rrScrPrivRec, *rrScrPrivPtr;
 
 extern _X_EXPORT DevPrivateKeyRec rrPrivKeyRec;
@@ -521,6 +542,9 @@ RRGetRotation (ScreenPtr pScreen);
 extern _X_EXPORT CARD16
 RRVerticalRefresh (xRRModeInfo *mode);
 
+extern _X_EXPORT RRScanoutPixmapInfo *
+RRQueryScanoutPixmapInfo(ScreenPtr screen, int *n_info);
+
 #ifdef RANDR_10_INTERFACE					
 /*
  * This is the old interface, deprecated but left
@@ -599,7 +623,8 @@ RRCrtcNotify (RRCrtcPtr	    crtc,
 	      Rotation	    rotation,
 	      RRTransformPtr transform,
 	      int	    numOutputs,
-	      RROutputPtr   *outputs);
+	      RROutputPtr   *outputs,
+	      PixmapPtr	    scanoutPixmap);
 
 extern _X_EXPORT void
 RRDeliverCrtcEvent (ClientPtr client, WindowPtr pWin, RRCrtcPtr crtc);
@@ -614,7 +639,8 @@ RRCrtcSet (RRCrtcPtr    crtc,
 	   int		y,
 	   Rotation	rotation,
 	   int		numOutput,
-	   RROutputPtr  *outputs);
+	   RROutputPtr  *outputs,
+	   PixmapPtr	scanout_pixmap);
 
 /*
  * Request that the Crtc gamma be changed
@@ -643,6 +669,10 @@ RRCrtcGammaGet(RRCrtcPtr crtc);
 extern _X_EXPORT Bool
 RRCrtcGammaNotify (RRCrtcPtr	crtc);
 
+void
+RRModeGetScanoutSize (RRModePtr mode, struct pixman_f_transform *transform,
+		      int *width, int *height);
+
 /*
  * Set the size of the gamma table at server startup time
  */
@@ -778,11 +808,23 @@ RRCrtcSpriteTransformSet(RRCrtcPtr crtc,
 			 struct pict_f_transform *f_image_transform);
 
 int
+ProcRRQueryScanoutPixmaps (ClientPtr client);
+
+int
+ProcRRCreateScanoutPixmap (ClientPtr client);
+
+int
+ProcRRSetCrtcPixmapConfig (ClientPtr client);
+
+int
 ProcRRSetCrtcSpriteTransform (ClientPtr client);
 
 int
 ProcRRGetCrtcSpriteTransform (ClientPtr client);
 
+int
+ProcRRSetCrtcConfigs (ClientPtr client);
+
 /* rrdispatch.c */
 extern _X_EXPORT Bool
 RRClientKnowsRates (ClientPtr	pClient);
diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
index 1f8f2e6..12982a8 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -138,7 +138,8 @@ RRCrtcNotify (RRCrtcPtr	    crtc,
 	      Rotation	    rotation,
 	      RRTransformPtr transform,
 	      int	    numOutputs,
-	      RROutputPtr   *outputs)
+	      RROutputPtr   *outputs,
+	      PixmapPtr	    scanoutPixmap)
 {
     int	    i, j;
 
@@ -236,6 +237,15 @@ RRCrtcNotify (RRCrtcPtr	    crtc,
 	RRCrtcChanged (crtc, TRUE);
     }
 
+    if (scanoutPixmap != crtc->scanoutPixmap)
+    {
+	if (scanoutPixmap)
+	    ++scanoutPixmap->refcnt;
+	if (crtc->scanoutPixmap)
+	    (*crtc->scanoutPixmap->drawable.pScreen->DestroyPixmap) (crtc->scanoutPixmap);
+	crtc->scanoutPixmap = scanoutPixmap;
+    }
+
     if (crtc->changed && mode)
     {
 	RRTransformCompute (x, y,
@@ -312,7 +322,8 @@ RRCrtcSet (RRCrtcPtr    crtc,
 	   int		y,
 	   Rotation	rotation,
 	   int		numOutputs,
-	   RROutputPtr  *outputs)
+	   RROutputPtr  *outputs,
+	   PixmapPtr	scanout_pixmap)
 {
     ScreenPtr	pScreen = crtc->pScreen;
     Bool	ret = FALSE;
@@ -326,7 +337,8 @@ RRCrtcSet (RRCrtcPtr    crtc,
 	crtc->numOutputs == numOutputs &&
 	!memcmp (crtc->outputs, outputs, numOutputs * sizeof (RROutputPtr)) &&
 	!RRCrtcPendingProperties (crtc) &&
-	!RRCrtcPendingTransform (crtc))
+	!RRCrtcPendingTransform (crtc) &&
+	crtc->scanoutPixmap == scanout_pixmap)
     {
 	ret = TRUE;
     }
@@ -336,7 +348,7 @@ RRCrtcSet (RRCrtcPtr    crtc,
 	if (pScrPriv->rrCrtcSet)
 	{
 	    ret = (*pScrPriv->rrCrtcSet) (pScreen, crtc, mode, x, y,
-					  rotation, numOutputs, outputs);
+					  rotation, numOutputs, outputs, scanout_pixmap);
 	}
 	else
 #endif
@@ -349,7 +361,7 @@ RRCrtcSet (RRCrtcPtr    crtc,
 
 		if (!mode)
 		{
-		    RRCrtcNotify (crtc, NULL, x, y, rotation, NULL, 0, NULL);
+		    RRCrtcNotify (crtc, NULL, x, y, rotation, NULL, 0, NULL, scanout_pixmap);
 		    ret = TRUE;
 		}
 		else
@@ -375,7 +387,7 @@ RRCrtcSet (RRCrtcPtr    crtc,
 		     */
 		    if (ret)
 		    {
-			RRCrtcNotify (crtc, mode, x, y, rotation, NULL, 1, outputs);
+			RRCrtcNotify (crtc, mode, x, y, rotation, NULL, 1, outputs, scanout_pixmap);
 			RRScreenSizeNotify (pScreen);
 		    }
 		}
@@ -573,7 +585,10 @@ RRCrtcGammaNotify (RRCrtcPtr	crtc)
     return TRUE;    /* not much going on here */
 }
 
-static void
+/*
+ * Compute overall scanout buffer requirements for the specified mode
+ */
+void
 RRModeGetScanoutSize (RRModePtr mode, struct pixman_f_transform *transform,
 		      int *width, int *height)
 {
@@ -1049,7 +1064,7 @@ ProcRRSetCrtcConfig (ClientPtr client)
     }
 
     if (!RRCrtcSet (crtc, mode, stuff->x, stuff->y,
-		   rotation, numOutputs, outputs))
+		    rotation, numOutputs, outputs, NULL))
     {
 	rep.status = RRSetConfigFailed;
 	goto sendReply;
diff --git a/randr/rrinfo.c b/randr/rrinfo.c
index fdf3726..549ebcc 100644
--- a/randr/rrinfo.c
+++ b/randr/rrinfo.c
@@ -168,7 +168,7 @@ RRScanOldConfig (ScreenPtr pScreen, Rotation rotations)
     /* notice current mode */
     if (newMode)
 	RRCrtcNotify (crtc, newMode, 0, 0, pScrPriv->rotation,
-		      NULL, 1, &output);
+		      NULL, 1, &output, NULL);
 }
 #endif
 
diff --git a/randr/rrpixmap.c b/randr/rrpixmap.c
new file mode 100644
index 0000000..7d4543c
--- /dev/null
+++ b/randr/rrpixmap.c
@@ -0,0 +1,154 @@
+/*
+ * Copyright © 2010 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 "randrstr.h"
+#include "xace.h"
+
+int
+ProcRRQueryScanoutPixmaps (ClientPtr client)
+{
+    REQUEST(xRRQueryScanoutPixmapsReq);
+    xRRQueryScanoutPixmapsReply	rep;
+    RRScanoutPixmapInfo		*info;
+    xRRScanoutPixmapInfo	*x_info;
+    int				n_info;
+    int				rc;
+    DrawablePtr			drawable;
+    ScreenPtr			screen;
+    rrScrPrivPtr		screen_priv;
+    int 			n, s;
+
+    REQUEST_SIZE_MATCH(xRRQueryScanoutPixmapsReq);
+    rc = dixLookupDrawable(&drawable, stuff->drawable, client, 0, DixGetAttrAccess);
+    if (rc != Success) {
+	client->errorValue = stuff->drawable;
+	return rc;
+    }
+
+    screen = drawable->pScreen;
+    screen_priv = rrGetScrPriv(screen);
+
+    rep.type = X_Reply;
+    /* rep.status has already been filled in */
+    rep.length = 0;
+    rep.sequenceNumber = client->sequence;
+
+    info = RRQueryScanoutPixmapInfo(screen, &n_info);
+    x_info = calloc(n_info, sizeof (xRRScanoutPixmapInfo));
+    if (n_info && !x_info)
+	return BadAlloc;
+    rep.length += (n_info * sizeof (xRRScanoutPixmapInfo)) >> 2;
+    if (client->swapped) {
+	swaps(&rep.sequenceNumber, n);
+	swapl(&rep.length, n);
+    }
+
+    for (s = 0; s < n_info; s++) {
+	x_info[s].format = info[s].format->id;
+	x_info[s].maxWidth = info[s].maxWidth;
+	x_info[s].maxHeight = info[s].maxHeight;
+	x_info[s].rotations = info[s].rotations;
+	if (client->swapped) {
+	    swapl(&x_info[s].format, n);
+	    swaps(&x_info[s].maxWidth, n);
+	    swaps(&x_info[s].maxHeight, n);
+	    swaps(&x_info[s].rotations, n);
+	}
+    }
+
+    WriteToClient(client, sizeof(rep), (char *)&rep);
+    if (n_info)
+	WriteToClient(client, n_info * sizeof (xRRScanoutPixmapInfo),
+		      (char *) x_info);
+    return Success;
+}
+
+int
+ProcRRCreateScanoutPixmap (ClientPtr client)
+{
+    REQUEST(xRRCreateScanoutPixmapReq);
+    int 		rc;
+    DrawablePtr		drawable;
+    ScreenPtr		screen;
+    rrScrPrivPtr	screen_priv;
+    PixmapPtr		pixmap;
+    int			n_info;
+    RRScanoutPixmapInfo	*info;
+    int			s;
+
+    REQUEST_SIZE_MATCH(xRRCreateScanoutPixmapReq);
+    client->errorValue = stuff->pid;
+    LEGAL_NEW_RESOURCE(stuff->pid, client);
+
+    rc = dixLookupDrawable(&drawable, stuff->drawable, client, 0, DixGetAttrAccess);
+    if (rc != Success) {
+	client->errorValue = stuff->drawable;
+	return rc;
+    }
+    screen = drawable->pScreen;
+    screen_priv = rrGetScrPriv(screen);
+    if (!screen_priv)
+	return BadValue;
+
+    info = RRQueryScanoutPixmapInfo(screen, &n_info);
+    for (s = 0; s < n_info; s++) {
+	if (info[s].format->id == stuff->format)
+	    break;
+    }
+    if (s == n_info || !screen_priv->rrCreateScanoutPixmap) {
+	client->errorValue = stuff->format;
+	return BadValue;
+    }
+    info = &info[s];
+    if (!stuff->width || stuff->width > info->maxWidth) {
+	client->errorValue = stuff->width;
+	return BadValue;
+    }
+    if (!stuff->height || stuff->height > info->maxHeight) {
+	client->errorValue = stuff->height;
+	return BadValue;
+    }
+    if ((stuff->rotations & info->rotations) != stuff->rotations) {
+	client->errorValue = stuff->rotations;
+	return BadValue;
+    }
+
+    pixmap = screen_priv->rrCreateScanoutPixmap (screen,
+						 stuff->width, stuff->height,
+						 info->depth,
+						 stuff->rotations,
+						 info->format);
+    if (!pixmap)
+	return BadAlloc;
+
+    pixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
+    pixmap->drawable.id = stuff->pid;
+    rc = XaceHook(XACE_RESOURCE_ACCESS, client, stuff->pid, RT_PIXMAP,
+		  pixmap, RT_NONE, NULL, DixCreateAccess);
+    if (rc != Success) {
+	screen->DestroyPixmap(pixmap);
+	return rc;
+    }
+    if (!AddResource(stuff->pid, RT_PIXMAP, pixmap))
+	return BadAlloc;
+    return Success;
+}
diff --git a/randr/rrscreen.c b/randr/rrscreen.c
index 62ea2b6..0c52347 100644
--- a/randr/rrscreen.c
+++ b/randr/rrscreen.c
@@ -794,8 +794,10 @@ ProcRRSetScreenConfig (ClientPtr client)
     }
     
     rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0, DixWriteAccess);
-    if (rc != Success)
+    if (rc != Success) {
+	client->errorValue = stuff->drawable;
 	return rc;
+    }
 
     pScreen = pDraw->pScreen;
 
@@ -940,7 +942,7 @@ ProcRRSetScreenConfig (ClientPtr client)
 	for (c = 0; c < pScrPriv->numCrtcs; c++)
 	{
 	    if (!RRCrtcSet (pScrPriv->crtcs[c], NULL, 0, 0, RR_Rotate_0,
-			    0, NULL))
+			    0, NULL, NULL))
 	    {
 		rep.status = RRSetConfigFailed;
 		/* XXX recover from failure */
@@ -956,7 +958,7 @@ ProcRRSetScreenConfig (ClientPtr client)
 	}
     }
 
-    if (!RRCrtcSet (crtc, mode, 0, 0, stuff->rotation, 1, &output))
+    if (!RRCrtcSet (crtc, mode, 0, 0, stuff->rotation, 1, &output, NULL))
 	rep.status = RRSetConfigFailed;
     else {
 	pScrPriv->lastSetTime = time;
commit 86c489c319c705f710bee3897fe27600ce15008e
Author: Keith Packard <keithp at keithp.com>
Date:   Sat Dec 4 20:12:26 2010 -0800

    hw/xfree86/modes: Add optional driver API for RRSetCrtcConfigs
    
    This provides a driver hook which can either completely replace, or
    just validate the parameters for, the RRSetCrtcConfigs request.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Aaron Plattner <aplattner at nvidia.com>

diff --git a/hw/xfree86/modes/xf86Crtc.h b/hw/xfree86/modes/xf86Crtc.h
index 8b42efc..c2e8131 100644
--- a/hw/xfree86/modes/xf86Crtc.h
+++ b/hw/xfree86/modes/xf86Crtc.h
@@ -647,6 +647,29 @@ struct _xf86Output {
     INT16           initialBorder[4];
 };
 
+typedef enum _xf86SetConfigResponse {
+    xf86SetConfigFailed,		/* set_config failed */
+    xf86SetConfigChecked,		/* set_config validated the configuration */
+    xf86SetConfigDone,			/* set_config finished the work */
+} xf86SetConfigResponse;
+
+typedef struct _xf86CrtcSetConfig {
+    xf86CrtcPtr			crtc;
+    int				x, y;
+    DisplayModeRec		mode;
+    Rotation			rotation;
+    int				numOutputs;
+    xf86OutputPtr		*outputs;
+    struct pict_f_transform	sprite_position_transform;
+    struct pict_f_transform	sprite_image_transform;
+
+    /* Probably want some internal structure for the pixmap so that
+     * this can be set before the server is running
+     */
+    PixmapPtr			pixmap;
+    int				pixmap_x, pixmap_y;
+} xf86CrtcSetConfigRec, *xf86CrtcSetConfigPtr;
+
 typedef struct _xf86CrtcConfigFuncs {
     /**
      * Requests that the driver resize the screen.
@@ -664,6 +687,12 @@ typedef struct _xf86CrtcConfigFuncs {
     (*resize)(ScrnInfoPtr	scrn,
 	      int		width,
 	      int		height);
+
+    xf86SetConfigResponse
+    (*set_config) (ScrnInfoPtr		scrn,
+		   RRScreenConfigPtr	screen_config,
+		   xf86CrtcSetConfigPtr	crtc_configs,
+		   int			num_configs);
 } xf86CrtcConfigFuncsRec, *xf86CrtcConfigFuncsPtr;
 
 typedef void (*xf86_crtc_notify_proc_ptr) (ScreenPtr pScreen);
diff --git a/hw/xfree86/modes/xf86RandR12.c b/hw/xfree86/modes/xf86RandR12.c
index ac58135..e3330f4 100644
--- a/hw/xfree86/modes/xf86RandR12.c
+++ b/hw/xfree86/modes/xf86RandR12.c
@@ -758,7 +758,7 @@ xf86RandR12CreateScreenResources (ScreenPtr pScreen)
 	xf86CrtcPtr crtc = config->crtc[c];
 	int	    crtc_width = crtc->x + xf86ModeWidth (&crtc->mode, crtc->rotation);
 	int	    crtc_height = crtc->y + xf86ModeHeight (&crtc->mode, crtc->rotation);
-	
+
 	if (crtc->enabled) {
 	    if (crtc_width > width)
 		width = crtc_width;
@@ -770,13 +770,13 @@ xf86RandR12CreateScreenResources (ScreenPtr pScreen)
 		height = crtc->panningTotalArea.y2;
 	}
     }
-    
+
     if (width && height)
     {
 	/*
 	 * Compute physical size of screen
 	 */
-	if (monitorResolution) 
+	if (monitorResolution)
 	{
 	    mmWidth = width * 25.4 / monitorResolution;
 	    mmHeight = height * 25.4 / monitorResolution;
@@ -1007,7 +1007,7 @@ xf86RandRModeMatches (RRModePtr		randr_mode,
 	if (memcmp (randr_mode->name, mode->name, len) != 0)	return FALSE;
     }
 #endif
-    
+
     /* check for same timings */
     if (randr_mode->mode.dotClock / 1000 != mode->Clock)    return FALSE;
     if (randr_mode->mode.width        != mode->HDisplay)    return FALSE;
@@ -1019,11 +1019,11 @@ xf86RandRModeMatches (RRModePtr		randr_mode,
     if (randr_mode->mode.vSyncStart   != mode->VSyncStart)  return FALSE;
     if (randr_mode->mode.vSyncEnd     != mode->VSyncEnd)    return FALSE;
     if (randr_mode->mode.vTotal       != mode->VTotal)	    return FALSE;
-    
+
     /* check for same flags (using only the XF86 valid flag bits) */
     if ((randr_mode->mode.modeFlags & FLAG_BITS) != (mode->Flags & FLAG_BITS))
 	return FALSE;
-    
+
     /* everything matches */
     return TRUE;
 }
@@ -1063,7 +1063,7 @@ xf86RandR12CrtcNotify (RRCrtcPtr	randr_crtc)
 	    randr_output = output->randr_output;
 	    randr_outputs[numOutputs++] = randr_output;
 	    /*
-	     * We make copies of modes, so pointer equality 
+	     * We make copies of modes, so pointer equality
 	     * isn't sufficient
 	     */
 	    for (j = 0; j < randr_output->numModes + randr_output->numUserModes; j++)
@@ -1071,7 +1071,7 @@ xf86RandR12CrtcNotify (RRCrtcPtr	randr_crtc)
 		RRModePtr   m = (j < randr_output->numModes ?
 				 randr_output->modes[j] :
 				 randr_output->userModes[j-randr_output->numModes]);
-					 
+
 		if (xf86RandRModeMatches (m, mode))
 		{
 		    randr_mode = m;
@@ -1081,7 +1081,7 @@ xf86RandR12CrtcNotify (RRCrtcPtr	randr_crtc)
 	}
     }
     ret = RRCrtcNotify (randr_crtc, randr_mode, x, y,
-			rotation, 
+			rotation,
 			crtc->transformPresent ? &crtc->transform : NULL,
 			numOutputs, randr_outputs);
     free(randr_outputs);
@@ -1100,13 +1100,13 @@ xf86RandRModeConvert (ScrnInfoPtr	scrn,
     mode->status = MODE_OK;
 
     mode->Clock = randr_mode->mode.dotClock / 1000;
-    
+
     mode->HDisplay = randr_mode->mode.width;
     mode->HSyncStart = randr_mode->mode.hSyncStart;
     mode->HSyncEnd = randr_mode->mode.hSyncEnd;
     mode->HTotal = randr_mode->mode.hTotal;
     mode->HSkew = randr_mode->mode.hSkew;
-    
+
     mode->VDisplay = randr_mode->mode.height;
     mode->VSyncStart = randr_mode->mode.vSyncStart;
     mode->VSyncEnd = randr_mode->mode.vSyncEnd;
@@ -1146,7 +1146,7 @@ xf86RandR12CrtcSet (ScreenPtr	    pScreen,
 	flags |= XF86CrtcSetMode;
     else if (randr_mode && !xf86RandRModeMatches (randr_mode, &crtc->mode))
 	flags |= XF86CrtcSetMode;
-    
+
     if (rotation != crtc->rotation)
 	flags |= XF86CrtcSetRotation;
 
@@ -1159,18 +1159,18 @@ xf86RandR12CrtcSet (ScreenPtr	    pScreen,
 
     if (x != crtc->x || y != crtc->y)
 	flags |= XF86CrtcSetOrigin;
-    for (o = 0; o < config->num_output; o++) 
+    for (o = 0; o < config->num_output; o++)
     {
 	xf86OutputPtr  output = config->output[o];
 	xf86CrtcPtr    new_crtc;
 
 	save_crtcs[o] = output->crtc;
-	
+
 	if (output->crtc == crtc)
 	    new_crtc = NULL;
 	else
 	    new_crtc = output->crtc;
-	for (ro = 0; ro < num_randr_outputs; ro++) 
+	for (ro = 0; ro < num_randr_outputs; ro++)
 	    if (output->randr_output == randr_outputs[ro])
 	    {
 		new_crtc = crtc;
@@ -1182,7 +1182,7 @@ xf86RandR12CrtcSet (ScreenPtr	    pScreen,
 	    output->crtc = new_crtc;
 	}
     }
-    for (ro = 0; ro < num_randr_outputs; ro++) 
+    for (ro = 0; ro < num_randr_outputs; ro++)
         if (randr_outputs[ro]->pendingProperties)
 	    flags |= XF86CrtcSetProperty;
 
@@ -1385,7 +1385,7 @@ xf86RROutputSetModes (RROutputPtr randr_output, DisplayModePtr modes)
 
     if (nmode) {
 	rrmodes = malloc(nmode * sizeof (RRModePtr));
-	
+
 	if (!rrmodes)
 	    return FALSE;
 	nmode = 0;
@@ -1395,7 +1395,7 @@ xf86RROutputSetModes (RROutputPtr randr_output, DisplayModePtr modes)
 		if ((pref != 0) == ((mode->type & M_T_PREFERRED) != 0)) {
 		    xRRModeInfo		modeInfo;
 		    RRModePtr		rrmode;
-		    
+
 		    modeInfo.nameLength = strlen (mode->name);
 		    modeInfo.width = mode->HDisplay;
 		    modeInfo.dotClock = mode->Clock * 1000;
@@ -1419,7 +1419,7 @@ xf86RROutputSetModes (RROutputPtr randr_output, DisplayModePtr modes)
 	    }
 	}
     }
-    
+
     ret = RROutputSetModes (randr_output, rrmodes, nmode, npreferred);
     free(rrmodes);
     return ret;
@@ -1439,13 +1439,13 @@ xf86RandR12SetInfo12 (ScreenPtr pScreen)
     int			o, c, l;
     RRCrtcPtr		randr_crtc;
     int			nclone;
-    
+
     clones = malloc(config->num_output * sizeof (RROutputPtr));
     crtcs = malloc(config->num_crtc * sizeof (RRCrtcPtr));
     for (o = 0; o < config->num_output; o++)
     {
 	xf86OutputPtr	output = config->output[o];
-	
+
 	ncrtc = 0;
 	for (c = 0; c < config->num_crtc; c++)
 	    if (output->possible_crtcs & (1 << c))
@@ -1463,7 +1463,7 @@ xf86RandR12SetInfo12 (ScreenPtr pScreen)
 	    return FALSE;
 	}
 
-	RROutputSetPhysicalSize(output->randr_output, 
+	RROutputSetPhysicalSize(output->randr_output,
 				output->mm_width,
 				output->mm_height);
 	xf86RROutputSetModes (output->randr_output, output->probed_modes);
@@ -1489,7 +1489,7 @@ xf86RandR12SetInfo12 (ScreenPtr pScreen)
 	for (l = 0; l < config->num_output; l++)
 	{
 	    xf86OutputPtr	    clone = config->output[l];
-	    
+
 	    if (l != o && (output->possible_clones & (1 << l)))
 		clones[nclone++] = clone->randr_output;
 	}
@@ -1530,7 +1530,7 @@ xf86RandR12CreateObjects12 (ScreenPtr pScreen)
     xf86CrtcConfigPtr   config = XF86_CRTC_CONFIG_PTR(pScrn);
     int			c;
     int			o;
-    
+
     if (!RRInit ())
 	return FALSE;
 
@@ -1540,7 +1540,7 @@ xf86RandR12CreateObjects12 (ScreenPtr pScreen)
     for (c = 0; c < config->num_crtc; c++)
     {
 	xf86CrtcPtr    crtc = config->crtc[c];
-	
+
 	crtc->randr_crtc = RRCrtcCreate (pScreen, crtc);
 	RRCrtcGammaSetSize (crtc->randr_crtc, 256);
     }
@@ -1551,7 +1551,7 @@ xf86RandR12CreateObjects12 (ScreenPtr pScreen)
     {
 	xf86OutputPtr	output = config->output[o];
 
-	output->randr_output = RROutputCreate (pScreen, output->name, 
+	output->randr_output = RROutputCreate (pScreen, output->name,
 					       strlen (output->name),
 					       output);
 
@@ -1574,7 +1574,7 @@ xf86RandR12CreateScreenResources12 (ScreenPtr pScreen)
 
     for (c = 0; c < config->num_crtc; c++)
         xf86RandR12CrtcNotify (config->crtc[c]->randr_crtc);
-    
+
     RRScreenSetSizeRange (pScreen, config->minWidth, config->minHeight,
 			  config->maxWidth, config->maxHeight);
     return TRUE;
@@ -1747,6 +1747,112 @@ xf86RandR14SetCrtcSpriteTransform(ScreenPtr		pScreen,
 }
 
 static Bool
+xf86RRConvertCrtcConfig(xf86CrtcSetConfigPtr	xf86_config,
+			RRCrtcConfigPtr		rr_config)
+{
+    RRCrtcPtr		rr_crtc = rr_config->crtc;
+    xf86CrtcPtr		crtc = rr_crtc->devPrivate;
+    ScrnInfoPtr		scrn = xf86Screens[rr_crtc->pScreen->myNum];
+    int			o;
+
+    xf86_config->crtc = crtc;
+    xf86_config->x = rr_config->x;
+    xf86_config->y = rr_config->y;
+    xf86RandRModeConvert(scrn, rr_config->mode, &xf86_config->mode);
+    xf86_config->rotation = rr_config->rotation;
+    xf86_config->numOutputs = rr_config->numOutputs;
+    xf86_config->outputs = calloc(rr_config->numOutputs, sizeof (xf86OutputPtr));
+    if (!xf86_config->outputs)
+	return FALSE;
+    for (o = 0; o < rr_config->numOutputs; o++)
+	xf86_config->outputs[o] = rr_config->outputs[o]->devPrivate;
+    xf86_config->sprite_position_transform = rr_config->sprite_position_transform;
+    xf86_config->sprite_image_transform = rr_config->sprite_image_transform;
+    xf86_config->pixmap = rr_config->pixmap;
+    xf86_config->pixmap_x = rr_config->pixmap_x;
+    xf86_config->pixmap_y = rr_config->pixmap_y;
+    return TRUE;
+}
+
+static void
+xf86FreeCrtcSetConfigs(xf86CrtcSetConfigPtr xf86_crtc_configs, int num_configs)
+{
+    int	i;
+
+    for (i = 0; i < num_configs; i++)
+	free(xf86_crtc_configs[i].outputs);
+    free(xf86_crtc_configs);
+}
+
+static Bool
+xf86RRSetCrtcConfigs(ScreenPtr screen,
+		     RRScreenConfigPtr screen_config,
+		     RRCrtcConfigPtr crtc_configs,
+		     int num_configs)
+{
+    ScrnInfoPtr	     		scrn = xf86Screens[screen->myNum];
+    xf86CrtcConfigPtr		config = XF86_CRTC_CONFIG_PTR(scrn);
+
+    if (config->funcs->set_config) {
+	xf86CrtcSetConfigPtr	xf86_crtc_configs;
+	int			i;
+	xf86SetConfigResponse	response;
+
+	/*
+	 * Convert RRCrtcConfigRecs to xf86CrtcSetConfigs
+	 */
+	xf86_crtc_configs = calloc(num_configs, sizeof (xf86CrtcSetConfigRec));
+	if (!xf86_crtc_configs)
+	    return FALSE;
+	for (i = 0; i < num_configs; i++)
+	    if (!xf86RRConvertCrtcConfig(&xf86_crtc_configs[i], &crtc_configs[i])) {
+		xf86FreeCrtcSetConfigs(xf86_crtc_configs, num_configs);
+		return FALSE;
+	    }
+
+	/*
+	 * Ask the driver to set the configuration
+	 */
+	response = (*config->funcs->set_config)(scrn,
+						screen_config,
+						xf86_crtc_configs,
+						num_configs);
+	xf86FreeCrtcSetConfigs(xf86_crtc_configs, num_configs);
+
+	/*
+	 * The driver is allowed to answer with one of three
+	 * responses:
+	 */
+	switch (response) {
+	case xf86SetConfigFailed:
+
+	    /* The configuration isn't usable, or some error
+	     * occurred while setting it. Everything has been
+	     * cleaned up and we're ready to return an error
+	     * back to the client
+	     */
+	    return FALSE;
+	case xf86SetConfigDone:
+
+	    /* The configuration was acceptable, and the whole
+	     * mode setting experience is over. Nothing more to do
+	     * here.
+	     */
+	    return TRUE;
+	case xf86SetConfigChecked:
+
+	    /* The configuration was acceptable, but the driver
+	     * didn't actually do anything. Go ask the DIX code
+	     * to do the mode setting operation using the simpler
+	     * interfaces
+	     */
+	    break;
+	}
+    }
+    return miRRSetCrtcConfigs(screen, screen_config, crtc_configs, num_configs);
+}
+
+static Bool
 xf86RandR12EnterVT (int screen_index, int flags)
 {
     ScreenPtr        pScreen = screenInfo.screens[screen_index];
@@ -1797,7 +1903,7 @@ xf86RandR12Init12 (ScreenPtr pScreen)
     pScrn->PointerMoved = xf86RandR12PointerMoved;
     pScrn->ChangeGamma = xf86RandR12ChangeGamma;
     rp->rrSetCrtcSpriteTransform = xf86RandR14SetCrtcSpriteTransform;
-    rp->rrSetCrtcConfigs = miRRSetCrtcConfigs;
+    rp->rrSetCrtcConfigs = xf86RRSetCrtcConfigs;
 
     randrp->orig_EnterVT = pScrn->EnterVT;
     pScrn->EnterVT = xf86RandR12EnterVT;
commit d94a035ea9eb3167fc4f35b2d9f0d53f8807014c
Author: Keith Packard <keithp at keithp.com>
Date:   Sat Dec 4 19:22:11 2010 -0800

    randr: Implement RRSetCrtcConfigs
    
    This provides a driver-independent implementation of the
    RRSetCrtcConfigs API by simply using the existing interfaces.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Aaron Plattner <aplattner at nvidia.com>

diff --git a/hw/xfree86/modes/xf86RandR12.c b/hw/xfree86/modes/xf86RandR12.c
index bbf28cd..ac58135 100644
--- a/hw/xfree86/modes/xf86RandR12.c
+++ b/hw/xfree86/modes/xf86RandR12.c
@@ -1797,6 +1797,7 @@ xf86RandR12Init12 (ScreenPtr pScreen)
     pScrn->PointerMoved = xf86RandR12PointerMoved;
     pScrn->ChangeGamma = xf86RandR12ChangeGamma;
     rp->rrSetCrtcSpriteTransform = xf86RandR14SetCrtcSpriteTransform;
+    rp->rrSetCrtcConfigs = miRRSetCrtcConfigs;
 
     randrp->orig_EnterVT = pScrn->EnterVT;
     pScrn->EnterVT = xf86RandR12EnterVT;
diff --git a/randr/Makefile.am b/randr/Makefile.am
index 4b38e52..a1c88dc 100644
--- a/randr/Makefile.am
+++ b/randr/Makefile.am
@@ -22,7 +22,9 @@ librandr_la_SOURCES =	\
 	rrsdispatch.c	\
 	rrsprite.c	\
 	rrtransform.h	\
-	rrtransform.c
+	rrtransform.c	\
+	mirrcrtc.c
+
 
 if XINERAMA
 librandr_la_SOURCES += ${XINERAMA_SRCS}
diff --git a/randr/mirrcrtc.c b/randr/mirrcrtc.c
new file mode 100644
index 0000000..b1e2c9f
--- /dev/null
+++ b/randr/mirrcrtc.c
@@ -0,0 +1,169 @@
+/*
+ * Copyright © 2010 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 "randrstr.h"
+
+Bool
+miRRSetScreenConfig(ScreenPtr screen,
+		    RRScreenConfigPtr screen_config)
+{
+    RRScreenConfigRec	old_screen_config;
+
+    /* XXX deal with separate pixmap/screen sizes */
+    if (screen_config->screen_pixmap_width != screen_config->screen_width ||
+	screen_config->screen_pixmap_height != screen_config->screen_height)
+	return FALSE;
+
+    RRScreenCurrentConfig(screen, &old_screen_config);
+
+    /* Check and see if nothing has changed */
+    if (old_screen_config.screen_width == screen_config->screen_width &&
+	old_screen_config.screen_height == screen_config->screen_height &&
+	old_screen_config.screen_pixmap_width == screen_config->screen_pixmap_width &&
+	old_screen_config.screen_pixmap_height == screen_config->screen_pixmap_height &&
+	old_screen_config.mm_width == screen_config->mm_width &&
+	old_screen_config.mm_height == screen_config->mm_height)
+	return TRUE;
+
+    return RRScreenSizeSet(screen,
+			   screen_config->screen_width,
+			   screen_config->screen_height,
+			   screen_config->mm_width,
+			   screen_config->mm_height);
+}
+
+Bool
+miRRSetCrtcConfig(RRCrtcConfigPtr crtc_config)
+{
+    int	x = crtc_config->x, y = crtc_config->y;
+
+    if (crtc_config->pixmap) {
+	x = crtc_config->pixmap_x;
+	y = crtc_config->pixmap_y;
+    }
+    return RRCrtcSet(crtc_config->crtc,
+		     crtc_config->mode,
+		     x,
+		     y,
+		     crtc_config->rotation,
+		     crtc_config->numOutputs,
+		     crtc_config->outputs);
+}
+
+Bool
+miRRDisableCrtc(RRCrtcPtr crtc)
+{
+    RRCrtcConfigRec	off_config;
+
+    memset(&off_config, '\0', sizeof (RRCrtcConfigRec));
+    off_config.crtc = crtc;
+    return miRRSetCrtcConfig(&off_config);
+}
+
+/*
+ * If the current crtc configuration doesn't fit
+ * with the new screen config, disable it
+ */
+Bool
+miRRCheckDisableCrtc(RRScreenConfigPtr new_screen_config,
+		     RRCrtcConfigPtr old_crtc_config)
+{
+    RRCrtcPtr crtc = old_crtc_config->crtc;
+
+    /* If it's already disabled, we're done */
+    if (!old_crtc_config->mode)
+	return TRUE;
+
+    /* If the crtc isn't scanning from the screen pixmap,
+     * we're done
+     */
+    if (old_crtc_config->pixmap)
+	return TRUE;
+
+    /* If the new screen configuration covers the existing CRTC space,
+     * we're done
+     */
+    if (RRScreenCoversCrtc(new_screen_config, old_crtc_config,
+			   &crtc->client_current_transform, NULL))
+	return TRUE;
+
+    /* Disable the crtc and let it get re-enabled */
+    return miRRDisableCrtc(crtc);
+}
+
+Bool
+miRRSetCrtcConfigs(ScreenPtr screen,
+		   RRScreenConfigPtr screen_config,
+		   RRCrtcConfigPtr crtc_configs,
+		   int num_configs)
+{
+    RRScreenConfigRec	old_screen_config;
+    RRCrtcConfigPtr	old_crtc_configs;
+    int			i;
+
+    /*
+     * Save existing state
+     */
+
+    RRScreenCurrentConfig(screen, &old_screen_config);
+    old_crtc_configs = calloc(num_configs, sizeof (RRCrtcConfigRec));
+    if (!old_crtc_configs)
+	return FALSE;
+
+    for (i = 0; i < num_configs; i++)
+	if (!RRCrtcCurrentConfig(crtc_configs[i].crtc, &old_crtc_configs[i]))
+	    goto fail_save;
+    /*
+     * Set the new configuration. If anything goes wrong,
+     * bail and restore the old configuration
+     */
+    for (i = 0; i < num_configs; i++)
+	if (!miRRCheckDisableCrtc(screen_config, &old_crtc_configs[i]))
+	    goto fail_disable;
+
+    if (!miRRSetScreenConfig(screen, screen_config))
+	goto fail_set_screen;
+
+    for (i = 0; i < num_configs; i++)
+	if (!miRRSetCrtcConfig(&crtc_configs[i]))
+	    goto fail_set_crtc;
+
+    RRFreeCrtcConfigs(old_crtc_configs, num_configs);
+    return TRUE;
+
+fail_set_crtc:
+    /*
+     * Restore the previous configuration. Ignore any errors
+     * as we just need to hope that the driver can manage to
+     * get back to the previous state without trouble.
+     */
+    for (i = 0; i < num_configs; i++)
+	(void) miRRDisableCrtc(old_crtc_configs[i].crtc);
+    (void) miRRSetScreenConfig(screen, &old_screen_config);
+fail_set_screen:
+fail_disable:
+    for (i = 0; i < num_configs; i++)
+	(void) miRRSetCrtcConfig(&old_crtc_configs[i]);
+fail_save:
+    RRFreeCrtcConfigs(old_crtc_configs, num_configs);
+    return FALSE;
+}
diff --git a/randr/randrstr.h b/randr/randrstr.h
index 5e2a351..2fe9602 100644
--- a/randr/randrstr.h
+++ b/randr/randrstr.h
@@ -78,6 +78,8 @@ typedef struct _rrMode		RRModeRec, *RRModePtr;
 typedef struct _rrPropertyValue	RRPropertyValueRec, *RRPropertyValuePtr;
 typedef struct _rrProperty	RRPropertyRec, *RRPropertyPtr;
 typedef struct _rrCrtc		RRCrtcRec, *RRCrtcPtr;
+typedef struct _rrScreenConfig	RRScreenConfigRec, *RRScreenConfigPtr;
+typedef struct _rrCrtcConfig	RRCrtcConfigRec, *RRCrtcConfigPtr;
 typedef struct _rrOutput	RROutputRec, *RROutputPtr;
 
 struct _rrMode {
@@ -135,6 +137,28 @@ struct _rrCrtc {
     struct pict_f_transform f_sprite_image_inverse;	/* image from crtc */
 };
 
+struct _rrScreenConfig {
+    CARD16			screen_pixmap_width;
+    CARD16			screen_pixmap_height;
+    CARD16			screen_width;
+    CARD16			screen_height;
+    CARD32			mm_width;
+    CARD32			mm_height;
+};
+
+struct _rrCrtcConfig {
+    RRCrtcPtr			crtc;
+    int				x, y;
+    RRModePtr			mode;
+    Rotation			rotation;
+    int				numOutputs;
+    RROutputPtr			*outputs;
+    struct pict_f_transform	sprite_position_transform;
+    struct pict_f_transform	sprite_image_transform;
+    PixmapPtr			pixmap;
+    int				pixmap_x, pixmap_y;
+};
+
 struct _rrOutput {
     RROutput	    id;
     ScreenPtr	    pScreen;
@@ -251,6 +275,11 @@ typedef void (*RRGetCrtcSpriteTransformPtr) (ScreenPtr pScreen,
 					     struct pict_f_transform *position_transform,
 					     struct pict_f_transform *image_transform);
 
+typedef Bool (*RRSetCrtcConfigsPtr) (ScreenPtr screen,
+				     RRScreenConfigPtr screen_config,
+				     RRCrtcConfigPtr crtc_configs,
+				     int num_configs);
+
 typedef struct _rrScrPriv {
     /*
      * 'public' part of the structure; DDXen fill this in
@@ -276,6 +305,7 @@ typedef struct _rrScrPriv {
 #endif
     RRSetCrtcSpriteTransformPtr	rrSetCrtcSpriteTransform;
     RRGetCrtcSpriteTransformPtr	rrGetCrtcSpriteTransform;
+    RRSetCrtcConfigsPtr rrSetCrtcConfigs;
 
     /*
      * Private part of the structure; not considered part of the ABI
@@ -428,6 +458,10 @@ RRScreenSizeSet (ScreenPtr  pScreen,
 		 CARD32	    mmWidth,
 		 CARD32	    mmHeight);
 
+extern _X_EXPORT void
+RRScreenCurrentConfig(ScreenPtr screen,
+		      RRScreenConfigPtr screen_config);
+
 /*
  * Send ConfigureNotify event to root window when 'something' happens
  */
@@ -671,6 +705,38 @@ extern _X_EXPORT void
 RRCrtcInitErrorValue (void);
 
 /*
+ * Free a set of crtc configs and their attached output arrays
+ */
+void
+RRFreeCrtcConfigs(RRCrtcConfigPtr configs, int num_configs);
+
+/*
+ * Convert the current crtc configuration into an RRCrtcConfig
+ */
+extern _X_EXPORT Bool
+RRCrtcCurrentConfig(RRCrtcPtr crtc,
+		    RRCrtcConfigPtr crtc_config);
+
+/*
+ * Figure out whether the specific crtc_config can fit
+ * within the screen_config
+ */
+Bool
+RRScreenCoversCrtc(RRScreenConfigPtr screen_config,
+		   RRCrtcConfigPtr crtc_config,
+		   RRTransformPtr client_transform,
+		   XID *errorValue);
+
+/*
+ * Set a screen and set of crtc configurations in one operation
+ */
+Bool
+RRSetCrtcConfigs(ScreenPtr screen,
+		 RRScreenConfigPtr screen_config,
+		 RRCrtcConfigPtr crtc_configs,
+		 int num_configs);
+
+/*
  * Crtc dispatch
  */
 
@@ -695,6 +761,9 @@ ProcRRSetCrtcTransform (ClientPtr client);
 extern _X_EXPORT int
 ProcRRGetCrtcTransform (ClientPtr client);
 
+extern _X_EXPORT int
+ProcRRSetCrtcConfigs (ClientPtr client);
+
 int
 ProcRRGetPanning (ClientPtr client);
 
@@ -916,6 +985,27 @@ extern _X_EXPORT void
 RRXineramaExtensionInit(void);
 #endif
 
+/* mirrcrtc.c */
+Bool
+miRRSetScreenConfig(ScreenPtr screen,
+		    RRScreenConfigPtr screen_config);
+
+Bool
+miRRSetCrtcConfig(RRCrtcConfigPtr crtc_config);
+
+Bool
+miRRDisableCrtc(RRCrtcPtr crtc);
+
+Bool
+miRRCheckDisableCrtc(RRScreenConfigPtr new_screen_config,
+		     RRCrtcConfigPtr old_crtc_config);
+
+Bool
+miRRSetCrtcConfigs(ScreenPtr screen,
+		   RRScreenConfigPtr screen_config,
+		   RRCrtcConfigPtr crtc_configs,
+		   int num_configs);
+
 #endif /* _RANDRSTR_H_ */
 
 /*
diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
index c2f6963..1f8f2e6 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -37,7 +37,7 @@ RRCrtcChanged (RRCrtcPtr crtc, Bool layoutChanged)
     if (pScreen)
     {
 	rrScrPriv(pScreen);
-    
+
 	pScrPriv->changed = TRUE;
 	/*
 	 * Send ConfigureNotify on any layout change
@@ -59,19 +59,19 @@ RRCrtcCreate (ScreenPtr pScreen, void *devPrivate)
 
     if (!RRInit())
 	return NULL;
-    
+
     pScrPriv = rrGetScrPriv(pScreen);
 
     /* make space for the crtc pointer */
     if (pScrPriv->numCrtcs)
-	crtcs = realloc(pScrPriv->crtcs, 
+	crtcs = realloc(pScrPriv->crtcs,
 			  (pScrPriv->numCrtcs + 1) * sizeof (RRCrtcPtr));
     else
 	crtcs = malloc(sizeof (RRCrtcPtr));
     if (!crtcs)
 	return FALSE;
     pScrPriv->crtcs = crtcs;
-    
+
     crtc = calloc(1, sizeof (RRCrtcRec));
     if (!crtc)
 	return NULL;
@@ -90,6 +90,8 @@ RRCrtcCreate (ScreenPtr pScreen, void *devPrivate)
     crtc->devPrivate = devPrivate;
     RRTransformInit (&crtc->client_pending_transform);
     RRTransformInit (&crtc->client_current_transform);
+    pixman_transform_init_identity (&crtc->client_sprite_position_transform);
+    pixman_transform_init_identity (&crtc->client_sprite_image_transform);
     pixman_transform_init_identity (&crtc->transform);
     pixman_f_transform_init_identity (&crtc->f_transform);
     pixman_f_transform_init_identity (&crtc->f_inverse);
@@ -102,7 +104,7 @@ RRCrtcCreate (ScreenPtr pScreen, void *devPrivate)
     /* attach the screen and crtc together */
     crtc->pScreen = pScreen;
     pScrPriv->crtcs[pScrPriv->numCrtcs++] = crtc;
-    
+
     return crtc;
 }
 
@@ -139,7 +141,7 @@ RRCrtcNotify (RRCrtcPtr	    crtc,
 	      RROutputPtr   *outputs)
 {
     int	    i, j;
-    
+
     /*
      * Check to see if any of the new outputs were
      * not in the old list and mark them as changed
@@ -179,7 +181,7 @@ RRCrtcNotify (RRCrtcPtr	    crtc,
     if (numOutputs != crtc->numOutputs)
     {
 	RROutputPtr *newoutputs;
-	
+
 	if (numOutputs)
 	{
 	    if (crtc->numOutputs)
@@ -258,7 +260,7 @@ RRDeliverCrtcEvent (ClientPtr client, WindowPtr pWin, RRCrtcPtr crtc)
     rrScrPriv (pScreen);
     xRRCrtcChangeNotifyEvent	ce;
     RRModePtr	mode = crtc->mode;
-    
+
     ce.type = RRNotify + RREventBase;
     ce.subCode = RRNotify_CrtcChange;
     ce.timestamp = pScrPriv->lastSetTime.milliseconds;
@@ -333,7 +335,7 @@ RRCrtcSet (RRCrtcPtr    crtc,
 #if RANDR_12_INTERFACE
 	if (pScrPriv->rrCrtcSet)
 	{
-	    ret = (*pScrPriv->rrCrtcSet) (pScreen, crtc, mode, x, y, 
+	    ret = (*pScrPriv->rrCrtcSet) (pScreen, crtc, mode, x, y,
 					  rotation, numOutputs, outputs);
 	}
 	else
@@ -392,6 +394,59 @@ RRCrtcSet (RRCrtcPtr    crtc,
     return ret;
 }
 
+void
+RRFreeCrtcConfigs(RRCrtcConfigPtr configs, int num_configs)
+{
+    int	i;
+
+    for (i = 0; i < num_configs; i++)
+	free(configs[i].outputs);
+    free(configs);
+}
+
+Bool
+RRCrtcCurrentConfig(RRCrtcPtr crtc,
+		    RRCrtcConfigPtr crtc_config)
+{
+    crtc_config->crtc = crtc;
+    crtc_config->x = crtc->x;
+    crtc_config->y = crtc->y;
+    crtc_config->mode = crtc->mode;
+    crtc_config->rotation = crtc->rotation;
+    crtc_config->numOutputs = crtc->numOutputs;
+    crtc_config->outputs = calloc(crtc->numOutputs, sizeof (RROutputPtr));
+    if (!crtc_config->outputs)
+	return FALSE;
+    memcpy(crtc_config->outputs, crtc->outputs, crtc->numOutputs * sizeof (RROutputPtr));
+    crtc_config->sprite_position_transform = crtc->client_sprite_f_position_transform;
+    crtc_config->sprite_image_transform = crtc->client_sprite_f_image_transform;
+
+    /* XXX add pixmap stuff */
+    crtc_config->pixmap = NULL;
+    crtc_config->pixmap_x = 0;
+    crtc_config->pixmap_y = 0;
+    return TRUE;
+}
+
+
+/*
+ * Request that a set of crtcs be configured at the same
+ * time on a single screen
+ */
+
+Bool
+RRSetCrtcConfigs(ScreenPtr screen,
+		 RRScreenConfigPtr screen_config,
+		 RRCrtcConfigPtr crtc_configs,
+		 int num_configs)
+{
+    rrScrPrivPtr	scr_priv = rrGetScrPriv(screen);
+
+    if (!scr_priv)
+	return FALSE;
+    return (*scr_priv->rrSetCrtcConfigs)(screen, screen_config, crtc_configs, num_configs);
+}
+
 /*
  * Return crtc transform
  */
@@ -435,7 +490,7 @@ RRCrtcDestroyResource (pointer value, XID pid)
     {
 	rrScrPriv(pScreen);
 	int		i;
-    
+
 	for (i = 0; i < pScrPriv->numCrtcs; i++)
 	{
 	    if (pScrPriv->crtcs[i] == crtc)
@@ -468,7 +523,7 @@ RRCrtcGammaSet (RRCrtcPtr   crtc,
 #if RANDR_12_INTERFACE
     ScreenPtr	pScreen = crtc->pScreen;
 #endif
-    
+
     memcpy (crtc->gammaRed, red, crtc->gammaSize * sizeof (CARD16));
     memcpy (crtc->gammaGreen, green, crtc->gammaSize * sizeof (CARD16));
     memcpy (crtc->gammaBlue, blue, crtc->gammaSize * sizeof (CARD16));
@@ -631,6 +686,44 @@ RRCrtcTransformSet (RRCrtcPtr		crtc,
 }
 
 /*
+ * Figure out whether the specific crtc_config can fit
+ * within the screen_config
+ */
+Bool
+RRScreenCoversCrtc(RRScreenConfigPtr screen_config,
+		   RRCrtcConfigPtr crtc_config,
+		   RRTransformPtr client_transform,
+		   XID *errorValue)
+{
+    int source_width;
+    int	source_height;
+    struct pixman_f_transform f_transform;
+
+    RRTransformCompute (crtc_config->x, crtc_config->y,
+			crtc_config->mode->mode.width, crtc_config->mode->mode.height,
+			crtc_config->rotation,
+			client_transform,
+			&crtc_config->sprite_position_transform,
+			&crtc_config->sprite_image_transform,
+			NULL, &f_transform, NULL, NULL, NULL, NULL);
+
+    RRModeGetScanoutSize (crtc_config->mode, &f_transform,
+			  &source_width, &source_height);
+    if (crtc_config->x + source_width > screen_config->screen_pixmap_width) {
+	if (errorValue)
+	    *errorValue = crtc_config->x;
+	return FALSE;
+    }
+
+    if (crtc_config->y + source_height > screen_config->screen_pixmap_height) {
+	if (errorValue)
+	    *errorValue = crtc_config->y;
+	return FALSE;
+    }
+    return TRUE;
+}
+
+/*
  * Initialize crtc type
  */
 Bool
@@ -639,7 +732,7 @@ RRCrtcInit (void)
     RRCrtcType = CreateNewResourceType (RRCrtcDestroyResource, "CRTC");
     if (!RRCrtcType)
 	return FALSE;
-    
+
     return TRUE;
 }
 
@@ -668,7 +761,7 @@ ProcRRGetCrtcInfo (ClientPtr client)
     int				i, j, k, n;
     int				width, height;
     BoxRec			panned_area;
-    
+
     REQUEST_SIZE_MATCH(xRRGetCrtcInfoReq);
     VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess);
 
@@ -679,7 +772,7 @@ ProcRRGetCrtcInfo (ClientPtr client)
     pScrPriv = rrGetScrPriv(pScreen);
 
     mode = crtc->mode;
-    
+
     rep.type = X_Reply;
     rep.status = RRSetConfigSuccess;
     rep.sequenceNumber = client->sequence;
@@ -712,7 +805,7 @@ ProcRRGetCrtcInfo (ClientPtr client)
 	    if (pScrPriv->outputs[i]->crtcs[j] == crtc)
 		k++;
     rep.nPossibleOutput = k;
-    
+
     rep.length = rep.nOutput + rep.nPossibleOutput;
 
     extraLen = rep.length << 2;
@@ -727,7 +820,7 @@ ProcRRGetCrtcInfo (ClientPtr client)
 
     outputs = (RROutput *) extra;
     possible = (RROutput *) (outputs + rep.nOutput);
-    
+
     for (i = 0; i < crtc->numOutputs; i++)
     {
 	outputs[i] = crtc->outputs[i]->id;
@@ -744,7 +837,7 @@ ProcRRGetCrtcInfo (ClientPtr client)
 		    swapl (&possible[k], n);
 		k++;
 	    }
-    
+
     if (client->swapped) {
 	swaps(&rep.sequenceNumber, n);
 	swapl(&rep.length, n);
@@ -765,7 +858,7 @@ ProcRRGetCrtcInfo (ClientPtr client)
 	WriteToClient (client, extraLen, (char *) extra);
 	free(extra);
     }
-    
+
     return Success;
 }
 
@@ -785,10 +878,10 @@ ProcRRSetCrtcConfig (ClientPtr client)
     TimeStamp		    time;
     Rotation		    rotation;
     int			    rc, i, j;
-    
+
     REQUEST_AT_LEAST_SIZE(xRRSetCrtcConfigReq);
     numOutputs = (stuff->length - bytes_to_int32(SIZEOF (xRRSetCrtcConfigReq)));
-    
+
     VERIFY_RR_CRTC(stuff->crtc, crtc, DixSetAttrAccess);
 
     if (stuff->mode == None)
@@ -811,7 +904,7 @@ ProcRRSetCrtcConfig (ClientPtr client)
     }
     else
 	outputs = NULL;
-    
+
     outputIds = (RROutput *) (stuff + 1);
     for (i = 0; i < numOutputs; i++)
     {
@@ -834,7 +927,7 @@ ProcRRSetCrtcConfig (ClientPtr client)
 	/* validate mode for this output */
 	for (j = 0; j < outputs[i]->numModes + outputs[i]->numUserModes; j++)
 	{
-	    RRModePtr	m = (j < outputs[i]->numModes ? 
+	    RRModePtr	m = (j < outputs[i]->numModes ?
 			     outputs[i]->modes[j] :
 			     outputs[i]->userModes[j - outputs[i]->numModes]);
 	    if (m == mode)
@@ -869,17 +962,17 @@ ProcRRSetCrtcConfig (ClientPtr client)
 
     pScreen = crtc->pScreen;
     pScrPriv = rrGetScrPriv(pScreen);
-    
+
     time = ClientTimeToServerTime(stuff->timestamp);
     configTime = ClientTimeToServerTime(stuff->configTimestamp);
-    
+
     if (!pScrPriv)
     {
 	time = currentTime;
 	rep.status = RRSetConfigFailed;
 	goto sendReply;
     }
-    
+
     /*
      * Validate requested rotation
      */
@@ -912,7 +1005,7 @@ ProcRRSetCrtcConfig (ClientPtr client)
 	    free(outputs);
 	    return BadMatch;
 	}
-    
+
 #ifdef RANDR_12_INTERFACE
 	/*
 	 * Check screen size bounds if the DDX provides a 1.2 interface
@@ -944,7 +1037,7 @@ ProcRRSetCrtcConfig (ClientPtr client)
 		free(outputs);
 		return BadValue;
 	    }
-	    
+
 	    if (stuff->y + source_height > pScreen->height)
 	    {
 		client->errorValue = stuff->y;
@@ -954,7 +1047,7 @@ ProcRRSetCrtcConfig (ClientPtr client)
 	}
 #endif
     }
-    
+
     if (!RRCrtcSet (crtc, mode, stuff->x, stuff->y,
 		   rotation, numOutputs, outputs))
     {
@@ -963,17 +1056,17 @@ ProcRRSetCrtcConfig (ClientPtr client)
     }
     rep.status = RRSetConfigSuccess;
     pScrPriv->lastSetTime = time;
-    
+
 sendReply:
     free(outputs);
-    
+
     rep.type = X_Reply;
     /* rep.status has already been filled in */
     rep.length = 0;
     rep.sequenceNumber = client->sequence;
     rep.newTimestamp = pScrPriv->lastSetTime.milliseconds;
 
-    if (client->swapped) 
+    if (client->swapped)
     {
 	int n;
     	swaps(&rep.sequenceNumber, n);
@@ -981,7 +1074,7 @@ sendReply:
 	swapl(&rep.newTimestamp, n);
     }
     WriteToClient(client, sizeof(xRRSetCrtcConfigReply), (char *)&rep);
-    
+
     return Success;
 }
 
@@ -997,7 +1090,7 @@ ProcRRGetPanning (ClientPtr client)
     BoxRec		tracking;
     INT16		border[4];
     int			n;
-    
+
     REQUEST_SIZE_MATCH(xRRGetPanningReq);
     VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess);
 
@@ -1067,7 +1160,7 @@ ProcRRSetPanning (ClientPtr client)
     BoxRec		tracking;
     INT16		border[4];
     int			n;
-    
+
     REQUEST_SIZE_MATCH(xRRSetPanningReq);
     VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess);
 
@@ -1082,9 +1175,9 @@ ProcRRSetPanning (ClientPtr client)
 	rep.status = RRSetConfigFailed;
 	goto sendReply;
     }
-    
+
     time = ClientTimeToServerTime(stuff->timestamp);
-    
+
     if (!pScrPriv->rrGetPanning)
 	return RRErrorBase + BadRRCrtc;
 
@@ -1160,7 +1253,7 @@ ProcRRGetCrtcGamma (ClientPtr client)
     int				n;
     unsigned long		len;
     char			*extra = NULL;
-    
+
     REQUEST_SIZE_MATCH(xRRGetCrtcGammaReq);
     VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess);
 
@@ -1169,7 +1262,7 @@ ProcRRGetCrtcGamma (ClientPtr client)
         return RRErrorBase + BadRRCrtc;
 
     len = crtc->gammaSize * 3 * 2;
-    
+
     if (crtc->gammaSize) {
 	extra = malloc(len);
 	if (!extra)
@@ -1203,21 +1296,21 @@ ProcRRSetCrtcGamma (ClientPtr client)
     RRCrtcPtr			crtc;
     unsigned long		len;
     CARD16			*red, *green, *blue;
-    
+
     REQUEST_AT_LEAST_SIZE(xRRSetCrtcGammaReq);
     VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess);
-    
+
     len = client->req_len - bytes_to_int32(sizeof (xRRSetCrtcGammaReq));
     if (len < (stuff->size * 3 + 1) >> 1)
 	return BadLength;
 
     if (stuff->size != crtc->gammaSize)
 	return BadMatch;
-    
+
     red = (CARD16 *) (stuff + 1);
     green = red + crtc->gammaSize;
     blue = green + crtc->gammaSize;
-    
+
     RRCrtcGammaSet (crtc, red, green, blue);
 
     return Success;
@@ -1258,7 +1351,7 @@ ProcRRSetCrtcTransform (ClientPtr client)
 
 
 #define CrtcTransformExtra	(SIZEOF(xRRGetCrtcTransformReply) - 32)
-				
+
 static int
 transform_filter_length (RRTransformPtr transform)
 {
@@ -1360,3 +1453,336 @@ ProcRRGetCrtcTransform (ClientPtr client)
     free(reply);
     return Success;
 }
+
+static void
+pixman_f_transform_from_xRenderTransform(struct pixman_f_transform *f_transform,
+					 xRenderTransform *x_transform)
+{
+    struct pixman_transform	transform;
+    PictTransform_from_xRenderTransform(&transform, x_transform);
+    pixman_f_transform_from_pixman_transform(f_transform, &transform);
+}
+
+static int
+RRConvertCrtcConfig(ClientPtr client, ScreenPtr screen,
+		    RRScreenConfigPtr screen_config,
+		    RRCrtcConfigPtr config, xRRCrtcConfig *x,
+		    RROutput *outputIds)
+{
+    RRCrtcPtr		crtc;
+    RROutputPtr		*outputs;
+    rrScrPrivPtr	scr_priv;
+    RRModePtr		mode;
+    PixmapPtr		pixmap;
+    int			rc, i, j;
+    Rotation		rotation;
+
+    VERIFY_RR_CRTC(x->crtc, crtc, DixSetAttrAccess);
+
+    if (x->mode == None)
+    {
+	mode = NULL;
+	if (x->nOutput > 0)
+	    return BadMatch;
+    }
+    else
+    {
+	VERIFY_RR_MODE(x->mode, mode, DixSetAttrAccess);
+	if (x->nOutput == 0)
+	    return BadMatch;
+    }
+    if (x->nOutput)
+    {
+	outputs = malloc(x->nOutput * sizeof (RROutputPtr));
+	if (!outputs)
+	    return BadAlloc;
+    }
+    else
+	outputs = NULL;
+
+    if (x->pixmap == None)
+	pixmap = NULL;
+    else
+    {
+	rc = dixLookupResourceByType((pointer *) &pixmap, x->pixmap,
+				     RT_PIXMAP, client, DixWriteAccess);
+	if (rc != Success) {
+	    free(outputs);
+	    return rc;
+	}
+	/* XXX check to make sure this is a scanout pixmap */
+    }
+
+    for (i = 0; i < x->nOutput; i++)
+    {
+	rc = dixLookupResourceByType((pointer *)(outputs + i), outputIds[i],
+				     RROutputType, client, DixSetAttrAccess);
+	if (rc != Success)
+	{
+	    free(outputs);
+	    return rc;
+	}
+	/* validate crtc for this output */
+	for (j = 0; j < outputs[i]->numCrtcs; j++)
+	    if (outputs[i]->crtcs[j] == crtc)
+		break;
+	if (j == outputs[i]->numCrtcs)
+	{
+	    free(outputs);
+	    return BadMatch;
+	}
+	/* validate mode for this output */
+	for (j = 0; j < outputs[i]->numModes + outputs[i]->numUserModes; j++)
+	{
+	    RRModePtr	m = (j < outputs[i]->numModes ?
+			     outputs[i]->modes[j] :
+			     outputs[i]->userModes[j - outputs[i]->numModes]);
+	    if (m == mode)
+		break;
+	}
+	if (j == outputs[i]->numModes + outputs[i]->numUserModes)
+	{
+	    free(outputs);
+	    return BadMatch;
+	}
+    }
+    /* validate clones */
+    for (i = 0; i < x->nOutput; i++)
+    {
+	for (j = 0; j < x->nOutput; j++)
+	{
+	    int k;
+	    if (i == j)
+		continue;
+	    for (k = 0; k < outputs[i]->numClones; k++)
+	    {
+		if (outputs[i]->clones[k] == outputs[j])
+		    break;
+	    }
+	    if (k == outputs[i]->numClones)
+	    {
+		free(outputs);
+		return BadMatch;
+	    }
+	}
+    }
+
+    if (crtc->pScreen != screen)
+	return BadMatch;
+
+    scr_priv = rrGetScrPriv(screen);
+
+    config->crtc = crtc;
+    config->x = x->x;
+    config->y = x->y;
+    config->mode = mode;
+    config->rotation = x->rotation;
+    config->numOutputs = x->nOutput;
+    config->outputs = outputs;
+    pixman_f_transform_from_xRenderTransform(&config->sprite_position_transform,
+					     &x->spritePositionTransform);
+    pixman_f_transform_from_xRenderTransform(&config->sprite_image_transform,
+					     &x->spriteImageTransform);
+    config->pixmap = pixmap;
+    config->pixmap_x = x->xPixmap;
+    config->pixmap_y = x->yPixmap;
+
+    /*
+     * Validate requested rotation
+     */
+    rotation = (Rotation) x->rotation;
+
+    /* test the rotation bits only! */
+    switch (rotation & 0xf) {
+    case RR_Rotate_0:
+    case RR_Rotate_90:
+    case RR_Rotate_180:
+    case RR_Rotate_270:
+	break;
+    default:
+	/*
+	 * Invalid rotation
+	 */
+	client->errorValue = x->rotation;
+	free(outputs);
+	return BadValue;
+    }
+
+    if (mode)
+    {
+	if ((~crtc->rotations) & rotation)
+	{
+	    /*
+	     * requested rotation or reflection not supported by screen
+	     */
+	    client->errorValue = x->rotation;
+	    free(outputs);
+	    return BadMatch;
+	}
+
+	/*
+	 * If scanning out from another pixmap, make sure the mode
+	 * fits
+	 */
+	if (pixmap)
+	{
+	    if (x->xPixmap + mode->mode.width > pixmap->drawable.width) {
+		client->errorValue = x->xPixmap;
+		free(outputs);
+		return BadValue;
+	    }
+	    if (x->yPixmap + mode->mode.height > pixmap->drawable.height) {
+		client->errorValue = x->yPixmap;
+		free(outputs);
+		return BadValue;
+	    }
+	}
+	/*
+	 * 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. 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.
+	 */
+	else if (scr_priv->rrScreenSetSize && !crtc->transforms)
+	{
+	    if (!RRScreenCoversCrtc(screen_config, config,
+				    &crtc->client_pending_transform,
+				    &client->errorValue))
+	    {
+		free(outputs);
+		return BadValue;
+	    }
+	}
+    }
+
+    return Success;
+}
+
+int
+ProcRRSetCrtcConfigs (ClientPtr client)
+{
+    REQUEST(xRRSetCrtcConfigsReq);
+    xRRSetCrtcConfigsReply  rep;
+    DrawablePtr		    drawable;
+    ScreenPtr		    screen;
+    rrScrPrivPtr	    scr_priv;
+    xRRCrtcConfig	    *x_configs;
+    RRScreenConfigRec	    screen_config;
+    RRCrtcConfigPtr	    configs;
+    RROutput		    *output_ids;
+    int			    num_configs;
+    int			    rc, i;
+    int			    extra_len;
+    int			    num_output_ids;
+
+    REQUEST_AT_LEAST_SIZE(xRRSetCrtcConfigsReq);
+
+    extra_len = client->req_len - bytes_to_int32(sizeof(xRRSetCrtcConfigsReq));
+
+    num_configs = stuff->nConfigs;
+
+    /* Check request length against number of configs specified */
+    if (num_configs * (sizeof (xRRCrtcConfig) >> 2) > extra_len)
+	return BadLength;
+
+    extra_len -= num_configs * (sizeof (xRRCrtcConfig) >> 2);
+    x_configs = (xRRCrtcConfig *) (stuff + 1);
+
+    /* Check remaining request length against number of outputs */
+    num_output_ids = 0;
+    for (i = 0; i < num_configs; i++)
+	num_output_ids += x_configs[i].nOutput;
+
+    if (extra_len != num_output_ids)
+	return BadLength;
+
+    rc = dixLookupDrawable(&drawable, stuff->drawable, client, 0, DixGetAttrAccess);
+    if (rc != Success)
+	return rc;
+
+    screen = drawable->pScreen;
+
+    scr_priv = rrGetScrPriv(screen);
+
+    if (!scr_priv)
+    {
+	rep.status = RRSetConfigFailed;
+	goto sendReply;
+    }
+
+    if (stuff->widthInMillimeters == 0 || stuff->heightInMillimeters == 0)
+    {
+	client->errorValue = 0;
+	return BadValue;
+    }
+
+    if (stuff->screenPixmapWidth < scr_priv->minWidth ||
+	scr_priv->maxWidth < stuff->screenPixmapWidth)
+    {
+	client->errorValue = stuff->screenPixmapWidth;
+	return BadValue;
+    }
+    if (stuff->screenPixmapHeight < scr_priv->minHeight ||
+	scr_priv->maxHeight < stuff->screenPixmapHeight)
+    {
+	client->errorValue = stuff->screenPixmapHeight;
+	return BadValue;
+    }
+
+    screen_config.screen_pixmap_width = stuff->screenPixmapWidth;
+    screen_config.screen_pixmap_height = stuff->screenPixmapHeight;
+    screen_config.screen_width = stuff->screenWidth;
+    screen_config.screen_height = stuff->screenHeight;
+    screen_config.mm_width = stuff->widthInMillimeters;
+    screen_config.mm_height = stuff->heightInMillimeters;
+
+    if (num_configs == 0)
+	return Success;
+
+    output_ids = (RROutput *) (x_configs + num_configs);
+
+    /*
+     * Convert protocol crtc configurations into
+     * server crtc configurations
+     */
+    configs = calloc(num_configs, sizeof (RRCrtcConfigRec));
+    if (!configs)
+	return BadAlloc;
+    for (i = 0; i < num_configs; i++) {
+	rc = RRConvertCrtcConfig(client, screen, &screen_config,
+				 &configs[i],
+				 &x_configs[i], output_ids);
+	if (rc != Success) {
+	    rep.status = RRSetConfigFailed;
+	    goto sendReply;
+	}
+	output_ids += x_configs[i].nOutput;
+    }
+
+    if (!RRSetCrtcConfigs (screen, &screen_config, configs, num_configs))
+    {
+	rep.status = RRSetConfigFailed;
+	goto sendReply;
+    }
+    rep.status = RRSetConfigSuccess;
+    scr_priv->lastSetTime = currentTime;
+
+sendReply:
+    RRFreeCrtcConfigs(configs, num_configs);
+
+    rep.type = X_Reply;
+    /* rep.status has already been filled in */
+    rep.length = 0;
+    rep.sequenceNumber = client->sequence;
+
+    if (client->swapped)
+    {
+	int n;
+	swaps(&rep.sequenceNumber, n);
+	swapl(&rep.length, n);
+    }
+    WriteToClient(client, sizeof(xRRSetCrtcConfigsReply), (char *)&rep);
+
+    return Success;
+}
diff --git a/randr/rrscreen.c b/randr/rrscreen.c
index f58e657..62ea2b6 100644
--- a/randr/rrscreen.c
+++ b/randr/rrscreen.c
@@ -191,6 +191,24 @@ RRScreenSizeSet (ScreenPtr  pScreen,
 }
 
 /*
+ * Compute an RRScreenConfig from the current screen information
+ */
+void
+RRScreenCurrentConfig(ScreenPtr screen,
+		      RRScreenConfigPtr screen_config)
+{
+    PixmapPtr		screen_pixmap = screen->GetScreenPixmap(screen);
+    WindowPtr		root = screen->root;
+
+    screen_config->screen_pixmap_width = screen_pixmap->drawable.width;
+    screen_config->screen_pixmap_height = screen_pixmap->drawable.height;
+    screen_config->screen_width = root->drawable.width;
+    screen_config->screen_height = root->drawable.height;
+    screen_config->mm_width = screen->mmWidth;
+    screen_config->mm_height = screen->mmHeight;
+}
+
+/*
  * Retrieve valid screen size range
  */
 int
commit 66294afcab7b7a82f7dd897767e46c48a94b8ee8
Author: Keith Packard <keithp at keithp.com>
Date:   Fri Dec 3 22:08:06 2010 -0800

    randr: Add sprite position transforms
    
    This implements sprite position transformations. Sprite image
    transforms are passed all the way to the DDX layer, but the images are
    not yet manipulated before being passed to the drivers.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Aaron Plattner <aplattner at nvidia.com>

diff --git a/hw/xfree86/modes/xf86Crtc.c b/hw/xfree86/modes/xf86Crtc.c
index 4573f62..3fccaea 100644
--- a/hw/xfree86/modes/xf86Crtc.c
+++ b/hw/xfree86/modes/xf86Crtc.c
@@ -106,12 +106,17 @@ xf86CrtcCreate (ScrnInfoPtr		scrn,
     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);
+    pixman_f_transform_init_identity (&crtc->f_screen_to_crtc);
+    pixman_f_transform_init_identity (&crtc->user_sprite_position_transform);
+    pixman_f_transform_init_identity (&crtc->f_crtc_to_cursor);
+    pixman_f_transform_init_identity (&crtc->user_sprite_image_transform);
     crtc->filter = NULL;
     crtc->params = NULL;
     crtc->nparams = 0;
     crtc->filter_width = 0;
     crtc->filter_height = 0;
     crtc->transform_in_use = FALSE;
+    crtc->sprite_transform_in_use = FALSE;
     crtc->transformPresent = FALSE;
     crtc->desiredTransformPresent = FALSE;
     memset (&crtc->bounds, '\0', sizeof (crtc->bounds));
diff --git a/hw/xfree86/modes/xf86Crtc.h b/hw/xfree86/modes/xf86Crtc.h
index f43e0a7..8b42efc 100644
--- a/hw/xfree86/modes/xf86Crtc.h
+++ b/hw/xfree86/modes/xf86Crtc.h
@@ -345,6 +345,7 @@ struct _xf86Crtc {
     int		    filter_width; /* ABI 2 */
     int		    filter_height; /* ABI 2 */
     Bool	    transform_in_use;
+    Bool	    sprite_transform_in_use;
     RRTransformRec  transform; /* ABI 2 */
     Bool	    transformPresent; /* ABI 2 */
     RRTransformRec  desiredTransform; /* ABI 2 */
@@ -384,6 +385,22 @@ struct _xf86Crtc {
      * Clear the shadow
      */
     Bool	    shadowClear;
+
+    /**
+     * Sprite position transforms
+     */
+
+    /* Transform a screen coordinate to a crtc coordinate */
+    struct pixman_f_transform f_screen_to_crtc;
+
+    /* The user-specified portion of the screen to crtc conversion */
+    struct pixman_f_transform user_sprite_position_transform;
+
+    /* Transform a hardware cursor coordinate to a cursor coordinate */
+    struct pixman_f_transform f_crtc_to_cursor;
+
+    /* The user-specified portion of the cursor to hardware transform */
+    struct pixman_f_transform user_sprite_image_transform;
 };
 
 typedef struct _xf86OutputFuncs {
@@ -777,6 +794,14 @@ xf86CrtcSetOrigin (xf86CrtcPtr crtc, int x, int y);
 extern _X_EXPORT Bool
 xf86CrtcRotate (xf86CrtcPtr crtc);
 
+
+/*
+ * Update cursor transform matrices after user changes
+ * This is just the cursor subset of xf86CrtcRotate
+ */
+extern _X_EXPORT void
+xf86CrtcRotateCursor (xf86CrtcPtr crtc);
+
 /*
  * Clean up any rotation data, used when a crtc is turned off
  * as well as when rotation is disabled.
diff --git a/hw/xfree86/modes/xf86Cursors.c b/hw/xfree86/modes/xf86Cursors.c
index 0667447..7b43bcb 100644
--- a/hw/xfree86/modes/xf86Cursors.c
+++ b/hw/xfree86/modes/xf86Cursors.c
@@ -338,7 +338,7 @@ xf86_crtc_set_cursor_position (xf86CrtcPtr crtc, int x, int y)
     /*
      * Transform position of cursor on screen
      */
-    if (crtc->transform_in_use)
+    if (crtc->sprite_transform_in_use)
     {
 	ScreenPtr	screen = scrn->pScreen;
 	xf86CursorScreenPtr ScreenPriv =
@@ -349,7 +349,7 @@ xf86_crtc_set_cursor_position (xf86CrtcPtr crtc, int x, int y)
 	v.v[0] = (x + ScreenPriv->HotX) + 0.5;
 	v.v[1] = (y + ScreenPriv->HotY) + 0.5;
 	v.v[2] = 1;
-	pixman_f_transform_point (&crtc->f_framebuffer_to_crtc, &v);
+	pixman_f_transform_point (&crtc->f_screen_to_crtc, &v);
 	/* cursor will have 0.5 added to it already so floor is sufficent */
 	x = floor (v.v[0]);
 	y = floor (v.v[1]);
diff --git a/hw/xfree86/modes/xf86RandR12.c b/hw/xfree86/modes/xf86RandR12.c
index d60ee3c..bbf28cd 100644
--- a/hw/xfree86/modes/xf86RandR12.c
+++ b/hw/xfree86/modes/xf86RandR12.c
@@ -180,14 +180,14 @@ xf86RandR13VerifyPanningArea (xf86CrtcPtr crtc, int screenWidth, int screenHeigh
  */
 
 static void
-xf86ComputeCrtcPan (Bool transform_in_use,
+xf86ComputeCrtcPan (Bool sprite_transform_in_use,
 		    struct pixman_f_transform *m,
 		    double screen_x, double screen_y,
 		    double crtc_x, double crtc_y,
 		    int old_pan_x, int old_pan_y,
 		    int *new_pan_x, int *new_pan_y)
 {
-    if (transform_in_use) {
+    if (sprite_transform_in_use) {
 	/*
 	 * Given the current transform, M, the current position
 	 * on the Screen, S, and the desired position on the CRTC,
@@ -374,8 +374,8 @@ xf86RandR13Pan (xf86CrtcPtr crtc, int x, int y)
 	c.v[0] = x;
 	c.v[1] = y;
 	c.v[2] = 1.0;
-	if (crtc->transform_in_use) {
-	    pixman_f_transform_point(&crtc->f_framebuffer_to_crtc, &c);
+	if (crtc->sprite_transform_in_use) {
+	    pixman_f_transform_point(&crtc->f_screen_to_crtc, &c);
 	} else {
 	    c.v[0] -= crtc->x;
 	    c.v[1] -= crtc->y;
@@ -402,8 +402,8 @@ xf86RandR13Pan (xf86CrtcPtr crtc, int x, int y)
 	    }
 	}
 	if (panned)
-	    xf86ComputeCrtcPan (crtc->transform_in_use,
-				&crtc->f_framebuffer_to_crtc,
+	    xf86ComputeCrtcPan (crtc->sprite_transform_in_use,
+				&crtc->f_screen_to_crtc,
 				x, y, c.v[0], c.v[1],
 				newX, newY, &newX, &newY);
     }
@@ -414,7 +414,7 @@ xf86RandR13Pan (xf86CrtcPtr crtc, int x, int y)
      * XXX This computation only works when we do not have a transform
      * in use.
      */
-    if (!crtc->transform_in_use)
+    if (!crtc->sprite_transform_in_use)
     {
 	/* Validate against [xy]1 after [xy]2, to be sure that results are > 0 for [xy]1 > 0 */
 	if (crtc->panningTotalArea.x2 > crtc->panningTotalArea.x1) {
@@ -1732,6 +1732,20 @@ xf86RandR12ChangeGamma(int scrnIndex, Gamma gamma)
     return Success;
 }
 
+static void
+xf86RandR14SetCrtcSpriteTransform(ScreenPtr		pScreen,
+				  RRCrtcPtr		randr_crtc,
+				  struct pixman_f_transform *f_position_transform,
+				  struct pixman_f_transform *f_image_transform)
+{
+    xf86CrtcPtr		crtc = randr_crtc->devPrivate;
+
+    crtc->user_sprite_position_transform = *f_position_transform;
+    crtc->user_sprite_image_transform = *f_image_transform;
+    xf86CrtcRotateCursor(crtc);
+    xf86_reload_cursors(pScreen);
+}
+
 static Bool
 xf86RandR12EnterVT (int screen_index, int flags)
 {
@@ -1740,6 +1754,7 @@ xf86RandR12EnterVT (int screen_index, int flags)
     XF86RandRInfoPtr randrp  = XF86RANDRINFO(pScreen);
     rrScrPrivPtr     rp = rrGetScrPriv(pScreen);
     Bool	     ret;
+    int i;
 
     if (randrp->orig_EnterVT) {
 	pScrn->EnterVT = randrp->orig_EnterVT;
@@ -1751,7 +1766,6 @@ xf86RandR12EnterVT (int screen_index, int flags)
     }
 
     /* reload gamma */
-    int i;
     for (i = 0; i < rp->numCrtcs; i++)
 	xf86RandR12CrtcSetGamma(pScreen, rp->crtcs[i]);
 
@@ -1782,6 +1796,7 @@ xf86RandR12Init12 (ScreenPtr pScreen)
     rp->rrSetConfig = NULL;
     pScrn->PointerMoved = xf86RandR12PointerMoved;
     pScrn->ChangeGamma = xf86RandR12ChangeGamma;
+    rp->rrSetCrtcSpriteTransform = xf86RandR14SetCrtcSpriteTransform;
 
     randrp->orig_EnterVT = pScrn->EnterVT;
     pScrn->EnterVT = xf86RandR12EnterVT;
diff --git a/hw/xfree86/modes/xf86Rotate.c b/hw/xfree86/modes/xf86Rotate.c
index 57c3499..ddc6d4c 100644
--- a/hw/xfree86/modes/xf86Rotate.c
+++ b/hw/xfree86/modes/xf86Rotate.c
@@ -369,6 +369,39 @@ xf86CrtcFitsScreen (xf86CrtcPtr crtc, struct pict_f_transform *crtc_to_fb)
 	    0 <= b.y1 && b.y2 <= pScrn->virtualY);
 }
 
+/*
+ * A subset of xf86CrtcRotate that just deals with
+ * cursor image/position transforms. Used when changing
+ * the cursor transform
+ */
+void
+xf86CrtcRotateCursor (xf86CrtcPtr crtc)
+{
+    /* if this is called during ScreenInit() we don't have pScrn->pScreen yet */
+    RRTransformPtr	transform = NULL;
+    PictTransform	crtc_to_fb;
+    struct pict_f_transform f_crtc_to_fb, f_fb_to_crtc, f_screen_to_crtc, f_crtc_to_cursor;
+
+    if (crtc->transformPresent)
+	transform = &crtc->transform;
+
+    (void) RRTransformCompute (crtc->x, crtc->y,
+			       crtc->mode.HDisplay, crtc->mode.VDisplay,
+			       crtc->rotation,
+			       transform,
+			       &crtc->user_sprite_position_transform,
+			       &crtc->user_sprite_image_transform,
+
+			       &crtc_to_fb,
+			       &f_crtc_to_fb,
+			       &f_fb_to_crtc,
+			       &f_screen_to_crtc,
+			       &f_crtc_to_cursor,
+			       &crtc->sprite_transform_in_use);
+    crtc->f_screen_to_crtc = f_screen_to_crtc;
+    crtc->f_crtc_to_cursor = f_crtc_to_cursor;
+}
+
 Bool
 xf86CrtcRotate (xf86CrtcPtr crtc)
 {
@@ -377,7 +410,7 @@ xf86CrtcRotate (xf86CrtcPtr crtc)
     /* if this is called during ScreenInit() we don't have pScrn->pScreen yet */
     ScreenPtr		pScreen = screenInfo.screens[pScrn->scrnIndex];
     PictTransform	crtc_to_fb;
-    struct pict_f_transform f_crtc_to_fb, f_fb_to_crtc;
+    struct pict_f_transform f_crtc_to_fb, f_fb_to_crtc, f_screen_to_crtc, f_crtc_to_cursor;
     xFixed		*new_params = NULL;
     int			new_nparams = 0;
     PictFilterPtr	new_filter = NULL;
@@ -393,10 +426,15 @@ xf86CrtcRotate (xf86CrtcPtr crtc)
 			     crtc->mode.HDisplay, crtc->mode.VDisplay,
 			     crtc->rotation,
 			     transform,
+			     &crtc->user_sprite_position_transform,
+			     &crtc->user_sprite_image_transform,
 
 			     &crtc_to_fb,
 			     &f_crtc_to_fb,
-			     &f_fb_to_crtc) &&
+			     &f_fb_to_crtc,
+			     &f_screen_to_crtc,
+			     &f_crtc_to_cursor,
+			     &crtc->sprite_transform_in_use) &&
 	xf86CrtcFitsScreen (crtc, &f_crtc_to_fb))
     {
 	/*
@@ -505,6 +543,8 @@ xf86CrtcRotate (xf86CrtcPtr crtc)
     crtc->crtc_to_framebuffer = crtc_to_fb;
     crtc->f_crtc_to_framebuffer = f_crtc_to_fb;
     crtc->f_framebuffer_to_crtc = f_fb_to_crtc;
+    crtc->f_screen_to_crtc = f_screen_to_crtc;
+    crtc->f_crtc_to_cursor = f_crtc_to_cursor;
     free(crtc->params);
     crtc->params = new_params;
     crtc->nparams = new_nparams;
diff --git a/randr/Makefile.am b/randr/Makefile.am
index de338b9..4b38e52 100644
--- a/randr/Makefile.am
+++ b/randr/Makefile.am
@@ -20,6 +20,7 @@ librandr_la_SOURCES =	\
 	rrproperty.c	\
 	rrscreen.c	\
 	rrsdispatch.c	\
+	rrsprite.c	\
 	rrtransform.h	\
 	rrtransform.c
 
diff --git a/randr/randrstr.h b/randr/randrstr.h
index 7ea6080..5e2a351 100644
--- a/randr/randrstr.h
+++ b/randr/randrstr.h
@@ -55,9 +55,10 @@
 #define RANDR_10_INTERFACE 1
 #define RANDR_12_INTERFACE 1
 #define RANDR_13_INTERFACE 1 /* requires RANDR_12_INTERFACE */
+#define RANDR_14_INTERFACE 1 /* requires RANDR_13_INTERFACE */
 #define RANDR_GET_CRTC_INTERFACE 1
 
-#define RANDR_INTERFACE_VERSION 0x0103
+#define RANDR_INTERFACE_VERSION 0x0104
 
 typedef XID	RRMode;
 typedef XID	RROutput;
@@ -122,9 +123,16 @@ struct _rrCrtc {
     Bool	    transforms;
     RRTransformRec  client_pending_transform;
     RRTransformRec  client_current_transform;
+    PictTransform   client_sprite_position_transform;
+    PictTransform   client_sprite_image_transform;
+    struct pict_f_transform	client_sprite_f_position_transform;
+    struct pict_f_transform	client_sprite_f_image_transform;
+
     PictTransform   transform;
     struct pict_f_transform f_transform;
     struct pict_f_transform f_inverse;
+    struct pict_f_transform f_sprite_position;		/* crtc from screen */
+    struct pict_f_transform f_sprite_image_inverse;	/* image from crtc */
 };
 
 struct _rrOutput {
@@ -233,6 +241,16 @@ typedef Bool (*RRSetConfigProcPtr) (ScreenPtr		pScreen,
 #endif
 	
 
+typedef void (*RRSetCrtcSpriteTransformPtr) (ScreenPtr pScreen,
+					     RRCrtcPtr randr_crtc,
+					     struct pict_f_transform *position_transform,
+					     struct pict_f_transform *image_transform);
+
+typedef void (*RRGetCrtcSpriteTransformPtr) (ScreenPtr pScreen,
+					     RRCrtcPtr randr_crtc,
+					     struct pict_f_transform *position_transform,
+					     struct pict_f_transform *image_transform);
+
 typedef struct _rrScrPriv {
     /*
      * 'public' part of the structure; DDXen fill this in
@@ -256,7 +274,9 @@ typedef struct _rrScrPriv {
     RRGetPanningProcPtr	rrGetPanning;
     RRSetPanningProcPtr	rrSetPanning;
 #endif
-    
+    RRSetCrtcSpriteTransformPtr	rrSetCrtcSpriteTransform;
+    RRGetCrtcSpriteTransformPtr	rrGetCrtcSpriteTransform;
+
     /*
      * Private part of the structure; not considered part of the ABI
      */
@@ -606,25 +626,6 @@ extern _X_EXPORT 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.
- */
-extern _X_EXPORT 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);
-
-/*
  * Return crtc transform
  */
 extern _X_EXPORT RRTransformPtr
@@ -700,6 +701,19 @@ ProcRRGetPanning (ClientPtr client);
 int
 ProcRRSetPanning (ClientPtr client);
 
+void
+RRCrtcSpriteTransformSet(RRCrtcPtr crtc,
+			 PictTransform *position_transform,
+			 PictTransform *image_transform,
+			 struct pict_f_transform *f_position_transform,
+			 struct pict_f_transform *f_image_transform);
+
+int
+ProcRRSetCrtcSpriteTransform (ClientPtr client);
+
+int
+ProcRRGetCrtcSpriteTransform (ClientPtr client);
+
 /* rrdispatch.c */
 extern _X_EXPORT Bool
 RRClientKnowsRates (ClientPtr	pClient);
@@ -889,6 +903,13 @@ ProcRRConfigureOutputProperty (ClientPtr client);
 extern _X_EXPORT int
 ProcRRDeleteOutputProperty (ClientPtr client);
 
+/* rrsprite.c */
+extern _X_EXPORT int
+ProcRRSetCrtcSpriteTransform (ClientPtr client);
+
+extern _X_EXPORT int
+ProcRRGetCrtcSpriteTransform (ClientPtr client);
+
 /* rrxinerama.c */
 #ifdef XINERAMA
 extern _X_EXPORT void
diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
index 98206a2..c2f6963 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -93,6 +93,8 @@ RRCrtcCreate (ScreenPtr pScreen, void *devPrivate)
     pixman_transform_init_identity (&crtc->transform);
     pixman_f_transform_init_identity (&crtc->f_transform);
     pixman_f_transform_init_identity (&crtc->f_inverse);
+    pixman_f_transform_init_identity (&crtc->f_sprite_position);
+    pixman_f_transform_init_identity (&crtc->f_sprite_image_inverse);
 
     if (!AddResource (crtc->id, RRCrtcType, (pointer) crtc))
 	return NULL;
@@ -231,15 +233,21 @@ RRCrtcNotify (RRCrtcPtr	    crtc,
 	RRTransformCopy (&crtc->client_current_transform, transform);
 	RRCrtcChanged (crtc, TRUE);
     }
+
     if (crtc->changed && mode)
     {
 	RRTransformCompute (x, y,
 			    mode->mode.width, mode->mode.height,
 			    rotation,
 			    &crtc->client_current_transform,
+			    &crtc->client_sprite_f_position_transform,
+			    &crtc->client_sprite_f_image_transform,
 			    &crtc->transform, &crtc->f_transform,
-			    &crtc->f_inverse);
+			    &crtc->f_inverse, &crtc->f_sprite_position,
+			    &crtc->f_sprite_image_inverse,
+			    NULL);
     }
+
     return TRUE;
 }
 
@@ -511,7 +519,7 @@ RRCrtcGammaNotify (RRCrtcPtr	crtc)
 }
 
 static void
-RRModeGetScanoutSize (RRModePtr mode, PictTransformPtr transform,
+RRModeGetScanoutSize (RRModePtr mode, struct pixman_f_transform *transform,
 		      int *width, int *height)
 {
     BoxRec  box;
@@ -527,7 +535,7 @@ RRModeGetScanoutSize (RRModePtr mode, PictTransformPtr transform,
     box.x2 = mode->mode.width;
     box.y2 = mode->mode.height;
 
-    pixman_transform_bounds (transform, &box);
+    pixman_f_transform_bounds (transform, &box);
     *width = box.x2 - box.x1;
     *height = box.y2 - box.y1;
 }
@@ -538,7 +546,7 @@ RRModeGetScanoutSize (RRModePtr mode, PictTransformPtr transform,
 void
 RRCrtcGetScanoutSize(RRCrtcPtr crtc, int *width, int *height)
 {
-    return RRModeGetScanoutSize (crtc->mode, &crtc->transform, width, height);
+    RRModeGetScanoutSize (crtc->mode, &crtc->f_transform, width, height);
 }
 
 /*
@@ -924,9 +932,12 @@ ProcRRSetCrtcConfig (ClientPtr client)
 				mode->mode.width, mode->mode.height,
 				rotation,
 				&crtc->client_pending_transform,
-				&transform, &f_transform, &f_inverse);
+				&crtc->client_sprite_f_position_transform,
+				&crtc->client_sprite_f_image_transform,
+				&transform, &f_transform, &f_inverse, NULL, NULL, NULL);
 
-	    RRModeGetScanoutSize (mode, &transform, &source_width, &source_height);
+	    RRModeGetScanoutSize (mode, &f_transform,
+				  &source_width, &source_height);
 	    if (stuff->x + source_width > pScreen->width)
 	    {
 		client->errorValue = stuff->x;
diff --git a/randr/rrsprite.c b/randr/rrsprite.c
new file mode 100644
index 0000000..5bf312c
--- /dev/null
+++ b/randr/rrsprite.c
@@ -0,0 +1,104 @@
+/*
+ * Copyright © 2010 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 "randrstr.h"
+#include "swaprep.h"
+
+void
+RRCrtcSpriteTransformSet(RRCrtcPtr crtc,
+			 PictTransform *position_transform,
+			 PictTransform *image_transform,
+			 struct pict_f_transform *f_position_transform,
+			 struct pict_f_transform *f_image_transform)
+{
+    ScreenPtr			pScreen;
+    rrScrPrivPtr		pScrPriv;
+
+    pScreen = crtc->pScreen;
+    pScrPriv = rrGetScrPriv(pScreen);
+    crtc->client_sprite_position_transform = *position_transform;
+    crtc->client_sprite_image_transform = *image_transform;
+    crtc->client_sprite_f_position_transform = *f_position_transform;
+    crtc->client_sprite_f_image_transform = *f_image_transform;
+    if (pScrPriv->rrSetCrtcSpriteTransform)
+	(*pScrPriv->rrSetCrtcSpriteTransform) (pScreen, crtc,
+					       &crtc->client_sprite_f_position_transform,
+					       &crtc->client_sprite_f_image_transform);
+}
+
+int
+ProcRRSetCrtcSpriteTransform (ClientPtr client)
+{
+    REQUEST(xRRSetCrtcSpriteTransformReq);
+    RRCrtcPtr		    crtc;
+    PictTransform	    position_transform, image_transform;
+    struct pixman_f_transform f_position_transform, f_image_transform;
+
+    REQUEST_AT_LEAST_SIZE(xRRSetCrtcSpriteTransformReq);
+    VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess);
+
+    PictTransform_from_xRenderTransform (&position_transform, &stuff->positionTransform);
+    PictTransform_from_xRenderTransform (&image_transform, &stuff->imageTransform);
+    pixman_f_transform_from_pixman_transform (&f_position_transform, &position_transform);
+    pixman_f_transform_from_pixman_transform (&f_image_transform, &image_transform);
+
+    RRCrtcSpriteTransformSet (crtc, &position_transform, &image_transform,
+			      &f_position_transform, &f_image_transform);
+    return Success;
+}
+
+#define CrtcSpriteTransformExtra	(SIZEOF(xRRGetCrtcSpriteTransformReply) - 32)
+
+int
+ProcRRGetCrtcSpriteTransform (ClientPtr client)
+{
+    REQUEST(xRRGetCrtcSpriteTransformReq);
+    xRRGetCrtcSpriteTransformReply	*reply;
+    RRCrtcPtr			crtc;
+    int				n;
+    char			*extra;
+
+    REQUEST_SIZE_MATCH (xRRGetCrtcSpriteTransformReq);
+    VERIFY_RR_CRTC(stuff->crtc, crtc, DixReadAccess);
+
+    reply = malloc(sizeof (xRRGetCrtcSpriteTransformReply));
+    if (!reply)
+	return BadAlloc;
+
+    extra = (char *) (reply + 1);
+    reply->type = X_Reply;
+    reply->sequenceNumber = client->sequence;
+    reply->length = bytes_to_int32(CrtcSpriteTransformExtra);
+
+    xRenderTransform_from_PictTransform(&reply->positionTransform, &crtc->client_sprite_position_transform);
+    xRenderTransform_from_PictTransform(&reply->imageTransform, &crtc->client_sprite_image_transform);
+
+    if (client->swapped) {
+	swaps (&reply->sequenceNumber, n);
+	swapl (&reply->length, n);
+	SwapLongs((CARD32 *) &reply->positionTransform, bytes_to_int32(sizeof(xRenderTransform)));
+	SwapLongs((CARD32 *) &reply->imageTransform, bytes_to_int32(sizeof(xRenderTransform)));
+    }
+    WriteToClient (client, sizeof (xRRGetCrtcSpriteTransformReply), (char *) reply);
+    free(reply);
+    return Success;
+}
diff --git a/randr/rrtransform.c b/randr/rrtransform.c
index e162049..3eda5f3 100644
--- a/randr/rrtransform.c
+++ b/randr/rrtransform.c
@@ -134,6 +134,24 @@ RRTransformRescale(struct pixman_f_transform *f_transform, double limit)
 	    f_transform->m[j][i] *= scale;
 }
 
+#define EPSILON (1e-20)
+#define IS_F_SAME(a,b)	(fabs((a)-(b)) < EPSILON)
+#define IS_F_ZERO(a)	(fabs(a) < EPSILON)
+
+static Bool
+pict_f_transform_is_identity (const struct pixman_f_transform *t)
+{
+    return (IS_F_SAME (t->m[0][0], t->m[1][1]) &&
+	    IS_F_SAME (t->m[0][0], t->m[2][2]) &&
+	    !IS_F_ZERO (t->m[0][0]) &&
+	    IS_F_ZERO (t->m[0][1]) &&
+	    IS_F_ZERO (t->m[0][2]) &&
+	    IS_F_ZERO (t->m[1][0]) &&
+	    IS_F_ZERO (t->m[1][2]) &&
+	    IS_F_ZERO (t->m[2][0]) &&
+	    IS_F_ZERO (t->m[2][1]));
+}
+
 /*
  * Compute the complete transformation matrix including
  * client-specified transform, rotation/reflection values and the crtc 
@@ -148,23 +166,39 @@ RRTransformCompute (int			    x,
 		    int			    height,
 		    Rotation		    rotation,
 		    RRTransformPtr	    rr_transform,
+		    struct pixman_f_transform *sprite_position_transform,
+		    struct pixman_f_transform *sprite_image_transform,
 
 		    PictTransformPtr	    transform,
 		    struct pixman_f_transform *f_transform,
-		    struct pixman_f_transform *f_inverse)
+		    struct pixman_f_transform *f_inverse,
+		    struct pixman_f_transform *f_fb_to_sprite,
+		    struct pixman_f_transform *f_sprite_to_image,
+		    Bool		      *sprite_transform_in_use)
 {
     PictTransform	    t_transform, inverse;
     struct pixman_f_transform tf_transform, tf_inverse;
+    struct pixman_f_transform sf_position_transform, sf_image_transform;
+    struct pixman_f_transform f_image_to_sprite;
     Bool		    overflow = FALSE;
+    Bool		    ret = TRUE;
 
     if (!transform) transform = &t_transform;
     if (!f_transform) f_transform = &tf_transform;
     if (!f_inverse) f_inverse = &tf_inverse;
+    if (!f_fb_to_sprite) f_fb_to_sprite = &sf_position_transform;
+    if (!f_sprite_to_image) f_sprite_to_image = &sf_image_transform;
+
+    /* invert the sprite image transform to have it go from dest to source */
+    if (!pixman_f_transform_invert (&f_image_to_sprite, f_sprite_to_image))
+	pixman_f_transform_init_identity(&f_image_to_sprite);
 
     pixman_transform_init_identity (transform);
     pixman_transform_init_identity (&inverse);
     pixman_f_transform_init_identity (f_transform);
     pixman_f_transform_init_identity (f_inverse);
+    pixman_f_transform_init_identity (f_fb_to_sprite);
+    pixman_f_transform_init_identity (f_sprite_to_image);
     if (rotation != RR_Rotate_0)
     {
 	double	f_rot_cos, f_rot_sin, f_rot_dx, f_rot_dy;
@@ -246,7 +280,14 @@ RRTransformCompute (int			    x,
 	pixman_f_transform_translate (f_transform, f_inverse, f_scale_dx, f_scale_dy);
     }
     
-#ifdef RANDR_12_INTERFACE
+    /*
+     * Sprite position is affected by the transform matrix,
+     * but the image is not
+     */
+    pixman_f_transform_multiply(f_sprite_to_image,
+				f_transform,
+				&f_image_to_sprite);
+
     if (rr_transform)
     {
         if (!pixman_transform_multiply (transform, &rr_transform->transform, transform))
@@ -254,7 +295,7 @@ RRTransformCompute (int			    x,
 	pixman_f_transform_multiply (f_transform, &rr_transform->f_transform, f_transform);
 	pixman_f_transform_multiply (f_inverse, f_inverse, &rr_transform->f_inverse);
     }
-#endif
+
     /*
      * Compute the class of the resulting transform
      */
@@ -264,7 +305,7 @@ RRTransformCompute (int			    x,
 
 	pixman_f_transform_init_translate (f_transform,  x,  y);
 	pixman_f_transform_init_translate (f_inverse,   -x, -y);
-	return FALSE;
+	ret = FALSE;
     }
     else
     {
@@ -278,6 +319,19 @@ RRTransformCompute (int			    x,
 	    RRTransformRescale(&f_scaled, 16384.0);
 	    pixman_transform_from_pixman_f_transform(transform, &f_scaled);
 	}
-	return TRUE;
+	ret = TRUE;
     }
+
+    /*
+     * Sprite position is affected by the transform matrix,
+     * but the image is not
+     */
+    pixman_f_transform_multiply(f_fb_to_sprite,
+				f_inverse,
+				sprite_position_transform);
+    if (sprite_transform_in_use)
+	*sprite_transform_in_use = ret || !pict_f_transform_is_identity(f_fb_to_sprite);
+    return ret;
 }
+
+
diff --git a/randr/rrtransform.h b/randr/rrtransform.h
index 561762d..5cfcf8d 100644
--- a/randr/rrtransform.h
+++ b/randr/rrtransform.h
@@ -59,6 +59,13 @@ RRTransformSetFilter (RRTransformPtr	dst,
 extern _X_EXPORT Bool
 RRTransformCopy (RRTransformPtr dst, RRTransformPtr src);
 
+/*
+ * 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.
+ */
 extern _X_EXPORT Bool
 RRTransformCompute (int			    x,
 		    int			    y,
@@ -66,10 +73,14 @@ RRTransformCompute (int			    x,
 		    int			    height,
 		    Rotation		    rotation,
 		    RRTransformPtr	    rr_transform,
+		    struct pict_f_transform *sprite_position_transform,
+		    struct pict_f_transform *sprite_image_transform,
 
 		    PictTransformPtr	    transform,
 		    struct pict_f_transform *f_transform,
-		    struct pict_f_transform *f_inverse);
-
+		    struct pict_f_transform *f_inverse,
+		    struct pict_f_transform *f_fb_to_sprite,
+		    struct pict_f_transform *f_sprite_to_image,
+		    Bool		    *sprite_transform_in_use);
 
 #endif /* _RRTRANSFORM_H_ */
commit c8bc25fd7629df10f2825b7cc713b031ae78f223
Author: Keith Packard <keithp at keithp.com>
Date:   Mon Dec 6 19:40:30 2010 -0800

    Require RandR protocol version 1.4 or newer
    
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/configure.ac b/configure.ac
index 3021bdd..d1fc379 100644
--- a/configure.ac
+++ b/configure.ac
@@ -788,7 +788,7 @@ WINDOWSWMPROTO="windowswmproto"
 APPLEWMPROTO="applewmproto >= 1.4"
 
 dnl Core modules for most extensions, et al.
-SDK_REQUIRED_MODULES="[xproto >= 7.0.17] [randrproto >= 1.2.99.3] [renderproto >= 0.11] [xextproto >= 7.1.99] [inputproto >= 1.9.99.902] [kbproto >= 1.0.3] fontsproto"
+SDK_REQUIRED_MODULES="[xproto >= 7.0.17] [randrproto >= 1.4] [renderproto >= 0.11] [xextproto >= 7.1.99] [inputproto >= 1.9.99.902] [kbproto >= 1.0.3] fontsproto"
 # Make SDK_REQUIRED_MODULES available for inclusion in xorg-server.pc
 AC_SUBST(SDK_REQUIRED_MODULES)
 
commit 8b35118c03590a7ad3786d3284bafb3f40fcb8cc
Author: Keith Packard <keithp at keithp.com>
Date:   Sun Jun 6 15:23:37 2010 -0700

    Replace huge argument list in xf86CrtcSetModeTransform with struct
    
    xf86CrtcSetModeTransform was starting to get ridiculous with 6
    arguments, this change has it take a single structure that contains
    all of those values along with a set of flags that says which have
    changed.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Aaron Plattner <aplattner at nvidia.com>

diff --git a/hw/xfree86/modes/xf86Crtc.c b/hw/xfree86/modes/xf86Crtc.c
index b94bc09..4573f62 100644
--- a/hw/xfree86/modes/xf86Crtc.c
+++ b/hw/xfree86/modes/xf86Crtc.c
@@ -247,15 +247,14 @@ xf86CrtcSetScreenSubpixelOrder (ScreenPtr pScreen)
  * Sets the given video mode on the given crtc
  */
 Bool
-xf86CrtcSetModeTransform (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation,
-			  RRTransformPtr transform, int x, int y)
+xf86CrtcSet(xf86CrtcPtr crtc, xf86CrtcSetRec *set)
 {
     ScrnInfoPtr		scrn = crtc->scrn;
     xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
     int			i;
     Bool		ret = FALSE;
     Bool		didLock = FALSE;
-    DisplayModePtr	adjusted_mode;
+    DisplayModePtr	adjusted_mode = NULL;
     DisplayModeRec	saved_mode;
     int			saved_x, saved_y;
     Rotation		saved_rotation;
@@ -272,8 +271,9 @@ xf86CrtcSetModeTransform (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotati
 	return TRUE;
     }
 
-    adjusted_mode = xf86DuplicateMode(mode);
-
+    /* See if nothing has changed */
+    if (!set->flags)
+	return TRUE;
 
     saved_mode = crtc->mode;
     saved_x = crtc->x;
@@ -288,21 +288,44 @@ xf86CrtcSetModeTransform (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotati
     /* Update crtc values up front so the driver can rely on them for mode
      * setting.
      */
-    crtc->mode = *mode;
-    crtc->x = x;
-    crtc->y = y;
-    crtc->rotation = rotation;
-    if (transform) {
-	RRTransformCopy (&crtc->transform, transform);
-	crtc->transformPresent = TRUE;
-    } else
-	crtc->transformPresent = FALSE;
+    if (set->flags & XF86CrtcSetMode)
+	crtc->mode = *set->mode;
+    if (set->flags & XF86CrtcSetOrigin) {
+	crtc->x = set->x;
+	crtc->y = set->y;
+    }
+    if (set->flags & XF86CrtcSetRotation)
+	crtc->rotation = set->rotation;
+
+    if (set->flags & XF86CrtcSetTransform) {
+	if (set->transform) {
+	    RRTransformCopy (&crtc->transform, set->transform);
+	    crtc->transformPresent = TRUE;
+	} else
+	    crtc->transformPresent = FALSE;
+    }
+
+    if (crtc->funcs->set) {
+	ret = crtc->funcs->set(crtc, set->flags);
+	goto done;
+    }
+
+    if (set->flags == XF86CrtcSetOrigin && crtc->funcs->set_origin) {
+	ret = xf86CrtcRotate(crtc);
+	if (ret)
+	    crtc->funcs->set_origin(crtc, crtc->x, crtc->y);
+	goto done;
+    }
 
     if (crtc->funcs->set_mode_major) {
-	ret = crtc->funcs->set_mode_major(crtc, mode, rotation, x, y);
+	ret = crtc->funcs->set_mode_major(crtc, &crtc->mode,
+					  crtc->rotation,
+					  crtc->x, crtc->y);
 	goto done;
     }
 
+    adjusted_mode = xf86DuplicateMode(&crtc->mode);
+
     didLock = crtc->funcs->lock (crtc);
     /* Pass our mode to the outputs and the CRTC to give them a chance to
      * adjust it according to limitations or output properties, and also
@@ -314,12 +337,12 @@ xf86CrtcSetModeTransform (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotati
 	if (output->crtc != crtc)
 	    continue;
 
-	if (!output->funcs->mode_fixup(output, mode, adjusted_mode)) {
+	if (!output->funcs->mode_fixup(output, &crtc->mode, adjusted_mode)) {
 	    goto done;
 	}
     }
 
-    if (!crtc->funcs->mode_fixup(crtc, mode, adjusted_mode)) {
+    if (!crtc->funcs->mode_fixup(crtc, &crtc->mode, adjusted_mode)) {
 	goto done;
     }
 
@@ -342,12 +365,12 @@ xf86CrtcSetModeTransform (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotati
     /* Set up the DPLL and any output state that needs to adjust or depend
      * on the DPLL.
      */
-    crtc->funcs->mode_set(crtc, mode, adjusted_mode, crtc->x, crtc->y);
+    crtc->funcs->mode_set(crtc, &crtc->mode, adjusted_mode, crtc->x, crtc->y);
     for (i = 0; i < xf86_config->num_output; i++) 
     {
 	xf86OutputPtr output = xf86_config->output[i];
 	if (output->crtc == crtc)
-	    output->funcs->mode_set(output, mode, adjusted_mode);
+	    output->funcs->mode_set(output, &crtc->mode, adjusted_mode);
     }
 
     /* Only upload when needed, to avoid unneeded delays. */
@@ -383,8 +406,10 @@ done:
 	crtc->transformPresent = saved_transform_present;
     }
 
-    free(adjusted_mode->name);
-    free(adjusted_mode);
+    if (adjusted_mode) {
+	free(adjusted_mode->name);
+	free(adjusted_mode);
+    }
 
     if (didLock)
 	crtc->funcs->unlock (crtc);
@@ -393,35 +418,19 @@ done:
 }
 
 /**
- * Sets the given video mode on the given crtc, but without providing
- * a transform
- */
-Bool
-xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation,
-		 int x, int y)
-{
-    return xf86CrtcSetModeTransform (crtc, mode, rotation, NULL, x, y);
-}
-
-/**
  * Pans the screen, does not change the mode
  */
 void
 xf86CrtcSetOrigin (xf86CrtcPtr crtc, int x, int y)
 {
-    ScrnInfoPtr scrn = crtc->scrn;
+    xf86CrtcSetRec	set;
 
-    crtc->x = x;
-    crtc->y = y;
-    if (crtc->funcs->set_origin) {
-	if (!xf86CrtcRotate (crtc))
-	    return;
-	crtc->funcs->set_origin (crtc, x, y);
-	if (scrn->ModeSet)
-	    scrn->ModeSet(scrn);
+    if (x != crtc->x || y != crtc->y) {
+	set.x = x;
+	set.y = y;
+	set.flags = XF86CrtcSetOrigin;
+	(void) xf86CrtcSet(crtc, &set);
     }
-    else
-	xf86CrtcSetMode (crtc, &crtc->mode, crtc->rotation, x, y);
 }
 
 /*
@@ -2617,6 +2626,7 @@ xf86SetDesiredModes (ScrnInfoPtr scrn)
     for (c = 0; c < config->num_crtc; c++)
     {
 	xf86OutputPtr	output = NULL;
+	xf86CrtcSetRec	set;
 	int		o;
 	RRTransformPtr	transform;
 
@@ -2660,8 +2670,15 @@ xf86SetDesiredModes (ScrnInfoPtr scrn)
 	    transform = &crtc->desiredTransform;
 	else
 	    transform = NULL;
-	if (!xf86CrtcSetModeTransform (crtc, &crtc->desiredMode, crtc->desiredRotation,
-				       transform, crtc->desiredX, crtc->desiredY))
+	set.mode = &crtc->desiredMode;
+	set.rotation = crtc->desiredRotation;
+	set.transform = transform;
+	set.x = crtc->desiredX;
+	set.y = crtc->desiredY;
+	set.flags = (XF86CrtcSetMode | XF86CrtcSetOutput |
+		     XF86CrtcSetOrigin | XF86CrtcSetTransform |
+		     XF86CrtcSetRotation);
+	if (!xf86CrtcSet(crtc, &set))
 	    return FALSE;
     }
 
@@ -2765,6 +2782,7 @@ xf86SetSingleMode (ScrnInfoPtr pScrn, DisplayModePtr desired, Rotation rotation)
 	xf86CrtcPtr	crtc = config->crtc[c];
 	DisplayModePtr	crtc_mode = NULL;
 	int		o;
+	xf86CrtcSetRec	set;
 
 	if (!crtc->enabled)
 	    continue;
@@ -2792,7 +2810,15 @@ xf86SetSingleMode (ScrnInfoPtr pScrn, DisplayModePtr desired, Rotation rotation)
 	    crtc->enabled = FALSE;
 	    continue;
 	}
-	if (!xf86CrtcSetModeTransform (crtc, crtc_mode, rotation, NULL, 0, 0))
+	set.mode = crtc_mode;
+	set.rotation = rotation;
+	set.transform = NULL;
+	set.x = 0;
+	set.y = 0;
+	set.flags = (XF86CrtcSetMode | XF86CrtcSetOutput |
+		     XF86CrtcSetOrigin | XF86CrtcSetTransform |
+		     XF86CrtcSetRotation);
+	if (!xf86CrtcSet (crtc, &set))
 	    ok = FALSE;
 	else
 	{
diff --git a/hw/xfree86/modes/xf86Crtc.h b/hw/xfree86/modes/xf86Crtc.h
index 68a968c..f43e0a7 100644
--- a/hw/xfree86/modes/xf86Crtc.h
+++ b/hw/xfree86/modes/xf86Crtc.h
@@ -72,6 +72,23 @@ typedef enum _xf86OutputStatus {
    XF86OutputStatusUnknown
 } xf86OutputStatus;
 
+typedef enum _xf86CrtcSetFlags {
+    XF86CrtcSetMode = 1,		/* mode */
+    XF86CrtcSetOutput = 2,		/* outputs */
+    XF86CrtcSetOrigin = 4,		/* x/y */
+    XF86CrtcSetTransform = 8,		/* transform */
+    XF86CrtcSetRotation = 16,		/* rotation */
+    XF86CrtcSetProperty = 32,		/* output property */
+} xf86CrtcSetFlags;
+
+typedef struct _xf86CrtcSet {
+    xf86CrtcSetFlags	flags;
+    DisplayModePtr	mode;
+    Rotation		rotation;
+    RRTransformPtr	transform;
+    int			x, y;
+} xf86CrtcSetRec;
+
 typedef struct _xf86CrtcFuncs {
    /**
     * Turns the crtc on/off, or sets intermediate power levels if available.
@@ -221,6 +238,12 @@ typedef struct _xf86CrtcFuncs {
     void
     (*set_origin)(xf86CrtcPtr crtc, int x, int y);
 
+    /**
+     * General mode setting entry point that does everything
+     */
+    Bool
+    (*set)(xf86CrtcPtr crtc, xf86CrtcSetFlags flags);
+
 } xf86CrtcFuncsRec, *xf86CrtcFuncsPtr;
 
 #define XF86_CRTC_VERSION 3
@@ -738,18 +761,12 @@ xf86CrtcCreate (ScrnInfoPtr		scrn,
 extern _X_EXPORT void
 xf86CrtcDestroy (xf86CrtcPtr		crtc);
 
-
 /**
- * Sets the given video mode on the given crtc
+ * Change a crtc configuration (modes, outputs, etc)
  */
 
 extern _X_EXPORT Bool
-xf86CrtcSetModeTransform (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation,
-			  RRTransformPtr transform, int x, int y);
-
-extern _X_EXPORT Bool
-xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation,
-		 int x, int y);
+xf86CrtcSet (xf86CrtcPtr crtc, xf86CrtcSetRec *set);
 
 extern _X_EXPORT void
 xf86CrtcSetOrigin (xf86CrtcPtr crtc, int x, int y);
diff --git a/hw/xfree86/modes/xf86RandR12.c b/hw/xfree86/modes/xf86RandR12.c
index 2fe0c47..d60ee3c 100644
--- a/hw/xfree86/modes/xf86RandR12.c
+++ b/hw/xfree86/modes/xf86RandR12.c
@@ -1133,7 +1133,7 @@ xf86RandR12CrtcSet (ScreenPtr	    pScreen,
     xf86CrtcConfigPtr   config = XF86_CRTC_CONFIG_PTR(pScrn);
     xf86CrtcPtr		crtc = randr_crtc->devPrivate;
     RRTransformPtr	transform;
-    Bool		changed = FALSE;
+    xf86CrtcSetFlags	flags = 0;
     int			o, ro;
     xf86CrtcPtr		*save_crtcs;
     Bool		save_enabled = crtc->enabled;
@@ -1143,22 +1143,22 @@ xf86RandR12CrtcSet (ScreenPtr	    pScreen,
 
     save_crtcs = malloc(config->num_output * sizeof (xf86CrtcPtr));
     if ((randr_mode != NULL) != crtc->enabled)
-	changed = TRUE;
+	flags |= XF86CrtcSetMode;
     else if (randr_mode && !xf86RandRModeMatches (randr_mode, &crtc->mode))
-	changed = TRUE;
+	flags |= XF86CrtcSetMode;
     
     if (rotation != crtc->rotation)
-	changed = TRUE;
+	flags |= XF86CrtcSetRotation;
 
     transform = RRCrtcGetTransform (randr_crtc);
     if ((transform != NULL) != crtc->transformPresent)
-	changed = TRUE;
+	flags |= XF86CrtcSetTransform;
     else if (transform && memcmp (&transform->transform, &crtc->transform.transform,
 				  sizeof (transform->transform)) != 0)
-	changed = TRUE;
+	flags |= XF86CrtcSetTransform;
 
     if (x != crtc->x || y != crtc->y)
-	changed = TRUE;
+	flags |= XF86CrtcSetOrigin;
     for (o = 0; o < config->num_output; o++) 
     {
 	xf86OutputPtr  output = config->output[o];
@@ -1178,16 +1178,16 @@ xf86RandR12CrtcSet (ScreenPtr	    pScreen,
 	    }
 	if (new_crtc != output->crtc)
 	{
-	    changed = TRUE;
+	    flags |= XF86CrtcSetOutput;
 	    output->crtc = new_crtc;
 	}
     }
     for (ro = 0; ro < num_randr_outputs; ro++) 
         if (randr_outputs[ro]->pendingProperties)
-	    changed = TRUE;
+	    flags |= XF86CrtcSetProperty;
 
     /* XXX need device-independent mode setting code through an API */
-    if (changed)
+    if (flags)
     {
 	crtc->enabled = randr_mode != NULL;
 
@@ -1195,9 +1195,16 @@ xf86RandR12CrtcSet (ScreenPtr	    pScreen,
 	{
 	    DisplayModeRec  mode;
 	    RRTransformPtr  transform = RRCrtcGetTransform (randr_crtc);
+	    xf86CrtcSetRec  set;
 
 	    xf86RandRModeConvert (pScrn, randr_mode, &mode);
-	    if (!xf86CrtcSetModeTransform (crtc, &mode, rotation, transform, x, y))
+	    set.mode = &mode;
+	    set.rotation = rotation;
+	    set.transform = transform;
+	    set.x = x;
+	    set.y = y;
+	    set.flags = flags;
+	    if (!xf86CrtcSet(crtc, &set))
 	    {
 		crtc->enabled = save_enabled;
 		for (o = 0; o < config->num_output; o++)


More information about the xorg-commit mailing list