• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © Microsoft Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21  * IN THE SOFTWARE.
22  */
23 
24 #include <stdio.h>
25 #include <stdbool.h>
26 #include <va/va_win32.h>
27 #include "va_display.h"
28 #include <directx/dxcore_interface.h>
29 
30 extern "C" const char *g_device_name;
31 
dxcore_resolve_adapter(const char * adapter_string,bool * ptr_device_found,LUID * ptr_adapter_luid)32 void dxcore_resolve_adapter(const char *adapter_string, /*out*/ bool* ptr_device_found, /*out*/ LUID* ptr_adapter_luid)
33 {
34     int selected_adapter_index = -1;
35     IDXCoreAdapterFactory *factory = nullptr;
36     IDXCoreAdapterList *adapter_list = nullptr;
37     IDXCoreAdapter *adapter = nullptr;
38     typedef HRESULT(WINAPI * PFN_CREATE_DXCORE_ADAPTER_FACTORY)(REFIID riid, void **ppFactory);
39     PFN_CREATE_DXCORE_ADAPTER_FACTORY DXCoreCreateAdapterFactory;
40     HRESULT hr = S_OK;
41 
42     memset(ptr_adapter_luid, 0, sizeof(LUID));
43     *ptr_device_found = false;
44 
45     HMODULE dxcore_mod = LoadLibrary("DXCore.DLL");
46     if (!dxcore_mod) {
47         fprintf(stderr, "Failed to load DXCore.DLL to enumerate adapters.\n");
48         goto fail;
49     }
50 
51     DXCoreCreateAdapterFactory = (PFN_CREATE_DXCORE_ADAPTER_FACTORY)GetProcAddress(dxcore_mod, "DXCoreCreateAdapterFactory");
52     if (!DXCoreCreateAdapterFactory) {
53         fprintf(stderr, "Failed to load DXCoreCreateAdapterFactory from DXCore.DLL.\n");
54         goto fail;
55     }
56 
57     hr = DXCoreCreateAdapterFactory(IID_IDXCoreAdapterFactory, (void **)&factory);
58     if (FAILED(hr)) {
59         fprintf(stderr, "DXCoreCreateAdapterFactory failed: %lx\n", hr);
60         goto fail;
61     }
62 
63     hr = factory->CreateAdapterList(1, &DXCORE_ADAPTER_ATTRIBUTE_D3D12_GRAPHICS, IID_IDXCoreAdapterList, (void **)&adapter_list);
64     if (FAILED(hr)) {
65         fprintf(stderr, "CreateAdapterList failed: %lx\n", hr);
66         goto fail;
67     }
68 
69     if (adapter_string && (sscanf_s(adapter_string, "%d", &selected_adapter_index) != 1)) {
70         fprintf(stderr, "Invalid device index received for -hwaccel_device %s\n", adapter_string ? adapter_string : "");
71     }
72 
73     if (!adapter_string) fprintf(stdout, "Available devices for --display win32:\n");
74     for (int i = 0; i < adapter_list->GetAdapterCount(); i++) {
75         if (SUCCEEDED(adapter_list->GetAdapter(i, IID_IDXCoreAdapter, (void **)&adapter))) {
76             size_t desc_size = 0;
77             if (FAILED(adapter->GetPropertySize(DXCoreAdapterProperty::DriverDescription, &desc_size))) {
78                 adapter->Release();
79                 continue;
80             }
81 
82             char *adapter_name = (char*)malloc(desc_size);
83             if (!adapter_name) {
84                 adapter->Release();
85                 continue;
86             }
87 
88             if (FAILED(adapter->GetProperty(DXCoreAdapterProperty::DriverDescription, desc_size, adapter_name))) {
89                 free(adapter_name);
90                 adapter->Release();
91                 continue;
92             }
93 
94             LUID cur_adapter_luid = { 0, 0 };
95             if (FAILED(adapter->GetProperty(DXCoreAdapterProperty::InstanceLuid, &cur_adapter_luid))) {
96                 free(adapter_name);
97                 adapter->Release();
98                 continue;
99             }
100 
101             if (selected_adapter_index == i) {
102                 *ptr_adapter_luid = cur_adapter_luid;
103                 *ptr_device_found = true;
104             }
105 
106             if (!adapter_string) fprintf(stdout, "\tDevice Index: %d Device LUID: %lu %ld - Device Name: %s\n", i, cur_adapter_luid.LowPart, cur_adapter_luid.HighPart, adapter_name);
107             free(adapter_name);
108             adapter->Release();
109         }
110     }
111 
112 fail:
113     if (adapter_list)
114         adapter_list->Release();
115     if (factory)
116         factory->Release();
117     if (dxcore_mod)
118         FreeLibrary(dxcore_mod);
119 }
120 
121 static VADisplay
va_open_display_win32(void)122 va_open_display_win32(void)
123 {
124     LUID adapter_luid = {0, 0};
125     bool device_found = false;
126     if (g_device_name) {
127         bool print_devices = (0 == strcmp(g_device_name, "help"));
128         dxcore_resolve_adapter(print_devices ? NULL : g_device_name, &device_found, &adapter_luid);
129         if (print_devices) {
130             exit(0);
131         } else if (g_device_name && !device_found) {
132             fprintf(stderr, "Could not find device %s for --display win32. Please try --device help for a list of available devices.\n", g_device_name);
133             exit(0);
134         }
135     }
136 
137     // Adapter automatic selection supported by sending NULL adapter to vaGetDisplayWin32
138     return vaGetDisplayWin32(device_found ? &adapter_luid : NULL);
139 }
140 
141 static void
va_close_display_win32(VADisplay va_dpy)142 va_close_display_win32(VADisplay va_dpy)
143 {
144 }
145 
146 static VAStatus
va_put_surface_win32(VADisplay va_dpy,VASurfaceID surface,const VARectangle * src_rect,const VARectangle * dst_rect)147 va_put_surface_win32(
148     VADisplay          va_dpy,
149     VASurfaceID        surface,
150     const VARectangle *src_rect,
151     const VARectangle *dst_rect
152 )
153 {
154     return VA_STATUS_ERROR_OPERATION_FAILED;
155 }
156 
157 #ifdef __cplusplus
158 extern "C" {
159 #endif
160 
161 extern const VADisplayHooks va_display_hooks_win32 = {
162     "win32",
163     va_open_display_win32,
164     va_close_display_win32,
165     va_put_surface_win32,
166 };
167 
168 #ifdef __cplusplus
169 }
170 #endif
171