diff options
Diffstat (limited to 'video')
41 files changed, 736 insertions, 382 deletions
diff --git a/video/filter/vf_gpu.c b/video/filter/vf_gpu.c index e19faaef42..d2ba990a00 100644 --- a/video/filter/vf_gpu.c +++ b/video/filter/vf_gpu.c @@ -24,95 +24,49 @@ #include "options/options.h" #include "video/out/aspect.h" #include "video/out/gpu/video.h" -#include "video/out/opengl/egl_helpers.h" -#include "video/out/opengl/ra_gl.h" - -struct offscreen_ctx { - struct mp_log *log; - struct ra *ra; - void *priv; - - void (*set_context)(struct offscreen_ctx *ctx, bool enable); -}; - -struct gl_offscreen_ctx { - GL gl; - EGLDisplay egl_display; - EGLContext egl_context; +#include "video/filter/vf_gpu.h" + +extern const struct offscreen_context offscreen_vk; +extern const struct offscreen_context offscreen_egl; + +static const struct offscreen_context *contexts[] = { +#if HAVE_EGL + &offscreen_egl, +#endif +#if HAVE_VULKAN + &offscreen_vk, +#endif }; -static void gl_ctx_destroy(void *p) +static inline OPT_STRING_VALIDATE_FUNC(offscreen_ctx_validate_api) { - struct offscreen_ctx *ctx = p; - struct gl_offscreen_ctx *gl = ctx->priv; - - ra_free(&ctx->ra); - - if (gl->egl_context) - eglDestroyContext(gl->egl_display, gl->egl_context); + struct bstr param = bstr0(*value); + for (int i = 0; i < MP_ARRAY_SIZE(contexts); i++) { + if (bstr_equals0(param, contexts[i]->api)) + return 1; + } + return M_OPT_INVALID; } -static void gl_ctx_set_context(struct offscreen_ctx *ctx, bool enable) +static int offscreen_ctx_api_help(struct mp_log *log, const struct m_option *opt, + struct bstr name) { - struct gl_offscreen_ctx *gl = ctx->priv; - EGLContext c = enable ? gl->egl_context : EGL_NO_CONTEXT; - - if (!eglMakeCurrent(gl->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, c)) - MP_ERR(ctx, "Could not make EGL context current.\n"); + mp_info(log, "GPU APIs (offscreen contexts):\n"); + for (int i = 0; i < MP_ARRAY_SIZE(contexts); i++) + mp_info(log, " %s\n", contexts[i]->api); + return M_OPT_EXIT; } -static struct offscreen_ctx *gl_offscreen_ctx_create(struct mpv_global *global, - struct mp_log *log) +static struct offscreen_ctx *offscreen_ctx_create(struct mpv_global *global, + struct mp_log *log, + const char *api) { - struct offscreen_ctx *ctx = talloc_zero(NULL, struct offscreen_ctx); - struct gl_offscreen_ctx *gl = talloc_zero(ctx, struct gl_offscreen_ctx); - talloc_set_destructor(ctx, gl_ctx_destroy); - *ctx = (struct offscreen_ctx){ - .log = log, - .priv = gl, - .set_context = gl_ctx_set_context, - }; - - // This appears to work with Mesa. EGL 1.5 doesn't specify what a "default - // display" is at all. - gl->egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY); - if (!eglInitialize(gl->egl_display, NULL, NULL)) { - MP_ERR(ctx, "Could not initialize EGL.\n"); - goto error; + for (int i = 0; i < MP_ARRAY_SIZE(contexts); i++) { + if (api && strcmp(contexts[i]->api, api) != 0) + continue; + mp_info(log, "Creating offscreen GPU context '%s'\n", contexts[i]->api); + return contexts[i]->offscreen_ctx_create(global, log); } - - // Unfortunately, mpegl_create_context() is entangled with ra_ctx. - // Fortunately, it does not need much, and we can provide a stub. - struct ra_ctx ractx = { - .log = ctx->log, - .global = global, - }; - EGLConfig config; - if (!mpegl_create_context(&ractx, gl->egl_display, &gl->egl_context, &config)) - { - MP_ERR(ctx, "Could not create EGL context.\n"); - goto error; - } - - if (!eglMakeCurrent(gl->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, - gl->egl_context)) - { - MP_ERR(ctx, "Could not make EGL context current.\n"); - goto error; - } - - mpegl_load_functions(&gl->gl, ctx->log); - ctx->ra = ra_create_gl(&gl->gl, ctx->log); - - if (!ctx->ra) - goto error; - - gl_ctx_set_context(ctx, false); - - return ctx; - -error: - talloc_free(ctx); return NULL; } @@ -124,6 +78,7 @@ static void offscreen_ctx_set_current(struct offscreen_ctx *ctx, bool enable) struct gpu_opts { int w, h; + char *api; }; struct priv { @@ -327,7 +282,7 @@ static struct mp_filter *gpu_create(struct mp_filter *parent, void *options) priv->vo_opts_cache = m_config_cache_alloc(f, f->global, &vo_sub_opts); priv->vo_opts = priv->vo_opts_cache->opts; - priv->ctx = gl_offscreen_ctx_create(f->global, f->log); + priv->ctx = offscreen_ctx_create(f->global, f->log, priv->opts->api); if (!priv->ctx) { MP_FATAL(f, "Could not create offscreen ra context.\n"); goto error; @@ -368,6 +323,8 @@ const struct mp_user_filter_entry vf_gpu = { .options = (const struct m_option[]){ {"w", OPT_INT(w)}, {"h", OPT_INT(h)}, + {"api", OPT_STRING_VALIDATE(api, offscreen_ctx_validate_api), + .help = offscreen_ctx_api_help}, {0} }, }, diff --git a/video/filter/vf_gpu.h b/video/filter/vf_gpu.h new file mode 100644 index 0000000000..2cc9a16eea --- /dev/null +++ b/video/filter/vf_gpu.h @@ -0,0 +1,35 @@ +/* + * This file is part of mpv. + * + * mpv is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * mpv is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with mpv. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once + +#include "common/common.h" +#include "common/global.h" + +struct offscreen_ctx { + struct mp_log *log; + struct ra *ra; + void *priv; + + void (*set_context)(struct offscreen_ctx *ctx, bool enable); +}; + +struct offscreen_context { + const char *api; + struct offscreen_ctx *(*offscreen_ctx_create)(struct mpv_global *, + struct mp_log *); +}; diff --git a/video/filter/vf_gpu_egl.c b/video/filter/vf_gpu_egl.c new file mode 100644 index 0000000000..cd90a6e06a --- /dev/null +++ b/video/filter/vf_gpu_egl.c @@ -0,0 +1,107 @@ +/* + * This file is part of mpv. + * + * mpv is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * mpv is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with mpv. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "common/common.h" +#include "video/filter/vf_gpu.h" +#include "video/out/opengl/egl_helpers.h" +#include "video/out/opengl/ra_gl.h" + +struct gl_offscreen_ctx { + GL gl; + EGLDisplay egl_display; + EGLContext egl_context; +}; + +static void gl_ctx_destroy(void *p) +{ + struct offscreen_ctx *ctx = p; + struct gl_offscreen_ctx *gl = ctx->priv; + + ra_free(&ctx->ra); + + if (gl->egl_context) + eglDestroyContext(gl->egl_display, gl->egl_context); +} + +static void gl_ctx_set_context(struct offscreen_ctx *ctx, bool enable) +{ + struct gl_offscreen_ctx *gl = ctx->priv; + EGLContext c = enable ? gl->egl_context : EGL_NO_CONTEXT; + + if (!eglMakeCurrent(gl->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, c)) + MP_ERR(ctx, "Could not make EGL context current.\n"); +} + +static struct offscreen_ctx *gl_offscreen_ctx_create(struct mpv_global *global, + struct mp_log *log) +{ + struct offscreen_ctx *ctx = talloc(NULL, struct offscreen_ctx); + struct gl_offscreen_ctx *gl = talloc_zero(ctx, struct gl_offscreen_ctx); + talloc_set_destructor(ctx, gl_ctx_destroy); + *ctx = (struct offscreen_ctx){ + .log = log, + .priv = gl, + .set_context = gl_ctx_set_context, + }; + + // This appears to work with Mesa. EGL 1.5 doesn't specify what a "default + // display" is at all. + gl->egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY); + if (!eglInitialize(gl->egl_display, NULL, NULL)) { + MP_ERR(ctx, "Could not initialize EGL.\n"); + goto error; + } + + // Unfortunately, mpegl_create_context() is entangled with ra_ctx. + // Fortunately, it does not need much, and we can provide a stub. + struct ra_ctx ractx = { + .log = ctx->log, + .global = global, + }; + EGLConfig config; + if (!mpegl_create_context(&ractx, gl->egl_display, &gl->egl_context, &config)) + { + MP_ERR(ctx, "Could not create EGL context.\n"); + goto error; + } + + if (!eglMakeCurrent(gl->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, + gl->egl_context)) + { + MP_ERR(ctx, "Could not make EGL context current.\n"); + goto error; + } + + mpegl_load_functions(&gl->gl, ctx->log); + ctx->ra = ra_create_gl(&gl->gl, ctx->log); + + if (!ctx->ra) + goto error; + + gl_ctx_set_context(ctx, false); + + return ctx; + +error: + talloc_free(ctx); + return NULL; +} + +const struct offscreen_context offscreen_egl = { + .api = "egl", + .offscreen_ctx_create = gl_offscreen_ctx_create +}; diff --git a/video/filter/vf_gpu_vulkan.c b/video/filter/vf_gpu_vulkan.c new file mode 100644 index 0000000000..81a84becfa --- /dev/null +++ b/video/filter/vf_gpu_vulkan.c @@ -0,0 +1,115 @@ +/* + * This file is part of mpv. + * + * mpv is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * mpv is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with mpv. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "options/m_config.h" +#include "video/filter/vf_gpu.h" +#include "video/out/placebo/ra_pl.h" +#include "video/out/placebo/utils.h" +#include "video/out/vulkan/context.h" +#include "video/out/vulkan/utils.h" + +struct vk_offscreen_ctx { + struct ra_ctx *ractx; + struct mpvk_ctx *vk; +}; + +extern const struct m_sub_options vulkan_conf; + +static void vk_ctx_destroy(void *p) +{ + struct offscreen_ctx *ctx = p; + struct vk_offscreen_ctx *vkctx = ctx->priv; + struct ra_ctx *ractx = vkctx->ractx; + struct mpvk_ctx *vk = vkctx->vk; + + if (ractx->ra) { + pl_gpu_finish(vk->gpu); + ractx->ra->fns->destroy(ctx->ra); + ractx->ra = NULL; + ctx->ra = NULL; + } + + vk->gpu = NULL; + pl_vulkan_destroy(&vk->vulkan); + mpvk_uninit(vk); + talloc_free(vk); + talloc_free(ractx); +} + +static struct offscreen_ctx *vk_offscreen_ctx_create(struct mpv_global *global, + struct mp_log *log) +{ + struct offscreen_ctx *ctx = talloc(NULL, struct offscreen_ctx); + talloc_set_destructor(ctx, vk_ctx_destroy); + *ctx = (struct offscreen_ctx){ + .log = log, + }; + + struct ra_ctx *ractx = talloc_zero(ctx, struct ra_ctx); + struct mpvk_ctx *vk = talloc_zero(ctx, struct mpvk_ctx); + ractx->log = ctx->log; + ractx->global = global; + + vk->pllog = mppl_log_create(ctx, log); + if (!vk->pllog) + goto error; + + struct pl_vk_inst_params pl_vk_params = {0}; + struct ra_ctx_opts *ctx_opts = mp_get_config_group(NULL, global, &ra_ctx_conf); + pl_vk_params.debug = ctx_opts->debug; + talloc_free(ctx_opts); + mppl_log_set_probing(vk->pllog, true); + vk->vkinst = pl_vk_inst_create(vk->pllog, &pl_vk_params); + mppl_log_set_probing(vk->pllog, false); + if (!vk->vkinst) + goto error; + + struct vulkan_opts *vk_opts = mp_get_config_group(NULL, global, &vulkan_conf); + vk->vulkan = mppl_create_vulkan(vk_opts, vk->vkinst, vk->pllog, NULL); + talloc_free(vk_opts); + if (!vk->vulkan) + goto error; + + vk->gpu = vk->vulkan->gpu; + ractx->ra = ra_create_pl(vk->gpu, ractx->log); + if (!ractx->ra) + goto error; + + struct vk_offscreen_ctx *vkctx = talloc(ctx, struct vk_offscreen_ctx); + *vkctx = (struct vk_offscreen_ctx){ + .ractx = ractx, + .vk = vk + }; + + ctx->ra = ractx->ra; + ctx->priv = vkctx; + + return ctx; + +error: + pl_vulkan_destroy(&vk->vulkan); + mpvk_uninit(vk); + talloc_free(vk); + talloc_free(ractx); + talloc_free(ctx); + return NULL; +} + +const struct offscreen_context offscreen_vk = { + .api = "vulkan", + .offscreen_ctx_create = vk_offscreen_ctx_create +}; diff --git a/video/out/cocoa_cb_common.swift b/video/out/cocoa_cb_common.swift index 9f32ed651f..38c47a19a2 100644 --- a/video/out/cocoa_cb_common.swift +++ b/video/out/cocoa_cb_common.swift @@ -87,8 +87,7 @@ class CocoaCB: Common, EventSubscriber { } func updateWindowSize(_ vo: UnsafeMutablePointer<vo>) { - guard let targetScreen = getTargetScreen(forFullscreen: false) ?? NSScreen.main else - { + guard let targetScreen = getTargetScreen(forFullscreen: false) ?? NSScreen.main else { log.warning("Couldn't update Window size, no Screen available") return } @@ -102,11 +101,10 @@ class CocoaCB: Common, EventSubscriber { } override func displayLinkCallback(_ displayLink: CVDisplayLink, - _ inNow: UnsafePointer<CVTimeStamp>, - _ inOutputTime: UnsafePointer<CVTimeStamp>, - _ flagsIn: CVOptionFlags, - _ flagsOut: UnsafeMutablePointer<CVOptionFlags>) -> CVReturn - { + _ inNow: UnsafePointer<CVTimeStamp>, + _ inOutputTime: UnsafePointer<CVTimeStamp>, + _ flagsIn: CVOptionFlags, + _ flagsOut: UnsafeMutablePointer<CVOptionFlags>) -> CVReturn { libmpv.reportRenderFlip() return kCVReturnSuccess } @@ -178,10 +176,9 @@ class CocoaCB: Common, EventSubscriber { } override func control(_ vo: UnsafeMutablePointer<vo>, - events: UnsafeMutablePointer<Int32>, - request: UInt32, - data: UnsafeMutableRawPointer?) -> Int32 - { + events: UnsafeMutablePointer<Int32>, + request: UInt32, + data: UnsafeMutableRawPointer?) -> Int32 { switch mp_voctrl(request) { case VOCTRL_PREINIT: DispatchQueue.main.sync { self.preinit(vo) } diff --git a/video/out/d3d11/context.c b/video/out/d3d11/context.c index c563b5fa15..f183ae8be5 100644 --- a/video/out/d3d11/context.c +++ b/video/out/d3d11/context.c @@ -547,6 +547,7 @@ bool ra_d3d11_ctx_prefer_8bit_output_format(struct ra_ctx *ra) const struct ra_ctx_fns ra_ctx_d3d11 = { .type = "d3d11", .name = "d3d11", + .description = "Direct3D 11", .reconfig = d3d11_reconfig, .control = d3d11_control, .update_render_opts = d3d11_update_render_opts, diff --git a/video/out/d3d11/ra_d3d11.c b/video/out/d3d11/ra_d3d11.c index 84fd004adc..4438b2083c 100644 --- a/video/out/d3d11/ra_d3d11.c +++ b/video/out/d3d11/ra_d3d11.c @@ -13,6 +13,7 @@ #include "osdep/windows_utils.h" #include "video/out/gpu/spirv.h" #include "video/out/gpu/utils.h" +#include "video/out/gpu/d3d11_helpers.h" #include "ra_d3d11.h" @@ -43,9 +44,11 @@ struct ra_d3d11 { struct dll_version d3d_compiler_ver; +#if HAVE_DXGI_DEBUG // Debug interfaces (--gpu-debug) - ID3D11Debug *debug; - ID3D11InfoQueue *iqueue; + IDXGIDebug *debug; + IDXGIInfoQueue *iqueue; +#endif // Device capabilities D3D_FEATURE_LEVEL fl; @@ -2094,24 +2097,25 @@ static uint64_t timer_stop(struct ra *ra, ra_timer *ratimer) return timer->result; } -static int map_msg_severity(D3D11_MESSAGE_SEVERITY sev) +#if HAVE_DXGI_DEBUG +static int map_msg_severity(DXGI_INFO_QUEUE_MESSAGE_SEVERITY sev) { switch (sev) { - case D3D11_MESSAGE_SEVERITY_CORRUPTION: + case DXGI_INFO_QUEUE_MESSAGE_SEVERITY_CORRUPTION: return MSGL_FATAL; - case D3D11_MESSAGE_SEVERITY_ERROR: + case DXGI_INFO_QUEUE_MESSAGE_SEVERITY_ERROR: return MSGL_ERR; - case D3D11_MESSAGE_SEVERITY_WARNING: + case DXGI_INFO_QUEUE_MESSAGE_SEVERITY_WARNING: return MSGL_WARN; default: - case D3D11_MESSAGE_SEVERITY_INFO: - case D3D11_MESSAGE_SEVERITY_MESSAGE: + case DXGI_INFO_QUEUE_MESSAGE_SEVERITY_INFO: + case DXGI_INFO_QUEUE_MESSAGE_SEVERITY_MESSAGE: return MSGL_DEBUG; } } static int map_msg_severity_by_id(D3D11_MESSAGE_ID id, - D3D11_MESSAGE_SEVERITY sev) + DXGI_INFO_QUEUE_MESSAGE_SEVERITY sev) { switch (id) { // These are normal. The RA timer queue habitually reuses timer objects @@ -2168,9 +2172,11 @@ static int map_msg_severity_by_id(D3D11_MESSAGE_ID id, return map_msg_severity(sev); } } +#endif static void debug_marker(struct ra *ra, const char *msg) { +#if HAVE_DXGI_DEBUG struct ra_d3d11 *p = ra->priv; void *talloc_ctx = talloc_new(NULL); HRESULT hr; @@ -2180,33 +2186,38 @@ static void debug_marker(struct ra *ra, const char *msg) // Copy debug-layer messages to mpv's log output bool printed_header = false; - uint64_t messages = ID3D11InfoQueue_GetNumStoredMessages(p->iqueue); + uint64_t messages = IDXGIInfoQueue_GetNumStoredMessages(p->iqueue, + DXGI_DEBUG_ALL); for (uint64_t i = 0; i < messages; i++) { SIZE_T len; - hr = ID3D11InfoQueue_GetMessage(p->iqueue, i, NULL, &len); + hr = IDXGIInfoQueue_GetMessage(p->iqueue, DXGI_DEBUG_ALL, i, NULL, &len); if (FAILED(hr) || !len) goto done; - D3D11_MESSAGE *d3dmsg = talloc_size(talloc_ctx, len); - hr = ID3D11InfoQueue_GetMessage(p->iqueue, i, d3dmsg, &len); + DXGI_INFO_QUEUE_MESSAGE *dxgimsg = talloc_size(talloc_ctx, len); + hr = IDXGIInfoQueue_GetMessage(p->iqueue, DXGI_DEBUG_ALL, i, dxgimsg, &len); if (FAILED(hr)) goto done; - int msgl = map_msg_severity_by_id(d3dmsg->ID, d3dmsg->Severity); + int msgl = IsEqualGUID(&dxgimsg->Producer, &DXGI_DEBUG_D3D11) + ? map_msg_severity_by_id(dxgimsg->ID, dxgimsg->Severity) + : map_msg_severity(dxgimsg->Severity); + if (mp_msg_test(ra->log, msgl)) { if (!printed_header) MP_INFO(ra, "%s:\n", msg); printed_header = true; - MP_MSG(ra, msgl, "%d: %.*s\n", (int)d3dmsg->ID, - (int)d3dmsg->DescriptionByteLength, d3dmsg->pDescription); - talloc_free(d3dmsg); + MP_MSG(ra, msgl, "%d: %.*s\n", (int)dxgimsg->ID, + (int)dxgimsg->DescriptionByteLength, dxgimsg->pDescription); + talloc_free(dxgimsg); } } - ID3D11InfoQueue_ClearStoredMessages(p->iqueue); + IDXGIInfoQueue_ClearStoredMessages(p->iqueue, DXGI_DEBUG_ALL); done: talloc_free(talloc_ctx); +#endif } static void destroy(struct ra *ra) @@ -2237,16 +2248,18 @@ static void destroy(struct ra *ra) } SAFE_RELEASE(p->ctx); +#if HAVE_DXGI_DEBUG if (p->debug) { // Report any leaked objects debug_marker(ra, "after destroy"); - ID3D11Debug_ReportLiveDeviceObjects(p->debug, D3D11_RLDO_DETAIL); + IDXGIDebug_ReportLiveObjects(p->debug, DXGI_DEBUG_ALL, DXGI_DEBUG_RLO_DETAIL); debug_marker(ra, "after leak check"); - ID3D11Debug_ReportLiveDeviceObjects(p->debug, D3D11_RLDO_SUMMARY); + IDXGIDebug_ReportLiveObjects(p->debug, DXGI_DEBUG_ALL, DXGI_DEBUG_RLO_SUMMARY); debug_marker(ra, "after leak summary"); } SAFE_RELEASE(p->debug); SAFE_RELEASE(p->iqueue); +#endif talloc_free(ra); } @@ -2280,34 +2293,6 @@ void ra_d3d11_flush(struct ra *ra) ID3D11DeviceContext_Flush(p->ctx); } -static void init_debug_layer(struct ra *ra) -{ - struct ra_d3d11 *p = ra->priv; - HRESULT hr; - - hr = ID3D11Device_QueryInterface(p->dev, &IID_ID3D11Debug, - (void**)&p->debug); - if (FAILED(hr)) { - MP_ERR(ra, "Failed to get debug device: %s\n", mp_HRESULT_to_str(hr)); - return; - } - - hr = ID3D11Device_QueryInterface(p->dev, &IID_ID3D11InfoQueue, - (void**)&p->iqueue); - if (FAILED(hr)) { - MP_ERR(ra, "Failed to get info queue: %s\n", mp_HRESULT_to_str(hr)); - return; - } - - // Store an unlimited amount of messages in the buffer. This is fine - // because we flush stored messages regularly (in debug_marker.) - ID3D11InfoQueue_SetMessageCountLimit(p->iqueue, -1); - - // Push empty filter to get everything - D3D11_INFO_QUEUE_FILTER filter = {0}; - ID3D11InfoQueue_PushStorageFilter(p->iqueue, &filter); -} - static struct dll_version get_dll_version(HMODULE dll) { void *ctx = talloc_new(NULL); @@ -2466,8 +2451,10 @@ struct ra *ra_d3d11_create(ID3D11Device *dev, struct mp_log *log, p->max_uavs = D3D11_PS_CS_UAV_REGISTER_COUNT; } +#if HAVE_DXGI_DEBUG if (ID3D11Device_GetCreationFlags(p->dev) & D3D11_CREATE_DEVICE_DEBUG) - init_debug_layer(ra); + mp_d3d11_get_debug_interfaces(ra->log, &p->debug, &p->iqueue); +#endif // Some level 9_x devices don't have timestamp queries hr = ID3D11Device_CreateQuery(p->dev, @@ -2481,9 +2468,11 @@ struct ra *ra_d3d11_create(ID3D11Device *dev, struct mp_log *log, // https://msdn.microsoft.com/en-us/library/windows/desktop/ff476874.aspx find_max_texture_dimension(ra); +#if HAVE_DXGI_DEBUG // Ignore any messages during find_max_texture_dimension if (p->iqueue) - ID3D11InfoQueue_ClearStoredMessages(p->iqueue); + IDXGIInfoQueue_ClearStoredMessages(p->iqueue, DXGI_DEBUG_ALL); +#endif MP_VERBOSE(ra, "Maximum Texture2D size: %dx%d\n", ra->max_texture_wh, ra->max_texture_wh); diff --git a/video/out/gpu/context.c b/video/out/gpu/context.c index 88d4f4232d..3202729741 100644 --- a/video/out/gpu/context.c +++ b/video/out/gpu/context.c @@ -57,7 +57,27 @@ extern const struct ra_ctx_fns ra_ctx_d3d11; /* No API */ extern const struct ra_ctx_fns ra_ctx_wldmabuf; +/* Autoprobe dummy. Always fails to create. */ +static bool dummy_init(struct ra_ctx *ctx) +{ + return false; +} + +static void dummy_uninit(struct ra_ctx *ctx) +{ +} + +static const struct ra_ctx_fns ra_ctx_dummy = { + .type = "auto", + .name = "auto", + .description = "Auto detect", + .init = dummy_init, + .uninit = dummy_uninit, +}; + static const struct ra_ctx_fns *contexts[] = { + &ra_ctx_dummy, +// Direct3D contexts: #if HAVE_D3D11 &ra_ctx_d3d11, #endif @@ -110,21 +130,53 @@ static const struct ra_ctx_fns *contexts[] = { &ra_ctx_vulkan_mac, #endif #endif +}; +static const struct ra_ctx_fns *no_api_contexts[] = { + &ra_ctx_dummy, /* No API contexts: */ #if HAVE_DMABUF_WAYLAND &ra_ctx_wldmabuf, #endif }; +static bool get_desc(struct m_obj_desc *dst, int index) +{ + if (index >= MP_ARRAY_SIZE(contexts)) + return false; |