Allow creating VA surfaces with userptr allocated buffers. This requires a recent enough version of libdrm (>= 2.4.57), but also a kernel (>= 3.16) which contains appropriate fixes for userptr.
v2: only request synchronized mappings (Chris Wilson). Signed-off-by: Gwenole Beauchesne <gwenole.beauche...@intel.com> --- configure.ac | 19 ++++++++++++ src/i965_drv_video.c | 81 +++++++++++++++++++++++++++++++++++++++++----------- src/i965_drv_video.h | 1 + src/intel_driver.h | 1 + src/intel_memman.c | 64 ++++++++++++++++++++++++++++++++++++++++- src/intel_memman.h | 7 +++++ 6 files changed, 156 insertions(+), 17 deletions(-) diff --git a/configure.ac b/configure.ac index d71a3cc..3c19cd2 100644 --- a/configure.ac +++ b/configure.ac @@ -76,6 +76,25 @@ LIBDRM_VERSION=libdrm_version PKG_CHECK_MODULES([DRM], [libdrm >= $LIBDRM_VERSION]) AC_SUBST(LIBDRM_VERSION) +AC_CACHE_CHECK([whether libdrm supports userptr allocations], + [ac_cv_libdrm_has_userptr], + [saved_CPPFLAGS="$CPPFLAGS" + saved_CFLAGS="$CFLAGS" + CPPFLAGS="$CPPFLAGS $DRM_CFLAGS" + LIBS="$LIBS $DRM_LIBS -ldrm_intel" + AC_TRY_LINK( + [#include <intel_bufmgr.h>], + [drm_intel_bo_alloc_userptr(NULL, NULL, NULL, 0, 0, 0, 0)], + [ac_cv_libdrm_has_userptr="yes"], + [ac_cv_libdrm_has_userptr="no"]) + CPPFLAGS="$saved_CPPFLAGS" + LIBS="$saved_LIBS"] +) +if test "$ac_cv_libdrm_has_userptr" = "yes"; then + AC_DEFINE([HAVE_DRM_INTEL_USERPTR], [1], + [Defined to 1 if libdrm supports userptr allocations]) +fi + dnl Check for gen4asm PKG_CHECK_MODULES(GEN4ASM, [intel-gen4asm >= 1.9], [gen4asm=yes], [gen4asm=no]) AC_PATH_PROG([GEN4ASM], [intel-gen4asm]) diff --git a/src/i965_drv_video.c b/src/i965_drv_video.c index 799ebad..0e4ccb7 100644 --- a/src/i965_drv_video.c +++ b/src/i965_drv_video.c @@ -992,24 +992,18 @@ i965_surface_native_memory(VADriverContextP ctx, return VA_STATUS_SUCCESS; } - + static VAStatus -i965_suface_external_memory(VADriverContextP ctx, - struct object_surface *obj_surface, - int external_memory_type, - VASurfaceAttribExternalBuffers *memory_attibute, - int index) +set_surface_info_from_extbuf(VADriverContextP tx, + struct object_surface *obj_surface, + VASurfaceAttribExternalBuffers *memory_attibute) { - struct i965_driver_data *i965 = i965_driver_data(ctx); - - if (!memory_attibute || - !memory_attibute->buffers || - index >= memory_attibute->num_buffers) - return VA_STATUS_ERROR_INVALID_PARAMETER; - - ASSERT_RET(obj_surface->orig_width == memory_attibute->width, VA_STATUS_ERROR_INVALID_PARAMETER); - ASSERT_RET(obj_surface->orig_height == memory_attibute->height, VA_STATUS_ERROR_INVALID_PARAMETER); - ASSERT_RET(memory_attibute->num_planes >= 1, VA_STATUS_ERROR_INVALID_PARAMETER); + ASSERT_RET(obj_surface->orig_width == memory_attibute->width, + VA_STATUS_ERROR_INVALID_PARAMETER); + ASSERT_RET(obj_surface->orig_height == memory_attibute->height, + VA_STATUS_ERROR_INVALID_PARAMETER); + ASSERT_RET(memory_attibute->num_planes >= 1, + VA_STATUS_ERROR_INVALID_PARAMETER); obj_surface->fourcc = memory_attibute->pixel_format; obj_surface->width = memory_attibute->pitches[0]; @@ -1175,6 +1169,27 @@ i965_suface_external_memory(VADriverContextP ctx, return VA_STATUS_ERROR_INVALID_PARAMETER; } + return VA_STATUS_SUCCESS; +} + +static VAStatus +i965_suface_external_memory(VADriverContextP ctx, + struct object_surface *obj_surface, + int external_memory_type, + VASurfaceAttribExternalBuffers *memory_attibute, + int index) +{ + struct i965_driver_data *i965 = i965_driver_data(ctx); + VAStatus status; + + if (!memory_attibute || + !memory_attibute->buffers || + index >= memory_attibute->num_buffers) + return VA_STATUS_ERROR_INVALID_PARAMETER; + + status = set_surface_info_from_extbuf(ctx, obj_surface, memory_attibute); + if (status != VA_STATUS_SUCCESS) + return status; if (external_memory_type == I965_SURFACE_MEM_GEM_FLINK) obj_surface->bo = drm_intel_bo_gem_create_from_name(i965->intel.bufmgr, @@ -1191,6 +1206,32 @@ i965_suface_external_memory(VADriverContextP ctx, return VA_STATUS_SUCCESS; } +static VAStatus +i965_surface_from_userptr(VADriverContextP ctx, + struct object_surface *obj_surface, + VASurfaceAttribExternalBuffers *memory_attribute, int index) +{ + struct i965_driver_data * const i965 = i965_driver_data(ctx); + VAStatus status; + + if (!memory_attribute || !memory_attribute->buffers) + return VA_STATUS_ERROR_INVALID_PARAMETER; + if (index >= memory_attribute->num_buffers) + return VA_STATUS_ERROR_MAX_NUM_EXCEEDED; + + status = set_surface_info_from_extbuf(ctx, obj_surface, memory_attribute); + if (status != VA_STATUS_SUCCESS) + return status; + + obj_surface->bo = intel_memman_import_userptr(&i965->intel, + "vaapi surface (userptr)", (void *)memory_attribute->buffers[index], + obj_surface->size, memory_attribute->flags); + if (!obj_surface->bo) + return VA_STATUS_ERROR_ALLOCATION_FAILED; + + return VA_STATUS_SUCCESS; +} + /* byte-per-pixel of the first plane */ static int bpp_1stplane_by_fourcc(unsigned int fourcc) @@ -1240,6 +1281,10 @@ i965_CreateSurfaces2( memory_type = I965_SURFACE_MEM_DRM_PRIME; /* drm prime fd */ else if (attrib_list[i].value.value.i == VA_SURFACE_ATTRIB_MEM_TYPE_VA) memory_type = I965_SURFACE_MEM_NATIVE; /* va native memory, to be allocated */ +#ifdef HAVE_DRM_INTEL_USERPTR + else if (attrib_list[i].value.value.i == VA_SURFACE_ATTRIB_MEM_TYPE_USER_PTR) + memory_type = I965_SURFACE_MEM_USERPTR; +#endif else memory_type = 0; } @@ -1345,6 +1390,10 @@ i965_CreateSurfaces2( memory_attibute, i); break; + case I965_SURFACE_MEM_USERPTR: + vaStatus = i965_surface_from_userptr(ctx, obj_surface, + memory_attibute, i); + break; } } diff --git a/src/i965_drv_video.h b/src/i965_drv_video.h index c39d53b..d63c9c1 100644 --- a/src/i965_drv_video.h +++ b/src/i965_drv_video.h @@ -509,6 +509,7 @@ enum { I965_SURFACE_MEM_NATIVE = 1, I965_SURFACE_MEM_GEM_FLINK, I965_SURFACE_MEM_DRM_PRIME, + I965_SURFACE_MEM_USERPTR, }; void diff --git a/src/intel_driver.h b/src/intel_driver.h index 3c20ce4..4a0bdd4 100644 --- a/src/intel_driver.h +++ b/src/intel_driver.h @@ -152,6 +152,7 @@ struct intel_driver_data dri_bufmgr *bufmgr; + unsigned int userptr_disabled; unsigned int has_exec2 : 1; /* Flag: has execbuffer2? */ unsigned int has_bsd : 1; /* Flag: has bitstream decoder for H.264? */ unsigned int has_blt : 1; /* Flag: has BLT unit? */ diff --git a/src/intel_memman.c b/src/intel_memman.c index 03ed216..531e72b 100644 --- a/src/intel_memman.c +++ b/src/intel_memman.c @@ -27,9 +27,12 @@ * */ +#include "config.h" #include <assert.h> - +#include <stdlib.h> +#include <unistd.h> #include "intel_driver.h" +#include "intel_memman.h" Bool intel_memman_init(struct intel_driver_data *intel) @@ -44,6 +47,8 @@ intel_memman_init(struct intel_driver_data *intel) drm_intel_bufmgr_gem_set_aub_dump(intel->bufmgr, 1); } + /* Only check for userptr when needed, through intel_memman_has_userptr() */ + intel->userptr_disabled = 2; return True; } @@ -53,3 +58,60 @@ intel_memman_terminate(struct intel_driver_data *intel) drm_intel_bufmgr_destroy(intel->bufmgr); return True; } + +drm_intel_bo * +do_import_userptr(struct intel_driver_data *intel, const char *name, + void *data, size_t data_size, uint32_t va_flags) +{ +#ifdef HAVE_DRM_INTEL_USERPTR + uint32_t page_size, tiling_mode, flags = 0; + drm_intel_bo *bo; + + /* XXX: userptr is only supported for page-aligned allocations */ + page_size = getpagesize(); + if ((uintptr_t)data & (page_size - 1)) + return NULL; + + tiling_mode = (va_flags & VA_SURFACE_EXTBUF_DESC_ENABLE_TILING) ? + I915_TILING_Y : I915_TILING_NONE; + + bo = drm_intel_bo_alloc_userptr(intel->bufmgr, name, data, tiling_mode, 0, + data_size, flags); + if (bo) + return bo; +#endif + return NULL; +} + +drm_intel_bo * +intel_memman_import_userptr(struct intel_driver_data *intel, const char *name, + void *data, size_t data_size, uint32_t va_flags) +{ + if (!intel_memman_has_userptr(intel)) + return NULL; + return do_import_userptr(intel, name, data, data_size, va_flags); +} + +bool +intel_memman_has_userptr(struct intel_driver_data *intel) +{ + drm_intel_bo *bo; + size_t page_size; + void *page; + + if (intel->userptr_disabled > 1) { + intel->userptr_disabled = 1; + + page_size = getpagesize(); + if (posix_memalign(&page, page_size, page_size) == 0) { + bo = do_import_userptr(intel, "userptr test buffer", + page, page_size, 0); + if (bo) { + drm_intel_bo_unreference(bo); + intel->userptr_disabled = 0; + } + free(page); + } + } + return !intel->userptr_disabled; +} diff --git a/src/intel_memman.h b/src/intel_memman.h index 4e516e5..3a1235d 100644 --- a/src/intel_memman.h +++ b/src/intel_memman.h @@ -4,4 +4,11 @@ Bool intel_memman_init(struct intel_driver_data *intel); Bool intel_memman_terminate(struct intel_driver_data *intel); +bool +intel_memman_has_userptr(struct intel_driver_data *intel); + +drm_intel_bo * +intel_memman_import_userptr(struct intel_driver_data *intel, const char *name, + void *data, size_t data_size, uint32_t va_flags); + #endif /* _INTEL_MEMMAN_H_ */ -- 1.9.1 _______________________________________________ Libva mailing list Libva@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libva