xserver: Branch 'master' - 9 commits

Matthias Hopf mhopf at kemper.freedesktop.org
Thu Dec 4 09:37:47 PST 2008


 hw/xfree86/modes/xf86Crtc.c    |   25 ++++
 hw/xfree86/modes/xf86Crtc.h    |   36 ++++++
 hw/xfree86/modes/xf86RandR12.c |  233 +++++++++++++++++++++++++++++++++++++++++
 randr/randrstr.h               |   19 +++
 randr/rrcrtc.c                 |  152 ++++++++++++++++++++++++++
 randr/rrdispatch.c             |    2 
 6 files changed, 464 insertions(+), 3 deletions(-)

New commits:
commit e5ab9e66628cde081757cf2a1013a78e927a622e
Author: Matthias Hopf <mhopf at suse.de>
Date:   Thu Dec 4 18:13:40 2008 +0100

    randr: Allow panning to be disabled per axis

diff --git a/hw/xfree86/modes/xf86RandR12.c b/hw/xfree86/modes/xf86RandR12.c
index c40c1e4..663d1a7 100644
--- a/hw/xfree86/modes/xf86RandR12.c
+++ b/hw/xfree86/modes/xf86RandR12.c
@@ -182,8 +182,8 @@ xf86RandR13Pan (xf86CrtcPtr crtc, int x, int y)
 	return;
 
     if (! crtc->enabled						||
-	crtc->panningTotalArea.x2 <= crtc->panningTotalArea.x1	||
-	crtc->panningTotalArea.y2 <= crtc->panningTotalArea.y1)
+	(crtc->panningTotalArea.x2 <= crtc->panningTotalArea.x1	&&
+	 crtc->panningTotalArea.y2 <= crtc->panningTotalArea.y1))
 	return;
 
     newX   = crtc->x;
@@ -191,26 +191,36 @@ xf86RandR13Pan (xf86CrtcPtr crtc, int x, int y)
     width  = crtc->mode.HDisplay;
     height = crtc->mode.VDisplay;
 
-    if (x >= crtc->panningTrackingArea.x1 && x < crtc->panningTrackingArea.x2 &&
-    	y >= crtc->panningTrackingArea.y1 && y < crtc->panningTrackingArea.y2) {
-	if (x < crtc->x + crtc->panningBorder[0])
-	    newX = x - crtc->panningBorder[0];
-	if (x >= crtc->x + width - crtc->panningBorder[2])
-	    newX = x - width + crtc->panningBorder[2] + 1;
-	if (y < crtc->y + crtc->panningBorder[1])
-	    newY = y - crtc->panningBorder[1];
-	if (y >= crtc->y + height - crtc->panningBorder[3])
-	    newY = y - height + crtc->panningBorder[3] + 1;
+    if ((crtc->panningTrackingArea.x2 <= crtc->panningTrackingArea.x1 ||
+	 (x >= crtc->panningTrackingArea.x1 && x < crtc->panningTrackingArea.x2)) &&
+	(crtc->panningTrackingArea.y2 <= crtc->panningTrackingArea.y1 ||
+	 (y >= crtc->panningTrackingArea.y1 && y < crtc->panningTrackingArea.y2))) {
+	if (crtc->panningTotalArea.x2 > crtc->panningTotalArea.x1) {
+	    if (x < crtc->x + crtc->panningBorder[0])
+		newX = x - crtc->panningBorder[0];
+	    if (x >= crtc->x + width - crtc->panningBorder[2])
+		newX = x - width + crtc->panningBorder[2] + 1;
+	}
+	if (crtc->panningTotalArea.y2 > crtc->panningTotalArea.y1) {
+	    if (y < crtc->y + crtc->panningBorder[1])
+		newY = y - crtc->panningBorder[1];
+	    if (y >= crtc->y + height - crtc->panningBorder[3])
+		newY = y - height + crtc->panningBorder[3] + 1;
+	}
     }
     /* Validate against [xy]1 after [xy]2, to be sure that results are > 0 for [xy]1 > 0 */
-    if (newX >= crtc->panningTotalArea.x2 - width)
-	newX =  crtc->panningTotalArea.x2 - width - 1;
-    if (newX <  crtc->panningTotalArea.x1)
-	newX =  crtc->panningTotalArea.x1;
-    if (newY >= crtc->panningTotalArea.y2 - height)
-	newY =  crtc->panningTotalArea.y2 - height - 1;
-    if (newY <  crtc->panningTotalArea.y1)
-	newY =  crtc->panningTotalArea.y1;
+    if (crtc->panningTotalArea.x2 > crtc->panningTotalArea.x1) {
+	if (newX >= crtc->panningTotalArea.x2 - width)
+	    newX =  crtc->panningTotalArea.x2 - width - 1;
+	if (newX <  crtc->panningTotalArea.x1)
+	    newX =  crtc->panningTotalArea.x1;
+    }
+    if (crtc->panningTotalArea.y2 > crtc->panningTotalArea.y1) {
+	if (newY >= crtc->panningTotalArea.y2 - height)
+	    newY =  crtc->panningTotalArea.y2 - height - 1;
+	if (newY <  crtc->panningTotalArea.y1)
+	    newY =  crtc->panningTotalArea.y1;
+    }
     if (newX != crtc->x || newY != crtc->y)
 	xf86CrtcSetOrigin (crtc, newX, newY);
 }
