feat_enable_offscreen_rendering_with_viz_compositor.patch 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683
  1. From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
  2. From: Andy Dill <[email protected]>
  3. Date: Thu, 30 Jan 2020 09:36:07 -0800
  4. Subject: feat: enable off-screen rendering with viz compositor
  5. This patch adds hooks in the relevant places that allow for off-screen
  6. rendering with the viz compositor by way of a custom HostDisplayClient
  7. and LayeredWindowUpdater.
  8. diff --git a/components/viz/host/host_display_client.cc b/components/viz/host/host_display_client.cc
  9. index d3970b4d86e1fadc5321e99be20813c0f811d6b3..66d3ae8ecc299456de8ff621b2957f9d18e984a1 100644
  10. --- a/components/viz/host/host_display_client.cc
  11. +++ b/components/viz/host/host_display_client.cc
  12. @@ -46,9 +46,9 @@ void HostDisplayClient::OnDisplayReceivedCALayerParams(
  13. }
  14. #endif
  15. -#if BUILDFLAG(IS_WIN)
  16. void HostDisplayClient::CreateLayeredWindowUpdater(
  17. mojo::PendingReceiver<mojom::LayeredWindowUpdater> receiver) {
  18. +#if BUILDFLAG(IS_WIN)
  19. if (!NeedsToUseLayerWindow(widget_)) {
  20. DLOG(ERROR) << "HWND shouldn't be using a layered window";
  21. return;
  22. @@ -56,8 +56,12 @@ void HostDisplayClient::CreateLayeredWindowUpdater(
  23. layered_window_updater_ =
  24. std::make_unique<LayeredWindowUpdaterImpl>(widget_, std::move(receiver));
  25. -}
  26. +#else
  27. + CHECK(false) << "Chromium is calling CreateLayeredWindowUpdater for non-OSR "
  28. + "windows on POSIX platforms, something is wrong with "
  29. + "Electron's OSR implementation.";
  30. #endif
  31. +}
  32. // TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
  33. // of lacros-chrome is complete.
  34. diff --git a/components/viz/host/host_display_client.h b/components/viz/host/host_display_client.h
  35. index 1c2885c42f4947bb22ce87c8b2d649689b278da1..e588d77072537b6b0760b278de72d69aa44f2b3f 100644
  36. --- a/components/viz/host/host_display_client.h
  37. +++ b/components/viz/host/host_display_client.h
  38. @@ -41,10 +41,9 @@ class VIZ_HOST_EXPORT HostDisplayClient : public mojom::DisplayClient {
  39. const gfx::CALayerParams& ca_layer_params) override;
  40. #endif
  41. -#if BUILDFLAG(IS_WIN)
  42. + protected:
  43. void CreateLayeredWindowUpdater(
  44. mojo::PendingReceiver<mojom::LayeredWindowUpdater> receiver) override;
  45. -#endif
  46. // TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
  47. // of lacros-chrome is complete.
  48. diff --git a/components/viz/host/layered_window_updater_impl.cc b/components/viz/host/layered_window_updater_impl.cc
  49. index b04f654fe820f821b18e059cdd40085fc2384c4e..ee22012b01ef92bb3b32b5b1081609a7bdfb0d93 100644
  50. --- a/components/viz/host/layered_window_updater_impl.cc
  51. +++ b/components/viz/host/layered_window_updater_impl.cc
  52. @@ -44,7 +44,9 @@ void LayeredWindowUpdaterImpl::OnAllocatedSharedMemory(
  53. // |region|'s handle will close when it goes out of scope.
  54. }
  55. -void LayeredWindowUpdaterImpl::Draw(DrawCallback draw_callback) {
  56. +void LayeredWindowUpdaterImpl::Draw(
  57. + const gfx::Rect& damage_rect,
  58. + DrawCallback draw_callback) {
  59. TRACE_EVENT0("viz", "LayeredWindowUpdaterImpl::Draw");
  60. if (!canvas_) {
  61. diff --git a/components/viz/host/layered_window_updater_impl.h b/components/viz/host/layered_window_updater_impl.h
  62. index 309422bcf85810db88a048bd0930c4072b41f234..759549f3046f4a897b597409b670bb1c2de7bec0 100644
  63. --- a/components/viz/host/layered_window_updater_impl.h
  64. +++ b/components/viz/host/layered_window_updater_impl.h
  65. @@ -38,7 +38,7 @@ class VIZ_HOST_EXPORT LayeredWindowUpdaterImpl
  66. // mojom::LayeredWindowUpdater implementation.
  67. void OnAllocatedSharedMemory(const gfx::Size& pixel_size,
  68. base::UnsafeSharedMemoryRegion region) override;
  69. - void Draw(DrawCallback draw_callback) override;
  70. + void Draw(const gfx::Rect& damage_rect, DrawCallback draw_callback) override;
  71. private:
  72. const HWND hwnd_;
  73. diff --git a/components/viz/service/BUILD.gn b/components/viz/service/BUILD.gn
  74. index 002b3ddfb0f77b787b74ee088578e3eb813d0192..a9003a98546bbfe78e2d30457a032218cc263441 100644
  75. --- a/components/viz/service/BUILD.gn
  76. +++ b/components/viz/service/BUILD.gn
  77. @@ -139,6 +139,8 @@ viz_component("service") {
  78. "display_embedder/output_surface_provider_impl.h",
  79. "display_embedder/server_shared_bitmap_manager.cc",
  80. "display_embedder/server_shared_bitmap_manager.h",
  81. + "display_embedder/software_output_device_proxy.cc",
  82. + "display_embedder/software_output_device_proxy.h",
  83. "display_embedder/software_output_surface.cc",
  84. "display_embedder/software_output_surface.h",
  85. "display_embedder/viz_process_context_provider.cc",
  86. diff --git a/components/viz/service/display_embedder/output_surface_provider.h b/components/viz/service/display_embedder/output_surface_provider.h
  87. index 77d463e683d8b8d3a202681a6884eacaab79d70d..05d51cb2637d34c073cd0025e365803633459a86 100644
  88. --- a/components/viz/service/display_embedder/output_surface_provider.h
  89. +++ b/components/viz/service/display_embedder/output_surface_provider.h
  90. @@ -39,7 +39,8 @@ class OutputSurfaceProvider {
  91. mojom::DisplayClient* display_client,
  92. DisplayCompositorMemoryAndTaskController* gpu_dependency,
  93. const RendererSettings& renderer_settings,
  94. - const DebugRendererSettings* debug_settings) = 0;
  95. + const DebugRendererSettings* debug_settings,
  96. + bool offscreen) = 0;
  97. };
  98. } // namespace viz
  99. diff --git a/components/viz/service/display_embedder/output_surface_provider_impl.cc b/components/viz/service/display_embedder/output_surface_provider_impl.cc
  100. index 8a277c6337d446890bb32814a68db2a9d3d3cd72..1c967969a03c985e68f744cf4815cefbdd2c0f71 100644
  101. --- a/components/viz/service/display_embedder/output_surface_provider_impl.cc
  102. +++ b/components/viz/service/display_embedder/output_surface_provider_impl.cc
  103. @@ -26,6 +26,7 @@
  104. #include "components/viz/service/display_embedder/server_shared_bitmap_manager.h"
  105. #include "components/viz/service/display_embedder/skia_output_surface_dependency_impl.h"
  106. #include "components/viz/service/display_embedder/skia_output_surface_impl.h"
  107. +#include "components/viz/service/display_embedder/software_output_device_proxy.h"
  108. #include "components/viz/service/display_embedder/software_output_surface.h"
  109. #include "components/viz/service/display_embedder/viz_process_context_provider.h"
  110. #include "components/viz/service/gl/gpu_service_impl.h"
  111. @@ -39,6 +40,7 @@
  112. #include "gpu/ipc/scheduler_sequence.h"
  113. #include "gpu/ipc/service/gpu_channel_manager_delegate.h"
  114. #include "gpu/ipc/service/image_transport_surface.h"
  115. +#include "services/viz/privileged/mojom/compositing/layered_window_updater.mojom.h"
  116. #include "ui/base/ui_base_switches.h"
  117. #include "ui/gl/gl_context.h"
  118. #include "ui/gl/init/gl_factory.h"
  119. @@ -126,7 +128,8 @@ std::unique_ptr<OutputSurface> OutputSurfaceProviderImpl::CreateOutputSurface(
  120. mojom::DisplayClient* display_client,
  121. DisplayCompositorMemoryAndTaskController* gpu_dependency,
  122. const RendererSettings& renderer_settings,
  123. - const DebugRendererSettings* debug_settings) {
  124. + const DebugRendererSettings* debug_settings,
  125. + bool offscreen) {
  126. #if BUILDFLAG(IS_CHROMEOS_ASH)
  127. if (surface_handle == gpu::kNullSurfaceHandle)
  128. return std::make_unique<OutputSurfaceUnified>();
  129. @@ -138,7 +141,7 @@ std::unique_ptr<OutputSurface> OutputSurfaceProviderImpl::CreateOutputSurface(
  130. if (!gpu_compositing) {
  131. output_surface = std::make_unique<SoftwareOutputSurface>(
  132. - CreateSoftwareOutputDeviceForPlatform(surface_handle, display_client));
  133. + CreateSoftwareOutputDeviceForPlatform(surface_handle, display_client, offscreen));
  134. } else if (renderer_settings.use_skia_renderer) {
  135. DCHECK(gpu_dependency);
  136. {
  137. @@ -243,10 +246,22 @@ std::unique_ptr<OutputSurface> OutputSurfaceProviderImpl::CreateOutputSurface(
  138. std::unique_ptr<SoftwareOutputDevice>
  139. OutputSurfaceProviderImpl::CreateSoftwareOutputDeviceForPlatform(
  140. gpu::SurfaceHandle surface_handle,
  141. - mojom::DisplayClient* display_client) {
  142. + mojom::DisplayClient* display_client,
  143. + bool offscreen) {
  144. if (headless_)
  145. return std::make_unique<SoftwareOutputDevice>();
  146. +#if !BUILDFLAG(IS_APPLE)
  147. + if (offscreen) {
  148. + DCHECK(display_client);
  149. + mojo::PendingRemote<mojom::LayeredWindowUpdater> layered_window_updater;
  150. + display_client->CreateLayeredWindowUpdater(
  151. + layered_window_updater.InitWithNewPipeAndPassReceiver());
  152. + return std::make_unique<SoftwareOutputDeviceProxy>(
  153. + std::move(layered_window_updater));
  154. + }
  155. +#endif
  156. +
  157. #if BUILDFLAG(IS_WIN)
  158. return CreateSoftwareOutputDeviceWin(surface_handle, &output_device_backing_,
  159. display_client);
  160. diff --git a/components/viz/service/display_embedder/output_surface_provider_impl.h b/components/viz/service/display_embedder/output_surface_provider_impl.h
  161. index fa9bc45b5c12821789270907f73c7e6f3c0c1424..6d2ad1d88631db82f41de2852c3e9a6ad1431b2e 100644
  162. --- a/components/viz/service/display_embedder/output_surface_provider_impl.h
  163. +++ b/components/viz/service/display_embedder/output_surface_provider_impl.h
  164. @@ -66,12 +66,14 @@ class VIZ_SERVICE_EXPORT OutputSurfaceProviderImpl
  165. mojom::DisplayClient* display_client,
  166. DisplayCompositorMemoryAndTaskController* gpu_dependency,
  167. const RendererSettings& renderer_settings,
  168. - const DebugRendererSettings* debug_settings) override;
  169. + const DebugRendererSettings* debug_settings,
  170. + bool offscreen) override;
  171. private:
  172. std::unique_ptr<SoftwareOutputDevice> CreateSoftwareOutputDeviceForPlatform(
  173. gpu::SurfaceHandle surface_handle,
  174. - mojom::DisplayClient* display_client);
  175. + mojom::DisplayClient* display_client,
  176. + bool offscreen);
  177. const raw_ptr<GpuServiceImpl> gpu_service_impl_;
  178. const raw_ptr<gpu::CommandBufferTaskExecutor> task_executor_;
  179. diff --git a/components/viz/service/display_embedder/software_output_device_mac.cc b/components/viz/service/display_embedder/software_output_device_mac.cc
  180. index 33e12349a951ef533b964d1158f8fa124623e946..fc04bcaffefc277dd1d0cdd766168de017fedca8 100644
  181. --- a/components/viz/service/display_embedder/software_output_device_mac.cc
  182. +++ b/components/viz/service/display_embedder/software_output_device_mac.cc
  183. @@ -105,6 +105,8 @@ void SoftwareOutputDeviceMac::UpdateAndCopyBufferDamage(
  184. SkCanvas* SoftwareOutputDeviceMac::BeginPaint(
  185. const gfx::Rect& new_damage_rect) {
  186. + last_damage = new_damage_rect;
  187. +
  188. // Record the previous paint buffer.
  189. Buffer* previous_paint_buffer =
  190. buffer_queue_.empty() ? nullptr : buffer_queue_.back().get();
  191. @@ -190,6 +192,7 @@ void SoftwareOutputDeviceMac::EndPaint() {
  192. ca_layer_params.is_empty = false;
  193. ca_layer_params.scale_factor = scale_factor_;
  194. ca_layer_params.pixel_size = pixel_size_;
  195. + ca_layer_params.damage = last_damage;
  196. ca_layer_params.io_surface_mach_port.reset(
  197. IOSurfaceCreateMachPort(current_paint_buffer_->io_surface));
  198. client_->SoftwareDeviceUpdatedCALayerParams(ca_layer_params);
  199. diff --git a/components/viz/service/display_embedder/software_output_device_mac.h b/components/viz/service/display_embedder/software_output_device_mac.h
  200. index a480befb5d8db36e7e281d5033aeef0bea83d220..4e54acc897d08c87bccc3b44f68634e2873cb132 100644
  201. --- a/components/viz/service/display_embedder/software_output_device_mac.h
  202. +++ b/components/viz/service/display_embedder/software_output_device_mac.h
  203. @@ -59,6 +59,7 @@ class VIZ_SERVICE_EXPORT SoftwareOutputDeviceMac : public SoftwareOutputDevice {
  204. void UpdateAndCopyBufferDamage(Buffer* previous_paint_buffer,
  205. const SkRegion& new_damage_rect);
  206. + gfx::Rect last_damage;
  207. gfx::Size pixel_size_;
  208. float scale_factor_ = 1;
  209. diff --git a/components/viz/service/display_embedder/software_output_device_proxy.cc b/components/viz/service/display_embedder/software_output_device_proxy.cc
  210. new file mode 100644
  211. index 0000000000000000000000000000000000000000..d5e90022d129ce6a7a8effd6c85d3a5295ac79bf
  212. --- /dev/null
  213. +++ b/components/viz/service/display_embedder/software_output_device_proxy.cc
  214. @@ -0,0 +1,158 @@
  215. +// Copyright 2014 The Chromium Authors. All rights reserved.
  216. +// Use of this source code is governed by a BSD-style license that can be
  217. +// found in the LICENSE file.
  218. +
  219. +#include "components/viz/service/display_embedder/software_output_device_proxy.h"
  220. +
  221. +#include "base/memory/unsafe_shared_memory_region.h"
  222. +#include "base/threading/thread_checker.h"
  223. +#include "base/trace_event/trace_event.h"
  224. +#include "build/build_config.h"
  225. +#include "components/viz/common/resources/resource_sizes.h"
  226. +#include "components/viz/service/display_embedder/output_device_backing.h"
  227. +#include "mojo/public/cpp/system/platform_handle.h"
  228. +#include "services/viz/privileged/mojom/compositing/layered_window_updater.mojom.h"
  229. +#include "skia/ext/platform_canvas.h"
  230. +#include "third_party/skia/include/core/SkCanvas.h"
  231. +#include "ui/gfx/skia_util.h"
  232. +
  233. +#if BUILDFLAG(IS_WIN)
  234. +#include "skia/ext/skia_utils_win.h"
  235. +#include "ui/gfx/gdi_util.h"
  236. +#include "ui/gfx/win/hwnd_util.h"
  237. +#else
  238. +#include "mojo/public/cpp/base/shared_memory_utils.h"
  239. +#endif
  240. +
  241. +namespace viz {
  242. +
  243. +SoftwareOutputDeviceBase::~SoftwareOutputDeviceBase() {
  244. + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  245. + DCHECK(!in_paint_);
  246. +}
  247. +
  248. +void SoftwareOutputDeviceBase::Resize(const gfx::Size& viewport_pixel_size,
  249. + float scale_factor) {
  250. + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  251. + DCHECK(!in_paint_);
  252. +
  253. + if (viewport_pixel_size_ == viewport_pixel_size)
  254. + return;
  255. +
  256. + viewport_pixel_size_ = viewport_pixel_size;
  257. + ResizeDelegated();
  258. +}
  259. +
  260. +SkCanvas* SoftwareOutputDeviceBase::BeginPaint(
  261. + const gfx::Rect& damage_rect) {
  262. + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  263. + DCHECK(!in_paint_);
  264. +
  265. + damage_rect_ = damage_rect;
  266. + in_paint_ = true;
  267. + return BeginPaintDelegated();
  268. +}
  269. +
  270. +void SoftwareOutputDeviceBase::EndPaint() {
  271. + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  272. + DCHECK(in_paint_);
  273. +
  274. + in_paint_ = false;
  275. +
  276. + gfx::Rect intersected_damage_rect = damage_rect_;
  277. + intersected_damage_rect.Intersect(gfx::Rect(viewport_pixel_size_));
  278. + if (intersected_damage_rect.IsEmpty())
  279. + return;
  280. +
  281. + EndPaintDelegated(intersected_damage_rect);
  282. +}
  283. +
  284. +SoftwareOutputDeviceProxy::~SoftwareOutputDeviceProxy() = default;
  285. +
  286. +SoftwareOutputDeviceProxy::SoftwareOutputDeviceProxy(
  287. + mojo::PendingRemote<mojom::LayeredWindowUpdater> layered_window_updater)
  288. + : layered_window_updater_(std::move(layered_window_updater)) {
  289. + DCHECK(layered_window_updater_.is_bound());
  290. +}
  291. +
  292. +void SoftwareOutputDeviceProxy::OnSwapBuffers(
  293. + SoftwareOutputDevice::SwapBuffersCallback swap_ack_callback) {
  294. + DCHECK(swap_ack_callback_.is_null());
  295. +
  296. + // We aren't waiting on DrawAck() and can immediately run the callback.
  297. + if (!waiting_on_draw_ack_) {
  298. + task_runner_->PostTask(FROM_HERE,
  299. + base::BindOnce(std::move(swap_ack_callback), viewport_pixel_size_));
  300. + return;
  301. + }
  302. +
  303. + swap_ack_callback_ = std::move(swap_ack_callback);
  304. +}
  305. +
  306. +void SoftwareOutputDeviceProxy::ResizeDelegated() {
  307. + canvas_.reset();
  308. +
  309. + size_t required_bytes;
  310. + if (!ResourceSizes::MaybeSizeInBytes(
  311. + viewport_pixel_size_, ResourceFormat::RGBA_8888, &required_bytes)) {
  312. + DLOG(ERROR) << "Invalid viewport size " << viewport_pixel_size_.ToString();
  313. + return;
  314. + }
  315. +
  316. + base::UnsafeSharedMemoryRegion region =
  317. + base::UnsafeSharedMemoryRegion::Create(required_bytes);
  318. + if (!region.IsValid()) {
  319. + DLOG(ERROR) << "Failed to allocate " << required_bytes << " bytes";
  320. + return;
  321. + }
  322. +
  323. + #if defined(WIN32)
  324. + canvas_ = skia::CreatePlatformCanvasWithSharedSection(
  325. + viewport_pixel_size_.width(), viewport_pixel_size_.height(), false,
  326. + region.GetPlatformHandle(), skia::CRASH_ON_FAILURE);
  327. + #else
  328. + shm_mapping_ = region.Map();
  329. + if (!shm_mapping_.IsValid()) {
  330. + DLOG(ERROR) << "Failed to map " << required_bytes << " bytes";
  331. + return;
  332. + }
  333. +
  334. + canvas_ = skia::CreatePlatformCanvasWithPixels(
  335. + viewport_pixel_size_.width(), viewport_pixel_size_.height(), false,
  336. + static_cast<uint8_t*>(shm_mapping_.memory()), skia::CRASH_ON_FAILURE);
  337. + #endif
  338. +
  339. + // Transfer region ownership to the browser process.
  340. + layered_window_updater_->OnAllocatedSharedMemory(viewport_pixel_size_,
  341. + std::move(region));
  342. +}
  343. +
  344. +SkCanvas* SoftwareOutputDeviceProxy::BeginPaintDelegated() {
  345. + return canvas_.get();
  346. +}
  347. +
  348. +void SoftwareOutputDeviceProxy::EndPaintDelegated(
  349. + const gfx::Rect& damage_rect) {
  350. + DCHECK(!waiting_on_draw_ack_);
  351. +
  352. + if (!canvas_)
  353. + return;
  354. +
  355. + layered_window_updater_->Draw(damage_rect, base::BindOnce(
  356. + &SoftwareOutputDeviceProxy::DrawAck, base::Unretained(this)));
  357. + waiting_on_draw_ack_ = true;
  358. +
  359. + TRACE_EVENT_ASYNC_BEGIN0("viz", "SoftwareOutputDeviceProxy::Draw", this);
  360. +}
  361. +
  362. +void SoftwareOutputDeviceProxy::DrawAck() {
  363. + DCHECK(waiting_on_draw_ack_);
  364. + DCHECK(!swap_ack_callback_.is_null());
  365. +
  366. + TRACE_EVENT_ASYNC_END0("viz", "SoftwareOutputDeviceProxy::Draw", this);
  367. +
  368. + waiting_on_draw_ack_ = false;
  369. + std::move(swap_ack_callback_).Run(viewport_pixel_size_);
  370. +}
  371. +
  372. +} // namespace viz
  373. diff --git a/components/viz/service/display_embedder/software_output_device_proxy.h b/components/viz/service/display_embedder/software_output_device_proxy.h
  374. new file mode 100644
  375. index 0000000000000000000000000000000000000000..daeabe1906b177adfe56b8057a72afb33269f976
  376. --- /dev/null
  377. +++ b/components/viz/service/display_embedder/software_output_device_proxy.h
  378. @@ -0,0 +1,95 @@
  379. +// Copyright 2014 The Chromium Authors. All rights reserved.
  380. +// Use of this source code is governed by a BSD-style license that can be
  381. +// found in the LICENSE file.
  382. +
  383. +#ifndef COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_SOFTWARE_OUTPUT_DEVICE_PROXY_H_
  384. +#define COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_SOFTWARE_OUTPUT_DEVICE_PROXY_H_
  385. +
  386. +#include <memory>
  387. +
  388. +#include "base/memory/shared_memory_mapping.h"
  389. +#include "base/threading/thread_checker.h"
  390. +#include "build/build_config.h"
  391. +#include "components/viz/host/host_display_client.h"
  392. +#include "components/viz/service/display/software_output_device.h"
  393. +#include "components/viz/service/viz_service_export.h"
  394. +#include "mojo/public/cpp/bindings/pending_remote.h"
  395. +#include "mojo/public/cpp/bindings/remote.h"
  396. +#include "services/viz/privileged/mojom/compositing/display_private.mojom.h"
  397. +#include "services/viz/privileged/mojom/compositing/layered_window_updater.mojom.h"
  398. +
  399. +#if BUILDFLAG(IS_WIN)
  400. +#include <windows.h>
  401. +#endif
  402. +
  403. +namespace viz {
  404. +
  405. +// Shared base class for SoftwareOutputDevice implementations.
  406. +class SoftwareOutputDeviceBase : public SoftwareOutputDevice {
  407. + public:
  408. + SoftwareOutputDeviceBase() = default;
  409. + ~SoftwareOutputDeviceBase() override;
  410. +
  411. + SoftwareOutputDeviceBase(const SoftwareOutputDeviceBase&) = delete;
  412. + SoftwareOutputDeviceBase& operator=(const SoftwareOutputDeviceBase&) = delete;
  413. +
  414. + // SoftwareOutputDevice implementation.
  415. + void Resize(const gfx::Size& viewport_pixel_size,
  416. + float scale_factor) override;
  417. + SkCanvas* BeginPaint(const gfx::Rect& damage_rect) override;
  418. + void EndPaint() override;
  419. +
  420. + // Called from Resize() if |viewport_pixel_size_| has changed.
  421. + virtual void ResizeDelegated() = 0;
  422. +
  423. + // Called from BeginPaint() and should return an SkCanvas.
  424. + virtual SkCanvas* BeginPaintDelegated() = 0;
  425. +
  426. + // Called from EndPaint() if there is damage.
  427. + virtual void EndPaintDelegated(const gfx::Rect& damage_rect) = 0;
  428. +
  429. + private:
  430. + bool in_paint_ = false;
  431. +
  432. + THREAD_CHECKER(thread_checker_);
  433. +};
  434. +
  435. +// SoftwareOutputDevice implementation that draws indirectly. An implementation
  436. +// of mojom::LayeredWindowUpdater in the browser process handles the actual
  437. +// drawing. Pixel backing is in SharedMemory so no copying between processes
  438. +// is required.
  439. +class SoftwareOutputDeviceProxy : public SoftwareOutputDeviceBase {
  440. + public:
  441. + explicit SoftwareOutputDeviceProxy(
  442. + mojo::PendingRemote<mojom::LayeredWindowUpdater> layered_window_updater);
  443. + ~SoftwareOutputDeviceProxy() override;
  444. +
  445. + SoftwareOutputDeviceProxy(const SoftwareOutputDeviceProxy&) = delete;
  446. + SoftwareOutputDeviceProxy& operator=(const SoftwareOutputDeviceProxy&) = delete;
  447. +
  448. + // SoftwareOutputDevice implementation.
  449. + void OnSwapBuffers(SoftwareOutputDevice::SwapBuffersCallback swap_ack_callback) override;
  450. +
  451. + // SoftwareOutputDeviceBase implementation.
  452. + void ResizeDelegated() override;
  453. + SkCanvas* BeginPaintDelegated() override;
  454. + void EndPaintDelegated(const gfx::Rect& rect) override;
  455. +
  456. + private:
  457. + // Runs |swap_ack_callback_| after draw has happened.
  458. + void DrawAck();
  459. +
  460. + mojo::Remote<mojom::LayeredWindowUpdater> layered_window_updater_;
  461. +
  462. + std::unique_ptr<SkCanvas> canvas_;
  463. + bool waiting_on_draw_ack_ = false;
  464. + SoftwareOutputDevice::SwapBuffersCallback swap_ack_callback_;
  465. +
  466. +#if !defined(WIN32)
  467. + base::WritableSharedMemoryMapping shm_mapping_;
  468. +#endif
  469. +};
  470. +
  471. +} // namespace viz
  472. +
  473. +#endif // COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_SOFTWARE_OUTPUT_DEVICE_PROXY_H_
  474. diff --git a/components/viz/service/display_embedder/software_output_device_win.cc b/components/viz/service/display_embedder/software_output_device_win.cc
  475. index 583e3e2525c753a0962d481fc67a3582df75d0e9..9416ec929bebcff7f07088e635376ef232eb515f 100644
  476. --- a/components/viz/service/display_embedder/software_output_device_win.cc
  477. +++ b/components/viz/service/display_embedder/software_output_device_win.cc
  478. @@ -191,7 +191,7 @@ void SoftwareOutputDeviceWinProxy::EndPaintDelegated(
  479. if (!canvas_)
  480. return;
  481. - layered_window_updater_->Draw(base::BindOnce(
  482. + layered_window_updater_->Draw(damage_rect, base::BindOnce(
  483. &SoftwareOutputDeviceWinProxy::DrawAck, base::Unretained(this)));
  484. waiting_on_draw_ack_ = true;
  485. 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
  486. index df92bab44402330869b44aa76bb40fc20e33b16a..2b3fbaee17c0a8bb7b04cd4c4edb13626dd1bb27 100644
  487. --- a/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.cc
  488. +++ b/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.cc
  489. @@ -84,7 +84,8 @@ RootCompositorFrameSinkImpl::Create(
  490. params->gpu_compositing, params->widget, params->renderer_settings);
  491. auto output_surface = output_surface_provider->CreateOutputSurface(
  492. params->widget, params->gpu_compositing, display_client.get(),
  493. - display_controller.get(), params->renderer_settings, debug_settings);
  494. + display_controller.get(), params->renderer_settings, debug_settings,
  495. + params->offscreen);
  496. // Creating output surface failed. The host can send a new request, possibly
  497. // with a different compositing mode.
  498. diff --git a/content/browser/compositor/viz_process_transport_factory.cc b/content/browser/compositor/viz_process_transport_factory.cc
  499. index 0e3af0f9280abe8560393325b400ad2543ed0556..7fe490e55a4bb8a183d0d241188ea15a44347245 100644
  500. --- a/content/browser/compositor/viz_process_transport_factory.cc
  501. +++ b/content/browser/compositor/viz_process_transport_factory.cc
  502. @@ -381,8 +381,14 @@ void VizProcessTransportFactory::OnEstablishedGpuChannel(
  503. compositor_data.display_private.reset();
  504. root_params->display_private =
  505. compositor_data.display_private.BindNewEndpointAndPassReceiver();
  506. - compositor_data.display_client =
  507. - std::make_unique<HostDisplayClient>(compositor);
  508. + if (compositor->delegate()) {
  509. + compositor_data.display_client = compositor->delegate()->CreateHostDisplayClient(
  510. + compositor);
  511. + root_params->offscreen = compositor->delegate()->IsOffscreen();
  512. + } else {
  513. + compositor_data.display_client =
  514. + std::make_unique<HostDisplayClient>(compositor);
  515. + }
  516. root_params->display_client =
  517. compositor_data.display_client->GetBoundRemote(resize_task_runner_);
  518. diff --git a/services/viz/privileged/mojom/compositing/display_private.mojom b/services/viz/privileged/mojom/compositing/display_private.mojom
  519. index b2f873919d68633103d115d7d9550a098c1a254c..8e38831a6df15d37e5fb87d63613b7dbdcefacc4 100644
  520. --- a/services/viz/privileged/mojom/compositing/display_private.mojom
  521. +++ b/services/viz/privileged/mojom/compositing/display_private.mojom
  522. @@ -102,7 +102,6 @@ interface DisplayClient {
  523. // Creates a LayeredWindowUpdater implementation to draw into a layered
  524. // window.
  525. - [EnableIf=is_win]
  526. CreateLayeredWindowUpdater(pending_receiver<LayeredWindowUpdater> receiver);
  527. // Notifies that a swap has occurred and provides information about the pixel
  528. diff --git a/services/viz/privileged/mojom/compositing/frame_sink_manager.mojom b/services/viz/privileged/mojom/compositing/frame_sink_manager.mojom
  529. index a9a0e5a1167b2018e6dc206ecb7d37aad94042aa..3997ecb0228914144d6b04595c47376679fca3ef 100644
  530. --- a/services/viz/privileged/mojom/compositing/frame_sink_manager.mojom
  531. +++ b/services/viz/privileged/mojom/compositing/frame_sink_manager.mojom
  532. @@ -32,6 +32,7 @@ struct RootCompositorFrameSinkParams {
  533. // Disables begin frame rate limiting for the display compositor.
  534. bool disable_frame_rate_limit = false;
  535. bool use_preferred_interval_for_video = false;
  536. + bool offscreen = false;
  537. [EnableIf=is_android]
  538. float refresh_rate;
  539. diff --git a/services/viz/privileged/mojom/compositing/layered_window_updater.mojom b/services/viz/privileged/mojom/compositing/layered_window_updater.mojom
  540. index 6b7fbb6cf13dc8ee6ade0878a9a2c1efc5d4d3f1..e2af75168cb914a7b3b4a6c9b6a285498c3f8e72 100644
  541. --- a/services/viz/privileged/mojom/compositing/layered_window_updater.mojom
  542. +++ b/services/viz/privileged/mojom/compositing/layered_window_updater.mojom
  543. @@ -26,5 +26,5 @@ interface LayeredWindowUpdater {
  544. // Draws to the HWND by copying pixels from shared memory. Callback must be
  545. // called after draw operation is complete to signal shared memory can be
  546. // modified.
  547. - Draw() => ();
  548. + Draw(gfx.mojom.Rect damage_rect) => ();
  549. };
  550. diff --git a/ui/compositor/compositor.h b/ui/compositor/compositor.h
  551. index b30b9460889b9bb3862f4e28b5f1292a118f2a09..d8f1f921d3e6e74c99d6a22c902f81dfc5bb646e 100644
  552. --- a/ui/compositor/compositor.h
  553. +++ b/ui/compositor/compositor.h
  554. @@ -81,6 +81,7 @@ class DisplayPrivate;
  555. class ExternalBeginFrameController;
  556. } // namespace mojom
  557. class ContextProvider;
  558. +class HostDisplayClient;
  559. class HostFrameSinkManager;
  560. class LocalSurfaceId;
  561. class RasterContextProvider;
  562. @@ -137,6 +138,16 @@ class COMPOSITOR_EXPORT ContextFactory {
  563. virtual viz::HostFrameSinkManager* GetHostFrameSinkManager() = 0;
  564. };
  565. +class COMPOSITOR_EXPORT CompositorDelegate {
  566. + public:
  567. + virtual bool IsOffscreen() const = 0;
  568. + virtual std::unique_ptr<viz::HostDisplayClient> CreateHostDisplayClient(
  569. + ui::Compositor* compositor) = 0;
  570. +
  571. + protected:
  572. + virtual ~CompositorDelegate() {}
  573. +};
  574. +
  575. // Compositor object to take care of GPU painting.
  576. // A Browser compositor object is responsible for generating the final
  577. // displayable form of pixels comprising a single widget's contents. It draws an
  578. @@ -178,6 +189,9 @@ class COMPOSITOR_EXPORT Compositor : public base::PowerSuspendObserver,
  579. // Schedules a redraw of the layer tree associated with this compositor.
  580. void ScheduleDraw();
  581. + CompositorDelegate* delegate() const { return delegate_; }
  582. + void SetDelegate(CompositorDelegate* delegate) { delegate_ = delegate; }
  583. +
  584. // Sets the root of the layer tree drawn by this Compositor. The root layer
  585. // must have no parent. The compositor's root layer is reset if the root layer
  586. // is destroyed. NULL can be passed to reset the root layer, in which case the
  587. @@ -466,6 +480,8 @@ class COMPOSITOR_EXPORT Compositor : public base::PowerSuspendObserver,
  588. std::unique_ptr<PendingBeginFrameArgs> pending_begin_frame_args_;
  589. + CompositorDelegate* delegate_ = nullptr;
  590. +
  591. // The root of the Layer tree drawn by this compositor.
  592. raw_ptr<Layer> root_layer_ = nullptr;
  593. diff --git a/ui/gfx/ca_layer_params.h b/ui/gfx/ca_layer_params.h
  594. index c5fb29b30b9c5b7483998c567ed9a479d8743939..dc10d78315f76a3914ccd6e2e99af97fa909918b 100644
  595. --- a/ui/gfx/ca_layer_params.h
  596. +++ b/ui/gfx/ca_layer_params.h
  597. @@ -6,6 +6,7 @@
  598. #define UI_GFX_CA_LAYER_PARAMS_H_
  599. #include "build/build_config.h"
  600. +#include "ui/gfx/geometry/rect.h"
  601. #include "ui/gfx/geometry/size.h"
  602. #include "ui/gfx/gfx_export.h"
  603. @@ -41,6 +42,8 @@ struct GFX_EXPORT CALayerParams {
  604. gfx::ScopedRefCountedIOSurfaceMachPort io_surface_mach_port;
  605. #endif
  606. + gfx::Rect damage;
  607. +
  608. // The geometry of the frame.
  609. gfx::Size pixel_size;
  610. float scale_factor = 1.f;
  611. diff --git a/ui/gfx/mojom/ca_layer_params.mojom b/ui/gfx/mojom/ca_layer_params.mojom
  612. index de00e766ba17532e10dcf5d0fd31fa344920a9f7..7aaedf83ad22dcc1d2dd39a31cf7e08b7b6ba4d3 100644
  613. --- a/ui/gfx/mojom/ca_layer_params.mojom
  614. +++ b/ui/gfx/mojom/ca_layer_params.mojom
  615. @@ -18,5 +18,6 @@ struct CALayerParams {
  616. bool is_empty;
  617. CALayerContent content;
  618. gfx.mojom.Size pixel_size;
  619. + gfx.mojom.Rect damage;
  620. float scale_factor;
  621. };
  622. diff --git a/ui/gfx/mojom/ca_layer_params_mojom_traits.cc b/ui/gfx/mojom/ca_layer_params_mojom_traits.cc
  623. index c7035798bd867f51b39f36f1be79293bf2b5cc12..131446361de812f9b915483bca2b6d2165b65e3d 100644
  624. --- a/ui/gfx/mojom/ca_layer_params_mojom_traits.cc
  625. +++ b/ui/gfx/mojom/ca_layer_params_mojom_traits.cc
  626. @@ -52,6 +52,9 @@ bool StructTraits<gfx::mojom::CALayerParamsDataView, gfx::CALayerParams>::Read(
  627. if (!data.ReadPixelSize(&out->pixel_size))
  628. return false;
  629. + if (!data.ReadDamage(&out->damage))
  630. + return false;
  631. +
  632. out->scale_factor = data.scale_factor();
  633. return true;
  634. }
  635. diff --git a/ui/gfx/mojom/ca_layer_params_mojom_traits.h b/ui/gfx/mojom/ca_layer_params_mojom_traits.h
  636. index 4cac766eae3161baedac4202f694129cd90c80de..0821495ad22944d8856bb750cac8912a2f8328c3 100644
  637. --- a/ui/gfx/mojom/ca_layer_params_mojom_traits.h
  638. +++ b/ui/gfx/mojom/ca_layer_params_mojom_traits.h
  639. @@ -20,6 +20,10 @@ struct StructTraits<gfx::mojom::CALayerParamsDataView, gfx::CALayerParams> {
  640. return ca_layer_params.pixel_size;
  641. }
  642. + static gfx::Rect damage(const gfx::CALayerParams& ca_layer_params) {
  643. + return ca_layer_params.damage;
  644. + }
  645. +
  646. static float scale_factor(const gfx::CALayerParams& ca_layer_params) {
  647. return ca_layer_params.scale_factor;
  648. }