| // Copyright 2023 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef ASH_FRAME_SINK_FRAME_SINK_HOST_H_ |
| #define ASH_FRAME_SINK_FRAME_SINK_HOST_H_ |
| |
| #include <memory> |
| |
| #include "ash/ash_export.h" |
| #include "ash/frame_sink/ui_resource_manager.h" |
| #include "base/memory/raw_ptr.h" |
| #include "components/viz/common/quads/compositor_frame.h" |
| #include "ui/aura/window.h" |
| #include "ui/aura/window_observer.h" |
| #include "ui/gfx/geometry/rect.h" |
| #include "ui/gfx/presentation_feedback.h" |
| |
| namespace cc { |
| class LayerTreeFrameSink; |
| } // namespace cc |
| |
| namespace ash { |
| |
| class FrameSinkHolder; |
| |
| // Base class for surfaces that render content by creating independent |
| // compositor frames and submitting them directly to display compositor. |
| // |
| // FrameSinkHost encapsulates interactions with the display compositor and |
| // manages relevant resources. Child classes override CreateCompositorFrame() to |
| // control compositor frame creation behavior. |
| // |
| // Note: The host_window must outlive the FrameSinkHost. |
| class ASH_EXPORT FrameSinkHost : public aura::WindowObserver { |
| public: |
| using PresentationCallback = |
| base::RepeatingCallback<void(const gfx::PresentationFeedback&)>; |
| |
| FrameSinkHost(); |
| |
| FrameSinkHost(const FrameSinkHost&) = delete; |
| FrameSinkHost& operator=(const FrameSinkHost&) = delete; |
| |
| ~FrameSinkHost() override; |
| |
| aura::Window* host_window() { return host_window_; } |
| |
| void SetPresentationCallback(PresentationCallback callback); |
| |
| // Initializes the FrameSinkHost on the host_window. |
| virtual void Init(aura::Window* host_window); |
| |
| virtual void InitForTesting( |
| aura::Window* host_window, |
| std::unique_ptr<cc::LayerTreeFrameSink> layer_tree_frame_sink); |
| |
| // Updates the surface by submitting a compositor frame. With |
| // synchronous_draw as true, we send a compositor frame as soon as we call the |
| // UpdateSurface method otherwise we draw asynchronously where we wait till |
| // display_compositor requests for a new frame. |
| // Note: Calling this method turns off the auto updating of the surface if |
| // enabled. |
| void UpdateSurface(const gfx::Rect& content_rect, |
| const gfx::Rect& damage_rect, |
| bool synchronous_draw); |
| |
| // Updates the surface by submitting frames asynchronously. Compared to |
| // `UpdateSurface()`, where we submit a single frame, after calling |
| // this method, we keep submitting frames asynchronously. It should be used if |
| // we expect that there are continuous updates within the content_rect. |
| void AutoUpdateSurface(const gfx::Rect& content_rect, |
| const gfx::Rect& damage_rect); |
| |
| // Overridden from aura::WindowObserver |
| void OnWindowDestroying(aura::Window* window) override; |
| |
| protected: |
| // Creates a compositor frame that can be sent to the display compositor. |
| // `begin_frame_ack` is a token that needs to be attached to the compositor |
| // frame being created. |
| // `resource_manager` helps manage resources that can be attached to the |
| // compositor frame and also give us a pool of reusable resources. |
| // `auto_update` if true means that we are continuously submitting frames |
| // asynchronously and should redraw full surface regardless of damage. |
| // `last_submitted_frame_size` and `last_submitted_frame_dsf` |
| // can be used to determine if a new surface needs to be identified on the |
| // `host_window_`. |
| // Returns nullptr if a compositor frame cannot be created. |
| virtual std::unique_ptr<viz::CompositorFrame> CreateCompositorFrame( |
| const viz::BeginFrameAck& begin_frame_ack, |
| UiResourceManager& resource_manager, |
| bool auto_update, |
| const gfx::Size& last_submitted_frame_size, |
| float last_submitted_frame_dsf) = 0; |
| |
| const gfx::Rect& GetTotalDamage() const { return total_damage_rect_; } |
| |
| void UnionDamage(const gfx::Rect& rect) { total_damage_rect_.Union(rect); } |
| |
| void IntersectDamage(const gfx::Rect& rect) { |
| total_damage_rect_.Intersect(rect); |
| } |
| |
| void ResetDamage() { total_damage_rect_ = gfx::Rect(); } |
| |
| const gfx::Rect& GetContentRect() const { return content_rect_; } |
| |
| private: |
| void InitFrameSinkHolder( |
| aura::Window* host_window, |
| std::unique_ptr<cc::LayerTreeFrameSink> layer_tree_frame_sink); |
| |
| void SetHostWindow(aura::Window* host_window); |
| |
| void InitInternal( |
| aura::Window* host_window, |
| std::unique_ptr<cc::LayerTreeFrameSink> layer_tree_frame_sink); |
| |
| // The window on which LayerTreeFrameSink is created on. |
| base::raw_ptr<aura::Window> host_window_ = nullptr; |
| |
| // The bounds of the content to be displayed in host window coordinates. |
| gfx::Rect content_rect_; |
| |
| // The damage rect in host window coordinates. |
| gfx::Rect total_damage_rect_; |
| |
| // Holds the LayerTreeFrameSink. For proper deletion of in flight |
| // resources, lifetime of the FrameSinkHolder is extended to either the root |
| // window of the`host_window` or till we reclaim all the exported resources |
| // to the display compositor. See `FrameSinkHolder` implementation for |
| // details. https://crbug.com/765763 |
| std::unique_ptr<FrameSinkHolder> frame_sink_holder_; |
| |
| base::WeakPtrFactory<FrameSinkHost> weak_ptr_factory_{this}; |
| }; |
| |
| } // namespace ash |
| |
| #endif // ASH_FRAME_SINK_FRAME_SINK_HOST_H_ |