123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516 |
- /*
- * Copyright © 2002 Keith Packard
- *
- * 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 "extinit.h"
- unsigned char DamageReqCode;
- int DamageEventBase;
- int DamageErrorBase;
- int DamageClientPrivateIndex;
- RESTYPE DamageExtType;
- RESTYPE DamageExtWinType;
- /* Version of the damage extension supported by the server, as opposed to the
- * DAMAGE_* defines from damageproto for what version the proto header
- * supports.
- */
- #define SERVER_DAMAGE_MAJOR 1
- #define SERVER_DAMAGE_MINOR 1
- #define prScreen screenInfo.screens[0]
- static void
- DamageExtNotify(DamageExtPtr pDamageExt, BoxPtr pBoxes, int nBoxes)
- {
- ClientPtr pClient = pDamageExt->pClient;
- DamageClientPtr pDamageClient = GetDamageClient(pClient);
- DrawablePtr pDrawable = pDamageExt->pDrawable;
- xDamageNotifyEvent ev;
- int i;
- UpdateCurrentTimeIf();
- ev = (xDamageNotifyEvent) {
- .type = DamageEventBase + XDamageNotify,
- .level = pDamageExt->level,
- .drawable = pDamageExt->drawable,
- .damage = pDamageExt->id,
- .timestamp = currentTime.milliseconds,
- .geometry.x = pDrawable->x,
- .geometry.y = pDrawable->y,
- .geometry.width = pDrawable->width,
- .geometry.height = pDrawable->height
- };
- 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 = pDrawable->width;
- ev.area.height = pDrawable->height;
- WriteEventsToClient(pClient, 1, (xEvent *) &ev);
- }
- /* Composite extension marks clients with manual Subwindows as critical */
- if (pDamageClient->critical > 0) {
- SetCriticalOutputPending();
- pClient->smart_priority = SMART_MAX_PRIORITY;
- }
- }
- static void
- DamageExtReport(DamagePtr pDamage, RegionPtr pRegion, void *closure)
- {
- DamageExtPtr pDamageExt = closure;
- switch (pDamageExt->level) {
- case DamageReportRawRegion:
- case DamageReportDeltaRegion:
- DamageExtNotify(pDamageExt, REGION_RECTS(pRegion),
- REGION_NUM_RECTS(pRegion));
- break;
- case DamageReportBoundingBox:
- DamageExtNotify(pDamageExt, REGION_EXTENTS(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;
- REQUEST(xDamageQueryVersionReq);
- REQUEST_SIZE_MATCH(xDamageQueryVersionReq);
- rep.type = X_Reply;
- rep.length = 0;
- rep.sequenceNumber = client->sequence;
- if (stuff->majorVersion < SERVER_DAMAGE_MAJOR) {
- rep.majorVersion = stuff->majorVersion;
- rep.minorVersion = stuff->minorVersion;
- }
- else {
- rep.majorVersion = SERVER_DAMAGE_MAJOR;
- if (stuff->majorVersion == SERVER_DAMAGE_MAJOR &&
- stuff->minorVersion < SERVER_DAMAGE_MINOR)
- rep.minorVersion = stuff->minorVersion;
- else
- rep.minorVersion = SERVER_DAMAGE_MINOR;
- }
- 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), (char *) &rep);
- return (client->noClientException);
- }
- static int
- ProcDamageCreate(ClientPtr client)
- {
- DrawablePtr pDrawable;
- DamageExtPtr pDamageExt;
- DamageReportLevel level;
- RegionPtr pRegion;
- REQUEST(xDamageCreateReq);
- REQUEST_SIZE_MATCH(xDamageCreateReq);
- LEGAL_NEW_RESOURCE(stuff->damage, client);
- SECURITY_VERIFY_DRAWABLE(pDrawable, stuff->drawable, client,
- SecurityReadAccess);
- 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;
- return BadValue;
- }
- pDamageExt = malloc(sizeof(DamageExtRec));
- if (!pDamageExt)
- return BadAlloc;
- pDamageExt->id = stuff->damage;
- 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 BadAlloc;
- }
- if (!AddResource(stuff->damage, DamageExtType, (pointer) pDamageExt))
- return BadAlloc;
- DamageRegister(pDamageExt->pDrawable, pDamageExt->pDamage);
- if (pDrawable->type == DRAWABLE_WINDOW) {
- pRegion = &((WindowPtr) pDrawable)->borderClip;
- DamageDamageRegion(pDrawable, pRegion);
- }
- return (client->noClientException);
- }
- static int
- ProcDamageDestroy(ClientPtr client)
- {
- REQUEST(xDamageDestroyReq);
- DamageExtPtr pDamageExt;
- REQUEST_SIZE_MATCH(xDamageDestroyReq);
- VERIFY_DAMAGEEXT(pDamageExt, stuff->damage, client, SecurityWriteAccess);
- FreeResource(stuff->damage, RT_NONE);
- return (client->noClientException);
- }
- static int
- ProcDamageSubtract(ClientPtr client)
- {
- REQUEST(xDamageSubtractReq);
- DamageExtPtr pDamageExt;
- RegionPtr pRepair;
- RegionPtr pParts;
- REQUEST_SIZE_MATCH(xDamageSubtractReq);
- VERIFY_DAMAGEEXT(pDamageExt, stuff->damage, client, SecurityWriteAccess);
- VERIFY_REGION_OR_NONE(pRepair, stuff->repair, client, SecurityWriteAccess);
- VERIFY_REGION_OR_NONE(pParts, stuff->parts, client, SecurityWriteAccess);
- if (pDamageExt->level != DamageReportRawRegion) {
- DamagePtr pDamage = pDamageExt->pDamage;
- if (pRepair) {
- if (pParts)
- REGION_INTERSECT(pParts, DamageRegion(pDamage),
- pRepair);
- if (DamageSubtract(pDamage, pRepair))
- DamageExtReport(pDamage, DamageRegion(pDamage),
- (void *) pDamageExt);
- }
- else {
- if (pParts)
- REGION_COPY(pParts, DamageRegion(pDamage));
- DamageEmpty(pDamage);
- }
- }
- return (client->noClientException);
- }
- static int
- ProcDamageAdd(ClientPtr client)
- {
- REQUEST(xDamageAddReq);
- DrawablePtr pDrawable;
- RegionPtr pRegion;
- REQUEST_SIZE_MATCH(xDamageAddReq);
- VERIFY_REGION(pRegion, stuff->region, client, SecurityWriteAccess);
- SECURITY_VERIFY_DRAWABLE(pDrawable, stuff->drawable, client,
- SecurityReadAccess);
- /* The region is relative to the drawable origin, so translate it out to
- * screen coordinates like damage expects.
- */
- REGION_TRANSLATE(pRegion, pDrawable->x, pDrawable->y);
- DamageDamageRegion(pDrawable, pRegion);
- REGION_TRANSLATE(pRegion, -pDrawable->x, -pDrawable->y);
- return (client->noClientException);
- }
- /* Major version controls available requests */
- static const int version_requests[] = {
- X_DamageQueryVersion, /* before client sends QueryVersion */
- X_DamageAdd, /* Version 1 */
- };
- #define NUM_VERSION_REQUESTS (sizeof (version_requests) / sizeof (version_requests[0]))
- 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 >= NUM_VERSION_REQUESTS)
- return BadRequest;
- if (stuff->damageReqType > version_requests[pDamageClient->major_version])
- return BadRequest;
- return (*ProcDamageVector[stuff->damageReqType]) (client);
- }
- static int
- 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
- 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
- SProcDamageDestroy(ClientPtr client)
- {
- REQUEST(xDamageDestroyReq);
- swaps(&stuff->length);
- REQUEST_SIZE_MATCH(xDamageDestroyReq);
- swapl(&stuff->damage);
- return (*ProcDamageVector[stuff->damageReqType]) (client);
- }
- static int
- 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
- SProcDamageAdd(ClientPtr client)
- {
- REQUEST(xDamageAddReq);
- swaps(&stuff->length);
- REQUEST_SIZE_MATCH(xDamageSubtractReq);
- swapl(&stuff->drawable);
- swapl(&stuff->region);
- return (*ProcDamageVector[stuff->damageReqType]) (client);
- }
- int (*SProcDamageVector[XDamageNumberRequests]) (ClientPtr) = {
- /*************** Version 1 ******************/
- SProcDamageQueryVersion,
- SProcDamageCreate, SProcDamageDestroy, SProcDamageSubtract,
- /*************** Version 1.1 ****************/
- SProcDamageAdd,};
- static int
- SProcDamageDispatch(ClientPtr client)
- {
- REQUEST(xDamageReq);
- if (stuff->damageReqType >= XDamageNumberRequests)
- return BadRequest;
- return (*SProcDamageVector[stuff->damageReqType]) (client);
- }
- static void
- DamageClientCallback(CallbackListPtr *list, pointer closure, pointer data)
- {
- NewClientInfoRec *clientinfo = (NewClientInfoRec *) data;
- ClientPtr pClient = clientinfo->client;
- DamageClientPtr pDamageClient = GetDamageClient(pClient);
- pDamageClient->critical = 0;
- pDamageClient->major_version = 0;
- pDamageClient->minor_version = 0;
- }
- /*ARGSUSED*/ static void
- DamageResetProc(ExtensionEntry * extEntry)
- {
- DeleteCallback(&ClientStateCallback, DamageClientCallback, 0);
- }
- static int
- FreeDamageExt(pointer value, XID did)
- {
- DamageExtPtr pDamageExt = (DamageExtPtr) value;
- /*
- * Get rid of the resource table entry hanging from the window id
- */
- pDamageExt->id = 0;
- if (WindowDrawable(pDamageExt->pDrawable->type))
- FreeResourceByType(pDamageExt->pDrawable->id, DamageExtWinType, TRUE);
- if (pDamageExt->pDamage) {
- DamageUnregister(pDamageExt->pDrawable, pDamageExt->pDamage);
- DamageDestroy(pDamageExt->pDamage);
- }
- free(pDamageExt);
- return Success;
- }
- static int
- FreeDamageExtWin(pointer value, XID wid)
- {
- DamageExtPtr pDamageExt = (DamageExtPtr) value;
- if (pDamageExt->id)
- FreeResource(pDamageExt->id, RT_NONE);
- return Success;
- }
- void
- 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);
- }
- void
- DamageExtensionInit(void)
- {
- ExtensionEntry *extEntry;
- int s;
- for (s = 0; s < screenInfo.numScreens; s++)
- DamageSetup(screenInfo.screens[s]);
- DamageExtType = CreateNewResourceType(FreeDamageExt);
- if (!DamageExtType)
- return;
- DamageExtWinType = CreateNewResourceType(FreeDamageExtWin);
- if (!DamageExtWinType)
- return;
- DamageClientPrivateIndex = AllocateClientPrivateIndex();
- if (!AllocateClientPrivate(DamageClientPrivateIndex,
- sizeof(DamageClientRec)))
- return;
- if (!AddCallback(&ClientStateCallback, DamageClientCallback, 0))
- return;
- if ((extEntry = AddExtension(DAMAGE_NAME, XDamageNumberEvents,
- XDamageNumberErrors,
- ProcDamageDispatch, SProcDamageDispatch,
- DamageResetProc, StandardMinorOpcode)) != 0) {
- DamageReqCode = (unsigned char) extEntry->base;
- DamageEventBase = extEntry->eventBase;
- DamageErrorBase = extEntry->errorBase;
- EventSwapVector[DamageEventBase + XDamageNotify] =
- (EventSwapPtr) SDamageNotifyEvent;
- }
- }
|