From 1642615ba659ab93bc58923d03e598f34ebd69e7 Mon Sep 17 00:00:00 2001 From: zhangyichix Date: Fri, 1 Dec 2023 10:38:04 +0800 Subject: [PATCH] Upgrade to release tag: Libva 2.20.0 * Release tag: https://github.com/intel/libva/releases/tag/2.20.0 Tracked-On: OAM-113713 Signed-off-by: zhangyichix --- NEWS | 30 ++++++- configure.ac | 2 +- meson.build | 4 +- va/android/va_android.cpp | 28 +++---- va/drm/va_drm.c | 29 +++---- va/drm/va_drm_utils.c | 131 +++++++++++------------------- va/drm/va_drm_utils.h | 24 +----- va/va.c | 153 +++++++++++++++-------------------- va/va.h | 28 +++++-- va/va_backend.h | 29 ++++++- va/va_dec_jpeg.h | 4 +- va/va_enc_av1.h | 3 +- va/va_trace.c | 69 ++++++++++++++-- va/va_trace.h | 10 +++ va/va_version.h | 6 +- va/wayland/va_wayland.c | 8 -- va/wayland/va_wayland_drm.c | 35 ++------ va/wayland/va_wayland_emgd.c | 11 ++- va/win32/va_win32.c | 71 ++++++---------- va/x11/Makefile.am | 1 + va/x11/va_dri2.c | 53 ++++++++++++ va/x11/va_dri2_priv.h | 43 ++++++++++ va/x11/va_dri3.c | 21 ++--- va/x11/va_dri3.h | 12 +-- va/x11/va_fglrx.c | 37 +++------ va/x11/va_fglrx.h | 6 +- va/x11/va_nvctrl.c | 51 +++++------- va/x11/va_nvctrl.h | 6 +- va/x11/va_x11.c | 130 +++-------------------------- 29 files changed, 491 insertions(+), 544 deletions(-) create mode 100644 va/x11/va_dri2_priv.h diff --git a/NEWS b/NEWS index 16408842..b327aa48 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,34 @@ -libva NEWS -- summary of user visible changes. 2023-07-04 +libva NEWS -- summary of user visible changes. 2023-09-14 Copyright (C) 2009-2023 Intel Corporation +version 2.20.0 - 14.Sep.2023 +* va: drop no longer applicable vaGetDriverNames check +* va: remove unreachable "DRIVER BUG" +* x11/dri2: limit the array handling to avoid out of range access +* va/backend: document the vaGetDriver* APIs +* va/backend: annotate vafool as deprecated +* win32: remove duplicate adapter_luid entry +* va: Added Q416 fourcc (three-plane 16-bit YUV 4:4:4) +* trace: fix minor issue about printf data type and value range +* jpeg: add support for crop and partial decode +* trace: Unlock mutex before return +* trace: Add trace for vaExportSurfaceHandle +* av1: Revise offsets comments for av1 encode +* va: Add new VADecodeErrorType to indicate the reset happended in the driver. +* drm: limit the array size to avoid out of range +* va: fix:set driver number to be zero if vaGetDriverNames failed +* va: fix:don't leak driver names, when override is set +* win32: Only print win32 driver messages in DEBUG builds +* va: Add vendor string on va_TraceInitialize +* va: remove legacy code paths +* drm: remove no longer used helpers +* x11: remove legacy code paths +* x11: allow disabling DRI3 via LIBVA_DRI3_DISABLE env var +* x11: implement vaGetDriverNames +* va/x11/va_nvctrl: remove some dead code +* va/x11/va_fglrx: remove some dead code +* va: optimize code of getting driver name for all protocols/os(wayland,x11,drm,win32,android) + version 2.19.0 - 04.Jul.2023 * docs: fix references and descriptions snf focyhrn mstkup * ci: add build docs test diff --git a/configure.ac b/configure.ac index eb82831f..eb6ef998 100644 --- a/configure.ac +++ b/configure.ac @@ -27,7 +27,7 @@ # - reset micro version to zero when minor version is incremented # - reset minor version to zero when major version is incremented m4_define([va_api_major_version], [1]) -m4_define([va_api_minor_version], [19]) +m4_define([va_api_minor_version], [20]) m4_define([va_api_micro_version], [0]) m4_define([va_api_version], diff --git a/meson.build b/meson.build index 011020eb..a8805b28 100644 --- a/meson.build +++ b/meson.build @@ -7,7 +7,7 @@ # - reset micro version to zero when VA-API major or minor version is changed project( 'libva', 'c', - version : '2.19.0', + version : '2.20.0', meson_version : '>= 0.53.0', default_options : [ 'warning_level=1', 'buildtype=debugoptimized' ]) @@ -19,7 +19,7 @@ project( # - reset micro version to zero when minor version is incremented # - reset minor version to zero when major version is incremented va_api_major_version = 1 -va_api_minor_version = 19 +va_api_minor_version = 20 va_api_micro_version = 0 va_api_version = '@0@.@1@.@2@'.format(va_api_major_version, diff --git a/va/android/va_android.cpp b/va/android/va_android.cpp index f103d155..a16dc6a3 100644 --- a/va/android/va_android.cpp +++ b/va/android/va_android.cpp @@ -1,5 +1,6 @@ /* * Copyright (c) 2007 Intel Corporation. All Rights Reserved. + * Copyright (c) 2023 Emil Velikov * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the @@ -61,38 +62,38 @@ static void va_DisplayContextDestroy( free(pDisplayContext); } -static VAStatus va_DisplayContextGetNumCandidates( - VADisplayContextP pDisplayContext, - int *num_candidates +static VAStatus va_DisplayContextConnect( + VADisplayContextP pDisplayContext ) { VADriverContextP const ctx = pDisplayContext->pDriverContext; - struct drm_state * drm_state = (struct drm_state *)ctx->drm_state; + struct drm_state * const drm_state = (struct drm_state *)ctx->drm_state; - memset(drm_state, 0, sizeof(*drm_state)); drm_state->fd = open(DEVICE_NAME, O_RDWR | O_CLOEXEC); - if (drm_state->fd < 0) { fprintf(stderr, "Cannot open DRM device '%s': %d, %s\n", DEVICE_NAME, errno, strerror(errno)); return VA_STATUS_ERROR_UNKNOWN; } drm_state->auth_type = VA_DRM_AUTH_CUSTOM; - return VA_DRM_GetNumCandidates(ctx, num_candidates); + return VA_STATUS_SUCCESS; } -static VAStatus va_DisplayContextGetDriverNameByIndex( +static VAStatus +va_DisplayContextGetDriverNames( VADisplayContextP pDisplayContext, - char **driver_name, - int candidate_index + char **drivers, + unsigned *num_drivers ) { VADriverContextP const ctx = pDisplayContext->pDriverContext; + VAStatus status = va_DisplayContextConnect(pDisplayContext); + if (status != VA_STATUS_SUCCESS) + return status; - return VA_DRM_GetDriverName(ctx, driver_name, candidate_index); + return VA_DRM_GetDriverNames(ctx, drivers, num_drivers); } - VADisplay vaGetDisplay( void *native_dpy /* implementation specific */ ) @@ -109,8 +110,7 @@ VADisplay vaGetDisplay( return NULL; pDisplayContext->vaDestroy = va_DisplayContextDestroy; - pDisplayContext->vaGetDriverNameByIndex = va_DisplayContextGetDriverNameByIndex; - pDisplayContext->vaGetNumCandidates = va_DisplayContextGetNumCandidates; + pDisplayContext->vaGetDriverNames = va_DisplayContextGetDriverNames; pDriverContext = va_newDriverContext(pDisplayContext); if (!pDriverContext) { diff --git a/va/drm/va_drm.c b/va/drm/va_drm.c index e09cf24f..edfd8f29 100644 --- a/va/drm/va_drm.c +++ b/va/drm/va_drm.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2012 Intel Corporation. All Rights Reserved. + * Copyright (c) 2023 Emil Velikov * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the @@ -41,19 +42,17 @@ va_DisplayContextDestroy(VADisplayContextP pDisplayContext) free(pDisplayContext->pDriverContext); free(pDisplayContext); } -static VAStatus va_DisplayContextGetNumCandidates( - VADisplayContextP pDisplayContext, - int *num_candidates + + +static VAStatus va_DisplayContextConnect( + VADisplayContextP pDisplayContext ) { VADriverContextP const ctx = pDisplayContext->pDriverContext; struct drm_state * const drm_state = ctx->drm_state; - VAStatus status = VA_STATUS_SUCCESS; drm_magic_t magic; int ret; - status = VA_DRM_GetNumCandidates(ctx, num_candidates); - if (status != VA_STATUS_SUCCESS) - return status; + /* Authentication is only needed for a legacy DRM device */ if (ctx->display_type != VA_DISPLAY_DRM_RENDERNODES) { ret = drmGetMagic(drm_state->fd, &magic); @@ -68,17 +67,20 @@ static VAStatus va_DisplayContextGetNumCandidates( return VA_STATUS_SUCCESS; } + static VAStatus -va_DisplayContextGetDriverNameByIndex( +va_DisplayContextGetDriverNames( VADisplayContextP pDisplayContext, - char **driver_name_ptr, - int candidate_index + char **drivers, + unsigned *num_drivers ) { - VADriverContextP const ctx = pDisplayContext->pDriverContext; + VAStatus status = va_DisplayContextConnect(pDisplayContext); + if (status != VA_STATUS_SUCCESS) + return status; - return VA_DRM_GetDriverName(ctx, driver_name_ptr, candidate_index); + return VA_DRM_GetDriverNames(ctx, drivers, num_drivers); } VADisplay @@ -104,8 +106,7 @@ vaGetDisplayDRM(int fd) goto error; pDisplayContext->vaDestroy = va_DisplayContextDestroy; - pDisplayContext->vaGetNumCandidates = va_DisplayContextGetNumCandidates; - pDisplayContext->vaGetDriverNameByIndex = va_DisplayContextGetDriverNameByIndex; + pDisplayContext->vaGetDriverNames = va_DisplayContextGetDriverNames; pDriverContext = va_newDriverContext(pDisplayContext); if (!pDriverContext) diff --git a/va/drm/va_drm_utils.c b/va/drm/va_drm_utils.c index 10e5fca8..ec550a73 100644 --- a/va/drm/va_drm_utils.c +++ b/va/drm/va_drm_utils.c @@ -2,6 +2,7 @@ * va_drm_utils.c - VA/DRM Utilities * * Copyright (c) 2012 Intel Corporation. All Rights Reserved. + * Copyright (c) 2023 Emil Velikov * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the @@ -31,22 +32,7 @@ #include "va_drm_utils.h" #include "va_drmcommon.h" -struct driver_name_map { - const char *key; - const char *name; -}; - -static const struct driver_name_map g_driver_name_map[] = { - { "i915", "iHD" }, // Intel Media driver - { "i915", "i965" }, // Intel OTC GenX driver - { "pvrsrvkm", "pvr" }, // Intel UMG PVR driver - { "radeon", "r600" }, // Mesa Gallium driver - { "radeon", "radeonsi" }, // Mesa Gallium driver - { "amdgpu", "radeonsi" }, // Mesa Gallium driver - { "WSL", "d3d12" }, // Mesa Gallium driver - { "nvidia-drm", "nvidia" }, // NVIDIA driver - { NULL, NULL } -}; +#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) static char * va_DRM_GetDrmDriverName(int fd) @@ -63,88 +49,61 @@ va_DRM_GetDrmDriverName(int fd) return driver_name; } -/* Returns the VA driver candidate num for the active display*/ +/* Returns the VA driver names and how many they are, for the active display */ VAStatus -VA_DRM_GetNumCandidates(VADriverContextP ctx, int * num_candidates) +VA_DRM_GetDriverNames(VADriverContextP ctx, char **drivers, unsigned *num_drivers) { - struct drm_state * const drm_state = ctx->drm_state; - int count = 0; - const struct driver_name_map *m = NULL; - char *driver_name; - - if (!drm_state || drm_state->fd < 0) - return VA_STATUS_ERROR_INVALID_DISPLAY; - - driver_name = va_DRM_GetDrmDriverName(drm_state->fd); - if (!driver_name) - return VA_STATUS_ERROR_UNKNOWN; - - for (m = g_driver_name_map; m->key != NULL; m++) { - if (strcmp(m->key, driver_name) == 0) { - count ++; - } - } - - free(driver_name); - - /* - * If the drm driver name does not have a mapped vaapi driver name, then - * assume they have the same name. - */ - if (count == 0) - count = 1; - - *num_candidates = count; - return VA_STATUS_SUCCESS; -} - -/* Returns the VA driver name for the active display */ -VAStatus -VA_DRM_GetDriverName(VADriverContextP ctx, char **driver_name_ptr, int candidate_index) -{ - struct drm_state * const drm_state = ctx->drm_state; - const struct driver_name_map *m; - int current_index = 0; - - *driver_name_ptr = NULL; - - if (!drm_state || drm_state->fd < 0) - return VA_STATUS_ERROR_INVALID_DISPLAY; - - *driver_name_ptr = va_DRM_GetDrmDriverName(drm_state->fd); - - if (!*driver_name_ptr) +#define MAX_NAMES 2 // Adjust if needed + + static const struct { + const char * const drm_driver; + const char * const va_driver[MAX_NAMES]; + } map[] = { + { "i915", { "iHD", "i965" } }, // Intel Media and OTC GenX + { "pvrsrvkm", { "pvr" } }, // Intel UMG PVR + { "radeon", { "r600", "radeonsi" } }, // Mesa Gallium + { "amdgpu", { "radeonsi" } }, // Mesa Gallium + { "WSL", { "d3d12" } }, // Mesa Gallium + { "nvidia-drm", { "nvidia" } }, // Unofficial NVIDIA + }; + + const struct drm_state * const drm_state = ctx->drm_state; + char *drm_driver; + unsigned count = 0; + + drm_driver = va_DRM_GetDrmDriverName(drm_state->fd); + if (!drm_driver) return VA_STATUS_ERROR_UNKNOWN; /* Map vgem to WSL2 for Windows subsystem for linux */ struct utsname sysinfo = {}; - if (!strncmp(*driver_name_ptr, "vgem", 4) && uname(&sysinfo) >= 0 && + if (!strncmp(drm_driver, "vgem", 4) && uname(&sysinfo) >= 0 && strstr(sysinfo.release, "WSL")) { - free(*driver_name_ptr); - *driver_name_ptr = strdup("WSL"); + free(drm_driver); + drm_driver = strdup("WSL"); + if (!drm_driver) + return VA_STATUS_ERROR_UNKNOWN; } - for (m = g_driver_name_map; m->key != NULL; m++) { - if (strcmp(m->key, *driver_name_ptr) == 0) { - if (current_index == candidate_index) { - break; - } - current_index ++; + for (unsigned i = 0; i < ARRAY_SIZE(map); i++) { + if (strcmp(map[i].drm_driver, drm_driver) == 0) { + const char * const *va_drivers = map[i].va_driver; + for (; count < MAX_NAMES && va_drivers[count] && count < *num_drivers; count++) + drivers[count] = strdup(va_drivers[count]); + + break; } } - /* - * If the drm driver name does not have a mapped vaapi driver name, then - * assume they have the same name. - */ - if (!m->name) - return VA_STATUS_SUCCESS; - - /* Use the mapped vaapi driver name */ - free(*driver_name_ptr); - *driver_name_ptr = strdup(m->name); - if (!*driver_name_ptr) - return VA_STATUS_ERROR_ALLOCATION_FAILED; + /* Fallback to the drm driver, if there's no va equivalent in the map. */ + if (!count) { + drivers[count] = drm_driver; + count++; + } else { + free(drm_driver); + } + + *num_drivers = count; return VA_STATUS_SUCCESS; } diff --git a/va/drm/va_drm_utils.h b/va/drm/va_drm_utils.h index 57108bb8..963933f6 100644 --- a/va/drm/va_drm_utils.h +++ b/va/drm/va_drm_utils.h @@ -41,30 +41,10 @@ #ifdef __cplusplus extern "C" { #endif + DLL_HIDDEN VAStatus -VA_DRM_GetNumCandidates(VADriverContextP ctx, int * num_candidates); -/** - * \brief Returns the VA driver name for the active display. - * - * This functions returns a newly allocated buffer in @driver_name_ptr that - * contains the VA driver name for the active display. Active display means - * the display obtained with any of the vaGetDisplay*() functions. - * - * The VADriverContext.drm_state structure must be valid, i.e. allocated - * and containing an open DRM connection descriptor. The DRM connection - * does *not* need to be authenticated as it only performs a call to - * drmGetVersion(). - * - * @param[in] ctx the pointer to a VADriverContext - * @param[out] driver_name_ptr the newly allocated buffer containing - * the VA driver name - * @return VA_STATUS_SUCCESS if operation is successful, or another - * #VAStatus value otherwise. - */ -DLL_HIDDEN -VAStatus -VA_DRM_GetDriverName(VADriverContextP ctx, char **driver_name_ptr, int candidate_index); +VA_DRM_GetDriverNames(VADriverContextP ctx, char **drivers, unsigned *num_drivers); /**@}*/ diff --git a/va/va.c b/va/va.c index fb62442a..8c4c8c9d 100644 --- a/va/va.c +++ b/va/va.c @@ -57,6 +57,8 @@ #define CHECK_MAXIMUM(s, ctx, var) if (!va_checkMaximum(dpy, ctx->max_##var, #var)) s = VA_STATUS_ERROR_UNKNOWN; #define CHECK_STRING(s, ctx, var) if (!va_checkString(dpy, ctx->str_##var, #var)) s = VA_STATUS_ERROR_UNKNOWN; +#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) + #ifndef HAVE_SECURE_GETENV static char * secure_getenv(const char *name) { @@ -350,66 +352,6 @@ va_getDriverInitName(char *name, int namelen, int major, int minor) int ret = snprintf(name, namelen, "__vaDriverInit_%d_%d", major, minor); return ret > 0 && ret < namelen; } -/** retrieve the back end driver candidate num , by default it should be 1 - * if there are no vaGetNumCandidates implementation in the display context - * it should be 1 to avoid backward compatible issue */ -static VAStatus va_getDriverNumCandidates(VADisplay dpy, int *num_candidates) -{ - VADisplayContextP pDisplayContext = (VADisplayContextP)dpy; - *num_candidates = 1; - const char *driver_name_env = NULL; - VAStatus vaStatus = VA_STATUS_SUCCESS; - VADriverContextP ctx; - - ctx = CTX(dpy); - driver_name_env = secure_getenv("LIBVA_DRIVER_NAME"); - - if (pDisplayContext->vaGetNumCandidates) - vaStatus = pDisplayContext->vaGetNumCandidates(pDisplayContext, num_candidates); - if ((ctx->override_driver_name) || (driver_name_env && (geteuid() == getuid()))) - *num_candidates = 1; - return vaStatus; -} - -static VAStatus va_getDriverNameByIndex(VADisplay dpy, char **driver_name, int candidate_index) -{ - VADisplayContextP pDisplayContext = (VADisplayContextP)dpy; - const char *driver_name_env = NULL; - VADriverContextP ctx; - VAStatus status = VA_STATUS_SUCCESS; - - ctx = CTX(dpy); - if (pDisplayContext->vaGetDriverNameByIndex) { - /*if vaGetDriverNameByIndex is implemented*/ - status = pDisplayContext->vaGetDriverNameByIndex(pDisplayContext, driver_name, candidate_index); - } else { - if (candidate_index == 0) - status = pDisplayContext->vaGetDriverName(pDisplayContext, driver_name); - else - status = VA_STATUS_ERROR_INVALID_PARAMETER; - } - driver_name_env = secure_getenv("LIBVA_DRIVER_NAME"); - /*if user set driver name by vaSetDriverName */ - if (ctx->override_driver_name) { - if (*driver_name) - free(*driver_name); - *driver_name = strdup(ctx->override_driver_name); - if (!(*driver_name)) { - va_errorMessage(dpy, "va_getDriverNameByIndex failed with %s, out of memory\n", vaErrorStr(VA_STATUS_ERROR_ALLOCATION_FAILED)); - return VA_STATUS_ERROR_ALLOCATION_FAILED; - } - va_infoMessage(dpy, "User requested driver '%s'\n", *driver_name); - return VA_STATUS_SUCCESS; - } else if (driver_name_env && (geteuid() == getuid())) { - if (*driver_name) - free(*driver_name); - /*if user set driver name by environment variable*/ - *driver_name = strdup(driver_name_env); - va_infoMessage(dpy, "User environment variable requested driver '%s'\n", *driver_name); - return VA_STATUS_SUCCESS; - } - return status; -} static char *va_getDriverPath(const char *driver_dir, const char *driver_name) { @@ -719,15 +661,74 @@ VAStatus vaSetDriverName( return VA_STATUS_SUCCESS; } +static VAStatus va_new_opendriver(VADisplay dpy) +{ + VADisplayContextP pDisplayContext = (VADisplayContextP)dpy; + /* In the extreme case we can get up-to 5ish names. Pad that out to be on + * the safe side. In the worst case, the DRIVER BUG below will print and + * we'll be capped to the current selection. + */ + char *drivers[20] = { 0, }; + unsigned int num_drivers = ARRAY_SIZE(drivers); + VAStatus vaStatus; + const char *driver_name_env; + VADriverContextP ctx; + + /* XXX: The order is bonkers - env var should take highest priority, then + * override (which ought to be nuked) than native. It's not possible atm, + * since the DPY connect/init happens during the GetDriverNames. + */ + vaStatus = pDisplayContext->vaGetDriverNames(pDisplayContext, drivers, &num_drivers); + if (vaStatus != VA_STATUS_SUCCESS) { + /* Print and error yet continue, as per the above ordering note */ + va_errorMessage(dpy, "vaGetDriverNames() failed with %s\n", vaErrorStr(vaStatus)); + num_drivers = 0; + } + + ctx = CTX(dpy); + driver_name_env = secure_getenv("LIBVA_DRIVER_NAME"); + if ((ctx->override_driver_name) || (driver_name_env && (geteuid() == getuid()))) { + const char *driver = ctx->override_driver_name ? + ctx->override_driver_name : driver_name_env; + + for (unsigned int i = 0; i < num_drivers; i++) + free(drivers[i]); + + drivers[0] = strdup(driver); + num_drivers = 1; + + va_infoMessage(dpy, "User %srequested driver '%s'\n", + ctx->override_driver_name ? "" : "environment variable ", + driver); + } + + for (unsigned int i = 0; i < num_drivers; i++) { + /* The strdup() may have failed. Check here instead of a dozen+ places */ + if (!drivers[i]) { + va_errorMessage(dpy, "%s:%d: Out of memory\n", __func__, __LINE__); + vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; + break; + } + + vaStatus = va_openDriver(dpy, drivers[i]); + va_infoMessage(dpy, "va_openDriver() returns %d\n", vaStatus); + + if (vaStatus == VA_STATUS_SUCCESS) + break; + } + + for (unsigned int i = 0; i < num_drivers; i++) + free(drivers[i]); + + return vaStatus; +} + VAStatus vaInitialize( VADisplay dpy, int *major_version, /* out */ int *minor_version /* out */ ) { - char *driver_name = NULL; - int num_candidates = 1; - int candidate_index = 0; VAStatus vaStatus; CHECK_DISPLAY(dpy); @@ -737,35 +738,13 @@ VAStatus vaInitialize( va_MessagingInit(); va_infoMessage(dpy, "VA-API version %s\n", VA_VERSION_S); - /*get backend driver candidate number, by default the value should be 1*/ - vaStatus = va_getDriverNumCandidates(dpy, &num_candidates); - if (vaStatus != VA_STATUS_SUCCESS) { - num_candidates = 1; - } - /*load driver one by one, until load success */ - for (candidate_index = 0; candidate_index < num_candidates; candidate_index ++) { - if (driver_name) - free(driver_name); - vaStatus = va_getDriverNameByIndex(dpy, &driver_name, candidate_index); - if (vaStatus != VA_STATUS_SUCCESS) { - va_errorMessage(dpy, "vaGetDriverNameByIndex() failed with %s, driver_name = %s\n", vaErrorStr(vaStatus), driver_name); - break; - } - vaStatus = va_openDriver(dpy, driver_name); - va_infoMessage(dpy, "va_openDriver() returns %d\n", vaStatus); - if (vaStatus == VA_STATUS_SUCCESS) { - break; - } + vaStatus = va_new_opendriver(dpy); - } *major_version = VA_MAJOR_VERSION; *minor_version = VA_MINOR_VERSION; - if (driver_name) - free(driver_name); - VA_TRACE_LOG(va_TraceInitialize, dpy, major_version, minor_version); VA_TRACE_RET(dpy, vaStatus); return vaStatus; @@ -1572,6 +1551,8 @@ vaExportSurfaceHandle(VADisplay dpy, VASurfaceID surface_id, vaStatus = ctx->vtable->vaExportSurfaceHandle(ctx, surface_id, mem_type, flags, descriptor); + VA_TRACE_LOG(va_TraceExportSurfaceHandle, dpy, surface_id, mem_type, flags, descriptor); + VA_TRACE_RET(dpy, vaStatus); return vaStatus; } diff --git a/va/va.h b/va/va.h index 5b98658e..311ff61a 100644 --- a/va/va.h +++ b/va/va.h @@ -305,7 +305,7 @@ typedef int VAStatus; /** Return status type from functions */ #define VA_STATUS_ERROR_NOT_ENOUGH_BUFFER 0x00000025 /** \brief Indicate an operation isn't completed because time-out interval elapsed. */ #define VA_STATUS_ERROR_TIMEDOUT 0x00000026 -#define VA_STATUS_ERROR_UNKNOWN 0xFFFFFFFF +#define VA_STATUS_ERROR_UNKNOWN 0xFFFFFFFF /** * 1. De-interlacing flags for vaPutSurface() @@ -669,8 +669,8 @@ typedef enum { * at vaBeginPicture() time refers to the decode output surface. The * target surface for the output of processing needs to be a different * surface since the decode process requires the original reconstructed buffer. - * The “surface” member of VAProcPipelineParameterBuffer should be set to the - * same as “render_target” set in vaBeginPicture(), but the driver may choose + * The "surface" member of VAProcPipelineParameterBuffer should be set to the + * same as "render_target" set in vaBeginPicture(), but the driver may choose * to ignore this parameter. */ VAConfigAttribDecProcessing = 8, @@ -1151,8 +1151,10 @@ typedef union _VAConfigAttribValDecJPEG { struct { /** \brief Set to (1 << VA_ROTATION_xxx) for supported rotation angles. */ uint32_t rotation : 4; + /** \brief set to 1 for crop and partial decode support, 0 if not supported */ + uint32_t crop : 1; /** \brief Reserved for future use. */ - uint32_t reserved : 28; + uint32_t reserved : 27; } bits; uint32_t value; } VAConfigAttribValDecJPEG; @@ -4205,6 +4207,7 @@ VAStatus vaQuerySurfaceStatus( typedef enum { VADecodeSliceMissing = 0, VADecodeMBError = 1, + VADecodeReset = 2, } VADecodeErrorType; /** @@ -4224,9 +4227,15 @@ typedef struct _VASurfaceDecodeMBErrors { /** * After the application gets VA_STATUS_ERROR_DECODING_ERROR after calling vaSyncSurface(), * it can call vaQuerySurfaceError to find out further details on the particular error. - * VA_STATUS_ERROR_DECODING_ERROR should be passed in as "error_status", - * upon the return, error_info will point to an array of _VASurfaceDecodeMBErrors structure, - * which is allocated and filled by libVA with detailed information on the missing or error macroblocks. + * VA_STATUS_ERROR_DECODING_ERROR should be passed in as "error_status". + * + * After the applications get VA_STATUS_HW_BUSY or VA_STATUS_SUCCESSFULL from vaSyncSurface(), + * it still can call vaQuerySurfaceError to find out further details to know if has real hw reset + * happened on this surface since umd and kmd could recover the context from reset with success in sometimes. + * VA_STATUS_HW_BUSY or VA_STATUS_SUCCESSFULL also could be passed in as "error_status". + * + * Upon the return, error_info will point to an array of _VASurfaceDecodeMBErrors structure, + * which is allocated and filled by libVA with detailed information on the VADecodeErrorType. * The array is terminated if "status==-1" is detected. */ VAStatus vaQuerySurfaceError( @@ -4574,6 +4583,11 @@ VAStatus vaSyncBuffer( * Four bytes per pixel: X, Y, U, V. */ #define VA_FOURCC_XYUV 0x56555958 +/** Q416: three-plane 16-bit YUV 4:4:4. + * + * The three planes contain Y, U and V respectively. + */ +#define VA_FOURCC_Q416 0x36313451 /* byte order */ #define VA_LSB_FIRST 1 diff --git a/va/va_backend.h b/va/va_backend.h index 6031db2d..51e80d05 100644 --- a/va/va_backend.h +++ b/va/va_backend.h @@ -663,6 +663,7 @@ struct VADisplayContext { VADisplayContextP ctx ); + /* Deprecated */ VAStatus(*vaGetDriverName)( VADisplayContextP ctx, char **driver_name @@ -670,25 +671,51 @@ struct VADisplayContext { void *opaque; /* opaque for display extensions (e.g. GLX) */ void *vatrace; /* opaque for VA trace context */ + /* Deprecated */ void *vafool; /* opaque for VA fool context */ VAMessageCallback error_callback; void *error_callback_user_context; VAMessageCallback info_callback; void *info_callback_user_context; + + /* Deprecated */ VAStatus(*vaGetNumCandidates)( VADisplayContextP ctx, int * num_candidates ); + /* Deprecated */ VAStatus(*vaGetDriverNameByIndex)( VADisplayContextP ctx, char **driver_name, int candidate_index ); + /** + * \brief Callback to get an array of driver names. + * + * + * The caller must provide a num_drivers + * This structure is allocated from libva with calloc(). + * + * @param drivers An num_drivers sized array of null terminated strings. + * The array is managed my the caller. The callee will + * populate the individual driver name strings and the + * caller must free them. + * @param num_driver The number of driver strings contained within drivers. + * The caller must set that to the size of the drivers + * array, where the callee will update the value to + * min(caller num_driver, num_drivers_support). + */ + VAStatus(*vaGetDriverNames)( + VADisplayContextP ctx, + char **drivers, + unsigned *num_drivers + ); + /** \brief Reserved bytes for future use, must be zero */ - unsigned long reserved[30]; + unsigned long reserved[29]; }; typedef VAStatus(*VADriverInit)( diff --git a/va/va_dec_jpeg.h b/va/va_dec_jpeg.h index 7bb26c2b..2cd6b42c 100644 --- a/va/va_dec_jpeg.h +++ b/va/va_dec_jpeg.h @@ -75,8 +75,10 @@ typedef struct _VAPictureParameterBufferJPEGBaseline { uint8_t color_space; /** \brief Set to VA_ROTATION_* for a single rotation angle reported by VAConfigAttribDecJPEG. */ uint32_t rotation; + /** \brief crop rectangle boundary in pixels */ + VARectangle crop_rectangle; /** \brief Reserved bytes for future use, must be zero */ - uint32_t va_reserved[VA_PADDING_MEDIUM - 1]; + uint32_t va_reserved[VA_PADDING_MEDIUM - 3]; } VAPictureParameterBufferJPEGBaseline; /** diff --git a/va/va_enc_av1.h b/va/va_enc_av1.h index e5520c9a..e47836b6 100644 --- a/va/va_enc_av1.h +++ b/va/va_enc_av1.h @@ -912,7 +912,8 @@ typedef struct _VAEncPictureParameterBufferAV1 { * underline encoder. Otherwise, app can set it to 0 and ignored by driver. * * In BRC mode, obu_size needs to be updated and this parameter should be set. - * In CQP mode, this parameter should be set to 0 and ignored by driver. + * In CQP mode, obu_size needs to be updated if \c enable_frame_obu == 1. Otherwise + * this parameter should be set to 0 and ignored by driver. */ uint32_t byte_offset_frame_hdr_obu_size; diff --git a/va/va_trace.c b/va/va_trace.c index 61b561ee..7d281db1 100644 --- a/va/va_trace.c +++ b/va/va_trace.c @@ -1096,6 +1096,11 @@ void va_TraceInitialize( { DPY2TRACE_VIRCTX(dpy); TRACE_FUNCNAME(idx); + + const char* vendor_string = vaQueryVendorString(dpy); + if (vendor_string) + va_TraceMsg(trace_ctx, "==========\tVA-API vendor string: %s\n", vendor_string); + DPY2TRACE_VIRCTX_EXIT(pva_trace); } @@ -1235,13 +1240,13 @@ static void va_TraceSurfaceAttributes( va_TraceMsg(trace_ctx, "\t\t width=%d\n", tmp->width); va_TraceMsg(trace_ctx, "\t\t height=%d\n", tmp->height); va_TraceMsg(trace_ctx, "\t\t num_objects=0x%08x\n", tmp->num_objects); - for (j = 0; j < tmp->num_objects; j++) { + for (j = 0; j < tmp->num_objects && tmp->num_objects <= 4; j++) { va_TraceMsg(trace_ctx, "\t\t\tobjects[%d].fd=%d\n", j, tmp->objects[j].fd); va_TraceMsg(trace_ctx, "\t\t\tobjects[%d].size=%d\n", j, tmp->objects[j].size); - va_TraceMsg(trace_ctx, "\t\t\tobjects[%d].drm_format_modifier=%d\n", j, tmp->objects[j].drm_format_modifier); + va_TraceMsg(trace_ctx, "\t\t\tobjects[%d].drm_format_modifier=%llx\n", j, tmp->objects[j].drm_format_modifier); } va_TraceMsg(trace_ctx, "\t\t num_layers=%d\n", tmp->num_layers); - for (j = 0; j < tmp->num_layers; j++) { + for (j = 0; j < tmp->num_layers && tmp->num_layers <= 4; j++) { va_TraceMsg(trace_ctx, "\t\t\tlayers[%d].drm_format=0x%08x\n", j, tmp->layers[j].drm_format); va_TraceMsg(trace_ctx, "\t\t\tlayers[%d].num_planes=0x%d\n", j, tmp->layers[j].num_planes); for (k = 0; k < 4; k++) { @@ -5975,7 +5980,7 @@ void va_TraceSyncSurface2( TRACE_FUNCNAME(idx); va_TraceMsg(trace_ctx, "\tsurface = 0x%08x\n", surface); - va_TraceMsg(trace_ctx, "\ttimeout_ns = %d\n", timeout_ns); + va_TraceMsg(trace_ctx, "\ttimeout_ns = %lld\n", timeout_ns); va_TraceMsg(trace_ctx, NULL); DPY2TRACE_VIRCTX_EXIT(pva_trace); @@ -6056,7 +6061,7 @@ void va_TraceSyncBuffer( TRACE_FUNCNAME(idx); va_TraceMsg(trace_ctx, "\tbuf_id = 0x%08x\n", buf_id); - va_TraceMsg(trace_ctx, "\ttimeout_ns = %d\n", timeout_ns); + va_TraceMsg(trace_ctx, "\ttimeout_ns = %lld\n", timeout_ns); va_TraceMsg(trace_ctx, NULL); DPY2TRACE_VIRCTX_EXIT(pva_trace); @@ -6236,7 +6241,7 @@ void va_TraceEvent( write_size = VA_TRACE_HEADER_SIZE; for (i = 0; i < num; i++) { if (write_size + desc[i].size > VA_TRACE_MAX_SIZE) { - va_errorMessage(pva_trace->dpy, "error: trace event %d carry too big data. max size \n", id, VA_TRACE_MAX_SIZE); + va_errorMessage(pva_trace->dpy, "error: trace event %d carry too big data. max size %d \n", id, VA_TRACE_MAX_SIZE); break; } if (desc[i].buf) { @@ -6311,3 +6316,55 @@ void va_TraceEventBuffers( } return; } + +void va_TraceExportSurfaceHandle( + VADisplay dpy, + VASurfaceID surfaceId, + uint32_t memType, + uint32_t flags, + void *descriptor) +{ + int i; + + DPY2TRACE_VIRCTX(dpy); + + TRACE_FUNCNAME(idx); + + va_TraceMsg(trace_ctx, "\tsurfaceId = 0x%08x\n", surfaceId); + va_TraceMsg(trace_ctx, "\tmemType = 0x%08x\n", memType); + va_TraceMsg(trace_ctx, "\tflags = 0x%08x\n", flags); + + if (memType != VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME_2) { + DPY2TRACE_VIRCTX_EXIT(pva_trace); + return; + } + + VADRMPRIMESurfaceDescriptor *desc = (VADRMPRIMESurfaceDescriptor *)descriptor; + + if (!desc) { + DPY2TRACE_VIRCTX_EXIT(pva_trace); + return; + } + + va_TraceMsg(trace_ctx, "\tfourcc = %u\n", desc->fourcc); + va_TraceMsg(trace_ctx, "\twidth = %u\n", desc->width); + va_TraceMsg(trace_ctx, "\theight = %u\n", desc->height); + + va_TraceMsg(trace_ctx, "\tnum_objects = %u\n", desc->num_objects); + for (i = 0; i < desc->num_objects; i++) { + va_TraceMsg(trace_ctx, "\tobject %d, fd = %d\n", i, desc->objects[i].fd); + va_TraceMsg(trace_ctx, "\tobject %d, size = %u\n", i, desc->objects[i].size); + va_TraceMsg(trace_ctx, "\tobject %d, modifier = 0x%llx\n", i, desc->objects[i].drm_format_modifier); + } + + va_TraceMsg(trace_ctx, "\tnum_objects = %u\n", desc->num_layers); + for (i = 0; i < desc->num_layers; i++) { + va_TraceMsg(trace_ctx, "\tlayer %d, drm_format = %d\n", i, desc->layers[i].drm_format); + va_TraceMsg(trace_ctx, "\tlayer %d, size = %u\n", i, desc->layers[i].num_planes); + va_TraceMsg(trace_ctx, "\tlayer %d, object idx = [%d, %d, %d, %d]\n", i, desc->layers[i].object_index[0], desc->layers[i].object_index[1], desc->layers[i].object_index[2], desc->layers[i].object_index[3]); + va_TraceMsg(trace_ctx, "\tlayer %d, offset = [%d, %d, %d, %d]\n", i, desc->layers[i].offset[0], desc->layers[i].offset[1], desc->layers[i].offset[2], desc->layers[i].offset[3]); + va_TraceMsg(trace_ctx, "\tlayer %d, pitch = [%d, %d, %d, %d]\n", i, desc->layers[i].pitch[0], desc->layers[i].pitch[1], desc->layers[i].pitch[2], desc->layers[i].pitch[3]); + } + + DPY2TRACE_VIRCTX_EXIT(pva_trace); +} diff --git a/va/va_trace.h b/va/va_trace.h index 08bb49ab..aeb1884a 100644 --- a/va/va_trace.h +++ b/va/va_trace.h @@ -496,6 +496,16 @@ void va_TraceEventBuffers( int num_buffers, VABufferID *buffers); +/** \brief va_TraceExportSurfaceHandle + * trace exported surface handle. */ +DLL_HIDDEN +void va_TraceExportSurfaceHandle( + VADisplay dpy, + VASurfaceID surfaceId, + uint32_t memType, + uint32_t flags, + void *descriptor); + #ifdef __cplusplus } #endif diff --git a/va/va_version.h b/va/va_version.h index 61c53e4f..bce6534f 100644 --- a/va/va_version.h +++ b/va/va_version.h @@ -37,7 +37,7 @@ * * The minor version of VA-API (2, if %VA_VERSION is 1.2.3) */ -#define VA_MINOR_VERSION 19 +#define VA_MINOR_VERSION 20 /** * VA_MICRO_VERSION: @@ -51,7 +51,7 @@ * * The full version of VA-API, like 1.2.3 */ -#define VA_VERSION 2.19.0 +#define VA_VERSION 2.20.0 /** * VA_VERSION_S: @@ -59,7 +59,7 @@ * The full version of VA-API, in string form (suited for string * concatenation) */ -#define VA_VERSION_S "2.19.0" +#define VA_VERSION_S "2.20.0" /** * VA_VERSION_HEX: diff --git a/va/wayland/va_wayland.c b/va/wayland/va_wayland.c index 69e88ab9..b3e1f5c8 100644 --- a/va/wayland/va_wayland.c +++ b/va/wayland/va_wayland.c @@ -80,13 +80,6 @@ va_DisplayContextDestroy(VADisplayContextP pDisplayContext) free(pDisplayContext); } -static VAStatus -va_DisplayContextGetDriverName(VADisplayContextP pDisplayContext, char **name) -{ - *name = NULL; - return VA_STATUS_ERROR_UNKNOWN; -} - /* -------------------------------------------------------------------------- */ /* --- Public interface --- */ /* -------------------------------------------------------------------------- */ @@ -123,7 +116,6 @@ vaGetDisplayWl(struct wl_display *display) return NULL; pDisplayContext->vaDestroy = va_DisplayContextDestroy; - pDisplayContext->vaGetDriverName = va_DisplayContextGetDriverName; pDriverContext = va_newDriverContext(pDisplayContext); if (!pDriverContext) diff --git a/va/wayland/va_wayland_drm.c b/va/wayland/va_wayland_drm.c index aca06e6b..e588c82f 100644 --- a/va/wayland/va_wayland_drm.c +++ b/va/wayland/va_wayland_drm.c @@ -2,6 +2,7 @@ * va_wayland_drm.c - Wayland/DRM helpers * * Copyright (c) 2012 Intel Corporation. All Rights Reserved. + * Copyright (c) 2023 Emil Velikov * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the @@ -124,37 +125,15 @@ static const struct wl_drm_listener drm_listener = { }; static VAStatus -va_DisplayContextGetNumCandidates( +va_DisplayContextGetDriverNames( VADisplayContextP pDisplayContext, - int *candidate_index + char **drivers, + unsigned *num_drivers ) { VADriverContextP const ctx = pDisplayContext->pDriverContext; - return VA_DRM_GetNumCandidates(ctx, candidate_index); -} - -static VAStatus -va_DisplayContextGetDriverNameByIndex( - VADisplayContextP pDisplayContext, - char **driver_name_ptr, - int candidate_index -) -{ - VADriverContextP const ctx = pDisplayContext->pDriverContext; - - return VA_DRM_GetDriverName(ctx, driver_name_ptr, candidate_index); -} - -static VAStatus -va_DisplayContextGetDriverName( - VADisplayContextP pDisplayContext, - char **driver_name_ptr -) -{ - VADriverContextP const ctx = pDisplayContext->pDriverContext; - - return VA_DRM_GetDriverName(ctx, driver_name_ptr, 0); + return VA_DRM_GetDriverNames(ctx, drivers, num_drivers); } void @@ -266,9 +245,7 @@ va_wayland_drm_create(VADisplayContextP pDisplayContext) wl_drm_ctx->registry = NULL; wl_drm_ctx->is_authenticated = 0; pDisplayContext->opaque = wl_drm_ctx; - pDisplayContext->vaGetDriverName = va_DisplayContextGetDriverName; - pDisplayContext->vaGetNumCandidates = va_DisplayContextGetNumCandidates; - pDisplayContext->vaGetDriverNameByIndex = va_DisplayContextGetDriverNameByIndex; + pDisplayContext->vaGetDriverNames = va_DisplayContextGetDriverNames; drm_state = calloc(1, sizeof(struct drm_state)); if (!drm_state) { diff --git a/va/wayland/va_wayland_emgd.c b/va/wayland/va_wayland_emgd.c index d88151c9..83aff054 100644 --- a/va/wayland/va_wayland_emgd.c +++ b/va/wayland/va_wayland_emgd.c @@ -2,6 +2,7 @@ * va_wayland_emgd.c - Wayland/EMGD helpers * * Copyright (c) 2012 Intel Corporation. All Rights Reserved. + * Copyright (c) 2023 Emil Velikov * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the @@ -53,12 +54,14 @@ wl_emgd_destroy(struct wl_emgd *emgd) } static VAStatus -va_DisplayContextGetDriverName( +va_DisplayContextGetDriverNames( VADisplayContextP pDisplayContext, - char **driver_name_ptr + char **drivers, + unsigned *num_drivers ) { - *driver_name_ptr = strdup("emgd"); + drivers[0] = strdup("emgd"); + *num_drivers = 1; return VA_STATUS_SUCCESS; } @@ -128,7 +131,7 @@ va_wayland_emgd_create(VADisplayContextP pDisplayContext) wl_emgd_ctx->emgd_interface = NULL; wl_emgd_ctx->is_created = 0; pDisplayContext->opaque = wl_emgd_ctx; - pDisplayContext->vaGetDriverName = va_DisplayContextGetDriverName; + pDisplayContext->vaGetDriverNames = va_DisplayContextGetDriverNames; drm_state = calloc(1, sizeof(struct drm_state)); if (!drm_state) diff --git a/va/win32/va_win32.c b/va/win32/va_win32.c index a64d55c2..7a6a895d 100644 --- a/va/win32/va_win32.c +++ b/va/win32/va_win32.c @@ -1,5 +1,6 @@ /* * Copyright © Microsoft Corporation + * Copyright (c) 2023 Emil Velikov * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -37,18 +38,17 @@ const char VAAPI_DEFAULT_DRIVER_NAME[] = "vaon12"; typedef struct _VADisplayContextWin32 { - LUID adapter_luid; char registry_driver_name[MAX_PATH]; bool registry_driver_available_flag; } VADisplayContextWin32; -static void LoadDriverNameFromRegistry(VADisplayContextWin32* pWin32Ctx) +static void LoadDriverNameFromRegistry(const LUID* adapter_luid, VADisplayContextWin32* pWin32Ctx) { HMODULE hGdi32 = LoadLibraryA("gdi32.dll"); if (!hGdi32) return; - D3DKMT_OPENADAPTERFROMLUID OpenArgs = { .AdapterLuid = pWin32Ctx->adapter_luid }; + D3DKMT_OPENADAPTERFROMLUID OpenArgs = { .AdapterLuid = *adapter_luid }; D3DDDI_QUERYREGISTRY_INFO RegistryInfo = { .QueryType = D3DDDI_QUERYREGISTRY_ADAPTERKEY, .QueryFlags.TranslatePath = true, @@ -131,47 +131,28 @@ static void va_DisplayContextDestroy( free(pDisplayContext); } -static VAStatus va_DisplayContextGetNumCandidates( +static VAStatus va_DisplayContextGetDriverNames( VADisplayContextP pDisplayContext, - int *num_candidates + char **drivers, + unsigned *num_drivers ) { - /* Always report the default driver name - If available, also add the adapter specific registered driver */ - LUID* adapter = pDisplayContext->pDriverContext->native_dpy; - VADisplayContextWin32* pWin32Ctx = (VADisplayContextWin32*) pDisplayContext->opaque; - if (adapter && pWin32Ctx->registry_driver_available_flag) - *num_candidates = 2; - else - *num_candidates = 1; - - return VA_STATUS_SUCCESS; -} + const LUID * const adapter = pDisplayContext->pDriverContext->native_dpy; + const VADisplayContextWin32 * const pWin32Ctx = pDisplayContext->opaque; + unsigned count = 0; -static VAStatus va_DisplayContextGetDriverNameByIndex( - VADisplayContextP pDisplayContext, - char **driver_name, - int candidate_index -) -{ - LUID* adapter = pDisplayContext->pDriverContext->native_dpy; - VADisplayContextWin32* pWin32Ctx = (VADisplayContextWin32*) pDisplayContext->opaque; + /* Always prefer the adapter registered driver name as first option */ if (adapter && pWin32Ctx->registry_driver_available_flag) { - /* Always prefer the adapter registered driver name as first option */ - if (candidate_index == 0) { - *driver_name = calloc(sizeof(pWin32Ctx->registry_driver_name), sizeof(char)); - memcpy(*driver_name, pWin32Ctx->registry_driver_name, sizeof(pWin32Ctx->registry_driver_name)); - } - /* Provide the default driver name as a fallback option */ - else if (candidate_index == 1) { - *driver_name = calloc(sizeof(VAAPI_DEFAULT_DRIVER_NAME), sizeof(char)); - memcpy(*driver_name, VAAPI_DEFAULT_DRIVER_NAME, sizeof(VAAPI_DEFAULT_DRIVER_NAME)); - } - } else { - /* Provide the default driver name as a fallback option */ - *driver_name = calloc(sizeof(VAAPI_DEFAULT_DRIVER_NAME), sizeof(char)); - memcpy(*driver_name, VAAPI_DEFAULT_DRIVER_NAME, sizeof(VAAPI_DEFAULT_DRIVER_NAME)); + drivers[count] = _strdup(pWin32Ctx->registry_driver_name); + count++; } + /* Provide the default driver name as a fallback option */ + if (*num_drivers > count) { + drivers[count] = _strdup(VAAPI_DEFAULT_DRIVER_NAME); + count++; + } + + *num_drivers = count; return VA_STATUS_SUCCESS; } @@ -189,8 +170,7 @@ VADisplay vaGetDisplayWin32( return NULL; pDisplayContext->vaDestroy = va_DisplayContextDestroy; - pDisplayContext->vaGetDriverNameByIndex = va_DisplayContextGetDriverNameByIndex; - pDisplayContext->vaGetNumCandidates = va_DisplayContextGetNumCandidates; + pDisplayContext->vaGetDriverNames = va_DisplayContextGetDriverNames; pDisplayContext->opaque = calloc(1, sizeof(VADisplayContextWin32)); if (!pDisplayContext->opaque) { va_DisplayContextDestroy(pDisplayContext); @@ -199,16 +179,15 @@ VADisplay vaGetDisplayWin32( VADisplayContextWin32* pWin32Ctx = (VADisplayContextWin32*) pDisplayContext->opaque; if (adapter_luid) { - /* Copy LUID information to display context */ - memcpy(&pWin32Ctx->adapter_luid, adapter_luid, sizeof(pWin32Ctx->adapter_luid)); - /* Load the preferred driver name from the driver registry if available */ - LoadDriverNameFromRegistry(pWin32Ctx); + LoadDriverNameFromRegistry(adapter_luid, pWin32Ctx); +#ifdef _DEBUG if (pWin32Ctx->registry_driver_available_flag) { - fprintf(stderr, "VA_Win32: Found driver %s in the registry for LUID %ld %ld \n", pWin32Ctx->registry_driver_name, pWin32Ctx->adapter_luid.LowPart, pWin32Ctx->adapter_luid.HighPart); + fprintf(stderr, "VA_Win32: Found driver %s in the registry for LUID %ld %ld \n", pWin32Ctx->registry_driver_name, adapter_luid.LowPart, adapter_luid.HighPart); } else { - fprintf(stderr, "VA_Win32: Couldn't find a driver in the registry for LUID %ld %ld. Using default driver: %s \n", pWin32Ctx->adapter_luid.LowPart, pWin32Ctx->adapter_luid.HighPart, VAAPI_DEFAULT_DRIVER_NAME); + fprintf(stderr, "VA_Win32: Couldn't find a driver in the registry for LUID %ld %ld. Using default driver: %s \n", adapter_luid.LowPart, adapter_luid.HighPart, VAAPI_DEFAULT_DRIVER_NAME); } +#endif // _DEBUG } pDriverContext = va_newDriverContext(pDisplayContext); diff --git a/va/x11/Makefile.am b/va/x11/Makefile.am index 8fae2f39..ff30be95 100644 --- a/va/x11/Makefile.am +++ b/va/x11/Makefile.am @@ -44,6 +44,7 @@ source_h = \ $(NULL) source_h_priv = \ + va_dri2_priv.h \ va_dri2str.h \ va_dri2tokens.h \ va_dri3.h \ diff --git a/va/x11/va_dri2.c b/va/x11/va_dri2.c index db4d7a19..da2a9f40 100644 --- a/va/x11/va_dri2.c +++ b/va/x11/va_dri2.c @@ -1,5 +1,6 @@ /* * Copyright © 2008 Red Hat, Inc. + * Copyright (c) 2023 Emil Velikov * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Soft- @@ -37,9 +38,13 @@ #include #include "xf86drm.h" #include "va_dri2.h" +#include "va_dri2_priv.h" +#include "va_dricommon.h" #include "va_dri2str.h" #include "va_dri2tokens.h" +#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) + #ifndef DRI2DriverDRI #define DRI2DriverDRI 0 #endif @@ -422,3 +427,51 @@ void VA_DRI2SwapBuffers(Display *dpy, XID drawable, CARD64 target_msc, UnlockDisplay(dpy); SyncHandle(); } + +VAStatus va_DRI2_GetDriverNames( + VADisplayContextP pDisplayContext, + char **drivers, + unsigned *num_drivers +) +{ +#define MAX_NAMES 2 // Adjust if needed + + static const struct { + const char * const dri_driver; + const char * const va_driver[MAX_NAMES]; + } map[] = { + { "i965", { "iHD", "i965" } }, // Intel Media and OTC GenX + { "iris", { "iHD", "i965" } }, // Intel Media and OTC GenX + { "crocus", { "i965" } }, // OTC GenX + }; + + VADriverContextP ctx = pDisplayContext->pDriverContext; + char *dri_driver; + unsigned count = 0; + + if (!(va_isDRI2Connected(ctx, &dri_driver) && dri_driver)) + return VA_STATUS_ERROR_UNKNOWN; + + for (unsigned i = 0; i < ARRAY_SIZE(map); i++) { + if (strcmp(map[i].dri_driver, dri_driver) == 0) { + const char * const *va_drivers = map[i].va_driver; + + for (; count < MAX_NAMES && va_drivers[count] && count < *num_drivers; count++) + drivers[count] = strdup(va_drivers[count]); + + break; + } + } + + /* Fallback to the dri driver, if there's no va equivalent in the map. */ + if (!count) { + drivers[count] = dri_driver; + count++; + } else { + free(dri_driver); + } + + *num_drivers = count; + + return VA_STATUS_SUCCESS; +} diff --git a/va/x11/va_dri2_priv.h b/va/x11/va_dri2_priv.h new file mode 100644 index 00000000..3fdc8df5 --- /dev/null +++ b/va/x11/va_dri2_priv.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2023 Emil Velikov + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Soft- + * ware"), to deal in the Software without restriction, including without + * limitation the rights to use, copy, modify, merge, publish, distribute, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, provided that the above copyright + * notice(s) and this permission notice appear in all copies of the Soft- + * ware and that both the above copyright notice(s) and this permission + * notice appear in supporting documentation. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- + * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY + * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN + * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE- + * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR- + * MANCE OF THIS SOFTWARE. + * + * Except as contained in this notice, the name of a copyright holder shall + * not be used in advertising or otherwise to promote the sale, use or + * other dealings in this Software without prior written authorization of + * the copyright holder. + */ + +#ifndef _VA_DRI2_PRIV_H_ +#define _VA_DRI2_PRIV_H_ + +#include "sysdeps.h" +#include "va_backend.h" + +DLL_HIDDEN +VAStatus va_DRI2_GetDriverNames( + VADisplayContextP pDisplayContext, + char **drivers, + unsigned *num_drivers +); + +#endif diff --git a/va/x11/va_dri3.c b/va/x11/va_dri3.c index b3ab7d5b..627563d0 100644 --- a/va/x11/va_dri3.c +++ b/va/x11/va_dri3.c @@ -1,5 +1,6 @@ /* * Copyright © 2022 Collabora Ltd. + * Copyright (c) 2023 Emil Velikov * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Soft- @@ -127,13 +128,14 @@ va_isDRI3Connected(VADriverContextP ctx, int *outfd) return 0; } -VAStatus va_DRI3_GetNumCandidates( +VAStatus va_DRI3_GetDriverNames( VADisplayContextP pDisplayContext, - int *num_candidates + char **drivers, + unsigned *num_drivers ) { VADriverContextP const ctx = pDisplayContext->pDriverContext; - struct drm_state * drm_state = (struct drm_state *)ctx->drm_state; + struct drm_state * const drm_state = ctx->drm_state; int fd = -1; if (va_isDRI3Connected(ctx, &fd) && fd != -1) @@ -141,16 +143,5 @@ VAStatus va_DRI3_GetNumCandidates( drm_state->fd = fd; drm_state->auth_type = VA_DRM_AUTH_CUSTOM; - return VA_DRM_GetNumCandidates(ctx, num_candidates); -} - -VAStatus va_DRI3_GetDriverName( - VADisplayContextP pDisplayContext, - char **driver_name, - int candidate_index -) -{ - VADriverContextP const ctx = pDisplayContext->pDriverContext; - - return VA_DRM_GetDriverName(ctx, driver_name, candidate_index); + return VA_DRM_GetDriverNames(ctx, drivers, num_drivers); } diff --git a/va/x11/va_dri3.h b/va/x11/va_dri3.h index 781a1d01..e032c273 100644 --- a/va/x11/va_dri3.h +++ b/va/x11/va_dri3.h @@ -37,16 +37,10 @@ #include "va_backend.h" DLL_HIDDEN -VAStatus va_DRI3_GetNumCandidates( +VAStatus va_DRI3_GetDriverNames( VADisplayContextP pDisplayContext, - int *num_candidates -); - -DLL_HIDDEN -VAStatus va_DRI3_GetDriverName( - VADisplayContextP pDisplayContext, - char **driver_name_ptr, - int candidate_index + char **drivers, + unsigned *num_drivers ); #endif diff --git a/va/x11/va_fglrx.c b/va/x11/va_fglrx.c index e2ef977c..b85603d3 100644 --- a/va/x11/va_fglrx.c +++ b/va/x11/va_fglrx.c @@ -125,9 +125,7 @@ static int match_display_name(Display *x11_dpy, const char *display_name) return m; } -static Bool VA_FGLRXGetClientDriverName(Display *dpy, int screen, - int *ddxDriverMajorVersion, int *ddxDriverMinorVersion, - int *ddxDriverPatchVersion, char **clientDriverName) +static Bool VA_FGLRXGetClientDriverName(Display *dpy, int screen, char **clientDriverName) { ADL_MAIN_CONTROL_CREATE ADL_Main_Control_Create; ADL_MAIN_CONTROL_DESTROY ADL_Main_Control_Destroy; @@ -142,15 +140,6 @@ static Bool VA_FGLRXGetClientDriverName(Display *dpy, int screen, int is_adl_initialized = 0; int i, num_adapters, lpAdapterInfo_size, lpXScreenInfo_size; - if (ddxDriverMajorVersion) - *ddxDriverMajorVersion = 0; - if (ddxDriverMinorVersion) - *ddxDriverMinorVersion = 0; - if (ddxDriverPatchVersion) - *ddxDriverPatchVersion = 0; - if (clientDriverName) - *clientDriverName = NULL; - libadl_handle = dlopen("libatiadlxx.so", RTLD_LAZY | RTLD_GLOBAL); if (!libadl_handle) goto end; @@ -231,9 +220,8 @@ static Bool VA_FGLRXGetClientDriverName(Display *dpy, int screen, #endif if (screen == lpCurrXScreenInfo->iXScreenNum && match_display_name(dpy, lpCurrAdapterInfo->strDisplayName)) { - if (clientDriverName) - *clientDriverName = strdup("fglrx"); - success = True; + *clientDriverName = strdup("fglrx"); + success = !!(*clientDriverName); break; } } @@ -250,25 +238,18 @@ static Bool VA_FGLRXGetClientDriverName(Display *dpy, int screen, return success; } -VAStatus va_FGLRX_GetDriverName( +VAStatus va_FGLRX_GetDriverNames( VADisplayContextP pDisplayContext, - char **driver_name, - int candidate_index + char **drivers, + unsigned *num_drivers ) { VADriverContextP ctx = pDisplayContext->pDriverContext; - int driver_major, driver_minor, driver_patch; - Bool result; - - if (candidate_index != 0) - return VA_STATUS_ERROR_INVALID_PARAMETER; - - result = VA_FGLRXGetClientDriverName(ctx->native_dpy, ctx->x11_screen, - &driver_major, &driver_minor, - &driver_patch, driver_name); - if (!result) + if (!VA_FGLRXGetClientDriverName(ctx->native_dpy, ctx->x11_screen, + drivers)) return VA_STATUS_ERROR_UNKNOWN; + *num_drivers = 1; return VA_STATUS_SUCCESS; } diff --git a/va/x11/va_fglrx.h b/va/x11/va_fglrx.h index 8544aec1..bbda2744 100644 --- a/va/x11/va_fglrx.h +++ b/va/x11/va_fglrx.h @@ -31,10 +31,10 @@ #include "va_backend.h" DLL_HIDDEN -VAStatus va_FGLRX_GetDriverName( +VAStatus va_FGLRX_GetDriverNames( VADisplayContextP pDisplayContext, - char **driver_name, - int candidate_index + char **drivers, + unsigned *num_drivers ); #endif diff --git a/va/x11/va_nvctrl.c b/va/x11/va_nvctrl.c index ade9bb21..18c56412 100644 --- a/va/x11/va_nvctrl.c +++ b/va/x11/va_nvctrl.c @@ -362,17 +362,9 @@ static Bool VA_NVCTRLQueryDirectRenderingCapable(Display *dpy, int screen, } static Bool VA_NVCTRLGetClientDriverName(Display *dpy, int screen, - int *ddxDriverMajorVersion, int *ddxDriverMinorVersion, - int *ddxDriverPatchVersion, char **clientDriverName) + char **clientDriverName) { - if (ddxDriverMajorVersion) - *ddxDriverMajorVersion = 0; - if (ddxDriverMinorVersion) - *ddxDriverMinorVersion = 0; - if (ddxDriverPatchVersion) - *ddxDriverPatchVersion = 0; - if (clientDriverName) - *clientDriverName = NULL; + int ddxDriverMajorVersion, ddxDriverMinorVersion, ddxDriverPatchVersion; char *nvidia_driver_version = NULL; if (!XNVCTRLQueryStringAttribute(dpy, screen, 0, NV_CTRL_STRING_NVIDIA_DRIVER_VERSION, &nvidia_driver_version)) @@ -381,55 +373,48 @@ static Bool VA_NVCTRLGetClientDriverName(Display *dpy, int screen, char *end, *str = nvidia_driver_version; unsigned long v = strtoul(str, &end, 10); if (end && end != str) { - if (ddxDriverMajorVersion) - *ddxDriverMajorVersion = v; + ddxDriverMajorVersion = v; if (*(str = end) == '.') { v = strtoul(str + 1, &end, 10); if (end && end != str && (*end == '.' || *end == '\0')) { - if (ddxDriverMinorVersion) - *ddxDriverMinorVersion = v; + ddxDriverMinorVersion = v; if (*(str = end) == '.') { v = strtoul(str + 1, &end, 10); if (end && end != str && *end == '\0') { - if (ddxDriverPatchVersion) - *ddxDriverPatchVersion = v; + ddxDriverPatchVersion = v; } } } } } Xfree(nvidia_driver_version); + (void) ddxDriverMajorVersion; + (void) ddxDriverMinorVersion; + (void) ddxDriverPatchVersion; - if (clientDriverName) - *clientDriverName = strdup("nvidia"); + *clientDriverName = strdup("nvidia"); return True; } -VAStatus va_NVCTRL_GetDriverName( +VAStatus va_NVCTRL_GetDriverNames( VADisplayContextP pDisplayContext, - char **driver_name, - int candidate_index + char **drivers, + unsigned *num_drivers ) { VADriverContextP ctx = pDisplayContext->pDriverContext; - int direct_capable, driver_major, driver_minor, driver_patch; - Bool result; + int direct_capable; - if (candidate_index != 0) - return VA_STATUS_ERROR_INVALID_PARAMETER; - - result = VA_NVCTRLQueryDirectRenderingCapable(ctx->native_dpy, ctx->x11_screen, - &direct_capable); - if (!result || !direct_capable) + if (!VA_NVCTRLQueryDirectRenderingCapable(ctx->native_dpy, ctx->x11_screen, + &direct_capable) || !direct_capable) return VA_STATUS_ERROR_UNKNOWN; - result = VA_NVCTRLGetClientDriverName(ctx->native_dpy, ctx->x11_screen, - &driver_major, &driver_minor, - &driver_patch, driver_name); - if (!result) + if (!VA_NVCTRLGetClientDriverName(ctx->native_dpy, ctx->x11_screen, + drivers)) return VA_STATUS_ERROR_UNKNOWN; + *num_drivers = 1; return VA_STATUS_SUCCESS; } diff --git a/va/x11/va_nvctrl.h b/va/x11/va_nvctrl.h index 20af25d5..6fa189b4 100644 --- a/va/x11/va_nvctrl.h +++ b/va/x11/va_nvctrl.h @@ -30,10 +30,10 @@ #include "va_backend.h" DLL_HIDDEN -VAStatus va_NVCTRL_GetDriverName( +VAStatus va_NVCTRL_GetDriverNames( VADisplayContextP pDisplayContext, - char **driver_name, - int candidate_index + char **drivers, + unsigned *num_drivers ); #endif diff --git a/va/x11/va_x11.c b/va/x11/va_x11.c index 3c5316da..242e6e7c 100644 --- a/va/x11/va_x11.c +++ b/va/x11/va_x11.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2007 Intel Corporation. All Rights Reserved. + * Copyright (c) 2023 Emil Velikov * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the @@ -30,6 +31,7 @@ #include "va_trace.h" #include "va_x11.h" #include "va_dri2.h" +#include "va_dri2_priv.h" #include "va_dri3.h" #include "va_dricommon.h" #include "va_nvctrl.h" @@ -44,20 +46,6 @@ #include #include -struct driver_name_map { - const char *key; - const char *name; -}; - -static const struct driver_name_map g_dri2_driver_name_map[] = { - { "i965", "iHD" }, // Intel iHD VAAPI driver with i965 DRI driver - { "i965", "i965" }, // Intel i965 VAAPI driver with i965 DRI driver - { "iris", "iHD" }, // Intel iHD VAAPI driver with iris DRI driver - { "iris", "i965" }, // Intel i965 VAAPI driver with iris DRI driver - { "crocus", "i965" }, // Intel i965 VAAPI driver with crocus DRI driver - { NULL, NULL } -}; - static void va_DisplayContextDestroy( VADisplayContextP pDisplayContext ) @@ -82,128 +70,29 @@ static void va_DisplayContextDestroy( free(pDisplayContext); } -static VAStatus va_DRI2_GetNumCandidates( - VADisplayContextP pDisplayContext, - int *num_candidates -) -{ - char *driver_name = NULL; - const struct driver_name_map *m = NULL; - VADriverContextP ctx = pDisplayContext->pDriverContext; - - *num_candidates = 0; - - if (!(va_isDRI2Connected(ctx, &driver_name) && driver_name)) - return VA_STATUS_ERROR_UNKNOWN; - - for (m = g_dri2_driver_name_map; m->key != NULL; m++) { - if (strcmp(m->key, driver_name) == 0) { - (*num_candidates)++; - } - } - - free(driver_name); - - /* - * If the dri2 driver name does not have a mapped vaapi driver name, then - * assume they have the same name. - */ - if (*num_candidates == 0) - *num_candidates = 1; - - return VA_STATUS_SUCCESS; -} - -static VAStatus va_DRI2_GetDriverName( +static VAStatus va_DisplayContextGetDriverNames( VADisplayContextP pDisplayContext, - char **driver_name_ptr, - int candidate_index -) -{ - const struct driver_name_map *m = NULL; - int current_index = 0; - VADriverContextP ctx = pDisplayContext->pDriverContext; - - *driver_name_ptr = NULL; - - if (!(va_isDRI2Connected(ctx, driver_name_ptr) && *driver_name_ptr)) - return VA_STATUS_ERROR_UNKNOWN; - - for (m = g_dri2_driver_name_map; m->key != NULL; m++) { - if (strcmp(m->key, *driver_name_ptr) == 0) { - if (current_index == candidate_index) { - break; - } - current_index++; - } - } - - /* - * If the dri2 driver name does not have a mapped vaapi driver name, then - * assume they have the same name. - */ - if (!m->name) - return VA_STATUS_SUCCESS; - - /* Use the mapped vaapi driver name */ - free(*driver_name_ptr); - *driver_name_ptr = strdup(m->name); - if (!*driver_name_ptr) - return VA_STATUS_ERROR_ALLOCATION_FAILED; - - return VA_STATUS_SUCCESS; -} - -static VAStatus va_DisplayContextGetDriverName( - VADisplayContextP pDisplayContext, - char **driver_name, int candidate_index + char **drivers, unsigned *num_drivers ) { VAStatus vaStatus = VA_STATUS_ERROR_UNKNOWN; - if (driver_name) - *driver_name = NULL; - else - return VA_STATUS_ERROR_UNKNOWN; - if (!getenv("LIBVA_DRI3_DISABLE")) - vaStatus = va_DRI3_GetDriverName(pDisplayContext, driver_name, candidate_index); + vaStatus = va_DRI3_GetDriverNames(pDisplayContext, drivers, num_drivers); if (vaStatus != VA_STATUS_SUCCESS) - vaStatus = va_DRI2_GetDriverName(pDisplayContext, driver_name, candidate_index); + vaStatus = va_DRI2_GetDriverNames(pDisplayContext, drivers, num_drivers); #ifdef HAVE_NVCTRL if (vaStatus != VA_STATUS_SUCCESS) - vaStatus = va_NVCTRL_GetDriverName(pDisplayContext, driver_name, candidate_index); + vaStatus = va_NVCTRL_GetDriverNames(pDisplayContext, drivers, num_drivers); #endif #ifdef HAVE_FGLRX if (vaStatus != VA_STATUS_SUCCESS) - vaStatus = va_FGLRX_GetDriverName(pDisplayContext, driver_name, candidate_index); + vaStatus = va_FGLRX_GetDriverNames(pDisplayContext, drivers, num_drivers); #endif return vaStatus; } -static VAStatus va_DisplayContextGetNumCandidates( - VADisplayContextP pDisplayContext, - int *num_candidates -) -{ - VAStatus vaStatus = VA_STATUS_ERROR_UNKNOWN; - - if (!getenv("LIBVA_DRI3_DISABLE")) - vaStatus = va_DRI3_GetNumCandidates(pDisplayContext, num_candidates); - if (vaStatus != VA_STATUS_SUCCESS) - vaStatus = va_DRI2_GetNumCandidates(pDisplayContext, num_candidates); - - /* A call to va_DisplayContextGetDriverName will fallback to other - * methods (i.e. NVCTRL, FGLRX) when DRI2 is unsuccessful. All of those - * fallbacks only have 1 candidate driver. - */ - if (vaStatus != VA_STATUS_SUCCESS) - *num_candidates = 1; - - return VA_STATUS_SUCCESS; -} - VADisplay vaGetDisplay( Display *native_dpy /* implementation specific */ ) @@ -220,8 +109,7 @@ VADisplay vaGetDisplay( return NULL; pDisplayContext->vaDestroy = va_DisplayContextDestroy; - pDisplayContext->vaGetNumCandidates = va_DisplayContextGetNumCandidates; - pDisplayContext->vaGetDriverNameByIndex = va_DisplayContextGetDriverName; + pDisplayContext->vaGetDriverNames = va_DisplayContextGetDriverNames; pDriverContext = va_newDriverContext(pDisplayContext); if (!pDriverContext) {