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