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

Christian König deathsimple at vodafone.de
Mon Apr 22 04:33:32 PDT 2013


Am 22.04.2013 13:21, schrieb Marek Olšák:
> 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.

Indeed this will probably fail if the FD is containing some sort of 
tiled buffer.

>
>>       }
>> -    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.

Why do we need to force this buffer to GTT anyway if it's shared using 
an FD instead of an handle?

Christian.

> Marek
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/mesa-dev
>



More information about the mesa-dev mailing list