@@ -485,12 +495,16 @@ xf86RandR12ScreenSetSize (ScreenPtr	pScreen,
     /* Update panning information */
     for (c = 0; c < config->num_crtc; c++) {
 	xf86CrtcPtr crtc = config->crtc[c];
-	if (crtc->panningTotalArea.x2 > crtc->panningTotalArea.x1 &&
+	if (crtc->panningTotalArea.x2 > crtc->panningTotalArea.x1 ||
 	    crtc->panningTotalArea.y2 > crtc->panningTotalArea.y1) {
-	    crtc->panningTotalArea.x2 += width  - pScreen->width;
-	    crtc->panningTotalArea.y2 += height - pScreen->height;
-	    crtc->panningTrackingArea.x2 += width  - pScreen->width;
-	    crtc->panningTrackingArea.y2 += height - pScreen->height;
+	    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);
 	}
commit bad118ace6c5bae5a5ed8a35129c90c38f1c1932
Author: Matthias Hopf <mhopf at suse.de>
Date:   Thu Dec 4 16:55:14 2008 +0100

    randr: Rework panning area verification

diff --git a/hw/xfree86/modes/xf86RandR12.c b/hw/xfree86/modes/xf86RandR12.c
index 8ef4ebe..c40c1e4 100644
--- a/hw/xfree86/modes/xf86RandR12.c
+++ b/hw/xfree86/modes/xf86RandR12.c
@@ -88,40 +88,88 @@ xf86RandR12ModeRefresh (DisplayModePtr mode)
 	return (int) (mode->Clock * 1000.0 / mode->HTotal / mode->VTotal + 0.5);
 }
 
+/* Adapt panning area; return TRUE if panning area was valid without adaption */
 static int
 xf86RandR13VerifyPanningArea (xf86CrtcPtr crtc, int screenWidth, int screenHeight)
 {
+    int ret = TRUE;
+
     if (crtc->version < 2)
 	return FALSE;
 
-    if (crtc->panningTotalArea.x2 <= crtc->panningTotalArea.x1				||
-	crtc->panningTotalArea.y2 <= crtc->panningTotalArea.y1) {
-	memset (&crtc->panningTotalArea, 0, sizeof(BoxRec));
-	memset (&crtc->panningTrackingArea, 0, sizeof(BoxRec));
-	memset (&crtc->panningBorder, 0, 4*sizeof(INT16));
-	return TRUE;
+    if (crtc->panningTotalArea.x2 <= crtc->panningTotalArea.x1) {
+	/* Panning in X is disabled */
+	if (crtc->panningTotalArea.x1 || crtc->panningTotalArea.x2)
+	    /* Illegal configuration -> fail/disable */
+	    ret = FALSE;
+	crtc->panningTotalArea.x1    = crtc->panningTotalArea.x2    = 0;
+	crtc->panningTrackingArea.x1 = crtc->panningTrackingArea.x2 = 0;
+	crtc->panningBorder[0]       = crtc->panningBorder[2]       = 0;
+    } else {
+	/* Panning in X is enabled */
+	if (crtc->panningTotalArea.x1 < 0) {
+	    /* Panning region outside screen -> move inside */
+	    crtc->panningTotalArea.x2 -= crtc->panningTotalArea.x1;
+	    crtc->panningTotalArea.x1 = 0;
+	    ret = FALSE;
+	}
+	if (crtc->panningTotalArea.x2 < crtc->panningTotalArea.x1 + crtc->mode.HDisplay) {
+	    /* Panning region smaller than displayed area -> crop to displayed area */
+	    crtc->panningTotalArea.x2 = crtc->panningTotalArea.x1 + crtc->mode.HDisplay;
+	    ret = FALSE;
+	}
+	if (crtc->panningTotalArea.x2 > screenWidth) {
+	    /* Panning region larger than screen -> move inside, then crop to screen */
+	    crtc->panningTotalArea.x1 -= crtc->panningTotalArea.x2 - screenWidth;
+	    crtc->panningTotalArea.x2 = screenWidth;
+	    ret = FALSE;
+	    if (crtc->panningTotalArea.x1 < 0)
+		crtc->panningTotalArea.x1 = 0;
+	}
+	if (crtc->panningBorder[0] + crtc->panningBorder[2] > crtc->mode.HDisplay) {
+	    /* Borders too large -> set to 0 */
+	    crtc->panningBorder[0] = crtc->panningBorder[2] = 0;
+	    ret = FALSE;
+	}
     }
 
-    if (crtc->panningTotalArea.x2 <= crtc->panningTotalArea.x1				||
-	crtc->panningTotalArea.y2 <= crtc->panningTotalArea.y1				||
-	crtc->panningTotalArea.x1 < 0							||
-	crtc->panningTotalArea.y1 < 0							||
-	crtc->panningTotalArea.x2 < crtc->panningTotalArea.x1 + crtc->mode.HDisplay	||
-	crtc->panningTotalArea.y2 < crtc->panningTotalArea.y1 + crtc->mode.VDisplay	||
-	crtc->panningTotalArea.x2 > screenWidth				 		||
-	crtc->panningTotalArea.y2 > screenHeight)
-    {
-	memset (&crtc->panningTotalArea, 0, sizeof(BoxRec));
-	memset (&crtc->panningTrackingArea, 0, sizeof(BoxRec));
-	memset (&crtc->panningBorder, 0, 4*sizeof(INT16));
-	return FALSE;
-    }
-    if (crtc->panningBorder[0] + crtc->panningBorder[2] > crtc->mode.HDisplay		||
-	crtc->panningBorder[1] + crtc->panningBorder[3] > crtc->mode.VDisplay) {
-	memset (&crtc->panningBorder, 0, 4*sizeof(INT16));
-	return FALSE;
+    if (crtc->panningTotalArea.y2 <= crtc->panningTotalArea.y1) {
+	/* Panning in Y is disabled */
+	if (crtc->panningTotalArea.y1 || crtc->panningTotalArea.y2)
+	    /* Illegal configuration -> fail/disable */
+	    ret = FALSE;
+	crtc->panningTotalArea.y1    = crtc->panningTotalArea.y2    = 0;
+	crtc->panningTrackingArea.y1 = crtc->panningTrackingArea.y2 = 0;
+	crtc->panningBorder[1]       = crtc->panningBorder[3]       = 0;
+    } else {
+	/* Panning in Y is enabled */
+	if (crtc->panningTotalArea.y1 < 0) {
+	    /* Panning region outside screen -> move inside */
+	    crtc->panningTotalArea.y2 -= crtc->panningTotalArea.y1;
+	    crtc->panningTotalArea.y1 = 0;
+	    ret = FALSE;
+	}
+	if (crtc->panningTotalArea.y2 < crtc->panningTotalArea.y1 + crtc->mode.VDisplay) {
+	    /* Panning region smaller than displayed area -> crop to displayed area */
+	    crtc->panningTotalArea.y2 = crtc->panningTotalArea.y1 + crtc->mode.VDisplay;
+	    ret = FALSE;
+	}
+	if (crtc->panningTotalArea.y2 > screenHeight) {
+	    /* Panning region larger than screen -> move inside, then crop to screen */
+	    crtc->panningTotalArea.y1 -= crtc->panningTotalArea.y2 - screenHeight;
+	    crtc->panningTotalArea.y2 = screenHeight;
+	    ret = FALSE;
+	    if (crtc->panningTotalArea.y1 < 0)
+		crtc->panningTotalArea.y1 = 0;
+	}
+	if (crtc->panningBorder[1] + crtc->panningBorder[3] > crtc->mode.VDisplay) {
+	    /* Borders too large -> set to 0 */
+	    crtc->panningBorder[1] = crtc->panningBorder[3] = 0;
+	    ret = FALSE;
+	}
     }
-    return TRUE;
+
+    return ret;
 }
 
 static void
commit 219c26ce0c65625d55cfd943ec66fe94a1a0ddfd
Author: Matthias Hopf <mhopf at suse.de>
Date:   Thu Dec 4 16:28:40 2008 +0100

    randr: Don't change panning parameters if verification fails.

diff --git a/hw/xfree86/modes/xf86RandR12.c b/hw/xfree86/modes/xf86RandR12.c
index 3745f4f..8ef4ebe 100644
--- a/hw/xfree86/modes/xf86RandR12.c
+++ b/hw/xfree86/modes/xf86RandR12.c
@@ -1327,20 +1327,35 @@ xf86RandR13SetPanning (ScreenPtr           pScreen,
 {
     XF86RandRInfoPtr	randrp  = XF86RANDRINFO(pScreen);
     xf86CrtcPtr		crtc = randr_crtc->devPrivate;
-    int			ret;
+    BoxRec		oldTotalArea;
+    BoxRec		oldTrackingArea;
+    INT16		oldBorder[4];
+
 
     if (crtc->version < 2)
 	return FALSE;
+
+    memcpy (&oldTotalArea,    &crtc->panningTotalArea,    sizeof(BoxRec));
+    memcpy (&oldTrackingArea, &crtc->panningTrackingArea, sizeof(BoxRec));
+    memcpy (oldBorder,         crtc->panningBorder,       4*sizeof(INT16));
+
     if (totalArea)
 	memcpy (&crtc->panningTotalArea, totalArea, sizeof(BoxRec));
     if (trackingArea)
 	memcpy (&crtc->panningTrackingArea, trackingArea, sizeof(BoxRec));
     if (border)
 	memcpy (crtc->panningBorder, border, 4*sizeof(INT16));
-    ret = xf86RandR13VerifyPanningArea (crtc, pScreen->width, pScreen->height);
-    xf86RandR13Pan (crtc, randrp->pointerX, randrp->pointerY);
 
-    return ret;
+    if (xf86RandR13VerifyPanningArea (crtc, pScreen->width, pScreen->height)) {
+	xf86RandR13Pan (crtc, randrp->pointerX, randrp->pointerY);
+	return TRUE;
+    } else {
+	/* Restore old settings */
+	memcpy (&crtc->panningTotalArea,    &oldTotalArea,    sizeof(BoxRec));
+	memcpy (&crtc->panningTrackingArea, &oldTrackingArea, sizeof(BoxRec));
+	memcpy (crtc->panningBorder,         oldBorder,       4*sizeof(INT16));
+	return FALSE;
+    }
 }
 
 static Bool
commit 18a8bac1a1567b6215928f96870554ea63f39aab
Author: Matthias Hopf <mhopf at suse.de>
Date:   Thu Dec 4 16:30:38 2008 +0100

    randr: Rename pan() to set_origin(), and xf86CrtcPan() to xf86CrtcSetOrigin()

diff --git a/hw/xfree86/modes/xf86Crtc.c b/hw/xfree86/modes/xf86Crtc.c
index 0b59521..be01992 100644
--- a/hw/xfree86/modes/xf86Crtc.c
+++ b/hw/xfree86/modes/xf86Crtc.c
@@ -328,10 +328,10 @@ xf86CrtcSetModeTransform (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotati
 		    crtc->x, crtc->y);
     }
 
-    if (crtc->funcs->pan &&
+    if (crtc->funcs->set_origin &&
 	memcmp (mode, &saved_mode, sizeof(saved_mode)) == 0 &&
 	saved_rotation == rotation) {
-	crtc->funcs->pan (crtc, crtc->x, crtc->y);
+	crtc->funcs->set_origin (crtc, crtc->x, crtc->y);
 	ret = TRUE;
 	goto done;
     }
@@ -428,12 +428,12 @@ xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation,
  * Pans the screen, does not change the mode
  */
 _X_EXPORT void
-xf86CrtcPan (xf86CrtcPtr crtc, int x, int y)
+xf86CrtcSetOrigin (xf86CrtcPtr crtc, int x, int y)
 {
     crtc->x = x;
     crtc->y = y;
-    if (crtc->funcs->pan)
-	crtc->funcs->pan (crtc, x, y);
+    if (crtc->funcs->set_origin)
+	crtc->funcs->set_origin (crtc, x, y);
     else
 	xf86CrtcSetMode (crtc, &crtc->mode, crtc->rotation, x, y);
 }
diff --git a/hw/xfree86/modes/xf86Crtc.h b/hw/xfree86/modes/xf86Crtc.h
index 097935f..2953241 100644
--- a/hw/xfree86/modes/xf86Crtc.h
+++ b/hw/xfree86/modes/xf86Crtc.h
@@ -218,7 +218,7 @@ typedef struct _xf86CrtcFuncs {
      * Callback for panning. Doesn't change the mode.
      */
     void
-    (*pan)(xf86CrtcPtr crtc, int x, int y);
+    (*set_origin)(xf86CrtcPtr crtc, int x, int y);
 
 } xf86CrtcFuncsRec, *xf86CrtcFuncsPtr;
 
@@ -695,7 +695,7 @@ xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation,
 		 int x, int y);
 
 void
-xf86CrtcPan (xf86CrtcPtr crtc, int x, int y);
+xf86CrtcSetOrigin (xf86CrtcPtr crtc, int x, int y);
 
 /*
  * Assign crtc rotation during mode set
diff --git a/hw/xfree86/modes/xf86RandR12.c b/hw/xfree86/modes/xf86RandR12.c
index fda2d25..3745f4f 100644
--- a/hw/xfree86/modes/xf86RandR12.c
+++ b/hw/xfree86/modes/xf86RandR12.c
@@ -164,7 +164,7 @@ xf86RandR13Pan (xf86CrtcPtr crtc, int x, int y)
     if (newY <  crtc->panningTotalArea.y1)
 	newY =  crtc->panningTotalArea.y1;
     if (newX != crtc->x || newY != crtc->y)
-	xf86CrtcPan (crtc, newX, newY);
+	xf86CrtcSetOrigin (crtc, newX, newY);
 }
 
 static Bool
commit 825b2c2f4a59ac4852f90bbbddf18ab832297fdd
Author: Matthias Hopf <mhopf at suse.de>
Date:   Thu Dec 4 16:11:21 2008 +0100

    randr: Nuke config-timestamp for panning

diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
index b8e4d11..99f7d1e 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -1056,7 +1056,6 @@ ProcRRSetPanning (ClientPtr client)
     RRCrtcPtr		crtc;
     ScreenPtr		pScreen;
     rrScrPrivPtr	pScrPriv;
-    TimeStamp		configTime;
     TimeStamp		time;
     BoxRec		total;
     BoxRec		tracking;
@@ -1083,21 +1082,7 @@ ProcRRSetPanning (ClientPtr client)
     }
     
     time = ClientTimeToServerTime(stuff->timestamp);
-    configTime = ClientTimeToServerTime(stuff->configTimestamp);
     
-#if 0
-    /*
-     * if the client's config timestamp is not the same as the last config
-     * timestamp, then the config information isn't up-to-date and
-     * can't even be validated
-     */
-    if (CompareTimeStamps (configTime, pScrPriv->lastConfigTime) != 0)
-    {
-	rep.status = RRSetConfigInvalidConfigTime;
-	goto sendReply;
-    }
-#endif
-
     /*
      * Make sure the requested set-time is not older than
      * the last set-time
commit eeeb98d1df59baaaec954b6318d788a37e388d11
Author: Matthias Hopf <mhopf at suse.de>
Date:   Fri Nov 28 17:51:20 2008 +0100

    randr: Protocol bits for panning support

diff --git a/randr/randrstr.h b/randr/randrstr.h
index e2338b7..0cc4ff7 100644
--- a/randr/randrstr.h
+++ b/randr/randrstr.h
@@ -190,6 +190,17 @@ typedef void (*RRModeDestroyProcPtr) (ScreenPtr	    pScreen,
 typedef Bool (*RROutputGetPropertyProcPtr) (ScreenPtr		pScreen,
 					    RROutputPtr		output,
 					    Atom		property);
+typedef Bool (*RRGetPanningProcPtr)    (ScreenPtr		pScrn,
+					RRCrtcPtr		crtc,
+					BoxPtr		totalArea,
+					BoxPtr		trackingArea,
+					INT16		*border);
+typedef Bool (*RRSetPanningProcPtr)    (ScreenPtr		pScrn,
+					RRCrtcPtr		crtc,
+					BoxPtr		totalArea,
+					BoxPtr		trackingArea,
+					INT16		*border);
+
 #endif /* RANDR_13_INTERFACE */
 
 typedef Bool (*RRGetInfoProcPtr) (ScreenPtr pScreen, Rotation *rotations);
@@ -239,6 +250,8 @@ typedef struct _rrScrPriv {
 #endif
 #if RANDR_13_INTERFACE
     RROutputGetPropertyProcPtr	rrOutputGetProperty;
+    RRGetPanningProcPtr	rrGetPanning;
+    RRSetPanningProcPtr	rrSetPanning;
 #endif
     
     /*
@@ -678,6 +691,12 @@ ProcRRSetCrtcTransform (ClientPtr client);
 extern _X_EXPORT int
 ProcRRGetCrtcTransform (ClientPtr client);
 
+int
+ProcRRGetPanning (ClientPtr client);
+
+int
+ProcRRSetPanning (ClientPtr client);
+
 /* rrdispatch.c */
 extern _X_EXPORT Bool
 RRClientKnowsRates (ClientPtr	pClient);
diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
index 90d93b5..b8e4d11 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -978,6 +978,173 @@ sendReply:
 }
 
 int
+ProcRRGetPanning (ClientPtr client)
+{
+    REQUEST(xRRGetPanningReq);
+    xRRGetPanningReply	rep;
+    RRCrtcPtr		crtc;
+    ScreenPtr		pScreen;
+    rrScrPrivPtr	pScrPriv;
+    BoxRec		total;
+    BoxRec		tracking;
+    INT16		border[4];
+    int			n;
+    
+    REQUEST_SIZE_MATCH(xRRGetPanningReq);
+    crtc = LookupCrtc(client, stuff->crtc, DixReadAccess);
+
+    if (!crtc)
+	return RRErrorBase + BadRRCrtc;
+
+    /* All crtcs must be associated with screens before client
+     * requests are processed
+     */
+    pScreen = crtc->pScreen;
+    pScrPriv = rrGetScrPriv(pScreen);
+
+    if (!pScrPriv || !pScrPriv->rrGetPanning)
+	return RRErrorBase + BadRRCrtc;
+
+    rep.type = X_Reply;
+    rep.status = RRSetConfigSuccess;
+    rep.sequenceNumber = client->sequence;
+    rep.length = 1;
+    rep.timestamp = pScrPriv->lastSetTime.milliseconds;
+
+    if (! pScrPriv->rrGetPanning (pScreen, crtc, &total, &tracking, border))
+	return RRErrorBase + BadRRCrtc;
+
+    rep.left          = total.x1;
+    rep.top           = total.y1;
+    rep.width         = total.x2 - total.x1;
+    rep.height        = total.y2 - total.y1;
+    rep.track_left    = tracking.x1;
+    rep.track_top     = tracking.y1;
+    rep.track_width   = tracking.x2 - tracking.x1;
+    rep.track_height  = tracking.y2 - tracking.y1;
+    rep.border_left   = border[0];
+    rep.border_top    = border[1];
+    rep.border_right  = border[2];
+    rep.border_bottom = border[3];
+
+    if (client->swapped) {
+	swaps(&rep.sequenceNumber, n);
+	swapl(&rep.length, n);
+	swaps(&rep.timestamp, n);
+	swaps(&rep.left, n);
+	swaps(&rep.top, n);
+	swaps(&rep.width, n);
+	swaps(&rep.height, n);
+	swaps(&rep.track_left, n);
+	swaps(&rep.track_top, n);
+	swaps(&rep.track_width, n);
+	swaps(&rep.track_height, n);
+	swaps(&rep.border_left, n);
+	swaps(&rep.border_top, n);
+	swaps(&rep.border_right, n);
+	swaps(&rep.border_bottom, n);
+    }
+    WriteToClient(client, sizeof(xRRGetPanningReply), (char *)&rep);
+    return client->noClientException;
+}
+
+int
+ProcRRSetPanning (ClientPtr client)
+{
+    REQUEST(xRRSetPanningReq);
+    xRRSetPanningReply	rep;
+    RRCrtcPtr		crtc;
+    ScreenPtr		pScreen;
+    rrScrPrivPtr	pScrPriv;
+    TimeStamp		configTime;
+    TimeStamp		time;
+    BoxRec		total;
+    BoxRec		tracking;
+    INT16		border[4];
+    int			n;
+    
+    REQUEST_SIZE_MATCH(xRRSetPanningReq);
+    crtc = LookupCrtc(client, stuff->crtc, DixReadAccess);
+
+    if (!crtc)
+	return RRErrorBase + BadRRCrtc;
+
+
+    /* All crtcs must be associated with screens before client
+     * requests are processed
+     */
+    pScreen = crtc->pScreen;
+    pScrPriv = rrGetScrPriv(pScreen);
+
+    if (!pScrPriv) {
+	time = currentTime;
+	rep.status = RRSetConfigFailed;
+	goto sendReply;
+    }
+    
+    time = ClientTimeToServerTime(stuff->timestamp);
+    configTime = ClientTimeToServerTime(stuff->configTimestamp);
+    
+#if 0
+    /*
+     * if the client's config timestamp is not the same as the last config
+     * timestamp, then the config information isn't up-to-date and
+     * can't even be validated
+     */
+    if (CompareTimeStamps (configTime, pScrPriv->lastConfigTime) != 0)
+    {
+	rep.status = RRSetConfigInvalidConfigTime;
+	goto sendReply;
+    }
+#endif
+
+    /*
+     * Make sure the requested set-time is not older than
+     * the last set-time
+     */
+    if (CompareTimeStamps (time, pScrPriv->lastSetTime) < 0)
+    {
+	rep.status = RRSetConfigInvalidTime;
+	goto sendReply;
+    }
+
+    if (!pScrPriv->rrGetPanning)
+	return RRErrorBase + BadRRCrtc;
+
+    total.x1    = stuff->left;
+    total.y1    = stuff->top;
+    total.x2    = stuff->width - total.x1;
+    total.y2    = stuff->height - total.y1;
+    tracking.x1 = stuff->track_left;
+    tracking.y1 = stuff->track_top;
+    tracking.x2 = stuff->track_width - tracking.x1;
+    tracking.y2 = stuff->track_height - tracking.y1;
+    border[0]   = stuff->border_left;
+    border[1]   = stuff->border_top;
+    border[2]   = stuff->border_right;
+    border[3]   = stuff->border_bottom;
+
+    if (! pScrPriv->rrSetPanning (pScreen, crtc, &total, &tracking, border))
+	return BadMatch;
+
+    rep.status = RRSetConfigSuccess;
+
+sendReply:
+    rep.type = X_Reply;
+    rep.sequenceNumber = client->sequence;
+    rep.length = 0;
+    rep.newTimestamp = pScrPriv->lastSetTime.milliseconds;
+
+    if (client->swapped) {
+	swaps(&rep.sequenceNumber, n);
+	swapl(&rep.length, n);
+	swaps(&rep.newTimestamp, n);
+    }
+    WriteToClient(client, sizeof(xRRSetPanningReply), (char *)&rep);
+    return client->noClientException;
+}
+
+int
 ProcRRGetCrtcGammaSize (ClientPtr client)
 {
     REQUEST(xRRGetCrtcGammaSizeReq);
diff --git a/randr/rrdispatch.c b/randr/rrdispatch.c
index 64af6ce..0cc0bca 100644
--- a/randr/rrdispatch.c
+++ b/randr/rrdispatch.c
@@ -215,5 +215,7 @@ int (*ProcRandrVector[RRNumberRequests])(ClientPtr) = {
     ProcRRGetScreenResourcesCurrent, /* 25 */
     ProcRRSetCrtcTransform,	/* 26 */
     ProcRRGetCrtcTransform,	/* 27 */
+    ProcRRGetPanning,		/* 28 */
+    ProcRRSetPanning,		/* 29 */
 };
 
commit b929d721efdb17bcc94b9984c4f34d0df3d267d5
Author: Matthias Hopf <mhopf at suse.de>
Date:   Fri Nov 28 17:49:31 2008 +0100

    randr: Panning support

diff --git a/hw/xfree86/modes/xf86Crtc.c b/hw/xfree86/modes/xf86Crtc.c
index bd64e03..0b59521 100644
--- a/hw/xfree86/modes/xf86Crtc.c
+++ b/hw/xfree86/modes/xf86Crtc.c
@@ -328,8 +328,14 @@ xf86CrtcSetModeTransform (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotati
 		    crtc->x, crtc->y);
     }
 
-    /* XXX short-circuit changes to base location only */
-    
+    if (crtc->funcs->pan &&
+	memcmp (mode, &saved_mode, sizeof(saved_mode)) == 0 &&
+	saved_rotation == rotation) {
+	crtc->funcs->pan (crtc, crtc->x, crtc->y);
+	ret = TRUE;
+	goto done;
+    }
+
     /* 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
      * a chance to reject the mode entirely.
@@ -418,6 +424,20 @@ xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation,
     return xf86CrtcSetModeTransform (crtc, mode, rotation, NULL, x, y);
 }
 
+/**
+ * Pans the screen, does not change the mode
+ */
+_X_EXPORT void
+xf86CrtcPan (xf86CrtcPtr crtc, int x, int y)
+{
+    crtc->x = x;
+    crtc->y = y;
+    if (crtc->funcs->pan)
+	crtc->funcs->pan (crtc, x, y);
+    else
+	xf86CrtcSetMode (crtc, &crtc->mode, crtc->rotation, x, y);
+}
+
 /*
  * Output functions
  */
diff --git a/hw/xfree86/modes/xf86RandR12.c b/hw/xfree86/modes/xf86RandR12.c
index 62f1edb..fda2d25 100644
--- a/hw/xfree86/modes/xf86RandR12.c
+++ b/hw/xfree86/modes/xf86RandR12.c
@@ -51,6 +51,8 @@ typedef struct _xf86RandR12Info {
     int				    mmHeight;
     int				    maxX;
     int				    maxY;
+    int				    pointerX;
+    int				    pointerY;
     Rotation			    rotation; /* current mode */
     Rotation                        supported_rotations; /* driver supported */
 } XF86RandRInfoRec, *XF86RandRInfoPtr;
@@ -86,6 +88,85 @@ xf86RandR12ModeRefresh (DisplayModePtr mode)
 	return (int) (mode->Clock * 1000.0 / mode->HTotal / mode->VTotal + 0.5);
 }
 
+static int
+xf86RandR13VerifyPanningArea (xf86CrtcPtr crtc, int screenWidth, int screenHeight)
+{
+    if (crtc->version < 2)
+	return FALSE;
+
+    if (crtc->panningTotalArea.x2 <= crtc->panningTotalArea.x1				||
+	crtc->panningTotalArea.y2 <= crtc->panningTotalArea.y1) {
+	memset (&crtc->panningTotalArea, 0, sizeof(BoxRec));
+	memset (&crtc->panningTrackingArea, 0, sizeof(BoxRec));
+	memset (&crtc->panningBorder, 0, 4*sizeof(INT16));
+	return TRUE;
+    }
+
+    if (crtc->panningTotalArea.x2 <= crtc->panningTotalArea.x1				||
+	crtc->panningTotalArea.y2 <= crtc->panningTotalArea.y1				||
+	crtc->panningTotalArea.x1 < 0							||
+	crtc->panningTotalArea.y1 < 0							||
+	crtc->panningTotalArea.x2 < crtc->panningTotalArea.x1 + crtc->mode.HDisplay	||
+	crtc->panningTotalArea.y2 < crtc->panningTotalArea.y1 + crtc->mode.VDisplay	||
+	crtc->panningTotalArea.x2 > screenWidth				 		||
+	crtc->panningTotalArea.y2 > screenHeight)
+    {
+	memset (&crtc->panningTotalArea, 0, sizeof(BoxRec));
+	memset (&crtc->panningTrackingArea, 0, sizeof(BoxRec));
+	memset (&crtc->panningBorder, 0, 4*sizeof(INT16));
+	return FALSE;
+    }
+    if (crtc->panningBorder[0] + crtc->panningBorder[2] > crtc->mode.HDisplay		||
+	crtc->panningBorder[1] + crtc->panningBorder[3] > crtc->mode.VDisplay) {
+	memset (&crtc->panningBorder, 0, 4*sizeof(INT16));
+	return FALSE;
+    }
+    return TRUE;
+}
+
+static void
+xf86RandR13Pan (xf86CrtcPtr crtc, int x, int y)
+{
+    int newX, newY;
+    int width, height;
+
+    if (crtc->version < 2)
+	return;
+
+    if (! crtc->enabled						||
+	crtc->panningTotalArea.x2 <= crtc->panningTotalArea.x1	||
+	crtc->panningTotalArea.y2 <= crtc->panningTotalArea.y1)
+	return;
+
+    newX   = crtc->x;
+    newY   = crtc->y;
+    width  = crtc->mode.HDisplay;
+    height = crtc->mode.VDisplay;
+
+    if (x >= crtc->panningTrackingArea.x1 && x < crtc->panningTrackingArea.x2 &&
+    	y >= crtc->panningTrackingArea.y1 && y < crtc->panningTrackingArea.y2) {
+	if (x < crtc->x + crtc->panningBorder[0])
+	    newX = x - crtc->panningBorder[0];
+	if (x >= crtc->x + width - crtc->panningBorder[2])
+	    newX = x - width + crtc->panningBorder[2] + 1;
+	if (y < crtc->y + crtc->panningBorder[1])
+	    newY = y - crtc->panningBorder[1];
+	if (y >= crtc->y + height - crtc->panningBorder[3])
+	    newY = y - height + crtc->panningBorder[3] + 1;
+    }
+    /* Validate against [xy]1 after [xy]2, to be sure that results are > 0 for [xy]1 > 0 */
+    if (newX >= crtc->panningTotalArea.x2 - width)
+	newX =  crtc->panningTotalArea.x2 - width - 1;
+    if (newX <  crtc->panningTotalArea.x1)
+	newX =  crtc->panningTotalArea.x1;
+    if (newY >= crtc->panningTotalArea.y2 - height)
+	newY =  crtc->panningTotalArea.y2 - height - 1;
+    if (newY <  crtc->panningTotalArea.y1)
+	newY =  crtc->panningTotalArea.y1;
+    if (newX != crtc->x || newY != crtc->y)
+	xf86CrtcPan (crtc, newX, newY);
+}
+
 static Bool
 xf86RandR12GetInfo (ScreenPtr pScreen, Rotation *rotations)
 {
@@ -332,6 +413,7 @@ xf86RandR12ScreenSetSize (ScreenPtr	pScreen,
     WindowPtr		pRoot = WindowTable[pScreen->myNum];
     PixmapPtr		pScrnPix = (*pScreen->GetScreenPixmap)(pScreen);
     Bool		ret = FALSE;
+    int                 c;
 
 #if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(7,0,0,0,0)
     if (xf86RandR12Key) {
@@ -352,6 +434,19 @@ xf86RandR12ScreenSetSize (ScreenPtr	pScreen,
 	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) {
+	    crtc->panningTotalArea.x2 += width  - pScreen->width;
+	    crtc->panningTotalArea.y2 += height - pScreen->height;
+	    crtc->panningTrackingArea.x2 += width  - pScreen->width;
+	    crtc->panningTrackingArea.y2 += height - pScreen->height;
+	    xf86RandR13VerifyPanningArea (crtc, width, height);
+	    xf86RandR13Pan (crtc, randrp->pointerX, randrp->pointerY);
+	}
+    }
 
     pScreen->width = pScrnPix->drawable.width = width;
     pScreen->height = pScrnPix->drawable.height = height;
@@ -762,6 +857,7 @@ xf86RandR12CrtcSet (ScreenPtr	    pScreen,
 		    int		    num_randr_outputs,
 		    RROutputPtr	    *randr_outputs)
 {
+    XF86RandRInfoPtr	randrp = XF86RANDRINFO(pScreen);
     ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
     xf86CrtcConfigPtr   config = XF86_CRTC_CONFIG_PTR(pScrn);
     xf86CrtcPtr		crtc = randr_crtc->devPrivate;
@@ -841,6 +937,8 @@ xf86RandR12CrtcSet (ScreenPtr	    pScreen,
 		xfree(save_crtcs);
 		return FALSE;
 	    }
+	    xf86RandR13VerifyPanningArea (crtc, pScreen->width, pScreen->height);
+	    xf86RandR13Pan (crtc, randrp->pointerX, randrp->pointerY);
 	    /*
 	     * Save the last successful setting for EnterVT
 	     */
@@ -1187,6 +1285,62 @@ xf86RandR12TellChanged (ScreenPtr pScreen)
 static void
 xf86RandR12PointerMoved (int scrnIndex, int x, int y)
 {
+    ScreenPtr		pScreen = screenInfo.screens[scrnIndex];
+    ScrnInfoPtr		pScrn   = XF86SCRNINFO(pScreen);
+    xf86CrtcConfigPtr	config  = XF86_CRTC_CONFIG_PTR(pScrn);
+    XF86RandRInfoPtr	randrp  = XF86RANDRINFO(pScreen);
+    int c;
+
+    randrp->pointerX = x;
+    randrp->pointerY = y;
+    for (c = 0; c < config->num_crtc; c++)
+	xf86RandR13Pan (config->crtc[c], x, y);
+}
+
+static Bool
+xf86RandR13GetPanning (ScreenPtr           pScreen,
+		       RRCrtcPtr           randr_crtc,
+		       BoxPtr              totalArea,
+		       BoxPtr              trackingArea,
+		       INT16               *border)
+{
+    xf86CrtcPtr		crtc = randr_crtc->devPrivate;
+
+    if (crtc->version < 2)
+	return FALSE;
+    if (totalArea)
+	memcpy (totalArea,    &crtc->panningTotalArea,    sizeof(BoxRec));
+    if (trackingArea)
+	memcpy (trackingArea, &crtc->panningTrackingArea, sizeof(BoxRec));
+    if (border)
+	memcpy (border,        crtc->panningBorder,       4*sizeof(INT16));
+
+    return TRUE;
+}
+
+static Bool
+xf86RandR13SetPanning (ScreenPtr           pScreen,
+		       RRCrtcPtr           randr_crtc,
+		       BoxPtr              totalArea,
+		       BoxPtr              trackingArea,
+		       INT16               *border)
+{
+    XF86RandRInfoPtr	randrp  = XF86RANDRINFO(pScreen);
+    xf86CrtcPtr		crtc = randr_crtc->devPrivate;
+    int			ret;
+
+    if (crtc->version < 2)
+	return FALSE;
+    if (totalArea)
+	memcpy (&crtc->panningTotalArea, totalArea, sizeof(BoxRec));
+    if (trackingArea)
+	memcpy (&crtc->panningTrackingArea, trackingArea, sizeof(BoxRec));
+    if (border)
+	memcpy (crtc->panningBorder, border, 4*sizeof(INT16));
+    ret = xf86RandR13VerifyPanningArea (crtc, pScreen->width, pScreen->height);
+    xf86RandR13Pan (crtc, randrp->pointerX, randrp->pointerY);
+
+    return ret;
 }
 
 static Bool
@@ -1203,6 +1357,8 @@ xf86RandR12Init12 (ScreenPtr pScreen)
     rp->rrOutputValidateMode = xf86RandR12OutputValidateMode;
 #if RANDR_13_INTERFACE
     rp->rrOutputGetProperty = xf86RandR13OutputGetProperty;
+    rp->rrGetPanning = xf86RandR13GetPanning;
+    rp->rrSetPanning = xf86RandR13SetPanning;
 #endif
     rp->rrModeDestroy = xf86RandR12ModeDestroy;
     rp->rrSetConfig = NULL;
commit 834cbc16f3eb539704faade7bff347b161ce69d9
Author: Matthias Hopf <mhopf at suse.de>
Date:   Fri Nov 28 17:39:23 2008 +0100

    randr: Crtc interface update for panning support.

diff --git a/hw/xfree86/modes/xf86Crtc.h b/hw/xfree86/modes/xf86Crtc.h
index 24195a3..097935f 100644
--- a/hw/xfree86/modes/xf86Crtc.h
+++ b/hw/xfree86/modes/xf86Crtc.h
@@ -213,9 +213,16 @@ typedef struct _xf86CrtcFuncs {
     Bool
     (*set_mode_major)(xf86CrtcPtr crtc, DisplayModePtr mode,
 		      Rotation rotation, int x, int y);
+
+    /**
+     * Callback for panning. Doesn't change the mode.
+     */
+    void
+    (*pan)(xf86CrtcPtr crtc, int x, int y);
+
 } xf86CrtcFuncsRec, *xf86CrtcFuncsPtr;
 
-#define XF86_CRTC_VERSION 1
+#define XF86_CRTC_VERSION 2
 
 struct _xf86Crtc {
     /**
@@ -321,6 +328,15 @@ struct _xf86Crtc {
      * Bounding box in screen space
      */
     BoxRec	    bounds;
+    /**
+     * Panning:
+     * TotalArea: total panning area, larger than CRTC's size
+     * TrackingArea: Area of the pointer for which the CRTC is panned
+     * border: Borders of the displayed CRTC area which induces panning if the pointer reaches them
+     */
+    BoxRec          panningTotalArea;
+    BoxRec          panningTrackingArea;
+    INT16           panningBorder[4];
 };
 
 typedef struct _xf86OutputFuncs {
@@ -678,6 +694,9 @@ extern _X_EXPORT Bool
 xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation,
 		 int x, int y);
 
+void
+xf86CrtcPan (xf86CrtcPtr crtc, int x, int y);
+
 /*
  * Assign crtc rotation during mode set
  */
@@ -868,4 +887,19 @@ xf86_unwrap_crtc_notify(ScreenPtr pScreen, xf86_crtc_notify_proc_ptr old);
 extern _X_EXPORT void
 xf86_crtc_notify(ScreenPtr pScreen);
 
+/**
+ * Panning
+ */
+Bool
+xf86_crtc_get_panning(ScrnInfoPtr pScrn,
+		      BoxPtr      totalArea,
+		      BoxPtr      TrackingArea,
+		      INT16      *border);
+
+Bool
+xf86_crtc_set_panning(ScrnInfoPtr pScrn,
+		      BoxPtr      totalArea,
+		      BoxPtr      TrackingArea,
+		      INT16      *border);
+
 #endif /* _XF86CRTC_H_ */
commit a475eb9feec75e9ce1e316da0f1679acd7dd3aa8
Author: Matthias Hopf <mhopf at suse.de>
Date:   Fri Nov 28 17:38:52 2008 +0100

    randr: Weird enough, crtc->version was never set upon creation. Fix that.

diff --git a/hw/xfree86/modes/xf86Crtc.c b/hw/xfree86/modes/xf86Crtc.c
index 948a56b..bd64e03 100644
--- a/hw/xfree86/modes/xf86Crtc.c
+++ b/hw/xfree86/modes/xf86Crtc.c
@@ -96,6 +96,7 @@ xf86CrtcCreate (ScrnInfoPtr		scrn,
     crtc = xcalloc (sizeof (xf86CrtcRec), 1);
     if (!crtc)
 	return NULL;
+    crtc->version = XF86_CRTC_VERSION;
     crtc->scrn = scrn;
     crtc->funcs = funcs;
 #ifdef RANDR_12_INTERFACE


More information about the xorg-commit mailing list