| // Copyright 2017 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef COMPONENTS_VIZ_HOST_HOST_FRAME_SINK_MANAGER_H_ |
| #define COMPONENTS_VIZ_HOST_HOST_FRAME_SINK_MANAGER_H_ |
| |
| #include <memory> |
| #include <string> |
| #include <unordered_map> |
| #include <vector> |
| |
| #include "base/compiler_specific.h" |
| #include "base/containers/flat_map.h" |
| #include "base/macros.h" |
| #include "base/memory/ref_counted.h" |
| #include "base/memory/weak_ptr.h" |
| #include "base/observer_list.h" |
| #include "base/optional.h" |
| #include "components/viz/common/surfaces/frame_sink_id.h" |
| #include "components/viz/host/client_frame_sink_video_capturer.h" |
| #include "components/viz/host/hit_test/hit_test_query.h" |
| #include "components/viz/host/hit_test/hit_test_region_observer.h" |
| #include "components/viz/host/host_frame_sink_client.h" |
| #include "components/viz/host/viz_host_export.h" |
| #include "components/viz/service/frame_sinks/compositor_frame_sink_support_manager.h" |
| #include "mojo/public/cpp/bindings/binding.h" |
| #include "services/viz/privileged/interfaces/compositing/frame_sink_manager.mojom.h" |
| |
| namespace base { |
| class SingleThreadTaskRunner; |
| } |
| |
| namespace viz { |
| |
| class CompositorFrameSinkSupport; |
| class FrameSinkManagerImpl; |
| class SurfaceInfo; |
| |
| enum class ReportFirstSurfaceActivation { kYes, kNo }; |
| |
| // Browser side wrapper of mojom::FrameSinkManager, to be used from the |
| // UI thread. Manages frame sinks and is intended to replace all usage of |
| // FrameSinkManagerImpl. |
| class VIZ_HOST_EXPORT HostFrameSinkManager |
| : public mojom::FrameSinkManagerClient, |
| public CompositorFrameSinkSupportManager { |
| public: |
| using DisplayHitTestQueryMap = |
| base::flat_map<FrameSinkId, std::unique_ptr<HitTestQuery>>; |
| |
| HostFrameSinkManager(); |
| ~HostFrameSinkManager() override; |
| |
| const DisplayHitTestQueryMap& display_hit_test_query() const { |
| return display_hit_test_query_; |
| } |
| |
| // Sets a local FrameSinkManagerImpl instance and connects directly to it. |
| void SetLocalManager(FrameSinkManagerImpl* frame_sink_manager_impl); |
| |
| // Binds |this| as a FrameSinkManagerClient for |request| on |task_runner|. On |
| // Mac |task_runner| will be the resize helper task runner. May only be called |
| // once. If |task_runner| is null, it uses the default mojo task runner for |
| // the thread this call is made on. |
| void BindAndSetManager( |
| mojom::FrameSinkManagerClientRequest request, |
| scoped_refptr<base::SingleThreadTaskRunner> task_runner, |
| mojom::FrameSinkManagerPtr ptr); |
| |
| // Sets a callback to be notified when the connection to the FrameSinkManager |
| // on |frame_sink_manager_ptr_| is lost. |
| void SetConnectionLostCallback(base::RepeatingClosure callback); |
| |
| // Sets a callback to be notified after Viz sent bad message to Viz host. |
| void SetBadMessageReceivedFromGpuCallback(base::RepeatingClosure callback); |
| |
| // Registers |frame_sink_id| so that a client can submit CompositorFrames |
| // using it. This must be called before creating a CompositorFrameSink or |
| // registering FrameSinkId hierarchy. |
| // |
| // When the client is done submitting CompositorFrames to |frame_sink_id| then |
| // InvalidateFrameSink() should be called. |
| void RegisterFrameSinkId(const FrameSinkId& frame_sink_id, |
| HostFrameSinkClient* client, |
| ReportFirstSurfaceActivation report_activation); |
| |
| // Returns true if RegisterFrameSinkId() was called with |frame_sink_id| and |
| // InvalidateFrameSinkId() has not been called. |
| bool IsFrameSinkIdRegistered(const FrameSinkId& frame_sink_id) const; |
| |
| // Invalidates |frame_sink_id| when the client is done submitting |
| // CompositorFrames. If there is a CompositorFrameSink for |frame_sink_id| |
| // then it will be destroyed and the message pipe to the client will be |
| // closed. |
| // |
| // It's expected, but not enforced, that RegisterFrameSinkId() will never be |
| // called for |frame_sink_id| again. This is to avoid problems with re-entrant |
| // code. If the same client wants to submit CompositorFrames later a new |
| // FrameSinkId should be allocated. |
| void InvalidateFrameSinkId(const FrameSinkId& frame_sink_id); |
| |
| // Tells FrameSinkManger to report when a synchronization event completes via |
| // tracing and UMA and the duration of that event. A synchronization event |
| // occurs when a CompositorFrame submitted to the CompositorFrameSink |
| // specified by |frame_sink_id| activates after having been blocked by |
| // unresolved dependencies. |
| void EnableSynchronizationReporting(const FrameSinkId& frame_sink_id, |
| const std::string& reporting_label); |
| |
| // |debug_label| is used when printing out the surface hierarchy so we know |
| // which clients are contributing which surfaces. |
| void SetFrameSinkDebugLabel(const FrameSinkId& frame_sink_id, |
| const std::string& debug_label); |
| |
| // Creates a connection from a display root to viz. Provides the same |
| // interfaces as CreateCompositorFramesink() plus the priviledged |
| // DisplayPrivate and (if requested) ExternalBeginFrameController interfaces. |
| // When no longer needed, call InvalidateFrameSinkId(). |
| // |
| // If there is already a CompositorFrameSink for |frame_sink_id| then calling |
| // this will destroy the existing CompositorFrameSink and create a new one. |
| void CreateRootCompositorFrameSink( |
| mojom::RootCompositorFrameSinkParamsPtr params); |
| |
| // Creates a connection from a client to viz, using |request| and |client|, |
| // that allows the client to submit CompositorFrames. When no longer needed, |
| // call InvalidateFrameSinkId(). |
| // |
| // If there is already a CompositorFrameSink for |frame_sink_id| then calling |
| // this will destroy the existing CompositorFrameSink and create a new one. |
| void CreateCompositorFrameSink(const FrameSinkId& frame_sink_id, |
| mojom::CompositorFrameSinkRequest request, |
| mojom::CompositorFrameSinkClientPtr client); |
| |
| // Registers FrameSink hierarchy. It's expected that the parent will embed |
| // the child. If |parent_frame_sink_id| is registered then it will be added as |
| // a parent of |child_frame_sink_id| and the function will return true. If |
| // |parent_frame_sink_id| is not registered then the function will return |
| // false. A frame sink can have multiple parents. |
| bool RegisterFrameSinkHierarchy(const FrameSinkId& parent_frame_sink_id, |
| const FrameSinkId& child_frame_sink_id); |
| |
| // Unregisters FrameSink hierarchy. Client must have registered frame sink |
| // hierarchy before unregistering. |
| void UnregisterFrameSinkHierarchy(const FrameSinkId& parent_frame_sink_id, |
| const FrameSinkId& child_frame_sink_id); |
| |
| // Returns true if RegisterFrameSinkHierarchy() was called with the supplied |
| // arguments. |
| bool IsFrameSinkHierarchyRegistered( |
| const FrameSinkId& parent_frame_sink_id, |
| const FrameSinkId& child_frame_sink_id) const; |
| |
| // Returns the first ancestor of |start| (including |start|) that is a root. |
| base::Optional<FrameSinkId> FindRootFrameSinkId( |
| const FrameSinkId& start) const; |
| |
| // Asks viz to send updates regarding video activity to |observer|. |
| void AddVideoDetectorObserver(mojom::VideoDetectorObserverPtr observer); |
| |
| // Creates a FrameSinkVideoCapturer instance in viz. |
| void CreateVideoCapturer(mojom::FrameSinkVideoCapturerRequest request); |
| |
| // Creates a FrameSinkVideoCapturer instance in viz and returns a |
| // ClientFrameSinkVideoCapturer that's connected to it. Clients should prefer |
| // this version because ClientFrameSinkVideoCapturer is resilient to viz |
| // crashes. |
| std::unique_ptr<ClientFrameSinkVideoCapturer> CreateVideoCapturer(); |
| |
| // Marks the given SurfaceIds for destruction. |
| void EvictSurfaces(const std::vector<SurfaceId>& surface_ids); |
| |
| // Takes snapshot of a |surface_id| or a newer surface with the same |
| // FrameSinkId. The FrameSinkId is used to identify which frame we're |
| // interested in. The snapshot will only be taken if the LocalSurfaceId is at |
| // least the given LocalSurfaceId (|surface_id.local_frame_id()|). If the |
| // LocalSurfaceId is lower than the given id, then the request is queued up to |
| // be executed later. |
| void RequestCopyOfOutput(const SurfaceId& surface_id, |
| std::unique_ptr<CopyOutputRequest> request); |
| |
| // Add/Remove an observer to receive notifications of when the host receives |
| // new hit test data. |
| void AddHitTestRegionObserver(HitTestRegionObserver* observer); |
| void RemoveHitTestRegionObserver(HitTestRegionObserver* observer); |
| |
| // CompositorFrameSinkSupportManager: |
| std::unique_ptr<CompositorFrameSinkSupport> CreateCompositorFrameSinkSupport( |
| mojom::CompositorFrameSinkClient* client, |
| const FrameSinkId& frame_sink_id, |
| bool is_root, |
| bool needs_sync_points) override; |
| |
| void OnFrameTokenChanged(const FrameSinkId& frame_sink_id, |
| uint32_t frame_token) override; |
| |
| void SetHitTestAsyncQueriedDebugRegions( |
| const FrameSinkId& root_frame_sink_id, |
| const std::vector<FrameSinkId>& hit_test_async_queried_debug_queue); |
| |
| private: |
| friend class HostFrameSinkManagerTestApi; |
| friend class HostFrameSinkManagerTestBase; |
| |
| struct FrameSinkData { |
| FrameSinkData(); |
| FrameSinkData(FrameSinkData&& other); |
| ~FrameSinkData(); |
| FrameSinkData& operator=(FrameSinkData&& other); |
| |
| bool IsFrameSinkRegistered() const { return client != nullptr; } |
| |
| // Returns true if there is nothing in FrameSinkData and it can be deleted. |
| bool IsEmpty() const { |
| return !IsFrameSinkRegistered() && !has_created_compositor_frame_sink && |
| parents.empty() && children.empty(); |
| } |
| |
| // The client to be notified of changes to this FrameSink. |
| HostFrameSinkClient* client = nullptr; |
| |
| // Indicates whether or not this client cares to receive |
| // FirstSurfaceActivation notifications. |
| ReportFirstSurfaceActivation report_activation = |
| ReportFirstSurfaceActivation::kYes; |
| |
| // The label to use whether this client would like reporting for |
| // synchronization events. |
| std::string synchronization_reporting_label; |
| |
| // The name of the HostFrameSinkClient used for debug purposes. |
| std::string debug_label; |
| |
| // If the frame sink is a root that corresponds to a Display. |
| bool is_root = false; |
| |
| // If a mojom::CompositorFrameSink was created for this FrameSinkId. This |
| // will always be false if not using Mojo. |
| bool has_created_compositor_frame_sink = false; |
| |
| // Track frame sink hierarchy in both directions. |
| std::vector<FrameSinkId> parents; |
| std::vector<FrameSinkId> children; |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(FrameSinkData); |
| }; |
| |
| // Handles connection loss to |frame_sink_manager_ptr_|. This should only |
| // happen when the GPU process crashes. |
| void OnConnectionLost(); |
| |
| // Registers FrameSinkId and FrameSink hierarchy again after connection loss. |
| void RegisterAfterConnectionLoss(); |
| |
| // mojom::FrameSinkManagerClient: |
| void OnFirstSurfaceActivation(const SurfaceInfo& surface_info) override; |
| void OnAggregatedHitTestRegionListUpdated( |
| const FrameSinkId& frame_sink_id, |
| const std::vector<AggregatedHitTestRegion>& hit_test_data) override; |
| |
| // This will point to |frame_sink_manager_ptr_| if using Mojo or |
| // |frame_sink_manager_impl_| if directly connected. Use this to make function |
| // calls. |
| mojom::FrameSinkManager* frame_sink_manager_ = nullptr; |
| |
| // Mojo connection to the FrameSinkManager. If this is bound then |
| // |frame_sink_manager_impl_| must be null. |
| mojom::FrameSinkManagerPtr frame_sink_manager_ptr_; |
| |
| // Mojo connection back from the FrameSinkManager. |
| mojo::Binding<mojom::FrameSinkManagerClient> binding_; |
| |
| // A direct connection to FrameSinkManagerImpl. If this is set then |
| // |frame_sink_manager_ptr_| must be unbound. For use in browser process only, |
| // viz process should not set this. |
| FrameSinkManagerImpl* frame_sink_manager_impl_ = nullptr; |
| |
| // Per CompositorFrameSink data. |
| std::unordered_map<FrameSinkId, FrameSinkData, FrameSinkIdHash> |
| frame_sink_data_map_; |
| |
| // If |frame_sink_manager_ptr_| connection was lost. |
| bool connection_was_lost_ = false; |
| |
| base::RepeatingClosure connection_lost_callback_; |
| |
| base::RepeatingClosure bad_message_received_from_gpu_callback_; |
| |
| DisplayHitTestQueryMap display_hit_test_query_; |
| |
| // TODO(jonross): Separate out all hit testing work into its own separate |
| // class. |
| base::ObserverList<HitTestRegionObserver>::Unchecked observers_; |
| |
| base::WeakPtrFactory<HostFrameSinkManager> weak_ptr_factory_; |
| |
| DISALLOW_COPY_AND_ASSIGN(HostFrameSinkManager); |
| }; |
| |
| } // namespace viz |
| |
| #endif // COMPONENTS_VIZ_HOST_HOST_FRAME_SINK_MANAGER_H_ |