| /* | |
| * Copyright © Microsoft Corporation | |
| * | |
| * Permission is hereby granted, free of charge, to any person obtaining a | |
| * copy of this software and associated documentation files (the "Software"), | |
| * to deal in the Software without restriction, including without limitation | |
| * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
| * and/or sell copies of the Software, and to permit persons to whom the | |
| * Software is furnished to do so, subject to the following conditions: | |
| * | |
| * The above copyright notice and this permission notice (including the next | |
| * paragraph) shall be included in all copies or substantial portions of the | |
| * Software. | |
| * | |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
| * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
| * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | |
| * IN THE SOFTWARE. | |
| */ | |
| #include <stdio.h> | |
| #include <stdbool.h> | |
| #include <va/va_win32.h> | |
| #include "va_display.h" | |
| #include <directx/dxcore_interface.h> | |
| extern "C" const char *g_device_name; | |
| void dxcore_resolve_adapter(const char *adapter_string, /*out*/ bool* ptr_device_found, /*out*/ LUID* ptr_adapter_luid) | |
| { | |
| int selected_adapter_index = -1; | |
| IDXCoreAdapterFactory *factory = nullptr; | |
| IDXCoreAdapterList *adapter_list = nullptr; | |
| IDXCoreAdapter *adapter = nullptr; | |
| typedef HRESULT(WINAPI * PFN_CREATE_DXCORE_ADAPTER_FACTORY)(REFIID riid, void **ppFactory); | |
| PFN_CREATE_DXCORE_ADAPTER_FACTORY DXCoreCreateAdapterFactory; | |
| HRESULT hr = S_OK; | |
| memset(ptr_adapter_luid, 0, sizeof(LUID)); | |
| *ptr_device_found = false; | |
| HMODULE dxcore_mod = LoadLibrary("DXCore.DLL"); | |
| if (!dxcore_mod) { | |
| fprintf(stderr, "Failed to load DXCore.DLL to enumerate adapters.\n"); | |
| goto fail; | |
| } | |
| DXCoreCreateAdapterFactory = (PFN_CREATE_DXCORE_ADAPTER_FACTORY)GetProcAddress(dxcore_mod, "DXCoreCreateAdapterFactory"); | |
| if (!DXCoreCreateAdapterFactory) { | |
| fprintf(stderr, "Failed to load DXCoreCreateAdapterFactory from DXCore.DLL.\n"); | |
| goto fail; | |
| } | |
| hr = DXCoreCreateAdapterFactory(IID_IDXCoreAdapterFactory, (void **)&factory); | |
| if (FAILED(hr)) { | |
| fprintf(stderr, "DXCoreCreateAdapterFactory failed: %lx\n", hr); | |
| goto fail; | |
| } | |
| hr = factory->CreateAdapterList(1, &DXCORE_ADAPTER_ATTRIBUTE_D3D12_GRAPHICS, IID_IDXCoreAdapterList, (void **)&adapter_list); | |
| if (FAILED(hr)) { | |
| fprintf(stderr, "CreateAdapterList failed: %lx\n", hr); | |
| goto fail; | |
| } | |
| if (adapter_string && (sscanf_s(adapter_string, "%d", &selected_adapter_index) != 1)) { | |
| fprintf(stderr, "Invalid device index received for -hwaccel_device %s\n", adapter_string ? adapter_string : ""); | |
| } | |
| if (!adapter_string) fprintf(stdout, "Available devices for --display win32:\n"); | |
| for (int i = 0; i < adapter_list->GetAdapterCount(); i++) { | |
| if (SUCCEEDED(adapter_list->GetAdapter(i, IID_IDXCoreAdapter, (void **)&adapter))) { | |
| size_t desc_size = 0; | |
| if (FAILED(adapter->GetPropertySize(DXCoreAdapterProperty::DriverDescription, &desc_size))) { | |
| adapter->Release(); | |
| continue; | |
| } | |
| char *adapter_name = (char*)malloc(desc_size); | |
| if (!adapter_name) { | |
| adapter->Release(); | |
| continue; | |
| } | |
| if (FAILED(adapter->GetProperty(DXCoreAdapterProperty::DriverDescription, desc_size, adapter_name))) { | |
| free(adapter_name); | |
| adapter->Release(); | |
| continue; | |
| } | |
| LUID cur_adapter_luid = { 0, 0 }; | |
| if (FAILED(adapter->GetProperty(DXCoreAdapterProperty::InstanceLuid, &cur_adapter_luid))) { | |
| free(adapter_name); | |
| adapter->Release(); | |
| continue; | |
| } | |
| if (selected_adapter_index == i) { | |
| *ptr_adapter_luid = cur_adapter_luid; | |
| *ptr_device_found = true; | |
| } | |
| 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); | |
| free(adapter_name); | |
| adapter->Release(); | |
| } | |
| } | |
| fail: | |
| if (adapter_list) | |
| adapter_list->Release(); | |
| if (factory) | |
| factory->Release(); | |
| if (dxcore_mod) | |
| FreeLibrary(dxcore_mod); | |
| } | |
| static VADisplay | |
| va_open_display_win32(void) | |
| { | |
| LUID adapter_luid = {0, 0}; | |
| bool device_found = false; | |
| if (g_device_name) { | |
| bool print_devices = (0 == strcmp(g_device_name, "help")); | |
| dxcore_resolve_adapter(print_devices ? NULL : g_device_name, &device_found, &adapter_luid); | |
| if (print_devices) { | |
| exit(0); | |
| } else if (g_device_name && !device_found) { | |
| fprintf(stderr, "Could not find device %s for --display win32. Please try --device help for a list of available devices.\n", g_device_name); | |
| exit(0); | |
| } | |
| } | |
| // Adapter automatic selection supported by sending NULL adapter to vaGetDisplayWin32 | |
| return vaGetDisplayWin32(device_found ? &adapter_luid : NULL); | |
| } | |
| static void | |
| va_close_display_win32(VADisplay va_dpy) | |
| { | |
| } | |
| static VAStatus | |
| va_put_surface_win32( | |
| VADisplay va_dpy, | |
| VASurfaceID surface, | |
| const VARectangle *src_rect, | |
| const VARectangle *dst_rect | |
| ) | |
| { | |
| return VA_STATUS_ERROR_OPERATION_FAILED; | |
| } | |
| #ifdef __cplusplus | |
| extern "C" { | |
| #endif | |
| extern const VADisplayHooks va_display_hooks_win32 = { | |
| "win32", | |
| va_open_display_win32, | |
| va_close_display_win32, | |
| va_put_surface_win32, | |
| }; | |
| #ifdef __cplusplus | |
| } | |
| #endif |