root_frame_sink.cc 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447
  1. // Copyright 2019 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "android_webview/browser/gfx/root_frame_sink.h"
  5. #include "android_webview/browser/gfx/child_frame.h"
  6. #include "android_webview/browser/gfx/display_scheduler_webview.h"
  7. #include "android_webview/browser/gfx/viz_compositor_thread_runner_webview.h"
  8. #include "base/memory/raw_ptr.h"
  9. #include "base/trace_event/trace_event.h"
  10. #include "components/viz/common/features.h"
  11. #include "components/viz/common/surfaces/frame_sink_id_allocator.h"
  12. #include "components/viz/service/frame_sinks/compositor_frame_sink_support.h"
  13. #include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
  14. #include "components/viz/service/surfaces/surface.h"
  15. namespace android_webview {
  16. namespace {
  17. viz::FrameSinkId AllocateParentSinkId() {
  18. static viz::FrameSinkIdAllocator allocator(0u);
  19. return allocator.NextFrameSinkId();
  20. }
  21. } // namespace
  22. class RootFrameSink::ChildCompositorFrameSink
  23. : public viz::mojom::CompositorFrameSinkClient {
  24. public:
  25. ChildCompositorFrameSink(RootFrameSink* owner,
  26. uint32_t layer_tree_frame_sink_id,
  27. viz::FrameSinkId frame_sink_id)
  28. : owner_(owner),
  29. layer_tree_frame_sink_id_(layer_tree_frame_sink_id),
  30. frame_sink_id_(frame_sink_id),
  31. support_(std::make_unique<viz::CompositorFrameSinkSupport>(
  32. this,
  33. owner->GetFrameSinkManager(),
  34. frame_sink_id,
  35. false)) {
  36. support_->SetBeginFrameSource(nullptr);
  37. }
  38. void DidReceiveCompositorFrameAck(
  39. std::vector<viz::ReturnedResource> resources) override {
  40. ReclaimResources(std::move(resources));
  41. }
  42. void OnBeginFrame(const viz::BeginFrameArgs& args,
  43. const viz::FrameTimingDetailsMap& feedbacks) override {}
  44. void OnBeginFramePausedChanged(bool paused) override {}
  45. void ReclaimResources(std::vector<viz::ReturnedResource> resources) override {
  46. owner_->ReturnResources(frame_sink_id_, layer_tree_frame_sink_id_,
  47. std::move(resources));
  48. }
  49. void OnCompositorFrameTransitionDirectiveProcessed(
  50. uint32_t sequence_id) override {
  51. owner_->OnCompositorFrameTransitionDirectiveProcessed(
  52. frame_sink_id_, layer_tree_frame_sink_id_, sequence_id);
  53. }
  54. const viz::FrameSinkId frame_sink_id() { return frame_sink_id_; }
  55. uint32_t layer_tree_frame_sink_id() { return layer_tree_frame_sink_id_; }
  56. viz::CompositorFrameSinkSupport* support() { return support_.get(); }
  57. gfx::Size size() { return size_; }
  58. void SubmitCompositorFrame(
  59. const viz::LocalSurfaceId& local_surface_id,
  60. viz::CompositorFrame frame,
  61. absl::optional<viz::HitTestRegionList> hit_test_region_list) {
  62. size_ = frame.size_in_pixels();
  63. support()->SubmitCompositorFrame(local_surface_id, std::move(frame),
  64. std::move(hit_test_region_list));
  65. }
  66. void EvictSurface(viz::SurfaceId surface_id) {
  67. if (surface_id.frame_sink_id() == frame_sink_id_)
  68. support_->EvictSurface(surface_id.local_surface_id());
  69. }
  70. private:
  71. const raw_ptr<RootFrameSink> owner_;
  72. const uint32_t layer_tree_frame_sink_id_;
  73. const viz::FrameSinkId frame_sink_id_;
  74. std::unique_ptr<viz::CompositorFrameSinkSupport> support_;
  75. gfx::Size size_;
  76. };
  77. RootFrameSink::RootFrameSink(RootFrameSinkClient* client)
  78. : root_frame_sink_id_(AllocateParentSinkId()),
  79. client_(client),
  80. use_new_invalidate_heuristic_(base::FeatureList::IsEnabled(
  81. features::kWebViewNewInvalidateHeuristic)) {
  82. constexpr bool is_root = true;
  83. GetFrameSinkManager()->RegisterFrameSinkId(root_frame_sink_id_,
  84. false /* report_activationa */);
  85. support_ = std::make_unique<viz::CompositorFrameSinkSupport>(
  86. this, GetFrameSinkManager(), root_frame_sink_id_, is_root);
  87. begin_frame_source_ = std::make_unique<viz::ExternalBeginFrameSource>(this);
  88. GetFrameSinkManager()->RegisterBeginFrameSource(begin_frame_source_.get(),
  89. root_frame_sink_id_);
  90. // Note, that this technically not part of the new heuristic. Without this
  91. // line root CF will "request" BeginFrames for delivery of presentation
  92. // feedback that we don't care about which leads to more begin frame requested
  93. // than necessary. But to avoid any side effects on invalidation, fixing this
  94. // is gates under same feature flag.
  95. if (use_new_invalidate_heuristic_)
  96. support_->SetBeginFrameSource(nullptr);
  97. }
  98. RootFrameSink::~RootFrameSink() {
  99. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  100. GetFrameSinkManager()->UnregisterBeginFrameSource(begin_frame_source_.get());
  101. begin_frame_source_.reset();
  102. support_.reset();
  103. GetFrameSinkManager()->InvalidateFrameSinkId(root_frame_sink_id_);
  104. }
  105. viz::FrameSinkManagerImpl* RootFrameSink::GetFrameSinkManager() {
  106. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  107. // FrameSinkManagerImpl is global and not owned by this class, which is
  108. // per-AwContents.
  109. return VizCompositorThreadRunnerWebView::GetInstance()->GetFrameSinkManager();
  110. }
  111. const viz::LocalSurfaceId& RootFrameSink::SubmitRootCompositorFrame(
  112. viz::CompositorFrame frame) {
  113. frame.metadata.frame_token = ++next_root_frame_token_;
  114. if (!root_local_surface_id_allocator_.HasValidLocalSurfaceId() ||
  115. root_surface_size_ != frame.size_in_pixels() ||
  116. root_device_scale_factor_ != frame.device_scale_factor()) {
  117. root_local_surface_id_allocator_.GenerateId();
  118. root_surface_size_ = frame.size_in_pixels();
  119. root_device_scale_factor_ = frame.device_scale_factor();
  120. }
  121. const auto& local_surface_id =
  122. root_local_surface_id_allocator_.GetCurrentLocalSurfaceId();
  123. support_->SubmitCompositorFrame(local_surface_id, std::move(frame));
  124. return local_surface_id;
  125. }
  126. void RootFrameSink::EvictRootSurface(
  127. const viz::LocalSurfaceId& local_surface_id) {
  128. const auto& current_local_surface_id =
  129. root_local_surface_id_allocator_.GetCurrentLocalSurfaceId();
  130. DLOG_IF(FATAL, !current_local_surface_id.IsSameOrNewerThan(local_surface_id))
  131. << "Evicting newer surface: " << local_surface_id.ToString()
  132. << " old: " << current_local_surface_id.ToString();
  133. if (current_local_surface_id == local_surface_id) {
  134. root_surface_size_ = gfx::Size();
  135. root_device_scale_factor_ = 0.0f;
  136. }
  137. support_->EvictSurface(local_surface_id);
  138. }
  139. void RootFrameSink::DidReceiveCompositorFrameAck(
  140. std::vector<viz::ReturnedResource> resources) {
  141. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  142. ReclaimResources(std::move(resources));
  143. }
  144. void RootFrameSink::ReclaimResources(
  145. std::vector<viz::ReturnedResource> resources) {
  146. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  147. // Root surface should have no resources to return.
  148. CHECK(resources.empty());
  149. }
  150. void RootFrameSink::OnNeedsBeginFrames(bool needs_begin_frames) {
  151. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  152. TRACE_EVENT_INSTANT1("android_webview", "RootFrameSink::OnNeedsBeginFrames",
  153. TRACE_EVENT_SCOPE_THREAD, "needs_begin_frames",
  154. needs_begin_frames);
  155. clients_need_begin_frames_ = needs_begin_frames;
  156. // Old heuristic doesn't need extra begin frames, so just forward client
  157. // needs.
  158. if (!use_new_invalidate_heuristic_) {
  159. UpdateNeedsBeginFrames(clients_need_begin_frames_);
  160. return;
  161. }
  162. // Make sure that we subscribed to BF if client needs them. We don't
  163. // unsubscribe from BF here to make sure that we invalidated for the latest
  164. // frames in necessary. We will stop observing them later in BeginFrame()
  165. // once we are done.
  166. if (clients_need_begin_frames_)
  167. UpdateNeedsBeginFrames(true);
  168. }
  169. void RootFrameSink::AddChildFrameSinkId(const viz::FrameSinkId& frame_sink_id) {
  170. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  171. child_frame_sink_ids_.insert(frame_sink_id);
  172. GetFrameSinkManager()->RegisterFrameSinkHierarchy(root_frame_sink_id_,
  173. frame_sink_id);
  174. }
  175. void RootFrameSink::RemoveChildFrameSinkId(
  176. const viz::FrameSinkId& frame_sink_id) {
  177. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  178. child_frame_sink_ids_.erase(frame_sink_id);
  179. GetFrameSinkManager()->UnregisterFrameSinkHierarchy(root_frame_sink_id_,
  180. frame_sink_id);
  181. }
  182. void RootFrameSink::SetContainedSurfaces(
  183. const base::flat_set<viz::SurfaceId>& ids) {
  184. contained_surfaces_ = ids;
  185. for (auto it = last_invalidated_frame_id_.begin();
  186. it != last_invalidated_frame_id_.end();) {
  187. if (!contained_surfaces_.contains(it->first))
  188. it = last_invalidated_frame_id_.erase(it);
  189. else
  190. ++it;
  191. }
  192. }
  193. void RootFrameSink::UpdateNeedsBeginFrames(bool needs_begin_frames) {
  194. if (needs_begin_frames_ != needs_begin_frames) {
  195. needs_begin_frames_ = needs_begin_frames;
  196. if (client_)
  197. client_->SetNeedsBeginFrames(needs_begin_frames_);
  198. }
  199. }
  200. bool RootFrameSink::HasPendingDependency(const viz::SurfaceId& surface_id) {
  201. auto* surface =
  202. GetFrameSinkManager()->surface_manager()->GetSurfaceForId(surface_id);
  203. if (!surface || !surface->HasActiveFrame())
  204. return true;
  205. for (auto& range : surface->GetActiveFrame().metadata.referenced_surfaces) {
  206. if (HasPendingDependency(range.end()))
  207. return true;
  208. }
  209. return false;
  210. }
  211. bool RootFrameSink::ProcessVisibleSurfacesInvalidation() {
  212. if (!use_new_invalidate_heuristic_) {
  213. // This handles only invalidation of sub clients, root client invalidation
  214. // is handled by Invalidate() from cc to |SynchronousLayerTreeFrameSink|. So
  215. // we return false unless we already have damage.
  216. return needs_draw_;
  217. }
  218. bool invalidate = false;
  219. // There are few possible cases:
  220. // * viz::Surface is visible (i.e was embedded last frame and any scheduled
  221. // draws don't change that). In this case surface is in `contained_surfaces`
  222. // and we need to invalidate for any CompositorFrame that we haven't
  223. // invalidated yet. This is a steady state.
  224. // * viz::Surface is visible, but there are scheduled draws that remove it. In
  225. // this case surface is in `contained_surfaces`, but technically there is no
  226. // need to invalidate it. We can't know that it will disappear, so we
  227. // invalidate anyway.
  228. // * viz::Surface is visible, but has pending dependencies (embedded surfaces
  229. // without active frame). In this case surface is in `contained_surfaces`, but
  230. // the dependents aren't. Invalidate in this case pessimistically assuming
  231. // there are uncommitted frames that can be activated on commit in dependent
  232. // frames.
  233. // * viz::Surface is not visible yet, but there is a pending draw that will
  234. // embed it. In this case the surface is not in `contained_surfaces` yet, so
  235. // we can't process it here. After the draw will happen it's possible that
  236. // there are uncommitted frames that are already scheduled to draw, but have
  237. // not been processed here. This can cause extra invalidation.
  238. // * viz::Surface is not visible and there is no pending draw. This shouldn't
  239. // be possible because the only way to embed a child surface is for the root
  240. // renderer to submit a compositor frame and invalidation of it is handled
  241. // separately.
  242. // If there is pending dependency, invalidate.
  243. if (root_local_surface_id_allocator_.HasValidLocalSurfaceId()) {
  244. auto surface_id = viz::SurfaceId(
  245. root_frame_sink_id(),
  246. root_local_surface_id_allocator_.GetCurrentLocalSurfaceId());
  247. invalidate = invalidate || HasPendingDependency(surface_id);
  248. }
  249. for (auto& surface_id : contained_surfaces_) {
  250. auto* surface =
  251. GetFrameSinkManager()->surface_manager()->GetSurfaceForId(surface_id);
  252. if (surface) {
  253. // Track last frame_id that we invalidated for. Note, that this doesn't
  254. // take into account what current frame is or what display compositor will
  255. // draw. The intent here is to invalidate once for each surface we see.
  256. auto& last_invalidated_id = last_invalidated_frame_id_[surface_id];
  257. auto uncommited_frame_id =
  258. last_invalidated_id.IsSequenceValid()
  259. ? surface->GetUncommitedFrameIdNewerThan(last_invalidated_id)
  260. : surface->GetFirstUncommitedFrameId();
  261. if (uncommited_frame_id.has_value()) {
  262. invalidate = true;
  263. last_invalidated_id = uncommited_frame_id.value();
  264. }
  265. }
  266. }
  267. return invalidate;
  268. }
  269. bool RootFrameSink::BeginFrame(const viz::BeginFrameArgs& args,
  270. bool had_input_event) {
  271. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  272. // We call ProcessVisibleSurfacesInvalidation() to make sure heuristic updated
  273. // it's state (e.g last invalidated begin frame args).
  274. bool invalidate = ProcessVisibleSurfacesInvalidation() || had_input_event;
  275. TRACE_EVENT_INSTANT1("android_webview", "RootFrameSink::BeginFrame",
  276. TRACE_EVENT_SCOPE_THREAD, "invalidate", invalidate);
  277. if (clients_need_begin_frames_) {
  278. begin_frame_source_->OnBeginFrame(args);
  279. } else if (!invalidate) {
  280. if (use_new_invalidate_heuristic_) {
  281. // Client don't need begin frames and we didn't invalidate, so we don't
  282. // need them either.
  283. UpdateNeedsBeginFrames(false);
  284. }
  285. }
  286. return invalidate;
  287. }
  288. void RootFrameSink::SetBeginFrameSourcePaused(bool paused) {
  289. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  290. begin_frame_source_->OnSetBeginFrameSourcePaused(paused);
  291. }
  292. void RootFrameSink::SetNeedsDraw(bool needs_draw) {
  293. // Only old heuristic needs this.
  294. DCHECK(!use_new_invalidate_heuristic_);
  295. needs_draw_ = needs_draw;
  296. // It's possible that client submitted last frame and unsubscribed from
  297. // BeginFrames, but we haven't draw it yet.
  298. if (!needs_begin_frames_ && needs_draw) {
  299. if (client_)
  300. client_->Invalidate();
  301. }
  302. }
  303. void RootFrameSink::OnNewUncommittedFrame(const viz::SurfaceId& surface_id) {
  304. // Only new heurstic needs this.
  305. if (!use_new_invalidate_heuristic_)
  306. return;
  307. // If there is new uncommitted frame in visible surface, make sure we request
  308. // a begin frame to check if we need to invalidate next frame.
  309. if (contained_surfaces_.contains(surface_id))
  310. UpdateNeedsBeginFrames(true);
  311. }
  312. bool RootFrameSink::IsChildSurface(const viz::FrameSinkId& frame_sink_id) {
  313. return child_frame_sink_ids_.contains(frame_sink_id);
  314. }
  315. void RootFrameSink::ReturnResources(
  316. viz::FrameSinkId frame_sink_id,
  317. uint32_t layer_tree_frame_sink_id,
  318. std::vector<viz::ReturnedResource> resources) {
  319. if (client_)
  320. client_->ReturnResources(frame_sink_id, layer_tree_frame_sink_id,
  321. std::move(resources));
  322. }
  323. void RootFrameSink::OnCompositorFrameTransitionDirectiveProcessed(
  324. viz::FrameSinkId frame_sink_id,
  325. uint32_t layer_tree_frame_sink_id,
  326. uint32_t sequence_id) {
  327. if (client_) {
  328. client_->OnCompositorFrameTransitionDirectiveProcessed(
  329. frame_sink_id, layer_tree_frame_sink_id, sequence_id);
  330. }
  331. }
  332. void RootFrameSink::DettachClient() {
  333. client_ = nullptr;
  334. }
  335. void RootFrameSink::SubmitChildCompositorFrame(ChildFrame* child_frame) {
  336. DCHECK(child_frame->frame);
  337. DCHECK(child_frame->local_surface_id.is_valid());
  338. if (!child_sink_support_ ||
  339. child_sink_support_->frame_sink_id() != child_frame->frame_sink_id ||
  340. child_sink_support_->layer_tree_frame_sink_id() !=
  341. child_frame->layer_tree_frame_sink_id) {
  342. child_sink_support_.reset();
  343. child_sink_support_ = std::make_unique<ChildCompositorFrameSink>(
  344. this, child_frame->layer_tree_frame_sink_id,
  345. child_frame->frame_sink_id);
  346. }
  347. child_sink_support_->SubmitCompositorFrame(
  348. child_frame->local_surface_id, std::move(*child_frame->frame),
  349. std::move(child_frame->hit_test_region_list));
  350. child_frame->frame.reset();
  351. }
  352. viz::FrameTimingDetailsMap RootFrameSink::TakeChildFrameTimingDetailsMap() {
  353. // Take timing for root CompositorFrameSinkSupport to avoid them accumulating.
  354. // We don't use them anyhow.
  355. std::ignore = support_->TakeFrameTimingDetailsMap();
  356. if (child_sink_support_)
  357. return child_sink_support_->support()->TakeFrameTimingDetailsMap();
  358. return viz::FrameTimingDetailsMap();
  359. }
  360. gfx::Size RootFrameSink::GetChildFrameSize() {
  361. // TODO(vasilyt): This is not going to work with VizFrameSubmissionForWebView.
  362. if (child_sink_support_) {
  363. return child_sink_support_->size();
  364. }
  365. return gfx::Size();
  366. }
  367. void RootFrameSink::EvictChildSurface(const viz::SurfaceId& surface_id) {
  368. DCHECK(child_sink_support_);
  369. child_sink_support_->EvictSurface(surface_id);
  370. }
  371. void RootFrameSink::OnCaptureStarted(const viz::FrameSinkId& frame_sink_id) {
  372. auto it = std::find_if(contained_surfaces_.begin(), contained_surfaces_.end(),
  373. [frame_sink_id](const viz::SurfaceId& surface_id) {
  374. return surface_id.frame_sink_id() == frame_sink_id;
  375. });
  376. if (it == contained_surfaces_.end())
  377. return;
  378. // When a capture is started we need to force an invalidate.
  379. if (client_)
  380. client_->Invalidate();
  381. }
  382. } // namespace android_webview