1 /* 2 3 Copyright 1991, 1993, 1998 The Open Group 4 5 Permission to use, copy, modify, distribute, and sell this software and its 6 documentation for any purpose is hereby granted without fee, provided that 7 the above copyright notice appear in all copies and that both that 8 copyright notice and this permission notice appear in supporting 9 documentation. 10 11 The above copyright notice and this permission notice shall be included 12 in all copies or substantial portions of the Software. 13 14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 OTHER DEALINGS IN THE SOFTWARE. 21 22 Except as contained in this notice, the name of The Open Group shall 23 not be used in advertising or otherwise to promote the sale, use or 24 other dealings in this Software without prior written authorization 25 from The Open Group. 26 27 */ 28 29 /*********************************************************** 30 Copyright 1991,1993 by Digital Equipment Corporation, Maynard, Massachusetts, 31 and Olivetti Research Limited, Cambridge, England. 32 33 All Rights Reserved 34 35 Permission to use, copy, modify, and distribute this software and its 36 documentation for any purpose and without fee is hereby granted, 37 provided that the above copyright notice appear in all copies and that 38 both that copyright notice and this permission notice appear in 39 supporting documentation, and that the names of Digital or Olivetti 40 not be used in advertising or publicity pertaining to distribution of the 41 software without specific, written prior permission. 42 43 DIGITAL AND OLIVETTI DISCLAIM ALL WARRANTIES WITH REGARD TO THIS 44 SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND 45 FITNESS, IN NO EVENT SHALL THEY BE LIABLE FOR ANY SPECIAL, INDIRECT OR 46 CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF 47 USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 48 OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 49 PERFORMANCE 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 64 static XExtensionInfo _sync_info_data; 65 static XExtensionInfo *sync_info = &_sync_info_data; 66 static 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 73 static int close_display(Display *dpy, XExtCodes *codes); 74 static Bool wire_to_event(Display *dpy, XEvent *event, xEvent *wire); 75 static Status event_to_wire(Display *dpy, XEvent *event, xEvent *wire); 76 static char *error_string(Display *dpy, int code, XExtCodes *codes, 77 char *buf, int n); 78 79 static 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 93 static const char *sync_error_list[] = { 94 "BadCounter", 95 "BadAlarm", 96 "BadFence", 97 }; 98 99 typedef struct _SyncVersionInfoRec { 100 short major; 101 short minor; 102 int num_errors; 103 } SyncVersionInfo; 104 105 static /* 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 114 static 115 const 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 153 static 154 XExtDisplayInfo *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 173 static 174 XExtDisplayInfo *find_display (Display *dpy) 175 { 176 return find_display_create_optional(dpy, True); 177 } 178 179 static 180 XEXT_GENERATE_CLOSE_DISPLAY(close_display, sync_info) 181 182 static 183 char *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 198 static Bool 199 wire_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 253 static Status 254 event_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 298 Status 299 XSyncQueryExtension( 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 315 Status 316 XSyncInitialize( 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 334 XSyncSystemCounter * 335 XSyncListSystemCounters(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 418 bail: 419 UnlockDisplay(dpy); 420 SyncHandle(); 421 return list; 422 } 423 424 void 425 XSyncFreeSystemCounterList(XSyncSystemCounter *list) 426 { 427 if (list) 428 { 429 Xfree( ((char *)list[0].name) - SIZEOF(xSyncSystemCounter)); 430 Xfree(list); 431 } 432 } 433 434 435 XSyncCounter 436 XSyncCreateCounter(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 457 Status 458 XSyncSetCounter(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 477 Status 478 XSyncChangeCounter(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 497 Status 498 XSyncDestroyCounter(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 516 Status 517 XSyncQueryCounter(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 544 Status 545 XSyncAwait(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 580 static 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 621 XSyncAlarm 622 XSyncCreateAlarm( 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 648 Status 649 XSyncDestroyAlarm(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 666 Status 667 XSyncQueryAlarm( 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 706 Status 707 XSyncChangeAlarm( 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 732 Status 733 XSyncSetPriority( 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 754 Status 755 XSyncGetPriority(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 783 XSyncFence 784 XSyncCreateFence(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 806 Bool 807 XSyncTriggerFence(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 826 Bool 827 XSyncResetFence(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 846 Bool 847 XSyncDestroyFence(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 866 Bool 867 XSyncQueryFence(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 895 Bool 896 XSyncAwaitFence(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 920 void 921 XSyncIntToValue(XSyncValue *pv, int i) 922 { 923 _XSyncIntToValue(pv,i); 924 } 925 926 void 927 XSyncIntsToValue(XSyncValue *pv, unsigned int l, int h) 928 { 929 _XSyncIntsToValue(pv, l, h); 930 } 931 932 Bool 933 XSyncValueGreaterThan(XSyncValue a, XSyncValue b) 934 { 935 return _XSyncValueGreaterThan(a, b); 936 } 937 938 Bool 939 XSyncValueLessThan(XSyncValue a, XSyncValue b) 940 { 941 return _XSyncValueLessThan(a, b); 942 } 943 944 Bool 945 XSyncValueGreaterOrEqual(XSyncValue a, XSyncValue b) 946 { 947 return _XSyncValueGreaterOrEqual(a, b); 948 } 949 950 Bool 951 XSyncValueLessOrEqual(XSyncValue a, XSyncValue b) 952 { 953 return _XSyncValueLessOrEqual(a, b); 954 } 955 956 Bool 957 XSyncValueEqual(XSyncValue a, XSyncValue b) 958 { 959 return _XSyncValueEqual(a, b); 960 } 961 962 Bool 963 XSyncValueIsNegative(XSyncValue v) 964 { 965 return _XSyncValueIsNegative(v); 966 } 967 968 Bool 969 XSyncValueIsZero(XSyncValue a) 970 { 971 return _XSyncValueIsZero(a); 972 } 973 974 Bool 975 XSyncValueIsPositive(XSyncValue v) 976 { 977 return _XSyncValueIsPositive(v); 978 } 979 980 unsigned int 981 XSyncValueLow32(XSyncValue v) 982 { 983 return _XSyncValueLow32(v); 984 } 985 986 int 987 XSyncValueHigh32(XSyncValue v) 988 { 989 return _XSyncValueHigh32(v); 990 } 991 992 void 993 XSyncValueAdd(XSyncValue *presult, XSyncValue a, XSyncValue b, Bool *poverflow) 994 { 995 _XSyncValueAdd(presult, a, b, poverflow); 996 } 997 998 void 999 XSyncValueSubtract( 1000 XSyncValue *presult, 1001 XSyncValue a, XSyncValue b, 1002 Bool *poverflow) 1003 { 1004 _XSyncValueSubtract(presult, a, b, poverflow); 1005 } 1006 1007 void 1008 XSyncMaxValue(XSyncValue *pv) 1009 { 1010 _XSyncMaxValue(pv); 1011 } 1012 1013 void 1014 XSyncMinValue(XSyncValue *pv) 1015 { 1016 _XSyncMinValue(pv); 1017 } 1018