[PATCH 09/13] xserver: randr: Panning support

Matthias Hopf mhopf at suse.de
Fri Nov 28 08:49:31 PST 2008


---
 hw/xfree86/modes/xf86Crtc.c    |   24 ++++++-
 hw/xfree86/modes/xf86RandR12.c |  156 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 178 insertions(+), 2 deletions(-)

diff --git a/hw/xfree86/modes/xf86Crtc.c b/hw/xfree86/modes/xf86Crtc.c
index 1c6eed0..566d703 100644
--- a/hw/xfree86/modes/xf86Crtc.c
+++ b/hw/xfree86/modes/xf86Crtc.c
@@ -315,8 +315,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.
@@ -405,6 +411,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 9d7750f..caf6429 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;
-- 
1.5.6



More information about the xorg mailing list