/** 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; }
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; }
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; }