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