Skip to content

Commit 7b148df

Browse files
committed
video/out/d3d11: add d3d11 composition mode support
1 parent d702e5f commit 7b148df

File tree

10 files changed

+73
-8
lines changed

10 files changed

+73
-8
lines changed

DOCS/interface-changes.rst

+1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ Interface changes
3131
::
3232

3333
--- mpv 0.41.0 ---
34+
- add `--d3d11-output-mode` enable use specific output mode for creating the D3D11 swapchain.
3435
--- mpv 0.40.0 ---
3536
- undeprecate list option suffixes that work with multiple items
3637
- add `-del` to string list and keyvalue list options

DOCS/man/options.rst

+8
Original file line numberDiff line numberDiff line change
@@ -6124,6 +6124,14 @@ them.
61246124
support D3D11. While the extended GPU features will work with WARP, they
61256125
can be very slow.
61266126

6127+
``--d3d11-output-mode=<auto|window|composition>``
6128+
Use a specific output mode for creating the D3D11 swapchain. "composition" will
6129+
not create a window. If you want to use the D3D11 GPU backend in WinUI
6130+
applications, you need to set this to "composition". "window" will create a
6131+
window and use the DWM to present the video. "auto" is the same as "window".
6132+
After creating the swapchain, you can get the swapchain address(int64 type value) by getting the
6133+
``display-swapchain`` property.
6134+
61276135
``--d3d11-feature-level=<12_1|12_0|11_1|11_0|10_1|10_0|9_3|9_2|9_1>``
61286136
Select a specific feature level when using the D3D11 GPU backend. By
61296137
default, the highest available feature level is used. This option can be

player/command.c

+15-1
Original file line numberDiff line numberDiff line change
@@ -2512,6 +2512,19 @@ static struct mp_image_params get_video_out_params(struct MPContext *mpctx)
25122512
return o_params;
25132513
}
25142514

