From b929d721efdb17bcc94b9984c4f34d0df3d267d5 Mon Sep 17 00:00:00 2001 From: Matthias Hopf Date: Fri, 28 Nov 2008 17:49:31 +0100 Subject: [PATCH] randr: Panning support --- 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 bd64e037a..0b5952112 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 62f1edb5b..fda2d25bf 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;