| // 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_EXO_LAYER_TREE_FRAME_SINK_HOLDER_H_ |
| #define COMPONENTS_EXO_LAYER_TREE_FRAME_SINK_HOLDER_H_ |
| |
| #include <memory> |
| #include <optional> |
| |
| #include "base/containers/queue.h" |
| #include "base/feature_list.h" |
| #include "base/memory/raw_ptr.h" |
| #include "base/timer/timer.h" |
| #include "cc/trees/layer_tree_frame_sink_client.h" |
| #include "components/exo/frame_sink_resource_manager.h" |
| #include "components/exo/frame_timing_history.h" |
| #include "components/exo/wm_helper.h" |
| #include "components/viz/common/frame_sinks/begin_frame_source.h" |
| #include "components/viz/common/quads/compositor_frame.h" |
| |
| namespace viz { |
| struct FrameTimingDetails; |
| } |
| |
| namespace cc::mojo_embedder { |
| class AsyncLayerTreeFrameSink; |
| } |
| |
| namespace exo { |
| |
| class SurfaceTreeHost; |
| |
| // When this feature is disabled (by default at the moment), frames are |
| // submitted to the remote side as soon as they arrive, disregarding BeginFrame |
| // requests. |
| // |
| // TODO(yzshen): Remove this flag and always submit according to BeginFrame |
| // requests. crbug.com/1408614 |
| BASE_DECLARE_FEATURE(kExoReactiveFrameSubmission); |
| |
| // This class talks to CompositorFrameSink and keeps track of references to |
| // the contents of Buffers. |
| class LayerTreeFrameSinkHolder : public cc::LayerTreeFrameSinkClient, |
| public WMHelper::LifetimeManager::Observer, |
| public viz::BeginFrameObserverBase { |
| public: |
| LayerTreeFrameSinkHolder( |
| SurfaceTreeHost* surface_tree_host, |
| std::unique_ptr<cc::mojo_embedder::AsyncLayerTreeFrameSink> frame_sink); |
| |
| LayerTreeFrameSinkHolder(const LayerTreeFrameSinkHolder&) = delete; |
| LayerTreeFrameSinkHolder& operator=(const LayerTreeFrameSinkHolder&) = delete; |
| |
| ~LayerTreeFrameSinkHolder() override; |
| |
| // Delete frame sink after having reclaimed and called all resource |
| // release callbacks. |
| // TODO(reveman): Find a better way to handle deletion of in-flight resources. |
| // crbug.com/765763 |
| static void DeleteWhenLastResourceHasBeenReclaimed( |
| std::unique_ptr<LayerTreeFrameSinkHolder> holder); |
| |
| // If a frame is submitted "now" (meaning before returning to event loop) |
| // via SubmitCompositorFrame(), whether it needs full damage. |
| bool NeedsFullDamageForNextFrame() const { return cached_frame_.has_value(); } |
| void SubmitCompositorFrame(viz::CompositorFrame frame, |
| bool submit_now = false); |
| void SetLocalSurfaceId(const viz::LocalSurfaceId& local_surface_id); |
| |
| // Properties of the `frame` from the last `SubmitCompositorFrame()` call, |
| // either from `cached_frame_`, or `frame_sink_`. |
| float LastDeviceScaleFactor() const; |
| const gfx::Size& LastSizeInPixels() const; |
| |
| // Returns true if owned LayerTreeFrameSink has been lost. |
| bool is_lost() const { return is_lost_; } |
| |
| FrameSinkResourceManager* resource_manager() { return &resource_manager_; } |
| |
| // Overridden from cc::LayerTreeFrameSinkClient: |
| void SetBeginFrameSource(viz::BeginFrameSource* source) override; |
| std::optional<viz::HitTestRegionList> BuildHitTestData() override; |
| void ReclaimResources(std::vector<viz::ReturnedResource> resources) override; |
| void SetTreeActivationCallback(base::RepeatingClosure callback) override {} |
| void DidReceiveCompositorFrameAck() override; |
| void DidPresentCompositorFrame( |
| uint32_t frame_token, |
| const viz::FrameTimingDetails& details) override; |
| void DidLoseLayerTreeFrameSink() override; |
| void OnDraw(const gfx::Transform& transform, |
| const gfx::Rect& viewport, |
| bool resourceless_software_draw, |
| bool skip_draw) override {} |
| void SetMemoryPolicy(const cc::ManagedMemoryPolicy& policy) override {} |
| void SetExternalTilePriorityConstraints( |
| const gfx::Rect& viewport_rect, |
| const gfx::Transform& transform) override {} |
| |
| void ClearPendingBeginFramesForTesting(); |
| |
| private: |
| struct PendingBeginFrame { |
| viz::BeginFrameAck begin_frame_ack; |
| base::TimeTicks send_deadline_estimate; |
| }; |
| |
| void ScheduleDelete(); |
| |
| // WMHelper::LifetimeManager::Observer: |
| void OnDestroyed() override; |
| |
| // viz::BeginFrameObserverBase: |
| bool OnBeginFrameDerivedImpl(const viz::BeginFrameArgs& args) override; |
| void OnBeginFrameSourcePausedChanged(bool paused) override; |
| |
| void SubmitCompositorFrameToRemote(viz::CompositorFrame* frame); |
| |
| // Discards `cached_frame_`, reclaims resources and returns failure |
| // presentation feedback. |
| void DiscardCachedFrame(const viz::CompositorFrame* new_frame); |
| void SendDiscardedFrameNotifications(uint32_t frame_token); |
| |
| void StopProcessingPendingFrames(); |
| |
| void OnSendDeadlineExpired(bool update_timer); |
| |
| // Starts timer based on estimated deadline of the first pending BeginFrame |
| // request; or stops timer if there is no pending BeginFrame request. |
| void UpdateSubmitFrameTimer(); |
| |
| void ProcessFirstPendingBeginFrame(viz::CompositorFrame* frame); |
| |
| bool ShouldSubmitFrameNow() const; |
| |
| void ObserveBeginFrameSource(bool start); |
| |
| // Returns true if the feature AutoNeedsBeginFrame is enabled, and currently |
| // we are not receiving BeginFrame requests. In this case, it is allowed to |
| // submit an unsolicited frame. |
| bool UnsolicitedFrameAllowed() const; |
| |
| raw_ptr<SurfaceTreeHost> surface_tree_host_; |
| std::unique_ptr<cc::mojo_embedder::AsyncLayerTreeFrameSink> frame_sink_; |
| |
| FrameSinkResourceManager resource_manager_; |
| |
| std::vector<viz::ResourceId> last_frame_resources_; |
| |
| std::optional<viz::CompositorFrame> cached_frame_; |
| |
| // Resources that are submitted and still in use by the remote side. |
| std::set<viz::ResourceId> in_use_resources_; |
| |
| bool is_lost_ = false; |
| bool delete_pending_ = false; |
| |
| raw_ptr<WMHelper::LifetimeManager> lifetime_manager_ = nullptr; |
| |
| raw_ptr<viz::BeginFrameSource> begin_frame_source_ = nullptr; |
| bool observing_begin_frame_source_ = false; |
| |
| base::queue<PendingBeginFrame> pending_begin_frames_; |
| |
| // The number of frames submitted to the remote side for which acks haven't |
| // been received. |
| int pending_submit_frames_ = 0; |
| |
| // A queue of discarded frame tokens for which acks and presentation feedbacks |
| // haven't been sent to `surface_tree_host_`. |
| base::queue<uint32_t> pending_discarded_frame_notifications_; |
| |
| base::DeadlineTimer submit_frame_timer_; |
| |
| const bool reactive_frame_submission_ = false; |
| |
| // Set if `reactive_frame_submission_` is enabled. |
| std::optional<FrameTimingHistory> frame_timing_history_; |
| }; |
| |
| } // namespace exo |
| |
| #endif // COMPONENTS_EXO_LAYER_TREE_FRAME_SINK_HOLDER_H_ |