1diff --git components/viz/host/host_display_client.cc components/viz/host/host_display_client.cc 2index d3970b4d86e1f..eac209e0a8159 100644 3--- components/viz/host/host_display_client.cc 4+++ components/viz/host/host_display_client.cc 5@@ -46,9 +46,14 @@ void HostDisplayClient::OnDisplayReceivedCALayerParams( 6 } 7 #endif 8 9-#if BUILDFLAG(IS_WIN) 10+void HostDisplayClient::UseProxyOutputDevice( 11+ UseProxyOutputDeviceCallback callback) { 12+ std::move(callback).Run(false); 13+} 14+ 15 void HostDisplayClient::CreateLayeredWindowUpdater( 16 mojo::PendingReceiver<mojom::LayeredWindowUpdater> receiver) { 17+#if BUILDFLAG(IS_WIN) 18 if (!NeedsToUseLayerWindow(widget_)) { 19 DLOG(ERROR) << "HWND shouldn't be using a layered window"; 20 return; 21@@ -56,8 +61,8 @@ void HostDisplayClient::CreateLayeredWindowUpdater( 22 23 layered_window_updater_ = 24 std::make_unique<LayeredWindowUpdaterImpl>(widget_, std::move(receiver)); 25-} 26 #endif 27+} 28 29 // TODO(crbug.com/1052397): Revisit the macro expression once build flag switch 30 // of lacros-chrome is complete. 31diff --git components/viz/host/host_display_client.h components/viz/host/host_display_client.h 32index 1c2885c42f494..7dc5f41a7da79 100644 33--- components/viz/host/host_display_client.h 34+++ components/viz/host/host_display_client.h 35@@ -34,17 +34,17 @@ class VIZ_HOST_EXPORT HostDisplayClient : public mojom::DisplayClient { 36 mojo::PendingRemote<mojom::DisplayClient> GetBoundRemote( 37 scoped_refptr<base::SingleThreadTaskRunner> task_runner); 38 39- private: 40+ protected: 41 // mojom::DisplayClient implementation: 42+ void UseProxyOutputDevice(UseProxyOutputDeviceCallback callback) override; 43+ 44 #if BUILDFLAG(IS_APPLE) 45 void OnDisplayReceivedCALayerParams( 46 const gfx::CALayerParams& ca_layer_params) override; 47 #endif 48 49-#if BUILDFLAG(IS_WIN) 50 void CreateLayeredWindowUpdater( 51 mojo::PendingReceiver<mojom::LayeredWindowUpdater> receiver) override; 52-#endif 53 54 // TODO(crbug.com/1052397): Revisit the macro expression once build flag switch 55 // of lacros-chrome is complete. 56diff --git components/viz/host/layered_window_updater_impl.cc components/viz/host/layered_window_updater_impl.cc 57index b04f654fe820f..131977a36591d 100644 58--- components/viz/host/layered_window_updater_impl.cc 59+++ components/viz/host/layered_window_updater_impl.cc 60@@ -44,7 +44,7 @@ void LayeredWindowUpdaterImpl::OnAllocatedSharedMemory( 61 // |region|'s handle will close when it goes out of scope. 62 } 63 64-void LayeredWindowUpdaterImpl::Draw(DrawCallback draw_callback) { 65+void LayeredWindowUpdaterImpl::Draw(const gfx::Rect& damage_rect, DrawCallback draw_callback) { 66 TRACE_EVENT0("viz", "LayeredWindowUpdaterImpl::Draw"); 67 68 if (!canvas_) { 69diff --git components/viz/host/layered_window_updater_impl.h components/viz/host/layered_window_updater_impl.h 70index 309422bcf8581..759549f3046f4 100644 71--- components/viz/host/layered_window_updater_impl.h 72+++ components/viz/host/layered_window_updater_impl.h 73@@ -38,7 +38,7 @@ class VIZ_HOST_EXPORT LayeredWindowUpdaterImpl 74 // mojom::LayeredWindowUpdater implementation. 75 void OnAllocatedSharedMemory(const gfx::Size& pixel_size, 76 base::UnsafeSharedMemoryRegion region) override; 77- void Draw(DrawCallback draw_callback) override; 78+ void Draw(const gfx::Rect& damage_rect, DrawCallback draw_callback) override; 79 80 private: 81 const HWND hwnd_; 82diff --git components/viz/service/BUILD.gn components/viz/service/BUILD.gn 83index c92e6d2ad10fb..a1d74b50e244b 100644 84--- components/viz/service/BUILD.gn 85+++ components/viz/service/BUILD.gn 86@@ -221,6 +221,8 @@ viz_component("service") { 87 "transitions/transferable_resource_tracker.cc", 88 "transitions/transferable_resource_tracker.h", 89 "viz_service_export.h", 90+ "//cef/libcef/browser/osr/software_output_device_proxy.cc", 91+ "//cef/libcef/browser/osr/software_output_device_proxy.h", 92 ] 93 94 defines = [ "VIZ_SERVICE_IMPLEMENTATION" ] 95diff --git components/viz/service/display_embedder/output_surface_provider_impl.cc components/viz/service/display_embedder/output_surface_provider_impl.cc 96index 8a277c6337d44..c857919b010c6 100644 97--- components/viz/service/display_embedder/output_surface_provider_impl.cc 98+++ components/viz/service/display_embedder/output_surface_provider_impl.cc 99@@ -17,6 +17,7 @@ 100 #include "build/chromecast_buildflags.h" 101 #include "build/chromeos_buildflags.h" 102 #include "cc/base/switches.h" 103+#include "cef/libcef/browser/osr/software_output_device_proxy.h" 104 #include "components/viz/common/display/renderer_settings.h" 105 #include "components/viz/common/frame_sinks/begin_frame_source.h" 106 #include "components/viz/service/display/display_compositor_memory_and_task_controller.h" 107@@ -247,6 +248,20 @@ OutputSurfaceProviderImpl::CreateSoftwareOutputDeviceForPlatform( 108 if (headless_) 109 return std::make_unique<SoftwareOutputDevice>(); 110 111+ { 112+ mojo::ScopedAllowSyncCallForTesting allow_sync; 113+ DCHECK(display_client); 114+ bool use_proxy_output_device = false; 115+ if (display_client->UseProxyOutputDevice(&use_proxy_output_device) && 116+ use_proxy_output_device) { 117+ mojom::LayeredWindowUpdaterPtr layered_window_updater; 118+ display_client->CreateLayeredWindowUpdater( 119+ mojo::MakeRequest(&layered_window_updater)); 120+ return std::make_unique<SoftwareOutputDeviceProxy>( 121+ std::move(layered_window_updater)); 122+ } 123+ } 124+ 125 #if BUILDFLAG(IS_WIN) 126 return CreateSoftwareOutputDeviceWin(surface_handle, &output_device_backing_, 127 display_client); 128diff --git components/viz/service/display_embedder/software_output_device_win.cc components/viz/service/display_embedder/software_output_device_win.cc 129index 583e3e2525c75..e1836039ad8a5 100644 130--- components/viz/service/display_embedder/software_output_device_win.cc 131+++ components/viz/service/display_embedder/software_output_device_win.cc 132@@ -191,8 +191,9 @@ void SoftwareOutputDeviceWinProxy::EndPaintDelegated( 133 if (!canvas_) 134 return; 135 136- layered_window_updater_->Draw(base::BindOnce( 137- &SoftwareOutputDeviceWinProxy::DrawAck, base::Unretained(this))); 138+ layered_window_updater_->Draw( 139+ damage_rect, base::BindOnce(&SoftwareOutputDeviceWinProxy::DrawAck, 140+ base::Unretained(this))); 141 waiting_on_draw_ack_ = true; 142 143 TRACE_EVENT_ASYNC_BEGIN0("viz", "SoftwareOutputDeviceWinProxy::Draw", this); 144diff --git content/browser/compositor/viz_process_transport_factory.cc content/browser/compositor/viz_process_transport_factory.cc 145index 0e3af0f9280ab..8a1e93995b316 100644 146--- content/browser/compositor/viz_process_transport_factory.cc 147+++ content/browser/compositor/viz_process_transport_factory.cc 148@@ -381,8 +381,13 @@ void VizProcessTransportFactory::OnEstablishedGpuChannel( 149 compositor_data.display_private.reset(); 150 root_params->display_private = 151 compositor_data.display_private.BindNewEndpointAndPassReceiver(); 152- compositor_data.display_client = 153- std::make_unique<HostDisplayClient>(compositor); 154+ if (compositor->delegate()) { 155+ compositor_data.display_client = 156+ compositor->delegate()->CreateHostDisplayClient(); 157+ } else { 158+ compositor_data.display_client = 159+ std::make_unique<HostDisplayClient>(compositor); 160+ } 161 root_params->display_client = 162 compositor_data.display_client->GetBoundRemote(resize_task_runner_); 163 164diff --git mojo/public/cpp/bindings/sync_call_restrictions.h mojo/public/cpp/bindings/sync_call_restrictions.h 165index e7e67ee824b2a..bb044cff83f58 100644 166--- mojo/public/cpp/bindings/sync_call_restrictions.h 167+++ mojo/public/cpp/bindings/sync_call_restrictions.h 168@@ -42,6 +42,7 @@ class Compositor; 169 } // namespace ui 170 171 namespace viz { 172+class GpuDisplayProvider; 173 class GpuHostImpl; 174 class HostFrameSinkManager; 175 class HostGpuMemoryBufferManager; 176@@ -104,6 +105,8 @@ class COMPONENT_EXPORT(MOJO_CPP_BINDINGS) SyncCallRestrictions { 177 // For preventing frame swaps of wrong size during resize on Windows. 178 // (https://crbug.com/811945) 179 friend class ui::Compositor; 180+ // For query of whether to use SoftwareOutputDevice or not. 181+ friend class viz::GpuDisplayProvider; 182 // For calling sync mojo API to get cdm origin. The service and the client are 183 // running in the same process, so it won't block anything. 184 // TODO(159346933) Remove once the origin isolation logic is moved outside of 185diff --git services/viz/privileged/mojom/compositing/display_private.mojom services/viz/privileged/mojom/compositing/display_private.mojom 186index 9f7583e424057..c301c518dd8ec 100644 187--- services/viz/privileged/mojom/compositing/display_private.mojom 188+++ services/viz/privileged/mojom/compositing/display_private.mojom 189@@ -89,12 +89,14 @@ interface DisplayPrivate { 190 }; 191 192 interface DisplayClient { 193+ [Sync] 194+ UseProxyOutputDevice() => (bool success); 195+ 196 [EnableIf=is_mac] 197 OnDisplayReceivedCALayerParams(gfx.mojom.CALayerParams ca_layer_params); 198 199 // Creates a LayeredWindowUpdater implementation to draw into a layered 200 // window. 201- [EnableIf=is_win] 202 CreateLayeredWindowUpdater(pending_receiver<LayeredWindowUpdater> receiver); 203 204 // Notifies that a swap has occurred and provides information about the pixel 205diff --git services/viz/privileged/mojom/compositing/layered_window_updater.mojom services/viz/privileged/mojom/compositing/layered_window_updater.mojom 206index 6b7fbb6cf13dc..e2af75168cb91 100644 207--- services/viz/privileged/mojom/compositing/layered_window_updater.mojom 208+++ services/viz/privileged/mojom/compositing/layered_window_updater.mojom 209@@ -26,5 +26,5 @@ interface LayeredWindowUpdater { 210 // Draws to the HWND by copying pixels from shared memory. Callback must be 211 // called after draw operation is complete to signal shared memory can be 212 // modified. 213- Draw() => (); 214+ Draw(gfx.mojom.Rect damage_rect) => (); 215 }; 216diff --git ui/compositor/compositor.h ui/compositor/compositor.h 217index 383aff3755d4b..a5b2a79d3a724 100644 218--- ui/compositor/compositor.h 219+++ ui/compositor/compositor.h 220@@ -30,7 +30,9 @@ 221 #include "components/viz/common/frame_sinks/begin_frame_args.h" 222 #include "components/viz/common/surfaces/frame_sink_id.h" 223 #include "components/viz/common/surfaces/subtree_capture_id.h" 224+#include "components/viz/host/host_display_client.h" 225 #include "components/viz/host/host_frame_sink_client.h" 226+#include "components/viz/service/display/software_output_device.h" 227 #include "mojo/public/cpp/bindings/pending_remote.h" 228 #include "services/viz/privileged/mojom/compositing/vsync_parameter_observer.mojom-forward.h" 229 #include "skia/ext/skia_matrix_44.h" 230@@ -137,6 +139,14 @@ class COMPOSITOR_EXPORT ContextFactory { 231 virtual viz::HostFrameSinkManager* GetHostFrameSinkManager() = 0; 232 }; 233 234+class COMPOSITOR_EXPORT CompositorDelegate { 235+ public: 236+ virtual std::unique_ptr<viz::HostDisplayClient> CreateHostDisplayClient() = 0; 237+ 238+ protected: 239+ virtual ~CompositorDelegate() {} 240+}; 241+ 242 // Compositor object to take care of GPU painting. 243 // A Browser compositor object is responsible for generating the final 244 // displayable form of pixels comprising a single widget's contents. It draws an 245@@ -177,6 +187,9 @@ class COMPOSITOR_EXPORT Compositor : public base::PowerSuspendObserver, 246 // Schedules a redraw of the layer tree associated with this compositor. 247 void ScheduleDraw(); 248 249+ CompositorDelegate* delegate() const { return delegate_; } 250+ void SetDelegate(CompositorDelegate* delegate) { delegate_ = delegate; } 251+ 252 // Sets the root of the layer tree drawn by this Compositor. The root layer 253 // must have no parent. The compositor's root layer is reset if the root layer 254 // is destroyed. NULL can be passed to reset the root layer, in which case the 255@@ -453,6 +466,8 @@ class COMPOSITOR_EXPORT Compositor : public base::PowerSuspendObserver, 256 257 std::unique_ptr<PendingBeginFrameArgs> pending_begin_frame_args_; 258 259+ CompositorDelegate* delegate_ = nullptr; 260+ 261 // The root of the Layer tree drawn by this compositor. 262 raw_ptr<Layer> root_layer_ = nullptr; 263 264