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 <[email protected]> wrote: > From: Christian König <[email protected]> > > Signed-off-by: Christian König <[email protected]> > --- > 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 > [email protected] > http://lists.freedesktop.org/mailman/listinfo/mesa-dev _______________________________________________ mesa-dev mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/mesa-dev
