1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560
|
// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_VIZ_SERVICE_FRAME_SINKS_COMPOSITOR_FRAME_SINK_SUPPORT_H_
#define COMPONENTS_VIZ_SERVICE_FRAME_SINKS_COMPOSITOR_FRAME_SINK_SUPPORT_H_
#include <memory>
#include <optional>
#include <set>
#include <utility>
#include <vector>
#include "base/containers/circular_deque.h"
#include "base/containers/flat_set.h"
#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/read_only_shared_memory_region.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
#include "components/viz/common/frame_sinks/begin_frame_source.h"
#include "components/viz/common/frame_timing_details_map.h"
#include "components/viz/common/quads/compositor_frame.h"
#include "components/viz/common/surfaces/frame_sink_bundle_id.h"
#include "components/viz/common/surfaces/region_capture_bounds.h"
#include "components/viz/common/surfaces/surface_info.h"
#include "components/viz/common/surfaces/surface_range.h"
#include "components/viz/common/surfaces/video_capture_target.h"
#include "components/viz/service/frame_sinks/begin_frame_tracker.h"
#include "components/viz/service/frame_sinks/surface_resource_holder.h"
#include "components/viz/service/frame_sinks/surface_resource_holder_client.h"
#include "components/viz/service/frame_sinks/video_capture/capturable_frame_sink.h"
#include "components/viz/service/hit_test/hit_test_aggregator.h"
#include "components/viz/service/surfaces/frame_index_constants.h"
#include "components/viz/service/surfaces/surface_client.h"
#include "components/viz/service/surfaces/surface_observer.h"
#include "components/viz/service/transitions/surface_animation_manager.h"
#include "components/viz/service/viz_service_export.h"
#include "services/viz/public/mojom/compositing/compositor_frame_sink.mojom.h"
#include "services/viz/public/mojom/compositing/layer_context.mojom.h"
#include "services/viz/public/mojom/hit_test/hit_test_region_list.mojom.h"
namespace viz {
class FrameSinkManagerImpl;
class LatestLocalSurfaceIdLookupDelegate;
class LayerContextImpl;
class Surface;
class SurfaceManager;
// Possible outcomes of MaybeSubmitCompositorFrame().
// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
enum class SubmitResult {
ACCEPTED = 0,
COPY_OUTPUT_REQUESTS_NOT_ALLOWED = 1,
// SURFACE_INVARIANTS_VIOLATION = 2 is deprecated.
SIZE_MISMATCH = 3,
SURFACE_ID_DECREASED = 4,
SURFACE_OWNED_BY_ANOTHER_CLIENT = 5,
// Magic constant used by the histogram macros.
kMaxValue = SURFACE_OWNED_BY_ANOTHER_CLIENT,
};
class VIZ_SERVICE_EXPORT CompositorFrameSinkSupport
: public BeginFrameObserver,
public SurfaceResourceHolderClient,
public SurfaceClient,
public CapturableFrameSink {
public:
using AggregatedDamageCallback =
base::RepeatingCallback<void(const LocalSurfaceId& local_surface_id,
const gfx::Size& frame_size_in_pixels,
const gfx::Rect& damage_rect,
base::TimeTicks expected_display_time)>;
// Determines maximum number of allowed undrawn frames. Once this limit is
// exceeded, we throttle sBeginFrames to 1 per second. Limit must be at least
// 1, as the relative ordering of renderer / browser frame submissions allows
// us to have one outstanding undrawn frame under normal operation.
static constexpr uint32_t kUndrawnFrameLimit = 3;
CompositorFrameSinkSupport(mojom::CompositorFrameSinkClient* client,
FrameSinkManagerImpl* frame_sink_manager,
const FrameSinkId& frame_sink_id,
bool is_root);
CompositorFrameSinkSupport(const CompositorFrameSinkSupport&) = delete;
CompositorFrameSinkSupport& operator=(const CompositorFrameSinkSupport&) =
delete;
~CompositorFrameSinkSupport() override;
const FrameSinkId& frame_sink_id() const { return frame_sink_id_; }
const SurfaceId& last_activated_surface_id() const {
return last_activated_surface_id_;
}
const LocalSurfaceId& last_activated_local_surface_id() const {
return last_activated_surface_id_.local_surface_id();
}
bool is_root() const { return is_root_; }
FrameSinkManagerImpl* frame_sink_manager() { return frame_sink_manager_; }
BeginFrameSource* begin_frame_source() { return begin_frame_source_; }
const FrameTimingDetailsMap& timing_details() {
return frame_timing_details_;
}
bool needs_begin_frame() const { return needs_begin_frame_; }
[[nodiscard]] FrameTimingDetailsMap TakeFrameTimingDetailsMap();
// Viz hit-test setup is only called when |is_root_| is true (except on
// android webview).
void SetUpHitTest(
LatestLocalSurfaceIdLookupDelegate* local_surface_id_lookup_delegate);
// The provided callback will be run every time a surface owned by this object
// or one of its descendents is determined to be damaged at aggregation time.
void SetAggregatedDamageCallbackForTesting(AggregatedDamageCallback callback);
// This allows the FrameSinkManagerImpl to pass a BeginFrameSource to use.
void SetBeginFrameSource(BeginFrameSource* begin_frame_source);
// Sets the ID of the FrameSinkBundle to which this sink should belong. If the
// sink is incompatible with the bundle (i.e. uses a different
// BeginFrameSource than this CompositorFrameSinkSupport) then the sink will
// be removed from the bundle and destroyed asynchronously, disconnecting its
// client.
void SetBundle(const FrameSinkBundleId& bundle_id);
void BindLayerContext(mojom::PendingLayerContext& context,
bool draw_mode_is_gpu);
void SetThreads(bool from_untrusted_client,
std::vector<Thread> unverified_threads);
// Throttles the BeginFrames to send at |interval| if |interval| is greater
// than zero, or clears previously set throttle if zero.
// If |simple_cadence_only| is true, then it will further check if the
// |interval| is a simple cadence and apply only if that is true. Returns true
// if we should throttle, otherwise false.
bool ThrottleBeginFrame(base::TimeDelta interval,
bool simple_cadence_only = false);
void SetLastKnownVsync(base::TimeDelta vsync_interval);
// SurfaceClient implementation.
void OnSurfaceCommitted(Surface* surface) override;
void OnSurfaceActivated(Surface* surface) override;
void OnSurfaceDestroyed(Surface* surface) override;
void OnSurfaceWillDraw(Surface* surface) override;
void RefResources(
const std::vector<TransferableResource>& resources) override;
void UnrefResources(std::vector<ReturnedResource> resources) override;
void ReturnResources(std::vector<ReturnedResource> resources) override;
void ReceiveFromChild(
const std::vector<TransferableResource>& resources) override;
// Takes the CopyOutputRequests that were requested for a surface with at
// most |local_surface_id|.
std::vector<PendingCopyOutputRequest> TakeCopyOutputRequests(
const LocalSurfaceId& local_surface_id) override;
void OnFrameTokenChanged(uint32_t frame_token) override;
void SendCompositorFrameAck() override;
void OnSurfaceAggregatedDamage(
Surface* surface,
const LocalSurfaceId& local_surface_id,
const CompositorFrame& frame,
const gfx::Rect& damage_rect,
base::TimeTicks expected_display_time) override;
void OnSurfacePresented(uint32_t frame_token,
base::TimeTicks draw_start_timestamp,
const gfx::SwapTimings& swap_timings,
const gfx::PresentationFeedback& feedback) override;
bool IsVideoCaptureStarted() override;
std::vector<Thread> GetThreads() override;
// mojom::CompositorFrameSink helpers.
void SetNeedsBeginFrame(bool needs_begin_frame);
void SetWantsAnimateOnlyBeginFrames();
void SetAutoNeedsBeginFrame();
void DidNotProduceFrame(const BeginFrameAck& ack);
virtual void SubmitCompositorFrame(
const LocalSurfaceId& local_surface_id,
CompositorFrame frame,
std::optional<HitTestRegionList> hit_test_region_list,
uint64_t submit_time);
void SubmitCompositorFrame(const LocalSurfaceId& local_surface_id,
CompositorFrame frame) {
SubmitCompositorFrame(local_surface_id, std::move(frame), std::nullopt, 0);
}
void SubmitCompositorFrame(
const LocalSurfaceId& local_surface_id,
CompositorFrame frame,
std::optional<HitTestRegionList> hit_test_region_list) {
SubmitCompositorFrame(local_surface_id, std::move(frame),
std::move(hit_test_region_list), 0);
}
void NotifyNewLocalSurfaceIdExpectedWhilePaused();
// Mark |id| and all surfaces with smaller ids for destruction. Note that |id|
// doesn't have to exist at the time of calling.
void EvictSurface(const LocalSurfaceId& id);
// Attempts to submit a new CompositorFrame to |local_surface_id| and returns
// whether the frame was accepted or the reason why it was rejected. If
// |local_surface_id| hasn't been submitted before then a new Surface will be
// created for it.
//
// This is called by SubmitCompositorFrame(), which DCHECK-fails on a
// non-accepted result. Prefer calling SubmitCompositorFrame() instead of this
// method unless the result value affects what the caller will do next.
SubmitResult MaybeSubmitCompositorFrame(
const LocalSurfaceId& local_surface_id,
CompositorFrame frame,
std::optional<HitTestRegionList> hit_test_region_list,
uint64_t submit_time,
mojom::CompositorFrameSink::SubmitCompositorFrameSyncCallback callback);
// CapturableFrameSink implementation.
const FrameSinkId& GetFrameSinkId() const override;
void AttachCaptureClient(CapturableFrameSink::Client* client) override;
void DetachCaptureClient(CapturableFrameSink::Client* client) override;
std::optional<CapturableFrameSink::RegionProperties>
GetRequestRegionProperties(
const VideoCaptureSubTarget& sub_target) const override;
void OnClientCaptureStarted() override;
void OnClientCaptureStopped() override;
void RequestCopyOfOutput(
PendingCopyOutputRequest pending_copy_output_request) override;
const CompositorFrameMetadata* GetLastActivatedFrameMetadata() override;
HitTestAggregator* GetHitTestAggregator();
// Permits submitted CompositorFrames to contain CopyOutputRequests, for
// special-case testing purposes only.
void set_allow_copy_output_requests_for_testing() {
allow_copy_output_requests_ = true;
}
Surface* GetLastCreatedSurfaceForTesting();
// Maps the |result| from MaybeSubmitCompositorFrame() to a human-readable
// string.
static const char* GetSubmitResultAsString(SubmitResult result);
const std::vector<PendingCopyOutputRequest>&
copy_output_requests_for_testing() const {
return copy_output_requests_;
}
bool IsEvicted(const LocalSurfaceId& local_surface_id) const;
// Clears `copy_output_requests_`. Should be called when the client or service
// is shutting down. The requests demanding an exact `LocalSurfaceid` match
// will be transferred to the corresponding `Surface`s
void ClearAllPendingCopyOutputRequests();
const RegionCaptureBounds& current_capture_bounds() const {
return current_capture_bounds_;
}
void SetExternalReservedResourceDelegate(ReservedResourceDelegate* delegate);
// Subscribes or unsubscribes `layer_context_` to subsequent BeginFrames.
void SetLayerContextWantsBeginFrames(bool wants_begin_frames);
void RegisterSurfaceAnimationManagerNotification(
base::OnceCallback<void()> callback);
private:
friend class AckOnSurfaceActivationWhenInteractiveTest;
friend class CompositorFrameSinkSupportTestBase;
friend class DisplayTest;
friend class FrameSinkManagerTest;
friend class LayerContextImpl;
friend class SurfaceAggregatorWithResourcesTest;
// Creates a surface reference from the top-level root to |surface_id|.
SurfaceReference MakeTopLevelRootReference(const SurfaceId& surface_id);
void ProcessCompositorFrameTransitionDirective(
const CompositorFrameTransitionDirective& directive,
Surface* surface);
void OnSaveTransitionDirectiveProcessed(
const CompositorFrameTransitionDirective& directive);
void DidReceiveCompositorFrameAck();
void DidPresentCompositorFrame(uint32_t frame_token,
base::TimeTicks draw_start_timestamp,
const gfx::SwapTimings& swap_timings,
const gfx::PresentationFeedback& feedback);
void DidRejectCompositorFrame(
uint32_t frame_token,
std::vector<TransferableResource> frame_resource_list,
std::vector<ui::LatencyInfo> latency_info);
// Update the display root reference with |surface|.
void UpdateDisplayRootReference(const Surface* surface);
// BeginFrameObserver implementation.
void OnBeginFrame(const BeginFrameArgs& args) override;
const BeginFrameArgs& LastUsedBeginFrameArgs() const override;
void OnBeginFrameSourcePausedChanged(bool paused) override;
bool WantsAnimateOnlyBeginFrames() const override;
bool IsRoot() const override;
void UpdateNeedsBeginFramesInternal();
void StartObservingBeginFrameSource();
void StopObservingBeginFrameSource();
// For the sync API calls, if we are blocking a client callback, runs it once
// BeginFrame and FrameAck are done.
void HandleCallback();
void MaybeEvictSurfaces();
void EvictLastActiveSurface();
bool ShouldSendBeginFrame(BeginFrameId frame_id,
base::TimeTicks timestamp,
base::TimeDelta vsync_interval);
// Checks if any of the pending surfaces should activate now because their
// deadline has passed. This is called every BeginFrame.
void CheckPendingSurfaces();
// When throttling is requested by a client, a BeginFrame will not be sent
// until the time elapsed has passed the requested throttle interval since the
// last sent BeginFrame. This function returns true if such interval has
// passed and a BeginFrame should be sent.
bool ShouldThrottleBeginFrameAsRequested(base::TimeTicks frame_time,
base::TimeDelta vsync_interval);
// Instructs the FrameSinkManager to destroy our CompositorFrameSinkImpl.
// To avoid reentrancy issues, this should be called from its own task.
void DestroySelf();
// Posts a task to invoke DestroySelf() ASAP.
void ScheduleSelfDestruction();
void UpdateThreadIdsPostVerification(std::vector<Thread> threads,
bool passed_verification);
void ForAllReservedResourceDelegates(
base::FunctionRef<void(ReservedResourceDelegate&)> func);
void DoReturnResources(std::vector<ReturnedResource> resources);
const raw_ptr<mojom::CompositorFrameSinkClient> client_;
const raw_ptr<FrameSinkManagerImpl> frame_sink_manager_;
const raw_ptr<SurfaceManager> surface_manager_;
const FrameSinkId frame_sink_id_;
SurfaceId last_activated_surface_id_;
SurfaceId last_created_surface_id_;
// If this contains a value then a surface reference from the top-level root
// to SurfaceId(frame_sink_id_, referenced_local_surface_id_.value()) was
// added. This will not contain a value if |is_root_| is false.
std::optional<LocalSurfaceId> referenced_local_surface_id_;
SurfaceResourceHolder surface_resource_holder_;
// This has a HitTestAggregator if and only if |is_root_| is true.
std::unique_ptr<HitTestAggregator> hit_test_aggregator_;
struct FrameData {
// True if this frame was submitted from viz itself. This happens during
// root surface eviction when an empty compositor frame is submitted to
// deref existing resources.
bool local_frame;
};
// Keeps track of CompositorFrames that have been submitted and have not
// yet received an ACK from their Surface.
base::circular_deque<FrameData> pending_frames_;
std::vector<ReturnedResource> surface_returned_resources_;
// The begin frame source being observered. Null if none.
raw_ptr<BeginFrameSource> begin_frame_source_ = nullptr;
// The last begin frame args generated by the begin frame source.
BeginFrameArgs last_begin_frame_args_;
// Whether a request for begin frames has been issued.
bool client_needs_begin_frame_ = false;
bool handling_auto_needs_begin_frame_ = false;
// Whether the sink currently needs begin frames for any reason.
bool needs_begin_frame_ = false;
// Whether or not a frame observer has been added.
bool added_frame_observer_ = false;
bool wants_animate_only_begin_frames_ = false;
bool auto_needs_begin_frame_ = false;
// Indicates the FrameSinkBundle to which this sink belongs, if any.
std::optional<FrameSinkBundleId> bundle_id_;
const bool is_root_;
// Device scale factor associated with this CompositorFrameSinkSupport.
// Default value is 1.0.
float device_scale_factor_ = 1.0;
bool is_mobile_optimized_ = false;
// By default, this is equivalent to |is_root_|, but may be overridden for
// testing. Generally, for non-roots, there must not be any CopyOutputRequests
// contained within submitted CompositorFrames. Otherwise, unprivileged
// clients would be able to capture content for which they are not authorized.
bool allow_copy_output_requests_;
// Used for tests only.
AggregatedDamageCallback aggregated_damage_callback_;
uint64_t last_frame_index_ = kFrameIndexStart - 1;
// The video capture clients hooking into this instance to observe frame
// begins and damage, and then make CopyOutputRequests on the appropriate
// frames.
std::vector<raw_ptr<CapturableFrameSink::Client, VectorExperimental>>
capture_clients_;
// These are the CopyOutputRequests made on the frame sink (as opposed to
// being included as a part of a CompositorFrame). They stay here until a
// Surface with a LocalSurfaceId which is at least the stored LocalSurfaceId
// takes them. For example, for a stored PendingCopyOutputRequest, a surface
// with LocalSurfaceId >= PendingCopyOutputRequest::local_surface_id will take
// it, but a surface with LocalSurfaceId <
// PendingCopyOutputRequest::local_surface_id will not. Note that if the
// PendingCopyOutputRequest::local_surface_id is default initialized, then the
// next surface will take it regardless of its LocalSurfaceId.
std::vector<PendingCopyOutputRequest> copy_output_requests_;
mojom::CompositorFrameSink::SubmitCompositorFrameSyncCallback
compositor_frame_callback_;
bool callback_received_begin_frame_ = true;
bool callback_received_receive_ack_ = true;
uint32_t trace_sequence_ = 0;
BeginFrameTracker begin_frame_tracker_;
// Keeps track of the timestamps for a specific frame's submission and
// embedding. Observes the surface if the frame hasn't been embedded yet.
class PendingFrameDetails : SurfaceObserver {
public:
PendingFrameDetails(base::TimeTicks frame_submit_timestamp,
SurfaceManager* surface_manager);
~PendingFrameDetails() override;
// Sets the surface ID and adds/observes the embedded timestamp for the
// surface, to set `frame_embed_timestamp_`.
void set_surface_id(SurfaceId surface_id);
void set_frame_id(BeginFrameId frame_id);
base::TimeTicks frame_submit_timestamp() const {
return frame_submit_timestamp_;
}
base::TimeTicks frame_embed_timestamp() const {
return frame_embed_timestamp_;
}
BeginFrameId frame_id() const { return frame_id_; }
private:
void OnAddedSurfaceReference(const SurfaceId& parent_id,
const SurfaceId& child_id) override;
// Either sets `frame_embed_timestamp_` to the time the surface with ID
// `surface_id_` is embedded (if it's embedded already), or starts
// observing `OnAddedSurfaceReference()` to watch and set the timestamp
// for when that surface gets embedded later.
void SetOrObserveFrameEmbedTimeStamp();
const base::TimeTicks frame_submit_timestamp_;
base::TimeTicks frame_embed_timestamp_;
// The surface ID that is associated with the frame.
SurfaceId surface_id_;
const raw_ptr<SurfaceManager> surface_manager_;
// This frame id maps to BeginFrameId during compositor frame submission in
// order to preserve frame submission info across atypical rendering flows.
// Values will be propagated through presentation promise feedback to
// renderer main thread, and being useful there as an indicator for
// unreliable presentation time.
BeginFrameId frame_id_;
};
// Maps |frame_token| to the timestamps when that frame was received and
// embedded. These timestamps will be combined with the information received
// in OnSurfacePresented() and stored in |frame_timing_details_|.
base::flat_map<uint32_t, std::unique_ptr<PendingFrameDetails>>
pending_received_frame_times_;
FrameTimingDetailsMap frame_timing_details_;
LocalSurfaceId last_evicted_local_surface_id_;
base::TimeTicks last_frame_time_;
// Initialize |last_drawn_frame_index_| as though the frame before the first
// has been drawn.
static_assert(kFrameIndexStart > 1,
"|last_drawn_frame_index| relies on kFrameIndexStart > 1");
uint64_t last_drawn_frame_index_ = kFrameIndexStart - 1;
// This value represents throttling on sending a BeginFrame. If non-zero, it
// represents the duration of time in between sending two consecutive frames.
// If zero, no throttling would be applied.
base::TimeDelta begin_frame_interval_;
base::TimeDelta last_known_vsync_interval_;
// The set of surfaces owned by this frame sink that have pending frame.
base::flat_set<raw_ptr<Surface, CtnExperimental>> pending_surfaces_;
// This is the last known frame interval for this sink used to decide
// when to throttle begin frames.
base::TimeDelta last_known_frame_interval_ = BeginFrameArgs::MinInterval();
base::flat_map<blink::ViewTransitionToken,
std::unique_ptr<SurfaceAnimationManager>>
view_transition_token_to_animation_manager_;
// This is used for any viz side resources that are managed by viz. These
// resources must use the reserved resource range defined by
// `kVizReservedRangeStartId`.
raw_ptr<ReservedResourceDelegate> external_reserved_resource_delegate_ =
nullptr;
std::vector<Thread> threads_;
// Number of frames skipped during throttling since last BeginFrame sent.
uint64_t frames_throttled_since_last_ = 0;
// Number of clients that have started video capturing.
uint32_t number_clients_capturing_ = 0;
// Region capture bounds associated with the last surface that was aggregated.
RegionCaptureBounds current_capture_bounds_;
// When TreesInViz is enabled, this owns the display tree and forwards its
// submitted compositor frames directly to `this`.
std::unique_ptr<LayerContextImpl> layer_context_;
bool layer_context_wants_begin_frames_ = false;
// If exists, then we need to notify this callback when we have a
// SurfaceAnimationManager.
base::OnceCallback<void()> surface_animation_manager_callback_;
base::WeakPtrFactory<CompositorFrameSinkSupport> weak_factory_{this};
};
} // namespace viz
#endif // COMPONENTS_VIZ_SERVICE_FRAME_SINKS_COMPOSITOR_FRAME_SINK_SUPPORT_H_
|