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