From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Andy Dill Date: Thu, 30 Jan 2020 09:36:07 -0800 Subject: feat: enable off-screen rendering with viz compositor This patch adds hooks in the relevant places that allow for off-screen rendering with the viz compositor by way of a custom HostDisplayClient and LayeredWindowUpdater. diff --git a/components/viz/host/host_display_client.cc b/components/viz/host/host_display_client.cc index b84296cc7e3bb9b7d3e10e476b14a59cf57bbc41..a5c79026c44b4f2c49e322fb53d1a263e76c632b 100644 --- a/components/viz/host/host_display_client.cc +++ b/components/viz/host/host_display_client.cc @@ -48,9 +48,9 @@ void HostDisplayClient::OnDisplayReceivedCALayerParams( } #endif -#if BUILDFLAG(IS_WIN) void HostDisplayClient::CreateLayeredWindowUpdater( mojo::PendingReceiver receiver) { +#if BUILDFLAG(IS_WIN) if (!NeedsToUseLayerWindow(widget_)) { DLOG(ERROR) << "HWND shouldn't be using a layered window"; return; @@ -58,7 +58,15 @@ void HostDisplayClient::CreateLayeredWindowUpdater( layered_window_updater_ = std::make_unique(widget_, std::move(receiver)); + +#else + CHECK(false) << "Chromium is calling CreateLayeredWindowUpdater for non-OSR " + "windows on POSIX platforms, something is wrong with " + "Electron's OSR implementation."; +#endif } + +#if BUILDFLAG(IS_WIN) void HostDisplayClient::AddChildWindowToBrowser( gpu::SurfaceHandle child_window) { NOTREACHED(); diff --git a/components/viz/host/host_display_client.h b/components/viz/host/host_display_client.h index 9e94f648060e9873a120f2c45591ad599a2e62df..93dabe09e44bda68644dcab568a827a92c550e4a 100644 --- a/components/viz/host/host_display_client.h +++ b/components/viz/host/host_display_client.h @@ -39,6 +39,9 @@ class VIZ_HOST_EXPORT HostDisplayClient : public mojom::DisplayClient { gfx::AcceleratedWidget widget() const { return widget_; } #endif + void CreateLayeredWindowUpdater( + mojo::PendingReceiver receiver) override; + private: // mojom::DisplayClient implementation: #if BUILDFLAG(IS_APPLE) @@ -47,8 +50,6 @@ class VIZ_HOST_EXPORT HostDisplayClient : public mojom::DisplayClient { #endif #if BUILDFLAG(IS_WIN) - void CreateLayeredWindowUpdater( - mojo::PendingReceiver receiver) override; void AddChildWindowToBrowser(gpu::SurfaceHandle child_window) override; #endif diff --git a/components/viz/host/layered_window_updater_impl.cc b/components/viz/host/layered_window_updater_impl.cc index 8f726bde2cb5da6acfe630006af0fc3a09811d6c..45d8cae3ba0fca9a1514f83032a10c8820b3126d 100644 --- a/components/viz/host/layered_window_updater_impl.cc +++ b/components/viz/host/layered_window_updater_impl.cc @@ -46,7 +46,9 @@ void LayeredWindowUpdaterImpl::OnAllocatedSharedMemory( // |region|'s handle will close when it goes out of scope. } -void LayeredWindowUpdaterImpl::Draw(DrawCallback draw_callback) { +void LayeredWindowUpdaterImpl::Draw( + const gfx::Rect& damage_rect, + DrawCallback draw_callback) { TRACE_EVENT0("viz", "LayeredWindowUpdaterImpl::Draw"); if (!canvas_) { diff --git a/components/viz/host/layered_window_updater_impl.h b/components/viz/host/layered_window_updater_impl.h index 8af69cac78b7488d28f1f05ccb174793fe5148cd..9f74e511c263d147b5fbe81fe100d217eb0b64c9 100644 --- a/components/viz/host/layered_window_updater_impl.h +++ b/components/viz/host/layered_window_updater_impl.h @@ -38,7 +38,7 @@ class VIZ_HOST_EXPORT LayeredWindowUpdaterImpl // mojom::LayeredWindowUpdater implementation. void OnAllocatedSharedMemory(const gfx::Size& pixel_size, base::UnsafeSharedMemoryRegion region) override; - void Draw(DrawCallback draw_callback) override; + void Draw(const gfx::Rect& damage_rect, DrawCallback draw_callback) override; private: const HWND hwnd_; diff --git a/components/viz/service/BUILD.gn b/components/viz/service/BUILD.gn index 41c3a5128b9936f48587d6fc6ddd2050bffc9c36..4dbcba1150645596532c53b99e309c0e52d4759f 100644 --- a/components/viz/service/BUILD.gn +++ b/components/viz/service/BUILD.gn @@ -178,6 +178,8 @@ viz_component("service") { "display_embedder/skia_output_surface_impl_on_gpu_debug_capture.h", "display_embedder/skia_render_copy_results.cc", "display_embedder/skia_render_copy_results.h", + "display_embedder/software_output_device_proxy.cc", + "display_embedder/software_output_device_proxy.h", "display_embedder/software_output_surface.cc", "display_embedder/software_output_surface.h", "display_embedder/vsync_parameter_listener.cc", diff --git a/components/viz/service/display_embedder/output_surface_provider.h b/components/viz/service/display_embedder/output_surface_provider.h index 7fbb05e606fc26364c674c6330b8a5eb9c016fb3..a190a42c2127011ab54aae937a3cab36880ce229 100644 --- a/components/viz/service/display_embedder/output_surface_provider.h +++ b/components/viz/service/display_embedder/output_surface_provider.h @@ -42,7 +42,8 @@ class OutputSurfaceProvider { mojom::DisplayClient* display_client, DisplayCompositorMemoryAndTaskController* gpu_dependency, const RendererSettings& renderer_settings, - const DebugRendererSettings* debug_settings) = 0; + const DebugRendererSettings* debug_settings, + bool offscreen) = 0; virtual gpu::SharedImageManager* GetSharedImageManager() = 0; virtual gpu::SyncPointManager* GetSyncPointManager() = 0; diff --git a/components/viz/service/display_embedder/output_surface_provider_impl.cc b/components/viz/service/display_embedder/output_surface_provider_impl.cc index 07502f4ff2afd53a43d8f0ab68d4c4c39f6c0737..20d51f86d5084edf0b05ce0ab11fcd1279ef8fa6 100644 --- a/components/viz/service/display_embedder/output_surface_provider_impl.cc +++ b/components/viz/service/display_embedder/output_surface_provider_impl.cc @@ -23,6 +23,7 @@ #include "components/viz/service/display/display_compositor_memory_and_task_controller.h" #include "components/viz/service/display_embedder/skia_output_surface_dependency_impl.h" #include "components/viz/service/display_embedder/skia_output_surface_impl.h" +#include "components/viz/service/display_embedder/software_output_device_proxy.h" #include "components/viz/service/display_embedder/software_output_surface.h" #include "components/viz/service/gl/gpu_service_impl.h" #include "gpu/command_buffer/client/shared_memory_limits.h" @@ -30,6 +31,7 @@ #include "gpu/command_buffer/service/scheduler_sequence.h" #include "gpu/config/gpu_finch_features.h" #include "gpu/ipc/common/surface_handle.h" +#include "services/viz/privileged/mojom/compositing/layered_window_updater.mojom.h" #include "ui/base/ui_base_switches.h" #if BUILDFLAG(IS_WIN) @@ -93,7 +95,8 @@ std::unique_ptr OutputSurfaceProviderImpl::CreateOutputSurface( mojom::DisplayClient* display_client, DisplayCompositorMemoryAndTaskController* gpu_dependency, const RendererSettings& renderer_settings, - const DebugRendererSettings* debug_settings) { + const DebugRendererSettings* debug_settings, + bool offscreen) { #if BUILDFLAG(IS_CHROMEOS) if (surface_handle == gpu::kNullSurfaceHandle) return std::make_unique(); @@ -101,7 +104,7 @@ std::unique_ptr OutputSurfaceProviderImpl::CreateOutputSurface( if (!gpu_compositing) { return std::make_unique( - CreateSoftwareOutputDeviceForPlatform(surface_handle, display_client)); + CreateSoftwareOutputDeviceForPlatform(surface_handle, display_client, offscreen)); } else { DCHECK(gpu_dependency); @@ -140,10 +143,22 @@ std::unique_ptr OutputSurfaceProviderImpl::CreateOutputSurface( std::unique_ptr OutputSurfaceProviderImpl::CreateSoftwareOutputDeviceForPlatform( gpu::SurfaceHandle surface_handle, - mojom::DisplayClient* display_client) { + mojom::DisplayClient* display_client, + bool offscreen) { if (headless_) return std::make_unique(); +#if !BUILDFLAG(IS_APPLE) + if (offscreen) { + DCHECK(display_client); + mojo::PendingRemote layered_window_updater; + display_client->CreateLayeredWindowUpdater( + layered_window_updater.InitWithNewPipeAndPassReceiver()); + return std::make_unique( + std::move(layered_window_updater)); + } +#endif + #if BUILDFLAG(IS_WIN) HWND child_hwnd; auto device = CreateSoftwareOutputDeviceWin( diff --git a/components/viz/service/display_embedder/output_surface_provider_impl.h b/components/viz/service/display_embedder/output_surface_provider_impl.h index e4b46a79560e7698a6400b2ab8a57f38205a8718..3cb2518c6644cf0618f625d981befd466a3dfb2c 100644 --- a/components/viz/service/display_embedder/output_surface_provider_impl.h +++ b/components/viz/service/display_embedder/output_surface_provider_impl.h @@ -54,7 +54,8 @@ class VIZ_SERVICE_EXPORT OutputSurfaceProviderImpl mojom::DisplayClient* display_client, DisplayCompositorMemoryAndTaskController* gpu_dependency, const RendererSettings& renderer_settings, - const DebugRendererSettings* debug_settings) override; + const DebugRendererSettings* debug_settings, + bool offscreen) override; gpu::SharedImageManager* GetSharedImageManager() override; gpu::SyncPointManager* GetSyncPointManager() override; @@ -63,7 +64,8 @@ class VIZ_SERVICE_EXPORT OutputSurfaceProviderImpl private: std::unique_ptr CreateSoftwareOutputDeviceForPlatform( gpu::SurfaceHandle surface_handle, - mojom::DisplayClient* display_client); + mojom::DisplayClient* display_client, + bool offscreen); const raw_ptr gpu_service_impl_; diff --git a/components/viz/service/display_embedder/software_output_device_mac.cc b/components/viz/service/display_embedder/software_output_device_mac.cc index 446229f7dea794a0148543d112c63b8c38183262..15d097a5761a07cfbc763d6fc739ca35cf3c8660 100644 --- a/components/viz/service/display_embedder/software_output_device_mac.cc +++ b/components/viz/service/display_embedder/software_output_device_mac.cc @@ -111,6 +111,8 @@ void SoftwareOutputDeviceMac::UpdateAndCopyBufferDamage( SkCanvas* SoftwareOutputDeviceMac::BeginPaint( const gfx::Rect& new_damage_rect) { + last_damage = new_damage_rect; + // Record the previous paint buffer. Buffer* previous_paint_buffer = buffer_queue_.empty() ? nullptr : buffer_queue_.back().get(); @@ -199,6 +201,7 @@ void SoftwareOutputDeviceMac::EndPaint() { ca_layer_params.is_empty = false; ca_layer_params.scale_factor = scale_factor_; ca_layer_params.pixel_size = pixel_size_; + ca_layer_params.damage = last_damage; ca_layer_params.io_surface_mach_port.reset( IOSurfaceCreateMachPort(current_paint_buffer_->io_surface.get())); client_->SoftwareDeviceUpdatedCALayerParams(ca_layer_params); diff --git a/components/viz/service/display_embedder/software_output_device_mac.h b/components/viz/service/display_embedder/software_output_device_mac.h index 67d5ff67d74c107a867b39b306c6528425b87e05..5fd12a25c9e319e8e675955926271c9d1cd3a7ca 100644 --- a/components/viz/service/display_embedder/software_output_device_mac.h +++ b/components/viz/service/display_embedder/software_output_device_mac.h @@ -62,6 +62,7 @@ class VIZ_SERVICE_EXPORT SoftwareOutputDeviceMac : public SoftwareOutputDevice { void UpdateAndCopyBufferDamage(Buffer* previous_paint_buffer, const SkRegion& new_damage_rect); + gfx::Rect last_damage; gfx::Size pixel_size_; float scale_factor_ = 1; diff --git a/components/viz/service/display_embedder/software_output_device_proxy.cc b/components/viz/service/display_embedder/software_output_device_proxy.cc new file mode 100644 index 0000000000000000000000000000000000000000..ef5cb8ae4c398e5834496c8b24eb98c41b10a7b3 --- /dev/null +++ b/components/viz/service/display_embedder/software_output_device_proxy.cc @@ -0,0 +1,162 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/viz/service/display_embedder/software_output_device_proxy.h" + +#include "base/memory/unsafe_shared_memory_region.h" +#include "base/threading/thread_checker.h" +#include "base/trace_event/trace_event.h" +#include "build/build_config.h" +#include "components/viz/common/resources/resource_sizes.h" +#include "mojo/public/cpp/system/platform_handle.h" +#include "services/viz/privileged/mojom/compositing/layered_window_updater.mojom.h" +#include "skia/ext/platform_canvas.h" +#include "third_party/skia/include/core/SkCanvas.h" +#include "ui/gfx/skia_util.h" + +#if BUILDFLAG(IS_WIN) +#include "components/viz/service/display_embedder/output_device_backing.h" +#include "skia/ext/skia_utils_win.h" +#include "ui/gfx/gdi_util.h" +#include "ui/gfx/win/hwnd_util.h" +#else +#include "mojo/public/cpp/base/shared_memory_utils.h" +#endif + +namespace viz { + +SoftwareOutputDeviceBase::~SoftwareOutputDeviceBase() { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + DCHECK(!in_paint_); +} + +void SoftwareOutputDeviceBase::Resize(const gfx::Size& viewport_pixel_size, + float scale_factor) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + DCHECK(!in_paint_); + + if (viewport_pixel_size_ == viewport_pixel_size) + return; + + viewport_pixel_size_ = viewport_pixel_size; + ResizeDelegated(); +} + +SkCanvas* SoftwareOutputDeviceBase::BeginPaint(const gfx::Rect& damage_rect) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + DCHECK(!in_paint_); + + damage_rect_ = damage_rect; + in_paint_ = true; + return BeginPaintDelegated(); +} + +void SoftwareOutputDeviceBase::EndPaint() { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + DCHECK(in_paint_); + + in_paint_ = false; + + gfx::Rect intersected_damage_rect = damage_rect_; + intersected_damage_rect.Intersect(gfx::Rect(viewport_pixel_size_)); + if (intersected_damage_rect.IsEmpty()) + return; + + EndPaintDelegated(intersected_damage_rect); +} + +SoftwareOutputDeviceProxy::~SoftwareOutputDeviceProxy() = default; + +SoftwareOutputDeviceProxy::SoftwareOutputDeviceProxy( + mojo::PendingRemote layered_window_updater) + : layered_window_updater_(std::move(layered_window_updater)) { + DCHECK(layered_window_updater_.is_bound()); +} + +void SoftwareOutputDeviceProxy::OnSwapBuffers( + SoftwareOutputDevice::SwapBuffersCallback swap_ack_callback, + gfx::FrameData data) { + DCHECK(swap_ack_callback_.is_null()); + + // We aren't waiting on DrawAck() and can immediately run the callback. + if (!waiting_on_draw_ack_) { + task_runner_->PostTask( + FROM_HERE, + base::BindOnce(std::move(swap_ack_callback), viewport_pixel_size_)); + return; + } + + swap_ack_callback_ = std::move(swap_ack_callback); +} + +void SoftwareOutputDeviceProxy::ResizeDelegated() { + canvas_.reset(); + + size_t required_bytes; + if (!ResourceSizes::MaybeSizeInBytes(viewport_pixel_size_, + SinglePlaneFormat::kRGBA_8888, + &required_bytes)) { + DLOG(ERROR) << "Invalid viewport size " << viewport_pixel_size_.ToString(); + return; + } + + base::UnsafeSharedMemoryRegion region = + base::UnsafeSharedMemoryRegion::Create(required_bytes); + if (!region.IsValid()) { + DLOG(ERROR) << "Failed to allocate " << required_bytes << " bytes"; + return; + } + +#if defined(WIN32) + canvas_ = skia::CreatePlatformCanvasWithSharedSection( + viewport_pixel_size_.width(), viewport_pixel_size_.height(), false, + region.GetPlatformHandle(), skia::CRASH_ON_FAILURE); +#else + shm_mapping_ = region.Map(); + if (!shm_mapping_.IsValid()) { + DLOG(ERROR) << "Failed to map " << required_bytes << " bytes"; + return; + } + + canvas_ = skia::CreatePlatformCanvasWithPixels( + viewport_pixel_size_.width(), viewport_pixel_size_.height(), false, + static_cast(shm_mapping_.memory()), 0, + skia::CRASH_ON_FAILURE); +#endif + + // Transfer region ownership to the browser process. + layered_window_updater_->OnAllocatedSharedMemory(viewport_pixel_size_, + std::move(region)); +} + +SkCanvas* SoftwareOutputDeviceProxy::BeginPaintDelegated() { + return canvas_.get(); +} + +void SoftwareOutputDeviceProxy::EndPaintDelegated( + const gfx::Rect& damage_rect) { + DCHECK(!waiting_on_draw_ack_); + + if (!canvas_) + return; + + layered_window_updater_->Draw( + damage_rect, base::BindOnce(&SoftwareOutputDeviceProxy::DrawAck, + base::Unretained(this))); + waiting_on_draw_ack_ = true; + + TRACE_EVENT_ASYNC_BEGIN0("viz", "SoftwareOutputDeviceProxy::Draw", this); +} + +void SoftwareOutputDeviceProxy::DrawAck() { + DCHECK(waiting_on_draw_ack_); + DCHECK(!swap_ack_callback_.is_null()); + + TRACE_EVENT_ASYNC_END0("viz", "SoftwareOutputDeviceProxy::Draw", this); + + waiting_on_draw_ack_ = false; + std::move(swap_ack_callback_).Run(viewport_pixel_size_); +} + +} // namespace viz diff --git a/components/viz/service/display_embedder/software_output_device_proxy.h b/components/viz/service/display_embedder/software_output_device_proxy.h new file mode 100644 index 0000000000000000000000000000000000000000..e1a22ee881c0fd679ac2d2d4d11a3c937cc4e9d1 --- /dev/null +++ b/components/viz/service/display_embedder/software_output_device_proxy.h @@ -0,0 +1,98 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_SOFTWARE_OUTPUT_DEVICE_PROXY_H_ +#define COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_SOFTWARE_OUTPUT_DEVICE_PROXY_H_ + +#include + +#include "base/memory/shared_memory_mapping.h" +#include "base/threading/thread_checker.h" +#include "build/build_config.h" +#include "components/viz/host/host_display_client.h" +#include "components/viz/service/display/software_output_device.h" +#include "components/viz/service/viz_service_export.h" +#include "mojo/public/cpp/bindings/pending_remote.h" +#include "mojo/public/cpp/bindings/remote.h" +#include "services/viz/privileged/mojom/compositing/display_private.mojom.h" +#include "services/viz/privileged/mojom/compositing/layered_window_updater.mojom.h" + +#if BUILDFLAG(IS_WIN) +#include +#endif + +namespace viz { + +// Shared base class for SoftwareOutputDevice implementations. +class SoftwareOutputDeviceBase : public SoftwareOutputDevice { + public: + SoftwareOutputDeviceBase() = default; + ~SoftwareOutputDeviceBase() override; + + SoftwareOutputDeviceBase(const SoftwareOutputDeviceBase&) = delete; + SoftwareOutputDeviceBase& operator=(const SoftwareOutputDeviceBase&) = delete; + + // SoftwareOutputDevice implementation. + void Resize(const gfx::Size& viewport_pixel_size, + float scale_factor) override; + SkCanvas* BeginPaint(const gfx::Rect& damage_rect) override; + void EndPaint() override; + + // Called from Resize() if |viewport_pixel_size_| has changed. + virtual void ResizeDelegated() = 0; + + // Called from BeginPaint() and should return an SkCanvas. + virtual SkCanvas* BeginPaintDelegated() = 0; + + // Called from EndPaint() if there is damage. + virtual void EndPaintDelegated(const gfx::Rect& damage_rect) = 0; + + private: + bool in_paint_ = false; + + THREAD_CHECKER(thread_checker_); +}; + +// SoftwareOutputDevice implementation that draws indirectly. An implementation +// of mojom::LayeredWindowUpdater in the browser process handles the actual +// drawing. Pixel backing is in SharedMemory so no copying between processes +// is required. +class SoftwareOutputDeviceProxy : public SoftwareOutputDeviceBase { + public: + explicit SoftwareOutputDeviceProxy( + mojo::PendingRemote layered_window_updater); + ~SoftwareOutputDeviceProxy() override; + + SoftwareOutputDeviceProxy(const SoftwareOutputDeviceProxy&) = delete; + SoftwareOutputDeviceProxy& operator=(const SoftwareOutputDeviceProxy&) = + delete; + + // SoftwareOutputDevice implementation. + void OnSwapBuffers( + SoftwareOutputDevice::SwapBuffersCallback swap_ack_callback, + gfx::FrameData data) override; + + // SoftwareOutputDeviceBase implementation. + void ResizeDelegated() override; + SkCanvas* BeginPaintDelegated() override; + void EndPaintDelegated(const gfx::Rect& rect) override; + + private: + // Runs |swap_ack_callback_| after draw has happened. + void DrawAck(); + + mojo::Remote layered_window_updater_; + + std::unique_ptr canvas_; + bool waiting_on_draw_ack_ = false; + SoftwareOutputDevice::SwapBuffersCallback swap_ack_callback_; + +#if !defined(WIN32) + base::WritableSharedMemoryMapping shm_mapping_; +#endif +}; + +} // namespace viz + +#endif // COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_SOFTWARE_OUTPUT_DEVICE_PROXY_H_ diff --git a/components/viz/service/display_embedder/software_output_device_win.cc b/components/viz/service/display_embedder/software_output_device_win.cc index 4d6cc977ed5000d93918336a0dd57f60c0e95bbb..54d936e86b60f0538c70c4ee69e109ccda35248f 100644 --- a/components/viz/service/display_embedder/software_output_device_win.cc +++ b/components/viz/service/display_embedder/software_output_device_win.cc @@ -149,7 +149,7 @@ void SoftwareOutputDeviceWinProxy::EndPaintDelegated( if (!canvas_) return; - layered_window_updater_->Draw(base::BindOnce( + layered_window_updater_->Draw(damage_rect, base::BindOnce( &SoftwareOutputDeviceWinProxy::DrawAck, base::Unretained(this))); waiting_on_draw_ack_ = true; diff --git a/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.cc b/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.cc index 8c660af0aaa1c031815082838dea1497b725e55b..852f4d9ac45aaa51f5edf0b3a5e3492eec52d743 100644 --- a/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.cc +++ b/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.cc @@ -112,7 +112,8 @@ RootCompositorFrameSinkImpl::Create( params->gpu_compositing, params->widget); auto output_surface = output_surface_provider->CreateOutputSurface( params->widget, params->gpu_compositing, display_client.get(), - display_controller.get(), params->renderer_settings, debug_settings); + display_controller.get(), params->renderer_settings, debug_settings, + params->offscreen); // Creating output surface failed. The host can send a new request, possibly // with a different compositing mode. diff --git a/components/viz/test/test_output_surface_provider.cc b/components/viz/test/test_output_surface_provider.cc index 47db87ff98bf8b3e76a1780e6a3c243be589eb03..8cfe341ff017868d549882f467e095f639ea9292 100644 --- a/components/viz/test/test_output_surface_provider.cc +++ b/components/viz/test/test_output_surface_provider.cc @@ -30,7 +30,8 @@ std::unique_ptr TestOutputSurfaceProvider::CreateOutputSurface( mojom::DisplayClient* display_client, DisplayCompositorMemoryAndTaskController* display_controller, const RendererSettings& renderer_settings, - const DebugRendererSettings* debug_settings) { + const DebugRendererSettings* debug_settings, + bool offscreen) { if (gpu_compositing) { return FakeSkiaOutputSurface::Create3d(); } else { diff --git a/components/viz/test/test_output_surface_provider.h b/components/viz/test/test_output_surface_provider.h index 399fba1a3d4e601dc2cdd5f1f4def8b7fd7a3011..8bcbe0d26c80323155d536c0d3a177a1f58e7aef 100644 --- a/components/viz/test/test_output_surface_provider.h +++ b/components/viz/test/test_output_surface_provider.h @@ -32,7 +32,8 @@ class TestOutputSurfaceProvider : public OutputSurfaceProvider { mojom::DisplayClient* display_client, DisplayCompositorMemoryAndTaskController* display_controller, const RendererSettings& renderer_settings, - const DebugRendererSettings* debug_settings) override; + const DebugRendererSettings* debug_settings, + bool offscreen) override; gpu::SharedImageManager* GetSharedImageManager() override; gpu::SyncPointManager* GetSyncPointManager() override; gpu::Scheduler* GetGpuScheduler() override; diff --git a/content/browser/compositor/viz_process_transport_factory.cc b/content/browser/compositor/viz_process_transport_factory.cc index 6e35e3a2e1cc10d62a487111d1e185bf900d9cfa..fe0dbc425746ec97372cade1365a5654b22881f3 100644 --- a/content/browser/compositor/viz_process_transport_factory.cc +++ b/content/browser/compositor/viz_process_transport_factory.cc @@ -436,8 +436,14 @@ void VizProcessTransportFactory::OnEstablishedGpuChannel( mojo::AssociatedRemote display_private; root_params->display_private = display_private.BindNewEndpointAndPassReceiver(); - compositor_data.display_client = - std::make_unique(compositor); + if (compositor->delegate()) { + compositor_data.display_client = compositor->delegate()->CreateHostDisplayClient( + compositor); + root_params->offscreen = compositor->delegate()->IsOffscreen(); + } else { + compositor_data.display_client = + std::make_unique(compositor); + } root_params->display_client = compositor_data.display_client->GetBoundRemote(resize_task_runner_); mojo::AssociatedRemote diff --git a/services/viz/privileged/mojom/compositing/display_private.mojom b/services/viz/privileged/mojom/compositing/display_private.mojom index 3046e60995bceb1c9931038be3d309577a830a60..4476f48510f807d03f05a4afa2a648dac8720010 100644 --- a/services/viz/privileged/mojom/compositing/display_private.mojom +++ b/services/viz/privileged/mojom/compositing/display_private.mojom @@ -125,7 +125,6 @@ interface DisplayClient { // Creates a LayeredWindowUpdater implementation to draw into a layered // window. - [EnableIf=is_win] CreateLayeredWindowUpdater(pending_receiver receiver); // Sends the created child window to the browser process so that it can be diff --git a/services/viz/privileged/mojom/compositing/frame_sink_manager.mojom b/services/viz/privileged/mojom/compositing/frame_sink_manager.mojom index 4828bfcb0c221ce9de3f1fe9952849c542e7e3df..4d3667deff36216db4d51ae3f01f732d691f4866 100644 --- a/services/viz/privileged/mojom/compositing/frame_sink_manager.mojom +++ b/services/viz/privileged/mojom/compositing/frame_sink_manager.mojom @@ -39,6 +39,7 @@ struct RootCompositorFrameSinkParams { bool send_swap_size_notifications = false; // Disables begin frame rate limiting for the display compositor. bool disable_frame_rate_limit = false; + bool offscreen = false; // Whether to create a surface control input receiver on Viz. [EnableIf=is_android] diff --git a/services/viz/privileged/mojom/compositing/layered_window_updater.mojom b/services/viz/privileged/mojom/compositing/layered_window_updater.mojom index 2f462f0deb5fc8a637457243fb5d5849fc214d14..695869b83cefaa24af93a2e11b39de05456071f3 100644 --- a/services/viz/privileged/mojom/compositing/layered_window_updater.mojom +++ b/services/viz/privileged/mojom/compositing/layered_window_updater.mojom @@ -26,5 +26,5 @@ interface LayeredWindowUpdater { // Draws to the HWND by copying pixels from shared memory. Callback must be // called after draw operation is complete to signal shared memory can be // modified. - Draw() => (); + Draw(gfx.mojom.Rect damage_rect) => (); }; diff --git a/ui/compositor/compositor.h b/ui/compositor/compositor.h index d353cd4613c734c34f5333607335cc9a434ad88e..cabb39363b30c97f63d323d7a8156774b67f6b32 100644 --- a/ui/compositor/compositor.h +++ b/ui/compositor/compositor.h @@ -92,6 +92,7 @@ class DisplayPrivate; class ExternalBeginFrameController; } // namespace mojom +class HostDisplayClient; class HostFrameSinkManager; class LocalSurfaceId; class RasterContextProvider; @@ -154,6 +155,15 @@ class COMPOSITOR_EXPORT ExternalBeginFrameControllerClientFactory { viz::mojom::ExternalBeginFrameControllerClient> CreateExternalBeginFrameControllerClient() = 0; }; +class COMPOSITOR_EXPORT CompositorDelegate { + public: + virtual bool IsOffscreen() const = 0; + virtual std::unique_ptr CreateHostDisplayClient( + ui::Compositor* compositor) = 0; + + protected: + virtual ~CompositorDelegate() {} +}; // Compositor object to take care of GPU painting. // A Browser compositor object is responsible for generating the final @@ -198,6 +208,9 @@ class COMPOSITOR_EXPORT Compositor : public base::PowerSuspendObserver, // Schedules a redraw of the layer tree associated with this compositor. void ScheduleDraw(); + CompositorDelegate* delegate() const { return delegate_; } + void SetDelegate(CompositorDelegate* delegate) { delegate_ = delegate; } + // Sets the root of the layer tree drawn by this Compositor. The root layer // must have no parent. The compositor's root layer is reset if the root layer // is destroyed. NULL can be passed to reset the root layer, in which case the @@ -616,6 +629,8 @@ class COMPOSITOR_EXPORT Compositor : public base::PowerSuspendObserver, simple_begin_frame_observers_; std::unique_ptr host_begin_frame_observer_; + raw_ptr delegate_ = nullptr; + // The root of the Layer tree drawn by this compositor. raw_ptr root_layer_ = nullptr; diff --git a/ui/gfx/ca_layer_params.h b/ui/gfx/ca_layer_params.h index 5b5bb16199d46f16be587856650b07121a786776..241efc4bddaf2ddfb4d4092766a9d3c9732ef36e 100644 --- a/ui/gfx/ca_layer_params.h +++ b/ui/gfx/ca_layer_params.h @@ -7,6 +7,7 @@ #include "base/component_export.h" #include "build/build_config.h" +#include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/size.h" #if BUILDFLAG(IS_APPLE) @@ -51,6 +52,8 @@ struct COMPONENT_EXPORT(GFX) CALayerParams { gfx::ScopedRefCountedIOSurfaceMachPort io_surface_mach_port; #endif + gfx::Rect damage; + // The geometry of the frame. gfx::Size pixel_size; float scale_factor = 1.f; diff --git a/ui/gfx/mojom/ca_layer_params.mojom b/ui/gfx/mojom/ca_layer_params.mojom index c380e4882d699232869c88bc65dc4d396bb95780..7d3c81b200cc9b390084a35ab5d0fc1904137144 100644 --- a/ui/gfx/mojom/ca_layer_params.mojom +++ b/ui/gfx/mojom/ca_layer_params.mojom @@ -18,5 +18,6 @@ struct CALayerParams { bool is_empty; CALayerContent content; gfx.mojom.Size pixel_size; + gfx.mojom.Rect damage; float scale_factor; }; diff --git a/ui/gfx/mojom/ca_layer_params_mojom_traits.cc b/ui/gfx/mojom/ca_layer_params_mojom_traits.cc index e1c6ed1b3a456b164945ee7eef34f9d4f0b80e07..87bff4350cdfcca97de6f66946b9cb6155e36634 100644 --- a/ui/gfx/mojom/ca_layer_params_mojom_traits.cc +++ b/ui/gfx/mojom/ca_layer_params_mojom_traits.cc @@ -52,6 +52,9 @@ bool StructTraits::Read( if (!data.ReadPixelSize(&out->pixel_size)) return false; + if (!data.ReadDamage(&out->damage)) + return false; + out->scale_factor = data.scale_factor(); return true; } diff --git a/ui/gfx/mojom/ca_layer_params_mojom_traits.h b/ui/gfx/mojom/ca_layer_params_mojom_traits.h index b6d3f2fea1d663ee1eba82a8008afc830897534c..e06f7d3184d66d9585af39c896036c1792693ac5 100644 --- a/ui/gfx/mojom/ca_layer_params_mojom_traits.h +++ b/ui/gfx/mojom/ca_layer_params_mojom_traits.h @@ -20,6 +20,10 @@ struct StructTraits { return ca_layer_params.pixel_size; } + static gfx::Rect damage(const gfx::CALayerParams& ca_layer_params) { + return ca_layer_params.damage; + } + static float scale_factor(const gfx::CALayerParams& ca_layer_params) { return ca_layer_params.scale_factor; }