feat_enable_offscreen_rendering_with_viz_compositor.patch 31 KB

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