From: Elizabeth Figura <zfigura@codeweavers.com> --- dlls/wined3d/decoder.c | 29 +++++++++++ dlls/wined3d/unixlib.h | 19 +++++++ dlls/wined3d/va.c | 111 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 159 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 949ca22381e..f855d81855c 100644 --- a/dlls/wined3d/va.c +++ b/dlls/wined3d/va.c @@ -46,6 +46,12 @@ struct va_context { void *libva_handle, *libva_drm_handle; #define MAKE_FUNCPTR(f) typeof(f) *f + MAKE_FUNCPTR(vaCreateConfig); + MAKE_FUNCPTR(vaCreateContext); + MAKE_FUNCPTR(vaCreateSurfaces); + MAKE_FUNCPTR(vaDestroyConfig); + MAKE_FUNCPTR(vaDestroyContext); + MAKE_FUNCPTR(vaDestroySurfaces); MAKE_FUNCPTR(vaGetDisplayDRM); MAKE_FUNCPTR(vaInitialize); MAKE_FUNCPTR(vaMaxNumProfiles); @@ -57,6 +63,14 @@ struct va_context int fd; }; +struct va_decoder +{ + struct va_context ctx; + VAConfigID config; + VAContextID context; + VASurfaceID surfaces[VA_DECODER_SURFACE_COUNT]; +}; + static void close_va_display(struct va_context *ctx) { if (ctx->fd != -1) @@ -95,6 +109,12 @@ static NTSTATUS open_va_display(UINT64 handle, struct va_context *ctx) ERR("Failed to load function %s.\n", #f); \ goto fail; \ } + LOAD_FUNCPTR(vaCreateConfig); + LOAD_FUNCPTR(vaCreateContext); + LOAD_FUNCPTR(vaCreateSurfaces); + LOAD_FUNCPTR(vaDestroyConfig); + LOAD_FUNCPTR(vaDestroyContext); + LOAD_FUNCPTR(vaDestroySurfaces); LOAD_FUNCPTR(vaInitialize); LOAD_FUNCPTR(vaMaxNumProfiles); LOAD_FUNCPTR(vaQueryConfigProfiles); @@ -178,14 +198,105 @@ 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; + struct va_context *ctx; + 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; + ctx = &decoder->ctx; + + if ((status = open_va_display(params->physical_device, ctx))) + return status; + + config_attribs[0].type = VAConfigAttribRTFormat; + config_attribs[0].value = format; + + if ((status = ctx->vaCreateConfig(ctx->display, VAProfileH264High, VAEntrypointVLD, + config_attribs, ARRAY_SIZE(config_attribs), &decoder->config)) != VA_STATUS_SUCCESS) + { + ERR("Failed to create config, error %#x.\n", status); + close_va_display(ctx); + 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 = ctx->vaCreateSurfaces(ctx->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); + ctx->vaDestroyConfig(ctx->display, decoder->config); + close_va_display(ctx); + goto fail; + } + + if ((status = ctx->vaCreateContext(ctx->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); + ctx->vaDestroySurfaces(ctx->display, decoder->surfaces, VA_DECODER_SURFACE_COUNT); + ctx->vaDestroyConfig(ctx->display, decoder->config); + close_va_display(ctx); + 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; + struct va_context *ctx = &decoder->ctx; + + ctx->vaDestroyContext(ctx->display, decoder->context); + ctx->vaDestroySurfaces(ctx->display, decoder->surfaces, VA_DECODER_SURFACE_COUNT); + ctx->vaDestroyConfig(ctx->display, decoder->config); + close_va_display(ctx); + 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