xf86HWCurs.c revision 1b5d61b8
11.51Smsaitoh
21.1Sjdolecek#ifdef HAVE_XORG_CONFIG_H
31.1Sjdolecek#include <xorg-config.h>
41.1Sjdolecek#endif
51.40Smartin
61.1Sjdolecek#include <string.h>
71.1Sjdolecek
81.1Sjdolecek#include "misc.h"
91.1Sjdolecek#include "xf86.h"
101.1Sjdolecek#include "xf86_OSproc.h"
111.1Sjdolecek
121.1Sjdolecek#include <X11/X.h>
131.1Sjdolecek#include "scrnintstr.h"
141.1Sjdolecek#include "pixmapstr.h"
151.1Sjdolecek#include "windowstr.h"
161.1Sjdolecek#include "xf86str.h"
171.1Sjdolecek#include "cursorstr.h"
181.1Sjdolecek#include "mi.h"
191.40Smartin#include "mipointer.h"
201.40Smartin#include "randrstr.h"
211.40Smartin#include "xf86CursorPriv.h"
221.40Smartin
231.40Smartin#include "servermd.h"
241.40Smartin
251.40Smartinstatic void
261.40Smartinxf86RecolorCursor_locked(xf86CursorScreenPtr ScreenPriv, CursorPtr pCurs);
271.40Smartin
281.40Smartinstatic CARD32
291.40Smartinxf86ReverseBitOrder(CARD32 v)
301.1Sjdolecek{
311.1Sjdolecek    return (((0x01010101 & v) << 7) | ((0x02020202 & v) << 5) |
321.1Sjdolecek            ((0x04040404 & v) << 3) | ((0x08080808 & v) << 1) |
331.1Sjdolecek            ((0x10101010 & v) >> 1) | ((0x20202020 & v) >> 3) |
341.1Sjdolecek            ((0x40404040 & v) >> 5) | ((0x80808080 & v) >> 7));
351.1Sjdolecek}
361.1Sjdolecek
371.1Sjdolecek#if BITMAP_SCANLINE_PAD == 64
381.1Sjdolecek
391.1Sjdolecek#if 1
401.1Sjdolecek/* Cursors might be only 32 wide. Give'em a chance */
411.11Sjdolecek#define SCANLINE CARD32
421.11Sjdolecek#define CUR_BITMAP_SCANLINE_PAD 32
431.1Sjdolecek#define CUR_LOG2_BITMAP_PAD 5
441.1Sjdolecek#define REVERSE_BIT_ORDER(w) xf86ReverseBitOrder(w)
451.1Sjdolecek#else
461.1Sjdolecek#define SCANLINE CARD64
471.10Slukem#define CUR_BITMAP_SCANLINE_PAD BITMAP_SCANLINE_PAD
481.10Slukem#define CUR_LOG2_BITMAP_PAD LOG2_BITMAP_PAD
491.51Smsaitoh#define REVERSE_BIT_ORDER(w) xf86CARD64ReverseBits(w)
501.1Sjdolecekstatic CARD64 xf86CARD64ReverseBits(CARD64 w);
511.1Sjdolecek
521.1Sjdolecekstatic CARD64
531.26Syamtxf86CARD64ReverseBits(CARD64 w)
541.26Syamt{
551.1Sjdolecek    unsigned char *p = (unsigned char *) &w;
561.1Sjdolecek
571.1Sjdolecek    p[0] = byte_reversed[p[0]];
581.1Sjdolecek    p[1] = byte_reversed[p[1]];
591.1Sjdolecek    p[2] = byte_reversed[p[2]];
601.1Sjdolecek    p[3] = byte_reversed[p[3]];
611.1Sjdolecek    p[4] = byte_reversed[p[4]];
621.1Sjdolecek    p[5] = byte_reversed[p[5]];
631.1Sjdolecek    p[6] = byte_reversed[p[6]];
641.1Sjdolecek    p[7] = byte_reversed[p[7]];
651.11Sjdolecek
661.50Sriastrad    return w;
671.1Sjdolecek}
681.38Sad#endif
691.38Sad
701.1Sjdolecek#else
711.1Sjdolecek
721.1Sjdolecek#define SCANLINE CARD32
731.1Sjdolecek#define CUR_BITMAP_SCANLINE_PAD BITMAP_SCANLINE_PAD
741.1Sjdolecek#define CUR_LOG2_BITMAP_PAD LOG2_BITMAP_PAD
751.1Sjdolecek#define REVERSE_BIT_ORDER(w) xf86ReverseBitOrder(w)
761.1Sjdolecek
771.1Sjdolecek#endif                          /* BITMAP_SCANLINE_PAD == 64 */
781.1Sjdolecek
791.25Sdrochnerstatic unsigned char *RealizeCursorInterleave0(xf86CursorInfoPtr, CursorPtr);
801.25Sdrochnerstatic unsigned char *RealizeCursorInterleave1(xf86CursorInfoPtr, CursorPtr);
811.9Sjdolecekstatic unsigned char *RealizeCursorInterleave8(xf86CursorInfoPtr, CursorPtr);
821.11Sjdolecekstatic unsigned char *RealizeCursorInterleave16(xf86CursorInfoPtr, CursorPtr);
831.9Sjdolecekstatic unsigned char *RealizeCursorInterleave32(xf86CursorInfoPtr, CursorPtr);
841.1Sjdolecekstatic unsigned char *RealizeCursorInterleave64(xf86CursorInfoPtr, CursorPtr);
851.47Schs
861.1SjdolecekBool
871.1Sjdolecekxf86InitHardwareCursor(ScreenPtr pScreen, xf86CursorInfoPtr infoPtr)
881.1Sjdolecek{
891.1Sjdolecek    if ((infoPtr->MaxWidth <= 0) || (infoPtr->MaxHeight <= 0))
901.11Sjdolecek        return FALSE;
911.1Sjdolecek
921.11Sjdolecek    /* These are required for now */
931.1Sjdolecek    if (!infoPtr->SetCursorPosition ||
941.1Sjdolecek        !xf86DriverHasLoadCursorImage(infoPtr) ||
951.1Sjdolecek        !infoPtr->HideCursor ||
961.1Sjdolecek        !xf86DriverHasShowCursor(infoPtr) ||
971.1Sjdolecek        !infoPtr->SetCursorColors)
981.11Sjdolecek        return FALSE;
991.9Sjdolecek
1001.1Sjdolecek    if (infoPtr->RealizeCursor) {
1011.11Sjdolecek        /* Don't overwrite a driver provided Realize Cursor function */
1021.11Sjdolecek    }
1031.11Sjdolecek    else if (HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1 & infoPtr->Flags) {
1041.11Sjdolecek        infoPtr->RealizeCursor = RealizeCursorInterleave1;
1051.16Sjdolecek    }
1061.16Sjdolecek    else if (HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_8 & infoPtr->Flags) {
1071.16Sjdolecek        infoPtr->RealizeCursor = RealizeCursorInterleave8;
1081.16Sjdolecek    }
1091.11Sjdolecek    else if (HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_16 & infoPtr->Flags) {
1101.16Sjdolecek        infoPtr->RealizeCursor = RealizeCursorInterleave16;
1111.16Sjdolecek    }
1121.16Sjdolecek    else if (HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_32 & infoPtr->Flags) {
1131.1Sjdolecek        infoPtr->RealizeCursor = RealizeCursorInterleave32;
1141.1Sjdolecek    }
1151.44Scegger    else if (HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64 & infoPtr->Flags) {
1161.44Scegger        infoPtr->RealizeCursor = RealizeCursorInterleave64;
1171.1Sjdolecek    }
1181.47Schs    else {                      /* not interleaved */
1191.20Sthorpej        infoPtr->RealizeCursor = RealizeCursorInterleave0;
1201.1Sjdolecek    }
1211.27Sperry
1221.27Sperry    infoPtr->pScrn = xf86ScreenToScrn(pScreen);
1231.27Sperry
1241.27Sperry    return TRUE;
1251.27Sperry}
1261.27Sperry
1271.1Sjdolecekstatic Bool
1281.1Sjdolecekxf86ScreenCheckHWCursor(ScreenPtr pScreen, CursorPtr cursor, xf86CursorInfoPtr infoPtr)
1291.47Schs{
1301.1Sjdolecek    return
1311.1Sjdolecek        (cursor->bits->argb && infoPtr->UseHWCursorARGB &&
1321.1Sjdolecek         infoPtr->UseHWCursorARGB(pScreen, cursor)) ||
1331.1Sjdolecek        (cursor->bits->argb == 0 &&
1341.1Sjdolecek         cursor->bits->height <= infoPtr->MaxHeight &&
1351.1Sjdolecek         cursor->bits->width <= infoPtr->MaxWidth &&
1361.1Sjdolecek         (!infoPtr->UseHWCursor || infoPtr->UseHWCursor(pScreen, cursor)));
1371.1Sjdolecek}
1381.1Sjdolecek
1391.1SjdolecekBool
1401.1Sjdolecekxf86CheckHWCursor(ScreenPtr pScreen, CursorPtr cursor, xf86CursorInfoPtr infoPtr)
1411.1Sjdolecek{
1421.1Sjdolecek    ScreenPtr pSlave;
1431.44Scegger    Bool use_hw_cursor = TRUE;
1441.1Sjdolecek
1451.33Sthorpej    input_lock();
1461.1Sjdolecek
1471.11Sjdolecek    if (!xf86ScreenCheckHWCursor(pScreen, cursor, infoPtr)) {
1481.1Sjdolecek        use_hw_cursor = FALSE;
1491.1Sjdolecek	goto unlock;
1501.1Sjdolecek    }
1511.11Sjdolecek
1521.29Sdrochner    /* ask each driver consuming a pixmap if it can support HW cursor */
1531.1Sjdolecek    xorg_list_for_each_entry(pSlave, &pScreen->slave_list, slave_head) {
1541.47Schs        xf86CursorScreenPtr sPriv;
1551.47Schs
1561.1Sjdolecek        if (!RRHasScanoutPixmap(pSlave))
1571.1Sjdolecek            continue;
1581.1Sjdolecek
1591.1Sjdolecek        sPriv = dixLookupPrivate(&pSlave->devPrivates, xf86CursorScreenKey);
1601.1Sjdolecek        if (!sPriv) { /* NULL if Option "SWCursor", possibly other conditions */
1611.1Sjdolecek            use_hw_cursor = FALSE;
1621.28Sperry	    break;
1631.1Sjdolecek	}
1641.1Sjdolecek
1651.23Swiz        /* FALSE if HWCursor not supported by slave */
1661.1Sjdolecek        if (!xf86ScreenCheckHWCursor(pSlave, cursor, sPriv->CursorInfoPtr)) {
1671.1Sjdolecek            use_hw_cursor = FALSE;
1681.1Sjdolecek	    break;
1691.1Sjdolecek	}
1701.1Sjdolecek    }
1711.1Sjdolecek
1721.28Sperryunlock:
1731.1Sjdolecek    input_unlock();
1741.1Sjdolecek
1751.1Sjdolecek    return use_hw_cursor;
1761.1Sjdolecek}
1771.1Sjdolecek
1781.1Sjdolecekstatic Bool
1791.28Sperryxf86ScreenSetCursor(ScreenPtr pScreen, CursorPtr pCurs, int x, int y)
1801.1Sjdolecek{
1811.1Sjdolecek    xf86CursorScreenPtr ScreenPriv =
1821.1Sjdolecek        (xf86CursorScreenPtr) dixLookupPrivate(&pScreen->devPrivates,
1831.1Sjdolecek                                               xf86CursorScreenKey);
1841.1Sjdolecek
1851.1Sjdolecek    xf86CursorInfoPtr infoPtr;
1861.1Sjdolecek    unsigned char *bits;
1871.1Sjdolecek
1881.1Sjdolecek    if (!ScreenPriv) { /* NULL if Option "SWCursor" */
1891.1Sjdolecek        return (pCurs == NullCursor);
1901.1Sjdolecek    }
1911.1Sjdolecek
1921.1Sjdolecek    infoPtr = ScreenPriv->CursorInfoPtr;
1931.1Sjdolecek
1941.1Sjdolecek    if (pCurs == NullCursor) {
1951.22Schristos        (*infoPtr->HideCursor) (infoPtr->pScrn);
1961.22Schristos        return TRUE;
1971.1Sjdolecek    }
1981.28Sperry
1991.1Sjdolecek    /*
2001.1Sjdolecek     * Hot plugged GPU's do not have a CursorScreenKey, force sw cursor.
2011.1Sjdolecek     * This check can be removed once dix/privates.c gets relocation code for
2021.1Sjdolecek     * PRIVATE_CURSOR. Also see the related comment in AddGPUScreen().
2031.7Sjdolecek     */
2041.7Sjdolecek    if (!_dixGetScreenPrivateKey(CursorScreenKey, pScreen))
2051.6Sjdolecek        return FALSE;
2061.1Sjdolecek
2071.1Sjdolecek    bits =
2081.1Sjdolecek        dixLookupScreenPrivate(&pCurs->devPrivates, CursorScreenKey, pScreen);
2091.23Swiz
2101.1Sjdolecek    x -= infoPtr->pScrn->frameX0;
2111.1Sjdolecek    y -= infoPtr->pScrn->frameY0;
2121.51Smsaitoh
2131.51Smsaitoh    if (!pCurs->bits->argb || !xf86DriverHasLoadCursorARGB(infoPtr))
2141.1Sjdolecek        if (!bits) {
2151.1Sjdolecek            bits = (*infoPtr->RealizeCursor) (infoPtr, pCurs);
2161.1Sjdolecek            dixSetScreenPrivate(&pCurs->devPrivates, CursorScreenKey, pScreen,
2171.1Sjdolecek                                bits);
2181.7Sjdolecek        }
2191.47Schs
2201.1Sjdolecek    if (!(infoPtr->Flags & HARDWARE_CURSOR_UPDATE_UNHIDDEN))
2211.1Sjdolecek        (*infoPtr->HideCursor) (infoPtr->pScrn);
2221.7Sjdolecek
2231.7Sjdolecek    if (pCurs->bits->argb && xf86DriverHasLoadCursorARGB(infoPtr)) {
2241.1Sjdolecek        if (!xf86DriverLoadCursorARGB (infoPtr, pCurs))
2251.1Sjdolecek            return FALSE;
2261.1Sjdolecek    } else
2271.1Sjdolecek    if (bits)
2281.1Sjdolecek        if (!xf86DriverLoadCursorImage (infoPtr, bits))
2291.1Sjdolecek            return FALSE;
2301.1Sjdolecek
2311.1Sjdolecek    xf86RecolorCursor_locked (ScreenPriv, pCurs);
2321.1Sjdolecek
2331.1Sjdolecek    (*infoPtr->SetCursorPosition) (infoPtr->pScrn, x, y);
2341.1Sjdolecek
2351.1Sjdolecek    return xf86DriverShowCursor(infoPtr);
2361.47Schs}
2371.1Sjdolecek
2381.1SjdolecekBool
2391.1Sjdolecekxf86SetCursor(ScreenPtr pScreen, CursorPtr pCurs, int x, int y)
2401.11Sjdolecek{
2411.11Sjdolecek    xf86CursorScreenPtr ScreenPriv =
2421.51Smsaitoh        (xf86CursorScreenPtr) dixLookupPrivate(&pScreen->devPrivates,
2431.51Smsaitoh                                               xf86CursorScreenKey);
2441.1Sjdolecek    ScreenPtr pSlave;
2451.1Sjdolecek    Bool ret = FALSE;
2461.1Sjdolecek
2471.11Sjdolecek    input_lock();
2481.1Sjdolecek
2491.11Sjdolecek    x -= ScreenPriv->HotX;
2501.14Sjdolecek    y -= ScreenPriv->HotY;
2511.12Sjdolecek
2521.51Smsaitoh    if (!xf86ScreenSetCursor(pScreen, pCurs, x, y))
2531.51Smsaitoh        goto out;
2541.1Sjdolecek
2551.1Sjdolecek    /* ask each slave driver to set the cursor. */
2561.1Sjdolecek    xorg_list_for_each_entry(pSlave, &pScreen->slave_list, slave_head) {
2571.1Sjdolecek        if (!RRHasScanoutPixmap(pSlave))
2581.1Sjdolecek            continue;
2591.1Sjdolecek
2601.1Sjdolecek        if (!xf86ScreenSetCursor(pSlave, pCurs, x, y)) {
2611.1Sjdolecek            /*
2621.11Sjdolecek             * hide the master (and successfully set slave) cursors,
2631.1Sjdolecek             * otherwise both the hw and sw cursor will show.
2641.11Sjdolecek             */
2651.1Sjdolecek            xf86SetCursor(pScreen, NullCursor, x, y);
2661.9Sjdolecek            goto out;
2671.9Sjdolecek        }
2681.9Sjdolecek    }
2691.9Sjdolecek    ret = TRUE;
2701.1Sjdolecek
2711.1Sjdolecek out:
2721.1Sjdolecek    input_unlock();
2731.1Sjdolecek    return ret;
2741.1Sjdolecek}
2751.47Schs
2761.1Sjdolecekvoid
2771.1Sjdolecekxf86SetTransparentCursor(ScreenPtr pScreen)
2781.1Sjdolecek{
2791.1Sjdolecek    xf86CursorScreenPtr ScreenPriv =
2801.1Sjdolecek        (xf86CursorScreenPtr) dixLookupPrivate(&pScreen->devPrivates,
2811.1Sjdolecek                                               xf86CursorScreenKey);
2821.25Sdrochner    xf86CursorInfoPtr infoPtr = ScreenPriv->CursorInfoPtr;
2831.9Sjdolecek
2841.16Sjdolecek    input_lock();
2851.9Sjdolecek
2861.9Sjdolecek    if (!ScreenPriv->transparentData)
2871.9Sjdolecek        ScreenPriv->transparentData =
2881.25Sdrochner            (*infoPtr->RealizeCursor) (infoPtr, NullCursor);
2891.9Sjdolecek
2901.9Sjdolecek    if (!(infoPtr->Flags & HARDWARE_CURSOR_UPDATE_UNHIDDEN))
2911.9Sjdolecek        (*infoPtr->HideCursor) (infoPtr->pScrn);
2921.9Sjdolecek
2931.9Sjdolecek    if (ScreenPriv->transparentData)
2941.1Sjdolecek        xf86DriverLoadCursorImage (infoPtr,
2951.11Sjdolecek                                   ScreenPriv->transparentData);
2961.1Sjdolecek
2971.1Sjdolecek    xf86DriverShowCursor(infoPtr);
2981.1Sjdolecek
2991.25Sdrochner    input_unlock();
3001.11Sjdolecek}
3011.29Sdrochner
3021.47Schsstatic void
3031.47Schsxf86ScreenMoveCursor(ScreenPtr pScreen, int x, int y)
3041.47Schs{
3051.47Schs    xf86CursorScreenPtr ScreenPriv =
3061.11Sjdolecek        (xf86CursorScreenPtr) dixLookupPrivate(&pScreen->devPrivates,
3071.11Sjdolecek                                               xf86CursorScreenKey);
3081.11Sjdolecek    xf86CursorInfoPtr infoPtr = ScreenPriv->CursorInfoPtr;
3091.11Sjdolecek
3101.11Sjdolecek    x -= infoPtr->pScrn->frameX0;
3111.1Sjdolecek    y -= infoPtr->pScrn->frameY0;
3121.1Sjdolecek
3131.1Sjdolecek    (*infoPtr->SetCursorPosition) (infoPtr->pScrn, x, y);
3141.1Sjdolecek}
3151.1Sjdolecek
3161.9Sjdolecekvoid
3171.9Sjdolecekxf86MoveCursor(ScreenPtr pScreen, int x, int y)
3181.9Sjdolecek{
3191.9Sjdolecek    xf86CursorScreenPtr ScreenPriv =
3201.25Sdrochner        (xf86CursorScreenPtr) dixLookupPrivate(&pScreen->devPrivates,
3211.11Sjdolecek                                               xf86CursorScreenKey);
3221.9Sjdolecek    ScreenPtr pSlave;
3231.9Sjdolecek
3241.11Sjdolecek    input_lock();
3251.11Sjdolecek
3261.9Sjdolecek    x -= ScreenPriv->HotX;
3271.47Schs    y -= ScreenPriv->HotY;
3281.9Sjdolecek
3291.11Sjdolecek    xf86ScreenMoveCursor(pScreen, x, y);
3301.9Sjdolecek
3311.11Sjdolecek    /* ask each slave driver to move the cursor */
3321.11Sjdolecek    xorg_list_for_each_entry(pSlave, &pScreen->slave_list, slave_head) {
3331.11Sjdolecek        if (!RRHasScanoutPixmap(pSlave))
3341.11Sjdolecek            continue;
3351.48Schristos
3361.36Sad        xf86ScreenMoveCursor(pSlave, x, y);
3371.47Schs    }
3381.51Smsaitoh
3391.51Smsaitoh    input_unlock();
3401.36Sad}
3411.36Sad
3421.1Sjdolecekstatic void
3431.1Sjdolecekxf86RecolorCursor_locked(xf86CursorScreenPtr ScreenPriv, CursorPtr pCurs)
3441.1Sjdolecek{
3451.34Schristos    xf86CursorInfoPtr infoPtr = ScreenPriv->CursorInfoPtr;
3461.1Sjdolecek
3471.11Sjdolecek    /* recoloring isn't applicable to ARGB cursors and drivers
3481.1Sjdolecek       shouldn't have to ignore SetCursorColors requests */
3491.1Sjdolecek    if (pCurs->bits->argb)
3501.1Sjdolecek        return;
3511.34Schristos
3521.1Sjdolecek    if (ScreenPriv->PalettedCursor) {
3531.1Sjdolecek        xColorItem sourceColor, maskColor;
3541.1Sjdolecek        ColormapPtr pmap = ScreenPriv->pInstalledMap;
3551.1Sjdolecek
3561.51Smsaitoh        if (!pmap)
3571.1Sjdolecek            return;
3581.1Sjdolecek
3591.1Sjdolecek        sourceColor.red = pCurs->foreRed;
3601.1Sjdolecek        sourceColor.green = pCurs->foreGreen;
3611.1Sjdolecek        sourceColor.blue = pCurs->foreBlue;
3621.1Sjdolecek        FakeAllocColor(pmap, &sourceColor);
3631.1Sjdolecek        maskColor.red = pCurs->backRed;
3641.1Sjdolecek        maskColor.green = pCurs->backGreen;
3651.1Sjdolecek        maskColor.blue = pCurs->backBlue;
3661.1Sjdolecek        FakeAllocColor(pmap, &maskColor);
3671.1Sjdolecek        FakeFreeColor(pmap, sourceColor.pixel);
3681.1Sjdolecek        FakeFreeColor(pmap, maskColor.pixel);
3691.1Sjdolecek        (*infoPtr->SetCursorColors) (infoPtr->pScrn,
3701.1Sjdolecek                                     maskColor.pixel, sourceColor.pixel);
3711.1Sjdolecek    }
3721.16Sjdolecek    else {                      /* Pass colors in 8-8-8 RGB format */
3731.1Sjdolecek        (*infoPtr->SetCursorColors) (infoPtr->pScrn,
3741.47Schs                                     (pCurs->backBlue >> 8) |
3751.1Sjdolecek                                     ((pCurs->backGreen >> 8) << 8) |
3761.1Sjdolecek                                     ((pCurs->backRed >> 8) << 16),
3771.1Sjdolecek                                     (pCurs->foreBlue >> 8) |
3781.1Sjdolecek                                     ((pCurs->foreGreen >> 8) << 8) |
3791.1Sjdolecek                                     ((pCurs->foreRed >> 8) << 16)
3801.1Sjdolecek            );
3811.1Sjdolecek    }
3821.1Sjdolecek}
3831.1Sjdolecek
3841.1Sjdolecekvoid
3851.1Sjdolecekxf86RecolorCursor(ScreenPtr pScreen, CursorPtr pCurs, Bool displayed)
3861.1Sjdolecek{
3871.1Sjdolecek    xf86CursorScreenPtr ScreenPriv =
3881.1Sjdolecek        (xf86CursorScreenPtr) dixLookupPrivate(&pScreen->devPrivates,
3891.9Sjdolecek                                               xf86CursorScreenKey);
3901.1Sjdolecek
3911.1Sjdolecek    input_lock();
3921.1Sjdolecek    xf86RecolorCursor_locked (ScreenPriv, pCurs);
3931.1Sjdolecek    input_unlock();
3941.1Sjdolecek}
3951.9Sjdolecek
3961.13Ssommerfe/* These functions assume that MaxWidth is a multiple of 32 */
3971.9Sjdolecekstatic unsigned char *
3981.47SchsRealizeCursorInterleave0(xf86CursorInfoPtr infoPtr, CursorPtr pCurs)
3991.13Ssommerfe{
4001.9Sjdolecek
4011.1Sjdolecek    SCANLINE *SrcS, *SrcM, *DstS, *DstM;
4021.1Sjdolecek    SCANLINE *pSrc, *pMsk;
4031.1Sjdolecek    unsigned char *mem;
4041.1Sjdolecek    int size = (infoPtr->MaxWidth * infoPtr->MaxHeight) >> 2;
4051.1Sjdolecek    int SrcPitch, DstPitch, Pitch, y, x;
4061.16Sjdolecek
4071.1Sjdolecek    /* how many words are in the source or mask */
4081.1Sjdolecek    int words = size / (CUR_BITMAP_SCANLINE_PAD / 4);
4091.1Sjdolecek
4101.16Sjdolecek    if (!(mem = calloc(1, size)))
4111.1Sjdolecek        return NULL;
4121.16Sjdolecek
4131.1Sjdolecek    if (pCurs == NullCursor) {
4141.1Sjdolecek        if (infoPtr->Flags & HARDWARE_CURSOR_INVERT_MASK) {
4151.16Sjdolecek            DstM = (SCANLINE *) mem;
4161.16Sjdolecek            if (!(infoPtr->Flags & HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK))
4171.16Sjdolecek                DstM += words;
4181.16Sjdolecek            memset(DstM, -1, words * sizeof(SCANLINE));
4191.16Sjdolecek        }
4201.1Sjdolecek        return mem;
4211.1Sjdolecek    }
4221.1Sjdolecek
4231.1Sjdolecek    /* SrcPitch == the number of scanlines wide the cursor image is */
4241.1Sjdolecek    SrcPitch = (pCurs->bits->width + (BITMAP_SCANLINE_PAD - 1)) >>
4251.11Sjdolecek        CUR_LOG2_BITMAP_PAD;
4261.11Sjdolecek
4271.1Sjdolecek    /* DstPitch is the width of the hw cursor in scanlines */
4281.11Sjdolecek    DstPitch = infoPtr->MaxWidth >> CUR_LOG2_BITMAP_PAD;
4291.11Sjdolecek    Pitch = SrcPitch < DstPitch ? SrcPitch : DstPitch;
4301.1Sjdolecek
4311.16Sjdolecek    SrcS = (SCANLINE *) pCurs->bits->source;
4321.1Sjdolecek    SrcM = (SCANLINE *) pCurs->bits->mask;
4331.1Sjdolecek    DstS = (SCANLINE *) mem;
4341.1Sjdolecek    DstM = DstS + words;
4351.1Sjdolecek
4361.11Sjdolecek    if (infoPtr->Flags & HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK) {
4371.11Sjdolecek        SCANLINE *tmp;
4381.11Sjdolecek
4391.11Sjdolecek        tmp = DstS;
4401.11Sjdolecek        DstS = DstM;
4411.16Sjdolecek        DstM = tmp;
4421.11Sjdolecek    }
4431.11Sjdolecek
4441.11Sjdolecek    if (infoPtr->Flags & HARDWARE_CURSOR_AND_SOURCE_WITH_MASK) {
4451.16Sjdolecek        for (y = pCurs->bits->height, pSrc = DstS, pMsk = DstM;
4461.1Sjdolecek             y--;
4471.16Sjdolecek             pSrc += DstPitch, pMsk += DstPitch, SrcS += SrcPitch, SrcM +=
4481.1Sjdolecek             SrcPitch) {
4491.1Sjdolecek            for (x = 0; x < Pitch; x++) {
4501.1Sjdolecek                pSrc[x] = SrcS[x] & SrcM[x];
4511.1Sjdolecek                pMsk[x] = SrcM[x];
4521.16Sjdolecek            }
4531.16Sjdolecek        }
4541.16Sjdolecek    }
4551.16Sjdolecek    else {
4561.28Sperry        for (y = pCurs->bits->height, pSrc = DstS, pMsk = DstM;
4571.16Sjdolecek             y--;
4581.16Sjdolecek             pSrc += DstPitch, pMsk += DstPitch, SrcS += SrcPitch, SrcM +=
4591.16Sjdolecek             SrcPitch) {
4601.47Schs            for (x = 0; x < Pitch; x++) {
4611.16Sjdolecek                pSrc[x] = SrcS[x];
4621.16Sjdolecek                pMsk[x] = SrcM[x];
4631.16Sjdolecek            }
4641.16Sjdolecek        }
4651.1Sjdolecek    }
4661.1Sjdolecek
4671.16Sjdolecek    if (infoPtr->Flags & HARDWARE_CURSOR_NIBBLE_SWAPPED) {
4681.1Sjdolecek        int count = size;
4691.16Sjdolecek        unsigned char *pntr1 = (unsigned char *) DstS;
4701.1Sjdolecek        unsigned char *pntr2 = (unsigned char *) DstM;
4711.1Sjdolecek        unsigned char a, b;
4721.28Sperry
4731.1Sjdolecek        while (count) {
4741.1Sjdolecek
4751.1Sjdolecek            a = *pntr1;
4761.1Sjdolecek            b = *pntr2;
4771.1Sjdolecek            *pntr1 = ((a & 0xF0) >> 4) | ((a & 0x0F) << 4);
4781.1Sjdolecek            *pntr2 = ((b & 0xF0) >> 4) | ((b & 0x0F) << 4);
4791.1Sjdolecek            pntr1++;
4801.1Sjdolecek            pntr2++;
4811.1Sjdolecek            count -= 2;
4821.1Sjdolecek        }
4831.16Sjdolecek    }
4841.16Sjdolecek
4851.16Sjdolecek    /*
4861.45Srmind     * Must be _after_ HARDWARE_CURSOR_AND_SOURCE_WITH_MASK to avoid wiping
4871.1Sjdolecek     * out entire source mask.
4881.1Sjdolecek     */
4891.1Sjdolecek    if (infoPtr->Flags & HARDWARE_CURSOR_INVERT_MASK) {
4901.1Sjdolecek        int count = words;
4911.1Sjdolecek        SCANLINE *pntr = DstM;
4921.1Sjdolecek
4931.1Sjdolecek        while (count--) {
4941.1Sjdolecek            *pntr = ~(*pntr);
4951.28Sperry            pntr++;
4961.1Sjdolecek        }
4971.34Schristos    }
4981.1Sjdolecek
4991.1Sjdolecek    if (infoPtr->Flags & HARDWARE_CURSOR_BIT_ORDER_MSBFIRST) {
5001.1Sjdolecek        for (y = pCurs->bits->height, pSrc = DstS, pMsk = DstM;
5011.1Sjdolecek             y--; pSrc += DstPitch, pMsk += DstPitch) {
5021.1Sjdolecek            for (x = 0; x < Pitch; x++) {
5031.1Sjdolecek                pSrc[x] = REVERSE_BIT_ORDER(pSrc[x]);
5041.9Sjdolecek                pMsk[x] = REVERSE_BIT_ORDER(pMsk[x]);
5051.9Sjdolecek            }
5061.9Sjdolecek        }
5071.9Sjdolecek    }
5081.1Sjdolecek
5091.16Sjdolecek    return mem;
5101.16Sjdolecek}
5111.16Sjdolecek
5121.16Sjdolecekstatic unsigned char *
5131.47SchsRealizeCursorInterleave1(xf86CursorInfoPtr infoPtr, CursorPtr pCurs)
5141.16Sjdolecek{
5151.16Sjdolecek    unsigned char *DstS, *DstM;
5161.9Sjdolecek    unsigned char *pntr;
5171.1Sjdolecek    unsigned char *mem, *mem2;
5181.16Sjdolecek    int count;
5191.1Sjdolecek    int size = (infoPtr->MaxWidth * infoPtr->MaxHeight) >> 2;
5201.1Sjdolecek
5211.1Sjdolecek    /* Realize the cursor without interleaving */
5221.9Sjdolecek    if (!(mem2 = RealizeCursorInterleave0(infoPtr, pCurs)))
5231.51Smsaitoh        return NULL;
5241.51Smsaitoh
5251.51Smsaitoh    if (!(mem = calloc(1, size))) {
5261.16Sjdolecek        free(mem2);
5271.1Sjdolecek        return NULL;
5281.1Sjdolecek    }
5291.1Sjdolecek
5301.1Sjdolecek    /* 1 bit interleave */
5311.1Sjdolecek    DstS = mem2;
5321.28Sperry    DstM = DstS + (size >> 1);
5331.16Sjdolecek    pntr = mem;
5341.1Sjdolecek    count = size;
5351.1Sjdolecek    while (count) {
5361.1Sjdolecek        *pntr++ = ((*DstS & 0x01)) | ((*DstM & 0x01) << 1) |
5371.1Sjdolecek            ((*DstS & 0x02) << 1) | ((*DstM & 0x02) << 2) |
5381.1Sjdolecek            ((*DstS & 0x04) << 2) | ((*DstM & 0x04) << 3) |
5391.1Sjdolecek            ((*DstS & 0x08) << 3) | ((*DstM & 0x08) << 4);
5401.1Sjdolecek        *pntr++ = ((*DstS & 0x10) >> 4) | ((*DstM & 0x10) >> 3) |
5411.1Sjdolecek            ((*DstS & 0x20) >> 3) | ((*DstM & 0x20) >> 2) |
5421.1Sjdolecek            ((*DstS & 0x40) >> 2) | ((*DstM & 0x40) >> 1) |
5431.1Sjdolecek            ((*DstS & 0x80) >> 1) | ((*DstM & 0x80));
5441.1Sjdolecek        DstS++;
5451.1Sjdolecek        DstM++;
5461.1Sjdolecek        count -= 2;
5471.1Sjdolecek    }
5481.16Sjdolecek
5491.34Schristos    /* Free the uninterleaved cursor */
5501.1Sjdolecek    free(mem2);
5511.16Sjdolecek
5521.1Sjdolecek    return mem;
5531.11Sjdolecek}
5541.16Sjdolecek
5551.11Sjdolecekstatic unsigned char *
5561.11SjdolecekRealizeCursorInterleave8(xf86CursorInfoPtr infoPtr, CursorPtr pCurs)
5571.11Sjdolecek{
5581.11Sjdolecek    unsigned char *DstS, *DstM;
5591.16Sjdolecek    unsigned char *pntr;
5601.16Sjdolecek    unsigned char *mem, *mem2;
5611.16Sjdolecek    int count;
5621.16Sjdolecek    int size = (infoPtr->MaxWidth * infoPtr->MaxHeight) >> 2;
5631.11Sjdolecek
5641.11Sjdolecek    /* Realize the cursor without interleaving */
5651.16Sjdolecek    if (!(mem2 = RealizeCursorInterleave0(infoPtr, pCurs)))
5661.16Sjdolecek        return NULL;
5671.16Sjdolecek
5681.16Sjdolecek    if (!(mem = calloc(1, size))) {
5691.16Sjdolecek        free(mem2);
5701.1Sjdolecek        return NULL;
5711.1Sjdolecek    }
5721.28Sperry
5731.16Sjdolecek    /* 8 bit interleave */
5741.16Sjdolecek    DstS = mem2;
5751.16Sjdolecek    DstM = DstS + (size >> 1);
5761.1Sjdolecek    pntr = mem;
5771.34Schristos    count = size;
5781.34Schristos    while (count) {
5791.1Sjdolecek        *pntr++ = *DstS++;
5801.9Sjdolecek        *pntr++ = *DstM++;
5811.1Sjdolecek        count -= 2;
5821.1Sjdolecek    }
5831.16Sjdolecek
5841.1Sjdolecek    /* Free the uninterleaved cursor */
5851.1Sjdolecek    free(mem2);
5861.1Sjdolecek
5871.1Sjdolecek    return mem;
5881.1Sjdolecek}
5891.1Sjdolecek
5901.1Sjdolecekstatic unsigned char *
5911.1SjdolecekRealizeCursorInterleave16(xf86CursorInfoPtr infoPtr, CursorPtr pCurs)
5921.1Sjdolecek{
5931.28Sperry    unsigned short *DstS, *DstM;
5941.1Sjdolecek    unsigned short *pntr;
5951.1Sjdolecek    unsigned char *mem, *mem2;
5961.1Sjdolecek    int count;
5971.1Sjdolecek    int size = (infoPtr->MaxWidth * infoPtr->MaxHeight) >> 2;
5981.1Sjdolecek
5991.1Sjdolecek    /* Realize the cursor without interleaving */
6001.1Sjdolecek    if (!(mem2 = RealizeCursorInterleave0(infoPtr, pCurs)))
6011.1Sjdolecek        return NULL;
6021.1Sjdolecek
6031.1Sjdolecek    if (!(mem = calloc(1, size))) {
6041.1Sjdolecek        free(mem2);
6051.1Sjdolecek        return NULL;
6061.28Sperry    }
6071.1Sjdolecek
6081.1Sjdolecek    /* 16 bit interleave */
6091.1Sjdolecek    DstS = (void *) mem2;
6101.11Sjdolecek    DstM = DstS + (size >> 2);
6111.16Sjdolecek    pntr = (void *) mem;
6121.1Sjdolecek    count = (size >> 1);
6131.1Sjdolecek    while (count) {
6141.1Sjdolecek        *pntr++ = *DstS++;
6151.1Sjdolecek        *pntr++ = *DstM++;
6161.28Sperry        count -= 2;
6171.16Sjdolecek    }
6181.9Sjdolecek
6191.11Sjdolecek    /* Free the uninterleaved cursor */
6201.16Sjdolecek    free(mem2);
6211.9Sjdolecek
6221.16Sjdolecek    return mem;
6231.1Sjdolecek}
6241.16Sjdolecek
6251.16Sjdolecekstatic unsigned char *
6261.16SjdolecekRealizeCursorInterleave32(xf86CursorInfoPtr infoPtr, CursorPtr pCurs)
6271.51Smsaitoh{
6281.51Smsaitoh    CARD32 *DstS, *DstM;
6291.16Sjdolecek    CARD32 *pntr;
6301.11Sjdolecek    unsigned char *mem, *mem2;
6311.1Sjdolecek    int count;
6321.1Sjdolecek    int size = (infoPtr->MaxWidth * infoPtr->MaxHeight) >> 2;
6331.1Sjdolecek
6341.16Sjdolecek    /* Realize the cursor without interleaving */
6351.1Sjdolecek    if (!(mem2 = RealizeCursorInterleave0(infoPtr, pCurs)))
6361.16Sjdolecek        return NULL;
6371.1Sjdolecek
6381.1Sjdolecek    if (!(mem = calloc(1, size))) {
6391.11Sjdolecek        free(mem2);
6401.1Sjdolecek        return NULL;
6411.1Sjdolecek    }
6421.1Sjdolecek
6431.1Sjdolecek    /* 32 bit interleave */
6441.1Sjdolecek    DstS = (void *) mem2;
6451.1Sjdolecek    DstM = DstS + (size >> 3);
6461.1Sjdolecek    pntr = (void *) mem;
6471.1Sjdolecek    count = (size >> 2);
6481.1Sjdolecek    while (count) {
6491.1Sjdolecek        *pntr++ = *DstS++;
6501.1Sjdolecek        *pntr++ = *DstM++;
6511.1Sjdolecek        count -= 2;
6521.1Sjdolecek    }
6531.1Sjdolecek
6541.1Sjdolecek    /* Free the uninterleaved cursor */
6551.1Sjdolecek    free(mem2);
6561.1Sjdolecek
6571.1Sjdolecek    return mem;
6581.1Sjdolecek}
6591.1Sjdolecek
6601.1Sjdolecekstatic unsigned char *
6611.1SjdolecekRealizeCursorInterleave64(xf86CursorInfoPtr infoPtr, CursorPtr pCurs)
6621.1Sjdolecek{
6631.1Sjdolecek    CARD32 *DstS, *DstM;
6641.1Sjdolecek    CARD32 *pntr;
6651.1Sjdolecek    unsigned char *mem, *mem2;
6661.1Sjdolecek    int count;
6671.1Sjdolecek    int size = (infoPtr->MaxWidth * infoPtr->MaxHeight) >> 2;
6681.1Sjdolecek
6691.1Sjdolecek    /* Realize the cursor without interleaving */
6701.1Sjdolecek    if (!(mem2 = RealizeCursorInterleave0(infoPtr, pCurs)))
6711.1Sjdolecek        return NULL;
6721.1Sjdolecek
6731.1Sjdolecek    if (!(mem = calloc(1, size))) {
6741.1Sjdolecek        free(mem2);
6751.1Sjdolecek        return NULL;
6761.1Sjdolecek    }
6771.1Sjdolecek
6781.1Sjdolecek    /* 64 bit interleave */
6791.1Sjdolecek    DstS = (void *) mem2;
6801.1Sjdolecek    DstM = DstS + (size >> 3);
6811.1Sjdolecek    pntr = (void *) mem;
6821.1Sjdolecek    count = (size >> 2);
6831.1Sjdolecek    while (count) {
6841.1Sjdolecek        *pntr++ = *DstS++;
6851.1Sjdolecek        *pntr++ = *DstS++;
6861.1Sjdolecek        *pntr++ = *DstM++;
6871.1Sjdolecek        *pntr++ = *DstM++;
6881.1Sjdolecek        count -= 4;
6891.1Sjdolecek    }
6901.1Sjdolecek
6911.1Sjdolecek    /* Free the uninterleaved cursor */
6921.1Sjdolecek    free(mem2);
6931.1Sjdolecek
6941.1Sjdolecek    return mem;
6951.1Sjdolecek}
6961.1Sjdolecek