105b261ecSmrg/* 205b261ecSmrg * Copyright © 2002 Keith Packard 335c4bbdfSmrg * Copyright 2013 Red Hat, Inc. 405b261ecSmrg * 505b261ecSmrg * Permission to use, copy, modify, distribute, and sell this software and its 605b261ecSmrg * documentation for any purpose is hereby granted without fee, provided that 705b261ecSmrg * the above copyright notice appear in all copies and that both that 805b261ecSmrg * copyright notice and this permission notice appear in supporting 905b261ecSmrg * documentation, and that the name of Keith Packard not be used in 1005b261ecSmrg * advertising or publicity pertaining to distribution of the software without 1105b261ecSmrg * specific, written prior permission. Keith Packard makes no 1205b261ecSmrg * representations about the suitability of this software for any purpose. It 1305b261ecSmrg * is provided "as is" without express or implied warranty. 1405b261ecSmrg * 1505b261ecSmrg * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 1605b261ecSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 1705b261ecSmrg * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR 1805b261ecSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 1905b261ecSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 2005b261ecSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 2105b261ecSmrg * PERFORMANCE OF THIS SOFTWARE. 2205b261ecSmrg */ 2305b261ecSmrg 2405b261ecSmrg#ifdef HAVE_DIX_CONFIG_H 2505b261ecSmrg#include <dix-config.h> 2605b261ecSmrg#endif 2705b261ecSmrg 2805b261ecSmrg#include "damageextint.h" 2935c4bbdfSmrg#include "damagestr.h" 306747b715Smrg#include "protocol-versions.h" 3135c4bbdfSmrg#include "extinit.h" 3205b261ecSmrg 3335c4bbdfSmrg#ifdef PANORAMIX 3435c4bbdfSmrg#include "panoramiX.h" 3535c4bbdfSmrg#include "panoramiXsrv.h" 3635c4bbdfSmrg 3735c4bbdfSmrgtypedef struct { 3835c4bbdfSmrg DamageExtPtr ext; 3935c4bbdfSmrg DamagePtr damage[MAXSCREENS]; 4035c4bbdfSmrg} PanoramiXDamageRes; 4135c4bbdfSmrg 4235c4bbdfSmrgstatic RESTYPE XRT_DAMAGE; 4335c4bbdfSmrgstatic int (*PanoramiXSaveDamageCreate) (ClientPtr); 4435c4bbdfSmrg 4535c4bbdfSmrg#endif 4635c4bbdfSmrg 4735c4bbdfSmrgstatic unsigned char DamageReqCode; 4835c4bbdfSmrgstatic int DamageEventBase; 4935c4bbdfSmrgstatic RESTYPE DamageExtType; 5005b261ecSmrg 516747b715Smrgstatic DevPrivateKeyRec DamageClientPrivateKeyRec; 5235c4bbdfSmrg 536747b715Smrg#define DamageClientPrivateKey (&DamageClientPrivateKeyRec) 5405b261ecSmrg 5505b261ecSmrgstatic void 5635c4bbdfSmrgDamageNoteCritical(ClientPtr pClient) 5735c4bbdfSmrg{ 5835c4bbdfSmrg DamageClientPtr pDamageClient = GetDamageClient(pClient); 5935c4bbdfSmrg 6035c4bbdfSmrg /* Composite extension marks clients with manual Subwindows as critical */ 6135c4bbdfSmrg if (pDamageClient->critical > 0) { 6235c4bbdfSmrg SetCriticalOutputPending(); 6335c4bbdfSmrg pClient->smart_priority = SMART_MAX_PRIORITY; 6405b261ecSmrg } 6535c4bbdfSmrg} 6635c4bbdfSmrg 6735c4bbdfSmrgstatic void 6835c4bbdfSmrgdamageGetGeometry(DrawablePtr draw, int *x, int *y, int *w, int *h) 6935c4bbdfSmrg{ 7035c4bbdfSmrg#ifdef PANORAMIX 7135c4bbdfSmrg if (!noPanoramiXExtension && draw->type == DRAWABLE_WINDOW) { 7235c4bbdfSmrg WindowPtr win = (WindowPtr)draw; 7335c4bbdfSmrg 7435c4bbdfSmrg if (!win->parent) { 7535c4bbdfSmrg *x = screenInfo.x; 7635c4bbdfSmrg *y = screenInfo.y; 7735c4bbdfSmrg *w = screenInfo.width; 7835c4bbdfSmrg *h = screenInfo.height; 7935c4bbdfSmrg return; 8035c4bbdfSmrg } 8105b261ecSmrg } 8235c4bbdfSmrg#endif 8335c4bbdfSmrg 8435c4bbdfSmrg *x = draw->x; 8535c4bbdfSmrg *y = draw->y; 8635c4bbdfSmrg *w = draw->width; 8735c4bbdfSmrg *h = draw->height; 8835c4bbdfSmrg} 8935c4bbdfSmrg 9035c4bbdfSmrgstatic void 9135c4bbdfSmrgDamageExtNotify(DamageExtPtr pDamageExt, BoxPtr pBoxes, int nBoxes) 9235c4bbdfSmrg{ 9335c4bbdfSmrg ClientPtr pClient = pDamageExt->pClient; 9435c4bbdfSmrg DrawablePtr pDrawable = pDamageExt->pDrawable; 9535c4bbdfSmrg xDamageNotifyEvent ev; 9635c4bbdfSmrg int i, x, y, w, h; 9735c4bbdfSmrg 9835c4bbdfSmrg damageGetGeometry(pDrawable, &x, &y, &w, &h); 9935c4bbdfSmrg 10035c4bbdfSmrg UpdateCurrentTimeIf(); 10135c4bbdfSmrg ev = (xDamageNotifyEvent) { 10235c4bbdfSmrg .type = DamageEventBase + XDamageNotify, 10335c4bbdfSmrg .level = pDamageExt->level, 10435c4bbdfSmrg .drawable = pDamageExt->drawable, 10535c4bbdfSmrg .damage = pDamageExt->id, 10635c4bbdfSmrg .timestamp = currentTime.milliseconds, 10735c4bbdfSmrg .geometry.x = x, 10835c4bbdfSmrg .geometry.y = y, 10935c4bbdfSmrg .geometry.width = w, 11035c4bbdfSmrg .geometry.height = h 11135c4bbdfSmrg }; 11235c4bbdfSmrg if (pBoxes) { 11335c4bbdfSmrg for (i = 0; i < nBoxes; i++) { 11435c4bbdfSmrg ev.level = pDamageExt->level; 11535c4bbdfSmrg if (i < nBoxes - 1) 11635c4bbdfSmrg ev.level |= DamageNotifyMore; 11735c4bbdfSmrg ev.area.x = pBoxes[i].x1; 11835c4bbdfSmrg ev.area.y = pBoxes[i].y1; 11935c4bbdfSmrg ev.area.width = pBoxes[i].x2 - pBoxes[i].x1; 12035c4bbdfSmrg ev.area.height = pBoxes[i].y2 - pBoxes[i].y1; 12135c4bbdfSmrg WriteEventsToClient(pClient, 1, (xEvent *) &ev); 12235c4bbdfSmrg } 12305b261ecSmrg } 12435c4bbdfSmrg else { 12535c4bbdfSmrg ev.area.x = 0; 12635c4bbdfSmrg ev.area.y = 0; 12735c4bbdfSmrg ev.area.width = w; 12835c4bbdfSmrg ev.area.height = h; 12935c4bbdfSmrg WriteEventsToClient(pClient, 1, (xEvent *) &ev); 13035c4bbdfSmrg } 13135c4bbdfSmrg 13235c4bbdfSmrg DamageNoteCritical(pClient); 13305b261ecSmrg} 13405b261ecSmrg 13505b261ecSmrgstatic void 13635c4bbdfSmrgDamageExtReport(DamagePtr pDamage, RegionPtr pRegion, void *closure) 13705b261ecSmrg{ 13835c4bbdfSmrg DamageExtPtr pDamageExt = closure; 13905b261ecSmrg 14005b261ecSmrg switch (pDamageExt->level) { 14105b261ecSmrg case DamageReportRawRegion: 14205b261ecSmrg case DamageReportDeltaRegion: 14335c4bbdfSmrg DamageExtNotify(pDamageExt, RegionRects(pRegion), 14435c4bbdfSmrg RegionNumRects(pRegion)); 14535c4bbdfSmrg break; 14605b261ecSmrg case DamageReportBoundingBox: 14735c4bbdfSmrg DamageExtNotify(pDamageExt, RegionExtents(pRegion), 1); 14835c4bbdfSmrg break; 14905b261ecSmrg case DamageReportNonEmpty: 15035c4bbdfSmrg DamageExtNotify(pDamageExt, NullBox, 0); 15135c4bbdfSmrg break; 15205b261ecSmrg case DamageReportNone: 15335c4bbdfSmrg break; 15405b261ecSmrg } 15505b261ecSmrg} 15605b261ecSmrg 15705b261ecSmrgstatic void 15835c4bbdfSmrgDamageExtDestroy(DamagePtr pDamage, void *closure) 15905b261ecSmrg{ 16035c4bbdfSmrg DamageExtPtr pDamageExt = closure; 16135c4bbdfSmrg 16205b261ecSmrg pDamageExt->pDamage = 0; 16305b261ecSmrg if (pDamageExt->id) 16435c4bbdfSmrg FreeResource(pDamageExt->id, RT_NONE); 16505b261ecSmrg} 16605b261ecSmrg 16705b261ecSmrgvoid 16835c4bbdfSmrgDamageExtSetCritical(ClientPtr pClient, Bool critical) 16905b261ecSmrg{ 17035c4bbdfSmrg DamageClientPtr pDamageClient = GetDamageClient(pClient); 17105b261ecSmrg 17205b261ecSmrg if (pDamageClient) 17335c4bbdfSmrg pDamageClient->critical += critical ? 1 : -1; 17405b261ecSmrg} 17505b261ecSmrg 17605b261ecSmrgstatic int 17705b261ecSmrgProcDamageQueryVersion(ClientPtr client) 17805b261ecSmrg{ 17935c4bbdfSmrg DamageClientPtr pDamageClient = GetDamageClient(client); 18035c4bbdfSmrg xDamageQueryVersionReply rep = { 18135c4bbdfSmrg .type = X_Reply, 18235c4bbdfSmrg .sequenceNumber = client->sequence, 18335c4bbdfSmrg .length = 0 18435c4bbdfSmrg }; 18535c4bbdfSmrg 18605b261ecSmrg REQUEST(xDamageQueryVersionReq); 18705b261ecSmrg 18805b261ecSmrg REQUEST_SIZE_MATCH(xDamageQueryVersionReq); 18935c4bbdfSmrg 1906747b715Smrg if (stuff->majorVersion < SERVER_DAMAGE_MAJOR_VERSION) { 19135c4bbdfSmrg rep.majorVersion = stuff->majorVersion; 19235c4bbdfSmrg rep.minorVersion = stuff->minorVersion; 19335c4bbdfSmrg } 19435c4bbdfSmrg else { 19535c4bbdfSmrg rep.majorVersion = SERVER_DAMAGE_MAJOR_VERSION; 19635c4bbdfSmrg if (stuff->majorVersion == SERVER_DAMAGE_MAJOR_VERSION && 19735c4bbdfSmrg stuff->minorVersion < SERVER_DAMAGE_MINOR_VERSION) 19835c4bbdfSmrg rep.minorVersion = stuff->minorVersion; 19935c4bbdfSmrg else 20035c4bbdfSmrg rep.minorVersion = SERVER_DAMAGE_MINOR_VERSION; 20105b261ecSmrg } 20205b261ecSmrg pDamageClient->major_version = rep.majorVersion; 20305b261ecSmrg pDamageClient->minor_version = rep.minorVersion; 20405b261ecSmrg if (client->swapped) { 20535c4bbdfSmrg swaps(&rep.sequenceNumber); 20635c4bbdfSmrg swapl(&rep.length); 20735c4bbdfSmrg swapl(&rep.majorVersion); 20835c4bbdfSmrg swapl(&rep.minorVersion); 20905b261ecSmrg } 21035c4bbdfSmrg WriteToClient(client, sizeof(xDamageQueryVersionReply), &rep); 2116747b715Smrg return Success; 21205b261ecSmrg} 21305b261ecSmrg 21435c4bbdfSmrgstatic void 21535c4bbdfSmrgDamageExtRegister(DrawablePtr pDrawable, DamagePtr pDamage, Bool report) 21635c4bbdfSmrg{ 21735c4bbdfSmrg DamageSetReportAfterOp(pDamage, TRUE); 21835c4bbdfSmrg DamageRegister(pDrawable, pDamage); 21935c4bbdfSmrg 22035c4bbdfSmrg if (report) { 22135c4bbdfSmrg RegionPtr pRegion = &((WindowPtr) pDrawable)->borderClip; 22235c4bbdfSmrg RegionTranslate(pRegion, -pDrawable->x, -pDrawable->y); 22335c4bbdfSmrg DamageReportDamage(pDamage, pRegion); 22435c4bbdfSmrg RegionTranslate(pRegion, pDrawable->x, pDrawable->y); 22535c4bbdfSmrg } 22635c4bbdfSmrg} 22735c4bbdfSmrg 22835c4bbdfSmrgstatic DamageExtPtr 22935c4bbdfSmrgDamageExtCreate(DrawablePtr pDrawable, DamageReportLevel level, 23035c4bbdfSmrg ClientPtr client, XID id, XID drawable) 23135c4bbdfSmrg{ 23235c4bbdfSmrg DamageExtPtr pDamageExt = malloc(sizeof(DamageExtRec)); 23335c4bbdfSmrg if (!pDamageExt) 23435c4bbdfSmrg return NULL; 23535c4bbdfSmrg 23635c4bbdfSmrg pDamageExt->id = id; 23735c4bbdfSmrg pDamageExt->drawable = drawable; 23835c4bbdfSmrg pDamageExt->pDrawable = pDrawable; 23935c4bbdfSmrg pDamageExt->level = level; 24035c4bbdfSmrg pDamageExt->pClient = client; 24135c4bbdfSmrg pDamageExt->pDamage = DamageCreate(DamageExtReport, DamageExtDestroy, level, 24235c4bbdfSmrg FALSE, pDrawable->pScreen, pDamageExt); 24335c4bbdfSmrg if (!pDamageExt->pDamage) { 24435c4bbdfSmrg free(pDamageExt); 24535c4bbdfSmrg return NULL; 24635c4bbdfSmrg } 24735c4bbdfSmrg 24835c4bbdfSmrg if (!AddResource(id, DamageExtType, (void *) pDamageExt)) 24935c4bbdfSmrg return NULL; 25035c4bbdfSmrg 25135c4bbdfSmrg DamageExtRegister(pDrawable, pDamageExt->pDamage, 25235c4bbdfSmrg pDrawable->type == DRAWABLE_WINDOW); 25335c4bbdfSmrg 25435c4bbdfSmrg return pDamageExt; 25535c4bbdfSmrg} 25635c4bbdfSmrg 25735c4bbdfSmrgstatic DamageExtPtr 25835c4bbdfSmrgdoDamageCreate(ClientPtr client, int *rc) 25935c4bbdfSmrg{ 26035c4bbdfSmrg DrawablePtr pDrawable; 26135c4bbdfSmrg DamageExtPtr pDamageExt; 26235c4bbdfSmrg DamageReportLevel level; 26335c4bbdfSmrg 26405b261ecSmrg REQUEST(xDamageCreateReq); 26505b261ecSmrg 26635c4bbdfSmrg *rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0, 26735c4bbdfSmrg DixGetAttrAccess | DixReadAccess); 26835c4bbdfSmrg if (*rc != Success) 26935c4bbdfSmrg return NULL; 27005b261ecSmrg 27105b261ecSmrg switch (stuff->level) { 27205b261ecSmrg case XDamageReportRawRectangles: 27335c4bbdfSmrg level = DamageReportRawRegion; 27435c4bbdfSmrg break; 27505b261ecSmrg case XDamageReportDeltaRectangles: 27635c4bbdfSmrg level = DamageReportDeltaRegion; 27735c4bbdfSmrg break; 27805b261ecSmrg case XDamageReportBoundingBox: 27935c4bbdfSmrg level = DamageReportBoundingBox; 28035c4bbdfSmrg break; 28105b261ecSmrg case XDamageReportNonEmpty: 28235c4bbdfSmrg level = DamageReportNonEmpty; 28335c4bbdfSmrg break; 28405b261ecSmrg default: 28535c4bbdfSmrg client->errorValue = stuff->level; 28635c4bbdfSmrg *rc = BadValue; 28735c4bbdfSmrg return NULL; 28805b261ecSmrg } 28905b261ecSmrg 29035c4bbdfSmrg pDamageExt = DamageExtCreate(pDrawable, level, client, stuff->damage, 29135c4bbdfSmrg stuff->drawable); 29235c4bbdfSmrg if (!pDamageExt) 29335c4bbdfSmrg *rc = BadAlloc; 29405b261ecSmrg 29535c4bbdfSmrg return pDamageExt; 29635c4bbdfSmrg} 29705b261ecSmrg 29835c4bbdfSmrgstatic int 29935c4bbdfSmrgProcDamageCreate(ClientPtr client) 30035c4bbdfSmrg{ 30135c4bbdfSmrg int rc; 30235c4bbdfSmrg REQUEST(xDamageCreateReq); 30335c4bbdfSmrg REQUEST_SIZE_MATCH(xDamageCreateReq); 30435c4bbdfSmrg LEGAL_NEW_RESOURCE(stuff->damage, client); 30535c4bbdfSmrg doDamageCreate(client, &rc); 30635c4bbdfSmrg return rc; 30705b261ecSmrg} 30805b261ecSmrg 30905b261ecSmrgstatic int 31035c4bbdfSmrgProcDamageDestroy(ClientPtr client) 31105b261ecSmrg{ 31205b261ecSmrg REQUEST(xDamageDestroyReq); 31335c4bbdfSmrg DamageExtPtr pDamageExt; 31405b261ecSmrg 31505b261ecSmrg REQUEST_SIZE_MATCH(xDamageDestroyReq); 31605b261ecSmrg VERIFY_DAMAGEEXT(pDamageExt, stuff->damage, client, DixWriteAccess); 31735c4bbdfSmrg FreeResource(stuff->damage, RT_NONE); 3186747b715Smrg return Success; 31905b261ecSmrg} 32005b261ecSmrg 32135c4bbdfSmrg#ifdef PANORAMIX 32235c4bbdfSmrgstatic RegionPtr 32335c4bbdfSmrgDamageExtSubtractWindowClip(DamageExtPtr pDamageExt) 32435c4bbdfSmrg{ 32535c4bbdfSmrg WindowPtr win = (WindowPtr)pDamageExt->pDrawable; 32635c4bbdfSmrg PanoramiXRes *res = NULL; 32735c4bbdfSmrg RegionPtr ret; 32835c4bbdfSmrg int i; 32935c4bbdfSmrg 33035c4bbdfSmrg if (!win->parent) 33135c4bbdfSmrg return &PanoramiXScreenRegion; 33235c4bbdfSmrg 33335c4bbdfSmrg dixLookupResourceByType((void **)&res, win->drawable.id, XRT_WINDOW, 33435c4bbdfSmrg serverClient, DixReadAccess); 33535c4bbdfSmrg if (!res) 33635c4bbdfSmrg return NULL; 33735c4bbdfSmrg 33835c4bbdfSmrg ret = RegionCreate(NULL, 0); 33935c4bbdfSmrg if (!ret) 34035c4bbdfSmrg return NULL; 34135c4bbdfSmrg 34235c4bbdfSmrg FOR_NSCREENS_FORWARD(i) { 34335c4bbdfSmrg ScreenPtr screen; 34435c4bbdfSmrg if (Success != dixLookupWindow(&win, res->info[i].id, serverClient, 34535c4bbdfSmrg DixReadAccess)) 34635c4bbdfSmrg goto out; 34735c4bbdfSmrg 34835c4bbdfSmrg screen = win->drawable.pScreen; 34935c4bbdfSmrg 35035c4bbdfSmrg RegionTranslate(ret, -screen->x, -screen->y); 35135c4bbdfSmrg if (!RegionUnion(ret, ret, &win->borderClip)) 35235c4bbdfSmrg goto out; 35335c4bbdfSmrg RegionTranslate(ret, screen->x, screen->y); 35435c4bbdfSmrg } 35535c4bbdfSmrg 35635c4bbdfSmrg return ret; 35735c4bbdfSmrg 35835c4bbdfSmrgout: 35935c4bbdfSmrg RegionDestroy(ret); 36035c4bbdfSmrg return NULL; 36135c4bbdfSmrg} 36235c4bbdfSmrg 36335c4bbdfSmrgstatic void 36435c4bbdfSmrgDamageExtFreeWindowClip(RegionPtr reg) 36535c4bbdfSmrg{ 36635c4bbdfSmrg if (reg != &PanoramiXScreenRegion) 36735c4bbdfSmrg RegionDestroy(reg); 36835c4bbdfSmrg} 36935c4bbdfSmrg#endif 37035c4bbdfSmrg 37135c4bbdfSmrg/* 37235c4bbdfSmrg * DamageSubtract intersects with borderClip, so we must reconstruct the 37335c4bbdfSmrg * protocol's perspective of same... 37435c4bbdfSmrg */ 37535c4bbdfSmrgstatic Bool 37635c4bbdfSmrgDamageExtSubtract(DamageExtPtr pDamageExt, const RegionPtr pRegion) 37735c4bbdfSmrg{ 37835c4bbdfSmrg DamagePtr pDamage = pDamageExt->pDamage; 37935c4bbdfSmrg 38035c4bbdfSmrg#ifdef PANORAMIX 38135c4bbdfSmrg if (!noPanoramiXExtension) { 38235c4bbdfSmrg RegionPtr damage = DamageRegion(pDamage); 38335c4bbdfSmrg RegionSubtract(damage, damage, pRegion); 38435c4bbdfSmrg 38535c4bbdfSmrg if (pDamageExt->pDrawable->type == DRAWABLE_WINDOW) { 38635c4bbdfSmrg DrawablePtr pDraw = pDamageExt->pDrawable; 38735c4bbdfSmrg RegionPtr clip = DamageExtSubtractWindowClip(pDamageExt); 38835c4bbdfSmrg if (clip) { 38935c4bbdfSmrg RegionTranslate(clip, -pDraw->x, -pDraw->y); 39035c4bbdfSmrg RegionIntersect(damage, damage, clip); 39135c4bbdfSmrg RegionTranslate(clip, pDraw->x, pDraw->y); 39235c4bbdfSmrg DamageExtFreeWindowClip(clip); 39335c4bbdfSmrg } 39435c4bbdfSmrg } 39535c4bbdfSmrg 39635c4bbdfSmrg return RegionNotEmpty(damage); 39735c4bbdfSmrg } 39835c4bbdfSmrg#endif 39935c4bbdfSmrg 40035c4bbdfSmrg return DamageSubtract(pDamage, pRegion); 40135c4bbdfSmrg} 40235c4bbdfSmrg 40305b261ecSmrgstatic int 40435c4bbdfSmrgProcDamageSubtract(ClientPtr client) 40505b261ecSmrg{ 40605b261ecSmrg REQUEST(xDamageSubtractReq); 40735c4bbdfSmrg DamageExtPtr pDamageExt; 40835c4bbdfSmrg RegionPtr pRepair; 40935c4bbdfSmrg RegionPtr pParts; 41005b261ecSmrg 41105b261ecSmrg REQUEST_SIZE_MATCH(xDamageSubtractReq); 41205b261ecSmrg VERIFY_DAMAGEEXT(pDamageExt, stuff->damage, client, DixWriteAccess); 41305b261ecSmrg VERIFY_REGION_OR_NONE(pRepair, stuff->repair, client, DixWriteAccess); 41405b261ecSmrg VERIFY_REGION_OR_NONE(pParts, stuff->parts, client, DixWriteAccess); 41505b261ecSmrg 41635c4bbdfSmrg if (pDamageExt->level != DamageReportRawRegion) { 41735c4bbdfSmrg DamagePtr pDamage = pDamageExt->pDamage; 41835c4bbdfSmrg 41935c4bbdfSmrg if (pRepair) { 42035c4bbdfSmrg if (pParts) 42135c4bbdfSmrg RegionIntersect(pParts, DamageRegion(pDamage), pRepair); 42235c4bbdfSmrg if (DamageExtSubtract(pDamageExt, pRepair)) 42335c4bbdfSmrg DamageExtReport(pDamage, DamageRegion(pDamage), 42435c4bbdfSmrg (void *) pDamageExt); 42535c4bbdfSmrg } 42635c4bbdfSmrg else { 42735c4bbdfSmrg if (pParts) 42835c4bbdfSmrg RegionCopy(pParts, DamageRegion(pDamage)); 42935c4bbdfSmrg DamageEmpty(pDamage); 43035c4bbdfSmrg } 43105b261ecSmrg } 43235c4bbdfSmrg 4336747b715Smrg return Success; 43405b261ecSmrg} 43505b261ecSmrg 43605b261ecSmrgstatic int 43735c4bbdfSmrgProcDamageAdd(ClientPtr client) 43805b261ecSmrg{ 43905b261ecSmrg REQUEST(xDamageAddReq); 44035c4bbdfSmrg DrawablePtr pDrawable; 44135c4bbdfSmrg RegionPtr pRegion; 44235c4bbdfSmrg int rc; 44305b261ecSmrg 44405b261ecSmrg REQUEST_SIZE_MATCH(xDamageAddReq); 44505b261ecSmrg VERIFY_REGION(pRegion, stuff->region, client, DixWriteAccess); 44605b261ecSmrg rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0, 44735c4bbdfSmrg DixWriteAccess); 44805b261ecSmrg if (rc != Success) 44935c4bbdfSmrg return rc; 45005b261ecSmrg 45105b261ecSmrg /* The region is relative to the drawable origin, so translate it out to 45205b261ecSmrg * screen coordinates like damage expects. 45305b261ecSmrg */ 4546747b715Smrg RegionTranslate(pRegion, pDrawable->x, pDrawable->y); 4558223e2f2Smrg DamageDamageRegion(pDrawable, pRegion); 4566747b715Smrg RegionTranslate(pRegion, -pDrawable->x, -pDrawable->y); 45705b261ecSmrg 4586747b715Smrg return Success; 45905b261ecSmrg} 46005b261ecSmrg 46105b261ecSmrg/* Major version controls available requests */ 46205b261ecSmrgstatic const int version_requests[] = { 46335c4bbdfSmrg X_DamageQueryVersion, /* before client sends QueryVersion */ 46435c4bbdfSmrg X_DamageAdd, /* Version 1 */ 46505b261ecSmrg}; 46605b261ecSmrg 46735c4bbdfSmrgstatic int (*ProcDamageVector[XDamageNumberRequests]) (ClientPtr) = { 46835c4bbdfSmrg /*************** Version 1 ******************/ 46905b261ecSmrg ProcDamageQueryVersion, 47005b261ecSmrg ProcDamageCreate, 47105b261ecSmrg ProcDamageDestroy, 47205b261ecSmrg ProcDamageSubtract, 47335c4bbdfSmrg /*************** Version 1.1 ****************/ 47405b261ecSmrg ProcDamageAdd, 47505b261ecSmrg}; 47605b261ecSmrg 47705b261ecSmrgstatic int 47835c4bbdfSmrgProcDamageDispatch(ClientPtr client) 47905b261ecSmrg{ 48005b261ecSmrg REQUEST(xDamageReq); 48135c4bbdfSmrg DamageClientPtr pDamageClient = GetDamageClient(client); 48205b261ecSmrg 4831b5d61b8Smrg if (pDamageClient->major_version >= ARRAY_SIZE(version_requests)) 48435c4bbdfSmrg return BadRequest; 48505b261ecSmrg if (stuff->damageReqType > version_requests[pDamageClient->major_version]) 48635c4bbdfSmrg return BadRequest; 48705b261ecSmrg return (*ProcDamageVector[stuff->damageReqType]) (client); 48805b261ecSmrg} 48905b261ecSmrg 4901b5d61b8Smrgstatic int _X_COLD 49105b261ecSmrgSProcDamageQueryVersion(ClientPtr client) 49205b261ecSmrg{ 49305b261ecSmrg REQUEST(xDamageQueryVersionReq); 49405b261ecSmrg 49535c4bbdfSmrg swaps(&stuff->length); 49605b261ecSmrg REQUEST_SIZE_MATCH(xDamageQueryVersionReq); 49735c4bbdfSmrg swapl(&stuff->majorVersion); 49835c4bbdfSmrg swapl(&stuff->minorVersion); 49905b261ecSmrg return (*ProcDamageVector[stuff->damageReqType]) (client); 50005b261ecSmrg} 50105b261ecSmrg 5021b5d61b8Smrgstatic int _X_COLD 50335c4bbdfSmrgSProcDamageCreate(ClientPtr client) 50405b261ecSmrg{ 50505b261ecSmrg REQUEST(xDamageCreateReq); 50635c4bbdfSmrg 50735c4bbdfSmrg swaps(&stuff->length); 50805b261ecSmrg REQUEST_SIZE_MATCH(xDamageCreateReq); 50935c4bbdfSmrg swapl(&stuff->damage); 51035c4bbdfSmrg swapl(&stuff->drawable); 51105b261ecSmrg return (*ProcDamageVector[stuff->damageReqType]) (client); 51205b261ecSmrg} 51305b261ecSmrg 5141b5d61b8Smrgstatic int _X_COLD 51535c4bbdfSmrgSProcDamageDestroy(ClientPtr client) 51605b261ecSmrg{ 51705b261ecSmrg REQUEST(xDamageDestroyReq); 51835c4bbdfSmrg 51935c4bbdfSmrg swaps(&stuff->length); 52005b261ecSmrg REQUEST_SIZE_MATCH(xDamageDestroyReq); 52135c4bbdfSmrg swapl(&stuff->damage); 52205b261ecSmrg return (*ProcDamageVector[stuff->damageReqType]) (client); 52305b261ecSmrg} 52405b261ecSmrg 5251b5d61b8Smrgstatic int _X_COLD 52635c4bbdfSmrgSProcDamageSubtract(ClientPtr client) 52705b261ecSmrg{ 52805b261ecSmrg REQUEST(xDamageSubtractReq); 52935c4bbdfSmrg 53035c4bbdfSmrg swaps(&stuff->length); 53105b261ecSmrg REQUEST_SIZE_MATCH(xDamageSubtractReq); 53235c4bbdfSmrg swapl(&stuff->damage); 53335c4bbdfSmrg swapl(&stuff->repair); 53435c4bbdfSmrg swapl(&stuff->parts); 53505b261ecSmrg return (*ProcDamageVector[stuff->damageReqType]) (client); 53605b261ecSmrg} 53705b261ecSmrg 5381b5d61b8Smrgstatic int _X_COLD 53935c4bbdfSmrgSProcDamageAdd(ClientPtr client) 54005b261ecSmrg{ 54105b261ecSmrg REQUEST(xDamageAddReq); 54205b261ecSmrg 54335c4bbdfSmrg swaps(&stuff->length); 54405b261ecSmrg REQUEST_SIZE_MATCH(xDamageSubtractReq); 54535c4bbdfSmrg swapl(&stuff->drawable); 54635c4bbdfSmrg swapl(&stuff->region); 54705b261ecSmrg return (*ProcDamageVector[stuff->damageReqType]) (client); 54805b261ecSmrg} 54905b261ecSmrg 55035c4bbdfSmrgstatic int (*SProcDamageVector[XDamageNumberRequests]) (ClientPtr) = { 55135c4bbdfSmrg /*************** Version 1 ******************/ 55205b261ecSmrg SProcDamageQueryVersion, 55305b261ecSmrg SProcDamageCreate, 55405b261ecSmrg SProcDamageDestroy, 55505b261ecSmrg SProcDamageSubtract, 55635c4bbdfSmrg /*************** Version 1.1 ****************/ 55705b261ecSmrg SProcDamageAdd, 55805b261ecSmrg}; 55905b261ecSmrg 5601b5d61b8Smrgstatic int _X_COLD 56135c4bbdfSmrgSProcDamageDispatch(ClientPtr client) 56205b261ecSmrg{ 56305b261ecSmrg REQUEST(xDamageReq); 564ed6184dfSmrg DamageClientPtr pDamageClient = GetDamageClient(client); 565ed6184dfSmrg 566ed6184dfSmrg if (pDamageClient->major_version >= ARRAY_SIZE(version_requests)) 567ed6184dfSmrg return BadRequest; 568ed6184dfSmrg if (stuff->damageReqType > version_requests[pDamageClient->major_version]) 56935c4bbdfSmrg return BadRequest; 57005b261ecSmrg return (*SProcDamageVector[stuff->damageReqType]) (client); 57105b261ecSmrg} 57205b261ecSmrg 57305b261ecSmrgstatic int 57435c4bbdfSmrgFreeDamageExt(void *value, XID did) 57505b261ecSmrg{ 57635c4bbdfSmrg DamageExtPtr pDamageExt = (DamageExtPtr) value; 57705b261ecSmrg 57805b261ecSmrg /* 57905b261ecSmrg * Get rid of the resource table entry hanging from the window id 58005b261ecSmrg */ 58105b261ecSmrg pDamageExt->id = 0; 58235c4bbdfSmrg if (pDamageExt->pDamage) { 58335c4bbdfSmrg DamageDestroy(pDamageExt->pDamage); 58405b261ecSmrg } 5856747b715Smrg free(pDamageExt); 58605b261ecSmrg return Success; 58705b261ecSmrg} 58805b261ecSmrg 5891b5d61b8Smrgstatic void _X_COLD 59035c4bbdfSmrgSDamageNotifyEvent(xDamageNotifyEvent * from, xDamageNotifyEvent * to) 59105b261ecSmrg{ 59235c4bbdfSmrg to->type = from->type; 59335c4bbdfSmrg cpswaps(from->sequenceNumber, to->sequenceNumber); 59435c4bbdfSmrg cpswapl(from->drawable, to->drawable); 59535c4bbdfSmrg cpswapl(from->damage, to->damage); 59635c4bbdfSmrg cpswaps(from->area.x, to->area.x); 59735c4bbdfSmrg cpswaps(from->area.y, to->area.y); 59835c4bbdfSmrg cpswaps(from->area.width, to->area.width); 59935c4bbdfSmrg cpswaps(from->area.height, to->area.height); 60035c4bbdfSmrg cpswaps(from->geometry.x, to->geometry.x); 60135c4bbdfSmrg cpswaps(from->geometry.y, to->geometry.y); 60235c4bbdfSmrg cpswaps(from->geometry.width, to->geometry.width); 60335c4bbdfSmrg cpswaps(from->geometry.height, to->geometry.height); 60435c4bbdfSmrg} 60505b261ecSmrg 60635c4bbdfSmrg#ifdef PANORAMIX 60735c4bbdfSmrg 60835c4bbdfSmrgstatic void 60935c4bbdfSmrgPanoramiXDamageReport(DamagePtr pDamage, RegionPtr pRegion, void *closure) 61035c4bbdfSmrg{ 61135c4bbdfSmrg PanoramiXDamageRes *res = closure; 61235c4bbdfSmrg DamageExtPtr pDamageExt = res->ext; 61335c4bbdfSmrg WindowPtr pWin = (WindowPtr)pDamage->pDrawable; 61435c4bbdfSmrg ScreenPtr pScreen = pDamage->pScreen; 61535c4bbdfSmrg 61635c4bbdfSmrg /* happens on unmap? sigh xinerama */ 61735c4bbdfSmrg if (RegionNil(pRegion)) 61835c4bbdfSmrg return; 61935c4bbdfSmrg 62035c4bbdfSmrg /* translate root windows if necessary */ 62135c4bbdfSmrg if (!pWin->parent) 62235c4bbdfSmrg RegionTranslate(pRegion, pScreen->x, pScreen->y); 62335c4bbdfSmrg 62435c4bbdfSmrg /* add our damage to the protocol view */ 62535c4bbdfSmrg DamageReportDamage(pDamageExt->pDamage, pRegion); 62635c4bbdfSmrg 62735c4bbdfSmrg /* empty our view */ 62835c4bbdfSmrg DamageEmpty(pDamage); 62905b261ecSmrg} 63005b261ecSmrg 63105b261ecSmrgstatic void 63235c4bbdfSmrgPanoramiXDamageExtDestroy(DamagePtr pDamage, void *closure) 63305b261ecSmrg{ 63435c4bbdfSmrg PanoramiXDamageRes *damage = closure; 63535c4bbdfSmrg damage->damage[pDamage->pScreen->myNum] = NULL; 63605b261ecSmrg} 63705b261ecSmrg 63835c4bbdfSmrgstatic int 63935c4bbdfSmrgPanoramiXDamageCreate(ClientPtr client) 64035c4bbdfSmrg{ 64135c4bbdfSmrg PanoramiXDamageRes *damage; 64235c4bbdfSmrg PanoramiXRes *draw; 64335c4bbdfSmrg int i, rc; 64435c4bbdfSmrg 64535c4bbdfSmrg REQUEST(xDamageCreateReq); 64635c4bbdfSmrg 64735c4bbdfSmrg REQUEST_SIZE_MATCH(xDamageCreateReq); 64835c4bbdfSmrg LEGAL_NEW_RESOURCE(stuff->damage, client); 64935c4bbdfSmrg rc = dixLookupResourceByClass((void **)&draw, stuff->drawable, XRC_DRAWABLE, 65035c4bbdfSmrg client, DixGetAttrAccess | DixReadAccess); 65135c4bbdfSmrg if (rc != Success) 65235c4bbdfSmrg return rc; 65335c4bbdfSmrg 65435c4bbdfSmrg if (!(damage = calloc(1, sizeof(PanoramiXDamageRes)))) 65535c4bbdfSmrg return BadAlloc; 65635c4bbdfSmrg 65735c4bbdfSmrg if (!AddResource(stuff->damage, XRT_DAMAGE, damage)) 65835c4bbdfSmrg return BadAlloc; 65935c4bbdfSmrg 66035c4bbdfSmrg damage->ext = doDamageCreate(client, &rc); 66135c4bbdfSmrg if (rc == Success && draw->type == XRT_WINDOW) { 66235c4bbdfSmrg FOR_NSCREENS_FORWARD(i) { 66335c4bbdfSmrg DrawablePtr pDrawable; 66435c4bbdfSmrg DamagePtr pDamage = DamageCreate(PanoramiXDamageReport, 66535c4bbdfSmrg PanoramiXDamageExtDestroy, 66635c4bbdfSmrg DamageReportRawRegion, 66735c4bbdfSmrg FALSE, 66835c4bbdfSmrg screenInfo.screens[i], 66935c4bbdfSmrg damage); 67035c4bbdfSmrg if (!pDamage) { 67135c4bbdfSmrg rc = BadAlloc; 67235c4bbdfSmrg } else { 67335c4bbdfSmrg damage->damage[i] = pDamage; 67435c4bbdfSmrg rc = dixLookupDrawable(&pDrawable, draw->info[i].id, client, 67535c4bbdfSmrg M_WINDOW, 67635c4bbdfSmrg DixGetAttrAccess | DixReadAccess); 67735c4bbdfSmrg } 67835c4bbdfSmrg if (rc != Success) 67935c4bbdfSmrg break; 68035c4bbdfSmrg 68135c4bbdfSmrg DamageExtRegister(pDrawable, pDamage, i != 0); 68235c4bbdfSmrg } 68335c4bbdfSmrg } 68435c4bbdfSmrg 68535c4bbdfSmrg if (rc != Success) 68635c4bbdfSmrg FreeResource(stuff->damage, RT_NONE); 68735c4bbdfSmrg 68835c4bbdfSmrg return rc; 68935c4bbdfSmrg} 69035c4bbdfSmrg 69135c4bbdfSmrgstatic int 69235c4bbdfSmrgPanoramiXDamageDelete(void *res, XID id) 69335c4bbdfSmrg{ 69435c4bbdfSmrg int i; 69535c4bbdfSmrg PanoramiXDamageRes *damage = res; 69635c4bbdfSmrg 69735c4bbdfSmrg FOR_NSCREENS_BACKWARD(i) { 69835c4bbdfSmrg if (damage->damage[i]) { 69935c4bbdfSmrg DamageDestroy(damage->damage[i]); 70035c4bbdfSmrg damage->damage[i] = NULL; 70135c4bbdfSmrg } 70235c4bbdfSmrg } 70335c4bbdfSmrg 70435c4bbdfSmrg free(damage); 70535c4bbdfSmrg return 1; 70635c4bbdfSmrg} 70735c4bbdfSmrg 70835c4bbdfSmrgvoid 70935c4bbdfSmrgPanoramiXDamageInit(void) 71035c4bbdfSmrg{ 71135c4bbdfSmrg XRT_DAMAGE = CreateNewResourceType(PanoramiXDamageDelete, "XineramaDamage"); 71235c4bbdfSmrg if (!XRT_DAMAGE) 71335c4bbdfSmrg FatalError("Couldn't Xineramify Damage extension\n"); 71435c4bbdfSmrg 71535c4bbdfSmrg PanoramiXSaveDamageCreate = ProcDamageVector[X_DamageCreate]; 71635c4bbdfSmrg ProcDamageVector[X_DamageCreate] = PanoramiXDamageCreate; 71735c4bbdfSmrg} 71835c4bbdfSmrg 71935c4bbdfSmrgvoid 72035c4bbdfSmrgPanoramiXDamageReset(void) 72135c4bbdfSmrg{ 72235c4bbdfSmrg ProcDamageVector[X_DamageCreate] = PanoramiXSaveDamageCreate; 72335c4bbdfSmrg} 72435c4bbdfSmrg 72535c4bbdfSmrg#endif /* PANORAMIX */ 72635c4bbdfSmrg 72705b261ecSmrgvoid 72805b261ecSmrgDamageExtensionInit(void) 72905b261ecSmrg{ 73005b261ecSmrg ExtensionEntry *extEntry; 73135c4bbdfSmrg int s; 73205b261ecSmrg 73305b261ecSmrg for (s = 0; s < screenInfo.numScreens; s++) 73435c4bbdfSmrg DamageSetup(screenInfo.screens[s]); 73505b261ecSmrg 73635c4bbdfSmrg DamageExtType = CreateNewResourceType(FreeDamageExt, "DamageExt"); 73705b261ecSmrg if (!DamageExtType) 73835c4bbdfSmrg return; 73935c4bbdfSmrg 74035c4bbdfSmrg if (!dixRegisterPrivateKey 74135c4bbdfSmrg (&DamageClientPrivateKeyRec, PRIVATE_CLIENT, sizeof(DamageClientRec))) 74235c4bbdfSmrg return; 74335c4bbdfSmrg 74435c4bbdfSmrg if ((extEntry = AddExtension(DAMAGE_NAME, XDamageNumberEvents, 74535c4bbdfSmrg XDamageNumberErrors, 74635c4bbdfSmrg ProcDamageDispatch, SProcDamageDispatch, 7471b5d61b8Smrg NULL, StandardMinorOpcode)) != 0) { 74835c4bbdfSmrg DamageReqCode = (unsigned char) extEntry->base; 74935c4bbdfSmrg DamageEventBase = extEntry->eventBase; 75035c4bbdfSmrg EventSwapVector[DamageEventBase + XDamageNotify] = 75135c4bbdfSmrg (EventSwapPtr) SDamageNotifyEvent; 75235c4bbdfSmrg SetResourceTypeErrorValue(DamageExtType, 75335c4bbdfSmrg extEntry->errorBase + BadDamage); 75435c4bbdfSmrg#ifdef PANORAMIX 75535c4bbdfSmrg if (XRT_DAMAGE) 75635c4bbdfSmrg SetResourceTypeErrorValue(XRT_DAMAGE, 75735c4bbdfSmrg extEntry->errorBase + BadDamage); 75835c4bbdfSmrg#endif 75905b261ecSmrg } 76005b261ecSmrg} 761