#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#define NEED_EVENTS
#define NEED_REPLIES
#include <X11/Xlibint.h>
#include <X11/extensions/Xext.h>
#include <X11/extensions/extutil.h>
#include <X11/extensions/syncstr.h>
static XExtensionInfo _sync_info_data;
static XExtensionInfo *sync_info = &_sync_info_data;
static char *sync_extension_name = SYNC_NAME;
#define SyncCheckExtension(dpy,i,val) \
XextCheckExtension(dpy, i, sync_extension_name, val)
#define SyncSimpleCheckExtension(dpy,i) \
XextSimpleCheckExtension(dpy, i, sync_extension_name)
static int close_display(Display *dpy, XExtCodes *codes);
static Bool wire_to_event(Display *dpy, XEvent *event, xEvent *wire);
static Status event_to_wire(Display *dpy, XEvent *event, xEvent *wire);
static char *error_string(Display *dpy, int code, XExtCodes *codes,
char *buf, int n);
static XExtensionHooks sync_extension_hooks = {
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
close_display,
wire_to_event,
event_to_wire,
NULL,
error_string,
};
static char *sync_error_list[] = {
"BadCounter",
"BadAlarm",
};
static
XEXT_GENERATE_FIND_DISPLAY(find_display, sync_info,
sync_extension_name,
&sync_extension_hooks,
XSyncNumberEvents, (XPointer) NULL)
static
XEXT_GENERATE_CLOSE_DISPLAY(close_display, sync_info)
static
XEXT_GENERATE_ERROR_STRING(error_string, sync_extension_name,
XSyncNumberErrors, sync_error_list)
static Bool
wire_to_event(Display *dpy, XEvent *event, xEvent *wire)
{
XExtDisplayInfo *info = find_display(dpy);
XSyncCounterNotifyEvent *aevent;
xSyncCounterNotifyEvent *awire;
XSyncAlarmNotifyEvent *anl;
xSyncAlarmNotifyEvent *ane;
SyncCheckExtension(dpy, info, False);
switch ((wire->u.u.type & 0x7F) - info->codes->first_event)
{
case XSyncCounterNotify:
awire = (xSyncCounterNotifyEvent *) wire;
aevent = (XSyncCounterNotifyEvent *) event;
aevent->type = awire->type & 0x7F;
aevent->serial = _XSetLastRequestRead(dpy,
(xGenericReply *) wire);
aevent->send_event = (awire->type & 0x80) != 0;
aevent->display = dpy;
aevent->counter = awire->counter;
XSyncIntsToValue(&aevent->wait_value, awire->wait_value_lo,
awire->wait_value_hi);
XSyncIntsToValue(&aevent->counter_value,
awire->counter_value_lo,
awire->counter_value_hi);
aevent->time = awire->time;
aevent->count = awire->count;
aevent->destroyed = awire->destroyed;
return True;
case XSyncAlarmNotify:
ane = (xSyncAlarmNotifyEvent *) wire;
anl = (XSyncAlarmNotifyEvent *) event;
anl->type = ane->type & 0x7F;
anl->serial = _XSetLastRequestRead(dpy,
(xGenericReply *) wire);
anl->send_event = (ane->type & 0x80) != 0;
anl->display = dpy;
anl->alarm = ane->alarm;
XSyncIntsToValue(&anl->counter_value,
ane->counter_value_lo,
ane->counter_value_hi);
XSyncIntsToValue(&anl->alarm_value,
ane->alarm_value_lo,
ane->alarm_value_hi);
anl->state = (XSyncAlarmState)ane->state;
anl->time = ane->time;
return True;
}
return False;
}
static Status
event_to_wire(Display *dpy, XEvent *event, xEvent *wire)
{
XExtDisplayInfo *info = find_display(dpy);
XSyncCounterNotifyEvent *aevent;
xSyncCounterNotifyEvent *awire;
XSyncAlarmNotifyEvent *anl;
xSyncAlarmNotifyEvent *ane;
SyncCheckExtension(dpy, info, False);
switch ((event->type & 0x7F) - info->codes->first_event)
{
case XSyncCounterNotify:
awire = (xSyncCounterNotifyEvent *) wire;
aevent = (XSyncCounterNotifyEvent *) event;
awire->type = aevent->type | (aevent->send_event ? 0x80 : 0);
awire->sequenceNumber = aevent->serial & 0xFFFF;
awire->counter = aevent->counter;
awire->wait_value_lo = XSyncValueLow32(aevent->wait_value);
awire->wait_value_hi = XSyncValueHigh32(aevent->wait_value);
awire->counter_value_lo = XSyncValueLow32(aevent->counter_value);
awire->counter_value_hi = XSyncValueHigh32(aevent->counter_value);
awire->time = aevent->time;
awire->count = aevent->count;
awire->destroyed = aevent->destroyed;
return True;
case XSyncAlarmNotify:
ane = (xSyncAlarmNotifyEvent *) wire;
anl = (XSyncAlarmNotifyEvent *) event;
ane->type = anl->type | (anl->send_event ? 0x80 : 0);
ane->sequenceNumber = anl->serial & 0xFFFF;
ane->alarm = anl->alarm;
ane->counter_value_lo = XSyncValueLow32(anl->counter_value);
ane->counter_value_hi = XSyncValueHigh32(anl->counter_value);
ane->alarm_value_lo = XSyncValueLow32(anl->alarm_value);
ane->alarm_value_hi = XSyncValueHigh32(anl->alarm_value);
ane->state = anl->state;
ane->time = anl->time;
return True;
}
return False;
}
Status
XSyncQueryExtension(
Display *dpy,
int *event_base_return, int *error_base_return)
{
XExtDisplayInfo *info = find_display(dpy);
if (XextHasExtension(info))
{
*event_base_return = info->codes->first_event;
*error_base_return = info->codes->first_error;
return True;
}
else
return False;
}
Status
XSyncInitialize(
Display *dpy,
int *major_version_return, int *minor_version_return)
{
XExtDisplayInfo *info = find_display(dpy);
xSyncInitializeReply rep;
xSyncInitializeReq *req;
SyncCheckExtension(dpy, info, False);
LockDisplay(dpy);
GetReq(SyncInitialize, req);
req->reqType = info->codes->major_opcode;
req->syncReqType = X_SyncInitialize;
req->majorVersion = SYNC_MAJOR_VERSION;
req->minorVersion = SYNC_MINOR_VERSION;
if (!_XReply(dpy, (xReply *) & rep, 0, xTrue))
{
UnlockDisplay(dpy);
SyncHandle();
return False;
}
UnlockDisplay(dpy);
SyncHandle();
*major_version_return = rep.majorVersion;
*minor_version_return = rep.minorVersion;
return ((rep.majorVersion == SYNC_MAJOR_VERSION)
#if SYNC_MINOR_VERSION > 0
&& (rep.minorVersion >= SYNC_MINOR_VERSION)
#endif
);
}
XSyncSystemCounter *
XSyncListSystemCounters(Display *dpy, int *n_counters_return)
{
XExtDisplayInfo *info = find_display(dpy);
xSyncListSystemCountersReply rep;
xSyncListSystemCountersReq *req;
XSyncSystemCounter *list = NULL;
SyncCheckExtension(dpy, info, NULL);
LockDisplay(dpy);
GetReq(SyncListSystemCounters, req);
req->reqType = info->codes->major_opcode;
req->syncReqType = X_SyncListSystemCounters;
if (!_XReply(dpy, (xReply *) & rep, 0, xFalse))
goto bail;
*n_counters_return = rep.nCounters;
if (rep.nCounters > 0)
{
xSyncSystemCounter *pWireSysCounter, *pNextWireSysCounter;
XSyncCounter counter;
int replylen;
int i;
list = (XSyncSystemCounter *)Xmalloc(
rep.nCounters * sizeof(XSyncSystemCounter));
replylen = rep.length << 2;
pWireSysCounter = (xSyncSystemCounter *) Xmalloc ((unsigned) replylen + 1);
if ((!list) || (!pWireSysCounter))
{
if (list) Xfree((char *) list);
if (pWireSysCounter) Xfree((char *) pWireSysCounter);
_XEatData(dpy, (unsigned long) replylen);
list = NULL;
goto bail;
}
_XReadPad(dpy, (char *)pWireSysCounter, replylen);
counter = pWireSysCounter->counter;
for (i = 0; i < rep.nCounters; i++)
{
list[i].counter = counter;
XSyncIntsToValue(&list[i].resolution,
pWireSysCounter->resolution_lo,
pWireSysCounter->resolution_hi);
pNextWireSysCounter = (xSyncSystemCounter *)
(((char *)pWireSysCounter) + ((SIZEOF(xSyncSystemCounter) +
pWireSysCounter->name_length + 3) & ~3));
counter = pNextWireSysCounter->counter;
list[i].name = ((char *)pWireSysCounter) +
SIZEOF(xSyncSystemCounter);
*(list[i].name + pWireSysCounter->name_length) = '\0';
pWireSysCounter = pNextWireSysCounter;
}
}
bail:
UnlockDisplay(dpy);
SyncHandle();
return list;
}
void
XSyncFreeSystemCounterList(XSyncSystemCounter *list)
{
if (list)
{
Xfree( ((char *)list[0].name) - SIZEOF(xSyncSystemCounter));
Xfree(list);
}
}
XSyncCounter
XSyncCreateCounter(Display *dpy, XSyncValue initial_value)
{
XExtDisplayInfo *info = find_display(dpy);
xSyncCreateCounterReq *req;
SyncCheckExtension(dpy, info, None);
LockDisplay(dpy);
GetReq(SyncCreateCounter, req);
req->reqType = info->codes->major_opcode;
req->syncReqType = X_SyncCreateCounter;
req->cid = XAllocID(dpy);
req->initial_value_lo = XSyncValueLow32(initial_value);
req->initial_value_hi = XSyncValueHigh32(initial_value);
UnlockDisplay(dpy);
SyncHandle();
return req->cid;
}
Status
XSyncSetCounter(Display *dpy, XSyncCounter counter, XSyncValue value)
{
XExtDisplayInfo *info = find_display(dpy);
xSyncSetCounterReq *req;
SyncCheckExtension(dpy, info, False);
LockDisplay(dpy);
GetReq(SyncSetCounter, req);
req->reqType = info->codes->major_opcode;
req->syncReqType = X_SyncSetCounter;
req->cid = counter;
req->value_lo = XSyncValueLow32(value);
req->value_hi = XSyncValueHigh32(value);
UnlockDisplay(dpy);
SyncHandle();
return True;
}
Status
XSyncChangeCounter(Display *dpy, XSyncCounter counter, XSyncValue value)
{
XExtDisplayInfo *info = find_display(dpy);
xSyncChangeCounterReq *req;
SyncCheckExtension(dpy, info, False);
LockDisplay(dpy);
GetReq(SyncChangeCounter, req);
req->reqType = info->codes->major_opcode;
req->syncReqType = X_SyncChangeCounter;
req->cid = counter;
req->value_lo = XSyncValueLow32(value);
req->value_hi = XSyncValueHigh32(value);
UnlockDisplay(dpy);
SyncHandle();
return True;
}
Status
XSyncDestroyCounter(Display *dpy, XSyncCounter counter)
{
XExtDisplayInfo *info = find_display(dpy);
xSyncDestroyCounterReq *req;
SyncCheckExtension(dpy, info, False);
LockDisplay(dpy);
GetReq(SyncDestroyCounter, req);
req->reqType = info->codes->major_opcode;
req->syncReqType = X_SyncDestroyCounter;
req->counter = counter;
UnlockDisplay(dpy);
SyncHandle();
return True;
}
Status
XSyncQueryCounter(Display *dpy, XSyncCounter counter, XSyncValue *value_return)
{
XExtDisplayInfo *info = find_display(dpy);
xSyncQueryCounterReply rep;
xSyncQueryCounterReq *req;
SyncCheckExtension(dpy, info, False);
LockDisplay(dpy);
GetReq(SyncQueryCounter, req);
req->reqType = info->codes->major_opcode;
req->syncReqType = X_SyncQueryCounter;
req->counter = counter;
if (!_XReply(dpy, (xReply *) & rep, 0, xTrue))
{
UnlockDisplay(dpy);
SyncHandle();
return False;
}
XSyncIntsToValue(value_return, rep.value_lo, rep.value_hi);
UnlockDisplay(dpy);
SyncHandle();
return True;
}
Status
XSyncAwait(Display *dpy, XSyncWaitCondition *wait_list, int n_conditions)
{
XExtDisplayInfo *info = find_display(dpy);
XSyncWaitCondition *wait_item = wait_list;
xSyncAwaitReq *req;
unsigned int len;
SyncCheckExtension(dpy, info, False);
LockDisplay(dpy);
GetReq(SyncAwait, req);
req->reqType = info->codes->major_opcode;
req->syncReqType = X_SyncAwait;
len = (n_conditions * SIZEOF(xSyncWaitCondition)) >> 2;
SetReqLen(req, len, len );
while (n_conditions--)
{
xSyncWaitCondition wc;
wc.counter = wait_item->trigger.counter;
wc.value_type = wait_item->trigger.value_type;
wc.wait_value_lo = XSyncValueLow32(wait_item->trigger.wait_value);
wc.wait_value_hi = XSyncValueHigh32(wait_item->trigger.wait_value);
wc.test_type = wait_item->trigger.test_type;
wc.event_threshold_lo = XSyncValueLow32(wait_item->event_threshold);
wc.event_threshold_hi = XSyncValueHigh32(wait_item->event_threshold);
Data(dpy, (char *)&wc, SIZEOF(xSyncWaitCondition));
wait_item++;
}
UnlockDisplay(dpy);
SyncHandle();
return True;
}
static void
_XProcessAlarmAttributes(Display *dpy, xSyncChangeAlarmReq *req,
unsigned long valuemask,
XSyncAlarmAttributes *attributes)
{
unsigned long values[32];
unsigned long *value = values;
unsigned int nvalues;
if (valuemask & XSyncCACounter)
*value++ = attributes->trigger.counter;
if (valuemask & XSyncCAValueType)
*value++ = attributes->trigger.value_type;
if (valuemask & XSyncCAValue)
{
*value++ = XSyncValueHigh32(attributes->trigger.wait_value);
*value++ = XSyncValueLow32(attributes->trigger.wait_value);
}
if (valuemask & XSyncCATestType)
*value++ = attributes->trigger.test_type;
if (valuemask & XSyncCADelta)
{
*value++ = XSyncValueHigh32(attributes->delta);
*value++ = XSyncValueLow32(attributes->delta);
}
if (valuemask & XSyncCAEvents)
*value++ = attributes->events;
req->length += (nvalues = value - values);
nvalues <<= 2;
Data32(dpy, (long *) values, (long) nvalues);
}
XSyncAlarm
XSyncCreateAlarm(
Display *dpy,
unsigned long values_mask,
XSyncAlarmAttributes *values)
{
XExtDisplayInfo *info = find_display(dpy);
xSyncCreateAlarmReq *req;
XSyncAlarm aid;
SyncCheckExtension(dpy, info, False);
LockDisplay(dpy);
GetReq(SyncCreateAlarm, req);
req->reqType = info->codes->major_opcode;
req->syncReqType = X_SyncCreateAlarm;
req->id = aid = XAllocID(dpy);
values_mask &= XSyncCACounter | XSyncCAValueType | XSyncCAValue
| XSyncCATestType | XSyncCADelta | XSyncCAEvents;
if ((req->valueMask = values_mask))
_XProcessAlarmAttributes(dpy, (xSyncChangeAlarmReq *) req,
values_mask, values);
UnlockDisplay(dpy);
SyncHandle();
return aid;
}
Status
XSyncDestroyAlarm(Display *dpy, XSyncAlarm alarm)
{
XExtDisplayInfo *info = find_display(dpy);
xSyncDestroyAlarmReq *req;
SyncCheckExtension(dpy, info, False);
LockDisplay(dpy);
GetReq(SyncDestroyAlarm, req);
req->reqType = info->codes->major_opcode;
req->syncReqType = X_SyncDestroyAlarm;
req->alarm = alarm;
UnlockDisplay(dpy);
SyncHandle();
return True;
}
Status
XSyncQueryAlarm(
Display *dpy,
XSyncAlarm alarm,
XSyncAlarmAttributes *values_return)
{
XExtDisplayInfo *info = find_display(dpy);
xSyncQueryAlarmReq *req;
xSyncQueryAlarmReply rep;
SyncCheckExtension(dpy, info, False);
LockDisplay(dpy);
GetReq(SyncQueryAlarm, req);
req->reqType = info->codes->major_opcode;
req->syncReqType = X_SyncQueryAlarm;
req->alarm = alarm;
if (!(_XReply(dpy, (xReply *) & rep,
((SIZEOF(xSyncQueryAlarmReply) - SIZEOF(xGenericReply)) >> 2), xFalse)))
{
UnlockDisplay(dpy);
SyncHandle();
return False;
}
values_return->trigger.counter = rep.counter;
values_return->trigger.value_type = (XSyncValueType)rep.value_type;
XSyncIntsToValue(&values_return->trigger.wait_value,
rep.wait_value_lo, rep.wait_value_hi);
values_return->trigger.test_type = (XSyncTestType)rep.test_type;
XSyncIntsToValue(&values_return->delta, rep.delta_lo,
rep.delta_hi);
values_return->events = rep.events;
values_return->state = (XSyncAlarmState)rep.state;
UnlockDisplay(dpy);
SyncHandle();
return True;
}
Status
XSyncChangeAlarm(
Display *dpy,
XSyncAlarm alarm,
unsigned long values_mask,
XSyncAlarmAttributes *values)
{
XExtDisplayInfo *info = find_display(dpy);
xSyncChangeAlarmReq *req;
SyncCheckExtension(dpy, info, False);
LockDisplay(dpy);
GetReq(SyncChangeAlarm, req);
req->reqType = info->codes->major_opcode;
req->syncReqType = X_SyncChangeAlarm;
req->alarm = alarm;
values_mask &= XSyncCACounter | XSyncCAValueType | XSyncCAValue
| XSyncCATestType | XSyncCADelta | XSyncCAEvents;
if ((req->valueMask = values_mask))
_XProcessAlarmAttributes(dpy, req, values_mask, values);
UnlockDisplay(dpy);
SyncHandle();
return True;
}
Status
XSyncSetPriority(
Display *dpy,
XID client_resource_id,
int priority)
{
XExtDisplayInfo *info = find_display(dpy);
xSyncSetPriorityReq *req;
SyncCheckExtension(dpy, info, False);
LockDisplay(dpy);
GetReq(SyncSetPriority, req);
req->reqType = info->codes->major_opcode;
req->syncReqType = X_SyncSetPriority;
req->id = client_resource_id;
req->priority = priority;
UnlockDisplay(dpy);
SyncHandle();
return True;
}
Status
XSyncGetPriority(Display *dpy, XID client_resource_id, int *return_priority)
{
XExtDisplayInfo *info = find_display(dpy);
xSyncGetPriorityReply rep;
xSyncGetPriorityReq *req;
SyncCheckExtension(dpy, info, False);
LockDisplay(dpy);
GetReq(SyncGetPriority, req);
req->reqType = info->codes->major_opcode;
req->syncReqType = X_SyncGetPriority;
req->id = client_resource_id;
if (!_XReply(dpy, (xReply *) & rep, 0, xFalse))
{
UnlockDisplay(dpy);
SyncHandle();
return False;
}
if (return_priority)
*return_priority = rep.priority;
UnlockDisplay(dpy);
SyncHandle();
return True;
}
#undef XSyncIntToValue
#undef XSyncIntsToValue
#undef XSyncValueGreaterThan
#undef XSyncValueLessThan
#undef XSyncValueGreaterOrEqual
#undef XSyncValueLessOrEqual
#undef XSyncValueEqual
#undef XSyncValueIsNegative
#undef XSyncValueIsZero
#undef XSyncValueIsPositive
#undef XSyncValueLow32
#undef XSyncValueHigh32
#undef XSyncValueAdd
#undef XSyncValueSubtract
#undef XSyncMaxValue
#undef XSyncMinValue
void
XSyncIntToValue(XSyncValue *pv, int i)
{
_XSyncIntToValue(pv,i);
}
void
XSyncIntsToValue(XSyncValue *pv, unsigned int l, int h)
{
_XSyncIntsToValue(pv, l, h);
}
Bool
XSyncValueGreaterThan(XSyncValue a, XSyncValue b)
{
return _XSyncValueGreaterThan(a, b);
}
Bool
XSyncValueLessThan(XSyncValue a, XSyncValue b)
{
return _XSyncValueLessThan(a, b);
}
Bool
XSyncValueGreaterOrEqual(XSyncValue a, XSyncValue b)
{
return _XSyncValueGreaterOrEqual(a, b);
}
Bool
XSyncValueLessOrEqual(XSyncValue a, XSyncValue b)
{
return _XSyncValueLessOrEqual(a, b);
}
Bool
XSyncValueEqual(XSyncValue a, XSyncValue b)
{
return _XSyncValueEqual(a, b);
}
Bool
XSyncValueIsNegative(XSyncValue v)
{
return _XSyncValueIsNegative(v);
}
Bool
XSyncValueIsZero(XSyncValue a)
{
return _XSyncValueIsZero(a);
}
Bool
XSyncValueIsPositive(XSyncValue v)
{
return _XSyncValueIsPositive(v);
}
unsigned int
XSyncValueLow32(XSyncValue v)
{
return _XSyncValueLow32(v);
}
int
XSyncValueHigh32(XSyncValue v)
{
return _XSyncValueHigh32(v);
}
void
XSyncValueAdd(XSyncValue *presult, XSyncValue a, XSyncValue b, Bool *poverflow)
{
_XSyncValueAdd(presult, a, b, poverflow);
}
void
XSyncValueSubtract(
XSyncValue *presult,
XSyncValue a, XSyncValue b,
Bool *poverflow)
{
_XSyncValueSubtract(presult, a, b, poverflow);
}
void
XSyncMaxValue(XSyncValue *pv)
{
_XSyncMaxValue(pv);
}
void
XSyncMinValue(XSyncValue *pv)
{
_XSyncMinValue(pv);
}