feat_enable_offscreen_rendering_with_viz_compositor.patch 32 KB

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