Commit 87d504a0 authored by Maggie Chen's avatar Maggie Chen Committed by Commit Bot

Adjust the overlay size to fit the screen when in fullscreen mode on Windows

In order to get the DWM full screen optimization and save power, the
overlay size must match the screen size when in fullscreen mode. If
there are a few pixels off, this CL adjusts the overlay size to fit the
screen.

Remove |disable_larger_than_screen_overlays| workaround since this is
now handled by this fullscreen size adjustment function.

Bug: 720059, 1027046
Change-Id: I08feb0ec42d0ae3157e64edac4b467795cf426f4
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2508203
Commit-Queue: Maggie Chen <magchen@chromium.org>
Reviewed-by: default avatarSunny Sachanandani <sunnyps@chromium.org>
Cr-Commit-Position: refs/heads/master@{#826943}
parent 352c4ce6
......@@ -2071,22 +2071,6 @@
"force_high_performance_gpu"
]
},
{
"id": 229,
"description": "Overlay sizes bigger than screen aren't accelerated on some Intel drivers",
"cr_bugs": [720059],
"os": {
"type": "win"
},
"vendor_id": "0x8086",
"driver_version": {
"op": "<",
"value": "21.20.16.4542"
},
"features": [
"disable_larger_than_screen_overlays"
]
},
{
"id": 231,
"description": "Multisampled color renderbuffers can't be resized on Qualcomm 4xx/5xx",
......
......@@ -38,7 +38,6 @@ disable_ext_draw_buffers
disable_gl_rgb_format
disable_half_float_for_gmb
disable_imagebitmap_from_video_using_gpu
disable_larger_than_screen_overlays
disable_mediafoundation_async_h264_encoding
disable_multisampling_color_mask_usage
disable_nv12_dxgi_video
......
......@@ -29,8 +29,6 @@ CreateDirectCompositionSurfaceSettings(
gl::DirectCompositionSurfaceWin::Settings settings;
settings.disable_nv12_dynamic_textures =
workarounds.disable_nv12_dynamic_textures;
settings.disable_larger_than_screen_overlays =
workarounds.disable_larger_than_screen_overlays;
settings.disable_vp_scaling = workarounds.disable_vp_scaling;
settings.use_angle_texture_offset = features::IsUsingSkiaRenderer();
settings.reset_vp_when_colorspace_changes =
......
......@@ -20,11 +20,9 @@ bool SizeContains(const gfx::Size& a, const gfx::Size& b) {
} // namespace
DCLayerTree::DCLayerTree(bool disable_nv12_dynamic_textures,
bool disable_larger_than_screen_overlays,
bool disable_vp_scaling,
bool reset_vp_when_colorspace_changes)
: disable_nv12_dynamic_textures_(disable_nv12_dynamic_textures),
disable_larger_than_screen_overlays_(disable_larger_than_screen_overlays),
disable_vp_scaling_(disable_vp_scaling),
reset_vp_when_colorspace_changes_(reset_vp_when_colorspace_changes) {}
......@@ -34,6 +32,8 @@ bool DCLayerTree::Initialize(
HWND window,
Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device,
Microsoft::WRL::ComPtr<IDCompositionDevice2> dcomp_device) {
DCHECK(window);
window_ = window;
DCHECK(d3d11_device);
d3d11_device_ = std::move(d3d11_device);
DCHECK(dcomp_device);
......@@ -44,7 +44,7 @@ bool DCLayerTree::Initialize(
DCHECK(desktop_device);
HRESULT hr =
desktop_device->CreateTargetForHwnd(window, TRUE, &dcomp_target_);
desktop_device->CreateTargetForHwnd(window_, TRUE, &dcomp_target_);
if (FAILED(hr)) {
DLOG(ERROR) << "CreateTargetForHwnd failed with error 0x" << std::hex << hr;
return false;
......@@ -200,6 +200,16 @@ DCLayerTree::GetLayerSwapChainForTesting(size_t index) const {
return nullptr;
}
void DCLayerTree::GetSwapChainVisualInfoForTesting(size_t index,
gfx::Transform* transform,
gfx::Point* offset,
gfx::Rect* clip_rect) const {
if (index < video_swap_chains_.size()) {
video_swap_chains_[index]->GetSwapChainVisualInfoForTesting( // IN-TEST
transform, offset, clip_rect);
}
}
bool DCLayerTree::CommitAndClearPendingOverlays(
DirectCompositionChildSurfaceWin* root_surface) {
TRACE_EVENT1("gpu", "DCLayerTree::CommitAndClearPendingOverlays",
......@@ -250,7 +260,7 @@ bool DCLayerTree::CommitAndClearPendingOverlays(
new_video_swap_chains.emplace_back(std::move(video_swap_chains_[i]));
} else {
new_video_swap_chains.emplace_back(std::make_unique<SwapChainPresenter>(
this, d3d11_device_, dcomp_device_));
this, window_, d3d11_device_, dcomp_device_));
if (frame_rate_ > 0)
new_video_swap_chains.back()->SetFrameRate(frame_rate_);
}
......
......@@ -29,7 +29,6 @@ class SwapChainPresenter;
class DCLayerTree {
public:
DCLayerTree(bool disable_nv12_dynamic_textures,
bool disable_larger_than_screen_overlays,
bool disable_vp_scaling,
bool reset_vp_when_colorspace_changes);
~DCLayerTree();
......@@ -65,10 +64,6 @@ class DCLayerTree {
return disable_nv12_dynamic_textures_;
}
bool disable_larger_than_screen_overlays() const {
return disable_larger_than_screen_overlays_;
}
bool disable_vp_scaling() const { return disable_vp_scaling_; }
const Microsoft::WRL::ComPtr<ID3D11VideoDevice>& video_device() const {
......@@ -91,12 +86,19 @@ class DCLayerTree {
Microsoft::WRL::ComPtr<IDXGISwapChain1> GetLayerSwapChainForTesting(
size_t index) const;
void GetSwapChainVisualInfoForTesting(size_t index,
gfx::Transform* transform,
gfx::Point* offset,
gfx::Rect* clip_rect) const;
void SetFrameRate(float frame_rate);
const std::unique_ptr<HDRMetadataHelperWin>& GetHDRMetadataHelper() {
return hdr_metadata_helper_;
}
HWND window() const { return window_; }
private:
void SetColorSpaceForVideoProcessor(
const gfx::ColorSpace& input_color_space,
......@@ -105,10 +107,10 @@ class DCLayerTree {
bool is_yuv_swapchain);
const bool disable_nv12_dynamic_textures_;
const bool disable_larger_than_screen_overlays_;
const bool disable_vp_scaling_;
const bool reset_vp_when_colorspace_changes_;
HWND window_;
Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device_;
Microsoft::WRL::ComPtr<IDCompositionDevice2> dcomp_device_;
Microsoft::WRL::ComPtr<IDCompositionTarget> dcomp_target_;
......
......@@ -82,8 +82,11 @@ bool CheckOverlayColorSpaceSupport(
DXGI_OVERLAY_COLOR_SPACE_SUPPORT_FLAG_PRESENT);
}
// Used for workaround limiting overlay size to monitor size.
gfx::Size g_overlay_monitor_size;
// Used for adjusting overlay size to monitor size.
gfx::Size g_primary_monitor_size;
// The number of all visible display monitors on a desktop.
int g_num_of_monitors = 0;
DirectCompositionSurfaceWin::OverlayHDRInfoUpdateCallback
g_overlay_hdr_gpu_info_callback;
......@@ -127,8 +130,7 @@ void GetGpuDriverOverlayInfo(bool* supports_overlays,
UINT* nv12_overlay_support_flags,
UINT* yuy2_overlay_support_flags,
UINT* bgra8_overlay_support_flags,
UINT* rgb10a2_overlay_support_flags,
gfx::Size* overlay_monitor_size) {
UINT* rgb10a2_overlay_support_flags) {
// Initialization
*supports_overlays = false;
*overlay_format_used = DXGI_FORMAT_NV12;
......@@ -137,7 +139,6 @@ void GetGpuDriverOverlayInfo(bool* supports_overlays,
*yuy2_overlay_support_flags = 0;
*bgra8_overlay_support_flags = 0;
*rgb10a2_overlay_support_flags = 0;
*overlay_monitor_size = gfx::Size();
// Check for DirectComposition support first to prevent likely crashes.
if (!DirectCompositionSurfaceWin::IsDirectCompositionSupported())
......@@ -227,13 +228,6 @@ void GetGpuDriverOverlayInfo(bool* supports_overlays,
*bgra8_overlay_support_flags = *yuy2_overlay_support_flags;
}
if (*supports_overlays) {
DXGI_OUTPUT_DESC monitor_desc = {};
if (SUCCEEDED(output3->GetDesc(&monitor_desc))) {
*overlay_monitor_size =
gfx::Rect(monitor_desc.DesktopCoordinates).size();
}
}
// RGB10A2 overlay is used for displaying HDR content. In Intel's
// platform, RGB10A2 overlay is enabled only when
// DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020 is supported.
......@@ -272,10 +266,6 @@ void GetGpuDriverOverlayInfo(bool* supports_overlays,
// Software overlays always use NV12 because it's slightly more efficient and
// YUY2 was only used because Skylake doesn't support NV12 hardware overlays.
*overlay_format_used = DXGI_FORMAT_NV12;
// This is only needed for https://crbug.com/720059 which is Intel only -- it
// doesn't affect software overlays.
*overlay_monitor_size = gfx::Size();
}
void UpdateOverlaySupport() {
......@@ -290,13 +280,11 @@ void UpdateOverlaySupport() {
UINT yuy2_overlay_support_flags = 0;
UINT bgra8_overlay_support_flags = 0;
UINT rgb10a2_overlay_support_flags = 0;
gfx::Size overlay_monitor_size = gfx::Size();
GetGpuDriverOverlayInfo(
&supports_overlays, &overlay_format_used, &overlay_format_used_hdr,
&nv12_overlay_support_flags, &yuy2_overlay_support_flags,
&bgra8_overlay_support_flags, &rgb10a2_overlay_support_flags,
&overlay_monitor_size);
&bgra8_overlay_support_flags, &rgb10a2_overlay_support_flags);
if (g_force_nv12_overlay_support) {
supports_overlays = true;
......@@ -339,13 +327,25 @@ void UpdateOverlaySupport() {
bgra8_overlay_support_flags, rgb10a2_overlay_support_flags);
g_overlay_format_used = overlay_format_used;
g_overlay_format_used_hdr = overlay_format_used_hdr;
g_overlay_monitor_size = overlay_monitor_size;
}
void RunOverlayHdrGpuInfoUpdateCallback() {
if (g_overlay_hdr_gpu_info_callback)
g_overlay_hdr_gpu_info_callback.Run();
}
void UpdateMonitorInfo() {
g_num_of_monitors = GetSystemMetrics(SM_CMONITORS);
MONITORINFO monitor_info;
monitor_info.cbSize = sizeof(monitor_info);
if (GetMonitorInfo(MonitorFromWindow(nullptr, MONITOR_DEFAULTTOPRIMARY),
&monitor_info)) {
g_primary_monitor_size = gfx::Rect(monitor_info.rcMonitor).size();
} else {
g_primary_monitor_size = gfx::Size();
}
}
} // namespace
DirectCompositionSurfaceWin::DirectCompositionSurfaceWin(
......@@ -361,7 +361,6 @@ DirectCompositionSurfaceWin::DirectCompositionSurfaceWin(
settings.force_root_surface_full_damage)),
layer_tree_(std::make_unique<DCLayerTree>(
settings.disable_nv12_dynamic_textures,
settings.disable_larger_than_screen_overlays,
settings.disable_vp_scaling,
settings.reset_vp_when_colorspace_changes)) {
ui::GpuSwitchingManager::GetInstance()->AddObserver(this);
......@@ -512,8 +511,13 @@ UINT DirectCompositionSurfaceWin::GetOverlaySupportFlags(DXGI_FORMAT format) {
}
// static
gfx::Size DirectCompositionSurfaceWin::GetOverlayMonitorSize() {
return g_overlay_monitor_size;
gfx::Size DirectCompositionSurfaceWin::GetPrimaryMonitorSize() {
return g_primary_monitor_size;
}
// static
int DirectCompositionSurfaceWin::GetNumOfMonitors() {
return g_num_of_monitors;
}
// static
......@@ -698,6 +702,7 @@ bool DirectCompositionSurfaceWin::Initialize(GLSurfaceFormat format) {
if (!root_surface_->Initialize(GLSurfaceFormat()))
return false;
UpdateMonitorInfo();
return true;
}
......@@ -840,16 +845,20 @@ void DirectCompositionSurfaceWin::OnGpuSwitched(
void DirectCompositionSurfaceWin::OnDisplayAdded() {
InvalidateOverlayCaps();
UpdateOverlaySupport();
UpdateMonitorInfo();
RunOverlayHdrGpuInfoUpdateCallback();
}
void DirectCompositionSurfaceWin::OnDisplayRemoved() {
InvalidateOverlayCaps();
UpdateOverlaySupport();
UpdateMonitorInfo();
RunOverlayHdrGpuInfoUpdateCallback();
}
void DirectCompositionSurfaceWin::OnDisplayMetricsChanged() {}
void DirectCompositionSurfaceWin::OnDisplayMetricsChanged() {
UpdateMonitorInfo();
}
scoped_refptr<base::TaskRunner>
DirectCompositionSurfaceWin::GetWindowTaskRunnerForTesting() {
......@@ -871,4 +880,20 @@ DirectCompositionSurfaceWin::GetRootSurfaceForTesting() const {
return root_surface_;
}
void DirectCompositionSurfaceWin::GetSwapChainVisualInfoForTesting(
size_t index,
gfx::Transform* transform,
gfx::Point* offset,
gfx::Rect* clip_rect) const {
layer_tree_->GetSwapChainVisualInfoForTesting( // IN-TEST
index, transform, offset, clip_rect);
}
void DirectCompositionSurfaceWin::SetMonitorInfoForTesting(
int num_of_monitors,
gfx::Size monitor_size) {
g_num_of_monitors = num_of_monitors;
g_primary_monitor_size = monitor_size;
}
} // namespace gl
......@@ -12,6 +12,7 @@
#include "base/callback.h"
#include "base/time/time.h"
#include "ui/gfx/transform.h"
#include "ui/gl/child_window_win.h"
#include "ui/gl/gl_export.h"
#include "ui/gl/gl_surface_egl.h"
......@@ -31,7 +32,6 @@ class GL_EXPORT DirectCompositionSurfaceWin : public GLSurfaceEGL,
struct Settings {
bool disable_nv12_dynamic_textures = false;
bool disable_larger_than_screen_overlays = false;
bool disable_vp_scaling = false;
size_t max_pending_frames = 2;
bool use_angle_texture_offset = false;
......@@ -73,7 +73,10 @@ class GL_EXPORT DirectCompositionSurfaceWin : public GLSurfaceEGL,
static DXGI_FORMAT GetOverlayFormatUsedForSDR();
// Returns monitor size.
static gfx::Size GetOverlayMonitorSize();
static gfx::Size GetPrimaryMonitorSize();
// Get the current number of all visible display monitors on the desktop.
static int GetNumOfMonitors();
// Returns overlay support flags for the given format.
// Caller should check for DXGI_OVERLAY_SUPPORT_FLAG_DIRECT and
......@@ -160,6 +163,13 @@ class GL_EXPORT DirectCompositionSurfaceWin : public GLSurfaceEGL,
scoped_refptr<DirectCompositionChildSurfaceWin> GetRootSurfaceForTesting()
const;
void GetSwapChainVisualInfoForTesting(size_t index,
gfx::Transform* transform,
gfx::Point* offset,
gfx::Rect* clip_rect) const;
void SetMonitorInfoForTesting(int num_of_monitors, gfx::Size monitor_size);
protected:
~DirectCompositionSurfaceWin() override;
......
......@@ -21,6 +21,7 @@
#include "ui/base/win/hidden_window.h"
#include "ui/gfx/buffer_format_util.h"
#include "ui/gfx/gdi_util.h"
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/gfx/transform.h"
#include "ui/gl/dc_renderer_layer_params.h"
#include "ui/gl/direct_composition_child_surface_win.h"
......@@ -1051,6 +1052,7 @@ TEST_F(DirectCompositionPixelTest, ResizeVideoLayer) {
ASSERT_TRUE(image_dxgi->InitializeHandle(base::win::ScopedHandle(handle), 0,
gfx::BufferFormat::RGBA_8888));
// (1) Test if swap chain is overridden to content rect size (50, 50).
{
ui::DCRendererLayerParams params;
params.images[0] = image_dxgi;
......@@ -1072,6 +1074,7 @@ TEST_F(DirectCompositionPixelTest, ResizeVideoLayer) {
EXPECT_EQ(desc.Width, 50u);
EXPECT_EQ(desc.Height, 50u);
// (2) Test if swap chain is overridden to content rect size (30, 30).
{
ui::DCRendererLayerParams params;
params.images[0] = image_dxgi;
......@@ -1087,6 +1090,74 @@ TEST_F(DirectCompositionPixelTest, ResizeVideoLayer) {
EXPECT_TRUE(SUCCEEDED(swap_chain->GetDesc1(&desc)));
EXPECT_EQ(desc.Width, 30u);
EXPECT_EQ(desc.Height, 30u);
// (3) Test if swap chain is adjusted to fit the monitor when overlay scaling
// is not supported and video on-screen size is slightly smaller than the
// monitor. Clipping is on.
DirectCompositionSurfaceWin::SetScaledOverlaysSupportedForTesting(false);
gfx::Size monitor_size = window_size;
surface_->SetMonitorInfoForTesting(1, window_size);
gfx::Rect on_screen_rect =
gfx::Rect(0, 0, monitor_size.width() - 2, monitor_size.height() - 2);
{
ui::DCRendererLayerParams params;
params.images[0] = image_dxgi;
params.content_rect = gfx::Rect(50, 50);
params.quad_rect = on_screen_rect;
params.clip_rect = on_screen_rect;
params.is_clipped = true;
surface_->ScheduleDCLayer(params);
EXPECT_EQ(gfx::SwapResult::SWAP_ACK,
surface_->SwapBuffers(base::DoNothing()));
}
// Swap chain is set to monitor size.
swap_chain = surface_->GetLayerSwapChainForTesting(0);
EXPECT_TRUE(SUCCEEDED(swap_chain->GetDesc1(&desc)));
EXPECT_EQ(static_cast<unsigned int>(monitor_size.width()), desc.Width);
EXPECT_EQ(static_cast<unsigned int>(monitor_size.height()), desc.Height);
gfx::Transform transform;
gfx::Point offset;
gfx::Rect clip_rect;
surface_->GetSwapChainVisualInfoForTesting(0, &transform, &offset,
&clip_rect);
EXPECT_TRUE(transform.IsIdentity());
EXPECT_EQ(gfx::Rect(monitor_size), clip_rect);
// (4) Test if the final on-screen size is adjusted to fit the monitor when
// overlay scaling is supported and video on-screen size is slightly bigger
// than the monitor. Clipping is off.
DirectCompositionSurfaceWin::SetScaledOverlaysSupportedForTesting(true);
on_screen_rect =
gfx::Rect(0, 0, monitor_size.width() + 2, monitor_size.height() + 2);
{
ui::DCRendererLayerParams params;
params.images[0] = image_dxgi;
params.content_rect = gfx::Rect(50, 50);
params.quad_rect = on_screen_rect;
surface_->ScheduleDCLayer(params);
EXPECT_EQ(gfx::SwapResult::SWAP_ACK,
surface_->SwapBuffers(base::DoNothing()));
}
// Swap chain is set to content rect size.
swap_chain = surface_->GetLayerSwapChainForTesting(0);
EXPECT_TRUE(SUCCEEDED(swap_chain->GetDesc1(&desc)));
EXPECT_EQ(50u, desc.Width);
EXPECT_EQ(50u, desc.Height);
// Make sure the new transform matrix is adjusted, so it transforms the swap
// chain to |new_on_screen_rect| which fits the monitor.
surface_->GetSwapChainVisualInfoForTesting(0, &transform, &offset,
&clip_rect);
gfx::RectF new_on_screen_rect = gfx::RectF(50, 50);
transform.TransformRect(&new_on_screen_rect);
EXPECT_EQ(gfx::Rect(monitor_size), gfx::ToEnclosingRect(new_on_screen_rect));
}
TEST_F(DirectCompositionPixelTest, SwapChainImage) {
......
This diff is collapsed.
......@@ -27,6 +27,7 @@ class GLImageMemory;
class SwapChainPresenter : public base::PowerObserver {
public:
SwapChainPresenter(DCLayerTree* layer_tree,
HWND window,
Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device,
Microsoft::WRL::ComPtr<IDCompositionDevice2> dcomp_device);
~SwapChainPresenter() override;
......@@ -44,6 +45,14 @@ class SwapChainPresenter : public base::PowerObserver {
void SetFrameRate(float frame_rate);
void GetSwapChainVisualInfoForTesting(gfx::Transform* transform,
gfx::Point* offset,
gfx::Rect* clip_rect) const {
*transform = visual_info_.transform;
*offset = visual_info_.offset;
*clip_rect = visual_info_.clip_rect;
}
private:
// Mapped to DirectCompositonVideoPresentationMode UMA enum. Do not remove or
// remap existing entries!
......@@ -125,12 +134,28 @@ class SwapChainPresenter : public base::PowerObserver {
bool content_is_hdr,
base::Optional<DXGI_HDR_METADATA_HDR10> stream_hdr_metadata);
gfx::Size GetMonitorSize();
// If the swap chain size is very close to the screen size but not exactly the
// same, the swap chain should be adjusted to fit the screen size in order to
// get the fullscreen DWM optimizations.
void AdjustSwapChainToFullScreenSizeIfNeeded(
const ui::DCRendererLayerParams& params,
const gfx::Rect& overlay_onscreen_rect,
gfx::Size* swap_chain_size,
gfx::Transform* transform,
gfx::Rect* clip_rect);
// Returns optimal swap chain size for given layer.
gfx::Size CalculateSwapChainSize(const ui::DCRendererLayerParams& params);
gfx::Size CalculateSwapChainSize(const ui::DCRendererLayerParams& params,
gfx::Transform* transform,
gfx::Rect* clip_rect);
// Update direct composition visuals for layer with given swap chain size.
void UpdateVisuals(const ui::DCRendererLayerParams& params,
const gfx::Size& swap_chain_size);
const gfx::Size& swap_chain_size,
const gfx::Transform& transform,
const gfx::Rect& clip_rect);
// Try presenting to a decode swap chain based on various conditions such as
// global state (e.g. finch, NV12 support), texture flags, and transform.
......@@ -169,6 +194,8 @@ class SwapChainPresenter : public base::PowerObserver {
// Layer tree instance that owns this swap chain presenter.
DCLayerTree* layer_tree_ = nullptr;
const HWND window_;
// Current size of swap chain.
gfx::Size swap_chain_size_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment