From: Elizabeth Figura <zfigura@codeweavers.com> --- dlls/wined3d/decoder.c | 29 ++++++++++++ dlls/wined3d/unixlib.h | 19 ++++++++ dlls/wined3d/va.c | 101 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 149 insertions(+) diff --git a/dlls/wined3d/decoder.c b/dlls/wined3d/decoder.c index 2cb1c5fdbfb..ce92568d642 100644 --- a/dlls/wined3d/decoder.c +++ b/dlls/wined3d/decoder.c @@ -1361,6 +1361,7 @@ const struct wined3d_decoder_ops wined3d_decoder_vk_ops = struct wined3d_decoder_va_vk { struct wined3d_decoder d; + uint64_t va_decoder; }; static struct wined3d_decoder_va_vk *wined3d_decoder_va_vk(struct wined3d_decoder *decoder) @@ -1388,6 +1389,29 @@ static void wined3d_decoder_va_vk_get_profiles(struct wined3d_adapter *adapter, WINE_UNIX_CALL(unix_va_get_profiles_vk, ¶ms); } +static void wined3d_decoder_va_vk_cs_init(void *object) +{ + struct wined3d_decoder_va_vk *decoder_va = object; + struct wined3d_adapter_vk *adapter_vk = wined3d_adapter_vk(decoder_va->d.device->adapter); + struct wined3d_device_vk *device_vk = wined3d_device_vk(decoder_va->d.device); + struct va_decoder_create_vk_params params; + HRESULT hr; + + params.desc = decoder_va->d.desc; + params.physical_device = (uintptr_t)adapter_vk->physical_device; + params.device = (uintptr_t)device_vk->vk_device; + params.width = decoder_va->d.width; + params.height = decoder_va->d.height; + + if (FAILED(hr = WINE_UNIX_CALL(unix_va_decoder_create_vk, ¶ms))) + { + ERR("Failed to initialize decoder, hr %#lx.\n", hr); + return; + } + + decoder_va->va_decoder = params.decoder; +} + static HRESULT wined3d_decoder_va_vk_create(struct wined3d_device *device, const struct wined3d_decoder_desc *desc, struct wined3d_decoder **decoder) { @@ -1410,6 +1434,8 @@ static HRESULT wined3d_decoder_va_vk_create(struct wined3d_device *device, return hr; } + wined3d_cs_init_object(device->cs, wined3d_decoder_va_vk_cs_init, object); + TRACE("Created decoder %p.\n", object); *decoder = &object->d; @@ -1419,9 +1445,12 @@ static HRESULT wined3d_decoder_va_vk_create(struct wined3d_device *device, static void wined3d_decoder_va_vk_destroy_object(void *object) { struct wined3d_decoder_va_vk *decoder_va = object; + struct va_decoder_destroy_vk_params params; TRACE("decoder_va %p.\n", decoder_va); + params.decoder = decoder_va->va_decoder; + WINE_UNIX_CALL(unix_va_decoder_destroy_vk, ¶ms); free(decoder_va); } diff --git a/dlls/wined3d/unixlib.h b/dlls/wined3d/unixlib.h index 45630418d08..9ed19aed67d 100644 --- a/dlls/wined3d/unixlib.h +++ b/dlls/wined3d/unixlib.h @@ -29,6 +29,8 @@ #include "wine/wined3d.h" #include "wine/unixlib.h" +#define VA_DECODER_SURFACE_COUNT 17 + struct va_get_profiles_vk_params { UINT64 physical_device; /* VkPhysicalDevice */ @@ -36,9 +38,26 @@ struct va_get_profiles_vk_params UINT64 profiles; /* GUID * */ }; +struct va_decoder_create_vk_params +{ + struct wined3d_decoder_desc desc; + UINT64 physical_device; /* VkPhysicalDevice */ + UINT64 device; /* VkDevice */ + UINT64 decoder; + unsigned int width; + unsigned int height; +}; + +struct va_decoder_destroy_vk_params +{ + UINT64 decoder; +}; + enum unix_funcs { unix_va_get_profiles_vk, + unix_va_decoder_create_vk, + unix_va_decoder_destroy_vk, }; #endif diff --git a/dlls/wined3d/va.c b/dlls/wined3d/va.c index bfb8d51522f..50a300be607 100644 --- a/dlls/wined3d/va.c +++ b/dlls/wined3d/va.c @@ -41,6 +41,15 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d); +struct va_decoder +{ + int drm_fd; + VADisplay display; + VAConfigID config; + VAContextID context; + VASurfaceID surfaces[VA_DECODER_SURFACE_COUNT]; +}; + static NTSTATUS open_va_display(UINT64 handle, VADisplay *ret_display, int *ret_fd) { VkPhysicalDeviceDrmPropertiesEXT drm_properties = {.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRM_PROPERTIES_EXT}; @@ -126,14 +135,106 @@ static NTSTATUS va_get_profiles_vk(void *args) return S_OK; } +static NTSTATUS va_decoder_create_vk(void *args) +{ + struct va_decoder_create_vk_params *params = args; + VASurfaceAttrib surface_attribs[1]; + VAConfigAttrib config_attribs[1]; + unsigned int format, fourcc; + struct va_decoder *decoder; + VAStatus status; + + if (params->desc.output_format == WINED3DFMT_NV12_PLANAR) + { + format = VA_RT_FORMAT_YUV420; + fourcc = VA_FOURCC_NV12; + } + else + { + FIXME("Unhandled output format %#x.\n", params->desc.output_format); + return E_NOTIMPL; + } + + if (!(decoder = calloc(1, sizeof(*decoder)))) + return E_OUTOFMEMORY; + + if ((status = open_va_display(params->physical_device, &decoder->display, &decoder->drm_fd))) + return status; + + config_attribs[0].type = VAConfigAttribRTFormat; + config_attribs[0].value = format; + + if ((status = vaCreateConfig(decoder->display, VAProfileH264High, VAEntrypointVLD, + config_attribs, ARRAY_SIZE(config_attribs), &decoder->config)) != VA_STATUS_SUCCESS) + { + ERR("Failed to create config, error %#x.\n", status); + vaTerminate(decoder->display); + close(decoder->drm_fd); + goto fail; + } + + surface_attribs[0].type = VASurfaceAttribPixelFormat; + surface_attribs[0].flags = VA_SURFACE_ATTRIB_SETTABLE; + surface_attribs[0].value.type = VAGenericValueTypeInteger; + surface_attribs[0].value.value.i = fourcc; + + if ((status = vaCreateSurfaces(decoder->display, format, params->width, params->height, decoder->surfaces, + VA_DECODER_SURFACE_COUNT, surface_attribs, ARRAY_SIZE(surface_attribs))) != VA_STATUS_SUCCESS) + { + ERR("Failed to create surfaces, error %#x.\n", status); + vaDestroyConfig(decoder->display, decoder->config); + vaTerminate(decoder->display); + close(decoder->drm_fd); + goto fail; + } + + if ((status = vaCreateContext(decoder->display, decoder->config, params->desc.width, params->desc.height, + VA_PROGRESSIVE, decoder->surfaces, ARRAY_SIZE(decoder->surfaces), &decoder->context)) != VA_STATUS_SUCCESS) + { + ERR("Failed to create context, error %#x.\n", status); + vaDestroySurfaces(decoder->display, decoder->surfaces, VA_DECODER_SURFACE_COUNT); + vaDestroyConfig(decoder->display, decoder->config); + vaTerminate(decoder->display); + close(decoder->drm_fd); + goto fail; + } + + TRACE("Created VA decoder %p.\n", decoder); + + params->decoder = (uintptr_t)decoder; + return S_OK; + +fail: + free(decoder); + return E_FAIL; +} + +static NTSTATUS va_decoder_destroy_vk(void *args) +{ + struct va_decoder_destroy_vk_params *params = args; + struct va_decoder *decoder = (struct va_decoder *)(uintptr_t)params->decoder; + + vaDestroyContext(decoder->display, decoder->context); + vaDestroySurfaces(decoder->display, decoder->surfaces, VA_DECODER_SURFACE_COUNT); + vaDestroyConfig(decoder->display, decoder->config); + vaTerminate(decoder->display); + close(decoder->drm_fd); + free(decoder); + return S_OK; +} + const unixlib_entry_t __wine_unix_call_funcs[] = { [unix_va_get_profiles_vk] = va_get_profiles_vk, + [unix_va_decoder_create_vk] = va_decoder_create_vk, + [unix_va_decoder_destroy_vk] = va_decoder_destroy_vk, }; const unixlib_entry_t __wine_unix_call_wow64_funcs[] = { [unix_va_get_profiles_vk] = va_get_profiles_vk, + [unix_va_decoder_create_vk] = va_decoder_create_vk, + [unix_va_decoder_destroy_vk] = va_decoder_destroy_vk, }; #endif -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11535