1 2#ifdef HAVE_XORG_CONFIG_H 3#include <xorg-config.h> 4#endif 5 6#include "xf86.h" 7#include "xf86CursorPriv.h" 8#include "colormapst.h" 9#include "cursorstr.h" 10 11/* FIXME: This was added with the ABI change of the miPointerSpriteFuncs for 12 * MPX. 13 * inputInfo is needed to pass the core pointer as the default argument into 14 * the cursor functions. 15 * 16 * Externing inputInfo is not the nice way to do it but it works. 17 */ 18#include "inputstr.h" 19extern InputInfo inputInfo; 20 21DevPrivateKeyRec xf86CursorScreenKeyRec; 22 23/* sprite functions */ 24 25static Bool xf86CursorRealizeCursor(DeviceIntPtr, ScreenPtr, CursorPtr); 26static Bool xf86CursorUnrealizeCursor(DeviceIntPtr, ScreenPtr, CursorPtr); 27static void xf86CursorSetCursor(DeviceIntPtr, ScreenPtr, CursorPtr, int, int); 28static void xf86CursorMoveCursor(DeviceIntPtr, ScreenPtr, int, int); 29static Bool xf86DeviceCursorInitialize(DeviceIntPtr, ScreenPtr); 30static void xf86DeviceCursorCleanup(DeviceIntPtr, ScreenPtr); 31 32static miPointerSpriteFuncRec xf86CursorSpriteFuncs = { 33 xf86CursorRealizeCursor, 34 xf86CursorUnrealizeCursor, 35 xf86CursorSetCursor, 36 xf86CursorMoveCursor, 37 xf86DeviceCursorInitialize, 38 xf86DeviceCursorCleanup 39}; 40 41/* Screen functions */ 42 43static void xf86CursorInstallColormap(ColormapPtr); 44static void xf86CursorRecolorCursor(DeviceIntPtr pDev, ScreenPtr, CursorPtr, Bool); 45static Bool xf86CursorCloseScreen(int, ScreenPtr); 46static void xf86CursorQueryBestSize(int, unsigned short*, unsigned short*, 47 ScreenPtr); 48 49/* ScrnInfoRec functions */ 50 51static void xf86CursorEnableDisableFBAccess(int, Bool); 52static Bool xf86CursorSwitchMode(int, DisplayModePtr,int); 53 54Bool 55xf86InitCursor( 56 ScreenPtr pScreen, 57 xf86CursorInfoPtr infoPtr 58) 59{ 60 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 61 xf86CursorScreenPtr ScreenPriv; 62 miPointerScreenPtr PointPriv; 63 64 if (!xf86InitHardwareCursor(pScreen, infoPtr)) 65 return FALSE; 66 67 if (!dixRegisterPrivateKey(&xf86CursorScreenKeyRec, PRIVATE_SCREEN, 0)) 68 return FALSE; 69 70 ScreenPriv = calloc(1, sizeof(xf86CursorScreenRec)); 71 if (!ScreenPriv) 72 return FALSE; 73 74 dixSetPrivate(&pScreen->devPrivates, xf86CursorScreenKey, ScreenPriv); 75 76 ScreenPriv->SWCursor = TRUE; 77 ScreenPriv->isUp = FALSE; 78 ScreenPriv->CurrentCursor = NULL; 79 ScreenPriv->CursorInfoPtr = infoPtr; 80 ScreenPriv->PalettedCursor = FALSE; 81 ScreenPriv->pInstalledMap = NULL; 82 83 ScreenPriv->CloseScreen = pScreen->CloseScreen; 84 pScreen->CloseScreen = xf86CursorCloseScreen; 85 ScreenPriv->QueryBestSize = pScreen->QueryBestSize; 86 pScreen->QueryBestSize = xf86CursorQueryBestSize; 87 ScreenPriv->RecolorCursor = pScreen->RecolorCursor; 88 pScreen->RecolorCursor = xf86CursorRecolorCursor; 89 90 if ((infoPtr->pScrn->bitsPerPixel == 8) && 91 !(infoPtr->Flags & HARDWARE_CURSOR_TRUECOLOR_AT_8BPP)) { 92 ScreenPriv->InstallColormap = pScreen->InstallColormap; 93 pScreen->InstallColormap = xf86CursorInstallColormap; 94 ScreenPriv->PalettedCursor = TRUE; 95 } 96 97 PointPriv = dixLookupPrivate(&pScreen->devPrivates, miPointerScreenKey); 98 99 ScreenPriv->showTransparent = PointPriv->showTransparent; 100 if (infoPtr->Flags & HARDWARE_CURSOR_SHOW_TRANSPARENT) 101 PointPriv->showTransparent = TRUE; 102 else 103 PointPriv->showTransparent = FALSE; 104 ScreenPriv->spriteFuncs = PointPriv->spriteFuncs; 105 PointPriv->spriteFuncs = &xf86CursorSpriteFuncs; 106 107 ScreenPriv->EnableDisableFBAccess = pScrn->EnableDisableFBAccess; 108 ScreenPriv->SwitchMode = pScrn->SwitchMode; 109 110 ScreenPriv->ForceHWCursorCount = 0; 111 ScreenPriv->HWCursorForced = FALSE; 112 113 pScrn->EnableDisableFBAccess = xf86CursorEnableDisableFBAccess; 114 if (pScrn->SwitchMode) 115 pScrn->SwitchMode = xf86CursorSwitchMode; 116 117 return TRUE; 118} 119 120/***** Screen functions *****/ 121 122static Bool 123xf86CursorCloseScreen(int i, ScreenPtr pScreen) 124{ 125 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 126 miPointerScreenPtr PointPriv = (miPointerScreenPtr)dixLookupPrivate( 127 &pScreen->devPrivates, miPointerScreenKey); 128 xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate( 129 &pScreen->devPrivates, xf86CursorScreenKey); 130 131 if (ScreenPriv->isUp && pScrn->vtSema) 132 xf86SetCursor(pScreen, NullCursor, ScreenPriv->x, ScreenPriv->y); 133 134 if (ScreenPriv->CurrentCursor) 135 FreeCursor(ScreenPriv->CurrentCursor, None); 136 137 pScreen->CloseScreen = ScreenPriv->CloseScreen; 138 pScreen->QueryBestSize = ScreenPriv->QueryBestSize; 139 pScreen->RecolorCursor = ScreenPriv->RecolorCursor; 140 if (ScreenPriv->InstallColormap) 141 pScreen->InstallColormap = ScreenPriv->InstallColormap; 142 143 PointPriv->spriteFuncs = ScreenPriv->spriteFuncs; 144 PointPriv->showTransparent = ScreenPriv->showTransparent; 145 146 pScrn->EnableDisableFBAccess = ScreenPriv->EnableDisableFBAccess; 147 pScrn->SwitchMode = ScreenPriv->SwitchMode; 148 149 free(ScreenPriv->transparentData); 150 free(ScreenPriv); 151 152 return (*pScreen->CloseScreen)(i, pScreen); 153} 154 155static void 156xf86CursorQueryBestSize( 157 int class, 158 unsigned short *width, 159 unsigned short *height, 160 ScreenPtr pScreen) 161{ 162 xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate( 163 &pScreen->devPrivates, xf86CursorScreenKey); 164 165 if (class == CursorShape) { 166 if(*width > ScreenPriv->CursorInfoPtr->MaxWidth) 167 *width = ScreenPriv->CursorInfoPtr->MaxWidth; 168 if(*height > ScreenPriv->CursorInfoPtr->MaxHeight) 169 *height = ScreenPriv->CursorInfoPtr->MaxHeight; 170 } else 171 (*ScreenPriv->QueryBestSize)(class, width, height, pScreen); 172} 173 174static void 175xf86CursorInstallColormap(ColormapPtr pMap) 176{ 177 xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate( 178 &pMap->pScreen->devPrivates, xf86CursorScreenKey); 179 180 ScreenPriv->pInstalledMap = pMap; 181 182 (*ScreenPriv->InstallColormap)(pMap); 183} 184 185static void 186xf86CursorRecolorCursor( 187 DeviceIntPtr pDev, 188 ScreenPtr pScreen, 189 CursorPtr pCurs, 190 Bool displayed) 191{ 192 xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate( 193 &pScreen->devPrivates, xf86CursorScreenKey); 194 195 if (!displayed) 196 return; 197 198 if (ScreenPriv->SWCursor) 199 (*ScreenPriv->RecolorCursor)(pDev, pScreen, pCurs, displayed); 200 else 201 xf86RecolorCursor(pScreen, pCurs, displayed); 202} 203 204/***** ScrnInfoRec functions *********/ 205 206static void 207xf86CursorEnableDisableFBAccess( 208 int index, 209 Bool enable) 210{ 211 DeviceIntPtr pDev = inputInfo.pointer; 212 213 ScreenPtr pScreen = screenInfo.screens[index]; 214 xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate( 215 &pScreen->devPrivates, xf86CursorScreenKey); 216 217 if (!enable && ScreenPriv->CurrentCursor != NullCursor) { 218 CursorPtr currentCursor = ScreenPriv->CurrentCursor; 219 xf86CursorSetCursor(pDev, pScreen, NullCursor, ScreenPriv->x, 220 ScreenPriv->y); 221 ScreenPriv->isUp = FALSE; 222 ScreenPriv->SWCursor = TRUE; 223 ScreenPriv->SavedCursor = currentCursor; 224 } 225 226 if (ScreenPriv->EnableDisableFBAccess) 227 (*ScreenPriv->EnableDisableFBAccess)(index, enable); 228 229 if (enable && ScreenPriv->SavedCursor) 230 { 231 /* 232 * Re-set current cursor so drivers can react to FB access having been 233 * temporarily disabled. 234 */ 235 xf86CursorSetCursor(pDev, pScreen, ScreenPriv->SavedCursor, 236 ScreenPriv->x, ScreenPriv->y); 237 ScreenPriv->SavedCursor = NULL; 238 } 239} 240 241static Bool 242xf86CursorSwitchMode(int index, DisplayModePtr mode, int flags) 243{ 244 Bool ret; 245 ScreenPtr pScreen = screenInfo.screens[index]; 246 xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate( 247 &pScreen->devPrivates, xf86CursorScreenKey); 248 249 if (ScreenPriv->isUp) { 250 xf86SetCursor(pScreen, NullCursor, ScreenPriv->x, ScreenPriv->y); 251 ScreenPriv->isUp = FALSE; 252 } 253 254 ret = (*ScreenPriv->SwitchMode)(index, mode, flags); 255 256 /* 257 * Cannot restore cursor here because the new frame[XY][01] haven't been 258 * calculated yet. However, because the hardware cursor was removed above, 259 * ensure the cursor is repainted by miPointerWarpCursor(). 260 */ 261 ScreenPriv->CursorToRestore = ScreenPriv->CurrentCursor; 262 miPointerSetWaitForUpdate(pScreen, FALSE); /* Force cursor repaint */ 263 264 return ret; 265} 266 267/****** miPointerSpriteFunctions *******/ 268 269static Bool 270xf86CursorRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCurs) 271{ 272 xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate( 273 &pScreen->devPrivates, xf86CursorScreenKey); 274 275 if (pCurs->refcnt <= 1) 276 dixSetPrivate(&pCurs->devPrivates, CursorScreenKey(pScreen), NULL); 277 278 return (*ScreenPriv->spriteFuncs->RealizeCursor)(pDev, pScreen, pCurs); 279} 280 281static Bool 282xf86CursorUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, 283 CursorPtr pCurs) 284{ 285 xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate( 286 &pScreen->devPrivates, xf86CursorScreenKey); 287 288 if (pCurs->refcnt <= 1) { 289 free(dixLookupPrivate(&pCurs->devPrivates, CursorScreenKey(pScreen))); 290 dixSetPrivate(&pCurs->devPrivates, CursorScreenKey(pScreen), NULL); 291 } 292 293 return (*ScreenPriv->spriteFuncs->UnrealizeCursor)(pDev, pScreen, pCurs); 294} 295 296static void 297xf86CursorSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCurs, 298 int x, int y) 299{ 300 xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate( 301 &pScreen->devPrivates, xf86CursorScreenKey); 302 xf86CursorInfoPtr infoPtr = ScreenPriv->CursorInfoPtr; 303 304 if (pCurs == NullCursor) { /* means we're supposed to remove the cursor */ 305 if (ScreenPriv->SWCursor || 306 !(GetMaster(pDev, MASTER_POINTER) == inputInfo.pointer)) 307 (*ScreenPriv->spriteFuncs->SetCursor)(pDev, pScreen, NullCursor, x, y); 308 else if (ScreenPriv->isUp) { 309 xf86SetCursor(pScreen, NullCursor, x, y); 310 ScreenPriv->isUp = FALSE; 311 } 312 if (ScreenPriv->CurrentCursor) 313 FreeCursor(ScreenPriv->CurrentCursor, None); 314 ScreenPriv->CurrentCursor = NullCursor; 315 return; 316 } 317 318 /* only update for VCP, otherwise we get cursor jumps when removing a 319 sprite. The second cursor is never HW rendered anyway. */ 320 if (pDev == inputInfo.pointer || 321 (!IsMaster(pDev) && pDev->u.master == inputInfo.pointer)) 322 { 323 pCurs->refcnt++; 324 if (ScreenPriv->CurrentCursor) 325 FreeCursor(ScreenPriv->CurrentCursor, None); 326 ScreenPriv->CurrentCursor = pCurs; 327 ScreenPriv->x = x; 328 ScreenPriv->y = y; 329 ScreenPriv->CursorToRestore = NULL; 330 ScreenPriv->HotX = pCurs->bits->xhot; 331 ScreenPriv->HotY = pCurs->bits->yhot; 332 333 if (!infoPtr->pScrn->vtSema) 334 ScreenPriv->SavedCursor = pCurs; 335 336 if (infoPtr->pScrn->vtSema && (ScreenPriv->ForceHWCursorCount || (( 337#ifdef ARGB_CURSOR 338 pCurs->bits->argb && infoPtr->UseHWCursorARGB && 339 (*infoPtr->UseHWCursorARGB) (pScreen, pCurs) ) || ( 340 pCurs->bits->argb == 0 && 341#endif 342 (pCurs->bits->height <= infoPtr->MaxHeight) && 343 (pCurs->bits->width <= infoPtr->MaxWidth) && 344 (!infoPtr->UseHWCursor || (*infoPtr->UseHWCursor)(pScreen, pCurs)))))) 345 { 346 347 if (ScreenPriv->SWCursor) /* remove the SW cursor */ 348 (*ScreenPriv->spriteFuncs->SetCursor)(pDev, pScreen, NullCursor, x, y); 349 350 xf86SetCursor(pScreen, pCurs, x, y); 351 ScreenPriv->SWCursor = FALSE; 352 ScreenPriv->isUp = TRUE; 353 354 miPointerSetWaitForUpdate(pScreen, !infoPtr->pScrn->silkenMouse); 355 return; 356 } 357 358 miPointerSetWaitForUpdate(pScreen, TRUE); 359 360 if (ScreenPriv->isUp) { 361 /* Remove the HW cursor, or make it transparent */ 362 if (infoPtr->Flags & HARDWARE_CURSOR_SHOW_TRANSPARENT) { 363 xf86SetTransparentCursor(pScreen); 364 } else { 365 xf86SetCursor(pScreen, NullCursor, x, y); 366 ScreenPriv->isUp = FALSE; 367 } 368 } 369 370 if (!ScreenPriv->SWCursor) 371 ScreenPriv->SWCursor = TRUE; 372 373 } 374 375 if (pCurs->bits->emptyMask && !ScreenPriv->showTransparent) 376 pCurs = NullCursor; 377 378 (*ScreenPriv->spriteFuncs->SetCursor)(pDev, pScreen, pCurs, x, y); 379} 380 381static void 382xf86CursorMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) 383{ 384 xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate( 385 &pScreen->devPrivates, xf86CursorScreenKey); 386 387 /* only update coordinate state for first sprite, otherwise we get jumps 388 when removing a sprite. The second sprite is never HW rendered anyway */ 389 if (pDev == inputInfo.pointer || 390 (!IsMaster(pDev) && pDev->u.master == inputInfo.pointer)) 391 { 392 ScreenPriv->x = x; 393 ScreenPriv->y = y; 394 395 if (ScreenPriv->CursorToRestore) 396 xf86CursorSetCursor(pDev, pScreen, ScreenPriv->CursorToRestore, x, y); 397 else if (ScreenPriv->SWCursor) 398 (*ScreenPriv->spriteFuncs->MoveCursor)(pDev, pScreen, x, y); 399 else if (ScreenPriv->isUp) 400 xf86MoveCursor(pScreen, x, y); 401 } else 402 (*ScreenPriv->spriteFuncs->MoveCursor)(pDev, pScreen, x, y); 403} 404 405void 406xf86ForceHWCursor (ScreenPtr pScreen, Bool on) 407{ 408 DeviceIntPtr pDev = inputInfo.pointer; 409 xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate( 410 &pScreen->devPrivates, xf86CursorScreenKey); 411 412 if (on) 413 { 414 if (ScreenPriv->ForceHWCursorCount++ == 0) 415 { 416 if (ScreenPriv->SWCursor && ScreenPriv->CurrentCursor) 417 { 418 ScreenPriv->HWCursorForced = TRUE; 419 xf86CursorSetCursor (pDev, pScreen, ScreenPriv->CurrentCursor, 420 ScreenPriv->x, ScreenPriv->y); 421 } 422 else 423 ScreenPriv->HWCursorForced = FALSE; 424 } 425 } 426 else 427 { 428 if (--ScreenPriv->ForceHWCursorCount == 0) 429 { 430 if (ScreenPriv->HWCursorForced && ScreenPriv->CurrentCursor) 431 xf86CursorSetCursor (pDev, pScreen, ScreenPriv->CurrentCursor, 432 ScreenPriv->x, ScreenPriv->y); 433 } 434 } 435} 436 437xf86CursorInfoPtr 438xf86CreateCursorInfoRec(void) 439{ 440 return calloc(1, sizeof(xf86CursorInfoRec)); 441} 442 443void 444xf86DestroyCursorInfoRec(xf86CursorInfoPtr infoPtr) 445{ 446 free(infoPtr); 447} 448 449/** 450 * New cursor has been created. Do your initalizations here. 451 */ 452static Bool 453xf86DeviceCursorInitialize(DeviceIntPtr pDev, ScreenPtr pScreen) 454{ 455 int ret; 456 xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate( 457 &pScreen->devPrivates, xf86CursorScreenKey); 458 459 /* Init SW cursor */ 460 ret = (*ScreenPriv->spriteFuncs->DeviceCursorInitialize)(pDev, pScreen); 461 462 return ret; 463} 464 465/** 466 * Cursor has been removed. Clean up after yourself. 467 */ 468static void 469xf86DeviceCursorCleanup(DeviceIntPtr pDev, ScreenPtr pScreen) 470{ 471 xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate( 472 &pScreen->devPrivates, xf86CursorScreenKey); 473 474 /* Clean up SW cursor */ 475 (*ScreenPriv->spriteFuncs->DeviceCursorCleanup)(pDev, pScreen); 476} 477 478 479/* Re-set the current cursor. This will switch between hardware and software 480 * cursor depending on whether hardware cursor is currently supported 481 * according to the driver. 482 */ 483void 484xf86CursorResetCursor(ScreenPtr pScreen) 485{ 486 xf86CursorScreenPtr ScreenPriv; 487 488 if (!inputInfo.pointer) 489 return; 490 491 if (!dixPrivateKeyRegistered(xf86CursorScreenKey)) 492 return; 493 494 ScreenPriv = (xf86CursorScreenPtr) dixLookupPrivate(&pScreen->devPrivates, 495 xf86CursorScreenKey); 496 if (!ScreenPriv) 497 return; 498 499 xf86CursorSetCursor(inputInfo.pointer, pScreen, ScreenPriv->CurrentCursor, 500 ScreenPriv->x, ScreenPriv->y); 501} 502