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.
This commit is contained in:
Eric Anholt 2006-12-27 13:45:06 -08:00
parent 84915ac8af
commit 46df75ccd4
4 changed files with 334 additions and 315 deletions

View File

@ -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->useEXA) {
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);
} 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");
}
}
}

View File

@ -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 (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);
if (tileable) {
align = KB(512);
alignflags = ALIGN_BOTH_ENDS;
} else {
align = KB(64);
alignflags = 0;
}
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 {

View File

@ -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)
{
ScreenPtr pScreen;
FBLinearPtr new_linear = NULL;
struct linear_alloc *linear = area->privData;
if (linear) {
if (linear->size >= size)
return linear;
linear->exa = NULL;
linear->offset = 0;
}
#endif /* I830_USE_EXA */
if (xf86ResizeOffscreenLinear(linear, size))
return linear;
/**
* 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 = pScrn->pScreen;
I830Ptr pI830 = I830PTR(pScrn);
xf86FreeOffscreenLinear(linear);
#ifdef I830_USE_EXA
if (pI830->useEXA) {
if (linear->exa != NULL) {
if (linear->exa->size >= size)
return;
exaOffscreenFree(pScreen, linear->exa);
linear->offset = 0;
}
linear->exa = exaOffscreenAlloc(pScreen, size, align, TRUE,
I830VideoSave, linear);
if (linear->exa == NULL)
return;
linear->offset = linear->exa->offset;
}
pScreen = screenInfo.screens[pScrn->scrnIndex];
new_linear = xf86AllocateOffscreenLinear(pScreen, size, 4,
NULL, NULL, NULL);
if (!new_linear) {
#endif /* I830_USE_EXA */
#ifdef I830_USE_XAA
if (!pI830->useEXA) {
int max_size;
xf86QueryLargestOffscreenLinear(pScreen, &max_size, 4,
/* 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;
if (linear->xaa != NULL) {
if (linear->xaa->size >= size) {
linear->offset = linear->xaa->offset * pI830->cpp;
return;
}
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, 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);

View File

@ -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;