misprite.c revision 05b261ec
1/* 2 * misprite.c 3 * 4 * machine independent software sprite routines 5 */ 6 7 8/* 9 10Copyright 1989, 1998 The Open Group 11 12Permission to use, copy, modify, distribute, and sell this software and its 13documentation for any purpose is hereby granted without fee, provided that 14the above copyright notice appear in all copies and that both that 15copyright notice and this permission notice appear in supporting 16documentation. 17 18The above copyright notice and this permission notice shall be included in 19all copies or substantial portions of the Software. 20 21THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 25AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 26CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27 28Except as contained in this notice, the name of The Open Group shall not be 29used in advertising or otherwise to promote the sale, use or other dealings 30in this Software without prior written authorization from The Open Group. 31*/ 32 33#ifdef HAVE_DIX_CONFIG_H 34#include <dix-config.h> 35#endif 36 37# include <X11/X.h> 38# include <X11/Xproto.h> 39# include "misc.h" 40# include "pixmapstr.h" 41# include "input.h" 42# include "mi.h" 43# include "cursorstr.h" 44# include <X11/fonts/font.h> 45# include "scrnintstr.h" 46# include "colormapst.h" 47# include "windowstr.h" 48# include "gcstruct.h" 49# include "mipointer.h" 50# include "mispritest.h" 51# include "dixfontstr.h" 52# include <X11/fonts/fontstruct.h> 53 54#ifdef RENDER 55# include "mipict.h" 56#endif 57# include "damage.h" 58 59#define SPRITE_DEBUG_ENABLE 0 60#if SPRITE_DEBUG_ENABLE 61#define SPRITE_DEBUG(x) ErrorF x 62#else 63#define SPRITE_DEBUG(x) 64#endif 65 66/* 67 * screen wrappers 68 */ 69 70static int miSpriteScreenIndex; 71static unsigned long miSpriteGeneration = 0; 72 73static Bool miSpriteCloseScreen(int i, ScreenPtr pScreen); 74static void miSpriteGetImage(DrawablePtr pDrawable, int sx, int sy, 75 int w, int h, unsigned int format, 76 unsigned long planemask, char *pdstLine); 77static void miSpriteGetSpans(DrawablePtr pDrawable, int wMax, 78 DDXPointPtr ppt, int *pwidth, int nspans, 79 char *pdstStart); 80static void miSpriteSourceValidate(DrawablePtr pDrawable, int x, int y, 81 int width, int height); 82static void miSpriteCopyWindow (WindowPtr pWindow, 83 DDXPointRec ptOldOrg, 84 RegionPtr prgnSrc); 85static void miSpriteBlockHandler(int i, pointer blockData, 86 pointer pTimeout, 87 pointer pReadMask); 88static void miSpriteInstallColormap(ColormapPtr pMap); 89static void miSpriteStoreColors(ColormapPtr pMap, int ndef, 90 xColorItem *pdef); 91 92static void miSpriteSaveDoomedAreas(WindowPtr pWin, 93 RegionPtr pObscured, int dx, 94 int dy); 95static void miSpriteComputeSaved(ScreenPtr pScreen); 96 97#define SCREEN_PROLOGUE(pScreen, field)\ 98 ((pScreen)->field = \ 99 ((miSpriteScreenPtr) (pScreen)->devPrivates[miSpriteScreenIndex].ptr)->field) 100 101#define SCREEN_EPILOGUE(pScreen, field)\ 102 ((pScreen)->field = miSprite##field) 103 104/* 105 * pointer-sprite method table 106 */ 107 108static Bool miSpriteRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor); 109static Bool miSpriteUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCursor); 110static void miSpriteSetCursor(ScreenPtr pScreen, CursorPtr pCursor, 111 int x, int y); 112static void miSpriteMoveCursor(ScreenPtr pScreen, int x, int y); 113 114_X_EXPORT miPointerSpriteFuncRec miSpritePointerFuncs = { 115 miSpriteRealizeCursor, 116 miSpriteUnrealizeCursor, 117 miSpriteSetCursor, 118 miSpriteMoveCursor, 119}; 120 121/* 122 * other misc functions 123 */ 124 125static void miSpriteRemoveCursor(ScreenPtr pScreen); 126static void miSpriteRestoreCursor(ScreenPtr pScreen); 127 128static void 129miSpriteReportDamage (DamagePtr pDamage, RegionPtr pRegion, void *closure) 130{ 131 ScreenPtr pScreen = closure; 132 miSpriteScreenPtr pScreenPriv; 133 134 pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr; 135 136 if (pScreenPriv->isUp && 137 RECT_IN_REGION (pScreen, pRegion, &pScreenPriv->saved) != rgnOUT) 138 { 139 SPRITE_DEBUG(("Damage remove\n")); 140 miSpriteRemoveCursor (pScreen); 141 } 142} 143 144/* 145 * miSpriteInitialize -- called from device-dependent screen 146 * initialization proc after all of the function pointers have 147 * been stored in the screen structure. 148 */ 149 150Bool 151miSpriteInitialize (pScreen, cursorFuncs, screenFuncs) 152 ScreenPtr pScreen; 153 miSpriteCursorFuncPtr cursorFuncs; 154 miPointerScreenFuncPtr screenFuncs; 155{ 156 miSpriteScreenPtr pScreenPriv; 157 VisualPtr pVisual; 158 159 if (!DamageSetup (pScreen)) 160 return FALSE; 161 162 if (miSpriteGeneration != serverGeneration) 163 { 164 miSpriteScreenIndex = AllocateScreenPrivateIndex (); 165 if (miSpriteScreenIndex < 0) 166 return FALSE; 167 miSpriteGeneration = serverGeneration; 168 } 169 170 pScreenPriv = (miSpriteScreenPtr) xalloc (sizeof (miSpriteScreenRec)); 171 if (!pScreenPriv) 172 return FALSE; 173 174 pScreenPriv->pDamage = DamageCreate (miSpriteReportDamage, 175 (DamageDestroyFunc) 0, 176 DamageReportRawRegion, 177 TRUE, 178 pScreen, 179 (void *) pScreen); 180 181 if (!miPointerInitialize (pScreen, &miSpritePointerFuncs, screenFuncs,TRUE)) 182 { 183 xfree ((pointer) pScreenPriv); 184 return FALSE; 185 } 186 for (pVisual = pScreen->visuals; 187 pVisual->vid != pScreen->rootVisual; 188 pVisual++) 189 ; 190 pScreenPriv->pVisual = pVisual; 191 pScreenPriv->CloseScreen = pScreen->CloseScreen; 192 pScreenPriv->GetImage = pScreen->GetImage; 193 pScreenPriv->GetSpans = pScreen->GetSpans; 194 pScreenPriv->SourceValidate = pScreen->SourceValidate; 195 196 pScreenPriv->CopyWindow = pScreen->CopyWindow; 197 198 pScreenPriv->SaveDoomedAreas = pScreen->SaveDoomedAreas; 199 200 pScreenPriv->InstallColormap = pScreen->InstallColormap; 201 pScreenPriv->StoreColors = pScreen->StoreColors; 202 203 pScreenPriv->BlockHandler = pScreen->BlockHandler; 204 205 pScreenPriv->pCursor = NULL; 206 pScreenPriv->x = 0; 207 pScreenPriv->y = 0; 208 pScreenPriv->isUp = FALSE; 209 pScreenPriv->shouldBeUp = FALSE; 210 pScreenPriv->pCacheWin = NullWindow; 211 pScreenPriv->isInCacheWin = FALSE; 212 pScreenPriv->checkPixels = TRUE; 213 pScreenPriv->pInstalledMap = NULL; 214 pScreenPriv->pColormap = NULL; 215 pScreenPriv->funcs = cursorFuncs; 216 pScreenPriv->colors[SOURCE_COLOR].red = 0; 217 pScreenPriv->colors[SOURCE_COLOR].green = 0; 218 pScreenPriv->colors[SOURCE_COLOR].blue = 0; 219 pScreenPriv->colors[MASK_COLOR].red = 0; 220 pScreenPriv->colors[MASK_COLOR].green = 0; 221 pScreenPriv->colors[MASK_COLOR].blue = 0; 222 pScreen->devPrivates[miSpriteScreenIndex].ptr = (pointer) pScreenPriv; 223 224 pScreen->CloseScreen = miSpriteCloseScreen; 225 pScreen->GetImage = miSpriteGetImage; 226 pScreen->GetSpans = miSpriteGetSpans; 227 pScreen->SourceValidate = miSpriteSourceValidate; 228 229 pScreen->CopyWindow = miSpriteCopyWindow; 230 231 pScreen->SaveDoomedAreas = miSpriteSaveDoomedAreas; 232 233 pScreen->InstallColormap = miSpriteInstallColormap; 234 pScreen->StoreColors = miSpriteStoreColors; 235 236 pScreen->BlockHandler = miSpriteBlockHandler; 237 238 return TRUE; 239} 240 241/* 242 * Screen wrappers 243 */ 244 245/* 246 * CloseScreen wrapper -- unwrap everything, free the private data 247 * and call the wrapped function 248 */ 249 250static Bool 251miSpriteCloseScreen (i, pScreen) 252 int i; 253 ScreenPtr pScreen; 254{ 255 miSpriteScreenPtr pScreenPriv; 256 257 pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr; 258 259 pScreen->CloseScreen = pScreenPriv->CloseScreen; 260 pScreen->GetImage = pScreenPriv->GetImage; 261 pScreen->GetSpans = pScreenPriv->GetSpans; 262 pScreen->SourceValidate = pScreenPriv->SourceValidate; 263 pScreen->BlockHandler = pScreenPriv->BlockHandler; 264 pScreen->InstallColormap = pScreenPriv->InstallColormap; 265 pScreen->StoreColors = pScreenPriv->StoreColors; 266 267 pScreen->SaveDoomedAreas = pScreenPriv->SaveDoomedAreas; 268 miSpriteIsUpFALSE (pScreen, pScreenPriv); 269 DamageDestroy (pScreenPriv->pDamage); 270 271 xfree ((pointer) pScreenPriv); 272 273 return (*pScreen->CloseScreen) (i, pScreen); 274} 275 276static void 277miSpriteGetImage (pDrawable, sx, sy, w, h, format, planemask, pdstLine) 278 DrawablePtr pDrawable; 279 int sx, sy, w, h; 280 unsigned int format; 281 unsigned long planemask; 282 char *pdstLine; 283{ 284 ScreenPtr pScreen = pDrawable->pScreen; 285 miSpriteScreenPtr pScreenPriv; 286 287 SCREEN_PROLOGUE (pScreen, GetImage); 288 289 pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr; 290 291 if (pDrawable->type == DRAWABLE_WINDOW && 292 pScreenPriv->isUp && 293 ORG_OVERLAP(&pScreenPriv->saved,pDrawable->x,pDrawable->y, sx, sy, w, h)) 294 { 295 SPRITE_DEBUG (("GetImage remove\n")); 296 miSpriteRemoveCursor (pScreen); 297 } 298 299 (*pScreen->GetImage) (pDrawable, sx, sy, w, h, 300 format, planemask, pdstLine); 301 302 SCREEN_EPILOGUE (pScreen, GetImage); 303} 304 305static void 306miSpriteGetSpans (pDrawable, wMax, ppt, pwidth, nspans, pdstStart) 307 DrawablePtr pDrawable; 308 int wMax; 309 DDXPointPtr ppt; 310 int *pwidth; 311 int nspans; 312 char *pdstStart; 313{ 314 ScreenPtr pScreen = pDrawable->pScreen; 315 miSpriteScreenPtr pScreenPriv; 316 317 SCREEN_PROLOGUE (pScreen, GetSpans); 318 319 pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr; 320 321 if (pDrawable->type == DRAWABLE_WINDOW && pScreenPriv->isUp) 322 { 323 DDXPointPtr pts; 324 int *widths; 325 int nPts; 326 int xorg, 327 yorg; 328 329 xorg = pDrawable->x; 330 yorg = pDrawable->y; 331 332 for (pts = ppt, widths = pwidth, nPts = nspans; 333 nPts--; 334 pts++, widths++) 335 { 336 if (SPN_OVERLAP(&pScreenPriv->saved,pts->y+yorg, 337 pts->x+xorg,*widths)) 338 { 339 SPRITE_DEBUG (("GetSpans remove\n")); 340 miSpriteRemoveCursor (pScreen); 341 break; 342 } 343 } 344 } 345 346 (*pScreen->GetSpans) (pDrawable, wMax, ppt, pwidth, nspans, pdstStart); 347 348 SCREEN_EPILOGUE (pScreen, GetSpans); 349} 350 351static void 352miSpriteSourceValidate (pDrawable, x, y, width, height) 353 DrawablePtr pDrawable; 354 int x, y, width, height; 355{ 356 ScreenPtr pScreen = pDrawable->pScreen; 357 miSpriteScreenPtr pScreenPriv; 358 359 SCREEN_PROLOGUE (pScreen, SourceValidate); 360 361 pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr; 362 363 if (pDrawable->type == DRAWABLE_WINDOW && pScreenPriv->isUp && 364 ORG_OVERLAP(&pScreenPriv->saved, pDrawable->x, pDrawable->y, 365 x, y, width, height)) 366 { 367 SPRITE_DEBUG (("SourceValidate remove\n")); 368 miSpriteRemoveCursor (pScreen); 369 } 370 371 if (pScreen->SourceValidate) 372 (*pScreen->SourceValidate) (pDrawable, x, y, width, height); 373 374 SCREEN_EPILOGUE (pScreen, SourceValidate); 375} 376 377static void 378miSpriteCopyWindow (WindowPtr pWindow, DDXPointRec ptOldOrg, RegionPtr prgnSrc) 379{ 380 ScreenPtr pScreen = pWindow->drawable.pScreen; 381 miSpriteScreenPtr pScreenPriv; 382 383 SCREEN_PROLOGUE (pScreen, CopyWindow); 384 385 pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr; 386 /* 387 * Damage will take care of destination check 388 */ 389 if (pScreenPriv->isUp && 390 RECT_IN_REGION (pScreen, prgnSrc, &pScreenPriv->saved) != rgnOUT) 391 { 392 SPRITE_DEBUG (("CopyWindow remove\n")); 393 miSpriteRemoveCursor (pScreen); 394 } 395 396 (*pScreen->CopyWindow) (pWindow, ptOldOrg, prgnSrc); 397 SCREEN_EPILOGUE (pScreen, CopyWindow); 398} 399 400static void 401miSpriteBlockHandler (i, blockData, pTimeout, pReadmask) 402 int i; 403 pointer blockData; 404 pointer pTimeout; 405 pointer pReadmask; 406{ 407 ScreenPtr pScreen = screenInfo.screens[i]; 408 miSpriteScreenPtr pPriv; 409 410 pPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr; 411 412 SCREEN_PROLOGUE(pScreen, BlockHandler); 413 414 (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask); 415 416 SCREEN_EPILOGUE(pScreen, BlockHandler); 417 418 if (!pPriv->isUp && pPriv->shouldBeUp) 419 { 420 SPRITE_DEBUG (("BlockHandler restore\n")); 421 miSpriteRestoreCursor (pScreen); 422 } 423} 424 425static void 426miSpriteInstallColormap (pMap) 427 ColormapPtr pMap; 428{ 429 ScreenPtr pScreen = pMap->pScreen; 430 miSpriteScreenPtr pPriv; 431 432 pPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr; 433 434 SCREEN_PROLOGUE(pScreen, InstallColormap); 435 436 (*pScreen->InstallColormap) (pMap); 437 438 SCREEN_EPILOGUE(pScreen, InstallColormap); 439 440 pPriv->pInstalledMap = pMap; 441 if (pPriv->pColormap != pMap) 442 { 443 pPriv->checkPixels = TRUE; 444 if (pPriv->isUp) 445 miSpriteRemoveCursor (pScreen); 446 } 447} 448 449static void 450miSpriteStoreColors (pMap, ndef, pdef) 451 ColormapPtr pMap; 452 int ndef; 453 xColorItem *pdef; 454{ 455 ScreenPtr pScreen = pMap->pScreen; 456 miSpriteScreenPtr pPriv; 457 int i; 458 int updated; 459 VisualPtr pVisual; 460 461 pPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr; 462 463 SCREEN_PROLOGUE(pScreen, StoreColors); 464 465 (*pScreen->StoreColors) (pMap, ndef, pdef); 466 467 SCREEN_EPILOGUE(pScreen, StoreColors); 468 469 if (pPriv->pColormap == pMap) 470 { 471 updated = 0; 472 pVisual = pMap->pVisual; 473 if (pVisual->class == DirectColor) 474 { 475 /* Direct color - match on any of the subfields */ 476 477#define MaskMatch(a,b,mask) (((a) & (pVisual->mask)) == ((b) & (pVisual->mask))) 478 479#define UpdateDAC(plane,dac,mask) {\ 480 if (MaskMatch (pPriv->colors[plane].pixel,pdef[i].pixel,mask)) {\ 481 pPriv->colors[plane].dac = pdef[i].dac; \ 482 updated = 1; \ 483 } \ 484} 485 486#define CheckDirect(plane) \ 487 UpdateDAC(plane,red,redMask) \ 488 UpdateDAC(plane,green,greenMask) \ 489 UpdateDAC(plane,blue,blueMask) 490 491 for (i = 0; i < ndef; i++) 492 { 493 CheckDirect (SOURCE_COLOR) 494 CheckDirect (MASK_COLOR) 495 } 496 } 497 else 498 { 499 /* PseudoColor/GrayScale - match on exact pixel */ 500 for (i = 0; i < ndef; i++) 501 { 502 if (pdef[i].pixel == pPriv->colors[SOURCE_COLOR].pixel) 503 { 504 pPriv->colors[SOURCE_COLOR] = pdef[i]; 505 if (++updated == 2) 506 break; 507 } 508 if (pdef[i].pixel == pPriv->colors[MASK_COLOR].pixel) 509 { 510 pPriv->colors[MASK_COLOR] = pdef[i]; 511 if (++updated == 2) 512 break; 513 } 514 } 515 } 516 if (updated) 517 { 518 pPriv->checkPixels = TRUE; 519 if (pPriv->isUp) 520 miSpriteRemoveCursor (pScreen); 521 } 522 } 523} 524 525static void 526miSpriteFindColors (ScreenPtr pScreen) 527{ 528 miSpriteScreenPtr pScreenPriv = (miSpriteScreenPtr) 529 pScreen->devPrivates[miSpriteScreenIndex].ptr; 530 CursorPtr pCursor; 531 xColorItem *sourceColor, *maskColor; 532 533 pCursor = pScreenPriv->pCursor; 534 sourceColor = &pScreenPriv->colors[SOURCE_COLOR]; 535 maskColor = &pScreenPriv->colors[MASK_COLOR]; 536 if (pScreenPriv->pColormap != pScreenPriv->pInstalledMap || 537 !(pCursor->foreRed == sourceColor->red && 538 pCursor->foreGreen == sourceColor->green && 539 pCursor->foreBlue == sourceColor->blue && 540 pCursor->backRed == maskColor->red && 541 pCursor->backGreen == maskColor->green && 542 pCursor->backBlue == maskColor->blue)) 543 { 544 pScreenPriv->pColormap = pScreenPriv->pInstalledMap; 545 sourceColor->red = pCursor->foreRed; 546 sourceColor->green = pCursor->foreGreen; 547 sourceColor->blue = pCursor->foreBlue; 548 FakeAllocColor (pScreenPriv->pColormap, sourceColor); 549 maskColor->red = pCursor->backRed; 550 maskColor->green = pCursor->backGreen; 551 maskColor->blue = pCursor->backBlue; 552 FakeAllocColor (pScreenPriv->pColormap, maskColor); 553 /* "free" the pixels right away, don't let this confuse you */ 554 FakeFreeColor(pScreenPriv->pColormap, sourceColor->pixel); 555 FakeFreeColor(pScreenPriv->pColormap, maskColor->pixel); 556 } 557 pScreenPriv->checkPixels = FALSE; 558} 559 560/* 561 * BackingStore wrappers 562 */ 563 564static void 565miSpriteSaveDoomedAreas (pWin, pObscured, dx, dy) 566 WindowPtr pWin; 567 RegionPtr pObscured; 568 int dx, dy; 569{ 570 ScreenPtr pScreen; 571 miSpriteScreenPtr pScreenPriv; 572 BoxRec cursorBox; 573 574 pScreen = pWin->drawable.pScreen; 575 576 SCREEN_PROLOGUE (pScreen, SaveDoomedAreas); 577 578 pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr; 579 if (pScreenPriv->isUp) 580 { 581 cursorBox = pScreenPriv->saved; 582 583 if (dx || dy) 584 { 585 cursorBox.x1 += dx; 586 cursorBox.y1 += dy; 587 cursorBox.x2 += dx; 588 cursorBox.y2 += dy; 589 } 590 if (RECT_IN_REGION( pScreen, pObscured, &cursorBox) != rgnOUT) 591 miSpriteRemoveCursor (pScreen); 592 } 593 594 (*pScreen->SaveDoomedAreas) (pWin, pObscured, dx, dy); 595 596 SCREEN_EPILOGUE (pScreen, SaveDoomedAreas); 597} 598 599/* 600 * miPointer interface routines 601 */ 602 603#define SPRITE_PAD 8 604 605static Bool 606miSpriteRealizeCursor (pScreen, pCursor) 607 ScreenPtr pScreen; 608 CursorPtr pCursor; 609{ 610 miSpriteScreenPtr pScreenPriv; 611 612 pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr; 613 if (pCursor == pScreenPriv->pCursor) 614 pScreenPriv->checkPixels = TRUE; 615 return (*pScreenPriv->funcs->RealizeCursor) (pScreen, pCursor); 616} 617 618static Bool 619miSpriteUnrealizeCursor (pScreen, pCursor) 620 ScreenPtr pScreen; 621 CursorPtr pCursor; 622{ 623 miSpriteScreenPtr pScreenPriv; 624 625 pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr; 626 return (*pScreenPriv->funcs->UnrealizeCursor) (pScreen, pCursor); 627} 628 629static void 630miSpriteSetCursor (pScreen, pCursor, x, y) 631 ScreenPtr pScreen; 632 CursorPtr pCursor; 633 int x; 634 int y; 635{ 636 miSpriteScreenPtr pScreenPriv; 637 638 pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr; 639 if (!pCursor) 640 { 641 pScreenPriv->shouldBeUp = FALSE; 642 if (pScreenPriv->isUp) 643 miSpriteRemoveCursor (pScreen); 644 pScreenPriv->pCursor = 0; 645 return; 646 } 647 pScreenPriv->shouldBeUp = TRUE; 648 if (pScreenPriv->x == x && 649 pScreenPriv->y == y && 650 pScreenPriv->pCursor == pCursor && 651 !pScreenPriv->checkPixels) 652 { 653 return; 654 } 655 pScreenPriv->x = x; 656 pScreenPriv->y = y; 657 pScreenPriv->pCacheWin = NullWindow; 658 if (pScreenPriv->checkPixels || pScreenPriv->pCursor != pCursor) 659 { 660 pScreenPriv->pCursor = pCursor; 661 miSpriteFindColors (pScreen); 662 } 663 if (pScreenPriv->isUp) { 664 int sx, sy; 665 /* 666 * check to see if the old saved region 667 * encloses the new sprite, in which case we use 668 * the flicker-free MoveCursor primitive. 669 */ 670 sx = pScreenPriv->x - (int)pCursor->bits->xhot; 671 sy = pScreenPriv->y - (int)pCursor->bits->yhot; 672 if (sx + (int) pCursor->bits->width >= pScreenPriv->saved.x1 && 673 sx < pScreenPriv->saved.x2 && 674 sy + (int) pCursor->bits->height >= pScreenPriv->saved.y1 && 675 sy < pScreenPriv->saved.y2 && 676 (int) pCursor->bits->width + (2 * SPRITE_PAD) == 677 pScreenPriv->saved.x2 - pScreenPriv->saved.x1 && 678 (int) pCursor->bits->height + (2 * SPRITE_PAD) == 679 pScreenPriv->saved.y2 - pScreenPriv->saved.y1 680 ) 681 { 682 DamageDrawInternal (pScreen, TRUE); 683 miSpriteIsUpFALSE (pScreen, pScreenPriv); 684 if (!(sx >= pScreenPriv->saved.x1 && 685 sx + (int)pCursor->bits->width < pScreenPriv->saved.x2 && 686 sy >= pScreenPriv->saved.y1 && 687 sy + (int)pCursor->bits->height < pScreenPriv->saved.y2)) 688 { 689 int oldx1, oldy1, dx, dy; 690 691 oldx1 = pScreenPriv->saved.x1; 692 oldy1 = pScreenPriv->saved.y1; 693 dx = oldx1 - (sx - SPRITE_PAD); 694 dy = oldy1 - (sy - SPRITE_PAD); 695 pScreenPriv->saved.x1 -= dx; 696 pScreenPriv->saved.y1 -= dy; 697 pScreenPriv->saved.x2 -= dx; 698 pScreenPriv->saved.y2 -= dy; 699 (void) (*pScreenPriv->funcs->ChangeSave) (pScreen, 700 pScreenPriv->saved.x1, 701 pScreenPriv->saved.y1, 702 pScreenPriv->saved.x2 - pScreenPriv->saved.x1, 703 pScreenPriv->saved.y2 - pScreenPriv->saved.y1, 704 dx, dy); 705 } 706 (void) (*pScreenPriv->funcs->MoveCursor) (pScreen, pCursor, 707 pScreenPriv->saved.x1, 708 pScreenPriv->saved.y1, 709 pScreenPriv->saved.x2 - pScreenPriv->saved.x1, 710 pScreenPriv->saved.y2 - pScreenPriv->saved.y1, 711 sx - pScreenPriv->saved.x1, 712 sy - pScreenPriv->saved.y1, 713 pScreenPriv->colors[SOURCE_COLOR].pixel, 714 pScreenPriv->colors[MASK_COLOR].pixel); 715 miSpriteIsUpTRUE (pScreen, pScreenPriv); 716 DamageDrawInternal (pScreen, FALSE); 717 } 718 else 719 { 720 SPRITE_DEBUG (("SetCursor remove\n")); 721 miSpriteRemoveCursor (pScreen); 722 } 723 } 724 if (!pScreenPriv->isUp && pScreenPriv->pCursor) 725 { 726 SPRITE_DEBUG (("SetCursor restore\n")); 727 miSpriteRestoreCursor (pScreen); 728 } 729} 730 731static void 732miSpriteMoveCursor (pScreen, x, y) 733 ScreenPtr pScreen; 734 int x, y; 735{ 736 miSpriteScreenPtr pScreenPriv; 737 738 pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr; 739 miSpriteSetCursor (pScreen, pScreenPriv->pCursor, x, y); 740} 741 742/* 743 * undraw/draw cursor 744 */ 745 746static void 747miSpriteRemoveCursor (pScreen) 748 ScreenPtr pScreen; 749{ 750 miSpriteScreenPtr pScreenPriv; 751 752 DamageDrawInternal (pScreen, TRUE); 753 pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr; 754 miSpriteIsUpFALSE (pScreen, pScreenPriv); 755 pScreenPriv->pCacheWin = NullWindow; 756 if (!(*pScreenPriv->funcs->RestoreUnderCursor) (pScreen, 757 pScreenPriv->saved.x1, 758 pScreenPriv->saved.y1, 759 pScreenPriv->saved.x2 - pScreenPriv->saved.x1, 760 pScreenPriv->saved.y2 - pScreenPriv->saved.y1)) 761 { 762 miSpriteIsUpTRUE (pScreen, pScreenPriv); 763 } 764 DamageDrawInternal (pScreen, FALSE); 765} 766 767/* 768 * Called from the block handler, restores the cursor 769 * before waiting for something to do. 770 */ 771 772static void 773miSpriteRestoreCursor (pScreen) 774 ScreenPtr pScreen; 775{ 776 miSpriteScreenPtr pScreenPriv; 777 int x, y; 778 CursorPtr pCursor; 779 780 DamageDrawInternal (pScreen, TRUE); 781 miSpriteComputeSaved (pScreen); 782 pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr; 783 pCursor = pScreenPriv->pCursor; 784 x = pScreenPriv->x - (int)pCursor->bits->xhot; 785 y = pScreenPriv->y - (int)pCursor->bits->yhot; 786 if ((*pScreenPriv->funcs->SaveUnderCursor) (pScreen, 787 pScreenPriv->saved.x1, 788 pScreenPriv->saved.y1, 789 pScreenPriv->saved.x2 - pScreenPriv->saved.x1, 790 pScreenPriv->saved.y2 - pScreenPriv->saved.y1)) 791 { 792 if (pScreenPriv->checkPixels) 793 miSpriteFindColors (pScreen); 794 if ((*pScreenPriv->funcs->PutUpCursor) (pScreen, pCursor, x, y, 795 pScreenPriv->colors[SOURCE_COLOR].pixel, 796 pScreenPriv->colors[MASK_COLOR].pixel)) 797 { 798 miSpriteIsUpTRUE (pScreen, pScreenPriv); 799 } 800 } 801 DamageDrawInternal (pScreen, FALSE); 802} 803 804/* 805 * compute the desired area of the screen to save 806 */ 807 808static void 809miSpriteComputeSaved (pScreen) 810 ScreenPtr pScreen; 811{ 812 miSpriteScreenPtr pScreenPriv; 813 int x, y, w, h; 814 int wpad, hpad; 815 CursorPtr pCursor; 816 817 pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr; 818 pCursor = pScreenPriv->pCursor; 819 x = pScreenPriv->x - (int)pCursor->bits->xhot; 820 y = pScreenPriv->y - (int)pCursor->bits->yhot; 821 w = pCursor->bits->width; 822 h = pCursor->bits->height; 823 wpad = SPRITE_PAD; 824 hpad = SPRITE_PAD; 825 pScreenPriv->saved.x1 = x - wpad; 826 pScreenPriv->saved.y1 = y - hpad; 827 pScreenPriv->saved.x2 = pScreenPriv->saved.x1 + w + wpad * 2; 828 pScreenPriv->saved.y2 = pScreenPriv->saved.y1 + h + hpad * 2; 829} 830