Imported Upstream version 1.15.1
[deb_xorg-server.git] / damageext / damageext.c
CommitLineData
a09e091a
JB
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, (pointer) 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, pointer closure, pointer 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(pointer 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}