From 894e37d0e19bee482e64855c95c99c83a7c902a3 Mon Sep 17 00:00:00 2001 From: jpark37 Date: Sun, 4 Sep 2022 12:16:44 -0700 Subject: [PATCH] libobs-winrt,win-capture: Allow forcing SDR We don't know if there's a way to get window color space, so we've been using the monitor color space of the window. This toggle forces OBS to ignore the monitor color space, and assume the window is SDR. --- libobs-winrt/winrt-capture.cpp | 34 +++++++++++++++-------- libobs-winrt/winrt-capture.h | 3 +- plugins/win-capture/data/locale/en-US.ini | 1 + plugins/win-capture/window-capture.c | 17 ++++++++++-- 4 files changed, 39 insertions(+), 16 deletions(-) diff --git a/libobs-winrt/winrt-capture.cpp b/libobs-winrt/winrt-capture.cpp index 7c49fec71..09d5d80b0 100644 --- a/libobs-winrt/winrt-capture.cpp +++ b/libobs-winrt/winrt-capture.cpp @@ -109,19 +109,26 @@ static bool get_client_box(HWND window, uint32_t width, uint32_t height, return client_box_available; } -static DXGI_FORMAT get_pixel_format(HWND window, HMONITOR monitor) +static DXGI_FORMAT get_pixel_format(HWND window, HMONITOR monitor, + BOOL force_sdr) { + static constexpr DXGI_FORMAT sdr_format = DXGI_FORMAT_B8G8R8A8_UNORM; + + if (force_sdr) + return sdr_format; + if (window) monitor = MonitorFromWindow(window, MONITOR_DEFAULTTONEAREST); return (monitor && gs_is_monitor_hdr(monitor)) ? DXGI_FORMAT_R16G16B16A16_FLOAT - : DXGI_FORMAT_B8G8R8A8_UNORM; + : sdr_format; } struct winrt_capture { HWND window; - bool client_area; + BOOL client_area; + BOOL force_sdr; HMONITOR monitor; DXGI_FORMAT format; @@ -177,7 +184,8 @@ struct winrt_capture { obs_enter_graphics(); - if (desc.Format == get_pixel_format(window, monitor)) { + if (desc.Format == + get_pixel_format(window, monitor, force_sdr)) { if (!client_area || get_client_box(window, desc.Width, desc.Height, &client_box)) { @@ -425,10 +433,9 @@ static void winrt_capture_device_loss_rebuild(void *device_void, void *data) } } -static struct winrt_capture *winrt_capture_init_internal(BOOL cursor, - HWND window, - BOOL client_area, - HMONITOR monitor) +static struct winrt_capture * +winrt_capture_init_internal(BOOL cursor, HWND window, BOOL client_area, + BOOL force_sdr, HMONITOR monitor) try { ID3D11Device *const d3d_device = (ID3D11Device *)gs_get_device_obj(); ComPtr dxgi_device; @@ -461,7 +468,7 @@ try { device = inspectable.as(); const winrt::Windows::Graphics::SizeInt32 size = item.Size(); - const DXGI_FORMAT format = get_pixel_format(window, monitor); + const DXGI_FORMAT format = get_pixel_format(window, monitor, force_sdr); const winrt::Windows::Graphics::Capture::Direct3D11CaptureFramePool frame_pool = winrt::Windows::Graphics::Capture:: Direct3D11CaptureFramePool::Create( @@ -490,6 +497,7 @@ try { struct winrt_capture *capture = new winrt_capture{}; capture->window = window; capture->client_area = client_area; + capture->force_sdr = force_sdr; capture->monitor = monitor; capture->format = format; capture->capture_cursor = cursor && cursor_toggle_supported; @@ -530,15 +538,17 @@ try { } extern "C" EXPORT struct winrt_capture * -winrt_capture_init_window(BOOL cursor, HWND window, BOOL client_area) +winrt_capture_init_window(BOOL cursor, HWND window, BOOL client_area, + BOOL force_sdr) { - return winrt_capture_init_internal(cursor, window, client_area, NULL); + return winrt_capture_init_internal(cursor, window, client_area, + force_sdr, NULL); } extern "C" EXPORT struct winrt_capture * winrt_capture_init_monitor(BOOL cursor, HMONITOR monitor) { - return winrt_capture_init_internal(cursor, NULL, false, monitor); + return winrt_capture_init_internal(cursor, NULL, false, false, monitor); } extern "C" EXPORT void winrt_capture_free(struct winrt_capture *capture) diff --git a/libobs-winrt/winrt-capture.h b/libobs-winrt/winrt-capture.h index fff5581b9..58eb51154 100644 --- a/libobs-winrt/winrt-capture.h +++ b/libobs-winrt/winrt-capture.h @@ -12,7 +12,8 @@ extern "C" { EXPORT BOOL winrt_capture_supported(); EXPORT BOOL winrt_capture_cursor_toggle_supported(); EXPORT struct winrt_capture *winrt_capture_init_window(BOOL cursor, HWND window, - BOOL client_area); + BOOL client_area, + BOOL force_sdr); EXPORT struct winrt_capture *winrt_capture_init_monitor(BOOL cursor, HMONITOR monitor); EXPORT void winrt_capture_free(struct winrt_capture *capture); diff --git a/plugins/win-capture/data/locale/en-US.ini b/plugins/win-capture/data/locale/en-US.ini index ca2c46ae2..740394ea4 100644 --- a/plugins/win-capture/data/locale/en-US.ini +++ b/plugins/win-capture/data/locale/en-US.ini @@ -12,6 +12,7 @@ WindowCapture.Priority.Exe="Match title, otherwise find window of same executabl CaptureCursor="Capture Cursor" Compatibility="Multi-adapter Compatibility" ClientArea="Client Area" +ForceSdr="Force SDR" SLIFix="SLI/Crossfire Capture Mode (Slow)" AllowTransparency="Allow Transparency" Monitor="Display" diff --git a/plugins/win-capture/window-capture.c b/plugins/win-capture/window-capture.c index 84808bdae..26b401b69 100644 --- a/plugins/win-capture/window-capture.c +++ b/plugins/win-capture/window-capture.c @@ -21,6 +21,7 @@ #define TEXT_CAPTURE_CURSOR obs_module_text("CaptureCursor") #define TEXT_COMPATIBILITY obs_module_text("Compatibility") #define TEXT_CLIENT_AREA obs_module_text("ClientArea") +#define TEXT_FORCE_SDR obs_module_text("ForceSdr") /* clang-format on */ @@ -30,8 +31,10 @@ typedef BOOL (*PFN_winrt_capture_supported)(); typedef BOOL (*PFN_winrt_capture_cursor_toggle_supported)(); -typedef struct winrt_capture *(*PFN_winrt_capture_init_window)( - BOOL cursor, HWND window, BOOL client_area); +typedef struct winrt_capture *(*PFN_winrt_capture_init_window)(BOOL cursor, + HWND window, + BOOL client_area, + BOOL force_sdr); typedef void (*PFN_winrt_capture_free)(struct winrt_capture *capture); typedef BOOL (*PFN_winrt_capture_active)(const struct winrt_capture *capture); @@ -82,6 +85,7 @@ struct window_capture { bool cursor; bool compatibility; bool client_area; + bool force_sdr; bool use_wildcards; /* TODO */ struct dc_capture capture; @@ -204,6 +208,7 @@ static void update_settings(struct window_capture *wc, obs_data_t *s) wc->method = choose_method(method, wgc_supported, wc->class); wc->priority = (enum window_priority)priority; wc->cursor = obs_data_get_bool(s, "cursor"); + wc->force_sdr = obs_data_get_bool(s, "force_sdr"); wc->use_wildcards = obs_data_get_bool(s, "use_wildcards"); wc->compatibility = obs_data_get_bool(s, "compatibility"); wc->client_area = obs_data_get_bool(s, "client_area"); @@ -370,6 +375,7 @@ static void wc_defaults(obs_data_t *defaults) { obs_data_set_default_int(defaults, "method", METHOD_AUTO); obs_data_set_default_bool(defaults, "cursor", true); + obs_data_set_default_bool(defaults, "force_sdr", false); obs_data_set_default_bool(defaults, "compatibility", false); obs_data_set_default_bool(defaults, "client_area", true); } @@ -396,6 +402,9 @@ static void update_settings_visibility(obs_properties_t *props, p = obs_properties_get(props, "client_area"); obs_property_set_visible(p, wgc_options); + p = obs_properties_get(props, "force_sdr"); + obs_property_set_visible(p, wgc_cursor_toggle); + pthread_mutex_unlock(&wc->update_mutex); } @@ -465,6 +474,8 @@ static obs_properties_t *wc_properties(void *data) obs_properties_add_bool(ppts, "client_area", TEXT_CLIENT_AREA); + obs_properties_add_bool(ppts, "force_sdr", TEXT_FORCE_SDR); + return ppts; } @@ -608,7 +619,7 @@ static void wc_tick(void *data, float seconds) wc->capture_winrt = wc->exports.winrt_capture_init_window( wc->cursor, wc->window, - wc->client_area); + wc->client_area, wc->force_sdr); if (!wc->capture_winrt) { wc->previously_failed = true;