summaryrefslogtreecommitdiffstats
path: root/video/out
diff options
context:
space:
mode:
authorJan Ekström <jeebjp@gmail.com>2019-10-12 00:35:22 +0300
committerJames Ross-Gowan <rossy@jrg.systems>2019-10-13 22:31:33 +1100
commit648d7859300562a99f035e06a0d42245c3c46e23 (patch)
treed627852fd319b8e6b3a11b2aef526b6b43712113 /video/out
parent4809a3f48d41f5414057e965c0f18e0279cc2abe (diff)
downloadmpv-648d7859300562a99f035e06a0d42245c3c46e23.tar.bz2
mpv-648d7859300562a99f035e06a0d42245c3c46e23.tar.xz
vo_gpu/d3d11: add support for configuring swap chain format
Query information on the system output most linked to the swap chain, and either utilize a user-configured format, or either 8bit RGBA or 10bit RGB with 2bit alpha depending on the system output's bit depth.
Diffstat (limited to 'video/out')
-rw-r--r--video/out/d3d11/context.c9
-rw-r--r--video/out/gpu/d3d11_helpers.c120
-rw-r--r--video/out/gpu/d3d11_helpers.h1
3 files changed, 129 insertions, 1 deletions
diff --git a/video/out/d3d11/context.c b/video/out/d3d11/context.c
index 003e3ff173..d2062a5619 100644
--- a/video/out/d3d11/context.c
+++ b/video/out/d3d11/context.c
@@ -36,6 +36,7 @@ struct d3d11_opts {
int flip;
int sync_interval;
char *adapter_name;
+ int output_format;
};
#define OPT_BASE_STRUCT struct d3d11_opts
@@ -59,6 +60,12 @@ const struct m_sub_options d3d11_conf = {
OPT_INTRANGE("d3d11-sync-interval", sync_interval, 0, 0, 4),
OPT_STRING_VALIDATE("d3d11-adapter", adapter_name, 0,
d3d11_validate_adapter),
+ OPT_CHOICE("d3d11-output-format", output_format, 0,
+ ({"auto", DXGI_FORMAT_UNKNOWN},
+ {"rgba8", DXGI_FORMAT_R8G8B8A8_UNORM},
+ {"bgra8", DXGI_FORMAT_B8G8R8A8_UNORM},
+ {"rgb10_a2", DXGI_FORMAT_R10G10B10A2_UNORM},
+ {"rgba16f", DXGI_FORMAT_R16G16B16A16_FLOAT})),
{0}
},
.defaults = &(const struct d3d11_opts) {
@@ -67,6 +74,7 @@ const struct m_sub_options d3d11_conf = {
.flip = 1,
.sync_interval = 1,
.adapter_name = NULL,
+ .output_format = DXGI_FORMAT_UNKNOWN,
},
.size = sizeof(struct d3d11_opts)
};
@@ -372,6 +380,7 @@ static bool d3d11_init(struct ra_ctx *ctx)
.window = vo_w32_hwnd(ctx->vo),
.width = ctx->vo->dwidth,
.height = ctx->vo->dheight,
+ .format = p->opts->output_format,
.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 14a30faa86..9e05b7b878 100644
--- a/video/out/gpu/d3d11_helpers.c
+++ b/video/out/gpu/d3d11_helpers.c
@@ -17,7 +17,8 @@
#include <windows.h>
#include <d3d11.h>
-#include <dxgi1_2.h>
+#include <dxgi1_6.h>
+#include <versionhelpers.h>
#include <pthread.h>
#include "common/common.h"
@@ -62,6 +63,71 @@ static bool load_d3d11_functions(struct mp_log *log)
return true;
}
+static bool query_output_format_and_colorspace(struct mp_log *log,
+ IDXGISwapChain *swapchain,
+ DXGI_FORMAT *out_fmt,
+ DXGI_COLOR_SPACE_TYPE *out_cspace)
+{
+ IDXGIOutput *output = NULL;
+ IDXGIOutput6 *output6 = NULL;
+ DXGI_OUTPUT_DESC1 desc = { 0 };
+ char *monitor_name = NULL;
+ bool success = false;
+
+ if (!out_fmt || !out_cspace)
+ return false;
+
+ HRESULT hr = IDXGISwapChain_GetContainingOutput(swapchain, &output);
+ if (FAILED(hr)) {
+ mp_err(log, "Failed to get swap chain's containing output: %s!\n",
+ mp_HRESULT_to_str(hr));
+ goto done;
+ }
+
+ hr = IDXGIOutput_QueryInterface(output, &IID_IDXGIOutput6,
+ (void**)&output6);
+ if (FAILED(hr)) {
+ // point where systems older than Windows 10 would fail,
+ // thus utilizing error log level only with windows 10+
+ mp_msg(log, IsWindows10OrGreater() ? MSGL_ERR : MSGL_V,
+ "Failed to create a DXGI 1.6 output interface: %s\n",
+ mp_HRESULT_to_str(hr));
+ goto done;
+ }
+
+ hr = IDXGIOutput6_GetDesc1(output6, &desc);
+ if (FAILED(hr)) {
+ mp_err(log, "Failed to query swap chain's output information: %s\n",
+ mp_HRESULT_to_str(hr));
+ goto done;
+ }
+
+ monitor_name = mp_to_utf8(NULL, desc.DeviceName);
+
+ mp_verbose(log, "Queried output: %s, %ldx%ld @ %d bits, colorspace: %d\n",
+ monitor_name,
+ desc.DesktopCoordinates.right - desc.DesktopCoordinates.left,
+ desc.DesktopCoordinates.bottom - desc.DesktopCoordinates.top,
+ desc.BitsPerColor, desc.ColorSpace);
+
+ *out_cspace = desc.ColorSpace;
+
+ // limit ourselves to the 8bit and 10bit formats for now.
+ // while the 16bit float format would be preferable as something
+ // to default to, it seems to be hard-coded to linear transfer
+ // in windowed mode, and follows configured colorspace in full screen.
+ *out_fmt = desc.BitsPerColor > 8 ?
+ DXGI_FORMAT_R10G10B10A2_UNORM : DXGI_FORMAT_R8G8B8A8_UNORM;
+
+ success = true;
+
+done:
+ talloc_free(monitor_name);
+ SAFE_RELEASE(output6);
+ SAFE_RELEASE(output);
+ return success;
+}
+
// Get a const array of D3D_FEATURE_LEVELs from max_fl to min_fl (inclusive)
static int get_feature_levels(int max_fl, int min_fl,
const D3D_FEATURE_LEVEL **out)
@@ -400,6 +466,56 @@ static HRESULT create_swapchain_1_1(ID3D11Device *dev, IDXGIFactory1 *factory,
swapchain_out);
}
+static bool update_swapchain_format(struct mp_log *log,
+ IDXGISwapChain *swapchain,
+ DXGI_FORMAT format)
+{
+ DXGI_SWAP_CHAIN_DESC desc;
+
+ HRESULT hr = IDXGISwapChain_GetDesc(swapchain, &desc);
+ if (FAILED(hr)) {
+ mp_fatal(log, "Failed to query swap chain's current state: %s\n",
+ mp_HRESULT_to_str(hr));
+ return false;
+ }
+
+ hr = IDXGISwapChain_ResizeBuffers(swapchain, 0, desc.BufferDesc.Width,
+ desc.BufferDesc.Height,
+ format, 0);
+ if (FAILED(hr)) {
+ mp_fatal(log, "Couldn't update swapchain format: %s\n",
+ mp_HRESULT_to_str(hr));
+ return false;
+ }
+
+ return true;
+}
+
+static bool configure_created_swapchain(struct mp_log *log,
+ IDXGISwapChain *swapchain,
+ DXGI_FORMAT requested_format)
+{
+ DXGI_FORMAT probed_format = DXGI_FORMAT_UNKNOWN;
+ DXGI_FORMAT selected_format = DXGI_FORMAT_UNKNOWN;
+ DXGI_COLOR_SPACE_TYPE probed_colorspace;
+
+ query_output_format_and_colorspace(log, swapchain,
+ &probed_format,
+ &probed_colorspace);
+
+
+ selected_format = requested_format != DXGI_FORMAT_UNKNOWN ?
+ requested_format :
+ (probed_format != DXGI_FORMAT_UNKNOWN ?
+ probed_format : DXGI_FORMAT_R8G8B8A8_UNORM);
+
+ mp_verbose(log, "Selected swapchain format %d, attempting "
+ "to utilize it.\n",
+ selected_format);
+
+ return update_swapchain_format(log, swapchain, selected_format);
+}
+
// Create a Direct3D 11 swapchain
bool mp_d3d11_create_swapchain(ID3D11Device *dev, struct mp_log *log,
struct d3d11_swapchain_opts *opts,
@@ -472,6 +588,8 @@ 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);
+
DXGI_SWAP_CHAIN_DESC scd = {0};
IDXGISwapChain_GetDesc(swapchain, &scd);
if (scd.SwapEffect == DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL) {
diff --git a/video/out/gpu/d3d11_helpers.h b/video/out/gpu/d3d11_helpers.h
index 705c5a59cb..cd22d4b145 100644
--- a/video/out/gpu/d3d11_helpers.h
+++ b/video/out/gpu/d3d11_helpers.h
@@ -71,6 +71,7 @@ struct d3d11_swapchain_opts {
HWND window;
int width;
int height;
+ DXGI_FORMAT format;
// Use DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL if possible
bool flip;