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.
This commit is contained in:
Eric Anholt 2007-01-25 15:31:22 -08:00
parent 83cc4601b2
commit 5c1e27cdd2
6 changed files with 152 additions and 99 deletions

View File

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

View File

@ -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 */
}

View File

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

View File

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

View File

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

View File

@ -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);
linear->xaa = i830_xf86AllocateOffscreenLinear(pScreen, size, align,
NULL, NULL, NULL);
if (linear->xaa == NULL)
return;
}
xf86QueryLargestOffscreenLinear(pScreen, &max_size, align,
PRIORITY_EXTREME);
if (max_size < size) {
ErrorF("No memory available\n");
linear->offset = 0;
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 */