damageext.c revision 05b261ec
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"
2805b261ecSmrg
2905b261ecSmrgstatic unsigned char	DamageReqCode;
3005b261ecSmrgstatic int		DamageEventBase;
3105b261ecSmrgstatic int		DamageErrorBase;
3205b261ecSmrgstatic int		DamageClientPrivateIndex;
3305b261ecSmrgstatic RESTYPE		DamageExtType;
3405b261ecSmrgstatic RESTYPE		DamageExtWinType;
3505b261ecSmrg
3605b261ecSmrg/* Version of the damage extension supported by the server, as opposed to the
3705b261ecSmrg * DAMAGE_* defines from damageproto for what version the proto header
3805b261ecSmrg * supports.
3905b261ecSmrg */
4005b261ecSmrg#define SERVER_DAMAGE_MAJOR	1
4105b261ecSmrg#define SERVER_DAMAGE_MINOR	1
4205b261ecSmrg
4305b261ecSmrg#define prScreen	screenInfo.screens[0]
4405b261ecSmrg
4505b261ecSmrgstatic void
4605b261ecSmrgDamageExtNotify (DamageExtPtr pDamageExt, BoxPtr pBoxes, int nBoxes)
4705b261ecSmrg{
4805b261ecSmrg    ClientPtr		pClient = pDamageExt->pClient;
4905b261ecSmrg    DamageClientPtr	pDamageClient = GetDamageClient (pClient);
5005b261ecSmrg    DrawablePtr		pDrawable = pDamageExt->pDrawable;
5105b261ecSmrg    xDamageNotifyEvent	ev;
5205b261ecSmrg    int			i;
5305b261ecSmrg
5405b261ecSmrg    UpdateCurrentTimeIf ();
5505b261ecSmrg    ev.type = DamageEventBase + XDamageNotify;
5605b261ecSmrg    ev.level = pDamageExt->level;
5705b261ecSmrg    ev.sequenceNumber = pClient->sequence;
5805b261ecSmrg    ev.drawable = pDrawable->id;
5905b261ecSmrg    ev.damage = pDamageExt->id;
6005b261ecSmrg    ev.timestamp = currentTime.milliseconds;
6105b261ecSmrg    ev.geometry.x = pDrawable->x;
6205b261ecSmrg    ev.geometry.y = pDrawable->y;
6305b261ecSmrg    ev.geometry.width = pDrawable->width;
6405b261ecSmrg    ev.geometry.height = pDrawable->height;
6505b261ecSmrg    if (pBoxes)
6605b261ecSmrg    {
6705b261ecSmrg	for (i = 0; i < nBoxes; i++)
6805b261ecSmrg	{
6905b261ecSmrg	    ev.level = pDamageExt->level;
7005b261ecSmrg	    if (i < nBoxes - 1)
7105b261ecSmrg		ev.level |= DamageNotifyMore;
7205b261ecSmrg	    ev.area.x = pBoxes[i].x1;
7305b261ecSmrg	    ev.area.y = pBoxes[i].y1;
7405b261ecSmrg	    ev.area.width = pBoxes[i].x2 - pBoxes[i].x1;
7505b261ecSmrg	    ev.area.height = pBoxes[i].y2 - pBoxes[i].y1;
7605b261ecSmrg	    if (!pClient->clientGone)
7705b261ecSmrg		WriteEventsToClient (pClient, 1, (xEvent *) &ev);
7805b261ecSmrg	}
7905b261ecSmrg    }
8005b261ecSmrg    else
8105b261ecSmrg    {
8205b261ecSmrg	ev.area.x = 0;
8305b261ecSmrg	ev.area.y = 0;
8405b261ecSmrg	ev.area.width = pDrawable->width;
8505b261ecSmrg	ev.area.height = pDrawable->height;
8605b261ecSmrg	if (!pClient->clientGone)
8705b261ecSmrg	    WriteEventsToClient (pClient, 1, (xEvent *) &ev);
8805b261ecSmrg    }
8905b261ecSmrg    /* Composite extension marks clients with manual Subwindows as critical */
9005b261ecSmrg    if (pDamageClient->critical > 0)
9105b261ecSmrg    {
9205b261ecSmrg	SetCriticalOutputPending ();
9305b261ecSmrg#ifdef SMART_SCHEDULE
9405b261ecSmrg	pClient->smart_priority = SMART_MAX_PRIORITY;
9505b261ecSmrg#endif
9605b261ecSmrg    }
9705b261ecSmrg}
9805b261ecSmrg
9905b261ecSmrgstatic void
10005b261ecSmrgDamageExtReport (DamagePtr pDamage, RegionPtr pRegion, void *closure)
10105b261ecSmrg{
10205b261ecSmrg    DamageExtPtr    pDamageExt = closure;
10305b261ecSmrg
10405b261ecSmrg    switch (pDamageExt->level) {
10505b261ecSmrg    case DamageReportRawRegion:
10605b261ecSmrg    case DamageReportDeltaRegion:
10705b261ecSmrg	DamageExtNotify (pDamageExt, REGION_RECTS(pRegion), REGION_NUM_RECTS(pRegion));
10805b261ecSmrg	break;
10905b261ecSmrg    case DamageReportBoundingBox:
11005b261ecSmrg	DamageExtNotify (pDamageExt, REGION_EXTENTS(prScreen, pRegion), 1);
11105b261ecSmrg	break;
11205b261ecSmrg    case DamageReportNonEmpty:
11305b261ecSmrg	DamageExtNotify (pDamageExt, NullBox, 0);
11405b261ecSmrg	break;
11505b261ecSmrg    case DamageReportNone:
11605b261ecSmrg	break;
11705b261ecSmrg    }
11805b261ecSmrg}
11905b261ecSmrg
12005b261ecSmrgstatic void
12105b261ecSmrgDamageExtDestroy (DamagePtr pDamage, void *closure)
12205b261ecSmrg{
12305b261ecSmrg    DamageExtPtr    pDamageExt = closure;
12405b261ecSmrg
12505b261ecSmrg    pDamageExt->pDamage = 0;
12605b261ecSmrg    if (pDamageExt->id)
12705b261ecSmrg	FreeResource (pDamageExt->id, RT_NONE);
12805b261ecSmrg}
12905b261ecSmrg
13005b261ecSmrgvoid
13105b261ecSmrgDamageExtSetCritical (ClientPtr pClient, Bool critical)
13205b261ecSmrg{
13305b261ecSmrg    DamageClientPtr pDamageClient = GetDamageClient (pClient);
13405b261ecSmrg
13505b261ecSmrg    if (pDamageClient)
13605b261ecSmrg	pDamageClient->critical += critical ? 1 : -1;
13705b261ecSmrg}
13805b261ecSmrg
13905b261ecSmrgstatic int
14005b261ecSmrgProcDamageQueryVersion(ClientPtr client)
14105b261ecSmrg{
14205b261ecSmrg    DamageClientPtr pDamageClient = GetDamageClient (client);
14305b261ecSmrg    xDamageQueryVersionReply rep;
14405b261ecSmrg    register int n;
14505b261ecSmrg    REQUEST(xDamageQueryVersionReq);
14605b261ecSmrg
14705b261ecSmrg    REQUEST_SIZE_MATCH(xDamageQueryVersionReq);
14805b261ecSmrg    rep.type = X_Reply;
14905b261ecSmrg    rep.length = 0;
15005b261ecSmrg    rep.sequenceNumber = client->sequence;
15105b261ecSmrg    if (stuff->majorVersion < SERVER_DAMAGE_MAJOR) {
15205b261ecSmrg	rep.majorVersion = stuff->majorVersion;
15305b261ecSmrg	rep.minorVersion = stuff->minorVersion;
15405b261ecSmrg    } else {
15505b261ecSmrg	rep.majorVersion = SERVER_DAMAGE_MAJOR;
15605b261ecSmrg	if (stuff->majorVersion == SERVER_DAMAGE_MAJOR &&
15705b261ecSmrg	    stuff->minorVersion < SERVER_DAMAGE_MINOR)
15805b261ecSmrg	    rep.minorVersion = stuff->minorVersion;
15905b261ecSmrg	else
16005b261ecSmrg	    rep.minorVersion = SERVER_DAMAGE_MINOR;
16105b261ecSmrg    }
16205b261ecSmrg    pDamageClient->major_version = rep.majorVersion;
16305b261ecSmrg    pDamageClient->minor_version = rep.minorVersion;
16405b261ecSmrg    if (client->swapped) {
16505b261ecSmrg    	swaps(&rep.sequenceNumber, n);
16605b261ecSmrg    	swapl(&rep.length, n);
16705b261ecSmrg	swapl(&rep.majorVersion, n);
16805b261ecSmrg	swapl(&rep.minorVersion, n);
16905b261ecSmrg    }
17005b261ecSmrg    WriteToClient(client, sizeof(xDamageQueryVersionReply), (char *)&rep);
17105b261ecSmrg    return(client->noClientException);
17205b261ecSmrg}
17305b261ecSmrg
17405b261ecSmrgstatic int
17505b261ecSmrgProcDamageCreate (ClientPtr client)
17605b261ecSmrg{
17705b261ecSmrg    DrawablePtr		pDrawable;
17805b261ecSmrg    DamageExtPtr	pDamageExt;
17905b261ecSmrg    DamageReportLevel	level;
18005b261ecSmrg    RegionPtr		pRegion;
18105b261ecSmrg    int			rc;
18205b261ecSmrg
18305b261ecSmrg    REQUEST(xDamageCreateReq);
18405b261ecSmrg
18505b261ecSmrg    REQUEST_SIZE_MATCH(xDamageCreateReq);
18605b261ecSmrg    LEGAL_NEW_RESOURCE(stuff->damage, client);
18705b261ecSmrg    rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0,
18805b261ecSmrg			   DixReadAccess);
18905b261ecSmrg    if (rc != Success)
19005b261ecSmrg	return rc;
19105b261ecSmrg
19205b261ecSmrg    switch (stuff->level) {
19305b261ecSmrg    case XDamageReportRawRectangles:
19405b261ecSmrg	level = DamageReportRawRegion;
19505b261ecSmrg	break;
19605b261ecSmrg    case XDamageReportDeltaRectangles:
19705b261ecSmrg	level = DamageReportDeltaRegion;
19805b261ecSmrg	break;
19905b261ecSmrg    case XDamageReportBoundingBox:
20005b261ecSmrg	level = DamageReportBoundingBox;
20105b261ecSmrg	break;
20205b261ecSmrg    case XDamageReportNonEmpty:
20305b261ecSmrg	level = DamageReportNonEmpty;
20405b261ecSmrg	break;
20505b261ecSmrg    default:
20605b261ecSmrg	client->errorValue = stuff->level;
20705b261ecSmrg	return BadValue;
20805b261ecSmrg    }
20905b261ecSmrg
21005b261ecSmrg    pDamageExt = xalloc (sizeof (DamageExtRec));
21105b261ecSmrg    if (!pDamageExt)
21205b261ecSmrg	return BadAlloc;
21305b261ecSmrg    pDamageExt->id = stuff->damage;
21405b261ecSmrg    pDamageExt->pDrawable = pDrawable;
21505b261ecSmrg    pDamageExt->level = level;
21605b261ecSmrg    pDamageExt->pClient = client;
21705b261ecSmrg    pDamageExt->pDamage = DamageCreate (DamageExtReport,
21805b261ecSmrg					DamageExtDestroy,
21905b261ecSmrg					level,
22005b261ecSmrg					FALSE,
22105b261ecSmrg					pDrawable->pScreen,
22205b261ecSmrg					pDamageExt);
22305b261ecSmrg    if (!pDamageExt->pDamage)
22405b261ecSmrg    {
22505b261ecSmrg	xfree (pDamageExt);
22605b261ecSmrg	return BadAlloc;
22705b261ecSmrg    }
22805b261ecSmrg    if (!AddResource (stuff->damage, DamageExtType, (pointer) pDamageExt))
22905b261ecSmrg	return BadAlloc;
23005b261ecSmrg
23105b261ecSmrg    DamageRegister (pDamageExt->pDrawable, pDamageExt->pDamage);
23205b261ecSmrg
23305b261ecSmrg    if (pDrawable->type == DRAWABLE_WINDOW)
23405b261ecSmrg    {
23505b261ecSmrg	pRegion = &((WindowPtr) pDrawable)->borderClip;
23605b261ecSmrg	DamageDamageRegion (pDrawable, pRegion);
23705b261ecSmrg    }
23805b261ecSmrg
23905b261ecSmrg    return (client->noClientException);
24005b261ecSmrg}
24105b261ecSmrg
24205b261ecSmrgstatic int
24305b261ecSmrgProcDamageDestroy (ClientPtr client)
24405b261ecSmrg{
24505b261ecSmrg    REQUEST(xDamageDestroyReq);
24605b261ecSmrg    DamageExtPtr    pDamageExt;
24705b261ecSmrg
24805b261ecSmrg    REQUEST_SIZE_MATCH(xDamageDestroyReq);
24905b261ecSmrg    VERIFY_DAMAGEEXT(pDamageExt, stuff->damage, client, DixWriteAccess);
25005b261ecSmrg    FreeResource (stuff->damage, RT_NONE);
25105b261ecSmrg    return (client->noClientException);
25205b261ecSmrg}
25305b261ecSmrg
25405b261ecSmrgstatic int
25505b261ecSmrgProcDamageSubtract (ClientPtr client)
25605b261ecSmrg{
25705b261ecSmrg    REQUEST(xDamageSubtractReq);
25805b261ecSmrg    DamageExtPtr    pDamageExt;
25905b261ecSmrg    RegionPtr	    pRepair;
26005b261ecSmrg    RegionPtr	    pParts;
26105b261ecSmrg
26205b261ecSmrg    REQUEST_SIZE_MATCH(xDamageSubtractReq);
26305b261ecSmrg    VERIFY_DAMAGEEXT(pDamageExt, stuff->damage, client, DixWriteAccess);
26405b261ecSmrg    VERIFY_REGION_OR_NONE(pRepair, stuff->repair, client, DixWriteAccess);
26505b261ecSmrg    VERIFY_REGION_OR_NONE(pParts, stuff->parts, client, DixWriteAccess);
26605b261ecSmrg
26705b261ecSmrg    if (pDamageExt->level != DamageReportRawRegion)
26805b261ecSmrg    {
26905b261ecSmrg	DamagePtr   pDamage = pDamageExt->pDamage;
27005b261ecSmrg	if (pRepair)
27105b261ecSmrg	{
27205b261ecSmrg	    if (pParts)
27305b261ecSmrg		REGION_INTERSECT (prScreen, pParts, DamageRegion (pDamage), pRepair);
27405b261ecSmrg	    if (DamageSubtract (pDamage, pRepair))
27505b261ecSmrg		DamageExtReport (pDamage, DamageRegion (pDamage), (void *) pDamageExt);
27605b261ecSmrg	}
27705b261ecSmrg	else
27805b261ecSmrg	{
27905b261ecSmrg	    if (pParts)
28005b261ecSmrg		REGION_COPY (prScreen, pParts, DamageRegion (pDamage));
28105b261ecSmrg	    DamageEmpty (pDamage);
28205b261ecSmrg	}
28305b261ecSmrg    }
28405b261ecSmrg    return (client->noClientException);
28505b261ecSmrg}
28605b261ecSmrg
28705b261ecSmrgstatic int
28805b261ecSmrgProcDamageAdd (ClientPtr client)
28905b261ecSmrg{
29005b261ecSmrg    REQUEST(xDamageAddReq);
29105b261ecSmrg    DrawablePtr	    pDrawable;
29205b261ecSmrg    RegionPtr	    pRegion;
29305b261ecSmrg    int		    rc;
29405b261ecSmrg
29505b261ecSmrg    REQUEST_SIZE_MATCH(xDamageAddReq);
29605b261ecSmrg    VERIFY_REGION(pRegion, stuff->region, client, DixWriteAccess);
29705b261ecSmrg    rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0,
29805b261ecSmrg			   DixReadAccess);
29905b261ecSmrg    if (rc != Success)
30005b261ecSmrg	return rc;
30105b261ecSmrg
30205b261ecSmrg    /* The region is relative to the drawable origin, so translate it out to
30305b261ecSmrg     * screen coordinates like damage expects.
30405b261ecSmrg     */
30505b261ecSmrg    REGION_TRANSLATE(pScreen, pRegion, pDrawable->x, pDrawable->y);
30605b261ecSmrg    DamageDamageRegion(pDrawable, pRegion);
30705b261ecSmrg    REGION_TRANSLATE(pScreen, pRegion, -pDrawable->x, -pDrawable->y);
30805b261ecSmrg
30905b261ecSmrg    return (client->noClientException);
31005b261ecSmrg}
31105b261ecSmrg
31205b261ecSmrg/* Major version controls available requests */
31305b261ecSmrgstatic const int version_requests[] = {
31405b261ecSmrg    X_DamageQueryVersion,	/* before client sends QueryVersion */
31505b261ecSmrg    X_DamageAdd,		/* Version 1 */
31605b261ecSmrg};
31705b261ecSmrg
31805b261ecSmrg#define NUM_VERSION_REQUESTS	(sizeof (version_requests) / sizeof (version_requests[0]))
31905b261ecSmrg
32005b261ecSmrgstatic int (*ProcDamageVector[XDamageNumberRequests])(ClientPtr) = {
32105b261ecSmrg/*************** Version 1 ******************/
32205b261ecSmrg    ProcDamageQueryVersion,
32305b261ecSmrg    ProcDamageCreate,
32405b261ecSmrg    ProcDamageDestroy,
32505b261ecSmrg    ProcDamageSubtract,
32605b261ecSmrg/*************** Version 1.1 ****************/
32705b261ecSmrg    ProcDamageAdd,
32805b261ecSmrg};
32905b261ecSmrg
33005b261ecSmrg
33105b261ecSmrgstatic int
33205b261ecSmrgProcDamageDispatch (ClientPtr client)
33305b261ecSmrg{
33405b261ecSmrg    REQUEST(xDamageReq);
33505b261ecSmrg    DamageClientPtr pDamageClient = GetDamageClient (client);
33605b261ecSmrg
33705b261ecSmrg    if (pDamageClient->major_version >= NUM_VERSION_REQUESTS)
33805b261ecSmrg	return BadRequest;
33905b261ecSmrg    if (stuff->damageReqType > version_requests[pDamageClient->major_version])
34005b261ecSmrg	return BadRequest;
34105b261ecSmrg    return (*ProcDamageVector[stuff->damageReqType]) (client);
34205b261ecSmrg}
34305b261ecSmrg
34405b261ecSmrgstatic int
34505b261ecSmrgSProcDamageQueryVersion(ClientPtr client)
34605b261ecSmrg{
34705b261ecSmrg    register int n;
34805b261ecSmrg    REQUEST(xDamageQueryVersionReq);
34905b261ecSmrg
35005b261ecSmrg    swaps(&stuff->length, n);
35105b261ecSmrg    REQUEST_SIZE_MATCH(xDamageQueryVersionReq);
35205b261ecSmrg    swapl(&stuff->majorVersion, n);
35305b261ecSmrg    swapl(&stuff->minorVersion, n);
35405b261ecSmrg    return (*ProcDamageVector[stuff->damageReqType]) (client);
35505b261ecSmrg}
35605b261ecSmrg
35705b261ecSmrgstatic int
35805b261ecSmrgSProcDamageCreate (ClientPtr client)
35905b261ecSmrg{
36005b261ecSmrg    register int n;
36105b261ecSmrg    REQUEST(xDamageCreateReq);
36205b261ecSmrg
36305b261ecSmrg    swaps (&stuff->length, n);
36405b261ecSmrg    REQUEST_SIZE_MATCH(xDamageCreateReq);
36505b261ecSmrg    swapl (&stuff->damage, n);
36605b261ecSmrg    swapl (&stuff->drawable, n);
36705b261ecSmrg    return (*ProcDamageVector[stuff->damageReqType]) (client);
36805b261ecSmrg}
36905b261ecSmrg
37005b261ecSmrgstatic int
37105b261ecSmrgSProcDamageDestroy (ClientPtr client)
37205b261ecSmrg{
37305b261ecSmrg    register int n;
37405b261ecSmrg    REQUEST(xDamageDestroyReq);
37505b261ecSmrg
37605b261ecSmrg    swaps (&stuff->length, n);
37705b261ecSmrg    REQUEST_SIZE_MATCH(xDamageDestroyReq);
37805b261ecSmrg    swapl (&stuff->damage, n);
37905b261ecSmrg    return (*ProcDamageVector[stuff->damageReqType]) (client);
38005b261ecSmrg}
38105b261ecSmrg
38205b261ecSmrgstatic int
38305b261ecSmrgSProcDamageSubtract (ClientPtr client)
38405b261ecSmrg{
38505b261ecSmrg    register int n;
38605b261ecSmrg    REQUEST(xDamageSubtractReq);
38705b261ecSmrg
38805b261ecSmrg    swaps (&stuff->length, n);
38905b261ecSmrg    REQUEST_SIZE_MATCH(xDamageSubtractReq);
39005b261ecSmrg    swapl (&stuff->damage, n);
39105b261ecSmrg    swapl (&stuff->repair, n);
39205b261ecSmrg    swapl (&stuff->parts, n);
39305b261ecSmrg    return (*ProcDamageVector[stuff->damageReqType]) (client);
39405b261ecSmrg}
39505b261ecSmrg
39605b261ecSmrgstatic int
39705b261ecSmrgSProcDamageAdd (ClientPtr client)
39805b261ecSmrg{
39905b261ecSmrg    register int n;
40005b261ecSmrg    REQUEST(xDamageAddReq);
40105b261ecSmrg
40205b261ecSmrg    swaps (&stuff->length, n);
40305b261ecSmrg    REQUEST_SIZE_MATCH(xDamageSubtractReq);
40405b261ecSmrg    swapl (&stuff->drawable, n);
40505b261ecSmrg    swapl (&stuff->region, n);
40605b261ecSmrg    return (*ProcDamageVector[stuff->damageReqType]) (client);
40705b261ecSmrg}
40805b261ecSmrg
40905b261ecSmrgstatic int (*SProcDamageVector[XDamageNumberRequests])(ClientPtr) = {
41005b261ecSmrg/*************** Version 1 ******************/
41105b261ecSmrg    SProcDamageQueryVersion,
41205b261ecSmrg    SProcDamageCreate,
41305b261ecSmrg    SProcDamageDestroy,
41405b261ecSmrg    SProcDamageSubtract,
41505b261ecSmrg/*************** Version 1.1 ****************/
41605b261ecSmrg    SProcDamageAdd,
41705b261ecSmrg};
41805b261ecSmrg
41905b261ecSmrgstatic int
42005b261ecSmrgSProcDamageDispatch (ClientPtr client)
42105b261ecSmrg{
42205b261ecSmrg    REQUEST(xDamageReq);
42305b261ecSmrg    if (stuff->damageReqType >= XDamageNumberRequests)
42405b261ecSmrg	return BadRequest;
42505b261ecSmrg    return (*SProcDamageVector[stuff->damageReqType]) (client);
42605b261ecSmrg}
42705b261ecSmrg
42805b261ecSmrgstatic void
42905b261ecSmrgDamageClientCallback (CallbackListPtr	*list,
43005b261ecSmrg		      pointer		closure,
43105b261ecSmrg		      pointer		data)
43205b261ecSmrg{
43305b261ecSmrg    NewClientInfoRec	*clientinfo = (NewClientInfoRec *) data;
43405b261ecSmrg    ClientPtr		pClient = clientinfo->client;
43505b261ecSmrg    DamageClientPtr	pDamageClient = GetDamageClient (pClient);
43605b261ecSmrg
43705b261ecSmrg    pDamageClient->critical = 0;
43805b261ecSmrg    pDamageClient->major_version = 0;
43905b261ecSmrg    pDamageClient->minor_version = 0;
44005b261ecSmrg}
44105b261ecSmrg
44205b261ecSmrg/*ARGSUSED*/
44305b261ecSmrgstatic void
44405b261ecSmrgDamageResetProc (ExtensionEntry *extEntry)
44505b261ecSmrg{
44605b261ecSmrg    DeleteCallback (&ClientStateCallback, DamageClientCallback, 0);
44705b261ecSmrg}
44805b261ecSmrg
44905b261ecSmrgstatic int
45005b261ecSmrgFreeDamageExt (pointer value, XID did)
45105b261ecSmrg{
45205b261ecSmrg    DamageExtPtr    pDamageExt = (DamageExtPtr) value;
45305b261ecSmrg
45405b261ecSmrg    /*
45505b261ecSmrg     * Get rid of the resource table entry hanging from the window id
45605b261ecSmrg     */
45705b261ecSmrg    pDamageExt->id = 0;
45805b261ecSmrg    if (WindowDrawable(pDamageExt->pDrawable->type))
45905b261ecSmrg	FreeResourceByType (pDamageExt->pDrawable->id, DamageExtWinType, TRUE);
46005b261ecSmrg    if (pDamageExt->pDamage)
46105b261ecSmrg    {
46205b261ecSmrg	DamageUnregister (pDamageExt->pDrawable, pDamageExt->pDamage);
46305b261ecSmrg	DamageDestroy (pDamageExt->pDamage);
46405b261ecSmrg    }
46505b261ecSmrg    xfree (pDamageExt);
46605b261ecSmrg    return Success;
46705b261ecSmrg}
46805b261ecSmrg
46905b261ecSmrgstatic int
47005b261ecSmrgFreeDamageExtWin (pointer value, XID wid)
47105b261ecSmrg{
47205b261ecSmrg    DamageExtPtr    pDamageExt = (DamageExtPtr) value;
47305b261ecSmrg
47405b261ecSmrg    if (pDamageExt->id)
47505b261ecSmrg	FreeResource (pDamageExt->id, RT_NONE);
47605b261ecSmrg    return Success;
47705b261ecSmrg}
47805b261ecSmrg
47905b261ecSmrgstatic void
48005b261ecSmrgSDamageNotifyEvent (xDamageNotifyEvent *from,
48105b261ecSmrg		    xDamageNotifyEvent *to)
48205b261ecSmrg{
48305b261ecSmrg    to->type = from->type;
48405b261ecSmrg    cpswaps (from->sequenceNumber, to->sequenceNumber);
48505b261ecSmrg    cpswapl (from->drawable, to->drawable);
48605b261ecSmrg    cpswapl (from->damage, to->damage);
48705b261ecSmrg    cpswaps (from->area.x, to->area.x);
48805b261ecSmrg    cpswaps (from->area.y, to->area.y);
48905b261ecSmrg    cpswaps (from->area.width, to->area.width);
49005b261ecSmrg    cpswaps (from->area.height, to->area.height);
49105b261ecSmrg    cpswaps (from->geometry.x, to->geometry.x);
49205b261ecSmrg    cpswaps (from->geometry.y, to->geometry.y);
49305b261ecSmrg    cpswaps (from->geometry.width, to->geometry.width);
49405b261ecSmrg    cpswaps (from->geometry.height, to->geometry.height);
49505b261ecSmrg}
49605b261ecSmrg
49705b261ecSmrgvoid
49805b261ecSmrgDamageExtensionInit(void)
49905b261ecSmrg{
50005b261ecSmrg    ExtensionEntry *extEntry;
50105b261ecSmrg    int		    s;
50205b261ecSmrg
50305b261ecSmrg    for (s = 0; s < screenInfo.numScreens; s++)
50405b261ecSmrg	DamageSetup (screenInfo.screens[s]);
50505b261ecSmrg
50605b261ecSmrg    DamageExtType = CreateNewResourceType (FreeDamageExt);
50705b261ecSmrg    if (!DamageExtType)
50805b261ecSmrg	return;
50905b261ecSmrg
51005b261ecSmrg    DamageExtWinType = CreateNewResourceType (FreeDamageExtWin);
51105b261ecSmrg    if (!DamageExtWinType)
51205b261ecSmrg	return;
51305b261ecSmrg
51405b261ecSmrg    DamageClientPrivateIndex = AllocateClientPrivateIndex ();
51505b261ecSmrg    if (!AllocateClientPrivate (DamageClientPrivateIndex,
51605b261ecSmrg				sizeof (DamageClientRec)))
51705b261ecSmrg	return;
51805b261ecSmrg    if (!AddCallback (&ClientStateCallback, DamageClientCallback, 0))
51905b261ecSmrg	return;
52005b261ecSmrg
52105b261ecSmrg    if ((extEntry = AddExtension(DAMAGE_NAME, XDamageNumberEvents,
52205b261ecSmrg				 XDamageNumberErrors,
52305b261ecSmrg				 ProcDamageDispatch, SProcDamageDispatch,
52405b261ecSmrg				 DamageResetProc, StandardMinorOpcode)) != 0)
52505b261ecSmrg    {
52605b261ecSmrg	DamageReqCode = (unsigned char)extEntry->base;
52705b261ecSmrg	DamageEventBase = extEntry->eventBase;
52805b261ecSmrg	DamageErrorBase = extEntry->errorBase;
52905b261ecSmrg	EventSwapVector[DamageEventBase + XDamageNotify] =
53005b261ecSmrg			(EventSwapPtr) SDamageNotifyEvent;
53105b261ecSmrg    }
53205b261ecSmrg}
533