- dpy = psc->base.dpy;
- c = XGetXCBConnection(dpy);
-
- buffer = calloc(1, sizeof (struct dri3_buffer));
- if (!buffer)
- goto no_buffer;
-
- fence_fd = xshmfence_alloc_shm();
- if (fence_fd < 0)
- goto no_fence;
- shm_fence = xshmfence_map_shm(fence_fd);
- if (shm_fence == NULL) {
- close (fence_fd);
- goto no_fence;
- }
-
- xcb_dri3_fence_from_fd(c,
- pixmap,
- (sync_fence = xcb_generate_id(c)),
- false,
- fence_fd);
-
- /* Get an FD for the pixmap object
- */
- bp_cookie = xcb_dri3_buffer_from_pixmap(c, pixmap);
- bp_reply = xcb_dri3_buffer_from_pixmap_reply(c, bp_cookie, NULL);
- if (!bp_reply)
- goto no_image;
- fds = xcb_dri3_buffer_from_pixmap_reply_fds(c, bp_reply);
-
- stride = bp_reply->stride;
- offset = 0;
-
- /* createImageFromFds creates a wrapper __DRIimage structure which
- * can deal with multiple planes for things like Yuv images. So, once
- * we've gotten the planar wrapper, pull the single plane out of it and
- * discard the wrapper.
- */
- image_planar = (*psc->image->createImageFromFds) (psc->driScreen,
- bp_reply->width,
- bp_reply->height,
- image_format_to_fourcc(format),
- fds, 1,
- &stride, &offset, buffer);
- close(fds[0]);
- if (!image_planar)
- goto no_image;
-
- buffer->image = (*psc->image->fromPlanar)(image_planar, 0, buffer);
-
- (*psc->image->destroyImage)(image_planar);
-
- if (!buffer->image)
- goto no_image;
-
- buffer->pixmap = pixmap;
- buffer->own_pixmap = false;
- buffer->width = bp_reply->width;
- buffer->height = bp_reply->height;
- buffer->buffer_type = buffer_type;
- buffer->shm_fence = shm_fence;
- buffer->sync_fence = sync_fence;
-
- pdraw->buffers[buf_id] = buffer;
- return buffer;
-
-no_image:
- xcb_sync_destroy_fence(c, sync_fence);
- xshmfence_unmap_shm(shm_fence);
-no_fence:
- free(buffer);
-no_buffer:
- return NULL;
-}
-
-/** dri3_find_back
- *
- * Find an idle back buffer. If there isn't one, then
- * wait for a present idle notify event from the X server
- */
-static int
-dri3_find_back(xcb_connection_t *c, struct dri3_drawable *priv)
-{
- int b;
- xcb_generic_event_t *ev;
- xcb_present_generic_event_t *ge;
-
- for (;;) {
- for (b = 0; b < priv->num_back; b++) {
- int id = DRI3_BACK_ID(b);
- struct dri3_buffer *buffer = priv->buffers[id];
-
- if (!buffer)
- return b;
- if (!buffer->busy)
- return b;
- }
- xcb_flush(c);
- ev = xcb_wait_for_special_event(c, priv->special_event);
- if (!ev)
- return -1;
- ge = (void *) ev;
- dri3_handle_present_event(priv, ge);
- }
-}
-
-/** dri3_get_buffer
- *
- * Find a front or back buffer, allocating new ones as necessary
- */
-static struct dri3_buffer *
-dri3_get_buffer(__DRIdrawable *driDrawable,
- unsigned int format,
- enum dri3_buffer_type buffer_type,
- void *loaderPrivate)
-{
- struct dri3_drawable *priv = loaderPrivate;
- xcb_connection_t *c = XGetXCBConnection(priv->base.psc->dpy);
- struct dri3_buffer *buffer;
- int buf_id;