summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Anholt <eric@anholt.net>2007-01-25 15:31:22 -0800
committerEric Anholt <eric@anholt.net>2007-01-25 15:31:22 -0800
commit5c1e27cdd243dc24dd2bfdeb46d757bbef6ba6af (patch)
tree7f5fe9402e38f5f902c6336a3819cb690ce70a73
parent83cc4601b27d871484a2408f31154e9387064b9e (diff)
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.
-rw-r--r--src/i830.h16
-rw-r--r--src/i830_display.c78
-rw-r--r--src/i830_driver.c18
-rw-r--r--src/i830_exa.c13
-rw-r--r--src/i830_memory.c104
-rw-r--r--src/i830_video.c22
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 */