1
2#ifdef HAVE_XORG_CONFIG_H
3#include <xorg-config.h>
4#endif
5
6#include <string.h>
7
8#include "misc.h"
9#include "xf86.h"
10#include "xf86_OSproc.h"
11
12#include <X11/X.h>
13#include "scrnintstr.h"
14#include "pixmapstr.h"
15#include "windowstr.h"
16#include "xf86str.h"
17#include "cursorstr.h"
18#include "mi.h"
19#include "mipointer.h"
20#include "randrstr.h"
21#include "xf86CursorPriv.h"
22
23#include "servermd.h"
24
25static void
26xf86RecolorCursor_locked(xf86CursorScreenPtr ScreenPriv, CursorPtr pCurs);
27
28static CARD32
29xf86ReverseBitOrder(CARD32 v)
30{
31    return (((0x01010101 & v) << 7) | ((0x02020202 & v) << 5) |
32            ((0x04040404 & v) << 3) | ((0x08080808 & v) << 1) |
33            ((0x10101010 & v) >> 1) | ((0x20202020 & v) >> 3) |
34            ((0x40404040 & v) >> 5) | ((0x80808080 & v) >> 7));
35}
36
37#if BITMAP_SCANLINE_PAD == 64
38
39#if 1
40/* Cursors might be only 32 wide. Give'em a chance */
41#define SCANLINE CARD32
42#define CUR_BITMAP_SCANLINE_PAD 32
43#define CUR_LOG2_BITMAP_PAD 5
44#define REVERSE_BIT_ORDER(w) xf86ReverseBitOrder(w)
45#else
46#define SCANLINE CARD64
47#define CUR_BITMAP_SCANLINE_PAD BITMAP_SCANLINE_PAD
48#define CUR_LOG2_BITMAP_PAD LOG2_BITMAP_PAD
49#define REVERSE_BIT_ORDER(w) xf86CARD64ReverseBits(w)
50static CARD64 xf86CARD64ReverseBits(CARD64 w);
51
52static CARD64
53xf86CARD64ReverseBits(CARD64 w)
54{
55    unsigned char *p = (unsigned char *) &w;
56
57    p[0] = byte_reversed[p[0]];
58    p[1] = byte_reversed[p[1]];
59    p[2] = byte_reversed[p[2]];
60    p[3] = byte_reversed[p[3]];
61    p[4] = byte_reversed[p[4]];
62    p[5] = byte_reversed[p[5]];
63    p[6] = byte_reversed[p[6]];
64    p[7] = byte_reversed[p[7]];
65
66    return w;
67}
68#endif
69
70#else
71
72#define SCANLINE CARD32
73#define CUR_BITMAP_SCANLINE_PAD BITMAP_SCANLINE_PAD
74#define CUR_LOG2_BITMAP_PAD LOG2_BITMAP_PAD
75#define REVERSE_BIT_ORDER(w) xf86ReverseBitOrder(w)
76
77#endif                          /* BITMAP_SCANLINE_PAD == 64 */
78
79static unsigned char *RealizeCursorInterleave0(xf86CursorInfoPtr, CursorPtr);
80static unsigned char *RealizeCursorInterleave1(xf86CursorInfoPtr, CursorPtr);
81static unsigned char *RealizeCursorInterleave8(xf86CursorInfoPtr, CursorPtr);
82static unsigned char *RealizeCursorInterleave16(xf86CursorInfoPtr, CursorPtr);
83static unsigned char *RealizeCursorInterleave32(xf86CursorInfoPtr, CursorPtr);
84static unsigned char *RealizeCursorInterleave64(xf86CursorInfoPtr, CursorPtr);
85
86Bool
87xf86InitHardwareCursor(ScreenPtr pScreen, xf86CursorInfoPtr infoPtr)
88{
89    if ((infoPtr->MaxWidth <= 0) || (infoPtr->MaxHeight <= 0))
90        return FALSE;
91
92    /* These are required for now */
93    if (!infoPtr->SetCursorPosition ||
94        !xf86DriverHasLoadCursorImage(infoPtr) ||
95        !infoPtr->HideCursor ||
96        !xf86DriverHasShowCursor(infoPtr) ||
97        !infoPtr->SetCursorColors)
98        return FALSE;
99
100    if (infoPtr->RealizeCursor) {
101        /* Don't overwrite a driver provided Realize Cursor function */
102    }
103    else if (HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1 & infoPtr->Flags) {
104        infoPtr->RealizeCursor = RealizeCursorInterleave1;
105    }
106    else if (HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_8 & infoPtr->Flags) {
107        infoPtr->RealizeCursor = RealizeCursorInterleave8;
108    }
109    else if (HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_16 & infoPtr->Flags) {
110        infoPtr->RealizeCursor = RealizeCursorInterleave16;
111    }
112    else if (HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_32 & infoPtr->Flags) {
113        infoPtr->RealizeCursor = RealizeCursorInterleave32;
114    }
115    else if (HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64 & infoPtr->Flags) {
116        infoPtr->RealizeCursor = RealizeCursorInterleave64;
117    }
118    else {                      /* not interleaved */
119        infoPtr->RealizeCursor = RealizeCursorInterleave0;
120    }
121
122    infoPtr->pScrn = xf86ScreenToScrn(pScreen);
123
124    return TRUE;
125}
126
127static Bool
128xf86ScreenCheckHWCursor(ScreenPtr pScreen, CursorPtr cursor, xf86CursorInfoPtr infoPtr)
129{
130    return
131        (cursor->bits->argb && infoPtr->UseHWCursorARGB &&
132         infoPtr->UseHWCursorARGB(pScreen, cursor)) ||
133        (cursor->bits->argb == 0 &&
134         cursor->bits->height <= infoPtr->MaxHeight &&
135         cursor->bits->width <= infoPtr->MaxWidth &&
136         (!infoPtr->UseHWCursor || infoPtr->UseHWCursor(pScreen, cursor)));
137}
138
139Bool
140xf86CheckHWCursor(ScreenPtr pScreen, CursorPtr cursor, xf86CursorInfoPtr infoPtr)
141{
142    ScreenPtr pSlave;
143    Bool use_hw_cursor = TRUE;
144
145    input_lock();
146
147    if (!xf86ScreenCheckHWCursor(pScreen, cursor, infoPtr)) {
148        use_hw_cursor = FALSE;
149	goto unlock;
150    }
151
152    /* ask each driver consuming a pixmap if it can support HW cursor */
153    xorg_list_for_each_entry(pSlave, &pScreen->secondary_list, secondary_head) {
154        xf86CursorScreenPtr sPriv;
155
156        if (!RRHasScanoutPixmap(pSlave))
157            continue;
158
159        sPriv = dixLookupPrivate(&pSlave->devPrivates, xf86CursorScreenKey);
160        if (!sPriv) { /* NULL if Option "SWCursor", possibly other conditions */
161            use_hw_cursor = FALSE;
162	    break;
163	}
164
165        /* FALSE if HWCursor not supported by secondary */
166        if (!xf86ScreenCheckHWCursor(pSlave, cursor, sPriv->CursorInfoPtr)) {
167            use_hw_cursor = FALSE;
168	    break;
169	}
170    }
171
172unlock:
173    input_unlock();
174
175    return use_hw_cursor;
176}
177
178static Bool
179xf86ScreenSetCursor(ScreenPtr pScreen, CursorPtr pCurs, int x, int y)
180{
181    xf86CursorScreenPtr ScreenPriv =
182        (xf86CursorScreenPtr) dixLookupPrivate(&pScreen->devPrivates,
183                                               xf86CursorScreenKey);
184
185    xf86CursorInfoPtr infoPtr;
186    unsigned char *bits;
187
188    if (!ScreenPriv) { /* NULL if Option "SWCursor" */
189        return (pCurs == NullCursor);
190    }
191
192    infoPtr = ScreenPriv->CursorInfoPtr;
193
194    if (pCurs == NullCursor) {
195        (*infoPtr->HideCursor) (infoPtr->pScrn);
196        return TRUE;
197    }
198
199    /*
200     * Hot plugged GPU's do not have a CursorScreenKey, force sw cursor.
201     * This check can be removed once dix/privates.c gets relocation code for
202     * PRIVATE_CURSOR. Also see the related comment in AddGPUScreen().
203     */
204    if (!_dixGetScreenPrivateKey(CursorScreenKey, pScreen))
205        return FALSE;
206
207    bits =
208        dixLookupScreenPrivate(&pCurs->devPrivates, CursorScreenKey, pScreen);
209
210    x -= infoPtr->pScrn->frameX0;
211    y -= infoPtr->pScrn->frameY0;
212
213    if (!pCurs->bits->argb || !xf86DriverHasLoadCursorARGB(infoPtr))
214        if (!bits) {
215            bits = (*infoPtr->RealizeCursor) (infoPtr, pCurs);
216            dixSetScreenPrivate(&pCurs->devPrivates, CursorScreenKey, pScreen,
217                                bits);
218        }
219
220    if (!(infoPtr->Flags & HARDWARE_CURSOR_UPDATE_UNHIDDEN))
221        (*infoPtr->HideCursor) (infoPtr->pScrn);
222
223    if (pCurs->bits->argb && xf86DriverHasLoadCursorARGB(infoPtr)) {
224        if (!xf86DriverLoadCursorARGB (infoPtr, pCurs))
225            return FALSE;
226    } else
227    if (bits)
228        if (!xf86DriverLoadCursorImage (infoPtr, bits))
229            return FALSE;
230
231    xf86RecolorCursor_locked (ScreenPriv, pCurs);
232
233    (*infoPtr->SetCursorPosition) (infoPtr->pScrn, x, y);
234
235    return xf86DriverShowCursor(infoPtr);
236}
237
238Bool
239xf86SetCursor(ScreenPtr pScreen, CursorPtr pCurs, int x, int y)
240{
241    xf86CursorScreenPtr ScreenPriv =
242        (xf86CursorScreenPtr) dixLookupPrivate(&pScreen->devPrivates,
243                                               xf86CursorScreenKey);
244    ScreenPtr pSlave;
245    Bool ret = FALSE;
246
247    input_lock();
248
249    x -= ScreenPriv->HotX;
250    y -= ScreenPriv->HotY;
251
252    if (!xf86ScreenSetCursor(pScreen, pCurs, x, y))
253        goto out;
254
255    /* ask each secondary driver to set the cursor. */
256    xorg_list_for_each_entry(pSlave, &pScreen->secondary_list, secondary_head) {
257        if (!RRHasScanoutPixmap(pSlave))
258            continue;
259
260        if (!xf86ScreenSetCursor(pSlave, pCurs, x, y)) {
261            /*
262             * hide the primary (and successfully set secondary) cursors,
263             * otherwise both the hw and sw cursor will show.
264             */
265            xf86SetCursor(pScreen, NullCursor, x, y);
266            goto out;
267        }
268    }
269    ret = TRUE;
270
271 out:
272    input_unlock();
273    return ret;
274}
275
276void
277xf86SetTransparentCursor(ScreenPtr pScreen)
278{
279    xf86CursorScreenPtr ScreenPriv =
280        (xf86CursorScreenPtr) dixLookupPrivate(&pScreen->devPrivates,
281                                               xf86CursorScreenKey);
282    xf86CursorInfoPtr infoPtr = ScreenPriv->CursorInfoPtr;
283
284    input_lock();
285
286    if (!ScreenPriv->transparentData)
287        ScreenPriv->transparentData =
288            (*infoPtr->RealizeCursor) (infoPtr, NullCursor);
289
290    if (!(infoPtr->Flags & HARDWARE_CURSOR_UPDATE_UNHIDDEN))
291        (*infoPtr->HideCursor) (infoPtr->pScrn);
292
293    if (ScreenPriv->transparentData)
294        xf86DriverLoadCursorImage (infoPtr,
295                                   ScreenPriv->transparentData);
296
297    xf86DriverShowCursor(infoPtr);
298
299    input_unlock();
300}
301
302static void
303xf86ScreenMoveCursor(ScreenPtr pScreen, int x, int y)
304{
305    xf86CursorScreenPtr ScreenPriv =
306        (xf86CursorScreenPtr) dixLookupPrivate(&pScreen->devPrivates,
307                                               xf86CursorScreenKey);
308    xf86CursorInfoPtr infoPtr = ScreenPriv->CursorInfoPtr;
309
310    x -= infoPtr->pScrn->frameX0;
311    y -= infoPtr->pScrn->frameY0;
312
313    (*infoPtr->SetCursorPosition) (infoPtr->pScrn, x, y);
314}
315
316void
317xf86MoveCursor(ScreenPtr pScreen, int x, int y)
318{
319    xf86CursorScreenPtr ScreenPriv =
320        (xf86CursorScreenPtr) dixLookupPrivate(&pScreen->devPrivates,
321                                               xf86CursorScreenKey);
322    ScreenPtr pSlave;
323
324    input_lock();
325
326    x -= ScreenPriv->HotX;
327    y -= ScreenPriv->HotY;
328
329    xf86ScreenMoveCursor(pScreen, x, y);
330
331    /* ask each secondary driver to move the cursor */
332    xorg_list_for_each_entry(pSlave, &pScreen->secondary_list, secondary_head) {
333        if (!RRHasScanoutPixmap(pSlave))
334            continue;
335
336        xf86ScreenMoveCursor(pSlave, x, y);
337    }
338
339    input_unlock();
340}
341
342static void
343xf86RecolorCursor_locked(xf86CursorScreenPtr ScreenPriv, CursorPtr pCurs)
344{
345    xf86CursorInfoPtr infoPtr = ScreenPriv->CursorInfoPtr;
346
347    /* recoloring isn't applicable to ARGB cursors and drivers
348       shouldn't have to ignore SetCursorColors requests */
349    if (pCurs->bits->argb)
350        return;
351
352    if (ScreenPriv->PalettedCursor) {
353        xColorItem sourceColor, maskColor;
354        ColormapPtr pmap = ScreenPriv->pInstalledMap;
355
356        if (!pmap)
357            return;
358
359        sourceColor.red = pCurs->foreRed;
360        sourceColor.green = pCurs->foreGreen;
361        sourceColor.blue = pCurs->foreBlue;
362        FakeAllocColor(pmap, &sourceColor);
363        maskColor.red = pCurs->backRed;
364        maskColor.green = pCurs->backGreen;
365        maskColor.blue = pCurs->backBlue;
366        FakeAllocColor(pmap, &maskColor);
367        FakeFreeColor(pmap, sourceColor.pixel);
368        FakeFreeColor(pmap, maskColor.pixel);
369        (*infoPtr->SetCursorColors) (infoPtr->pScrn,
370                                     maskColor.pixel, sourceColor.pixel);
371    }
372    else {                      /* Pass colors in 8-8-8 RGB format */
373        (*infoPtr->SetCursorColors) (infoPtr->pScrn,
374                                     (pCurs->backBlue >> 8) |
375                                     ((pCurs->backGreen >> 8) << 8) |
376                                     ((pCurs->backRed >> 8) << 16),
377                                     (pCurs->foreBlue >> 8) |
378                                     ((pCurs->foreGreen >> 8) << 8) |
379                                     ((pCurs->foreRed >> 8) << 16)
380            );
381    }
382}
383
384void
385xf86RecolorCursor(ScreenPtr pScreen, CursorPtr pCurs, Bool displayed)
386{
387    xf86CursorScreenPtr ScreenPriv =
388        (xf86CursorScreenPtr) dixLookupPrivate(&pScreen->devPrivates,
389                                               xf86CursorScreenKey);
390
391    input_lock();
392    xf86RecolorCursor_locked (ScreenPriv, pCurs);
393    input_unlock();
394}
395
396/* These functions assume that MaxWidth is a multiple of 32 */
397static unsigned char *
398RealizeCursorInterleave0(xf86CursorInfoPtr infoPtr, CursorPtr pCurs)
399{
400
401    SCANLINE *SrcS, *SrcM, *DstS, *DstM;
402    SCANLINE *pSrc, *pMsk;
403    unsigned char *mem;
404    int size = (infoPtr->MaxWidth * infoPtr->MaxHeight) >> 2;
405    int SrcPitch, DstPitch, Pitch, y, x;
406
407    /* how many words are in the source or mask */
408    int words = size / (CUR_BITMAP_SCANLINE_PAD / 4);
409
410    if (!(mem = calloc(1, size)))
411        return NULL;
412
413    if (pCurs == NullCursor) {
414        if (infoPtr->Flags & HARDWARE_CURSOR_INVERT_MASK) {
415            DstM = (SCANLINE *) mem;
416            if (!(infoPtr->Flags & HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK))
417                DstM += words;
418            memset(DstM, -1, words * sizeof(SCANLINE));
419        }
420        return mem;
421    }
422
423    /* SrcPitch == the number of scanlines wide the cursor image is */
424    SrcPitch = (pCurs->bits->width + (BITMAP_SCANLINE_PAD - 1)) >>
425        CUR_LOG2_BITMAP_PAD;
426
427    /* DstPitch is the width of the hw cursor in scanlines */
428    DstPitch = infoPtr->MaxWidth >> CUR_LOG2_BITMAP_PAD;
429    Pitch = SrcPitch < DstPitch ? SrcPitch : DstPitch;
430
431    SrcS = (SCANLINE *) pCurs->bits->source;
432    SrcM = (SCANLINE *) pCurs->bits->mask;
433    DstS = (SCANLINE *) mem;
434    DstM = DstS + words;
435
436    if (infoPtr->Flags & HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK) {
437        SCANLINE *tmp;
438
439        tmp = DstS;
440        DstS = DstM;
441        DstM = tmp;
442    }
443
444    if (infoPtr->Flags & HARDWARE_CURSOR_AND_SOURCE_WITH_MASK) {
445        for (y = pCurs->bits->height, pSrc = DstS, pMsk = DstM;
446             y--;
447             pSrc += DstPitch, pMsk += DstPitch, SrcS += SrcPitch, SrcM +=
448             SrcPitch) {
449            for (x = 0; x < Pitch; x++) {
450                pSrc[x] = SrcS[x] & SrcM[x];
451                pMsk[x] = SrcM[x];
452            }
453        }
454    }
455    else {
456        for (y = pCurs->bits->height, pSrc = DstS, pMsk = DstM;
457             y--;
458             pSrc += DstPitch, pMsk += DstPitch, SrcS += SrcPitch, SrcM +=
459             SrcPitch) {
460            for (x = 0; x < Pitch; x++) {
461                pSrc[x] = SrcS[x];
462                pMsk[x] = SrcM[x];
463            }
464        }
465    }
466
467    if (infoPtr->Flags & HARDWARE_CURSOR_NIBBLE_SWAPPED) {
468        int count = size;
469        unsigned char *pntr1 = (unsigned char *) DstS;
470        unsigned char *pntr2 = (unsigned char *) DstM;
471        unsigned char a, b;
472
473        while (count) {
474
475            a = *pntr1;
476            b = *pntr2;
477            *pntr1 = ((a & 0xF0) >> 4) | ((a & 0x0F) << 4);
478            *pntr2 = ((b & 0xF0) >> 4) | ((b & 0x0F) << 4);
479            pntr1++;
480            pntr2++;
481            count -= 2;
482        }
483    }
484
485    /*
486     * Must be _after_ HARDWARE_CURSOR_AND_SOURCE_WITH_MASK to avoid wiping
487     * out entire source mask.
488     */
489    if (infoPtr->Flags & HARDWARE_CURSOR_INVERT_MASK) {
490        int count = words;
491        SCANLINE *pntr = DstM;
492
493        while (count--) {
494            *pntr = ~(*pntr);
495            pntr++;
496        }
497    }
498
499    if (infoPtr->Flags & HARDWARE_CURSOR_BIT_ORDER_MSBFIRST) {
500        for (y = pCurs->bits->height, pSrc = DstS, pMsk = DstM;
501             y--; pSrc += DstPitch, pMsk += DstPitch) {
502            for (x = 0; x < Pitch; x++) {
503                pSrc[x] = REVERSE_BIT_ORDER(pSrc[x]);
504                pMsk[x] = REVERSE_BIT_ORDER(pMsk[x]);
505            }
506        }
507    }
508
509    return mem;
510}
511
512static unsigned char *
513RealizeCursorInterleave1(xf86CursorInfoPtr infoPtr, CursorPtr pCurs)
514{
515    unsigned char *DstS, *DstM;
516    unsigned char *pntr;
517    unsigned char *mem, *mem2;
518    int count;
519    int size = (infoPtr->MaxWidth * infoPtr->MaxHeight) >> 2;
520
521    /* Realize the cursor without interleaving */
522    if (!(mem2 = RealizeCursorInterleave0(infoPtr, pCurs)))
523        return NULL;
524
525    if (!(mem = calloc(1, size))) {
526        free(mem2);
527        return NULL;
528    }
529
530    /* 1 bit interleave */
531    DstS = mem2;
532    DstM = DstS + (size >> 1);
533    pntr = mem;
534    count = size;
535    while (count) {
536        *pntr++ = ((*DstS & 0x01)) | ((*DstM & 0x01) << 1) |
537            ((*DstS & 0x02) << 1) | ((*DstM & 0x02) << 2) |
538            ((*DstS & 0x04) << 2) | ((*DstM & 0x04) << 3) |
539            ((*DstS & 0x08) << 3) | ((*DstM & 0x08) << 4);
540        *pntr++ = ((*DstS & 0x10) >> 4) | ((*DstM & 0x10) >> 3) |
541            ((*DstS & 0x20) >> 3) | ((*DstM & 0x20) >> 2) |
542            ((*DstS & 0x40) >> 2) | ((*DstM & 0x40) >> 1) |
543            ((*DstS & 0x80) >> 1) | ((*DstM & 0x80));
544        DstS++;
545        DstM++;
546        count -= 2;
547    }
548
549    /* Free the uninterleaved cursor */
550    free(mem2);
551
552    return mem;
553}
554
555static unsigned char *
556RealizeCursorInterleave8(xf86CursorInfoPtr infoPtr, CursorPtr pCurs)
557{
558    unsigned char *DstS, *DstM;
559    unsigned char *pntr;
560    unsigned char *mem, *mem2;
561    int count;
562    int size = (infoPtr->MaxWidth * infoPtr->MaxHeight) >> 2;
563
564    /* Realize the cursor without interleaving */
565    if (!(mem2 = RealizeCursorInterleave0(infoPtr, pCurs)))
566        return NULL;
567
568    if (!(mem = calloc(1, size))) {
569        free(mem2);
570        return NULL;
571    }
572
573    /* 8 bit interleave */
574    DstS = mem2;
575    DstM = DstS + (size >> 1);
576    pntr = mem;
577    count = size;
578    while (count) {
579        *pntr++ = *DstS++;
580        *pntr++ = *DstM++;
581        count -= 2;
582    }
583
584    /* Free the uninterleaved cursor */
585    free(mem2);
586
587    return mem;
588}
589
590static unsigned char *
591RealizeCursorInterleave16(xf86CursorInfoPtr infoPtr, CursorPtr pCurs)
592{
593    unsigned short *DstS, *DstM;
594    unsigned short *pntr;
595    unsigned char *mem, *mem2;
596    int count;
597    int size = (infoPtr->MaxWidth * infoPtr->MaxHeight) >> 2;
598
599    /* Realize the cursor without interleaving */
600    if (!(mem2 = RealizeCursorInterleave0(infoPtr, pCurs)))
601        return NULL;
602
603    if (!(mem = calloc(1, size))) {
604        free(mem2);
605        return NULL;
606    }
607
608    /* 16 bit interleave */
609    DstS = (void *) mem2;
610    DstM = DstS + (size >> 2);
611    pntr = (void *) mem;
612    count = (size >> 1);
613    while (count) {
614        *pntr++ = *DstS++;
615        *pntr++ = *DstM++;
616        count -= 2;
617    }
618
619    /* Free the uninterleaved cursor */
620    free(mem2);
621
622    return mem;
623}
624
625static unsigned char *
626RealizeCursorInterleave32(xf86CursorInfoPtr infoPtr, CursorPtr pCurs)
627{
628    CARD32 *DstS, *DstM;
629    CARD32 *pntr;
630    unsigned char *mem, *mem2;
631    int count;
632    int size = (infoPtr->MaxWidth * infoPtr->MaxHeight) >> 2;
633
634    /* Realize the cursor without interleaving */
635    if (!(mem2 = RealizeCursorInterleave0(infoPtr, pCurs)))
636        return NULL;
637
638    if (!(mem = calloc(1, size))) {
639        free(mem2);
640        return NULL;
641    }
642
643    /* 32 bit interleave */
644    DstS = (void *) mem2;
645    DstM = DstS + (size >> 3);
646    pntr = (void *) mem;
647    count = (size >> 2);
648    while (count) {
649        *pntr++ = *DstS++;
650        *pntr++ = *DstM++;
651        count -= 2;
652    }
653
654    /* Free the uninterleaved cursor */
655    free(mem2);
656
657    return mem;
658}
659
660static unsigned char *
661RealizeCursorInterleave64(xf86CursorInfoPtr infoPtr, CursorPtr pCurs)
662{
663    CARD32 *DstS, *DstM;
664    CARD32 *pntr;
665    unsigned char *mem, *mem2;
666    int count;
667    int size = (infoPtr->MaxWidth * infoPtr->MaxHeight) >> 2;
668
669    /* Realize the cursor without interleaving */
670    if (!(mem2 = RealizeCursorInterleave0(infoPtr, pCurs)))
671        return NULL;
672
673    if (!(mem = calloc(1, size))) {
674        free(mem2);
675        return NULL;
676    }
677
678    /* 64 bit interleave */
679    DstS = (void *) mem2;
680    DstM = DstS + (size >> 3);
681    pntr = (void *) mem;
682    count = (size >> 2);
683    while (count) {
684        *pntr++ = *DstS++;
685        *pntr++ = *DstS++;
686        *pntr++ = *DstM++;
687        *pntr++ = *DstM++;
688        count -= 4;
689    }
690
691    /* Free the uninterleaved cursor */
692    free(mem2);
693
694    return mem;
695}
696