1/* 2 3Copyright 1991, 1993, 1998 The Open Group 4 5Permission to use, copy, modify, distribute, and sell this software and its 6documentation for any purpose is hereby granted without fee, provided that 7the above copyright notice appear in all copies and that both that 8copyright notice and this permission notice appear in supporting 9documentation. 10 11The above copyright notice and this permission notice shall be included 12in all copies or substantial portions of the Software. 13 14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR 18OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20OTHER DEALINGS IN THE SOFTWARE. 21 22Except as contained in this notice, the name of The Open Group shall 23not be used in advertising or otherwise to promote the sale, use or 24other dealings in this Software without prior written authorization 25from The Open Group. 26 27*/ 28 29/*********************************************************** 30Copyright 1991,1993 by Digital Equipment Corporation, Maynard, Massachusetts, 31and Olivetti Research Limited, Cambridge, England. 32 33 All Rights Reserved 34 35Permission to use, copy, modify, and distribute this software and its 36documentation for any purpose and without fee is hereby granted, 37provided that the above copyright notice appear in all copies and that 38both that copyright notice and this permission notice appear in 39supporting documentation, and that the names of Digital or Olivetti 40not be used in advertising or publicity pertaining to distribution of the 41software without specific, written prior permission. 42 43DIGITAL AND OLIVETTI DISCLAIM ALL WARRANTIES WITH REGARD TO THIS 44SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND 45FITNESS, IN NO EVENT SHALL THEY BE LIABLE FOR ANY SPECIAL, INDIRECT OR 46CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF 47USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 48OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 49PERFORMANCE OF THIS SOFTWARE. 50 51******************************************************************/ 52 53#ifdef HAVE_CONFIG_H 54#include <config.h> 55#endif 56#include <stdio.h> 57#include <X11/Xlibint.h> 58#include <X11/extensions/Xext.h> 59#include <X11/extensions/extutil.h> 60#include <X11/extensions/sync.h> 61#include <X11/extensions/syncproto.h> 62#include <limits.h> 63 64static XExtensionInfo _sync_info_data; 65static XExtensionInfo *sync_info = &_sync_info_data; 66static const char *sync_extension_name = SYNC_NAME; 67 68#define SyncCheckExtension(dpy,i,val) \ 69 XextCheckExtension(dpy, i, sync_extension_name, val) 70#define SyncSimpleCheckExtension(dpy,i) \ 71 XextSimpleCheckExtension(dpy, i, sync_extension_name) 72 73static int close_display(Display *dpy, XExtCodes *codes); 74static Bool wire_to_event(Display *dpy, XEvent *event, xEvent *wire); 75static Status event_to_wire(Display *dpy, XEvent *event, xEvent *wire); 76static char *error_string(Display *dpy, int code, XExtCodes *codes, 77 char *buf, int n); 78 79static XExtensionHooks sync_extension_hooks = { 80 NULL, /* create_gc */ 81 NULL, /* copy_gc */ 82 NULL, /* flush_gc */ 83 NULL, /* free_gc */ 84 NULL, /* create_font */ 85 NULL, /* free_font */ 86 close_display, /* close_display */ 87 wire_to_event, /* wire_to_event */ 88 event_to_wire, /* event_to_wire */ 89 NULL, /* error */ 90 error_string, /* error_string */ 91}; 92 93static const char *sync_error_list[] = { 94 "BadCounter", 95 "BadAlarm", 96 "BadFence", 97}; 98 99typedef struct _SyncVersionInfoRec { 100 short major; 101 short minor; 102 int num_errors; 103} SyncVersionInfo; 104 105static /* const */ SyncVersionInfo supported_versions[] = { 106 { 3 /* major */, 0 /* minor */, 2 /* num_errors */ }, 107 { 3 /* major */, 1 /* minor */, 3 /* num_errors */ }, 108}; 109 110#define NUM_VERSIONS (sizeof(supported_versions)/sizeof(supported_versions[0])) 111#define GET_VERSION(info) ((const SyncVersionInfo*)(info)->data) 112#define IS_VERSION_SUPPORTED(info) (!!(info)) 113 114static 115const SyncVersionInfo* GetVersionInfo(Display *dpy) 116{ 117 xSyncInitializeReply rep; 118 xSyncInitializeReq *req; 119 XExtCodes codes; 120 int i; 121 122 if (!XQueryExtension(dpy, sync_extension_name, 123 &codes.major_opcode, 124 &codes.first_event, 125 &codes.first_error)) 126 return NULL; 127 128 LockDisplay(dpy); 129 GetReq(SyncInitialize, req); 130 req->reqType = codes.major_opcode; 131 req->syncReqType = X_SyncInitialize; 132 req->majorVersion = SYNC_MAJOR_VERSION; 133 req->minorVersion = SYNC_MINOR_VERSION; 134 if (!_XReply(dpy, (xReply *) & rep, 0, xTrue)) 135 { 136 UnlockDisplay(dpy); 137 SyncHandle(); 138 return NULL; 139 } 140 UnlockDisplay(dpy); 141 SyncHandle(); 142 143 for (i = 0; i < NUM_VERSIONS; i++) { 144 if (supported_versions[i].major == rep.majorVersion && 145 supported_versions[i].minor == rep.minorVersion) { 146 return &supported_versions[i]; 147 } 148 } 149 150 return NULL; 151} 152 153static 154XExtDisplayInfo *find_display_create_optional(Display *dpy, Bool create) 155{ 156 XExtDisplayInfo *dpyinfo; 157 158 if (!sync_info) { 159 if (!(sync_info = XextCreateExtension())) return NULL; 160 } 161 162 if (!(dpyinfo = XextFindDisplay (sync_info, dpy)) && create) { 163 dpyinfo = XextAddDisplay(sync_info, dpy, 164 sync_extension_name, 165 &sync_extension_hooks, 166 XSyncNumberEvents, 167 (XPointer)GetVersionInfo(dpy)); 168 } 169 170 return dpyinfo; 171} 172 173static 174XExtDisplayInfo *find_display (Display *dpy) 175{ 176 return find_display_create_optional(dpy, True); 177} 178 179static 180XEXT_GENERATE_CLOSE_DISPLAY(close_display, sync_info) 181 182static 183char *error_string(Display *dpy, int code, XExtCodes *codes, char *buf, int n) 184{ 185 XExtDisplayInfo *info = find_display_create_optional(dpy, False); 186 int nerr = IS_VERSION_SUPPORTED(info) ? GET_VERSION(info)->num_errors : 0; 187 188 code -= codes->first_error; 189 if (code >= 0 && code < nerr) { 190 char tmp[256]; 191 snprintf (tmp, sizeof(tmp), "%s.%d", sync_extension_name, code); 192 XGetErrorDatabaseText (dpy, "XProtoError", tmp, sync_error_list[code], buf, n); 193 return buf; 194 } 195 return (char *)0; 196} 197 198static Bool 199wire_to_event(Display *dpy, XEvent *event, xEvent *wire) 200{ 201 XExtDisplayInfo *info = find_display(dpy); 202 XSyncCounterNotifyEvent *aevent; 203 xSyncCounterNotifyEvent *awire; 204 XSyncAlarmNotifyEvent *anl; 205 xSyncAlarmNotifyEvent *ane; 206 207 SyncCheckExtension(dpy, info, False); 208 209 switch ((wire->u.u.type & 0x7F) - info->codes->first_event) 210 { 211 case XSyncCounterNotify: 212 awire = (xSyncCounterNotifyEvent *) wire; 213 aevent = (XSyncCounterNotifyEvent *) event; 214 aevent->type = awire->type & 0x7F; 215 aevent->serial = _XSetLastRequestRead(dpy, 216 (xGenericReply *) wire); 217 aevent->send_event = (awire->type & 0x80) != 0; 218 aevent->display = dpy; 219 aevent->counter = awire->counter; 220 XSyncIntsToValue(&aevent->wait_value, awire->wait_value_lo, 221 awire->wait_value_hi); 222 XSyncIntsToValue(&aevent->counter_value, 223 awire->counter_value_lo, 224 awire->counter_value_hi); 225 aevent->time = awire->time; 226 aevent->count = awire->count; 227 aevent->destroyed = awire->destroyed; 228 return True; 229 230 case XSyncAlarmNotify: 231 ane = (xSyncAlarmNotifyEvent *) wire; /* ENCODING EVENT PTR */ 232 anl = (XSyncAlarmNotifyEvent *) event; /* LIBRARY EVENT PTR */ 233 anl->type = ane->type & 0x7F; 234 anl->serial = _XSetLastRequestRead(dpy, 235 (xGenericReply *) wire); 236 anl->send_event = (ane->type & 0x80) != 0; 237 anl->display = dpy; 238 anl->alarm = ane->alarm; 239 XSyncIntsToValue(&anl->counter_value, 240 ane->counter_value_lo, 241 ane->counter_value_hi); 242 XSyncIntsToValue(&anl->alarm_value, 243 ane->alarm_value_lo, 244 ane->alarm_value_hi); 245 anl->state = (XSyncAlarmState)ane->state; 246 anl->time = ane->time; 247 return True; 248 } 249 250 return False; 251} 252 253static Status 254event_to_wire(Display *dpy, XEvent *event, xEvent *wire) 255{ 256 XExtDisplayInfo *info = find_display(dpy); 257 XSyncCounterNotifyEvent *aevent; 258 xSyncCounterNotifyEvent *awire; 259 XSyncAlarmNotifyEvent *anl; 260 xSyncAlarmNotifyEvent *ane; 261 262 SyncCheckExtension(dpy, info, False); 263 264 switch ((event->type & 0x7F) - info->codes->first_event) 265 { 266 case XSyncCounterNotify: 267 awire = (xSyncCounterNotifyEvent *) wire; 268 aevent = (XSyncCounterNotifyEvent *) event; 269 awire->type = aevent->type | (aevent->send_event ? 0x80 : 0); 270 awire->sequenceNumber = aevent->serial & 0xFFFF; 271 awire->counter = aevent->counter; 272 awire->wait_value_lo = XSyncValueLow32(aevent->wait_value); 273 awire->wait_value_hi = XSyncValueHigh32(aevent->wait_value); 274 awire->counter_value_lo = XSyncValueLow32(aevent->counter_value); 275 awire->counter_value_hi = XSyncValueHigh32(aevent->counter_value); 276 awire->time = aevent->time; 277 awire->count = aevent->count; 278 awire->destroyed = aevent->destroyed; 279 return True; 280 281 case XSyncAlarmNotify: 282 ane = (xSyncAlarmNotifyEvent *) wire; /* ENCODING EVENT PTR */ 283 anl = (XSyncAlarmNotifyEvent *) event; /* LIBRARY EVENT PTR */ 284 ane->type = anl->type | (anl->send_event ? 0x80 : 0); 285 ane->sequenceNumber = anl->serial & 0xFFFF; 286 ane->alarm = anl->alarm; 287 ane->counter_value_lo = XSyncValueLow32(anl->counter_value); 288 ane->counter_value_hi = XSyncValueHigh32(anl->counter_value); 289 ane->alarm_value_lo = XSyncValueLow32(anl->alarm_value); 290 ane->alarm_value_hi = XSyncValueHigh32(anl->alarm_value); 291 ane->state = anl->state; 292 ane->time = anl->time; 293 return True; 294 } 295 return False; 296} 297 298Status 299XSyncQueryExtension( 300 Display *dpy, 301 int *event_base_return, int *error_base_return) 302{ 303 XExtDisplayInfo *info = find_display(dpy); 304 305 if (XextHasExtension(info)) 306 { 307 *event_base_return = info->codes->first_event; 308 *error_base_return = info->codes->first_error; 309 return True; 310 } 311 else 312 return False; 313} 314 315Status 316XSyncInitialize( 317 Display *dpy, 318 int *major_version_return, int *minor_version_return) 319{ 320 XExtDisplayInfo *info = find_display(dpy); 321 322 SyncCheckExtension(dpy, info, False); 323 324 if (IS_VERSION_SUPPORTED(info)) { 325 *major_version_return = GET_VERSION(info)->major; 326 *minor_version_return = GET_VERSION(info)->minor; 327 328 return True; 329 } else { 330 return False; 331 } 332} 333 334XSyncSystemCounter * 335XSyncListSystemCounters(Display *dpy, int *n_counters_return) 336{ 337 XExtDisplayInfo *info = find_display(dpy); 338 xSyncListSystemCountersReply rep; 339 xSyncListSystemCountersReq *req; 340 XSyncSystemCounter *list = NULL; 341 342 SyncCheckExtension(dpy, info, NULL); 343 344 LockDisplay(dpy); 345 GetReq(SyncListSystemCounters, req); 346 req->reqType = info->codes->major_opcode; 347 req->syncReqType = X_SyncListSystemCounters; 348 if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) 349 goto bail; 350 351 *n_counters_return = rep.nCounters; 352 if (rep.nCounters > 0) 353 { 354 xSyncSystemCounter *pWireSysCounter, *pNextWireSysCounter; 355 xSyncSystemCounter *pLastWireSysCounter; 356 XSyncCounter counter; 357 unsigned int replylen; 358 int i; 359 360 if (rep.nCounters < (INT_MAX / sizeof(XSyncSystemCounter))) 361 list = Xcalloc(rep.nCounters, sizeof(XSyncSystemCounter)); 362 if (rep.length < (INT_MAX >> 2)) { 363 replylen = rep.length << 2; 364 pWireSysCounter = Xmalloc (replylen + sizeof(XSyncCounter)); 365 /* +1 to leave room for last counter read-ahead */ 366 pLastWireSysCounter = (xSyncSystemCounter *) 367 ((char *)pWireSysCounter) + replylen; 368 } else { 369 replylen = 0; 370 pWireSysCounter = NULL; 371 } 372 373 if ((!list) || (!pWireSysCounter)) 374 { 375 Xfree(list); 376 Xfree(pWireSysCounter); 377 _XEatDataWords(dpy, rep.length); 378 list = NULL; 379 goto bail; 380 } 381 382 _XReadPad(dpy, (char *)pWireSysCounter, replylen); 383 384 counter = pWireSysCounter->counter; 385 for (i = 0; i < rep.nCounters; i++) 386 { 387 list[i].counter = counter; 388 XSyncIntsToValue(&list[i].resolution, 389 pWireSysCounter->resolution_lo, 390 pWireSysCounter->resolution_hi); 391 392 /* we may be about to clobber the counter field of the 393 * next syscounter because we have to add a null terminator 394 * to the counter name string. So we save the next counter 395 * here. 396 */ 397 pNextWireSysCounter = (xSyncSystemCounter *) 398 (((char *)pWireSysCounter) + ((SIZEOF(xSyncSystemCounter) + 399 pWireSysCounter->name_length + 3) & ~3)); 400 /* Make sure we haven't gone too far */ 401 if (pNextWireSysCounter > pLastWireSysCounter) { 402 Xfree(list); 403 Xfree(pWireSysCounter); 404 list = NULL; 405 goto bail; 406 } 407 408 counter = pNextWireSysCounter->counter; 409 410 list[i].name = ((char *)pWireSysCounter) + 411 SIZEOF(xSyncSystemCounter); 412 /* null-terminate the string */ 413 *(list[i].name + pWireSysCounter->name_length) = '\0'; 414 pWireSysCounter = pNextWireSysCounter; 415 } 416 } 417 418bail: 419 UnlockDisplay(dpy); 420 SyncHandle(); 421 return list; 422} 423 424void 425XSyncFreeSystemCounterList(XSyncSystemCounter *list) 426{ 427 if (list) 428 { 429 Xfree( ((char *)list[0].name) - SIZEOF(xSyncSystemCounter)); 430 Xfree(list); 431 } 432} 433 434 435XSyncCounter 436XSyncCreateCounter(Display *dpy, XSyncValue initial_value) 437{ 438 XExtDisplayInfo *info = find_display(dpy); 439 xSyncCreateCounterReq *req; 440 441 SyncCheckExtension(dpy, info, None); 442 443 LockDisplay(dpy); 444 GetReq(SyncCreateCounter, req); 445 req->reqType = info->codes->major_opcode; 446 req->syncReqType = X_SyncCreateCounter; 447 448 req->cid = XAllocID(dpy); 449 req->initial_value_lo = XSyncValueLow32(initial_value); 450 req->initial_value_hi = XSyncValueHigh32(initial_value); 451 452 UnlockDisplay(dpy); 453 SyncHandle(); 454 return req->cid; 455} 456 457Status 458XSyncSetCounter(Display *dpy, XSyncCounter counter, XSyncValue value) 459{ 460 XExtDisplayInfo *info = find_display(dpy); 461 xSyncSetCounterReq *req; 462 463 SyncCheckExtension(dpy, info, False); 464 465 LockDisplay(dpy); 466 GetReq(SyncSetCounter, req); 467 req->reqType = info->codes->major_opcode; 468 req->syncReqType = X_SyncSetCounter; 469 req->cid = counter; 470 req->value_lo = XSyncValueLow32(value); 471 req->value_hi = XSyncValueHigh32(value); 472 UnlockDisplay(dpy); 473 SyncHandle(); 474 return True; 475} 476 477Status 478XSyncChangeCounter(Display *dpy, XSyncCounter counter, XSyncValue value) 479{ 480 XExtDisplayInfo *info = find_display(dpy); 481 xSyncChangeCounterReq *req; 482 483 SyncCheckExtension(dpy, info, False); 484 485 LockDisplay(dpy); 486 GetReq(SyncChangeCounter, req); 487 req->reqType = info->codes->major_opcode; 488 req->syncReqType = X_SyncChangeCounter; 489 req->cid = counter; 490 req->value_lo = XSyncValueLow32(value); 491 req->value_hi = XSyncValueHigh32(value); 492 UnlockDisplay(dpy); 493 SyncHandle(); 494 return True; 495} 496 497Status 498XSyncDestroyCounter(Display *dpy, XSyncCounter counter) 499{ 500 XExtDisplayInfo *info = find_display(dpy); 501 xSyncDestroyCounterReq *req; 502 503 SyncCheckExtension(dpy, info, False); 504 505 LockDisplay(dpy); 506 GetReq(SyncDestroyCounter, req); 507 req->reqType = info->codes->major_opcode; 508 req->syncReqType = X_SyncDestroyCounter; 509 req->counter = counter; 510 UnlockDisplay(dpy); 511 SyncHandle(); 512 513 return True; 514} 515 516Status 517XSyncQueryCounter(Display *dpy, XSyncCounter counter, XSyncValue *value_return) 518{ 519 XExtDisplayInfo *info = find_display(dpy); 520 xSyncQueryCounterReply rep; 521 xSyncQueryCounterReq *req; 522 523 SyncCheckExtension(dpy, info, False); 524 525 LockDisplay(dpy); 526 GetReq(SyncQueryCounter, req); 527 req->reqType = info->codes->major_opcode; 528 req->syncReqType = X_SyncQueryCounter; 529 req->counter = counter; 530 if (!_XReply(dpy, (xReply *) & rep, 0, xTrue)) 531 { 532 UnlockDisplay(dpy); 533 SyncHandle(); 534 return False; 535 } 536 XSyncIntsToValue(value_return, rep.value_lo, rep.value_hi); 537 UnlockDisplay(dpy); 538 SyncHandle(); 539 540 return True; 541} 542 543 544Status 545XSyncAwait(Display *dpy, XSyncWaitCondition *wait_list, int n_conditions) 546{ 547 XExtDisplayInfo *info = find_display(dpy); 548 XSyncWaitCondition *wait_item = wait_list; 549 xSyncAwaitReq *req; 550 unsigned int len; 551 552 SyncCheckExtension(dpy, info, False); 553 554 LockDisplay(dpy); 555 GetReq(SyncAwait, req); 556 req->reqType = info->codes->major_opcode; 557 req->syncReqType = X_SyncAwait; 558 len = (n_conditions * SIZEOF(xSyncWaitCondition)) >> 2; 559 SetReqLen(req, len, len /* XXX */ ); 560 561 while (n_conditions--) 562 { 563 xSyncWaitCondition wc; 564 wc.counter = wait_item->trigger.counter; 565 wc.value_type = wait_item->trigger.value_type; 566 wc.wait_value_lo = XSyncValueLow32(wait_item->trigger.wait_value); 567 wc.wait_value_hi = XSyncValueHigh32(wait_item->trigger.wait_value); 568 wc.test_type = wait_item->trigger.test_type; 569 wc.event_threshold_lo = XSyncValueLow32(wait_item->event_threshold); 570 wc.event_threshold_hi = XSyncValueHigh32(wait_item->event_threshold); 571 Data(dpy, (char *)&wc, SIZEOF(xSyncWaitCondition)); 572 wait_item++; /* get next trigger */ 573 } 574 575 UnlockDisplay(dpy); 576 SyncHandle(); 577 return True; 578} 579 580static void 581_XProcessAlarmAttributes(Display *dpy, xSyncChangeAlarmReq *req, 582 unsigned long valuemask, 583 XSyncAlarmAttributes *attributes) 584{ 585 586 unsigned long values[32]; 587 unsigned long *value = values; 588 unsigned int nvalues; 589 590 if (valuemask & XSyncCACounter) 591 *value++ = attributes->trigger.counter; 592 593 if (valuemask & XSyncCAValueType) 594 *value++ = attributes->trigger.value_type; 595 596 if (valuemask & XSyncCAValue) 597 { 598 *value++ = XSyncValueHigh32(attributes->trigger.wait_value); 599 *value++ = XSyncValueLow32(attributes->trigger.wait_value); 600 } 601 602 if (valuemask & XSyncCATestType) 603 *value++ = attributes->trigger.test_type; 604 605 if (valuemask & XSyncCADelta) 606 { 607 *value++ = XSyncValueHigh32(attributes->delta); 608 *value++ = XSyncValueLow32(attributes->delta); 609 } 610 611 if (valuemask & XSyncCAEvents) 612 *value++ = attributes->events; 613 614 /* N.B. the 'state' field cannot be set or changed */ 615 req->length += (nvalues = value - values); 616 nvalues <<= 2; /* watch out for macros... */ 617 618 Data32(dpy, (long *) values, (long) nvalues); 619} 620 621XSyncAlarm 622XSyncCreateAlarm( 623 Display *dpy, 624 unsigned long values_mask, 625 XSyncAlarmAttributes *values) 626{ 627 XExtDisplayInfo *info = find_display(dpy); 628 xSyncCreateAlarmReq *req; 629 XSyncAlarm aid; 630 631 SyncCheckExtension(dpy, info, False); 632 633 LockDisplay(dpy); 634 GetReq(SyncCreateAlarm, req); 635 req->reqType = info->codes->major_opcode; 636 req->syncReqType = X_SyncCreateAlarm; 637 req->id = aid = XAllocID(dpy); 638 values_mask &= XSyncCACounter | XSyncCAValueType | XSyncCAValue 639 | XSyncCATestType | XSyncCADelta | XSyncCAEvents; 640 if ((req->valueMask = values_mask)) 641 _XProcessAlarmAttributes(dpy, (xSyncChangeAlarmReq *) req, 642 values_mask, values); 643 UnlockDisplay(dpy); 644 SyncHandle(); 645 return aid; 646} 647 648Status 649XSyncDestroyAlarm(Display *dpy, XSyncAlarm alarm) 650{ 651 XExtDisplayInfo *info = find_display(dpy); 652 xSyncDestroyAlarmReq *req; 653 654 SyncCheckExtension(dpy, info, False); 655 656 LockDisplay(dpy); 657 GetReq(SyncDestroyAlarm, req); 658 req->reqType = info->codes->major_opcode; 659 req->syncReqType = X_SyncDestroyAlarm; 660 req->alarm = alarm; 661 UnlockDisplay(dpy); 662 SyncHandle(); 663 return True; 664} 665 666Status 667XSyncQueryAlarm( 668 Display *dpy, 669 XSyncAlarm alarm, 670 XSyncAlarmAttributes *values_return) 671{ 672 XExtDisplayInfo *info = find_display(dpy); 673 xSyncQueryAlarmReq *req; 674 xSyncQueryAlarmReply rep; 675 676 SyncCheckExtension(dpy, info, False); 677 678 LockDisplay(dpy); 679 GetReq(SyncQueryAlarm, req); 680 req->reqType = info->codes->major_opcode; 681 req->syncReqType = X_SyncQueryAlarm; 682 req->alarm = alarm; 683 684 if (!(_XReply(dpy, (xReply *) & rep, 685 ((SIZEOF(xSyncQueryAlarmReply) - SIZEOF(xGenericReply)) >> 2), xFalse))) 686 { 687 UnlockDisplay(dpy); 688 SyncHandle(); 689 return False; 690 } 691 692 values_return->trigger.counter = rep.counter; 693 values_return->trigger.value_type = (XSyncValueType)rep.value_type; 694 XSyncIntsToValue(&values_return->trigger.wait_value, 695 rep.wait_value_lo, rep.wait_value_hi); 696 values_return->trigger.test_type = (XSyncTestType)rep.test_type; 697 XSyncIntsToValue(&values_return->delta, rep.delta_lo, 698 rep.delta_hi); 699 values_return->events = rep.events; 700 values_return->state = (XSyncAlarmState)rep.state; 701 UnlockDisplay(dpy); 702 SyncHandle(); 703 return True; 704} 705 706Status 707XSyncChangeAlarm( 708 Display *dpy, 709 XSyncAlarm alarm, 710 unsigned long values_mask, 711 XSyncAlarmAttributes *values) 712{ 713 XExtDisplayInfo *info = find_display(dpy); 714 xSyncChangeAlarmReq *req; 715 716 SyncCheckExtension(dpy, info, False); 717 718 LockDisplay(dpy); 719 GetReq(SyncChangeAlarm, req); 720 req->reqType = info->codes->major_opcode; 721 req->syncReqType = X_SyncChangeAlarm; 722 req->alarm = alarm; 723 values_mask &= XSyncCACounter | XSyncCAValueType | XSyncCAValue 724 | XSyncCATestType | XSyncCADelta | XSyncCAEvents; 725 if ((req->valueMask = values_mask)) 726 _XProcessAlarmAttributes(dpy, req, values_mask, values); 727 UnlockDisplay(dpy); 728 SyncHandle(); 729 return True; 730} 731 732Status 733XSyncSetPriority( 734 Display *dpy, 735 XID client_resource_id, 736 int priority) 737{ 738 XExtDisplayInfo *info = find_display(dpy); 739 xSyncSetPriorityReq *req; 740 741 SyncCheckExtension(dpy, info, False); 742 743 LockDisplay(dpy); 744 GetReq(SyncSetPriority, req); 745 req->reqType = info->codes->major_opcode; 746 req->syncReqType = X_SyncSetPriority; 747 req->id = client_resource_id; 748 req->priority = priority; 749 UnlockDisplay(dpy); 750 SyncHandle(); 751 return True; 752} 753 754Status 755XSyncGetPriority(Display *dpy, XID client_resource_id, int *return_priority) 756{ 757 XExtDisplayInfo *info = find_display(dpy); 758 xSyncGetPriorityReply rep; 759 xSyncGetPriorityReq *req; 760 761 SyncCheckExtension(dpy, info, False); 762 763 LockDisplay(dpy); 764 GetReq(SyncGetPriority, req); 765 req->reqType = info->codes->major_opcode; 766 req->syncReqType = X_SyncGetPriority; 767 req->id = client_resource_id; 768 769 if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) 770 { 771 UnlockDisplay(dpy); 772 SyncHandle(); 773 return False; 774 } 775 if (return_priority) 776 *return_priority = rep.priority; 777 778 UnlockDisplay(dpy); 779 SyncHandle(); 780 return True; 781} 782 783XSyncFence 784XSyncCreateFence(Display *dpy, Drawable d, Bool initially_triggered) 785{ 786 XExtDisplayInfo *info = find_display(dpy); 787 xSyncCreateFenceReq *req; 788 XSyncFence id; 789 790 SyncCheckExtension(dpy, info, None); 791 792 LockDisplay(dpy); 793 GetReq(SyncCreateFence, req); 794 req->reqType = info->codes->major_opcode; 795 req->syncReqType = X_SyncCreateFence; 796 797 req->d = d; 798 id = req->fid = XAllocID(dpy); 799 req->initially_triggered = initially_triggered; 800 801 UnlockDisplay(dpy); 802 SyncHandle(); 803 return id; 804} 805 806Bool 807XSyncTriggerFence(Display *dpy, XSyncFence fence) 808{ 809 XExtDisplayInfo *info = find_display(dpy); 810 xSyncTriggerFenceReq *req; 811 812 SyncCheckExtension(dpy, info, None); 813 814 LockDisplay(dpy); 815 GetReq(SyncTriggerFence, req); 816 req->reqType = info->codes->major_opcode; 817 req->syncReqType = X_SyncTriggerFence; 818 819 req->fid = fence; 820 821 UnlockDisplay(dpy); 822 SyncHandle(); 823 return True; 824} 825 826Bool 827XSyncResetFence(Display *dpy, XSyncFence fence) 828{ 829 XExtDisplayInfo *info = find_display(dpy); 830 xSyncResetFenceReq *req; 831 832 SyncCheckExtension(dpy, info, None); 833 834 LockDisplay(dpy); 835 GetReq(SyncResetFence, req); 836 req->reqType = info->codes->major_opcode; 837 req->syncReqType = X_SyncResetFence; 838 839 req->fid = fence; 840 841 UnlockDisplay(dpy); 842 SyncHandle(); 843 return True; 844} 845 846Bool 847XSyncDestroyFence(Display *dpy, XSyncFence fence) 848{ 849 XExtDisplayInfo *info = find_display(dpy); 850 xSyncDestroyFenceReq *req; 851 852 SyncCheckExtension(dpy, info, None); 853 854 LockDisplay(dpy); 855 GetReq(SyncDestroyFence, req); 856 req->reqType = info->codes->major_opcode; 857 req->syncReqType = X_SyncDestroyFence; 858 859 req->fid = fence; 860 861 UnlockDisplay(dpy); 862 SyncHandle(); 863 return True; 864} 865 866Bool 867XSyncQueryFence(Display *dpy, XSyncFence fence, Bool *triggered) 868{ 869 XExtDisplayInfo *info = find_display(dpy); 870 xSyncQueryFenceReply rep; 871 xSyncQueryFenceReq *req; 872 873 SyncCheckExtension(dpy, info, None); 874 875 LockDisplay(dpy); 876 GetReq(SyncQueryFence, req); 877 req->reqType = info->codes->major_opcode; 878 req->syncReqType = X_SyncQueryFence; 879 req->fid = fence; 880 881 if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) 882 { 883 UnlockDisplay(dpy); 884 SyncHandle(); 885 return False; 886 } 887 if (triggered) 888 *triggered = rep.triggered; 889 890 UnlockDisplay(dpy); 891 SyncHandle(); 892 return True; 893} 894 895Bool 896XSyncAwaitFence(Display *dpy, const XSyncFence *fence_list, int n_fences) 897{ 898 XExtDisplayInfo *info = find_display(dpy); 899 xSyncAwaitFenceReq *req; 900 901 SyncCheckExtension(dpy, info, False); 902 903 LockDisplay(dpy); 904 GetReq(SyncAwaitFence, req); 905 req->reqType = info->codes->major_opcode; 906 req->syncReqType = X_SyncAwaitFence; 907 SetReqLen(req, n_fences, n_fences); 908 909 Data32(dpy, (char *)fence_list, sizeof(CARD32) * n_fences); 910 911 UnlockDisplay(dpy); 912 SyncHandle(); 913 return True; 914} 915 916/* 917 * Functions corresponding to the macros for manipulating 64-bit values 918 */ 919 920void 921XSyncIntToValue(XSyncValue *pv, int i) 922{ 923 _XSyncIntToValue(pv,i); 924} 925 926void 927XSyncIntsToValue(XSyncValue *pv, unsigned int l, int h) 928{ 929 _XSyncIntsToValue(pv, l, h); 930} 931 932Bool 933XSyncValueGreaterThan(XSyncValue a, XSyncValue b) 934{ 935 return _XSyncValueGreaterThan(a, b); 936} 937 938Bool 939XSyncValueLessThan(XSyncValue a, XSyncValue b) 940{ 941 return _XSyncValueLessThan(a, b); 942} 943 944Bool 945XSyncValueGreaterOrEqual(XSyncValue a, XSyncValue b) 946{ 947 return _XSyncValueGreaterOrEqual(a, b); 948} 949 950Bool 951XSyncValueLessOrEqual(XSyncValue a, XSyncValue b) 952{ 953 return _XSyncValueLessOrEqual(a, b); 954} 955 956Bool 957XSyncValueEqual(XSyncValue a, XSyncValue b) 958{ 959 return _XSyncValueEqual(a, b); 960} 961 962Bool 963XSyncValueIsNegative(XSyncValue v) 964{ 965 return _XSyncValueIsNegative(v); 966} 967 968Bool 969XSyncValueIsZero(XSyncValue a) 970{ 971 return _XSyncValueIsZero(a); 972} 973 974Bool 975XSyncValueIsPositive(XSyncValue v) 976{ 977 return _XSyncValueIsPositive(v); 978} 979 980unsigned int 981XSyncValueLow32(XSyncValue v) 982{ 983 return _XSyncValueLow32(v); 984} 985 986int 987XSyncValueHigh32(XSyncValue v) 988{ 989 return _XSyncValueHigh32(v); 990} 991 992void 993XSyncValueAdd(XSyncValue *presult, XSyncValue a, XSyncValue b, Bool *poverflow) 994{ 995 _XSyncValueAdd(presult, a, b, poverflow); 996} 997 998void 999XSyncValueSubtract( 1000 XSyncValue *presult, 1001 XSyncValue a, XSyncValue b, 1002 Bool *poverflow) 1003{ 1004 _XSyncValueSubtract(presult, a, b, poverflow); 1005} 1006 1007void 1008XSyncMaxValue(XSyncValue *pv) 1009{ 1010 _XSyncMaxValue(pv); 1011} 1012 1013void 1014XSyncMinValue(XSyncValue *pv) 1015{ 1016 _XSyncMinValue(pv); 1017} 1018