feat_enable_offscreen_rendering_with_viz_compositor.patch 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677
  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 3b00759e513dc7e19fd68398e853c8ce6ac73905..47f4e7cc2e8b3141dcaf9e7a498fec32c9342f40 100644
  10. --- a/components/viz/host/host_display_client.cc
  11. +++ b/components/viz/host/host_display_client.cc
  12. @@ -45,9 +45,9 @@ void HostDisplayClient::OnDisplayReceivedCALayerParams(
  13. }
  14. #endif
  15. -#if defined(OS_WIN)
  16. void HostDisplayClient::CreateLayeredWindowUpdater(
  17. mojo::PendingReceiver<mojom::LayeredWindowUpdater> receiver) {
  18. +#if defined(OS_WIN)
  19. if (!NeedsToUseLayerWindow(widget_)) {
  20. DLOG(ERROR) << "HWND shouldn't be using a layered window";
  21. return;
  22. @@ -55,8 +55,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 5e260e13762f61971c99f755e93d73aa794d9175..a57770718b71def04fa35c7655d9368a58f39f20 100644
  36. --- a/components/viz/host/host_display_client.h
  37. +++ b/components/viz/host/host_display_client.h
  38. @@ -39,10 +39,9 @@ class VIZ_HOST_EXPORT HostDisplayClient : public mojom::DisplayClient {
  39. const gfx::CALayerParams& ca_layer_params) override;
  40. #endif
  41. -#if defined(OS_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 1026b739d283f0fc252fa2af83a6d4cf51bc8553..fe562ab60ce98b8bb0c5080a6428deb319a4dd04 100644
  63. --- a/components/viz/host/layered_window_updater_impl.h
  64. +++ b/components/viz/host/layered_window_updater_impl.h
  65. @@ -35,7 +35,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 7692a2aaf9e4aced560ee4af170e967b7d612eb9..85a2af12aee6eca62b624ae68bccf824750b367b 100644
  75. --- a/components/viz/service/BUILD.gn
  76. +++ b/components/viz/service/BUILD.gn
  77. @@ -137,6 +137,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 bd64ee19f71691bfaf9be2a523b5f5efbbff5066..dc82c4653b2fe22de0ed4ab73c06b85d8f3ecd35 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. @@ -25,6 +25,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. @@ -38,6 +39,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. @@ -131,7 +133,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. @@ -143,7 +146,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. @@ -252,10 +255,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 !defined(OS_MAC)
  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 defined(OS_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 a6bb42cdbc567f526cc70c5c4d9b967274dc0332..d116844635922c8a1086dfa13063b8ae8b43ce59 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. @@ -61,12 +61,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. GpuServiceImpl* const gpu_service_impl_;
  178. gpu::CommandBufferTaskExecutor* const 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 49149081cc603f14eacee647cbb2fcf8ed5e66fd..9ff3f2ee203403fdaa31edb8a0bcc000c4d214d7 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. @@ -102,6 +102,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. @@ -187,6 +189,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 f3867356e3d641416e00e6d115ae9ae2a0be90ab..b1d192d2b20ccb63fba07093101d745e5ffe86dd 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. @@ -56,6 +56,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..48fa86caaab3c15764f105eb7ad2aecf2b89bf36
  375. --- /dev/null
  376. +++ b/components/viz/service/display_embedder/software_output_device_proxy.h
  377. @@ -0,0 +1,90 @@
  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. + // SoftwareOutputDevice implementation.
  408. + void Resize(const gfx::Size& viewport_pixel_size,
  409. + float scale_factor) override;
  410. + SkCanvas* BeginPaint(const gfx::Rect& damage_rect) override;
  411. + void EndPaint() override;
  412. +
  413. + // Called from Resize() if |viewport_pixel_size_| has changed.
  414. + virtual void ResizeDelegated() = 0;
  415. +
  416. + // Called from BeginPaint() and should return an SkCanvas.
  417. + virtual SkCanvas* BeginPaintDelegated() = 0;
  418. +
  419. + // Called from EndPaint() if there is damage.
  420. + virtual void EndPaintDelegated(const gfx::Rect& damage_rect) = 0;
  421. +
  422. + private:
  423. + bool in_paint_ = false;
  424. +
  425. + THREAD_CHECKER(thread_checker_);
  426. +
  427. + DISALLOW_COPY_AND_ASSIGN(SoftwareOutputDeviceBase);
  428. +};
  429. +
  430. +// SoftwareOutputDevice implementation that draws indirectly. An implementation
  431. +// of mojom::LayeredWindowUpdater in the browser process handles the actual
  432. +// drawing. Pixel backing is in SharedMemory so no copying between processes
  433. +// is required.
  434. +class SoftwareOutputDeviceProxy : public SoftwareOutputDeviceBase {
  435. + public:
  436. + explicit SoftwareOutputDeviceProxy(
  437. + mojom::LayeredWindowUpdaterPtr layered_window_updater);
  438. + ~SoftwareOutputDeviceProxy() override;
  439. +
  440. + // SoftwareOutputDevice implementation.
  441. + void OnSwapBuffers(SoftwareOutputDevice::SwapBuffersCallback swap_ack_callback) override;
  442. +
  443. + // SoftwareOutputDeviceBase implementation.
  444. + void ResizeDelegated() override;
  445. + SkCanvas* BeginPaintDelegated() override;
  446. + void EndPaintDelegated(const gfx::Rect& rect) override;
  447. +
  448. + private:
  449. + // Runs |swap_ack_callback_| after draw has happened.
  450. + void DrawAck();
  451. +
  452. + mojom::LayeredWindowUpdaterPtr layered_window_updater_;
  453. +
  454. + std::unique_ptr<SkCanvas> canvas_;
  455. + bool waiting_on_draw_ack_ = false;
  456. + SoftwareOutputDevice::SwapBuffersCallback swap_ack_callback_;
  457. +
  458. +#if !defined(WIN32)
  459. + base::WritableSharedMemoryMapping shm_mapping_;
  460. +#endif
  461. +
  462. + DISALLOW_COPY_AND_ASSIGN(SoftwareOutputDeviceProxy);
  463. +};
  464. +
  465. +} // namespace viz
  466. +
  467. +#endif // COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_SOFTWARE_OUTPUT_DEVICE_PROXY_H_
  468. diff --git a/components/viz/service/display_embedder/software_output_device_win.cc b/components/viz/service/display_embedder/software_output_device_win.cc
  469. index 599b06c1765ef4ddbfeb2fd96e0875098f7c6ae1..2151fc8aa710162a3870639bd6e952df9d15a0be 100644
  470. --- a/components/viz/service/display_embedder/software_output_device_win.cc
  471. +++ b/components/viz/service/display_embedder/software_output_device_win.cc
  472. @@ -191,7 +191,7 @@ void SoftwareOutputDeviceWinProxy::EndPaintDelegated(
  473. if (!canvas_)
  474. return;
  475. - layered_window_updater_->Draw(base::BindOnce(
  476. + layered_window_updater_->Draw(damage_rect, base::BindOnce(
  477. &SoftwareOutputDeviceWinProxy::DrawAck, base::Unretained(this)));
  478. waiting_on_draw_ack_ = true;
  479. 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
  480. index 6ea2c624e1e31414bf8765582ab89dd0551c1111..07248135401dc29d6747c91edd027b0abb433e3e 100644
  481. --- a/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.cc
  482. +++ b/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.cc
  483. @@ -47,7 +47,8 @@ RootCompositorFrameSinkImpl::Create(
  484. params->gpu_compositing, params->widget, params->renderer_settings);
  485. auto output_surface = output_surface_provider->CreateOutputSurface(
  486. params->widget, params->gpu_compositing, display_client.get(),
  487. - display_controller.get(), params->renderer_settings, debug_settings);
  488. + display_controller.get(), params->renderer_settings, debug_settings,
  489. + params->offscreen);
  490. // Creating output surface failed. The host can send a new request, possibly
  491. // with a different compositing mode.
  492. diff --git a/content/browser/compositor/viz_process_transport_factory.cc b/content/browser/compositor/viz_process_transport_factory.cc
  493. index 83a23404d1c029af6f7e7aa695bfe60e71d86fde..eef92d3366715774670ebcdcb76ad84ddd8a4ed0 100644
  494. --- a/content/browser/compositor/viz_process_transport_factory.cc
  495. +++ b/content/browser/compositor/viz_process_transport_factory.cc
  496. @@ -395,8 +395,14 @@ void VizProcessTransportFactory::OnEstablishedGpuChannel(
  497. compositor_data.display_private.reset();
  498. root_params->display_private =
  499. compositor_data.display_private.BindNewEndpointAndPassReceiver();
  500. - compositor_data.display_client =
  501. - std::make_unique<HostDisplayClient>(compositor);
  502. + if (compositor->delegate()) {
  503. + compositor_data.display_client = compositor->delegate()->CreateHostDisplayClient(
  504. + compositor);
  505. + root_params->offscreen = compositor->delegate()->IsOffscreen();
  506. + } else {
  507. + compositor_data.display_client =
  508. + std::make_unique<HostDisplayClient>(compositor);
  509. + }
  510. root_params->display_client =
  511. compositor_data.display_client->GetBoundRemote(resize_task_runner_);
  512. diff --git a/services/viz/privileged/mojom/compositing/display_private.mojom b/services/viz/privileged/mojom/compositing/display_private.mojom
  513. index 03ad7c39128fc408d576a23e595021ffa3238423..de1c1f6984f8d81081643415d1724bce333ca940 100644
  514. --- a/services/viz/privileged/mojom/compositing/display_private.mojom
  515. +++ b/services/viz/privileged/mojom/compositing/display_private.mojom
  516. @@ -90,7 +90,6 @@ interface DisplayClient {
  517. // Creates a LayeredWindowUpdater implementation to draw into a layered
  518. // window.
  519. - [EnableIf=is_win]
  520. CreateLayeredWindowUpdater(pending_receiver<LayeredWindowUpdater> receiver);
  521. // Notifies that a swap has occurred and provides information about the pixel
  522. diff --git a/services/viz/privileged/mojom/compositing/frame_sink_manager.mojom b/services/viz/privileged/mojom/compositing/frame_sink_manager.mojom
  523. index 8d7cfe54e819f3d6c362c62db2f183c901bea991..e08c4556240f0f566a91c3fb9ba142170b4b0c3a 100644
  524. --- a/services/viz/privileged/mojom/compositing/frame_sink_manager.mojom
  525. +++ b/services/viz/privileged/mojom/compositing/frame_sink_manager.mojom
  526. @@ -30,6 +30,7 @@ struct RootCompositorFrameSinkParams {
  527. // Disables begin frame rate limiting for the display compositor.
  528. bool disable_frame_rate_limit = false;
  529. bool use_preferred_interval_for_video = false;
  530. + bool offscreen = false;
  531. [EnableIf=is_android]
  532. float refresh_rate;
  533. diff --git a/services/viz/privileged/mojom/compositing/layered_window_updater.mojom b/services/viz/privileged/mojom/compositing/layered_window_updater.mojom
  534. index 6b7fbb6cf13dc8ee6ade0878a9a2c1efc5d4d3f1..e2af75168cb914a7b3b4a6c9b6a285498c3f8e72 100644
  535. --- a/services/viz/privileged/mojom/compositing/layered_window_updater.mojom
  536. +++ b/services/viz/privileged/mojom/compositing/layered_window_updater.mojom
  537. @@ -26,5 +26,5 @@ interface LayeredWindowUpdater {
  538. // Draws to the HWND by copying pixels from shared memory. Callback must be
  539. // called after draw operation is complete to signal shared memory can be
  540. // modified.
  541. - Draw() => ();
  542. + Draw(gfx.mojom.Rect damage_rect) => ();
  543. };
  544. diff --git a/ui/compositor/compositor.h b/ui/compositor/compositor.h
  545. index 5bf36e2873bfb7dfa46ca6f010c780f1f02235ac..0378d1246930c3dc4ac8b4d1886fc5dc497dcb66 100644
  546. --- a/ui/compositor/compositor.h
  547. +++ b/ui/compositor/compositor.h
  548. @@ -81,6 +81,7 @@ class DisplayPrivate;
  549. class ExternalBeginFrameController;
  550. } // namespace mojom
  551. class ContextProvider;
  552. +class HostDisplayClient;
  553. class HostFrameSinkManager;
  554. class LocalSurfaceId;
  555. class RasterContextProvider;
  556. @@ -137,6 +138,16 @@ class COMPOSITOR_EXPORT ContextFactory {
  557. virtual viz::HostFrameSinkManager* GetHostFrameSinkManager() = 0;
  558. };
  559. +class COMPOSITOR_EXPORT CompositorDelegate {
  560. + public:
  561. + virtual bool IsOffscreen() const = 0;
  562. + virtual std::unique_ptr<viz::HostDisplayClient> CreateHostDisplayClient(
  563. + ui::Compositor* compositor) = 0;
  564. +
  565. + protected:
  566. + virtual ~CompositorDelegate() {}
  567. +};
  568. +
  569. // Compositor object to take care of GPU painting.
  570. // A Browser compositor object is responsible for generating the final
  571. // displayable form of pixels comprising a single widget's contents. It draws an
  572. @@ -172,6 +183,9 @@ class COMPOSITOR_EXPORT Compositor : public cc::LayerTreeHostClient,
  573. // Schedules a redraw of the layer tree associated with this compositor.
  574. void ScheduleDraw();
  575. + CompositorDelegate* delegate() const { return delegate_; }
  576. + void SetDelegate(CompositorDelegate* delegate) { delegate_ = delegate; }
  577. +
  578. // Sets the root of the layer tree drawn by this Compositor. The root layer
  579. // must have no parent. The compositor's root layer is reset if the root layer
  580. // is destroyed. NULL can be passed to reset the root layer, in which case the
  581. @@ -443,6 +457,8 @@ class COMPOSITOR_EXPORT Compositor : public cc::LayerTreeHostClient,
  582. std::unique_ptr<PendingBeginFrameArgs> pending_begin_frame_args_;
  583. + CompositorDelegate* delegate_ = nullptr;
  584. +
  585. // The root of the Layer tree drawn by this compositor.
  586. Layer* root_layer_ = nullptr;
  587. diff --git a/ui/gfx/ca_layer_params.h b/ui/gfx/ca_layer_params.h
  588. index 64af450ed36a982124c6fcce7056b4058140747a..dcee2ec9de0e759b868b0de2c7106b2cf084c41c 100644
  589. --- a/ui/gfx/ca_layer_params.h
  590. +++ b/ui/gfx/ca_layer_params.h
  591. @@ -6,6 +6,7 @@
  592. #define UI_GFX_CA_LAYER_PARAMS_H_
  593. #include "build/build_config.h"
  594. +#include "ui/gfx/geometry/rect.h"
  595. #include "ui/gfx/geometry/size.h"
  596. #include "ui/gfx/gfx_export.h"
  597. @@ -41,6 +42,8 @@ struct GFX_EXPORT CALayerParams {
  598. gfx::ScopedRefCountedIOSurfaceMachPort io_surface_mach_port;
  599. #endif
  600. + gfx::Rect damage;
  601. +
  602. // The geometry of the frame.
  603. gfx::Size pixel_size;
  604. float scale_factor = 1.f;
  605. diff --git a/ui/gfx/mojom/ca_layer_params.mojom b/ui/gfx/mojom/ca_layer_params.mojom
  606. index de00e766ba17532e10dcf5d0fd31fa344920a9f7..7aaedf83ad22dcc1d2dd39a31cf7e08b7b6ba4d3 100644
  607. --- a/ui/gfx/mojom/ca_layer_params.mojom
  608. +++ b/ui/gfx/mojom/ca_layer_params.mojom
  609. @@ -18,5 +18,6 @@ struct CALayerParams {
  610. bool is_empty;
  611. CALayerContent content;
  612. gfx.mojom.Size pixel_size;
  613. + gfx.mojom.Rect damage;
  614. float scale_factor;
  615. };
  616. diff --git a/ui/gfx/mojom/ca_layer_params_mojom_traits.cc b/ui/gfx/mojom/ca_layer_params_mojom_traits.cc
  617. index c1f21d7f4348df96f7be5c0adb1b9650304048e0..760c849aebba70e575e59883655d707f36c5424a 100644
  618. --- a/ui/gfx/mojom/ca_layer_params_mojom_traits.cc
  619. +++ b/ui/gfx/mojom/ca_layer_params_mojom_traits.cc
  620. @@ -52,6 +52,9 @@ bool StructTraits<gfx::mojom::CALayerParamsDataView, gfx::CALayerParams>::Read(
  621. if (!data.ReadPixelSize(&out->pixel_size))
  622. return false;
  623. + if (!data.ReadDamage(&out->damage))
  624. + return false;
  625. +
  626. out->scale_factor = data.scale_factor();
  627. return true;
  628. }
  629. diff --git a/ui/gfx/mojom/ca_layer_params_mojom_traits.h b/ui/gfx/mojom/ca_layer_params_mojom_traits.h
  630. index 4cac766eae3161baedac4202f694129cd90c80de..0821495ad22944d8856bb750cac8912a2f8328c3 100644
  631. --- a/ui/gfx/mojom/ca_layer_params_mojom_traits.h
  632. +++ b/ui/gfx/mojom/ca_layer_params_mojom_traits.h
  633. @@ -20,6 +20,10 @@ struct StructTraits<gfx::mojom::CALayerParamsDataView, gfx::CALayerParams> {
  634. return ca_layer_params.pixel_size;
  635. }
  636. + static gfx::Rect damage(const gfx::CALayerParams& ca_layer_params) {
  637. + return ca_layer_params.damage;
  638. + }
  639. +
  640. static float scale_factor(const gfx::CALayerParams& ca_layer_params) {
  641. return ca_layer_params.scale_factor;
  642. }