[Mesa-dev] [PATCH 1/3] vl/dri3: use external texture as back buffers
Christian König
deathsimple at vodafone.de
Mon Oct 24 15:18:57 UTC 2016
Nice work, have you been able to fix all the issues you mentioned on
your last mail?
Additional to that make sure that this set also keeps DRI2 working, in
patch #2 it looks like you call the new function without checking if
it's available or not.
Keep in mind that we possible compile both DRI2 and DRI3 into the
driver, but it can happen that we fallback to DRI2 on runtime.
Regards,
Christian.
Am 24.10.2016 um 15:55 schrieb Nayan Deshmukh:
> Suggested-by: Leo Liu <leo.liu at amd.com>
> Signed-off-by: Nayan Deshmukh <nayan26deshmukh at gmail.com>
> ---
> src/gallium/auxiliary/vl/vl_winsys.h | 4 ++
> src/gallium/auxiliary/vl/vl_winsys_dri3.c | 89 +++++++++++++++++++++++++++----
> 2 files changed, 83 insertions(+), 10 deletions(-)
>
> diff --git a/src/gallium/auxiliary/vl/vl_winsys.h b/src/gallium/auxiliary/vl/vl_winsys.h
> index 26db9f2..7c56b48 100644
> --- a/src/gallium/auxiliary/vl/vl_winsys.h
> +++ b/src/gallium/auxiliary/vl/vl_winsys.h
> @@ -59,6 +59,10 @@ struct vl_screen
> void *
> (*get_private)(struct vl_screen *vscreen);
>
> + void
> + (*set_output_texture)(struct vl_screen *vscreen, struct pipe_resource *buffer,
> + uint32_t width, uint32_t height);
> +
> struct pipe_screen *pscreen;
> struct pipe_loader_device *dev;
> };
> diff --git a/src/gallium/auxiliary/vl/vl_winsys_dri3.c b/src/gallium/auxiliary/vl/vl_winsys_dri3.c
> index 2929928..44d6f4c 100644
> --- a/src/gallium/auxiliary/vl/vl_winsys_dri3.c
> +++ b/src/gallium/auxiliary/vl/vl_winsys_dri3.c
> @@ -56,6 +56,7 @@ struct vl_dri3_buffer
> struct xshmfence *shm_fence;
>
> bool busy;
> + bool is_external_texture;
> uint32_t width, height, pitch;
> };
>
> @@ -71,6 +72,9 @@ struct vl_dri3_screen
> xcb_special_event_t *special_event;
>
> struct pipe_context *pipe;
> + struct pipe_resource *output_texture;
> + uint32_t output_texture_width;
> + uint32_t output_texture_height;
>
> struct vl_dri3_buffer *back_buffers[BACK_BUFFER_NUM];
> int cur_back;
> @@ -105,7 +109,8 @@ dri3_free_back_buffer(struct vl_dri3_screen *scrn,
> xcb_free_pixmap(scrn->conn, buffer->pixmap);
> xcb_sync_destroy_fence(scrn->conn, buffer->sync_fence);
> xshmfence_unmap_shm(buffer->shm_fence);
> - pipe_resource_reference(&buffer->texture, NULL);
> + if (!buffer->is_external_texture)
> + pipe_resource_reference(&buffer->texture, NULL);
> if (buffer->linear_texture)
> pipe_resource_reference(&buffer->linear_texture, NULL);
> FREE(buffer);
> @@ -236,13 +241,24 @@ dri3_alloc_back_buffer(struct vl_dri3_screen *scrn)
> templ.format = PIPE_FORMAT_B8G8R8X8_UNORM;
> templ.target = PIPE_TEXTURE_2D;
> templ.last_level = 0;
> - templ.width0 = scrn->width;
> - templ.height0 = scrn->height;
> + if (scrn->output_texture) {
> + templ.width0 = (scrn->output_texture_width) ?
> + scrn->output_texture_width :
> + scrn->output_texture->width0;
> + templ.height0 = (scrn->output_texture_height) ?
> + scrn->output_texture_height :
> + scrn->output_texture->height0;
> + } else {
> + templ.width0 = scrn->width;
> + templ.height0 = scrn->height;
> + }
> templ.depth0 = 1;
> templ.array_size = 1;
>
> if (scrn->is_different_gpu) {
> - buffer->texture = scrn->base.pscreen->resource_create(scrn->base.pscreen,
> + buffer->texture = (scrn->output_texture) ?
> + scrn->output_texture :
> + scrn->base.pscreen->resource_create(scrn->base.pscreen,
> &templ);
> if (!buffer->texture)
> goto unmap_shm;
> @@ -257,7 +273,9 @@ dri3_alloc_back_buffer(struct vl_dri3_screen *scrn)
> goto no_linear_texture;
> } else {
> templ.bind |= PIPE_BIND_SCANOUT | PIPE_BIND_SHARED;
> - buffer->texture = scrn->base.pscreen->resource_create(scrn->base.pscreen,
> + buffer->texture = (scrn->output_texture) ?
> + scrn->output_texture :
> + scrn->base.pscreen->resource_create(scrn->base.pscreen,
> &templ);
> if (!buffer->texture)
> goto unmap_shm;
> @@ -271,11 +289,20 @@ dri3_alloc_back_buffer(struct vl_dri3_screen *scrn)
> usage);
> buffer_fd = whandle.handle;
> buffer->pitch = whandle.stride;
> + buffer->width = templ.width0;
> + buffer->height = templ.height0;
> + buffer->is_external_texture = (scrn->output_texture) ?
> + true :
> + false;
> + scrn->output_texture = NULL;
> + scrn->output_texture_width = 0;
> + scrn->output_texture_height = 0;
> +
> xcb_dri3_pixmap_from_buffer(scrn->conn,
> (pixmap = xcb_generate_id(scrn->conn)),
> scrn->drawable,
> 0,
> - scrn->width, scrn->height, buffer->pitch,
> + buffer->width, buffer->height, buffer->pitch,
> scrn->depth, 32,
> buffer_fd);
> xcb_dri3_fence_from_fd(scrn->conn,
> @@ -287,8 +314,6 @@ dri3_alloc_back_buffer(struct vl_dri3_screen *scrn)
> 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);
>
> @@ -310,6 +335,7 @@ dri3_get_back_buffer(struct vl_dri3_screen *scrn)
> {
> struct vl_dri3_buffer *buffer;
> struct pipe_resource *texture = NULL;
> + bool allocate_new_buffer = false;
>
> assert(scrn);
>
> @@ -318,8 +344,30 @@ dri3_get_back_buffer(struct vl_dri3_screen *scrn)
> return NULL;
> buffer = scrn->back_buffers[scrn->cur_back];
>
> - if (!buffer || buffer->width != scrn->width ||
> - buffer->height != scrn->height) {
> + /* This is normal case when our buffer is smaller
> + * than the screen this will be same for external
> + * texture
> + */
> + if (!buffer || buffer->width < scrn->width ||
> + buffer->height < scrn->height)
> + allocate_new_buffer = true;
> +
> + /* If we were using a external texture buffer and
> + * the texture is not provided then we need a new
> + * buffer
> + */
> + if (buffer && buffer->is_external_texture &&
> + !scrn->output_texture)
> + allocate_new_buffer = true;
> +
> + /* In case of a single gpu we need to get the
> + * handle and pixmap for the texture that is set
> + */
> + if (buffer && buffer->is_external_texture &&
> + !scrn->is_different_gpu)
> + allocate_new_buffer = true;
> +
> + if (allocate_new_buffer) {
> struct vl_dri3_buffer *new_buffer;
>
> new_buffer = dri3_alloc_back_buffer(scrn);
> @@ -332,6 +380,13 @@ dri3_get_back_buffer(struct vl_dri3_screen *scrn)
> vl_compositor_reset_dirty_area(&scrn->dirty_areas[scrn->cur_back]);
> buffer = new_buffer;
> scrn->back_buffers[scrn->cur_back] = buffer;
> + } else if (buffer->is_external_texture) {
> + /* In case of different gpu we can reuse the linear
> + * texture so we only need to set the external
> + * texture for copying
> + */
> + buffer->texture = scrn->output_texture;
> + scrn->output_texture = NULL;
> }
>
> pipe_resource_reference(&texture, buffer->texture);
> @@ -627,6 +682,19 @@ vl_dri3_screen_get_private(struct vl_screen *vscreen)
> }
>
> static void
> +vl_dri3_screen_set_output_texture(struct vl_screen *vscreen, struct pipe_resource *buffer,
> + uint32_t width, uint32_t height)
> +{
> + struct vl_dri3_screen *scrn = (struct vl_dri3_screen *)vscreen;
> +
> + assert(scrn);
> +
> + scrn->output_texture = buffer;
> + scrn->output_texture_width = width;
> + scrn->output_texture_height = height;
> +}
> +
> +static void
> vl_dri3_screen_destroy(struct vl_screen *vscreen)
> {
> struct vl_dri3_screen *scrn = (struct vl_dri3_screen *)vscreen;
> @@ -744,6 +812,7 @@ vl_dri3_screen_create(Display *display, int screen)
> scrn->base.set_next_timestamp = vl_dri3_screen_set_next_timestamp;
> scrn->base.get_private = vl_dri3_screen_get_private;
> scrn->base.pscreen->flush_frontbuffer = vl_dri3_flush_frontbuffer;
> + scrn->base.set_output_texture = vl_dri3_screen_set_output_texture;
>
> return &scrn->base;
>
More information about the mesa-dev
mailing list