xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

damageext.c (21376B)


      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
     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
     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
     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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    561 SProcDamageDispatch(ClientPtr client)
    562 {
    563     REQUEST(xDamageReq);
    564     DamageClientPtr pDamageClient = GetDamageClient(client);
    565 
    566     if (pDamageClient->major_version >= ARRAY_SIZE(version_requests))
    567         return BadRequest;
    568     if (stuff->damageReqType > version_requests[pDamageClient->major_version])
    569         return BadRequest;
    570     return (*SProcDamageVector[stuff->damageReqType]) (client);
    571 }
    572 
    573 static int
    574 FreeDamageExt(void *value, XID did)
    575 {
    576     DamageExtPtr pDamageExt = (DamageExtPtr) value;
    577 
    578     /*
    579      * Get rid of the resource table entry hanging from the window id
    580      */
    581     pDamageExt->id = 0;
    582     if (pDamageExt->pDamage) {
    583         DamageDestroy(pDamageExt->pDamage);
    584     }
    585     free(pDamageExt);
    586     return Success;
    587 }
    588 
    589 static void _X_COLD
    590 SDamageNotifyEvent(xDamageNotifyEvent * from, xDamageNotifyEvent * to)
    591 {
    592     to->type = from->type;
    593     cpswaps(from->sequenceNumber, to->sequenceNumber);
    594     cpswapl(from->drawable, to->drawable);
    595     cpswapl(from->damage, to->damage);
    596     cpswaps(from->area.x, to->area.x);
    597     cpswaps(from->area.y, to->area.y);
    598     cpswaps(from->area.width, to->area.width);
    599     cpswaps(from->area.height, to->area.height);
    600     cpswaps(from->geometry.x, to->geometry.x);
    601     cpswaps(from->geometry.y, to->geometry.y);
    602     cpswaps(from->geometry.width, to->geometry.width);
    603     cpswaps(from->geometry.height, to->geometry.height);
    604 }
    605 
    606 #ifdef PANORAMIX
    607 
    608 static void
    609 PanoramiXDamageReport(DamagePtr pDamage, RegionPtr pRegion, void *closure)
    610 {
    611     PanoramiXDamageRes *res = closure;
    612     DamageExtPtr pDamageExt = res->ext;
    613     WindowPtr pWin = (WindowPtr)pDamage->pDrawable;
    614     ScreenPtr pScreen = pDamage->pScreen;
    615 
    616     /* happens on unmap? sigh xinerama */
    617     if (RegionNil(pRegion))
    618         return;
    619 
    620     /* translate root windows if necessary */
    621     if (!pWin->parent)
    622         RegionTranslate(pRegion, pScreen->x, pScreen->y);
    623 
    624     /* add our damage to the protocol view */
    625     DamageReportDamage(pDamageExt->pDamage, pRegion);
    626 
    627     /* empty our view */
    628     DamageEmpty(pDamage);
    629 }
    630 
    631 static void
    632 PanoramiXDamageExtDestroy(DamagePtr pDamage, void *closure)
    633 {
    634     PanoramiXDamageRes *damage = closure;
    635     damage->damage[pDamage->pScreen->myNum] = NULL;
    636 }
    637 
    638 static int
    639 PanoramiXDamageCreate(ClientPtr client)
    640 {
    641     PanoramiXDamageRes *damage;
    642     PanoramiXRes *draw;
    643     int i, rc;
    644 
    645     REQUEST(xDamageCreateReq);
    646 
    647     REQUEST_SIZE_MATCH(xDamageCreateReq);
    648     LEGAL_NEW_RESOURCE(stuff->damage, client);
    649     rc = dixLookupResourceByClass((void **)&draw, stuff->drawable, XRC_DRAWABLE,
    650                                   client, DixGetAttrAccess | DixReadAccess);
    651     if (rc != Success)
    652         return rc;
    653 
    654     if (!(damage = calloc(1, sizeof(PanoramiXDamageRes))))
    655         return BadAlloc;
    656 
    657     if (!AddResource(stuff->damage, XRT_DAMAGE, damage))
    658         return BadAlloc;
    659 
    660     damage->ext = doDamageCreate(client, &rc);
    661     if (rc == Success && draw->type == XRT_WINDOW) {
    662         FOR_NSCREENS_FORWARD(i) {
    663             DrawablePtr pDrawable;
    664             DamagePtr pDamage = DamageCreate(PanoramiXDamageReport,
    665                                              PanoramiXDamageExtDestroy,
    666                                              DamageReportRawRegion,
    667                                              FALSE,
    668                                              screenInfo.screens[i],
    669                                              damage);
    670             if (!pDamage) {
    671                 rc = BadAlloc;
    672             } else {
    673                 damage->damage[i] = pDamage;
    674                 rc = dixLookupDrawable(&pDrawable, draw->info[i].id, client,
    675                                        M_WINDOW,
    676                                        DixGetAttrAccess | DixReadAccess);
    677             }
    678             if (rc != Success)
    679                 break;
    680 
    681             DamageExtRegister(pDrawable, pDamage, i != 0);
    682         }
    683     }
    684 
    685     if (rc != Success)
    686         FreeResource(stuff->damage, RT_NONE);
    687 
    688     return rc;
    689 }
    690 
    691 static int
    692 PanoramiXDamageDelete(void *res, XID id)
    693 {
    694     int i;
    695     PanoramiXDamageRes *damage = res;
    696 
    697     FOR_NSCREENS_BACKWARD(i) {
    698         if (damage->damage[i]) {
    699             DamageDestroy(damage->damage[i]);
    700             damage->damage[i] = NULL;
    701         }
    702     }
    703 
    704     free(damage);
    705     return 1;
    706 }
    707 
    708 void
    709 PanoramiXDamageInit(void)
    710 {
    711     XRT_DAMAGE = CreateNewResourceType(PanoramiXDamageDelete, "XineramaDamage");
    712     if (!XRT_DAMAGE)
    713         FatalError("Couldn't Xineramify Damage extension\n");
    714 
    715     PanoramiXSaveDamageCreate = ProcDamageVector[X_DamageCreate];
    716     ProcDamageVector[X_DamageCreate] = PanoramiXDamageCreate;
    717 }
    718 
    719 void
    720 PanoramiXDamageReset(void)
    721 {
    722     ProcDamageVector[X_DamageCreate] = PanoramiXSaveDamageCreate;
    723 }
    724 
    725 #endif /* PANORAMIX */
    726 
    727 void
    728 DamageExtensionInit(void)
    729 {
    730     ExtensionEntry *extEntry;
    731     int s;
    732 
    733     for (s = 0; s < screenInfo.numScreens; s++)
    734         DamageSetup(screenInfo.screens[s]);
    735 
    736     DamageExtType = CreateNewResourceType(FreeDamageExt, "DamageExt");
    737     if (!DamageExtType)
    738         return;
    739 
    740     if (!dixRegisterPrivateKey
    741         (&DamageClientPrivateKeyRec, PRIVATE_CLIENT, sizeof(DamageClientRec)))
    742         return;
    743 
    744     if ((extEntry = AddExtension(DAMAGE_NAME, XDamageNumberEvents,
    745                                  XDamageNumberErrors,
    746                                  ProcDamageDispatch, SProcDamageDispatch,
    747                                  NULL, StandardMinorOpcode)) != 0) {
    748         DamageReqCode = (unsigned char) extEntry->base;
    749         DamageEventBase = extEntry->eventBase;
    750         EventSwapVector[DamageEventBase + XDamageNotify] =
    751             (EventSwapPtr) SDamageNotifyEvent;
    752         SetResourceTypeErrorValue(DamageExtType,
    753                                   extEntry->errorBase + BadDamage);
    754 #ifdef PANORAMIX
    755         if (XRT_DAMAGE)
    756             SetResourceTypeErrorValue(XRT_DAMAGE,
    757                                       extEntry->errorBase + BadDamage);
    758 #endif
    759     }
    760 }