Skip to content

video/out/d3d11: add d3d11 composition mode support #16285

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions DOCS/interface-changes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ Interface changes
::

--- mpv 0.41.0 ---
- add `--d3d11-output-mode` enable use specific output mode for creating the D3D11 swapchain.
--- mpv 0.40.0 ---
- undeprecate list option suffixes that work with multiple items
- add `-del` to string list and keyvalue list options
Expand Down
8 changes: 8 additions & 0 deletions DOCS/man/options.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6124,6 +6124,14 @@ them.
support D3D11. While the extended GPU features will work with WARP, they
can be very slow.

``--d3d11-output-mode=<auto|window|composition>``
Use a specific output mode for creating the D3D11 swapchain. "composition" will
not create a window. If you want to use the D3D11 GPU backend in WinUI
applications, you need to set this to "composition". "window" will create a
window and use the DWM to present the video. "auto" is the same as "window".
After creating the swapchain, you can get the swapchain address(int64 type value) by getting the
``display-swapchain`` property.

``--d3d11-feature-level=<12_1|12_0|11_1|11_0|10_1|10_0|9_3|9_2|9_1>``
Select a specific feature level when using the D3D11 GPU backend. By
default, the highest available feature level is used. This option can be
Expand Down
16 changes: 15 additions & 1 deletion player/command.c
Original file line number Diff line number Diff line change
Expand Up @@ -2512,6 +2512,19 @@ static struct mp_image_params get_video_out_params(struct MPContext *mpctx)
return o_params;
}

static int mp_property_vo_display_swapchain(void *ctx, struct m_property *prop,
int action, void *arg)
{
MPContext *mpctx = ctx;
struct vo *vo = mpctx->video_out;
if (!vo)
return M_PROPERTY_UNAVAILABLE;

int64_t swapchain = (intptr_t)vo_get_display_swapchain(vo);

return m_property_int64_ro(action, arg, swapchain);
}

