1
/* Copyright (C) 2003-2006 Jamey Sharp, Josh Triplett
2
* This file is licensed under the MIT license. See the file COPYING. */
11
#include <xcb/xcbext.h>
12
#include <xcb/xcbxlib.h>
16
static void _XCBLockDisplay(Display *dpy)
18
if(dpy->xcb->lock_fns.lock_display)
19
dpy->xcb->lock_fns.lock_display(dpy);
20
if(!dpy->lock || dpy->lock->locking_level == 0)
21
xcb_xlib_lock(dpy->xcb->connection);
22
if(!(dpy->flags & XlibDisplayIOError))
26
/* XXX: If you change this function, update _XReply's copy of its guts! */
27
static void _XCBUnlockDisplay(Display *dpy)
29
if(!(dpy->flags & XlibDisplayIOError))
32
assert(dpy->xcb->partial_request == 0);
33
assert(xcb_get_request_sent(dpy->xcb->connection) == dpy->request);
35
/* Traditional Xlib does this in _XSend; see the Xlib/XCB version
36
* of that function for why we do it here instead. */
37
_XSetSeqSyncFunction(dpy);
40
if(!dpy->lock || dpy->lock->locking_level == 0)
41
xcb_xlib_unlock(dpy->xcb->connection);
42
if(dpy->xcb->lock_fns.unlock_display)
43
dpy->xcb->lock_fns.unlock_display(dpy);
46
int _XCBInitDisplayLock(Display *dpy)
48
if(!dpy->lock_fns && !(dpy->lock_fns = Xcalloc(1, sizeof(*dpy->lock_fns))))
50
dpy->xcb->lock_fns.lock_display = dpy->lock_fns->lock_display;
51
dpy->lock_fns->lock_display = _XCBLockDisplay;
52
dpy->xcb->lock_fns.unlock_display = dpy->lock_fns->unlock_display;
53
dpy->lock_fns->unlock_display = _XCBUnlockDisplay;
57
void _XCBShutdownDisplayLock(Display *dpy)
60
Xfree((char *)dpy->lock_fns);
65
void _XGetXCBBuffer(Display *dpy)
67
static const xReq dummy_request;
68
unsigned int xcb_req = xcb_get_request_sent(dpy->xcb->connection);
69
if(xcb_connection_has_error(dpy->xcb->connection))
72
/* if Xlib has a partial request pending then XCB doesn't know about
73
* the current request yet */
74
if(dpy->xcb->partial_request)
77
assert(XCB_SEQUENCE_COMPARE(xcb_req, >=, dpy->request));
78
dpy->request = xcb_req;
80
dpy->last_req = (char *) &dummy_request;
83
static size_t request_length(struct iovec *vec)
85
/* we have at least part of a request. dig out the length field.
86
* note that length fields are always in vec[0]: Xlib doesn't split
87
* fixed-length request parts. */
89
assert(vec[0].iov_len >= 4);
90
len = ((uint16_t *) vec[0].iov_base)[1];
93
/* it's a bigrequest. dig out the *real* length field. */
94
assert(vec[0].iov_len >= 8);
95
len = ((uint32_t *) vec[0].iov_base)[1];
100
static inline int issue_complete_request(Display *dpy, int veclen, struct iovec *vec)
102
xcb_protocol_request_t xcb_req = { 0 };
103
unsigned int sequence;
104
int flags = XCB_REQUEST_RAW;
108
/* skip empty iovecs. if no iovecs remain, we're done. */
110
while(veclen > 0 && vec[0].iov_len == 0)
115
len = request_length(vec);
117
/* do we have enough data for a complete request? how many iovec
118
* elements does it span? */
119
for(i = 0; i < veclen; ++i)
122
len -= vec[i].iov_len;
123
/* if len is now 0 or has wrapped, we have enough data. */
124
if((len - 1) > oldlen)
130
/* we have enough data to issue one complete request. the remaining
131
* code can't fail. */
133
/* len says how far we overshot our data needs. (it's "negative" if
134
* we actually overshot, or 0 if we're right on.) */
135
vec[i].iov_len += len;
136
xcb_req.count = i + 1;
137
xcb_req.opcode = ((uint8_t *) vec[0].iov_base)[0];
139
/* if we don't own the event queue, we have to ask XCB to set our
140
* errors aside for us. */
141
if(dpy->xcb->event_owner != XlibOwnsEventQueue)
142
flags |= XCB_REQUEST_CHECKED;
144
/* XCB will always skip request 0; account for that in the Xlib count */
145
if (xcb_get_request_sent(dpy->xcb->connection) == 0xffffffff)
147
/* send the accumulated request. */
148
sequence = xcb_send_request(dpy->xcb->connection, flags, vec, &xcb_req);
152
/* update the iovecs to refer only to data not yet sent. */
153
vec[i].iov_len = -len;
155
/* iff we asked XCB to set aside errors, we must pick those up
156
* eventually. iff there are async handlers, we may have just
157
* issued requests that will generate replies. in either case,
158
* we need to remember to check later. */
159
if(flags & XCB_REQUEST_CHECKED || dpy->async_handlers)
161
PendingRequest *req = malloc(sizeof(PendingRequest));
165
req->sequence = sequence;
166
*dpy->xcb->pending_requests_tail = req;
167
dpy->xcb->pending_requests_tail = &req->next;
172
void _XPutXCBBuffer(Display *dpy)
174
static char const pad[3];
175
const int padsize = -dpy->xcb->request_extra_size & 3;
176
xcb_connection_t *c = dpy->xcb->connection;
180
assert_sequence_less(dpy->last_request_read, dpy->request);
181
assert_sequence_less(xcb_get_request_sent(c), dpy->request);
183
for(ext = dpy->flushes; ext; ext = ext->next_flush)
185
ext->before_flush(dpy, &ext->codes, dpy->buffer, dpy->bufptr - dpy->buffer);
186
if(dpy->xcb->request_extra)
188
ext->before_flush(dpy, &ext->codes, dpy->xcb->request_extra, dpy->xcb->request_extra_size);
190
ext->before_flush(dpy, &ext->codes, pad, padsize);
194
iov[2].iov_base = dpy->xcb->partial_request;
195
iov[2].iov_len = dpy->xcb->partial_request_offset;
196
iov[3].iov_base = dpy->buffer;
197
iov[3].iov_len = dpy->bufptr - dpy->buffer;
198
iov[4].iov_base = (caddr_t) dpy->xcb->request_extra;
199
iov[4].iov_len = dpy->xcb->request_extra_size;
200
iov[5].iov_base = (caddr_t) pad;
201
iov[5].iov_len = padsize;
203
while(issue_complete_request(dpy, 4, iov + 2))
206
/* first discard any completed partial_request. */
207
if(iov[2].iov_len == 0 && dpy->xcb->partial_request)
209
free(dpy->xcb->partial_request);
210
dpy->xcb->partial_request = 0;
211
dpy->xcb->partial_request_offset = 0;
214
/* is there anything to copy into partial_request? */
215
if(iov[3].iov_len != 0 || iov[4].iov_len != 0 || iov[5].iov_len != 0)
218
if(!dpy->xcb->partial_request)
220
size_t len = request_length(iov + 3);
221
assert(!dpy->xcb->partial_request_offset);
222
dpy->xcb->partial_request = malloc(len);
223
assert(dpy->xcb->partial_request);
225
for(i = 3; i < sizeof(iov) / sizeof(*iov); ++i)
227
memcpy(dpy->xcb->partial_request + dpy->xcb->partial_request_offset, iov[i].iov_base, iov[i].iov_len);
228
dpy->xcb->partial_request_offset += iov[i].iov_len;
232
dpy->xcb->request_extra = 0;
233
dpy->xcb->request_extra_size = 0;
234
dpy->bufptr = dpy->buffer;