2515+
static int mp_property_vo_display_swapchain(void *ctx, struct m_property *prop,
2516+
int action, void *arg)
2517+
{
2518+
MPContext *mpctx = ctx;
2519+
struct vo *vo = mpctx->video_out;
2520+
if (!vo)
2521+
return M_PROPERTY_UNAVAILABLE;
2522+
2523+
int64_t swapchain = (intptr_t)vo_get_display_swapchain(vo);
2524+
2525+
return m_property_int64_ro(action, arg, swapchain);
2526+
}
2527+
25152528
static int mp_property_vo_imgparams(void *ctx, struct m_property *prop,
25162529
int action, void *arg)
25172530
{
@@ -2834,7 +2847,7 @@ static int mp_property_display_names(void *ctx, struct m_property *prop,
28342847
{
28352848
MPContext *mpctx = ctx;
28362849
struct vo *vo = mpctx->video_out;
2837-
if (!vo)
2850+
if (!vo || vo->display_swapchain)
28382851
return M_PROPERTY_UNAVAILABLE;
28392852

28402853
switch (action) {
@@ -4318,6 +4331,7 @@ static const struct m_property mp_properties_base[] = {
43184331
{"deinterlace-active", mp_property_deinterlace},
43194332
{"idle-active", mp_property_idle},
43204333
{"window-id", mp_property_window_id},
4334+
{"display-swapchain", mp_property_vo_display_swapchain},
43214335

43224336
{"chapter-list", mp_property_list_chapters},
43234337
{"track-list", mp_property_list_tracks},

video/out/d3d11/context.c

+26-6
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ struct d3d11_opts {
3636
int output_format;
3737
int color_space;
3838
bool exclusive_fs;
39+
int output_mode;
3940
};
4041

4142
#define OPT_BASE_STRUCT struct d3d11_opts
@@ -82,6 +83,12 @@ const struct m_sub_options d3d11_conf = {
8283
.flags = UPDATE_VO,
8384
},
8485
{"d3d11-exclusive-fs", OPT_BOOL(exclusive_fs)},
86+
{"d3d11-output-mode", OPT_CHOICE(output_mode,
87+
{"auto", -1},
88+
{"window", 0},
89+
{"composition", 1}),
90+
.flags = UPDATE_VO,
91+
},
8592
{0}
8693
},
8794
.defaults = &(const struct d3d11_opts) {
@@ -92,6 +99,7 @@ const struct m_sub_options d3d11_conf = {
9299
.adapter_name = NULL,
93100
.output_format = DXGI_FORMAT_UNKNOWN,
94101
.color_space = -1,
102+
.output_mode = -1,
95103
},
96104
.size = sizeof(struct d3d11_opts)
97105
};
@@ -157,7 +165,8 @@ static bool resize(struct ra_ctx *ctx)
157165

158166
static bool d3d11_reconfig(struct ra_ctx *ctx)
159167
{
160-
vo_w32_config(ctx->vo);
168+
if (!ctx->opts.composition)
169+
vo_w32_config(ctx->vo);
161170
return resize(ctx);
162171
}
163172

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

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

459468
// if entering full screen, handle d3d11 after general windowing stuff
460469
if (fullscreen_switch_needed && p->vo_opts->fullscreen) {
@@ -481,7 +490,11 @@ static void d3d11_uninit(struct ra_ctx *ctx)
481490
if (ctx->ra)
482491
ra_tex_free(ctx->ra, &p->backbuffer);
483492
SAFE_RELEASE(p->swapchain);
484-
vo_w32_uninit(ctx->vo);
493+
if (!ctx->opts.composition) {
494+
vo_w32_uninit(ctx->vo);
495+
} else {
496+
vo_w32_swapchain(ctx->vo, NULL);
497+
}
485498
SAFE_RELEASE(p->device);
486499

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

537-
if (!vo_w32_init(ctx->vo))
550+
ctx->opts.composition = p->opts->output_mode == 1;
551+
if (!ctx->opts.composition && !vo_w32_init(ctx->vo))
538552
goto error;
539553

540-
if (ctx->opts.want_alpha)
554+
if (!ctx->opts.composition && ctx->opts.want_alpha)
541555
vo_w32_set_transparency(ctx->vo, ctx->opts.want_alpha);
542556

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

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

580+
if (ctx->opts.composition) {
581+
vo_w32_swapchain(ctx->vo, p->swapchain);
582+
}
566583
return true;
567584

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

573590
static void d3d11_update_render_opts(struct ra_ctx *ctx)
574591
{
592+
if (ctx->opts.composition) {
593+
return;
594+
}
575595
vo_w32_set_transparency(ctx->vo, ctx->opts.want_alpha);
576596
}
577597

video/out/gpu/context.h

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ struct ra_ctx_opts {
1212
bool want_alpha; // create an alpha framebuffer if possible
1313
bool debug; // enable debugging layers/callbacks etc.
1414
bool probing; // the backend was auto-probed
15+
bool composition; // enable swapchain composition
1516
struct m_obj_settings *context_list; // list of `ra_ctx_fns.name` to probe
1617
struct m_obj_settings *context_type_list; // list of `ra_ctx_fns.type` to probe
1718
};

video/out/gpu/d3d11_helpers.c

+7-1
Original file line numberDiff line numberDiff line change
@@ -674,8 +674,14 @@ static HRESULT create_swapchain_1_2(ID3D11Device *dev, IDXGIFactory2 *factory,
674674
desc.BufferCount = 1;
675675
}
676676

677-
hr = IDXGIFactory2_CreateSwapChainForHwnd(factory, (IUnknown*)dev,
677+
if (opts->window == NULL) {
678+
desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
679+
hr = IDXGIFactory2_CreateSwapChainForComposition(factory, (IUnknown*)dev,
680+
&desc, NULL, &swapchain1);
681+
} else {
682+
hr = IDXGIFactory2_CreateSwapChainForHwnd(factory, (IUnknown*)dev,
678683
opts->window, &desc, NULL, NULL, &swapchain1);
684+
}
679685
if (FAILED(hr))
680686
goto done;
681687
hr = IDXGISwapChain1_QueryInterface(swapchain1, &IID_IDXGISwapChain,

video/out/vo.c

+5
Original file line numberDiff line numberDiff line change
@@ -1417,6 +1417,11 @@ double vo_get_display_fps(struct vo *vo)
14171417
return res;
14181418
}
14191419

1420+
void * vo_get_display_swapchain(struct vo *vo)
1421+
{
1422+
return vo->display_swapchain;
1423+
}
1424+
14201425
// Set specific event flags, and wakeup the playback core if needed.
14211426
// vo_query_and_reset_events() can retrieve the events again.
14221427
void vo_event(struct vo *vo, int event)

video/out/vo.h

+4
Original file line numberDiff line numberDiff line change
@@ -525,6 +525,9 @@ struct vo {
525525

526526
// current GPU context (--vo=gpu and --vo=gpu-next only)
527527
const char *context_name;
528+
529+
// composition swapchain (--d3d11-output-mode=composition only)
530+
void *display_swapchain;
528531
};
529532

530533
struct mpv_global;
@@ -559,6 +562,7 @@ double vo_get_vsync_interval(struct vo *vo);
559562
double vo_get_estimated_vsync_interval(struct vo *vo);
560563
double vo_get_estimated_vsync_jitter(struct vo *vo);
561564
double vo_get_display_fps(struct vo *vo);
565+
void * vo_get_display_swapchain(struct vo *vo);
562566
double vo_get_delay(struct vo *vo);
563567
void vo_discard_timing_info(struct vo *vo);
564568
struct vo_frame *vo_get_current_vo_frame(struct vo *vo);

video/out/w32_common.c

+5
Original file line numberDiff line numberDiff line change
@@ -2499,6 +2499,11 @@ HWND vo_w32_hwnd(struct vo *vo)
24992499
return w32->window; // immutable, so no synchronization needed
25002500
}
25012501

2502+
void vo_w32_swapchain(struct vo *vo, void *swapchain)
2503+
{
2504+
vo->display_swapchain = swapchain;
2505+
}
2506+
25022507
void vo_w32_run_on_thread(struct vo *vo, void (*cb)(void *ctx), void *ctx)
25032508
{
25042509
struct vo_w32_state *w32 = vo->w32;

video/out/w32_common.h

+1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ void vo_w32_uninit(struct vo *vo);
3131
int vo_w32_control(struct vo *vo, int *events, int request, void *arg);
3232
void vo_w32_config(struct vo *vo);
3333
HWND vo_w32_hwnd(struct vo *vo);
34+
void vo_w32_swapchain(struct vo *vo, void *swapchain);
3435
void vo_w32_run_on_thread(struct vo *vo, void (*cb)(void *ctx), void *ctx);
3536
void vo_w32_set_transparency(struct vo *vo, bool enable);
3637

0 commit comments

Comments
 (0)