damageext.c revision 35c4bbdf
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 46705b261ecSmrg#define NUM_VERSION_REQUESTS (sizeof (version_requests) / sizeof (version_requests[0])) 46835c4bbdfSmrg 46935c4bbdfSmrgstatic int (*ProcDamageVector[XDamageNumberRequests]) (ClientPtr) = { 47035c4bbdfSmrg /*************** Version 1 ******************/ 47105b261ecSmrg ProcDamageQueryVersion, 47205b261ecSmrg ProcDamageCreate, 47305b261ecSmrg ProcDamageDestroy, 47405b261ecSmrg ProcDamageSubtract, 47535c4bbdfSmrg /*************** Version 1.1 ****************/ 47605b261ecSmrg ProcDamageAdd, 47705b261ecSmrg}; 47805b261ecSmrg 47905b261ecSmrgstatic int 48035c4bbdfSmrgProcDamageDispatch(ClientPtr client) 48105b261ecSmrg{ 48205b261ecSmrg REQUEST(xDamageReq); 48335c4bbdfSmrg DamageClientPtr pDamageClient = GetDamageClient(client); 48405b261ecSmrg 48505b261ecSmrg if (pDamageClient->major_version >= NUM_VERSION_REQUESTS) 48635c4bbdfSmrg return BadRequest; 48705b261ecSmrg if (stuff->damageReqType > version_requests[pDamageClient->major_version]) 48835c4bbdfSmrg return BadRequest; 48905b261ecSmrg return (*ProcDamageVector[stuff->damageReqType]) (client); 49005b261ecSmrg} 49105b261ecSmrg 49205b261ecSmrgstatic int 49305b261ecSmrgSProcDamageQueryVersion(ClientPtr client) 49405b261ecSmrg{ 49505b261ecSmrg REQUEST(xDamageQueryVersionReq); 49605b261ecSmrg 49735c4bbdfSmrg swaps(&stuff->length); 49805b261ecSmrg REQUEST_SIZE_MATCH(xDamageQueryVersionReq); 49935c4bbdfSmrg swapl(&stuff->majorVersion); 50035c4bbdfSmrg swapl(&stuff->minorVersion); 50105b261ecSmrg return (*ProcDamageVector[stuff->damageReqType]) (client); 50205b261ecSmrg} 50305b261ecSmrg 50405b261ecSmrgstatic int 50535c4bbdfSmrgSProcDamageCreate(ClientPtr client) 50605b261ecSmrg{ 50705b261ecSmrg REQUEST(xDamageCreateReq); 50835c4bbdfSmrg 50935c4bbdfSmrg swaps(&stuff->length); 51005b261ecSmrg REQUEST_SIZE_MATCH(xDamageCreateReq); 51135c4bbdfSmrg swapl(&stuff->damage); 51235c4bbdfSmrg swapl(&stuff->drawable); 51305b261ecSmrg return (*ProcDamageVector[stuff->damageReqType]) (client); 51405b261ecSmrg} 51505b261ecSmrg 51605b261ecSmrgstatic int 51735c4bbdfSmrgSProcDamageDestroy(ClientPtr client) 51805b261ecSmrg{ 51905b261ecSmrg REQUEST(xDamageDestroyReq); 52035c4bbdfSmrg 52135c4bbdfSmrg swaps(&stuff->length); 52205b261ecSmrg REQUEST_SIZE_MATCH(xDamageDestroyReq); 52335c4bbdfSmrg swapl(&stuff->damage); 52405b261ecSmrg return (*ProcDamageVector[stuff->damageReqType]) (client); 52505b261ecSmrg} 52605b261ecSmrg 52705b261ecSmrgstatic int 52835c4bbdfSmrgSProcDamageSubtract(ClientPtr client) 52905b261ecSmrg{ 53005b261ecSmrg REQUEST(xDamageSubtractReq); 53135c4bbdfSmrg 53235c4bbdfSmrg swaps(&stuff->length); 53305b261ecSmrg REQUEST_SIZE_MATCH(xDamageSubtractReq); 53435c4bbdfSmrg swapl(&stuff->damage); 53535c4bbdfSmrg swapl(&stuff->repair); 53635c4bbdfSmrg swapl(&stuff->parts); 53705b261ecSmrg return (*ProcDamageVector[stuff->damageReqType]) (client); 53805b261ecSmrg} 53905b261ecSmrg 54005b261ecSmrgstatic int 54135c4bbdfSmrgSProcDamageAdd(ClientPtr client) 54205b261ecSmrg{ 54305b261ecSmrg REQUEST(xDamageAddReq); 54405b261ecSmrg 54535c4bbdfSmrg swaps(&stuff->length); 54605b261ecSmrg REQUEST_SIZE_MATCH(xDamageSubtractReq); 54735c4bbdfSmrg swapl(&stuff->drawable); 54835c4bbdfSmrg swapl(&stuff->region); 54905b261ecSmrg return (*ProcDamageVector[stuff->damageReqType]) (client); 55005b261ecSmrg} 55105b261ecSmrg 55235c4bbdfSmrgstatic int (*SProcDamageVector[XDamageNumberRequests]) (ClientPtr) = { 55335c4bbdfSmrg /*************** Version 1 ******************/ 55405b261ecSmrg SProcDamageQueryVersion, 55505b261ecSmrg SProcDamageCreate, 55605b261ecSmrg SProcDamageDestroy, 55705b261ecSmrg SProcDamageSubtract, 55835c4bbdfSmrg /*************** Version 1.1 ****************/ 55905b261ecSmrg SProcDamageAdd, 56005b261ecSmrg}; 56105b261ecSmrg 56205b261ecSmrgstatic int 56335c4bbdfSmrgSProcDamageDispatch(ClientPtr client) 56405b261ecSmrg{ 56505b261ecSmrg REQUEST(xDamageReq); 56605b261ecSmrg if (stuff->damageReqType >= XDamageNumberRequests) 56735c4bbdfSmrg return BadRequest; 56805b261ecSmrg return (*SProcDamageVector[stuff->damageReqType]) (client); 56905b261ecSmrg} 57005b261ecSmrg 57105b261ecSmrgstatic void 57235c4bbdfSmrgDamageClientCallback(CallbackListPtr *list, void *closure, void *data) 57305b261ecSmrg{ 57435c4bbdfSmrg NewClientInfoRec *clientinfo = (NewClientInfoRec *) data; 57535c4bbdfSmrg ClientPtr pClient = clientinfo->client; 57635c4bbdfSmrg DamageClientPtr pDamageClient = GetDamageClient(pClient); 57705b261ecSmrg 57805b261ecSmrg pDamageClient->critical = 0; 57905b261ecSmrg pDamageClient->major_version = 0; 58005b261ecSmrg pDamageClient->minor_version = 0; 58105b261ecSmrg} 58205b261ecSmrg 58335c4bbdfSmrg /*ARGSUSED*/ static void 58435c4bbdfSmrgDamageResetProc(ExtensionEntry * extEntry) 58505b261ecSmrg{ 58635c4bbdfSmrg DeleteCallback(&ClientStateCallback, DamageClientCallback, 0); 58705b261ecSmrg} 58805b261ecSmrg 58905b261ecSmrgstatic int 59035c4bbdfSmrgFreeDamageExt(void *value, XID did) 59105b261ecSmrg{ 59235c4bbdfSmrg DamageExtPtr pDamageExt = (DamageExtPtr) value; 59305b261ecSmrg 59405b261ecSmrg /* 59505b261ecSmrg * Get rid of the resource table entry hanging from the window id 59605b261ecSmrg */ 59705b261ecSmrg pDamageExt->id = 0; 59835c4bbdfSmrg if (pDamageExt->pDamage) { 59935c4bbdfSmrg DamageDestroy(pDamageExt->pDamage); 60005b261ecSmrg } 6016747b715Smrg free(pDamageExt); 60205b261ecSmrg return Success; 60305b261ecSmrg} 60405b261ecSmrg 60535c4bbdfSmrgstatic void 60635c4bbdfSmrgSDamageNotifyEvent(xDamageNotifyEvent * from, xDamageNotifyEvent * to) 60705b261ecSmrg{ 60835c4bbdfSmrg to->type = from->type; 60935c4bbdfSmrg cpswaps(from->sequenceNumber, to->sequenceNumber); 61035c4bbdfSmrg cpswapl(from->drawable, to->drawable); 61135c4bbdfSmrg cpswapl(from->damage, to->damage); 61235c4bbdfSmrg cpswaps(from->area.x, to->area.x); 61335c4bbdfSmrg cpswaps(from->area.y, to->area.y); 61435c4bbdfSmrg cpswaps(from->area.width, to->area.width); 61535c4bbdfSmrg cpswaps(from->area.height, to->area.height); 61635c4bbdfSmrg cpswaps(from->geometry.x, to->geometry.x); 61735c4bbdfSmrg cpswaps(from->geometry.y, to->geometry.y); 61835c4bbdfSmrg cpswaps(from->geometry.width, to->geometry.width); 61935c4bbdfSmrg cpswaps(from->geometry.height, to->geometry.height); 62035c4bbdfSmrg} 62105b261ecSmrg 62235c4bbdfSmrg#ifdef PANORAMIX 62335c4bbdfSmrg 62435c4bbdfSmrgstatic void 62535c4bbdfSmrgPanoramiXDamageReport(DamagePtr pDamage, RegionPtr pRegion, void *closure) 62635c4bbdfSmrg{ 62735c4bbdfSmrg PanoramiXDamageRes *res = closure; 62835c4bbdfSmrg DamageExtPtr pDamageExt = res->ext; 62935c4bbdfSmrg WindowPtr pWin = (WindowPtr)pDamage->pDrawable; 63035c4bbdfSmrg ScreenPtr pScreen = pDamage->pScreen; 63135c4bbdfSmrg 63235c4bbdfSmrg /* happens on unmap? sigh xinerama */ 63335c4bbdfSmrg if (RegionNil(pRegion)) 63435c4bbdfSmrg return; 63535c4bbdfSmrg 63635c4bbdfSmrg /* translate root windows if necessary */ 63735c4bbdfSmrg if (!pWin->parent) 63835c4bbdfSmrg RegionTranslate(pRegion, pScreen->x, pScreen->y); 63935c4bbdfSmrg 64035c4bbdfSmrg /* add our damage to the protocol view */ 64135c4bbdfSmrg DamageReportDamage(pDamageExt->pDamage, pRegion); 64235c4bbdfSmrg 64335c4bbdfSmrg /* empty our view */ 64435c4bbdfSmrg DamageEmpty(pDamage); 64505b261ecSmrg} 64605b261ecSmrg 64705b261ecSmrgstatic void 64835c4bbdfSmrgPanoramiXDamageExtDestroy(DamagePtr pDamage, void *closure) 64905b261ecSmrg{ 65035c4bbdfSmrg PanoramiXDamageRes *damage = closure; 65135c4bbdfSmrg damage->damage[pDamage->pScreen->myNum] = NULL; 65205b261ecSmrg} 65305b261ecSmrg 65435c4bbdfSmrgstatic int 65535c4bbdfSmrgPanoramiXDamageCreate(ClientPtr client) 65635c4bbdfSmrg{ 65735c4bbdfSmrg PanoramiXDamageRes *damage; 65835c4bbdfSmrg PanoramiXRes *draw; 65935c4bbdfSmrg int i, rc; 66035c4bbdfSmrg 66135c4bbdfSmrg REQUEST(xDamageCreateReq); 66235c4bbdfSmrg 66335c4bbdfSmrg REQUEST_SIZE_MATCH(xDamageCreateReq); 66435c4bbdfSmrg LEGAL_NEW_RESOURCE(stuff->damage, client); 66535c4bbdfSmrg rc = dixLookupResourceByClass((void **)&draw, stuff->drawable, XRC_DRAWABLE, 66635c4bbdfSmrg client, DixGetAttrAccess | DixReadAccess); 66735c4bbdfSmrg if (rc != Success) 66835c4bbdfSmrg return rc; 66935c4bbdfSmrg 67035c4bbdfSmrg if (!(damage = calloc(1, sizeof(PanoramiXDamageRes)))) 67135c4bbdfSmrg return BadAlloc; 67235c4bbdfSmrg 67335c4bbdfSmrg if (!AddResource(stuff->damage, XRT_DAMAGE, damage)) 67435c4bbdfSmrg return BadAlloc; 67535c4bbdfSmrg 67635c4bbdfSmrg damage->ext = doDamageCreate(client, &rc); 67735c4bbdfSmrg if (rc == Success && draw->type == XRT_WINDOW) { 67835c4bbdfSmrg FOR_NSCREENS_FORWARD(i) { 67935c4bbdfSmrg DrawablePtr pDrawable; 68035c4bbdfSmrg DamagePtr pDamage = DamageCreate(PanoramiXDamageReport, 68135c4bbdfSmrg PanoramiXDamageExtDestroy, 68235c4bbdfSmrg DamageReportRawRegion, 68335c4bbdfSmrg FALSE, 68435c4bbdfSmrg screenInfo.screens[i], 68535c4bbdfSmrg damage); 68635c4bbdfSmrg if (!pDamage) { 68735c4bbdfSmrg rc = BadAlloc; 68835c4bbdfSmrg } else { 68935c4bbdfSmrg damage->damage[i] = pDamage; 69035c4bbdfSmrg rc = dixLookupDrawable(&pDrawable, draw->info[i].id, client, 69135c4bbdfSmrg M_WINDOW, 69235c4bbdfSmrg DixGetAttrAccess | DixReadAccess); 69335c4bbdfSmrg } 69435c4bbdfSmrg if (rc != Success) 69535c4bbdfSmrg break; 69635c4bbdfSmrg 69735c4bbdfSmrg DamageExtRegister(pDrawable, pDamage, i != 0); 69835c4bbdfSmrg } 69935c4bbdfSmrg } 70035c4bbdfSmrg 70135c4bbdfSmrg if (rc != Success) 70235c4bbdfSmrg FreeResource(stuff->damage, RT_NONE); 70335c4bbdfSmrg 70435c4bbdfSmrg return rc; 70535c4bbdfSmrg} 70635c4bbdfSmrg 70735c4bbdfSmrgstatic int 70835c4bbdfSmrgPanoramiXDamageDelete(void *res, XID id) 70935c4bbdfSmrg{ 71035c4bbdfSmrg int i; 71135c4bbdfSmrg PanoramiXDamageRes *damage = res; 71235c4bbdfSmrg 71335c4bbdfSmrg FOR_NSCREENS_BACKWARD(i) { 71435c4bbdfSmrg if (damage->damage[i]) { 71535c4bbdfSmrg DamageDestroy(damage->damage[i]); 71635c4bbdfSmrg damage->damage[i] = NULL; 71735c4bbdfSmrg } 71835c4bbdfSmrg } 71935c4bbdfSmrg 72035c4bbdfSmrg free(damage); 72135c4bbdfSmrg return 1; 72235c4bbdfSmrg} 72335c4bbdfSmrg 72435c4bbdfSmrgvoid 72535c4bbdfSmrgPanoramiXDamageInit(void) 72635c4bbdfSmrg{ 72735c4bbdfSmrg XRT_DAMAGE = CreateNewResourceType(PanoramiXDamageDelete, "XineramaDamage"); 72835c4bbdfSmrg if (!XRT_DAMAGE) 72935c4bbdfSmrg FatalError("Couldn't Xineramify Damage extension\n"); 73035c4bbdfSmrg 73135c4bbdfSmrg PanoramiXSaveDamageCreate = ProcDamageVector[X_DamageCreate]; 73235c4bbdfSmrg ProcDamageVector[X_DamageCreate] = PanoramiXDamageCreate; 73335c4bbdfSmrg} 73435c4bbdfSmrg 73535c4bbdfSmrgvoid 73635c4bbdfSmrgPanoramiXDamageReset(void) 73735c4bbdfSmrg{ 73835c4bbdfSmrg ProcDamageVector[X_DamageCreate] = PanoramiXSaveDamageCreate; 73935c4bbdfSmrg} 74035c4bbdfSmrg 74135c4bbdfSmrg#endif /* PANORAMIX */ 74235c4bbdfSmrg 74305b261ecSmrgvoid 74405b261ecSmrgDamageExtensionInit(void) 74505b261ecSmrg{ 74605b261ecSmrg ExtensionEntry *extEntry; 74735c4bbdfSmrg int s; 74805b261ecSmrg 74905b261ecSmrg for (s = 0; s < screenInfo.numScreens; s++) 75035c4bbdfSmrg DamageSetup(screenInfo.screens[s]); 75105b261ecSmrg 75235c4bbdfSmrg DamageExtType = CreateNewResourceType(FreeDamageExt, "DamageExt"); 75305b261ecSmrg if (!DamageExtType) 75435c4bbdfSmrg return; 75535c4bbdfSmrg 75635c4bbdfSmrg if (!dixRegisterPrivateKey 75735c4bbdfSmrg (&DamageClientPrivateKeyRec, PRIVATE_CLIENT, sizeof(DamageClientRec))) 75835c4bbdfSmrg return; 75935c4bbdfSmrg 76035c4bbdfSmrg if (!AddCallback(&ClientStateCallback, DamageClientCallback, 0)) 76135c4bbdfSmrg return; 76235c4bbdfSmrg 76335c4bbdfSmrg if ((extEntry = AddExtension(DAMAGE_NAME, XDamageNumberEvents, 76435c4bbdfSmrg XDamageNumberErrors, 76535c4bbdfSmrg ProcDamageDispatch, SProcDamageDispatch, 76635c4bbdfSmrg DamageResetProc, StandardMinorOpcode)) != 0) { 76735c4bbdfSmrg DamageReqCode = (unsigned char) extEntry->base; 76835c4bbdfSmrg DamageEventBase = extEntry->eventBase; 76935c4bbdfSmrg EventSwapVector[DamageEventBase + XDamageNotify] = 77035c4bbdfSmrg (EventSwapPtr) SDamageNotifyEvent; 77135c4bbdfSmrg SetResourceTypeErrorValue(DamageExtType, 77235c4bbdfSmrg extEntry->errorBase + BadDamage); 77335c4bbdfSmrg#ifdef PANORAMIX 77435c4bbdfSmrg if (XRT_DAMAGE) 77535c4bbdfSmrg SetResourceTypeErrorValue(XRT_DAMAGE, 77635c4bbdfSmrg extEntry->errorBase + BadDamage); 77735c4bbdfSmrg#endif 77805b261ecSmrg } 77905b261ecSmrg} 780