c0ef82fb880485f142276b88a2770cd91b170f5d
[profile/ivi/ecore.git] / src / lib / ecore_x / xcb / ecore_xcb_sync.c
1 #include "ecore_xcb_private.h"
2
3 /**
4  * @defgroup Ecore_X_Sync_Group X Sync Extension Functions
5  *
6  * Functions related to the X Sync extension.
7  */
8
9 #ifdef ECORE_XCB_SYNC
10 static int _sync_available = 0;
11 static xcb_sync_initialize_cookie_t _ecore_xcb_sync_init_cookie;
12 #endif /* ECORE_XCB_SYNC */
13
14 /* To avoid round trips, the initialization is separated in 2
15    functions: _ecore_xcb_sync_init and
16    _ecore_xcb_sync_init_finalize. The first one gets the cookies and
17    the second one gets the replies and set the atoms. */
18
19 void
20 _ecore_x_sync_init(const xcb_query_extension_reply_t *reply)
21 {
22 #ifdef ECORE_XCB_SYNC
23    if (reply && (reply->present))
24       _ecore_xcb_sync_init_cookie = xcb_sync_initialize_unchecked(_ecore_xcb_conn,
25                                                                   XCB_SYNC_MAJOR_VERSION,
26                                                                   XCB_SYNC_MINOR_VERSION);
27
28 #endif /* ECORE_XCB_SYNC */
29 } /* _ecore_x_sync_init */
30
31 void
32 _ecore_x_sync_init_finalize(void)
33 {
34 #ifdef ECORE_XCB_SYNC
35    xcb_sync_initialize_reply_t *reply;
36
37    reply = xcb_sync_initialize_reply(_ecore_xcb_conn,
38                                      _ecore_xcb_sync_init_cookie, NULL);
39
40    if (reply)
41      {
42         if (reply->major_version >= 3)
43            _sync_available = 1;
44
45         free(reply);
46      }
47
48 #endif /* ECORE_XCB_SYNC */
49 } /* _ecore_x_sync_init_finalize */
50
51 /**
52  * Return whether the X server supports the Sync Extension.
53  * @return 1 if the X Sync Extension is available, 0 otherwise.
54  *
55  * Return 1 if the X server supports the Sync Extension version 3.0,
56  * 0 otherwise.
57  * @ingroup Ecore_X_Sync_Group
58  */
59 EAPI int
60 ecore_x_sync_query(void)
61 {
62 #ifdef ECORE_XCB_SYNC
63    return _sync_available;
64 #else /* ifdef ECORE_XCB_SYNC */
65    return 0;
66 #endif /* ECORE_XCB_SYNC */
67 } /* ecore_x_sync_query */
68
69 /**
70  * Create a new alarm.
71  * @param counter A counter.
72  * @return        A newly created alarm.
73  *
74  * Create a new alarm.
75  * @ingroup Ecore_X_Sync_Group
76  */
77 EAPI Ecore_X_Sync_Alarm
78 ecore_x_sync_alarm_new(Ecore_X_Sync_Counter counter)
79 {
80 #ifdef ECORE_XCB_SYNC
81    uint32_t value_list[6];
82    xcb_sync_int64_t init;
83    Ecore_X_Sync_Alarm alarm;
84    uint32_t value_mask;
85
86    init.lo = 0;
87    init.hi = 0;
88    xcb_sync_set_counter(_ecore_xcb_conn, counter, init);
89
90    value_mask =
91       XCB_SYNC_CA_COUNTER | XCB_SYNC_CA_VALUE_TYPE |
92       XCB_SYNC_CA_VALUE | XCB_SYNC_CA_TEST_TYPE |
93       XCB_SYNC_CA_DELTA | XCB_SYNC_CA_EVENTS;
94    value_list[0] = counter;
95    value_list[1] = XCB_SYNC_VALUETYPE_ABSOLUTE;
96    value_list[2] = 1;
97    value_list[3] = XCB_SYNC_TESTTYPE_POSITIVE_COMPARISON;
98    value_list[4] = 1;
99    value_list[5] = 1;
100    alarm = xcb_generate_id(_ecore_xcb_conn);
101    xcb_sync_create_alarm(_ecore_xcb_conn,
102                          alarm,
103                          value_mask,
104                          (const uint32_t *)value_list);
105
106    ecore_x_sync();
107    return alarm;
108 #else /* ifdef ECORE_XCB_SYNC */
109    return 0;
110 #endif /* ECORE_XCB_SYNC */
111 } /* ecore_x_sync_alarm_new */
112
113 /**
114  * Delete an alarm.
115  * @param alarm The alarm to delete.
116  * @return      1 on success, 0 otherwise.
117  *
118  * Delete the @p alarm. Returns 1 on success, 0 otherwise.
119  * @ingroup Ecore_X_Sync_Group
120  */
121 EAPI int
122 ecore_x_sync_alarm_free(Ecore_X_Sync_Alarm alarm)
123 {
124 #ifdef ECORE_XCB_SYNC
125    xcb_sync_destroy_alarm(_ecore_xcb_conn, alarm);
126    return 1;
127 #else /* ifdef ECORE_XCB_SYNC */
128    return 0;
129 #endif /* ECORE_XCB_SYNC */
130 } /* ecore_x_sync_alarm_free */
131
132 /* FIXME: round trip */
133
134 EAPI int
135 ecore_x_sync_counter_query(Ecore_X_Sync_Counter counter, unsigned int *val)
136 {
137 #ifdef ECORE_XCB_SYNC
138    xcb_sync_query_counter_cookie_t cookie;
139    xcb_sync_query_counter_reply_t *reply;
140
141    cookie = xcb_sync_query_counter_unchecked(_ecore_xcb_conn, counter);
142    reply = xcb_sync_query_counter_reply(_ecore_xcb_conn, cookie, NULL);
143    if (reply)
144      {
145         *val = (unsigned int)reply->counter_value.lo;
146         free(reply);
147         return 1;
148      }
149
150 #endif /* ECORE_XCB_SYNC */
151
152    return 0;
153 } /* ecore_x_sync_counter_query */
154
155 EAPI Ecore_X_Sync_Counter
156 ecore_x_sync_counter_new(int val)
157 {
158 #ifdef ECORE_XCB_SYNC
159    xcb_sync_counter_t counter;
160    xcb_sync_int64_t v;
161
162    counter = xcb_generate_id(_ecore_xcb_conn);
163    v.hi = (val < 0) ? ~0 : 0;
164    v.lo = val;
165    xcb_sync_create_counter(_ecore_xcb_conn, counter, v);
166    return counter;
167 #else  /* ! ECORE_XCB_SYNC */
168    return 0;
169 #endif /* ! ECORE_XCB_SYNC */
170 } /* ecore_x_sync_counter_new */
171
172 EAPI void
173 ecore_x_sync_counter_free(Ecore_X_Sync_Counter counter)
174 {
175 #ifdef ECORE_XCB_SYNC
176    xcb_sync_destroy_counter(_ecore_xcb_conn, counter);
177 #endif /* ECORE_XCB_SYNC */
178 } /* ecore_x_sync_counter_free */
179
180 EAPI void
181 ecore_x_sync_counter_inc(Ecore_X_Sync_Counter counter, int by)
182 {
183 #ifdef ECORE_XCB_SYNC
184    xcb_sync_int64_t v;
185
186    v.hi = (by < 0) ? ~0 : 0;
187    v.lo = by;
188    xcb_sync_change_counter(_ecore_xcb_conn, counter, v);
189 #endif /* ECORE_XCB_SYNC */
190 } /* ecore_x_sync_counter_inc */
191
192 EAPI void
193 ecore_x_sync_counter_val_wait(Ecore_X_Sync_Counter counter, int val)
194 {
195 #ifdef ECORE_XCB_SYNC
196    xcb_sync_query_counter_cookie_t cookie;
197    xcb_sync_query_counter_reply_t *reply;
198    xcb_sync_int64_t v1;
199    xcb_sync_int64_t v2;
200    xcb_sync_waitcondition_t cond;
201
202    /* what's the purpose of that call ?? as the value is erased... */
203    cookie = xcb_sync_query_counter_unchecked(_ecore_xcb_conn, counter);
204    reply = xcb_sync_query_counter_reply(_ecore_xcb_conn, cookie, NULL);
205    v1 = reply->counter_value;
206    free(reply);
207
208    v1.hi = (val < 0) ? ~0 : 0;
209    v1.lo = val;
210    v2.hi = ((val + 1) < 0) ? ~0 : 0;
211    v2.lo = val + 1;
212    cond.trigger.counter = counter;
213    cond.trigger.wait_type = XCB_SYNC_VALUETYPE_ABSOLUTE;
214    cond.trigger.wait_value = v1;
215    cond.trigger.test_type = XCB_SYNC_TESTTYPE_POSITIVE_COMPARISON;
216    cond.event_threshold = v2;
217
218    xcb_sync_await(_ecore_xcb_conn, 1, (const xcb_sync_waitcondition_t *)&cond);
219 #endif /* ECORE_XCB_SYNC */
220 } /* ecore_x_sync_counter_val_wait */
221