feat_enable_offscreen_rendering_with_viz_compositor.patch 29 KB

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