0

Add support for updating the browser with the latest HDR and Overlay status

Add an info-update callback function to DirectCompositionSurfaceWin so
the status change of HDR, direct composition or overlay can be
propagated to the browser. The status change could be a result of swap
chain creation failure.

Bug:1089998

Change-Id: If3ca647cf73edbb776b35775dcc7df46ea8b5ba4
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2225144
Reviewed-by: Bo <boliu@chromium.org>
Reviewed-by: Daniel Cheng <dcheng@chromium.org>
Reviewed-by: Zhenyao Mo <zmo@chromium.org>
Reviewed-by: ccameron <ccameron@chromium.org>
Commit-Queue: Maggie Chen <magchen@chromium.org>
Cr-Commit-Position: refs/heads/master@{#774541}
This commit is contained in:
Maggie Chen
2020-06-03 08:34:06 +00:00
committed by Commit Bot
parent e5eb7354c9
commit 05364bf39d
16 changed files with 133 additions and 65 deletions

@ -512,6 +512,10 @@ void GpuHostImpl::DidUpdateOverlayInfo(const gpu::OverlayInfo& overlay_info) {
delegate_->DidUpdateOverlayInfo(overlay_info);
}
void GpuHostImpl::DidUpdateHDRStatus(bool hdr_enabled) {
delegate_->DidUpdateHDRStatus(hdr_enabled);
}
void GpuHostImpl::SetChildSurface(gpu::SurfaceHandle parent,
gpu::SurfaceHandle child) {
if (pid_ != base::kNullProcessId) {

@ -73,6 +73,7 @@ class VIZ_HOST_EXPORT GpuHostImpl : public mojom::GpuHost {
virtual void MaybeShutdownGpuProcess() = 0;
#if defined(OS_WIN)
virtual void DidUpdateOverlayInfo(const gpu::OverlayInfo& overlay_info) = 0;
virtual void DidUpdateHDRStatus(bool hdr_enabled) = 0;
#endif
virtual void BlockDomainFrom3DAPIs(const GURL& url,
gpu::DomainGuilt guilt) = 0;
@ -231,6 +232,7 @@ class VIZ_HOST_EXPORT GpuHostImpl : public mojom::GpuHost {
void DisableGpuCompositing() override;
#if defined(OS_WIN)
void DidUpdateOverlayInfo(const gpu::OverlayInfo& overlay_info) override;
void DidUpdateHDRStatus(bool hdr_enabled) override;
void SetChildSurface(gpu::SurfaceHandle parent,
gpu::SurfaceHandle child) override;
#endif

@ -405,6 +405,13 @@ GpuServiceImpl::GpuServiceImpl(
}
#endif
#if defined(OS_WIN)
auto info_callback = base::BindRepeating(
&GpuServiceImpl::UpdateOverlayAndHDRInfo, weak_ptr_factory_.GetWeakPtr());
gl::DirectCompositionSurfaceWin::SetOverlayHDRGpuInfoUpdateCallback(
info_callback);
#endif
gpu_memory_buffer_factory_ =
gpu::GpuMemoryBufferFactory::CreateNativeType(vulkan_context_provider());
@ -768,12 +775,12 @@ void GpuServiceImpl::RequestHDRStatus(RequestHDRStatusCallback callback) {
void GpuServiceImpl::RequestHDRStatusOnMainThread(
RequestHDRStatusCallback callback) {
DCHECK(main_runner_->BelongsToCurrentThread());
bool hdr_enabled = false;
#if defined(OS_WIN)
hdr_enabled = gl::DirectCompositionSurfaceWin::IsHDRSupported();
hdr_enabled_ = gl::DirectCompositionSurfaceWin::IsHDRSupported();
#endif
io_runner_->PostTask(FROM_HERE,
base::BindOnce(std::move(callback), hdr_enabled));
base::BindOnce(std::move(callback), hdr_enabled_));
}
void GpuServiceImpl::RegisterDisplayContext(
@ -837,6 +844,10 @@ void GpuServiceImpl::DidUpdateOverlayInfo(
const gpu::OverlayInfo& overlay_info) {
gpu_host_->DidUpdateOverlayInfo(gpu_info_.overlay_info);
}
void GpuServiceImpl::DidUpdateHDRStatus(bool hdr_enabled) {
gpu_host_->DidUpdateHDRStatus(hdr_enabled);
}
#endif
void GpuServiceImpl::StoreShaderToDisk(int client_id,
@ -968,12 +979,6 @@ void GpuServiceImpl::DisplayAdded() {
if (!in_host_process())
ui::GpuSwitchingManager::GetInstance()->NotifyDisplayAdded();
#if defined(OS_WIN)
// Update overlay info in the GPU process and send the updated data back to
// the GPU host in the Browser process through mojom if the info has changed.
UpdateOverlayInfo();
#endif
}
void GpuServiceImpl::DisplayRemoved() {
@ -986,12 +991,6 @@ void GpuServiceImpl::DisplayRemoved() {
if (!in_host_process())
ui::GpuSwitchingManager::GetInstance()->NotifyDisplayRemoved();
#if defined(OS_WIN)
// Update overlay info in the GPU process and send the updated data back to
// the GPU host in the Browser process through mojom if the info has changed.
UpdateOverlayInfo();
#endif
}
void GpuServiceImpl::DestroyAllChannels() {
@ -1141,12 +1140,20 @@ gpu::Scheduler* GpuServiceImpl::GetGpuScheduler() {
}
#if defined(OS_WIN)
void GpuServiceImpl::UpdateOverlayInfo() {
void GpuServiceImpl::UpdateOverlayAndHDRInfo() {
gpu::OverlayInfo old_overlay_info = gpu_info_.overlay_info;
gpu::CollectHardwareOverlayInfo(&gpu_info_.overlay_info);
// Update overlay info in the GPU process and send the updated data back to
// the GPU host in the Browser process through mojom if the info has changed.
if (old_overlay_info != gpu_info_.overlay_info)
DidUpdateOverlayInfo(gpu_info_.overlay_info);
// Update HDR status in the GPU process through the GPU host mojom.
bool old_hdr_enabled_status = hdr_enabled_;
hdr_enabled_ = gl::DirectCompositionSurfaceWin::IsHDRSupported();
if (old_hdr_enabled_status != hdr_enabled_)
DidUpdateHDRStatus(hdr_enabled_);
}
#endif

@ -210,6 +210,7 @@ class VIZ_SERVICE_EXPORT GpuServiceImpl : public gpu::GpuChannelManagerDelegate,
const GURL& active_url) override;
#if defined(OS_WIN)
void DidUpdateOverlayInfo(const gpu::OverlayInfo& overlay_info) override;
void DidUpdateHDRStatus(bool hdr_enabled) override;
#endif
void StoreShaderToDisk(int client_id,
const std::string& key,
@ -342,10 +343,10 @@ class VIZ_SERVICE_EXPORT GpuServiceImpl : public gpu::GpuChannelManagerDelegate,
// process. If |for_context_loss| is true an error message will be logged.
void MaybeExit(bool for_context_loss);
// Update overlay info on the GPU process and send the updated info back
// to the browser process if there is a change.
// Update overlay info and HDR status on the GPU process and send the updated
// info back to the browser process if there is a change.
#if defined(OS_WIN)
void UpdateOverlayInfo();
void UpdateOverlayAndHDRInfo();
#endif
scoped_refptr<base::SingleThreadTaskRunner> main_runner_;
@ -363,6 +364,8 @@ class VIZ_SERVICE_EXPORT GpuServiceImpl : public gpu::GpuChannelManagerDelegate,
// Information about general chrome feature support for the GPU.
gpu::GpuFeatureInfo gpu_feature_info_;
bool hdr_enabled_ = false;
// What we would have gotten if we haven't fallen back to SwiftShader or
// pure software (in the viz case).
base::Optional<gpu::GPUInfo> gpu_info_for_hardware_gpu_;

@ -181,7 +181,6 @@
#include "content/browser/renderer_host/dwrite_font_lookup_table_builder_win.h"
#include "net/base/winsock_init.h"
#include "services/service_manager/sandbox/win/sandbox_win.h"
#include "ui/display/win/screen_win.h"
#endif
#if defined(OS_CHROMEOS)
@ -473,49 +472,6 @@ class GpuDataManagerVisualProxy : public GpuDataManagerObserver {
} // namespace internal
#endif
#if defined(OS_WIN)
namespace {
// Provides a bridge whereby display::win::ScreenWin can ask the GPU process
// about the HDR status of the system.
class HDRProxy {
public:
static void Initialize() {
display::win::ScreenWin::SetRequestHDRStatusCallback(
base::BindRepeating(&HDRProxy::RequestHDRStatus));
}
static void RequestHDRStatus() {
// The request must be sent to the GPU process from the IO thread.
GetIOThreadTaskRunner({})->PostTask(
FROM_HERE, base::BindOnce(&HDRProxy::RequestOnIOThread));
}
private:
static void RequestOnIOThread() {
auto* gpu_process_host =
GpuProcessHost::Get(GPU_PROCESS_KIND_SANDBOXED, false);
if (gpu_process_host) {
auto* gpu_service = gpu_process_host->gpu_host()->gpu_service();
gpu_service->RequestHDRStatus(
base::BindOnce(&HDRProxy::GotResultOnIOThread));
} else {
bool hdr_enabled = false;
GotResultOnIOThread(hdr_enabled);
}
}
static void GotResultOnIOThread(bool hdr_enabled) {
GetUIThreadTaskRunner({})->PostTask(
FROM_HERE, base::BindOnce(&HDRProxy::GotResult, hdr_enabled));
}
static void GotResult(bool hdr_enabled) {
display::win::ScreenWin::SetHDREnabled(hdr_enabled);
}
};
} // namespace
#endif
// The currently-running BrowserMainLoop. There can be one or zero.
BrowserMainLoop* g_current_browser_main_loop = nullptr;
@ -1316,7 +1272,6 @@ int BrowserMainLoop::BrowserThreadsStarted() {
}
#if defined(OS_WIN)
HDRProxy::Initialize();
system_message_window_.reset(new media::SystemMessageWindowWin);
#elif defined(OS_LINUX) && defined(USE_UDEV)
device_monitor_linux_ = std::make_unique<media::DeviceMonitorLinux>();

@ -145,6 +145,10 @@ void GpuDataManagerImpl::UpdateOverlayInfo(
base::AutoLock auto_lock(lock_);
private_->UpdateOverlayInfo(overlay_info);
}
void GpuDataManagerImpl::UpdateHDRStatus(bool hdr_enabled) {
base::AutoLock auto_lock(lock_);
private_->UpdateHDRStatus(hdr_enabled);
}
void GpuDataManagerImpl::UpdateDxDiagNodeRequestStatus(bool request_continues) {
base::AutoLock auto_lock(lock_);

@ -87,6 +87,7 @@ class CONTENT_EXPORT GpuDataManagerImpl : public GpuDataManager,
const gpu::Dx12VulkanVersionInfo& dx12_vulkan_version_info);
void UpdateDevicePerfInfo(const gpu::DevicePerfInfo& device_perf_info);
void UpdateOverlayInfo(const gpu::OverlayInfo& overlay_info);
void UpdateHDRStatus(bool hdr_enabled);
void UpdateDxDiagNodeRequestStatus(bool request_continues);
void UpdateDx12VulkanRequestStatus(bool request_continues);
bool Dx12VulkanRequested() const;

@ -85,6 +85,7 @@
#if defined(OS_WIN)
#include "base/base_paths_win.h"
#include "base/win/windows_version.h"
#include "ui/display/win/screen_win.h"
#endif // OS_WIN
namespace content {
@ -450,6 +451,45 @@ void CollectExtraDevicePerfInfo(const gpu::GPUInfo& gpu_info,
device_perf_info->software_rendering = true;
}
}
// Provides a bridge whereby display::win::ScreenWin can ask the GPU process
// about the HDR status of the system.
class HDRProxy {
public:
static void Initialize() {
display::win::ScreenWin::SetRequestHDRStatusCallback(
base::BindRepeating(&HDRProxy::RequestHDRStatus));
}
static void RequestHDRStatus() {
// The request must be sent to the GPU process from the IO thread.
GetIOThreadTaskRunner({})->PostTask(
FROM_HERE, base::BindOnce(&HDRProxy::RequestOnIOThread));
}
static void GotResultOnIOThread(bool hdr_enabled) {
GetUIThreadTaskRunner({})->PostTask(
FROM_HERE, base::BindOnce(&HDRProxy::GotResult, hdr_enabled));
}
private:
static void RequestOnIOThread() {
auto* gpu_process_host =
GpuProcessHost::Get(GPU_PROCESS_KIND_SANDBOXED, false);
if (gpu_process_host) {
auto* gpu_service = gpu_process_host->gpu_host()->gpu_service();
gpu_service->RequestHDRStatus(
base::BindOnce(&HDRProxy::GotResultOnIOThread));
} else {
bool hdr_enabled = false;
GotResultOnIOThread(hdr_enabled);
}
}
static void GotResult(bool hdr_enabled) {
display::win::ScreenWin::SetHDREnabled(hdr_enabled);
}
};
#endif // OS_WIN
} // anonymous namespace
@ -863,6 +903,12 @@ void GpuDataManagerImplPrivate::UpdateOverlayInfo(
NotifyGpuInfoUpdate();
}
void GpuDataManagerImplPrivate::UpdateHDRStatus(bool hdr_enabled) {
// This is running on the IO thread;
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
HDRProxy::GotResultOnIOThread(hdr_enabled);
}
void GpuDataManagerImplPrivate::UpdateDxDiagNodeRequestStatus(
bool request_continues) {
gpu_info_dx_diag_request_failed_ = !request_continues;
@ -896,6 +942,9 @@ void GpuDataManagerImplPrivate::OnBrowserThreadsStarted() {
// Observer for display change.
if (display::Screen::GetScreen())
display::Screen::GetScreen()->AddObserver(owner_);
// Initialization for HDR status update.
HDRProxy::Initialize();
}
void GpuDataManagerImplPrivate::TerminateInfoCollectionGpuProcess() {

@ -67,6 +67,7 @@ class CONTENT_EXPORT GpuDataManagerImplPrivate {
void UpdateDevicePerfInfo(const gpu::DevicePerfInfo& device_perf_info);
void UpdateOverlayInfo(const gpu::OverlayInfo& overlay_info);
void UpdateHDRStatus(bool hdr_enabled);
void UpdateDx12VulkanRequestStatus(bool request_continues);
void UpdateDxDiagNodeRequestStatus(bool request_continues);
bool Dx12VulkanRequested() const;

@ -1021,6 +1021,10 @@ void GpuProcessHost::DidUpdateOverlayInfo(
const gpu::OverlayInfo& overlay_info) {
GpuDataManagerImpl::GetInstance()->UpdateOverlayInfo(overlay_info);
}
void GpuProcessHost::DidUpdateHDRStatus(bool hdr_enabled) {
GpuDataManagerImpl::GetInstance()->UpdateHDRStatus(hdr_enabled);
}
#endif
void GpuProcessHost::BlockDomainFrom3DAPIs(const GURL& url,

@ -165,6 +165,7 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate,
void MaybeShutdownGpuProcess() override;
#if defined(OS_WIN)
void DidUpdateOverlayInfo(const gpu::OverlayInfo& overlay_info) override;
void DidUpdateHDRStatus(bool hdr_enabled) override;
#endif
void BlockDomainFrom3DAPIs(const GURL& url, gpu::DomainGuilt guilt) override;
void DisableGpuCompositing() override;

@ -74,6 +74,9 @@ class GpuChannelManagerDelegate {
// Tells the delegate that overlay info was updated.
virtual void DidUpdateOverlayInfo(const gpu::OverlayInfo& overlay_info) = 0;
// Tells the delegate that HDR status was updated.
virtual void DidUpdateHDRStatus(bool hdr_enabled) = 0;
// Tells the delegate that |child_window| was created in the GPU process and
// to send an IPC to make SetParent() syscall. This syscall is blocked by the
// GPU sandbox and must be made in the browser process.

@ -48,6 +48,7 @@ class TestGpuChannelManagerDelegate : public GpuChannelManagerDelegate {
bool IsExiting() const override { return is_exiting_; }
#if defined(OS_WIN)
void DidUpdateOverlayInfo(const gpu::OverlayInfo& overlay_info) override {}
void DidUpdateHDRStatus(bool hdr_enabled) override {}
void SendCreatedChildWindow(SurfaceHandle parent_window,
SurfaceHandle child_window) override {}
#endif

@ -41,6 +41,11 @@ interface GpuHost {
[EnableIf=is_win]
DidUpdateOverlayInfo(gpu.mojom.OverlayInfo overlay_info);
// Tells the GPU host that the HDR status has been updated in the GPU
// process.
[EnableIf=is_win]
DidUpdateHDRStatus(bool hdr_enabled);
// GPU process has decided to disable GPU compositing. Host process keeps
// track of this decision in case the GPU process crashes.
DisableGpuCompositing();

@ -67,6 +67,9 @@ void SetOverlayCapsValid(bool valid) {
// Used for workaround limiting overlay size to monitor size.
gfx::Size g_overlay_monitor_size;
DirectCompositionSurfaceWin::OverlayHDRInfoUpdateCallback
g_overlay_hdr_gpu_info_callback;
// Preferred overlay format set when detecting overlay support during
// initialization. Set to NV12 by default so that it's used when enabling
// overlays using command line flags.
@ -257,6 +260,11 @@ bool SupportsLowLatencyPresentation() {
features::kDirectCompositionLowLatencyPresentation) &&
SupportsPresentationFeedback();
}
void RunOverlayHdrGpuInfoUpdateCallback() {
if (g_overlay_hdr_gpu_info_callback)
g_overlay_hdr_gpu_info_callback.Run();
}
} // namespace
DirectCompositionSurfaceWin::PendingFrame::PendingFrame(
@ -384,6 +392,7 @@ bool DirectCompositionSurfaceWin::IsDecodeSwapChainSupported() {
// static
void DirectCompositionSurfaceWin::DisableOverlays() {
SetSupportsOverlays(false);
RunOverlayHdrGpuInfoUpdateCallback();
}
// static
@ -556,6 +565,12 @@ bool DirectCompositionSurfaceWin::AllowTearing() {
DirectCompositionSurfaceWin::IsSwapChainTearingSupported();
}
// static
void DirectCompositionSurfaceWin::SetOverlayHDRGpuInfoUpdateCallback(
OverlayHDRInfoUpdateCallback callback) {
g_overlay_hdr_gpu_info_callback = std::move(callback);
}
bool DirectCompositionSurfaceWin::Initialize(GLSurfaceFormat format) {
d3d11_device_ = QueryD3D11DeviceObjectFromANGLE();
if (!d3d11_device_) {
@ -719,7 +734,13 @@ bool DirectCompositionSurfaceWin::SupportsProtectedVideo() const {
}
bool DirectCompositionSurfaceWin::SetDrawRectangle(const gfx::Rect& rectangle) {
return root_surface_->SetDrawRectangle(rectangle);
bool result = root_surface_->SetDrawRectangle(rectangle);
if (!result &&
DirectCompositionChildSurfaceWin::IsDirectCompositionSwapChainFailed()) {
RunOverlayHdrGpuInfoUpdateCallback();
}
return result;
}
bool DirectCompositionSurfaceWin::SupportsGpuVSync() const {
@ -843,11 +864,13 @@ void DirectCompositionSurfaceWin::OnGpuSwitched(
void DirectCompositionSurfaceWin::OnDisplayAdded() {
InvalidateOverlayCaps();
UpdateOverlaySupport();
RunOverlayHdrGpuInfoUpdateCallback();
}
void DirectCompositionSurfaceWin::OnDisplayRemoved() {
InvalidateOverlayCaps();
UpdateOverlaySupport();
RunOverlayHdrGpuInfoUpdateCallback();
}
scoped_refptr<base::TaskRunner>

@ -31,6 +31,8 @@ class GL_EXPORT DirectCompositionSurfaceWin : public GLSurfaceEGL,
using VSyncCallback =
base::RepeatingCallback<void(base::TimeTicks, base::TimeDelta)>;
using OverlayHDRInfoUpdateCallback = base::RepeatingClosure;
struct Settings {
bool disable_nv12_dynamic_textures = false;
bool disable_larger_than_screen_overlays = false;
@ -91,6 +93,9 @@ class GL_EXPORT DirectCompositionSurfaceWin : public GLSurfaceEGL,
static void SetOverlayFormatUsedForTesting(DXGI_FORMAT format);
static void SetOverlayHDRGpuInfoUpdateCallback(
OverlayHDRInfoUpdateCallback callback);
// GLSurfaceEGL implementation.
bool Initialize(GLSurfaceFormat format) override;
void Destroy() override;