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