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