summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Ekström <jeebjp@gmail.com>2018-05-06 03:01:58 +0300
committerJan Ekström <jeebjp@gmail.com>2019-10-30 02:41:25 +0200
commitfc29620ec876b8cf8a95e9d1aedd24e76ef3204c (patch)
treeca13858d0e9aba6dfbcf7e48cebc2b85526a1377
parent93dd77b38e4eefd13bc2d3aab24adaa46e72f728 (diff)
downloadmpv-fc29620ec876b8cf8a95e9d1aedd24e76ef3204c.tar.bz2
mpv-fc29620ec876b8cf8a95e9d1aedd24e76ef3204c.tar.xz
vo_gpu/d3d11: add support for configuring swap chain color space
By default utilizes the color space of the desktop on which the swap chain is located. If a specific value is defined, it will be instead be utilized. Enables configuration of the PQ color space (BT.2020 primaries, PQ transfer function) for HDR. Additionally, signals the swap chain color space to the renderer, so that the render looks correct without having to specify target-trc or target-prim manually. Due to all of the APIs being Win10+ only, will only work starting with Windows 10.
-rw-r--r--DOCS/interface-changes.rst2
-rw-r--r--DOCS/man/options.rst13
-rw-r--r--video/out/d3d11/context.c12
-rw-r--r--video/out/gpu/d3d11_helpers.c170
-rw-r--r--video/out/gpu/d3d11_helpers.h6
5 files changed, 198 insertions, 5 deletions
diff --git a/DOCS/interface-changes.rst b/DOCS/interface-changes.rst
index 59891272da..4383e1343a 100644
--- a/DOCS/interface-changes.rst
+++ b/DOCS/interface-changes.rst
@@ -25,6 +25,8 @@ Interface changes
::
--- mpv 0.30.0 ---
+ - add `--d3d11-output-csp` to enable explicit selection of a D3D11
+ swap chain color space.
- add `--d3d11-output-format` to enable explicit selection of a D3D11
swap chain format.
- rewrite DVB channel switching to use an integer value
diff --git a/DOCS/man/options.rst b/DOCS/man/options.rst
index 197423e6b2..c8af27bcb7 100644
--- a/DOCS/man/options.rst
+++ b/DOCS/man/options.rst
@@ -4746,6 +4746,19 @@ The following video options are currently all specific to ``--vo=gpu`` and
from Windows 10. Thus on older systems it will only automatically
utilize the rgba8 output format.
+``--d3d11-output-csp=<auto|srgb|linear|pq|bt.2020>``
+ Select a specific D3D11 output color space to utilize for D3D11 rendering.
+ "auto" is the default, which will select the color space of the desktop
+ on which the swap chain is located.
+
+ Values other than "srgb" and "pq" have had issues in testing, so they
+ are mostly available for manual testing.
+
+ .. note::
+
+ Swap chain color space configuration is only available from an API
+ available from Windows 10. Thus on older systems it will not work.
+
``--d3d11va-zero-copy=<yes|no>``
By default, when using hardware decoding with ``--gpu-api=d3d11``, the
video image will be copied (GPU-to-GPU) from the decoder surface to a
diff --git a/video/out/d3d11/context.c b/video/out/d3d11/context.c
index f03f93df92..bdfbacfe54 100644
--- a/video/out/d3d11/context.c
+++ b/video/out/d3d11/context.c
@@ -37,6 +37,7 @@ struct d3d11_opts {
int sync_interval;
char *adapter_name;
int output_format;
+ int color_space;
};
#define OPT_BASE_STRUCT struct d3d11_opts
@@ -66,6 +67,12 @@ const struct m_sub_options d3d11_conf = {
{"bgra8", DXGI_FORMAT_B8G8R8A8_UNORM},
{"rgb10_a2", DXGI_FORMAT_R10G10B10A2_UNORM},
{"rgba16f", DXGI_FORMAT_R16G16B16A16_FLOAT})),
+ OPT_CHOICE("d3d11-output-csp", color_space, 0,
+ ({"auto", -1},
+ {"srgb", DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709},
+ {"linear", DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709},
+ {"pq", DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020},
+ {"bt.2020", DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P2020})),
{0}
},
.defaults = &(const struct d3d11_opts) {
@@ -75,6 +82,7 @@ const struct m_sub_options d3d11_conf = {
.sync_interval = 1,
.adapter_name = NULL,
.output_format = DXGI_FORMAT_UNKNOWN,
+ .color_space = -1,
},
.size = sizeof(struct d3d11_opts)
};
@@ -85,6 +93,7 @@ struct priv {
struct ra_tex *backbuffer;
ID3D11Device *device;
IDXGISwapChain *swapchain;
+ struct mp_colorspace swapchain_csp;
int64_t perf_freq;
unsigned last_sync_refresh_count;
@@ -188,6 +197,7 @@ static bool d3d11_start_frame(struct ra_swapchain *sw, struct ra_fbo *out_fbo)
*out_fbo = (struct ra_fbo) {
.tex = p->backbuffer,
.flip = false,
+ .color_space = p->swapchain_csp
};
return true;
}
@@ -382,6 +392,8 @@ static bool d3d11_init(struct ra_ctx *ctx)
.width = ctx->vo->dwidth,
.height = ctx->vo->dheight,
.format = p->opts->output_format,
+ .color_space = p->opts->color_space,
+ .configured_csp = &p->swapchain_csp,
.flip = p->opts->flip,
// Add one frame for the backbuffer and one frame of "slack" to reduce
// contention with the window manager when acquiring the backbuffer
diff --git a/video/out/gpu/d3d11_helpers.c b/video/out/gpu/d3d11_helpers.c
index 11c891b352..33d01e0861 100644
--- a/video/out/gpu/d3d11_helpers.c
+++ b/video/out/gpu/d3d11_helpers.c
@@ -227,6 +227,52 @@ static const char *d3d11_get_csp_name(DXGI_COLOR_SPACE_TYPE csp)
}
}
+static bool d3d11_get_mp_csp(DXGI_COLOR_SPACE_TYPE csp,
+ struct mp_colorspace *mp_csp)
+{
+ if (!mp_csp)
+ return false;
+
+ // Colorspaces utilizing gamma 2.2 (G22) are set to
+ // AUTO as that keeps the current default flow regarding
+ // SDR transfer function handling.
+ // (no adjustment is done unless the user has a CMS LUT).
+ //
+ // Additionally, only set primary information with colorspaces
+ // utilizing non-709 primaries to keep the current behavior
+ // regarding not doing conversion from BT.601 to BT.709.
+ switch (csp) {
+ case DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709:
+ *mp_csp = (struct mp_colorspace){
+ .gamma = MP_CSP_TRC_AUTO,
+ .primaries = MP_CSP_PRIM_AUTO,
+ };
+ break;
+ case DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709:
+ *mp_csp = (struct mp_colorspace) {
+ .gamma = MP_CSP_TRC_LINEAR,
+ .primaries = MP_CSP_PRIM_AUTO,
+ };
+ break;
+ case DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020:
+ *mp_csp = (struct mp_colorspace) {
+ .gamma = MP_CSP_TRC_PQ,
+ .primaries = MP_CSP_PRIM_BT_2020,
+ };
+ break;
+ case DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P2020:
+ *mp_csp = (struct mp_colorspace) {
+ .gamma = MP_CSP_TRC_AUTO,
+ .primaries = MP_CSP_PRIM_BT_2020,
+ };
+ break;
+ default:
+ return false;
+ }
+
+ return true;
+}
+
static bool query_output_format_and_colorspace(struct mp_log *log,
IDXGISwapChain *swapchain,
DXGI_FORMAT *out_fmt,
@@ -658,14 +704,82 @@ static bool update_swapchain_format(struct mp_log *log,
return true;
}
+static bool update_swapchain_color_space(struct mp_log *log,
+ IDXGISwapChain *swapchain,
+ DXGI_COLOR_SPACE_TYPE color_space)
+{
+ IDXGISwapChain4 *swapchain4 = NULL;
+ const char *csp_name = d3d11_get_csp_name(color_space);
+ bool success = false;
+ HRESULT hr = E_FAIL;
+ unsigned int csp_support_flags;
+
+ hr = IDXGISwapChain_QueryInterface(swapchain, &IID_IDXGISwapChain4,
+ (void *)&(swapchain4));
+ if (FAILED(hr)) {
+ mp_err(log, "Failed to create v4 swapchain for color space "
+ "configuration (%s)!\n",
+ mp_HRESULT_to_str(hr));
+ goto done;
+ }
+
+ hr = IDXGISwapChain4_CheckColorSpaceSupport(swapchain4,
+ color_space,
+ &csp_support_flags);
+ if (FAILED(hr)) {
+ mp_err(log, "Failed to check color space support for color space "
+ "%s (%d): %s!\n",
+ csp_name, color_space, mp_HRESULT_to_str(hr));
+ goto done;
+ }
+
+ mp_verbose(log,
+ "Swapchain capabilities for color space %s (%d): "
+ "normal: %s, overlay: %s\n",
+ csp_name, color_space,
+ (csp_support_flags & DXGI_SWAP_CHAIN_COLOR_SPACE_SUPPORT_FLAG_PRESENT) ?
+ "yes" : "no",
+ (csp_support_flags & DXGI_SWAP_CHAIN_COLOR_SPACE_SUPPORT_FLAG_OVERLAY_PRESENT) ?
+ "yes" : "no");
+
+ if (!(csp_support_flags & DXGI_SWAP_CHAIN_COLOR_SPACE_SUPPORT_FLAG_PRESENT)) {
+ mp_err(log, "Color space %s (%d) is not supported by this swapchain!\n",
+ csp_name, color_space);
+ goto done;
+ }
+
+ hr = IDXGISwapChain4_SetColorSpace1(swapchain4, color_space);
+ if (FAILED(hr)) {
+ mp_err(log, "Failed to set color space %s (%d) for this swapchain "
+ "(%s)!\n",
+ csp_name, color_space, mp_HRESULT_to_str(hr));
+ goto done;
+ }
+
+ mp_verbose(log, "Swapchain successfully configured to color space %s (%d)!\n",
+ csp_name, color_space);
+
+ success = true;
+
+done:
+ SAFE_RELEASE(swapchain4);
+ return success;
+}
+
static bool configure_created_swapchain(struct mp_log *log,
IDXGISwapChain *swapchain,
- DXGI_FORMAT requested_format)
+ DXGI_FORMAT requested_format,
+ DXGI_COLOR_SPACE_TYPE requested_csp,
+ struct mp_colorspace *configured_csp)
{
DXGI_FORMAT probed_format = DXGI_FORMAT_UNKNOWN;
DXGI_FORMAT selected_format = DXGI_FORMAT_UNKNOWN;
- DXGI_COLOR_SPACE_TYPE probed_colorspace;
+ DXGI_COLOR_SPACE_TYPE probed_colorspace = DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709;
+ DXGI_COLOR_SPACE_TYPE selected_colorspace;
const char *format_name = NULL;
+ const char *csp_name = NULL;
+ struct mp_colorspace mp_csp = { 0 };
+ bool mp_csp_mapped = false;
query_output_format_and_colorspace(log, swapchain,
&probed_format,
@@ -676,13 +790,57 @@ static bool configure_created_swapchain(struct mp_log *log,
requested_format :
(probed_format != DXGI_FORMAT_UNKNOWN ?
probed_format : DXGI_FORMAT_R8G8B8A8_UNORM);
- format_name = d3d11_get_format_name(selected_format);
+ selected_colorspace = requested_csp != -1 ?
+ requested_csp : probed_colorspace;
+ format_name = d3d11_get_format_name(selected_format);
+ csp_name = d3d11_get_csp_name(selected_colorspace);
+ mp_csp_mapped = d3d11_get_mp_csp(selected_colorspace, &mp_csp);
mp_verbose(log, "Selected swapchain format %s (%d), attempting "
"to utilize it.\n",
format_name, selected_format);
- return update_swapchain_format(log, swapchain, selected_format);
+ if (!update_swapchain_format(log, swapchain, selected_format)) {
+ return false;
+ }
+
+ if (!IsWindows10OrGreater()) {
+ // On older than Windows 10, query_output_format_and_colorspace
+ // will not change probed_colorspace, and even if a user sets
+ // a colorspace it will not get applied. Thus warn user in case a
+ // value was specifically set and finish.
+ if (requested_csp != -1) {
+ mp_warn(log, "User selected a D3D11 color space %s (%d), "
+ "but configuration of color spaces is only supported"
+ "from Windows 10! The default configuration has been "
+ "left as-is.\n",
+ csp_name, selected_colorspace);
+ }
+
+ return true;
+ }
+
+ if (!mp_csp_mapped) {
+ mp_warn(log, "Color space %s (%d) does not have an mpv color space "
+ "mapping! Overriding to standard sRGB!\n",
+ csp_name, selected_colorspace);
+ selected_colorspace = DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709;
+ d3d11_get_mp_csp(selected_colorspace, &mp_csp);
+ }
+
+ mp_verbose(log, "Selected swapchain color space %s (%d), attempting to "
+ "utilize it.\n",
+ csp_name, selected_colorspace);
+
+ if (!update_swapchain_color_space(log, swapchain, selected_colorspace)) {
+ return false;
+ }
+
+ if (configured_csp) {
+ *configured_csp = mp_csp;
+ }
+
+ return true;
}
// Create a Direct3D 11 swapchain
@@ -757,7 +915,9 @@ bool mp_d3d11_create_swapchain(ID3D11Device *dev, struct mp_log *log,
mp_verbose(log, "Using DXGI 1.1\n");
}
- configure_created_swapchain(log, swapchain, opts->format);
+ configure_created_swapchain(log, swapchain, opts->format,
+ opts->color_space,
+ opts->configured_csp);
DXGI_SWAP_CHAIN_DESC scd = {0};
IDXGISwapChain_GetDesc(swapchain, &scd);
diff --git a/video/out/gpu/d3d11_helpers.h b/video/out/gpu/d3d11_helpers.h
index 5ce23c68cb..c115d330d5 100644
--- a/video/out/gpu/d3d11_helpers.h
+++ b/video/out/gpu/d3d11_helpers.h
@@ -78,6 +78,12 @@ struct d3d11_swapchain_opts {
int width;
int height;
DXGI_FORMAT format;
+ DXGI_COLOR_SPACE_TYPE color_space;
+
+ // mp_colorspace mapping of the configured swapchain colorspace
+ // shall be written into this memory location if configuration
+ // succeeds. Will be ignored if NULL.
+ struct mp_colorspace *configured_csp;
// Use DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL if possible
bool flip;