mirror of
https://github.com/mpv-player/mpv.git
synced 2024-09-20 12:02:23 +02:00
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.
This commit is contained in:
parent
4809a3f48d
commit
648d785930
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
2
wscript
2
wscript
@ -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',
|
||||
|
Loading…
Reference in New Issue
Block a user