2 * Copyright © 2002 Keith Packard
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of Keith Packard not be used in
9 * advertising or publicity pertaining to distribution of the software without
10 * specific, written prior permission. Keith Packard makes no
11 * representations about the suitability of this software for any purpose. It
12 * is provided "as is" without express or implied warranty.
14 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20 * PERFORMANCE OF THIS SOFTWARE.
23 #ifdef HAVE_DIX_CONFIG_H
24 #include <dix-config.h>
27 #include "damageextint.h"
29 static unsigned char DamageReqCode
;
30 static int DamageEventBase
;
31 static int DamageErrorBase
;
32 static int DamageClientPrivateIndex
;
33 static RESTYPE DamageExtType
;
34 static RESTYPE DamageExtWinType
;
36 /* Version of the damage extension supported by the server, as opposed to the
37 * DAMAGE_* defines from damageproto for what version the proto header
40 #define SERVER_DAMAGE_MAJOR 1
41 #define SERVER_DAMAGE_MINOR 1
43 #define prScreen screenInfo.screens[0]
46 DamageExtNotify (DamageExtPtr pDamageExt
, BoxPtr pBoxes
, int nBoxes
)
48 ClientPtr pClient
= pDamageExt
->pClient
;
49 DamageClientPtr pDamageClient
= GetDamageClient (pClient
);
50 DrawablePtr pDrawable
= pDamageExt
->pDrawable
;
51 xDamageNotifyEvent ev
;
54 UpdateCurrentTimeIf ();
55 ev
.type
= DamageEventBase
+ XDamageNotify
;
56 ev
.level
= pDamageExt
->level
;
57 ev
.sequenceNumber
= pClient
->sequence
;
58 ev
.drawable
= pDrawable
->id
;
59 ev
.damage
= pDamageExt
->id
;
60 ev
.timestamp
= currentTime
.milliseconds
;
61 ev
.geometry
.x
= pDrawable
->x
;
62 ev
.geometry
.y
= pDrawable
->y
;
63 ev
.geometry
.width
= pDrawable
->width
;
64 ev
.geometry
.height
= pDrawable
->height
;
67 for (i
= 0; i
< nBoxes
; i
++)
69 ev
.level
= pDamageExt
->level
;
71 ev
.level
|= DamageNotifyMore
;
72 ev
.area
.x
= pBoxes
[i
].x1
;
73 ev
.area
.y
= pBoxes
[i
].y1
;
74 ev
.area
.width
= pBoxes
[i
].x2
- pBoxes
[i
].x1
;
75 ev
.area
.height
= pBoxes
[i
].y2
- pBoxes
[i
].y1
;
76 if (!pClient
->clientGone
)
77 WriteEventsToClient (pClient
, 1, (xEvent
*) &ev
);
84 ev
.area
.width
= pDrawable
->width
;
85 ev
.area
.height
= pDrawable
->height
;
86 if (!pClient
->clientGone
)
87 WriteEventsToClient (pClient
, 1, (xEvent
*) &ev
);
89 /* Composite extension marks clients with manual Subwindows as critical */
90 if (pDamageClient
->critical
> 0)
92 SetCriticalOutputPending ();
94 pClient
->smart_priority
= SMART_MAX_PRIORITY
;
100 DamageExtReport (DamagePtr pDamage
, RegionPtr pRegion
, void *closure
)
102 DamageExtPtr pDamageExt
= closure
;
104 switch (pDamageExt
->level
) {
105 case DamageReportRawRegion
:
106 case DamageReportDeltaRegion
:
107 DamageExtNotify (pDamageExt
, REGION_RECTS(pRegion
), REGION_NUM_RECTS(pRegion
));
109 case DamageReportBoundingBox
:
110 DamageExtNotify (pDamageExt
, REGION_EXTENTS(prScreen
, pRegion
), 1);
112 case DamageReportNonEmpty
:
113 DamageExtNotify (pDamageExt
, NullBox
, 0);
115 case DamageReportNone
:
121 DamageExtDestroy (DamagePtr pDamage
, void *closure
)
123 DamageExtPtr pDamageExt
= closure
;
125 pDamageExt
->pDamage
= 0;
127 FreeResource (pDamageExt
->id
, RT_NONE
);
131 DamageExtSetCritical (ClientPtr pClient
, Bool critical
)
133 DamageClientPtr pDamageClient
= GetDamageClient (pClient
);
136 pDamageClient
->critical
+= critical
? 1 : -1;
140 ProcDamageQueryVersion(ClientPtr client
)
142 DamageClientPtr pDamageClient
= GetDamageClient (client
);
143 xDamageQueryVersionReply rep
;
145 REQUEST(xDamageQueryVersionReq
);
147 REQUEST_SIZE_MATCH(xDamageQueryVersionReq
);
150 rep
.sequenceNumber
= client
->sequence
;
151 if (stuff
->majorVersion
< SERVER_DAMAGE_MAJOR
) {
152 rep
.majorVersion
= stuff
->majorVersion
;
153 rep
.minorVersion
= stuff
->minorVersion
;
155 rep
.majorVersion
= SERVER_DAMAGE_MAJOR
;
156 if (stuff
->majorVersion
== SERVER_DAMAGE_MAJOR
&&
157 stuff
->minorVersion
< SERVER_DAMAGE_MINOR
)
158 rep
.minorVersion
= stuff
->minorVersion
;
160 rep
.minorVersion
= SERVER_DAMAGE_MINOR
;
162 pDamageClient
->major_version
= rep
.majorVersion
;
163 pDamageClient
->minor_version
= rep
.minorVersion
;
164 if (client
->swapped
) {
165 swaps(&rep
.sequenceNumber
, n
);
166 swapl(&rep
.length
, n
);
167 swapl(&rep
.majorVersion
, n
);
168 swapl(&rep
.minorVersion
, n
);
170 WriteToClient(client
, sizeof(xDamageQueryVersionReply
), (char *)&rep
);
171 return(client
->noClientException
);
175 ProcDamageCreate (ClientPtr client
)
177 DrawablePtr pDrawable
;
178 DamageExtPtr pDamageExt
;
179 DamageReportLevel level
;
183 REQUEST(xDamageCreateReq
);
185 REQUEST_SIZE_MATCH(xDamageCreateReq
);
186 LEGAL_NEW_RESOURCE(stuff
->damage
, client
);
187 rc
= dixLookupDrawable(&pDrawable
, stuff
->drawable
, client
, 0,
192 switch (stuff
->level
) {
193 case XDamageReportRawRectangles
:
194 level
= DamageReportRawRegion
;
196 case XDamageReportDeltaRectangles
:
197 level
= DamageReportDeltaRegion
;
199 case XDamageReportBoundingBox
:
200 level
= DamageReportBoundingBox
;
202 case XDamageReportNonEmpty
:
203 level
= DamageReportNonEmpty
;
206 client
->errorValue
= stuff
->level
;
210 pDamageExt
= xalloc (sizeof (DamageExtRec
));
213 pDamageExt
->id
= stuff
->damage
;
214 pDamageExt
->pDrawable
= pDrawable
;
215 pDamageExt
->level
= level
;
216 pDamageExt
->pClient
= client
;
217 pDamageExt
->pDamage
= DamageCreate (DamageExtReport
,
223 if (!pDamageExt
->pDamage
)
228 if (!AddResource (stuff
->damage
, DamageExtType
, (pointer
) pDamageExt
))
231 DamageRegister (pDamageExt
->pDrawable
, pDamageExt
->pDamage
);
233 if (pDrawable
->type
== DRAWABLE_WINDOW
)
235 pRegion
= &((WindowPtr
) pDrawable
)->borderClip
;
236 DamageDamageRegion (pDrawable
, pRegion
);
239 return (client
->noClientException
);
243 ProcDamageDestroy (ClientPtr client
)
245 REQUEST(xDamageDestroyReq
);
246 DamageExtPtr pDamageExt
;
248 REQUEST_SIZE_MATCH(xDamageDestroyReq
);
249 VERIFY_DAMAGEEXT(pDamageExt
, stuff
->damage
, client
, DixWriteAccess
);
250 FreeResource (stuff
->damage
, RT_NONE
);
251 return (client
->noClientException
);
255 ProcDamageSubtract (ClientPtr client
)
257 REQUEST(xDamageSubtractReq
);
258 DamageExtPtr pDamageExt
;
262 REQUEST_SIZE_MATCH(xDamageSubtractReq
);
263 VERIFY_DAMAGEEXT(pDamageExt
, stuff
->damage
, client
, DixWriteAccess
);
264 VERIFY_REGION_OR_NONE(pRepair
, stuff
->repair
, client
, DixWriteAccess
);
265 VERIFY_REGION_OR_NONE(pParts
, stuff
->parts
, client
, DixWriteAccess
);
267 if (pDamageExt
->level
!= DamageReportRawRegion
)
269 DamagePtr pDamage
= pDamageExt
->pDamage
;
273 REGION_INTERSECT (prScreen
, pParts
, DamageRegion (pDamage
), pRepair
);
274 if (DamageSubtract (pDamage
, pRepair
))
275 DamageExtReport (pDamage
, DamageRegion (pDamage
), (void *) pDamageExt
);
280 REGION_COPY (prScreen
, pParts
, DamageRegion (pDamage
));
281 DamageEmpty (pDamage
);
284 return (client
->noClientException
);
288 ProcDamageAdd (ClientPtr client
)
290 REQUEST(xDamageAddReq
);
291 DrawablePtr pDrawable
;
295 REQUEST_SIZE_MATCH(xDamageAddReq
);
296 VERIFY_REGION(pRegion
, stuff
->region
, client
, DixWriteAccess
);
297 rc
= dixLookupDrawable(&pDrawable
, stuff
->drawable
, client
, 0,
302 /* The region is relative to the drawable origin, so translate it out to
303 * screen coordinates like damage expects.
305 REGION_TRANSLATE(pScreen
, pRegion
, pDrawable
->x
, pDrawable
->y
);
306 DamageDamageRegion(pDrawable
, pRegion
);
307 REGION_TRANSLATE(pScreen
, pRegion
, -pDrawable
->x
, -pDrawable
->y
);
309 return (client
->noClientException
);
312 /* Major version controls available requests */
313 static const int version_requests
[] = {
314 X_DamageQueryVersion
, /* before client sends QueryVersion */
315 X_DamageAdd
, /* Version 1 */
318 #define NUM_VERSION_REQUESTS (sizeof (version_requests) / sizeof (version_requests[0]))
320 static int (*ProcDamageVector
[XDamageNumberRequests
])(ClientPtr
) = {
321 /*************** Version 1 ******************/
322 ProcDamageQueryVersion
,
326 /*************** Version 1.1 ****************/
332 ProcDamageDispatch (ClientPtr client
)
335 DamageClientPtr pDamageClient
= GetDamageClient (client
);
337 if (pDamageClient
->major_version
>= NUM_VERSION_REQUESTS
)
339 if (stuff
->damageReqType
> version_requests
[pDamageClient
->major_version
])
341 return (*ProcDamageVector
[stuff
->damageReqType
]) (client
);
345 SProcDamageQueryVersion(ClientPtr client
)
348 REQUEST(xDamageQueryVersionReq
);
350 swaps(&stuff
->length
, n
);
351 REQUEST_SIZE_MATCH(xDamageQueryVersionReq
);
352 swapl(&stuff
->majorVersion
, n
);
353 swapl(&stuff
->minorVersion
, n
);
354 return (*ProcDamageVector
[stuff
->damageReqType
]) (client
);
358 SProcDamageCreate (ClientPtr client
)
361 REQUEST(xDamageCreateReq
);
363 swaps (&stuff
->length
, n
);
364 REQUEST_SIZE_MATCH(xDamageCreateReq
);
365 swapl (&stuff
->damage
, n
);
366 swapl (&stuff
->drawable
, n
);
367 return (*ProcDamageVector
[stuff
->damageReqType
]) (client
);
371 SProcDamageDestroy (ClientPtr client
)
374 REQUEST(xDamageDestroyReq
);
376 swaps (&stuff
->length
, n
);
377 REQUEST_SIZE_MATCH(xDamageDestroyReq
);
378 swapl (&stuff
->damage
, n
);
379 return (*ProcDamageVector
[stuff
->damageReqType
]) (client
);
383 SProcDamageSubtract (ClientPtr client
)
386 REQUEST(xDamageSubtractReq
);
388 swaps (&stuff
->length
, n
);
389 REQUEST_SIZE_MATCH(xDamageSubtractReq
);
390 swapl (&stuff
->damage
, n
);
391 swapl (&stuff
->repair
, n
);
392 swapl (&stuff
->parts
, n
);
393 return (*ProcDamageVector
[stuff
->damageReqType
]) (client
);
397 SProcDamageAdd (ClientPtr client
)
400 REQUEST(xDamageAddReq
);
402 swaps (&stuff
->length
, n
);
403 REQUEST_SIZE_MATCH(xDamageSubtractReq
);
404 swapl (&stuff
->drawable
, n
);
405 swapl (&stuff
->region
, n
);
406 return (*ProcDamageVector
[stuff
->damageReqType
]) (client
);
409 static int (*SProcDamageVector
[XDamageNumberRequests
])(ClientPtr
) = {
410 /*************** Version 1 ******************/
411 SProcDamageQueryVersion
,
415 /*************** Version 1.1 ****************/
420 SProcDamageDispatch (ClientPtr client
)
423 if (stuff
->damageReqType
>= XDamageNumberRequests
)
425 return (*SProcDamageVector
[stuff
->damageReqType
]) (client
);
429 DamageClientCallback (CallbackListPtr
*list
,
433 NewClientInfoRec
*clientinfo
= (NewClientInfoRec
*) data
;
434 ClientPtr pClient
= clientinfo
->client
;
435 DamageClientPtr pDamageClient
= GetDamageClient (pClient
);
437 pDamageClient
->critical
= 0;
438 pDamageClient
->major_version
= 0;
439 pDamageClient
->minor_version
= 0;
444 DamageResetProc (ExtensionEntry
*extEntry
)
446 DeleteCallback (&ClientStateCallback
, DamageClientCallback
, 0);
450 FreeDamageExt (pointer value
, XID did
)
452 DamageExtPtr pDamageExt
= (DamageExtPtr
) value
;
455 * Get rid of the resource table entry hanging from the window id
458 if (WindowDrawable(pDamageExt
->pDrawable
->type
))
459 FreeResourceByType (pDamageExt
->pDrawable
->id
, DamageExtWinType
, TRUE
);
460 if (pDamageExt
->pDamage
)
462 DamageUnregister (pDamageExt
->pDrawable
, pDamageExt
->pDamage
);
463 DamageDestroy (pDamageExt
->pDamage
);
470 FreeDamageExtWin (pointer value
, XID wid
)
472 DamageExtPtr pDamageExt
= (DamageExtPtr
) value
;
475 FreeResource (pDamageExt
->id
, RT_NONE
);
480 SDamageNotifyEvent (xDamageNotifyEvent
*from
,
481 xDamageNotifyEvent
*to
)
483 to
->type
= from
->type
;
484 cpswaps (from
->sequenceNumber
, to
->sequenceNumber
);
485 cpswapl (from
->drawable
, to
->drawable
);
486 cpswapl (from
->damage
, to
->damage
);
487 cpswaps (from
->area
.x
, to
->area
.x
);
488 cpswaps (from
->area
.y
, to
->area
.y
);
489 cpswaps (from
->area
.width
, to
->area
.width
);
490 cpswaps (from
->area
.height
, to
->area
.height
);
491 cpswaps (from
->geometry
.x
, to
->geometry
.x
);
492 cpswaps (from
->geometry
.y
, to
->geometry
.y
);
493 cpswaps (from
->geometry
.width
, to
->geometry
.width
);
494 cpswaps (from
->geometry
.height
, to
->geometry
.height
);
498 DamageExtensionInit(void)
500 ExtensionEntry
*extEntry
;
503 for (s
= 0; s
< screenInfo
.numScreens
; s
++)
504 DamageSetup (screenInfo
.screens
[s
]);
506 DamageExtType
= CreateNewResourceType (FreeDamageExt
);
510 DamageExtWinType
= CreateNewResourceType (FreeDamageExtWin
);
511 if (!DamageExtWinType
)
514 DamageClientPrivateIndex
= AllocateClientPrivateIndex ();
515 if (!AllocateClientPrivate (DamageClientPrivateIndex
,
516 sizeof (DamageClientRec
)))
518 if (!AddCallback (&ClientStateCallback
, DamageClientCallback
, 0))
521 if ((extEntry
= AddExtension(DAMAGE_NAME
, XDamageNumberEvents
,
523 ProcDamageDispatch
, SProcDamageDispatch
,
524 DamageResetProc
, StandardMinorOpcode
)) != 0)
526 DamageReqCode
= (unsigned char)extEntry
->base
;
527 DamageEventBase
= extEntry
->eventBase
;
528 DamageErrorBase
= extEntry
->errorBase
;
529 EventSwapVector
[DamageEventBase
+ XDamageNotify
] =
530 (EventSwapPtr
) SDamageNotifyEvent
;