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