Commit | Line | Data |
---|---|---|
a09e091a JB |
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 "xf86CursorPriv.h" | |
21 | ||
22 | #include "servermd.h" | |
23 | ||
24 | static CARD32 | |
25 | xf86ReverseBitOrder(CARD32 v) | |
26 | { | |
27 | return (((0x01010101 & v) << 7) | ((0x02020202 & v) << 5) | | |
28 | ((0x04040404 & v) << 3) | ((0x08080808 & v) << 1) | | |
29 | ((0x10101010 & v) >> 1) | ((0x20202020 & v) >> 3) | | |
30 | ((0x40404040 & v) >> 5) | ((0x80808080 & v) >> 7)); | |
31 | } | |
32 | ||
33 | #if BITMAP_SCANLINE_PAD == 64 | |
34 | ||
35 | #if 1 | |
36 | /* Cursors might be only 32 wide. Give'em a chance */ | |
37 | #define SCANLINE CARD32 | |
38 | #define CUR_BITMAP_SCANLINE_PAD 32 | |
39 | #define CUR_LOG2_BITMAP_PAD 5 | |
40 | #define REVERSE_BIT_ORDER(w) xf86ReverseBitOrder(w) | |
41 | #else | |
42 | #define SCANLINE CARD64 | |
43 | #define CUR_BITMAP_SCANLINE_PAD BITMAP_SCANLINE_PAD | |
44 | #define CUR_LOG2_BITMAP_PAD LOG2_BITMAP_PAD | |
45 | #define REVERSE_BIT_ORDER(w) xf86CARD64ReverseBits(w) | |
46 | static CARD64 xf86CARD64ReverseBits(CARD64 w); | |
47 | ||
48 | static CARD64 | |
49 | xf86CARD64ReverseBits(CARD64 w) | |
50 | { | |
51 | unsigned char *p = (unsigned char *) &w; | |
52 | ||
53 | p[0] = byte_reversed[p[0]]; | |
54 | p[1] = byte_reversed[p[1]]; | |
55 | p[2] = byte_reversed[p[2]]; | |
56 | p[3] = byte_reversed[p[3]]; | |
57 | p[4] = byte_reversed[p[4]]; | |
58 | p[5] = byte_reversed[p[5]]; | |
59 | p[6] = byte_reversed[p[6]]; | |
60 | p[7] = byte_reversed[p[7]]; | |
61 | ||
62 | return w; | |
63 | } | |
64 | #endif | |
65 | ||
66 | #else | |
67 | ||
68 | #define SCANLINE CARD32 | |
69 | #define CUR_BITMAP_SCANLINE_PAD BITMAP_SCANLINE_PAD | |
70 | #define CUR_LOG2_BITMAP_PAD LOG2_BITMAP_PAD | |
71 | #define REVERSE_BIT_ORDER(w) xf86ReverseBitOrder(w) | |
72 | ||
73 | #endif /* BITMAP_SCANLINE_PAD == 64 */ | |
74 | ||
75 | static unsigned char *RealizeCursorInterleave0(xf86CursorInfoPtr, CursorPtr); | |
76 | static unsigned char *RealizeCursorInterleave1(xf86CursorInfoPtr, CursorPtr); | |
77 | static unsigned char *RealizeCursorInterleave8(xf86CursorInfoPtr, CursorPtr); | |
78 | static unsigned char *RealizeCursorInterleave16(xf86CursorInfoPtr, CursorPtr); | |
79 | static unsigned char *RealizeCursorInterleave32(xf86CursorInfoPtr, CursorPtr); | |
80 | static unsigned char *RealizeCursorInterleave64(xf86CursorInfoPtr, CursorPtr); | |
81 | ||
82 | Bool | |
83 | xf86InitHardwareCursor(ScreenPtr pScreen, xf86CursorInfoPtr infoPtr) | |
84 | { | |
85 | if ((infoPtr->MaxWidth <= 0) || (infoPtr->MaxHeight <= 0)) | |
86 | return FALSE; | |
87 | ||
88 | /* These are required for now */ | |
89 | if (!infoPtr->SetCursorPosition || | |
90 | !infoPtr->LoadCursorImage || | |
91 | !infoPtr->HideCursor || | |
92 | !infoPtr->ShowCursor || !infoPtr->SetCursorColors) | |
93 | return FALSE; | |
94 | ||
95 | if (infoPtr->RealizeCursor) { | |
96 | /* Don't overwrite a driver provided Realize Cursor function */ | |
97 | } | |
98 | else if (HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1 & infoPtr->Flags) { | |
99 | infoPtr->RealizeCursor = RealizeCursorInterleave1; | |
100 | } | |
101 | else if (HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_8 & infoPtr->Flags) { | |
102 | infoPtr->RealizeCursor = RealizeCursorInterleave8; | |
103 | } | |
104 | else if (HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_16 & infoPtr->Flags) { | |
105 | infoPtr->RealizeCursor = RealizeCursorInterleave16; | |
106 | } | |
107 | else if (HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_32 & infoPtr->Flags) { | |
108 | infoPtr->RealizeCursor = RealizeCursorInterleave32; | |
109 | } | |
110 | else if (HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64 & infoPtr->Flags) { | |
111 | infoPtr->RealizeCursor = RealizeCursorInterleave64; | |
112 | } | |
113 | else { /* not interleaved */ | |
114 | infoPtr->RealizeCursor = RealizeCursorInterleave0; | |
115 | } | |
116 | ||
117 | infoPtr->pScrn = xf86ScreenToScrn(pScreen); | |
118 | ||
119 | return TRUE; | |
120 | } | |
121 | ||
122 | void | |
123 | xf86SetCursor(ScreenPtr pScreen, CursorPtr pCurs, int x, int y) | |
124 | { | |
125 | xf86CursorScreenPtr ScreenPriv = | |
126 | (xf86CursorScreenPtr) dixLookupPrivate(&pScreen->devPrivates, | |
127 | xf86CursorScreenKey); | |
128 | xf86CursorInfoPtr infoPtr = ScreenPriv->CursorInfoPtr; | |
129 | unsigned char *bits; | |
130 | ||
131 | if (pCurs == NullCursor) { | |
132 | (*infoPtr->HideCursor) (infoPtr->pScrn); | |
133 | return; | |
134 | } | |
135 | ||
136 | bits = | |
137 | dixLookupScreenPrivate(&pCurs->devPrivates, CursorScreenKey, pScreen); | |
138 | ||
139 | x -= infoPtr->pScrn->frameX0 + ScreenPriv->HotX; | |
140 | y -= infoPtr->pScrn->frameY0 + ScreenPriv->HotY; | |
141 | ||
142 | #ifdef ARGB_CURSOR | |
143 | if (!pCurs->bits->argb || !infoPtr->LoadCursorARGB) | |
144 | #endif | |
145 | if (!bits) { | |
146 | bits = (*infoPtr->RealizeCursor) (infoPtr, pCurs); | |
147 | dixSetScreenPrivate(&pCurs->devPrivates, CursorScreenKey, pScreen, | |
148 | bits); | |
149 | } | |
150 | ||
151 | if (!(infoPtr->Flags & HARDWARE_CURSOR_UPDATE_UNHIDDEN)) | |
152 | (*infoPtr->HideCursor) (infoPtr->pScrn); | |
153 | ||
154 | #ifdef ARGB_CURSOR | |
155 | if (pCurs->bits->argb && infoPtr->LoadCursorARGB) | |
156 | (*infoPtr->LoadCursorARGB) (infoPtr->pScrn, pCurs); | |
157 | else | |
158 | #endif | |
159 | if (bits) | |
160 | (*infoPtr->LoadCursorImage) (infoPtr->pScrn, bits); | |
161 | ||
162 | xf86RecolorCursor(pScreen, pCurs, 1); | |
163 | ||
164 | (*infoPtr->SetCursorPosition) (infoPtr->pScrn, x, y); | |
165 | ||
166 | (*infoPtr->ShowCursor) (infoPtr->pScrn); | |
167 | } | |
168 | ||
169 | void | |
170 | xf86SetTransparentCursor(ScreenPtr pScreen) | |
171 | { | |
172 | xf86CursorScreenPtr ScreenPriv = | |
173 | (xf86CursorScreenPtr) dixLookupPrivate(&pScreen->devPrivates, | |
174 | xf86CursorScreenKey); | |
175 | xf86CursorInfoPtr infoPtr = ScreenPriv->CursorInfoPtr; | |
176 | ||
177 | if (!ScreenPriv->transparentData) | |
178 | ScreenPriv->transparentData = | |
179 | (*infoPtr->RealizeCursor) (infoPtr, NullCursor); | |
180 | ||
181 | if (!(infoPtr->Flags & HARDWARE_CURSOR_UPDATE_UNHIDDEN)) | |
182 | (*infoPtr->HideCursor) (infoPtr->pScrn); | |
183 | ||
184 | if (ScreenPriv->transparentData) | |
185 | (*infoPtr->LoadCursorImage) (infoPtr->pScrn, | |
186 | ScreenPriv->transparentData); | |
187 | ||
188 | (*infoPtr->ShowCursor) (infoPtr->pScrn); | |
189 | } | |
190 | ||
191 | void | |
192 | xf86MoveCursor(ScreenPtr pScreen, int x, int y) | |
193 | { | |
194 | xf86CursorScreenPtr ScreenPriv = | |
195 | (xf86CursorScreenPtr) dixLookupPrivate(&pScreen->devPrivates, | |
196 | xf86CursorScreenKey); | |
197 | xf86CursorInfoPtr infoPtr = ScreenPriv->CursorInfoPtr; | |
198 | ||
199 | x -= infoPtr->pScrn->frameX0 + ScreenPriv->HotX; | |
200 | y -= infoPtr->pScrn->frameY0 + ScreenPriv->HotY; | |
201 | ||
202 | (*infoPtr->SetCursorPosition) (infoPtr->pScrn, x, y); | |
203 | } | |
204 | ||
205 | void | |
206 | xf86RecolorCursor(ScreenPtr pScreen, CursorPtr pCurs, Bool displayed) | |
207 | { | |
208 | xf86CursorScreenPtr ScreenPriv = | |
209 | (xf86CursorScreenPtr) dixLookupPrivate(&pScreen->devPrivates, | |
210 | xf86CursorScreenKey); | |
211 | xf86CursorInfoPtr infoPtr = ScreenPriv->CursorInfoPtr; | |
212 | ||
213 | #ifdef ARGB_CURSOR | |
214 | /* recoloring isn't applicable to ARGB cursors and drivers | |
215 | shouldn't have to ignore SetCursorColors requests */ | |
216 | if (pCurs->bits->argb) | |
217 | return; | |
218 | #endif | |
219 | ||
220 | if (ScreenPriv->PalettedCursor) { | |
221 | xColorItem sourceColor, maskColor; | |
222 | ColormapPtr pmap = ScreenPriv->pInstalledMap; | |
223 | ||
224 | if (!pmap) | |
225 | return; | |
226 | ||
227 | sourceColor.red = pCurs->foreRed; | |
228 | sourceColor.green = pCurs->foreGreen; | |
229 | sourceColor.blue = pCurs->foreBlue; | |
230 | FakeAllocColor(pmap, &sourceColor); | |
231 | maskColor.red = pCurs->backRed; | |
232 | maskColor.green = pCurs->backGreen; | |
233 | maskColor.blue = pCurs->backBlue; | |
234 | FakeAllocColor(pmap, &maskColor); | |
235 | FakeFreeColor(pmap, sourceColor.pixel); | |
236 | FakeFreeColor(pmap, maskColor.pixel); | |
237 | (*infoPtr->SetCursorColors) (infoPtr->pScrn, | |
238 | maskColor.pixel, sourceColor.pixel); | |
239 | } | |
240 | else { /* Pass colors in 8-8-8 RGB format */ | |
241 | (*infoPtr->SetCursorColors) (infoPtr->pScrn, | |
242 | (pCurs->backBlue >> 8) | | |
243 | ((pCurs->backGreen >> 8) << 8) | | |
244 | ((pCurs->backRed >> 8) << 16), | |
245 | (pCurs->foreBlue >> 8) | | |
246 | ((pCurs->foreGreen >> 8) << 8) | | |
247 | ((pCurs->foreRed >> 8) << 16) | |
248 | ); | |
249 | } | |
250 | } | |
251 | ||
252 | /* These functions assume that MaxWidth is a multiple of 32 */ | |
253 | static unsigned char * | |
254 | RealizeCursorInterleave0(xf86CursorInfoPtr infoPtr, CursorPtr pCurs) | |
255 | { | |
256 | ||
257 | SCANLINE *SrcS, *SrcM, *DstS, *DstM; | |
258 | SCANLINE *pSrc, *pMsk; | |
259 | unsigned char *mem; | |
260 | int size = (infoPtr->MaxWidth * infoPtr->MaxHeight) >> 2; | |
261 | int SrcPitch, DstPitch, Pitch, y, x; | |
262 | ||
263 | /* how many words are in the source or mask */ | |
264 | int words = size / (CUR_BITMAP_SCANLINE_PAD / 4); | |
265 | ||
266 | if (!(mem = calloc(1, size))) | |
267 | return NULL; | |
268 | ||
269 | if (pCurs == NullCursor) { | |
270 | if (infoPtr->Flags & HARDWARE_CURSOR_INVERT_MASK) { | |
271 | DstM = (SCANLINE *) mem; | |
272 | if (!(infoPtr->Flags & HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK)) | |
273 | DstM += words; | |
274 | memset(DstM, -1, words * sizeof(SCANLINE)); | |
275 | } | |
276 | return mem; | |
277 | } | |
278 | ||
279 | /* SrcPitch == the number of scanlines wide the cursor image is */ | |
280 | SrcPitch = (pCurs->bits->width + (BITMAP_SCANLINE_PAD - 1)) >> | |
281 | CUR_LOG2_BITMAP_PAD; | |
282 | ||
283 | /* DstPitch is the width of the hw cursor in scanlines */ | |
284 | DstPitch = infoPtr->MaxWidth >> CUR_LOG2_BITMAP_PAD; | |
285 | Pitch = SrcPitch < DstPitch ? SrcPitch : DstPitch; | |
286 | ||
287 | SrcS = (SCANLINE *) pCurs->bits->source; | |
288 | SrcM = (SCANLINE *) pCurs->bits->mask; | |
289 | DstS = (SCANLINE *) mem; | |
290 | DstM = DstS + words; | |
291 | ||
292 | if (infoPtr->Flags & HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK) { | |
293 | SCANLINE *tmp; | |
294 | ||
295 | tmp = DstS; | |
296 | DstS = DstM; | |
297 | DstM = tmp; | |
298 | } | |
299 | ||
300 | if (infoPtr->Flags & HARDWARE_CURSOR_AND_SOURCE_WITH_MASK) { | |
301 | for (y = pCurs->bits->height, pSrc = DstS, pMsk = DstM; | |
302 | y--; | |
303 | pSrc += DstPitch, pMsk += DstPitch, SrcS += SrcPitch, SrcM += | |
304 | SrcPitch) { | |
305 | for (x = 0; x < Pitch; x++) { | |
306 | pSrc[x] = SrcS[x] & SrcM[x]; | |
307 | pMsk[x] = SrcM[x]; | |
308 | } | |
309 | } | |
310 | } | |
311 | else { | |
312 | for (y = pCurs->bits->height, pSrc = DstS, pMsk = DstM; | |
313 | y--; | |
314 | pSrc += DstPitch, pMsk += DstPitch, SrcS += SrcPitch, SrcM += | |
315 | SrcPitch) { | |
316 | for (x = 0; x < Pitch; x++) { | |
317 | pSrc[x] = SrcS[x]; | |
318 | pMsk[x] = SrcM[x]; | |
319 | } | |
320 | } | |
321 | } | |
322 | ||
323 | if (infoPtr->Flags & HARDWARE_CURSOR_NIBBLE_SWAPPED) { | |
324 | int count = size; | |
325 | unsigned char *pntr1 = (unsigned char *) DstS; | |
326 | unsigned char *pntr2 = (unsigned char *) DstM; | |
327 | unsigned char a, b; | |
328 | ||
329 | while (count) { | |
330 | ||
331 | a = *pntr1; | |
332 | b = *pntr2; | |
333 | *pntr1 = ((a & 0xF0) >> 4) | ((a & 0x0F) << 4); | |
334 | *pntr2 = ((b & 0xF0) >> 4) | ((b & 0x0F) << 4); | |
335 | pntr1++; | |
336 | pntr2++; | |
337 | count -= 2; | |
338 | } | |
339 | } | |
340 | ||
341 | /* | |
342 | * Must be _after_ HARDWARE_CURSOR_AND_SOURCE_WITH_MASK to avoid wiping | |
343 | * out entire source mask. | |
344 | */ | |
345 | if (infoPtr->Flags & HARDWARE_CURSOR_INVERT_MASK) { | |
346 | int count = words; | |
347 | SCANLINE *pntr = DstM; | |
348 | ||
349 | while (count--) { | |
350 | *pntr = ~(*pntr); | |
351 | pntr++; | |
352 | } | |
353 | } | |
354 | ||
355 | if (infoPtr->Flags & HARDWARE_CURSOR_BIT_ORDER_MSBFIRST) { | |
356 | for (y = pCurs->bits->height, pSrc = DstS, pMsk = DstM; | |
357 | y--; pSrc += DstPitch, pMsk += DstPitch) { | |
358 | for (x = 0; x < Pitch; x++) { | |
359 | pSrc[x] = REVERSE_BIT_ORDER(pSrc[x]); | |
360 | pMsk[x] = REVERSE_BIT_ORDER(pMsk[x]); | |
361 | } | |
362 | } | |
363 | } | |
364 | ||
365 | return mem; | |
366 | } | |
367 | ||
368 | static unsigned char * | |
369 | RealizeCursorInterleave1(xf86CursorInfoPtr infoPtr, CursorPtr pCurs) | |
370 | { | |
371 | unsigned char *DstS, *DstM; | |
372 | unsigned char *pntr; | |
373 | unsigned char *mem, *mem2; | |
374 | int count; | |
375 | int size = (infoPtr->MaxWidth * infoPtr->MaxHeight) >> 2; | |
376 | ||
377 | /* Realize the cursor without interleaving */ | |
378 | if (!(mem2 = RealizeCursorInterleave0(infoPtr, pCurs))) | |
379 | return NULL; | |
380 | ||
381 | if (!(mem = calloc(1, size))) { | |
382 | free(mem2); | |
383 | return NULL; | |
384 | } | |
385 | ||
386 | /* 1 bit interleave */ | |
387 | DstS = mem2; | |
388 | DstM = DstS + (size >> 1); | |
389 | pntr = mem; | |
390 | count = size; | |
391 | while (count) { | |
392 | *pntr++ = ((*DstS & 0x01)) | ((*DstM & 0x01) << 1) | | |
393 | ((*DstS & 0x02) << 1) | ((*DstM & 0x02) << 2) | | |
394 | ((*DstS & 0x04) << 2) | ((*DstM & 0x04) << 3) | | |
395 | ((*DstS & 0x08) << 3) | ((*DstM & 0x08) << 4); | |
396 | *pntr++ = ((*DstS & 0x10) >> 4) | ((*DstM & 0x10) >> 3) | | |
397 | ((*DstS & 0x20) >> 3) | ((*DstM & 0x20) >> 2) | | |
398 | ((*DstS & 0x40) >> 2) | ((*DstM & 0x40) >> 1) | | |
399 | ((*DstS & 0x80) >> 1) | ((*DstM & 0x80)); | |
400 | DstS++; | |
401 | DstM++; | |
402 | count -= 2; | |
403 | } | |
404 | ||
405 | /* Free the uninterleaved cursor */ | |
406 | free(mem2); | |
407 | ||
408 | return mem; | |
409 | } | |
410 | ||
411 | static unsigned char * | |
412 | RealizeCursorInterleave8(xf86CursorInfoPtr infoPtr, CursorPtr pCurs) | |
413 | { | |
414 | unsigned char *DstS, *DstM; | |
415 | unsigned char *pntr; | |
416 | unsigned char *mem, *mem2; | |
417 | int count; | |
418 | int size = (infoPtr->MaxWidth * infoPtr->MaxHeight) >> 2; | |
419 | ||
420 | /* Realize the cursor without interleaving */ | |
421 | if (!(mem2 = RealizeCursorInterleave0(infoPtr, pCurs))) | |
422 | return NULL; | |
423 | ||
424 | if (!(mem = calloc(1, size))) { | |
425 | free(mem2); | |
426 | return NULL; | |
427 | } | |
428 | ||
429 | /* 8 bit interleave */ | |
430 | DstS = mem2; | |
431 | DstM = DstS + (size >> 1); | |
432 | pntr = mem; | |
433 | count = size; | |
434 | while (count) { | |
435 | *pntr++ = *DstS++; | |
436 | *pntr++ = *DstM++; | |
437 | count -= 2; | |
438 | } | |
439 | ||
440 | /* Free the uninterleaved cursor */ | |
441 | free(mem2); | |
442 | ||
443 | return mem; | |
444 | } | |
445 | ||
446 | static unsigned char * | |
447 | RealizeCursorInterleave16(xf86CursorInfoPtr infoPtr, CursorPtr pCurs) | |
448 | { | |
449 | unsigned short *DstS, *DstM; | |
450 | unsigned short *pntr; | |
451 | unsigned char *mem, *mem2; | |
452 | int count; | |
453 | int size = (infoPtr->MaxWidth * infoPtr->MaxHeight) >> 2; | |
454 | ||
455 | /* Realize the cursor without interleaving */ | |
456 | if (!(mem2 = RealizeCursorInterleave0(infoPtr, pCurs))) | |
457 | return NULL; | |
458 | ||
459 | if (!(mem = calloc(1, size))) { | |
460 | free(mem2); | |
461 | return NULL; | |
462 | } | |
463 | ||
464 | /* 16 bit interleave */ | |
465 | DstS = (pointer) mem2; | |
466 | DstM = DstS + (size >> 2); | |
467 | pntr = (pointer) mem; | |
468 | count = (size >> 1); | |
469 | while (count) { | |
470 | *pntr++ = *DstS++; | |
471 | *pntr++ = *DstM++; | |
472 | count -= 2; | |
473 | } | |
474 | ||
475 | /* Free the uninterleaved cursor */ | |
476 | free(mem2); | |
477 | ||
478 | return mem; | |
479 | } | |
480 | ||
481 | static unsigned char * | |
482 | RealizeCursorInterleave32(xf86CursorInfoPtr infoPtr, CursorPtr pCurs) | |
483 | { | |
484 | CARD32 *DstS, *DstM; | |
485 | CARD32 *pntr; | |
486 | unsigned char *mem, *mem2; | |
487 | int count; | |
488 | int size = (infoPtr->MaxWidth * infoPtr->MaxHeight) >> 2; | |
489 | ||
490 | /* Realize the cursor without interleaving */ | |
491 | if (!(mem2 = RealizeCursorInterleave0(infoPtr, pCurs))) | |
492 | return NULL; | |
493 | ||
494 | if (!(mem = calloc(1, size))) { | |
495 | free(mem2); | |
496 | return NULL; | |
497 | } | |
498 | ||
499 | /* 32 bit interleave */ | |
500 | DstS = (pointer) mem2; | |
501 | DstM = DstS + (size >> 3); | |
502 | pntr = (pointer) mem; | |
503 | count = (size >> 2); | |
504 | while (count) { | |
505 | *pntr++ = *DstS++; | |
506 | *pntr++ = *DstM++; | |
507 | count -= 2; | |
508 | } | |
509 | ||
510 | /* Free the uninterleaved cursor */ | |
511 | free(mem2); | |
512 | ||
513 | return mem; | |
514 | } | |
515 | ||
516 | static unsigned char * | |
517 | RealizeCursorInterleave64(xf86CursorInfoPtr infoPtr, CursorPtr pCurs) | |
518 | { | |
519 | CARD32 *DstS, *DstM; | |
520 | CARD32 *pntr; | |
521 | unsigned char *mem, *mem2; | |
522 | int count; | |
523 | int size = (infoPtr->MaxWidth * infoPtr->MaxHeight) >> 2; | |
524 | ||
525 | /* Realize the cursor without interleaving */ | |
526 | if (!(mem2 = RealizeCursorInterleave0(infoPtr, pCurs))) | |
527 | return NULL; | |
528 | ||
529 | if (!(mem = calloc(1, size))) { | |
530 | free(mem2); | |
531 | return NULL; | |
532 | } | |
533 | ||
534 | /* 64 bit interleave */ | |
535 | DstS = (pointer) mem2; | |
536 | DstM = DstS + (size >> 3); | |
537 | pntr = (pointer) mem; | |
538 | count = (size >> 2); | |
539 | while (count) { | |
540 | *pntr++ = *DstS++; | |
541 | *pntr++ = *DstS++; | |
542 | *pntr++ = *DstM++; | |
543 | *pntr++ = *DstM++; | |
544 | count -= 4; | |
545 | } | |
546 | ||
547 | /* Free the uninterleaved cursor */ | |
548 | free(mem2); | |
549 | ||
550 | return mem; | |
551 | } |