/* Initialize hardware cursor support. */
Bool R128CursorInit(ScreenPtr pScreen)
{
    ScrnInfoPtr           pScrn   = xf86Screens[pScreen->myNum];
    R128InfoPtr           info    = R128PTR(pScrn);
    xf86CursorInfoPtr     cursor;
    FBAreaPtr             fbarea;
    int                   width;
    int                   height;
    int                   size;


    if (!(cursor = info->cursor = xf86CreateCursorInfoRec())) return FALSE;

    cursor->MaxWidth          = 64;
    cursor->MaxHeight         = 64;
    cursor->Flags             = (HARDWARE_CURSOR_TRUECOLOR_AT_8BPP
				 | HARDWARE_CURSOR_SHOW_TRANSPARENT
				 | HARDWARE_CURSOR_UPDATE_UNHIDDEN
#if X_BYTE_ORDER == X_LITTLE_ENDIAN
				 | HARDWARE_CURSOR_BIT_ORDER_MSBFIRST
#endif
				 | HARDWARE_CURSOR_INVERT_MASK
				 | HARDWARE_CURSOR_AND_SOURCE_WITH_MASK
				 | HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64
				 | HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK);

    cursor->SetCursorColors   = R128SetCursorColors;
    cursor->SetCursorPosition = R128SetCursorPosition;
    cursor->LoadCursorImage   = R128LoadCursorImage;
    cursor->HideCursor        = R128HideCursor;
    cursor->ShowCursor        = R128ShowCursor;
    cursor->UseHWCursor       = R128UseHWCursor;

    size                      = (cursor->MaxWidth/4) * cursor->MaxHeight;
    width                     = pScrn->displayWidth;
    height                    = (size*2 + 1023) / pScrn->displayWidth;
    fbarea                    = xf86AllocateOffscreenArea(pScreen,
							  width,
							  height,
							  16,
							  NULL,
							  NULL,
							  NULL);

    if (!fbarea) {
	info->cursor_start    = 0;
	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
		   "Hardware cursor disabled"
		   " due to insufficient offscreen memory\n");
    } else {
	info->cursor_start    = R128_ALIGN((fbarea->box.x1
					    + width * fbarea->box.y1)
					   * info->CurrentLayout.pixel_bytes, 16);
	info->cursor_end      = info->cursor_start + size;
    }

    R128TRACE(("R128CursorInit (0x%08x-0x%08x)\n",
	       info->cursor_start, info->cursor_end));

    return xf86InitCursor(pScreen, cursor);
}
static PixmapPtr
XAACreatePixmap(ScreenPtr pScreen, int w, int h, int depth, unsigned usage_hint)
{
    XAAInfoRecPtr infoRec = GET_XAAINFORECPTR_FROM_SCREEN(pScreen);
    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
    XAAPixmapPtr pPriv;
    PixmapPtr pPix = NULL;
    int size = w * h;

    if (w > 32767 || h > 32767)
        return NullPixmap;

    if (!infoRec->offscreenDepthsInitialized)
        XAAInitializeOffscreenDepths (pScreen);

    if(pScrn->vtSema &&
            (usage_hint != CREATE_PIXMAP_USAGE_GLYPH_PICTURE) &&
            (infoRec->offscreenDepths & (1 << (depth - 1))) &&
            (size >= MIN_OFFPIX_SIZE) && !SwitchedOut &&
            (!infoRec->maxOffPixWidth || (w <= infoRec->maxOffPixWidth)) &&
            (!infoRec->maxOffPixHeight || (h <= infoRec->maxOffPixHeight)) )
    {
        PixmapLinkPtr pLink;
        PixmapPtr pScreenPix;
        FBAreaPtr area;
        int gran = 0;

        switch(pScrn->bitsPerPixel) {
        case 24:
        case 8:
            gran = 4;
            break;
        case 16:
            gran = 2;
            break;
        case 32:
            gran = 1;
            break;
        default:
            break;
        }

        if(BITMAP_SCANLINE_PAD == 64)
            gran *= 2;

        if(!(area = xf86AllocateOffscreenArea(pScreen, w, h, gran, 0,
                                              XAARemoveAreaCallback, NULL))) {
            goto BAILOUT;
        }

        if(!(pLink = malloc(sizeof(PixmapLink)))) {
            xf86FreeOffscreenArea(area);
            goto BAILOUT;
        }

        XAA_SCREEN_PROLOGUE (pScreen, CreatePixmap);
        pPix = (*pScreen->CreatePixmap) (pScreen, 0, 0, depth, usage_hint);
        XAA_SCREEN_EPILOGUE (pScreen, CreatePixmap, XAACreatePixmap);

        if (!pPix) {
            free(pLink);
            xf86FreeOffscreenArea(area);
            goto BAILOUT;
        }

        pScreenPix = (*pScreen->GetScreenPixmap)(pScreen);

        pPriv = XAA_GET_PIXMAP_PRIVATE(pPix);
        pPix->drawable.x = area->box.x1;
        pPix->drawable.y = area->box.y1;
        pPix->drawable.width = w;
        pPix->drawable.height = h;
        pPix->drawable.bitsPerPixel = pScrn->bitsPerPixel;
        pPix->devKind = pScreenPix->devKind;
        pPix->devPrivate.ptr = pScreenPix->devPrivate.ptr;
        area->devPrivate.ptr = pPix;

        pPriv->flags = OFFSCREEN;
        pPriv->offscreenArea = area;
        pPriv->freeData = FALSE;

        pLink->next = infoRec->OffscreenPixmaps;
        pLink->pPix = pPix;
        infoRec->OffscreenPixmaps = pLink;
        return pPix;
    }
BAILOUT:
    XAA_SCREEN_PROLOGUE (pScreen, CreatePixmap);
    pPix = (*pScreen->CreatePixmap) (pScreen, w, h, depth, usage_hint);
    XAA_SCREEN_EPILOGUE (pScreen, CreatePixmap, XAACreatePixmap);

    if(pPix) {
        pPriv = XAA_GET_PIXMAP_PRIVATE(pPix);
        pPriv->flags = 0;
        pPriv->offscreenArea = NULL;
        pPriv->freeData = FALSE;
        if(!w || !h) /* either scratch or shared memory */
            pPriv->flags |= SHARED_PIXMAP;
    }

    return pPix;
}