diff options
author | Keith Packard <keithp@neko.keithp.com> | 2007-01-29 21:25:13 -0800 |
---|---|---|
committer | Keith Packard <keithp@neko.keithp.com> | 2007-01-29 21:25:13 -0800 |
commit | c8581254cb811f76aa6eae49d74489b543b3eb05 (patch) | |
tree | 95de90111a0088a78856647b3595db52787ad356 | |
parent | 9da1791eeca446cd59e2e7d0803e8a7920dbbea5 (diff) | |
parent | d329fa121b2401cadb991c2854e077cfa68e15e8 (diff) |
Merge branch 'modesetting-rotation' into modesetting
This adds reasonably driver-independent rotation support to the common
layer. The piece required in the driver is to allocate and redirect the crtc
to a shadow frame buffer. The driver uses Render to perform the actual
rotation operation (which leaves us free to do fun projective transforms at
some point in the future :-).
-rw-r--r-- | src/Makefile.am | 1 | ||||
-rw-r--r-- | src/i830.h | 23 | ||||
-rw-r--r-- | src/i830_crt.c | 2 | ||||
-rw-r--r-- | src/i830_cursor.c | 160 | ||||
-rw-r--r-- | src/i830_display.c | 289 | ||||
-rw-r--r-- | src/i830_display.h | 6 | ||||
-rw-r--r-- | src/i830_driver.c | 99 | ||||
-rw-r--r-- | src/i830_exa.c | 13 | ||||
-rw-r--r-- | src/i830_lvds.c | 6 | ||||
-rw-r--r-- | src/i830_memory.c | 240 | ||||
-rw-r--r-- | src/i830_modes.c | 6 | ||||
-rw-r--r-- | src/i830_randr.c | 46 | ||||
-rw-r--r-- | src/i830_tv.c | 2 | ||||
-rw-r--r-- | src/i830_video.c | 22 | ||||
-rw-r--r-- | src/i830_xf86Crtc.c | 323 | ||||
-rw-r--r-- | src/i830_xf86Crtc.h | 85 | ||||
-rw-r--r-- | src/i830_xf86Modes.c | 26 | ||||
-rw-r--r-- | src/i830_xf86Modes.h | 69 | ||||
-rw-r--r-- | src/i830_xf86Rename.h | 66 | ||||
-rw-r--r-- | src/i830_xf86Rotate.c | 401 | ||||
-rw-r--r-- | src/local_xf86Rename.h | 23 |
21 files changed, 1326 insertions, 582 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 80cea10a..02e85768 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -85,6 +85,7 @@ i810_drv_la_SOURCES = \ i830_xf86cvt.c \ i830_xf86Crtc.h \ i830_xf86Crtc.c \ + i830_xf86Rotate.c \ i915_3d.c \ i915_3d.h \ i915_reg.h \ @@ -195,8 +195,19 @@ extern const char *i830_output_type_names[]; typedef struct _I830CrtcPrivateRec { int pipe; + /* Lookup table values to be set when the CRTC is enabled */ CARD8 lut_r[256], lut_g[256], lut_b[256]; + +#ifdef I830_USE_XAA + FBLinearPtr rotate_mem_xaa; +#endif +#ifdef I830_USE_EXA + ExaOffscreenArea *rotate_mem_exa; +#endif + + I830MemRange cursor_mem; + I830MemRange cursor_mem_argb; } I830CrtcPrivateRec, *I830CrtcPrivatePtr; #define I830CrtcPrivate(c) ((I830CrtcPrivatePtr) (c)->driver_private) @@ -221,6 +232,7 @@ enum last_3d { LAST_3D_ROTATION }; +#if 0 typedef struct _I830PipeRec { Bool enabled; int x; @@ -233,6 +245,7 @@ typedef struct _I830PipeRec { RRCrtcPtr randr_crtc; #endif } I830PipeRec, *I830PipePtr; +#endif typedef struct _I830Rec { unsigned char *MMIOBase; @@ -271,8 +284,6 @@ typedef struct _I830Rec { I830MemRange EXAStateMem; /* specific exa state for G965 */ #endif /* Regions allocated either from the above pools, or from agpgart. */ - I830MemRange *CursorMem; - I830MemRange *CursorMemARGB; I830RingBuffer *LpRing; #if REMAP_RESERVED @@ -608,6 +619,14 @@ extern void i830WaitSync(ScrnInfoPtr pScrn); /* i830_memory.c */ Bool I830BindAGPMemory(ScrnInfoPtr pScrn); Bool I830UnbindAGPMemory(ScrnInfoPtr pScrn); +#ifdef I830_USE_XAA +FBLinearPtr +i830_xf86AllocateOffscreenLinear(ScreenPtr pScreen, int length, + int granularity, + MoveLinearCallbackProcPtr moveCB, + RemoveLinearCallbackProcPtr removeCB, + pointer privData); +#endif /* I830_USE_EXA */ /* i830_modes.c */ DisplayModePtr i830_ddc_get_modes(xf86OutputPtr output); diff --git a/src/i830_crt.c b/src/i830_crt.c index 4e9e3706..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); - i830PipeSetMode (crtc, &mode, FALSE); + 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..464eb6dd 100644 --- a/src/i830_cursor.c +++ b/src/i830_cursor.c @@ -94,9 +94,9 @@ I830SetPipeCursorBase (xf86CrtcPtr crtc) FatalError("Bad pipe number for cursor base setting\n"); if (pI830->CursorIsARGB) - cursor_mem = pI830->CursorMemARGB; + cursor_mem = &intel_crtc->cursor_mem_argb; else - cursor_mem = pI830->CursorMem; + cursor_mem = &intel_crtc->cursor_mem; if (pI830->CursorNeedsPhysical) { OUTREG(cursor_base, cursor_mem->Physical); @@ -251,21 +251,13 @@ I830CursorInit(ScreenPtr pScreen) infoPtr->HideCursor = I830HideCursor; infoPtr->ShowCursor = I830ShowCursor; infoPtr->UseHWCursor = I830UseHWCursor; - - pI830->pCurs = NULL; - #ifdef ARGB_CURSOR - pI830->CursorIsARGB = FALSE; - - if (pI830->CursorMemARGB->Start) { - /* Use ARGB if we were able to allocate the 16kb needed */ - infoPtr->UseHWCursorARGB = I830UseHWCursorARGB; - infoPtr->LoadCursorARGB = I830LoadCursorARGB; - } + infoPtr->UseHWCursorARGB = I830UseHWCursorARGB; + infoPtr->LoadCursorARGB = I830LoadCursorARGB; #endif - if (pI830->CursorNeedsPhysical && !pI830->CursorMem->Physical) - return FALSE; + pI830->pCurs = NULL; + I830HideCursor(pScrn); @@ -280,18 +272,16 @@ I830UseHWCursor(ScreenPtr pScreen, CursorPtr pCurs) pI830->pCurs = pCurs; - DPRINTF(PFX, "I830UseHWCursor\n"); - if (pI830->CursorNeedsPhysical && !pI830->CursorMem->Physical) - return FALSE; - return TRUE; } static void -I830LoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src) +I830CRTCLoadCursorImage(xf86CrtcPtr crtc, unsigned char *src) { + ScrnInfoPtr pScrn = crtc->scrn; I830Ptr pI830 = I830PTR(pScrn); - CARD8 *pcurs = (CARD8 *) (pI830->FbBase + pI830->CursorMem->Start); + I830CrtcPrivatePtr intel_crtc = crtc->driver_private; + CARD8 *pcurs = (CARD8 *) (pI830->FbBase + intel_crtc->cursor_mem.Start); int x, y; DPRINTF(PFX, "I830LoadCursorImage\n"); @@ -310,7 +300,7 @@ I830LoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src) (*(image + (x) / 8 + (y) * (128/8)) |=\ (int) (1 << (7-((x) % 8)))) - switch (pI830->rotation) { + switch (crtc->rotation) { case RR_Rotate_90: for (y = 0; y < 64; y++) { for (x = 0; x < 64; x++) { @@ -353,6 +343,17 @@ I830LoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src) } } +static void +I830LoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src) +{ + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + int pipe; + + for (pipe = 0; pipe < xf86_config->num_crtc; pipe++) { + I830CRTCLoadCursorImage(xf86_config->crtc[pipe], src); + } +} + #ifdef ARGB_CURSOR #include "cursorstr.h" @@ -360,15 +361,22 @@ static Bool I830UseHWCursorARGB (ScreenPtr pScreen, CursorPtr pCurs) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; I830Ptr pI830 = I830PTR(pScrn); + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + int i; DPRINTF(PFX, "I830UseHWCursorARGB\n"); pI830->pCurs = pCurs; - if (pScrn->bitsPerPixel == 8) - return FALSE; + /* Check that our ARGB allocations succeeded */ + for (i = 0; i < xf86_config->num_crtc; i++) { + I830CrtcPrivatePtr intel_crtc = xf86_config->crtc[i]->driver_private; + + if (!intel_crtc->cursor_mem_argb.Start) + return FALSE; + } - if (pI830->CursorNeedsPhysical && !pI830->CursorMemARGB->Physical) + if (pScrn->bitsPerPixel == 8) return FALSE; if (pCurs->bits->height <= 64 && pCurs->bits->width <= 64) @@ -377,10 +385,11 @@ static Bool I830UseHWCursorARGB (ScreenPtr pScreen, CursorPtr pCurs) return FALSE; } -static void I830LoadCursorARGB (ScrnInfoPtr pScrn, CursorPtr pCurs) +static void I830CRTCLoadCursorARGB (xf86CrtcPtr crtc, CursorPtr pCurs) { - I830Ptr pI830 = I830PTR(pScrn); - CARD32 *dst = (CARD32 *) (pI830->FbBase + pI830->CursorMemARGB->Start); + I830Ptr pI830 = I830PTR(crtc->scrn); + I830CrtcPrivatePtr intel_crtc = crtc->driver_private; + CARD32 *dst = (CARD32 *) (pI830->FbBase + intel_crtc->cursor_mem_argb.Start); CARD32 *image = (CARD32 *)pCurs->bits->argb; int x, y, w, h; @@ -394,7 +403,7 @@ static void I830LoadCursorARGB (ScrnInfoPtr pScrn, CursorPtr pCurs) w = pCurs->bits->width; h = pCurs->bits->height; - switch (pI830->rotation) { + switch (crtc->rotation) { case RR_Rotate_90: for (y = 0; y < h; y++) { for (x = 0; x < w; x++) @@ -447,58 +456,69 @@ static void I830LoadCursorARGB (ScrnInfoPtr pScrn, CursorPtr pCurs) *dst++ = 0; } } + +static void +I830LoadCursorARGB(ScrnInfoPtr pScrn, CursorPtr pCurs) +{ + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + int pipe; + + for (pipe = 0; pipe < xf86_config->num_crtc; pipe++) { + I830CRTCLoadCursorARGB(xf86_config->crtc[pipe], pCurs); + } +} #endif static void I830SetCursorPosition(ScrnInfoPtr pScrn, int x, int y) { - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); I830Ptr pI830 = I830PTR(pScrn); CARD32 temp; Bool inrange; - int oldx = x, oldy = y; - int hotspotx = 0, hotspoty = 0; + int root_x = x, root_y = y; int pipe; - oldx += pScrn->frameX0; /* undo what xf86HWCurs did */ - oldy += pScrn->frameY0; - - switch (pI830->rotation) { - case RR_Rotate_0: - x = oldx; - y = oldy; - break; - case RR_Rotate_90: - x = oldy; - y = pScrn->pScreen->width - oldx; - hotspoty = I810_CURSOR_X; - break; - case RR_Rotate_180: - x = pScrn->pScreen->width - oldx; - y = pScrn->pScreen->height - oldy; - hotspotx = I810_CURSOR_X; - hotspoty = I810_CURSOR_Y; - break; - case RR_Rotate_270: - x = pScrn->pScreen->height - oldy; - y = oldx; - hotspotx = I810_CURSOR_Y; - break; - } - - x -= hotspotx; - y -= hotspoty; + root_x = x + pScrn->frameX0; /* undo what xf86HWCurs did */ + root_y = y + pScrn->frameY0; for (pipe = 0; pipe < xf86_config->num_crtc; pipe++) { - xf86CrtcPtr crtc = xf86_config->crtc[pipe]; - DisplayModePtr mode = &crtc->curMode; - int thisx = x - crtc->x; - int thisy = y - crtc->y; + xf86CrtcPtr crtc = xf86_config->crtc[pipe]; + DisplayModePtr mode = &crtc->mode; + int thisx = 0; + int thisy = 0; + int hotspotx = 0, hotspoty = 0; if (!crtc->enabled) continue; + switch (crtc->rotation) { + case RR_Rotate_0: + thisx = (root_x - crtc->x); + thisy = (root_y - crtc->y); + break; + case RR_Rotate_90: + thisx = (root_y - crtc->y); + thisy = mode->VDisplay - (root_x - crtc->x); + hotspoty = I810_CURSOR_X; + break; + case RR_Rotate_180: + thisx = mode->HDisplay - (root_x - crtc->x); + thisy = mode->VDisplay - (root_y - crtc->y); + hotspotx = I810_CURSOR_X; + hotspoty = I810_CURSOR_Y; + break; + case RR_Rotate_270: + thisx = mode->VDisplay - (root_y - crtc->y); + thisy = (root_x - crtc->x); + hotspotx = I810_CURSOR_Y; + break; + } + + thisx -= hotspotx; + thisy -= hotspoty; + /* * There is a screen display problem when the cursor position is set * wholely outside of the viewport. We trap that here, turning the @@ -541,19 +561,11 @@ I830SetCursorPosition(ScrnInfoPtr pScrn, int x, int y) static void I830ShowCursor(ScrnInfoPtr pScrn) { - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); - I830Ptr pI830 = I830PTR(pScrn); + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + I830Ptr pI830 = I830PTR(pScrn); int pipe; - DPRINTF(PFX, "I830ShowCursor\n"); - DPRINTF(PFX, - "Value of CursorMem->Physical is %x, " - " Value of CursorMem->Start is %x ", - pI830->CursorMem->Physical, pI830->CursorMem->Start); - DPRINTF(PFX, - "Value of CursorMemARGB->Physical is %x, " - " Value of CursorMemARGB->Start is %x ", - pI830->CursorMemARGB->Physical, pI830->CursorMemARGB->Start); + DPRINTF(PFX, "I830ShowCursor\n"); pI830->cursorOn = TRUE; for (pipe = 0; pipe < xf86_config->num_crtc; pipe++) diff --git a/src/i830_display.c b/src/i830_display.c index f47a9dbf..82029850 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -342,9 +342,12 @@ i830PipeSetBase(xf86CrtcPtr crtc, int x, int y) int dspbase = (pipe == 0 ? DSPABASE : DSPBBASE); int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF); - if (I830IsPrimary(pScrn)) + if (crtc->rotatedPixmap != NULL) { + Start = (char *)crtc->rotatedPixmap->devPrivate.ptr - + (char *)pI830->FbBase; + } else if (I830IsPrimary(pScrn)) { Start = pI830->FrontBuffer.Start; - else { + } else { I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1); Start = pI8301->FrontBuffer2.Start; } @@ -358,9 +361,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; } /** @@ -465,23 +465,6 @@ i830PipeFindClosestMode(xf86CrtcPtr crtc, DisplayModePtr pMode) } /** - * Return whether any outputs are connected to the specified pipe - */ - -Bool -i830PipeInUse (xf86CrtcPtr crtc) -{ - ScrnInfoPtr pScrn = crtc->scrn; - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); - int i; - - for (i = 0; i < xf86_config->num_output; i++) - if (xf86_config->output[i]->crtc == crtc) - return TRUE; - return FALSE; -} - -/** * Sets the power management mode of the pipe and plane. * * This code should probably grow support for turning the cursor off and back @@ -581,6 +564,27 @@ i830_crtc_dpms(xf86CrtcPtr crtc, int mode) } static Bool +i830_crtc_lock (xf86CrtcPtr crtc) +{ + /* Sync the engine before mode switch */ + i830WaitSync(crtc->scrn); + +#ifdef XF86DRI + return I830DRILock(crtc->scrn); +#else + return FALSE; +#endif +} + +static void +i830_crtc_unlock (xf86CrtcPtr crtc) +{ +#ifdef XF86DRI + I830DRIUnlock (crtc->scrn); +#endif +} + +static Bool i830_crtc_mode_fixup(xf86CrtcPtr crtc, DisplayModePtr mode, DisplayModePtr adjusted_mode) { @@ -597,7 +601,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); @@ -833,7 +838,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); } @@ -881,165 +886,111 @@ i830_crtc_gamma_set(xf86CrtcPtr crtc, CARD16 *red, CARD16 *green, CARD16 *blue, } /** - * Sets the given video mode on the given pipe. + * Creates a locked-in-framebuffer pixmap of the given width and height for + * this CRTC's rotated shadow framebuffer. * - * Plane A is always output to pipe A, and plane B to pipe B. The plane - * will not be enabled if plane_enable is FALSE, which is used for - * load detection, when something else will be output to the pipe other than - * display data. + * The current implementation uses fixed buffers allocated at startup at the + * maximal size. */ -Bool -i830PipeSetMode(xf86CrtcPtr crtc, DisplayModePtr pMode, - Bool plane_enable) +static PixmapPtr +i830_crtc_shadow_create(xf86CrtcPtr crtc, int width, int height) { ScrnInfoPtr pScrn = crtc->scrn; - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); - int i; - Bool ret = FALSE; -#ifdef XF86DRI - Bool didLock = FALSE; -#endif - DisplayModePtr adjusted_mode; - - /* XXX: curMode */ - - adjusted_mode = xf86DuplicateMode(pMode); - - crtc->enabled = i830PipeInUse (crtc); - - if (!crtc->enabled) - { - /* XXX disable crtc? */ - return TRUE; - } - -#ifdef XF86DRI - didLock = I830DRILock(pScrn); -#endif - - /* 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. + ScreenPtr pScreen = pScrn->pScreen; + I830Ptr pI830 = I830PTR(pScrn); + I830CrtcPrivatePtr intel_crtc = crtc->driver_private; + unsigned long rotate_pitch; + PixmapPtr rotate_pixmap; + unsigned long rotate_offset; + int align = KB(4), size; + + rotate_pitch = pI830->displayWidth * pI830->cpp; + size = rotate_pitch * height; + +#ifdef I830_USE_EXA + /* We could get close to what we want here by just creating a pixmap like + * normal, but we have to lock it down in framebuffer, and there is no + * setter for offscreen area locking in EXA currently. So, we just + * allocate offscreen memory and fake up a pixmap header for it. */ - for (i = 0; i < xf86_config->num_output; i++) { - xf86OutputPtr output = xf86_config->output[i]; - - if (output->crtc != crtc) - continue; - - if (!output->funcs->mode_fixup(output, pMode, adjusted_mode)) { - ret = FALSE; - goto done; + if (pI830->useEXA) { + assert(intel_crtc->rotate_mem_exa == NULL); + + intel_crtc->rotate_mem_exa = exaOffscreenAlloc(pScreen, size, align, + TRUE, NULL, NULL); + if (intel_crtc->rotate_mem_exa == NULL) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Couldn't allocate shadow memory for rotated CRTC\n"); + return NULL; } + rotate_offset = intel_crtc->rotate_mem_exa->offset; } - - if (!crtc->funcs->mode_fixup(crtc, pMode, adjusted_mode)) { - ret = FALSE; - goto done; - } - - /* Disable the outputs and CRTCs before setting the mode. */ - for (i = 0; i < xf86_config->num_output; i++) { - xf86OutputPtr output = xf86_config->output[i]; - - if (output->crtc != crtc) - continue; - - /* Disable the output as the first thing we do. */ - output->funcs->dpms(output, DPMSModeOff); - } - - crtc->funcs->dpms(crtc, DPMSModeOff); - - /* Set up the DPLL and any output state that needs to adjust or depend - * on the DPLL. - */ - crtc->funcs->mode_set(crtc, pMode, adjusted_mode); - for (i = 0; i < xf86_config->num_output; i++) { - xf86OutputPtr output = xf86_config->output[i]; - if (output->crtc == crtc) - output->funcs->mode_set(output, pMode, adjusted_mode); +#endif /* I830_USE_EXA */ +#ifdef I830_USE_XAA + if (!pI830->useEXA) { + /* The XFree86 linear allocator operates in units of screen pixels, + * sadly. + */ + size = (size + pI830->cpp - 1) / pI830->cpp; + align = (align + pI830->cpp - 1) / pI830->cpp; + + assert(intel_crtc->rotate_mem_xaa == NULL); + + intel_crtc->rotate_mem_xaa = + i830_xf86AllocateOffscreenLinear(pScreen, size, align, + NULL, NULL, NULL); + if (intel_crtc->rotate_mem_xaa == NULL) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Couldn't allocate shadow memory for rotated CRTC\n"); + return NULL; + } + rotate_offset = pI830->FrontBuffer.Start + + intel_crtc->rotate_mem_xaa->offset * pI830->cpp; } - - /* Now, enable the clocks, plane, pipe, and outputs that we set up. */ - crtc->funcs->dpms(crtc, DPMSModeOn); - for (i = 0; i < xf86_config->num_output; i++) { - xf86OutputPtr output = xf86_config->output[i]; - if (output->crtc == crtc) - output->funcs->dpms(output, DPMSModeOn); +#endif /* I830_USE_XAA */ + + rotate_pixmap = GetScratchPixmapHeader(pScrn->pScreen, + width, height, + pScrn->depth, + pScrn->bitsPerPixel, + rotate_pitch, + pI830->FbBase + rotate_offset); + if (rotate_pixmap == NULL) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Couldn't allocate shadow pixmap for rotated CRTC\n"); } - -#if 0 - /* - * If the display isn't solid, it may be running out - * of memory bandwidth. This code will dump out the - * pipe status, if bit 31 is on, the fifo underran - */ - for (i = 0; i < 4; i++) { - i830WaitForVblank(pScrn); - - OUTREG(pipestat_reg, INREG(pipestat_reg) | 0x80000000); - - i830WaitForVblank(pScrn); - - temp = INREG(pipestat_reg); - ErrorF ("pipe status 0x%x\n", temp); - } -#endif - - crtc->curMode = *pMode; - - /* XXX free adjustedmode */ - ret = TRUE; -done: -#ifdef XF86DRI - if (didLock) - I830DRIUnlock(pScrn); -#endif - return ret; + return rotate_pixmap; } -void -i830DisableUnusedFunctions(ScrnInfoPtr pScrn) +static void +i830_crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap) { - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); - int o, pipe; - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling unused functions\n"); + ScrnInfoPtr pScrn = crtc->scrn; + I830Ptr pI830 = I830PTR(pScrn); + I830CrtcPrivatePtr intel_crtc = crtc->driver_private; - for (o = 0; o < xf86_config->num_output; o++) - { - xf86OutputPtr output = xf86_config->output[o]; - if (!output->crtc) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling output %s\n", - output->name); - (*output->funcs->dpms)(output, DPMSModeOff); - } + FreeScratchPixmapHeader(rotate_pixmap); +#ifdef I830_USE_EXA + if (pI830->useEXA && intel_crtc->rotate_mem_exa != NULL) { + exaOffscreenFree(pScrn->pScreen, intel_crtc->rotate_mem_exa); + intel_crtc->rotate_mem_exa = NULL; } - - for (pipe = 0; pipe < xf86_config->num_crtc; pipe++) - { - xf86CrtcPtr crtc = xf86_config->crtc[pipe]; - I830CrtcPrivatePtr intel_crtc = crtc->driver_private; - int pipe = intel_crtc->pipe; - char *pipe_name = pipe == 0 ? "A" : "B"; - - if (!crtc->enabled) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling CRTC %s\n", - pipe_name); - crtc->funcs->dpms(crtc, DPMSModeOff); - - memset(&crtc->curMode, 0, sizeof(crtc->curMode)); - } +#endif /* I830_USE_EXA */ +#ifdef I830_USE_XAA + if (!pI830->useEXA) { + xf86FreeOffscreenLinear(intel_crtc->rotate_mem_xaa); + intel_crtc->rotate_mem_xaa = NULL; } +#endif /* I830_USE_XAA */ } + /** * This function configures the screens in clone mode on * all active outputs using a mode similar to the specified mode. */ Bool -i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) +i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, Rotation rotation) { xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); Bool ok = TRUE; @@ -1049,9 +1000,9 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) if (crtc && crtc->enabled) { - ok = i830PipeSetMode(crtc, - i830PipeFindClosestMode(crtc, pMode), - TRUE); + ok = xf86CrtcSetMode(crtc, + i830PipeFindClosestMode(crtc, pMode), + rotation, 0, 0); if (!ok) goto done; crtc->desiredMode = *pMode; @@ -1061,7 +1012,7 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) (int)(pMode->HDisplay * pMode->VDisplay * pMode->VRefresh / 1000000)); - i830DisableUnusedFunctions(pScrn); + xf86DisableUnusedFunctions(pScrn); i830DescribeOutputConfiguration(pScrn); @@ -1153,7 +1104,7 @@ i830GetLoadDetectPipe(xf86OutputPtr output) return output->crtc; for (i = 0; i < xf86_config->num_crtc; i++) - if (!i830PipeInUse(xf86_config->crtc[i])) + if (!xf86CrtcInUse (xf86_config->crtc[i])) break; if (i == xf86_config->num_crtc) @@ -1177,7 +1128,7 @@ i830ReleaseLoadDetectPipe(xf86OutputPtr output) { output->crtc = NULL; intel_output->load_detect_temp = FALSE; - i830DisableUnusedFunctions(pScrn); + xf86DisableUnusedFunctions(pScrn); } } @@ -1185,9 +1136,13 @@ static const xf86CrtcFuncsRec i830_crtc_funcs = { .dpms = i830_crtc_dpms, .save = NULL, /* XXX */ .restore = NULL, /* XXX */ + .lock = i830_crtc_lock, + .unlock = i830_crtc_unlock, .mode_fixup = i830_crtc_mode_fixup, .mode_set = i830_crtc_mode_set, .gamma_set = i830_crtc_gamma_set, + .shadow_create = i830_crtc_shadow_create, + .shadow_destroy = i830_crtc_shadow_destroy, .destroy = NULL, /* XXX */ }; diff --git a/src/i830_display.h b/src/i830_display.h index 66ab17e8..dc800553 100644 --- a/src/i830_display.h +++ b/src/i830_display.h @@ -30,16 +30,12 @@ /* i830_display.c */ DisplayModePtr i830PipeFindClosestMode(xf86CrtcPtr crtc, DisplayModePtr pMode); -Bool i830PipeSetMode(xf86CrtcPtr crtc, DisplayModePtr pMode, - Bool plane_enable); -void i830DisableUnusedFunctions(ScrnInfoPtr pScrn); -Bool i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode); +Bool i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, Rotation rotation); void i830PipeSetBase(xf86CrtcPtr crtc, int x, int y); void i830WaitForVblank(ScrnInfoPtr pScrn); void i830DescribeOutputConfiguration(ScrnInfoPtr pScrn); xf86CrtcPtr i830GetLoadDetectPipe(xf86OutputPtr output); void i830ReleaseLoadDetectPipe(xf86OutputPtr output); -Bool i830PipeInUse(xf86CrtcPtr crtc); void i830_crtc_init(ScrnInfoPtr pScrn, int pipe); void i830_crtc_load_lut(xf86CrtcPtr crtc); diff --git a/src/i830_driver.c b/src/i830_driver.c index 32729c17..d6d0df09 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -764,12 +764,6 @@ PreInitCleanup(ScrnInfoPtr pScrn) if (pI830->LpRing) xfree(pI830->LpRing); pI830->LpRing = NULL; - if (pI830->CursorMem) - xfree(pI830->CursorMem); - pI830->CursorMem = NULL; - if (pI830->CursorMemARGB) - xfree(pI830->CursorMemARGB); - pI830->CursorMemARGB = NULL; if (pI830->OverlayMem) xfree(pI830->OverlayMem); pI830->OverlayMem = NULL; @@ -1526,12 +1520,10 @@ I830PreInit(ScrnInfoPtr pScrn, int flags) /* Alloc our pointers for the primary head */ if (I830IsPrimary(pScrn)) { pI830->LpRing = xalloc(sizeof(I830RingBuffer)); - pI830->CursorMem = xalloc(sizeof(I830MemRange)); - pI830->CursorMemARGB = xalloc(sizeof(I830MemRange)); pI830->OverlayMem = xalloc(sizeof(I830MemRange)); pI830->overlayOn = xalloc(sizeof(Bool)); pI830->used3D = xalloc(sizeof(int)); - if (!pI830->LpRing || !pI830->CursorMem || !pI830->CursorMemARGB || + if (!pI830->LpRing || !pI830->OverlayMem || !pI830->overlayOn || !pI830->used3D) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Could not allocate primary data structures.\n"); @@ -2563,17 +2555,13 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) if (I830IsPrimary(pScrn)) { if (!pI830->LpRing) pI830->LpRing = xalloc(sizeof(I830RingBuffer)); - if (!pI830->CursorMem) - pI830->CursorMem = xalloc(sizeof(I830MemRange)); - if (!pI830->CursorMemARGB) - pI830->CursorMemARGB = xalloc(sizeof(I830MemRange)); if (!pI830->OverlayMem) pI830->OverlayMem = xalloc(sizeof(I830MemRange)); if (!pI830->overlayOn) pI830->overlayOn = xalloc(sizeof(Bool)); if (!pI830->used3D) pI830->used3D = xalloc(sizeof(int)); - if (!pI830->LpRing || !pI830->CursorMem || !pI830->CursorMemARGB || + if (!pI830->LpRing || !pI830->OverlayMem || !pI830->overlayOn || !pI830->used3D) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Could not allocate primary data structures.\n"); @@ -2588,8 +2576,6 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) if (!I830IsPrimary(pScrn)) { pI8301 = I830PTR(pI830->entityPrivate->pScrn_1); pI830->LpRing = pI8301->LpRing; - pI830->CursorMem = pI8301->CursorMem; - pI830->CursorMemARGB = pI8301->CursorMemARGB; pI830->OverlayMem = pI8301->OverlayMem; pI830->overlayOn = pI8301->overlayOn; pI830->used3D = pI8301->used3D; @@ -2638,15 +2624,6 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) } } - if (!pI830->SWCursor) { - if (pI830->CursorMem->Size == 0) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Disabling HW cursor because the cursor memory " - "allocation failed.\n"); - pI830->SWCursor = TRUE; - } - } - #ifdef I830_XV if (pI830->XvEnabled) { if (pI830->noAccel) { @@ -2882,7 +2859,23 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) shadowSetup(pScreen); /* support all rotations */ xf86RandR12Init (pScreen); - xf86RandR12SetRotations (pScreen, RR_Rotate_0 | RR_Rotate_90 | RR_Rotate_180 | RR_Rotate_270); + if (pI830->useEXA) { +#ifdef I830_USE_EXA + if (pI830->EXADriverPtr->exa_minor >= 1) { + xf86RandR12SetRotations (pScreen, RR_Rotate_0 | RR_Rotate_90 | + RR_Rotate_180 | RR_Rotate_270); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "EXA version %d.%d too old to support rotation\n", + pI830->EXADriverPtr->exa_major, + pI830->EXADriverPtr->exa_minor); + xf86RandR12SetRotations (pScreen, RR_Rotate_0); + } +#endif /* I830_USE_EXA */ + } else { + xf86RandR12SetRotations (pScreen, RR_Rotate_0 | RR_Rotate_90 | + RR_Rotate_180 | RR_Rotate_270); + } pI830->PointerMoved = pScrn->PointerMoved; pScrn->PointerMoved = I830PointerMoved; pI830->CreateScreenResources = pScreen->CreateScreenResources; @@ -2997,6 +2990,8 @@ i830AdjustFrame(int scrnIndex, int x, int y, int flags) /* Sync the engine before adjust frame */ i830WaitSync(pScrn); i830PipeSetBase(crtc, output->initial_x + x, output->initial_y + y); + crtc->x = output->initial_x + x; + crtc->y = output->initial_y + y; } } @@ -3107,18 +3102,24 @@ I830EnterVT(int scrnIndex, int flags) ResetState(pScrn, FALSE); SetHWOperatingState(pScrn); - i830DisableUnusedFunctions(pScrn); + xf86DisableUnusedFunctions(pScrn); for (i = 0; i < xf86_config->num_crtc; i++) { 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 (!i830PipeSetMode (crtc, &crtc->desiredMode, TRUE)) + if (!xf86CrtcSetMode (crtc, &crtc->desiredMode, crtc->desiredRotation, + crtc->desiredX, crtc->desiredY)) return FALSE; } @@ -3199,45 +3200,11 @@ I830SwitchMode(int scrnIndex, DisplayModePtr mode, int flags) ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; I830Ptr pI830 = I830PTR(pScrn); Bool ret = TRUE; - PixmapPtr pspix = (*pScrn->pScreen->GetScreenPixmap) (pScrn->pScreen); DPRINTF(PFX, "I830SwitchMode: mode == %p\n", mode); - /* Sync the engine before mode switch */ - i830WaitSync(pScrn); - - /* Check if our currentmode is about to change. We do this so if we - * are rotating, we don't need to call the mode setup again. - */ - if (pI830->currentMode != mode) { - if (!i830SetMode(pScrn, mode)) - ret = FALSE; - } - - /* Kludge to detect Rotate or Vidmode switch. Not very elegant, but - * workable given the implementation currently. We only need to call - * the rotation function when we know that the framebuffer has been - * disabled by the EnableDisableFBAccess() function. - * - * The extra WindowTable check detects a rotation at startup. - */ - if ( (!WindowTable[pScrn->scrnIndex] || pspix->devPrivate.ptr == NULL) && - !pI830->DGAactive && (pScrn->PointerMoved == I830PointerMoved)) { - if (!I830Rotate(pScrn, mode)) - ret = FALSE; - } - - /* Either the original setmode or rotation failed, so restore the previous - * video mode here, as we'll have already re-instated the original rotation. - */ - if (!ret) { - if (!i830SetMode(pScrn, pI830->currentMode)) { - xf86DrvMsg(scrnIndex, X_INFO, - "Failed to restore previous mode (SwitchMode)\n"); - } - } else { + if (!i830SetMode(pScrn, mode, pI830->rotation)) pI830->currentMode = mode; - } return ret; } @@ -3309,10 +3276,6 @@ I830CloseScreen(int scrnIndex, ScreenPtr pScreen) xfree(pI830->LpRing); pI830->LpRing = NULL; - xfree(pI830->CursorMem); - pI830->CursorMem = NULL; - xfree(pI830->CursorMemARGB); - pI830->CursorMemARGB = NULL; xfree(pI830->OverlayMem); pI830->OverlayMem = NULL; xfree(pI830->overlayOn); diff --git a/src/i830_exa.c b/src/i830_exa.c index f1cd1e36..3fd5e4ae 100644 --- a/src/i830_exa.c +++ b/src/i830_exa.c @@ -418,7 +418,7 @@ I830EXAInit(ScreenPtr pScreen) pI830->bufferOffset = 0; pI830->EXADriverPtr->exa_major = 2; - pI830->EXADriverPtr->exa_minor = 0; + pI830->EXADriverPtr->exa_minor = 1; pI830->EXADriverPtr->memoryBase = pI830->FbBase; pI830->EXADriverPtr->offScreenBase = pI830->Offscreen.Start; pI830->EXADriverPtr->memorySize = pI830->Offscreen.End; @@ -520,9 +520,14 @@ I830EXAInit(ScreenPtr pScreen) } if(!exaDriverInit(pScreen, pI830->EXADriverPtr)) { - xfree(pI830->EXADriverPtr); - pI830->noAccel = TRUE; - return FALSE; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "EXA initialization failed; trying older version\n"); + pI830->EXADriverPtr->exa_minor = 0; + if(!exaDriverInit(pScreen, pI830->EXADriverPtr)) { + xfree(pI830->EXADriverPtr); + pI830->noAccel = TRUE; + return FALSE; + } } I830SelectBuffer(pScrn, I830_SELECT_FRONT); diff --git a/src/i830_lvds.c b/src/i830_lvds.c index 0092dedb..59af13b9 100644 --- a/src/i830_lvds.c +++ b/src/i830_lvds.c @@ -270,10 +270,10 @@ i830_lvds_get_modes(xf86OutputPtr output) xf86MonPtr edid_mon; DisplayModePtr modes; - edid_mon = i830_xf86OutputGetEDID (output, intel_output->pDDCBus); - i830_xf86OutputSetEDID (output, edid_mon); + edid_mon = xf86OutputGetEDID (output, intel_output->pDDCBus); + xf86OutputSetEDID (output, edid_mon); - modes = i830_xf86OutputGetEDIDModes (output); + modes = xf86OutputGetEDIDModes (output); if (modes != NULL) return modes; diff --git a/src/i830_memory.c b/src/i830_memory.c index 426242a9..24f0b296 100644 --- a/src/i830_memory.c +++ b/src/i830_memory.c @@ -769,6 +769,91 @@ I830AllocateFramebuffer(ScrnInfoPtr pScrn, I830Ptr pI830, BoxPtr FbMemBox, return TRUE; } +static Bool +I830AllocateCursorBuffers(xf86CrtcPtr crtc, const int flags) +{ + ScrnInfoPtr pScrn = crtc->scrn; + I830CrtcPrivatePtr intel_crtc = crtc->driver_private; + I830Ptr pI830 = I830PTR(pScrn); + Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0); + int verbosity = dryrun ? 4 : 1; + const char *s = dryrun ? "[dryrun] " : ""; + long size, alloced; + int cursFlags = 0; + + /* Clear cursor info */ + memset(&intel_crtc->cursor_mem, 0, sizeof(I830MemRange)); + intel_crtc->cursor_mem.Key = -1; + memset(&intel_crtc->cursor_mem_argb, 0, sizeof(I830MemRange)); + intel_crtc->cursor_mem_argb.Key = -1; + + if (pI830->SWCursor) + return FALSE; + + /* + * Mouse cursor -- The i810-i830 need a physical address in system + * memory from which to upload the cursor. We get this from + * the agpgart module using a special memory type. + */ + + size = HWCURSOR_SIZE; + cursFlags = FROM_ANYWHERE | ALLOCATE_AT_TOP; + if (pI830->CursorNeedsPhysical) + cursFlags |= NEED_PHYSICAL_ADDR; + + alloced = I830AllocVidMem(pScrn, &intel_crtc->cursor_mem, + &pI830->StolenPool, size, + GTT_PAGE_SIZE, flags | cursFlags); + if (alloced < size || + (pI830->CursorNeedsPhysical && !intel_crtc->cursor_mem.Physical)) + { + if (!dryrun) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to allocate HW cursor space.\n"); + return FALSE; + } + } else { + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, + "%sAllocated %ld kB for HW cursor at 0x%lx", s, + alloced / 1024, intel_crtc->cursor_mem.Start); + if (pI830->CursorNeedsPhysical) { + xf86ErrorFVerb(verbosity, " (0x%08lx)", + intel_crtc->cursor_mem.Physical); + } + xf86ErrorFVerb(verbosity, "\n"); + } + + /* Allocate the ARGB cursor space. Its success is optional -- we won't set + * SWCursor if it fails. + */ + size = HWCURSOR_SIZE_ARGB; + cursFlags = FROM_ANYWHERE | ALLOCATE_AT_TOP; + if (pI830->CursorNeedsPhysical) + cursFlags |= NEED_PHYSICAL_ADDR; + + alloced = I830AllocVidMem(pScrn, &intel_crtc->cursor_mem_argb, + &pI830->StolenPool, size, + GTT_PAGE_SIZE, flags | cursFlags); + if (alloced < size || + (pI830->CursorNeedsPhysical && !intel_crtc->cursor_mem_argb.Physical)) { + if (!dryrun) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to allocate HW (ARGB) cursor space.\n"); + } + } else { + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, + "%sAllocated %ld kB for HW (ARGB) cursor at 0x%lx", s, + alloced / 1024, intel_crtc->cursor_mem_argb.Start); + if (pI830->CursorNeedsPhysical) { + xf86ErrorFVerb(verbosity, " (0x%08lx)", + intel_crtc->cursor_mem_argb.Physical); + } + xf86ErrorFVerb(verbosity, "\n"); + } + + return FALSE; +} + /* * Allocate memory for 2D operation. This includes the (front) framebuffer, * ring buffer, scratch memory, HW cursor. @@ -777,12 +862,13 @@ Bool I830Allocate2DMemory(ScrnInfoPtr pScrn, const int flags) { I830Ptr pI830 = I830PTR(pScrn); + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); long size, alloced; Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0); int verbosity = dryrun ? 4 : 1; const char *s = dryrun ? "[dryrun] " : ""; Bool tileable; - int align, alignflags; + int align, alignflags, i; DPRINTF(PFX, "I830Allocate2DMemory: inital is %s\n", BOOLTOSTRING(flags & ALLOC_INITIAL)); @@ -814,7 +900,6 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, const int flags) pI830->StolenPool.Free.Size); if (flags & ALLOC_INITIAL) { - if (pI830->NeedRingBufferLow) AllocateRingBuffer(pScrn, flags | FORCE_LOW); @@ -979,63 +1064,18 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, const int flags) } #endif - /* Clear cursor info */ - memset(pI830->CursorMem, 0, sizeof(I830MemRange)); - pI830->CursorMem->Key = -1; - memset(pI830->CursorMemARGB, 0, sizeof(I830MemRange)); - pI830->CursorMemARGB->Key = -1; - - if (!pI830->SWCursor) { - int cursFlags = 0; - /* - * Mouse cursor -- The i810-i830 need a physical address in system - * memory from which to upload the cursor. We get this from - * the agpgart module using a special memory type. - */ - - size = HWCURSOR_SIZE; - cursFlags = FROM_ANYWHERE | ALLOCATE_AT_TOP; - if (pI830->CursorNeedsPhysical) - cursFlags |= NEED_PHYSICAL_ADDR; - - alloced = I830AllocVidMem(pScrn, pI830->CursorMem, - &(pI830->StolenPool), size, - GTT_PAGE_SIZE, flags | cursFlags); - if (alloced < size) { - if (!dryrun) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Failed to allocate HW cursor space.\n"); - } - } else { - xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, - "%sAllocated %ld kB for HW cursor at 0x%lx", s, - alloced / 1024, pI830->CursorMem->Start); - if (pI830->CursorNeedsPhysical) - xf86ErrorFVerb(verbosity, " (0x%08lx)", pI830->CursorMem->Physical); - xf86ErrorFVerb(verbosity, "\n"); - } - - size = HWCURSOR_SIZE_ARGB; - cursFlags = FROM_ANYWHERE | ALLOCATE_AT_TOP; - if (pI830->CursorNeedsPhysical) - cursFlags |= NEED_PHYSICAL_ADDR; - - alloced = I830AllocVidMem(pScrn, pI830->CursorMemARGB, - &(pI830->StolenPool), size, - GTT_PAGE_SIZE, flags | cursFlags); - if (alloced < size) { - if (!dryrun) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Failed to allocate HW (ARGB) cursor space.\n"); - } - } else { - xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, - "%sAllocated %ld kB for HW (ARGB) cursor at 0x%lx", s, - alloced / 1024, pI830->CursorMemARGB->Start); - if (pI830->CursorNeedsPhysical) - xf86ErrorFVerb(verbosity, " (0x%08lx)", pI830->CursorMemARGB->Physical); - xf86ErrorFVerb(verbosity, "\n"); - } + if (!pI830->SWCursor && !dryrun) { + for (i = 0; i < xf86_config->num_crtc; i++) { + if (!I830AllocateCursorBuffers(xf86_config->crtc[i], flags) && + pI830->SWCursor) + { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Disabling HW cursor because the cursor memory " + "allocation failed.\n"); + pI830->SWCursor = TRUE; + break; + } + } } #ifdef I830_XV @@ -1505,6 +1545,8 @@ Bool I830FixupOffsets(ScrnInfoPtr pScrn) { I830Ptr pI830 = I830PTR(pScrn); + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + int i; DPRINTF(PFX, "I830FixupOffsets\n"); @@ -1512,8 +1554,14 @@ I830FixupOffsets(ScrnInfoPtr pScrn) if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2) I830FixOffset(pScrn, &(pI830->FrontBuffer2)); I830FixOffset(pScrn, &(pI830->FrontBuffer)); - I830FixOffset(pScrn, pI830->CursorMem); - I830FixOffset(pScrn, pI830->CursorMemARGB); + + for (i = 0; i < xf86_config->num_crtc; i++) { + I830CrtcPrivatePtr intel_crtc = xf86_config->crtc[i]->driver_private; + + I830FixOffset(pScrn, &intel_crtc->cursor_mem); + I830FixOffset(pScrn, &intel_crtc->cursor_mem_argb); + } + I830FixOffset(pScrn, &(pI830->LpRing->mem)); I830FixOffset(pScrn, &(pI830->Scratch)); if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2) @@ -1896,6 +1944,9 @@ I830BindAGPMemory(ScrnInfoPtr pScrn) return TRUE; if (xf86AgpGARTSupported() && !pI830->GttBound) { + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + int i; + if (!xf86AcquireGART(pScrn->scrnIndex)) return FALSE; @@ -1911,10 +1962,15 @@ I830BindAGPMemory(ScrnInfoPtr pScrn) return FALSE; if (!BindMemRange(pScrn, &(pI830->FrontBuffer))) return FALSE; - if (!BindMemRange(pScrn, pI830->CursorMem)) - return FALSE; - if (!BindMemRange(pScrn, pI830->CursorMemARGB)) - return FALSE; + + for (i = 0; i < xf86_config->num_crtc; i++) { + I830CrtcPrivatePtr intel_crtc = xf86_config->crtc[i]->driver_private; + + if (!BindMemRange(pScrn, &intel_crtc->cursor_mem)) + return FALSE; + if (!BindMemRange(pScrn, &intel_crtc->cursor_mem_argb)) + return FALSE; + } if (!BindMemRange(pScrn, &(pI830->LpRing->mem))) return FALSE; if (!BindMemRange(pScrn, &(pI830->Scratch))) @@ -1991,6 +2047,8 @@ I830UnbindAGPMemory(ScrnInfoPtr pScrn) return TRUE; if (xf86AgpGARTSupported() && pI830->GttBound) { + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + int i; #if REMAP_RESERVED /* "unbind" the pre-allocated region. */ @@ -2004,10 +2062,16 @@ I830UnbindAGPMemory(ScrnInfoPtr pScrn) return FALSE; if (!UnbindMemRange(pScrn, &(pI830->FrontBuffer))) return FALSE; - if (!UnbindMemRange(pScrn, pI830->CursorMem)) - return FALSE; - if (!UnbindMemRange(pScrn, pI830->CursorMemARGB)) - return FALSE; + + for (i = 0; i < xf86_config->num_crtc; i++) { + I830CrtcPrivatePtr intel_crtc = xf86_config->crtc[i]->driver_private; + + if (!UnbindMemRange(pScrn, &intel_crtc->cursor_mem)) + return FALSE; + if (!UnbindMemRange(pScrn, &intel_crtc->cursor_mem_argb)) + return FALSE; + } + if (!UnbindMemRange(pScrn, &(pI830->LpRing->mem))) return FALSE; if (!UnbindMemRange(pScrn, &(pI830->Scratch))) @@ -2079,3 +2143,41 @@ I830CheckAvailableMemory(ScrnInfoPtr pScrn) return maxPages * 4; } + +#ifdef I830_USE_XAA +/** + * Allocates memory from the XF86 linear allocator, but also purges + * memory if possible to cause the allocation to succeed. + */ +FBLinearPtr +i830_xf86AllocateOffscreenLinear(ScreenPtr pScreen, int length, + int granularity, + MoveLinearCallbackProcPtr moveCB, + RemoveLinearCallbackProcPtr removeCB, + pointer privData) +{ + FBLinearPtr linear; + int max_size; + + linear = xf86AllocateOffscreenLinear(pScreen, length, granularity, moveCB, + removeCB, privData); + if (linear != NULL) + return linear; + + /* The above allocation didn't succeed, so purge unlocked stuff and try + * again. + */ + xf86QueryLargestOffscreenLinear(pScreen, &max_size, granularity, + PRIORITY_EXTREME); + + if (max_size < length) + return NULL; + + xf86PurgeUnlockedOffscreenAreas(pScreen); + + linear = xf86AllocateOffscreenLinear(pScreen, length, granularity, moveCB, + removeCB, privData); + + return linear; +} +#endif diff --git a/src/i830_modes.c b/src/i830_modes.c index b4e22c35..405dcc61 100644 --- a/src/i830_modes.c +++ b/src/i830_modes.c @@ -62,9 +62,9 @@ i830_ddc_get_modes (xf86OutputPtr output) xf86MonPtr edid_mon; DisplayModePtr modes; - edid_mon = i830_xf86OutputGetEDID (output, intel_output->pDDCBus); - i830_xf86OutputSetEDID (output, edid_mon); + edid_mon = xf86OutputGetEDID (output, intel_output->pDDCBus); + xf86OutputSetEDID (output, edid_mon); - modes = i830_xf86OutputGetEDIDModes (output); + modes = xf86OutputGetEDIDModes (output); return modes; } diff --git a/src/i830_randr.c b/src/i830_randr.c index 63888494..5eccf4bd 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; @@ -494,8 +494,19 @@ void xf86RandR12SetRotations (ScreenPtr pScreen, Rotation rotations) { XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + int c; randrp->supported_rotations = rotations; + +#if RANDR_12_INTERFACE + for (c = 0; c < config->num_crtc; c++) { + xf86CrtcPtr crtc = config->crtc[c]; + + RRCrtcSetRotations (crtc->randr_crtc, rotations); + } +#endif } void @@ -533,7 +544,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 +552,7 @@ xf86RandR12CrtcNotify (RRCrtcPtr randr_crtc) return FALSE; x = crtc->x; y = crtc->y; - rotation = RR_Rotate_0; + rotation = crtc->rotation; numOutputs = 0; randr_mode = NULL; for (i = 0; i < config->num_output; i++) @@ -558,7 +569,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 +598,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 +605,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]; @@ -629,12 +638,9 @@ xf86RandR12CrtcSet (ScreenPtr pScreen, { crtc->enabled = mode != NULL; - /* Sync the engine before adjust mode */ - i830WaitSync(pScrn); - if (mode) { - if (!i830PipeSetMode (crtc, mode, TRUE)) + if (!xf86CrtcSetMode (crtc, mode, rotation, x, y)) { crtc->enabled = save_enabled; for (o = 0; o < config->num_output; o++) @@ -645,14 +651,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; } - i830DisableUnusedFunctions (pScrn); - - i830DumpRegs(pScrn); + xf86DisableUnusedFunctions (pScrn); } - if (pos_changed && mode) - i830PipeSetBase(crtc, x, y); DEALLOCATE_LOCAL(save_crtcs); return xf86RandR12CrtcNotify (randr_crtc); } @@ -830,6 +838,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 92e417e0..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); - i830PipeSetMode (crtc, &mode, FALSE); + xf86CrtcSetMode (crtc, &mode, RR_Rotate_0, 0, 0); } i830_tv_detect_type (crtc, output); i830ReleaseLoadDetectPipe (output); diff --git a/src/i830_video.c b/src/i830_video.c index a330eb5f..22f5bee4 100644 --- a/src/i830_video.c +++ b/src/i830_video.c @@ -2073,8 +2073,6 @@ I830AllocateMemory(ScrnInfoPtr pScrn, struct linear_alloc *linear, int size, #endif /* I830_USE_EXA */ #ifdef I830_USE_XAA if (!pI830->useEXA) { - int max_size; - /* Converts an offset from XAA's linear allocator to an offset from the * start of fb. */ @@ -2100,25 +2098,11 @@ I830AllocateMemory(ScrnInfoPtr pScrn, struct linear_alloc *linear, int size, xf86FreeOffscreenLinear(linear->xaa); } - linear->xaa = xf86AllocateOffscreenLinear(pScreen, size, align, - NULL, NULL, NULL); - if (linear->xaa != NULL) { - linear->offset = XAA_OFFSET_TO_OFFSET(linear->xaa->offset); - return; - } - - xf86QueryLargestOffscreenLinear(pScreen, &max_size, align, - PRIORITY_EXTREME); - - if (max_size < size) { - ErrorF("No memory available\n"); - linear->offset = 0; + linear->xaa = i830_xf86AllocateOffscreenLinear(pScreen, size, align, + NULL, NULL, NULL); + if (linear->xaa == NULL) return; - } - xf86PurgeUnlockedOffscreenAreas(pScreen); - linear->xaa = xf86AllocateOffscreenLinear(pScreen, size, 4, - NULL, NULL, NULL); linear->offset = XAA_OFFSET_TO_OFFSET(linear->xaa->offset); } #endif /* I830_USE_XAA */ diff --git a/src/i830_xf86Crtc.c b/src/i830_xf86Crtc.c index 34fa7369..a2099149 100644 --- a/src/i830_xf86Crtc.c +++ b/src/i830_xf86Crtc.c @@ -87,6 +87,8 @@ xf86CrtcCreate (ScrnInfoPtr scrn, #ifdef RANDR_12_INTERFACE crtc->randr_crtc = NULL; #endif + crtc->rotation = RR_Rotate_0; + crtc->desiredRotation = RR_Rotate_0; if (xf86_config->crtc) crtcs = xrealloc (xf86_config->crtc, (xf86_config->num_crtc + 1) * sizeof (xf86CrtcPtr)); @@ -121,6 +123,139 @@ xf86CrtcDestroy (xf86CrtcPtr crtc) xfree (crtc); } + +/** + * Return whether any outputs are connected to the specified pipe + */ + +Bool +xf86CrtcInUse (xf86CrtcPtr crtc) +{ + ScrnInfoPtr pScrn = crtc->scrn; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + int o; + + for (o = 0; o < xf86_config->num_output; o++) + if (xf86_config->output[o]->crtc == crtc) + return TRUE; + return FALSE; +} + +/** + * Sets the given video mode on the given crtc + */ +Bool +xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation, + int x, int y) +{ + ScrnInfoPtr scrn = crtc->scrn; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); + int i; + Bool ret = FALSE; + Bool didLock = FALSE; + DisplayModePtr adjusted_mode; + DisplayModeRec saved_mode; + int saved_x, saved_y; + Rotation saved_rotation; + + adjusted_mode = xf86DuplicateMode(mode); + + crtc->enabled = xf86CrtcInUse (crtc); + + if (!crtc->enabled) + { + /* XXX disable crtc? */ + return TRUE; + } + + didLock = crtc->funcs->lock (crtc); + + saved_mode = crtc->mode; + saved_x = crtc->x; + saved_y = crtc->y; + saved_rotation = crtc->rotation; + /* 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; + + /* 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. + */ + for (i = 0; i < xf86_config->num_output; i++) { + xf86OutputPtr output = xf86_config->output[i]; + + if (output->crtc != crtc) + continue; + + if (!output->funcs->mode_fixup(output, mode, adjusted_mode)) { + goto done; + } + } + + if (!crtc->funcs->mode_fixup(crtc, mode, adjusted_mode)) { + goto done; + } + + if (!xf86CrtcRotate (crtc, mode, rotation)) { + goto done; + } + + /* Disable the outputs and CRTCs before setting the mode. */ + for (i = 0; i < xf86_config->num_output; i++) { + xf86OutputPtr output = xf86_config->output[i]; + + if (output->crtc != crtc) + continue; + + /* Disable the output as the first thing we do. */ + output->funcs->dpms(output, DPMSModeOff); + } + + crtc->funcs->dpms(crtc, DPMSModeOff); + + /* 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, x, 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); + } + + /* Now, enable the clocks, plane, pipe, and outputs that we set up. */ + crtc->funcs->dpms(crtc, DPMSModeOn); + for (i = 0; i < xf86_config->num_output; i++) + { + xf86OutputPtr output = xf86_config->output[i]; + if (output->crtc == crtc) + output->funcs->dpms(output, DPMSModeOn); + } + + /* XXX free adjustedmode */ + ret = TRUE; +done: + if (!ret) { + crtc->x = saved_x; + crtc->y = saved_y; + crtc->rotation = saved_rotation; + crtc->mode = saved_mode; + } + + if (didLock) + crtc->funcs->unlock (crtc); + + return ret; +} + /* * Output functions */ @@ -362,14 +497,14 @@ xf86OutputHasPreferredMode (xf86OutputPtr output, int width, int height) } static int -xf86PickCrtcs (ScrnInfoPtr pScrn, +xf86PickCrtcs (ScrnInfoPtr scrn, xf86CrtcPtr *best_crtcs, DisplayModePtr *modes, int n, int width, int height) { - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); int c, o, l; xf86OutputPtr output; xf86CrtcPtr crtc; @@ -388,7 +523,7 @@ xf86PickCrtcs (ScrnInfoPtr pScrn, */ best_crtcs[n] = NULL; best_crtc = NULL; - best_score = xf86PickCrtcs (pScrn, best_crtcs, modes, n+1, width, height); + best_score = xf86PickCrtcs (scrn, best_crtcs, modes, n+1, width, height); if (modes[n] == NULL) return best_score; @@ -442,7 +577,7 @@ xf86PickCrtcs (ScrnInfoPtr pScrn, } crtcs[n] = crtc; memcpy (crtcs, best_crtcs, n * sizeof (xf86CrtcPtr)); - score = my_score + xf86PickCrtcs (pScrn, crtcs, modes, n+1, width, height); + score = my_score + xf86PickCrtcs (scrn, crtcs, modes, n+1, width, height); if (score > best_score) { best_crtc = crtc; @@ -462,9 +597,9 @@ xf86PickCrtcs (ScrnInfoPtr pScrn, */ static void -xf86DefaultScreenLimits (ScrnInfoPtr pScrn, int *widthp, int *heightp) +xf86DefaultScreenLimits (ScrnInfoPtr scrn, int *widthp, int *heightp) { - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); int width = 0, height = 0; int o; int c; @@ -513,9 +648,9 @@ xf86DefaultScreenLimits (ScrnInfoPtr pScrn, int *widthp, int *heightp) #define POSITION_UNSET -100000 static Bool -xf86InitialOutputPositions (ScrnInfoPtr pScrn, DisplayModePtr *modes) +xf86InitialOutputPositions (ScrnInfoPtr scrn, DisplayModePtr *modes) { - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); int o; int min_x, min_y; @@ -563,7 +698,7 @@ xf86InitialOutputPositions (ScrnInfoPtr pScrn, DisplayModePtr *modes) } else { - xf86DrvMsg (pScrn->scrnIndex, X_ERROR, + xf86DrvMsg (scrn->scrnIndex, X_ERROR, "Output %s position not of form \"x y\"\n", output->name); output->initial_x = output->initial_y = 0; @@ -606,7 +741,7 @@ xf86InitialOutputPositions (ScrnInfoPtr pScrn, DisplayModePtr *modes) } if (!relative) { - xf86DrvMsg (pScrn->scrnIndex, X_ERROR, + xf86DrvMsg (scrn->scrnIndex, X_ERROR, "Cannot position output %s relative to unknown output %s\n", output->name, relative_name); output->initial_x = 0; @@ -655,7 +790,7 @@ xf86InitialOutputPositions (ScrnInfoPtr pScrn, DisplayModePtr *modes) xf86OutputPtr output = config->output[o]; if (output->initial_x == POSITION_UNSET) { - xf86DrvMsg (pScrn->scrnIndex, X_ERROR, + xf86DrvMsg (scrn->scrnIndex, X_ERROR, "Output position loop. Moving %s to 0,0\n", output->name); output->initial_x = output->initial_y = 0; @@ -778,16 +913,16 @@ i830xf86SortModes (DisplayModePtr input) #define DEBUG_REPROBE 1 void -xf86ProbeOutputModes (ScrnInfoPtr pScrn, int maxX, int maxY) +xf86ProbeOutputModes (ScrnInfoPtr scrn, int maxX, int maxY) { - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); int o; if (maxX == 0 || maxY == 0) - xf86RandR12GetOriginalVirtualSize (pScrn, &maxX, &maxY); + xf86RandR12GetOriginalVirtualSize (scrn, &maxX, &maxY); /* Elide duplicate modes before defaulting code uses them */ - xf86PruneDuplicateMonitorModes (pScrn->monitor); + xf86PruneDuplicateMonitorModes (scrn->monitor); /* Probe the list of modes for each output. */ for (o = 0; o < config->num_output; o++) @@ -837,7 +972,7 @@ xf86ProbeOutputModes (ScrnInfoPtr pScrn, int maxX, int maxY) mon_rec.nVrefresh++; sync_source = sync_config; } - config_modes = i830xf86GetMonitorModes (pScrn, conf_monitor); + config_modes = xf86GetMonitorModes (scrn, conf_monitor); } output_modes = (*output->funcs->get_modes) (output); @@ -901,27 +1036,27 @@ xf86ProbeOutputModes (ScrnInfoPtr pScrn, int maxX, int maxY) mon_rec.vrefresh[0].hi = 62.0; mon_rec.nVrefresh = 1; } - default_modes = i830xf86GetDefaultModes (output->interlaceAllowed, - output->doubleScanAllowed); + default_modes = xf86GetDefaultModes (output->interlaceAllowed, + output->doubleScanAllowed); if (sync_source == sync_config) { /* * Check output and config modes against sync range from config file */ - i830xf86ValidateModesSync (pScrn, output_modes, &mon_rec); - i830xf86ValidateModesSync (pScrn, config_modes, &mon_rec); + xf86ValidateModesSync (scrn, output_modes, &mon_rec); + xf86ValidateModesSync (scrn, config_modes, &mon_rec); } /* * Check default modes against sync range */ - i830xf86ValidateModesSync (pScrn, default_modes, &mon_rec); + xf86ValidateModesSync (scrn, default_modes, &mon_rec); /* * Check default modes against monitor max clock */ if (max_clock) - i830xf86ValidateModesClocks(pScrn, default_modes, - &min_clock, &max_clock, 1); + xf86ValidateModesClocks(scrn, default_modes, + &min_clock, &max_clock, 1); output->probed_modes = NULL; output->probed_modes = xf86ModesAdd (output->probed_modes, config_modes); @@ -932,7 +1067,7 @@ xf86ProbeOutputModes (ScrnInfoPtr pScrn, int maxX, int maxY) * Check all modes against max size */ if (maxX && maxY) - i830xf86ValidateModesSize (pScrn, output->probed_modes, + xf86ValidateModesSize (scrn, output->probed_modes, maxX, maxY, 0); /* @@ -942,7 +1077,7 @@ xf86ProbeOutputModes (ScrnInfoPtr pScrn, int maxX, int maxY) if (mode->status == MODE_OK) mode->status = (*output->funcs->mode_valid)(output, mode); - i830xf86PruneInvalidModes(pScrn, &output->probed_modes, TRUE); + xf86PruneInvalidModes(scrn, &output->probed_modes, TRUE); output->probed_modes = i830xf86SortModes (output->probed_modes); @@ -975,11 +1110,11 @@ xf86ProbeOutputModes (ScrnInfoPtr pScrn, int maxX, int maxY) #ifdef DEBUG_REPROBE if (output->probed_modes != NULL) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, + xf86DrvMsg(scrn->scrnIndex, X_INFO, "Printing probed modes for output %s\n", output->name); } else { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, + xf86DrvMsg(scrn->scrnIndex, X_INFO, "No remaining probed modes for output %s\n", output->name); } @@ -993,7 +1128,7 @@ xf86ProbeOutputModes (ScrnInfoPtr pScrn, int maxX, int maxY) xf86SetModeCrtc(mode, INTERLACE_HALVE_V); #ifdef DEBUG_REPROBE - xf86PrintModeline(pScrn->scrnIndex, mode); + xf86PrintModeline(scrn->scrnIndex, mode); #endif } } @@ -1006,12 +1141,12 @@ xf86ProbeOutputModes (ScrnInfoPtr pScrn, int maxX, int maxY) /* XXX where does this function belong? Here? */ void -xf86RandR12GetOriginalVirtualSize(ScrnInfoPtr pScrn, int *x, int *y); +xf86RandR12GetOriginalVirtualSize(ScrnInfoPtr scrn, int *x, int *y); void -xf86SetScrnInfoModes (ScrnInfoPtr pScrn) +xf86SetScrnInfoModes (ScrnInfoPtr scrn) { - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); xf86OutputPtr output; xf86CrtcPtr crtc; DisplayModePtr last, mode; @@ -1035,31 +1170,31 @@ xf86SetScrnInfoModes (ScrnInfoPtr pScrn) } crtc = output->crtc; - /* Clear any existing modes from pScrn->modes */ - while (pScrn->modes != NULL) - xf86DeleteMode(&pScrn->modes, pScrn->modes); + /* Clear any existing modes from scrn->modes */ + while (scrn->modes != NULL) + xf86DeleteMode(&scrn->modes, scrn->modes); - /* Set pScrn->modes to the mode list for the 'compat' output */ - pScrn->modes = xf86DuplicateModes(pScrn, output->probed_modes); + /* Set scrn->modes to the mode list for the 'compat' output */ + scrn->modes = xf86DuplicateModes(scrn, output->probed_modes); - for (mode = pScrn->modes; mode; mode = mode->next) + for (mode = scrn->modes; mode; mode = mode->next) if (xf86ModesEqual (mode, &crtc->desiredMode)) break; - if (pScrn->modes != NULL) { - /* For some reason, pScrn->modes is circular, unlike the other mode + if (scrn->modes != NULL) { + /* For some reason, scrn->modes is circular, unlike the other mode * lists. How great is that? */ - for (last = pScrn->modes; last && last->next; last = last->next) + for (last = scrn->modes; last && last->next; last = last->next) ; - last->next = pScrn->modes; - pScrn->modes->prev = last; + last->next = scrn->modes; + scrn->modes->prev = last; if (mode) { - while (pScrn->modes != mode) - pScrn->modes = pScrn->modes->next; + while (scrn->modes != mode) + scrn->modes = scrn->modes->next; } } - pScrn->currentMode = pScrn->modes; + scrn->currentMode = scrn->modes; } /** @@ -1070,9 +1205,9 @@ xf86SetScrnInfoModes (ScrnInfoPtr pScrn) */ Bool -xf86InitialConfiguration (ScrnInfoPtr pScrn) +xf86InitialConfiguration (ScrnInfoPtr scrn) { - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); int o, c; DisplayModePtr target_mode = NULL; xf86CrtcPtr *crtcs; @@ -1081,16 +1216,16 @@ xf86InitialConfiguration (ScrnInfoPtr pScrn) int width; int height; - if (pScrn->display->virtualX) - width = pScrn->display->virtualX; + if (scrn->display->virtualX) + width = scrn->display->virtualX; else width = config->maxWidth; - if (pScrn->display->virtualY) - height = pScrn->display->virtualY; + if (scrn->display->virtualY) + height = scrn->display->virtualY; else height = config->maxHeight; - xf86ProbeOutputModes (pScrn, width, height); + xf86ProbeOutputModes (scrn, width, height); crtcs = xnfcalloc (config->num_output, sizeof (xf86CrtcPtr)); modes = xnfcalloc (config->num_output, sizeof (DisplayModePtr)); @@ -1152,7 +1287,7 @@ xf86InitialConfiguration (ScrnInfoPtr pScrn) /* * Set the position of each output */ - if (!xf86InitialOutputPositions (pScrn, modes)) + if (!xf86InitialOutputPositions (scrn, modes)) { xfree (crtcs); xfree (modes); @@ -1162,7 +1297,7 @@ xf86InitialConfiguration (ScrnInfoPtr pScrn) /* * Assign CRTCs to fit output configuration */ - if (!xf86PickCrtcs (pScrn, crtcs, modes, 0, width, height)) + if (!xf86PickCrtcs (scrn, crtcs, modes, 0, width, height)) { xfree (crtcs); xfree (modes); @@ -1171,8 +1306,8 @@ xf86InitialConfiguration (ScrnInfoPtr pScrn) /* XXX override xf86 common frame computation code */ - pScrn->display->frameX0 = 0; - pScrn->display->frameY0 = 0; + scrn->display->frameX0 = 0; + scrn->display->frameY0 = 0; for (c = 0; c < config->num_crtc; c++) { @@ -1201,24 +1336,24 @@ xf86InitialConfiguration (ScrnInfoPtr pScrn) } } - if (pScrn->display->virtualX == 0) + if (scrn->display->virtualX == 0) { /* * Expand virtual size to cover potential mode switches */ - xf86DefaultScreenLimits (pScrn, &width, &height); + xf86DefaultScreenLimits (scrn, &width, &height); - pScrn->display->virtualX = width; - pScrn->display->virtualY = height; + scrn->display->virtualX = width; + scrn->display->virtualY = height; } - if (width > pScrn->virtualX) - pScrn->virtualX = width; - if (height > pScrn->virtualY) - pScrn->virtualY = height; + if (width > scrn->virtualX) + scrn->virtualX = width; + if (height > scrn->virtualY) + scrn->virtualY = height; - /* Mirror output modes to pScrn mode list */ - xf86SetScrnInfoModes (pScrn); + /* Mirror output modes to scrn mode list */ + xf86SetScrnInfoModes (scrn); xfree (crtcs); xfree (modes); @@ -1232,12 +1367,12 @@ xf86InitialConfiguration (ScrnInfoPtr pScrn) * Otherwise, it will affect CRTCs before outputs. */ void -xf86DPMSSet(ScrnInfoPtr pScrn, int mode, int flags) +xf86DPMSSet(ScrnInfoPtr scrn, int mode, int flags) { - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); int i; - if (!pScrn->vtSema) + if (!scrn->vtSema) return; if (mode == DPMSModeOff) { @@ -1282,6 +1417,34 @@ xf86SaveScreen(ScreenPtr pScreen, int mode) return TRUE; } +/** + * Disable all inactive crtcs and outputs + */ +void +xf86DisableUnusedFunctions(ScrnInfoPtr pScrn) +{ + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + int o, c; + + for (o = 0; o < xf86_config->num_output; o++) + { + xf86OutputPtr output = xf86_config->output[o]; + if (!output->crtc) + (*output->funcs->dpms)(output, DPMSModeOff); + } + + for (c = 0; c < xf86_config->num_crtc; c++) + { + xf86CrtcPtr crtc = xf86_config->crtc[c]; + + if (!crtc->enabled) + { + crtc->funcs->dpms(crtc, DPMSModeOff); + memset(&crtc->mode, 0, sizeof(crtc->mode)); + } + } +} + #ifdef RANDR_12_INTERFACE #define EDID_ATOM_NAME "EDID_DATA" @@ -1312,10 +1475,10 @@ xf86OutputSetEDIDProperty (xf86OutputPtr output, void *data, int data_len) * Set the EDID information for the specified output */ void -i830_xf86OutputSetEDID (xf86OutputPtr output, xf86MonPtr edid_mon) +xf86OutputSetEDID (xf86OutputPtr output, xf86MonPtr edid_mon) { - ScrnInfoPtr pScrn = output->scrn; - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + ScrnInfoPtr scrn = output->scrn; + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); int i; #ifdef RANDR_12_INTERFACE int size; @@ -1327,12 +1490,12 @@ i830_xf86OutputSetEDID (xf86OutputPtr output, xf86MonPtr edid_mon) output->MonInfo = edid_mon; /* Debug info for now, at least */ - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "EDID for output %s\n", output->name); + xf86DrvMsg(scrn->scrnIndex, X_INFO, "EDID for output %s\n", output->name); xf86PrintEDID(edid_mon); /* Set the DDC properties for the 'compat' output */ if (output == config->output[config->compat_output]) - xf86SetDDCproperties(pScrn, edid_mon); + xf86SetDDCproperties(scrn, edid_mon); #ifdef RANDR_12_INTERFACE /* Set the RandR output properties */ @@ -1376,20 +1539,20 @@ i830_xf86OutputSetEDID (xf86OutputPtr output, xf86MonPtr edid_mon) * stored in 'output' */ DisplayModePtr -i830_xf86OutputGetEDIDModes (xf86OutputPtr output) +xf86OutputGetEDIDModes (xf86OutputPtr output) { - ScrnInfoPtr pScrn = output->scrn; + ScrnInfoPtr scrn = output->scrn; xf86MonPtr edid_mon = output->MonInfo; if (!edid_mon) return NULL; - return xf86DDCGetModes(pScrn->scrnIndex, edid_mon); + return xf86DDCGetModes(scrn->scrnIndex, edid_mon); } xf86MonPtr -i830_xf86OutputGetEDID (xf86OutputPtr output, I2CBusPtr pDDCBus) +xf86OutputGetEDID (xf86OutputPtr output, I2CBusPtr pDDCBus) { - ScrnInfoPtr pScrn = output->scrn; + ScrnInfoPtr scrn = output->scrn; - return xf86DoEDID_DDC2 (pScrn->scrnIndex, pDDCBus); + return xf86DoEDID_DDC2 (scrn->scrnIndex, pDDCBus); } diff --git a/src/i830_xf86Crtc.h b/src/i830_xf86Crtc.h index f8b561a2..6de2c923 100644 --- a/src/i830_xf86Crtc.h +++ b/src/i830_xf86Crtc.h @@ -24,8 +24,10 @@ #include <edid.h> #include "randrstr.h" +#include "i830_xf86Rename.h" #include "i830_xf86Modes.h" #include "xf86Parser.h" +#include "damage.h" /* Compat definitions for older X Servers. */ #ifndef M_T_PREFERRED @@ -68,7 +70,19 @@ typedef struct _xf86CrtcFuncs { void (*restore)(xf86CrtcPtr crtc); - + /** + * Lock CRTC prior to mode setting, mostly for DRI. + * Returns whether unlock is needed + */ + Bool + (*lock) (xf86CrtcPtr crtc); + + /** + * Unlock CRTC after mode setting, mostly for DRI + */ + void + (*unlock) (xf86CrtcPtr crtc); + /** * Callback to adjust the mode to be set in the CRTC. * @@ -87,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 @@ -95,6 +110,18 @@ typedef struct _xf86CrtcFuncs { int size); /** + * Create shadow pixmap for rotation support + */ + PixmapPtr + (*shadow_create) (xf86CrtcPtr crtc, int width, int height); + + /** + * Destroy shadow pixmap + */ + void + (*shadow_destroy) (xf86CrtcPtr crtc, PixmapPtr pPixmap); + + /** * Clean up driver-specific bits of the crtc */ void @@ -114,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; @@ -134,7 +154,15 @@ struct _xf86Crtc { * It will be cleared when the VT is not active or * during server startup */ - DisplayModeRec curMode; + DisplayModeRec mode; + Rotation rotation; + PixmapPtr rotatedPixmap; + /** + * Position on screen + * + * Locates this CRTC within the frame buffer + */ + int x, y; /** * Desired mode @@ -145,6 +173,8 @@ struct _xf86Crtc { * on VT switch. */ DisplayModeRec desiredMode; + Rotation desiredRotation; + int desiredX, desiredY; /** crtc-specific functions */ const xf86CrtcFuncsRec *funcs; @@ -379,6 +409,13 @@ typedef struct _xf86CrtcConfig { int minWidth, minHeight; int maxWidth, maxHeight; + + /* For crtc-based rotation */ + DamagePtr rotationDamage; + + /* DGA */ + unsigned int dga_flags; + } xf86CrtcConfigRec, *xf86CrtcConfigPtr; extern int xf86CrtcConfigPrivateIndex; @@ -427,6 +464,25 @@ xf86AllocCrtc (xf86OutputPtr output); void xf86FreeCrtc (xf86CrtcPtr crtc); +/** + * Sets the given video mode on the given crtc + */ +Bool +xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation, + int x, int y); + +/* + * Assign crtc rotation during mode set + */ +Bool +xf86CrtcRotate (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation); + +/** + * Return whether any output is assigned to the crtc + */ +Bool +xf86CrtcInUse (xf86CrtcPtr crtc); + /* * Output functions */ @@ -456,20 +512,23 @@ xf86DPMSSet(ScrnInfoPtr pScrn, int PowerManagementMode, int flags); Bool xf86SaveScreen(ScreenPtr pScreen, int mode); +void +xf86DisableUnusedFunctions(ScrnInfoPtr pScrn); + /** * Set the EDID information for the specified output */ void -i830_xf86OutputSetEDID (xf86OutputPtr output, xf86MonPtr edid_mon); +xf86OutputSetEDID (xf86OutputPtr output, xf86MonPtr edid_mon); /** * Return the list of modes supported by the EDID information * stored in 'output' */ DisplayModePtr -i830_xf86OutputGetEDIDModes (xf86OutputPtr output); +xf86OutputGetEDIDModes (xf86OutputPtr output); xf86MonPtr -i830_xf86OutputGetEDID (xf86OutputPtr output, I2CBusPtr pDDCBus); +xf86OutputGetEDID (xf86OutputPtr output, I2CBusPtr pDDCBus); #endif /* _XF86CRTC_H_ */ diff --git a/src/i830_xf86Modes.c b/src/i830_xf86Modes.c index a08d5a47..f620d4d5 100644 --- a/src/i830_xf86Modes.c +++ b/src/i830_xf86Modes.c @@ -303,7 +303,7 @@ xf86PrintModeline(int scrnIndex,DisplayModePtr mode) * This is not in xf86Modes.c, but would be part of the proposed new API. */ void -i830xf86ValidateModesFlags(ScrnInfoPtr pScrn, DisplayModePtr modeList, +xf86ValidateModesFlags(ScrnInfoPtr pScrn, DisplayModePtr modeList, int flags) { DisplayModePtr mode; @@ -324,7 +324,7 @@ i830xf86ValidateModesFlags(ScrnInfoPtr pScrn, DisplayModePtr modeList, * This is not in xf86Modes.c, but would be part of the proposed new API. */ void -i830xf86ValidateModesSize(ScrnInfoPtr pScrn, DisplayModePtr modeList, +xf86ValidateModesSize(ScrnInfoPtr pScrn, DisplayModePtr modeList, int maxX, int maxY, int maxPitch) { DisplayModePtr mode; @@ -353,7 +353,7 @@ i830xf86ValidateModesSize(ScrnInfoPtr pScrn, DisplayModePtr modeList, * This is not in xf86Modes.c, but would be part of the proposed new API. */ void -i830xf86ValidateModesSync(ScrnInfoPtr pScrn, DisplayModePtr modeList, +xf86ValidateModesSync(ScrnInfoPtr pScrn, DisplayModePtr modeList, MonPtr mon) { DisplayModePtr mode; @@ -400,7 +400,7 @@ i830xf86ValidateModesSync(ScrnInfoPtr pScrn, DisplayModePtr modeList, * This is not in xf86Modes.c, but would be part of the proposed new API. */ void -i830xf86ValidateModesClocks(ScrnInfoPtr pScrn, DisplayModePtr modeList, +xf86ValidateModesClocks(ScrnInfoPtr pScrn, DisplayModePtr modeList, int *min, int *max, int n_ranges) { DisplayModePtr mode; @@ -434,7 +434,7 @@ i830xf86ValidateModesClocks(ScrnInfoPtr pScrn, DisplayModePtr modeList, * This is not in xf86Modes.c, but would be part of the proposed new API. */ void -i830xf86ValidateModesUserConfig(ScrnInfoPtr pScrn, DisplayModePtr modeList) +xf86ValidateModesUserConfig(ScrnInfoPtr pScrn, DisplayModePtr modeList) { DisplayModePtr mode; @@ -468,7 +468,7 @@ i830xf86ValidateModesUserConfig(ScrnInfoPtr pScrn, DisplayModePtr modeList) * This is not in xf86Modes.c, but would be part of the proposed new API. */ void -i830xf86PruneInvalidModes(ScrnInfoPtr pScrn, DisplayModePtr *modeList, +xf86PruneInvalidModes(ScrnInfoPtr pScrn, DisplayModePtr *modeList, Bool verbose) { DisplayModePtr mode; @@ -524,13 +524,13 @@ xf86ModesAdd(DisplayModePtr modes, DisplayModePtr new) * Build a mode list from a list of config file modes */ static DisplayModePtr -i830xf86GetConfigModes (XF86ConfModeLinePtr conf_mode) +xf86GetConfigModes (XF86ConfModeLinePtr conf_mode) { DisplayModePtr head = NULL, prev = NULL, mode; for (; conf_mode; conf_mode = (XF86ConfModeLinePtr) conf_mode->list.next) { - mode = xalloc(sizeof(DisplayModeRec)); + mode = xcalloc(1, sizeof(DisplayModeRec)); if (!mode) continue; mode->name = xstrdup(conf_mode->ml_identifier); @@ -539,8 +539,6 @@ i830xf86GetConfigModes (XF86ConfModeLinePtr conf_mode) xfree (mode); continue; } - - memset(mode,'\0',sizeof(DisplayModeRec)); mode->type = 0; mode->Clock = conf_mode->ml_clock; mode->HDisplay = conf_mode->ml_hdisplay; @@ -570,7 +568,7 @@ i830xf86GetConfigModes (XF86ConfModeLinePtr conf_mode) * Build a mode list from a monitor configuration */ DisplayModePtr -i830xf86GetMonitorModes (ScrnInfoPtr pScrn, XF86ConfMonitorPtr conf_monitor) +xf86GetMonitorModes (ScrnInfoPtr pScrn, XF86ConfMonitorPtr conf_monitor) { DisplayModePtr modes = NULL; XF86ConfModesLinkPtr modes_link; @@ -591,18 +589,18 @@ i830xf86GetMonitorModes (ScrnInfoPtr pScrn, XF86ConfMonitorPtr conf_monitor) xf86configptr->conf_modes_lst); if (modes_link->ml_modes) modes = xf86ModesAdd (modes, - i830xf86GetConfigModes (modes_link->ml_modes->mon_modeline_lst)); + xf86GetConfigModes (modes_link->ml_modes->mon_modeline_lst)); } return xf86ModesAdd (modes, - i830xf86GetConfigModes (conf_monitor->mon_modeline_lst)); + xf86GetConfigModes (conf_monitor->mon_modeline_lst)); } /** * Build a mode list containing all of the default modes */ DisplayModePtr -i830xf86GetDefaultModes (Bool interlaceAllowed, Bool doubleScanAllowed) +xf86GetDefaultModes (Bool interlaceAllowed, Bool doubleScanAllowed) { DisplayModePtr head = NULL, prev = NULL, mode; int i; diff --git a/src/i830_xf86Modes.h b/src/i830_xf86Modes.h index a7d0839d..d032199d 100644 --- a/src/i830_xf86Modes.h +++ b/src/i830_xf86Modes.h @@ -29,67 +29,54 @@ #define _I830_XF86MODES_H_ #include "xorgVersion.h" #include "xf86Parser.h" +#include "i830_xf86Rename.h" -#if XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(7,2,99,2,0) -double i830_xf86ModeHSync(DisplayModePtr mode); -double i830_xf86ModeVRefresh(DisplayModePtr mode); -DisplayModePtr i830_xf86DuplicateMode(DisplayModePtr pMode); -DisplayModePtr i830_xf86DuplicateModes(ScrnInfoPtr pScrn, +double xf86ModeHSync(DisplayModePtr mode); +double xf86ModeVRefresh(DisplayModePtr mode); +DisplayModePtr xf86DuplicateMode(DisplayModePtr pMode); +DisplayModePtr xf86DuplicateModes(ScrnInfoPtr pScrn, DisplayModePtr modeList); -void i830_xf86SetModeDefaultName(DisplayModePtr mode); -void i830_xf86SetModeCrtc(DisplayModePtr p, int adjustFlags); -Bool i830_xf86ModesEqual(DisplayModePtr pMode1, DisplayModePtr pMode2); -void i830_xf86PrintModeline(int scrnIndex,DisplayModePtr mode); -DisplayModePtr i830_xf86ModesAdd(DisplayModePtr modes, DisplayModePtr new); +void xf86SetModeDefaultName(DisplayModePtr mode); +void xf86SetModeCrtc(DisplayModePtr p, int adjustFlags); +Bool xf86ModesEqual(DisplayModePtr pMode1, DisplayModePtr pMode2); +void xf86PrintModeline(int scrnIndex,DisplayModePtr mode); +DisplayModePtr xf86ModesAdd(DisplayModePtr modes, DisplayModePtr new); -DisplayModePtr i830_xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC); -DisplayModePtr i830_xf86CVTMode(int HDisplay, int VDisplay, float VRefresh, - Bool Reduced, Bool Interlaced); - -#define xf86ModeHSync i830_xf86ModeHSync -#define xf86ModeVRefresh i830_xf86ModeVRefresh -#define xf86DuplicateMode i830_xf86DuplicateMode -#define xf86DuplicateModes i830_xf86DuplicateModes -#define xf86SetModeDefaultName i830_xf86SetModeDefaultName -#define xf86SetModeCrtc i830_xf86SetModeCrtc -#define xf86ModesEqual i830_xf86ModesEqual -#define xf86PrintModeline i830_xf86PrintModeline -#define xf86ModesAdd i830_xf86ModesAdd -#define xf86DDCGetModes i830_xf86DDCGetModes -#define xf86CVTMode i830_xf86CVTMode -#endif /* XORG_VERSION_CURRENT <= 7.2.99.2 */ +DisplayModePtr xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC); +DisplayModePtr xf86CVTMode(int HDisplay, int VDisplay, float VRefresh, + Bool Reduced, Bool Interlaced); void -i830xf86ValidateModesFlags(ScrnInfoPtr pScrn, DisplayModePtr modeList, - int flags); +xf86ValidateModesFlags(ScrnInfoPtr pScrn, DisplayModePtr modeList, + int flags); void -i830xf86ValidateModesClocks(ScrnInfoPtr pScrn, DisplayModePtr modeList, - int *min, int *max, int n_ranges); +xf86ValidateModesClocks(ScrnInfoPtr pScrn, DisplayModePtr modeList, + int *min, int *max, int n_ranges); void -i830xf86ValidateModesSize(ScrnInfoPtr pScrn, DisplayModePtr modeList, - int maxX, int maxY, int maxPitch); +xf86ValidateModesSize(ScrnInfoPtr pScrn, DisplayModePtr modeList, + int maxX, int maxY, int maxPitch); void -i830xf86ValidateModesSync(ScrnInfoPtr pScrn, DisplayModePtr modeList, - MonPtr mon); +xf86ValidateModesSync(ScrnInfoPtr pScrn, DisplayModePtr modeList, + MonPtr mon); void -i830xf86PruneInvalidModes(ScrnInfoPtr pScrn, DisplayModePtr *modeList, - Bool verbose); +xf86PruneInvalidModes(ScrnInfoPtr pScrn, DisplayModePtr *modeList, + Bool verbose); void -i830xf86ValidateModesFlags(ScrnInfoPtr pScrn, DisplayModePtr modeList, - int flags); +xf86ValidateModesFlags(ScrnInfoPtr pScrn, DisplayModePtr modeList, + int flags); void -i830xf86ValidateModesUserConfig(ScrnInfoPtr pScrn, DisplayModePtr modeList); +xf86ValidateModesUserConfig(ScrnInfoPtr pScrn, DisplayModePtr modeList); DisplayModePtr -i830xf86GetMonitorModes (ScrnInfoPtr pScrn, XF86ConfMonitorPtr conf_monitor); +xf86GetMonitorModes (ScrnInfoPtr pScrn, XF86ConfMonitorPtr conf_monitor); DisplayModePtr -i830xf86GetDefaultModes (Bool interlaceAllowed, Bool doubleScanAllowed); +xf86GetDefaultModes (Bool interlaceAllowed, Bool doubleScanAllowed); #endif /* _I830_XF86MODES_H_ */ diff --git a/src/i830_xf86Rename.h b/src/i830_xf86Rename.h new file mode 100644 index 00000000..cf8de622 --- /dev/null +++ b/src/i830_xf86Rename.h @@ -0,0 +1,66 @@ +/* + * Copyright © 2006 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. + */ + +#ifndef _XF86RENAME_H_ +#define _XF86RENAME_H_ + +#include "local_xf86Rename.h" + +#define xf86CrtcConfigInit XF86NAME(xf86CrtcConfigInit) +#define xf86CrtcConfigPrivateIndex XF86NAME(xf86CrtcConfigPrivateIndex) +#define xf86CrtcCreate XF86NAME(xf86CrtcCreate) +#define xf86CrtcDestroy XF86NAME(xf86CrtcDestroy) +#define xf86CrtcInUse XF86NAME(xf86CrtcInUse) +#define xf86CrtcRotate XF86NAME(xf86CrtcRotate) +#define xf86CrtcSetMode XF86NAME(xf86CrtcSetMode) +#define xf86CrtcSetSizeRange XF86NAME(xf86CrtcSetSizeRange) +#define xf86CVTMode XF86NAME(xf86CVTMode) +#define xf86DisableUnusedFunctions XF86NAME(xf86DisableUnusedFunctions) +#define xf86DPMSSet XF86NAME(xf86DPMSSet) +#define xf86DuplicateMode XF86NAME(xf86DuplicateMode) +#define xf86DuplicateModes XF86NAME(xf86DuplicateModes) +#define xf86GetDefaultModes XF86NAME(xf86GetDefaultModes) +#define xf86GetMonitorModes XF86NAME(xf86GetMonitorModes) +#define xf86InitialConfiguration XF86NAME(xf86InitialConfiguration) +#define xf86ModeHSync XF86NAME(xf86ModeHSync) +#define xf86ModesAdd XF86NAME(xf86ModesAdd) +#define xf86ModesEqual XF86NAME(xf86ModesEqual) +#define xf86ModeVRefresh XF86NAME(xf86ModeVRefresh) +#define xf86OutputCreate XF86NAME(xf86OutputCreate) +#define xf86OutputDestroy XF86NAME(xf86OutputDestroy) +#define xf86OutputGetEDID XF86NAME(xf86OutputGetEDID) +#define xf86OutputGetEDIDModes XF86NAME(xf86OutputGetEDIDModes) +#define xf86OutputRename XF86NAME(xf86OutputRename) +#define xf86OutputSetEDID XF86NAME(xf86OutputSetEDID) +#define xf86PrintModeline XF86NAME(xf86PrintModeline) +#define xf86ProbeOutputModes XF86NAME(xf86ProbeOutputModes) +#define xf86PruneInvalidModes XF86NAME(xf86PruneInvalidModes) +#define xf86SetModeCrtc XF86NAME(xf86SetModeCrtc) +#define xf86SetModeDefaultName XF86NAME(xf86SetModeDefaultName) +#define xf86SetScrnInfoModes XF86NAME(xf86SetScrnInfoModes) +#define xf86ValidateModesClocks XF86NAME(xf86ValidateModesClocks) +#define xf86ValidateModesFlags XF86NAME(xf86ValidateModesFlags) +#define xf86ValidateModesSize XF86NAME(xf86ValidateModesSize) +#define xf86ValidateModesSync XF86NAME(xf86ValidateModesSync) +#define xf86ValidateModesUserConfig XF86NAME(xf86ValidateModesUserConfig) + +#endif /* _XF86RENAME_H_ */ diff --git a/src/i830_xf86Rotate.c b/src/i830_xf86Rotate.c new file mode 100644 index 00000000..3b8be613 --- /dev/null +++ b/src/i830_xf86Rotate.c @@ -0,0 +1,401 @@ +/* + * Copyright © 2006 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stddef.h> +#include <string.h> +#include <stdio.h> + +#include "xf86.h" +#include "xf86DDC.h" +/*#include "i830.h" */ +#include "i830_xf86Crtc.h" +#include "i830_xf86Modes.h" +#include "i830_randr.h" +#include "X11/extensions/render.h" +#define DPMS_SERVER +#include "X11/extensions/dpms.h" +#include "X11/Xatom.h" + +static int +mode_height (DisplayModePtr mode, Rotation rotation) +{ + switch (rotation & 0xf) { + case RR_Rotate_0: + case RR_Rotate_180: + return mode->VDisplay; + case RR_Rotate_90: + case RR_Rotate_270: + return mode->HDisplay; + default: + return 0; + } +} + +static int +mode_width (DisplayModePtr mode, Rotation rotation) +{ + switch (rotation & 0xf) { + case RR_Rotate_0: + case RR_Rotate_180: + return mode->HDisplay; + case RR_Rotate_90: + case RR_Rotate_270: + return mode->VDisplay; + default: + return 0; + } +} + +/* borrowed from composite extension, move to Render and publish? */ + +static VisualPtr +compGetWindowVisual (WindowPtr pWin) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + VisualID vid = wVisual (pWin); + int i; + + for (i = 0; i < pScreen->numVisuals; i++) + if (pScreen->visuals[i].vid == vid) + return &pScreen->visuals[i]; + return 0; +} + +static PictFormatPtr +compWindowFormat (WindowPtr pWin) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + + return PictureMatchVisual (pScreen, pWin->drawable.depth, + compGetWindowVisual (pWin)); +} + +static void +xf86RotateBox (BoxPtr dst, BoxPtr src, Rotation rotation, + int dest_width, int dest_height) +{ + switch (rotation & 0xf) { + default: + case RR_Rotate_0: + *dst = *src; + break; + case RR_Rotate_90: + dst->x1 = src->y1; + dst->y1 = dest_height - src->x2; + dst->x2 = src->y2; + dst->y2 = dest_height - src->x1; + break; + case RR_Rotate_180: + dst->x1 = dest_width - src->x2; + dst->y1 = dest_height - src->y2; + dst->x2 = dest_width - src->x1; + dst->y2 = dest_height - src->y1; + break; + case RR_Rotate_270: + dst->x1 = dest_width - src->y2; + dst->y1 = src->x1; + dst->y2 = src->x2; + dst->x2 = dest_width - src->y1; + break; + } + if (rotation & RR_Reflect_X) { + int x1 = dst->x1; + dst->x1 = dest_width - dst->x2; + dst->x2 = dest_width - x1; + } + if (rotation & RR_Reflect_Y) { + int y1 = dst->y1; + dst->y1 = dest_height - dst->y2; + dst->y2 = dest_height - y1; + } +} + +static void +xf86RotateCrtcRedisplay (xf86CrtcPtr crtc, RegionPtr region) +{ + ScrnInfoPtr scrn = crtc->scrn; + ScreenPtr screen = scrn->pScreen; + WindowPtr root = WindowTable[screen->myNum]; + PixmapPtr dst_pixmap = crtc->rotatedPixmap; + PictFormatPtr format = compWindowFormat (WindowTable[screen->myNum]); + int error; + PicturePtr src, dst; + PictTransform transform; + int n = REGION_NUM_RECTS(region); + BoxPtr b = REGION_RECTS(region); + XID include_inferiors = IncludeInferiors; + + src = CreatePicture (None, + &root->drawable, + format, + CPSubwindowMode, + &include_inferiors, + serverClient, + &error); + if (!src) { + ErrorF("couldn't create src pict\n"); + return; + } + dst = CreatePicture (None, + &dst_pixmap->drawable, + format, + 0L, + NULL, + serverClient, + &error); + if (!dst) { + ErrorF("couldn't create src pict\n"); + return; + } + + memset (&transform, '\0', sizeof (transform)); + transform.matrix[2][2] = IntToxFixed(1); + transform.matrix[0][2] = IntToxFixed(crtc->x); + transform.matrix[1][2] = IntToxFixed(crtc->y); + switch (crtc->rotation & 0xf) { + default: + case RR_Rotate_0: + transform.matrix[0][0] = IntToxFixed(1); + transform.matrix[1][1] = IntToxFixed(1); + break; + case RR_Rotate_90: + transform.matrix[0][1] = IntToxFixed(-1); + transform.matrix[1][0] = IntToxFixed(1); + transform.matrix[0][2] += IntToxFixed(crtc->mode.VDisplay); + break; + case RR_Rotate_180: + transform.matrix[0][0] = IntToxFixed(-1); + transform.matrix[1][1] = IntToxFixed(-1); + transform.matrix[0][2] += IntToxFixed(crtc->mode.HDisplay); + transform.matrix[1][2] += IntToxFixed(crtc->mode.VDisplay); + break; + case RR_Rotate_270: + transform.matrix[0][1] = IntToxFixed(1); + transform.matrix[1][0] = IntToxFixed(-1); + transform.matrix[1][2] += IntToxFixed(crtc->mode.VDisplay); + break; + } + + /* handle reflection */ + if (crtc->rotation & RR_Reflect_X) + { + /* XXX figure this out */ + } + if (crtc->rotation & RR_Reflect_Y) + { + /* XXX figure this out too */ + } + + error = SetPictureTransform (src, &transform); + if (error) { + ErrorF("Couldn't set transform\n"); + return; + } + + while (n--) + { + BoxRec dst_box; + + xf86RotateBox (&dst_box, b, crtc->rotation, + crtc->mode.HDisplay, crtc->mode.VDisplay); + CompositePicture (PictOpSrc, + src, NULL, dst, + dst_box.x1, dst_box.y1, 0, 0, dst_box.x1, dst_box.y1, + dst_box.x2 - dst_box.x1, + dst_box.y2 - dst_box.y1); + b++; + } + FreePicture (src, None); + FreePicture (dst, None); +} + +static void +xf86RotateRedisplay(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + DamagePtr damage = xf86_config->rotationDamage; + RegionPtr region; + + if (!damage) + return; + region = DamageRegion(damage); + if (REGION_NOTEMPTY(pScreen, region)) + { + int c; + + for (c = 0; c < xf86_config->num_crtc; c++) + { + xf86CrtcPtr crtc = xf86_config->crtc[c]; + + 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->mode, crtc->rotation); + box.y1 = crtc->y; + 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); + + /* update damaged region */ + if (REGION_NOTEMPTY(pScreen, &crtc_damage)) + xf86RotateCrtcRedisplay (crtc, &crtc_damage); + + REGION_UNINIT (pScreen, &crtc_damage); + } + } + DamageEmpty(damage); + } +} + +static void +xf86RotateBlockHandler(pointer data, OSTimePtr pTimeout, pointer pRead) +{ + ScreenPtr pScreen = (ScreenPtr) data; + + xf86RotateRedisplay(pScreen); +} + +static void +xf86RotateWakeupHandler(pointer data, int i, pointer LastSelectMask) +{ +} + +Bool +xf86CrtcRotate (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation) +{ + ScrnInfoPtr pScrn = crtc->scrn; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + ScreenPtr pScreen = pScrn->pScreen; + + if (rotation == RR_Rotate_0) + { + /* Free memory from rotation */ + if (crtc->rotatedPixmap) + { + crtc->funcs->shadow_destroy (crtc, crtc->rotatedPixmap); + crtc->rotatedPixmap = NULL; + } + + if (xf86_config->rotationDamage) + { + /* Free damage structure */ + DamageUnregister (&(*pScreen->GetScreenPixmap)(pScreen)->drawable, + xf86_config->rotationDamage); + DamageDestroy (xf86_config->rotationDamage); + xf86_config->rotationDamage = NULL; + /* Free block/wakeup handler */ + RemoveBlockAndWakeupHandlers (xf86RotateBlockHandler, + xf86RotateWakeupHandler, + (pointer) pScreen); + } + } + else + { + /* + * these are the size of the shadow pixmap, which + * matches the mode, not the pre-rotated copy in the + * frame buffer + */ + int width = mode->HDisplay; + int height = mode->VDisplay; + PixmapPtr shadow = crtc->rotatedPixmap; + int old_width = shadow ? shadow->drawable.width : 0; + int old_height = shadow ? shadow->drawable.height : 0; + BoxRec damage_box; + RegionRec damage_region; + + /* Allocate memory for rotation */ + if (old_width != width || old_height != height) + { + if (shadow) + { + crtc->funcs->shadow_destroy (crtc, shadow); + crtc->rotatedPixmap = NULL; + } + shadow = crtc->funcs->shadow_create (crtc, width, height); + if (!shadow) + goto bail1; + crtc->rotatedPixmap = shadow; + } + + if (!xf86_config->rotationDamage) + { + /* Create damage structure */ + xf86_config->rotationDamage = DamageCreate (NULL, NULL, + DamageReportNone, + TRUE, pScreen, pScreen); + if (!xf86_config->rotationDamage) + goto bail2; + + /* Hook damage to screen pixmap */ + DamageRegister (&(*pScreen->GetScreenPixmap)(pScreen)->drawable, + xf86_config->rotationDamage); + + /* Assign block/wakeup handler */ + if (!RegisterBlockAndWakeupHandlers (xf86RotateBlockHandler, + xf86RotateWakeupHandler, + (pointer) pScreen)) + { + goto bail3; + } + damage_box.x1 = 0; + damage_box.y1 = 0; + damage_box.x2 = mode_width (mode, rotation); + damage_box.y2 = mode_height (mode, rotation); + REGION_INIT (pScreen, &damage_region, &damage_box, 1); + DamageDamageRegion (&(*pScreen->GetScreenPixmap)(pScreen)->drawable, + &damage_region); + REGION_UNINIT (pScreen, &damage_region); + } + if (0) + { +bail3: + DamageDestroy (xf86_config->rotationDamage); + xf86_config->rotationDamage = NULL; + +bail2: + if (shadow) + { + crtc->funcs->shadow_destroy (crtc, shadow); + crtc->rotatedPixmap = NULL; + } +bail1: + if (old_width && old_height) + crtc->rotatedPixmap = crtc->funcs->shadow_create (crtc, + old_width, + old_height); + return FALSE; + } + } + + /* All done */ + return TRUE; +} diff --git a/src/local_xf86Rename.h b/src/local_xf86Rename.h new file mode 100644 index 00000000..e1e788f3 --- /dev/null +++ b/src/local_xf86Rename.h @@ -0,0 +1,23 @@ +/* + * Copyright © 2006 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. + */ + +#define XF86NAME(x) intel_##x |