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

Marek Olšák maraeo at gmail.com
Mon Apr 22 04:21:37 PDT 2013


On Mon, Apr 22, 2013 at 8:38 AM,
<christopher.halse.rogers at canonical.com> wrote:
> 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);
> +

This piece of code should be moved to radeon_bomgr_create_bo.
radeon_winsys_bo_create is only a wrapper.

>      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;

Can you by any chance obtain the size from the kernel? The kernel
should know it and some drivers (r300 for sure, not sure about r600)
refuse to initialize the texture if the size is too small.

>      }
> -    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;
> +

ws->allocated_vram shouldn't be incremented if the initial domain is
GTT. ws->allocated_gtt should be incremented instead.

Marek


More information about the mesa-dev mailing list