-
Notifications
You must be signed in to change notification settings - Fork 302
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
win32/driver loader: Allow backends to load drivers from registry path #715
base: master
Are you sure you want to change the base?
Changes from all commits
19481b9
afda003
e63b0ad
39913d8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -38,14 +38,12 @@ | |
#include <string.h> | ||
#if defined(_WIN32) | ||
#include "compat_win32.h" | ||
#define DRIVER_EXTENSION "_drv_video.dll" | ||
#define DRIVER_PATH_STRING "%s\\%s%s" | ||
#define ENV_VAR_SEPARATOR ";" | ||
#else | ||
#include <dlfcn.h> | ||
#include <unistd.h> | ||
#define DRIVER_EXTENSION "_drv_video.so" | ||
#define DRIVER_PATH_STRING "%s/%s%s" | ||
#define DRIVER_PATH_STRING "%s/%s%s.so" | ||
#define ENV_VAR_SEPARATOR ":" | ||
#endif | ||
#ifdef ANDROID | ||
|
@@ -353,26 +351,163 @@ va_getDriverInitName(char *name, int namelen, int major, int minor) | |
return ret > 0 && ret < namelen; | ||
} | ||
|
||
static char *va_getDriverPath(const char *driver_dir, const char *driver_name) | ||
static char *va_getDriverPath(const char *driver_dir, const char *driver_name, bool use_suffix) | ||
{ | ||
int n = snprintf(0, 0, DRIVER_PATH_STRING, driver_dir, driver_name, DRIVER_EXTENSION); | ||
int n = snprintf(0, 0, DRIVER_PATH_STRING, driver_dir, driver_name, use_suffix ? "_drv_video" : ""); | ||
if (n < 0) | ||
return NULL; | ||
char *driver_path = (char *) malloc(n + 1); | ||
if (!driver_path) | ||
return NULL; | ||
n = snprintf(driver_path, n + 1, DRIVER_PATH_STRING, | ||
driver_dir, driver_name, DRIVER_EXTENSION); | ||
driver_dir, driver_name, use_suffix ? "_drv_video" : ""); | ||
if (n < 0) { | ||
free(driver_path); | ||
return NULL; | ||
} | ||
return driver_path; | ||
} | ||
|
||
static VAStatus va_openDriver(VADisplay dpy, char *driver_name) | ||
static VAStatus va_openDriverFromPath(VADisplay dpy, char *driver_path) | ||
{ | ||
VADriverContextP ctx = CTX(dpy); | ||
VAStatus vaStatus = VA_STATUS_ERROR_UNKNOWN; | ||
va_infoMessage(dpy, "Trying to open %s\n", driver_path); | ||
#if defined(RTLD_NODELETE) && !defined(ANDROID) | ||
void* handle = dlopen(driver_path, RTLD_NOW | RTLD_GLOBAL | RTLD_NODELETE); | ||
#else | ||
void* handle = dlopen(driver_path, RTLD_NOW | RTLD_GLOBAL); | ||
#endif | ||
if (!handle) { | ||
/* Don't give errors for non-existing files */ | ||
if (0 == access(driver_path, F_OK)) | ||
va_errorMessage(dpy, "dlopen of %s failed: %s\n", driver_path, dlerror()); | ||
} else { | ||
VADriverInit init_func = NULL; | ||
char init_func_s[256]; | ||
int i; | ||
|
||
struct { | ||
int major; | ||
int minor; | ||
} compatible_versions[VA_MINOR_VERSION + 2]; | ||
for (i = 0; i <= VA_MINOR_VERSION; i ++) { | ||
compatible_versions[i].major = VA_MAJOR_VERSION; | ||
compatible_versions[i].minor = VA_MINOR_VERSION - i; | ||
} | ||
compatible_versions[i].major = -1; | ||
compatible_versions[i].minor = -1; | ||
|
||
for (i = 0; compatible_versions[i].major >= 0; i++) { | ||
if (va_getDriverInitName(init_func_s, sizeof(init_func_s), | ||
compatible_versions[i].major, | ||
compatible_versions[i].minor)) { | ||
init_func = (VADriverInit)dlsym(handle, init_func_s); | ||
if (init_func) { | ||
va_infoMessage(dpy, "Found init function %s\n", init_func_s); | ||
break; | ||
} | ||
} | ||
} | ||
|
||
if (compatible_versions[i].major < 0) { | ||
va_errorMessage(dpy, "%s has no function %s\n", | ||
driver_path, init_func_s); | ||
dlclose(handle); | ||
} else { | ||
struct VADriverVTable *vtable = ctx->vtable; | ||
struct VADriverVTableVPP *vtable_vpp = ctx->vtable_vpp; | ||
struct VADriverVTableProt *vtable_prot = ctx->vtable_prot; | ||
|
||
vaStatus = VA_STATUS_SUCCESS; | ||
if (!vtable) { | ||
vtable = calloc(1, sizeof(*vtable)); | ||
if (!vtable) | ||
vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; | ||
} | ||
ctx->vtable = vtable; | ||
|
||
if (!vtable_vpp) { | ||
vtable_vpp = calloc(1, sizeof(*vtable_vpp)); | ||
if (vtable_vpp) | ||
vtable_vpp->version = VA_DRIVER_VTABLE_VPP_VERSION; | ||
else | ||
vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; | ||
} | ||
ctx->vtable_vpp = vtable_vpp; | ||
|
||
if (!vtable_prot) { | ||
vtable_prot = calloc(1, sizeof(*vtable_prot)); | ||
if (vtable_prot) | ||
vtable_prot->version = VA_DRIVER_VTABLE_PROT_VERSION; | ||
else | ||
vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; | ||
} | ||
ctx->vtable_prot = vtable_prot; | ||
|
||
if (init_func && VA_STATUS_SUCCESS == vaStatus) | ||
vaStatus = (*init_func)(ctx); | ||
|
||
if (VA_STATUS_SUCCESS == vaStatus) { | ||
CHECK_MAXIMUM(vaStatus, ctx, profiles); | ||
CHECK_MAXIMUM(vaStatus, ctx, entrypoints); | ||
CHECK_MAXIMUM(vaStatus, ctx, attributes); | ||
CHECK_MAXIMUM(vaStatus, ctx, image_formats); | ||
CHECK_MAXIMUM(vaStatus, ctx, subpic_formats); | ||
CHECK_STRING(vaStatus, ctx, vendor); | ||
CHECK_VTABLE(vaStatus, ctx, Terminate); | ||
CHECK_VTABLE(vaStatus, ctx, QueryConfigProfiles); | ||
CHECK_VTABLE(vaStatus, ctx, QueryConfigEntrypoints); | ||
CHECK_VTABLE(vaStatus, ctx, QueryConfigAttributes); | ||
CHECK_VTABLE(vaStatus, ctx, CreateConfig); | ||
CHECK_VTABLE(vaStatus, ctx, DestroyConfig); | ||
CHECK_VTABLE(vaStatus, ctx, GetConfigAttributes); | ||
CHECK_VTABLE(vaStatus, ctx, CreateSurfaces); | ||
CHECK_VTABLE(vaStatus, ctx, DestroySurfaces); | ||
CHECK_VTABLE(vaStatus, ctx, CreateContext); | ||
CHECK_VTABLE(vaStatus, ctx, DestroyContext); | ||
CHECK_VTABLE(vaStatus, ctx, CreateBuffer); | ||
CHECK_VTABLE(vaStatus, ctx, BufferSetNumElements); | ||
CHECK_VTABLE(vaStatus, ctx, MapBuffer); | ||
CHECK_VTABLE(vaStatus, ctx, UnmapBuffer); | ||
CHECK_VTABLE(vaStatus, ctx, DestroyBuffer); | ||
CHECK_VTABLE(vaStatus, ctx, BeginPicture); | ||
CHECK_VTABLE(vaStatus, ctx, RenderPicture); | ||
CHECK_VTABLE(vaStatus, ctx, EndPicture); | ||
CHECK_VTABLE(vaStatus, ctx, SyncSurface); | ||
CHECK_VTABLE(vaStatus, ctx, QuerySurfaceStatus); | ||
CHECK_VTABLE(vaStatus, ctx, QueryImageFormats); | ||
CHECK_VTABLE(vaStatus, ctx, CreateImage); | ||
CHECK_VTABLE(vaStatus, ctx, DeriveImage); | ||
CHECK_VTABLE(vaStatus, ctx, DestroyImage); | ||
CHECK_VTABLE(vaStatus, ctx, SetImagePalette); | ||
CHECK_VTABLE(vaStatus, ctx, GetImage); | ||
CHECK_VTABLE(vaStatus, ctx, PutImage); | ||
CHECK_VTABLE(vaStatus, ctx, QuerySubpictureFormats); | ||
CHECK_VTABLE(vaStatus, ctx, CreateSubpicture); | ||
CHECK_VTABLE(vaStatus, ctx, DestroySubpicture); | ||
CHECK_VTABLE(vaStatus, ctx, SetSubpictureImage); | ||
CHECK_VTABLE(vaStatus, ctx, SetSubpictureChromakey); | ||
CHECK_VTABLE(vaStatus, ctx, SetSubpictureGlobalAlpha); | ||
CHECK_VTABLE(vaStatus, ctx, AssociateSubpicture); | ||
CHECK_VTABLE(vaStatus, ctx, DeassociateSubpicture); | ||
CHECK_VTABLE(vaStatus, ctx, QueryDisplayAttributes); | ||
CHECK_VTABLE(vaStatus, ctx, GetDisplayAttributes); | ||
CHECK_VTABLE(vaStatus, ctx, SetDisplayAttributes); | ||
} | ||
if (VA_STATUS_SUCCESS != vaStatus) { | ||
va_errorMessage(dpy, "%s init failed\n", driver_path); | ||
dlclose(handle); | ||
} | ||
if (VA_STATUS_SUCCESS == vaStatus) | ||
ctx->handle = handle; | ||
} | ||
} | ||
return vaStatus; | ||
} | ||
|
||
static VAStatus va_openDriver(VADisplay dpy, char *driver_name) | ||
{ | ||
VAStatus vaStatus = VA_STATUS_ERROR_UNKNOWN; | ||
char *search_path = NULL; | ||
char *saveptr; | ||
|
@@ -392,150 +527,20 @@ static VAStatus va_openDriver(VADisplay dpy, char *driver_name) | |
} | ||
driver_dir = strtok_r(search_path, ENV_VAR_SEPARATOR, &saveptr); | ||
while (driver_dir) { | ||
void *handle = NULL; | ||
char *driver_path = va_getDriverPath(driver_dir, driver_name); | ||
if (!driver_path) { | ||
va_errorMessage(dpy, "%s L%d Out of memory\n", | ||
__FUNCTION__, __LINE__); | ||
free(search_path); | ||
return VA_STATUS_ERROR_ALLOCATION_FAILED; | ||
} | ||
|
||
va_infoMessage(dpy, "Trying to open %s\n", driver_path); | ||
#if defined(RTLD_NODELETE) && !defined(ANDROID) | ||
handle = dlopen(driver_path, RTLD_NOW | RTLD_GLOBAL | RTLD_NODELETE); | ||
#else | ||
handle = dlopen(driver_path, RTLD_NOW | RTLD_GLOBAL); | ||
#endif | ||
if (!handle) { | ||
/* Don't give errors for non-existing files */ | ||
if (0 == access(driver_path, F_OK)) | ||
va_errorMessage(dpy, "dlopen of %s failed: %s\n", driver_path, dlerror()); | ||
} else { | ||
VADriverInit init_func = NULL; | ||
char init_func_s[256]; | ||
int i; | ||
|
||
struct { | ||
int major; | ||
int minor; | ||
} compatible_versions[VA_MINOR_VERSION + 2]; | ||
for (i = 0; i <= VA_MINOR_VERSION; i ++) { | ||
compatible_versions[i].major = VA_MAJOR_VERSION; | ||
compatible_versions[i].minor = VA_MINOR_VERSION - i; | ||
} | ||
compatible_versions[i].major = -1; | ||
compatible_versions[i].minor = -1; | ||
|
||
for (i = 0; compatible_versions[i].major >= 0; i++) { | ||
if (va_getDriverInitName(init_func_s, sizeof(init_func_s), | ||
compatible_versions[i].major, | ||
compatible_versions[i].minor)) { | ||
init_func = (VADriverInit)dlsym(handle, init_func_s); | ||
if (init_func) { | ||
va_infoMessage(dpy, "Found init function %s\n", init_func_s); | ||
break; | ||
} | ||
} | ||
for (int use_suffix = 1; use_suffix >= 0; use_suffix--) { | ||
char *driver_path = va_getDriverPath(driver_dir, driver_name, use_suffix); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. will this construct There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, the first attempt will be |
||
if (!driver_path) { | ||
va_errorMessage(dpy, "%s L%d Out of memory\n", | ||
__FUNCTION__, __LINE__); | ||
free(search_path); | ||
return VA_STATUS_ERROR_ALLOCATION_FAILED; | ||
} | ||
|
||
if (compatible_versions[i].major < 0) { | ||
va_errorMessage(dpy, "%s has no function %s\n", | ||
driver_path, init_func_s); | ||
dlclose(handle); | ||
} else { | ||
struct VADriverVTable *vtable = ctx->vtable; | ||
struct VADriverVTableVPP *vtable_vpp = ctx->vtable_vpp; | ||
struct VADriverVTableProt *vtable_prot = ctx->vtable_prot; | ||
|
||
vaStatus = VA_STATUS_SUCCESS; | ||
if (!vtable) { | ||
vtable = calloc(1, sizeof(*vtable)); | ||
if (!vtable) | ||
vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; | ||
} | ||
ctx->vtable = vtable; | ||
|
||
if (!vtable_vpp) { | ||
vtable_vpp = calloc(1, sizeof(*vtable_vpp)); | ||
if (vtable_vpp) | ||
vtable_vpp->version = VA_DRIVER_VTABLE_VPP_VERSION; | ||
else | ||
vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; | ||
} | ||
ctx->vtable_vpp = vtable_vpp; | ||
|
||
if (!vtable_prot) { | ||
vtable_prot = calloc(1, sizeof(*vtable_prot)); | ||
if (vtable_prot) | ||
vtable_prot->version = VA_DRIVER_VTABLE_PROT_VERSION; | ||
else | ||
vaStatus = VA_STATUS_ERROR_ALLOCATION_FAILED; | ||
} | ||
ctx->vtable_prot = vtable_prot; | ||
|
||
if (init_func && VA_STATUS_SUCCESS == vaStatus) | ||
vaStatus = (*init_func)(ctx); | ||
|
||
if (VA_STATUS_SUCCESS == vaStatus) { | ||
CHECK_MAXIMUM(vaStatus, ctx, profiles); | ||
CHECK_MAXIMUM(vaStatus, ctx, entrypoints); | ||
CHECK_MAXIMUM(vaStatus, ctx, attributes); | ||
CHECK_MAXIMUM(vaStatus, ctx, image_formats); | ||
CHECK_MAXIMUM(vaStatus, ctx, subpic_formats); | ||
CHECK_STRING(vaStatus, ctx, vendor); | ||
CHECK_VTABLE(vaStatus, ctx, Terminate); | ||
CHECK_VTABLE(vaStatus, ctx, QueryConfigProfiles); | ||
CHECK_VTABLE(vaStatus, ctx, QueryConfigEntrypoints); | ||
CHECK_VTABLE(vaStatus, ctx, QueryConfigAttributes); | ||
CHECK_VTABLE(vaStatus, ctx, CreateConfig); | ||
CHECK_VTABLE(vaStatus, ctx, DestroyConfig); | ||
CHECK_VTABLE(vaStatus, ctx, GetConfigAttributes); | ||
CHECK_VTABLE(vaStatus, ctx, CreateSurfaces); | ||
CHECK_VTABLE(vaStatus, ctx, DestroySurfaces); | ||
CHECK_VTABLE(vaStatus, ctx, CreateContext); | ||
CHECK_VTABLE(vaStatus, ctx, DestroyContext); | ||
CHECK_VTABLE(vaStatus, ctx, CreateBuffer); | ||
CHECK_VTABLE(vaStatus, ctx, BufferSetNumElements); | ||
CHECK_VTABLE(vaStatus, ctx, MapBuffer); | ||
CHECK_VTABLE(vaStatus, ctx, UnmapBuffer); | ||
CHECK_VTABLE(vaStatus, ctx, DestroyBuffer); | ||
CHECK_VTABLE(vaStatus, ctx, BeginPicture); | ||
CHECK_VTABLE(vaStatus, ctx, RenderPicture); | ||
CHECK_VTABLE(vaStatus, ctx, EndPicture); | ||
CHECK_VTABLE(vaStatus, ctx, SyncSurface); | ||
CHECK_VTABLE(vaStatus, ctx, QuerySurfaceStatus); | ||
CHECK_VTABLE(vaStatus, ctx, QueryImageFormats); | ||
CHECK_VTABLE(vaStatus, ctx, CreateImage); | ||
CHECK_VTABLE(vaStatus, ctx, DeriveImage); | ||
CHECK_VTABLE(vaStatus, ctx, DestroyImage); | ||
CHECK_VTABLE(vaStatus, ctx, SetImagePalette); | ||
CHECK_VTABLE(vaStatus, ctx, GetImage); | ||
CHECK_VTABLE(vaStatus, ctx, PutImage); | ||
CHECK_VTABLE(vaStatus, ctx, QuerySubpictureFormats); | ||
CHECK_VTABLE(vaStatus, ctx, CreateSubpicture); | ||
CHECK_VTABLE(vaStatus, ctx, DestroySubpicture); | ||
CHECK_VTABLE(vaStatus, ctx, SetSubpictureImage); | ||
CHECK_VTABLE(vaStatus, ctx, SetSubpictureChromakey); | ||
CHECK_VTABLE(vaStatus, ctx, SetSubpictureGlobalAlpha); | ||
CHECK_VTABLE(vaStatus, ctx, AssociateSubpicture); | ||
CHECK_VTABLE(vaStatus, ctx, DeassociateSubpicture); | ||
CHECK_VTABLE(vaStatus, ctx, QueryDisplayAttributes); | ||
CHECK_VTABLE(vaStatus, ctx, GetDisplayAttributes); | ||
CHECK_VTABLE(vaStatus, ctx, SetDisplayAttributes); | ||
} | ||
if (VA_STATUS_SUCCESS != vaStatus) { | ||
va_errorMessage(dpy, "%s init failed\n", driver_path); | ||
dlclose(handle); | ||
} | ||
if (VA_STATUS_SUCCESS == vaStatus) | ||
ctx->handle = handle; | ||
free(driver_path); | ||
vaStatus = va_openDriverFromPath(dpy, driver_path); | ||
free(driver_path); | ||
if (VA_STATUS_SUCCESS == vaStatus) | ||
break; | ||
} | ||
} | ||
free(driver_path); | ||
|
||
driver_dir = strtok_r(NULL, ENV_VAR_SEPARATOR, &saveptr); | ||
} | ||
|
||
|
@@ -715,6 +720,10 @@ static VAStatus va_new_opendriver(VADisplay dpy) | |
} | ||
|
||
vaStatus = va_openDriver(dpy, drivers[i]); | ||
/* Try as path as fallback */ | ||
if (vaStatus != VA_STATUS_SUCCESS) | ||
sivileri marked this conversation as resolved.
Show resolved
Hide resolved
|
||
vaStatus = va_openDriverFromPath(dpy, drivers[i]); | ||
|
||
va_infoMessage(dpy, "va_openDriver() returns %d\n", vaStatus); | ||
|
||
if (vaStatus == VA_STATUS_SUCCESS) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -35,7 +35,7 @@ | |
* which will be selected when provided with an adapter LUID which | ||
* does not have a registered VA driver | ||
*/ | ||
const char VAAPI_DEFAULT_DRIVER_NAME[] = "vaon12"; | ||
const char VAAPI_DEFAULT_DRIVER_NAME[] = "vaon12_drv_video"; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. emmm. But "vaon12_drv_video" is not a full path. Full path (on Windows) would be for example "C:\msys64\mingw64\bin\vaon12_drv_video.dll". You probably can name it "full driver name", but saying "full path" I personally understand different thing. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree the commit message is confusing, I'll reword it. The full path should be As in Win
|
||
|
||
typedef struct _VADisplayContextWin32 { | ||
LUID adapter_luid; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why :). Besides that's not true since you will return default
VA_STATUS_ERROR_UNKNOWN
defined above. So, maybe we need the following for simplicity:There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd happy to make that change to make it cleaner/simpler, but that is the already existing behavior in va.c in master too, I didn't want to make any functional changes here other than extracting the
va_OpenDriverFromPath
function. Maybe this behaviour has a historical reason for being like this? The last change to this line was 16 years ago :/