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