// Copyright 2014 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_SURFACES_SURFACE_H_ #define COMPONENTS_VIZ_SERVICE_SURFACES_SURFACE_H_ #include #include #include #include #include #include #include #include "base/callback.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "base/optional.h" #include "base/time/time.h" #include "components/viz/common/frame_sinks/copy_output_request.h" #include "components/viz/common/quads/compositor_frame.h" #include "components/viz/common/surfaces/frame_sink_id.h" #include "components/viz/common/surfaces/surface_info.h" #include "components/viz/service/surfaces/surface_dependency_deadline.h" #include "components/viz/service/viz_service_export.h" #include "ui/gfx/geometry/size.h" namespace cc { class CopyOutputRequest; } namespace ui { class LatencyInfo; } namespace viz { class SurfaceClient; class SurfaceManager; // A Surface is a representation of a sequence of CompositorFrames with a // common set of properties uniquely identified by a SurfaceId. In particular, // all CompositorFrames submitted to a single Surface share properties described // in SurfaceInfo: device scale factor and size. A Surface can hold up to two // CompositorFrames at a given time: // // Active frame: An active frame is a candidate for display. A // CompositorFrame is active if it has been explicitly marked // as active after a deadline has passed or all its // dependencies are active. // // Pending frame: A pending CompositorFrame cannot be displayed on screen. A // CompositorFrame is pending if it has unresolved // dependencies: surface Ids to which there are no active // CompositorFrames. // // This two stage mechanism for managing CompositorFrames from a client exists // to enable best-effort synchronization across clients. A surface subtree will // remain pending until all dependencies are resolved: all clients have // submitted CompositorFrames corresponding to a new property of the subtree // (e.g. a new size). // // Clients are assumed to be untrusted and so a client may not submit a // CompositorFrame to satisfy the dependency of the parent. Thus, by default, a // surface has an activation deadline associated with its dependencies. If the // deadline passes, then the CompositorFrame will activate despite missing // dependencies. The activated CompositorFrame can specify fallback behavior in // the event of missing dependencies at display time. class VIZ_SERVICE_EXPORT Surface final : public SurfaceDeadlineClient { public: using AggregatedDamageCallback = base::RepeatingCallback; using PresentedCallback = base::OnceCallback; Surface(const SurfaceInfo& surface_info, SurfaceManager* surface_manager, base::WeakPtr surface_client, bool needs_sync_tokens); ~Surface(); void SetDependencyDeadline( std::unique_ptr deadline); // Clears the pending and active frame data as well as the // |seen_first_frame_activation_| bit causing a FirstSurfaceActivation to be // triggered on the next CompositorFrame activation. void Reset(base::WeakPtr client); const SurfaceId& surface_id() const { return surface_info_.id(); } const SurfaceId& previous_frame_surface_id() const { return previous_frame_surface_id_; } const gfx::Size& size_in_pixels() const { return surface_info_.size_in_pixels(); } base::WeakPtr client() { return surface_client_; } bool has_deadline() const { return deadline_ && deadline_->has_deadline(); } // Inherits the same deadline as the one specified by |surface|. A deadline // may be set further out in order to avoid doing unnecessary work while a // parent surface is blocked on dependencies. A deadline may be shortened // in order to minimize guttering (by unblocking children blocked on their // grandchildren sooner). void InheritActivationDeadlineFrom(Surface* surface); void SetPreviousFrameSurface(Surface* surface); // Increments the reference count on resources specified by |resources|. void RefResources(const std::vector& resources); // Decrements the reference count on resources specified by |resources|. void UnrefResources(const std::vector& resources); bool needs_sync_tokens() const { return needs_sync_tokens_; } // Returns false if |frame| is invalid. // |draw_callback| is called once to notify the client that the previously // submitted CompositorFrame is processed and that another frame can be // there is visible damage. // |aggregated_damage_callback| is called when |surface| or one of its // descendents is determined to be damaged at aggregation time. // |presented_callback| is called when the |frame| has been turned into light // the first time on display, or the |frame| will never be displayed. bool QueueFrame(CompositorFrame frame, uint64_t frame_index, base::OnceClosure draw_callback, const AggregatedDamageCallback& aggregated_damage_callback, PresentedCallback presented_callback); // Notifies the Surface that a blocking SurfaceId now has an active // frame. void NotifySurfaceIdAvailable(const SurfaceId& surface_id); // Called if a deadline has been hit and this surface is not yet active but // it's marked as respecting deadlines. void ActivatePendingFrameForDeadline( base::Optional duration); using CopyRequestsMap = std::multimap>; // Adds each CopyOutputRequest in the current frame to copy_requests. The // caller takes ownership of them. |copy_requests| is keyed by RenderPass // ids. void TakeCopyOutputRequests(CopyRequestsMap* copy_requests); // Takes CopyOutputRequests made at the client level and adds them to this // Surface. void TakeCopyOutputRequestsFromClient(); // Returns whether there is a CopyOutputRequest inside the active frame or at // the client level. bool HasCopyOutputRequests(); // Returns the most recent frame that is eligible to be rendered. // You must check whether HasActiveFrame() returns true before calling this // method. const CompositorFrame& GetActiveFrame() const; // Returns the currently pending frame. You must check where HasPendingFrame() // returns true before calling this method. const CompositorFrame& GetPendingFrame(); // Returns a number that increments by 1 every time a new frame is enqueued. uint64_t GetActiveFrameIndex() const { return active_frame_data_ ? active_frame_data_->frame_index : 0; } void TakeLatencyInfo(std::vector* latency_info); bool TakePresentedCallback(PresentedCallback* callback); void RunDrawCallback(); void NotifyAggregatedDamage(const gfx::Rect& damage_rect, base::TimeTicks expected_display_time); const std::vector* active_referenced_surfaces() const { return active_frame_data_ ? &active_frame_data_->frame.metadata.referenced_surfaces : nullptr; } // Returns the set of dependencies blocking this surface's pending frame // that themselves have not yet activated. const base::flat_set& activation_dependencies() const { return activation_dependencies_; } // Returns the set of activation dependencies that have been ignored because // the last CompositorFrame was activated due to a deadline. Late // dependencies activate immediately when they arrive. const base::flat_set& late_activation_dependencies() const { return late_activation_dependencies_; } bool HasActiveFrame() const { return active_frame_data_.has_value(); } bool HasPendingFrame() const { return pending_frame_data_.has_value(); } bool HasUndrawnActiveFrame() const { return HasActiveFrame() && active_frame_data_->draw_callback; } // SurfaceDeadlineClient implementation: void OnDeadline(base::TimeDelta duration) override; // Called when this surface will be included in the next display frame. void OnWillBeDrawn(); private: struct SequenceNumbers { uint32_t parent_sequence_number = 0u; uint32_t child_sequence_number = 0u; }; struct FrameData { FrameData(CompositorFrame&& frame, uint64_t frame_index, base::OnceClosure draw_callback, const AggregatedDamageCallback& aggregated_damage_callback, PresentedCallback presented_callback); FrameData(FrameData&& other); ~FrameData(); FrameData& operator=(FrameData&& other); CompositorFrame frame; uint64_t frame_index; base::OnceClosure draw_callback; AggregatedDamageCallback aggregated_damage_callback; PresentedCallback presented_callback; }; // Rejects CompositorFrames submitted to surfaces referenced from this // CompositorFrame as fallbacks. This saves some CPU cycles to allow // children to catch up to the parent. void RejectCompositorFramesToFallbackSurfaces(); // Called to prevent additional CompositorFrames from being accepted into this // surface. Once a Surface is closed, it cannot accept CompositorFrames again. void Close(); void ActivatePendingFrame(base::Optional duration); // Called when all of the surface's dependencies have been resolved. void ActivateFrame(FrameData frame_data, base::Optional duration); // Updates the set of unresolved activation dependenices of the // |current_frame|. If the deadline requested by the frame is 0 then no // dependencies will be added even if they're not yet available. FrameDeadline UpdateActivationDependencies( const CompositorFrame& current_frame); void ComputeChangeInDependencies( const base::flat_map& new_dependencies); void UnrefFrameResourcesAndRunCallbacks(base::Optional frame_data); void ClearCopyRequests(); void TakeLatencyInfoFromPendingFrame( std::vector* latency_info); static void TakeLatencyInfoFromFrame( CompositorFrame* frame, std::vector* latency_info); void RequestCopyOfOutput(std::unique_ptr copy_request); const SurfaceInfo surface_info_; SurfaceId previous_frame_surface_id_; SurfaceManager* const surface_manager_; base::WeakPtr surface_client_; std::unique_ptr deadline_; base::Optional pending_frame_data_; base::Optional active_frame_data_; bool closed_ = false; bool seen_first_frame_activation_ = false; const bool needs_sync_tokens_; base::flat_set activation_dependencies_; base::flat_set late_activation_dependencies_; // A map from FrameSinkIds of SurfaceIds that this surface depends on for // activation to the latest local_id associated with the given FrameSinkId // that this surface is dependent on. This map is used to determine which // FrameSinkIds this surface would like to observe activations for. Once // the latest activated SurfaceId associated with the given FrameSinkId // passes the local_id in the map, then this surface is no longer interested // in observing activations for that FrameSinkId. base::flat_map frame_sink_id_dependencies_; DISALLOW_COPY_AND_ASSIGN(Surface); }; } // namespace viz #endif // COMPONENTS_VIZ_SERVICE_SURFACES_SURFACE_H_