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" 286c9573adSmrg#include <X11/Xfuncproto.h> 29af7c02bdSmrg 30af7c02bdSmrgXDamageExtInfo XDamageExtensionInfo; 31af7c02bdSmrg 32af7c02bdSmrgconst char XDamageExtensionName[] = DAMAGE_NAME; 33af7c02bdSmrg 34af7c02bdSmrgstatic int 35af7c02bdSmrgXDamageCloseDisplay (Display *dpy, XExtCodes *codes); 366dda92f9Smrg 37af7c02bdSmrgstatic Bool 38af7c02bdSmrgXDamageWireToEvent(Display *dpy, XEvent *event, xEvent *wire); 39af7c02bdSmrg 40af7c02bdSmrgstatic Status 41af7c02bdSmrgXDamageEventToWire(Display *dpy, XEvent *event, xEvent *wire); 42af7c02bdSmrg 43af7c02bdSmrg/* 44af7c02bdSmrg * XDamageExtAddDisplay - add a display to this extension. (Replaces 45af7c02bdSmrg * XextAddDisplay) 46af7c02bdSmrg */ 47af7c02bdSmrgstatic XDamageExtDisplayInfo * 48af7c02bdSmrgXDamageExtAddDisplay (XDamageExtInfo *extinfo, 49af7c02bdSmrg Display *dpy, 50af7c02bdSmrg const char *ext_name) 51af7c02bdSmrg{ 52af7c02bdSmrg XDamageExtDisplayInfo *info; 53af7c02bdSmrg 546c9573adSmrg info = Xmalloc (sizeof (XDamageExtDisplayInfo)); 55af7c02bdSmrg if (!info) return NULL; 56af7c02bdSmrg info->display = dpy; 57af7c02bdSmrg 58af7c02bdSmrg info->codes = XInitExtension (dpy, ext_name); 59af7c02bdSmrg 60af7c02bdSmrg /* 616dda92f9Smrg * 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; 676dda92f9Smrg XESetCloseDisplay (dpy, info->codes->extension, 68af7c02bdSmrg XDamageCloseDisplay); 696c9573adSmrg for (int 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); 816c9573adSmrg req->reqType = (CARD8) info->codes->major_opcode; 82af7c02bdSmrg req->damageReqType = X_DamageQueryVersion; 83af7c02bdSmrg req->majorVersion = DAMAGE_MAJOR; 84af7c02bdSmrg req->minorVersion = DAMAGE_MINOR; 856dda92f9Smrg 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) { 1046c9573adSmrg 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 */ 1276dda92f9Smrgstatic int 1286c9573adSmrgXDamageExtRemoveDisplay (XDamageExtInfo *extinfo, const 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 1586c9573adSmrg Xfree (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 * 1686dda92f9SmrgXDamageExtFindDisplay (XDamageExtInfo *extinfo, 1696c9573adSmrg const Display *dpy) 170af7c02bdSmrg{ 171af7c02bdSmrg XDamageExtDisplayInfo *info; 172af7c02bdSmrg 173af7c02bdSmrg /* 174af7c02bdSmrg * see if this was the most recently accessed display 175af7c02bdSmrg */ 1766dda92f9Smrg 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) 2026dda92f9Smrg info = XDamageExtAddDisplay (&XDamageExtensionInfo, dpy, 203af7c02bdSmrg XDamageExtensionName); 204af7c02bdSmrg return info; 205af7c02bdSmrg} 2066dda92f9Smrg 207af7c02bdSmrgstatic int 2086c9573adSmrgXDamageCloseDisplay (Display *dpy, _X_UNUSED 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; 2646c9573adSmrg awire->type = (CARD8) aevent->type | (aevent->send_event ? 0x80 : 0); 2656c9573adSmrg awire->drawable = (CARD32) aevent->drawable; 2666c9573adSmrg awire->damage = (CARD32) aevent->damage; 2676c9573adSmrg awire->level = (CARD8) aevent->level | (aevent->more ? DamageNotifyMore : 0); 2686c9573adSmrg awire->timestamp = (CARD32) 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 2836dda92f9SmrgBool 28481c81b28SmrgXDamageQueryExtension (Display *dpy, 28581c81b28Smrg int *event_base_return, 28681c81b28Smrg int *error_base_return) 287af7c02bdSmrg{ 288af7c02bdSmrg XDamageExtDisplayInfo *info = XDamageFindDisplay (dpy); 289af7c02bdSmrg 2906dda92f9Smrg if (XDamageHasExtension(info)) 291af7c02bdSmrg { 29281c81b28Smrg *event_base_return = info->codes->first_event; 29381c81b28Smrg *error_base_return = info->codes->first_error; 294af7c02bdSmrg return True; 2956dda92f9Smrg } 296af7c02bdSmrg else 297af7c02bdSmrg return False; 298af7c02bdSmrg} 299af7c02bdSmrg 3006dda92f9SmrgStatus 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); 3246c9573adSmrg req->reqType = (CARD8) info->codes->major_opcode; 325af7c02bdSmrg req->damageReqType = X_DamageCreate; 3266c9573adSmrg damage = XAllocID (dpy); 3276c9573adSmrg req->damage = (CARD32) damage; 3286c9573adSmrg req->drawable = (CARD32) drawable; 3296c9573adSmrg req->level = (CARD8) level; 330af7c02bdSmrg UnlockDisplay (dpy); 331af7c02bdSmrg SyncHandle (); 332af7c02bdSmrg return damage; 333af7c02bdSmrg} 334af7c02bdSmrg 335af7c02bdSmrgvoid 336af7c02bdSmrgXDamageDestroy (Display *dpy, Damage damage) 337af7c02bdSmrg{ 338af7c02bdSmrg XDamageExtDisplayInfo *info = XDamageFindDisplay (dpy); 339af7c02bdSmrg xDamageDestroyReq *req; 340af7c02bdSmrg 341af7c02bdSmrg XDamageSimpleCheckExtension (dpy, info); 342af7c02bdSmrg LockDisplay (dpy); 343af7c02bdSmrg GetReq (DamageDestroy, req); 3446c9573adSmrg req->reqType = (CARD8) info->codes->major_opcode; 345af7c02bdSmrg req->damageReqType = X_DamageDestroy; 3466c9573adSmrg req->damage = (CARD32) damage; 347af7c02bdSmrg UnlockDisplay (dpy); 348af7c02bdSmrg SyncHandle (); 349af7c02bdSmrg} 350af7c02bdSmrg 351af7c02bdSmrgvoid 3526dda92f9SmrgXDamageSubtract (Display *dpy, Damage damage, 353af7c02bdSmrg XserverRegion repair, XserverRegion parts) 354af7c02bdSmrg{ 355af7c02bdSmrg XDamageExtDisplayInfo *info = XDamageFindDisplay (dpy); 356af7c02bdSmrg xDamageSubtractReq *req; 357af7c02bdSmrg 358af7c02bdSmrg XDamageSimpleCheckExtension (dpy, info); 359af7c02bdSmrg LockDisplay (dpy); 360af7c02bdSmrg GetReq (DamageSubtract, req); 3616c9573adSmrg req->reqType = (CARD8) info->codes->major_opcode; 362af7c02bdSmrg req->damageReqType = X_DamageSubtract; 3636c9573adSmrg req->damage = (CARD32) damage; 3646c9573adSmrg req->repair = (CARD32) repair; 3656c9573adSmrg req->parts = (CARD32) parts; 366af7c02bdSmrg UnlockDisplay (dpy); 367af7c02bdSmrg SyncHandle (); 368af7c02bdSmrg} 369af7c02bdSmrg 370af7c02bdSmrgvoid 371af7c02bdSmrgXDamageAdd (Display *dpy, Drawable drawable, XserverRegion region) 372af7c02bdSmrg{ 373af7c02bdSmrg XDamageExtDisplayInfo *info = XDamageFindDisplay (dpy); 374af7c02bdSmrg xDamageAddReq *req; 375af7c02bdSmrg 376af7c02bdSmrg XDamageSimpleCheckExtension (dpy, info); 377af7c02bdSmrg LockDisplay (dpy); 378af7c02bdSmrg GetReq (DamageAdd, req); 3796c9573adSmrg req->reqType = (CARD8) info->codes->major_opcode; 380af7c02bdSmrg req->damageReqType = X_DamageAdd; 3816c9573adSmrg req->drawable = (CARD32) drawable; 3826c9573adSmrg req->region = (CARD32) region; 383af7c02bdSmrg 384af7c02bdSmrg UnlockDisplay (dpy); 385af7c02bdSmrg SyncHandle (); 386af7c02bdSmrg} 387