| // Copyright 2017 The Fuchsia 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 SRC_UI_SCENIC_LIB_SCHEDULING_FRAME_SCHEDULER_H_ |
| #define SRC_UI_SCENIC_LIB_SCHEDULING_FRAME_SCHEDULER_H_ |
| |
| #include <lib/fit/function.h> |
| #include <lib/zx/event.h> |
| #include <lib/zx/time.h> |
| |
| #include <map> |
| #include <unordered_map> |
| #include <unordered_set> |
| |
| #include "src/ui/scenic/lib/scheduling/id.h" |
| |
| namespace scheduling { |
| |
| struct PresentTimestamps { |
| zx::time presented_time = zx::time(0); |
| zx::duration vsync_interval = zx::duration(0); |
| }; |
| |
| struct FuturePresentationInfo { |
| zx::time latch_point = zx::time(0); |
| zx::time presentation_time = zx::time(0); |
| }; |
| |
| // Interface for performing session updates. |
| class SessionUpdater { |
| public: |
| // Returned by |UpdateSessions()|. |
| struct UpdateResults { |
| // SessionIds whose updates failed. |
| std::unordered_set<SessionId> sessions_with_failed_updates; |
| |
| void merge(UpdateResults& other) { |
| sessions_with_failed_updates.merge(other.sessions_with_failed_updates); |
| } |
| void merge(UpdateResults&& other) { |
| sessions_with_failed_updates.merge(other.sessions_with_failed_updates); |
| } |
| }; |
| |
| virtual ~SessionUpdater() = default; |
| |
| // For each known session in |sessions_to_update|, apply all updates up to and including |
| // |PresentId|. |
| virtual UpdateResults UpdateSessions( |
| const std::unordered_map<SessionId, PresentId>& sessions_to_update, uint64_t trace_id) = 0; |
| |
| // Signaled after FrameRenderer::RenderFrame() completes. |
| virtual void OnCpuWorkDone() = 0; |
| |
| // Called whenever a new set of presents have been presented to the screen. |latched_times| gives |
| // information about when each individual update was latched. |
| virtual void OnFramePresented( |
| const std::unordered_map<SessionId, std::map<PresentId, /*latched_time*/ zx::time>>& |
| latched_times, |
| PresentTimestamps present_times) = 0; |
| }; |
| |
| // Interface for rendering frames. |
| class FrameRenderer { |
| public: |
| // Time value used to signal the time measurement was dropped. |
| static constexpr zx::time kTimeDropped = zx::time(ZX_TIME_INFINITE); |
| |
| // The timestamp data that is expected to be delivered after rendering and presenting a frame. |
| // TODO(fxbug.dev/24669): If there are multiple render passes, |render_done_time| is the time |
| // furthest forward in time. Solving 24669 may involve expanding this struct to support multiple |
| // passes in data. |
| struct Timestamps { |
| zx::time render_done_time; |
| zx::time actual_presentation_time; |
| }; |
| |
| virtual ~FrameRenderer() = default; |
| |
| // Called when it's time to render a new frame. It is the responsibility of the renderer to |
| // trigger the callback once all timestamp data is available. The callback must be triggered at |
| // some point, though multiple callbacks can be pending at any point in time. |
| // |
| // Frames must be rendered in the order they are requested, and callbacks must be triggered in the |
| // same order. |
| using FramePresentedCallback = std::function<void(const Timestamps&)>; |
| virtual void RenderScheduledFrame(uint64_t frame_number, zx::time presentation_time, |
| FramePresentedCallback callback) = 0; |
| |
| // The FrameRenderer should signal these events when all pending rendering is complete. |
| virtual void SignalFencesWhenPreviousRendersAreDone(std::vector<zx::event> events) = 0; |
| }; |
| |
| // The FrameScheduler is responsible for scheduling frames to be drawn in response to requests from |
| // clients. When a frame is requested, the FrameScheduler will decide at which Vsync the frame |
| // should be displayed at. This time will be no earlier than the requested time, and will be as |
| // close as possible to the requested time, subject to various constraints. For example, if the |
| // requested time is earlier than the time that rendering would finish, were it started immediately, |
| // then the frame will be scheduled for a later Vsync. |
| class FrameScheduler { |
| public: |
| virtual ~FrameScheduler() = default; |
| |
| // If |render_continuously|, we keep scheduling new frames immediately after each presented frame, |
| // regardless of whether they're explicitly requested using RequestFrame(). |
| virtual void SetRenderContinuously(bool render_continuously) = 0; |
| |
| // Registers per-present information with the frame scheduler and returns an incrementing |
| // PresentId unique to that session. When not equal to scheduling::kInvalidPresentId, the |
| // |present_id| argument will be used in place of a new PresentId, allowing feed-forward |
| // semantics for clients that need them. |
| virtual PresentId RegisterPresent(SessionId session_id, std::vector<zx::event> release_fences, |
| PresentId present_id = kInvalidPresentId) = 0; |
| |
| // Tell the FrameScheduler to schedule a frame. This is also used for updates triggered by |
| // something other than a Session update i.e. an ImagePipe with a new Image to present. |
| // |squashable| determines if the update is allowed to be combined with a following one in case |
| // of delays. |
| virtual void ScheduleUpdateForSession(zx::time presentation_time, SchedulingIdPair id_pair, |
| bool squashable) = 0; |
| |
| // Gets the predicted latch points and presentation times for the frames at or before the next |
| // |requested_prediction_span| time span. Uses the FramePredictor to do so. |
| using GetFuturePresentationInfosCallback = |
| fit::function<void(std::vector<FuturePresentationInfo>)>; |
| virtual void GetFuturePresentationInfos(zx::duration requested_prediction_span, |
| GetFuturePresentationInfosCallback callback) = 0; |
| |
| // Removes all references to |session_id|. |
| virtual void RemoveSession(SessionId session_id) = 0; |
| |
| // Clients cannot call Present() anymore when |presents_in_flight_| reaches this value. Scenic |
| // uses this to apply backpressure to clients. |
| // TODO(fxbug.dev/44211): Move into implementation. |
| static constexpr int64_t kMaxPresentsInFlight = 5; |
| }; |
| |
| } // namespace scheduling |
| |
| #endif // SRC_UI_SCENIC_LIB_SCHEDULING_FRAME_SCHEDULER_H_ |