blob: e39c460354327333e232352c1968f51c5397b6e7 [file] [log] [blame]
// Copyright 2019 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.
#include "src/ui/scenic/lib/scheduling/frame_predictor.h"
#include <lib/syslog/cpp/macros.h>
#include <algorithm>
namespace scheduling {
// static
zx::time FramePredictor::ComputeNextSyncTime(zx::time last_sync_time, zx::duration sync_interval,
zx::time min_sync_time) {
FX_DCHECK(sync_interval.get() > 0);
// If the last sync time is greater than or equal to the minimum acceptable
// sync time, just return the last sync.
// Note: in practice, these numbers will likely differ. The "equal to"
// comparison is necessary for tests, which have much tighter control on time.
if (last_sync_time >= min_sync_time) {
return last_sync_time;
}
const int64_t num_intervals = (min_sync_time - last_sync_time) / sync_interval;
return last_sync_time + (sync_interval * (num_intervals + 1));
}
// static
PredictedTimes FramePredictor::ComputePredictionFromDuration(PredictionRequest request,
zx::duration required_frame_duration) {
// Calculate minimum time this would sync to. It is last vsync time plus half
// a vsync-interval (to allow for jitter for the VSYNC signal), or the current
// time plus the expected render time, whichever is larger, so we know we have
// enough time to render for that sync.
zx::time min_sync_time = std::max((request.last_vsync_time + (request.vsync_interval / 2)),
(request.now + required_frame_duration));
const zx::time target_vsync_time =
ComputeNextSyncTime(request.last_vsync_time, request.vsync_interval, min_sync_time);
// Ensure the requested presentation time is current.
zx::time target_presentation_time = std::max(request.requested_presentation_time, request.now);
// Compute the next presentation time from the target vsync time (inclusive),
// that is at least the current requested present time.
target_presentation_time =
ComputeNextSyncTime(target_vsync_time, request.vsync_interval, target_presentation_time);
// Find time the client should latch and start rendering in order to
// frame in time for the target present.
zx::time latch_point = target_presentation_time - required_frame_duration;
return {.latch_point_time = latch_point, .presentation_time = target_presentation_time};
}
} // namespace scheduling