~sircmpwn/mesa

11a3679e3aba3524cf987f1f808d92c25f16e080 — Michel Dänzer 1 year, 10 days ago cb446dc
winsys/amdgpu: Make KMS handles valid for original DRM file descriptor

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>
M src/gallium/drivers/r300/r300_texture.c => src/gallium/drivers/r300/r300_texture.c +1 -1
@@ 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);
}


M src/gallium/drivers/r600/r600_texture.c => src/gallium/drivers/r600/r600_texture.c +2 -2
@@ 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,

M src/gallium/drivers/radeon/radeon_winsys.h => src/gallium/drivers/radeon/radeon_winsys.h +3 -1
@@ 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);

M src/gallium/drivers/radeonsi/si_texture.c => src/gallium/drivers/radeonsi/si_texture.c +2 -2
@@ 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,

M src/gallium/winsys/amdgpu/drm/amdgpu_bo.c => src/gallium/winsys/amdgpu/drm/amdgpu_bo.c +14 -4
@@ 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);

M src/gallium/winsys/radeon/drm/radeon_drm_bo.c => src/gallium/winsys/radeon/drm/radeon_drm_bo.c +2 -1
@@ 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)