static void dri3_free_front_buffer(struct vl_dri3_screen *scrn, struct vl_dri3_buffer *buffer) { xcb_sync_destroy_fence(scrn->conn, buffer->sync_fence); xshmfence_unmap_shm(buffer->shm_fence); FREE(buffer); }
static void dri3_free_front_buffer(struct vl_dri3_screen *scrn, struct vl_dri3_buffer *buffer) { xcb_sync_destroy_fence(scrn->conn, buffer->sync_fence); xshmfence_unmap_shm(buffer->shm_fence); pipe_resource_reference(&buffer->texture, NULL); FREE(buffer); }
/** dri3_free_render_buffer * * Free everything associated with one render buffer including pixmap, fence * stuff and the driver image */ static void dri3_free_render_buffer(struct loader_dri3_drawable *draw, struct loader_dri3_buffer *buffer) { if (buffer->own_pixmap) xcb_free_pixmap(draw->conn, buffer->pixmap); xcb_sync_destroy_fence(draw->conn, buffer->sync_fence); xshmfence_unmap_shm(buffer->shm_fence); (draw->ext->image->destroyImage)(buffer->image); if (buffer->linear_buffer) (draw->ext->image->destroyImage)(buffer->linear_buffer); free(buffer); }
static void dri3_free_back_buffer(struct vl_dri3_screen *scrn, struct vl_dri3_buffer *buffer) { xcb_free_pixmap(scrn->conn, buffer->pixmap); xcb_sync_destroy_fence(scrn->conn, buffer->sync_fence); xshmfence_unmap_shm(buffer->shm_fence); if (!scrn->output_texture) pipe_resource_reference(&buffer->texture, NULL); if (buffer->linear_texture) pipe_resource_reference(&buffer->linear_texture, NULL); FREE(buffer); }
static void x11_image_finish(struct x11_swapchain *chain, const VkAllocationCallbacks* pAllocator, struct x11_image *image) { xcb_void_cookie_t cookie; cookie = xcb_sync_destroy_fence(chain->conn, image->sync_fence); xcb_discard_reply(chain->conn, cookie.sequence); xshmfence_unmap_shm(image->shm_fence); cookie = xcb_free_pixmap(chain->conn, image->pixmap); xcb_discard_reply(chain->conn, cookie.sequence); chain->base.image_fns->free_wsi_image(chain->base.device, pAllocator, image->image, image->memory); }
void xshmfence_init(int fd) { struct xshmfence *f = xshmfence_map_shm(fd); pthread_mutexattr_t mutex_attr; pthread_condattr_t cond_attr; if (!f) return; pthread_mutexattr_init(&mutex_attr); pthread_mutexattr_setpshared(&mutex_attr, PTHREAD_PROCESS_SHARED); pthread_mutex_init(&f->lock, &mutex_attr); pthread_condattr_init(&cond_attr); pthread_condattr_setpshared(&cond_attr, PTHREAD_PROCESS_SHARED); pthread_cond_init(&f->wakeup, &cond_attr); f->value = 0; f->waiting = 0; xshmfence_unmap_shm(f); }
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; }
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; 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 | PIPE_BIND_SCANOUT | PIPE_BIND_SHARED; templ.format = PIPE_FORMAT_B8G8R8X8_UNORM; templ.target = PIPE_TEXTURE_2D; templ.last_level = 0; templ.width0 = scrn->width; templ.height0 = scrn->height; templ.depth0 = 1; templ.array_size = 1; buffer->texture = scrn->base.pscreen->resource_create(scrn->base.pscreen, &templ); if (!buffer->texture) goto unmap_shm; memset(&whandle, 0, sizeof(whandle)); whandle.type= DRM_API_HANDLE_TYPE_FD; usage = PIPE_HANDLE_USAGE_EXPLICIT_FLUSH | PIPE_HANDLE_USAGE_READ; scrn->base.pscreen->resource_get_handle(scrn->base.pscreen, buffer->texture, &whandle, usage); buffer_fd = whandle.handle; buffer->pitch = whandle.stride; xcb_dri3_pixmap_from_buffer(scrn->conn, (pixmap = xcb_generate_id(scrn->conn)), scrn->drawable, 0, scrn->width, scrn->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; buffer->width = scrn->width; buffer->height = scrn->height; xshmfence_trigger(buffer->shm_fence); return buffer; unmap_shm: xshmfence_unmap_shm(shm_fence); close_fd: close(fence_fd); free_buffer: FREE(buffer); return NULL; }
/** loader_dri3_alloc_render_buffer * * Use the driver createImage function to construct a __DRIimage, then * get a file descriptor for that and create an X pixmap from that * * Allocate an xshmfence for synchronization */ static struct loader_dri3_buffer * dri3_alloc_render_buffer(struct loader_dri3_drawable *draw, unsigned int format, int width, int height, int depth) { struct loader_dri3_buffer *buffer; __DRIimage *pixmap_buffer; xcb_pixmap_t pixmap; xcb_sync_fence_t sync_fence; struct xshmfence *shm_fence; int buffer_fd, fence_fd; int stride; /* Create an xshmfence object and * prepare to send that to the X server */ fence_fd = xshmfence_alloc_shm(); if (fence_fd < 0) return NULL; shm_fence = xshmfence_map_shm(fence_fd); if (shm_fence == NULL) goto no_shm_fence; /* Allocate the image from the driver */ buffer = calloc(1, sizeof *buffer); if (!buffer) goto no_buffer; buffer->cpp = dri3_cpp_for_format(format); if (!buffer->cpp) goto no_image; if (!draw->is_different_gpu) { buffer->image = (draw->ext->image->createImage)(draw->dri_screen, width, height, format, __DRI_IMAGE_USE_SHARE | __DRI_IMAGE_USE_SCANOUT | __DRI_IMAGE_USE_BACKBUFFER, buffer); pixmap_buffer = buffer->image; if (!buffer->image) goto no_image; } else { buffer->image = (draw->ext->image->createImage)(draw->dri_screen, width, height, format, 0, buffer); if (!buffer->image) goto no_image; buffer->linear_buffer = (draw->ext->image->createImage)(draw->dri_screen, width, height, format, __DRI_IMAGE_USE_SHARE | __DRI_IMAGE_USE_LINEAR | __DRI_IMAGE_USE_BACKBUFFER, buffer); pixmap_buffer = buffer->linear_buffer; if (!buffer->linear_buffer) goto no_linear_buffer; } /* X wants the stride, so ask the image for it */ if (!(draw->ext->image->queryImage)(pixmap_buffer, __DRI_IMAGE_ATTRIB_STRIDE, &stride)) goto no_buffer_attrib; buffer->pitch = stride; if (!(draw->ext->image->queryImage)(pixmap_buffer, __DRI_IMAGE_ATTRIB_FD, &buffer_fd)) goto no_buffer_attrib; xcb_dri3_pixmap_from_buffer(draw->conn, (pixmap = xcb_generate_id(draw->conn)), draw->drawable, buffer->size, width, height, buffer->pitch, depth, buffer->cpp * 8, buffer_fd); xcb_dri3_fence_from_fd(draw->conn, pixmap, (sync_fence = xcb_generate_id(draw->conn)), false, fence_fd); buffer->pixmap = pixmap; buffer->own_pixmap = true; buffer->sync_fence = sync_fence; buffer->shm_fence = shm_fence; buffer->width = width; buffer->height = height; /* Mark the buffer as idle */ dri3_fence_set(buffer); return buffer; no_buffer_attrib: (draw->ext->image->destroyImage)(pixmap_buffer); no_linear_buffer: if (draw->is_different_gpu) (draw->ext->image->destroyImage)(buffer->image); no_image: free(buffer); no_buffer: xshmfence_unmap_shm(shm_fence); no_shm_fence: close(fence_fd); 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; }
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; }