xf86HWCurs.c revision 35c4bbdf
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 24static CARD32 25xf86ReverseBitOrder(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) 46static CARD64 xf86CARD64ReverseBits(CARD64 w); 47 48static CARD64 49xf86CARD64ReverseBits(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 75static unsigned char *RealizeCursorInterleave0(xf86CursorInfoPtr, CursorPtr); 76static unsigned char *RealizeCursorInterleave1(xf86CursorInfoPtr, CursorPtr); 77static unsigned char *RealizeCursorInterleave8(xf86CursorInfoPtr, CursorPtr); 78static unsigned char *RealizeCursorInterleave16(xf86CursorInfoPtr, CursorPtr); 79static unsigned char *RealizeCursorInterleave32(xf86CursorInfoPtr, CursorPtr); 80static unsigned char *RealizeCursorInterleave64(xf86CursorInfoPtr, CursorPtr); 81 82Bool 83xf86InitHardwareCursor(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 !xf86DriverHasLoadCursorImage(infoPtr) || 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 122Bool 123xf86SetCursor(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 TRUE; 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 if (!pCurs->bits->argb || !xf86DriverHasLoadCursorARGB(infoPtr)) 143 if (!bits) { 144 bits = (*infoPtr->RealizeCursor) (infoPtr, pCurs); 145 dixSetScreenPrivate(&pCurs->devPrivates, CursorScreenKey, pScreen, 146 bits); 147 } 148 149 if (!(infoPtr->Flags & HARDWARE_CURSOR_UPDATE_UNHIDDEN)) 150 (*infoPtr->HideCursor) (infoPtr->pScrn); 151 152 if (pCurs->bits->argb && xf86DriverHasLoadCursorARGB(infoPtr)) { 153 if (!xf86DriverLoadCursorARGB (infoPtr, pCurs)) 154 return FALSE; 155 } else 156 if (bits) 157 if (!xf86DriverLoadCursorImage (infoPtr, bits)) 158 return FALSE; 159 160 xf86RecolorCursor(pScreen, pCurs, 1); 161 162 (*infoPtr->SetCursorPosition) (infoPtr->pScrn, x, y); 163 164 (*infoPtr->ShowCursor) (infoPtr->pScrn); 165 return TRUE; 166} 167 168void 169xf86SetTransparentCursor(ScreenPtr pScreen) 170{ 171 xf86CursorScreenPtr ScreenPriv = 172 (xf86CursorScreenPtr) dixLookupPrivate(&pScreen->devPrivates, 173 xf86CursorScreenKey); 174 xf86CursorInfoPtr infoPtr = ScreenPriv->CursorInfoPtr; 175 176 if (!ScreenPriv->transparentData) 177 ScreenPriv->transparentData = 178 (*infoPtr->RealizeCursor) (infoPtr, NullCursor); 179 180 if (!(infoPtr->Flags & HARDWARE_CURSOR_UPDATE_UNHIDDEN)) 181 (*infoPtr->HideCursor) (infoPtr->pScrn); 182 183 if (ScreenPriv->transparentData) 184 xf86DriverLoadCursorImage (infoPtr, 185 ScreenPriv->transparentData); 186 187 (*infoPtr->ShowCursor) (infoPtr->pScrn); 188} 189 190void 191xf86MoveCursor(ScreenPtr pScreen, int x, int y) 192{ 193 xf86CursorScreenPtr ScreenPriv = 194 (xf86CursorScreenPtr) dixLookupPrivate(&pScreen->devPrivates, 195 xf86CursorScreenKey); 196 xf86CursorInfoPtr infoPtr = ScreenPriv->CursorInfoPtr; 197 198 x -= infoPtr->pScrn->frameX0 + ScreenPriv->HotX; 199 y -= infoPtr->pScrn->frameY0 + ScreenPriv->HotY; 200 201 (*infoPtr->SetCursorPosition) (infoPtr->pScrn, x, y); 202} 203 204void 205xf86RecolorCursor(ScreenPtr pScreen, CursorPtr pCurs, Bool displayed) 206{ 207 xf86CursorScreenPtr ScreenPriv = 208 (xf86CursorScreenPtr) dixLookupPrivate(&pScreen->devPrivates, 209 xf86CursorScreenKey); 210 xf86CursorInfoPtr infoPtr = ScreenPriv->CursorInfoPtr; 211 212 /* recoloring isn't applicable to ARGB cursors and drivers 213 shouldn't have to ignore SetCursorColors requests */ 214 if (pCurs->bits->argb) 215 return; 216 217 if (ScreenPriv->PalettedCursor) { 218 xColorItem sourceColor, maskColor; 219 ColormapPtr pmap = ScreenPriv->pInstalledMap; 220 221 if (!pmap) 222 return; 223 224 sourceColor.red = pCurs->foreRed; 225 sourceColor.green = pCurs->foreGreen; 226 sourceColor.blue = pCurs->foreBlue; 227 FakeAllocColor(pmap, &sourceColor); 228 maskColor.red = pCurs->backRed; 229 maskColor.green = pCurs->backGreen; 230 maskColor.blue = pCurs->backBlue; 231 FakeAllocColor(pmap, &maskColor); 232 FakeFreeColor(pmap, sourceColor.pixel); 233 FakeFreeColor(pmap, maskColor.pixel); 234 (*infoPtr->SetCursorColors) (infoPtr->pScrn, 235 maskColor.pixel, sourceColor.pixel); 236 } 237 else { /* Pass colors in 8-8-8 RGB format */ 238 (*infoPtr->SetCursorColors) (infoPtr->pScrn, 239 (pCurs->backBlue >> 8) | 240 ((pCurs->backGreen >> 8) << 8) | 241 ((pCurs->backRed >> 8) << 16), 242 (pCurs->foreBlue >> 8) | 243 ((pCurs->foreGreen >> 8) << 8) | 244 ((pCurs->foreRed >> 8) << 16) 245 ); 246 } 247} 248 249/* These functions assume that MaxWidth is a multiple of 32 */ 250static unsigned char * 251RealizeCursorInterleave0(xf86CursorInfoPtr infoPtr, CursorPtr pCurs) 252{ 253 254 SCANLINE *SrcS, *SrcM, *DstS, *DstM; 255 SCANLINE *pSrc, *pMsk; 256 unsigned char *mem; 257 int size = (infoPtr->MaxWidth * infoPtr->MaxHeight) >> 2; 258 int SrcPitch, DstPitch, Pitch, y, x; 259 260 /* how many words are in the source or mask */ 261 int words = size / (CUR_BITMAP_SCANLINE_PAD / 4); 262 263 if (!(mem = calloc(1, size))) 264 return NULL; 265 266 if (pCurs == NullCursor) { 267 if (infoPtr->Flags & HARDWARE_CURSOR_INVERT_MASK) { 268 DstM = (SCANLINE *) mem; 269 if (!(infoPtr->Flags & HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK)) 270 DstM += words; 271 memset(DstM, -1, words * sizeof(SCANLINE)); 272 } 273 return mem; 274 } 275 276 /* SrcPitch == the number of scanlines wide the cursor image is */ 277 SrcPitch = (pCurs->bits->width + (BITMAP_SCANLINE_PAD - 1)) >> 278 CUR_LOG2_BITMAP_PAD; 279 280 /* DstPitch is the width of the hw cursor in scanlines */ 281 DstPitch = infoPtr->MaxWidth >> CUR_LOG2_BITMAP_PAD; 282 Pitch = SrcPitch < DstPitch ? SrcPitch : DstPitch; 283 284 SrcS = (SCANLINE *) pCurs->bits->source; 285 SrcM = (SCANLINE *) pCurs->bits->mask; 286 DstS = (SCANLINE *) mem; 287 DstM = DstS + words; 288 289 if (infoPtr->Flags & HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK) { 290 SCANLINE *tmp; 291 292 tmp = DstS; 293 DstS = DstM; 294 DstM = tmp; 295 } 296 297 if (infoPtr->Flags & HARDWARE_CURSOR_AND_SOURCE_WITH_MASK) { 298 for (y = pCurs->bits->height, pSrc = DstS, pMsk = DstM; 299 y--; 300 pSrc += DstPitch, pMsk += DstPitch, SrcS += SrcPitch, SrcM += 301 SrcPitch) { 302 for (x = 0; x < Pitch; x++) { 303 pSrc[x] = SrcS[x] & SrcM[x]; 304 pMsk[x] = SrcM[x]; 305 } 306 } 307 } 308 else { 309 for (y = pCurs->bits->height, pSrc = DstS, pMsk = DstM; 310 y--; 311 pSrc += DstPitch, pMsk += DstPitch, SrcS += SrcPitch, SrcM += 312 SrcPitch) { 313 for (x = 0; x < Pitch; x++) { 314 pSrc[x] = SrcS[x]; 315 pMsk[x] = SrcM[x]; 316 } 317 } 318 } 319 320 if (infoPtr->Flags & HARDWARE_CURSOR_NIBBLE_SWAPPED) { 321 int count = size; 322 unsigned char *pntr1 = (unsigned char *) DstS; 323 unsigned char *pntr2 = (unsigned char *) DstM; 324 unsigned char a, b; 325 326 while (count) { 327 328 a = *pntr1; 329 b = *pntr2; 330 *pntr1 = ((a & 0xF0) >> 4) | ((a & 0x0F) << 4); 331 *pntr2 = ((b & 0xF0) >> 4) | ((b & 0x0F) << 4); 332 pntr1++; 333 pntr2++; 334 count -= 2; 335 } 336 } 337 338 /* 339 * Must be _after_ HARDWARE_CURSOR_AND_SOURCE_WITH_MASK to avoid wiping 340 * out entire source mask. 341 */ 342 if (infoPtr->Flags & HARDWARE_CURSOR_INVERT_MASK) { 343 int count = words; 344 SCANLINE *pntr = DstM; 345 346 while (count--) { 347 *pntr = ~(*pntr); 348 pntr++; 349 } 350 } 351 352 if (infoPtr->Flags & HARDWARE_CURSOR_BIT_ORDER_MSBFIRST) { 353 for (y = pCurs->bits->height, pSrc = DstS, pMsk = DstM; 354 y--; pSrc += DstPitch, pMsk += DstPitch) { 355 for (x = 0; x < Pitch; x++) { 356 pSrc[x] = REVERSE_BIT_ORDER(pSrc[x]); 357 pMsk[x] = REVERSE_BIT_ORDER(pMsk[x]); 358 } 359 } 360 } 361 362 return mem; 363} 364 365static unsigned char * 366RealizeCursorInterleave1(xf86CursorInfoPtr infoPtr, CursorPtr pCurs) 367{ 368 unsigned char *DstS, *DstM; 369 unsigned char *pntr; 370 unsigned char *mem, *mem2; 371 int count; 372 int size = (infoPtr->MaxWidth * infoPtr->MaxHeight) >> 2; 373 374 /* Realize the cursor without interleaving */ 375 if (!(mem2 = RealizeCursorInterleave0(infoPtr, pCurs))) 376 return NULL; 377 378 if (!(mem = calloc(1, size))) { 379 free(mem2); 380 return NULL; 381 } 382 383 /* 1 bit interleave */ 384 DstS = mem2; 385 DstM = DstS + (size >> 1); 386 pntr = mem; 387 count = size; 388 while (count) { 389 *pntr++ = ((*DstS & 0x01)) | ((*DstM & 0x01) << 1) | 390 ((*DstS & 0x02) << 1) | ((*DstM & 0x02) << 2) | 391 ((*DstS & 0x04) << 2) | ((*DstM & 0x04) << 3) | 392 ((*DstS & 0x08) << 3) | ((*DstM & 0x08) << 4); 393 *pntr++ = ((*DstS & 0x10) >> 4) | ((*DstM & 0x10) >> 3) | 394 ((*DstS & 0x20) >> 3) | ((*DstM & 0x20) >> 2) | 395 ((*DstS & 0x40) >> 2) | ((*DstM & 0x40) >> 1) | 396 ((*DstS & 0x80) >> 1) | ((*DstM & 0x80)); 397 DstS++; 398 DstM++; 399 count -= 2; 400 } 401 402 /* Free the uninterleaved cursor */ 403 free(mem2); 404 405 return mem; 406} 407 408static unsigned char * 409RealizeCursorInterleave8(xf86CursorInfoPtr infoPtr, CursorPtr pCurs) 410{ 411 unsigned char *DstS, *DstM; 412 unsigned char *pntr; 413 unsigned char *mem, *mem2; 414 int count; 415 int size = (infoPtr->MaxWidth * infoPtr->MaxHeight) >> 2; 416 417 /* Realize the cursor without interleaving */ 418 if (!(mem2 = RealizeCursorInterleave0(infoPtr, pCurs))) 419 return NULL; 420 421 if (!(mem = calloc(1, size))) { 422 free(mem2); 423 return NULL; 424 } 425 426 /* 8 bit interleave */ 427 DstS = mem2; 428 DstM = DstS + (size >> 1); 429 pntr = mem; 430 count = size; 431 while (count) { 432 *pntr++ = *DstS++; 433 *pntr++ = *DstM++; 434 count -= 2; 435 } 436 437 /* Free the uninterleaved cursor */ 438 free(mem2); 439 440 return mem; 441} 442 443static unsigned char * 444RealizeCursorInterleave16(xf86CursorInfoPtr infoPtr, CursorPtr pCurs) 445{ 446 unsigned short *DstS, *DstM; 447 unsigned short *pntr; 448 unsigned char *mem, *mem2; 449 int count; 450 int size = (infoPtr->MaxWidth * infoPtr->MaxHeight) >> 2; 451 452 /* Realize the cursor without interleaving */ 453 if (!(mem2 = RealizeCursorInterleave0(infoPtr, pCurs))) 454 return NULL; 455 456 if (!(mem = calloc(1, size))) { 457 free(mem2); 458 return NULL; 459 } 460 461 /* 16 bit interleave */ 462 DstS = (void *) mem2; 463 DstM = DstS + (size >> 2); 464 pntr = (void *) mem; 465 count = (size >> 1); 466 while (count) { 467 *pntr++ = *DstS++; 468 *pntr++ = *DstM++; 469 count -= 2; 470 } 471 472 /* Free the uninterleaved cursor */ 473 free(mem2); 474 475 return mem; 476} 477 478static unsigned char * 479RealizeCursorInterleave32(xf86CursorInfoPtr infoPtr, CursorPtr pCurs) 480{ 481 CARD32 *DstS, *DstM; 482 CARD32 *pntr; 483 unsigned char *mem, *mem2; 484 int count; 485 int size = (infoPtr->MaxWidth * infoPtr->MaxHeight) >> 2; 486 487 /* Realize the cursor without interleaving */ 488 if (!(mem2 = RealizeCursorInterleave0(infoPtr, pCurs))) 489 return NULL; 490 491 if (!(mem = calloc(1, size))) { 492 free(mem2); 493 return NULL; 494 } 495 496 /* 32 bit interleave */ 497 DstS = (void *) mem2; 498 DstM = DstS + (size >> 3); 499 pntr = (void *) mem; 500 count = (size >> 2); 501 while (count) { 502 *pntr++ = *DstS++; 503 *pntr++ = *DstM++; 504 count -= 2; 505 } 506 507 /* Free the uninterleaved cursor */ 508 free(mem2); 509 510 return mem; 511} 512 513static unsigned char * 514RealizeCursorInterleave64(xf86CursorInfoPtr infoPtr, CursorPtr pCurs) 515{ 516 CARD32 *DstS, *DstM; 517 CARD32 *pntr; 518 unsigned char *mem, *mem2; 519 int count; 520 int size = (infoPtr->MaxWidth * infoPtr->MaxHeight) >> 2; 521 522 /* Realize the cursor without interleaving */ 523 if (!(mem2 = RealizeCursorInterleave0(infoPtr, pCurs))) 524 return NULL; 525 526 if (!(mem = calloc(1, size))) { 527 free(mem2); 528 return NULL; 529 } 530 531 /* 64 bit interleave */ 532 DstS = (void *) mem2; 533 DstM = DstS + (size >> 3); 534 pntr = (void *) mem; 535 count = (size >> 2); 536 while (count) { 537 *pntr++ = *DstS++; 538 *pntr++ = *DstS++; 539 *pntr++ = *DstM++; 540 *pntr++ = *DstM++; 541 count -= 4; 542 } 543 544 /* Free the uninterleaved cursor */ 545 free(mem2); 546 547 return mem; 548} 549