From 5c1e27cdd243dc24dd2bfdeb46d757bbef6ba6af Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 25 Jan 2007 15:31:22 -0800 Subject: Make rotated shadow buffer allocation dynamic. For EXA, this requires version 2.1 of EXA to do rotation, as the VT switching issues were too complicated otherwise. --- src/i830.h | 16 ++++++++- src/i830_display.c | 78 +++++++++++++++++++++++++++++++++++----- src/i830_driver.c | 18 +++++++++- src/i830_exa.c | 13 ++++--- src/i830_memory.c | 104 ++++++++++++++++++++--------------------------------- src/i830_video.c | 22 ++---------- 6 files changed, 152 insertions(+), 99 deletions(-) diff --git a/src/i830.h b/src/i830.h index a7c889d4..9ffae94c 100644 --- a/src/i830.h +++ b/src/i830.h @@ -199,7 +199,13 @@ typedef struct _I830CrtcPrivateRec { /* Lookup table values to be set when the CRTC is enabled */ CARD8 lut_r[256], lut_g[256], lut_b[256]; - I830MemRange rotate_mem; +#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; @@ -613,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_display.c b/src/i830_display.c index 2313f768..82029850 100644 --- a/src/i830_display.c +++ b/src/i830_display.c @@ -342,8 +342,9 @@ i830PipeSetBase(xf86CrtcPtr crtc, int x, int y) int dspbase = (pipe == 0 ? DSPABASE : DSPBBASE); int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF); - if (crtc->rotation != RR_Rotate_0) { - Start = intel_crtc->rotate_mem.Start; + if (crtc->rotatedPixmap != NULL) { + Start = (char *)crtc->rotatedPixmap->devPrivate.ptr - + (char *)pI830->FbBase; } else if (I830IsPrimary(pScrn)) { Start = pI830->FrontBuffer.Start; } else { @@ -895,31 +896,92 @@ static PixmapPtr i830_crtc_shadow_create(xf86CrtcPtr crtc, int width, int height) { ScrnInfoPtr pScrn = crtc->scrn; + ScreenPtr pScreen = pScrn->pScreen; I830Ptr pI830 = I830PTR(pScrn); I830CrtcPrivatePtr intel_crtc = crtc->driver_private; unsigned long rotate_pitch; PixmapPtr rotate_pixmap; - pointer rotate_offset; - - if (intel_crtc->rotate_mem.Start == 0) - return NULL; + unsigned long rotate_offset; + int align = KB(4), size; rotate_pitch = pI830->displayWidth * pI830->cpp; - rotate_offset = pI830->FbBase + intel_crtc->rotate_mem.Start; + 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. + */ + 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; + } +#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; + } +#endif /* I830_USE_XAA */ rotate_pixmap = GetScratchPixmapHeader(pScrn->pScreen, width, height, pScrn->depth, pScrn->bitsPerPixel, rotate_pitch, - rotate_offset); + pI830->FbBase + rotate_offset); + if (rotate_pixmap == NULL) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Couldn't allocate shadow pixmap for rotated CRTC\n"); + } return rotate_pixmap; } static void i830_crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap) { + ScrnInfoPtr pScrn = crtc->scrn; + I830Ptr pI830 = I830PTR(pScrn); + I830CrtcPrivatePtr intel_crtc = crtc->driver_private; + 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; + } +#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 */ } diff --git a/src/i830_driver.c b/src/i830_driver.c index 644ea57f..19e97b00 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -2879,7 +2879,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; 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_memory.c b/src/i830_memory.c index 14dacc86..24f0b296 100644 --- a/src/i830_memory.c +++ b/src/i830_memory.c @@ -769,63 +769,6 @@ I830AllocateFramebuffer(ScrnInfoPtr pScrn, I830Ptr pI830, BoxPtr FbMemBox, return TRUE; } -/** - * Allocates memory for the rotated shadow buffers. - * - * This memory would be better allocated normally through the linear allocator, - * but it gets rotation working for now. - */ -static Bool -I830AllocateRotateBuffers(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); - unsigned long avail, lineSize; - int verbosity = dryrun ? 4 : 1; - const char *s = dryrun ? "[dryrun] " : ""; - int align, alignflags; - long size, alloced; - int rotate_width, rotate_height; - - memset(&intel_crtc->rotate_mem, 0, sizeof(intel_crtc->rotate_mem)); - - rotate_width = pScrn->displayWidth; - if (pScrn->virtualX > pScrn->virtualY) - rotate_height = pScrn->virtualX; - else - rotate_height = pScrn->virtualY; - - lineSize = pScrn->displayWidth * pI830->cpp; - avail = pScrn->videoRam * 1024; - - align = KB(64); - alignflags = 0; - - size = lineSize * rotate_height; - size = ROUND_TO_PAGE(size); - xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, - "%sInitial %sshadow framebuffer allocation size: " - "%ld kByte\n", - s, (intel_crtc->pipe == 0) ? "" : "secondary ", - size / 1024); - alloced = I830AllocVidMem(pScrn, &intel_crtc->rotate_mem, - &pI830->StolenPool, size, align, - flags | alignflags | - FROM_ANYWHERE | ALLOCATE_AT_BOTTOM); - if (alloced < size) { - if (!dryrun) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to allocate " - "%sshadow framebuffer. Is your VideoRAM set too low?\n", - (intel_crtc->pipe == 0) ? "" : "secondary "); - } - return FALSE; - } - - return TRUE; -} - static Bool I830AllocateCursorBuffers(xf86CrtcPtr crtc, const int flags) { @@ -981,10 +924,6 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, const int flags) return FALSE; } - for (i = 0; i < xf86_config->num_crtc; i++) { - I830AllocateRotateBuffers(xf86_config->crtc[i], flags); - } - #ifdef I830_USE_EXA if (pI830->useEXA) { /* Default EXA to having 3 screens worth of offscreen memory space @@ -1619,7 +1558,6 @@ I830FixupOffsets(ScrnInfoPtr pScrn) for (i = 0; i < xf86_config->num_crtc; i++) { I830CrtcPrivatePtr intel_crtc = xf86_config->crtc[i]->driver_private; - I830FixOffset(pScrn, &intel_crtc->rotate_mem); I830FixOffset(pScrn, &intel_crtc->cursor_mem); I830FixOffset(pScrn, &intel_crtc->cursor_mem_argb); } @@ -2028,8 +1966,6 @@ I830BindAGPMemory(ScrnInfoPtr pScrn) for (i = 0; i < xf86_config->num_crtc; i++) { I830CrtcPrivatePtr intel_crtc = xf86_config->crtc[i]->driver_private; - if (!BindMemRange(pScrn, &intel_crtc->rotate_mem)) - return FALSE; if (!BindMemRange(pScrn, &intel_crtc->cursor_mem)) return FALSE; if (!BindMemRange(pScrn, &intel_crtc->cursor_mem_argb)) @@ -2130,8 +2066,6 @@ I830UnbindAGPMemory(ScrnInfoPtr pScrn) for (i = 0; i < xf86_config->num_crtc; i++) { I830CrtcPrivatePtr intel_crtc = xf86_config->crtc[i]->driver_private; - if (!UnbindMemRange(pScrn, &intel_crtc->rotate_mem)) - return FALSE; if (!UnbindMemRange(pScrn, &intel_crtc->cursor_mem)) return FALSE; if (!UnbindMemRange(pScrn, &intel_crtc->cursor_mem_argb)) @@ -2209,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_video.c b/src/i830_video.c index 79f5a7c8..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, align, - NULL, NULL, NULL); linear->offset = XAA_OFFSET_TO_OFFSET(linear->xaa->offset); } #endif /* I830_USE_XAA */ -- cgit v1.2.3