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 = WINSYS_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 = vl_dri2_format_for_depth(&scrn->base, bp_reply->depth); 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_FRAMEBUFFER_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; }
static struct pipe_resource * vl_dri2_screen_texture_from_drawable(struct vl_screen *vscreen, void *drawable) { struct vl_dri_screen *scrn = (struct vl_dri_screen *)vscreen; struct winsys_handle dri2_handle; struct pipe_resource templ, *tex; xcb_dri2_get_buffers_reply_t *reply; xcb_dri2_dri2_buffer_t *buffers, *back_left; unsigned depth = ((xcb_screen_t *)(vscreen->xcb_screen))->root_depth; unsigned i; assert(scrn); vl_dri2_set_drawable(scrn, (Drawable)drawable); reply = vl_dri2_get_flush_reply(scrn); if (!reply) { xcb_dri2_get_buffers_cookie_t cookie; cookie = xcb_dri2_get_buffers_unchecked(scrn->conn, (Drawable)drawable, 1, 1, attachments); reply = xcb_dri2_get_buffers_reply(scrn->conn, cookie, NULL); } if (!reply) return NULL; buffers = xcb_dri2_get_buffers_buffers(reply); if (!buffers) { free(reply); return NULL; } for (i = 0; i < reply->count; ++i) { if (buffers[i].attachment == XCB_DRI2_ATTACHMENT_BUFFER_BACK_LEFT) { back_left = &buffers[i]; break; } } if (i == reply->count) { free(reply); return NULL; } if (reply->width != scrn->width || reply->height != scrn->height) { vl_compositor_reset_dirty_area(&scrn->dirty_areas[0]); vl_compositor_reset_dirty_area(&scrn->dirty_areas[1]); scrn->width = reply->width; scrn->height = reply->height; } else if (back_left->name != scrn->buffer_names[scrn->current_buffer]) { vl_compositor_reset_dirty_area(&scrn->dirty_areas[scrn->current_buffer]); scrn->buffer_names[scrn->current_buffer] = back_left->name; } memset(&dri2_handle, 0, sizeof(dri2_handle)); dri2_handle.type = WINSYS_HANDLE_TYPE_SHARED; dri2_handle.handle = back_left->name; dri2_handle.stride = back_left->pitch; memset(&templ, 0, sizeof(templ)); templ.target = PIPE_TEXTURE_2D; templ.format = vl_dri2_format_for_depth(vscreen, depth); templ.last_level = 0; templ.width0 = reply->width; templ.height0 = reply->height; templ.depth0 = 1; templ.array_size = 1; templ.usage = PIPE_USAGE_DEFAULT; templ.bind = PIPE_BIND_RENDER_TARGET; templ.flags = 0; tex = scrn->base.pscreen->resource_from_handle(scrn->base.pscreen, &templ, &dri2_handle, PIPE_HANDLE_USAGE_READ_WRITE); free(reply); return tex; }
static struct vl_dri3_buffer * dri3_alloc_back_buffer(struct vl_dri3_screen *scrn) { struct vl_dri3_buffer *buffer; xcb_pixmap_t pixmap; xcb_sync_fence_t sync_fence; struct xshmfence *shm_fence; int buffer_fd, fence_fd; struct pipe_resource templ, *pixmap_buffer_texture; struct winsys_handle whandle; unsigned usage; buffer = CALLOC_STRUCT(vl_dri3_buffer); if (!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; memset(&templ, 0, sizeof(templ)); templ.bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW; templ.format = vl_dri2_format_for_depth(&scrn->base, scrn->depth); templ.target = PIPE_TEXTURE_2D; templ.last_level = 0; templ.width0 = (scrn->output_texture) ? scrn->output_texture->width0 : scrn->width; templ.height0 = (scrn->output_texture) ? scrn->output_texture->height0 : scrn->height; templ.depth0 = 1; templ.array_size = 1; if (scrn->is_different_gpu) { buffer->texture = (scrn->output_texture) ? scrn->output_texture : scrn->base.pscreen->resource_create(scrn->base.pscreen, &templ); if (!buffer->texture) goto unmap_shm; templ.bind |= PIPE_BIND_SCANOUT | PIPE_BIND_SHARED | PIPE_BIND_LINEAR; buffer->linear_texture = scrn->base.pscreen->resource_create(scrn->base.pscreen, &templ); pixmap_buffer_texture = buffer->linear_texture; if (!buffer->linear_texture) goto no_linear_texture; } else { templ.bind |= PIPE_BIND_SCANOUT | PIPE_BIND_SHARED; buffer->texture = (scrn->output_texture) ? scrn->output_texture : scrn->base.pscreen->resource_create(scrn->base.pscreen, &templ); if (!buffer->texture) goto unmap_shm; pixmap_buffer_texture = buffer->texture; } memset(&whandle, 0, sizeof(whandle)); whandle.type= WINSYS_HANDLE_TYPE_FD; usage = PIPE_HANDLE_USAGE_EXPLICIT_FLUSH; scrn->base.pscreen->resource_get_handle(scrn->base.pscreen, NULL, pixmap_buffer_texture, &whandle, usage); buffer_fd = whandle.handle; buffer->pitch = whandle.stride; buffer->width = templ.width0; buffer->height = templ.height0; xcb_dri3_pixmap_from_buffer(scrn->conn, (pixmap = xcb_generate_id(scrn->conn)), scrn->drawable, 0, buffer->width, buffer->height, buffer->pitch, scrn->depth, 32, buffer_fd); xcb_dri3_fence_from_fd(scrn->conn, pixmap, (sync_fence = xcb_generate_id(scrn->conn)), false, fence_fd); buffer->pixmap = pixmap; buffer->sync_fence = sync_fence; buffer->shm_fence = shm_fence; xshmfence_trigger(buffer->shm_fence); return buffer; no_linear_texture: pipe_resource_reference(&buffer->texture, NULL); unmap_shm: xshmfence_unmap_shm(shm_fence); close_fd: close(fence_fd); free_buffer: FREE(buffer); return NULL; }