[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