1 // Copyright 2016 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/compositor_frame_sink_support.h"
6
7 #include <algorithm>
8 #include <string>
9 #include <utility>
10
11 #include "base/bind.h"
12 #include "base/metrics/histogram_macros.h"
13 #include "base/stl_util.h"
14 #include "base/time/time.h"
15 #include "build/build_config.h"
16 #include "components/viz/common/frame_sinks/begin_frame_source.h"
17 #include "components/viz/common/quads/compositor_frame.h"
18 #include "components/viz/common/resources/bitmap_allocation.h"
19 #include "components/viz/common/surfaces/surface_info.h"
20 #include "components/viz/service/display/display.h"
21 #include "components/viz/service/display/shared_bitmap_manager.h"
22 #include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
23 #include "components/viz/service/surfaces/surface.h"
24 #include "components/viz/service/surfaces/surface_reference.h"
25 #include "mojo/public/cpp/system/platform_handle.h"
26
27 namespace viz {
28 namespace {
29
RecordShouldSendBeginFrame(const std::string & reason)30 void RecordShouldSendBeginFrame(const std::string& reason) {
31 TRACE_EVENT1("viz", "ShouldNotSendBeginFrame", "reason", reason);
32 }
33
AdjustPresentationFeedback(gfx::PresentationFeedback * feedback,base::TimeTicks swap_start)34 void AdjustPresentationFeedback(gfx::PresentationFeedback* feedback,
35 base::TimeTicks swap_start) {
36 // Swap start to end breakdown is always reported if ready timestamp is
37 // available. The other timestamps are adjusted to assume 0 delay in those
38 // stages if the breakdown is not available.
39 if (feedback->ready_timestamp.is_null())
40 return;
41
42 feedback->available_timestamp =
43 std::max(feedback->available_timestamp, swap_start);
44 feedback->latch_timestamp =
45 std::max(feedback->latch_timestamp, feedback->ready_timestamp);
46 }
47
48 } // namespace
49
CompositorFrameSinkSupport(mojom::CompositorFrameSinkClient * client,FrameSinkManagerImpl * frame_sink_manager,const FrameSinkId & frame_sink_id,bool is_root)50 CompositorFrameSinkSupport::CompositorFrameSinkSupport(
51 mojom::CompositorFrameSinkClient* client,
52 FrameSinkManagerImpl* frame_sink_manager,
53 const FrameSinkId& frame_sink_id,
54 bool is_root)
55 : client_(client),
56 frame_sink_manager_(frame_sink_manager),
57 surface_manager_(frame_sink_manager->surface_manager()),
58 frame_sink_id_(frame_sink_id),
59 surface_resource_holder_(this),
60 is_root_(is_root),
61 allow_copy_output_requests_(is_root) {
62 // This may result in SetBeginFrameSource() being called.
63 frame_sink_manager_->RegisterCompositorFrameSinkSupport(frame_sink_id_, this);
64 }
65
~CompositorFrameSinkSupport()66 CompositorFrameSinkSupport::~CompositorFrameSinkSupport() {
67 // Unregister |this| as a BeginFrameObserver so that the
68 // BeginFrameSource does not call into |this| after it's deleted.
69 callback_received_begin_frame_ = true;
70 callback_received_receive_ack_ = true;
71 frame_timing_details_.clear();
72 SetNeedsBeginFrame(false);
73
74 // For display root surfaces the surface is no longer going to be visible.
75 // Make it unreachable from the top-level root.
76 if (referenced_local_surface_id_.has_value()) {
77 auto reference = MakeTopLevelRootReference(
78 SurfaceId(frame_sink_id_, referenced_local_surface_id_.value()));
79 surface_manager_->RemoveSurfaceReferences({reference});
80 }
81
82 if (last_activated_surface_id_.is_valid())
83 EvictLastActiveSurface();
84 if (last_created_surface_id_.is_valid())
85 surface_manager_->MarkSurfaceForDestruction(last_created_surface_id_);
86 frame_sink_manager_->UnregisterCompositorFrameSinkSupport(frame_sink_id_);
87
88 // The display compositor has ownership of shared memory for each
89 // SharedBitmapId that has been reported from the client. Since the client is
90 // gone that memory can be freed. If we don't then it would leak.
91 for (const auto& id : owned_bitmaps_)
92 frame_sink_manager_->shared_bitmap_manager()->ChildDeletedSharedBitmap(id);
93
94 // No video capture clients should remain after calling
95 // UnregisterCompositorFrameSinkSupport().
96 DCHECK(capture_clients_.empty());
97
98 if (begin_frame_source_ && added_frame_observer_)
99 begin_frame_source_->RemoveObserver(this);
100 }
101
TakeFrameTimingDetailsMap()102 FrameTimingDetailsMap CompositorFrameSinkSupport::TakeFrameTimingDetailsMap() {
103 FrameTimingDetailsMap map;
104 map.swap(frame_timing_details_);
105 return map;
106 }
107
SetUpHitTest(LatestLocalSurfaceIdLookupDelegate * local_surface_id_lookup_delegate)108 void CompositorFrameSinkSupport::SetUpHitTest(
109 LatestLocalSurfaceIdLookupDelegate* local_surface_id_lookup_delegate) {
110 DCHECK(is_root_);
111 hit_test_aggregator_ = std::make_unique<HitTestAggregator>(
112 frame_sink_manager_->hit_test_manager(), frame_sink_manager_,
113 local_surface_id_lookup_delegate, frame_sink_id_);
114 }
115
SetAggregatedDamageCallbackForTesting(AggregatedDamageCallback callback)116 void CompositorFrameSinkSupport::SetAggregatedDamageCallbackForTesting(
117 AggregatedDamageCallback callback) {
118 aggregated_damage_callback_ = std::move(callback);
119 }
120
SetBeginFrameSource(BeginFrameSource * begin_frame_source)121 void CompositorFrameSinkSupport::SetBeginFrameSource(
122 BeginFrameSource* begin_frame_source) {
123 if (begin_frame_source_ && added_frame_observer_) {
124 begin_frame_source_->RemoveObserver(this);
125 added_frame_observer_ = false;
126 }
127 begin_frame_source_ = begin_frame_source;
128 UpdateNeedsBeginFramesInternal();
129 }
130
ThrottleBeginFrame(base::TimeDelta interval)131 void CompositorFrameSinkSupport::ThrottleBeginFrame(base::TimeDelta interval) {
132 begin_frame_interval_ = interval;
133 }
134
OnSurfaceActivated(Surface * surface)135 void CompositorFrameSinkSupport::OnSurfaceActivated(Surface* surface) {
136 DCHECK(surface);
137 DCHECK(surface->HasActiveFrame());
138 DCHECK(!surface->HasPendingFrame());
139
140 pending_surfaces_.erase(surface);
141 if (pending_surfaces_.empty())
142 UpdateNeedsBeginFramesInternal();
143
144 if (surface->surface_id() == last_activated_surface_id_)
145 return;
146
147 Surface* previous_surface =
148 surface_manager_->GetSurfaceForId(last_activated_surface_id_);
149
150 if (!previous_surface) {
151 last_activated_surface_id_ = surface->surface_id();
152 } else if (previous_surface->GetActiveFrameIndex() <
153 surface->GetActiveFrameIndex()) {
154 surface_manager_->MarkSurfaceForDestruction(last_activated_surface_id_);
155 last_activated_surface_id_ = surface->surface_id();
156 // TODO(samans): Why is this not done when creating the surface?
157 surface->SetPreviousFrameSurface(previous_surface);
158 } else {
159 DCHECK_GT(previous_surface->GetActiveFrameIndex(),
160 surface->GetActiveFrameIndex());
161 // We can get into a situation where a child-initiated synchronization is
162 // deferred until after a parent-initiated synchronization happens resulting
163 // in activations happening out of order. In that case, we simply discard
164 // the stale surface.
165 surface_manager_->MarkSurfaceForDestruction(surface->surface_id());
166 }
167
168 // Check if this is a display root surface and the SurfaceId is changing.
169 if (is_root_ && (!referenced_local_surface_id_ ||
170 *referenced_local_surface_id_ !=
171 last_activated_surface_id_.local_surface_id())) {
172 UpdateDisplayRootReference(surface);
173 }
174
175 MaybeEvictSurfaces();
176 }
177
OnSurfaceWillDraw(Surface * surface)178 void CompositorFrameSinkSupport::OnSurfaceWillDraw(Surface* surface) {
179 if (last_drawn_frame_index_ >= surface->GetActiveFrameIndex())
180 return;
181 last_drawn_frame_index_ = surface->GetActiveFrameIndex();
182 }
183
OnFrameTokenChanged(uint32_t frame_token)184 void CompositorFrameSinkSupport::OnFrameTokenChanged(uint32_t frame_token) {
185 frame_sink_manager_->OnFrameTokenChanged(frame_sink_id_, frame_token);
186 }
187
OnSurfaceProcessed(Surface * surface)188 void CompositorFrameSinkSupport::OnSurfaceProcessed(Surface* surface) {
189 DidReceiveCompositorFrameAck();
190 }
191
OnSurfaceAggregatedDamage(Surface * surface,const LocalSurfaceId & local_surface_id,const CompositorFrame & frame,const gfx::Rect & damage_rect,base::TimeTicks expected_display_time)192 void CompositorFrameSinkSupport::OnSurfaceAggregatedDamage(
193 Surface* surface,
194 const LocalSurfaceId& local_surface_id,
195 const CompositorFrame& frame,
196 const gfx::Rect& damage_rect,
197 base::TimeTicks expected_display_time) {
198 DCHECK(!damage_rect.IsEmpty());
199
200 const gfx::Size& frame_size_in_pixels = frame.size_in_pixels();
201 if (aggregated_damage_callback_) {
202 aggregated_damage_callback_.Run(local_surface_id, frame_size_in_pixels,
203 damage_rect, expected_display_time);
204 }
205
206 for (CapturableFrameSink::Client* client : capture_clients_) {
207 client->OnFrameDamaged(frame_size_in_pixels, damage_rect,
208 expected_display_time, frame.metadata);
209 }
210 }
211
OnSurfaceDestroyed(Surface * surface)212 void CompositorFrameSinkSupport::OnSurfaceDestroyed(Surface* surface) {
213 pending_surfaces_.erase(surface);
214
215 if (surface->surface_id() == last_activated_surface_id_)
216 last_activated_surface_id_ = SurfaceId();
217
218 if (surface->surface_id() == last_created_surface_id_)
219 last_created_surface_id_ = SurfaceId();
220 }
221
OnSurfacePresented(uint32_t frame_token,base::TimeTicks draw_start_timestamp,const gfx::SwapTimings & swap_timings,const gfx::PresentationFeedback & feedback)222 void CompositorFrameSinkSupport::OnSurfacePresented(
223 uint32_t frame_token,
224 base::TimeTicks draw_start_timestamp,
225 const gfx::SwapTimings& swap_timings,
226 const gfx::PresentationFeedback& feedback) {
227 DidPresentCompositorFrame(frame_token, draw_start_timestamp, swap_timings,
228 feedback);
229 }
230
RefResources(const std::vector<TransferableResource> & resources)231 void CompositorFrameSinkSupport::RefResources(
232 const std::vector<TransferableResource>& resources) {
233 surface_resource_holder_.RefResources(resources);
234 }
235
UnrefResources(const std::vector<ReturnedResource> & resources)236 void CompositorFrameSinkSupport::UnrefResources(
237 const std::vector<ReturnedResource>& resources) {
238 surface_resource_holder_.UnrefResources(resources);
239 }
240
ReturnResources(const std::vector<ReturnedResource> & resources)241 void CompositorFrameSinkSupport::ReturnResources(
242 const std::vector<ReturnedResource>& resources) {
243 if (resources.empty())
244 return;
245 if (!ack_pending_count_ && client_) {
246 client_->ReclaimResources(resources);
247 return;
248 }
249
250 std::copy(resources.begin(), resources.end(),
251 std::back_inserter(surface_returned_resources_));
252 }
253
ReceiveFromChild(const std::vector<TransferableResource> & resources)254 void CompositorFrameSinkSupport::ReceiveFromChild(
255 const std::vector<TransferableResource>& resources) {
256 surface_resource_holder_.ReceiveFromChild(resources);
257 }
258
259 std::vector<std::unique_ptr<CopyOutputRequest>>
TakeCopyOutputRequests(const LocalSurfaceId & latest_local_id)260 CompositorFrameSinkSupport::TakeCopyOutputRequests(
261 const LocalSurfaceId& latest_local_id) {
262 std::vector<std::unique_ptr<CopyOutputRequest>> results;
263 for (auto it = copy_output_requests_.begin();
264 it != copy_output_requests_.end();) {
265 // Requests with a non-valid local id should be satisfied as soon as
266 // possible.
267 if (!it->first.is_valid() || it->first <= latest_local_id) {
268 results.push_back(std::move(it->second));
269 it = copy_output_requests_.erase(it);
270 } else {
271 ++it;
272 }
273 }
274 return results;
275 }
276
EvictSurface(const LocalSurfaceId & id)277 void CompositorFrameSinkSupport::EvictSurface(const LocalSurfaceId& id) {
278 DCHECK(id.embed_token() != last_evicted_local_surface_id_.embed_token() ||
279 id.parent_sequence_number() >=
280 last_evicted_local_surface_id_.parent_sequence_number());
281 last_evicted_local_surface_id_ = id;
282 surface_manager_->DropTemporaryReference(SurfaceId(frame_sink_id_, id));
283 MaybeEvictSurfaces();
284 }
285
MaybeEvictSurfaces()286 void CompositorFrameSinkSupport::MaybeEvictSurfaces() {
287 if (IsEvicted(last_activated_surface_id_.local_surface_id()))
288 EvictLastActiveSurface();
289 if (IsEvicted(last_created_surface_id_.local_surface_id())) {
290 surface_manager_->MarkSurfaceForDestruction(last_created_surface_id_);
291 last_created_surface_id_ = SurfaceId();
292 }
293 }
294
EvictLastActiveSurface()295 void CompositorFrameSinkSupport::EvictLastActiveSurface() {
296 SurfaceId to_destroy_surface_id = last_activated_surface_id_;
297 if (last_created_surface_id_ == last_activated_surface_id_)
298 last_created_surface_id_ = SurfaceId();
299 last_activated_surface_id_ = SurfaceId();
300 surface_manager_->MarkSurfaceForDestruction(to_destroy_surface_id);
301
302 // For display root surfaces the surface is no longer going to be visible.
303 // Make it unreachable from the top-level root.
304 if (referenced_local_surface_id_.has_value()) {
305 auto reference = MakeTopLevelRootReference(
306 SurfaceId(frame_sink_id_, referenced_local_surface_id_.value()));
307 surface_manager_->RemoveSurfaceReferences({reference});
308 referenced_local_surface_id_.reset();
309 }
310 }
311
SetNeedsBeginFrame(bool needs_begin_frame)312 void CompositorFrameSinkSupport::SetNeedsBeginFrame(bool needs_begin_frame) {
313 client_needs_begin_frame_ = needs_begin_frame;
314 UpdateNeedsBeginFramesInternal();
315 }
316
SetWantsAnimateOnlyBeginFrames()317 void CompositorFrameSinkSupport::SetWantsAnimateOnlyBeginFrames() {
318 wants_animate_only_begin_frames_ = true;
319 }
320
WantsAnimateOnlyBeginFrames() const321 bool CompositorFrameSinkSupport::WantsAnimateOnlyBeginFrames() const {
322 return wants_animate_only_begin_frames_;
323 }
324
InitializeCompositorFrameSinkType(mojom::CompositorFrameSinkType type)325 void CompositorFrameSinkSupport::InitializeCompositorFrameSinkType(
326 mojom::CompositorFrameSinkType type) {
327 if (frame_sink_type_ != mojom::CompositorFrameSinkType::kUnspecified ||
328 type == mojom::CompositorFrameSinkType::kUnspecified) {
329 return;
330 }
331 frame_sink_type_ = type;
332 }
333
GetPreferredFrameInterval(mojom::CompositorFrameSinkType * type) const334 base::TimeDelta CompositorFrameSinkSupport::GetPreferredFrameInterval(
335 mojom::CompositorFrameSinkType* type) const {
336 if (type)
337 *type = frame_sink_type_;
338 return preferred_frame_interval_;
339 }
340
IsRoot() const341 bool CompositorFrameSinkSupport::IsRoot() const {
342 return is_root_;
343 }
344
DidNotProduceFrame(const BeginFrameAck & ack)345 void CompositorFrameSinkSupport::DidNotProduceFrame(const BeginFrameAck& ack) {
346 TRACE_EVENT_WITH_FLOW2(
347 "viz,benchmark", "Graphics.Pipeline", TRACE_ID_GLOBAL(ack.trace_id),
348 TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT, "step",
349 "DidNotProduceFrame", "FrameSinkId", frame_sink_id_.ToString());
350 DCHECK(ack.frame_id.IsSequenceValid());
351
352 begin_frame_tracker_.ReceivedAck(ack);
353
354 // Override the has_damage flag (ignoring invalid data from clients).
355 BeginFrameAck modified_ack(ack);
356 modified_ack.has_damage = false;
357
358 if (last_activated_surface_id_.is_valid())
359 surface_manager_->SurfaceModified(last_activated_surface_id_, modified_ack);
360
361 if (begin_frame_source_) {
362 begin_frame_source_->DidFinishFrame(this);
363 frame_sink_manager_->DidFinishFrame(frame_sink_id_, last_begin_frame_args_);
364 }
365 }
366
SubmitCompositorFrame(const LocalSurfaceId & local_surface_id,CompositorFrame frame,base::Optional<HitTestRegionList> hit_test_region_list,uint64_t submit_time)367 void CompositorFrameSinkSupport::SubmitCompositorFrame(
368 const LocalSurfaceId& local_surface_id,
369 CompositorFrame frame,
370 base::Optional<HitTestRegionList> hit_test_region_list,
371 uint64_t submit_time) {
372 const auto result = MaybeSubmitCompositorFrame(
373 local_surface_id, std::move(frame), std::move(hit_test_region_list),
374 submit_time,
375 mojom::CompositorFrameSink::SubmitCompositorFrameSyncCallback());
376 DCHECK_EQ(result, SubmitResult::ACCEPTED);
377 }
378
DidAllocateSharedBitmap(base::ReadOnlySharedMemoryRegion region,const SharedBitmapId & id)379 bool CompositorFrameSinkSupport::DidAllocateSharedBitmap(
380 base::ReadOnlySharedMemoryRegion region,
381 const SharedBitmapId& id) {
382 if (!frame_sink_manager_->shared_bitmap_manager()->ChildAllocatedSharedBitmap(
383 region.Map(), id)) {
384 return false;
385 }
386
387 owned_bitmaps_.insert(id);
388 return true;
389 }
390
DidDeleteSharedBitmap(const SharedBitmapId & id)391 void CompositorFrameSinkSupport::DidDeleteSharedBitmap(
392 const SharedBitmapId& id) {
393 frame_sink_manager_->shared_bitmap_manager()->ChildDeletedSharedBitmap(id);
394 owned_bitmaps_.erase(id);
395 }
396
MaybeSubmitCompositorFrame(const LocalSurfaceId & local_surface_id,CompositorFrame frame,base::Optional<HitTestRegionList> hit_test_region_list,uint64_t submit_time,mojom::CompositorFrameSink::SubmitCompositorFrameSyncCallback callback)397 SubmitResult CompositorFrameSinkSupport::MaybeSubmitCompositorFrame(
398 const LocalSurfaceId& local_surface_id,
399 CompositorFrame frame,
400 base::Optional<HitTestRegionList> hit_test_region_list,
401 uint64_t submit_time,
402 mojom::CompositorFrameSink::SubmitCompositorFrameSyncCallback callback) {
403 TRACE_EVENT_WITH_FLOW2(
404 "viz,benchmark", "Graphics.Pipeline",
405 TRACE_ID_GLOBAL(frame.metadata.begin_frame_ack.trace_id),
406 TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT, "step",
407 "ReceiveCompositorFrame", "FrameSinkId", frame_sink_id_.ToString());
408
409 DCHECK(local_surface_id.is_valid());
410 DCHECK(!frame.render_pass_list.empty());
411 DCHECK(!frame.size_in_pixels().IsEmpty());
412
413 CHECK(callback_received_begin_frame_);
414 CHECK(callback_received_receive_ack_);
415
416 begin_frame_tracker_.ReceivedAck(frame.metadata.begin_frame_ack);
417 ++ack_pending_count_;
418
419 compositor_frame_callback_ = std::move(callback);
420 if (compositor_frame_callback_) {
421 callback_received_begin_frame_ = false;
422 callback_received_receive_ack_ = false;
423 UpdateNeedsBeginFramesInternal();
424 }
425
426 base::TimeTicks now_time = base::TimeTicks::Now();
427 pending_received_frame_times_.emplace(frame.metadata.frame_token, now_time);
428
429 // Override the has_damage flag (ignoring invalid data from clients).
430 frame.metadata.begin_frame_ack.has_damage = true;
431 DCHECK(frame.metadata.begin_frame_ack.frame_id.IsSequenceValid());
432
433 if (!ui::LatencyInfo::Verify(
434 frame.metadata.latency_info,
435 "CompositorFrameSinkSupport::MaybeSubmitCompositorFrame")) {
436 for (auto& info : frame.metadata.latency_info) {
437 info.Terminate();
438 }
439 std::vector<ui::LatencyInfo>().swap(frame.metadata.latency_info);
440 }
441 for (ui::LatencyInfo& latency : frame.metadata.latency_info) {
442 if (latency.latency_components().size() > 0) {
443 latency.AddLatencyNumberWithTimestamp(
444 ui::DISPLAY_COMPOSITOR_RECEIVED_FRAME_COMPONENT, now_time);
445 }
446 }
447
448 base::ScopedClosureRunner frame_rejected_callback(
449 base::BindOnce(&CompositorFrameSinkSupport::DidRejectCompositorFrame,
450 weak_factory_.GetWeakPtr(), frame.metadata.frame_token,
451 frame.resource_list, frame.metadata.latency_info));
452
453 // Ensure no CopyOutputRequests have been submitted if they are banned.
454 if (!allow_copy_output_requests_ && frame.HasCopyOutputRequests()) {
455 TRACE_EVENT_INSTANT0("viz", "CopyOutputRequests not allowed",
456 TRACE_EVENT_SCOPE_THREAD);
457 return SubmitResult::COPY_OUTPUT_REQUESTS_NOT_ALLOWED;
458 }
459
460 // TODO(crbug.com/846739): It should be possible to use
461 // |frame.metadata.frame_token| instead of maintaining a |last_frame_index_|.
462 uint64_t frame_index = ++last_frame_index_;
463
464 if (frame.metadata.preferred_frame_interval)
465 preferred_frame_interval_ = *frame.metadata.preferred_frame_interval;
466 else
467 preferred_frame_interval_ = BeginFrameArgs::MinInterval();
468
469 Surface* prev_surface =
470 surface_manager_->GetSurfaceForId(last_created_surface_id_);
471 Surface* current_surface = nullptr;
472 if (prev_surface &&
473 local_surface_id == last_created_surface_id_.local_surface_id()) {
474 current_surface = prev_surface;
475 } else {
476 TRACE_EVENT_WITH_FLOW2(
477 TRACE_DISABLED_BY_DEFAULT("viz.surface_id_flow"),
478 "LocalSurfaceId.Submission.Flow",
479 TRACE_ID_GLOBAL(local_surface_id.submission_trace_id()),
480 TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT, "step",
481 "ReceiveCompositorFrame", "local_surface_id",
482 local_surface_id.ToString());
483
484 SurfaceId surface_id(frame_sink_id_, local_surface_id);
485 SurfaceInfo surface_info(surface_id, frame.device_scale_factor(),
486 frame.size_in_pixels());
487
488 // LocalSurfaceIds should be monotonically increasing. This ID is used
489 // to determine the freshness of a surface at aggregation time.
490 const LocalSurfaceId& last_created_local_surface_id =
491 last_created_surface_id_.local_surface_id();
492
493 bool child_initiated_synchronization_event =
494 last_created_local_surface_id.is_valid() &&
495 local_surface_id.child_sequence_number() >
496 last_created_local_surface_id.child_sequence_number();
497
498 // Neither sequence numbers of the LocalSurfaceId can decrease and at least
499 // one must increase.
500 bool monotonically_increasing_id =
501 (local_surface_id.parent_sequence_number() >=
502 last_created_local_surface_id.parent_sequence_number() &&
503 local_surface_id.child_sequence_number() >=
504 last_created_local_surface_id.child_sequence_number()) &&
505 (local_surface_id.parent_sequence_number() >
506 last_created_local_surface_id.parent_sequence_number() ||
507 child_initiated_synchronization_event);
508
509 DCHECK(surface_info.is_valid());
510 if (local_surface_id.embed_token() ==
511 last_created_local_surface_id.embed_token() &&
512 !monotonically_increasing_id) {
513 TRACE_EVENT_INSTANT0("viz", "LocalSurfaceId decreased",
514 TRACE_EVENT_SCOPE_THREAD);
515 return SubmitResult::SURFACE_ID_DECREASED;
516 }
517
518 // Don't recreate a surface that was previously evicted. Drop the
519 // CompositorFrame and return all its resources.
520 if (IsEvicted(local_surface_id)) {
521 TRACE_EVENT_INSTANT0("viz", "Submit rejected to evicted surface",
522 TRACE_EVENT_SCOPE_THREAD);
523 return SubmitResult::ACCEPTED;
524 }
525
526 current_surface = surface_manager_->CreateSurface(
527 weak_factory_.GetWeakPtr(), surface_info);
528 if (!current_surface) {
529 TRACE_EVENT_INSTANT0("viz", "Surface belongs to another client",
530 TRACE_EVENT_SCOPE_THREAD);
531 return SubmitResult::SURFACE_OWNED_BY_ANOTHER_CLIENT;
532 }
533 last_created_surface_id_ = SurfaceId(frame_sink_id_, local_surface_id);
534
535 surface_manager_->SurfaceDamageExpected(current_surface->surface_id(),
536 last_begin_frame_args_);
537 }
538
539 const int64_t trace_id = ~frame.metadata.begin_frame_ack.trace_id;
540 TRACE_EVENT_WITH_FLOW1(TRACE_DISABLED_BY_DEFAULT("viz.hit_testing_flow"),
541 "Event.Pipeline", TRACE_ID_GLOBAL(trace_id),
542 TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT,
543 "step", "ReceiveHitTestData");
544
545 // QueueFrame can fail in unit tests, so SubmitHitTestRegionList has to be
546 // called before that.
547 frame_sink_manager()->SubmitHitTestRegionList(
548 last_created_surface_id_, frame_index, std::move(hit_test_region_list));
549
550 Surface::QueueFrameResult result = current_surface->QueueFrame(
551 std::move(frame), frame_index, std::move(frame_rejected_callback));
552 switch (result) {
553 case Surface::QueueFrameResult::REJECTED:
554 TRACE_EVENT_INSTANT0("viz", "QueueFrame failed",
555 TRACE_EVENT_SCOPE_THREAD);
556 return SubmitResult::SIZE_MISMATCH;
557 case Surface::QueueFrameResult::ACCEPTED_PENDING:
558 // Make sure we periodically check if the frame should activate.
559 pending_surfaces_.insert(current_surface);
560 UpdateNeedsBeginFramesInternal();
561 break;
562 case Surface::QueueFrameResult::ACCEPTED_ACTIVE:
563 // Nothing to do here.
564 break;
565 }
566
567 if (begin_frame_source_) {
568 begin_frame_source_->DidFinishFrame(this);
569 frame_sink_manager_->DidFinishFrame(frame_sink_id_, last_begin_frame_args_);
570 }
571
572 return SubmitResult::ACCEPTED;
573 }
574
MakeTopLevelRootReference(const SurfaceId & surface_id)575 SurfaceReference CompositorFrameSinkSupport::MakeTopLevelRootReference(
576 const SurfaceId& surface_id) {
577 return SurfaceReference(surface_manager_->GetRootSurfaceId(), surface_id);
578 }
579
HandleCallback()580 void CompositorFrameSinkSupport::HandleCallback() {
581 if (!compositor_frame_callback_ || !callback_received_begin_frame_ ||
582 !callback_received_receive_ack_) {
583 return;
584 }
585
586 std::move(compositor_frame_callback_)
587 .Run(std::move(surface_returned_resources_));
588 surface_returned_resources_.clear();
589 }
590
DidReceiveCompositorFrameAck()591 void CompositorFrameSinkSupport::DidReceiveCompositorFrameAck() {
592 DCHECK_GT(ack_pending_count_, 0);
593 ack_pending_count_--;
594 if (!client_)
595 return;
596
597 // If we have a callback, we only return the resource on onBeginFrame.
598 if (compositor_frame_callback_) {
599 callback_received_receive_ack_ = true;
600 UpdateNeedsBeginFramesInternal();
601 HandleCallback();
602 return;
603 }
604
605 client_->DidReceiveCompositorFrameAck(surface_returned_resources_);
606 surface_returned_resources_.clear();
607 }
608
DidPresentCompositorFrame(uint32_t frame_token,base::TimeTicks draw_start_timestamp,const gfx::SwapTimings & swap_timings,const gfx::PresentationFeedback & feedback)609 void CompositorFrameSinkSupport::DidPresentCompositorFrame(
610 uint32_t frame_token,
611 base::TimeTicks draw_start_timestamp,
612 const gfx::SwapTimings& swap_timings,
613 const gfx::PresentationFeedback& feedback) {
614 DCHECK(frame_token);
615 DCHECK((feedback.flags & gfx::PresentationFeedback::kFailure) ||
616 (!draw_start_timestamp.is_null() && !swap_timings.is_null()));
617
618 DCHECK_LE(pending_received_frame_times_.size(), 25u);
619 auto received_frame_timestamp =
620 pending_received_frame_times_.find(frame_token);
621 DCHECK(received_frame_timestamp != pending_received_frame_times_.end());
622
623 FrameTimingDetails details;
624 details.received_compositor_frame_timestamp =
625 received_frame_timestamp->second;
626 details.draw_start_timestamp = draw_start_timestamp;
627 details.swap_timings = swap_timings;
628 details.presentation_feedback = feedback;
629 AdjustPresentationFeedback(&details.presentation_feedback,
630 swap_timings.swap_start);
631 pending_received_frame_times_.erase(received_frame_timestamp);
632
633 // We should only ever get one PresentationFeedback per frame_token.
634 DCHECK(frame_timing_details_.find(frame_token) ==
635 frame_timing_details_.end());
636 frame_timing_details_.emplace(frame_token, details);
637
638 UpdateNeedsBeginFramesInternal();
639 }
640
DidRejectCompositorFrame(uint32_t frame_token,std::vector<TransferableResource> frame_resource_list,std::vector<ui::LatencyInfo> latency_info)641 void CompositorFrameSinkSupport::DidRejectCompositorFrame(
642 uint32_t frame_token,
643 std::vector<TransferableResource> frame_resource_list,
644 std::vector<ui::LatencyInfo> latency_info) {
645 TRACE_EVENT_INSTANT0("viz", "DidRejectCompositorFrame",
646 TRACE_EVENT_SCOPE_THREAD);
647 // TODO(eseckler): Should these be stored and attached to the next successful
648 // frame submission instead?
649 for (ui::LatencyInfo& info : latency_info)
650 info.Terminate();
651
652 std::vector<ReturnedResource> resources =
653 TransferableResource::ReturnResources(frame_resource_list);
654 ReturnResources(resources);
655 DidReceiveCompositorFrameAck();
656 DidPresentCompositorFrame(frame_token, base::TimeTicks(), gfx::SwapTimings(),
657 gfx::PresentationFeedback::Failure());
658 }
659
UpdateDisplayRootReference(const Surface * surface)660 void CompositorFrameSinkSupport::UpdateDisplayRootReference(
661 const Surface* surface) {
662 // Make the new SurfaceId reachable from the top-level root.
663 surface_manager_->AddSurfaceReferences(
664 {MakeTopLevelRootReference(surface->surface_id())});
665
666 // Make the old SurfaceId unreachable from the top-level root if applicable.
667 if (referenced_local_surface_id_) {
668 surface_manager_->RemoveSurfaceReferences({MakeTopLevelRootReference(
669 SurfaceId(frame_sink_id_, *referenced_local_surface_id_))});
670 }
671
672 referenced_local_surface_id_ = surface->surface_id().local_surface_id();
673 }
674
OnBeginFrame(const BeginFrameArgs & args)675 void CompositorFrameSinkSupport::OnBeginFrame(const BeginFrameArgs& args) {
676 if (compositor_frame_callback_) {
677 callback_received_begin_frame_ = true;
678 UpdateNeedsBeginFramesInternal();
679 HandleCallback();
680 }
681
682 CheckPendingSurfaces();
683
684 if (client_ && ShouldSendBeginFrame(args.frame_time)) {
685 if (last_activated_surface_id_.is_valid())
686 surface_manager_->SurfaceDamageExpected(last_activated_surface_id_, args);
687 last_begin_frame_args_ = args;
688
689 BeginFrameArgs copy_args = args;
690 // Force full frame if surface not yet activated to ensure surface creation.
691 if (!last_activated_surface_id_.is_valid())
692 copy_args.animate_only = false;
693
694 copy_args.trace_id = ComputeTraceId();
695 TRACE_EVENT_WITH_FLOW1("viz,benchmark", "Graphics.Pipeline",
696 TRACE_ID_GLOBAL(copy_args.trace_id),
697 TRACE_EVENT_FLAG_FLOW_OUT, "step",
698 "IssueBeginFrame");
699 last_frame_time_ = args.frame_time;
700 client_->OnBeginFrame(copy_args, std::move(frame_timing_details_));
701 begin_frame_tracker_.SentBeginFrame(args);
702 frame_sink_manager_->DidBeginFrame(frame_sink_id_, args);
703 frame_timing_details_.clear();
704 UpdateNeedsBeginFramesInternal();
705 }
706 }
707
LastUsedBeginFrameArgs() const708 const BeginFrameArgs& CompositorFrameSinkSupport::LastUsedBeginFrameArgs()
709 const {
710 return last_begin_frame_args_;
711 }
712
OnBeginFrameSourcePausedChanged(bool paused)713 void CompositorFrameSinkSupport::OnBeginFrameSourcePausedChanged(bool paused) {
714 if (client_)
715 client_->OnBeginFramePausedChanged(paused);
716 }
717
UpdateNeedsBeginFramesInternal()718 void CompositorFrameSinkSupport::UpdateNeedsBeginFramesInternal() {
719 if (!begin_frame_source_)
720 return;
721
722 // We require a begin frame if there's a callback pending, or if the client
723 // requested it, or if the client needs to get some frame timing details.
724 bool needs_begin_frame =
725 client_needs_begin_frame_ || !frame_timing_details_.empty() ||
726 !pending_surfaces_.empty() ||
727 (compositor_frame_callback_ && !callback_received_begin_frame_);
728
729 if (needs_begin_frame == added_frame_observer_)
730 return;
731
732 added_frame_observer_ = needs_begin_frame;
733 if (needs_begin_frame)
734 begin_frame_source_->AddObserver(this);
735 else
736 begin_frame_source_->RemoveObserver(this);
737 }
738
AttachCaptureClient(CapturableFrameSink::Client * client)739 void CompositorFrameSinkSupport::AttachCaptureClient(
740 CapturableFrameSink::Client* client) {
741 DCHECK(!base::Contains(capture_clients_, client));
742 capture_clients_.push_back(client);
743 }
744
DetachCaptureClient(CapturableFrameSink::Client * client)745 void CompositorFrameSinkSupport::DetachCaptureClient(
746 CapturableFrameSink::Client* client) {
747 const auto it =
748 std::find(capture_clients_.begin(), capture_clients_.end(), client);
749 if (it != capture_clients_.end())
750 capture_clients_.erase(it);
751 }
752
GetActiveFrameSize()753 gfx::Size CompositorFrameSinkSupport::GetActiveFrameSize() {
754 if (last_activated_surface_id_.is_valid()) {
755 Surface* current_surface =
756 surface_manager_->GetSurfaceForId(last_activated_surface_id_);
757 DCHECK(current_surface);
758 if (current_surface->HasActiveFrame()) {
759 DCHECK(current_surface->GetActiveFrame().size_in_pixels() ==
760 current_surface->size_in_pixels());
761 return current_surface->size_in_pixels();
762 }
763 }
764 return gfx::Size();
765 }
766
RequestCopyOfOutput(const LocalSurfaceId & local_surface_id,std::unique_ptr<CopyOutputRequest> copy_request)767 void CompositorFrameSinkSupport::RequestCopyOfOutput(
768 const LocalSurfaceId& local_surface_id,
769 std::unique_ptr<CopyOutputRequest> copy_request) {
770 copy_output_requests_.push_back(
771 std::make_pair(local_surface_id, std::move(copy_request)));
772 if (last_activated_surface_id_.is_valid()) {
773 BeginFrameAck ack;
774 ack.has_damage = true;
775 surface_manager_->SurfaceModified(last_activated_surface_id_, ack);
776 }
777 }
778
779 const CompositorFrameMetadata*
GetLastActivatedFrameMetadata()780 CompositorFrameSinkSupport::GetLastActivatedFrameMetadata() {
781 if (!last_activated_surface_id_.is_valid())
782 return nullptr;
783 Surface* surface =
784 surface_manager_->GetSurfaceForId(last_activated_surface_id_);
785 DCHECK(surface);
786 return &surface->GetActiveFrame().metadata;
787 }
788
GetHitTestAggregator()789 HitTestAggregator* CompositorFrameSinkSupport::GetHitTestAggregator() {
790 DCHECK(is_root_);
791 return hit_test_aggregator_.get();
792 }
793
GetLastCreatedSurfaceForTesting()794 Surface* CompositorFrameSinkSupport::GetLastCreatedSurfaceForTesting() {
795 return surface_manager_->GetSurfaceForId(last_created_surface_id_);
796 }
797
798 // static
GetSubmitResultAsString(SubmitResult result)799 const char* CompositorFrameSinkSupport::GetSubmitResultAsString(
800 SubmitResult result) {
801 switch (result) {
802 case SubmitResult::ACCEPTED:
803 return "Accepted";
804 case SubmitResult::COPY_OUTPUT_REQUESTS_NOT_ALLOWED:
805 return "CopyOutputRequests not allowed";
806 case SubmitResult::SIZE_MISMATCH:
807 return "CompositorFrame size doesn't match surface size";
808 case SubmitResult::SURFACE_ID_DECREASED:
809 return "LocalSurfaceId sequence numbers decreased";
810 case SubmitResult::SURFACE_OWNED_BY_ANOTHER_CLIENT:
811 return "Surface belongs to another client";
812 }
813 NOTREACHED();
814 return nullptr;
815 }
816
ComputeTraceId()817 int64_t CompositorFrameSinkSupport::ComputeTraceId() {
818 // This is losing some info, but should normally be sufficient to avoid
819 // collisions.
820 ++trace_sequence_;
821 uint64_t client = (frame_sink_id_.client_id() & 0xffff);
822 uint64_t sink = (frame_sink_id_.sink_id() & 0xffff);
823 return (client << 48) | (sink << 32) | trace_sequence_;
824 }
825
ShouldSendBeginFrame(base::TimeTicks frame_time)826 bool CompositorFrameSinkSupport::ShouldSendBeginFrame(
827 base::TimeTicks frame_time) {
828 // We should throttle OnBeginFrame() if it has been less than
829 // |begin_frame_interval_| since the last one was sent because clients have
830 // requested to update at such rate.
831 const bool should_throttle_as_requested =
832 begin_frame_interval_ > base::TimeDelta() &&
833 (frame_time - last_frame_time_) < begin_frame_interval_;
834 // We might throttle this OnBeginFrame() if it's been less than a second since
835 // the last one was sent, either because clients are unresponsive or have
836 // submitted too many undrawn frames.
837 const bool can_throttle_if_unresponsive_or_excessive =
838 frame_time - last_frame_time_ < base::TimeDelta::FromSeconds(1);
839
840 // If there are pending timing details from the previous frame(s),
841 // then the client needs to receive the begin-frame.
842 if (!frame_timing_details_.empty() && !should_throttle_as_requested) {
843 RecordShouldSendBeginFrame("SendFrameTiming");
844 return true;
845 }
846
847 if (!client_needs_begin_frame_) {
848 RecordShouldSendBeginFrame("StopNotRequested");
849 return false;
850 }
851
852 // Stop sending BeginFrames to clients that are totally unresponsive.
853 if (begin_frame_tracker_.ShouldStopBeginFrame()) {
854 RecordShouldSendBeginFrame("StopUnresponsiveClient");
855 return false;
856 }
857
858 // Throttle clients that are unresponsive.
859 if (can_throttle_if_unresponsive_or_excessive &&
860 begin_frame_tracker_.ShouldThrottleBeginFrame()) {
861 RecordShouldSendBeginFrame("ThrottleUnresponsiveClient");
862 return false;
863 }
864
865 if (!last_activated_surface_id_.is_valid()) {
866 RecordShouldSendBeginFrame("SendNoActiveSurface");
867 return true;
868 }
869
870 // We should never throttle BeginFrames if there is another client waiting for
871 // this client to submit a frame.
872 if (surface_manager_->HasBlockedEmbedder(frame_sink_id_)) {
873 RecordShouldSendBeginFrame("SendBlockedEmbedded");
874 return true;
875 }
876
877 if (should_throttle_as_requested) {
878 RecordShouldSendBeginFrame("ThrottleRequested");
879 return false;
880 }
881
882 Surface* surface =
883 surface_manager_->GetSurfaceForId(last_activated_surface_id_);
884
885 DCHECK(surface);
886 DCHECK(surface->HasActiveFrame());
887
888 uint64_t active_frame_index = surface->GetActiveFrameIndex();
889
890 // Since we have an active frame, and frame indexes strictly increase
891 // during the lifetime of the CompositorFrameSinkSupport, our active frame
892 // index must be at least as large as our last drawn frame index.
893 DCHECK_GE(active_frame_index, last_drawn_frame_index_);
894
895 // Throttle clients that have submitted too many undrawn frames.
896 uint64_t num_undrawn_frames = active_frame_index - last_drawn_frame_index_;
897 if (can_throttle_if_unresponsive_or_excessive &&
898 num_undrawn_frames > kUndrawnFrameLimit) {
899 RecordShouldSendBeginFrame("ThrottleUndrawnFrames");
900 return false;
901 }
902
903 // No other conditions apply so send the begin frame.
904 RecordShouldSendBeginFrame("SendDefault");
905 return true;
906 }
907
IsEvicted(const LocalSurfaceId & local_surface_id) const908 bool CompositorFrameSinkSupport::IsEvicted(
909 const LocalSurfaceId& local_surface_id) const {
910 return local_surface_id.embed_token() ==
911 last_evicted_local_surface_id_.embed_token() &&
912 local_surface_id.parent_sequence_number() <=
913 last_evicted_local_surface_id_.parent_sequence_number();
914 }
915
CheckPendingSurfaces()916 void CompositorFrameSinkSupport::CheckPendingSurfaces() {
917 if (pending_surfaces_.empty())
918 return;
919 base::flat_set<Surface*> pending_surfaces(pending_surfaces_);
920 for (Surface* surface : pending_surfaces) {
921 surface->ActivateIfDeadlinePassed();
922 }
923 }
924
925 } // namespace viz
926