diff options
author | Eric Anholt <eric@anholt.net> | 2006-12-27 13:45:06 -0800 |
---|---|---|
committer | Eric Anholt <eric@anholt.net> | 2006-12-27 13:54:22 -0800 |
commit | 46df75ccd4647ea033583130253a2a2218b34a20 (patch) | |
tree | 91d0bc85a384b8c428b50d71ee283a0772c3d8b9 | |
parent | 84915ac8afeb4bbc03df8f94ab3ba351788d6501 (diff) |
Bug #7524: Major improvements to EXA/XAA static memory allocation.
With this, we no longer allocate XV through the XF86 linear allocator in the
EXA case. We also no longer allocate extra space for the XF86 2D allocator
that we don't use in EXA mode, or space for the EXA allocator in XAA mode.
The EXA offscreen allocator now gets enough space for several screenfuls of
pixmaps plus one 1920x1088 movie.
A large duplicated section of code for allocating each framebuffer in the old
dual-screen mode was also factored out.
-rw-r--r-- | src/i830_driver.c | 34 | ||||
-rw-r--r-- | src/i830_memory.c | 397 | ||||
-rw-r--r-- | src/i830_video.c | 199 | ||||
-rw-r--r-- | src/i830_video.h | 15 |
4 files changed, 332 insertions, 313 deletions
diff --git a/src/i830_driver.c b/src/i830_driver.c index d30af07c..e2653c15 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -2855,20 +2855,28 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) DPRINTF(PFX, "assert( if(!I830InitFBManager(pScreen, &(pI830->FbMemBox))) )\n"); - if (I830IsPrimary(pScrn)) { - if (!I830InitFBManager(pScreen, &(pI830->FbMemBox))) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Failed to init memory manager\n"); - } - - if (pI830->LinearAlloc && xf86InitFBManagerLinear(pScreen, pI830->LinearMem.Offset / pI830->cpp, pI830->LinearMem.Size / pI830->cpp)) - xf86DrvMsg(scrnIndex, X_INFO, - "Using %ld bytes of offscreen memory for linear (offset=0x%lx)\n", pI830->LinearMem.Size, pI830->LinearMem.Offset); + if (!pI830->useEXA) { + if (I830IsPrimary(pScrn)) { + if (!I830InitFBManager(pScreen, &(pI830->FbMemBox))) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to init memory manager\n"); + } - } else { - if (!I830InitFBManager(pScreen, &(pI8301->FbMemBox2))) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Failed to init memory manager\n"); + if (pI830->LinearAlloc && + xf86InitFBManagerLinear(pScreen, + pI830->LinearMem.Offset / pI830->cpp, + pI830->LinearMem.Size / pI830->cpp)) + { + xf86DrvMsg(scrnIndex, X_INFO, + "Using %ld bytes of offscreen memory for linear " + "(offset=0x%lx)\n", pI830->LinearMem.Size, + pI830->LinearMem.Offset); + } + } else { + if (!I830InitFBManager(pScreen, &(pI8301->FbMemBox2))) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to init memory manager\n"); + } } } diff --git a/src/i830_memory.c b/src/i830_memory.c index 7b0c6fe4..b41a73d2 100644 --- a/src/i830_memory.c +++ b/src/i830_memory.c @@ -602,11 +602,141 @@ GetFreeSpace(ScrnInfoPtr pScrn) return extra; } +/** + * Allocates a framebuffer for a screen. + * + * Used once for each X screen, so once with RandR 1.2 and twice with classic + * dualhead. + * + * \param pScrn ScrnInfoPtr for the screen being allocated + * \param pI830 I830Ptr for the screen being allocated. + * \param FbMemBox + */ +static Bool +I830AllocateFramebuffer(ScrnInfoPtr pScrn, I830Ptr pI830, BoxPtr FbMemBox, + I830MemRange *FrontBuffer, I830MemPool *StolenPool, + Bool secondary, const int flags) +{ + Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0); + unsigned long minspace, avail, lineSize; + int cacheLines, maxCacheLines; + int verbosity = dryrun ? 4 : 1; + const char *s = dryrun ? "[dryrun] " : ""; + Bool tileable; + int align, alignflags; + long size, alloced, fb_height; + + /* Clear everything first. */ + memset(FbMemBox, 0, sizeof(*FbMemBox)); + memset(FrontBuffer, 0, sizeof(*FrontBuffer)); + FrontBuffer->Key = -1; + + /* We'll allocate the fb such that the root window will fit regardless of + * rotation. + */ + if (pScrn->virtualX > pScrn->virtualY) + fb_height = pScrn->virtualX; + else + fb_height = pScrn->virtualY; + + FbMemBox->x1 = 0; + FbMemBox->x2 = pScrn->displayWidth; + FbMemBox->y1 = 0; + FbMemBox->y2 = fb_height; + + /* Calculate how much framebuffer memory to allocate. For the + * initial allocation, calculate a reasonable minimum. This is + * enough for the virtual screen size, plus some pixmap cache + * space if we're using XAA. + */ + + lineSize = pScrn->displayWidth * pI830->cpp; + minspace = lineSize * pScrn->virtualY; + avail = pScrn->videoRam * 1024; + + if (!pI830->useEXA) { + maxCacheLines = (avail - minspace) / lineSize; + /* This shouldn't happen. */ + if (maxCacheLines < 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Internal Error: " + "maxCacheLines < 0 in I830Allocate2DMemory()\n"); + maxCacheLines = 0; + } + if (maxCacheLines > (MAX_DISPLAY_HEIGHT - pScrn->virtualY)) + maxCacheLines = MAX_DISPLAY_HEIGHT - pScrn->virtualY; + + if (pI830->CacheLines >= 0) { + cacheLines = pI830->CacheLines; + } else { +#if 1 + /* Make sure there is enough for two DVD sized YUV buffers */ + cacheLines = (pScrn->depth == 24) ? 256 : 384; + if (pScrn->displayWidth <= 1024) + cacheLines *= 2; +#else + /* + * Make sure there is enough for two DVD sized YUV buffers. + * Make that 1.5MB, which is around what was allocated with + * the old algorithm + */ + cacheLines = (MB(1) + KB(512)) / pI830->cpp / pScrn->displayWidth; +#endif + } + if (cacheLines > maxCacheLines) + cacheLines = maxCacheLines; + + FbMemBox->y2 += cacheLines; + + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, + "%sAllocating at least %d scanlines for pixmap cache\n", + s, cacheLines); + } else { + /* For EXA, we have a separate allocation for the linear allocator which + * also does the pixmap cache. + */ + cacheLines = 0; + } + + tileable = !(flags & ALLOC_NO_TILING) && pI830->allowPageFlip && + IsTileable(pScrn->displayWidth * pI830->cpp); + if (tileable) { + if (IS_I9XX(pI830)) + align = MB(1); + else + align = KB(512); + alignflags = ALIGN_BOTH_ENDS; + } else { + align = KB(64); + alignflags = 0; + } + + size = lineSize * (fb_height + cacheLines); + size = ROUND_TO_PAGE(size); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, + "%sInitial %sframebuffer allocation size: %ld kByte\n", + s, secondary ? "secondary " : "", + size / 1024); + alloced = I830AllocVidMem(pScrn, FrontBuffer, + StolenPool, size, align, + flags | alignflags | + FROM_ANYWHERE | ALLOCATE_AT_BOTTOM); + if (alloced < size) { + if (!dryrun) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to allocate " + "%sframebuffer. Is your VideoRAM set too low?\n", + secondary ? "secondary " : ""); + } + return FALSE; + } + + return TRUE; +} + /* * Allocate memory for 2D operation. This includes the (front) framebuffer, * ring buffer, scratch memory, HW cursor. */ - Bool I830Allocate2DMemory(ScrnInfoPtr pScrn, const int flags) { @@ -648,8 +778,6 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, const int flags) pI830->StolenPool.Free.Size); if (flags & ALLOC_INITIAL) { - unsigned long minspace, avail, lineSize; - int cacheLines, maxCacheLines; if (pI830->NeedRingBufferLow) AllocateRingBuffer(pScrn, flags | FORCE_LOW); @@ -660,242 +788,45 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, const int flags) I830EntPtr pI830Ent = pI830->entityPrivate; I830Ptr pI8302 = I830PTR(pI830Ent->pScrn_2); - /* Clear everything first. */ - memset(&(pI830->FbMemBox2), 0, sizeof(pI830->FbMemBox2)); - memset(&(pI830->FrontBuffer2), 0, sizeof(pI830->FrontBuffer2)); - pI830->FrontBuffer2.Key = -1; - -#if 1 /* ROTATION */ - pI830->FbMemBox2.x1 = 0; - pI830->FbMemBox2.x2 = pI830Ent->pScrn_2->displayWidth; - pI830->FbMemBox2.y1 = 0; - if (pI830Ent->pScrn_2->virtualX > pI830Ent->pScrn_2->virtualY) - pI830->FbMemBox2.y2 = pI830Ent->pScrn_2->virtualX; - else - pI830->FbMemBox2.y2 = pI830Ent->pScrn_2->virtualY; -#else - pI830->FbMemBox2.x1 = 0; - pI830->FbMemBox2.x2 = pI830Ent->pScrn_2->displayWidth; - pI830->FbMemBox2.y1 = 0; - pI830->FbMemBox2.y2 = pI830Ent->pScrn_2->virtualY; -#endif - - /* - * Calculate how much framebuffer memory to allocate. For the - * initial allocation, calculate a reasonable minimum. This is - * enough for the virtual screen size, plus some pixmap cache - * space. - */ - - lineSize = pI830Ent->pScrn_2->displayWidth * pI8302->cpp; - minspace = lineSize * pI830Ent->pScrn_2->virtualY; - avail = pI830Ent->pScrn_2->videoRam * 1024; - maxCacheLines = (avail - minspace) / lineSize; - /* This shouldn't happen. */ - if (maxCacheLines < 0) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Internal Error: " - "maxCacheLines < 0 in I830Allocate2DMemory()\n"); - maxCacheLines = 0; - } - if (maxCacheLines > (MAX_DISPLAY_HEIGHT - pI830Ent->pScrn_2->virtualY)) - maxCacheLines = MAX_DISPLAY_HEIGHT - pI830Ent->pScrn_2->virtualY; - - if (pI8302->CacheLines >= 0) { - cacheLines = pI8302->CacheLines; - } else { -#if 1 - /* Make sure there is enough for two DVD sized YUV buffers */ - cacheLines = (pI830Ent->pScrn_2->depth == 24) ? 256 : 384; - if (pI830Ent->pScrn_2->displayWidth <= 1024) - cacheLines *= 2; -#else - /* - * Make sure there is enough for two DVD sized YUV buffers. - * Make that 1.5MB, which is around what was allocated with - * the old algorithm - */ - cacheLines = (MB(1) + KB(512)) / pI8302->cpp / pI830Ent->pScrn_2->displayWidth; -#endif - } - if (cacheLines > maxCacheLines) - cacheLines = maxCacheLines; - - pI830->FbMemBox2.y2 += cacheLines; - - xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, - "%sAllocating at least %d scanlines for pixmap cache\n", - s, cacheLines); - - tileable = !(flags & ALLOC_NO_TILING) && pI8302->allowPageFlip && - IsTileable(pI830Ent->pScrn_2->displayWidth * pI8302->cpp); - if (tileable) { - if (IS_I9XX(pI830)) - align = MB(1); - else - align = KB(512); - alignflags = ALIGN_BOTH_ENDS; - } else { - align = KB(64); - alignflags = 0; - } - -#if 1 /* ROTATION */ - if (pI830Ent->pScrn_2->virtualX > pI830Ent->pScrn_2->virtualY) - size = lineSize * (pI830Ent->pScrn_2->virtualX + cacheLines); - else - size = lineSize * (pI830Ent->pScrn_2->virtualY + cacheLines); - size = ROUND_TO_PAGE(size); -#else - size = lineSize * (pI830Ent->pScrn_2->virtualY + cacheLines); - size = ROUND_TO_PAGE(size); -#endif - xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, - "%sSecondary framebuffer allocation size: %ld kByte\n", s, - size / 1024); - alloced = I830AllocVidMem(pScrn, &(pI830->FrontBuffer2), - &(pI830->StolenPool), size, align, - flags | alignflags | - FROM_ANYWHERE | ALLOCATE_AT_BOTTOM); - if (alloced < size) { - if (!dryrun) { - xf86DrvMsg(pI830Ent->pScrn_2->scrnIndex, X_ERROR, - "Failed to allocate secondary framebuffer.\n"); - } - return FALSE; - } - } - - /* Clear everything first. */ - memset(&(pI830->FbMemBox), 0, sizeof(pI830->FbMemBox)); - memset(&(pI830->FrontBuffer), 0, sizeof(pI830->FrontBuffer)); - pI830->FrontBuffer.Key = -1; - -#if 1 /* ROTATION */ - pI830->FbMemBox.x1 = 0; - pI830->FbMemBox.x2 = pScrn->displayWidth; - pI830->FbMemBox.y1 = 0; - if (pScrn->virtualX > pScrn->virtualY) - pI830->FbMemBox.y2 = pScrn->virtualX; - else - pI830->FbMemBox.y2 = pScrn->virtualY; -#else - pI830->FbMemBox.x1 = 0; - pI830->FbMemBox.x2 = pScrn->displayWidth; - pI830->FbMemBox.y1 = 0; - pI830->FbMemBox.y2 = pScrn->virtualY; -#endif - - /* - * Calculate how much framebuffer memory to allocate. For the - * initial allocation, calculate a reasonable minimum. This is - * enough for the virtual screen size, plus some pixmap cache - * space. - */ - - lineSize = pScrn->displayWidth * pI830->cpp; - minspace = lineSize * pScrn->virtualY; - avail = pScrn->videoRam * 1024; - maxCacheLines = (avail - minspace) / lineSize; - /* This shouldn't happen. */ - if (maxCacheLines < 0) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Internal Error: " - "maxCacheLines < 0 in I830Allocate2DMemory()\n"); - maxCacheLines = 0; - } - if (maxCacheLines > (MAX_DISPLAY_HEIGHT - pScrn->virtualY)) - maxCacheLines = MAX_DISPLAY_HEIGHT - pScrn->virtualY; - - if (pI830->CacheLines >= 0) { - cacheLines = pI830->CacheLines; - } else { -#if 1 - /* Make sure there is enough for two DVD sized YUV buffers */ - cacheLines = (pScrn->depth == 24) ? 256 : 384; - if (pScrn->displayWidth <= 1024) - cacheLines *= 2; -#else - /* - * Make sure there is enough for two DVD sized YUV buffers. - * Make that 1.5MB, which is around what was allocated with - * the old algorithm - */ - cacheLines = (MB(1) + KB(512)) / pI830->cpp / pScrn->displayWidth; -#endif - } - if (cacheLines > maxCacheLines) - cacheLines = maxCacheLines; - - pI830->FbMemBox.y2 += cacheLines; - - xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, - "%sAllocating at least %d scanlines for pixmap cache\n", - s, cacheLines); - - tileable = !(flags & ALLOC_NO_TILING) && pI830->allowPageFlip && - IsTileable(pScrn->displayWidth * pI830->cpp); - if (tileable) { - if (IS_I9XX(pI830)) - align = MB(1); - else - align = KB(512); - alignflags = ALIGN_BOTH_ENDS; - } else { - align = KB(64); - alignflags = 0; - } - -#if 1 /* ROTATION */ - if (pScrn->virtualX > pScrn->virtualY) - size = lineSize * (pScrn->virtualX + cacheLines); - else - size = lineSize * (pScrn->virtualY + cacheLines); - size = ROUND_TO_PAGE(size); -#else - size = lineSize * (pScrn->virtualY + cacheLines); - size = ROUND_TO_PAGE(size); -#endif - xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, - "%sInitial framebuffer allocation size: %ld kByte\n", s, - size / 1024); - alloced = I830AllocVidMem(pScrn, &(pI830->FrontBuffer), - &(pI830->StolenPool), size, align, - flags | alignflags | - FROM_ANYWHERE | ALLOCATE_AT_BOTTOM); - if (alloced < size) { - if (!dryrun) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to allocate " - "framebuffer. Is your VideoRAM set too low ??\n"); + if (!I830AllocateFramebuffer(pI830Ent->pScrn_2, pI8302, + &pI830->FbMemBox2, + &pI830->FrontBuffer2, &pI830->StolenPool, + TRUE, flags)) + { + return FALSE; } + } + if (!I830AllocateFramebuffer(pScrn, pI830, &pI830->FbMemBox, + &pI830->FrontBuffer, &pI830->StolenPool, + FALSE, flags)) + { return FALSE; } -#ifdef I830_USE_EXA - size = lineSize * pScrn->virtualY; - size = ROUND_TO_PAGE(size); - if (tileable) { - align = KB(512); - alignflags = ALIGN_BOTH_ENDS; - } else { - align = KB(64); - alignflags = 0; - } +#ifdef I830_USE_EXA + if (pI830->useEXA) { + /* Default EXA to having 3 screens worth of offscreen memory space + * (for pixmaps), plus a double-buffered, 1920x1088 video's worth. + */ + size = 3 * pScrn->displayWidth * pI830->cpp * pScrn->virtualY; + size += 1920 * 1088 * 2 * 2; + size = ROUND_TO_PAGE(size); - alloced = I830AllocVidMem(pScrn, &(pI830->Offscreen), - &(pI830->StolenPool), size, align, - flags | alignflags | - FROM_ANYWHERE | ALLOCATE_AT_BOTTOM); - if (alloced < size) { - if (!dryrun) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to allocate " - "offscreen memory. Not enough VRAM?\n"); + alloced = I830AllocVidMem(pScrn, &(pI830->Offscreen), + &(pI830->StolenPool), size, 1, + flags | + FROM_ANYWHERE | ALLOCATE_AT_BOTTOM); + if (alloced < size) { + if (!dryrun) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to allocate " + "offscreen memory. Not enough VRAM?\n"); + } + return FALSE; + } else { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Successful allocation of " + "EXA offscreen memory at 0x%lx, size %ld KB\n", + pI830->Offscreen.Start, pI830->Offscreen.Size/1024); } - return FALSE; - } else { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Successful allocate " - "offscreen memory at 0x%lx, size %ld KB\n", - pI830->Offscreen.Start, pI830->Offscreen.Size/1024); } #endif } else { diff --git a/src/i830_video.c b/src/i830_video.c index d10fd168..946a447e 100644 --- a/src/i830_video.c +++ b/src/i830_video.c @@ -120,8 +120,8 @@ static int I830QueryImageAttributesTextured(ScrnInfoPtr, int, unsigned short *, static void I830BlockHandler(int, pointer, pointer, pointer); -static FBLinearPtr -I830AllocateMemory(ScrnInfoPtr pScrn, FBLinearPtr linear, int size); +static void +I830FreeMemory(ScrnInfoPtr pScrn, struct linear_alloc *linear); #define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) @@ -715,7 +715,7 @@ I830SetupImageVideoOverlay(ScreenPtr pScreen) pPriv->contrast = 64; pPriv->saturation = 128; pPriv->pipe = 0; /* XXX must choose pipe wisely */ - pPriv->linear = NULL; + memset(&pPriv->linear, 0, sizeof(pPriv->linear)); pPriv->currentBuf = 0; pPriv->gamma5 = 0xc0c0c0; pPriv->gamma4 = 0x808080; @@ -838,7 +838,7 @@ I830SetupImageVideoTextured(ScreenPtr pScreen) pPriv->textured = TRUE; pPriv->videoStatus = 0; - pPriv->linear = NULL; + memset(&pPriv->linear, 0, sizeof(pPriv->linear)); pPriv->currentBuf = 0; pPriv->doubleBuffer = 0; @@ -902,10 +902,7 @@ I830StopVideo(ScrnInfoPtr pScrn, pointer data, Bool shutdown) if (pI830->entityPrivate) pI830->entityPrivate->XvInUse = -1; } - if (pPriv->linear) { - xf86FreeOffscreenLinear(pPriv->linear); - pPriv->linear = NULL; - } + I830FreeMemory(pScrn, &pPriv->linear); pPriv->videoStatus = 0; } else { if (pPriv->videoStatus & CLIENT_VIDEO_ON) { @@ -2224,9 +2221,7 @@ BroadwaterDisplayVideoTextured(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, int id, /* * Use the extra space allocated at the end of the Xv buffer */ - state_base_offset = (pPriv->YBuf0offset + - pPriv->linear->size * pI830->cpp - - BRW_LINEAR_EXTRA); + state_base_offset = pPriv->extra_offset; state_base_offset = ALIGN(state_base_offset, 64); state_base = (char *)(pI830->FbBase + state_base_offset); @@ -2798,44 +2793,119 @@ BroadwaterDisplayVideoTextured(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, int id, #endif } -static FBLinearPtr -I830AllocateMemory(ScrnInfoPtr pScrn, FBLinearPtr linear, int size) +#ifdef I830_USE_EXA +static void +I830VideoSave(ScreenPtr pScreen, ExaOffscreenArea *area) +{ + struct linear_alloc *linear = area->privData; + + linear->exa = NULL; + linear->offset = 0; +} +#endif /* I830_USE_EXA */ + +/** + * Allocates linear memory using the XFree86 (XAA) or EXA allocator. + * + * \param pPriv adaptor the memory is being allocated for. + * \param size size of the allocation, in bytes. + * \param alignment offset alignment of the allocation, in bytes. + * \return offset of the allocated memory. + */ +static void +I830AllocateMemory(ScrnInfoPtr pScrn, struct linear_alloc *linear, int size, + int align) { - ScreenPtr pScreen; - FBLinearPtr new_linear = NULL; + ScreenPtr pScreen = pScrn->pScreen; + I830Ptr pI830 = I830PTR(pScrn); - if (linear) { - if (linear->size >= size) - return linear; +#ifdef I830_USE_EXA + if (pI830->useEXA) { + if (linear->exa != NULL) { + if (linear->exa->size >= size) + return; - if (xf86ResizeOffscreenLinear(linear, size)) - return linear; + exaOffscreenFree(pScreen, linear->exa); + linear->offset = 0; + } - xf86FreeOffscreenLinear(linear); + linear->exa = exaOffscreenAlloc(pScreen, size, align, TRUE, + I830VideoSave, linear); + if (linear->exa == NULL) + return; + linear->offset = linear->exa->offset; } +#endif /* I830_USE_EXA */ +#ifdef I830_USE_XAA + if (!pI830->useEXA) { + int max_size; - pScreen = screenInfo.screens[pScrn->scrnIndex]; + /* 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; - new_linear = xf86AllocateOffscreenLinear(pScreen, size, 4, - NULL, NULL, NULL); + if (linear->xaa != NULL) { + if (linear->xaa->size >= size) { + linear->offset = linear->xaa->offset * pI830->cpp; + return; + } - if (!new_linear) { - int max_size; + if (xf86ResizeOffscreenLinear(linear->xaa, size)) { + linear->offset = linear->xaa->offset * pI830->cpp; + return; + } + + xf86FreeOffscreenLinear(linear->xaa); + } + + linear->xaa = xf86AllocateOffscreenLinear(pScreen, size, align, + NULL, NULL, NULL); + if (linear->xaa != NULL) { + linear->offset = linear->xaa->offset * pI830->cpp; + return; + } - xf86QueryLargestOffscreenLinear(pScreen, &max_size, 4, + xf86QueryLargestOffscreenLinear(pScreen, &max_size, align, PRIORITY_EXTREME); if (max_size < size) { - ErrorF("No memory available\n"); - return NULL; + ErrorF("No memory available\n"); + linear->offset = 0; + return; } xf86PurgeUnlockedOffscreenAreas(pScreen); - new_linear = xf86AllocateOffscreenLinear(pScreen, size, 4, - NULL, NULL, NULL); + linear->xaa = xf86AllocateOffscreenLinear(pScreen, size, 4, + NULL, NULL, NULL); + linear->offset = linear->xaa->offset * pI830->cpp; } +#endif /* I830_USE_XAA */ +} - return new_linear; +static void +I830FreeMemory(ScrnInfoPtr pScrn, struct linear_alloc *linear) +{ + I830Ptr pI830 = I830PTR(pScrn); + +#ifdef I830_USE_EXA + if (pI830->useEXA) { + if (linear->exa != NULL) { + exaOffscreenFree(pScrn->pScreen, linear->exa); + linear->exa = NULL; + } + } +#endif /* I830_USE_EXA */ +#ifdef I830_USE_XAA + if (!pI830->useEXA) { + if (linear->xaa != NULL) { + xf86FreeOffscreenLinear(linear->xaa); + linear->xaa = NULL; + } + } +#endif /* I830_USE_XAA */ + linear->offset = 0; } /* @@ -2981,19 +3051,21 @@ I830PutImage(ScrnInfoPtr pScrn, extraLinear = 0; /* size is multiplied by 2 because we have two buffers that are flipping */ - pPriv->linear = I830AllocateMemory(pScrn, pPriv->linear, - (extraLinear + - (pPriv->doubleBuffer ? size * 2 : size)) / - pI830->cpp); + I830AllocateMemory(pScrn, &pPriv->linear, + extraLinear + (pPriv->doubleBuffer ? size * 2 : size), + 16); - if(!pPriv->linear || pPriv->linear->offset < (pScrn->virtualX * pScrn->virtualY)) + if (pPriv->linear.offset == 0) return BadAlloc; + pPriv->extra_offset = pPriv->linear.offset + + pPriv->doubleBuffer ? size * 2 : size; + /* fixup pointers */ #if 0 - pPriv->YBuf0offset = pScrn->fbOffset + pPriv->linear->offset * pI830->cpp; + pPriv->YBuf0offset = pScrn->fbOffset + pPriv->linear.offset; #else - pPriv->YBuf0offset = pI830->FrontBuffer.Start + pPriv->linear->offset * pI830->cpp; + pPriv->YBuf0offset = pI830->FrontBuffer.Start + pPriv->linear.offset; #endif if (pI830->rotation & (RR_Rotate_90 | RR_Rotate_270)) { pPriv->UBuf0offset = pPriv->YBuf0offset + (dstPitch * 2 * width); @@ -3236,10 +3308,7 @@ I830BlockHandler(int i, } } else { /* FREE_TIMER */ if (pPriv->freeTime < now) { - if (pPriv->linear) { - xf86FreeOffscreenLinear(pPriv->linear); - pPriv->linear = NULL; - } + I830FreeMemory(pScrn, &pPriv->linear); pPriv->videoStatus = 0; } } @@ -3251,7 +3320,7 @@ I830BlockHandler(int i, ***************************************************************************/ typedef struct { - FBLinearPtr linear; + struct linear_alloc linear; Bool isOn; } OffscreenPrivRec, *OffscreenPrivPtr; @@ -3261,8 +3330,7 @@ I830AllocateSurface(ScrnInfoPtr pScrn, unsigned short w, unsigned short h, XF86SurfacePtr surface) { - FBLinearPtr linear; - int pitch, fbpitch, size, bpp; + int pitch, fbpitch, size; OffscreenPrivPtr pPriv; I830Ptr pI830 = I830PTR(pScrn); @@ -3280,41 +3348,40 @@ I830AllocateSurface(ScrnInfoPtr pScrn, if (pI830->rotation != RR_Rotate_0) return BadAlloc; - w = (w + 1) & ~1; - pitch = ((w << 1) + 15) & ~15; - bpp = pScrn->bitsPerPixel >> 3; - fbpitch = bpp * pScrn->displayWidth; - size = ((pitch * h) + bpp - 1) / bpp; - - if (!(linear = I830AllocateMemory(pScrn, NULL, size))) + if (!(surface->pitches = xalloc(sizeof(int)))) return BadAlloc; - - surface->width = w; - surface->height = h; - - if (!(surface->pitches = xalloc(sizeof(int)))) { - xf86FreeOffscreenLinear(linear); - return BadAlloc; - } if (!(surface->offsets = xalloc(sizeof(int)))) { xfree(surface->pitches); - xf86FreeOffscreenLinear(linear); return BadAlloc; } if (!(pPriv = xalloc(sizeof(OffscreenPrivRec)))) { xfree(surface->pitches); xfree(surface->offsets); - xf86FreeOffscreenLinear(linear); return BadAlloc; } - pPriv->linear = linear; + w = (w + 1) & ~1; + pitch = ((w << 1) + 15) & ~15; + fbpitch = pI830->cpp * pScrn->displayWidth; + size = pitch * h; + + I830AllocateMemory(pScrn, &pPriv->linear, size, 16); + if (pPriv->linear.offset == 0) { + xfree(surface->pitches); + xfree(surface->offsets); + xfree(pPriv); + return BadAlloc; + } + + surface->width = w; + surface->height = h; + pPriv->isOn = FALSE; surface->pScrn = pScrn; surface->id = id; surface->pitches[0] = pitch; - surface->offsets[0] = linear->offset * bpp; + surface->offsets[0] = pPriv->linear.offset; surface->devPrivate.ptr = (pointer) pPriv; #if 0 @@ -3358,7 +3425,7 @@ I830FreeSurface(XF86SurfacePtr surface) if (pPriv->isOn) { I830StopSurface(surface); } - xf86FreeOffscreenLinear(pPriv->linear); + I830FreeMemory(surface->pScrn, &pPriv->linear); xfree(surface->pitches); xfree(surface->offsets); xfree(surface->devPrivate.ptr); diff --git a/src/i830_video.h b/src/i830_video.h index 6a09a258..12a5bda2 100644 --- a/src/i830_video.h +++ b/src/i830_video.h @@ -27,6 +27,18 @@ THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "xf86.h" #include "xf86_OSproc.h" +/* Ugly mess to support the old XF86 allocator or EXA using the same code. + */ +struct linear_alloc { +#ifdef I830_USE_XAA + FBLinearPtr xaa; +#endif +#ifdef I830_USE_EXA + ExaOffscreenArea *exa; +#endif + unsigned int offset; +}; + typedef struct { CARD32 YBuf0offset; CARD32 UBuf0offset; @@ -57,7 +69,8 @@ typedef struct { CARD32 videoStatus; Time offTime; Time freeTime; - FBLinearPtr linear; + struct linear_alloc linear; + unsigned int extra_offset; Bool overlayOK; int oneLineMode; |