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