os/log: trivial cleanups
[xserver/hramrach.git] / damageext / damageext.c
blobf21f71ca81ecfe64bb5affcbb3a1d1404bc5531d
1 /*
2 * Copyright © 2002 Keith Packard
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of Keith Packard not be used in
9 * advertising or publicity pertaining to distribution of the software without
10 * specific, written prior permission. Keith Packard makes no
11 * representations about the suitability of this software for any purpose. It
12 * is provided "as is" without express or implied warranty.
14 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20 * PERFORMANCE OF THIS SOFTWARE.
23 #ifdef HAVE_DIX_CONFIG_H
24 #include <dix-config.h>
25 #endif
27 #include "damageextint.h"
28 #include "protocol-versions.h"
30 static unsigned char DamageReqCode;
31 static int DamageEventBase;
32 static RESTYPE DamageExtType;
33 static RESTYPE DamageExtWinType;
35 static DevPrivateKeyRec DamageClientPrivateKeyRec;
37 #define DamageClientPrivateKey (&DamageClientPrivateKeyRec)
39 static void
40 DamageExtNotify(DamageExtPtr pDamageExt, BoxPtr pBoxes, int nBoxes)
42 ClientPtr pClient = pDamageExt->pClient;
43 DamageClientPtr pDamageClient = GetDamageClient(pClient);
44 DrawablePtr pDrawable = pDamageExt->pDrawable;
45 xDamageNotifyEvent ev;
46 int i;
48 UpdateCurrentTimeIf();
49 ev.type = DamageEventBase + XDamageNotify;
50 ev.level = pDamageExt->level;
51 ev.drawable = pDamageExt->drawable;
52 ev.damage = pDamageExt->id;
53 ev.timestamp = currentTime.milliseconds;
54 ev.geometry.x = pDrawable->x;
55 ev.geometry.y = pDrawable->y;
56 ev.geometry.width = pDrawable->width;
57 ev.geometry.height = pDrawable->height;
58 if (pBoxes) {
59 for (i = 0; i < nBoxes; i++) {
60 ev.level = pDamageExt->level;
61 if (i < nBoxes - 1)
62 ev.level |= DamageNotifyMore;
63 ev.area.x = pBoxes[i].x1;
64 ev.area.y = pBoxes[i].y1;
65 ev.area.width = pBoxes[i].x2 - pBoxes[i].x1;
66 ev.area.height = pBoxes[i].y2 - pBoxes[i].y1;
67 WriteEventsToClient(pClient, 1, (xEvent *) &ev);
70 else {
71 ev.area.x = 0;
72 ev.area.y = 0;
73 ev.area.width = pDrawable->width;
74 ev.area.height = pDrawable->height;
75 WriteEventsToClient(pClient, 1, (xEvent *) &ev);
77 /* Composite extension marks clients with manual Subwindows as critical */
78 if (pDamageClient->critical > 0) {
79 SetCriticalOutputPending();
80 pClient->smart_priority = SMART_MAX_PRIORITY;
84 static void
85 DamageExtReport(DamagePtr pDamage, RegionPtr pRegion, void *closure)
87 DamageExtPtr pDamageExt = closure;
89 switch (pDamageExt->level) {
90 case DamageReportRawRegion:
91 case DamageReportDeltaRegion:
92 DamageExtNotify(pDamageExt, RegionRects(pRegion),
93 RegionNumRects(pRegion));
94 break;
95 case DamageReportBoundingBox:
96 DamageExtNotify(pDamageExt, RegionExtents(pRegion), 1);
97 break;
98 case DamageReportNonEmpty:
99 DamageExtNotify(pDamageExt, NullBox, 0);
100 break;
101 case DamageReportNone:
102 break;
106 static void
107 DamageExtDestroy(DamagePtr pDamage, void *closure)
109 DamageExtPtr pDamageExt = closure;
111 pDamageExt->pDamage = 0;
112 if (pDamageExt->id)
113 FreeResource(pDamageExt->id, RT_NONE);
116 void
117 DamageExtSetCritical(ClientPtr pClient, Bool critical)
119 DamageClientPtr pDamageClient = GetDamageClient(pClient);
121 if (pDamageClient)
122 pDamageClient->critical += critical ? 1 : -1;
125 static int
126 ProcDamageQueryVersion(ClientPtr client)
128 DamageClientPtr pDamageClient = GetDamageClient(client);
129 xDamageQueryVersionReply rep;
131 REQUEST(xDamageQueryVersionReq);
133 REQUEST_SIZE_MATCH(xDamageQueryVersionReq);
134 rep.type = X_Reply;
135 rep.length = 0;
136 rep.sequenceNumber = client->sequence;
137 if (stuff->majorVersion < SERVER_DAMAGE_MAJOR_VERSION) {
138 rep.majorVersion = stuff->majorVersion;
139 rep.minorVersion = stuff->minorVersion;
141 else {
142 rep.majorVersion = SERVER_DAMAGE_MAJOR_VERSION;
143 if (stuff->majorVersion == SERVER_DAMAGE_MAJOR_VERSION &&
144 stuff->minorVersion < SERVER_DAMAGE_MINOR_VERSION)
145 rep.minorVersion = stuff->minorVersion;
146 else
147 rep.minorVersion = SERVER_DAMAGE_MINOR_VERSION;
149 pDamageClient->major_version = rep.majorVersion;
150 pDamageClient->minor_version = rep.minorVersion;
151 if (client->swapped) {
152 swaps(&rep.sequenceNumber);
153 swapl(&rep.length);
154 swapl(&rep.majorVersion);
155 swapl(&rep.minorVersion);
157 WriteToClient(client, sizeof(xDamageQueryVersionReply), (char *) &rep);
158 return Success;
161 static int
162 ProcDamageCreate(ClientPtr client)
164 DrawablePtr pDrawable;
165 DamageExtPtr pDamageExt;
166 DamageReportLevel level;
167 RegionPtr pRegion;
168 int rc;
170 REQUEST(xDamageCreateReq);
172 REQUEST_SIZE_MATCH(xDamageCreateReq);
173 LEGAL_NEW_RESOURCE(stuff->damage, client);
174 rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0,
175 DixGetAttrAccess | DixReadAccess);
176 if (rc != Success)
177 return rc;
179 switch (stuff->level) {
180 case XDamageReportRawRectangles:
181 level = DamageReportRawRegion;
182 break;
183 case XDamageReportDeltaRectangles:
184 level = DamageReportDeltaRegion;
185 break;
186 case XDamageReportBoundingBox:
187 level = DamageReportBoundingBox;
188 break;
189 case XDamageReportNonEmpty:
190 level = DamageReportNonEmpty;
191 break;
192 default:
193 client->errorValue = stuff->level;
194 return BadValue;
197 pDamageExt = malloc(sizeof(DamageExtRec));
198 if (!pDamageExt)
199 return BadAlloc;
200 pDamageExt->id = stuff->damage;
201 pDamageExt->drawable = stuff->drawable;
202 pDamageExt->pDrawable = pDrawable;
203 pDamageExt->level = level;
204 pDamageExt->pClient = client;
205 pDamageExt->pDamage = DamageCreate(DamageExtReport,
206 DamageExtDestroy,
207 level,
208 FALSE, pDrawable->pScreen, pDamageExt);
209 if (!pDamageExt->pDamage) {
210 free(pDamageExt);
211 return BadAlloc;
213 if (!AddResource(stuff->damage, DamageExtType, (pointer) pDamageExt))
214 return BadAlloc;
216 DamageSetReportAfterOp(pDamageExt->pDamage, TRUE);
217 DamageRegister(pDamageExt->pDrawable, pDamageExt->pDamage);
219 if (pDrawable->type == DRAWABLE_WINDOW) {
220 pRegion = &((WindowPtr) pDrawable)->borderClip;
221 DamageReportDamage(pDamageExt->pDamage, pRegion);
224 return Success;
227 static int
228 ProcDamageDestroy(ClientPtr client)
230 REQUEST(xDamageDestroyReq);
231 DamageExtPtr pDamageExt;
233 REQUEST_SIZE_MATCH(xDamageDestroyReq);
234 VERIFY_DAMAGEEXT(pDamageExt, stuff->damage, client, DixWriteAccess);
235 FreeResource(stuff->damage, RT_NONE);
236 return Success;
239 static int
240 ProcDamageSubtract(ClientPtr client)
242 REQUEST(xDamageSubtractReq);
243 DamageExtPtr pDamageExt;
244 RegionPtr pRepair;
245 RegionPtr pParts;
247 REQUEST_SIZE_MATCH(xDamageSubtractReq);
248 VERIFY_DAMAGEEXT(pDamageExt, stuff->damage, client, DixWriteAccess);
249 VERIFY_REGION_OR_NONE(pRepair, stuff->repair, client, DixWriteAccess);
250 VERIFY_REGION_OR_NONE(pParts, stuff->parts, client, DixWriteAccess);
252 if (pDamageExt->level != DamageReportRawRegion) {
253 DamagePtr pDamage = pDamageExt->pDamage;
255 if (pRepair) {
256 if (pParts)
257 RegionIntersect(pParts, DamageRegion(pDamage), pRepair);
258 if (DamageSubtract(pDamage, pRepair))
259 DamageExtReport(pDamage, DamageRegion(pDamage),
260 (void *) pDamageExt);
262 else {
263 if (pParts)
264 RegionCopy(pParts, DamageRegion(pDamage));
265 DamageEmpty(pDamage);
268 return Success;
271 static int
272 ProcDamageAdd(ClientPtr client)
274 REQUEST(xDamageAddReq);
275 DrawablePtr pDrawable;
276 RegionPtr pRegion;
277 int rc;
279 REQUEST_SIZE_MATCH(xDamageAddReq);
280 VERIFY_REGION(pRegion, stuff->region, client, DixWriteAccess);
281 rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0,
282 DixWriteAccess);
283 if (rc != Success)
284 return rc;
286 /* The region is relative to the drawable origin, so translate it out to
287 * screen coordinates like damage expects.
289 RegionTranslate(pRegion, pDrawable->x, pDrawable->y);
290 DamageDamageRegion(pDrawable, pRegion);
291 RegionTranslate(pRegion, -pDrawable->x, -pDrawable->y);
293 return Success;
296 /* Major version controls available requests */
297 static const int version_requests[] = {
298 X_DamageQueryVersion, /* before client sends QueryVersion */
299 X_DamageAdd, /* Version 1 */
302 #define NUM_VERSION_REQUESTS (sizeof (version_requests) / sizeof (version_requests[0]))
304 static int (*ProcDamageVector[XDamageNumberRequests]) (ClientPtr) = {
305 /*************** Version 1 ******************/
306 ProcDamageQueryVersion,
307 ProcDamageCreate, ProcDamageDestroy, ProcDamageSubtract,
308 /*************** Version 1.1 ****************/
309 ProcDamageAdd,};
311 static int
312 ProcDamageDispatch(ClientPtr client)
314 REQUEST(xDamageReq);
315 DamageClientPtr pDamageClient = GetDamageClient(client);
317 if (pDamageClient->major_version >= NUM_VERSION_REQUESTS)
318 return BadRequest;
319 if (stuff->damageReqType > version_requests[pDamageClient->major_version])
320 return BadRequest;
321 return (*ProcDamageVector[stuff->damageReqType]) (client);
324 static int
325 SProcDamageQueryVersion(ClientPtr client)
327 REQUEST(xDamageQueryVersionReq);
329 swaps(&stuff->length);
330 REQUEST_SIZE_MATCH(xDamageQueryVersionReq);
331 swapl(&stuff->majorVersion);
332 swapl(&stuff->minorVersion);
333 return (*ProcDamageVector[stuff->damageReqType]) (client);
336 static int
337 SProcDamageCreate(ClientPtr client)
339 REQUEST(xDamageCreateReq);
341 swaps(&stuff->length);
342 REQUEST_SIZE_MATCH(xDamageCreateReq);
343 swapl(&stuff->damage);
344 swapl(&stuff->drawable);
345 return (*ProcDamageVector[stuff->damageReqType]) (client);
348 static int
349 SProcDamageDestroy(ClientPtr client)
351 REQUEST(xDamageDestroyReq);
353 swaps(&stuff->length);
354 REQUEST_SIZE_MATCH(xDamageDestroyReq);
355 swapl(&stuff->damage);
356 return (*ProcDamageVector[stuff->damageReqType]) (client);
359 static int
360 SProcDamageSubtract(ClientPtr client)
362 REQUEST(xDamageSubtractReq);
364 swaps(&stuff->length);
365 REQUEST_SIZE_MATCH(xDamageSubtractReq);
366 swapl(&stuff->damage);
367 swapl(&stuff->repair);
368 swapl(&stuff->parts);
369 return (*ProcDamageVector[stuff->damageReqType]) (client);
372 static int
373 SProcDamageAdd(ClientPtr client)
375 REQUEST(xDamageAddReq);
377 swaps(&stuff->length);
378 REQUEST_SIZE_MATCH(xDamageSubtractReq);
379 swapl(&stuff->drawable);
380 swapl(&stuff->region);
381 return (*ProcDamageVector[stuff->damageReqType]) (client);
384 static int (*SProcDamageVector[XDamageNumberRequests]) (ClientPtr) = {
385 /*************** Version 1 ******************/
386 SProcDamageQueryVersion,
387 SProcDamageCreate, SProcDamageDestroy, SProcDamageSubtract,
388 /*************** Version 1.1 ****************/
389 SProcDamageAdd,};
391 static int
392 SProcDamageDispatch(ClientPtr client)
394 REQUEST(xDamageReq);
395 if (stuff->damageReqType >= XDamageNumberRequests)
396 return BadRequest;
397 return (*SProcDamageVector[stuff->damageReqType]) (client);
400 static void
401 DamageClientCallback(CallbackListPtr *list, pointer closure, pointer data)
403 NewClientInfoRec *clientinfo = (NewClientInfoRec *) data;
404 ClientPtr pClient = clientinfo->client;
405 DamageClientPtr pDamageClient = GetDamageClient(pClient);
407 pDamageClient->critical = 0;
408 pDamageClient->major_version = 0;
409 pDamageClient->minor_version = 0;
412 /*ARGSUSED*/ static void
413 DamageResetProc(ExtensionEntry * extEntry)
415 DeleteCallback(&ClientStateCallback, DamageClientCallback, 0);
418 static int
419 FreeDamageExt(pointer value, XID did)
421 DamageExtPtr pDamageExt = (DamageExtPtr) value;
424 * Get rid of the resource table entry hanging from the window id
426 pDamageExt->id = 0;
427 if (WindowDrawable(pDamageExt->pDrawable->type))
428 FreeResourceByType(pDamageExt->pDrawable->id, DamageExtWinType, TRUE);
429 if (pDamageExt->pDamage) {
430 DamageUnregister(pDamageExt->pDrawable, pDamageExt->pDamage);
431 DamageDestroy(pDamageExt->pDamage);
433 free(pDamageExt);
434 return Success;
437 static int
438 FreeDamageExtWin(pointer value, XID wid)
440 DamageExtPtr pDamageExt = (DamageExtPtr) value;
442 if (pDamageExt->id)
443 FreeResource(pDamageExt->id, RT_NONE);
444 return Success;
447 static void
448 SDamageNotifyEvent(xDamageNotifyEvent * from, xDamageNotifyEvent * to)
450 to->type = from->type;
451 cpswaps(from->sequenceNumber, to->sequenceNumber);
452 cpswapl(from->drawable, to->drawable);
453 cpswapl(from->damage, to->damage);
454 cpswaps(from->area.x, to->area.x);
455 cpswaps(from->area.y, to->area.y);
456 cpswaps(from->area.width, to->area.width);
457 cpswaps(from->area.height, to->area.height);
458 cpswaps(from->geometry.x, to->geometry.x);
459 cpswaps(from->geometry.y, to->geometry.y);
460 cpswaps(from->geometry.width, to->geometry.width);
461 cpswaps(from->geometry.height, to->geometry.height);
464 void
465 DamageExtensionInit(void)
467 ExtensionEntry *extEntry;
468 int s;
470 for (s = 0; s < screenInfo.numScreens; s++)
471 DamageSetup(screenInfo.screens[s]);
473 DamageExtType = CreateNewResourceType(FreeDamageExt, "DamageExt");
474 if (!DamageExtType)
475 return;
477 DamageExtWinType = CreateNewResourceType(FreeDamageExtWin, "DamageExtWin");
478 if (!DamageExtWinType)
479 return;
481 if (!dixRegisterPrivateKey
482 (&DamageClientPrivateKeyRec, PRIVATE_CLIENT, sizeof(DamageClientRec)))
483 return;
485 if (!AddCallback(&ClientStateCallback, DamageClientCallback, 0))
486 return;
488 if ((extEntry = AddExtension(DAMAGE_NAME, XDamageNumberEvents,
489 XDamageNumberErrors,
490 ProcDamageDispatch, SProcDamageDispatch,
491 DamageResetProc, StandardMinorOpcode)) != 0) {
492 DamageReqCode = (unsigned char) extEntry->base;
493 DamageEventBase = extEntry->eventBase;
494 EventSwapVector[DamageEventBase + XDamageNotify] =
495 (EventSwapPtr) SDamageNotifyEvent;
496 SetResourceTypeErrorValue(DamageExtType,
497 extEntry->errorBase + BadDamage);