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