Skip to content

Commit c0c0296

Browse files
committed
video/out/d3d11: add d3d11 composition mode support
1 parent 2b38b38 commit c0c0296

File tree

9 files changed

+69
-7
lines changed

9 files changed

+69
-7
lines changed

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

+14
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
{
@@ -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

+24-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,9 @@ 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);
170+
}
161171
return resize(ctx);
162172
}
163173

@@ -454,7 +464,7 @@ static int d3d11_control(struct ra_ctx *ctx, int *events, int request, void *arg
454464
fullscreen_switch_needed = false;
455465
}
456466

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

459469
// if entering full screen, handle d3d11 after general windowing stuff
460470
if (fullscreen_switch_needed && p->vo_opts->fullscreen) {
@@ -481,7 +491,11 @@ static void d3d11_uninit(struct ra_ctx *ctx)
481491
if (ctx->ra)
482492
ra_tex_free(ctx->ra, &p->backbuffer);
483493
SAFE_RELEASE(p->swapchain);
484-
vo_w32_uninit(ctx->vo);
494+
if (!ctx->opts.composition) {
495+
vo_w32_uninit(ctx->vo);
496+
} else {
497+
vo_w32_swapchain(ctx->vo, NULL);
498+
}
485499
SAFE_RELEASE(p->device);
486500

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

537-
if (!vo_w32_init(ctx->vo))
551+
ctx->opts.composition = p->opts->output_mode == 1;
552+
if (!ctx->opts.composition && !vo_w32_init(ctx->vo))
538553
goto error;
539554

540-
if (ctx->opts.want_alpha)
555+
if (!ctx->opts.composition && ctx->opts.want_alpha)
541556
vo_w32_set_transparency(ctx->vo, ctx->opts.want_alpha);
542557

543558
UINT usage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_SHADER_INPUT;
@@ -548,7 +563,7 @@ static bool d3d11_init(struct ra_ctx *ctx)
548563
}
549564

550565
struct d3d11_swapchain_opts scopts = {
551-
.window = vo_w32_hwnd(ctx->vo),
566+
.window = ctx->opts.composition ? NULL : vo_w32_hwnd(ctx->vo),
552567
.width = ctx->vo->dwidth,
553568
.height = ctx->vo->dheight,
554569
.format = p->opts->output_format,
@@ -563,6 +578,9 @@ static bool d3d11_init(struct ra_ctx *ctx)
563578
if (!mp_d3d11_create_swapchain(p->device, ctx->log, &scopts, &p->swapchain))
564579
goto error;
565580

581+
if (ctx->opts.composition) {
582+
vo_w32_swapchain(ctx->vo, p->swapchain);
583+
}
566584
return true;
567585

568586
error:

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
@@ -1414,6 +1414,11 @@ double vo_get_display_fps(struct vo *vo)
14141414
return res;
14151415
}
14161416

1417+
void * vo_get_display_swapchain(struct vo *vo)
1418+
{
1419+
return vo->display_swapchain;
1420+
}
1421+
14171422
// Set specific event flags, and wakeup the playback core if needed.
14181423
// vo_query_and_reset_events() can retrieve the events again.
14191424
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)