Xdamage.c revision 417cc7e8
1af7c02bdSmrg/* 2af7c02bdSmrg * Copyright © 2003 Keith Packard 3af7c02bdSmrg * Copyright © 2007 Eric Anholt 4af7c02bdSmrg * 5af7c02bdSmrg * Permission to use, copy, modify, distribute, and sell this software and its 6af7c02bdSmrg * documentation for any purpose is hereby granted without fee, provided that 7af7c02bdSmrg * the above copyright notice appear in all copies and that both that 8af7c02bdSmrg * copyright notice and this permission notice appear in supporting 9af7c02bdSmrg * documentation, and that the name of Keith Packard not be used in 10af7c02bdSmrg * advertising or publicity pertaining to distribution of the software without 11af7c02bdSmrg * specific, written prior permission. Keith Packard makes no 12af7c02bdSmrg * representations about the suitability of this software for any purpose. It 13af7c02bdSmrg * is provided "as is" without express or implied warranty. 14af7c02bdSmrg * 15af7c02bdSmrg * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 16af7c02bdSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 17af7c02bdSmrg * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR 18af7c02bdSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 19af7c02bdSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 20af7c02bdSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 21af7c02bdSmrg * PERFORMANCE OF THIS SOFTWARE. 22af7c02bdSmrg */ 23af7c02bdSmrg 24af7c02bdSmrg#ifdef HAVE_CONFIG_H 25af7c02bdSmrg#include <config.h> 26af7c02bdSmrg#endif 27af7c02bdSmrg#include "xdamageint.h" 28af7c02bdSmrg 29af7c02bdSmrgXDamageExtInfo XDamageExtensionInfo; 30af7c02bdSmrg 31af7c02bdSmrgconst char XDamageExtensionName[] = DAMAGE_NAME; 32af7c02bdSmrg 33af7c02bdSmrgstatic int 34af7c02bdSmrgXDamageCloseDisplay (Display *dpy, XExtCodes *codes); 35af7c02bdSmrg 36af7c02bdSmrgstatic Bool 37af7c02bdSmrgXDamageWireToEvent(Display *dpy, XEvent *event, xEvent *wire); 38af7c02bdSmrg 39af7c02bdSmrgstatic Status 40af7c02bdSmrgXDamageEventToWire(Display *dpy, XEvent *event, xEvent *wire); 41af7c02bdSmrg 42af7c02bdSmrg/* 43af7c02bdSmrg * XDamageExtAddDisplay - add a display to this extension. (Replaces 44af7c02bdSmrg * XextAddDisplay) 45af7c02bdSmrg */ 46af7c02bdSmrgstatic XDamageExtDisplayInfo * 47af7c02bdSmrgXDamageExtAddDisplay (XDamageExtInfo *extinfo, 48af7c02bdSmrg Display *dpy, 49af7c02bdSmrg const char *ext_name) 50af7c02bdSmrg{ 51af7c02bdSmrg XDamageExtDisplayInfo *info; 52af7c02bdSmrg int ev; 53af7c02bdSmrg 54af7c02bdSmrg info = (XDamageExtDisplayInfo *) Xmalloc (sizeof (XDamageExtDisplayInfo)); 55af7c02bdSmrg if (!info) return NULL; 56af7c02bdSmrg info->display = dpy; 57af7c02bdSmrg 58af7c02bdSmrg info->codes = XInitExtension (dpy, ext_name); 59af7c02bdSmrg 60af7c02bdSmrg /* 61af7c02bdSmrg * if the server has the extension, then we can initialize the 62af7c02bdSmrg * appropriate function vectors 63af7c02bdSmrg */ 64af7c02bdSmrg if (info->codes) { 65af7c02bdSmrg xDamageQueryVersionReply rep; 66af7c02bdSmrg xDamageQueryVersionReq *req; 67af7c02bdSmrg XESetCloseDisplay (dpy, info->codes->extension, 68af7c02bdSmrg XDamageCloseDisplay); 69af7c02bdSmrg for (ev = info->codes->first_event; 70af7c02bdSmrg ev < info->codes->first_event + XDamageNumberEvents; 71af7c02bdSmrg ev++) 72af7c02bdSmrg { 73af7c02bdSmrg XESetWireToEvent (dpy, ev, XDamageWireToEvent); 74af7c02bdSmrg XESetEventToWire (dpy, ev, XDamageEventToWire); 75af7c02bdSmrg } 76af7c02bdSmrg /* 77af7c02bdSmrg * Get the version info 78af7c02bdSmrg */ 79af7c02bdSmrg LockDisplay (dpy); 80af7c02bdSmrg GetReq (DamageQueryVersion, req); 81af7c02bdSmrg req->reqType = info->codes->major_opcode; 82af7c02bdSmrg req->damageReqType = X_DamageQueryVersion; 83af7c02bdSmrg req->majorVersion = DAMAGE_MAJOR; 84af7c02bdSmrg req->minorVersion = DAMAGE_MINOR; 85af7c02bdSmrg if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) 86af7c02bdSmrg { 87af7c02bdSmrg UnlockDisplay (dpy); 88af7c02bdSmrg SyncHandle (); 89af7c02bdSmrg Xfree(info); 9081c81b28Smrg return NULL; 91af7c02bdSmrg } 92af7c02bdSmrg info->major_version = rep.majorVersion; 93af7c02bdSmrg info->minor_version = rep.minorVersion; 94af7c02bdSmrg UnlockDisplay (dpy); 95417cc7e8Smrg SyncHandle (); 96af7c02bdSmrg } else { 97af7c02bdSmrg /* The server doesn't have this extension. 98af7c02bdSmrg * Use a private Xlib-internal extension to hang the close_display 99af7c02bdSmrg * hook on so that the "cache" (extinfo->cur) is properly cleaned. 100af7c02bdSmrg * (XBUG 7955) 101af7c02bdSmrg */ 102af7c02bdSmrg XExtCodes *codes = XAddExtension(dpy); 103af7c02bdSmrg if (!codes) { 104af7c02bdSmrg XFree(info); 105af7c02bdSmrg return NULL; 106af7c02bdSmrg } 107af7c02bdSmrg XESetCloseDisplay (dpy, codes->extension, XDamageCloseDisplay); 108af7c02bdSmrg } 109af7c02bdSmrg 110af7c02bdSmrg /* 111af7c02bdSmrg * now, chain it onto the list 112af7c02bdSmrg */ 113af7c02bdSmrg _XLockMutex(_Xglobal_lock); 114af7c02bdSmrg info->next = extinfo->head; 115af7c02bdSmrg extinfo->head = info; 116af7c02bdSmrg extinfo->cur = info; 117af7c02bdSmrg extinfo->ndisplays++; 118af7c02bdSmrg _XUnlockMutex(_Xglobal_lock); 119af7c02bdSmrg return info; 120af7c02bdSmrg} 121af7c02bdSmrg 122af7c02bdSmrg 123af7c02bdSmrg/* 124af7c02bdSmrg * XDamageExtRemoveDisplay - remove the indicated display from the 125af7c02bdSmrg * extension object. (Replaces XextRemoveDisplay.) 126af7c02bdSmrg */ 127af7c02bdSmrgstatic int 128af7c02bdSmrgXDamageExtRemoveDisplay (XDamageExtInfo *extinfo, Display *dpy) 129af7c02bdSmrg{ 130af7c02bdSmrg XDamageExtDisplayInfo *info, *prev; 131af7c02bdSmrg 132af7c02bdSmrg /* 133af7c02bdSmrg * locate this display and its back link so that it can be removed 134af7c02bdSmrg */ 135af7c02bdSmrg _XLockMutex(_Xglobal_lock); 136af7c02bdSmrg prev = NULL; 137af7c02bdSmrg for (info = extinfo->head; info; info = info->next) { 138af7c02bdSmrg if (info->display == dpy) break; 139af7c02bdSmrg prev = info; 140af7c02bdSmrg } 141af7c02bdSmrg if (!info) { 142af7c02bdSmrg _XUnlockMutex(_Xglobal_lock); 143af7c02bdSmrg return 0; /* hmm, actually an error */ 144af7c02bdSmrg } 145af7c02bdSmrg 146af7c02bdSmrg /* 147af7c02bdSmrg * remove the display from the list; handles going to zero 148af7c02bdSmrg */ 149af7c02bdSmrg if (prev) 150af7c02bdSmrg prev->next = info->next; 151af7c02bdSmrg else 152af7c02bdSmrg extinfo->head = info->next; 153af7c02bdSmrg 154af7c02bdSmrg extinfo->ndisplays--; 155af7c02bdSmrg if (info == extinfo->cur) extinfo->cur = NULL; /* flush cache */ 156af7c02bdSmrg _XUnlockMutex(_Xglobal_lock); 157af7c02bdSmrg 158af7c02bdSmrg Xfree ((char *) info); 159af7c02bdSmrg return 1; 160af7c02bdSmrg} 161af7c02bdSmrg 162af7c02bdSmrg/* 163af7c02bdSmrg * XDamageExtFindDisplay - look for a display in this extension; keeps a 164af7c02bdSmrg * cache of the most-recently used for efficiency. (Replaces 165af7c02bdSmrg * XextFindDisplay.) 166af7c02bdSmrg */ 167af7c02bdSmrgstatic XDamageExtDisplayInfo * 168af7c02bdSmrgXDamageExtFindDisplay (XDamageExtInfo *extinfo, 169af7c02bdSmrg Display *dpy) 170af7c02bdSmrg{ 171af7c02bdSmrg XDamageExtDisplayInfo *info; 172af7c02bdSmrg 173af7c02bdSmrg /* 174af7c02bdSmrg * see if this was the most recently accessed display 175af7c02bdSmrg */ 176af7c02bdSmrg if ((info = extinfo->cur) && info->display == dpy) 177af7c02bdSmrg return info; 178af7c02bdSmrg 179af7c02bdSmrg /* 180af7c02bdSmrg * look for display in list 181af7c02bdSmrg */ 182af7c02bdSmrg _XLockMutex(_Xglobal_lock); 183af7c02bdSmrg for (info = extinfo->head; info; info = info->next) { 184af7c02bdSmrg if (info->display == dpy) { 185af7c02bdSmrg extinfo->cur = info; /* cache most recently used */ 186af7c02bdSmrg _XUnlockMutex(_Xglobal_lock); 187af7c02bdSmrg return info; 188af7c02bdSmrg } 189af7c02bdSmrg } 190af7c02bdSmrg _XUnlockMutex(_Xglobal_lock); 191af7c02bdSmrg 192af7c02bdSmrg return NULL; 193af7c02bdSmrg} 194af7c02bdSmrg 195af7c02bdSmrgXDamageExtDisplayInfo * 196af7c02bdSmrgXDamageFindDisplay (Display *dpy) 197af7c02bdSmrg{ 198af7c02bdSmrg XDamageExtDisplayInfo *info; 199af7c02bdSmrg 200af7c02bdSmrg info = XDamageExtFindDisplay (&XDamageExtensionInfo, dpy); 201af7c02bdSmrg if (!info) 202af7c02bdSmrg info = XDamageExtAddDisplay (&XDamageExtensionInfo, dpy, 203af7c02bdSmrg XDamageExtensionName); 204af7c02bdSmrg return info; 205af7c02bdSmrg} 206af7c02bdSmrg 207af7c02bdSmrgstatic int 208af7c02bdSmrgXDamageCloseDisplay (Display *dpy, XExtCodes *codes) 209af7c02bdSmrg{ 210af7c02bdSmrg return XDamageExtRemoveDisplay (&XDamageExtensionInfo, dpy); 211af7c02bdSmrg} 212af7c02bdSmrg 213af7c02bdSmrgstatic Bool 214af7c02bdSmrgXDamageWireToEvent(Display *dpy, XEvent *event, xEvent *wire) 215af7c02bdSmrg{ 216af7c02bdSmrg XDamageExtDisplayInfo *info = XDamageFindDisplay(dpy); 217af7c02bdSmrg 218af7c02bdSmrg XDamageCheckExtension(dpy, info, False); 219af7c02bdSmrg 220af7c02bdSmrg switch ((wire->u.u.type & 0x7F) - info->codes->first_event) 221af7c02bdSmrg { 222af7c02bdSmrg case XDamageNotify: { 223af7c02bdSmrg XDamageNotifyEvent *aevent = (XDamageNotifyEvent *) event; 224af7c02bdSmrg xDamageNotifyEvent *awire = (xDamageNotifyEvent *) wire; 225af7c02bdSmrg 226af7c02bdSmrg aevent->type = awire->type & 0x7F; 227af7c02bdSmrg aevent->serial = _XSetLastRequestRead(dpy, 228af7c02bdSmrg (xGenericReply *) wire); 229af7c02bdSmrg aevent->send_event = (awire->type & 0x80) != 0; 230af7c02bdSmrg aevent->display = dpy; 231af7c02bdSmrg aevent->drawable = awire->drawable; 232af7c02bdSmrg aevent->damage = awire->damage; 23381c81b28Smrg aevent->level = awire->level & ~DamageNotifyMore; 23481c81b28Smrg aevent->more = (awire->level & DamageNotifyMore) ? True : False; 235af7c02bdSmrg aevent->timestamp = awire->timestamp; 236af7c02bdSmrg aevent->area.x = awire->area.x; 237af7c02bdSmrg aevent->area.y = awire->area.y; 238af7c02bdSmrg aevent->area.width = awire->area.width; 239af7c02bdSmrg aevent->area.height = awire->area.height; 240af7c02bdSmrg aevent->geometry.x = awire->geometry.x; 241af7c02bdSmrg aevent->geometry.y = awire->geometry.y; 242af7c02bdSmrg aevent->geometry.width = awire->geometry.width; 243af7c02bdSmrg aevent->geometry.height = awire->geometry.height; 244af7c02bdSmrg return True; 245af7c02bdSmrg } 246af7c02bdSmrg } 247af7c02bdSmrg return False; 248af7c02bdSmrg} 249af7c02bdSmrg 250af7c02bdSmrgstatic Status 251af7c02bdSmrgXDamageEventToWire(Display *dpy, XEvent *event, xEvent *wire) 252af7c02bdSmrg{ 253af7c02bdSmrg XDamageExtDisplayInfo *info = XDamageFindDisplay(dpy); 254af7c02bdSmrg 255af7c02bdSmrg XDamageCheckExtension(dpy, info, False); 256af7c02bdSmrg 257af7c02bdSmrg switch ((event->type & 0x7F) - info->codes->first_event) 258af7c02bdSmrg { 259af7c02bdSmrg case XDamageNotify: { 260af7c02bdSmrg XDamageNotifyEvent *aevent; 261af7c02bdSmrg xDamageNotifyEvent *awire; 262af7c02bdSmrg awire = (xDamageNotifyEvent *) wire; 263af7c02bdSmrg aevent = (XDamageNotifyEvent *) event; 264af7c02bdSmrg awire->type = aevent->type | (aevent->send_event ? 0x80 : 0); 265af7c02bdSmrg awire->drawable = aevent->drawable; 266af7c02bdSmrg awire->damage = aevent->damage; 26781c81b28Smrg awire->level = aevent->level | (aevent->more ? DamageNotifyMore : 0); 268af7c02bdSmrg awire->timestamp = aevent->timestamp; 269af7c02bdSmrg awire->area.x = aevent->area.x; 270af7c02bdSmrg awire->area.y = aevent->area.y; 271af7c02bdSmrg awire->area.width = aevent->area.width; 272af7c02bdSmrg awire->area.height = aevent->area.height; 273af7c02bdSmrg awire->geometry.x = aevent->geometry.x; 274af7c02bdSmrg awire->geometry.y = aevent->geometry.y; 275af7c02bdSmrg awire->geometry.width = aevent->geometry.width; 276af7c02bdSmrg awire->geometry.height = aevent->geometry.height; 277af7c02bdSmrg return True; 278af7c02bdSmrg } 279af7c02bdSmrg } 280af7c02bdSmrg return False; 281af7c02bdSmrg} 282af7c02bdSmrg 283af7c02bdSmrgBool 28481c81b28SmrgXDamageQueryExtension (Display *dpy, 28581c81b28Smrg int *event_base_return, 28681c81b28Smrg int *error_base_return) 287af7c02bdSmrg{ 288af7c02bdSmrg XDamageExtDisplayInfo *info = XDamageFindDisplay (dpy); 289af7c02bdSmrg 290af7c02bdSmrg if (XDamageHasExtension(info)) 291af7c02bdSmrg { 29281c81b28Smrg *event_base_return = info->codes->first_event; 29381c81b28Smrg *error_base_return = info->codes->first_error; 294af7c02bdSmrg return True; 295af7c02bdSmrg } 296af7c02bdSmrg else 297af7c02bdSmrg return False; 298af7c02bdSmrg} 299af7c02bdSmrg 300af7c02bdSmrgStatus 301af7c02bdSmrgXDamageQueryVersion (Display *dpy, 30281c81b28Smrg int *major_version_return, 30381c81b28Smrg int *minor_version_return) 304af7c02bdSmrg{ 305af7c02bdSmrg XDamageExtDisplayInfo *info = XDamageFindDisplay (dpy); 306af7c02bdSmrg 307af7c02bdSmrg XDamageCheckExtension (dpy, info, 0); 308af7c02bdSmrg 30981c81b28Smrg *major_version_return = info->major_version; 31081c81b28Smrg *minor_version_return = info->minor_version; 311af7c02bdSmrg return 1; 312af7c02bdSmrg} 313af7c02bdSmrg 314af7c02bdSmrgDamage 315af7c02bdSmrgXDamageCreate (Display *dpy, Drawable drawable, int level) 316af7c02bdSmrg{ 317af7c02bdSmrg XDamageExtDisplayInfo *info = XDamageFindDisplay (dpy); 318af7c02bdSmrg xDamageCreateReq *req; 319af7c02bdSmrg Damage damage; 320af7c02bdSmrg 321af7c02bdSmrg XDamageCheckExtension (dpy, info, 0); 322af7c02bdSmrg LockDisplay (dpy); 323af7c02bdSmrg GetReq (DamageCreate, req); 324af7c02bdSmrg req->reqType = info->codes->major_opcode; 325af7c02bdSmrg req->damageReqType = X_DamageCreate; 326af7c02bdSmrg req->damage = damage = XAllocID (dpy); 327af7c02bdSmrg req->drawable = drawable; 328af7c02bdSmrg req->level = level; 329af7c02bdSmrg UnlockDisplay (dpy); 330af7c02bdSmrg SyncHandle (); 331af7c02bdSmrg return damage; 332af7c02bdSmrg} 333af7c02bdSmrg 334af7c02bdSmrgvoid 335af7c02bdSmrgXDamageDestroy (Display *dpy, Damage damage) 336af7c02bdSmrg{ 337af7c02bdSmrg XDamageExtDisplayInfo *info = XDamageFindDisplay (dpy); 338af7c02bdSmrg xDamageDestroyReq *req; 339af7c02bdSmrg 340af7c02bdSmrg XDamageSimpleCheckExtension (dpy, info); 341af7c02bdSmrg LockDisplay (dpy); 342af7c02bdSmrg GetReq (DamageDestroy, req); 343af7c02bdSmrg req->reqType = info->codes->major_opcode; 344af7c02bdSmrg req->damageReqType = X_DamageDestroy; 345af7c02bdSmrg req->damage = damage; 346af7c02bdSmrg UnlockDisplay (dpy); 347af7c02bdSmrg SyncHandle (); 348af7c02bdSmrg} 349af7c02bdSmrg 350af7c02bdSmrgvoid 351af7c02bdSmrgXDamageSubtract (Display *dpy, Damage damage, 352af7c02bdSmrg XserverRegion repair, XserverRegion parts) 353af7c02bdSmrg{ 354af7c02bdSmrg XDamageExtDisplayInfo *info = XDamageFindDisplay (dpy); 355af7c02bdSmrg xDamageSubtractReq *req; 356af7c02bdSmrg 357af7c02bdSmrg XDamageSimpleCheckExtension (dpy, info); 358af7c02bdSmrg LockDisplay (dpy); 359af7c02bdSmrg GetReq (DamageSubtract, req); 360af7c02bdSmrg req->reqType = info->codes->major_opcode; 361af7c02bdSmrg req->damageReqType = X_DamageSubtract; 362af7c02bdSmrg req->damage = damage; 363af7c02bdSmrg req->repair = repair; 364af7c02bdSmrg req->parts = parts; 365af7c02bdSmrg UnlockDisplay (dpy); 366af7c02bdSmrg SyncHandle (); 367af7c02bdSmrg} 368af7c02bdSmrg 369af7c02bdSmrgvoid 370af7c02bdSmrgXDamageAdd (Display *dpy, Drawable drawable, XserverRegion region) 371af7c02bdSmrg{ 372af7c02bdSmrg XDamageExtDisplayInfo *info = XDamageFindDisplay (dpy); 373af7c02bdSmrg xDamageAddReq *req; 374af7c02bdSmrg 375af7c02bdSmrg XDamageSimpleCheckExtension (dpy, info); 376af7c02bdSmrg LockDisplay (dpy); 377af7c02bdSmrg GetReq (DamageAdd, req); 378af7c02bdSmrg req->reqType = info->codes->major_opcode; 379af7c02bdSmrg req->damageReqType = X_DamageAdd; 380af7c02bdSmrg req->drawable = drawable; 381af7c02bdSmrg req->region = region; 382af7c02bdSmrg 383af7c02bdSmrg UnlockDisplay (dpy); 384af7c02bdSmrg SyncHandle (); 385af7c02bdSmrg} 386