From 37946c9c8a4afa4a4fc1fe9864a8eec1c4571d2c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 16 Jan 2007 12:14:55 +1100 Subject: [PATCH] Interim work on rotation support with new xf86 code. Yes, there are lots of bits tied together here, and we should split this patch apart. Move I830 mode setting to xf86 mode setting. Make mode setting function also set the base address. This should fix problems where the base gets set incorrectly at times. Add driver-independent rotation support, requires driver-specific hooks for shadow pixmap allocation, otherwise it uses Render for painting. --- src/i830.h | 2 ++ src/i830_crt.c | 2 +- src/i830_cursor.c | 2 +- src/i830_display.c | 10 ++++------ src/i830_driver.c | 10 ++++++++-- src/i830_randr.c | 37 ++++++++++++++++--------------------- src/i830_tv.c | 2 +- src/i830_xf86Crtc.c | 16 +++++++++++----- src/i830_xf86Crtc.h | 29 +++++++++++++++++------------ src/i830_xf86Rotate.c | 21 ++++++++++----------- 10 files changed, 71 insertions(+), 60 deletions(-) diff --git a/src/i830.h b/src/i830.h index 95bea2f0..66dad9b9 100644 --- a/src/i830.h +++ b/src/i830.h @@ -221,6 +221,7 @@ enum last_3d { LAST_3D_ROTATION }; +#if 0 typedef struct _I830PipeRec { Bool enabled; int x; @@ -233,6 +234,7 @@ typedef struct _I830PipeRec { RRCrtcPtr randr_crtc; #endif } I830PipeRec, *I830PipePtr; +#endif typedef struct _I830Rec { unsigned char *MMIOBase; diff --git a/src/i830_crt.c b/src/i830_crt.c index 00e637ad..573e6526 100644 --- a/src/i830_crt.c +++ b/src/i830_crt.c @@ -314,7 +314,7 @@ i830_crt_detect(xf86OutputPtr output) if (intel_output->load_detect_temp) { xf86SetModeCrtc (&mode, INTERLACE_HALVE_V); - xf86CrtcSetMode (crtc, &mode, RR_Rotate_0); + xf86CrtcSetMode (crtc, &mode, RR_Rotate_0, 0, 0); } connected = i830_crt_detect_load (crtc, output); diff --git a/src/i830_cursor.c b/src/i830_cursor.c index 81cb3bd8..5e7a21a1 100644 --- a/src/i830_cursor.c +++ b/src/i830_cursor.c @@ -492,7 +492,7 @@ I830SetCursorPosition(ScrnInfoPtr pScrn, int x, int y) for (pipe = 0; pipe < xf86_config->num_crtc; pipe++) { xf86CrtcPtr crtc = xf86_config->crtc[pipe]; - DisplayModePtr mode = &crtc->curMode; + DisplayModePtr mode = &crtc->mode; int thisx = x - crtc->x; int thisy = y - crtc->y; diff --git a/src/i830_display.c b/src/i830_display.c index d80eb4e0..de6c7225 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -358,9 +358,6 @@ i830PipeSetBase(xf86CrtcPtr crtc, int x, int y) OUTREG(dspbase, Start + ((y * pScrn->displayWidth + x) * pI830->cpp)); (void) INREG(dspbase); } - - crtc->x = x; - crtc->y = y; } /** @@ -601,7 +598,8 @@ i830_crtc_mode_fixup(xf86CrtcPtr crtc, DisplayModePtr mode, */ static void i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode, - DisplayModePtr adjusted_mode) + DisplayModePtr adjusted_mode, + int x, int y) { ScrnInfoPtr pScrn = crtc->scrn; xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); @@ -837,7 +835,7 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode, OUTREG(dspcntr_reg, dspcntr); /* Flush the plane changes */ - i830PipeSetBase(crtc, crtc->x, crtc->y); + i830PipeSetBase(crtc, x, y); i830WaitForVblank(pScrn); } @@ -901,7 +899,7 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, Rotation rotation) { ok = xf86CrtcSetMode(crtc, i830PipeFindClosestMode(crtc, pMode), - rotation); + rotation, 0, 0); if (!ok) goto done; crtc->desiredMode = *pMode; diff --git a/src/i830_driver.c b/src/i830_driver.c index daa5a3b2..56a599cc 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -3020,7 +3020,10 @@ i830AdjustFrame(int scrnIndex, int x, int y, int flags) (*pI830->AccelInfoRec->Sync)(pScrn); pI830->AccelInfoRec->NeedToSync = FALSE; } + /* XXX should have xf86-based frame adjuster */ i830PipeSetBase(crtc, output->initial_x + x, output->initial_y + y); + crtc->x = output->initial_x + x; + crtc->y = output->initial_y + y; } } @@ -3138,14 +3141,17 @@ I830EnterVT(int scrnIndex, int flags) xf86CrtcPtr crtc = xf86_config->crtc[i]; /* Mark that we'll need to re-set the mode for sure */ - memset(&crtc->curMode, 0, sizeof(crtc->curMode)); + memset(&crtc->mode, 0, sizeof(crtc->mode)); if (!crtc->desiredMode.CrtcHDisplay) { crtc->desiredMode = *i830PipeFindClosestMode (crtc, pScrn->currentMode); crtc->desiredRotation = RR_Rotate_0; + crtc->desiredX = 0; + crtc->desiredY = 0; } - if (!xf86CrtcSetMode (crtc, &crtc->desiredMode, crtc->desiredRotation)) + if (!xf86CrtcSetMode (crtc, &crtc->desiredMode, crtc->desiredRotation, + crtc->desiredX, crtc->desiredY)) return FALSE; } diff --git a/src/i830_randr.c b/src/i830_randr.c index d6df4190..3aaf88b1 100644 --- a/src/i830_randr.c +++ b/src/i830_randr.c @@ -393,8 +393,8 @@ xf86RandR12CreateScreenResources (ScreenPtr pScreen) for (c = 0; c < config->num_crtc; c++) { xf86CrtcPtr crtc = config->crtc[c]; - int crtc_width = crtc->x + crtc->curMode.HDisplay; - int crtc_height = crtc->y + crtc->curMode.VDisplay; + int crtc_width = crtc->x + crtc->mode.HDisplay; + int crtc_height = crtc->y + crtc->mode.VDisplay; if (crtc->enabled && crtc_width > width) width = crtc_width; @@ -533,7 +533,7 @@ xf86RandR12CrtcNotify (RRCrtcPtr randr_crtc) xf86CrtcPtr crtc = randr_crtc->devPrivate; xf86OutputPtr output; int i, j; - DisplayModePtr curMode = &crtc->curMode; + DisplayModePtr mode = &crtc->mode; Bool ret; randr_outputs = ALLOCATE_LOCAL(config->num_output * sizeof (RROutputPtr)); @@ -541,7 +541,7 @@ xf86RandR12CrtcNotify (RRCrtcPtr randr_crtc) return FALSE; x = crtc->x; y = crtc->y; - rotation = crtc->curRotation; + rotation = crtc->rotation; numOutputs = 0; randr_mode = NULL; for (i = 0; i < config->num_output; i++) @@ -558,7 +558,7 @@ xf86RandR12CrtcNotify (RRCrtcPtr randr_crtc) for (j = 0; j < randr_output->numModes; j++) { DisplayModePtr outMode = randr_output->modes[j]->devPrivate; - if (xf86ModesEqual(curMode, outMode)) + if (xf86ModesEqual(mode, outMode)) { randr_mode = randr_output->modes[j]; break; @@ -587,7 +587,6 @@ xf86RandR12CrtcSet (ScreenPtr pScreen, xf86CrtcPtr crtc = randr_crtc->devPrivate; DisplayModePtr mode = randr_mode ? randr_mode->devPrivate : NULL; Bool changed = FALSE; - Bool pos_changed; int o, ro; xf86CrtcPtr *save_crtcs; Bool save_enabled = crtc->enabled; @@ -595,12 +594,11 @@ xf86RandR12CrtcSet (ScreenPtr pScreen, save_crtcs = ALLOCATE_LOCAL(config->num_crtc * sizeof (xf86CrtcPtr)); if ((mode != NULL) != crtc->enabled) changed = TRUE; - else if (mode && !xf86ModesEqual (&crtc->curMode, mode)) + else if (mode && !xf86ModesEqual (&crtc->mode, mode)) changed = TRUE; - pos_changed = changed; if (x != crtc->x || y != crtc->y) - pos_changed = TRUE; + changed = TRUE; for (o = 0; o < config->num_output; o++) { xf86OutputPtr output = config->output[o]; @@ -627,18 +625,11 @@ xf86RandR12CrtcSet (ScreenPtr pScreen, /* XXX need device-independent mode setting code through an API */ if (changed) { - I830Ptr pI830 = I830PTR(pScrn); crtc->enabled = mode != NULL; - /* Sync the engine before adjust mode */ - if (pI830->AccelInfoRec && pI830->AccelInfoRec->NeedToSync) { - (*pI830->AccelInfoRec->Sync)(pScrn); - pI830->AccelInfoRec->NeedToSync = FALSE; - } - if (mode) { - if (!xf86CrtcSetMode (crtc, mode, rotation)) + if (!xf86CrtcSetMode (crtc, mode, rotation, x, y)) { crtc->enabled = save_enabled; for (o = 0; o < config->num_output; o++) @@ -649,14 +640,16 @@ xf86RandR12CrtcSet (ScreenPtr pScreen, DEALLOCATE_LOCAL(save_crtcs); return FALSE; } + /* + * Save the last successful setting for EnterVT + */ crtc->desiredMode = *mode; + crtc->desiredRotation = rotation; + crtc->desiredX = x; + crtc->desiredY = y; } xf86DisableUnusedFunctions (pScrn); - - i830DumpRegs(pScrn); } - if (pos_changed && mode) - i830PipeSetBase(crtc, x, y); DEALLOCATE_LOCAL(save_crtcs); return xf86RandR12CrtcNotify (randr_crtc); } @@ -817,6 +810,8 @@ xf86RandR12SetInfo12 (ScreenPtr pScreen) return TRUE; } + + /* * Query the hardware for the current state, then mirror * that to RandR diff --git a/src/i830_tv.c b/src/i830_tv.c index a76cbffa..79b6ae8b 100644 --- a/src/i830_tv.c +++ b/src/i830_tv.c @@ -1065,7 +1065,7 @@ i830_tv_detect(xf86OutputPtr output) /* we only need the pixel clock set correctly here */ mode = reported_modes[0]; xf86SetModeCrtc (&mode, INTERLACE_HALVE_V); - xf86CrtcSetMode (crtc, &mode, RR_Rotate_0); + xf86CrtcSetMode (crtc, &mode, RR_Rotate_0, 0, 0); } i830_tv_detect_type (crtc, output); i830ReleaseLoadDetectPipe (output); diff --git a/src/i830_xf86Crtc.c b/src/i830_xf86Crtc.c index 5eb55e96..504ea0b9 100644 --- a/src/i830_xf86Crtc.c +++ b/src/i830_xf86Crtc.c @@ -87,7 +87,7 @@ xf86CrtcCreate (ScrnInfoPtr scrn, #ifdef RANDR_12_INTERFACE crtc->randr_crtc = NULL; #endif - crtc->curRotation = RR_Rotate_0; + crtc->rotation = RR_Rotate_0; crtc->desiredRotation = RR_Rotate_0; if (xf86_config->crtc) crtcs = xrealloc (xf86_config->crtc, @@ -145,7 +145,8 @@ xf86CrtcInUse (xf86CrtcPtr crtc) * Sets the given video mode on the given crtc */ Bool -xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation) +xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation, + int x, int y) { ScrnInfoPtr scrn = crtc->scrn; xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); @@ -166,6 +167,8 @@ xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation) didLock = crtc->funcs->lock (crtc); + /* XXX short-circuit changes to base location only */ + /* 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. @@ -211,7 +214,7 @@ xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation) /* 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->funcs->mode_set(crtc, mode, adjusted_mode, x, y); for (i = 0; i < xf86_config->num_output; i++) { xf86OutputPtr output = xf86_config->output[i]; @@ -228,7 +231,10 @@ xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation) output->funcs->dpms(output, DPMSModeOn); } - crtc->curMode = *mode; + crtc->mode = *mode; + crtc->x = x; + crtc->y = y; + crtc->rotation = rotation; /* XXX free adjustedmode */ ret = TRUE; @@ -1401,7 +1407,7 @@ xf86DisableUnusedFunctions(ScrnInfoPtr pScrn) if (!crtc->enabled) { crtc->funcs->dpms(crtc, DPMSModeOff); - memset(&crtc->curMode, 0, sizeof(crtc->curMode)); + memset(&crtc->mode, 0, sizeof(crtc->mode)); } } } diff --git a/src/i830_xf86Crtc.h b/src/i830_xf86Crtc.h index e72dda63..4b17dce4 100644 --- a/src/i830_xf86Crtc.h +++ b/src/i830_xf86Crtc.h @@ -70,7 +70,6 @@ typedef struct _xf86CrtcFuncs { void (*restore)(xf86CrtcPtr crtc); - /** * Lock CRTC prior to mode setting, mostly for DRI. * Returns whether unlock is needed @@ -102,7 +101,8 @@ typedef struct _xf86CrtcFuncs { void (*mode_set)(xf86CrtcPtr crtc, DisplayModePtr mode, - DisplayModePtr adjusted_mode); + DisplayModePtr adjusted_mode, + int x, int y); /* Set the color ramps for the CRTC to the given values. */ void @@ -141,13 +141,6 @@ struct _xf86Crtc { */ Bool enabled; - /** - * Position on screen - * - * Locates this CRTC within the frame buffer - */ - int x, y; - /** Track whether cursor is within CRTC range */ Bool cursorInRange; @@ -161,9 +154,15 @@ struct _xf86Crtc { * It will be cleared when the VT is not active or * during server startup */ - DisplayModeRec curMode; - Rotation curRotation; + DisplayModeRec mode; + Rotation rotation; PixmapPtr rotatedPixmap; + /** + * Position on screen + * + * Locates this CRTC within the frame buffer + */ + int x, y; /** * Desired mode @@ -175,6 +174,7 @@ struct _xf86Crtc { */ DisplayModeRec desiredMode; Rotation desiredRotation; + int desiredX, desiredY; /** crtc-specific functions */ const xf86CrtcFuncsRec *funcs; @@ -396,6 +396,10 @@ typedef struct _xf86CrtcConfig { /* For crtc-based rotation */ DamagePtr rotationDamage; + + /* DGA */ + unsigned int dga_flags; + } xf86CrtcConfigRec, *xf86CrtcConfigPtr; extern int xf86CrtcConfigPrivateIndex; @@ -448,7 +452,8 @@ xf86FreeCrtc (xf86CrtcPtr crtc); * Sets the given video mode on the given crtc */ Bool -xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation); +xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation, + int x, int y); /* * Assign crtc rotation during mode set diff --git a/src/i830_xf86Rotate.c b/src/i830_xf86Rotate.c index 12b20919..5482a6e1 100644 --- a/src/i830_xf86Rotate.c +++ b/src/i830_xf86Rotate.c @@ -128,7 +128,7 @@ xf86RotateCrtcRedisplay (xf86CrtcPtr crtc, RegionPtr region) transform.matrix[2][2] = 1; transform.matrix[0][2] = crtc->x; transform.matrix[1][2] = crtc->y; - switch (crtc->curRotation & 0xf) { + switch (crtc->rotation & 0xf) { case RR_Rotate_0: transform.matrix[0][0] = 1; transform.matrix[1][1] = 1; @@ -137,28 +137,28 @@ xf86RotateCrtcRedisplay (xf86CrtcPtr crtc, RegionPtr region) /* XXX probably wrong */ transform.matrix[0][1] = 1; transform.matrix[1][0] = -1; - transform.matrix[1][2] += crtc->curMode.HDisplay; + transform.matrix[1][2] += crtc->mode.HDisplay; break; case RR_Rotate_180: /* XXX probably wrong */ transform.matrix[0][0] = -1; transform.matrix[1][1] = -1; - transform.matrix[0][2] += crtc->curMode.HDisplay; - transform.matrix[1][2] += crtc->curMode.VDisplay; + transform.matrix[0][2] += crtc->mode.HDisplay; + transform.matrix[1][2] += crtc->mode.VDisplay; break; case RR_Rotate_270: /* XXX probably wrong */ transform.matrix[0][1] = -1; transform.matrix[1][0] = 1; - transform.matrix[0][2] += crtc->curMode.VDisplay; + transform.matrix[0][2] += crtc->mode.VDisplay; break; } /* handle reflection */ - if (crtc->curRotation & RR_Reflect_X) + if (crtc->rotation & RR_Reflect_X) { /* XXX figure this out */ } - if (crtc->curRotation & RR_Reflect_Y) + if (crtc->rotation & RR_Reflect_Y) { /* XXX figure this out too */ } @@ -191,16 +191,16 @@ xf86RotateRedisplay(ScreenPtr pScreen) { xf86CrtcPtr crtc = xf86_config->crtc[c]; - if (crtc->curRotation != RR_Rotate_0) + if (crtc->rotation != RR_Rotate_0) { BoxRec box; RegionRec crtc_damage; /* compute portion of damage that overlaps crtc */ box.x1 = crtc->x; - box.x2 = crtc->x + mode_width (&crtc->curMode, crtc->curRotation); + box.x2 = crtc->x + mode_width (&crtc->mode, crtc->rotation); box.y1 = crtc->y; - box.y2 = crtc->y + mode_height (&crtc->curMode, crtc->curRotation); + box.y2 = crtc->y + mode_height (&crtc->mode, crtc->rotation); REGION_INIT(pScreen, &crtc_damage, &box, 1); REGION_INTERSECT (pScreen, &crtc_damage, &crtc_damage, region); @@ -319,6 +319,5 @@ bail1: } /* All done */ - crtc->curRotation = rotation; return TRUE; }