1*54e60f84SAndroid Build Coastguard Worker /*
2*54e60f84SAndroid Build Coastguard Worker * Copyright © Microsoft Corporation
3*54e60f84SAndroid Build Coastguard Worker * Copyright (c) 2023 Emil Velikov
4*54e60f84SAndroid Build Coastguard Worker *
5*54e60f84SAndroid Build Coastguard Worker * Permission is hereby granted, free of charge, to any person obtaining a
6*54e60f84SAndroid Build Coastguard Worker * copy of this software and associated documentation files (the "Software"),
7*54e60f84SAndroid Build Coastguard Worker * to deal in the Software without restriction, including without limitation
8*54e60f84SAndroid Build Coastguard Worker * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9*54e60f84SAndroid Build Coastguard Worker * and/or sell copies of the Software, and to permit persons to whom the
10*54e60f84SAndroid Build Coastguard Worker * Software is furnished to do so, subject to the following conditions:
11*54e60f84SAndroid Build Coastguard Worker *
12*54e60f84SAndroid Build Coastguard Worker * The above copyright notice and this permission notice (including the next
13*54e60f84SAndroid Build Coastguard Worker * paragraph) shall be included in all copies or substantial portions of the
14*54e60f84SAndroid Build Coastguard Worker * Software.
15*54e60f84SAndroid Build Coastguard Worker *
16*54e60f84SAndroid Build Coastguard Worker * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17*54e60f84SAndroid Build Coastguard Worker * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18*54e60f84SAndroid Build Coastguard Worker * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19*54e60f84SAndroid Build Coastguard Worker * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20*54e60f84SAndroid Build Coastguard Worker * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21*54e60f84SAndroid Build Coastguard Worker * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22*54e60f84SAndroid Build Coastguard Worker * IN THE SOFTWARE.
23*54e60f84SAndroid Build Coastguard Worker */
24*54e60f84SAndroid Build Coastguard Worker
25*54e60f84SAndroid Build Coastguard Worker #include "sysdeps.h"
26*54e60f84SAndroid Build Coastguard Worker #include "va.h"
27*54e60f84SAndroid Build Coastguard Worker #include "va_backend.h"
28*54e60f84SAndroid Build Coastguard Worker #include "va_internal.h"
29*54e60f84SAndroid Build Coastguard Worker #include "va_trace.h"
30*54e60f84SAndroid Build Coastguard Worker #include "va_win32.h"
31*54e60f84SAndroid Build Coastguard Worker #include "compat_win32.h"
32*54e60f84SAndroid Build Coastguard Worker
33*54e60f84SAndroid Build Coastguard Worker /*
34*54e60f84SAndroid Build Coastguard Worker * Initialize default driver to the VAOn12 driver implementation
35*54e60f84SAndroid Build Coastguard Worker * which will be selected when provided with an adapter LUID which
36*54e60f84SAndroid Build Coastguard Worker * does not have a registered VA driver
37*54e60f84SAndroid Build Coastguard Worker */
38*54e60f84SAndroid Build Coastguard Worker const char VAAPI_DEFAULT_DRIVER_NAME[] = "vaon12";
39*54e60f84SAndroid Build Coastguard Worker
40*54e60f84SAndroid Build Coastguard Worker typedef struct _VADisplayContextWin32 {
41*54e60f84SAndroid Build Coastguard Worker char registry_driver_name[MAX_PATH];
42*54e60f84SAndroid Build Coastguard Worker bool registry_driver_available_flag;
43*54e60f84SAndroid Build Coastguard Worker } VADisplayContextWin32;
44*54e60f84SAndroid Build Coastguard Worker
LoadDriverNameFromRegistry(const LUID * adapter_luid,VADisplayContextWin32 * pWin32Ctx)45*54e60f84SAndroid Build Coastguard Worker static void LoadDriverNameFromRegistry(const LUID* adapter_luid, VADisplayContextWin32* pWin32Ctx)
46*54e60f84SAndroid Build Coastguard Worker {
47*54e60f84SAndroid Build Coastguard Worker HMODULE hGdi32 = LoadLibraryA("gdi32.dll");
48*54e60f84SAndroid Build Coastguard Worker if (!hGdi32)
49*54e60f84SAndroid Build Coastguard Worker return;
50*54e60f84SAndroid Build Coastguard Worker
51*54e60f84SAndroid Build Coastguard Worker D3DKMT_OPENADAPTERFROMLUID OpenArgs = { .AdapterLuid = *adapter_luid };
52*54e60f84SAndroid Build Coastguard Worker D3DDDI_QUERYREGISTRY_INFO RegistryInfo = {
53*54e60f84SAndroid Build Coastguard Worker .QueryType = D3DDDI_QUERYREGISTRY_ADAPTERKEY,
54*54e60f84SAndroid Build Coastguard Worker .QueryFlags.TranslatePath = true,
55*54e60f84SAndroid Build Coastguard Worker .ValueName = L"VAAPIDriverName",
56*54e60f84SAndroid Build Coastguard Worker .ValueType = REG_SZ,
57*54e60f84SAndroid Build Coastguard Worker };
58*54e60f84SAndroid Build Coastguard Worker D3DDDI_QUERYREGISTRY_INFO *pRegistryInfo = &RegistryInfo;
59*54e60f84SAndroid Build Coastguard Worker #ifndef _WIN64
60*54e60f84SAndroid Build Coastguard Worker BOOL isWowProcess = false;
61*54e60f84SAndroid Build Coastguard Worker if (IsWow64Process(GetCurrentProcess(), &isWowProcess) && isWowProcess)
62*54e60f84SAndroid Build Coastguard Worker wcscpy(RegistryInfo.ValueName, L"VAAPIDriverNameWow");
63*54e60f84SAndroid Build Coastguard Worker #endif
64*54e60f84SAndroid Build Coastguard Worker D3DKMT_QUERYADAPTERINFO QAI = {
65*54e60f84SAndroid Build Coastguard Worker .Type = KMTQAITYPE_QUERYREGISTRY,
66*54e60f84SAndroid Build Coastguard Worker .pPrivateDriverData = &RegistryInfo,
67*54e60f84SAndroid Build Coastguard Worker .PrivateDriverDataSize = sizeof(RegistryInfo),
68*54e60f84SAndroid Build Coastguard Worker };
69*54e60f84SAndroid Build Coastguard Worker
70*54e60f84SAndroid Build Coastguard Worker PFND3DKMT_OPENADAPTERFROMLUID pfnOpenAdapterFromLuid = (PFND3DKMT_OPENADAPTERFROMLUID)GetProcAddress(hGdi32, "D3DKMTOpenAdapterFromLuid");
71*54e60f84SAndroid Build Coastguard Worker PFND3DKMT_CLOSEADAPTER pfnCloseAdapter = (PFND3DKMT_CLOSEADAPTER)GetProcAddress(hGdi32, "D3DKMTCloseAdapter");
72*54e60f84SAndroid Build Coastguard Worker PFND3DKMT_QUERYADAPTERINFO pfnQueryAdapterInfo = (PFND3DKMT_QUERYADAPTERINFO)GetProcAddress(hGdi32, "D3DKMTQueryAdapterInfo");
73*54e60f84SAndroid Build Coastguard Worker if (!pfnOpenAdapterFromLuid || !pfnCloseAdapter || !pfnQueryAdapterInfo)
74*54e60f84SAndroid Build Coastguard Worker goto cleanup;
75*54e60f84SAndroid Build Coastguard Worker
76*54e60f84SAndroid Build Coastguard Worker if (!NT_SUCCESS(pfnOpenAdapterFromLuid(&OpenArgs)))
77*54e60f84SAndroid Build Coastguard Worker goto cleanup;
78*54e60f84SAndroid Build Coastguard Worker
79*54e60f84SAndroid Build Coastguard Worker QAI.hAdapter = OpenArgs.hAdapter;
80*54e60f84SAndroid Build Coastguard Worker if (!NT_SUCCESS(pfnQueryAdapterInfo(&QAI)) ||
81*54e60f84SAndroid Build Coastguard Worker pRegistryInfo->Status != D3DDDI_QUERYREGISTRY_STATUS_BUFFER_OVERFLOW)
82*54e60f84SAndroid Build Coastguard Worker goto cleanup;
83*54e60f84SAndroid Build Coastguard Worker
84*54e60f84SAndroid Build Coastguard Worker size_t RegistryInfoSize = sizeof(RegistryInfo) + RegistryInfo.OutputValueSize;
85*54e60f84SAndroid Build Coastguard Worker pRegistryInfo = malloc(RegistryInfoSize);
86*54e60f84SAndroid Build Coastguard Worker if (!pRegistryInfo)
87*54e60f84SAndroid Build Coastguard Worker goto cleanup;
88*54e60f84SAndroid Build Coastguard Worker
89*54e60f84SAndroid Build Coastguard Worker memcpy(pRegistryInfo, &RegistryInfo, sizeof(RegistryInfo));
90*54e60f84SAndroid Build Coastguard Worker QAI.pPrivateDriverData = pRegistryInfo;
91*54e60f84SAndroid Build Coastguard Worker QAI.PrivateDriverDataSize = RegistryInfoSize;
92*54e60f84SAndroid Build Coastguard Worker if (!NT_SUCCESS(pfnQueryAdapterInfo(&QAI)) ||
93*54e60f84SAndroid Build Coastguard Worker pRegistryInfo->Status != D3DDDI_QUERYREGISTRY_STATUS_SUCCESS)
94*54e60f84SAndroid Build Coastguard Worker goto cleanup;
95*54e60f84SAndroid Build Coastguard Worker
96*54e60f84SAndroid Build Coastguard Worker if (!WideCharToMultiByte(CP_ACP, 0, pRegistryInfo->OutputString,
97*54e60f84SAndroid Build Coastguard Worker RegistryInfo.OutputValueSize / sizeof(wchar_t),
98*54e60f84SAndroid Build Coastguard Worker pWin32Ctx->registry_driver_name,
99*54e60f84SAndroid Build Coastguard Worker sizeof(pWin32Ctx->registry_driver_name),
100*54e60f84SAndroid Build Coastguard Worker NULL, NULL))
101*54e60f84SAndroid Build Coastguard Worker goto cleanup;
102*54e60f84SAndroid Build Coastguard Worker
103*54e60f84SAndroid Build Coastguard Worker pWin32Ctx->registry_driver_available_flag = true;
104*54e60f84SAndroid Build Coastguard Worker
105*54e60f84SAndroid Build Coastguard Worker cleanup:
106*54e60f84SAndroid Build Coastguard Worker if (pRegistryInfo && pRegistryInfo != &RegistryInfo)
107*54e60f84SAndroid Build Coastguard Worker free(pRegistryInfo);
108*54e60f84SAndroid Build Coastguard Worker if (pfnCloseAdapter && OpenArgs.hAdapter) {
109*54e60f84SAndroid Build Coastguard Worker D3DKMT_CLOSEADAPTER Close = { OpenArgs.hAdapter };
110*54e60f84SAndroid Build Coastguard Worker /* The explicit negation is a no-op, yet required to silence the
111*54e60f84SAndroid Build Coastguard Worker * Wunused-result warning.
112*54e60f84SAndroid Build Coastguard Worker */
113*54e60f84SAndroid Build Coastguard Worker (void) !pfnCloseAdapter(&Close);
114*54e60f84SAndroid Build Coastguard Worker }
115*54e60f84SAndroid Build Coastguard Worker FreeLibrary(hGdi32);
116*54e60f84SAndroid Build Coastguard Worker }
117*54e60f84SAndroid Build Coastguard Worker
va_DisplayContextDestroy(VADisplayContextP pDisplayContext)118*54e60f84SAndroid Build Coastguard Worker static void va_DisplayContextDestroy(
119*54e60f84SAndroid Build Coastguard Worker VADisplayContextP pDisplayContext
120*54e60f84SAndroid Build Coastguard Worker )
121*54e60f84SAndroid Build Coastguard Worker {
122*54e60f84SAndroid Build Coastguard Worker if (pDisplayContext == NULL)
123*54e60f84SAndroid Build Coastguard Worker return;
124*54e60f84SAndroid Build Coastguard Worker
125*54e60f84SAndroid Build Coastguard Worker if (pDisplayContext->pDriverContext
126*54e60f84SAndroid Build Coastguard Worker && pDisplayContext->pDriverContext->native_dpy)
127*54e60f84SAndroid Build Coastguard Worker free(pDisplayContext->pDriverContext->native_dpy);
128*54e60f84SAndroid Build Coastguard Worker
129*54e60f84SAndroid Build Coastguard Worker free(pDisplayContext->pDriverContext);
130*54e60f84SAndroid Build Coastguard Worker free(pDisplayContext->opaque);
131*54e60f84SAndroid Build Coastguard Worker free(pDisplayContext);
132*54e60f84SAndroid Build Coastguard Worker }
133*54e60f84SAndroid Build Coastguard Worker
va_DisplayContextGetDriverNames(VADisplayContextP pDisplayContext,char ** drivers,unsigned * num_drivers)134*54e60f84SAndroid Build Coastguard Worker static VAStatus va_DisplayContextGetDriverNames(
135*54e60f84SAndroid Build Coastguard Worker VADisplayContextP pDisplayContext,
136*54e60f84SAndroid Build Coastguard Worker char **drivers,
137*54e60f84SAndroid Build Coastguard Worker unsigned *num_drivers
138*54e60f84SAndroid Build Coastguard Worker )
139*54e60f84SAndroid Build Coastguard Worker {
140*54e60f84SAndroid Build Coastguard Worker const LUID * const adapter = pDisplayContext->pDriverContext->native_dpy;
141*54e60f84SAndroid Build Coastguard Worker const VADisplayContextWin32 * const pWin32Ctx = pDisplayContext->opaque;
142*54e60f84SAndroid Build Coastguard Worker unsigned count = 0;
143*54e60f84SAndroid Build Coastguard Worker
144*54e60f84SAndroid Build Coastguard Worker /* Always prefer the adapter registered driver name as first option */
145*54e60f84SAndroid Build Coastguard Worker if (adapter && pWin32Ctx->registry_driver_available_flag) {
146*54e60f84SAndroid Build Coastguard Worker drivers[count] = _strdup(pWin32Ctx->registry_driver_name);
147*54e60f84SAndroid Build Coastguard Worker count++;
148*54e60f84SAndroid Build Coastguard Worker }
149*54e60f84SAndroid Build Coastguard Worker /* Provide the default driver name as a fallback option */
150*54e60f84SAndroid Build Coastguard Worker if (*num_drivers > count) {
151*54e60f84SAndroid Build Coastguard Worker drivers[count] = _strdup(VAAPI_DEFAULT_DRIVER_NAME);
152*54e60f84SAndroid Build Coastguard Worker count++;
153*54e60f84SAndroid Build Coastguard Worker }
154*54e60f84SAndroid Build Coastguard Worker
155*54e60f84SAndroid Build Coastguard Worker *num_drivers = count;
156*54e60f84SAndroid Build Coastguard Worker
157*54e60f84SAndroid Build Coastguard Worker return VA_STATUS_SUCCESS;
158*54e60f84SAndroid Build Coastguard Worker }
159*54e60f84SAndroid Build Coastguard Worker
vaGetDisplayWin32(const LUID * adapter_luid)160*54e60f84SAndroid Build Coastguard Worker VADisplay vaGetDisplayWin32(
161*54e60f84SAndroid Build Coastguard Worker /* Can be null for adapter autoselection in the VA driver */
162*54e60f84SAndroid Build Coastguard Worker const LUID* adapter_luid
163*54e60f84SAndroid Build Coastguard Worker )
164*54e60f84SAndroid Build Coastguard Worker {
165*54e60f84SAndroid Build Coastguard Worker VADisplayContextP pDisplayContext;
166*54e60f84SAndroid Build Coastguard Worker VADriverContextP pDriverContext;
167*54e60f84SAndroid Build Coastguard Worker
168*54e60f84SAndroid Build Coastguard Worker pDisplayContext = va_newDisplayContext();
169*54e60f84SAndroid Build Coastguard Worker if (!pDisplayContext)
170*54e60f84SAndroid Build Coastguard Worker return NULL;
171*54e60f84SAndroid Build Coastguard Worker
172*54e60f84SAndroid Build Coastguard Worker pDisplayContext->vaDestroy = va_DisplayContextDestroy;
173*54e60f84SAndroid Build Coastguard Worker pDisplayContext->vaGetDriverNames = va_DisplayContextGetDriverNames;
174*54e60f84SAndroid Build Coastguard Worker pDisplayContext->opaque = calloc(1, sizeof(VADisplayContextWin32));
175*54e60f84SAndroid Build Coastguard Worker if (!pDisplayContext->opaque) {
176*54e60f84SAndroid Build Coastguard Worker va_DisplayContextDestroy(pDisplayContext);
177*54e60f84SAndroid Build Coastguard Worker return NULL;
178*54e60f84SAndroid Build Coastguard Worker }
179*54e60f84SAndroid Build Coastguard Worker
180*54e60f84SAndroid Build Coastguard Worker VADisplayContextWin32* pWin32Ctx = (VADisplayContextWin32*) pDisplayContext->opaque;
181*54e60f84SAndroid Build Coastguard Worker if (adapter_luid) {
182*54e60f84SAndroid Build Coastguard Worker /* Load the preferred driver name from the driver registry if available */
183*54e60f84SAndroid Build Coastguard Worker LoadDriverNameFromRegistry(adapter_luid, pWin32Ctx);
184*54e60f84SAndroid Build Coastguard Worker #ifdef _DEBUG
185*54e60f84SAndroid Build Coastguard Worker if (pWin32Ctx->registry_driver_available_flag) {
186*54e60f84SAndroid Build Coastguard Worker 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);
187*54e60f84SAndroid Build Coastguard Worker } else {
188*54e60f84SAndroid Build Coastguard Worker 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);
189*54e60f84SAndroid Build Coastguard Worker }
190*54e60f84SAndroid Build Coastguard Worker #endif // _DEBUG
191*54e60f84SAndroid Build Coastguard Worker }
192*54e60f84SAndroid Build Coastguard Worker
193*54e60f84SAndroid Build Coastguard Worker pDriverContext = va_newDriverContext(pDisplayContext);
194*54e60f84SAndroid Build Coastguard Worker if (!pDriverContext) {
195*54e60f84SAndroid Build Coastguard Worker va_DisplayContextDestroy(pDisplayContext);
196*54e60f84SAndroid Build Coastguard Worker return NULL;
197*54e60f84SAndroid Build Coastguard Worker }
198*54e60f84SAndroid Build Coastguard Worker
199*54e60f84SAndroid Build Coastguard Worker pDriverContext->display_type = VA_DISPLAY_WIN32;
200*54e60f84SAndroid Build Coastguard Worker
201*54e60f84SAndroid Build Coastguard Worker if (adapter_luid) {
202*54e60f84SAndroid Build Coastguard Worker /* Copy LUID information to driver context */
203*54e60f84SAndroid Build Coastguard Worker pDriverContext->native_dpy = calloc(1, sizeof(*adapter_luid));
204*54e60f84SAndroid Build Coastguard Worker memcpy(pDriverContext->native_dpy, adapter_luid, sizeof(*adapter_luid));
205*54e60f84SAndroid Build Coastguard Worker }
206*54e60f84SAndroid Build Coastguard Worker
207*54e60f84SAndroid Build Coastguard Worker return (VADisplay)pDisplayContext;
208*54e60f84SAndroid Build Coastguard Worker }
209