mirror of
https://gitlab.freedesktop.org/xorg/lib/libx11.git
synced 2026-05-07 16:48:31 +02:00
Refactor the code that passes requests down to XCB into a separate issue_complete_request function.
This commit is contained in:
parent
67d06e0fe4
commit
41c0121a87
1 changed files with 102 additions and 46 deletions
|
|
@ -149,12 +149,103 @@ void _XGetXCBBuffer(Display *dpy)
|
|||
assert_sequence_less(dpy->last_request_read, dpy->request);
|
||||
}
|
||||
|
||||
static inline int issue_complete_request(Display *dpy, int veclen, struct iovec *vec)
|
||||
{
|
||||
XCBProtocolRequest xcb_req = { 0 };
|
||||
unsigned int sequence;
|
||||
int bigreq = 0;
|
||||
int i;
|
||||
CARD32 len;
|
||||
size_t rem;
|
||||
|
||||
/* skip empty iovecs. if no iovecs remain, we're done. */
|
||||
while(veclen > 0 && vec[0].iov_len == 0)
|
||||
--veclen, ++vec;
|
||||
if(!veclen)
|
||||
return 0;
|
||||
|
||||
/* we have at least part of a request. dig out the length field.
|
||||
* note that length fields are always in vec[0]: Xlib doesn't split
|
||||
* fixed-length request parts. */
|
||||
len = ((CARD16 *) vec[0].iov_base)[1];
|
||||
if(len == 0)
|
||||
{
|
||||
/* it's a bigrequest. dig out the *real* length field. */
|
||||
len = ((CARD32 *) vec[0].iov_base)[1];
|
||||
bigreq = 1;
|
||||
}
|
||||
|
||||
/* do we have enough data for a complete request? how many iovec
|
||||
* elements does it span? */
|
||||
for(i = 0; i < veclen; ++i)
|
||||
{
|
||||
CARD32 oldlen = len;
|
||||
len -= (vec[i].iov_len + 3) >> 2;
|
||||
/* if len is now 0 or has wrapped, we have enough data. */
|
||||
if((len - 1) > oldlen)
|
||||
break;
|
||||
}
|
||||
if(i == veclen)
|
||||
return 0;
|
||||
|
||||
/* we have enough data to issue one complete request. the remaining
|
||||
* code can't fail. */
|
||||
|
||||
/* len says how far we overshot our data needs in 4-byte units.
|
||||
* (it's negative if we actually overshot, or 0 if we're right on.)
|
||||
* rem is overshoot in 1-byte units, so it needs to have trailing
|
||||
* padding subtracted off if we're not using that padding in this
|
||||
* request. */
|
||||
if(len)
|
||||
rem = (-len << 2) - (-vec[i].iov_len & 3);
|
||||
else
|
||||
rem = 0;
|
||||
vec[i].iov_len -= rem;
|
||||
xcb_req.count = i + 1;
|
||||
xcb_req.opcode = ((CARD8 *) vec[0].iov_base)[0];
|
||||
|
||||
/* undo bigrequest formatting. XCBSendRequest will redo it. */
|
||||
if(bigreq)
|
||||
{
|
||||
CARD32 *p = vec[0].iov_base;
|
||||
p[1] = p[0];
|
||||
vec[0].iov_base = (char *) vec[0].iov_base + 4;
|
||||
vec[0].iov_len -= 4;
|
||||
}
|
||||
|
||||
/* send the accumulated request. */
|
||||
XCBSendRequest(XCBConnectionOfDisplay(dpy), &sequence, vec, &xcb_req);
|
||||
|
||||
/* update the iovecs to refer only to data not yet sent. */
|
||||
vec[i].iov_base = (char *) vec[i].iov_base + vec[i].iov_len;
|
||||
vec[i].iov_len = rem;
|
||||
while(--i >= 0)
|
||||
vec[i].iov_len = 0;
|
||||
|
||||
/* For requests we issue, we need to get back replies and
|
||||
* errors. That's true even if we don't own the event queue, and
|
||||
* also if there are async handlers registered. If we do own the
|
||||
* event queue then errors can be handled elsewhere more
|
||||
* cheaply; and if there aren't any async handlers (but the
|
||||
* pure-Xlib code was correct) then there won't be any replies
|
||||
* so we needn't look for them. */
|
||||
if(dpy->xcl->event_owner != XlibOwnsEventQueue || dpy->async_handlers)
|
||||
{
|
||||
PendingRequest *req = malloc(sizeof(PendingRequest));
|
||||
assert(req);
|
||||
req->next = 0;
|
||||
req->sequence = sequence;
|
||||
*dpy->xcl->pending_requests_tail = req;
|
||||
dpy->xcl->pending_requests_tail = &req->next;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void _XPutXCBBuffer(Display *dpy)
|
||||
{
|
||||
XCBConnection *c = XCBConnectionOfDisplay(dpy);
|
||||
_XExtension *ext;
|
||||
XCBProtocolRequest xcb_req = { /* count */ 1 };
|
||||
char *bufptr = dpy->buffer;
|
||||
struct iovec iov[2];
|
||||
|
||||
assert_sequence_less(dpy->last_request_read, dpy->request);
|
||||
assert_sequence_less(XCBGetRequestSent(c), dpy->request);
|
||||
|
|
@ -172,53 +263,18 @@ void _XPutXCBBuffer(Display *dpy)
|
|||
}
|
||||
}
|
||||
|
||||
while(bufptr < dpy->bufptr)
|
||||
{
|
||||
struct iovec iov[2];
|
||||
unsigned int sequence;
|
||||
CARD32 len = ((CARD16 *) bufptr)[1];
|
||||
if(len == 0)
|
||||
len = ((CARD32 *) bufptr)[1];
|
||||
iov[0].iov_base = dpy->buffer;
|
||||
iov[0].iov_len = dpy->bufptr - dpy->buffer;
|
||||
iov[1].iov_base = (caddr_t) dpy->xcl->request_extra;
|
||||
iov[1].iov_len = dpy->xcl->request_extra_size;
|
||||
|
||||
xcb_req.opcode = bufptr[0];
|
||||
iov[0].iov_base = (caddr_t) bufptr;
|
||||
iov[0].iov_len = len << 2;
|
||||
while(issue_complete_request(dpy, 2, iov))
|
||||
/* empty */;
|
||||
|
||||
/* if we have extra request data and this is the last request
|
||||
* in the buffer, send the extra data along with this request. */
|
||||
if(bufptr == dpy->last_req && dpy->xcl->request_extra && dpy->xcl->request_extra_size)
|
||||
{
|
||||
xcb_req.count = 2;
|
||||
iov[1].iov_base = (void *) dpy->xcl->request_extra;
|
||||
iov[1].iov_len = dpy->xcl->request_extra_size;
|
||||
iov[0].iov_len -= iov[1].iov_len;
|
||||
iov[0].iov_len &= ~3;
|
||||
dpy->xcl->request_extra = 0;
|
||||
assert(bufptr + iov[0].iov_len == dpy->bufptr);
|
||||
}
|
||||
assert(iov[0].iov_len == 0 && iov[1].iov_len == 0);
|
||||
|
||||
bufptr += iov[0].iov_len;
|
||||
assert(bufptr <= dpy->bufptr);
|
||||
|
||||
XCBSendRequest(c, &sequence, iov, &xcb_req);
|
||||
|
||||
/* For requests we issue, we need to get back replies and
|
||||
* errors. That's true even if we don't own the event queue, and
|
||||
* also if there are async handlers registered. If we do own the
|
||||
* event queue then errors can be handled elsewhere more
|
||||
* cheaply; and if there aren't any async handlers (but the
|
||||
* pure-Xlib code was correct) then there won't be any replies
|
||||
* so we needn't look for them. */
|
||||
if(dpy->xcl->event_owner != XlibOwnsEventQueue || dpy->async_handlers)
|
||||
{
|
||||
PendingRequest *req = malloc(sizeof(PendingRequest));
|
||||
assert(req);
|
||||
req->next = 0;
|
||||
req->sequence = sequence;
|
||||
*dpy->xcl->pending_requests_tail = req;
|
||||
dpy->xcl->pending_requests_tail = &req->next;
|
||||
}
|
||||
}
|
||||
dpy->xcl->request_extra = 0;
|
||||
dpy->xcl->request_extra_size = 0;
|
||||
dpy->bufptr = dpy->buffer;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue