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
37 typedef struct {
38 DamageExtPtr ext;
39 DamagePtr damage[MAXSCREENS];
40 } PanoramiXDamageRes;
41
42 static RESTYPE XRT_DAMAGE;
43 static int (*PanoramiXSaveDamageCreate) (ClientPtr);
44
45 #endif
46
47 static unsigned char DamageReqCode;
48 static int DamageEventBase;
49 static RESTYPE DamageExtType;
50
51 static DevPrivateKeyRec DamageClientPrivateKeyRec;
52
53 #define DamageClientPrivateKey (&DamageClientPrivateKeyRec)
54
55 static void
DamageNoteCritical(ClientPtr pClient)56 DamageNoteCritical(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
67 static void
damageGetGeometry(DrawablePtr draw,int * x,int * y,int * w,int * h)68 damageGetGeometry(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
90 static void
DamageExtNotify(DamageExtPtr pDamageExt,BoxPtr pBoxes,int nBoxes)91 DamageExtNotify(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
135 static void
DamageExtReport(DamagePtr pDamage,RegionPtr pRegion,void * closure)136 DamageExtReport(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
157 static void
DamageExtDestroy(DamagePtr pDamage,void * closure)158 DamageExtDestroy(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
167 void
DamageExtSetCritical(ClientPtr pClient,Bool critical)168 DamageExtSetCritical(ClientPtr pClient, Bool critical)
169 {
170 DamageClientPtr pDamageClient = GetDamageClient(pClient);
171
172 if (pDamageClient)
173 pDamageClient->critical += critical ? 1 : -1;
174 }
175
176 static int
ProcDamageQueryVersion(ClientPtr client)177 ProcDamageQueryVersion(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
214 static void
DamageExtRegister(DrawablePtr pDrawable,DamagePtr pDamage,Bool report)215 DamageExtRegister(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
228 static DamageExtPtr
DamageExtCreate(DrawablePtr pDrawable,DamageReportLevel level,ClientPtr client,XID id,XID drawable)229 DamageExtCreate(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
257 static DamageExtPtr
doDamageCreate(ClientPtr client,int * rc)258 doDamageCreate(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
298 static int
ProcDamageCreate(ClientPtr client)299 ProcDamageCreate(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
309 static int
ProcDamageDestroy(ClientPtr client)310 ProcDamageDestroy(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
322 static RegionPtr
DamageExtSubtractWindowClip(DamageExtPtr pDamageExt)323 DamageExtSubtractWindowClip(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
358 out:
359 RegionDestroy(ret);
360 return NULL;
361 }
362
363 static void
DamageExtFreeWindowClip(RegionPtr reg)364 DamageExtFreeWindowClip(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 */
375 static Bool
DamageExtSubtract(DamageExtPtr pDamageExt,const RegionPtr pRegion)376 DamageExtSubtract(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
403 static int
ProcDamageSubtract(ClientPtr client)404 ProcDamageSubtract(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
436 static int
ProcDamageAdd(ClientPtr client)437 ProcDamageAdd(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 */
462 static const int version_requests[] = {
463 X_DamageQueryVersion, /* before client sends QueryVersion */
464 X_DamageAdd, /* Version 1 */
465 };
466
467 static int (*ProcDamageVector[XDamageNumberRequests]) (ClientPtr) = {
468 /*************** Version 1 ******************/
469 ProcDamageQueryVersion,
470 ProcDamageCreate,
471 ProcDamageDestroy,
472 ProcDamageSubtract,
473 /*************** Version 1.1 ****************/
474 ProcDamageAdd,
475 };
476
477 static int
ProcDamageDispatch(ClientPtr client)478 ProcDamageDispatch(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
490 static int _X_COLD
SProcDamageQueryVersion(ClientPtr client)491 SProcDamageQueryVersion(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
502 static int _X_COLD
SProcDamageCreate(ClientPtr client)503 SProcDamageCreate(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
514 static int _X_COLD
SProcDamageDestroy(ClientPtr client)515 SProcDamageDestroy(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
525 static int _X_COLD
SProcDamageSubtract(ClientPtr client)526 SProcDamageSubtract(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
538 static int _X_COLD
SProcDamageAdd(ClientPtr client)539 SProcDamageAdd(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
550 static int (*SProcDamageVector[XDamageNumberRequests]) (ClientPtr) = {
551 /*************** Version 1 ******************/
552 SProcDamageQueryVersion,
553 SProcDamageCreate,
554 SProcDamageDestroy,
555 SProcDamageSubtract,
556 /*************** Version 1.1 ****************/
557 SProcDamageAdd,
558 };
559
560 static int _X_COLD
SProcDamageDispatch(ClientPtr client)561 SProcDamageDispatch(ClientPtr client)
562 {
563 REQUEST(xDamageReq);
564 if (stuff->damageReqType >= XDamageNumberRequests)
565 return BadRequest;
566 return (*SProcDamageVector[stuff->damageReqType]) (client);
567 }
568
569 static int
FreeDamageExt(void * value,XID did)570 FreeDamageExt(void *value, XID did)
571 {
572 DamageExtPtr pDamageExt = (DamageExtPtr) value;
573
574 /*
575 * Get rid of the resource table entry hanging from the window id
576 */
577 pDamageExt->id = 0;
578 if (pDamageExt->pDamage) {
579 DamageDestroy(pDamageExt->pDamage);
580 }
581 free(pDamageExt);
582 return Success;
583 }
584
585 static void _X_COLD
SDamageNotifyEvent(xDamageNotifyEvent * from,xDamageNotifyEvent * to)586 SDamageNotifyEvent(xDamageNotifyEvent * from, xDamageNotifyEvent * to)
587 {
588 to->type = from->type;
589 cpswaps(from->sequenceNumber, to->sequenceNumber);
590 cpswapl(from->drawable, to->drawable);
591 cpswapl(from->damage, to->damage);
592 cpswaps(from->area.x, to->area.x);
593 cpswaps(from->area.y, to->area.y);
594 cpswaps(from->area.width, to->area.width);
595 cpswaps(from->area.height, to->area.height);
596 cpswaps(from->geometry.x, to->geometry.x);
597 cpswaps(from->geometry.y, to->geometry.y);
598 cpswaps(from->geometry.width, to->geometry.width);
599 cpswaps(from->geometry.height, to->geometry.height);
600 }
601
602 #ifdef PANORAMIX
603
604 static void
PanoramiXDamageReport(DamagePtr pDamage,RegionPtr pRegion,void * closure)605 PanoramiXDamageReport(DamagePtr pDamage, RegionPtr pRegion, void *closure)
606 {
607 PanoramiXDamageRes *res = closure;
608 DamageExtPtr pDamageExt = res->ext;
609 WindowPtr pWin = (WindowPtr)pDamage->pDrawable;
610 ScreenPtr pScreen = pDamage->pScreen;
611
612 /* happens on unmap? sigh xinerama */
613 if (RegionNil(pRegion))
614 return;
615
616 /* translate root windows if necessary */
617 if (!pWin->parent)
618 RegionTranslate(pRegion, pScreen->x, pScreen->y);
619
620 /* add our damage to the protocol view */
621 DamageReportDamage(pDamageExt->pDamage, pRegion);
622
623 /* empty our view */
624 DamageEmpty(pDamage);
625 }
626
627 static void
PanoramiXDamageExtDestroy(DamagePtr pDamage,void * closure)628 PanoramiXDamageExtDestroy(DamagePtr pDamage, void *closure)
629 {
630 PanoramiXDamageRes *damage = closure;
631 damage->damage[pDamage->pScreen->myNum] = NULL;
632 }
633
634 static int
PanoramiXDamageCreate(ClientPtr client)635 PanoramiXDamageCreate(ClientPtr client)
636 {
637 PanoramiXDamageRes *damage;
638 PanoramiXRes *draw;
639 int i, rc;
640
641 REQUEST(xDamageCreateReq);
642
643 REQUEST_SIZE_MATCH(xDamageCreateReq);
644 LEGAL_NEW_RESOURCE(stuff->damage, client);
645 rc = dixLookupResourceByClass((void **)&draw, stuff->drawable, XRC_DRAWABLE,
646 client, DixGetAttrAccess | DixReadAccess);
647 if (rc != Success)
648 return rc;
649
650 if (!(damage = calloc(1, sizeof(PanoramiXDamageRes))))
651 return BadAlloc;
652
653 if (!AddResource(stuff->damage, XRT_DAMAGE, damage))
654 return BadAlloc;
655
656 damage->ext = doDamageCreate(client, &rc);
657 if (rc == Success && draw->type == XRT_WINDOW) {
658 FOR_NSCREENS_FORWARD(i) {
659 DrawablePtr pDrawable;
660 DamagePtr pDamage = DamageCreate(PanoramiXDamageReport,
661 PanoramiXDamageExtDestroy,
662 DamageReportRawRegion,
663 FALSE,
664 screenInfo.screens[i],
665 damage);
666 if (!pDamage) {
667 rc = BadAlloc;
668 } else {
669 damage->damage[i] = pDamage;
670 rc = dixLookupDrawable(&pDrawable, draw->info[i].id, client,
671 M_WINDOW,
672 DixGetAttrAccess | DixReadAccess);
673 }
674 if (rc != Success)
675 break;
676
677 DamageExtRegister(pDrawable, pDamage, i != 0);
678 }
679 }
680
681 if (rc != Success)
682 FreeResource(stuff->damage, RT_NONE);
683
684 return rc;
685 }
686
687 static int
PanoramiXDamageDelete(void * res,XID id)688 PanoramiXDamageDelete(void *res, XID id)
689 {
690 int i;
691 PanoramiXDamageRes *damage = res;
692
693 FOR_NSCREENS_BACKWARD(i) {
694 if (damage->damage[i]) {
695 DamageDestroy(damage->damage[i]);
696 damage->damage[i] = NULL;
697 }
698 }
699
700 free(damage);
701 return 1;
702 }
703
704 void
PanoramiXDamageInit(void)705 PanoramiXDamageInit(void)
706 {
707 XRT_DAMAGE = CreateNewResourceType(PanoramiXDamageDelete, "XineramaDamage");
708 if (!XRT_DAMAGE)
709 FatalError("Couldn't Xineramify Damage extension\n");
710
711 PanoramiXSaveDamageCreate = ProcDamageVector[X_DamageCreate];
712 ProcDamageVector[X_DamageCreate] = PanoramiXDamageCreate;
713 }
714
715 void
PanoramiXDamageReset(void)716 PanoramiXDamageReset(void)
717 {
718 ProcDamageVector[X_DamageCreate] = PanoramiXSaveDamageCreate;
719 }
720
721 #endif /* PANORAMIX */
722
723 void
DamageExtensionInit(void)724 DamageExtensionInit(void)
725 {
726 ExtensionEntry *extEntry;
727 int s;
728
729 for (s = 0; s < screenInfo.numScreens; s++)
730 DamageSetup(screenInfo.screens[s]);
731
732 DamageExtType = CreateNewResourceType(FreeDamageExt, "DamageExt");
733 if (!DamageExtType)
734 return;
735
736 if (!dixRegisterPrivateKey
737 (&DamageClientPrivateKeyRec, PRIVATE_CLIENT, sizeof(DamageClientRec)))
738 return;
739
740 if ((extEntry = AddExtension(DAMAGE_NAME, XDamageNumberEvents,
741 XDamageNumberErrors,
742 ProcDamageDispatch, SProcDamageDispatch,
743 NULL, StandardMinorOpcode)) != 0) {
744 DamageReqCode = (unsigned char) extEntry->base;
745 DamageEventBase = extEntry->eventBase;
746 EventSwapVector[DamageEventBase + XDamageNotify] =
747 (EventSwapPtr) SDamageNotifyEvent;
748 SetResourceTypeErrorValue(DamageExtType,
749 extEntry->errorBase + BadDamage);
750 #ifdef PANORAMIX
751 if (XRT_DAMAGE)
752 SetResourceTypeErrorValue(XRT_DAMAGE,
753 extEntry->errorBase + BadDamage);
754 #endif
755 }
756 }
757