105b261ecSmrg
205b261ecSmrg#ifdef HAVE_XORG_CONFIG_H
305b261ecSmrg#include <xorg-config.h>
405b261ecSmrg#endif
505b261ecSmrg
605b261ecSmrg#include <string.h>
705b261ecSmrg
805b261ecSmrg#include "misc.h"
905b261ecSmrg#include "xf86.h"
1005b261ecSmrg#include "xf86_OSproc.h"
1105b261ecSmrg
1205b261ecSmrg#include <X11/X.h>
1305b261ecSmrg#include "scrnintstr.h"
1405b261ecSmrg#include "pixmapstr.h"
1505b261ecSmrg#include "windowstr.h"
1605b261ecSmrg#include "xf86str.h"
1705b261ecSmrg#include "cursorstr.h"
1805b261ecSmrg#include "mi.h"
1905b261ecSmrg#include "mipointer.h"
201b5d61b8Smrg#include "randrstr.h"
2105b261ecSmrg#include "xf86CursorPriv.h"
2205b261ecSmrg
2305b261ecSmrg#include "servermd.h"
2405b261ecSmrg
251b5d61b8Smrgstatic void
261b5d61b8Smrgxf86RecolorCursor_locked(xf86CursorScreenPtr ScreenPriv, CursorPtr pCurs);
271b5d61b8Smrg
2835c4bbdfSmrgstatic CARD32
2935c4bbdfSmrgxf86ReverseBitOrder(CARD32 v)
3035c4bbdfSmrg{
3135c4bbdfSmrg    return (((0x01010101 & v) << 7) | ((0x02020202 & v) << 5) |
3235c4bbdfSmrg            ((0x04040404 & v) << 3) | ((0x08080808 & v) << 1) |
3335c4bbdfSmrg            ((0x10101010 & v) >> 1) | ((0x20202020 & v) >> 3) |
3435c4bbdfSmrg            ((0x40404040 & v) >> 5) | ((0x80808080 & v) >> 7));
3535c4bbdfSmrg}
3635c4bbdfSmrg
3705b261ecSmrg#if BITMAP_SCANLINE_PAD == 64
3805b261ecSmrg
3905b261ecSmrg#if 1
4005b261ecSmrg/* Cursors might be only 32 wide. Give'em a chance */
4105b261ecSmrg#define SCANLINE CARD32
4205b261ecSmrg#define CUR_BITMAP_SCANLINE_PAD 32
4305b261ecSmrg#define CUR_LOG2_BITMAP_PAD 5
4405b261ecSmrg#define REVERSE_BIT_ORDER(w) xf86ReverseBitOrder(w)
4505b261ecSmrg#else
4605b261ecSmrg#define SCANLINE CARD64
4705b261ecSmrg#define CUR_BITMAP_SCANLINE_PAD BITMAP_SCANLINE_PAD
4805b261ecSmrg#define CUR_LOG2_BITMAP_PAD LOG2_BITMAP_PAD
4905b261ecSmrg#define REVERSE_BIT_ORDER(w) xf86CARD64ReverseBits(w)
5005b261ecSmrgstatic CARD64 xf86CARD64ReverseBits(CARD64 w);
5105b261ecSmrg
5205b261ecSmrgstatic CARD64
5305b261ecSmrgxf86CARD64ReverseBits(CARD64 w)
5405b261ecSmrg{
5535c4bbdfSmrg    unsigned char *p = (unsigned char *) &w;
5635c4bbdfSmrg
5735c4bbdfSmrg    p[0] = byte_reversed[p[0]];
5835c4bbdfSmrg    p[1] = byte_reversed[p[1]];
5935c4bbdfSmrg    p[2] = byte_reversed[p[2]];
6035c4bbdfSmrg    p[3] = byte_reversed[p[3]];
6135c4bbdfSmrg    p[4] = byte_reversed[p[4]];
6235c4bbdfSmrg    p[5] = byte_reversed[p[5]];
6335c4bbdfSmrg    p[6] = byte_reversed[p[6]];
6435c4bbdfSmrg    p[7] = byte_reversed[p[7]];
6535c4bbdfSmrg
6635c4bbdfSmrg    return w;
6705b261ecSmrg}
6805b261ecSmrg#endif
6905b261ecSmrg
7005b261ecSmrg#else
7105b261ecSmrg
7205b261ecSmrg#define SCANLINE CARD32
7305b261ecSmrg#define CUR_BITMAP_SCANLINE_PAD BITMAP_SCANLINE_PAD
7405b261ecSmrg#define CUR_LOG2_BITMAP_PAD LOG2_BITMAP_PAD
7505b261ecSmrg#define REVERSE_BIT_ORDER(w) xf86ReverseBitOrder(w)
7605b261ecSmrg
7735c4bbdfSmrg#endif                          /* BITMAP_SCANLINE_PAD == 64 */
7805b261ecSmrg
7935c4bbdfSmrgstatic unsigned char *RealizeCursorInterleave0(xf86CursorInfoPtr, CursorPtr);
8035c4bbdfSmrgstatic unsigned char *RealizeCursorInterleave1(xf86CursorInfoPtr, CursorPtr);
8135c4bbdfSmrgstatic unsigned char *RealizeCursorInterleave8(xf86CursorInfoPtr, CursorPtr);
8235c4bbdfSmrgstatic unsigned char *RealizeCursorInterleave16(xf86CursorInfoPtr, CursorPtr);
8335c4bbdfSmrgstatic unsigned char *RealizeCursorInterleave32(xf86CursorInfoPtr, CursorPtr);
8435c4bbdfSmrgstatic unsigned char *RealizeCursorInterleave64(xf86CursorInfoPtr, CursorPtr);
8505b261ecSmrg
8605b261ecSmrgBool
8705b261ecSmrgxf86InitHardwareCursor(ScreenPtr pScreen, xf86CursorInfoPtr infoPtr)
8805b261ecSmrg{
8905b261ecSmrg    if ((infoPtr->MaxWidth <= 0) || (infoPtr->MaxHeight <= 0))
9035c4bbdfSmrg        return FALSE;
9105b261ecSmrg
9205b261ecSmrg    /* These are required for now */
9305b261ecSmrg    if (!infoPtr->SetCursorPosition ||
9435c4bbdfSmrg        !xf86DriverHasLoadCursorImage(infoPtr) ||
9535c4bbdfSmrg        !infoPtr->HideCursor ||
961b5d61b8Smrg        !xf86DriverHasShowCursor(infoPtr) ||
971b5d61b8Smrg        !infoPtr->SetCursorColors)
9835c4bbdfSmrg        return FALSE;
9905b261ecSmrg
10005b261ecSmrg    if (infoPtr->RealizeCursor) {
10135c4bbdfSmrg        /* Don't overwrite a driver provided Realize Cursor function */
10235c4bbdfSmrg    }
10335c4bbdfSmrg    else if (HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1 & infoPtr->Flags) {
10435c4bbdfSmrg        infoPtr->RealizeCursor = RealizeCursorInterleave1;
10535c4bbdfSmrg    }
10635c4bbdfSmrg    else if (HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_8 & infoPtr->Flags) {
10735c4bbdfSmrg        infoPtr->RealizeCursor = RealizeCursorInterleave8;
10835c4bbdfSmrg    }
10935c4bbdfSmrg    else if (HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_16 & infoPtr->Flags) {
11035c4bbdfSmrg        infoPtr->RealizeCursor = RealizeCursorInterleave16;
11135c4bbdfSmrg    }
11235c4bbdfSmrg    else if (HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_32 & infoPtr->Flags) {
11335c4bbdfSmrg        infoPtr->RealizeCursor = RealizeCursorInterleave32;
11435c4bbdfSmrg    }
11535c4bbdfSmrg    else if (HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64 & infoPtr->Flags) {
11635c4bbdfSmrg        infoPtr->RealizeCursor = RealizeCursorInterleave64;
11735c4bbdfSmrg    }
11835c4bbdfSmrg    else {                      /* not interleaved */
11935c4bbdfSmrg        infoPtr->RealizeCursor = RealizeCursorInterleave0;
12005b261ecSmrg    }
12105b261ecSmrg
12235c4bbdfSmrg    infoPtr->pScrn = xf86ScreenToScrn(pScreen);
12305b261ecSmrg
12405b261ecSmrg    return TRUE;
12505b261ecSmrg}
12605b261ecSmrg
1271b5d61b8Smrgstatic Bool
1281b5d61b8Smrgxf86ScreenCheckHWCursor(ScreenPtr pScreen, CursorPtr cursor, xf86CursorInfoPtr infoPtr)
1291b5d61b8Smrg{
1301b5d61b8Smrg    return
1311b5d61b8Smrg        (cursor->bits->argb && infoPtr->UseHWCursorARGB &&
1321b5d61b8Smrg         infoPtr->UseHWCursorARGB(pScreen, cursor)) ||
1331b5d61b8Smrg        (cursor->bits->argb == 0 &&
1341b5d61b8Smrg         cursor->bits->height <= infoPtr->MaxHeight &&
1351b5d61b8Smrg         cursor->bits->width <= infoPtr->MaxWidth &&
1361b5d61b8Smrg         (!infoPtr->UseHWCursor || infoPtr->UseHWCursor(pScreen, cursor)));
1371b5d61b8Smrg}
1381b5d61b8Smrg
13935c4bbdfSmrgBool
1401b5d61b8Smrgxf86CheckHWCursor(ScreenPtr pScreen, CursorPtr cursor, xf86CursorInfoPtr infoPtr)
1411b5d61b8Smrg{
1421b5d61b8Smrg    ScreenPtr pSlave;
1431b5d61b8Smrg    Bool use_hw_cursor = TRUE;
1441b5d61b8Smrg
1451b5d61b8Smrg    input_lock();
1461b5d61b8Smrg
1471b5d61b8Smrg    if (!xf86ScreenCheckHWCursor(pScreen, cursor, infoPtr)) {
1481b5d61b8Smrg        use_hw_cursor = FALSE;
1491b5d61b8Smrg	goto unlock;
1501b5d61b8Smrg    }
1511b5d61b8Smrg
1521b5d61b8Smrg    /* ask each driver consuming a pixmap if it can support HW cursor */
153ed6184dfSmrg    xorg_list_for_each_entry(pSlave, &pScreen->secondary_list, secondary_head) {
1541b5d61b8Smrg        xf86CursorScreenPtr sPriv;
1551b5d61b8Smrg
1561b5d61b8Smrg        if (!RRHasScanoutPixmap(pSlave))
1571b5d61b8Smrg            continue;
1581b5d61b8Smrg
1591b5d61b8Smrg        sPriv = dixLookupPrivate(&pSlave->devPrivates, xf86CursorScreenKey);
1601b5d61b8Smrg        if (!sPriv) { /* NULL if Option "SWCursor", possibly other conditions */
1611b5d61b8Smrg            use_hw_cursor = FALSE;
1621b5d61b8Smrg	    break;
1631b5d61b8Smrg	}
1641b5d61b8Smrg
165ed6184dfSmrg        /* FALSE if HWCursor not supported by secondary */
1661b5d61b8Smrg        if (!xf86ScreenCheckHWCursor(pSlave, cursor, sPriv->CursorInfoPtr)) {
1671b5d61b8Smrg            use_hw_cursor = FALSE;
1681b5d61b8Smrg	    break;
1691b5d61b8Smrg	}
1701b5d61b8Smrg    }
1711b5d61b8Smrg
1721b5d61b8Smrgunlock:
1731b5d61b8Smrg    input_unlock();
1741b5d61b8Smrg
1751b5d61b8Smrg    return use_hw_cursor;
1761b5d61b8Smrg}
1771b5d61b8Smrg
1781b5d61b8Smrgstatic Bool
1791b5d61b8Smrgxf86ScreenSetCursor(ScreenPtr pScreen, CursorPtr pCurs, int x, int y)
18005b261ecSmrg{
18135c4bbdfSmrg    xf86CursorScreenPtr ScreenPriv =
18235c4bbdfSmrg        (xf86CursorScreenPtr) dixLookupPrivate(&pScreen->devPrivates,
18335c4bbdfSmrg                                               xf86CursorScreenKey);
1841b5d61b8Smrg
1851b5d61b8Smrg    xf86CursorInfoPtr infoPtr;
18605b261ecSmrg    unsigned char *bits;
18705b261ecSmrg
1881b5d61b8Smrg    if (!ScreenPriv) { /* NULL if Option "SWCursor" */
1891b5d61b8Smrg        return (pCurs == NullCursor);
1901b5d61b8Smrg    }
1911b5d61b8Smrg
1921b5d61b8Smrg    infoPtr = ScreenPriv->CursorInfoPtr;
1931b5d61b8Smrg
19405b261ecSmrg    if (pCurs == NullCursor) {
19535c4bbdfSmrg        (*infoPtr->HideCursor) (infoPtr->pScrn);
19635c4bbdfSmrg        return TRUE;
19705b261ecSmrg    }
19805b261ecSmrg
1991b5d61b8Smrg    /*
2001b5d61b8Smrg     * Hot plugged GPU's do not have a CursorScreenKey, force sw cursor.
2011b5d61b8Smrg     * This check can be removed once dix/privates.c gets relocation code for
2021b5d61b8Smrg     * PRIVATE_CURSOR. Also see the related comment in AddGPUScreen().
2031b5d61b8Smrg     */
2041b5d61b8Smrg    if (!_dixGetScreenPrivateKey(CursorScreenKey, pScreen))
2051b5d61b8Smrg        return FALSE;
2061b5d61b8Smrg
20735c4bbdfSmrg    bits =
20835c4bbdfSmrg        dixLookupScreenPrivate(&pCurs->devPrivates, CursorScreenKey, pScreen);
20905b261ecSmrg
2101b5d61b8Smrg    x -= infoPtr->pScrn->frameX0;
2111b5d61b8Smrg    y -= infoPtr->pScrn->frameY0;
21205b261ecSmrg
21335c4bbdfSmrg    if (!pCurs->bits->argb || !xf86DriverHasLoadCursorARGB(infoPtr))
21435c4bbdfSmrg        if (!bits) {
21535c4bbdfSmrg            bits = (*infoPtr->RealizeCursor) (infoPtr, pCurs);
21635c4bbdfSmrg            dixSetScreenPrivate(&pCurs->devPrivates, CursorScreenKey, pScreen,
21735c4bbdfSmrg                                bits);
21835c4bbdfSmrg        }
21905b261ecSmrg
22005b261ecSmrg    if (!(infoPtr->Flags & HARDWARE_CURSOR_UPDATE_UNHIDDEN))
22135c4bbdfSmrg        (*infoPtr->HideCursor) (infoPtr->pScrn);
22205b261ecSmrg
22335c4bbdfSmrg    if (pCurs->bits->argb && xf86DriverHasLoadCursorARGB(infoPtr)) {
22435c4bbdfSmrg        if (!xf86DriverLoadCursorARGB (infoPtr, pCurs))
22535c4bbdfSmrg            return FALSE;
22635c4bbdfSmrg    } else
22705b261ecSmrg    if (bits)
22835c4bbdfSmrg        if (!xf86DriverLoadCursorImage (infoPtr, bits))
22935c4bbdfSmrg            return FALSE;
23005b261ecSmrg
2311b5d61b8Smrg    xf86RecolorCursor_locked (ScreenPriv, pCurs);
23205b261ecSmrg
23335c4bbdfSmrg    (*infoPtr->SetCursorPosition) (infoPtr->pScrn, x, y);
23405b261ecSmrg
2351b5d61b8Smrg    return xf86DriverShowCursor(infoPtr);
2361b5d61b8Smrg}
2371b5d61b8Smrg
2381b5d61b8SmrgBool
2391b5d61b8Smrgxf86SetCursor(ScreenPtr pScreen, CursorPtr pCurs, int x, int y)
2401b5d61b8Smrg{
2411b5d61b8Smrg    xf86CursorScreenPtr ScreenPriv =
2421b5d61b8Smrg        (xf86CursorScreenPtr) dixLookupPrivate(&pScreen->devPrivates,
2431b5d61b8Smrg                                               xf86CursorScreenKey);
2441b5d61b8Smrg    ScreenPtr pSlave;
2451b5d61b8Smrg    Bool ret = FALSE;
2461b5d61b8Smrg
2471b5d61b8Smrg    input_lock();
2481b5d61b8Smrg
2491b5d61b8Smrg    x -= ScreenPriv->HotX;
2501b5d61b8Smrg    y -= ScreenPriv->HotY;
2511b5d61b8Smrg
2521b5d61b8Smrg    if (!xf86ScreenSetCursor(pScreen, pCurs, x, y))
2531b5d61b8Smrg        goto out;
2541b5d61b8Smrg
255ed6184dfSmrg    /* ask each secondary driver to set the cursor. */
256ed6184dfSmrg    xorg_list_for_each_entry(pSlave, &pScreen->secondary_list, secondary_head) {
2571b5d61b8Smrg        if (!RRHasScanoutPixmap(pSlave))
2581b5d61b8Smrg            continue;
2591b5d61b8Smrg
2601b5d61b8Smrg        if (!xf86ScreenSetCursor(pSlave, pCurs, x, y)) {
2611b5d61b8Smrg            /*
262ed6184dfSmrg             * hide the primary (and successfully set secondary) cursors,
2631b5d61b8Smrg             * otherwise both the hw and sw cursor will show.
2641b5d61b8Smrg             */
2651b5d61b8Smrg            xf86SetCursor(pScreen, NullCursor, x, y);
2661b5d61b8Smrg            goto out;
2671b5d61b8Smrg        }
2681b5d61b8Smrg    }
2691b5d61b8Smrg    ret = TRUE;
2701b5d61b8Smrg
2711b5d61b8Smrg out:
2721b5d61b8Smrg    input_unlock();
2731b5d61b8Smrg    return ret;
27405b261ecSmrg}
27505b261ecSmrg
27605b261ecSmrgvoid
27705b261ecSmrgxf86SetTransparentCursor(ScreenPtr pScreen)
27805b261ecSmrg{
27935c4bbdfSmrg    xf86CursorScreenPtr ScreenPriv =
28035c4bbdfSmrg        (xf86CursorScreenPtr) dixLookupPrivate(&pScreen->devPrivates,
28135c4bbdfSmrg                                               xf86CursorScreenKey);
28205b261ecSmrg    xf86CursorInfoPtr infoPtr = ScreenPriv->CursorInfoPtr;
28305b261ecSmrg
2841b5d61b8Smrg    input_lock();
2851b5d61b8Smrg
28605b261ecSmrg    if (!ScreenPriv->transparentData)
28735c4bbdfSmrg        ScreenPriv->transparentData =
28835c4bbdfSmrg            (*infoPtr->RealizeCursor) (infoPtr, NullCursor);
28905b261ecSmrg
29005b261ecSmrg    if (!(infoPtr->Flags & HARDWARE_CURSOR_UPDATE_UNHIDDEN))
29135c4bbdfSmrg        (*infoPtr->HideCursor) (infoPtr->pScrn);
29205b261ecSmrg
29305b261ecSmrg    if (ScreenPriv->transparentData)
29435c4bbdfSmrg        xf86DriverLoadCursorImage (infoPtr,
29535c4bbdfSmrg                                   ScreenPriv->transparentData);
29605b261ecSmrg
2971b5d61b8Smrg    xf86DriverShowCursor(infoPtr);
2981b5d61b8Smrg
2991b5d61b8Smrg    input_unlock();
30005b261ecSmrg}
30105b261ecSmrg
3021b5d61b8Smrgstatic void
3031b5d61b8Smrgxf86ScreenMoveCursor(ScreenPtr pScreen, int x, int y)
30405b261ecSmrg{
30535c4bbdfSmrg    xf86CursorScreenPtr ScreenPriv =
30635c4bbdfSmrg        (xf86CursorScreenPtr) dixLookupPrivate(&pScreen->devPrivates,
30735c4bbdfSmrg                                               xf86CursorScreenKey);
30805b261ecSmrg    xf86CursorInfoPtr infoPtr = ScreenPriv->CursorInfoPtr;
30905b261ecSmrg
3101b5d61b8Smrg    x -= infoPtr->pScrn->frameX0;
3111b5d61b8Smrg    y -= infoPtr->pScrn->frameY0;
31205b261ecSmrg
31335c4bbdfSmrg    (*infoPtr->SetCursorPosition) (infoPtr->pScrn, x, y);
31405b261ecSmrg}
31505b261ecSmrg
31605b261ecSmrgvoid
3171b5d61b8Smrgxf86MoveCursor(ScreenPtr pScreen, int x, int y)
31805b261ecSmrg{
31935c4bbdfSmrg    xf86CursorScreenPtr ScreenPriv =
32035c4bbdfSmrg        (xf86CursorScreenPtr) dixLookupPrivate(&pScreen->devPrivates,
32135c4bbdfSmrg                                               xf86CursorScreenKey);
3221b5d61b8Smrg    ScreenPtr pSlave;
3231b5d61b8Smrg
3241b5d61b8Smrg    input_lock();
3251b5d61b8Smrg
3261b5d61b8Smrg    x -= ScreenPriv->HotX;
3271b5d61b8Smrg    y -= ScreenPriv->HotY;
3281b5d61b8Smrg
3291b5d61b8Smrg    xf86ScreenMoveCursor(pScreen, x, y);
3301b5d61b8Smrg
331ed6184dfSmrg    /* ask each secondary driver to move the cursor */
332ed6184dfSmrg    xorg_list_for_each_entry(pSlave, &pScreen->secondary_list, secondary_head) {
3331b5d61b8Smrg        if (!RRHasScanoutPixmap(pSlave))
3341b5d61b8Smrg            continue;
3351b5d61b8Smrg
3361b5d61b8Smrg        xf86ScreenMoveCursor(pSlave, x, y);
3371b5d61b8Smrg    }
3381b5d61b8Smrg
3391b5d61b8Smrg    input_unlock();
3401b5d61b8Smrg}
3411b5d61b8Smrg
3421b5d61b8Smrgstatic void
3431b5d61b8Smrgxf86RecolorCursor_locked(xf86CursorScreenPtr ScreenPriv, CursorPtr pCurs)
3441b5d61b8Smrg{
34505b261ecSmrg    xf86CursorInfoPtr infoPtr = ScreenPriv->CursorInfoPtr;
34605b261ecSmrg
34735c4bbdfSmrg    /* recoloring isn't applicable to ARGB cursors and drivers
34805b261ecSmrg       shouldn't have to ignore SetCursorColors requests */
34905b261ecSmrg    if (pCurs->bits->argb)
35005b261ecSmrg        return;
35105b261ecSmrg
35205b261ecSmrg    if (ScreenPriv->PalettedCursor) {
35335c4bbdfSmrg        xColorItem sourceColor, maskColor;
35435c4bbdfSmrg        ColormapPtr pmap = ScreenPriv->pInstalledMap;
35535c4bbdfSmrg
35635c4bbdfSmrg        if (!pmap)
35735c4bbdfSmrg            return;
35835c4bbdfSmrg
35935c4bbdfSmrg        sourceColor.red = pCurs->foreRed;
36035c4bbdfSmrg        sourceColor.green = pCurs->foreGreen;
36135c4bbdfSmrg        sourceColor.blue = pCurs->foreBlue;
36235c4bbdfSmrg        FakeAllocColor(pmap, &sourceColor);
36335c4bbdfSmrg        maskColor.red = pCurs->backRed;
36435c4bbdfSmrg        maskColor.green = pCurs->backGreen;
36535c4bbdfSmrg        maskColor.blue = pCurs->backBlue;
36635c4bbdfSmrg        FakeAllocColor(pmap, &maskColor);
36735c4bbdfSmrg        FakeFreeColor(pmap, sourceColor.pixel);
36835c4bbdfSmrg        FakeFreeColor(pmap, maskColor.pixel);
36935c4bbdfSmrg        (*infoPtr->SetCursorColors) (infoPtr->pScrn,
37035c4bbdfSmrg                                     maskColor.pixel, sourceColor.pixel);
37135c4bbdfSmrg    }
37235c4bbdfSmrg    else {                      /* Pass colors in 8-8-8 RGB format */
37335c4bbdfSmrg        (*infoPtr->SetCursorColors) (infoPtr->pScrn,
37435c4bbdfSmrg                                     (pCurs->backBlue >> 8) |
37535c4bbdfSmrg                                     ((pCurs->backGreen >> 8) << 8) |
37635c4bbdfSmrg                                     ((pCurs->backRed >> 8) << 16),
37735c4bbdfSmrg                                     (pCurs->foreBlue >> 8) |
37835c4bbdfSmrg                                     ((pCurs->foreGreen >> 8) << 8) |
37935c4bbdfSmrg                                     ((pCurs->foreRed >> 8) << 16)
38035c4bbdfSmrg            );
38105b261ecSmrg    }
38205b261ecSmrg}
38305b261ecSmrg
3841b5d61b8Smrgvoid
3851b5d61b8Smrgxf86RecolorCursor(ScreenPtr pScreen, CursorPtr pCurs, Bool displayed)
3861b5d61b8Smrg{
3871b5d61b8Smrg    xf86CursorScreenPtr ScreenPriv =
3881b5d61b8Smrg        (xf86CursorScreenPtr) dixLookupPrivate(&pScreen->devPrivates,
3891b5d61b8Smrg                                               xf86CursorScreenKey);
3901b5d61b8Smrg
3911b5d61b8Smrg    input_lock();
3921b5d61b8Smrg    xf86RecolorCursor_locked (ScreenPriv, pCurs);
3931b5d61b8Smrg    input_unlock();
3941b5d61b8Smrg}
3951b5d61b8Smrg
39605b261ecSmrg/* These functions assume that MaxWidth is a multiple of 32 */
39735c4bbdfSmrgstatic unsigned char *
39805b261ecSmrgRealizeCursorInterleave0(xf86CursorInfoPtr infoPtr, CursorPtr pCurs)
39905b261ecSmrg{
40005b261ecSmrg
40105b261ecSmrg    SCANLINE *SrcS, *SrcM, *DstS, *DstM;
40205b261ecSmrg    SCANLINE *pSrc, *pMsk;
40305b261ecSmrg    unsigned char *mem;
40405b261ecSmrg    int size = (infoPtr->MaxWidth * infoPtr->MaxHeight) >> 2;
40505b261ecSmrg    int SrcPitch, DstPitch, Pitch, y, x;
40635c4bbdfSmrg
40705b261ecSmrg    /* how many words are in the source or mask */
40805b261ecSmrg    int words = size / (CUR_BITMAP_SCANLINE_PAD / 4);
40905b261ecSmrg
4106747b715Smrg    if (!(mem = calloc(1, size)))
41135c4bbdfSmrg        return NULL;
41205b261ecSmrg
41305b261ecSmrg    if (pCurs == NullCursor) {
41435c4bbdfSmrg        if (infoPtr->Flags & HARDWARE_CURSOR_INVERT_MASK) {
41535c4bbdfSmrg            DstM = (SCANLINE *) mem;
41635c4bbdfSmrg            if (!(infoPtr->Flags & HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK))
41735c4bbdfSmrg                DstM += words;
41835c4bbdfSmrg            memset(DstM, -1, words * sizeof(SCANLINE));
41935c4bbdfSmrg        }
42035c4bbdfSmrg        return mem;
42105b261ecSmrg    }
42205b261ecSmrg
42305b261ecSmrg    /* SrcPitch == the number of scanlines wide the cursor image is */
42405b261ecSmrg    SrcPitch = (pCurs->bits->width + (BITMAP_SCANLINE_PAD - 1)) >>
42535c4bbdfSmrg        CUR_LOG2_BITMAP_PAD;
42605b261ecSmrg
42705b261ecSmrg    /* DstPitch is the width of the hw cursor in scanlines */
42805b261ecSmrg    DstPitch = infoPtr->MaxWidth >> CUR_LOG2_BITMAP_PAD;
42905b261ecSmrg    Pitch = SrcPitch < DstPitch ? SrcPitch : DstPitch;
43005b261ecSmrg
43135c4bbdfSmrg    SrcS = (SCANLINE *) pCurs->bits->source;
43235c4bbdfSmrg    SrcM = (SCANLINE *) pCurs->bits->mask;
43335c4bbdfSmrg    DstS = (SCANLINE *) mem;
43405b261ecSmrg    DstM = DstS + words;
43505b261ecSmrg
43605b261ecSmrg    if (infoPtr->Flags & HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK) {
43735c4bbdfSmrg        SCANLINE *tmp;
43835c4bbdfSmrg
43935c4bbdfSmrg        tmp = DstS;
44035c4bbdfSmrg        DstS = DstM;
44135c4bbdfSmrg        DstM = tmp;
44205b261ecSmrg    }
44305b261ecSmrg
44405b261ecSmrg    if (infoPtr->Flags & HARDWARE_CURSOR_AND_SOURCE_WITH_MASK) {
44535c4bbdfSmrg        for (y = pCurs->bits->height, pSrc = DstS, pMsk = DstM;
44635c4bbdfSmrg             y--;
44735c4bbdfSmrg             pSrc += DstPitch, pMsk += DstPitch, SrcS += SrcPitch, SrcM +=
44835c4bbdfSmrg             SrcPitch) {
44935c4bbdfSmrg            for (x = 0; x < Pitch; x++) {
45035c4bbdfSmrg                pSrc[x] = SrcS[x] & SrcM[x];
45135c4bbdfSmrg                pMsk[x] = SrcM[x];
45235c4bbdfSmrg            }
45335c4bbdfSmrg        }
45435c4bbdfSmrg    }
45535c4bbdfSmrg    else {
45635c4bbdfSmrg        for (y = pCurs->bits->height, pSrc = DstS, pMsk = DstM;
45735c4bbdfSmrg             y--;
45835c4bbdfSmrg             pSrc += DstPitch, pMsk += DstPitch, SrcS += SrcPitch, SrcM +=
45935c4bbdfSmrg             SrcPitch) {
46035c4bbdfSmrg            for (x = 0; x < Pitch; x++) {
46135c4bbdfSmrg                pSrc[x] = SrcS[x];
46235c4bbdfSmrg                pMsk[x] = SrcM[x];
46335c4bbdfSmrg            }
46435c4bbdfSmrg        }
46505b261ecSmrg    }
46605b261ecSmrg
46705b261ecSmrg    if (infoPtr->Flags & HARDWARE_CURSOR_NIBBLE_SWAPPED) {
46835c4bbdfSmrg        int count = size;
46935c4bbdfSmrg        unsigned char *pntr1 = (unsigned char *) DstS;
47035c4bbdfSmrg        unsigned char *pntr2 = (unsigned char *) DstM;
47135c4bbdfSmrg        unsigned char a, b;
47235c4bbdfSmrg
47335c4bbdfSmrg        while (count) {
47435c4bbdfSmrg
47535c4bbdfSmrg            a = *pntr1;
47635c4bbdfSmrg            b = *pntr2;
47735c4bbdfSmrg            *pntr1 = ((a & 0xF0) >> 4) | ((a & 0x0F) << 4);
47835c4bbdfSmrg            *pntr2 = ((b & 0xF0) >> 4) | ((b & 0x0F) << 4);
47935c4bbdfSmrg            pntr1++;
48035c4bbdfSmrg            pntr2++;
48135c4bbdfSmrg            count -= 2;
48235c4bbdfSmrg        }
48305b261ecSmrg    }
48405b261ecSmrg
48505b261ecSmrg    /*
48605b261ecSmrg     * Must be _after_ HARDWARE_CURSOR_AND_SOURCE_WITH_MASK to avoid wiping
48705b261ecSmrg     * out entire source mask.
48805b261ecSmrg     */
48905b261ecSmrg    if (infoPtr->Flags & HARDWARE_CURSOR_INVERT_MASK) {
49035c4bbdfSmrg        int count = words;
49135c4bbdfSmrg        SCANLINE *pntr = DstM;
49235c4bbdfSmrg
49335c4bbdfSmrg        while (count--) {
49435c4bbdfSmrg            *pntr = ~(*pntr);
49535c4bbdfSmrg            pntr++;
49635c4bbdfSmrg        }
49705b261ecSmrg    }
49805b261ecSmrg
49905b261ecSmrg    if (infoPtr->Flags & HARDWARE_CURSOR_BIT_ORDER_MSBFIRST) {
50035c4bbdfSmrg        for (y = pCurs->bits->height, pSrc = DstS, pMsk = DstM;
50135c4bbdfSmrg             y--; pSrc += DstPitch, pMsk += DstPitch) {
50235c4bbdfSmrg            for (x = 0; x < Pitch; x++) {
50335c4bbdfSmrg                pSrc[x] = REVERSE_BIT_ORDER(pSrc[x]);
50435c4bbdfSmrg                pMsk[x] = REVERSE_BIT_ORDER(pMsk[x]);
50535c4bbdfSmrg            }
50635c4bbdfSmrg        }
50705b261ecSmrg    }
50805b261ecSmrg
50905b261ecSmrg    return mem;
51005b261ecSmrg}
51105b261ecSmrg
51235c4bbdfSmrgstatic unsigned char *
51305b261ecSmrgRealizeCursorInterleave1(xf86CursorInfoPtr infoPtr, CursorPtr pCurs)
51405b261ecSmrg{
51505b261ecSmrg    unsigned char *DstS, *DstM;
51605b261ecSmrg    unsigned char *pntr;
51705b261ecSmrg    unsigned char *mem, *mem2;
51805b261ecSmrg    int count;
51905b261ecSmrg    int size = (infoPtr->MaxWidth * infoPtr->MaxHeight) >> 2;
52005b261ecSmrg
52105b261ecSmrg    /* Realize the cursor without interleaving */
52205b261ecSmrg    if (!(mem2 = RealizeCursorInterleave0(infoPtr, pCurs)))
52335c4bbdfSmrg        return NULL;
52405b261ecSmrg
5256747b715Smrg    if (!(mem = calloc(1, size))) {
52635c4bbdfSmrg        free(mem2);
52735c4bbdfSmrg        return NULL;
52805b261ecSmrg    }
52905b261ecSmrg
53035c4bbdfSmrg    /* 1 bit interleave */
53105b261ecSmrg    DstS = mem2;
53205b261ecSmrg    DstM = DstS + (size >> 1);
53305b261ecSmrg    pntr = mem;
53405b261ecSmrg    count = size;
53505b261ecSmrg    while (count) {
53635c4bbdfSmrg        *pntr++ = ((*DstS & 0x01)) | ((*DstM & 0x01) << 1) |
53735c4bbdfSmrg            ((*DstS & 0x02) << 1) | ((*DstM & 0x02) << 2) |
53835c4bbdfSmrg            ((*DstS & 0x04) << 2) | ((*DstM & 0x04) << 3) |
53935c4bbdfSmrg            ((*DstS & 0x08) << 3) | ((*DstM & 0x08) << 4);
54035c4bbdfSmrg        *pntr++ = ((*DstS & 0x10) >> 4) | ((*DstM & 0x10) >> 3) |
54135c4bbdfSmrg            ((*DstS & 0x20) >> 3) | ((*DstM & 0x20) >> 2) |
54235c4bbdfSmrg            ((*DstS & 0x40) >> 2) | ((*DstM & 0x40) >> 1) |
54335c4bbdfSmrg            ((*DstS & 0x80) >> 1) | ((*DstM & 0x80));
54435c4bbdfSmrg        DstS++;
54535c4bbdfSmrg        DstM++;
54635c4bbdfSmrg        count -= 2;
54705b261ecSmrg    }
54805b261ecSmrg
54905b261ecSmrg    /* Free the uninterleaved cursor */
5506747b715Smrg    free(mem2);
55105b261ecSmrg
55205b261ecSmrg    return mem;
55305b261ecSmrg}
55405b261ecSmrg
55535c4bbdfSmrgstatic unsigned char *
55605b261ecSmrgRealizeCursorInterleave8(xf86CursorInfoPtr infoPtr, CursorPtr pCurs)
55705b261ecSmrg{
55805b261ecSmrg    unsigned char *DstS, *DstM;
55905b261ecSmrg    unsigned char *pntr;
56005b261ecSmrg    unsigned char *mem, *mem2;
56105b261ecSmrg    int count;
56205b261ecSmrg    int size = (infoPtr->MaxWidth * infoPtr->MaxHeight) >> 2;
56305b261ecSmrg
56405b261ecSmrg    /* Realize the cursor without interleaving */
56505b261ecSmrg    if (!(mem2 = RealizeCursorInterleave0(infoPtr, pCurs)))
56635c4bbdfSmrg        return NULL;
56705b261ecSmrg
5686747b715Smrg    if (!(mem = calloc(1, size))) {
56935c4bbdfSmrg        free(mem2);
57035c4bbdfSmrg        return NULL;
57105b261ecSmrg    }
57205b261ecSmrg
57305b261ecSmrg    /* 8 bit interleave */
57405b261ecSmrg    DstS = mem2;
57505b261ecSmrg    DstM = DstS + (size >> 1);
57605b261ecSmrg    pntr = mem;
57705b261ecSmrg    count = size;
57805b261ecSmrg    while (count) {
57935c4bbdfSmrg        *pntr++ = *DstS++;
58035c4bbdfSmrg        *pntr++ = *DstM++;
58135c4bbdfSmrg        count -= 2;
58205b261ecSmrg    }
58305b261ecSmrg
58405b261ecSmrg    /* Free the uninterleaved cursor */
5856747b715Smrg    free(mem2);
58605b261ecSmrg
58705b261ecSmrg    return mem;
58805b261ecSmrg}
58905b261ecSmrg
59035c4bbdfSmrgstatic unsigned char *
59105b261ecSmrgRealizeCursorInterleave16(xf86CursorInfoPtr infoPtr, CursorPtr pCurs)
59205b261ecSmrg{
59305b261ecSmrg    unsigned short *DstS, *DstM;
59405b261ecSmrg    unsigned short *pntr;
59505b261ecSmrg    unsigned char *mem, *mem2;
59605b261ecSmrg    int count;
59705b261ecSmrg    int size = (infoPtr->MaxWidth * infoPtr->MaxHeight) >> 2;
59805b261ecSmrg
59905b261ecSmrg    /* Realize the cursor without interleaving */
60005b261ecSmrg    if (!(mem2 = RealizeCursorInterleave0(infoPtr, pCurs)))
60135c4bbdfSmrg        return NULL;
60205b261ecSmrg
6036747b715Smrg    if (!(mem = calloc(1, size))) {
60435c4bbdfSmrg        free(mem2);
60535c4bbdfSmrg        return NULL;
60605b261ecSmrg    }
60705b261ecSmrg
60805b261ecSmrg    /* 16 bit interleave */
60935c4bbdfSmrg    DstS = (void *) mem2;
61005b261ecSmrg    DstM = DstS + (size >> 2);
61135c4bbdfSmrg    pntr = (void *) mem;
61205b261ecSmrg    count = (size >> 1);
61305b261ecSmrg    while (count) {
61435c4bbdfSmrg        *pntr++ = *DstS++;
61535c4bbdfSmrg        *pntr++ = *DstM++;
61635c4bbdfSmrg        count -= 2;
61705b261ecSmrg    }
61805b261ecSmrg
61905b261ecSmrg    /* Free the uninterleaved cursor */
6206747b715Smrg    free(mem2);
62105b261ecSmrg
62205b261ecSmrg    return mem;
62305b261ecSmrg}
62405b261ecSmrg
62535c4bbdfSmrgstatic unsigned char *
62605b261ecSmrgRealizeCursorInterleave32(xf86CursorInfoPtr infoPtr, CursorPtr pCurs)
62705b261ecSmrg{
62805b261ecSmrg    CARD32 *DstS, *DstM;
62905b261ecSmrg    CARD32 *pntr;
63005b261ecSmrg    unsigned char *mem, *mem2;
63105b261ecSmrg    int count;
63205b261ecSmrg    int size = (infoPtr->MaxWidth * infoPtr->MaxHeight) >> 2;
63305b261ecSmrg
63405b261ecSmrg    /* Realize the cursor without interleaving */
63505b261ecSmrg    if (!(mem2 = RealizeCursorInterleave0(infoPtr, pCurs)))
63635c4bbdfSmrg        return NULL;
63705b261ecSmrg
6386747b715Smrg    if (!(mem = calloc(1, size))) {
63935c4bbdfSmrg        free(mem2);
64035c4bbdfSmrg        return NULL;
64105b261ecSmrg    }
64205b261ecSmrg
64305b261ecSmrg    /* 32 bit interleave */
64435c4bbdfSmrg    DstS = (void *) mem2;
64505b261ecSmrg    DstM = DstS + (size >> 3);
64635c4bbdfSmrg    pntr = (void *) mem;
64705b261ecSmrg    count = (size >> 2);
64805b261ecSmrg    while (count) {
64935c4bbdfSmrg        *pntr++ = *DstS++;
65035c4bbdfSmrg        *pntr++ = *DstM++;
65135c4bbdfSmrg        count -= 2;
65205b261ecSmrg    }
65305b261ecSmrg
65405b261ecSmrg    /* Free the uninterleaved cursor */
6556747b715Smrg    free(mem2);
65605b261ecSmrg
65705b261ecSmrg    return mem;
65805b261ecSmrg}
65905b261ecSmrg
66035c4bbdfSmrgstatic unsigned char *
66105b261ecSmrgRealizeCursorInterleave64(xf86CursorInfoPtr infoPtr, CursorPtr pCurs)
66205b261ecSmrg{
66305b261ecSmrg    CARD32 *DstS, *DstM;
66405b261ecSmrg    CARD32 *pntr;
66505b261ecSmrg    unsigned char *mem, *mem2;
66605b261ecSmrg    int count;
66705b261ecSmrg    int size = (infoPtr->MaxWidth * infoPtr->MaxHeight) >> 2;
66805b261ecSmrg
66905b261ecSmrg    /* Realize the cursor without interleaving */
67005b261ecSmrg    if (!(mem2 = RealizeCursorInterleave0(infoPtr, pCurs)))
67135c4bbdfSmrg        return NULL;
67205b261ecSmrg
6736747b715Smrg    if (!(mem = calloc(1, size))) {
67435c4bbdfSmrg        free(mem2);
67535c4bbdfSmrg        return NULL;
67605b261ecSmrg    }
67705b261ecSmrg
67805b261ecSmrg    /* 64 bit interleave */
67935c4bbdfSmrg    DstS = (void *) mem2;
68005b261ecSmrg    DstM = DstS + (size >> 3);
68135c4bbdfSmrg    pntr = (void *) mem;
68205b261ecSmrg    count = (size >> 2);
68305b261ecSmrg    while (count) {
68435c4bbdfSmrg        *pntr++ = *DstS++;
68535c4bbdfSmrg        *pntr++ = *DstS++;
68635c4bbdfSmrg        *pntr++ = *DstM++;
68735c4bbdfSmrg        *pntr++ = *DstM++;
68835c4bbdfSmrg        count -= 4;
68905b261ecSmrg    }
69005b261ecSmrg
69105b261ecSmrg    /* Free the uninterleaved cursor */
6926747b715Smrg    free(mem2);
69305b261ecSmrg
69405b261ecSmrg    return mem;
69505b261ecSmrg}
696