winsys/amdgpu: Make KMS handles valid for original DRM file descriptor
authorMichel Dänzer <michel.daenzer@amd.com>
Fri, 28 Jun 2019 16:35:56 +0000 (18:35 +0200)
committerMichel Dänzer <michel@daenzer.net>
Wed, 3 Jul 2019 09:19:07 +0000 (09:19 +0000)
Getting a DMA-buf fd and converting that to a handle using our duplicate
of that file descriptor (getting at which requires passing a
radeon_winsys pointer to the buffer_get_handle hook) makes sure of this,
since duplicated file descriptors reference the same file description
and therefore the same GEM handle namespace.

This is necessary because libdrm_amdgpu may use a different DRM file
descriptor with a separate handle namespace internally, e.g. because it
always reuses any existing amdgpu_device_handle for the same device.
amdgpu_bo_export returns a handle which is valid for that internal
file descriptor.

Bugzilla: https://bugs.freedesktop.org/110903
Reviewed-by: Marek Olšák <marek.olsak@amd.com>
Tested-by: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com>
src/gallium/drivers/r300/r300_texture.c
src/gallium/drivers/r600/r600_texture.c
src/gallium/drivers/radeon/radeon_winsys.h
src/gallium/drivers/radeonsi/si_texture.c
src/gallium/winsys/amdgpu/drm/amdgpu_bo.c
src/gallium/winsys/radeon/drm/radeon_drm_bo.c

index 21ade4022c5e18c74d301dc2a6ddda98882d99b1..a9dc869b87c4ac076985fe826c0a9c466ca337b6 100644 (file)
@@ -1048,7 +1048,7 @@ boolean r300_resource_get_handle(struct pipe_screen* screen,
         return FALSE;
     }
 
-    return rws->buffer_get_handle(tex->buf, tex->tex.stride_in_bytes[0],
+    return rws->buffer_get_handle(rws, tex->buf, tex->tex.stride_in_bytes[0],
                                   0, 0, whandle);
 }
 
index 12812e0e39614d49547ea2c5324c8709ec9b0c3b..cd09debf273ceed3ad723d99701c7033e6f2da1f 100644 (file)
@@ -572,8 +572,8 @@ static boolean r600_texture_get_handle(struct pipe_screen* screen,
                res->external_usage = usage;
        }
 
-       return rscreen->ws->buffer_get_handle(res->buf, stride, offset,
-                                             slice_size, whandle);
+       return rscreen->ws->buffer_get_handle(rscreen->ws, res->buf, stride,
+                                             offset, slice_size, whandle);
 }
 
 static void r600_texture_destroy(struct pipe_screen *screen,
index c27627e8926a2edc991eb759d29b107168f83ca0..525c28182ed17e9497bc7765adf6c6799340d77d 100644 (file)
@@ -411,12 +411,14 @@ struct radeon_winsys {
      * Get a winsys handle from a winsys buffer. The internal structure
      * of the handle is platform-specific and only a winsys should access it.
      *
+     * \param ws        The winsys instance for which the handle is to be valid
      * \param buf       A winsys buffer object to get the handle from.
      * \param whandle   A winsys handle pointer.
      * \param stride    A stride of the buffer in bytes, for texturing.
      * \return          true on success.
      */
-    bool (*buffer_get_handle)(struct pb_buffer *buf,
+    bool (*buffer_get_handle)(struct radeon_winsys *ws,
+                              struct pb_buffer *buf,
                               unsigned stride, unsigned offset,
                               unsigned slice_size,
                               struct winsys_handle *whandle);
index dd383635675cb4b3209241000d22f0bd7ef193df..4f9b85cd76879b6f0a9c35cf1deb49514c924eeb 100644 (file)
@@ -944,8 +944,8 @@ static boolean si_texture_get_handle(struct pipe_screen* screen,
                res->external_usage = usage;
        }
 
-       return sscreen->ws->buffer_get_handle(res->buf, stride, offset,
-                                             slice_size, whandle);
+       return sscreen->ws->buffer_get_handle(sscreen->ws, res->buf, stride,
+                                             offset, slice_size, whandle);
 }
 
 static void si_texture_destroy(struct pipe_screen *screen,
index f1a6cc41af72ea1968f870d76d4f0ebe8bfb33be..7ff84cfb175b6f546945eebdc9476fb5232b9171 100644 (file)
@@ -1524,11 +1524,13 @@ error:
    return NULL;
 }
 
-static bool amdgpu_bo_get_handle(struct pb_buffer *buffer,
+static bool amdgpu_bo_get_handle(struct radeon_winsys *rws,
+                                 struct pb_buffer *buffer,
                                  unsigned stride, unsigned offset,
                                  unsigned slice_size,
                                  struct winsys_handle *whandle)
 {
+   struct amdgpu_screen_winsys *sws = amdgpu_screen_winsys(rws);
    struct amdgpu_winsys_bo *bo = amdgpu_winsys_bo(buffer);
    struct amdgpu_winsys *ws = bo->ws;
    enum amdgpu_bo_handle_type type;
@@ -1544,12 +1546,10 @@ static bool amdgpu_bo_get_handle(struct pb_buffer *buffer,
    case WINSYS_HANDLE_TYPE_SHARED:
       type = amdgpu_bo_handle_type_gem_flink_name;
       break;
+   case WINSYS_HANDLE_TYPE_KMS:
    case WINSYS_HANDLE_TYPE_FD:
       type = amdgpu_bo_handle_type_dma_buf_fd;
       break;
-   case WINSYS_HANDLE_TYPE_KMS:
-      type = amdgpu_bo_handle_type_kms;
-      break;
    default:
       return false;
    }
@@ -1558,6 +1558,16 @@ static bool amdgpu_bo_get_handle(struct pb_buffer *buffer,
    if (r)
       return false;
 
+   if (whandle->type == WINSYS_HANDLE_TYPE_KMS) {
+      int dma_fd = whandle->handle;
+
+      r = drmPrimeFDToHandle(sws->fd, dma_fd, &whandle->handle);
+      close(dma_fd);
+
+      if (r)
+         return false;
+   }
+
    simple_mtx_lock(&ws->bo_export_table_lock);
    util_hash_table_set(ws->bo_export_table, bo->bo, bo);
    simple_mtx_unlock(&ws->bo_export_table_lock);
index d1e2a8685ba91a5932bc21652b980668e68fd9e2..e9e0784e9ab4146c1477480b36a17b06bafc429c 100644 (file)
@@ -1285,7 +1285,8 @@ fail:
     return NULL;
 }
 
-static bool radeon_winsys_bo_get_handle(struct pb_buffer *buffer,
+static bool radeon_winsys_bo_get_handle(struct radeon_winsys *rws,
+                                        struct pb_buffer *buffer,
                                         unsigned stride, unsigned offset,
                                         unsigned slice_size,
                                         struct winsys_handle *whandle)