static int mp_property_vo_imgparams(void *ctx, struct m_property *prop,
int action, void *arg)
{
Expand Down Expand Up @@ -2834,7 +2847,7 @@ static int mp_property_display_names(void *ctx, struct m_property *prop,
{
MPContext *mpctx = ctx;
struct vo *vo = mpctx->video_out;
if (!vo)
if (!vo || vo->display_swapchain)
return M_PROPERTY_UNAVAILABLE;

switch (action) {
Expand Down Expand Up @@ -4318,6 +4331,7 @@ static const struct m_property mp_properties_base[] = {
{"deinterlace-active", mp_property_deinterlace},
{"idle-active", mp_property_idle},
{"window-id", mp_property_window_id},
{"display-swapchain", mp_property_vo_display_swapchain},

{"chapter-list", mp_property_list_chapters},
{"track-list", mp_property_list_tracks},
Expand Down
32 changes: 26 additions & 6 deletions video/out/d3d11/context.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ struct d3d11_opts {
int output_format;
int color_space;
bool exclusive_fs;
int output_mode;
};

#define OPT_BASE_STRUCT struct d3d11_opts
Expand Down Expand Up @@ -82,6 +83,12 @@ const struct m_sub_options d3d11_conf = {
.flags = UPDATE_VO,
},
{"d3d11-exclusive-fs", OPT_BOOL(exclusive_fs)},
{"d3d11-output-mode", OPT_CHOICE(output_mode,
{"auto", -1},
{"window", 0},
{"composition", 1}),
.flags = UPDATE_VO,
},
{0}
},
.defaults = &(const struct d3d11_opts) {
Expand All @@ -92,6 +99,7 @@ const struct m_sub_options d3d11_conf = {
.adapter_name = NULL,
.output_format = DXGI_FORMAT_UNKNOWN,
.color_space = -1,
.output_mode = -1,
},
.size = sizeof(struct d3d11_opts)
};
Expand Down Expand Up @@ -157,7 +165,8 @@ static bool resize(struct ra_ctx *ctx)

static bool d3d11_reconfig(struct ra_ctx *ctx)
{
vo_w32_config(ctx->vo);
if (!ctx->opts.composition)
vo_w32_config(ctx->vo);
return resize(ctx);
}

Expand Down Expand Up @@ -454,7 +463,7 @@ static int d3d11_control(struct ra_ctx *ctx, int *events, int request, void *arg
fullscreen_switch_needed = false;
}

ret = vo_w32_control(ctx->vo, events, request, arg);
ret = ctx->opts.composition ? VO_TRUE : vo_w32_control(ctx->vo, events, request, arg);

// if entering full screen, handle d3d11 after general windowing stuff
if (fullscreen_switch_needed && p->vo_opts->fullscreen) {
Expand All @@ -481,7 +490,11 @@ static void d3d11_uninit(struct ra_ctx *ctx)
if (ctx->ra)
ra_tex_free(ctx->ra, &p->backbuffer);
SAFE_RELEASE(p->swapchain);
vo_w32_uninit(ctx->vo);
if (!ctx->opts.composition) {
vo_w32_uninit(ctx->vo);
} else {
vo_w32_swapchain(ctx->vo, NULL);
}
SAFE_RELEASE(p->device);

// Destroy the RA last to prevent objects we hold from showing up in D3D's
Expand Down Expand Up @@ -534,10 +547,11 @@ static bool d3d11_init(struct ra_ctx *ctx)
if (!ctx->ra)
goto error;

if (!vo_w32_init(ctx->vo))
ctx->opts.composition = p->opts->output_mode == 1;
if (!ctx->opts.composition && !vo_w32_init(ctx->vo))
goto error;

if (ctx->opts.want_alpha)
if (!ctx->opts.composition && ctx->opts.want_alpha)
vo_w32_set_transparency(ctx->vo, ctx->opts.want_alpha);

UINT usage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_SHADER_INPUT;
Expand All @@ -548,7 +562,7 @@ static bool d3d11_init(struct ra_ctx *ctx)
}

struct d3d11_swapchain_opts scopts = {
.window = vo_w32_hwnd(ctx->vo),
.window = ctx->opts.composition ? NULL : vo_w32_hwnd(ctx->vo),
.width = ctx->vo->dwidth,
.height = ctx->vo->dheight,
.format = p->opts->output_format,
Expand All @@ -563,6 +577,9 @@ static bool d3d11_init(struct ra_ctx *ctx)
if (!mp_d3d11_create_swapchain(p->device, ctx->log, &scopts, &p->swapchain))
goto error;

if (ctx->opts.composition) {
vo_w32_swapchain(ctx->vo, p->swapchain);
}
return true;

error:
Expand All @@ -572,6 +589,9 @@ static bool d3d11_init(struct ra_ctx *ctx)

static void d3d11_update_render_opts(struct ra_ctx *ctx)
{
if (ctx->opts.composition) {
return;
}
vo_w32_set_transparency(ctx->vo, ctx->opts.want_alpha);
}

Expand Down
1 change: 1 addition & 0 deletions video/out/gpu/context.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ struct ra_ctx_opts {
bool want_alpha; // create an alpha framebuffer if possible
bool debug; // enable debugging layers/callbacks etc.
bool probing; // the backend was auto-probed
bool composition; // enable swapchain composition
struct m_obj_settings *context_list; // list of `ra_ctx_fns.name` to probe
struct m_obj_settings *context_type_list; // list of `ra_ctx_fns.type` to probe
};
Expand Down
8 changes: 7 additions & 1 deletion video/out/gpu/d3d11_helpers.c
Original file line number Diff line number Diff line change
Expand Up @@ -674,8 +674,14 @@ static HRESULT create_swapchain_1_2(ID3D11Device *dev, IDXGIFactory2 *factory,
desc.BufferCount = 1;
}

hr = IDXGIFactory2_CreateSwapChainForHwnd(factory, (IUnknown*)dev,
if (opts->window == NULL) {
desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
hr = IDXGIFactory2_CreateSwapChainForComposition(factory, (IUnknown*)dev,
&desc, NULL, &swapchain1);
} else {
hr = IDXGIFactory2_CreateSwapChainForHwnd(factory, (IUnknown*)dev,
opts->window, &desc, NULL, NULL, &swapchain1);
}
if (FAILED(hr))
goto done;
hr = IDXGISwapChain1_QueryInterface(swapchain1, &IID_IDXGISwapChain,
Expand Down
5 changes: 5 additions & 0 deletions video/out/vo.c
Original file line number Diff line number Diff line change
Expand Up @@ -1417,6 +1417,11 @@ double vo_get_display_fps(struct vo *vo)
return res;
}

void * vo_get_display_swapchain(struct vo *vo)
{
return vo->display_swapchain;
}

// Set specific event flags, and wakeup the playback core if needed.
// vo_query_and_reset_events() can retrieve the events again.
void vo_event(struct vo *vo, int event)
Expand Down
4 changes: 4 additions & 0 deletions video/out/vo.h
Original file line number Diff line number Diff line change
Expand Up @@ -525,6 +525,9 @@ struct vo {

// current GPU context (--vo=gpu and --vo=gpu-next only)
const char *context_name;

// composition swapchain (--d3d11-output-mode=composition only)
void *display_swapchain;
};

struct mpv_global;
Expand Down Expand Up @@ -559,6 +562,7 @@ double vo_get_vsync_interval(struct vo *vo);
double vo_get_estimated_vsync_interval(struct vo *vo);
double vo_get_estimated_vsync_jitter(struct vo *vo);
double vo_get_display_fps(struct vo *vo);
void * vo_get_display_swapchain(struct vo *vo);
double vo_get_delay(struct vo *vo);
void vo_discard_timing_info(struct vo *vo);
struct vo_frame *vo_get_current_vo_frame(struct vo *vo);
Expand Down
5 changes: 5 additions & 0 deletions video/out/w32_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -2499,6 +2499,11 @@ HWND vo_w32_hwnd(struct vo *vo)
return w32->window; // immutable, so no synchronization needed
}

void vo_w32_swapchain(struct vo *vo, void *swapchain)
{
vo->display_swapchain = swapchain;
}

void vo_w32_run_on_thread(struct vo *vo, void (*cb)(void *ctx), void *ctx)
{
struct vo_w32_state *w32 = vo->w32;
Expand Down
1 change: 1 addition & 0 deletions video/out/w32_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ void vo_w32_uninit(struct vo *vo);
int vo_w32_control(struct vo *vo, int *events, int request, void *arg);
void vo_w32_config(struct vo *vo);
HWND vo_w32_hwnd(struct vo *vo);
void vo_w32_swapchain(struct vo *vo, void *swapchain);
void vo_w32_run_on_thread(struct vo *vo, void (*cb)(void *ctx), void *ctx);
void vo_w32_set_transparency(struct vo *vo, bool enable);

Expand Down