[Libva] [PATCH intel-driver v2 3/3] extbuf: add support for userptr imports.
Gwenole Beauchesne
gb.devel at gmail.com
Thu Apr 2 07:30:24 PDT 2015
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.beauchesne at 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
More information about the Libva
mailing list