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 d3970b4d86e1fadc5321e99be20813c0f811d6b3..66d3ae8ecc299456de8ff621b2957f9d18e984a1 100644 --- a/components/viz/host/host_display_client.cc +++ b/components/viz/host/host_display_client.cc @@ -46,9 +46,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; @@ -56,8 +56,12 @@ 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 +} // TODO(crbug.com/1052397): Revisit the macro expression once build flag switch // of lacros-chrome is complete. diff --git a/components/viz/host/host_display_client.h b/components/viz/host/host_display_client.h index 1c2885c42f4947bb22ce87c8b2d649689b278da1..e588d77072537b6b0760b278de72d69aa44f2b3f 100644 --- a/components/viz/host/host_display_client.h +++ b/components/viz/host/host_display_client.h @@ -41,10 +41,9 @@ class VIZ_HOST_EXPORT HostDisplayClient : public mojom::DisplayClient { const gfx::CALayerParams& ca_layer_params) override; #endif -#if BUILDFLAG(IS_WIN) + protected: void CreateLayeredWindowUpdater( mojo::PendingReceiver receiver) override; -#endif // TODO(crbug.com/1052397): Revisit the macro expression once build flag switch // of lacros-chrome is complete. diff --git a/components/viz/host/layered_window_updater_impl.cc b/components/viz/host/layered_window_updater_impl.cc index b04f654fe820f821b18e059cdd40085fc2384c4e..ee22012b01ef92bb3b32b5b1081609a7bdfb0d93 100644 --- a/components/viz/host/layered_window_updater_impl.cc +++ b/components/viz/host/layered_window_updater_impl.cc @@ -44,7 +44,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 309422bcf85810db88a048bd0930c4072b41f234..759549f3046f4a897b597409b670bb1c2de7bec0 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 002b3ddfb0f77b787b74ee088578e3eb813d0192..a9003a98546bbfe78e2d30457a032218cc263441 100644 --- a/components/viz/service/BUILD.gn +++ b/components/viz/service/BUILD.gn @@ -139,6 +139,8 @@ viz_component("service") { "display_embedder/output_surface_provider_impl.h", "display_embedder/server_shared_bitmap_manager.cc", "display_embedder/server_shared_bitmap_manager.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/viz_process_context_provider.cc", diff --git a/components/viz/service/display_embedder/output_surface_provider.h b/components/viz/service/display_embedder/output_surface_provider.h index 77d463e683d8b8d3a202681a6884eacaab79d70d..05d51cb2637d34c073cd0025e365803633459a86 100644 --- a/components/viz/service/display_embedder/output_surface_provider.h +++ b/components/viz/service/display_embedder/output_surface_provider.h @@ -39,7 +39,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; }; } // namespace viz 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 8a277c6337d446890bb32814a68db2a9d3d3cd72..1c967969a03c985e68f744cf4815cefbdd2c0f71 100644 --- a/components/viz/service/display_embedder/output_surface_provider_impl.cc +++ b/components/viz/service/display_embedder/output_surface_provider_impl.cc @@ -26,6 +26,7 @@ #include "components/viz/service/display_embedder/server_shared_bitmap_manager.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/display_embedder/viz_process_context_provider.h" #include "components/viz/service/gl/gpu_service_impl.h" @@ -39,6 +40,7 @@ #include "gpu/ipc/scheduler_sequence.h" #include "gpu/ipc/service/gpu_channel_manager_delegate.h" #include "gpu/ipc/service/image_transport_surface.h" +#include "services/viz/privileged/mojom/compositing/layered_window_updater.mojom.h" #include "ui/base/ui_base_switches.h" #include "ui/gl/gl_context.h" #include "ui/gl/init/gl_factory.h" @@ -126,7 +128,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_ASH) if (surface_handle == gpu::kNullSurfaceHandle) return std::make_unique(); @@ -138,7 +141,7 @@ std::unique_ptr OutputSurfaceProviderImpl::CreateOutputSurface( if (!gpu_compositing) { output_surface = std::make_unique( - CreateSoftwareOutputDeviceForPlatform(surface_handle, display_client)); + CreateSoftwareOutputDeviceForPlatform(surface_handle, display_client, offscreen)); } else if (renderer_settings.use_skia_renderer) { DCHECK(gpu_dependency); { @@ -243,10 +246,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) return CreateSoftwareOutputDeviceWin(surface_handle, &output_device_backing_, display_client); 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 fa9bc45b5c12821789270907f73c7e6f3c0c1424..6d2ad1d88631db82f41de2852c3e9a6ad1431b2e 100644 --- a/components/viz/service/display_embedder/output_surface_provider_impl.h +++ b/components/viz/service/display_embedder/output_surface_provider_impl.h @@ -66,12 +66,14 @@ 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; 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_; const raw_ptr task_executor_; 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 33e12349a951ef533b964d1158f8fa124623e946..fc04bcaffefc277dd1d0cdd766168de017fedca8 100644 --- a/components/viz/service/display_embedder/software_output_device_mac.cc +++ b/components/viz/service/display_embedder/software_output_device_mac.cc @@ -105,6 +105,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(); @@ -190,6 +192,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)); 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 a480befb5d8db36e7e281d5033aeef0bea83d220..4e54acc897d08c87bccc3b44f68634e2873cb132 100644 --- a/components/viz/service/display_embedder/software_output_device_mac.h +++ b/components/viz/service/display_embedder/software_output_device_mac.h @@ -59,6 +59,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..d5e90022d129ce6a7a8effd6c85d3a5295ac79bf --- /dev/null +++ b/components/viz/service/display_embedder/software_output_device_proxy.cc @@ -0,0 +1,158 @@ +// 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 "components/viz/service/display_embedder/output_device_backing.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 "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) { + 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_, ResourceFormat::RGBA_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()), 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..daeabe1906b177adfe56b8057a72afb33269f976 --- /dev/null +++ b/components/viz/service/display_embedder/software_output_device_proxy.h @@ -0,0 +1,95 @@ +// 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) 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 583e3e2525c753a0962d481fc67a3582df75d0e9..9416ec929bebcff7f07088e635376ef232eb515f 100644 --- a/components/viz/service/display_embedder/software_output_device_win.cc +++ b/components/viz/service/display_embedder/software_output_device_win.cc @@ -191,7 +191,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 df92bab44402330869b44aa76bb40fc20e33b16a..2b3fbaee17c0a8bb7b04cd4c4edb13626dd1bb27 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 @@ -84,7 +84,8 @@ RootCompositorFrameSinkImpl::Create( params->gpu_compositing, params->widget, params->renderer_settings); 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/content/browser/compositor/viz_process_transport_factory.cc b/content/browser/compositor/viz_process_transport_factory.cc index 0e3af0f9280abe8560393325b400ad2543ed0556..7fe490e55a4bb8a183d0d241188ea15a44347245 100644 --- a/content/browser/compositor/viz_process_transport_factory.cc +++ b/content/browser/compositor/viz_process_transport_factory.cc @@ -381,8 +381,14 @@ void VizProcessTransportFactory::OnEstablishedGpuChannel( compositor_data.display_private.reset(); root_params->display_private = compositor_data.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_); diff --git a/services/viz/privileged/mojom/compositing/display_private.mojom b/services/viz/privileged/mojom/compositing/display_private.mojom index b2f873919d68633103d115d7d9550a098c1a254c..8e38831a6df15d37e5fb87d63613b7dbdcefacc4 100644 --- a/services/viz/privileged/mojom/compositing/display_private.mojom +++ b/services/viz/privileged/mojom/compositing/display_private.mojom @@ -102,7 +102,6 @@ interface DisplayClient { // Creates a LayeredWindowUpdater implementation to draw into a layered // window. - [EnableIf=is_win] CreateLayeredWindowUpdater(pending_receiver receiver); // Notifies that a swap has occurred and provides information about the pixel diff --git a/services/viz/privileged/mojom/compositing/frame_sink_manager.mojom b/services/viz/privileged/mojom/compositing/frame_sink_manager.mojom index a9a0e5a1167b2018e6dc206ecb7d37aad94042aa..3997ecb0228914144d6b04595c47376679fca3ef 100644 --- a/services/viz/privileged/mojom/compositing/frame_sink_manager.mojom +++ b/services/viz/privileged/mojom/compositing/frame_sink_manager.mojom @@ -32,6 +32,7 @@ struct RootCompositorFrameSinkParams { // Disables begin frame rate limiting for the display compositor. bool disable_frame_rate_limit = false; bool use_preferred_interval_for_video = false; + bool offscreen = false; [EnableIf=is_android] float refresh_rate; diff --git a/services/viz/privileged/mojom/compositing/layered_window_updater.mojom b/services/viz/privileged/mojom/compositing/layered_window_updater.mojom index 6b7fbb6cf13dc8ee6ade0878a9a2c1efc5d4d3f1..e2af75168cb914a7b3b4a6c9b6a285498c3f8e72 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 b30b9460889b9bb3862f4e28b5f1292a118f2a09..d8f1f921d3e6e74c99d6a22c902f81dfc5bb646e 100644 --- a/ui/compositor/compositor.h +++ b/ui/compositor/compositor.h @@ -81,6 +81,7 @@ class DisplayPrivate; class ExternalBeginFrameController; } // namespace mojom class ContextProvider; +class HostDisplayClient; class HostFrameSinkManager; class LocalSurfaceId; class RasterContextProvider; @@ -137,6 +138,16 @@ class COMPOSITOR_EXPORT ContextFactory { virtual viz::HostFrameSinkManager* GetHostFrameSinkManager() = 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 // displayable form of pixels comprising a single widget's contents. It draws an @@ -178,6 +189,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 @@ -466,6 +480,8 @@ class COMPOSITOR_EXPORT Compositor : public base::PowerSuspendObserver, std::unique_ptr pending_begin_frame_args_; + CompositorDelegate* 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 c5fb29b30b9c5b7483998c567ed9a479d8743939..dc10d78315f76a3914ccd6e2e99af97fa909918b 100644 --- a/ui/gfx/ca_layer_params.h +++ b/ui/gfx/ca_layer_params.h @@ -6,6 +6,7 @@ #define UI_GFX_CA_LAYER_PARAMS_H_ #include "build/build_config.h" +#include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/size.h" #include "ui/gfx/gfx_export.h" @@ -41,6 +42,8 @@ struct GFX_EXPORT 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 de00e766ba17532e10dcf5d0fd31fa344920a9f7..7aaedf83ad22dcc1d2dd39a31cf7e08b7b6ba4d3 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 c7035798bd867f51b39f36f1be79293bf2b5cc12..131446361de812f9b915483bca2b6d2165b65e3d 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 4cac766eae3161baedac4202f694129cd90c80de..0821495ad22944d8856bb750cac8912a2f8328c3 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; }