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