| // Copyright 2016 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_SERVICE_FRAME_SINKS_COMPOSITOR_FRAME_SINK_SUPPORT_H_ |
| #define COMPONENTS_VIZ_SERVICE_FRAME_SINKS_COMPOSITOR_FRAME_SINK_SUPPORT_H_ |
| |
| #include <memory> |
| #include <vector> |
| |
| #include "base/callback.h" |
| #include "base/compiler_specific.h" |
| #include "base/memory/weak_ptr.h" |
| #include "components/viz/common/frame_sinks/begin_frame_source.h" |
| #include "components/viz/common/quads/compositor_frame.h" |
| #include "components/viz/common/surfaces/surface_info.h" |
| #include "components/viz/service/frame_sinks/referenced_surface_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/surface_client.h" |
| #include "components/viz/service/viz_service_export.h" |
| #include "services/viz/public/interfaces/compositing/compositor_frame_sink.mojom.h" |
| #include "services/viz/public/interfaces/hit_test/hit_test_region_list.mojom.h" |
| |
| namespace viz { |
| |
| class FrameSinkManagerImpl; |
| class Surface; |
| class SurfaceManager; |
| |
| class VIZ_SERVICE_EXPORT CompositorFrameSinkSupport |
| : public BeginFrameObserver, |
| public SurfaceResourceHolderClient, |
| public SurfaceClient, |
| public CapturableFrameSink, |
| public mojom::CompositorFrameSink { |
| public: |
| // Possible outcomes of MaybeSubmitCompositorFrame(). |
| enum SubmitResult { |
| ACCEPTED, |
| COPY_OUTPUT_REQUESTS_NOT_ALLOWED, |
| SURFACE_INVARIANTS_VIOLATION, |
| }; |
| |
| using AggregatedDamageCallback = |
| base::RepeatingCallback<void(const LocalSurfaceId& local_surface_id, |
| const gfx::Rect& damage_rect)>; |
| |
| static const uint64_t kFrameIndexStart = 2; |
| |
| CompositorFrameSinkSupport(mojom::CompositorFrameSinkClient* client, |
| FrameSinkManagerImpl* frame_sink_manager, |
| const FrameSinkId& frame_sink_id, |
| bool is_root, |
| bool needs_sync_tokens); |
| ~CompositorFrameSinkSupport() override; |
| |
| const FrameSinkId& frame_sink_id() const { return frame_sink_id_; } |
| |
| const SurfaceId& current_surface_id() const { return current_surface_id_; } |
| |
| const LocalSurfaceId& local_surface_id() const { |
| return current_surface_id_.local_surface_id(); |
| } |
| |
| FrameSinkManagerImpl* frame_sink_manager() { return frame_sink_manager_; } |
| |
| // Viz hit-test setup is only called when |is_root_| is true (except on |
| // android webview). |
| void SetUpHitTest(); |
| |
| // 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); |
| |
| // Sets callback called on destruction. |
| void SetDestructionCallback(base::OnceClosure callback); |
| |
| // This allows the FrameSinkManagerImpl to pass a BeginFrameSource to use. |
| void SetBeginFrameSource(BeginFrameSource* begin_frame_source); |
| |
| // SurfaceClient implementation. |
| void OnSurfaceActivated(Surface* surface) override; |
| void RefResources( |
| const std::vector<TransferableResource>& resources) override; |
| void UnrefResources(const std::vector<ReturnedResource>& resources) override; |
| void ReturnResources(const std::vector<ReturnedResource>& resources) override; |
| void ReceiveFromChild( |
| const std::vector<TransferableResource>& resources) override; |
| |
| // mojom::CompositorFrameSink implementation. |
| void SetNeedsBeginFrame(bool needs_begin_frame) override; |
| void SetWantsAnimateOnlyBeginFrames() override; |
| void DidNotProduceFrame(const BeginFrameAck& ack) override; |
| void SubmitCompositorFrame( |
| const LocalSurfaceId& local_surface_id, |
| CompositorFrame frame, |
| mojom::HitTestRegionListPtr hit_test_region_list = nullptr, |
| uint64_t submit_time = 0) override; |
| |
| void EvictCurrentSurface(); |
| |
| // 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, |
| mojom::HitTestRegionListPtr hit_test_region_list); |
| |
| // CapturableFrameSink implementation. |
| void AttachCaptureClient(CapturableFrameSink::Client* client) override; |
| void DetachCaptureClient(CapturableFrameSink::Client* client) override; |
| gfx::Size GetActiveFrameSize() override; |
| void RequestCopyOfSurface( |
| std::unique_ptr<CopyOutputRequest> request) 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* GetCurrentSurfaceForTesting(); |
| |
| // Maps the |result| from MaybeSubmitCompositorFrame() to a human-readable |
| // string. |
| static const char* GetSubmitResultAsString(SubmitResult result); |
| |
| private: |
| friend class FrameSinkManagerTest; |
| |
| // Updates surface references using |active_referenced_surfaces| from the most |
| // recent CompositorFrame. This will add and remove top-level root references |
| // if |is_root_| is true and |local_surface_id| has changed. Modifies surface |
| // references stored in SurfaceManager. |
| void UpdateSurfaceReferences( |
| const LocalSurfaceId& local_surface_id, |
| const std::vector<SurfaceId>& active_referenced_surfaces); |
| |
| // Creates a surface reference from the top-level root to |surface_id|. |
| SurfaceReference MakeTopLevelRootReference(const SurfaceId& surface_id); |
| |
| void DidReceiveCompositorFrameAck(); |
| void DidPresentCompositorFrame(uint32_t presentation_token, |
| base::TimeTicks time, |
| base::TimeDelta refresh, |
| uint32_t flags); |
| |
| // BeginFrameObserver implementation. |
| void OnBeginFrame(const BeginFrameArgs& args) override; |
| const BeginFrameArgs& LastUsedBeginFrameArgs() const override; |
| void OnBeginFrameSourcePausedChanged(bool paused) override; |
| bool WantsAnimateOnlyBeginFrames() const override; |
| |
| void UpdateNeedsBeginFramesInternal(); |
| Surface* CreateSurface(const SurfaceInfo& surface_info); |
| |
| void OnAggregatedDamage(const LocalSurfaceId& local_surface_id, |
| const gfx::Rect& damage_rect, |
| const CompositorFrame& frame) const; |
| |
| mojom::CompositorFrameSinkClient* const client_; |
| |
| FrameSinkManagerImpl* const frame_sink_manager_; |
| SurfaceManager* const surface_manager_; |
| |
| const FrameSinkId frame_sink_id_; |
| SurfaceId current_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. |
| base::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_; |
| |
| // Counts the number of CompositorFrames that have been submitted and have not |
| // yet received an ACK. |
| int ack_pending_count_ = 0; |
| std::vector<ReturnedResource> surface_returned_resources_; |
| |
| // The begin frame source being observered. Null if none. |
| 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 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; |
| |
| const bool is_root_; |
| const bool needs_sync_tokens_; |
| |
| // 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_; |
| |
| // A callback that will be run at the start of the destructor if set. |
| base::OnceClosure destruction_callback_; |
| |
| // TODO(crbug.com/754872): Remove once tab capture has moved into VIZ. |
| AggregatedDamageCallback aggregated_damage_callback_; |
| |
| uint64_t last_frame_index_ = kFrameIndexStart; |
| |
| // The video capture clients hooking into this instance to observe frame |
| // begins and damage, and then make CopyOutputRequests on the appropriate |
| // frames. |
| std::vector<CapturableFrameSink::Client*> capture_clients_; |
| |
| base::WeakPtrFactory<CompositorFrameSinkSupport> weak_factory_; |
| |
| DISALLOW_COPY_AND_ASSIGN(CompositorFrameSinkSupport); |
| }; |
| |
| } // namespace viz |
| |
| #endif // COMPONENTS_VIZ_SERVICE_FRAME_SINKS_COMPOSITOR_FRAME_SINK_SUPPORT_H_ |