Commit bde7f92c authored by Maggie Chen's avatar Maggie Chen Committed by Commit Bot

Add the Display Observer for Direct Composition in Windows.

The purpose is to observe the events of monitor plugged-in/unplugged for
Direct Composition overlays so we can update the hardware overlay caps
upon display change. DisplayAdded() and DisplayRemoved() are added to
DirectCompositionSurfaceWin.

The display observer goes through the GPU data manager in the browser
process first. It will then notify the GPU switch observer in the GPU
process through Mojo.

This CL is limited to Windows only. The display observer might work (not
tested yet) for Mac if we need it later. (But no code support for Linux.)


Bug: 1042989
Change-Id: I53dc1689795d569ea60290c13dacfcc7f3ee9152
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2011134
Commit-Queue: Maggie Chen <magchen@chromium.org>
Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Reviewed-by: default avatarZhenyao Mo <zmo@chromium.org>
Reviewed-by: default avatarEric Karl <ericrk@chromium.org>
Cr-Commit-Position: refs/heads/master@{#735009}
parent 4f0592d4
......@@ -162,6 +162,10 @@ class TestGpuService : public mojom::GpuService {
void GpuSwitched(gl::GpuPreference active_gpu_heuristic) override {}
void DisplayAdded() override {}
void DisplayRemoved() override {}
void DestroyAllChannels() override {}
void OnBackgroundCleanup() override {}
......
......@@ -848,6 +848,20 @@ void GpuServiceImpl::GpuSwitched(gl::GpuPreference active_gpu_heuristic) {
active_gpu_heuristic);
}
void GpuServiceImpl::DisplayAdded() {
DVLOG(1) << "GPU: A monitor is plugged in";
if (!in_host_process())
ui::GpuSwitchingManager::GetInstance()->NotifyDisplayAdded();
}
void GpuServiceImpl::DisplayRemoved() {
DVLOG(1) << "GPU: A monitor is unplugged ";
if (!in_host_process())
ui::GpuSwitchingManager::GetInstance()->NotifyDisplayRemoved();
}
void GpuServiceImpl::DestroyAllChannels() {
if (io_runner_->BelongsToCurrentThread()) {
main_runner_->PostTask(
......
......@@ -169,6 +169,8 @@ class VIZ_SERVICE_EXPORT GpuServiceImpl : public gpu::GpuChannelManagerDelegate,
const std::string& data) override;
void WakeUpGpu() override;
void GpuSwitched(gl::GpuPreference active_gpu_heuristic) override;
void DisplayAdded() override;
void DisplayRemoved() override;
void DestroyAllChannels() override;
void OnBackgroundCleanup() override;
void OnBackgrounded() override;
......
......@@ -69,14 +69,12 @@ void GpuDataManagerImpl::RequestVideoMemoryUsageStatsUpdate(
private_->RequestVideoMemoryUsageStatsUpdate(std::move(callback));
}
void GpuDataManagerImpl::AddObserver(
GpuDataManagerObserver* observer) {
void GpuDataManagerImpl::AddObserver(GpuDataManagerObserver* observer) {
base::AutoLock auto_lock(lock_);
private_->AddObserver(observer);
}
void GpuDataManagerImpl::RemoveObserver(
GpuDataManagerObserver* observer) {
void GpuDataManagerImpl::RemoveObserver(GpuDataManagerObserver* observer) {
base::AutoLock auto_lock(lock_);
private_->RemoveObserver(observer);
}
......@@ -198,8 +196,7 @@ void GpuDataManagerImpl::AddLogMessage(int level,
private_->AddLogMessage(level, header, message);
}
void GpuDataManagerImpl::ProcessCrashed(
base::TerminationStatus exit_code) {
void GpuDataManagerImpl::ProcessCrashed(base::TerminationStatus exit_code) {
base::AutoLock auto_lock(lock_);
private_->ProcessCrashed(exit_code);
}
......@@ -225,8 +222,8 @@ bool GpuDataManagerImpl::Are3DAPIsBlocked(const GURL& top_origin_url,
int render_frame_id,
ThreeDAPIType requester) {
base::AutoLock auto_lock(lock_);
return private_->Are3DAPIsBlocked(
top_origin_url, render_process_id, render_frame_id, requester);
return private_->Are3DAPIsBlocked(top_origin_url, render_process_id,
render_frame_id, requester);
}
void GpuDataManagerImpl::UnblockDomainFrom3DAPIs(const GURL& url) {
......@@ -265,6 +262,16 @@ void GpuDataManagerImpl::SetApplicationVisible(bool is_visible) {
private_->SetApplicationVisible(is_visible);
}
void GpuDataManagerImpl::OnDisplayAdded(const display::Display& new_display) {
base::AutoLock auto_lock(lock_);
private_->OnDisplayAdded(new_display);
}
void GpuDataManagerImpl::OnDisplayRemoved(const display::Display& old_display) {
base::AutoLock auto_lock(lock_);
private_->OnDisplayRemoved(old_display);
}
GpuDataManagerImpl::GpuDataManagerImpl()
: private_(std::make_unique<GpuDataManagerImplPrivate>(this)) {}
......
......@@ -29,6 +29,7 @@
#include "gpu/config/gpu_feature_info.h"
#include "gpu/config/gpu_info.h"
#include "gpu/config/gpu_mode.h"
#include "ui/display/display_observer.h"
class GURL;
......@@ -40,7 +41,8 @@ namespace content {
class GpuDataManagerImplPrivate;
class CONTENT_EXPORT GpuDataManagerImpl : public GpuDataManager {
class CONTENT_EXPORT GpuDataManagerImpl : public GpuDataManager,
public display::DisplayObserver {
public:
// Getter for the singleton. This will return NULL on failure.
static GpuDataManagerImpl* GetInstance();
......@@ -159,6 +161,10 @@ class CONTENT_EXPORT GpuDataManagerImpl : public GpuDataManager {
// whether we are in the foreground or background.
void SetApplicationVisible(bool is_visible);
// DisplayObserver overrides.
void OnDisplayAdded(const display::Display& new_display) override;
void OnDisplayRemoved(const display::Display& old_display) override;
private:
friend class GpuDataManagerImplPrivate;
friend class GpuDataManagerImplPrivateTest;
......
......@@ -55,6 +55,7 @@
#include "gpu/vulkan/buildflags.h"
#include "media/media_buildflags.h"
#include "ui/base/ui_base_switches.h"
#include "ui/display/screen.h"
#include "ui/gfx/switches.h"
#include "ui/gl/buildflags.h"
#include "ui/gl/gl_implementation.h"
......@@ -349,6 +350,12 @@ GpuDataManagerImplPrivate::GpuDataManagerImplPrivate(GpuDataManagerImpl* owner)
CGDisplayRegisterReconfigurationCallback(DisplayReconfigCallback, owner_);
#endif // OS_MACOSX
#if defined(OS_WIN)
if (BrowserThread::CurrentlyOn(BrowserThread::UI) &&
display::Screen::GetScreen())
display::Screen::GetScreen()->AddObserver(owner_);
#endif
// For testing only.
if (command_line->HasSwitch(switches::kDisableDomainBlockingFor3DAPIs))
domain_blocking_enabled_ = false;
......@@ -365,6 +372,11 @@ GpuDataManagerImplPrivate::~GpuDataManagerImplPrivate() {
#if defined(OS_MACOSX)
CGDisplayRemoveReconfigurationCallback(DisplayReconfigCallback, owner_);
#endif
#if defined(OS_WIN)
if (display::Screen::GetScreen())
display::Screen::GetScreen()->RemoveObserver(owner_);
#endif
}
void GpuDataManagerImplPrivate::InitializeGpuModes() {
......@@ -907,8 +919,9 @@ void GpuDataManagerImplPrivate::OnGpuBlocked() {
NotifyGpuInfoUpdate();
}
void GpuDataManagerImplPrivate::AddLogMessage(
int level, const std::string& header, const std::string& message) {
void GpuDataManagerImplPrivate::AddLogMessage(int level,
const std::string& header,
const std::string& message) {
// Some clients emit many log messages. This has been observed to consume GBs
// of memory in the wild
// https://bugs.chromium.org/p/chromium/issues/detail?id=798012. Use a limit
......@@ -955,6 +968,32 @@ void GpuDataManagerImplPrivate::HandleGpuSwitch() {
active_gpu_heuristic_));
}
void GpuDataManagerImplPrivate::OnDisplayAdded(
const display::Display& new_display) {
base::AutoUnlock unlock(owner_->lock_);
// Notify observers in the browser process.
ui::GpuSwitchingManager::GetInstance()->NotifyDisplayAdded();
// Pass the notification to the GPU process to notify observers there.
GpuProcessHost::CallOnIO(GPU_PROCESS_KIND_SANDBOXED, false /* force_create */,
base::BindOnce([](GpuProcessHost* host) {
if (host)
host->gpu_service()->DisplayAdded();
}));
}
void GpuDataManagerImplPrivate::OnDisplayRemoved(
const display::Display& old_display) {
base::AutoUnlock unlock(owner_->lock_);
// Notify observers in the browser process.
ui::GpuSwitchingManager::GetInstance()->NotifyDisplayRemoved();
// Pass the notification to the GPU process to notify observers there.
GpuProcessHost::CallOnIO(GPU_PROCESS_KIND_SANDBOXED, false /* force_create */,
base::BindOnce([](GpuProcessHost* host) {
if (host)
host->gpu_service()->DisplayRemoved();
}));
}
bool GpuDataManagerImplPrivate::UpdateActiveGpu(uint32_t vendor_id,
uint32_t device_id) {
// Heuristics for dual-GPU detection.
......
......@@ -24,6 +24,7 @@
#include "base/values.h"
#include "build/build_config.h"
#include "content/browser/gpu/gpu_data_manager_impl.h"
#include "ui/display/display_observer.h"
#include "ui/gl/gpu_preference.h"
namespace base {
......@@ -122,6 +123,9 @@ class CONTENT_EXPORT GpuDataManagerImplPrivate {
void SetApplicationVisible(bool is_visible);
void OnDisplayAdded(const display::Display& new_display);
void OnDisplayRemoved(const display::Display& old_display);
private:
friend class GpuDataManagerImplPrivateTest;
......
......@@ -104,6 +104,8 @@ class TestGpuService : public viz::mojom::GpuService {
const std::string& data) override {}
void WakeUpGpu() override {}
void GpuSwitched(gl::GpuPreference active_gpu_heuristic) override {}
void DisplayAdded() override {}
void DisplayRemoved() override {}
void DestroyAllChannels() override {}
void OnBackgroundCleanup() override {}
void OnBackgrounded() override {}
......
......@@ -120,6 +120,13 @@ interface GpuService {
// is reconfigured, for example.
GpuSwitched(gl.mojom.GpuPreference active_gpu_heuristic);
// Tells GPU that host has seen a monitor being plugged in.
DisplayAdded();
// Tells GPU that host has seen a monitor being unplugged.
DisplayRemoved();
// Tells GPU that all GPU channels are to be destroyed.
DestroyAllChannels();
// Called by the browser shortly after the application is backgrounded. The
......
......@@ -21,6 +21,7 @@
#include "ui/gl/gl_angle_util_win.h"
#include "ui/gl/gl_surface_presentation_helper.h"
#include "ui/gl/gl_switches.h"
#include "ui/gl/gpu_switching_manager.h"
#include "ui/gl/vsync_thread_win.h"
#ifndef EGL_ANGLE_flexible_surface_compatibility
......@@ -227,9 +228,11 @@ DirectCompositionSurfaceWin::DirectCompositionSurfaceWin(
// Call GetWeakPtr() on main thread before calling on vsync thread so that the
// internal weak reference is initialized in a thread-safe way.
weak_ptr_ = weak_factory_.GetWeakPtr();
ui::GpuSwitchingManager::GetInstance()->AddObserver(this);
}
DirectCompositionSurfaceWin::~DirectCompositionSurfaceWin() {
ui::GpuSwitchingManager::GetInstance()->RemoveObserver(this);
Destroy();
}
......@@ -756,6 +759,13 @@ void DirectCompositionSurfaceWin::HandleVSyncOnMainThread(
}
}
void DirectCompositionSurfaceWin::OnGpuSwitched(
gl::GpuPreference active_gpu_heuristic) {}
void DirectCompositionSurfaceWin::OnDisplayAdded() {}
void DirectCompositionSurfaceWin::OnDisplayRemoved() {}
scoped_refptr<base::TaskRunner>
DirectCompositionSurfaceWin::GetWindowTaskRunnerForTesting() {
return child_window_.GetTaskRunnerForTesting();
......
......@@ -15,6 +15,7 @@
#include "ui/gl/child_window_win.h"
#include "ui/gl/gl_export.h"
#include "ui/gl/gl_surface_egl.h"
#include "ui/gl/gpu_switching_observer.h"
#include "ui/gl/vsync_observer.h"
namespace gl {
......@@ -24,7 +25,8 @@ class GLSurfacePresentationHelper;
class VSyncThreadWin;
class GL_EXPORT DirectCompositionSurfaceWin : public GLSurfaceEGL,
public VSyncObserver {
public VSyncObserver,
public ui::GpuSwitchingObserver {
public:
using VSyncCallback =
base::RepeatingCallback<void(base::TimeTicks, base::TimeDelta)>;
......@@ -129,6 +131,11 @@ class GL_EXPORT DirectCompositionSurfaceWin : public GLSurfaceEGL,
// VSyncObserver implementation.
void OnVSync(base::TimeTicks vsync_time, base::TimeDelta interval) override;
// Implements GpuSwitchingObserver.
void OnGpuSwitched(gl::GpuPreference active_gpu_heuristic) override;
void OnDisplayAdded() override;
void OnDisplayRemoved() override;
HWND window() const { return window_; }
scoped_refptr<base::TaskRunner> GetWindowTaskRunnerForTesting();
......
......@@ -29,4 +29,14 @@ void GpuSwitchingManager::NotifyGpuSwitched(
observer.OnGpuSwitched(active_gpu_heuristic);
}
void GpuSwitchingManager::NotifyDisplayAdded() {
for (GpuSwitchingObserver& observer : observer_list_)
observer.OnDisplayAdded();
}
void GpuSwitchingManager::NotifyDisplayRemoved() {
for (GpuSwitchingObserver& observer : observer_list_)
observer.OnDisplayRemoved();
}
} // namespace ui
......@@ -33,6 +33,12 @@ class GL_EXPORT GpuSwitchingManager {
// If this heuristic fails, then kDefault is passed as argument.
void NotifyGpuSwitched(gl::GpuPreference active_gpu_heuristic);
// Called when a monitor is plugged in.
void NotifyDisplayAdded();
// Called when a monitor is unplugged.
void NotifyDisplayRemoved();
private:
friend struct base::DefaultSingletonTraits<GpuSwitchingManager>;
......
......@@ -14,6 +14,12 @@ class GL_EXPORT GpuSwitchingObserver {
public:
// Called for any observer when the system switches to a different GPU.
virtual void OnGpuSwitched(gl::GpuPreference active_gpu_heuristic) {}
// Called for any observer when a monitor is plugged in.
virtual void OnDisplayAdded() {}
// Called for any observer when a monitor is unplugged.
virtual void OnDisplayRemoved() {}
};
} // namespace ui
......
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