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