damageext.c revision 8223e2f2
105b261ecSmrg/*
205b261ecSmrg * Copyright © 2002 Keith Packard
305b261ecSmrg *
405b261ecSmrg * Permission to use, copy, modify, distribute, and sell this software and its
505b261ecSmrg * documentation for any purpose is hereby granted without fee, provided that
605b261ecSmrg * the above copyright notice appear in all copies and that both that
705b261ecSmrg * copyright notice and this permission notice appear in supporting
805b261ecSmrg * documentation, and that the name of Keith Packard not be used in
905b261ecSmrg * advertising or publicity pertaining to distribution of the software without
1005b261ecSmrg * specific, written prior permission.  Keith Packard makes no
1105b261ecSmrg * representations about the suitability of this software for any purpose.  It
1205b261ecSmrg * is provided "as is" without express or implied warranty.
1305b261ecSmrg *
1405b261ecSmrg * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
1505b261ecSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
1605b261ecSmrg * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
1705b261ecSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
1805b261ecSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
1905b261ecSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
2005b261ecSmrg * PERFORMANCE OF THIS SOFTWARE.
2105b261ecSmrg */
2205b261ecSmrg
2305b261ecSmrg#ifdef HAVE_DIX_CONFIG_H
2405b261ecSmrg#include <dix-config.h>
2505b261ecSmrg#endif
2605b261ecSmrg
2705b261ecSmrg#include "damageextint.h"
286747b715Smrg#include "protocol-versions.h"
2905b261ecSmrg
3005b261ecSmrgstatic unsigned char	DamageReqCode;
3105b261ecSmrgstatic int		DamageEventBase;
3205b261ecSmrgstatic RESTYPE		DamageExtType;
3305b261ecSmrgstatic RESTYPE		DamageExtWinType;
3405b261ecSmrg
356747b715Smrgstatic DevPrivateKeyRec DamageClientPrivateKeyRec;
366747b715Smrg#define DamageClientPrivateKey (&DamageClientPrivateKeyRec)
3705b261ecSmrg
3805b261ecSmrgstatic void
3905b261ecSmrgDamageExtNotify (DamageExtPtr pDamageExt, BoxPtr pBoxes, int nBoxes)
4005b261ecSmrg{
4105b261ecSmrg    ClientPtr		pClient = pDamageExt->pClient;
4205b261ecSmrg    DamageClientPtr	pDamageClient = GetDamageClient (pClient);
4305b261ecSmrg    DrawablePtr		pDrawable = pDamageExt->pDrawable;
4405b261ecSmrg    xDamageNotifyEvent	ev;
4505b261ecSmrg    int			i;
4605b261ecSmrg
4705b261ecSmrg    UpdateCurrentTimeIf ();
4805b261ecSmrg    ev.type = DamageEventBase + XDamageNotify;
4905b261ecSmrg    ev.level = pDamageExt->level;
506747b715Smrg    ev.drawable = pDamageExt->drawable;
5105b261ecSmrg    ev.damage = pDamageExt->id;
5205b261ecSmrg    ev.timestamp = currentTime.milliseconds;
5305b261ecSmrg    ev.geometry.x = pDrawable->x;
5405b261ecSmrg    ev.geometry.y = pDrawable->y;
5505b261ecSmrg    ev.geometry.width = pDrawable->width;
5605b261ecSmrg    ev.geometry.height = pDrawable->height;
5705b261ecSmrg    if (pBoxes)
5805b261ecSmrg    {
5905b261ecSmrg	for (i = 0; i < nBoxes; i++)
6005b261ecSmrg	{
6105b261ecSmrg	    ev.level = pDamageExt->level;
6205b261ecSmrg	    if (i < nBoxes - 1)
6305b261ecSmrg		ev.level |= DamageNotifyMore;
6405b261ecSmrg	    ev.area.x = pBoxes[i].x1;
6505b261ecSmrg	    ev.area.y = pBoxes[i].y1;
6605b261ecSmrg	    ev.area.width = pBoxes[i].x2 - pBoxes[i].x1;
6705b261ecSmrg	    ev.area.height = pBoxes[i].y2 - pBoxes[i].y1;
686747b715Smrg	    WriteEventsToClient (pClient, 1, (xEvent *) &ev);
6905b261ecSmrg	}
7005b261ecSmrg    }
7105b261ecSmrg    else
7205b261ecSmrg    {
7305b261ecSmrg	ev.area.x = 0;
7405b261ecSmrg	ev.area.y = 0;
7505b261ecSmrg	ev.area.width = pDrawable->width;
7605b261ecSmrg	ev.area.height = pDrawable->height;
776747b715Smrg	WriteEventsToClient (pClient, 1, (xEvent *) &ev);
7805b261ecSmrg    }
7905b261ecSmrg    /* Composite extension marks clients with manual Subwindows as critical */
8005b261ecSmrg    if (pDamageClient->critical > 0)
8105b261ecSmrg    {
8205b261ecSmrg	SetCriticalOutputPending ();
8305b261ecSmrg	pClient->smart_priority = SMART_MAX_PRIORITY;
8405b261ecSmrg    }
8505b261ecSmrg}
8605b261ecSmrg
8705b261ecSmrgstatic void
8805b261ecSmrgDamageExtReport (DamagePtr pDamage, RegionPtr pRegion, void *closure)
8905b261ecSmrg{
9005b261ecSmrg    DamageExtPtr    pDamageExt = closure;
9105b261ecSmrg
9205b261ecSmrg    switch (pDamageExt->level) {
9305b261ecSmrg    case DamageReportRawRegion:
9405b261ecSmrg    case DamageReportDeltaRegion:
956747b715Smrg	DamageExtNotify (pDamageExt, RegionRects(pRegion), RegionNumRects(pRegion));
9605b261ecSmrg	break;
9705b261ecSmrg    case DamageReportBoundingBox:
986747b715Smrg	DamageExtNotify (pDamageExt, RegionExtents(pRegion), 1);
9905b261ecSmrg	break;
10005b261ecSmrg    case DamageReportNonEmpty:
10105b261ecSmrg	DamageExtNotify (pDamageExt, NullBox, 0);
10205b261ecSmrg	break;
10305b261ecSmrg    case DamageReportNone:
10405b261ecSmrg	break;
10505b261ecSmrg    }
10605b261ecSmrg}
10705b261ecSmrg
10805b261ecSmrgstatic void
10905b261ecSmrgDamageExtDestroy (DamagePtr pDamage, void *closure)
11005b261ecSmrg{
11105b261ecSmrg    DamageExtPtr    pDamageExt = closure;
11205b261ecSmrg
11305b261ecSmrg    pDamageExt->pDamage = 0;
11405b261ecSmrg    if (pDamageExt->id)
11505b261ecSmrg	FreeResource (pDamageExt->id, RT_NONE);
11605b261ecSmrg}
11705b261ecSmrg
11805b261ecSmrgvoid
11905b261ecSmrgDamageExtSetCritical (ClientPtr pClient, Bool critical)
12005b261ecSmrg{
12105b261ecSmrg    DamageClientPtr pDamageClient = GetDamageClient (pClient);
12205b261ecSmrg
12305b261ecSmrg    if (pDamageClient)
12405b261ecSmrg	pDamageClient->critical += critical ? 1 : -1;
12505b261ecSmrg}
12605b261ecSmrg
12705b261ecSmrgstatic int
12805b261ecSmrgProcDamageQueryVersion(ClientPtr client)
12905b261ecSmrg{
13005b261ecSmrg    DamageClientPtr pDamageClient = GetDamageClient (client);
13105b261ecSmrg    xDamageQueryVersionReply rep;
13205b261ecSmrg    register int n;
13305b261ecSmrg    REQUEST(xDamageQueryVersionReq);
13405b261ecSmrg
13505b261ecSmrg    REQUEST_SIZE_MATCH(xDamageQueryVersionReq);
13605b261ecSmrg    rep.type = X_Reply;
13705b261ecSmrg    rep.length = 0;
13805b261ecSmrg    rep.sequenceNumber = client->sequence;
1396747b715Smrg    if (stuff->majorVersion < SERVER_DAMAGE_MAJOR_VERSION) {
14005b261ecSmrg	rep.majorVersion = stuff->majorVersion;
14105b261ecSmrg	rep.minorVersion = stuff->minorVersion;
14205b261ecSmrg    } else {
1436747b715Smrg	rep.majorVersion = SERVER_DAMAGE_MAJOR_VERSION;
1446747b715Smrg	if (stuff->majorVersion == SERVER_DAMAGE_MAJOR_VERSION &&
1456747b715Smrg	    stuff->minorVersion < SERVER_DAMAGE_MINOR_VERSION)
14605b261ecSmrg	    rep.minorVersion = stuff->minorVersion;
14705b261ecSmrg	else
1486747b715Smrg	    rep.minorVersion = SERVER_DAMAGE_MINOR_VERSION;
14905b261ecSmrg    }
15005b261ecSmrg    pDamageClient->major_version = rep.majorVersion;
15105b261ecSmrg    pDamageClient->minor_version = rep.minorVersion;
15205b261ecSmrg    if (client->swapped) {
15305b261ecSmrg    	swaps(&rep.sequenceNumber, n);
15405b261ecSmrg    	swapl(&rep.length, n);
15505b261ecSmrg	swapl(&rep.majorVersion, n);
15605b261ecSmrg	swapl(&rep.minorVersion, n);
15705b261ecSmrg    }
15805b261ecSmrg    WriteToClient(client, sizeof(xDamageQueryVersionReply), (char *)&rep);
1596747b715Smrg    return Success;
16005b261ecSmrg}
16105b261ecSmrg
16205b261ecSmrgstatic int
16305b261ecSmrgProcDamageCreate (ClientPtr client)
16405b261ecSmrg{
16505b261ecSmrg    DrawablePtr		pDrawable;
16605b261ecSmrg    DamageExtPtr	pDamageExt;
16705b261ecSmrg    DamageReportLevel	level;
16805b261ecSmrg    RegionPtr		pRegion;
16905b261ecSmrg    int			rc;
17005b261ecSmrg
17105b261ecSmrg    REQUEST(xDamageCreateReq);
17205b261ecSmrg
17305b261ecSmrg    REQUEST_SIZE_MATCH(xDamageCreateReq);
17405b261ecSmrg    LEGAL_NEW_RESOURCE(stuff->damage, client);
17505b261ecSmrg    rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0,
1764642e01fSmrg			   DixGetAttrAccess|DixReadAccess);
17705b261ecSmrg    if (rc != Success)
17805b261ecSmrg	return rc;
17905b261ecSmrg
18005b261ecSmrg    switch (stuff->level) {
18105b261ecSmrg    case XDamageReportRawRectangles:
18205b261ecSmrg	level = DamageReportRawRegion;
18305b261ecSmrg	break;
18405b261ecSmrg    case XDamageReportDeltaRectangles:
18505b261ecSmrg	level = DamageReportDeltaRegion;
18605b261ecSmrg	break;
18705b261ecSmrg    case XDamageReportBoundingBox:
18805b261ecSmrg	level = DamageReportBoundingBox;
18905b261ecSmrg	break;
19005b261ecSmrg    case XDamageReportNonEmpty:
19105b261ecSmrg	level = DamageReportNonEmpty;
19205b261ecSmrg	break;
19305b261ecSmrg    default:
19405b261ecSmrg	client->errorValue = stuff->level;
19505b261ecSmrg	return BadValue;
19605b261ecSmrg    }
19705b261ecSmrg
1986747b715Smrg    pDamageExt = malloc(sizeof (DamageExtRec));
19905b261ecSmrg    if (!pDamageExt)
20005b261ecSmrg	return BadAlloc;
20105b261ecSmrg    pDamageExt->id = stuff->damage;
2026747b715Smrg    pDamageExt->drawable = stuff->drawable;
20305b261ecSmrg    pDamageExt->pDrawable = pDrawable;
20405b261ecSmrg    pDamageExt->level = level;
20505b261ecSmrg    pDamageExt->pClient = client;
20605b261ecSmrg    pDamageExt->pDamage = DamageCreate (DamageExtReport,
20705b261ecSmrg					DamageExtDestroy,
20805b261ecSmrg					level,
20905b261ecSmrg					FALSE,
21005b261ecSmrg					pDrawable->pScreen,
21105b261ecSmrg					pDamageExt);
21205b261ecSmrg    if (!pDamageExt->pDamage)
21305b261ecSmrg    {
2146747b715Smrg	free(pDamageExt);
21505b261ecSmrg	return BadAlloc;
21605b261ecSmrg    }
21705b261ecSmrg    if (!AddResource (stuff->damage, DamageExtType, (pointer) pDamageExt))
21805b261ecSmrg	return BadAlloc;
21905b261ecSmrg
2206747b715Smrg    DamageSetReportAfterOp (pDamageExt->pDamage, TRUE);
22105b261ecSmrg    DamageRegister (pDamageExt->pDrawable, pDamageExt->pDamage);
22205b261ecSmrg
22305b261ecSmrg    if (pDrawable->type == DRAWABLE_WINDOW)
22405b261ecSmrg    {
22505b261ecSmrg	pRegion = &((WindowPtr) pDrawable)->borderClip;
2268223e2f2Smrg	DamageDamageRegion(pDrawable, pRegion);
22705b261ecSmrg    }
22805b261ecSmrg
2296747b715Smrg    return Success;
23005b261ecSmrg}
23105b261ecSmrg
23205b261ecSmrgstatic int
23305b261ecSmrgProcDamageDestroy (ClientPtr client)
23405b261ecSmrg{
23505b261ecSmrg    REQUEST(xDamageDestroyReq);
23605b261ecSmrg    DamageExtPtr    pDamageExt;
23705b261ecSmrg
23805b261ecSmrg    REQUEST_SIZE_MATCH(xDamageDestroyReq);
23905b261ecSmrg    VERIFY_DAMAGEEXT(pDamageExt, stuff->damage, client, DixWriteAccess);
24005b261ecSmrg    FreeResource (stuff->damage, RT_NONE);
2416747b715Smrg    return Success;
24205b261ecSmrg}
24305b261ecSmrg
24405b261ecSmrgstatic int
24505b261ecSmrgProcDamageSubtract (ClientPtr client)
24605b261ecSmrg{
24705b261ecSmrg    REQUEST(xDamageSubtractReq);
24805b261ecSmrg    DamageExtPtr    pDamageExt;
24905b261ecSmrg    RegionPtr	    pRepair;
25005b261ecSmrg    RegionPtr	    pParts;
25105b261ecSmrg
25205b261ecSmrg    REQUEST_SIZE_MATCH(xDamageSubtractReq);
25305b261ecSmrg    VERIFY_DAMAGEEXT(pDamageExt, stuff->damage, client, DixWriteAccess);
25405b261ecSmrg    VERIFY_REGION_OR_NONE(pRepair, stuff->repair, client, DixWriteAccess);
25505b261ecSmrg    VERIFY_REGION_OR_NONE(pParts, stuff->parts, client, DixWriteAccess);
25605b261ecSmrg
25705b261ecSmrg    if (pDamageExt->level != DamageReportRawRegion)
25805b261ecSmrg    {
25905b261ecSmrg	DamagePtr   pDamage = pDamageExt->pDamage;
26005b261ecSmrg	if (pRepair)
26105b261ecSmrg	{
26205b261ecSmrg	    if (pParts)
2636747b715Smrg		RegionIntersect(pParts, DamageRegion (pDamage), pRepair);
26405b261ecSmrg	    if (DamageSubtract (pDamage, pRepair))
26505b261ecSmrg		DamageExtReport (pDamage, DamageRegion (pDamage), (void *) pDamageExt);
26605b261ecSmrg	}
26705b261ecSmrg	else
26805b261ecSmrg	{
26905b261ecSmrg	    if (pParts)
2706747b715Smrg		RegionCopy(pParts, DamageRegion (pDamage));
27105b261ecSmrg	    DamageEmpty (pDamage);
27205b261ecSmrg	}
27305b261ecSmrg    }
2746747b715Smrg    return Success;
27505b261ecSmrg}
27605b261ecSmrg
27705b261ecSmrgstatic int
27805b261ecSmrgProcDamageAdd (ClientPtr client)
27905b261ecSmrg{
28005b261ecSmrg    REQUEST(xDamageAddReq);
28105b261ecSmrg    DrawablePtr	    pDrawable;
28205b261ecSmrg    RegionPtr	    pRegion;
28305b261ecSmrg    int		    rc;
28405b261ecSmrg
28505b261ecSmrg    REQUEST_SIZE_MATCH(xDamageAddReq);
28605b261ecSmrg    VERIFY_REGION(pRegion, stuff->region, client, DixWriteAccess);
28705b261ecSmrg    rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0,
2884642e01fSmrg			   DixWriteAccess);
28905b261ecSmrg    if (rc != Success)
29005b261ecSmrg	return rc;
29105b261ecSmrg
29205b261ecSmrg    /* The region is relative to the drawable origin, so translate it out to
29305b261ecSmrg     * screen coordinates like damage expects.
29405b261ecSmrg     */
2956747b715Smrg    RegionTranslate(pRegion, pDrawable->x, pDrawable->y);
2968223e2f2Smrg    DamageDamageRegion(pDrawable, pRegion);
2976747b715Smrg    RegionTranslate(pRegion, -pDrawable->x, -pDrawable->y);
29805b261ecSmrg
2996747b715Smrg    return Success;
30005b261ecSmrg}
30105b261ecSmrg
30205b261ecSmrg/* Major version controls available requests */
30305b261ecSmrgstatic const int version_requests[] = {
30405b261ecSmrg    X_DamageQueryVersion,	/* before client sends QueryVersion */
30505b261ecSmrg    X_DamageAdd,		/* Version 1 */
30605b261ecSmrg};
30705b261ecSmrg
30805b261ecSmrg#define NUM_VERSION_REQUESTS	(sizeof (version_requests) / sizeof (version_requests[0]))
30905b261ecSmrg
31005b261ecSmrgstatic int (*ProcDamageVector[XDamageNumberRequests])(ClientPtr) = {
31105b261ecSmrg/*************** Version 1 ******************/
31205b261ecSmrg    ProcDamageQueryVersion,
31305b261ecSmrg    ProcDamageCreate,
31405b261ecSmrg    ProcDamageDestroy,
31505b261ecSmrg    ProcDamageSubtract,
31605b261ecSmrg/*************** Version 1.1 ****************/
31705b261ecSmrg    ProcDamageAdd,
31805b261ecSmrg};
31905b261ecSmrg
32005b261ecSmrg
32105b261ecSmrgstatic int
32205b261ecSmrgProcDamageDispatch (ClientPtr client)
32305b261ecSmrg{
32405b261ecSmrg    REQUEST(xDamageReq);
32505b261ecSmrg    DamageClientPtr pDamageClient = GetDamageClient (client);
32605b261ecSmrg
32705b261ecSmrg    if (pDamageClient->major_version >= NUM_VERSION_REQUESTS)
32805b261ecSmrg	return BadRequest;
32905b261ecSmrg    if (stuff->damageReqType > version_requests[pDamageClient->major_version])
33005b261ecSmrg	return BadRequest;
33105b261ecSmrg    return (*ProcDamageVector[stuff->damageReqType]) (client);
33205b261ecSmrg}
33305b261ecSmrg
33405b261ecSmrgstatic int
33505b261ecSmrgSProcDamageQueryVersion(ClientPtr client)
33605b261ecSmrg{
33705b261ecSmrg    register int n;
33805b261ecSmrg    REQUEST(xDamageQueryVersionReq);
33905b261ecSmrg
34005b261ecSmrg    swaps(&stuff->length, n);
34105b261ecSmrg    REQUEST_SIZE_MATCH(xDamageQueryVersionReq);
34205b261ecSmrg    swapl(&stuff->majorVersion, n);
34305b261ecSmrg    swapl(&stuff->minorVersion, n);
34405b261ecSmrg    return (*ProcDamageVector[stuff->damageReqType]) (client);
34505b261ecSmrg}
34605b261ecSmrg
34705b261ecSmrgstatic int
34805b261ecSmrgSProcDamageCreate (ClientPtr client)
34905b261ecSmrg{
35005b261ecSmrg    register int n;
35105b261ecSmrg    REQUEST(xDamageCreateReq);
35205b261ecSmrg
35305b261ecSmrg    swaps (&stuff->length, n);
35405b261ecSmrg    REQUEST_SIZE_MATCH(xDamageCreateReq);
35505b261ecSmrg    swapl (&stuff->damage, n);
35605b261ecSmrg    swapl (&stuff->drawable, n);
35705b261ecSmrg    return (*ProcDamageVector[stuff->damageReqType]) (client);
35805b261ecSmrg}
35905b261ecSmrg
36005b261ecSmrgstatic int
36105b261ecSmrgSProcDamageDestroy (ClientPtr client)
36205b261ecSmrg{
36305b261ecSmrg    register int n;
36405b261ecSmrg    REQUEST(xDamageDestroyReq);
36505b261ecSmrg
36605b261ecSmrg    swaps (&stuff->length, n);
36705b261ecSmrg    REQUEST_SIZE_MATCH(xDamageDestroyReq);
36805b261ecSmrg    swapl (&stuff->damage, n);
36905b261ecSmrg    return (*ProcDamageVector[stuff->damageReqType]) (client);
37005b261ecSmrg}
37105b261ecSmrg
37205b261ecSmrgstatic int
37305b261ecSmrgSProcDamageSubtract (ClientPtr client)
37405b261ecSmrg{
37505b261ecSmrg    register int n;
37605b261ecSmrg    REQUEST(xDamageSubtractReq);
37705b261ecSmrg
37805b261ecSmrg    swaps (&stuff->length, n);
37905b261ecSmrg    REQUEST_SIZE_MATCH(xDamageSubtractReq);
38005b261ecSmrg    swapl (&stuff->damage, n);
38105b261ecSmrg    swapl (&stuff->repair, n);
38205b261ecSmrg    swapl (&stuff->parts, n);
38305b261ecSmrg    return (*ProcDamageVector[stuff->damageReqType]) (client);
38405b261ecSmrg}
38505b261ecSmrg
38605b261ecSmrgstatic int
38705b261ecSmrgSProcDamageAdd (ClientPtr client)
38805b261ecSmrg{
38905b261ecSmrg    register int n;
39005b261ecSmrg    REQUEST(xDamageAddReq);
39105b261ecSmrg
39205b261ecSmrg    swaps (&stuff->length, n);
39305b261ecSmrg    REQUEST_SIZE_MATCH(xDamageSubtractReq);
39405b261ecSmrg    swapl (&stuff->drawable, n);
39505b261ecSmrg    swapl (&stuff->region, n);
39605b261ecSmrg    return (*ProcDamageVector[stuff->damageReqType]) (client);
39705b261ecSmrg}
39805b261ecSmrg
39905b261ecSmrgstatic int (*SProcDamageVector[XDamageNumberRequests])(ClientPtr) = {
40005b261ecSmrg/*************** Version 1 ******************/
40105b261ecSmrg    SProcDamageQueryVersion,
40205b261ecSmrg    SProcDamageCreate,
40305b261ecSmrg    SProcDamageDestroy,
40405b261ecSmrg    SProcDamageSubtract,
40505b261ecSmrg/*************** Version 1.1 ****************/
40605b261ecSmrg    SProcDamageAdd,
40705b261ecSmrg};
40805b261ecSmrg
40905b261ecSmrgstatic int
41005b261ecSmrgSProcDamageDispatch (ClientPtr client)
41105b261ecSmrg{
41205b261ecSmrg    REQUEST(xDamageReq);
41305b261ecSmrg    if (stuff->damageReqType >= XDamageNumberRequests)
41405b261ecSmrg	return BadRequest;
41505b261ecSmrg    return (*SProcDamageVector[stuff->damageReqType]) (client);
41605b261ecSmrg}
41705b261ecSmrg
41805b261ecSmrgstatic void
41905b261ecSmrgDamageClientCallback (CallbackListPtr	*list,
42005b261ecSmrg		      pointer		closure,
42105b261ecSmrg		      pointer		data)
42205b261ecSmrg{
42305b261ecSmrg    NewClientInfoRec	*clientinfo = (NewClientInfoRec *) data;
42405b261ecSmrg    ClientPtr		pClient = clientinfo->client;
42505b261ecSmrg    DamageClientPtr	pDamageClient = GetDamageClient (pClient);
42605b261ecSmrg
42705b261ecSmrg    pDamageClient->critical = 0;
42805b261ecSmrg    pDamageClient->major_version = 0;
42905b261ecSmrg    pDamageClient->minor_version = 0;
43005b261ecSmrg}
43105b261ecSmrg
43205b261ecSmrg/*ARGSUSED*/
43305b261ecSmrgstatic void
43405b261ecSmrgDamageResetProc (ExtensionEntry *extEntry)
43505b261ecSmrg{
43605b261ecSmrg    DeleteCallback (&ClientStateCallback, DamageClientCallback, 0);
43705b261ecSmrg}
43805b261ecSmrg
43905b261ecSmrgstatic int
44005b261ecSmrgFreeDamageExt (pointer value, XID did)
44105b261ecSmrg{
44205b261ecSmrg    DamageExtPtr    pDamageExt = (DamageExtPtr) value;
44305b261ecSmrg
44405b261ecSmrg    /*
44505b261ecSmrg     * Get rid of the resource table entry hanging from the window id
44605b261ecSmrg     */
44705b261ecSmrg    pDamageExt->id = 0;
44805b261ecSmrg    if (WindowDrawable(pDamageExt->pDrawable->type))
44905b261ecSmrg	FreeResourceByType (pDamageExt->pDrawable->id, DamageExtWinType, TRUE);
45005b261ecSmrg    if (pDamageExt->pDamage)
45105b261ecSmrg    {
45205b261ecSmrg	DamageUnregister (pDamageExt->pDrawable, pDamageExt->pDamage);
45305b261ecSmrg	DamageDestroy (pDamageExt->pDamage);
45405b261ecSmrg    }
4556747b715Smrg    free(pDamageExt);
45605b261ecSmrg    return Success;
45705b261ecSmrg}
45805b261ecSmrg
45905b261ecSmrgstatic int
46005b261ecSmrgFreeDamageExtWin (pointer value, XID wid)
46105b261ecSmrg{
46205b261ecSmrg    DamageExtPtr    pDamageExt = (DamageExtPtr) value;
46305b261ecSmrg
46405b261ecSmrg    if (pDamageExt->id)
46505b261ecSmrg	FreeResource (pDamageExt->id, RT_NONE);
46605b261ecSmrg    return Success;
46705b261ecSmrg}
46805b261ecSmrg
46905b261ecSmrgstatic void
47005b261ecSmrgSDamageNotifyEvent (xDamageNotifyEvent *from,
47105b261ecSmrg		    xDamageNotifyEvent *to)
47205b261ecSmrg{
47305b261ecSmrg    to->type = from->type;
47405b261ecSmrg    cpswaps (from->sequenceNumber, to->sequenceNumber);
47505b261ecSmrg    cpswapl (from->drawable, to->drawable);
47605b261ecSmrg    cpswapl (from->damage, to->damage);
47705b261ecSmrg    cpswaps (from->area.x, to->area.x);
47805b261ecSmrg    cpswaps (from->area.y, to->area.y);
47905b261ecSmrg    cpswaps (from->area.width, to->area.width);
48005b261ecSmrg    cpswaps (from->area.height, to->area.height);
48105b261ecSmrg    cpswaps (from->geometry.x, to->geometry.x);
48205b261ecSmrg    cpswaps (from->geometry.y, to->geometry.y);
48305b261ecSmrg    cpswaps (from->geometry.width, to->geometry.width);
48405b261ecSmrg    cpswaps (from->geometry.height, to->geometry.height);
48505b261ecSmrg}
48605b261ecSmrg
48705b261ecSmrgvoid
48805b261ecSmrgDamageExtensionInit(void)
48905b261ecSmrg{
49005b261ecSmrg    ExtensionEntry *extEntry;
49105b261ecSmrg    int		    s;
49205b261ecSmrg
49305b261ecSmrg    for (s = 0; s < screenInfo.numScreens; s++)
49405b261ecSmrg	DamageSetup (screenInfo.screens[s]);
49505b261ecSmrg
4966747b715Smrg    DamageExtType = CreateNewResourceType (FreeDamageExt, "DamageExt");
49705b261ecSmrg    if (!DamageExtType)
49805b261ecSmrg	return;
49905b261ecSmrg
5006747b715Smrg    DamageExtWinType = CreateNewResourceType (FreeDamageExtWin, "DamageExtWin");
50105b261ecSmrg    if (!DamageExtWinType)
50205b261ecSmrg	return;
50305b261ecSmrg
5046747b715Smrg    if (!dixRegisterPrivateKey(&DamageClientPrivateKeyRec, PRIVATE_CLIENT, sizeof (DamageClientRec)))
50505b261ecSmrg	return;
5066747b715Smrg
50705b261ecSmrg    if (!AddCallback (&ClientStateCallback, DamageClientCallback, 0))
50805b261ecSmrg	return;
50905b261ecSmrg
51005b261ecSmrg    if ((extEntry = AddExtension(DAMAGE_NAME, XDamageNumberEvents,
51105b261ecSmrg				 XDamageNumberErrors,
51205b261ecSmrg				 ProcDamageDispatch, SProcDamageDispatch,
51305b261ecSmrg				 DamageResetProc, StandardMinorOpcode)) != 0)
51405b261ecSmrg    {
51505b261ecSmrg	DamageReqCode = (unsigned char)extEntry->base;
51605b261ecSmrg	DamageEventBase = extEntry->eventBase;
51705b261ecSmrg	EventSwapVector[DamageEventBase + XDamageNotify] =
51805b261ecSmrg			(EventSwapPtr) SDamageNotifyEvent;
5196747b715Smrg	SetResourceTypeErrorValue(DamageExtType, extEntry->errorBase + BadDamage);
52005b261ecSmrg    }
52105b261ecSmrg}
522