feat_enable_offscreen_rendering_with_viz_compositor.patch 32 KB

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