diff --git a/src/platform/common.h b/src/platform/common.h index 7c8828a8dc9..ada26600735 100644 --- a/src/platform/common.h +++ b/src/platform/common.h @@ -153,6 +153,7 @@ struct img_t { std::int32_t height {}; std::int32_t pixel_pitch {}; std::int32_t row_pitch {}; + bool is_bgr = true; virtual ~img_t() = default; }; diff --git a/src/platform/windows/display.h b/src/platform/windows/display.h index 52faddb7179..46f06676f1b 100644 --- a/src/platform/windows/display.h +++ b/src/platform/windows/display.h @@ -31,6 +31,7 @@ using device_ctx_t = util::safe_ptr>; using output_t = util::safe_ptr>; using output1_t = util::safe_ptr>; +using output5_t = util::safe_ptr>; using dup_t = util::safe_ptr>; using texture2d_t = util::safe_ptr>; using texture1d_t = util::safe_ptr>; diff --git a/src/platform/windows/display_base.cpp b/src/platform/windows/display_base.cpp index e6951cce47e..30e4e29b64e 100644 --- a/src/platform/windows/display_base.cpp +++ b/src/platform/windows/display_base.cpp @@ -4,6 +4,7 @@ #include #include +#include #include "display.h" #include "misc.h" @@ -79,22 +80,21 @@ duplication_t::~duplication_t() { } int display_base_t::init(int framerate, const std::string &display_name) { - /* Uncomment when use of IDXGIOutput5 is implemented + std::once_flag windows_cpp_once_flag; + std::call_once(windows_cpp_once_flag, []() { DECLARE_HANDLE(DPI_AWARENESS_CONTEXT); - const auto DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 = ((DPI_AWARENESS_CONTEXT)-4); typedef BOOL (*User32_SetProcessDpiAwarenessContext)(DPI_AWARENESS_CONTEXT value); auto user32 = LoadLibraryA("user32.dll"); - auto f = (User32_SetProcessDpiAwarenessContext)GetProcAddress(user32, "SetProcessDpiAwarenessContext"); + auto f = (User32_SetProcessDpiAwarenessContext)GetProcAddress(user32, "SetProcessDpiAwarenessContext"); if(f) { f(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2); } FreeLibrary(user32); }); -*/ // Ensure we can duplicate the current display syncThreadDesktop(); @@ -291,18 +291,31 @@ int display_base_t::init(int framerate, const std::string &display_name) { } //FIXME: Duplicate output on RX580 in combination with DOOM (2016) --> BSOD - //TODO: Use IDXGIOutput5 for improved performance { + const DXGI_FORMAT DesktopFormats[] = { + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT_R16G16B16A16_FLOAT, + DXGI_FORMAT_R10G10B10A2_UNORM, + }; + const unsigned DesktopFormatsCounts = sizeof(DesktopFormats) / sizeof(DesktopFormats[0]); dxgi::output1_t output1 {}; - status = output->QueryInterface(IID_IDXGIOutput1, (void **)&output1); + dxgi::output5_t output5 {}; + + status = output->QueryInterface(IID_IDXGIOutput5, (void **)&output5); if(FAILED(status)) { - BOOST_LOG(error) << "Failed to query IDXGIOutput1 from the output"sv; - return -1; + BOOST_LOG(warning) << "Failed to query IDXGIOutput5 from the output"sv; + + status = output->QueryInterface(IID_IDXGIOutput1, (void **)&output1); + if(FAILED(status)) { + BOOST_LOG(error) << "Failed to query IDXGIOutput1 from the output"sv; + return -1; + } } // We try this twice, in case we still get an error on reinitialization for(int x = 0; x < 2; ++x) { - status = output1->DuplicateOutput((IUnknown *)device.get(), &dup.dup); + status = output5->DuplicateOutput1((IUnknown *)device.get(), 0, DesktopFormatsCounts, DesktopFormats, &dup.dup); if(SUCCEEDED(status)) { break; } @@ -310,8 +323,19 @@ int display_base_t::init(int framerate, const std::string &display_name) { } if(FAILED(status)) { - BOOST_LOG(error) << "DuplicateOutput Failed [0x"sv << util::hex(status).to_string_view() << ']'; - return -1; + BOOST_LOG(warning) << "DuplicateOutput1 Failed [0x"sv << util::hex(status).to_string_view() << ']'; + for(int x = 0; x < 2; ++x) { + status = output1->DuplicateOutput((IUnknown *)device.get(), &dup.dup); + if(SUCCEEDED(status)) { + break; + } + std::this_thread::sleep_for(200ms); + } + + if(FAILED(status)) { + BOOST_LOG(error) << "DuplicateOutput Failed [0x"sv << util::hex(status).to_string_view() << ']'; + return -1; + } } } diff --git a/src/platform/windows/display_ram.cpp b/src/platform/windows/display_ram.cpp index 596d4880ff3..eaa68896f75 100644 --- a/src/platform/windows/display_ram.cpp +++ b/src/platform/windows/display_ram.cpp @@ -285,6 +285,7 @@ std::shared_ptr display_ram_t::alloc_img() { img->width = width; img->height = height; img->data = new std::uint8_t[img->row_pitch * height]; + img->is_bgr = (format == DXGI_FORMAT_B8G8R8A8_UNORM ? true : false); return img; } diff --git a/src/platform/windows/display_vram.cpp b/src/platform/windows/display_vram.cpp index 3cf7c97789b..72f1c3ff26e 100644 --- a/src/platform/windows/display_vram.cpp +++ b/src/platform/windows/display_vram.cpp @@ -434,6 +434,7 @@ class hwdevice_t : public platf::hwdevice_t { this->device_ctx_p = device_ctx_p; + DXGI_FORMAT src_format = format; format = (pix_fmt == pix_fmt_e::nv12 ? DXGI_FORMAT_NV12 : DXGI_FORMAT_P010); status = device_p->CreateVertexShader(scene_vs_hlsl->GetBufferPointer(), scene_vs_hlsl->GetBufferSize(), nullptr, &scene_vs); if(status) { @@ -490,7 +491,7 @@ class hwdevice_t : public platf::hwdevice_t { } D3D11_SHADER_RESOURCE_VIEW_DESC desc { - DXGI_FORMAT_B8G8R8A8_UNORM, + src_format, D3D11_SRV_DIMENSION_TEXTURE2D }; desc.Texture2D.MipLevels = 1; @@ -885,4 +886,4 @@ int init() { return 0; } -} // namespace platf::dxgi \ No newline at end of file +} // namespace platf::dxgi diff --git a/src/video.cpp b/src/video.cpp index 70d7a6c4bcd..e42dfd8da81 100644 --- a/src/video.cpp +++ b/src/video.cpp @@ -89,10 +89,14 @@ class swdevice_t : public platf::hwdevice_t { data[1] = sw_frame->data[1] + offsetUV * 2; data[2] = nullptr; } - else { + else if (img.is_bgr) { // BGR0 data[1] = sw_frame->data[1] + offsetUV; data[2] = sw_frame->data[2] + offsetUV; data[3] = nullptr; + } else { // RGB0 + data[1] = sw_frame->data[2] + offsetUV; + data[2] = sw_frame->data[1] + offsetUV; + data[3] = nullptr; } int ret = sws_scale(sws.get(), (std::uint8_t *const *)&img.data, linesizes, 0, img.height, data, sw_frame->linesize);