Пример #1
0
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;
}
Пример #2
0
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;
}
Пример #3
0
/** 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;
}
Пример #4
0
/** 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;
}
Пример #5
0
static VkResult
x11_image_init(VkDevice device_h, struct x11_swapchain *chain,
               const VkSwapchainCreateInfoKHR *pCreateInfo,
               const VkAllocationCallbacks* pAllocator,
               struct x11_image *image)
{
   xcb_void_cookie_t cookie;
   VkResult result;
   uint32_t row_pitch;
   uint32_t offset;
   uint32_t bpp = 32;
   int fd;
   uint32_t size;

   result = chain->base.image_fns->create_wsi_image(device_h,
                                                    pCreateInfo,
                                                    pAllocator,
                                                    &image->image,
                                                    &image->memory,
                                                    &size,
                                                    &offset,
                                                    &row_pitch,
                                                    &fd);
   if (result != VK_SUCCESS)
      return result;

   image->pixmap = xcb_generate_id(chain->conn);

   cookie =
      xcb_dri3_pixmap_from_buffer_checked(chain->conn,
                                          image->pixmap,
                                          chain->window,
                                          size,
                                          pCreateInfo->imageExtent.width,
                                          pCreateInfo->imageExtent.height,
                                          row_pitch,
                                          chain->depth, bpp, fd);
   xcb_discard_reply(chain->conn, cookie.sequence);

   int fence_fd = xshmfence_alloc_shm();
   if (fence_fd < 0)
      goto fail_pixmap;

   image->shm_fence = xshmfence_map_shm(fence_fd);
   if (image->shm_fence == NULL)
      goto fail_shmfence_alloc;

   image->sync_fence = xcb_generate_id(chain->conn);
   xcb_dri3_fence_from_fd(chain->conn,
                          image->pixmap,
                          image->sync_fence,
                          false,
                          fence_fd);

   image->busy = false;
   xshmfence_trigger(image->shm_fence);

   return VK_SUCCESS;

fail_shmfence_alloc:
   close(fence_fd);

fail_pixmap:
   cookie = xcb_free_pixmap(chain->conn, image->pixmap);
   xcb_discard_reply(chain->conn, cookie.sequence);

   chain->base.image_fns->free_wsi_image(device_h, pAllocator,
                                        image->image, image->memory);

   return result;
}
Пример #6
0
/** 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;
}
Пример #7
0
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;
}