Fix crashes and other failures when a cursor allocation fails.

Now, we allocate one single block of memory for cursors, and either succeed or
fail once, rather than trying to support partial fallback modes that generally
resulted in pain due to being untested.  In particular, this fixes cursors on
FreeBSD, which only allowed one large physically-contiguous allocation.
This commit is contained in:
Eric Anholt 2007-03-15 19:13:28 -07:00
parent 316ee682d3
commit 213394fbaa
3 changed files with 65 additions and 86 deletions

View File

@ -227,8 +227,14 @@ typedef struct _I830CrtcPrivateRec {
ExaOffscreenArea *rotate_mem_exa;
#endif
i830_memory *cursor_mem;
i830_memory *cursor_mem_argb;
/* Card virtual address of the cursor */
unsigned long cursor_offset;
unsigned long cursor_argb_offset;
/* Physical or virtual addresses of the cursor for setting in the cursor
* registers.
*/
unsigned long cursor_addr;
unsigned long cursor_argb_addr;
Bool cursor_is_argb;
} I830CrtcPrivateRec, *I830CrtcPrivatePtr;
@ -276,6 +282,7 @@ typedef struct _I830Rec {
i830_memory *front_buffer;
i830_memory *front_buffer_2;
i830_memory *cursor_mem;
i830_memory *xaa_scratch;
i830_memory *xaa_scratch_2;
#ifdef I830_USE_EXA

View File

@ -75,21 +75,14 @@ I830SetPipeCursorBase (xf86CrtcPtr crtc)
I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
int pipe = intel_crtc->pipe;
I830Ptr pI830 = I830PTR(pScrn);
int cursor_base = (pipe == 0 ? CURSOR_A_BASE : CURSOR_B_BASE);
i830_memory *cursor_mem;
CARD32 value;
int cursor_base;
if (intel_crtc->cursor_is_argb)
cursor_mem = intel_crtc->cursor_mem_argb;
else
cursor_mem = intel_crtc->cursor_mem;
if (pI830->CursorNeedsPhysical)
value = cursor_mem->bus_addr;
else
value = cursor_mem->offset;
cursor_base = (pipe == 0) ? CURSOR_A_BASE : CURSOR_B_BASE;
OUTREG(cursor_base, value);
if (intel_crtc->cursor_is_argb)
OUTREG(cursor_base, intel_crtc->cursor_argb_addr);
else
OUTREG(cursor_base, intel_crtc->cursor_addr);
}
void
@ -143,11 +136,11 @@ I830CursorInit(ScreenPtr pScreen)
void
i830_crtc_load_cursor_image (xf86CrtcPtr crtc, unsigned char *src)
{
ScrnInfoPtr scrn = crtc->scrn;
I830Ptr pI830 = I830PTR(scrn);
I830Ptr pI830 = I830PTR(crtc->scrn);
I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
CARD8 *pcurs = (CARD8 *) (pI830->FbBase +
intel_crtc->cursor_mem->offset);
CARD8 *pcurs;
pcurs = pI830->FbBase + intel_crtc->cursor_offset;
intel_crtc->cursor_is_argb = FALSE;
memcpy (pcurs, src, I810_CURSOR_X * I810_CURSOR_Y / 4);
@ -157,11 +150,11 @@ i830_crtc_load_cursor_image (xf86CrtcPtr crtc, unsigned char *src)
void
i830_crtc_load_cursor_argb (xf86CrtcPtr crtc, CARD32 *image)
{
ScrnInfoPtr scrn = crtc->scrn;
I830Ptr pI830 = I830PTR(scrn);
I830Ptr pI830 = I830PTR(crtc->scrn);
I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
CARD32 *pcurs = (CARD32 *) (pI830->FbBase +
intel_crtc->cursor_mem_argb->offset);
CARD32 *pcurs;
pcurs = pI830->FbBase + intel_crtc->cursor_argb_offset;
intel_crtc->cursor_is_argb = TRUE;
memcpy (pcurs, image, I810_CURSOR_Y * I810_CURSOR_X * 4);

View File

@ -62,10 +62,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* The allocations we might do:
*
* - Ring buffer
* - HW cursor 1
* - HW cursor 2
* - HW ARGB cursor 1
* - HW ARGB cursor 2
* - HW cursor block
* - Overlay registers
* - XAA linear allocator (optional)
* - EXA 965 state buffer
@ -214,8 +211,6 @@ void
i830_reset_allocations(ScrnInfoPtr pScrn)
{
I830Ptr pI830 = I830PTR(pScrn);
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
int i;
/* While there is any memory between the start and end markers, free it. */
while (pI830->memory_list->next->next != NULL)
@ -224,13 +219,7 @@ i830_reset_allocations(ScrnInfoPtr pScrn)
/* Null out the pointers for all the allocations we just freed. This is
* kind of gross, but at least it's just one place now.
*/
for (i = 0; i < xf86_config->num_crtc; i++) {
I830CrtcPrivatePtr intel_crtc = xf86_config->crtc[i]->driver_private;
intel_crtc->cursor_mem = NULL;
intel_crtc->cursor_mem_argb = NULL;
}
pI830->cursor_mem = NULL;
pI830->front_buffer = NULL;
pI830->front_buffer_2 = NULL;
pI830->xaa_scratch = NULL;
@ -849,51 +838,51 @@ i830_allocate_framebuffer(ScrnInfoPtr pScrn, I830Ptr pI830, BoxPtr FbMemBox,
}
static Bool
i830_allocate_cursor_buffers(xf86CrtcPtr crtc)
i830_allocate_cursor_buffers(ScrnInfoPtr pScrn)
{
ScrnInfoPtr pScrn = crtc->scrn;
I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
I830Ptr pI830 = I830PTR(pScrn);
long size;
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
int flags = pI830->CursorNeedsPhysical ? NEED_PHYSICAL_ADDR : 0;
int i;
long size;
if (pI830->SWCursor)
return FALSE;
/* Mouse cursor -- The i810-i830 need a physical address in system
* memory from which to upload the cursor. We get this from
* the agpgart module using a special memory type.
/* Try to allocate one big blob for our cursor memory. This works
* around a limitation in the FreeBSD AGP driver that allows only one
* physical allocation larger than a page, and could allos us
* to pack the cursors smaller.
*/
size = xf86_config->num_crtc * (HWCURSOR_SIZE + HWCURSOR_SIZE_ARGB);
size = HWCURSOR_SIZE;
pI830->cursor_mem = i830_allocate_memory(pScrn, "HW cursors",
size, GTT_PAGE_SIZE,
flags);
if (pI830->cursor_mem != NULL) {
unsigned long cursor_offset_base = pI830->cursor_mem->offset;
unsigned long cursor_addr_base, offset = 0;
if (intel_crtc->cursor_mem == NULL) {
intel_crtc->cursor_mem = i830_allocate_memory(pScrn, "HW cursor",
size, GTT_PAGE_SIZE,
flags);
if (intel_crtc->cursor_mem == NULL) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"Failed to allocate HW cursor space.\n");
return FALSE;
if (pI830->CursorNeedsPhysical)
cursor_addr_base = pI830->cursor_mem->bus_addr;
else
cursor_addr_base = pI830->cursor_mem->offset;
/* Set up the offsets for our cursors in each CRTC. */
for (i = 0; i < xf86_config->num_crtc; i++) {
xf86CrtcPtr crtc = xf86_config->crtc[i];
I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
intel_crtc->cursor_argb_addr = cursor_addr_base + offset;
intel_crtc->cursor_argb_offset = cursor_offset_base + offset;
offset += HWCURSOR_SIZE_ARGB;
intel_crtc->cursor_addr = cursor_addr_base + offset;
intel_crtc->cursor_offset = cursor_offset_base + offset;
offset += HWCURSOR_SIZE;
}
return TRUE;
}
if (intel_crtc->cursor_mem_argb == NULL) {
/* Allocate the ARGB cursor space. Its success is optional -- we won't
* set SWCursor if it fails.
*/
intel_crtc->cursor_mem_argb = i830_allocate_memory(pScrn,
"HW ARGB cursor",
HWCURSOR_SIZE_ARGB,
GTT_PAGE_SIZE,
flags);
if (intel_crtc->cursor_mem_argb == NULL) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"Failed to allocate HW (ARGB) cursor space.\n");
}
}
return TRUE;
return FALSE;
}
/*
@ -904,10 +893,8 @@ Bool
i830_allocate_2d_memory(ScrnInfoPtr pScrn)
{
I830Ptr pI830 = I830PTR(pScrn);
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
unsigned int pitch = pScrn->displayWidth * pI830->cpp;
long size;
int i;
if (!pI830->StolenOnly &&
(!xf86AgpGARTSupported() || !xf86AcquireGART(pScrn->scrnIndex))) {
@ -923,19 +910,11 @@ i830_allocate_2d_memory(ScrnInfoPtr pScrn)
i830_allocate_ringbuffer(pScrn);
/* Next, allocate other fixed-size allocations we have. */
if (!pI830->SWCursor) {
/* Allocate cursor memory */
for (i = 0; i < xf86_config->num_crtc; i++) {
if (!i830_allocate_cursor_buffers(xf86_config->crtc[i]) &&
!pI830->SWCursor)
{
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
"Disabling HW cursor because the cursor memory "
"allocation failed.\n");
pI830->SWCursor = TRUE;
break;
}
}
if (!pI830->SWCursor && !i830_allocate_cursor_buffers(pScrn)) {
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
"Disabling HW cursor because the cursor memory "
"allocation failed.\n");
pI830->SWCursor = TRUE;
}
/* Space for the X Server's 3D context. 32k is fine for right now. */