| // 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 GARNET_LIB_UI_GFX_ENGINE_FRAME_TIMINGS_H_ |
| #define GARNET_LIB_UI_GFX_ENGINE_FRAME_TIMINGS_H_ |
| |
| #include <lib/zx/time.h> |
| |
| #include <vector> |
| |
| #include "src/ui/lib/escher/base/reffable.h" |
| |
| namespace scenic_impl { |
| namespace gfx { |
| |
| class FrameTimings; |
| class FrameScheduler; |
| class Swapchain; |
| using FrameTimingsPtr = fxl::RefPtr<FrameTimings>; |
| |
| // Each frame, an instance of FrameTimings is used by the FrameScheduler to |
| // collect timing information about all swapchains that were rendered to during |
| // the frame. Once all swapchains have finished rendering/presenting, the |
| // FrameScheduler is notified via OnFramePresented(). |
| class FrameTimings : public escher::Reffable { |
| public: |
| FrameTimings(FrameScheduler* frame_scheduler, uint64_t frame_number, |
| zx_time_t target_presentation_time, |
| zx_time_t rendering_started_time); |
| |
| // Add a swapchain that is used as a render target this frame. Return an |
| // index that can be used to indicate when rendering for that swapchain is |
| // finished, and when the frame is actually presented on that swapchain. |
| size_t AddSwapchain(Swapchain* swapchain); |
| |
| void OnFrameRendered(size_t swapchain_index, zx_time_t time); |
| void OnFramePresented(size_t swapchain_index, zx_time_t time); |
| void OnFrameDropped(size_t swapchain_index); |
| |
| // Returns true when the frame timing has been passed to the scheduler |
| // and can be discarded. |
| // |
| // Although the actual frame presentation depends on the actual frame |
| // rendering, there is currently no guaranteed ordering between when the |
| // two events are received by the engine (due to the redispatch |
| // in EventTimestamper). |
| bool finalized() const { return finalized_; } |
| |
| uint64_t frame_number() const { return frame_number_; } |
| zx_time_t target_presentation_time() const { |
| return target_presentation_time_; |
| } |
| |
| bool frame_was_dropped() const { |
| return actual_presentation_time_ == ZX_TIME_INFINITE; |
| } |
| // Should only be called if frame_was_dropped returns false. |
| zx_time_t actual_presentation_time() const { |
| FXL_DCHECK(actual_presentation_time_ > 0 && |
| actual_presentation_time_ != ZX_TIME_INFINITE); |
| return actual_presentation_time_; |
| } |
| |
| zx_time_t rendering_started_time() const { return rendering_started_time_; } |
| |
| zx_time_t rendering_finished_time() const { return rendering_finished_time_; } |
| |
| private: |
| // Called once all swapchains have reported back with their render-finished |
| // and presentation times. |
| void Finalize(); |
| |
| bool received_all_frame_rendered_callbacks() { |
| return frame_rendered_count_ == swapchain_records_.size(); |
| } |
| |
| bool received_all_callbacks() { |
| return frame_rendered_count_ == swapchain_records_.size() && |
| frame_presented_count_ == swapchain_records_.size(); |
| } |
| |
| struct Record { |
| zx_time_t frame_rendered_time = 0; |
| zx_time_t frame_presented_time = 0; |
| }; |
| std::vector<Record> swapchain_records_; |
| FrameScheduler* const frame_scheduler_; |
| const uint64_t frame_number_; |
| const zx_time_t target_presentation_time_; |
| const zx_time_t rendering_started_time_; |
| zx_time_t actual_presentation_time_ = 0; |
| zx_time_t rendering_finished_time_ = 0; |
| size_t frame_rendered_count_ = 0; |
| size_t frame_presented_count_ = 0; |
| bool finalized_ = false; |
| }; |
| |
| } // namespace gfx |
| } // namespace scenic_impl |
| |
| #endif // GARNET_LIB_UI_GFX_ENGINE_FRAME_TIMINGS_H_ |