Skip to content

Commit

Permalink
vo_gpu/d3d11: add support for configuring swap chain format
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
jeeb committed Oct 13, 2019
1 parent 4c4e013 commit 35f17cf
Show file tree
Hide file tree
Showing 6 changed files with 144 additions and 2 deletions.
2 changes: 2 additions & 0 deletions DOCS/interface-changes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ Interface changes
::

--- mpv 0.30.0 ---
- add `--d3d11-output-format` to enable explicit selection of a D3D11
swap chain format.
- rewrite DVB channel switching to use an integer value
`--dvbin-channel-switch-offset` for switching instead of the old
stream controls which are now gone. Cycling this property up or down will
Expand Down
12 changes: 12 additions & 0 deletions DOCS/man/options.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4708,6 +4708,18 @@ The following video options are currently all specific to ``--vo=gpu`` and
functionality to receive a device, such as D3D11VA or DXVA2's DXGI
mode, will be affected by this choice.

``--d3d11-output-format=<auto|rgba8|bgra8|rgb10_a2|rgba16f>``
Select a specific D3D11 output format to utilize for D3D11 rendering.
"auto" is the default, which will pick either rgba8 or rgb10_a2 depending
on the configured desktop bit depth. rgba16f and bgra8 are left out of
the autodetection logic, and are available for manual testing.

.. note::

Desktop bit depth querying is only available from an API available
from Windows 10. Thus on older systems it will only automatically
utilize the rgba8 output format.

``--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
Expand Down
9 changes: 9 additions & 0 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 flip;
int sync_interval;
char *adapter_name;
int output_format;
};

#define OPT_BASE_STRUCT struct d3d11_opts
Expand All @@ -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) {
Expand All @@ -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)
};
Expand Down Expand Up @@ -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
Expand Down
120 changes: 119 additions & 1 deletion video/out/gpu/d3d11_helpers.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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) {
Expand Down
1 change: 1 addition & 0 deletions video/out/gpu/d3d11_helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion wscript
Original file line number Diff line number Diff line change
Expand Up @@ -770,7 +770,7 @@ video_output_features = [
'name': '--d3d11',
'desc': 'Direct3D 11 video output',
'deps': 'win32-desktop && shaderc && spirv-cross',
'func': check_cc(header_name=['d3d11_1.h', 'dxgi1_2.h']),
'func': check_cc(header_name=['d3d11_1.h', 'dxgi1_6.h']),
}, {
'name': '--rpi',
'desc': 'Raspberry Pi support',
Expand Down

0 comments on commit 35f17cf

Please sign in to comment.