damageext.c revision 35c4bbdf
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 467#define NUM_VERSION_REQUESTS (sizeof (version_requests) / sizeof (version_requests[0])) 468 469static int (*ProcDamageVector[XDamageNumberRequests]) (ClientPtr) = { 470 /*************** Version 1 ******************/ 471 ProcDamageQueryVersion, 472 ProcDamageCreate, 473 ProcDamageDestroy, 474 ProcDamageSubtract, 475 /*************** Version 1.1 ****************/ 476 ProcDamageAdd, 477}; 478 479static int 480ProcDamageDispatch(ClientPtr client) 481{ 482 REQUEST(xDamageReq); 483 DamageClientPtr pDamageClient = GetDamageClient(client); 484 485 if (pDamageClient->major_version >= NUM_VERSION_REQUESTS) 486 return BadRequest; 487 if (stuff->damageReqType > version_requests[pDamageClient->major_version]) 488 return BadRequest; 489 return (*ProcDamageVector[stuff->damageReqType]) (client); 490} 491 492static int 493SProcDamageQueryVersion(ClientPtr client) 494{ 495 REQUEST(xDamageQueryVersionReq); 496 497 swaps(&stuff->length); 498 REQUEST_SIZE_MATCH(xDamageQueryVersionReq); 499 swapl(&stuff->majorVersion); 500 swapl(&stuff->minorVersion); 501 return (*ProcDamageVector[stuff->damageReqType]) (client); 502} 503 504static int 505SProcDamageCreate(ClientPtr client) 506{ 507 REQUEST(xDamageCreateReq); 508 509 swaps(&stuff->length); 510 REQUEST_SIZE_MATCH(xDamageCreateReq); 511 swapl(&stuff->damage); 512 swapl(&stuff->drawable); 513 return (*ProcDamageVector[stuff->damageReqType]) (client); 514} 515 516static int 517SProcDamageDestroy(ClientPtr client) 518{ 519 REQUEST(xDamageDestroyReq); 520 521 swaps(&stuff->length); 522 REQUEST_SIZE_MATCH(xDamageDestroyReq); 523 swapl(&stuff->damage); 524 return (*ProcDamageVector[stuff->damageReqType]) (client); 525} 526 527static int 528SProcDamageSubtract(ClientPtr client) 529{ 530 REQUEST(xDamageSubtractReq); 531 532 swaps(&stuff->length); 533 REQUEST_SIZE_MATCH(xDamageSubtractReq); 534 swapl(&stuff->damage); 535 swapl(&stuff->repair); 536 swapl(&stuff->parts); 537 return (*ProcDamageVector[stuff->damageReqType]) (client); 538} 539 540static int 541SProcDamageAdd(ClientPtr client) 542{ 543 REQUEST(xDamageAddReq); 544 545 swaps(&stuff->length); 546 REQUEST_SIZE_MATCH(xDamageSubtractReq); 547 swapl(&stuff->drawable); 548 swapl(&stuff->region); 549 return (*ProcDamageVector[stuff->damageReqType]) (client); 550} 551 552static int (*SProcDamageVector[XDamageNumberRequests]) (ClientPtr) = { 553 /*************** Version 1 ******************/ 554 SProcDamageQueryVersion, 555 SProcDamageCreate, 556 SProcDamageDestroy, 557 SProcDamageSubtract, 558 /*************** Version 1.1 ****************/ 559 SProcDamageAdd, 560}; 561 562static int 563SProcDamageDispatch(ClientPtr client) 564{ 565 REQUEST(xDamageReq); 566 if (stuff->damageReqType >= XDamageNumberRequests) 567 return BadRequest; 568 return (*SProcDamageVector[stuff->damageReqType]) (client); 569} 570 571static void 572DamageClientCallback(CallbackListPtr *list, void *closure, void *data) 573{ 574 NewClientInfoRec *clientinfo = (NewClientInfoRec *) data; 575 ClientPtr pClient = clientinfo->client; 576 DamageClientPtr pDamageClient = GetDamageClient(pClient); 577 578 pDamageClient->critical = 0; 579 pDamageClient->major_version = 0; 580 pDamageClient->minor_version = 0; 581} 582 583 /*ARGSUSED*/ static void 584DamageResetProc(ExtensionEntry * extEntry) 585{ 586 DeleteCallback(&ClientStateCallback, DamageClientCallback, 0); 587} 588 589static int 590FreeDamageExt(void *value, XID did) 591{ 592 DamageExtPtr pDamageExt = (DamageExtPtr) value; 593 594 /* 595 * Get rid of the resource table entry hanging from the window id 596 */ 597 pDamageExt->id = 0; 598 if (pDamageExt->pDamage) { 599 DamageDestroy(pDamageExt->pDamage); 600 } 601 free(pDamageExt); 602 return Success; 603} 604 605static void 606SDamageNotifyEvent(xDamageNotifyEvent * from, xDamageNotifyEvent * to) 607{ 608 to->type = from->type; 609 cpswaps(from->sequenceNumber, to->sequenceNumber); 610 cpswapl(from->drawable, to->drawable); 611 cpswapl(from->damage, to->damage); 612 cpswaps(from->area.x, to->area.x); 613 cpswaps(from->area.y, to->area.y); 614 cpswaps(from->area.width, to->area.width); 615 cpswaps(from->area.height, to->area.height); 616 cpswaps(from->geometry.x, to->geometry.x); 617 cpswaps(from->geometry.y, to->geometry.y); 618 cpswaps(from->geometry.width, to->geometry.width); 619 cpswaps(from->geometry.height, to->geometry.height); 620} 621 622#ifdef PANORAMIX 623 624static void 625PanoramiXDamageReport(DamagePtr pDamage, RegionPtr pRegion, void *closure) 626{ 627 PanoramiXDamageRes *res = closure; 628 DamageExtPtr pDamageExt = res->ext; 629 WindowPtr pWin = (WindowPtr)pDamage->pDrawable; 630 ScreenPtr pScreen = pDamage->pScreen; 631 632 /* happens on unmap? sigh xinerama */ 633 if (RegionNil(pRegion)) 634 return; 635 636 /* translate root windows if necessary */ 637 if (!pWin->parent) 638 RegionTranslate(pRegion, pScreen->x, pScreen->y); 639 640 /* add our damage to the protocol view */ 641 DamageReportDamage(pDamageExt->pDamage, pRegion); 642 643 /* empty our view */ 644 DamageEmpty(pDamage); 645} 646 647static void 648PanoramiXDamageExtDestroy(DamagePtr pDamage, void *closure) 649{ 650 PanoramiXDamageRes *damage = closure; 651 damage->damage[pDamage->pScreen->myNum] = NULL; 652} 653 654static int 655PanoramiXDamageCreate(ClientPtr client) 656{ 657 PanoramiXDamageRes *damage; 658 PanoramiXRes *draw; 659 int i, rc; 660 661 REQUEST(xDamageCreateReq); 662 663 REQUEST_SIZE_MATCH(xDamageCreateReq); 664 LEGAL_NEW_RESOURCE(stuff->damage, client); 665 rc = dixLookupResourceByClass((void **)&draw, stuff->drawable, XRC_DRAWABLE, 666 client, DixGetAttrAccess | DixReadAccess); 667 if (rc != Success) 668 return rc; 669 670 if (!(damage = calloc(1, sizeof(PanoramiXDamageRes)))) 671 return BadAlloc; 672 673 if (!AddResource(stuff->damage, XRT_DAMAGE, damage)) 674 return BadAlloc; 675 676 damage->ext = doDamageCreate(client, &rc); 677 if (rc == Success && draw->type == XRT_WINDOW) { 678 FOR_NSCREENS_FORWARD(i) { 679 DrawablePtr pDrawable; 680 DamagePtr pDamage = DamageCreate(PanoramiXDamageReport, 681 PanoramiXDamageExtDestroy, 682 DamageReportRawRegion, 683 FALSE, 684 screenInfo.screens[i], 685 damage); 686 if (!pDamage) { 687 rc = BadAlloc; 688 } else { 689 damage->damage[i] = pDamage; 690 rc = dixLookupDrawable(&pDrawable, draw->info[i].id, client, 691 M_WINDOW, 692 DixGetAttrAccess | DixReadAccess); 693 } 694 if (rc != Success) 695 break; 696 697 DamageExtRegister(pDrawable, pDamage, i != 0); 698 } 699 } 700 701 if (rc != Success) 702 FreeResource(stuff->damage, RT_NONE); 703 704 return rc; 705} 706 707static int 708PanoramiXDamageDelete(void *res, XID id) 709{ 710 int i; 711 PanoramiXDamageRes *damage = res; 712 713 FOR_NSCREENS_BACKWARD(i) { 714 if (damage->damage[i]) { 715 DamageDestroy(damage->damage[i]); 716 damage->damage[i] = NULL; 717 } 718 } 719 720 free(damage); 721 return 1; 722} 723 724void 725PanoramiXDamageInit(void) 726{ 727 XRT_DAMAGE = CreateNewResourceType(PanoramiXDamageDelete, "XineramaDamage"); 728 if (!XRT_DAMAGE) 729 FatalError("Couldn't Xineramify Damage extension\n"); 730 731 PanoramiXSaveDamageCreate = ProcDamageVector[X_DamageCreate]; 732 ProcDamageVector[X_DamageCreate] = PanoramiXDamageCreate; 733} 734 735void 736PanoramiXDamageReset(void) 737{ 738 ProcDamageVector[X_DamageCreate] = PanoramiXSaveDamageCreate; 739} 740 741#endif /* PANORAMIX */ 742 743void 744DamageExtensionInit(void) 745{ 746 ExtensionEntry *extEntry; 747 int s; 748 749 for (s = 0; s < screenInfo.numScreens; s++) 750 DamageSetup(screenInfo.screens[s]); 751 752 DamageExtType = CreateNewResourceType(FreeDamageExt, "DamageExt"); 753 if (!DamageExtType) 754 return; 755 756 if (!dixRegisterPrivateKey 757 (&DamageClientPrivateKeyRec, PRIVATE_CLIENT, sizeof(DamageClientRec))) 758 return; 759 760 if (!AddCallback(&ClientStateCallback, DamageClientCallback, 0)) 761 return; 762 763 if ((extEntry = AddExtension(DAMAGE_NAME, XDamageNumberEvents, 764 XDamageNumberErrors, 765 ProcDamageDispatch, SProcDamageDispatch, 766 DamageResetProc, StandardMinorOpcode)) != 0) { 767 DamageReqCode = (unsigned char) extEntry->base; 768 DamageEventBase = extEntry->eventBase; 769 EventSwapVector[DamageEventBase + XDamageNotify] = 770 (EventSwapPtr) SDamageNotifyEvent; 771 SetResourceTypeErrorValue(DamageExtType, 772 extEntry->errorBase + BadDamage); 773#ifdef PANORAMIX 774 if (XRT_DAMAGE) 775 SetResourceTypeErrorValue(XRT_DAMAGE, 776 extEntry->errorBase + BadDamage); 777#endif 778 } 779} 780