blob: e6e28c02758f25a19773642cd56c7b613aca0188 [file] [log] [blame]
// 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 "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();
FrameTimings(FrameScheduler* frame_scheduler, uint64_t frame_number,
zx_time_t target_presentation_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 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_;
}
private:
// Called once all swapchains have reported back with their render-finished
// and presentation times.
void Finalize();
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_;
zx_time_t actual_presentation_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_