summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/i830_driver.c34
-rw-r--r--src/i830_memory.c397
-rw-r--r--src/i830_video.c199
-rw-r--r--src/i830_video.h15
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;