Example #1
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 = 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;
}
Example #3
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;
}