1/* 2 * Copyright © 2002 Keith Packard 3 * Copyright 2013 Red Hat, Inc. 4 * 5 * Permission to use, copy, modify, distribute, and sell this software and its 6 * documentation for any purpose is hereby granted without fee, provided that 7 * the above copyright notice appear in all copies and that both that 8 * copyright notice and this permission notice appear in supporting 9 * documentation, and that the name of Keith Packard not be used in 10 * advertising or publicity pertaining to distribution of the software without 11 * specific, written prior permission. Keith Packard makes no 12 * representations about the suitability of this software for any purpose. It 13 * is provided "as is" without express or implied warranty. 14 * 15 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 16 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 17 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR 18 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 19 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 20 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 21 * PERFORMANCE OF THIS SOFTWARE. 22 */ 23 24#ifdef HAVE_DIX_CONFIG_H 25#include <dix-config.h> 26#endif 27 28#include "damageextint.h" 29#include "damagestr.h" 30#include "protocol-versions.h" 31#include "extinit.h" 32 33#ifdef PANORAMIX 34#include "panoramiX.h" 35#include "panoramiXsrv.h" 36 37typedef struct { 38 DamageExtPtr ext; 39 DamagePtr damage[MAXSCREENS]; 40} PanoramiXDamageRes; 41 42static RESTYPE XRT_DAMAGE; 43static int (*PanoramiXSaveDamageCreate) (ClientPtr); 44 45#endif 46 47static unsigned char DamageReqCode; 48static int DamageEventBase; 49static RESTYPE DamageExtType; 50 51static DevPrivateKeyRec DamageClientPrivateKeyRec; 52 53#define DamageClientPrivateKey (&DamageClientPrivateKeyRec) 54 55static void 56DamageNoteCritical(ClientPtr pClient) 57{ 58 DamageClientPtr pDamageClient = GetDamageClient(pClient); 59 60 /* Composite extension marks clients with manual Subwindows as critical */ 61 if (pDamageClient->critical > 0) { 62 SetCriticalOutputPending(); 63 pClient->smart_priority = SMART_MAX_PRIORITY; 64 } 65} 66 67static void 68damageGetGeometry(DrawablePtr draw, int *x, int *y, int *w, int *h) 69{ 70#ifdef PANORAMIX 71 if (!noPanoramiXExtension && draw->type == DRAWABLE_WINDOW) { 72 WindowPtr win = (WindowPtr)draw; 73 74 if (!win->parent) { 75 *x = screenInfo.x; 76 *y = screenInfo.y; 77 *w = screenInfo.width; 78 *h = screenInfo.height; 79 return; 80 } 81 } 82#endif 83 84 *x = draw->x; 85 *y = draw->y; 86 *w = draw->width; 87 *h = draw->height; 88} 89 90static void 91DamageExtNotify(DamageExtPtr pDamageExt, BoxPtr pBoxes, int nBoxes) 92{ 93 ClientPtr pClient = pDamageExt->pClient; 94 DrawablePtr pDrawable = pDamageExt->pDrawable; 95 xDamageNotifyEvent ev; 96 int i, x, y, w, h; 97 98 damageGetGeometry(pDrawable, &x, &y, &w, &h); 99 100 UpdateCurrentTimeIf(); 101 ev = (xDamageNotifyEvent) { 102 .type = DamageEventBase + XDamageNotify, 103 .level = pDamageExt->level, 104 .drawable = pDamageExt->drawable, 105 .damage = pDamageExt->id, 106 .timestamp = currentTime.milliseconds, 107 .geometry.x = x, 108 .geometry.y = y, 109 .geometry.width = w, 110 .geometry.height = h 111 }; 112 if (pBoxes) { 113 for (i = 0; i < nBoxes; i++) { 114 ev.level = pDamageExt->level; 115 if (i < nBoxes - 1) 116 ev.level |= DamageNotifyMore; 117 ev.area.x = pBoxes[i].x1; 118 ev.area.y = pBoxes[i].y1; 119 ev.area.width = pBoxes[i].x2 - pBoxes[i].x1; 120 ev.area.height = pBoxes[i].y2 - pBoxes[i].y1; 121 WriteEventsToClient(pClient, 1, (xEvent *) &ev); 122 } 123 } 124 else { 125 ev.area.x = 0; 126 ev.area.y = 0; 127 ev.area.width = w; 128 ev.area.height = h; 129 WriteEventsToClient(pClient, 1, (xEvent *) &ev); 130 } 131 132 DamageNoteCritical(pClient); 133} 134 135static void 136DamageExtReport(DamagePtr pDamage, RegionPtr pRegion, void *closure) 137{ 138 DamageExtPtr pDamageExt = closure; 139 140 switch (pDamageExt->level) { 141 case DamageReportRawRegion: 142 case DamageReportDeltaRegion: 143 DamageExtNotify(pDamageExt, RegionRects(pRegion), 144 RegionNumRects(pRegion)); 145 break; 146 case DamageReportBoundingBox: 147 DamageExtNotify(pDamageExt, RegionExtents(pRegion), 1); 148 break; 149 case DamageReportNonEmpty: 150 DamageExtNotify(pDamageExt, NullBox, 0); 151 break; 152 case DamageReportNone: 153 break; 154 } 155} 156 157static void 158DamageExtDestroy(DamagePtr pDamage, void *closure) 159{ 160 DamageExtPtr pDamageExt = closure; 161 162 pDamageExt->pDamage = 0; 163 if (pDamageExt->id) 164 FreeResource(pDamageExt->id, RT_NONE); 165} 166 167void 168DamageExtSetCritical(ClientPtr pClient, Bool critical) 169{ 170 DamageClientPtr pDamageClient = GetDamageClient(pClient); 171 172 if (pDamageClient) 173 pDamageClient->critical += critical ? 1 : -1; 174} 175 176static int 177ProcDamageQueryVersion(ClientPtr client) 178{ 179 DamageClientPtr pDamageClient = GetDamageClient(client); 180 xDamageQueryVersionReply rep = { 181 .type = X_Reply, 182 .sequenceNumber = client->sequence, 183 .length = 0 184 }; 185 186 REQUEST(xDamageQueryVersionReq); 187 188 REQUEST_SIZE_MATCH(xDamageQueryVersionReq); 189 190 if (stuff->majorVersion < SERVER_DAMAGE_MAJOR_VERSION) { 191 rep.majorVersion = stuff->majorVersion; 192 rep.minorVersion = stuff->minorVersion; 193 } 194 else { 195 rep.majorVersion = SERVER_DAMAGE_MAJOR_VERSION; 196 if (stuff->majorVersion == SERVER_DAMAGE_MAJOR_VERSION && 197 stuff->minorVersion < SERVER_DAMAGE_MINOR_VERSION) 198 rep.minorVersion = stuff->minorVersion; 199 else 200 rep.minorVersion = SERVER_DAMAGE_MINOR_VERSION; 201 } 202 pDamageClient->major_version = rep.majorVersion; 203 pDamageClient->minor_version = rep.minorVersion; 204 if (client->swapped) { 205 swaps(&rep.sequenceNumber); 206 swapl(&rep.length); 207 swapl(&rep.majorVersion); 208 swapl(&rep.minorVersion); 209 } 210 WriteToClient(client, sizeof(xDamageQueryVersionReply), &rep); 211 return Success; 212} 213 214static void 215DamageExtRegister(DrawablePtr pDrawable, DamagePtr pDamage, Bool report) 216{ 217 DamageSetReportAfterOp(pDamage, TRUE); 218 DamageRegister(pDrawable, pDamage); 219 220 if (report) { 221 RegionPtr pRegion = &((WindowPtr) pDrawable)->borderClip; 222 RegionTranslate(pRegion, -pDrawable->x, -pDrawable->y); 223 DamageReportDamage(pDamage, pRegion); 224 RegionTranslate(pRegion, pDrawable->x, pDrawable->y); 225 } 226} 227 228static DamageExtPtr 229DamageExtCreate(DrawablePtr pDrawable, DamageReportLevel level, 230 ClientPtr client, XID id, XID drawable) 231{ 232 DamageExtPtr pDamageExt = malloc(sizeof(DamageExtRec)); 233 if (!pDamageExt) 234 return NULL; 235 236 pDamageExt->id = id; 237 pDamageExt->drawable = drawable; 238 pDamageExt->pDrawable = pDrawable; 239 pDamageExt->level = level; 240 pDamageExt->pClient = client; 241 pDamageExt->pDamage = DamageCreate(DamageExtReport, DamageExtDestroy, level, 242 FALSE, pDrawable->pScreen, pDamageExt); 243 if (!pDamageExt->pDamage) { 244 free(pDamageExt); 245 return NULL; 246 } 247 248 if (!AddResource(id, DamageExtType, (void *) pDamageExt)) 249 return NULL; 250 251 DamageExtRegister(pDrawable, pDamageExt->pDamage, 252 pDrawable->type == DRAWABLE_WINDOW); 253 254 return pDamageExt; 255} 256 257static DamageExtPtr 258doDamageCreate(ClientPtr client, int *rc) 259{ 260 DrawablePtr pDrawable; 261 DamageExtPtr pDamageExt; 262 DamageReportLevel level; 263 264 REQUEST(xDamageCreateReq); 265 266 *rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0, 267 DixGetAttrAccess | DixReadAccess); 268 if (*rc != Success) 269 return NULL; 270 271 switch (stuff->level) { 272 case XDamageReportRawRectangles: 273 level = DamageReportRawRegion; 274 break; 275 case XDamageReportDeltaRectangles: 276 level = DamageReportDeltaRegion; 277 break; 278 case XDamageReportBoundingBox: 279 level = DamageReportBoundingBox; 280 break; 281 case XDamageReportNonEmpty: 282 level = DamageReportNonEmpty; 283 break; 284 default: 285 client->errorValue = stuff->level; 286 *rc = BadValue; 287 return NULL; 288 } 289 290 pDamageExt = DamageExtCreate(pDrawable, level, client, stuff->damage, 291 stuff->drawable); 292 if (!pDamageExt) 293 *rc = BadAlloc; 294 295 return pDamageExt; 296} 297 298static int 299ProcDamageCreate(ClientPtr client) 300{ 301 int rc; 302 REQUEST(xDamageCreateReq); 303 REQUEST_SIZE_MATCH(xDamageCreateReq); 304 LEGAL_NEW_RESOURCE(stuff->damage, client); 305 doDamageCreate(client, &rc); 306 return rc; 307} 308 309static int 310ProcDamageDestroy(ClientPtr client) 311{ 312 REQUEST(xDamageDestroyReq); 313 DamageExtPtr pDamageExt; 314 315 REQUEST_SIZE_MATCH(xDamageDestroyReq); 316 VERIFY_DAMAGEEXT(pDamageExt, stuff->damage, client, DixWriteAccess); 317 FreeResource(stuff->damage, RT_NONE); 318 return Success; 319} 320 321#ifdef PANORAMIX 322static RegionPtr 323DamageExtSubtractWindowClip(DamageExtPtr pDamageExt) 324{ 325 WindowPtr win = (WindowPtr)pDamageExt->pDrawable; 326 PanoramiXRes *res = NULL; 327 RegionPtr ret; 328 int i; 329 330 if (!win->parent) 331 return &PanoramiXScreenRegion; 332 333 dixLookupResourceByType((void **)&res, win->drawable.id, XRT_WINDOW, 334 serverClient, DixReadAccess); 335 if (!res) 336 return NULL; 337 338 ret = RegionCreate(NULL, 0); 339 if (!ret) 340 return NULL; 341 342 FOR_NSCREENS_FORWARD(i) { 343 ScreenPtr screen; 344 if (Success != dixLookupWindow(&win, res->info[i].id, serverClient, 345 DixReadAccess)) 346 goto out; 347 348 screen = win->drawable.pScreen; 349 350 RegionTranslate(ret, -screen->x, -screen->y); 351 if (!RegionUnion(ret, ret, &win->borderClip)) 352 goto out; 353 RegionTranslate(ret, screen->x, screen->y); 354 } 355 356 return ret; 357 358out: 359 RegionDestroy(ret); 360 return NULL; 361} 362 363static void 364DamageExtFreeWindowClip(RegionPtr reg) 365{ 366 if (reg != &PanoramiXScreenRegion) 367 RegionDestroy(reg); 368} 369#endif 370 371/* 372 * DamageSubtract intersects with borderClip, so we must reconstruct the 373 * protocol's perspective of same... 374 */ 375static Bool 376DamageExtSubtract(DamageExtPtr pDamageExt, const RegionPtr pRegion) 377{ 378 DamagePtr pDamage = pDamageExt->pDamage; 379 380#ifdef PANORAMIX 381 if (!noPanoramiXExtension) { 382 RegionPtr damage = DamageRegion(pDamage); 383 RegionSubtract(damage, damage, pRegion); 384 385 if (pDamageExt->pDrawable->type == DRAWABLE_WINDOW) { 386 DrawablePtr pDraw = pDamageExt->pDrawable; 387 RegionPtr clip = DamageExtSubtractWindowClip(pDamageExt); 388 if (clip) { 389 RegionTranslate(clip, -pDraw->x, -pDraw->y); 390 RegionIntersect(damage, damage, clip); 391 RegionTranslate(clip, pDraw->x, pDraw->y); 392 DamageExtFreeWindowClip(clip); 393 } 394 } 395 396 return RegionNotEmpty(damage); 397 } 398#endif 399 400 return DamageSubtract(pDamage, pRegion); 401} 402 403static int 404ProcDamageSubtract(ClientPtr client) 405{ 406 REQUEST(xDamageSubtractReq); 407 DamageExtPtr pDamageExt; 408 RegionPtr pRepair; 409 RegionPtr pParts; 410 411 REQUEST_SIZE_MATCH(xDamageSubtractReq); 412 VERIFY_DAMAGEEXT(pDamageExt, stuff->damage, client, DixWriteAccess); 413 VERIFY_REGION_OR_NONE(pRepair, stuff->repair, client, DixWriteAccess); 414 VERIFY_REGION_OR_NONE(pParts, stuff->parts, client, DixWriteAccess); 415 416 if (pDamageExt->level != DamageReportRawRegion) { 417 DamagePtr pDamage = pDamageExt->pDamage; 418 419 if (pRepair) { 420 if (pParts) 421 RegionIntersect(pParts, DamageRegion(pDamage), pRepair); 422 if (DamageExtSubtract(pDamageExt, pRepair)) 423 DamageExtReport(pDamage, DamageRegion(pDamage), 424 (void *) pDamageExt); 425 } 426 else { 427 if (pParts) 428 RegionCopy(pParts, DamageRegion(pDamage)); 429 DamageEmpty(pDamage); 430 } 431 } 432 433 return Success; 434} 435 436static int 437ProcDamageAdd(ClientPtr client) 438{ 439 REQUEST(xDamageAddReq); 440 DrawablePtr pDrawable; 441 RegionPtr pRegion; 442 int rc; 443 444 REQUEST_SIZE_MATCH(xDamageAddReq); 445 VERIFY_REGION(pRegion, stuff->region, client, DixWriteAccess); 446 rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0, 447 DixWriteAccess); 448 if (rc != Success) 449 return rc; 450 451 /* The region is relative to the drawable origin, so translate it out to 452 * screen coordinates like damage expects. 453 */ 454 RegionTranslate(pRegion, pDrawable->x, pDrawable->y); 455 DamageDamageRegion(pDrawable, pRegion); 456 RegionTranslate(pRegion, -pDrawable->x, -pDrawable->y); 457 458 return Success; 459} 460 461/* Major version controls available requests */ 462static const int version_requests[] = { 463 X_DamageQueryVersion, /* before client sends QueryVersion */ 464 X_DamageAdd, /* Version 1 */ 465}; 466 467static int (*ProcDamageVector[XDamageNumberRequests]) (ClientPtr) = { 468 /*************** Version 1 ******************/ 469 ProcDamageQueryVersion, 470 ProcDamageCreate, 471 ProcDamageDestroy, 472 ProcDamageSubtract, 473 /*************** Version 1.1 ****************/ 474 ProcDamageAdd, 475}; 476 477static int 478ProcDamageDispatch(ClientPtr client) 479{ 480 REQUEST(xDamageReq); 481 DamageClientPtr pDamageClient = GetDamageClient(client); 482 483 if (pDamageClient->major_version >= ARRAY_SIZE(version_requests)) 484 return BadRequest; 485 if (stuff->damageReqType > version_requests[pDamageClient->major_version]) 486 return BadRequest; 487 return (*ProcDamageVector[stuff->damageReqType]) (client); 488} 489 490static int _X_COLD 491SProcDamageQueryVersion(ClientPtr client) 492{ 493 REQUEST(xDamageQueryVersionReq); 494 495 swaps(&stuff->length); 496 REQUEST_SIZE_MATCH(xDamageQueryVersionReq); 497 swapl(&stuff->majorVersion); 498 swapl(&stuff->minorVersion); 499 return (*ProcDamageVector[stuff->damageReqType]) (client); 500} 501 502static int _X_COLD 503SProcDamageCreate(ClientPtr client) 504{ 505 REQUEST(xDamageCreateReq); 506 507 swaps(&stuff->length); 508 REQUEST_SIZE_MATCH(xDamageCreateReq); 509 swapl(&stuff->damage); 510 swapl(&stuff->drawable); 511 return (*ProcDamageVector[stuff->damageReqType]) (client); 512} 513 514static int _X_COLD 515SProcDamageDestroy(ClientPtr client) 516{ 517 REQUEST(xDamageDestroyReq); 518 519 swaps(&stuff->length); 520 REQUEST_SIZE_MATCH(xDamageDestroyReq); 521 swapl(&stuff->damage); 522 return (*ProcDamageVector[stuff->damageReqType]) (client); 523} 524 525static int _X_COLD 526SProcDamageSubtract(ClientPtr client) 527{ 528 REQUEST(xDamageSubtractReq); 529 530 swaps(&stuff->length); 531 REQUEST_SIZE_MATCH(xDamageSubtractReq); 532 swapl(&stuff->damage); 533 swapl(&stuff->repair); 534 swapl(&stuff->parts); 535 return (*ProcDamageVector[stuff->damageReqType]) (client); 536} 537 538static int _X_COLD 539SProcDamageAdd(ClientPtr client) 540{ 541 REQUEST(xDamageAddReq); 542 543 swaps(&stuff->length); 544 REQUEST_SIZE_MATCH(xDamageSubtractReq); 545 swapl(&stuff->drawable); 546 swapl(&stuff->region); 547 return (*ProcDamageVector[stuff->damageReqType]) (client); 548} 549 550static int (*SProcDamageVector[XDamageNumberRequests]) (ClientPtr) = { 551 /*************** Version 1 ******************/ 552 SProcDamageQueryVersion, 553 SProcDamageCreate, 554 SProcDamageDestroy, 555 SProcDamageSubtract, 556 /*************** Version 1.1 ****************/ 557 SProcDamageAdd, 558}; 559 560static int _X_COLD 561SProcDamageDispatch(ClientPtr client) 562{ 563 REQUEST(xDamageReq); 564 DamageClientPtr pDamageClient = GetDamageClient(client); 565 566 if (pDamageClient->major_version >= ARRAY_SIZE(version_requests)) 567 return BadRequest; 568 if (stuff->damageReqType > version_requests[pDamageClient->major_version]) 569 return BadRequest; 570 return (*SProcDamageVector[stuff->damageReqType]) (client); 571} 572 573static int 574FreeDamageExt(void *value, XID did) 575{ 576 DamageExtPtr pDamageExt = (DamageExtPtr) value; 577 578 /* 579 * Get rid of the resource table entry hanging from the window id 580 */ 581 pDamageExt->id = 0; 582 if (pDamageExt->pDamage) { 583 DamageDestroy(pDamageExt->pDamage); 584 } 585 free(pDamageExt); 586 return Success; 587} 588 589static void _X_COLD 590SDamageNotifyEvent(xDamageNotifyEvent * from, xDamageNotifyEvent * to) 591{ 592 to->type = from->type; 593 cpswaps(from->sequenceNumber, to->sequenceNumber); 594 cpswapl(from->drawable, to->drawable); 595 cpswapl(from->damage, to->damage); 596 cpswaps(from->area.x, to->area.x); 597 cpswaps(from->area.y, to->area.y); 598 cpswaps(from->area.width, to->area.width); 599 cpswaps(from->area.height, to->area.height); 600 cpswaps(from->geometry.x, to->geometry.x); 601 cpswaps(from->geometry.y, to->geometry.y); 602 cpswaps(from->geometry.width, to->geometry.width); 603 cpswaps(from->geometry.height, to->geometry.height); 604} 605 606#ifdef PANORAMIX 607 608static void 609PanoramiXDamageReport(DamagePtr pDamage, RegionPtr pRegion, void *closure) 610{ 611 PanoramiXDamageRes *res = closure; 612 DamageExtPtr pDamageExt = res->ext; 613 WindowPtr pWin = (WindowPtr)pDamage->pDrawable; 614 ScreenPtr pScreen = pDamage->pScreen; 615 616 /* happens on unmap? sigh xinerama */ 617 if (RegionNil(pRegion)) 618 return; 619 620 /* translate root windows if necessary */ 621 if (!pWin->parent) 622 RegionTranslate(pRegion, pScreen->x, pScreen->y); 623 624 /* add our damage to the protocol view */ 625 DamageReportDamage(pDamageExt->pDamage, pRegion); 626 627 /* empty our view */ 628 DamageEmpty(pDamage); 629} 630 631static void 632PanoramiXDamageExtDestroy(DamagePtr pDamage, void *closure) 633{ 634 PanoramiXDamageRes *damage = closure; 635 damage->damage[pDamage->pScreen->myNum] = NULL; 636} 637 638static int 639PanoramiXDamageCreate(ClientPtr client) 640{ 641 PanoramiXDamageRes *damage; 642 PanoramiXRes *draw; 643 int i, rc; 644 645 REQUEST(xDamageCreateReq); 646 647 REQUEST_SIZE_MATCH(xDamageCreateReq); 648 LEGAL_NEW_RESOURCE(stuff->damage, client); 649 rc = dixLookupResourceByClass((void **)&draw, stuff->drawable, XRC_DRAWABLE, 650 client, DixGetAttrAccess | DixReadAccess); 651 if (rc != Success) 652 return rc; 653 654 if (!(damage = calloc(1, sizeof(PanoramiXDamageRes)))) 655 return BadAlloc; 656 657 if (!AddResource(stuff->damage, XRT_DAMAGE, damage)) 658 return BadAlloc; 659 660 damage->ext = doDamageCreate(client, &rc); 661 if (rc == Success && draw->type == XRT_WINDOW) { 662 FOR_NSCREENS_FORWARD(i) { 663 DrawablePtr pDrawable; 664 DamagePtr pDamage = DamageCreate(PanoramiXDamageReport, 665 PanoramiXDamageExtDestroy, 666 DamageReportRawRegion, 667 FALSE, 668 screenInfo.screens[i], 669 damage); 670 if (!pDamage) { 671 rc = BadAlloc; 672 } else { 673 damage->damage[i] = pDamage; 674 rc = dixLookupDrawable(&pDrawable, draw->info[i].id, client, 675 M_WINDOW, 676 DixGetAttrAccess | DixReadAccess); 677 } 678 if (rc != Success) 679 break; 680 681 DamageExtRegister(pDrawable, pDamage, i != 0); 682 } 683 } 684 685 if (rc != Success) 686 FreeResource(stuff->damage, RT_NONE); 687 688 return rc; 689} 690 691static int 692PanoramiXDamageDelete(void *res, XID id) 693{ 694 int i; 695 PanoramiXDamageRes *damage = res; 696 697 FOR_NSCREENS_BACKWARD(i) { 698 if (damage->damage[i]) { 699 DamageDestroy(damage->damage[i]); 700 damage->damage[i] = NULL; 701 } 702 } 703 704 free(damage); 705 return 1; 706} 707 708void 709PanoramiXDamageInit(void) 710{ 711 XRT_DAMAGE = CreateNewResourceType(PanoramiXDamageDelete, "XineramaDamage"); 712 if (!XRT_DAMAGE) 713 FatalError("Couldn't Xineramify Damage extension\n"); 714 715 PanoramiXSaveDamageCreate = ProcDamageVector[X_DamageCreate]; 716 ProcDamageVector[X_DamageCreate] = PanoramiXDamageCreate; 717} 718 719void 720PanoramiXDamageReset(void) 721{ 722 ProcDamageVector[X_DamageCreate] = PanoramiXSaveDamageCreate; 723} 724 725#endif /* PANORAMIX */ 726 727void 728DamageExtensionInit(void) 729{ 730 ExtensionEntry *extEntry; 731 int s; 732 733 for (s = 0; s < screenInfo.numScreens; s++) 734 DamageSetup(screenInfo.screens[s]); 735 736 DamageExtType = CreateNewResourceType(FreeDamageExt, "DamageExt"); 737 if (!DamageExtType) 738 return; 739 740 if (!dixRegisterPrivateKey 741 (&DamageClientPrivateKeyRec, PRIVATE_CLIENT, sizeof(DamageClientRec))) 742 return; 743 744 if ((extEntry = AddExtension(DAMAGE_NAME, XDamageNumberEvents, 745 XDamageNumberErrors, 746 ProcDamageDispatch, SProcDamageDispatch, 747 NULL, StandardMinorOpcode)) != 0) { 748 DamageReqCode = (unsigned char) extEntry->base; 749 DamageEventBase = extEntry->eventBase; 750 EventSwapVector[DamageEventBase + XDamageNotify] = 751 (EventSwapPtr) SDamageNotifyEvent; 752 SetResourceTypeErrorValue(DamageExtType, 753 extEntry->errorBase + BadDamage); 754#ifdef PANORAMIX 755 if (XRT_DAMAGE) 756 SetResourceTypeErrorValue(XRT_DAMAGE, 757 extEntry->errorBase + BadDamage); 758#endif 759 } 760} 761