···12611261 bool compositor_visible;
12621262 bool compositor_focused;
1263126312641264+ // the number of xrWaitFrame calls that did not yet have a corresponding
12651265+ // xrEndFrame or xrBeginFrame (discarded frame) call
12661266+ int active_wait_frames;
12671267+ struct os_mutex active_wait_frames_lock;
12681268+12641269 bool frame_started;
12651270 bool exiting;
12661271
+44-1
src/xrt/state_trackers/oxr/oxr_session.c
···521521 return oxr_session_success_result(sess);
522522 }
523523524524- // Before calling wait frame make sure that begin frame has been called.
524524+ os_mutex_lock(&sess->active_wait_frames_lock);
525525+ sess->active_wait_frames++;
526526+ os_mutex_unlock(&sess->active_wait_frames_lock);
527527+528528+ // A subsequent xrWaitFrame call must: block until the previous frame
529529+ // has been begun
525530 os_semaphore_wait(&sess->sem, 0);
526531527532 uint64_t predicted_display_time;
···561566562567 struct xrt_compositor *xc = sess->compositor;
563568569569+ os_mutex_lock(&sess->active_wait_frames_lock);
570570+ int active_wait_frames = sess->active_wait_frames;
571571+ os_mutex_unlock(&sess->active_wait_frames_lock);
572572+564573 XrResult ret;
574574+ if (active_wait_frames == 0) {
575575+ return oxr_error(log, XR_ERROR_CALL_ORDER_INVALID,
576576+ "xrBeginFrame without xrWaitFrame");
577577+ }
578578+565579 if (sess->frame_started) {
580580+ // max 2 xrWaitFrame can be in flight so a second xrBeginFrame
581581+ // is only valid if we have a second xrWaitFrame in flight
582582+ if (active_wait_frames != 2) {
583583+ return oxr_error(log, XR_ERROR_CALL_ORDER_INVALID,
584584+ "xrBeginFrame without xrWaitFrame");
585585+ }
586586+587587+566588 ret = XR_FRAME_DISCARDED;
567589 if (xc != NULL) {
568590 CALL_CHK(
569591 xrt_comp_discard_frame(xc, sess->frame_id.begun));
570592 sess->frame_id.begun = -1;
593593+594594+ os_mutex_lock(&sess->active_wait_frames_lock);
595595+ sess->active_wait_frames--;
596596+ os_mutex_unlock(&sess->active_wait_frames_lock);
571597 }
572598 } else {
573599 ret = oxr_session_success_result(sess);
···18491875 if (xc == NULL) {
18501876 sess->frame_started = false;
1851187718781878+ os_mutex_lock(&sess->active_wait_frames_lock);
18791879+ sess->active_wait_frames--;
18801880+ os_mutex_unlock(&sess->active_wait_frames_lock);
18811881+18521882 do_synchronize_state_change(log, sess);
1853188318541884 return oxr_session_success_result(sess);
···18851915 * Early out for discarded frame if layer count is 0.
18861916 */
18871917 if (frameEndInfo->layerCount == 0) {
19181918+19191919+ sess->active_wait_frames--;
19201920+18881921 CALL_CHK(xrt_comp_discard_frame(xc, sess->frame_id.begun));
18891922 sess->frame_id.begun = -1;
18901923 sess->frame_started = false;
···2020205320212054 sess->frame_started = false;
2022205520562056+ os_mutex_lock(&sess->active_wait_frames_lock);
20572057+ sess->active_wait_frames--;
20582058+ os_mutex_unlock(&sess->active_wait_frames_lock);
20592059+20232060 return oxr_session_success_result(sess);
20242061}
20252062···20482085 u_hashmap_int_destroy(&sess->act_attachments_by_key);
2049208620502087 xrt_comp_destroy(&sess->compositor);
20882088+20892089+ os_semaphore_destroy(&sess->sem);
20902090+ os_mutex_destroy(&sess->active_wait_frames_lock);
2051209120522092 free(sess);
20532093···2185222521862226 // Init the begin/wait frame semaphore.
21872227 os_semaphore_init(&sess->sem, 1);
22282228+22292229+ sess->active_wait_frames = 0;
22302230+ os_mutex_init(&sess->active_wait_frames_lock);
2188223121892232 struct xrt_compositor *xc = sess->compositor;
21902233 if (xc != NULL) {