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
GetVersionInfo(Display * dpy)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
find_display_create_optional(Display * dpy,Bool create)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
find_display(Display * dpy)174 XExtDisplayInfo *find_display (Display *dpy)
175 {
176     return find_display_create_optional(dpy, True);
177 }
178 
179 static
XEXT_GENERATE_CLOSE_DISPLAY(close_display,sync_info)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
wire_to_event(Display * dpy,XEvent * event,xEvent * wire)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
event_to_wire(Display * dpy,XEvent * event,xEvent * wire)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
XSyncQueryExtension(Display * dpy,int * event_base_return,int * error_base_return)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
XSyncInitialize(Display * dpy,int * major_version_return,int * minor_version_return)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 *
XSyncListSystemCounters(Display * dpy,int * n_counters_return)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 = Xmalloc(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
XSyncFreeSystemCounterList(XSyncSystemCounter * list)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
XSyncCreateCounter(Display * dpy,XSyncValue initial_value)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
XSyncSetCounter(Display * dpy,XSyncCounter counter,XSyncValue value)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
XSyncChangeCounter(Display * dpy,XSyncCounter counter,XSyncValue value)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
XSyncDestroyCounter(Display * dpy,XSyncCounter counter)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
XSyncQueryCounter(Display * dpy,XSyncCounter counter,XSyncValue * value_return)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
XSyncAwait(Display * dpy,XSyncWaitCondition * wait_list,int n_conditions)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
_XProcessAlarmAttributes(Display * dpy,xSyncChangeAlarmReq * req,unsigned long valuemask,XSyncAlarmAttributes * attributes)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
XSyncCreateAlarm(Display * dpy,unsigned long values_mask,XSyncAlarmAttributes * values)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
XSyncDestroyAlarm(Display * dpy,XSyncAlarm alarm)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
XSyncQueryAlarm(Display * dpy,XSyncAlarm alarm,XSyncAlarmAttributes * values_return)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
XSyncChangeAlarm(Display * dpy,XSyncAlarm alarm,unsigned long values_mask,XSyncAlarmAttributes * values)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
XSyncSetPriority(Display * dpy,XID client_resource_id,int priority)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
XSyncGetPriority(Display * dpy,XID client_resource_id,int * return_priority)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
XSyncCreateFence(Display * dpy,Drawable d,Bool initially_triggered)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
XSyncTriggerFence(Display * dpy,XSyncFence fence)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
XSyncResetFence(Display * dpy,XSyncFence fence)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
XSyncDestroyFence(Display * dpy,XSyncFence fence)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
XSyncQueryFence(Display * dpy,XSyncFence fence,Bool * triggered)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
XSyncAwaitFence(Display * dpy,const XSyncFence * fence_list,int n_fences)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
XSyncIntToValue(XSyncValue * pv,int i)921 XSyncIntToValue(XSyncValue *pv, int i)
922 {
923     _XSyncIntToValue(pv,i);
924 }
925 
926 void
XSyncIntsToValue(XSyncValue * pv,unsigned int l,int h)927 XSyncIntsToValue(XSyncValue *pv, unsigned int l, int h)
928 {
929     _XSyncIntsToValue(pv, l, h);
930 }
931 
932 Bool
XSyncValueGreaterThan(XSyncValue a,XSyncValue b)933 XSyncValueGreaterThan(XSyncValue a, XSyncValue b)
934 {
935     return _XSyncValueGreaterThan(a, b);
936 }
937 
938 Bool
XSyncValueLessThan(XSyncValue a,XSyncValue b)939 XSyncValueLessThan(XSyncValue a, XSyncValue b)
940 {
941     return _XSyncValueLessThan(a, b);
942 }
943 
944 Bool
XSyncValueGreaterOrEqual(XSyncValue a,XSyncValue b)945 XSyncValueGreaterOrEqual(XSyncValue a, XSyncValue b)
946 {
947     return _XSyncValueGreaterOrEqual(a, b);
948 }
949 
950 Bool
XSyncValueLessOrEqual(XSyncValue a,XSyncValue b)951 XSyncValueLessOrEqual(XSyncValue a, XSyncValue b)
952 {
953     return _XSyncValueLessOrEqual(a, b);
954 }
955 
956 Bool
XSyncValueEqual(XSyncValue a,XSyncValue b)957 XSyncValueEqual(XSyncValue a, XSyncValue b)
958 {
959     return _XSyncValueEqual(a, b);
960 }
961 
962 Bool
XSyncValueIsNegative(XSyncValue v)963 XSyncValueIsNegative(XSyncValue v)
964 {
965     return _XSyncValueIsNegative(v);
966 }
967 
968 Bool
XSyncValueIsZero(XSyncValue a)969 XSyncValueIsZero(XSyncValue a)
970 {
971     return _XSyncValueIsZero(a);
972 }
973 
974 Bool
XSyncValueIsPositive(XSyncValue v)975 XSyncValueIsPositive(XSyncValue v)
976 {
977     return _XSyncValueIsPositive(v);
978 }
979 
980 unsigned int
XSyncValueLow32(XSyncValue v)981 XSyncValueLow32(XSyncValue v)
982 {
983     return _XSyncValueLow32(v);
984 }
985 
986 int
XSyncValueHigh32(XSyncValue v)987 XSyncValueHigh32(XSyncValue v)
988 {
989     return _XSyncValueHigh32(v);
990 }
991 
992 void
XSyncValueAdd(XSyncValue * presult,XSyncValue a,XSyncValue b,Bool * poverflow)993 XSyncValueAdd(XSyncValue *presult, XSyncValue a, XSyncValue b, Bool *poverflow)
994 {
995     _XSyncValueAdd(presult, a, b, poverflow);
996 }
997 
998 void
XSyncValueSubtract(XSyncValue * presult,XSyncValue a,XSyncValue b,Bool * poverflow)999 XSyncValueSubtract(
1000     XSyncValue *presult,
1001     XSyncValue a, XSyncValue b,
1002     Bool *poverflow)
1003 {
1004     _XSyncValueSubtract(presult, a, b, poverflow);
1005 }
1006 
1007 void
XSyncMaxValue(XSyncValue * pv)1008 XSyncMaxValue(XSyncValue *pv)
1009 {
1010     _XSyncMaxValue(pv);
1011 }
1012 
1013 void
XSyncMinValue(XSyncValue * pv)1014 XSyncMinValue(XSyncValue *pv)
1015 {
1016     _XSyncMinValue(pv);
1017 }
1018