BOOL DRI3DmaBufFromPixmap(Display *dpy, Pixmap pixmap, int *fd, int *width, int *height, int *stride, int *depth, int *bpp) { xcb_connection_t *xcb_connection = XGetXCBConnection(dpy); xcb_dri3_buffer_from_pixmap_cookie_t bp_cookie; xcb_dri3_buffer_from_pixmap_reply_t *bp_reply; bp_cookie = xcb_dri3_buffer_from_pixmap(xcb_connection, pixmap); bp_reply = xcb_dri3_buffer_from_pixmap_reply(xcb_connection, bp_cookie, NULL); if (!bp_reply) return FALSE; *fd = xcb_dri3_buffer_from_pixmap_reply_fds(xcb_connection, bp_reply)[0]; *width = bp_reply->width; *height = bp_reply->height; *stride = bp_reply->stride; *depth = bp_reply->depth; *bpp = bp_reply->depth; return TRUE; }
static struct vl_dri3_buffer * dri3_get_front_buffer(struct vl_dri3_screen *scrn) { xcb_dri3_buffer_from_pixmap_cookie_t bp_cookie; xcb_dri3_buffer_from_pixmap_reply_t *bp_reply; xcb_sync_fence_t sync_fence; struct xshmfence *shm_fence; int fence_fd, *fds; struct winsys_handle whandle; struct pipe_resource templ, *texture = NULL; if (scrn->front_buffer) { pipe_resource_reference(&texture, scrn->front_buffer->texture); return scrn->front_buffer; } scrn->front_buffer = CALLOC_STRUCT(vl_dri3_buffer); if (!scrn->front_buffer) return NULL; fence_fd = xshmfence_alloc_shm(); if (fence_fd < 0) goto free_buffer; shm_fence = xshmfence_map_shm(fence_fd); if (!shm_fence) goto close_fd; bp_cookie = xcb_dri3_buffer_from_pixmap(scrn->conn, scrn->drawable); bp_reply = xcb_dri3_buffer_from_pixmap_reply(scrn->conn, bp_cookie, NULL); if (!bp_reply) goto unmap_shm; fds = xcb_dri3_buffer_from_pixmap_reply_fds(scrn->conn, bp_reply); if (fds[0] < 0) goto free_reply; memset(&whandle, 0, sizeof(whandle)); whandle.type = DRM_API_HANDLE_TYPE_FD; whandle.handle = (unsigned)fds[0]; whandle.stride = bp_reply->stride; memset(&templ, 0, sizeof(templ)); templ.bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW; templ.format = PIPE_FORMAT_B8G8R8X8_UNORM; templ.target = PIPE_TEXTURE_2D; templ.last_level = 0; templ.width0 = bp_reply->width; templ.height0 = bp_reply->height; templ.depth0 = 1; templ.array_size = 1; scrn->front_buffer->texture = scrn->base.pscreen->resource_from_handle(scrn->base.pscreen, &templ, &whandle, PIPE_HANDLE_USAGE_READ_WRITE); close(fds[0]); if (!scrn->front_buffer->texture) goto free_reply; xcb_dri3_fence_from_fd(scrn->conn, scrn->drawable, (sync_fence = xcb_generate_id(scrn->conn)), false, fence_fd); pipe_resource_reference(&texture, scrn->front_buffer->texture); scrn->front_buffer->pixmap = scrn->drawable; scrn->front_buffer->width = bp_reply->width; scrn->front_buffer->height = bp_reply->height; scrn->front_buffer->shm_fence = shm_fence; scrn->front_buffer->sync_fence = sync_fence; free(bp_reply); return scrn->front_buffer; free_reply: free(bp_reply); unmap_shm: xshmfence_unmap_shm(shm_fence); close_fd: close(fence_fd); free_buffer: FREE(scrn->front_buffer); return NULL; }
/** dri3_get_pixmap_buffer * * Get the DRM object for a pixmap from the X server and * wrap that with a __DRIimage structure using createImageFromFds */ static struct loader_dri3_buffer * dri3_get_pixmap_buffer(__DRIdrawable *driDrawable, unsigned int format, enum loader_dri3_buffer_type buffer_type, struct loader_dri3_drawable *draw) { int buf_id = loader_dri3_pixmap_buf_id(buffer_type); struct loader_dri3_buffer *buffer = draw->buffers[buf_id]; xcb_drawable_t pixmap; xcb_dri3_buffer_from_pixmap_cookie_t bp_cookie; xcb_dri3_buffer_from_pixmap_reply_t *bp_reply; xcb_sync_fence_t sync_fence; struct xshmfence *shm_fence; int fence_fd; if (buffer) return buffer; pixmap = draw->drawable; buffer = calloc(1, sizeof *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(draw->conn, pixmap, (sync_fence = xcb_generate_id(draw->conn)), false, fence_fd); bp_cookie = xcb_dri3_buffer_from_pixmap(draw->conn, pixmap); bp_reply = xcb_dri3_buffer_from_pixmap_reply(draw->conn, bp_cookie, NULL); if (!bp_reply) goto no_image; buffer->image = loader_dri3_create_image(draw->conn, bp_reply, format, draw->dri_screen, draw->ext->image, buffer); 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; draw->buffers[buf_id] = buffer; free(bp_reply); return buffer; no_image: free(bp_reply); xcb_sync_destroy_fence(draw->conn, sync_fence); xshmfence_unmap_shm(shm_fence); no_fence: free(buffer); no_buffer: return NULL; }
/** dri3_get_pixmap_buffer * * Get the DRM object for a pixmap from the X server and * wrap that with a __DRIimage structure using createImageFromFds */ static struct loader_dri3_buffer * dri3_get_pixmap_buffer(__DRIdrawable *driDrawable, unsigned int format, enum loader_dri3_buffer_type buffer_type, struct loader_dri3_drawable *draw) { int buf_id = loader_dri3_pixmap_buf_id(buffer_type); struct loader_dri3_buffer *buffer = draw->buffers[buf_id]; xcb_drawable_t pixmap; xcb_dri3_buffer_from_pixmap_cookie_t bp_cookie; xcb_dri3_buffer_from_pixmap_reply_t *bp_reply; xcb_sync_fence_t sync_fence; struct xshmfence *shm_fence; int fence_fd; __DRIscreen *cur_screen; if (buffer) return buffer; pixmap = draw->drawable; buffer = calloc(1, sizeof *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(draw->conn, pixmap, (sync_fence = xcb_generate_id(draw->conn)), false, fence_fd); bp_cookie = xcb_dri3_buffer_from_pixmap(draw->conn, pixmap); bp_reply = xcb_dri3_buffer_from_pixmap_reply(draw->conn, bp_cookie, NULL); if (!bp_reply) goto no_image; /* Get the currently-bound screen or revert to using the drawable's screen if * no contexts are currently bound. The latter case is at least necessary for * obs-studio, when using Window Capture (Xcomposite) as a Source. */ cur_screen = draw->vtable->get_dri_screen(draw); if (!cur_screen) { cur_screen = draw->dri_screen; } buffer->image = loader_dri3_create_image(draw->conn, bp_reply, format, cur_screen, draw->ext->image, buffer); 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; draw->buffers[buf_id] = buffer; free(bp_reply); return buffer; no_image: free(bp_reply); xcb_sync_destroy_fence(draw->conn, sync_fence); xshmfence_unmap_shm(shm_fence); no_fence: free(buffer); no_buffer: return NULL; }