Edit

IABSD.fr/xenocara/xserver/damageext/damageext.c

Branch :

  • Show log

    Commit

  • Author : matthieu
    Date : 2021-11-11 09:03:02
    Hash : e086cf5a
    Message : Update to xserver 21.1.0

  • xserver/damageext/damageext.c
  • /*
     * Copyright © 2002 Keith Packard
     * Copyright 2013 Red Hat, Inc.
     *
     * Permission to use, copy, modify, distribute, and sell this software and its
     * documentation for any purpose is hereby granted without fee, provided that
     * the above copyright notice appear in all copies and that both that
     * copyright notice and this permission notice appear in supporting
     * documentation, and that the name of Keith Packard not be used in
     * advertising or publicity pertaining to distribution of the software without
     * specific, written prior permission.  Keith Packard makes no
     * representations about the suitability of this software for any purpose.  It
     * is provided "as is" without express or implied warranty.
     *
     * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
     * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
     * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
     * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
     * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
     * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
     * PERFORMANCE OF THIS SOFTWARE.
     */
    
    #ifdef HAVE_DIX_CONFIG_H
    #include <dix-config.h>
    #endif
    
    #include "damageextint.h"
    #include "damagestr.h"
    #include "protocol-versions.h"
    #include "extinit.h"
    
    #ifdef PANORAMIX
    #include "panoramiX.h"
    #include "panoramiXsrv.h"
    
    typedef struct {
        DamageExtPtr ext;
        DamagePtr damage[MAXSCREENS];
    } PanoramiXDamageRes;
    
    static RESTYPE XRT_DAMAGE;
    static int (*PanoramiXSaveDamageCreate) (ClientPtr);
    
    #endif
    
    static unsigned char DamageReqCode;
    static int DamageEventBase;
    static RESTYPE DamageExtType;
    
    static DevPrivateKeyRec DamageClientPrivateKeyRec;
    
    #define DamageClientPrivateKey (&DamageClientPrivateKeyRec)
    
    static void
    DamageNoteCritical(ClientPtr pClient)
    {
        DamageClientPtr pDamageClient = GetDamageClient(pClient);
    
        /* Composite extension marks clients with manual Subwindows as critical */
        if (pDamageClient->critical > 0) {
            SetCriticalOutputPending();
            pClient->smart_priority = SMART_MAX_PRIORITY;
        }
    }
    
    static void
    damageGetGeometry(DrawablePtr draw, int *x, int *y, int *w, int *h)
    {
    #ifdef PANORAMIX
        if (!noPanoramiXExtension && draw->type == DRAWABLE_WINDOW) {
            WindowPtr win = (WindowPtr)draw;
    
            if (!win->parent) {
                *x = screenInfo.x;
                *y = screenInfo.y;
                *w = screenInfo.width;
                *h = screenInfo.height;
                return;
            }
        }
    #endif
    
        *x = draw->x;
        *y = draw->y;
        *w = draw->width;
        *h = draw->height;
    }
    
    static void
    DamageExtNotify(DamageExtPtr pDamageExt, BoxPtr pBoxes, int nBoxes)
    {
        ClientPtr pClient = pDamageExt->pClient;
        DrawablePtr pDrawable = pDamageExt->pDrawable;
        xDamageNotifyEvent ev;
        int i, x, y, w, h;
    
        damageGetGeometry(pDrawable, &x, &y, &w, &h);
    
        UpdateCurrentTimeIf();
        ev = (xDamageNotifyEvent) {
            .type = DamageEventBase + XDamageNotify,
            .level = pDamageExt->level,
            .drawable = pDamageExt->drawable,
            .damage = pDamageExt->id,
            .timestamp = currentTime.milliseconds,
            .geometry.x = x,
            .geometry.y = y,
            .geometry.width = w,
            .geometry.height = h
        };
        if (pBoxes) {
            for (i = 0; i < nBoxes; i++) {
                ev.level = pDamageExt->level;
                if (i < nBoxes - 1)
                    ev.level |= DamageNotifyMore;
                ev.area.x = pBoxes[i].x1;
                ev.area.y = pBoxes[i].y1;
                ev.area.width = pBoxes[i].x2 - pBoxes[i].x1;
                ev.area.height = pBoxes[i].y2 - pBoxes[i].y1;
                WriteEventsToClient(pClient, 1, (xEvent *) &ev);
            }
        }
        else {
            ev.area.x = 0;
            ev.area.y = 0;
            ev.area.width = w;
            ev.area.height = h;
            WriteEventsToClient(pClient, 1, (xEvent *) &ev);
        }
    
        DamageNoteCritical(pClient);
    }
    
    static void
    DamageExtReport(DamagePtr pDamage, RegionPtr pRegion, void *closure)
    {
        DamageExtPtr pDamageExt = closure;
    
        switch (pDamageExt->level) {
        case DamageReportRawRegion:
        case DamageReportDeltaRegion:
            DamageExtNotify(pDamageExt, RegionRects(pRegion),
                            RegionNumRects(pRegion));
            break;
        case DamageReportBoundingBox:
            DamageExtNotify(pDamageExt, RegionExtents(pRegion), 1);
            break;
        case DamageReportNonEmpty:
            DamageExtNotify(pDamageExt, NullBox, 0);
            break;
        case DamageReportNone:
            break;
        }
    }
    
    static void
    DamageExtDestroy(DamagePtr pDamage, void *closure)
    {
        DamageExtPtr pDamageExt = closure;
    
        pDamageExt->pDamage = 0;
        if (pDamageExt->id)
            FreeResource(pDamageExt->id, RT_NONE);
    }
    
    void
    DamageExtSetCritical(ClientPtr pClient, Bool critical)
    {
        DamageClientPtr pDamageClient = GetDamageClient(pClient);
    
        if (pDamageClient)
            pDamageClient->critical += critical ? 1 : -1;
    }
    
    static int
    ProcDamageQueryVersion(ClientPtr client)
    {
        DamageClientPtr pDamageClient = GetDamageClient(client);
        xDamageQueryVersionReply rep = {
            .type = X_Reply,
            .sequenceNumber = client->sequence,
            .length = 0
        };
    
        REQUEST(xDamageQueryVersionReq);
    
        REQUEST_SIZE_MATCH(xDamageQueryVersionReq);
    
        if (stuff->majorVersion < SERVER_DAMAGE_MAJOR_VERSION) {
            rep.majorVersion = stuff->majorVersion;
            rep.minorVersion = stuff->minorVersion;
        }
        else {
            rep.majorVersion = SERVER_DAMAGE_MAJOR_VERSION;
            if (stuff->majorVersion == SERVER_DAMAGE_MAJOR_VERSION &&
                stuff->minorVersion < SERVER_DAMAGE_MINOR_VERSION)
                rep.minorVersion = stuff->minorVersion;
            else
                rep.minorVersion = SERVER_DAMAGE_MINOR_VERSION;
        }
        pDamageClient->major_version = rep.majorVersion;
        pDamageClient->minor_version = rep.minorVersion;
        if (client->swapped) {
            swaps(&rep.sequenceNumber);
            swapl(&rep.length);
            swapl(&rep.majorVersion);
            swapl(&rep.minorVersion);
        }
        WriteToClient(client, sizeof(xDamageQueryVersionReply), &rep);
        return Success;
    }
    
    static void
    DamageExtRegister(DrawablePtr pDrawable, DamagePtr pDamage, Bool report)
    {
        DamageSetReportAfterOp(pDamage, TRUE);
        DamageRegister(pDrawable, pDamage);
    
        if (report) {
            RegionPtr pRegion = &((WindowPtr) pDrawable)->borderClip;
            RegionTranslate(pRegion, -pDrawable->x, -pDrawable->y);
            DamageReportDamage(pDamage, pRegion);
            RegionTranslate(pRegion, pDrawable->x, pDrawable->y);
        }
    }
    
    static DamageExtPtr
    DamageExtCreate(DrawablePtr pDrawable, DamageReportLevel level,
                    ClientPtr client, XID id, XID drawable)
    {
        DamageExtPtr pDamageExt = malloc(sizeof(DamageExtRec));
        if (!pDamageExt)
            return NULL;
    
        pDamageExt->id = id;
        pDamageExt->drawable = drawable;
        pDamageExt->pDrawable = pDrawable;
        pDamageExt->level = level;
        pDamageExt->pClient = client;
        pDamageExt->pDamage = DamageCreate(DamageExtReport, DamageExtDestroy, level,
                                           FALSE, pDrawable->pScreen, pDamageExt);
        if (!pDamageExt->pDamage) {
            free(pDamageExt);
            return NULL;
        }
    
        if (!AddResource(id, DamageExtType, (void *) pDamageExt))
            return NULL;
    
        DamageExtRegister(pDrawable, pDamageExt->pDamage,
                          pDrawable->type == DRAWABLE_WINDOW);
    
        return pDamageExt;
    }
    
    static DamageExtPtr
    doDamageCreate(ClientPtr client, int *rc)
    {
        DrawablePtr pDrawable;
        DamageExtPtr pDamageExt;
        DamageReportLevel level;
    
        REQUEST(xDamageCreateReq);
    
        *rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0,
                                DixGetAttrAccess | DixReadAccess);
        if (*rc != Success)
            return NULL;
    
        switch (stuff->level) {
        case XDamageReportRawRectangles:
            level = DamageReportRawRegion;
            break;
        case XDamageReportDeltaRectangles:
            level = DamageReportDeltaRegion;
            break;
        case XDamageReportBoundingBox:
            level = DamageReportBoundingBox;
            break;
        case XDamageReportNonEmpty:
            level = DamageReportNonEmpty;
            break;
        default:
            client->errorValue = stuff->level;
            *rc = BadValue;
            return NULL;
        }
    
        pDamageExt = DamageExtCreate(pDrawable, level, client, stuff->damage,
                                     stuff->drawable);
        if (!pDamageExt)
            *rc = BadAlloc;
    
        return pDamageExt;
    }
    
    static int
    ProcDamageCreate(ClientPtr client)
    {
        int rc;
        REQUEST(xDamageCreateReq);
        REQUEST_SIZE_MATCH(xDamageCreateReq);
        LEGAL_NEW_RESOURCE(stuff->damage, client);
        doDamageCreate(client, &rc);
        return rc;
    }
    
    static int
    ProcDamageDestroy(ClientPtr client)
    {
        REQUEST(xDamageDestroyReq);
        DamageExtPtr pDamageExt;
    
        REQUEST_SIZE_MATCH(xDamageDestroyReq);
        VERIFY_DAMAGEEXT(pDamageExt, stuff->damage, client, DixWriteAccess);
        FreeResource(stuff->damage, RT_NONE);
        return Success;
    }
    
    #ifdef PANORAMIX
    static RegionPtr
    DamageExtSubtractWindowClip(DamageExtPtr pDamageExt)
    {
        WindowPtr win = (WindowPtr)pDamageExt->pDrawable;
        PanoramiXRes *res = NULL;
        RegionPtr ret;
        int i;
    
        if (!win->parent)
            return &PanoramiXScreenRegion;
    
        dixLookupResourceByType((void **)&res, win->drawable.id, XRT_WINDOW,
                                serverClient, DixReadAccess);
        if (!res)
            return NULL;
    
        ret = RegionCreate(NULL, 0);
        if (!ret)
            return NULL;
    
        FOR_NSCREENS_FORWARD(i) {
            ScreenPtr screen;
            if (Success != dixLookupWindow(&win, res->info[i].id, serverClient,
                                           DixReadAccess))
                goto out;
    
            screen = win->drawable.pScreen;
    
            RegionTranslate(ret, -screen->x, -screen->y);
            if (!RegionUnion(ret, ret, &win->borderClip))
                goto out;
            RegionTranslate(ret, screen->x, screen->y);
        }
    
        return ret;
    
    out:
        RegionDestroy(ret);
        return NULL;
    }
    
    static void
    DamageExtFreeWindowClip(RegionPtr reg)
    {
        if (reg != &PanoramiXScreenRegion)
            RegionDestroy(reg);
    }
    #endif
    
    /*
     * DamageSubtract intersects with borderClip, so we must reconstruct the
     * protocol's perspective of same...
     */
    static Bool
    DamageExtSubtract(DamageExtPtr pDamageExt, const RegionPtr pRegion)
    {
        DamagePtr pDamage = pDamageExt->pDamage;
    
    #ifdef PANORAMIX
        if (!noPanoramiXExtension) {
            RegionPtr damage = DamageRegion(pDamage);
            RegionSubtract(damage, damage, pRegion);
    
            if (pDamageExt->pDrawable->type == DRAWABLE_WINDOW) {
                DrawablePtr pDraw = pDamageExt->pDrawable;
                RegionPtr clip = DamageExtSubtractWindowClip(pDamageExt);
                if (clip) {
                    RegionTranslate(clip, -pDraw->x, -pDraw->y);
                    RegionIntersect(damage, damage, clip);
                    RegionTranslate(clip, pDraw->x, pDraw->y);
                    DamageExtFreeWindowClip(clip);
                }
            }
    
            return RegionNotEmpty(damage);
        }
    #endif
    
        return DamageSubtract(pDamage, pRegion);
    }
    
    static int
    ProcDamageSubtract(ClientPtr client)
    {
        REQUEST(xDamageSubtractReq);
        DamageExtPtr pDamageExt;
        RegionPtr pRepair;
        RegionPtr pParts;
    
        REQUEST_SIZE_MATCH(xDamageSubtractReq);
        VERIFY_DAMAGEEXT(pDamageExt, stuff->damage, client, DixWriteAccess);
        VERIFY_REGION_OR_NONE(pRepair, stuff->repair, client, DixWriteAccess);
        VERIFY_REGION_OR_NONE(pParts, stuff->parts, client, DixWriteAccess);
    
        if (pDamageExt->level != DamageReportRawRegion) {
            DamagePtr pDamage = pDamageExt->pDamage;
    
            if (pRepair) {
                if (pParts)
                    RegionIntersect(pParts, DamageRegion(pDamage), pRepair);
                if (DamageExtSubtract(pDamageExt, pRepair))
                    DamageExtReport(pDamage, DamageRegion(pDamage),
                                    (void *) pDamageExt);
            }
            else {
                if (pParts)
                    RegionCopy(pParts, DamageRegion(pDamage));
                DamageEmpty(pDamage);
            }
        }
    
        return Success;
    }
    
    static int
    ProcDamageAdd(ClientPtr client)
    {
        REQUEST(xDamageAddReq);
        DrawablePtr pDrawable;
        RegionPtr pRegion;
        int rc;
    
        REQUEST_SIZE_MATCH(xDamageAddReq);
        VERIFY_REGION(pRegion, stuff->region, client, DixWriteAccess);
        rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0,
                               DixWriteAccess);
        if (rc != Success)
            return rc;
    
        /* The region is relative to the drawable origin, so translate it out to
         * screen coordinates like damage expects.
         */
        RegionTranslate(pRegion, pDrawable->x, pDrawable->y);
        DamageDamageRegion(pDrawable, pRegion);
        RegionTranslate(pRegion, -pDrawable->x, -pDrawable->y);
    
        return Success;
    }
    
    /* Major version controls available requests */
    static const int version_requests[] = {
        X_DamageQueryVersion,       /* before client sends QueryVersion */
        X_DamageAdd,                /* Version 1 */
    };
    
    static int (*ProcDamageVector[XDamageNumberRequests]) (ClientPtr) = {
        /*************** Version 1 ******************/
        ProcDamageQueryVersion,
        ProcDamageCreate,
        ProcDamageDestroy,
        ProcDamageSubtract,
        /*************** Version 1.1 ****************/
        ProcDamageAdd,
    };
    
    static int
    ProcDamageDispatch(ClientPtr client)
    {
        REQUEST(xDamageReq);
        DamageClientPtr pDamageClient = GetDamageClient(client);
    
        if (pDamageClient->major_version >= ARRAY_SIZE(version_requests))
            return BadRequest;
        if (stuff->damageReqType > version_requests[pDamageClient->major_version])
            return BadRequest;
        return (*ProcDamageVector[stuff->damageReqType]) (client);
    }
    
    static int _X_COLD
    SProcDamageQueryVersion(ClientPtr client)
    {
        REQUEST(xDamageQueryVersionReq);
    
        swaps(&stuff->length);
        REQUEST_SIZE_MATCH(xDamageQueryVersionReq);
        swapl(&stuff->majorVersion);
        swapl(&stuff->minorVersion);
        return (*ProcDamageVector[stuff->damageReqType]) (client);
    }
    
    static int _X_COLD
    SProcDamageCreate(ClientPtr client)
    {
        REQUEST(xDamageCreateReq);
    
        swaps(&stuff->length);
        REQUEST_SIZE_MATCH(xDamageCreateReq);
        swapl(&stuff->damage);
        swapl(&stuff->drawable);
        return (*ProcDamageVector[stuff->damageReqType]) (client);
    }
    
    static int _X_COLD
    SProcDamageDestroy(ClientPtr client)
    {
        REQUEST(xDamageDestroyReq);
    
        swaps(&stuff->length);
        REQUEST_SIZE_MATCH(xDamageDestroyReq);
        swapl(&stuff->damage);
        return (*ProcDamageVector[stuff->damageReqType]) (client);
    }
    
    static int _X_COLD
    SProcDamageSubtract(ClientPtr client)
    {
        REQUEST(xDamageSubtractReq);
    
        swaps(&stuff->length);
        REQUEST_SIZE_MATCH(xDamageSubtractReq);
        swapl(&stuff->damage);
        swapl(&stuff->repair);
        swapl(&stuff->parts);
        return (*ProcDamageVector[stuff->damageReqType]) (client);
    }
    
    static int _X_COLD
    SProcDamageAdd(ClientPtr client)
    {
        REQUEST(xDamageAddReq);
    
        swaps(&stuff->length);
        REQUEST_SIZE_MATCH(xDamageSubtractReq);
        swapl(&stuff->drawable);
        swapl(&stuff->region);
        return (*ProcDamageVector[stuff->damageReqType]) (client);
    }
    
    static int (*SProcDamageVector[XDamageNumberRequests]) (ClientPtr) = {
        /*************** Version 1 ******************/
        SProcDamageQueryVersion,
        SProcDamageCreate,
        SProcDamageDestroy,
        SProcDamageSubtract,
        /*************** Version 1.1 ****************/
        SProcDamageAdd,
    };
    
    static int _X_COLD
    SProcDamageDispatch(ClientPtr client)
    {
        REQUEST(xDamageReq);
        DamageClientPtr pDamageClient = GetDamageClient(client);
    
        if (pDamageClient->major_version >= ARRAY_SIZE(version_requests))
            return BadRequest;
        if (stuff->damageReqType > version_requests[pDamageClient->major_version])
            return BadRequest;
        return (*SProcDamageVector[stuff->damageReqType]) (client);
    }
    
    static int
    FreeDamageExt(void *value, XID did)
    {
        DamageExtPtr pDamageExt = (DamageExtPtr) value;
    
        /*
         * Get rid of the resource table entry hanging from the window id
         */
        pDamageExt->id = 0;
        if (pDamageExt->pDamage) {
            DamageDestroy(pDamageExt->pDamage);
        }
        free(pDamageExt);
        return Success;
    }
    
    static void _X_COLD
    SDamageNotifyEvent(xDamageNotifyEvent * from, xDamageNotifyEvent * to)
    {
        to->type = from->type;
        cpswaps(from->sequenceNumber, to->sequenceNumber);
        cpswapl(from->drawable, to->drawable);
        cpswapl(from->damage, to->damage);
        cpswaps(from->area.x, to->area.x);
        cpswaps(from->area.y, to->area.y);
        cpswaps(from->area.width, to->area.width);
        cpswaps(from->area.height, to->area.height);
        cpswaps(from->geometry.x, to->geometry.x);
        cpswaps(from->geometry.y, to->geometry.y);
        cpswaps(from->geometry.width, to->geometry.width);
        cpswaps(from->geometry.height, to->geometry.height);
    }
    
    #ifdef PANORAMIX
    
    static void
    PanoramiXDamageReport(DamagePtr pDamage, RegionPtr pRegion, void *closure)
    {
        PanoramiXDamageRes *res = closure;
        DamageExtPtr pDamageExt = res->ext;
        WindowPtr pWin = (WindowPtr)pDamage->pDrawable;
        ScreenPtr pScreen = pDamage->pScreen;
    
        /* happens on unmap? sigh xinerama */
        if (RegionNil(pRegion))
            return;
    
        /* translate root windows if necessary */
        if (!pWin->parent)
            RegionTranslate(pRegion, pScreen->x, pScreen->y);
    
        /* add our damage to the protocol view */
        DamageReportDamage(pDamageExt->pDamage, pRegion);
    
        /* empty our view */
        DamageEmpty(pDamage);
    }
    
    static void
    PanoramiXDamageExtDestroy(DamagePtr pDamage, void *closure)
    {
        PanoramiXDamageRes *damage = closure;
        damage->damage[pDamage->pScreen->myNum] = NULL;
    }
    
    static int
    PanoramiXDamageCreate(ClientPtr client)
    {
        PanoramiXDamageRes *damage;
        PanoramiXRes *draw;
        int i, rc;
    
        REQUEST(xDamageCreateReq);
    
        REQUEST_SIZE_MATCH(xDamageCreateReq);
        LEGAL_NEW_RESOURCE(stuff->damage, client);
        rc = dixLookupResourceByClass((void **)&draw, stuff->drawable, XRC_DRAWABLE,
                                      client, DixGetAttrAccess | DixReadAccess);
        if (rc != Success)
            return rc;
    
        if (!(damage = calloc(1, sizeof(PanoramiXDamageRes))))
            return BadAlloc;
    
        if (!AddResource(stuff->damage, XRT_DAMAGE, damage))
            return BadAlloc;
    
        damage->ext = doDamageCreate(client, &rc);
        if (rc == Success && draw->type == XRT_WINDOW) {
            FOR_NSCREENS_FORWARD(i) {
                DrawablePtr pDrawable;
                DamagePtr pDamage = DamageCreate(PanoramiXDamageReport,
                                                 PanoramiXDamageExtDestroy,
                                                 DamageReportRawRegion,
                                                 FALSE,
                                                 screenInfo.screens[i],
                                                 damage);
                if (!pDamage) {
                    rc = BadAlloc;
                } else {
                    damage->damage[i] = pDamage;
                    rc = dixLookupDrawable(&pDrawable, draw->info[i].id, client,
                                           M_WINDOW,
                                           DixGetAttrAccess | DixReadAccess);
                }
                if (rc != Success)
                    break;
    
                DamageExtRegister(pDrawable, pDamage, i != 0);
            }
        }
    
        if (rc != Success)
            FreeResource(stuff->damage, RT_NONE);
    
        return rc;
    }
    
    static int
    PanoramiXDamageDelete(void *res, XID id)
    {
        int i;
        PanoramiXDamageRes *damage = res;
    
        FOR_NSCREENS_BACKWARD(i) {
            if (damage->damage[i]) {
                DamageDestroy(damage->damage[i]);
                damage->damage[i] = NULL;
            }
        }
    
        free(damage);
        return 1;
    }
    
    void
    PanoramiXDamageInit(void)
    {
        XRT_DAMAGE = CreateNewResourceType(PanoramiXDamageDelete, "XineramaDamage");
        if (!XRT_DAMAGE)
            FatalError("Couldn't Xineramify Damage extension\n");
    
        PanoramiXSaveDamageCreate = ProcDamageVector[X_DamageCreate];
        ProcDamageVector[X_DamageCreate] = PanoramiXDamageCreate;
    }
    
    void
    PanoramiXDamageReset(void)
    {
        ProcDamageVector[X_DamageCreate] = PanoramiXSaveDamageCreate;
    }
    
    #endif /* PANORAMIX */
    
    void
    DamageExtensionInit(void)
    {
        ExtensionEntry *extEntry;
        int s;
    
        for (s = 0; s < screenInfo.numScreens; s++)
            DamageSetup(screenInfo.screens[s]);
    
        DamageExtType = CreateNewResourceType(FreeDamageExt, "DamageExt");
        if (!DamageExtType)
            return;
    
        if (!dixRegisterPrivateKey
            (&DamageClientPrivateKeyRec, PRIVATE_CLIENT, sizeof(DamageClientRec)))
            return;
    
        if ((extEntry = AddExtension(DAMAGE_NAME, XDamageNumberEvents,
                                     XDamageNumberErrors,
                                     ProcDamageDispatch, SProcDamageDispatch,
                                     NULL, StandardMinorOpcode)) != 0) {
            DamageReqCode = (unsigned char) extEntry->base;
            DamageEventBase = extEntry->eventBase;
            EventSwapVector[DamageEventBase + XDamageNotify] =
                (EventSwapPtr) SDamageNotifyEvent;
            SetResourceTypeErrorValue(DamageExtType,
                                      extEntry->errorBase + BadDamage);
    #ifdef PANORAMIX
            if (XRT_DAMAGE)
                SetResourceTypeErrorValue(XRT_DAMAGE,
                                          extEntry->errorBase + BadDamage);
    #endif
        }
    }