1 // Copyright 2014 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 
5 #include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
6 
7 #include <stddef.h>
8 #include <stdint.h>
9 
10 #include "base/bind.h"
11 #include "base/check_op.h"
12 #include "base/metrics/histogram_functions.h"
13 #include "base/trace_event/trace_event.h"
14 #include "components/viz/service/display/shared_bitmap_manager.h"
15 #include "components/viz/service/display_embedder/output_surface_provider.h"
16 #include "components/viz/service/frame_sinks/compositor_frame_sink_support.h"
17 #include "components/viz/service/frame_sinks/video_capture/capturable_frame_sink.h"
18 #include "components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.h"
19 
20 namespace viz {
21 
22 FrameSinkManagerImpl::InitParams::InitParams() = default;
InitParams(SharedBitmapManager * shared_bitmap_manager,OutputSurfaceProvider * output_surface_provider)23 FrameSinkManagerImpl::InitParams::InitParams(
24     SharedBitmapManager* shared_bitmap_manager,
25     OutputSurfaceProvider* output_surface_provider)
26     : shared_bitmap_manager(shared_bitmap_manager),
27       output_surface_provider(output_surface_provider) {}
28 FrameSinkManagerImpl::InitParams::InitParams(InitParams&& other) = default;
29 FrameSinkManagerImpl::InitParams::~InitParams() = default;
30 FrameSinkManagerImpl::InitParams& FrameSinkManagerImpl::InitParams::operator=(
31     InitParams&& other) = default;
32 
33 FrameSinkManagerImpl::FrameSinkSourceMapping::FrameSinkSourceMapping() =
34     default;
35 
36 FrameSinkManagerImpl::FrameSinkSourceMapping::FrameSinkSourceMapping(
37     FrameSinkSourceMapping&& other) = default;
38 
39 FrameSinkManagerImpl::FrameSinkSourceMapping::~FrameSinkSourceMapping() =
40     default;
41 
42 FrameSinkManagerImpl::FrameSinkSourceMapping&
43 FrameSinkManagerImpl::FrameSinkSourceMapping::operator=(
44     FrameSinkSourceMapping&& other) = default;
45 
FrameSinkData(bool report_activation)46 FrameSinkManagerImpl::FrameSinkData::FrameSinkData(bool report_activation)
47     : report_activation(report_activation) {}
48 
49 FrameSinkManagerImpl::FrameSinkData::FrameSinkData(FrameSinkData&& other) =
50     default;
51 FrameSinkManagerImpl::FrameSinkData::~FrameSinkData() = default;
52 FrameSinkManagerImpl::FrameSinkData& FrameSinkManagerImpl::FrameSinkData::
53 operator=(FrameSinkData&& other) = default;
54 
FrameSinkManagerImpl(const InitParams & params)55 FrameSinkManagerImpl::FrameSinkManagerImpl(const InitParams& params)
56     : shared_bitmap_manager_(params.shared_bitmap_manager),
57       output_surface_provider_(params.output_surface_provider),
58       surface_manager_(this, params.activation_deadline_in_frames),
59       hit_test_manager_(surface_manager()),
60       restart_id_(params.restart_id),
61       run_all_compositor_stages_before_draw_(
62           params.run_all_compositor_stages_before_draw),
63       log_capture_pipeline_in_webrtc_(params.log_capture_pipeline_in_webrtc),
64       debug_settings_(params.debug_renderer_settings) {
65   surface_manager_.AddObserver(&hit_test_manager_);
66   surface_manager_.AddObserver(this);
67 }
68 
FrameSinkManagerImpl(SharedBitmapManager * shared_bitmap_manager,OutputSurfaceProvider * output_surface_provider)69 FrameSinkManagerImpl::FrameSinkManagerImpl(
70     SharedBitmapManager* shared_bitmap_manager,
71     OutputSurfaceProvider* output_surface_provider)
72     : FrameSinkManagerImpl(
73           InitParams(shared_bitmap_manager, output_surface_provider)) {}
74 
~FrameSinkManagerImpl()75 FrameSinkManagerImpl::~FrameSinkManagerImpl() {
76   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
77   video_capturers_.clear();
78 
79   // All mojom::CompositorFrameSinks and BeginFrameSources should be deleted by
80   // this point.
81   DCHECK(sink_map_.empty());
82   DCHECK(root_sink_map_.empty());
83   DCHECK(cached_back_buffers_.empty());
84   DCHECK(registered_sources_.empty());
85 
86   surface_manager_.RemoveObserver(this);
87   surface_manager_.RemoveObserver(&hit_test_manager_);
88 }
89 
BindAndSetClient(mojo::PendingReceiver<mojom::FrameSinkManager> receiver,scoped_refptr<base::SingleThreadTaskRunner> task_runner,mojo::PendingRemote<mojom::FrameSinkManagerClient> client)90 void FrameSinkManagerImpl::BindAndSetClient(
91     mojo::PendingReceiver<mojom::FrameSinkManager> receiver,
92     scoped_refptr<base::SingleThreadTaskRunner> task_runner,
93     mojo::PendingRemote<mojom::FrameSinkManagerClient> client) {
94   DCHECK(!client_);
95   DCHECK(!receiver_.is_bound());
96   receiver_.Bind(std::move(receiver), std::move(task_runner));
97   client_remote_.Bind(std::move(client));
98   client_ = client_remote_.get();
99 }
100 
SetLocalClient(mojom::FrameSinkManagerClient * client,scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner)101 void FrameSinkManagerImpl::SetLocalClient(
102     mojom::FrameSinkManagerClient* client,
103     scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) {
104   DCHECK(!client_remote_);
105   DCHECK(!ui_task_runner_);
106   client_ = client;
107   ui_task_runner_ = ui_task_runner;
108 }
109 
ForceShutdown()110 void FrameSinkManagerImpl::ForceShutdown() {
111   if (receiver_.is_bound())
112     receiver_.reset();
113 
114   for (auto& it : cached_back_buffers_)
115     it.second.RunAndReset();
116   cached_back_buffers_.clear();
117 
118   sink_map_.clear();
119   root_sink_map_.clear();
120 }
121 
RegisterFrameSinkId(const FrameSinkId & frame_sink_id,bool report_activation)122 void FrameSinkManagerImpl::RegisterFrameSinkId(const FrameSinkId& frame_sink_id,
123                                                bool report_activation) {
124   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
125   DCHECK(!base::Contains(frame_sink_data_, frame_sink_id));
126 
127   frame_sink_data_.emplace(std::make_pair(frame_sink_id, report_activation));
128 
129   if (video_detector_)
130     video_detector_->OnFrameSinkIdRegistered(frame_sink_id);
131 
132   for (auto& observer : observer_list_)
133     observer.OnRegisteredFrameSinkId(frame_sink_id);
134 }
135 
InvalidateFrameSinkId(const FrameSinkId & frame_sink_id)136 void FrameSinkManagerImpl::InvalidateFrameSinkId(
137     const FrameSinkId& frame_sink_id) {
138   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
139 
140   surface_manager_.InvalidateFrameSinkId(frame_sink_id);
141   if (video_detector_)
142     video_detector_->OnFrameSinkIdInvalidated(frame_sink_id);
143 
144   // Destroy the [Root]CompositorFrameSinkImpl if there is one.
145   sink_map_.erase(frame_sink_id);
146   root_sink_map_.erase(frame_sink_id);
147 
148   frame_sink_data_.erase(frame_sink_id);
149 
150   for (auto& observer : observer_list_)
151     observer.OnInvalidatedFrameSinkId(frame_sink_id);
152 }
153 
SetFrameSinkDebugLabel(const FrameSinkId & frame_sink_id,const std::string & debug_label)154 void FrameSinkManagerImpl::SetFrameSinkDebugLabel(
155     const FrameSinkId& frame_sink_id,
156     const std::string& debug_label) {
157   auto it = frame_sink_data_.find(frame_sink_id);
158   if (it != frame_sink_data_.end())
159     it->second.debug_label = debug_label;
160 }
161 
CreateRootCompositorFrameSink(mojom::RootCompositorFrameSinkParamsPtr params)162 void FrameSinkManagerImpl::CreateRootCompositorFrameSink(
163     mojom::RootCompositorFrameSinkParamsPtr params) {
164   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
165   DCHECK(!base::Contains(root_sink_map_, params->frame_sink_id));
166   DCHECK(output_surface_provider_);
167 
168   // We are transfering ownership of |params| so remember FrameSinkId here.
169   FrameSinkId frame_sink_id = params->frame_sink_id;
170 
171   // Creating RootCompositorFrameSinkImpl can fail and return null.
172   auto root_compositor_frame_sink = RootCompositorFrameSinkImpl::Create(
173       std::move(params), this, output_surface_provider_, restart_id_,
174       run_all_compositor_stages_before_draw_, &debug_settings_);
175 
176   if (root_compositor_frame_sink)
177     root_sink_map_[frame_sink_id] = std::move(root_compositor_frame_sink);
178 }
179 
CreateCompositorFrameSink(const FrameSinkId & frame_sink_id,mojo::PendingReceiver<mojom::CompositorFrameSink> receiver,mojo::PendingRemote<mojom::CompositorFrameSinkClient> client)180 void FrameSinkManagerImpl::CreateCompositorFrameSink(
181     const FrameSinkId& frame_sink_id,
182     mojo::PendingReceiver<mojom::CompositorFrameSink> receiver,
183     mojo::PendingRemote<mojom::CompositorFrameSinkClient> client) {
184   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
185   DCHECK(!base::Contains(sink_map_, frame_sink_id));
186 
187   sink_map_[frame_sink_id] = std::make_unique<CompositorFrameSinkImpl>(
188       this, frame_sink_id, std::move(receiver), std::move(client));
189 }
190 
DestroyCompositorFrameSink(const FrameSinkId & frame_sink_id,DestroyCompositorFrameSinkCallback callback)191 void FrameSinkManagerImpl::DestroyCompositorFrameSink(
192     const FrameSinkId& frame_sink_id,
193     DestroyCompositorFrameSinkCallback callback) {
194   sink_map_.erase(frame_sink_id);
195   root_sink_map_.erase(frame_sink_id);
196   std::move(callback).Run();
197 }
198 
RegisterFrameSinkHierarchy(const FrameSinkId & parent_frame_sink_id,const FrameSinkId & child_frame_sink_id)199 void FrameSinkManagerImpl::RegisterFrameSinkHierarchy(
200     const FrameSinkId& parent_frame_sink_id,
201     const FrameSinkId& child_frame_sink_id) {
202   // If it's possible to reach the parent through the child's descendant chain,
203   // then this will create an infinite loop.  Might as well just crash here.
204   CHECK(!ChildContains(child_frame_sink_id, parent_frame_sink_id));
205 
206   auto& children = frame_sink_source_map_[parent_frame_sink_id].children;
207   DCHECK(!base::Contains(children, child_frame_sink_id));
208   children.insert(child_frame_sink_id);
209 
210   for (auto& observer : observer_list_) {
211     observer.OnRegisteredFrameSinkHierarchy(parent_frame_sink_id,
212                                             child_frame_sink_id);
213   }
214 
215   // If the parent has no source, then attaching it to this child will
216   // not change any downstream sources.
217   BeginFrameSource* parent_source =
218       frame_sink_source_map_[parent_frame_sink_id].source;
219   if (!parent_source)
220     return;
221 
222   DCHECK_EQ(registered_sources_.count(parent_source), 1u);
223   RecursivelyAttachBeginFrameSource(child_frame_sink_id, parent_source);
224 }
225 
UnregisterFrameSinkHierarchy(const FrameSinkId & parent_frame_sink_id,const FrameSinkId & child_frame_sink_id)226 void FrameSinkManagerImpl::UnregisterFrameSinkHierarchy(
227     const FrameSinkId& parent_frame_sink_id,
228     const FrameSinkId& child_frame_sink_id) {
229   // Deliberately do not check validity of either parent or child FrameSinkId
230   // here. They were valid during the registration, so were valid at some point
231   // in time. This makes it possible to invalidate parent and child FrameSinkIds
232   // independently of each other and not have an ordering dependency of
233   // unregistering the hierarchy first before either of them.
234 
235   for (auto& observer : observer_list_) {
236     observer.OnUnregisteredFrameSinkHierarchy(parent_frame_sink_id,
237                                               child_frame_sink_id);
238   }
239 
240   auto iter = frame_sink_source_map_.find(parent_frame_sink_id);
241   DCHECK(iter != frame_sink_source_map_.end());
242 
243   // Remove |child_frame_sink_id| from parents list of children.
244   auto& mapping = iter->second;
245   DCHECK(base::Contains(mapping.children, child_frame_sink_id));
246   mapping.children.erase(child_frame_sink_id);
247 
248   // Delete the FrameSinkSourceMapping for |parent_frame_sink_id| if empty.
249   if (mapping.children.empty() && !mapping.source) {
250     frame_sink_source_map_.erase(iter);
251     return;
252   }
253 
254   // If the parent does not have a begin frame source, then disconnecting it
255   // will not change any of its children.
256   BeginFrameSource* parent_source = iter->second.source;
257   if (!parent_source)
258     return;
259 
260   // TODO(enne): these walks could be done in one step.
261   RecursivelyDetachBeginFrameSource(child_frame_sink_id, parent_source);
262   for (auto& source_iter : registered_sources_)
263     RecursivelyAttachBeginFrameSource(source_iter.second, source_iter.first);
264 }
265 
AddVideoDetectorObserver(mojo::PendingRemote<mojom::VideoDetectorObserver> observer)266 void FrameSinkManagerImpl::AddVideoDetectorObserver(
267     mojo::PendingRemote<mojom::VideoDetectorObserver> observer) {
268   if (!video_detector_) {
269     video_detector_ = std::make_unique<VideoDetector>(
270         GetRegisteredFrameSinkIds(), &surface_manager_);
271   }
272   video_detector_->AddObserver(std::move(observer));
273 }
274 
CreateVideoCapturer(mojo::PendingReceiver<mojom::FrameSinkVideoCapturer> receiver)275 void FrameSinkManagerImpl::CreateVideoCapturer(
276     mojo::PendingReceiver<mojom::FrameSinkVideoCapturer> receiver) {
277   video_capturers_.emplace(std::make_unique<FrameSinkVideoCapturerImpl>(
278       this, std::move(receiver),
279       std::make_unique<media::VideoCaptureOracle>(
280           true /* enable_auto_throttling */),
281       log_capture_pipeline_in_webrtc_));
282 }
283 
EvictSurfaces(const std::vector<SurfaceId> & surface_ids)284 void FrameSinkManagerImpl::EvictSurfaces(
285     const std::vector<SurfaceId>& surface_ids) {
286   for (const SurfaceId& surface_id : surface_ids) {
287     auto it = support_map_.find(surface_id.frame_sink_id());
288     if (it == support_map_.end())
289       continue;
290     it->second->EvictSurface(surface_id.local_surface_id());
291   }
292 }
293 
RequestCopyOfOutput(const SurfaceId & surface_id,std::unique_ptr<CopyOutputRequest> request)294 void FrameSinkManagerImpl::RequestCopyOfOutput(
295     const SurfaceId& surface_id,
296     std::unique_ptr<CopyOutputRequest> request) {
297   TRACE_EVENT0("viz", "FrameSinkManagerImpl::RequestCopyOfOutput");
298   auto it = support_map_.find(surface_id.frame_sink_id());
299   if (it == support_map_.end()) {
300     // |request| will send an empty result when it goes out of scope.
301     return;
302   }
303   it->second->RequestCopyOfOutput(surface_id.local_surface_id(),
304                                   std::move(request));
305 }
306 
SetHitTestAsyncQueriedDebugRegions(const FrameSinkId & root_frame_sink_id,const std::vector<FrameSinkId> & hit_test_async_queried_debug_queue)307 void FrameSinkManagerImpl::SetHitTestAsyncQueriedDebugRegions(
308     const FrameSinkId& root_frame_sink_id,
309     const std::vector<FrameSinkId>& hit_test_async_queried_debug_queue) {
310   hit_test_manager_.SetHitTestAsyncQueriedDebugRegions(
311       root_frame_sink_id, hit_test_async_queried_debug_queue);
312   DCHECK(base::Contains(root_sink_map_, root_frame_sink_id));
313   root_sink_map_[root_frame_sink_id]->ForceImmediateDrawAndSwapIfPossible();
314 }
315 
OnFirstSurfaceActivation(const SurfaceInfo & surface_info)316 void FrameSinkManagerImpl::OnFirstSurfaceActivation(
317     const SurfaceInfo& surface_info) {
318   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
319   DCHECK_GT(surface_info.device_scale_factor(), 0.0f);
320 
321   auto it = frame_sink_data_.find(surface_info.id().frame_sink_id());
322   if (it == frame_sink_data_.end())
323     return;
324 
325   const FrameSinkData& frame_sink_data = it->second;
326 
327   if (client_ && frame_sink_data.report_activation)
328     client_->OnFirstSurfaceActivation(surface_info);
329 }
330 
OnAggregatedHitTestRegionListUpdated(const FrameSinkId & frame_sink_id,const std::vector<AggregatedHitTestRegion> & hit_test_data)331 void FrameSinkManagerImpl::OnAggregatedHitTestRegionListUpdated(
332     const FrameSinkId& frame_sink_id,
333     const std::vector<AggregatedHitTestRegion>& hit_test_data) {
334   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
335   if (client_) {
336     client_->OnAggregatedHitTestRegionListUpdated(frame_sink_id, hit_test_data);
337   }
338 }
339 
GetFrameSinkDebugLabel(const FrameSinkId & frame_sink_id) const340 base::StringPiece FrameSinkManagerImpl::GetFrameSinkDebugLabel(
341     const FrameSinkId& frame_sink_id) const {
342   auto it = frame_sink_data_.find(frame_sink_id);
343   if (it != frame_sink_data_.end())
344     return it->second.debug_label;
345   return base::StringPiece();
346 }
347 
AggregatedFrameSinksChanged()348 void FrameSinkManagerImpl::AggregatedFrameSinksChanged() {
349   hit_test_manager_.SetNeedsSubmit();
350 }
351 
RegisterCompositorFrameSinkSupport(const FrameSinkId & frame_sink_id,CompositorFrameSinkSupport * support)352 void FrameSinkManagerImpl::RegisterCompositorFrameSinkSupport(
353     const FrameSinkId& frame_sink_id,
354     CompositorFrameSinkSupport* support) {
355   DCHECK(support);
356   DCHECK(!base::Contains(support_map_, frame_sink_id));
357 
358   support_map_[frame_sink_id] = support;
359 
360   for (auto& capturer : video_capturers_) {
361     if (capturer->requested_target() == frame_sink_id)
362       capturer->SetResolvedTarget(support);
363   }
364 
365   auto it = frame_sink_source_map_.find(frame_sink_id);
366   if (it != frame_sink_source_map_.end() && it->second.source)
367     support->SetBeginFrameSource(it->second.source);
368 
369   for (auto& observer : observer_list_)
370     observer.OnCreatedCompositorFrameSink(frame_sink_id, support->is_root());
371 }
372 
UnregisterCompositorFrameSinkSupport(const FrameSinkId & frame_sink_id)373 void FrameSinkManagerImpl::UnregisterCompositorFrameSinkSupport(
374     const FrameSinkId& frame_sink_id) {
375   DCHECK(base::Contains(support_map_, frame_sink_id));
376 
377   for (auto& observer : observer_list_)
378     observer.OnDestroyedCompositorFrameSink(frame_sink_id);
379 
380   for (auto& capturer : video_capturers_) {
381     if (capturer->requested_target() == frame_sink_id)
382       capturer->OnTargetWillGoAway();
383   }
384 
385   support_map_.erase(frame_sink_id);
386 }
387 
RegisterBeginFrameSource(BeginFrameSource * source,const FrameSinkId & frame_sink_id)388 void FrameSinkManagerImpl::RegisterBeginFrameSource(
389     BeginFrameSource* source,
390     const FrameSinkId& frame_sink_id) {
391   DCHECK(source);
392   DCHECK_EQ(registered_sources_.count(source), 0u);
393 
394   registered_sources_[source] = frame_sink_id;
395   RecursivelyAttachBeginFrameSource(frame_sink_id, source);
396 }
397 
UnregisterBeginFrameSource(BeginFrameSource * source)398 void FrameSinkManagerImpl::UnregisterBeginFrameSource(
399     BeginFrameSource* source) {
400   DCHECK(source);
401   DCHECK_EQ(registered_sources_.count(source), 1u);
402 
403   FrameSinkId frame_sink_id = registered_sources_[source];
404   registered_sources_.erase(source);
405 
406   if (frame_sink_source_map_.count(frame_sink_id) == 0u)
407     return;
408 
409   // TODO(enne): these walks could be done in one step.
410   // Remove this begin frame source from its subtree.
411   RecursivelyDetachBeginFrameSource(frame_sink_id, source);
412   // Then flush every remaining registered source to fix any sources that
413   // became null because of the previous step but that have an alternative.
414   for (auto source_iter : registered_sources_)
415     RecursivelyAttachBeginFrameSource(source_iter.second, source_iter.first);
416 }
417 
RecursivelyAttachBeginFrameSource(const FrameSinkId & frame_sink_id,BeginFrameSource * source)418 void FrameSinkManagerImpl::RecursivelyAttachBeginFrameSource(
419     const FrameSinkId& frame_sink_id,
420     BeginFrameSource* source) {
421   FrameSinkSourceMapping& mapping = frame_sink_source_map_[frame_sink_id];
422   if (!mapping.source) {
423     mapping.source = source;
424     auto iter = support_map_.find(frame_sink_id);
425     if (iter != support_map_.end())
426       iter->second->SetBeginFrameSource(source);
427   }
428 
429   // Copy the list of children because RecursivelyAttachBeginFrameSource() can
430   // modify |frame_sink_source_map_| and invalidate iterators.
431   base::flat_set<FrameSinkId> children = mapping.children;
432   for (const FrameSinkId& child : children)
433     RecursivelyAttachBeginFrameSource(child, source);
434 }
435 
RecursivelyDetachBeginFrameSource(const FrameSinkId & frame_sink_id,BeginFrameSource * source)436 void FrameSinkManagerImpl::RecursivelyDetachBeginFrameSource(
437     const FrameSinkId& frame_sink_id,
438     BeginFrameSource* source) {
439   auto iter = frame_sink_source_map_.find(frame_sink_id);
440   if (iter == frame_sink_source_map_.end())
441     return;
442 
443   auto& mapping = iter->second;
444   if (mapping.source == source) {
445     mapping.source = nullptr;
446     auto client_iter = support_map_.find(frame_sink_id);
447     if (client_iter != support_map_.end())
448       client_iter->second->SetBeginFrameSource(nullptr);
449   }
450 
451   // Delete the FrameSinkSourceMapping for |frame_sink_id| if empty.
452   if (mapping.children.empty()) {
453     frame_sink_source_map_.erase(iter);
454     return;
455   }
456 
457   // Copy the list of children because RecursivelyDetachBeginFrameSource() can
458   // modify |frame_sink_source_map_| and invalidate iterators.
459   base::flat_set<FrameSinkId> children = mapping.children;
460   for (const FrameSinkId& child : children)
461     RecursivelyDetachBeginFrameSource(child, source);
462 }
463 
FindCapturableFrameSink(const FrameSinkId & frame_sink_id)464 CapturableFrameSink* FrameSinkManagerImpl::FindCapturableFrameSink(
465     const FrameSinkId& frame_sink_id) {
466   const auto it = support_map_.find(frame_sink_id);
467   if (it == support_map_.end())
468     return nullptr;
469   return it->second;
470 }
471 
OnCapturerConnectionLost(FrameSinkVideoCapturerImpl * capturer)472 void FrameSinkManagerImpl::OnCapturerConnectionLost(
473     FrameSinkVideoCapturerImpl* capturer) {
474   video_capturers_.erase(capturer);
475 }
476 
ChildContains(const FrameSinkId & child_frame_sink_id,const FrameSinkId & search_frame_sink_id) const477 bool FrameSinkManagerImpl::ChildContains(
478     const FrameSinkId& child_frame_sink_id,
479     const FrameSinkId& search_frame_sink_id) const {
480   auto iter = frame_sink_source_map_.find(child_frame_sink_id);
481   if (iter == frame_sink_source_map_.end())
482     return false;
483 
484   for (const FrameSinkId& child : iter->second.children) {
485     if (child == search_frame_sink_id)
486       return true;
487     if (ChildContains(child, search_frame_sink_id))
488       return true;
489   }
490   return false;
491 }
492 
SubmitHitTestRegionList(const SurfaceId & surface_id,uint64_t frame_index,base::Optional<HitTestRegionList> hit_test_region_list)493 void FrameSinkManagerImpl::SubmitHitTestRegionList(
494     const SurfaceId& surface_id,
495     uint64_t frame_index,
496     base::Optional<HitTestRegionList> hit_test_region_list) {
497   hit_test_manager_.SubmitHitTestRegionList(surface_id, frame_index,
498                                             std::move(hit_test_region_list));
499 }
500 
OnFrameTokenChangedDirect(const FrameSinkId & frame_sink_id,uint32_t frame_token)501 void FrameSinkManagerImpl::OnFrameTokenChangedDirect(
502     const FrameSinkId& frame_sink_id,
503     uint32_t frame_token) {
504   if (client_)
505     client_->OnFrameTokenChanged(frame_sink_id, frame_token);
506 }
507 
OnFrameTokenChanged(const FrameSinkId & frame_sink_id,uint32_t frame_token)508 void FrameSinkManagerImpl::OnFrameTokenChanged(const FrameSinkId& frame_sink_id,
509                                                uint32_t frame_token) {
510   if (client_remote_ || !ui_task_runner_) {
511     // This is a Mojo client or a locally-connected client *without* a task
512     // runner. In this case, call directly.
513     OnFrameTokenChangedDirect(frame_sink_id, frame_token);
514   } else {
515     // This is a locally-connected client *with* a task runner - post task.
516     ui_task_runner_->PostTask(
517         FROM_HERE,
518         base::BindOnce(&FrameSinkManagerImpl::OnFrameTokenChangedDirect,
519                        base::Unretained(this), frame_sink_id, frame_token));
520   }
521 }
522 
CreateVideoDetectorForTesting(const base::TickClock * tick_clock,scoped_refptr<base::SequencedTaskRunner> task_runner)523 VideoDetector* FrameSinkManagerImpl::CreateVideoDetectorForTesting(
524     const base::TickClock* tick_clock,
525     scoped_refptr<base::SequencedTaskRunner> task_runner) {
526   DCHECK(!video_detector_);
527   video_detector_ = std::make_unique<VideoDetector>(
528       GetRegisteredFrameSinkIds(), surface_manager(), tick_clock, task_runner);
529   return video_detector_.get();
530 }
531 
DidBeginFrame(const FrameSinkId & frame_sink_id,const BeginFrameArgs & args)532 void FrameSinkManagerImpl::DidBeginFrame(const FrameSinkId& frame_sink_id,
533                                          const BeginFrameArgs& args) {
534   for (auto& observer : observer_list_)
535     observer.OnFrameSinkDidBeginFrame(frame_sink_id, args);
536 }
537 
DidFinishFrame(const FrameSinkId & frame_sink_id,const BeginFrameArgs & args)538 void FrameSinkManagerImpl::DidFinishFrame(const FrameSinkId& frame_sink_id,
539                                           const BeginFrameArgs& args) {
540   for (auto& observer : observer_list_)
541     observer.OnFrameSinkDidFinishFrame(frame_sink_id, args);
542 }
543 
AddObserver(FrameSinkObserver * obs)544 void FrameSinkManagerImpl::AddObserver(FrameSinkObserver* obs) {
545   observer_list_.AddObserver(obs);
546 }
547 
RemoveObserver(FrameSinkObserver * obs)548 void FrameSinkManagerImpl::RemoveObserver(FrameSinkObserver* obs) {
549   observer_list_.RemoveObserver(obs);
550 }
551 
GetRegisteredFrameSinkIds() const552 std::vector<FrameSinkId> FrameSinkManagerImpl::GetRegisteredFrameSinkIds()
553     const {
554   std::vector<FrameSinkId> frame_sink_ids;
555   for (auto& map_entry : frame_sink_data_)
556     frame_sink_ids.push_back(map_entry.first);
557   return frame_sink_ids;
558 }
559 
GetChildrenByParent(const FrameSinkId & parent_frame_sink_id) const560 base::flat_set<FrameSinkId> FrameSinkManagerImpl::GetChildrenByParent(
561     const FrameSinkId& parent_frame_sink_id) const {
562   auto it = frame_sink_source_map_.find(parent_frame_sink_id);
563   if (it != frame_sink_source_map_.end())
564     return it->second.children;
565   return {};
566 }
567 
GetFrameSinkForId(const FrameSinkId & frame_sink_id) const568 const CompositorFrameSinkSupport* FrameSinkManagerImpl::GetFrameSinkForId(
569     const FrameSinkId& frame_sink_id) const {
570   auto it = support_map_.find(frame_sink_id);
571   if (it != support_map_.end())
572     return it->second;
573   return nullptr;
574 }
575 
GetPreferredFrameIntervalForFrameSinkId(const FrameSinkId & id,mojom::CompositorFrameSinkType * type) const576 base::TimeDelta FrameSinkManagerImpl::GetPreferredFrameIntervalForFrameSinkId(
577     const FrameSinkId& id,
578     mojom::CompositorFrameSinkType* type) const {
579   auto it = support_map_.find(id);
580   if (it != support_map_.end())
581     return it->second->GetPreferredFrameInterval(type);
582 
583   if (type)
584     *type = mojom::CompositorFrameSinkType::kUnspecified;
585   return BeginFrameArgs::MinInterval();
586 }
587 
DiscardPendingCopyOfOutputRequests(const BeginFrameSource * source)588 void FrameSinkManagerImpl::DiscardPendingCopyOfOutputRequests(
589     const BeginFrameSource* source) {
590   const auto& root_sink = registered_sources_.at(source);
591   base::queue<FrameSinkId> queue;
592   for (queue.push(root_sink); !queue.empty(); queue.pop()) {
593     auto& frame_sink_id = queue.front();
594     auto support = support_map_.find(frame_sink_id);
595     // The returned copy requests are destroyed upon going out of scope, which
596     // invokes the pending callbacks.
597     if (support != support_map_.end())
598       support->second->TakeCopyOutputRequests(LocalSurfaceId::MaxSequenceId());
599     for (auto child : GetChildrenByParent(frame_sink_id))
600       queue.push(child);
601   }
602 }
603 
CacheBackBuffer(uint32_t cache_id,const FrameSinkId & root_frame_sink_id)604 void FrameSinkManagerImpl::CacheBackBuffer(
605     uint32_t cache_id,
606     const FrameSinkId& root_frame_sink_id) {
607   auto it = root_sink_map_.find(root_frame_sink_id);
608 
609   DCHECK(it != root_sink_map_.end());
610   DCHECK(cached_back_buffers_.find(cache_id) == cached_back_buffers_.end());
611 
612   cached_back_buffers_[cache_id] = it->second->GetCacheBackBufferCb();
613 }
614 
EvictBackBuffer(uint32_t cache_id,EvictBackBufferCallback callback)615 void FrameSinkManagerImpl::EvictBackBuffer(uint32_t cache_id,
616                                            EvictBackBufferCallback callback) {
617   auto it = cached_back_buffers_.find(cache_id);
618   DCHECK(it != cached_back_buffers_.end());
619 
620   cached_back_buffers_.erase(it);
621   std::move(callback).Run();
622 }
623 
UpdateDebugRendererSettings(const DebugRendererSettings & debug_settings)624 void FrameSinkManagerImpl::UpdateDebugRendererSettings(
625     const DebugRendererSettings& debug_settings) {
626   debug_settings_ = debug_settings;
627 }
628 
UpdateThrottlingRecursively(const FrameSinkId & frame_sink_id,base::TimeDelta interval)629 void FrameSinkManagerImpl::UpdateThrottlingRecursively(
630     const FrameSinkId& frame_sink_id,
631     base::TimeDelta interval) {
632   auto it = support_map_.find(frame_sink_id);
633   if (it != support_map_.end()) {
634     it->second->ThrottleBeginFrame(interval);
635   }
636   auto children = GetChildrenByParent(frame_sink_id);
637   for (auto& id : children)
638     UpdateThrottlingRecursively(id, interval);
639 }
640 
StartThrottling(const std::vector<FrameSinkId> & frame_sink_ids,base::TimeDelta interval)641 void FrameSinkManagerImpl::StartThrottling(
642     const std::vector<FrameSinkId>& frame_sink_ids,
643     base::TimeDelta interval) {
644   DCHECK_GT(interval, base::TimeDelta());
645   DCHECK(!frame_sinks_throttled_);
646 
647   frame_sinks_throttled_ = true;
648   for (auto& frame_sink_id : frame_sink_ids) {
649     UpdateThrottlingRecursively(frame_sink_id, interval);
650   }
651 }
652 
EndThrottling()653 void FrameSinkManagerImpl::EndThrottling() {
654   for (auto& support_map_item : support_map_) {
655     support_map_item.second->ThrottleBeginFrame(base::TimeDelta());
656   }
657   frame_sinks_throttled_ = false;
658 }
659 }  // namespace viz
660