xref: /aosp_15_r20/external/libva/va/win32/va_win32.c (revision 54e60f844a168e9a219354de272cd517ee8cd4b7)
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