mirror of
https://github.com/LizardByte/Sunshine.git
synced 2025-08-10 00:52:16 +00:00
HDR prep work (#808)
This commit is contained in:
@@ -17,6 +17,7 @@ typedef long NTSTATUS;
|
||||
#include "src/config.h"
|
||||
#include "src/main.h"
|
||||
#include "src/platform/common.h"
|
||||
#include "src/video.h"
|
||||
|
||||
namespace platf {
|
||||
using namespace std::literals;
|
||||
@@ -106,10 +107,16 @@ capture_e display_base_t::capture(snapshot_cb_t &&snapshot_cb, std::shared_ptr<:
|
||||
});
|
||||
|
||||
while(img) {
|
||||
auto wait_time_us = std::chrono::duration_cast<std::chrono::microseconds>(next_frame - std::chrono::steady_clock::now()).count();
|
||||
// This will return false if the HDR state changes or for any number of other
|
||||
// display or GPU changes. We should reinit to examine the updated state of
|
||||
// the display subsystem. It is recommended to call this once per frame.
|
||||
if(!factory->IsCurrent()) {
|
||||
return platf::capture_e::reinit;
|
||||
}
|
||||
|
||||
// If the wait time is between 1 us and 1 second, wait the specified time
|
||||
// and offset the next frame time from the exact current frame time target.
|
||||
auto wait_time_us = std::chrono::duration_cast<std::chrono::microseconds>(next_frame - std::chrono::steady_clock::now()).count();
|
||||
if(wait_time_us > 0 && wait_time_us < 1000000) {
|
||||
LARGE_INTEGER due_time { .QuadPart = -10LL * wait_time_us };
|
||||
SetWaitableTimer(timer, &due_time, 0, nullptr, nullptr, false);
|
||||
@@ -276,7 +283,7 @@ bool test_dxgi_duplication(adapter_t &adapter, output_t &output) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int display_base_t::init(int framerate, const std::string &display_name) {
|
||||
int display_base_t::init(const ::video::config_t &config, const std::string &display_name) {
|
||||
std::once_flag windows_cpp_once_flag;
|
||||
|
||||
std::call_once(windows_cpp_once_flag, []() {
|
||||
@@ -296,7 +303,7 @@ int display_base_t::init(int framerate, const std::string &display_name) {
|
||||
// Ensure we can duplicate the current display
|
||||
syncThreadDesktop();
|
||||
|
||||
delay = std::chrono::nanoseconds { 1s } / framerate;
|
||||
delay = std::chrono::nanoseconds { 1s } / config.framerate;
|
||||
|
||||
// Get rectangle of full desktop for absolute mouse coordinates
|
||||
env_width = GetSystemMetrics(SM_CXVIRTUALSCREEN);
|
||||
@@ -421,7 +428,7 @@ int display_base_t::init(int framerate, const std::string &display_name) {
|
||||
<< "Virtual Desktop : "sv << env_width << 'x' << env_height;
|
||||
|
||||
// Enable DwmFlush() only if the current refresh rate can match the client framerate.
|
||||
auto refresh_rate = framerate;
|
||||
auto refresh_rate = config.framerate;
|
||||
DWM_TIMING_INFO timing_info;
|
||||
timing_info.cbSize = sizeof(timing_info);
|
||||
|
||||
@@ -433,7 +440,7 @@ int display_base_t::init(int framerate, const std::string &display_name) {
|
||||
refresh_rate = std::round((double)timing_info.rateRefresh.uiNumerator / (double)timing_info.rateRefresh.uiDenominator);
|
||||
}
|
||||
|
||||
dup.use_dwmflush = config::video.dwmflush && !(framerate > refresh_rate) ? true : false;
|
||||
dup.use_dwmflush = config::video.dwmflush && !(config.framerate > refresh_rate) ? true : false;
|
||||
|
||||
// Bump up thread priority
|
||||
{
|
||||
@@ -502,7 +509,7 @@ int display_base_t::init(int framerate, const std::string &display_name) {
|
||||
status = output->QueryInterface(IID_IDXGIOutput5, (void **)&output5);
|
||||
if(SUCCEEDED(status)) {
|
||||
// Ask the display implementation which formats it supports
|
||||
auto supported_formats = get_supported_sdr_capture_formats();
|
||||
auto supported_formats = config.dynamicRange ? get_supported_hdr_capture_formats() : get_supported_sdr_capture_formats();
|
||||
if(supported_formats.empty()) {
|
||||
BOOST_LOG(warning) << "No compatible capture formats for this encoder"sv;
|
||||
return -1;
|
||||
@@ -562,6 +569,57 @@ int display_base_t::init(int framerate, const std::string &display_name) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool display_base_t::is_hdr() {
|
||||
dxgi::output6_t output6 {};
|
||||
|
||||
auto status = output->QueryInterface(IID_IDXGIOutput6, (void **)&output6);
|
||||
if(FAILED(status)) {
|
||||
BOOST_LOG(warning) << "Failed to query IDXGIOutput6 from the output"sv;
|
||||
return false;
|
||||
}
|
||||
|
||||
DXGI_OUTPUT_DESC1 desc1;
|
||||
output6->GetDesc1(&desc1);
|
||||
|
||||
return desc1.ColorSpace == DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020;
|
||||
}
|
||||
|
||||
bool display_base_t::get_hdr_metadata(SS_HDR_METADATA &metadata) {
|
||||
dxgi::output6_t output6 {};
|
||||
|
||||
std::memset(&metadata, 0, sizeof(metadata));
|
||||
|
||||
auto status = output->QueryInterface(IID_IDXGIOutput6, (void **)&output6);
|
||||
if(FAILED(status)) {
|
||||
BOOST_LOG(warning) << "Failed to query IDXGIOutput6 from the output"sv;
|
||||
return false;
|
||||
}
|
||||
|
||||
DXGI_OUTPUT_DESC1 desc1;
|
||||
output6->GetDesc1(&desc1);
|
||||
|
||||
metadata.displayPrimaries[0].x = desc1.RedPrimary[0] * 50000;
|
||||
metadata.displayPrimaries[0].y = desc1.RedPrimary[1] * 50000;
|
||||
metadata.displayPrimaries[1].x = desc1.GreenPrimary[0] * 50000;
|
||||
metadata.displayPrimaries[1].y = desc1.GreenPrimary[1] * 50000;
|
||||
metadata.displayPrimaries[2].x = desc1.BluePrimary[0] * 50000;
|
||||
metadata.displayPrimaries[2].y = desc1.BluePrimary[1] * 50000;
|
||||
|
||||
metadata.whitePoint.x = desc1.WhitePoint[0] * 50000;
|
||||
metadata.whitePoint.y = desc1.WhitePoint[1] * 50000;
|
||||
|
||||
metadata.maxDisplayLuminance = desc1.MaxLuminance;
|
||||
metadata.minDisplayLuminance = desc1.MinLuminance * 10000;
|
||||
|
||||
// These are content-specific metadata parameters that this interface doesn't give us
|
||||
metadata.maxContentLightLevel = 0;
|
||||
metadata.maxFrameAverageLightLevel = 0;
|
||||
|
||||
metadata.maxFullFrameLuminance = desc1.MaxFullFrameLuminance;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const char *format_str[] = {
|
||||
"DXGI_FORMAT_UNKNOWN",
|
||||
"DXGI_FORMAT_R32G32B32A32_TYPELESS",
|
||||
@@ -694,18 +752,18 @@ const char *display_base_t::dxgi_format_to_string(DXGI_FORMAT format) {
|
||||
} // namespace platf::dxgi
|
||||
|
||||
namespace platf {
|
||||
std::shared_ptr<display_t> display(mem_type_e hwdevice_type, const std::string &display_name, int framerate) {
|
||||
std::shared_ptr<display_t> display(mem_type_e hwdevice_type, const std::string &display_name, const video::config_t &config) {
|
||||
if(hwdevice_type == mem_type_e::dxgi) {
|
||||
auto disp = std::make_shared<dxgi::display_vram_t>();
|
||||
|
||||
if(!disp->init(framerate, display_name)) {
|
||||
if(!disp->init(config, display_name)) {
|
||||
return disp;
|
||||
}
|
||||
}
|
||||
else if(hwdevice_type == mem_type_e::system) {
|
||||
auto disp = std::make_shared<dxgi::display_ram_t>();
|
||||
|
||||
if(!disp->init(framerate, display_name)) {
|
||||
if(!disp->init(config, display_name)) {
|
||||
return disp;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user