Index: gpu/ipc/service/direct_composition_surface_win.cc |
diff --git a/gpu/ipc/service/direct_composition_surface_win.cc b/gpu/ipc/service/direct_composition_surface_win.cc |
index a28ad409d2680fce285faee3eb28b04ee127f984..ac184e96e62625f2d9ebf3fb886cc2998e6d0867 100644 |
--- a/gpu/ipc/service/direct_composition_surface_win.cc |
+++ b/gpu/ipc/service/direct_composition_surface_win.cc |
@@ -7,6 +7,7 @@ |
#include <d3d11_1.h> |
#include <dcomptypes.h> |
+#include "base/feature_list.h" |
#include "base/memory/ptr_util.h" |
#include "base/metrics/histogram_macros.h" |
#include "base/optional.h" |
@@ -18,6 +19,7 @@ |
#include "gpu/ipc/service/gpu_channel_manager_delegate.h" |
#include "gpu/ipc/service/switches.h" |
#include "ui/display/display_switches.h" |
+#include "ui/gfx/color_space_win.h" |
#include "ui/gfx/geometry/size_conversions.h" |
#include "ui/gfx/native_widget_types.h" |
#include "ui/gfx/transform.h" |
@@ -42,6 +44,11 @@ |
namespace gpu { |
namespace { |
+// Some drivers fail to correctly handle BT.709 video in overlays. This flag |
+// converts them to BT.601 in the video processor. |
+const base::Feature kFallbackBT709VideoToBT601{ |
+ "FallbackBT709VideoToBT601", base::FEATURE_ENABLED_BY_DEFAULT}; |
+ |
// This class is used to make sure a specified surface isn't current, and upon |
// destruction it will make the surface current again if it had been before. |
class ScopedReleaseCurrent { |
@@ -179,6 +186,7 @@ class DCLayerTree::SwapChainPresenter { |
gfx::Size swap_chain_size_; |
gfx::Size processor_input_size_; |
gfx::Size processor_output_size_; |
+ bool is_yuy2_swapchain_ = false; |
// This is the scale from the swapchain size to the size of the contents |
// onscreen. |
@@ -327,6 +335,47 @@ void DCLayerTree::SwapChainPresenter::PresentToSwapChain( |
out_view_.Receive()); |
CHECK(SUCCEEDED(hr)); |
} |
+ |
+ // TODO(jbauman): Use correct colorspace. |
+ gfx::ColorSpace src_color_space = gfx::ColorSpace::CreateREC709(); |
+ base::win::ScopedComPtr<ID3D11VideoContext1> context1; |
+ if (SUCCEEDED(video_context_.QueryInterface(context1.Receive()))) { |
+ context1->VideoProcessorSetStreamColorSpace1( |
+ video_processor_.get(), 0, |
+ gfx::ColorSpaceWin::GetDXGIColorSpace(src_color_space)); |
+ } else { |
+ // This can't handle as many different types of color spaces, so use it |
+ // only if ID3D11VideoContext1 isn't available. |
+ D3D11_VIDEO_PROCESSOR_COLOR_SPACE color_space = |
+ gfx::ColorSpaceWin::GetD3D11ColorSpace(src_color_space); |
+ video_context_->VideoProcessorSetStreamColorSpace(video_processor_.get(), 0, |
+ &color_space); |
+ } |
+ |
+ gfx::ColorSpace output_color_space = |
+ is_yuy2_swapchain_ ? src_color_space : gfx::ColorSpace::CreateSRGB(); |
+ if (base::FeatureList::IsEnabled(kFallbackBT709VideoToBT601) && |
+ (output_color_space == gfx::ColorSpace::CreateREC709())) { |
+ output_color_space = gfx::ColorSpace::CreateREC601(); |
+ } |
+ |
+ base::win::ScopedComPtr<IDXGISwapChain3> swap_chain3; |
+ if (SUCCEEDED(swap_chain_.QueryInterface(swap_chain3.Receive()))) { |
+ DXGI_COLOR_SPACE_TYPE color_space = |
+ gfx::ColorSpaceWin::GetDXGIColorSpace(output_color_space); |
+ HRESULT hr = swap_chain3->SetColorSpace1(color_space); |
+ CHECK(SUCCEEDED(hr)); |
+ if (context1) { |
+ context1->VideoProcessorSetOutputColorSpace1(video_processor_.get(), |
+ color_space); |
+ } else { |
+ D3D11_VIDEO_PROCESSOR_COLOR_SPACE d3d11_color_space = |
+ gfx::ColorSpaceWin::GetD3D11ColorSpace(output_color_space); |
+ video_context_->VideoProcessorSetOutputColorSpace(video_processor_.get(), |
+ &d3d11_color_space); |
+ } |
+ } |
+ |
{ |
D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC in_desc = {}; |
in_desc.ViewDimension = D3D11_VPIV_DIMENSION_TEXTURE2D; |
@@ -426,37 +475,28 @@ void DCLayerTree::SwapChainPresenter::ReallocateSwapChain() { |
&handle); |
swap_chain_handle_.Set(handle); |
+ is_yuy2_swapchain_ = true; |
// The composition surface handle isn't actually used, but |
// CreateSwapChainForComposition can't create YUY2 swapchains. |
HRESULT hr = media_factory->CreateSwapChainForCompositionSurfaceHandle( |
d3d11_device_.get(), swap_chain_handle_.Get(), &desc, nullptr, |
swap_chain_.Receive()); |
- bool yuy2_swapchain = true; |
- |
if (FAILED(hr)) { |
// This should not be hit in production but is a simple fallback for |
// testing on systems without YUY2 swapchain support. |
DLOG(ERROR) << "YUY2 creation failed with " << std::hex << hr |
<< ". Falling back to BGRA"; |
+ is_yuy2_swapchain_ = false; |
desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; |
desc.Flags = 0; |
hr = media_factory->CreateSwapChainForCompositionSurfaceHandle( |
d3d11_device_.get(), swap_chain_handle_.Get(), &desc, nullptr, |
swap_chain_.Receive()); |
CHECK(SUCCEEDED(hr)); |
- yuy2_swapchain = false; |
- } else { |
- // This is a sensible default colorspace for most videos. |
- // TODO(jbauman): Use correct colorspace. |
- base::win::ScopedComPtr<IDXGISwapChain3> swap_chain3; |
- swap_chain_.QueryInterface(swap_chain3.Receive()); |
- hr = swap_chain3->SetColorSpace1( |
- DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P709); |
- CHECK(SUCCEEDED(hr)); |
} |
UMA_HISTOGRAM_BOOLEAN("GPU.DirectComposition.SwapchainFormat", |
- yuy2_swapchain); |
+ is_yuy2_swapchain_); |
out_view_.Reset(); |
} |