[Mesa-dev] [PATCH] winsys/radeon: add user pointer support
Marek Olšák
maraeo at gmail.com
Mon Feb 9 16:29:44 PST 2015
Hi Christian,
What hardware is this supported on? SI and later? Or even r600? r300?
Thanks,
Marek
On Thu, Feb 5, 2015 at 6:34 PM, Christian König <deathsimple at vodafone.de> wrote:
> From: Christian König <christian.koenig at amd.com>
>
> Signed-off-by: Christian König <christian.koenig at amd.com>
> ---
> src/gallium/winsys/radeon/drm/radeon_drm_bo.c | 102 ++++++++++++++++++++++++++
> src/gallium/winsys/radeon/drm/radeon_winsys.h | 11 +++
> 2 files changed, 113 insertions(+)
>
> diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_bo.c b/src/gallium/winsys/radeon/drm/radeon_drm_bo.c
> index 1ebec10..2605ca6 100644
> --- a/src/gallium/winsys/radeon/drm/radeon_drm_bo.c
> +++ b/src/gallium/winsys/radeon/drm/radeon_drm_bo.c
> @@ -42,6 +42,24 @@
> #include <fcntl.h>
> #include <stdio.h>
>
> +#ifndef DRM_RADEON_GEM_USERPTR
> +
> +#define DRM_RADEON_GEM_USERPTR 0x2d
> +
> +#define RADEON_GEM_USERPTR_READONLY (1 << 0)
> +#define RADEON_GEM_USERPTR_ANONONLY (1 << 1)
> +#define RADEON_GEM_USERPTR_VALIDATE (1 << 2)
> +#define RADEON_GEM_USERPTR_REGISTER (1 << 3)
> +
> +struct drm_radeon_gem_userptr {
> + uint64_t addr;
> + uint64_t size;
> + uint32_t flags;
> + uint32_t handle;
> +};
> +
> +#endif
> +
> extern const struct pb_vtbl radeon_bo_vtbl;
>
> static INLINE struct radeon_bo *radeon_bo(struct pb_buffer *bo)
> @@ -846,6 +864,89 @@ radeon_winsys_bo_create(struct radeon_winsys *rws,
> return (struct pb_buffer*)buffer;
> }
>
> +static struct pb_buffer *radeon_winsys_bo_from_ptr(struct radeon_winsys *rws,
> + void *pointer, unsigned size)
> +{
> + struct radeon_drm_winsys *ws = radeon_drm_winsys(rws);
> + struct radeon_bomgr *mgr = radeon_bomgr(ws->kman);
> + struct drm_radeon_gem_userptr args;
> + struct radeon_bo *bo;
> + int r;
> +
> + bo = CALLOC_STRUCT(radeon_bo);
> + if (!bo)
> + return NULL;
> +
> + memset(&args, 0, sizeof(args));
> + args.addr = (uintptr_t)pointer;
> + args.size = size;
> + args.flags = RADEON_GEM_USERPTR_ANONONLY |
> + RADEON_GEM_USERPTR_VALIDATE |
> + RADEON_GEM_USERPTR_REGISTER;
> + if (drmCommandWriteRead(ws->fd, DRM_RADEON_GEM_USERPTR,
> + &args, sizeof(args))) {
> + FREE(bo);
> + return NULL;
> + }
> +
> + pipe_mutex_lock(mgr->bo_handles_mutex);
> +
> + /* Initialize it. */
> + pipe_reference_init(&bo->base.reference, 1);
> + bo->handle = args.handle;
> + bo->base.alignment = 0;
> + bo->base.usage = PB_USAGE_GPU_WRITE | PB_USAGE_GPU_READ;
> + bo->base.size = size;
> + bo->base.vtbl = &radeon_bo_vtbl;
> + bo->mgr = mgr;
> + bo->rws = mgr->rws;
> + bo->va = 0;
> + bo->initial_domain = RADEON_DOMAIN_GTT;
> + pipe_mutex_init(bo->map_mutex);
> +
> + util_hash_table_set(mgr->bo_handles, (void*)(uintptr_t)bo->handle, bo);
> +
> + pipe_mutex_unlock(mgr->bo_handles_mutex);
> +
> + if (mgr->va) {
> + struct drm_radeon_gem_va va;
> +
> + bo->va = radeon_bomgr_find_va(mgr, bo->base.size, 1 << 20);
> +
> + va.handle = bo->handle;
> + va.operation = RADEON_VA_MAP;
> + va.vm_id = 0;
> + va.offset = bo->va;
> + va.flags = RADEON_VM_PAGE_READABLE |
> + RADEON_VM_PAGE_WRITEABLE |
> + RADEON_VM_PAGE_SNOOPED;
> + va.offset = bo->va;
> + r = drmCommandWriteRead(ws->fd, DRM_RADEON_GEM_VA, &va, sizeof(va));
> + if (r && va.operation == RADEON_VA_RESULT_ERROR) {
> + fprintf(stderr, "radeon: Failed to assign virtual address space\n");
> + radeon_bo_destroy(&bo->base);
> + return NULL;
> + }
> + pipe_mutex_lock(mgr->bo_handles_mutex);
> + if (va.operation == RADEON_VA_RESULT_VA_EXIST) {
> + struct pb_buffer *b = &bo->base;
> + struct radeon_bo *old_bo =
> + util_hash_table_get(mgr->bo_vas, (void*)(uintptr_t)va.offset);
> +
> + pipe_mutex_unlock(mgr->bo_handles_mutex);
> + pb_reference(&b, &old_bo->base);
> + return b;
> + }
> +
> + util_hash_table_set(mgr->bo_vas, (void*)(uintptr_t)bo->va, bo);
> + pipe_mutex_unlock(mgr->bo_handles_mutex);
> + }
> +
> + ws->allocated_gtt += align(bo->base.size, 4096);
> +
> + return (struct pb_buffer*)bo;
> +}
> +
> static struct pb_buffer *radeon_winsys_bo_from_handle(struct radeon_winsys *rws,
> struct winsys_handle *whandle,
> unsigned *stride)
> @@ -1040,6 +1141,7 @@ void radeon_bomgr_init_functions(struct radeon_drm_winsys *ws)
> ws->base.buffer_is_busy = radeon_bo_is_busy;
> ws->base.buffer_create = radeon_winsys_bo_create;
> ws->base.buffer_from_handle = radeon_winsys_bo_from_handle;
> + ws->base.buffer_from_ptr = radeon_winsys_bo_from_ptr;
> ws->base.buffer_get_handle = radeon_winsys_bo_get_handle;
> ws->base.buffer_get_virtual_address = radeon_winsys_bo_va;
> ws->base.buffer_get_initial_domain = radeon_bo_get_initial_domain;
> diff --git a/src/gallium/winsys/radeon/drm/radeon_winsys.h b/src/gallium/winsys/radeon/drm/radeon_winsys.h
> index 5dc9313..d9fa1ab 100644
> --- a/src/gallium/winsys/radeon/drm/radeon_winsys.h
> +++ b/src/gallium/winsys/radeon/drm/radeon_winsys.h
> @@ -394,6 +394,17 @@ struct radeon_winsys {
> unsigned *stride);
>
> /**
> + * Get a winsys buffer from a user pointer. The resulting buffer can't be
> + * mapped or exported. Both pointer and size must be page aligned.
> + *
> + * \param ws The winsys this function is called from.
> + * \param pointer User pointer to turn into a buffer object.
> + * \param Size Size in bytes for the new buffer.
> + */
> + struct pb_buffer *(*buffer_from_ptr)(struct radeon_winsys *ws,
> + void *pointer, unsigned size);
> +
> + /**
> * Get a winsys handle from a winsys buffer. The internal structure
> * of the handle is platform-specific and only a winsys should access it.
> *
> --
> 1.9.1
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/mesa-dev
More information about the mesa-dev
mailing list