···11-// Copyright 2020-2021, Collabora, Ltd.
11+// Copyright 2020-2022, Collabora, Ltd.
22// SPDX-License-Identifier: BSL-1.0
33/*!
44 * @file
···194194 return is_within_of_each_other(l, r, U_TIME_HALF_MS_IN_NS);
195195}
196196197197+/*!
198198+ * Gets a frame data structure based on the @p frame_id.
199199+ *
200200+ * Note that this is done modulo the number of frame data structs we hold: the data in the frame you receive may not
201201+ * match the @p frame_id you passed!
202202+ *
203203+ * @see create_frame to create a frame id and (partially) initialize the frame data structure, @ref do_clean_slate_frame
204204+ * for a more complete initialization
205205+ */
197206static struct frame *
198207get_frame(struct display_timing *dt, int64_t frame_id)
199208{
···205214 return &dt->frames[index];
206215}
207216217217+/*!
218218+ * Assign the next available frame ID, initialize the corresponding frame data with the ID and @p state, and return a
219219+ * pointer to that frame data.
220220+ *
221221+ * Fields other than frame::frame_id and frame::state are not modified, so may have old data in them. This may be a
222222+ * feature rather than a bug.
223223+ */
208224static struct frame *
209225create_frame(struct display_timing *dt, enum frame_state state)
210226{
···217233 return f;
218234}
219235236236+/*!
237237+ * Gets the most recent frame data whose state is greater than or equal to @p state, if any
238238+ *
239239+ * @return a frame pointer, or null if no frames have at least @p state
240240+ */
220241static struct frame *
221242get_latest_frame_with_state_at_least(struct display_timing *dt, enum frame_state state)
222243{
···233254 return NULL;
234255}
235256257257+/*!
258258+ * "Create" a frame ID in state @ref STATE_PREDICTED (by calling @ref create_frame), and additionally initialize
259259+ * frame::desired_present_time_ns (with a crude estimate) and frame::when_predict_ns.
260260+ */
236261static struct frame *
237262do_clean_slate_frame(struct display_timing *dt)
238263{
···247272 return f;
248273}
249274275275+/*!
276276+ * Find the next possible present time for rendering that has not yet occurred, and create a frame/frame id with that
277277+ * prediction in it.
278278+ */
250279static struct frame *
251280walk_forward_through_frames(struct display_timing *dt, uint64_t last_present_time_ns)
252281{
253282 uint64_t now_ns = os_monotonic_get_ns();
283283+ // This is the earliest possible time we could present, assuming rendering still must take place.
254284 uint64_t from_time_ns = now_ns + calc_total_app_time(dt);
255285 uint64_t desired_present_time_ns = last_present_time_ns + dt->frame_period_ns;
256286···441471442472 struct frame *last = get_latest_frame_with_state_at_least(dt, STATE_INFO);
443473 struct frame *f = get_frame(dt, frame_id);
474474+ if (f->frame_id != frame_id) {
475475+ FT_LOG_W("Discarded info for unsubmitted or expired frame_id %" PRIx64, frame_id);
476476+ if (last != NULL) {
477477+ FT_LOG_W("The latest frame_id we have info for is %" PRIx64, last->frame_id);
478478+ }
479479+ return;
480480+ }
444481 assert(f->state == STATE_SUBMITTED);
482482+ assert(f->desired_present_time_ns == desired_present_time_ns);
445483446484 f->when_infoed_ns = os_monotonic_get_ns();
447485 f->actual_present_time_ns = actual_present_time_ns;