[Mesa-dev] [PATCH v3] vl/dri3: handle the case of different GPU

Nayan Deshmukh nayan26deshmukh at gmail.com
Fri Sep 9 15:49:11 UTC 2016


In case of prime when rendering is done on GPU other then the
server GPU, use a seprate linear buffer for each back buffer
which will be displayed using present extension.

v2: Use a seprate linear buffer for each back buffer (Michel)
v3: change variable names and fix coding style (Leo and Emil)

Signed-off-by: Nayan Deshmukh <nayan26deshmukh at gmail.com>
---
 src/gallium/auxiliary/vl/vl_winsys_dri3.c | 63 ++++++++++++++++++++++++-------
 1 file changed, 50 insertions(+), 13 deletions(-)

diff --git a/src/gallium/auxiliary/vl/vl_winsys_dri3.c b/src/gallium/auxiliary/vl/vl_winsys_dri3.c
index 3d596a6..3607f86 100644
--- a/src/gallium/auxiliary/vl/vl_winsys_dri3.c
+++ b/src/gallium/auxiliary/vl/vl_winsys_dri3.c
@@ -49,6 +49,7 @@
 struct vl_dri3_buffer
 {
    struct pipe_resource *texture;
+   struct pipe_resource *linear_texture;
 
    uint32_t pixmap;
    uint32_t sync_fence;
@@ -69,6 +70,8 @@ struct vl_dri3_screen
    xcb_present_event_t eid;
    xcb_special_event_t *special_event;
 
+   struct pipe_context *pipe;
+
    struct vl_dri3_buffer *back_buffers[BACK_BUFFER_NUM];
    int cur_back;
 
@@ -82,6 +85,7 @@ struct vl_dri3_screen
    int64_t last_ust, ns_frame, last_msc, next_msc;
 
    bool flushed;
+   bool is_different_gpu;
 };
 
 static void
@@ -102,6 +106,8 @@ dri3_free_back_buffer(struct vl_dri3_screen *scrn,
    xcb_sync_destroy_fence(scrn->conn, buffer->sync_fence);
    xshmfence_unmap_shm(buffer->shm_fence);
    pipe_resource_reference(&buffer->texture, NULL);
+   if (buffer->linear_texture)
+       pipe_resource_reference(&buffer->linear_texture, NULL);
    FREE(buffer);
 }
 
@@ -209,7 +215,7 @@ dri3_alloc_back_buffer(struct vl_dri3_screen *scrn)
    xcb_sync_fence_t sync_fence;
    struct xshmfence *shm_fence;
    int buffer_fd, fence_fd;
-   struct pipe_resource templ;
+   struct pipe_resource templ, *pixmap_buffer_texture;
    struct winsys_handle whandle;
    unsigned usage;
 
@@ -226,8 +232,7 @@ dri3_alloc_back_buffer(struct vl_dri3_screen *scrn)
       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.bind = PIPE_BIND_RENDER_TARGET;
    templ.format = PIPE_FORMAT_B8G8R8X8_UNORM;
    templ.target = PIPE_TEXTURE_2D;
    templ.last_level = 0;
@@ -235,16 +240,36 @@ dri3_alloc_back_buffer(struct vl_dri3_screen *scrn)
    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;
 
+   if (scrn->is_different_gpu) {
+      buffer->texture = scrn->base.pscreen->resource_create(scrn->base.pscreen,
+                                                            &templ);
+      if (!buffer->texture)
+         goto unmap_shm;
+
+      templ.bind |= PIPE_BIND_SAMPLER_VIEW | 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_SAMPLER_VIEW | PIPE_BIND_SCANOUT |
+                    PIPE_BIND_SHARED;
+      buffer->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= DRM_API_HANDLE_TYPE_FD;
    usage = PIPE_HANDLE_USAGE_EXPLICIT_FLUSH | PIPE_HANDLE_USAGE_READ;
    scrn->base.pscreen->resource_get_handle(scrn->base.pscreen, NULL,
-                                           buffer->texture, &whandle,
+                                           pixmap_buffer_texture, &whandle,
                                            usage);
    buffer_fd = whandle.handle;
    buffer->pitch = whandle.stride;
@@ -271,6 +296,8 @@ dri3_alloc_back_buffer(struct vl_dri3_screen *scrn)
 
    return buffer;
 
+no_linear_texture:
+   pipe_resource_reference(&buffer->texture, NULL);
 unmap_shm:
    xshmfence_unmap_shm(shm_fence);
 close_fd:
@@ -474,6 +501,7 @@ vl_dri3_flush_frontbuffer(struct pipe_screen *screen,
    struct vl_dri3_screen *scrn = (struct vl_dri3_screen *)context_private;
    uint32_t options = XCB_PRESENT_OPTION_NONE;
    struct vl_dri3_buffer *back;
+   struct pipe_box src_box;
 
    back = scrn->back_buffers[scrn->cur_back];
    if (!back)
@@ -485,6 +513,16 @@ vl_dri3_flush_frontbuffer(struct pipe_screen *screen,
             return;
    }
 
+   if (scrn->is_different_gpu) {
+      u_box_origin_2d(scrn->width, scrn->height, &src_box);
+      scrn->pipe->resource_copy_region(scrn->pipe,
+                                       back->linear_texture,
+                                       0, 0, 0, 0,
+                                       back->texture,
+                                       0, &src_box);
+
+      scrn->pipe->flush(scrn->pipe, NULL, 0);
+   }
    xshmfence_reset(back->shm_fence);
    back->busy = true;
 
@@ -638,7 +676,6 @@ vl_dri3_screen_create(Display *display, int screen)
    xcb_dri3_open_reply_t *open_reply;
    xcb_get_geometry_cookie_t geom_cookie;
    xcb_get_geometry_reply_t *geom_reply;
-   int is_different_gpu;
    int fd;
 
    assert(display);
@@ -677,10 +714,7 @@ vl_dri3_screen_create(Display *display, int screen)
    fcntl(fd, F_SETFD, FD_CLOEXEC);
    free(open_reply);
 
-   fd = loader_get_user_preferred_fd(fd, &is_different_gpu);
-   /* TODO support different GPU */
-   if (is_different_gpu)
-      goto close_fd;
+   fd = loader_get_user_preferred_fd(fd, &scrn->is_different_gpu);
 
    geom_cookie = xcb_get_geometry(scrn->conn, RootWindow(display, screen));
    geom_reply = xcb_get_geometry_reply(scrn->conn, geom_cookie, NULL);
@@ -699,6 +733,9 @@ vl_dri3_screen_create(Display *display, int screen)
    if (!scrn->base.pscreen)
       goto release_pipe;
 
+   scrn->pipe = scrn->base.pscreen->context_create(scrn->base.pscreen,
+                                                   &scrn->base, 0);
+
    scrn->base.destroy = vl_dri3_screen_destroy;
    scrn->base.texture_from_drawable = vl_dri3_screen_texture_from_drawable;
    scrn->base.get_dirty_area = vl_dri3_screen_get_dirty_area;
-- 
2.7.4



More information about the mesa-dev mailing list