diff --git a/components/viz/service/display/surface_aggregator.cc b/components/viz/service/display/surface_aggregator.cc index 989191eefdec2a..00cef152dc20c2 100644 --- a/components/viz/service/display/surface_aggregator.cc +++ b/components/viz/service/display/surface_aggregator.cc @@ -659,6 +659,8 @@ void SurfaceAggregator::AddColorConversionPass() { color_conversion_pass->SetNew(color_conversion_render_pass_id_, output_rect, root_render_pass->damage_rect, root_render_pass->transform_to_root_target); + color_conversion_pass->has_transparent_background = + root_render_pass->has_transparent_background; color_conversion_pass->color_space = output_color_space_; auto* shared_quad_state = diff --git a/gpu/ipc/service/direct_composition_child_surface_win.cc b/gpu/ipc/service/direct_composition_child_surface_win.cc index daa25f685b5210..ee825178d61c81 100644 --- a/gpu/ipc/service/direct_composition_child_surface_win.cc +++ b/gpu/ipc/service/direct_composition_child_surface_win.cc @@ -14,6 +14,7 @@ #include "base/win/windows_version.h" #include "ui/display/display_switches.h" #include "ui/gfx/native_widget_types.h" +#include "ui/gl/color_space_utils.h" #include "ui/gl/egl_util.h" #include "ui/gl/gl_angle_util_win.h" #include "ui/gl/gl_context.h" @@ -84,7 +85,6 @@ bool IsSwapChainTearingSupported() { }(); return supported; } - } // namespace DirectCompositionChildSurfaceWin::DirectCompositionChildSurfaceWin() = default; @@ -285,8 +285,8 @@ bool DirectCompositionChildSurfaceWin::SetDrawRectangle( // |real_surface_|. ui::ScopedReleaseCurrent release_current; - DXGI_FORMAT output_format = - is_hdr_ ? DXGI_FORMAT_R16G16B16A16_FLOAT : DXGI_FORMAT_B8G8R8A8_UNORM; + DXGI_FORMAT dxgi_format = gl::ColorSpaceUtils::GetDXGIFormat(color_space_); + if (enable_dc_layers_ && !dcomp_surface_) { TRACE_EVENT2("gpu", "DirectCompositionChildSurfaceWin::CreateSurface", "width", size_.width(), "height", size_.height()); @@ -294,7 +294,7 @@ bool DirectCompositionChildSurfaceWin::SetDrawRectangle( // Always treat as premultiplied, because an underlay could cause it to // become transparent. HRESULT hr = dcomp_device_->CreateSurface( - size_.width(), size_.height(), output_format, + size_.width(), size_.height(), dxgi_format, DXGI_ALPHA_MODE_PREMULTIPLIED, &dcomp_surface_); if (FAILED(hr)) { DLOG(ERROR) << "CreateSurface failed with error " << std::hex << hr; @@ -305,8 +305,6 @@ bool DirectCompositionChildSurfaceWin::SetDrawRectangle( "width", size_.width(), "height", size_.height()); dcomp_surface_.Reset(); - DXGI_ALPHA_MODE alpha_mode = - has_alpha_ ? DXGI_ALPHA_MODE_PREMULTIPLIED : DXGI_ALPHA_MODE_IGNORE; Microsoft::WRL::ComPtr dxgi_device; d3d11_device_.As(&dxgi_device); DCHECK(dxgi_device); @@ -320,14 +318,15 @@ bool DirectCompositionChildSurfaceWin::SetDrawRectangle( DXGI_SWAP_CHAIN_DESC1 desc = {}; desc.Width = size_.width(); desc.Height = size_.height(); - desc.Format = output_format; + desc.Format = dxgi_format; desc.Stereo = FALSE; desc.SampleDesc.Count = 1; desc.BufferCount = 2; desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; desc.Scaling = DXGI_SCALING_STRETCH; desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; - desc.AlphaMode = alpha_mode; + desc.AlphaMode = + has_alpha_ ? DXGI_ALPHA_MODE_PREMULTIPLIED : DXGI_ALPHA_MODE_IGNORE; desc.Flags = IsSwapChainTearingSupported() ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 0; HRESULT hr = dxgi_factory->CreateSwapChainForComposition( @@ -338,6 +337,11 @@ bool DirectCompositionChildSurfaceWin::SetDrawRectangle( << std::hex << hr; return false; } + Microsoft::WRL::ComPtr swap_chain; + if (SUCCEEDED(swap_chain_.As(&swap_chain))) { + swap_chain->SetColorSpace1( + gl::ColorSpaceUtils::GetDXGIColorSpace(color_space_)); + } } swap_rect_ = rectangle; @@ -396,11 +400,7 @@ bool DirectCompositionChildSurfaceWin::Resize(const gfx::Size& size, float scale_factor, ColorSpace color_space, bool has_alpha) { - bool size_changed = size != size_; - bool is_hdr = color_space == ColorSpace::SCRGB_LINEAR; - bool hdr_changed = is_hdr != is_hdr_; - bool alpha_changed = has_alpha != has_alpha_; - if (!size_changed && !hdr_changed && !alpha_changed) + if (size_ == size && has_alpha_ == has_alpha && color_space_ == color_space) return true; // This will release indirect references to swap chain (|real_surface_|) by @@ -408,14 +408,15 @@ bool DirectCompositionChildSurfaceWin::Resize(const gfx::Size& size, if (!ReleaseDrawTexture(true /* will_discard */)) return false; + bool resize_only = has_alpha_ == has_alpha && color_space_ == color_space; + size_ = size; - is_hdr_ = is_hdr; + color_space_ = color_space; has_alpha_ = has_alpha; // ResizeBuffers can't change alpha blending mode. - if (swap_chain_ && !alpha_changed) { - DXGI_FORMAT format = - is_hdr_ ? DXGI_FORMAT_R16G16B16A16_FLOAT : DXGI_FORMAT_B8G8R8A8_UNORM; + if (swap_chain_ && resize_only) { + DXGI_FORMAT format = gl::ColorSpaceUtils::GetDXGIFormat(color_space_); UINT flags = IsSwapChainTearingSupported() ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 0; HRESULT hr = swap_chain_->ResizeBuffers(2 /* BufferCount */, size.width(), diff --git a/gpu/ipc/service/direct_composition_child_surface_win.h b/gpu/ipc/service/direct_composition_child_surface_win.h index 52cbce9099e521..3ee8dcc9761829 100644 --- a/gpu/ipc/service/direct_composition_child_surface_win.h +++ b/gpu/ipc/service/direct_composition_child_surface_win.h @@ -61,9 +61,9 @@ class GPU_IPC_SERVICE_EXPORT DirectCompositionChildSurfaceWin gfx::Size size_ = gfx::Size(1, 1); bool enable_dc_layers_ = false; - bool is_hdr_ = false; bool has_alpha_ = true; bool vsync_enabled_ = true; + ColorSpace color_space_ = ColorSpace::UNSPECIFIED; // This is a placeholder surface used when not rendering to the // DirectComposition surface. diff --git a/third_party/blink/renderer/platform/graphics/color_space_gamut.cc b/third_party/blink/renderer/platform/graphics/color_space_gamut.cc index 1ca39aec8cb79d..7d3c1854c3fbc3 100644 --- a/third_party/blink/renderer/platform/graphics/color_space_gamut.cc +++ b/third_party/blink/renderer/platform/graphics/color_space_gamut.cc @@ -15,11 +15,17 @@ ColorSpaceGamut GetColorSpaceGamut(const WebScreenInfo& screen_info) { const gfx::ColorSpace& color_space = screen_info.color_space; if (!color_space.IsValid()) return ColorSpaceGamut::kUnknown; + // Return the gamut of the color space used for raster (this will return a // wide gamut for HDR profiles). + sk_sp sk_color_space = + color_space.GetRasterColorSpace().ToSkColorSpace(); + if (!sk_color_space) + return ColorSpaceGamut::kUnknown; + skcms_ICCProfile color_profile; - color_space.GetRasterColorSpace().ToSkColorSpace()->toProfile(&color_profile); - return color_space_utilities::GetColorSpaceGamut(&color_profile); + sk_color_space->toProfile(&color_profile); + return GetColorSpaceGamut(&color_profile); } ColorSpaceGamut GetColorSpaceGamut(const skcms_ICCProfile* color_profile) { diff --git a/ui/aura/test/test_screen.cc b/ui/aura/test/test_screen.cc index 29806203c467f0..ea51785b87e337 100644 --- a/ui/aura/test/test_screen.cc +++ b/ui/aura/test/test_screen.cc @@ -77,9 +77,10 @@ void TestScreen::SetDeviceScaleFactor(float device_scale_factor) { host_->OnHostResizedInPixels(bounds_in_pixel.size()); } -void TestScreen::SetColorSpace(const gfx::ColorSpace& color_space) { +void TestScreen::SetColorSpace(const gfx::ColorSpace& color_space, + float sdr_white_level) { display::Display display(GetPrimaryDisplay()); - display.set_color_space(color_space); + display.SetColorSpaceAndDepth(color_space, sdr_white_level); display_list().UpdateDisplay(display); } diff --git a/ui/aura/test/test_screen.h b/ui/aura/test/test_screen.h index 9cd689900a1f87..95208aceba78fb 100644 --- a/ui/aura/test/test_screen.h +++ b/ui/aura/test/test_screen.h @@ -37,7 +37,9 @@ class TestScreen : public display::ScreenBase, public WindowObserver { WindowTreeHost* CreateHostForPrimaryDisplay(Env* env = nullptr); void SetDeviceScaleFactor(float device_scale_fator); - void SetColorSpace(const gfx::ColorSpace& color_space); + void SetColorSpace( + const gfx::ColorSpace& color_space, + float sdr_white_level = gfx::ColorSpace::kDefaultSDRWhiteLevel); void SetDisplayRotation(display::Display::Rotation rotation); void SetUIScale(float ui_scale); void SetWorkAreaInsets(const gfx::Insets& insets); diff --git a/ui/aura/window_tree_host.cc b/ui/aura/window_tree_host.cc index f8cbd4ad7957e8..9fdcf7f338f925 100644 --- a/ui/aura/window_tree_host.cc +++ b/ui/aura/window_tree_host.cc @@ -422,7 +422,8 @@ void WindowTreeHost::InitCompositor() { display::Display display = display::Screen::GetScreen()->GetDisplayNearestWindow(window()); - compositor_->SetDisplayColorSpace(display.color_space()); + compositor_->SetDisplayColorSpace(display.color_space(), + display.sdr_white_level()); } void WindowTreeHost::OnAcceleratedWidgetAvailable() { @@ -480,7 +481,8 @@ void WindowTreeHost::OnHostDisplayChanged() { return; display::Display display = display::Screen::GetScreen()->GetDisplayNearestWindow(window()); - compositor_->SetDisplayColorSpace(display.color_space()); + compositor_->SetDisplayColorSpace(display.color_space(), + display.sdr_white_level()); } void WindowTreeHost::OnHostCloseRequested() { @@ -506,7 +508,8 @@ void WindowTreeHost::OnDisplayMetricsChanged(const display::Display& display, display::Screen* screen = display::Screen::GetScreen(); if (compositor_ && display.id() == screen->GetDisplayNearestView(window()).id()) { - compositor_->SetDisplayColorSpace(display.color_space()); + compositor_->SetDisplayColorSpace(display.color_space(), + display.sdr_white_level()); } } } diff --git a/ui/aura/window_tree_host_unittest.cc b/ui/aura/window_tree_host_unittest.cc index 9404b140b91c92..cd73b939d67ddc 100644 --- a/ui/aura/window_tree_host_unittest.cc +++ b/ui/aura/window_tree_host_unittest.cc @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "build/build_config.h" #include "ui/aura/test/aura_test_base.h" #include "ui/aura/test/test_cursor_client.h" #include "ui/aura/test/test_screen.h" @@ -83,10 +84,41 @@ TEST_F(WindowTreeHostTest, NoRewritesPostIME) { TEST_F(WindowTreeHostTest, ColorSpace) { EXPECT_EQ(gfx::ColorSpace::CreateSRGB(), host()->compositor()->output_color_space()); + + test_screen()->SetColorSpace(gfx::ColorSpace::CreateDisplayP3D65()); + EXPECT_EQ(gfx::ColorSpace::CreateDisplayP3D65(), + host()->compositor()->output_color_space()); +} + +#if defined(OS_WIN) +TEST_F(WindowTreeHostTest, ColorSpaceHDR) { + EXPECT_EQ(gfx::ColorSpace::CreateSRGB(), + host()->compositor()->output_color_space()); + + // UI compositor overrides HDR color space based on whether alpha blending is + // needed or not. test_screen()->SetColorSpace(gfx::ColorSpace::CreateSCRGBLinear()); + host()->compositor()->SetBackgroundColor(SK_ColorBLACK); + EXPECT_EQ(gfx::ColorSpace::CreateHDR10(), + host()->compositor()->output_color_space()); + + test_screen()->SetColorSpace(gfx::ColorSpace::CreateHDR10()); + host()->compositor()->SetBackgroundColor(SK_ColorTRANSPARENT); EXPECT_EQ(gfx::ColorSpace::CreateSCRGBLinear(), host()->compositor()->output_color_space()); + + // Setting SDR white level scales HDR color spaces but not SDR color spaces. + host()->compositor()->SetBackgroundColor(SK_ColorTRANSPARENT); + test_screen()->SetColorSpace(gfx::ColorSpace::CreateSCRGBLinear(), 200.f); + EXPECT_EQ(gfx::ColorSpace::CreateSCRGBLinear().GetScaledColorSpace( + gfx::ColorSpace::kDefaultSDRWhiteLevel / 200.f), + host()->compositor()->output_color_space()); + + test_screen()->SetColorSpace(gfx::ColorSpace::CreateSRGB(), 200.f); + EXPECT_EQ(gfx::ColorSpace::CreateSRGB(), + host()->compositor()->output_color_space()); } +#endif // OS_WIN class TestWindow : public ui::StubWindow { public: diff --git a/ui/compositor/compositor.cc b/ui/compositor/compositor.cc index cb4d038b4b051d..460ad0323a2a99 100644 --- a/ui/compositor/compositor.cc +++ b/ui/compositor/compositor.cc @@ -444,11 +444,30 @@ viz::LocalSurfaceIdAllocation Compositor::RequestNewChildLocalSurfaceId() { base::TimeTicks::Now()); } -void Compositor::SetDisplayColorSpace(const gfx::ColorSpace& color_space) { - if (output_color_space_ == color_space) +void Compositor::SetDisplayColorSpace(const gfx::ColorSpace& color_space, + float sdr_white_level) { + gfx::ColorSpace output_color_space = color_space; + +#if defined(OS_WIN) + // Ensure output color space for HDR is linear if we need alpha blending, and + // HDR10 (BT.2020 primaries with PQ transfer function) otherwise. + if (color_space.IsHDR()) { + bool transparent = SkColorGetA(host_->background_color()) != SK_AlphaOPAQUE; + output_color_space = transparent ? gfx::ColorSpace::CreateSCRGBLinear() + : gfx::ColorSpace::CreateHDR10(); + output_color_space = output_color_space.GetScaledColorSpace( + gfx::ColorSpace::kDefaultSDRWhiteLevel / sdr_white_level); + } +#endif // OS_WIN + + if (output_color_space_ == output_color_space && + sdr_white_level_ == sdr_white_level) { return; - output_color_space_ = color_space; + } + + output_color_space_ = output_color_space; blending_color_space_ = output_color_space_.GetBlendingColorSpace(); + sdr_white_level_ = sdr_white_level; // Do all ui::Compositor rasterization to sRGB because UI resources will not // have their color conversion results cached, and will suffer repeated // image color conversions. @@ -471,6 +490,8 @@ void Compositor::SetDisplayColorSpace(const gfx::ColorSpace& color_space) { void Compositor::SetBackgroundColor(SkColor color) { host_->set_background_color(color); + // Update color space based on whether background color is transparent. + SetDisplayColorSpace(output_color_space_, sdr_white_level_); ScheduleDraw(); } diff --git a/ui/compositor/compositor.h b/ui/compositor/compositor.h index 0242dfa3aaf59a..f7c3da2727287e 100644 --- a/ui/compositor/compositor.h +++ b/ui/compositor/compositor.h @@ -293,8 +293,11 @@ class COMPOSITOR_EXPORT Compositor : public cc::LayerTreeHostClient, // number. viz::LocalSurfaceIdAllocation RequestNewChildLocalSurfaceId(); - // Set the output color profile into which this compositor should render. - void SetDisplayColorSpace(const gfx::ColorSpace& color_space); + // Set the output color profile into which this compositor should render. Also + // sets the SDR white level (in nits) used to scale HDR color space primaries. + void SetDisplayColorSpace( + const gfx::ColorSpace& color_space, + float sdr_white_level = gfx::ColorSpace::kDefaultSDRWhiteLevel); // Returns the size of the widget that is being drawn to in pixel coordinates. const gfx::Size& size() const { return size_; } @@ -506,6 +509,8 @@ class COMPOSITOR_EXPORT Compositor : public cc::LayerTreeHostClient, gfx::ColorSpace output_color_space_; gfx::ColorSpace blending_color_space_; + float sdr_white_level_ = gfx::ColorSpace::kDefaultSDRWhiteLevel; + // If true, all paint commands are recorded at pixel size instead of DIP. const bool is_pixel_canvas_; diff --git a/ui/display/display.cc b/ui/display/display.cc index 585d2be1ff48ab..18cef1b9a4ffc8 100644 --- a/ui/display/display.cc +++ b/ui/display/display.cc @@ -24,8 +24,9 @@ namespace { constexpr int DEFAULT_BITS_PER_PIXEL = 24; constexpr int DEFAULT_BITS_PER_COMPONENT = 8; -constexpr int HDR_BITS_PER_PIXEL = 48; -constexpr int HDR_BITS_PER_COMPONENT = 16; +// Assuming HDR10 color space with RGB10A2 backbuffer. +constexpr int HDR_BITS_PER_PIXEL = 30; +constexpr int HDR_BITS_PER_COMPONENT = 10; // This variable tracks whether the forced device scale factor switch needs to // be read from the command line, i.e. if it is set to -1 then the command line @@ -209,12 +210,10 @@ Display::Display(int64_t id, const gfx::Rect& bounds) : id_(id), bounds_(bounds), work_area_(bounds), - device_scale_factor_(GetForcedDeviceScaleFactor()), - color_space_(gfx::ColorSpace::CreateSRGB()), - color_depth_(DEFAULT_BITS_PER_PIXEL), - depth_per_component_(DEFAULT_BITS_PER_COMPONENT) { - if (HasForceDisplayColorProfile()) - SetColorSpaceAndDepth(GetForcedDisplayColorProfile()); + device_scale_factor_(GetForcedDeviceScaleFactor()) { + SetColorSpaceAndDepth(HasForceDisplayColorProfile() + ? GetForcedDisplayColorProfile() + : gfx::ColorSpace::CreateSRGB()); #if defined(USE_AURA) SetScaleAndBounds(device_scale_factor_, bounds); #endif @@ -298,8 +297,11 @@ void Display::SetSize(const gfx::Size& size_in_pixel) { SetScaleAndBounds(device_scale_factor_, gfx::Rect(origin, size_in_pixel)); } -void Display::SetColorSpaceAndDepth(const gfx::ColorSpace& color_space) { +void Display::SetColorSpaceAndDepth(const gfx::ColorSpace& color_space, + float sdr_white_level) { color_space_ = color_space; + sdr_white_level_ = sdr_white_level; + // Assuming HDR10 color space and buffer format. if (color_space_.IsHDR()) { color_depth_ = HDR_BITS_PER_PIXEL; depth_per_component_ = HDR_BITS_PER_COMPONENT; diff --git a/ui/display/display.h b/ui/display/display.h index 53f3e95c8243da..d38e37fd4baa2a 100644 --- a/ui/display/display.h +++ b/ui/display/display.h @@ -228,9 +228,14 @@ class DISPLAY_EXPORT Display final { color_space_ = color_space; } - // Set the color space of the display and reset the color depth and depth per - // component based on whether or not the color space is HDR. - void SetColorSpaceAndDepth(const gfx::ColorSpace& color_space); + // SDR white level used to scale HDR color spaces. + float sdr_white_level() const { return sdr_white_level_; } + + // Set the color space and SDR white level of the display, and reset the color + // depth and depth per component based on whether the color space is HDR. + void SetColorSpaceAndDepth( + const gfx::ColorSpace& color_space, + float sdr_white_level = gfx::ColorSpace::kDefaultSDRWhiteLevel); // The number of bits per pixel. Used by media query APIs. int color_depth() const { return color_depth_; } @@ -256,7 +261,7 @@ class DISPLAY_EXPORT Display final { private: friend struct mojo::StructTraits; - int64_t id_; + int64_t id_ = kInvalidDisplayId; gfx::Rect bounds_; // If non-empty, then should be same size as |bounds_|. Used to avoid rounding // errors. @@ -270,6 +275,7 @@ class DISPLAY_EXPORT Display final { // NOTE: this is not currently written to the mojom as it is not used in // aura. gfx::ColorSpace color_space_; + float sdr_white_level_; int color_depth_; int depth_per_component_; bool is_monochrome_ = false; diff --git a/ui/display/display_list.cc b/ui/display/display_list.cc index 9edacb7399ea8d..177aa33246cfc2 100644 --- a/ui/display/display_list.cc +++ b/ui/display/display_list.cc @@ -93,8 +93,10 @@ uint32_t DisplayList::UpdateDisplay(const Display& display, Type type) { local_display->set_device_scale_factor(display.device_scale_factor()); changed_values |= DisplayObserver::DISPLAY_METRIC_DEVICE_SCALE_FACTOR; } - if (local_display->color_space() != display.color_space()) { - local_display->set_color_space(display.color_space()); + if (local_display->color_space() != display.color_space() || + local_display->sdr_white_level() != display.sdr_white_level()) { + local_display->SetColorSpaceAndDepth(display.color_space(), + display.sdr_white_level()); changed_values |= DisplayObserver::DISPLAY_METRIC_COLOR_SPACE; } if (should_notify_observers()) { diff --git a/ui/display/display_unittest.cc b/ui/display/display_unittest.cc index 8fb0a0fdcf7cca..7f90962d08c9b8 100644 --- a/ui/display/display_unittest.cc +++ b/ui/display/display_unittest.cc @@ -76,9 +76,14 @@ TEST(DisplayTest, DisplayHDRValues) { EXPECT_EQ(24, display.color_depth()); EXPECT_EQ(8, display.depth_per_component()); + // All HDR color spaces report the same bit depth as HDR10. + display.SetColorSpaceAndDepth(gfx::ColorSpace::CreateHDR10()); + EXPECT_EQ(30, display.color_depth()); + EXPECT_EQ(10, display.depth_per_component()); + display.SetColorSpaceAndDepth(gfx::ColorSpace::CreateSCRGBLinear()); - EXPECT_EQ(48, display.color_depth()); - EXPECT_EQ(16, display.depth_per_component()); + EXPECT_EQ(30, display.color_depth()); + EXPECT_EQ(10, display.depth_per_component()); display.SetColorSpaceAndDepth(gfx::ColorSpace::CreateSRGB()); EXPECT_EQ(24, display.color_depth()); diff --git a/ui/display/manager/display_manager.cc b/ui/display/manager/display_manager.cc index 8a456e81048478..e755be61378d3d 100644 --- a/ui/display/manager/display_manager.cc +++ b/ui/display/manager/display_manager.cc @@ -2097,7 +2097,7 @@ Display DisplayManager::CreateDisplayFromDisplayInfoById(int64_t id) { new_display.set_rotation(display_info.GetActiveRotation()); new_display.set_touch_support(display_info.touch_support()); new_display.set_maximum_cursor_size(display_info.maximum_cursor_size()); - new_display.set_color_space(display_info.color_space()); + new_display.SetColorSpaceAndDepth(display_info.color_space()); if (internal_display_has_accelerometer_ && Display::IsInternalDisplayId(id)) { new_display.set_accelerometer_support( diff --git a/ui/display/win/screen_win.cc b/ui/display/win/screen_win.cc index cb17d76dd94f59..cf47db26995166 100644 --- a/ui/display/win/screen_win.cc +++ b/ui/display/win/screen_win.cc @@ -181,9 +181,10 @@ Display CreateDisplayFromDisplayInfo(const DisplayInfo& display_info, display.set_rotation(display_info.rotation()); if (!Display::HasForceDisplayColorProfile()) { if (hdr_enabled) { - display.SetColorSpaceAndDepth( - gfx::ColorSpace::CreateSCRGBLinear().GetScaledColorSpace( - 80.0 / display_info.sdr_white_level())); + // It doesn't matter what HDR color space we set since UI compositor will + // override it to HDR10 if opaque or SCRGB linear if translucent. + display.SetColorSpaceAndDepth(gfx::ColorSpace::CreateHDR10(), + display_info.sdr_white_level()); } else { display.SetColorSpaceAndDepth( color_profile_reader->GetDisplayColorSpace(display_info.id())); diff --git a/ui/gfx/color_space.cc b/ui/gfx/color_space.cc index 3549274122e6a1..d94a1c6841b161 100644 --- a/ui/gfx/color_space.cc +++ b/ui/gfx/color_space.cc @@ -43,7 +43,8 @@ static bool FloatsEqualWithinTolerance(const float* a, } // namespace // static -int ColorSpace::kInvalidId = -1; +constexpr int ColorSpace::kInvalidId; +constexpr float ColorSpace::kDefaultSDRWhiteLevel; ColorSpace::ColorSpace(PrimaryID primaries, TransferID transfer) diff --git a/ui/gfx/color_space.h b/ui/gfx/color_space.h index 75ad4a4e8a1956..cb72649b715402 100644 --- a/ui/gfx/color_space.h +++ b/ui/gfx/color_space.h @@ -210,7 +210,9 @@ class COLOR_SPACE_EXPORT ColorSpace { // Generates a process global unique ID that can be used to key a color space. static int GetNextId(); - static int kInvalidId; + static constexpr int kInvalidId = -1; + + static constexpr float kDefaultSDRWhiteLevel = 80.f; bool operator==(const ColorSpace& other) const; bool operator!=(const ColorSpace& other) const; diff --git a/ui/gl/color_space_utils.cc b/ui/gl/color_space_utils.cc index b342b9fb7d8e46..008db391464476 100644 --- a/ui/gl/color_space_utils.cc +++ b/ui/gl/color_space_utils.cc @@ -30,4 +30,25 @@ GLSurface::ColorSpace ColorSpaceUtils::GetGLSurfaceColorSpace( return GLSurface::ColorSpace::UNSPECIFIED; } +#if defined(OS_WIN) +DXGI_COLOR_SPACE_TYPE ColorSpaceUtils::GetDXGIColorSpace( + GLSurface::ColorSpace color_space) { + if (color_space == GLSurface::ColorSpace::SCRGB_LINEAR) + return DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709; + else if (color_space == GLSurface::ColorSpace::HDR10) + return DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020; + else + return DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709; +} + +DXGI_FORMAT ColorSpaceUtils::GetDXGIFormat(GLSurface::ColorSpace color_space) { + if (color_space == GLSurface::ColorSpace::SCRGB_LINEAR) + return DXGI_FORMAT_R16G16B16A16_FLOAT; + else if (color_space == GLSurface::ColorSpace::HDR10) + return DXGI_FORMAT_R10G10B10A2_UNORM; + else + return DXGI_FORMAT_B8G8R8A8_UNORM; +} +#endif // OS_WIN + } // namespace gl diff --git a/ui/gl/color_space_utils.h b/ui/gl/color_space_utils.h index 5b491886c98b44..ead0918cc19d52 100644 --- a/ui/gl/color_space_utils.h +++ b/ui/gl/color_space_utils.h @@ -5,9 +5,15 @@ #ifndef UI_GL_COLOR_SPACE_UTILS_H_ #define UI_GL_COLOR_SPACE_UTILS_H_ +#include "build/build_config.h" #include "ui/gl/gl_export.h" #include "ui/gl/gl_surface.h" +#if defined(OS_WIN) +#include +#include +#endif // OS_WIN + typedef unsigned int GLenum; namespace gfx { @@ -24,6 +30,15 @@ class GL_EXPORT ColorSpaceUtils { // Get the color space used for GLSurface::Resize(). static GLSurface::ColorSpace GetGLSurfaceColorSpace( const gfx::ColorSpace& color_space); + +#if defined(OS_WIN) + // Get DXGI color space for swap chain. + static DXGI_COLOR_SPACE_TYPE GetDXGIColorSpace( + GLSurface::ColorSpace color_space); + + // Get DXGI format for swap chain. + static DXGI_FORMAT GetDXGIFormat(GLSurface::ColorSpace color_space); +#endif // OS_WIN }; } // namespace gl