From: Christopher James Halse Rogers <r...@ubuntu.com> --- src/gallium/drivers/r300/r300_screen.c | 8 ++- src/gallium/drivers/r300/r300_texture.c | 2 +- src/gallium/drivers/r600/r600_pipe.c | 7 ++- src/gallium/drivers/r600/r600_texture.c | 2 +- src/gallium/drivers/radeonsi/r600_texture.c | 2 +- src/gallium/drivers/radeonsi/radeonsi_pipe.c | 6 +- src/gallium/winsys/radeon/drm/radeon_drm_bo.c | 70 ++++++++++++++++++----- src/gallium/winsys/radeon/drm/radeon_drm_winsys.c | 4 ++ src/gallium/winsys/radeon/drm/radeon_winsys.h | 3 + 9 files changed, 84 insertions(+), 20 deletions(-)
diff --git a/src/gallium/drivers/r300/r300_screen.c b/src/gallium/drivers/r300/r300_screen.c index 000c71d..b7a7a2d 100644 --- a/src/gallium/drivers/r300/r300_screen.c +++ b/src/gallium/drivers/r300/r300_screen.c @@ -28,6 +28,8 @@ #include "vl/vl_decoder.h" #include "vl/vl_video_buffer.h" +#include <drm.h> + #include "r300_context.h" #include "r300_texture.h" #include "r300_screen_buffer.h" @@ -163,7 +165,6 @@ static int r300_get_param(struct pipe_screen* pscreen, enum pipe_cap param) case PIPE_CAP_TEXTURE_BUFFER_OBJECTS: case PIPE_CAP_TEXTURE_BUFFER_OFFSET_ALIGNMENT: case PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK: - case PIPE_CAP_PRIME: return 0; /* SWTCL-only features. */ @@ -191,6 +192,11 @@ static int r300_get_param(struct pipe_screen* pscreen, enum pipe_cap param) /* Render targets. */ case PIPE_CAP_MAX_RENDER_TARGETS: return 4; + + /* PRIME import/export support */ + case PIPE_CAP_PRIME: + return r300screen->info.prime_caps & + (DRM_PRIME_CAP_IMPORT | DRM_PRIME_CAP_EXPORT); } return 0; } diff --git a/src/gallium/drivers/r300/r300_texture.c b/src/gallium/drivers/r300/r300_texture.c index 13e9bc3..442b575 100644 --- a/src/gallium/drivers/r300/r300_texture.c +++ b/src/gallium/drivers/r300/r300_texture.c @@ -1111,7 +1111,7 @@ struct pipe_resource *r300_texture_from_handle(struct pipe_screen *screen, return NULL; } - buffer = rws->buffer_from_handle(rws, whandle, &stride); + buffer = rws->buffer_from_handle(rws, whandle, base->height0, &stride); if (!buffer) return NULL; diff --git a/src/gallium/drivers/r600/r600_pipe.c b/src/gallium/drivers/r600/r600_pipe.c index b056041..03e67f9 100644 --- a/src/gallium/drivers/r600/r600_pipe.c +++ b/src/gallium/drivers/r600/r600_pipe.c @@ -26,6 +26,8 @@ #include "evergreen_compute.h" #include "r600d.h" +#include <drm.h> + #include <errno.h> #include "pipe/p_shader_tokens.h" #include "util/u_blitter.h" @@ -612,7 +614,6 @@ static int r600_get_param(struct pipe_screen* pscreen, enum pipe_cap param) case PIPE_CAP_FRAGMENT_COLOR_CLAMPED: case PIPE_CAP_VERTEX_COLOR_CLAMPED: case PIPE_CAP_USER_VERTEX_BUFFERS: - case PIPE_CAP_PRIME: return 0; /* Stream output. */ @@ -655,9 +656,11 @@ static int r600_get_param(struct pipe_screen* pscreen, enum pipe_cap param) case PIPE_CAP_MAX_TEXEL_OFFSET: return 7; - case PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK: return PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_R600; + case PIPE_CAP_PRIME: + return rscreen->info.prime_caps & + (DRM_PRIME_CAP_IMPORT | DRM_PRIME_CAP_EXPORT); } return 0; } diff --git a/src/gallium/drivers/r600/r600_texture.c b/src/gallium/drivers/r600/r600_texture.c index 98cb118..8fa821b 100644 --- a/src/gallium/drivers/r600/r600_texture.c +++ b/src/gallium/drivers/r600/r600_texture.c @@ -670,7 +670,7 @@ struct pipe_resource *r600_texture_from_handle(struct pipe_screen *screen, templ->depth0 != 1 || templ->last_level != 0) return NULL; - buf = rscreen->ws->buffer_from_handle(rscreen->ws, whandle, &stride); + buf = rscreen->ws->buffer_from_handle(rscreen->ws, whandle, templ->height0, &stride); if (!buf) return NULL; diff --git a/src/gallium/drivers/radeonsi/r600_texture.c b/src/gallium/drivers/radeonsi/r600_texture.c index 8992f9a..5ef526c 100644 --- a/src/gallium/drivers/radeonsi/r600_texture.c +++ b/src/gallium/drivers/radeonsi/r600_texture.c @@ -602,7 +602,7 @@ struct pipe_resource *si_texture_from_handle(struct pipe_screen *screen, templ->depth0 != 1 || templ->last_level != 0) return NULL; - buf = rscreen->ws->buffer_from_handle(rscreen->ws, whandle, &stride); + buf = rscreen->ws->buffer_from_handle(rscreen->ws, whandle, templ->height0, &stride); if (!buf) return NULL; diff --git a/src/gallium/drivers/radeonsi/radeonsi_pipe.c b/src/gallium/drivers/radeonsi/radeonsi_pipe.c index 1705e3e..60c40f5 100644 --- a/src/gallium/drivers/radeonsi/radeonsi_pipe.c +++ b/src/gallium/drivers/radeonsi/radeonsi_pipe.c @@ -20,6 +20,7 @@ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE * USE OR OTHER DEALINGS IN THE SOFTWARE. */ +#include <drm.h> #include <stdio.h> #include <errno.h> #include "pipe/p_defines.h" @@ -381,7 +382,6 @@ static int r600_get_param(struct pipe_screen* pscreen, enum pipe_cap param) case PIPE_CAP_TEXTURE_BUFFER_OBJECTS: case PIPE_CAP_TEXTURE_BUFFER_OFFSET_ALIGNMENT: case PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK: - case PIPE_CAP_PRIME: return 0; /* Stream output. */ @@ -424,6 +424,10 @@ static int r600_get_param(struct pipe_screen* pscreen, enum pipe_cap param) case PIPE_CAP_MAX_TEXEL_OFFSET: return 7; + + case PIPE_CAP_PRIME: + return rscreen->info.prime_caps & + (DRM_PRIME_CAP_IMPORT | DRM_PRIME_CAP_EXPORT); } return 0; } diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_bo.c b/src/gallium/winsys/radeon/drm/radeon_drm_bo.c index c0ea4c0..53d9e9c 100644 --- a/src/gallium/winsys/radeon/drm/radeon_drm_bo.c +++ b/src/gallium/winsys/radeon/drm/radeon_drm_bo.c @@ -40,6 +40,7 @@ #include <sys/ioctl.h> #include <xf86drm.h> #include <errno.h> +#include <fcntl.h> /* * this are copy from radeon_drm, once an updated libdrm is released @@ -116,6 +117,8 @@ struct radeon_bomgr { /* List of buffer GEM names. Protected by bo_handles_mutex. */ struct util_hash_table *bo_names; + /* List of buffer handles. Protectded by bo_handles_mutex. */ + struct util_hash_table *bo_handles; pipe_mutex bo_handles_mutex; pipe_mutex bo_va_mutex; @@ -370,12 +373,13 @@ static void radeon_bo_destroy(struct pb_buffer *_buf) memset(&args, 0, sizeof(args)); + pipe_mutex_lock(bo->mgr->bo_handles_mutex); + util_hash_table_remove(bo->mgr->bo_handles, (void*)(uintptr_t)bo->handle); if (bo->name) { - pipe_mutex_lock(bo->mgr->bo_handles_mutex); util_hash_table_remove(bo->mgr->bo_names, (void*)(uintptr_t)bo->name); - pipe_mutex_unlock(bo->mgr->bo_handles_mutex); } + pipe_mutex_unlock(bo->mgr->bo_handles_mutex); if (bo->ptr) os_munmap(bo->ptr, bo->base.size); @@ -659,6 +663,7 @@ static void radeon_bomgr_destroy(struct pb_manager *_mgr) { struct radeon_bomgr *mgr = radeon_bomgr(_mgr); util_hash_table_destroy(mgr->bo_names); + util_hash_table_destroy(mgr->bo_handles);; pipe_mutex_destroy(mgr->bo_handles_mutex); pipe_mutex_destroy(mgr->bo_va_mutex); FREE(mgr); @@ -691,6 +696,7 @@ struct pb_manager *radeon_bomgr_create(struct radeon_drm_winsys *rws) mgr->rws = rws; mgr->bo_names = util_hash_table_create(handle_hash, handle_compare); + mgr->bo_handles = util_hash_table_create(handle_hash, handle_compare); pipe_mutex_init(mgr->bo_handles_mutex); pipe_mutex_init(mgr->bo_va_mutex); @@ -839,6 +845,7 @@ radeon_winsys_bo_create(struct radeon_winsys *rws, enum radeon_bo_domain domain) { struct radeon_drm_winsys *ws = radeon_drm_winsys(rws); + struct radeon_bomgr *mgr = radeon_bomgr(ws->kman); struct radeon_bo_desc desc; struct pb_manager *provider; struct pb_buffer *buffer; @@ -860,11 +867,16 @@ radeon_winsys_bo_create(struct radeon_winsys *rws, if (!buffer) return NULL; + pipe_mutex_lock(mgr->bo_handles_mutex); + util_hash_table_set(mgr->bo_handles, (void*)(uintptr_t)get_radeon_bo(buffer)->handle, buffer); + pipe_mutex_unlock(mgr->bo_handles_mutex); + return (struct pb_buffer*)buffer; } static struct pb_buffer *radeon_winsys_bo_from_handle(struct radeon_winsys *rws, struct winsys_handle *whandle, + unsigned height, unsigned *stride) { struct radeon_drm_winsys *ws = radeon_drm_winsys(rws); @@ -872,6 +884,7 @@ static struct pb_buffer *radeon_winsys_bo_from_handle(struct radeon_winsys *rws, struct radeon_bomgr *mgr = radeon_bomgr(ws->kman); struct drm_gem_open open_arg = {}; int r; + unsigned handle, size; memset(&open_arg, 0, sizeof(open_arg)); @@ -883,8 +896,20 @@ static struct pb_buffer *radeon_winsys_bo_from_handle(struct radeon_winsys *rws, * The list of pairs is guarded by a mutex, of course. */ pipe_mutex_lock(mgr->bo_handles_mutex); - /* First check if there already is an existing bo for the handle. */ - bo = util_hash_table_get(mgr->bo_names, (void*)(uintptr_t)whandle->handle); + if (whandle->type == DRM_API_HANDLE_TYPE_SHARED) { + /* First check if there already is an existing bo for the handle. */ + bo = util_hash_table_get(mgr->bo_names, (void*)(uintptr_t)whandle->handle); + } else if (whandle->type == DRM_API_HANDLE_TYPE_FD) { + /* We must first get the GEM handle, as fds are unreliable keys */ + r = drmPrimeFDToHandle(ws->fd, whandle->handle, &handle); + if (r) + goto fail; + bo = util_hash_table_get(mgr->bo_handles, (void*)(uintptr_t)handle); + } else { + /* Unknown handle type */ + goto fail; + } + if (bo) { /* Increase the refcount. */ struct pb_buffer *b = NULL; @@ -898,27 +923,40 @@ static struct pb_buffer *radeon_winsys_bo_from_handle(struct radeon_winsys *rws, goto fail; } - /* Open the BO. */ - open_arg.name = whandle->handle; - if (drmIoctl(ws->fd, DRM_IOCTL_GEM_OPEN, &open_arg)) { - FREE(bo); - goto fail; + if (whandle->type == DRM_API_HANDLE_TYPE_SHARED) { + /* Open the BO. */ + open_arg.name = whandle->handle; + if (drmIoctl(ws->fd, DRM_IOCTL_GEM_OPEN, &open_arg)) { + FREE(bo); + goto fail; + } + handle = open_arg.handle; + size = open_arg.size; + bo->name = whandle->handle; + } else if (whandle->type == DRM_API_HANDLE_TYPE_FD) { + /* You know, it'd be really nice if we could get size out of the + * dma-buf fd. + */ + size = height * whandle->stride; } - bo->handle = open_arg.handle; - bo->name = whandle->handle; + + bo->handle = handle; /* Initialize it. */ pipe_reference_init(&bo->base.reference, 1); bo->base.alignment = 0; bo->base.usage = PB_USAGE_GPU_WRITE | PB_USAGE_GPU_READ; - bo->base.size = open_arg.size; + bo->base.size = size; bo->base.vtbl = &radeon_bo_vtbl; bo->mgr = mgr; bo->rws = mgr->rws; bo->va = 0; pipe_mutex_init(bo->map_mutex); - util_hash_table_set(mgr->bo_names, (void*)(uintptr_t)whandle->handle, bo); + if (bo->name) + util_hash_table_set(mgr->bo_names, (void*)(uintptr_t)bo->name, bo); + + util_hash_table_set(mgr->bo_handles, (void*)(uintptr_t)bo->handle, bo); done: pipe_mutex_unlock(mgr->bo_handles_mutex); @@ -956,6 +994,9 @@ done: ws->allocated_vram += align(open_arg.size, 4096); bo->initial_domain = RADEON_DOMAIN_VRAM; + if (whandle->type == DRM_API_HANDLE_TYPE_FD) + bo->initial_domain = RADEON_DOMAIN_GTT; + return (struct pb_buffer*)bo; fail: @@ -990,6 +1031,9 @@ static boolean radeon_winsys_bo_get_handle(struct pb_buffer *buffer, whandle->handle = bo->flink; } else if (whandle->type == DRM_API_HANDLE_TYPE_KMS) { whandle->handle = bo->handle; + } else if (whandle->type == DRM_API_HANDLE_TYPE_FD) { + if (drmPrimeHandleToFD(bo->rws->fd, bo->handle, DRM_CLOEXEC, (int*)&whandle->handle)) + return FALSE; } whandle->stride = stride; diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c b/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c index f6877d5..412d280 100644 --- a/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c +++ b/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c @@ -340,6 +340,10 @@ static boolean do_winsys_init(struct radeon_drm_winsys *ws) ws->info.has_uvd = value; } + /* Check for PRIME */ + ws->info.prime_caps = 0; + drmGetCap(ws->fd, DRM_CAP_PRIME, &ws->info.prime_caps); + /* Get GEM info. */ retval = drmCommandWriteRead(ws->fd, DRM_RADEON_GEM_INFO, &gem_info, sizeof(gem_info)); diff --git a/src/gallium/winsys/radeon/drm/radeon_winsys.h b/src/gallium/winsys/radeon/drm/radeon_winsys.h index a37bd12..448b305 100644 --- a/src/gallium/winsys/radeon/drm/radeon_winsys.h +++ b/src/gallium/winsys/radeon/drm/radeon_winsys.h @@ -178,6 +178,8 @@ struct radeon_info { uint32_t r300_num_gb_pipes; uint32_t r300_num_z_pipes; + uint64_t prime_caps; + uint32_t r600_num_backends; uint32_t r600_clock_crystal_freq; uint32_t r600_tiling_config; @@ -334,6 +336,7 @@ struct radeon_winsys { */ struct pb_buffer *(*buffer_from_handle)(struct radeon_winsys *ws, struct winsys_handle *whandle, + unsigned height, unsigned *stride); /** -- 1.8.1.2 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev