[Mesa-dev] [PATCH 4/4] radeon: Enable DRI Image 7 support

christopher.halse.rogers at canonical.com christopher.halse.rogers at canonical.com
Sun Apr 21 23:38:07 PDT 2013


From: Christopher James Halse Rogers <raof at 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



More information about the mesa-dev mailing list