oxr: Implement additional xrWaitFrame/xrBeginFrame call order checks

Relevant CTS tests: https://github.com/KhronosGroup/OpenXR-CTS/pull/7
This commit is contained in:
Christoph Haag 2020-11-03 20:54:34 +01:00
parent 965fa60bff
commit 7eaa7abb89
2 changed files with 49 additions and 1 deletions

View file

@ -1261,6 +1261,11 @@ struct oxr_session
bool compositor_visible;
bool compositor_focused;
// the number of xrWaitFrame calls that did not yet have a corresponding
// xrEndFrame or xrBeginFrame (discarded frame) call
int active_wait_frames;
struct os_mutex active_wait_frames_lock;
bool frame_started;
bool exiting;

View file

@ -521,7 +521,12 @@ oxr_session_frame_wait(struct oxr_logger *log,
return oxr_session_success_result(sess);
}
// Before calling wait frame make sure that begin frame has been called.
os_mutex_lock(&sess->active_wait_frames_lock);
sess->active_wait_frames++;
os_mutex_unlock(&sess->active_wait_frames_lock);
// A subsequent xrWaitFrame call must: block until the previous frame
// has been begun
os_semaphore_wait(&sess->sem, 0);
uint64_t predicted_display_time;
@ -561,13 +566,34 @@ oxr_session_frame_begin(struct oxr_logger *log, struct oxr_session *sess)
struct xrt_compositor *xc = sess->compositor;
os_mutex_lock(&sess->active_wait_frames_lock);
int active_wait_frames = sess->active_wait_frames;
os_mutex_unlock(&sess->active_wait_frames_lock);
XrResult ret;
if (active_wait_frames == 0) {
return oxr_error(log, XR_ERROR_CALL_ORDER_INVALID,
"xrBeginFrame without xrWaitFrame");
}
if (sess->frame_started) {
// max 2 xrWaitFrame can be in flight so a second xrBeginFrame
// is only valid if we have a second xrWaitFrame in flight
if (active_wait_frames != 2) {
return oxr_error(log, XR_ERROR_CALL_ORDER_INVALID,
"xrBeginFrame without xrWaitFrame");
}
ret = XR_FRAME_DISCARDED;
if (xc != NULL) {
CALL_CHK(
xrt_comp_discard_frame(xc, sess->frame_id.begun));
sess->frame_id.begun = -1;
os_mutex_lock(&sess->active_wait_frames_lock);
sess->active_wait_frames--;
os_mutex_unlock(&sess->active_wait_frames_lock);
}
} else {
ret = oxr_session_success_result(sess);
@ -1849,6 +1875,10 @@ oxr_session_frame_end(struct oxr_logger *log,
if (xc == NULL) {
sess->frame_started = false;
os_mutex_lock(&sess->active_wait_frames_lock);
sess->active_wait_frames--;
os_mutex_unlock(&sess->active_wait_frames_lock);
do_synchronize_state_change(log, sess);
return oxr_session_success_result(sess);
@ -1885,6 +1915,9 @@ oxr_session_frame_end(struct oxr_logger *log,
* Early out for discarded frame if layer count is 0.
*/
if (frameEndInfo->layerCount == 0) {
sess->active_wait_frames--;
CALL_CHK(xrt_comp_discard_frame(xc, sess->frame_id.begun));
sess->frame_id.begun = -1;
sess->frame_started = false;
@ -2020,6 +2053,10 @@ oxr_session_frame_end(struct oxr_logger *log,
sess->frame_started = false;
os_mutex_lock(&sess->active_wait_frames_lock);
sess->active_wait_frames--;
os_mutex_unlock(&sess->active_wait_frames_lock);
return oxr_session_success_result(sess);
}
@ -2049,6 +2086,9 @@ oxr_session_destroy(struct oxr_logger *log, struct oxr_handle_base *hb)
xrt_comp_destroy(&sess->compositor);
os_semaphore_destroy(&sess->sem);
os_mutex_destroy(&sess->active_wait_frames_lock);
free(sess);
return ret;
@ -2186,6 +2226,9 @@ oxr_session_create(struct oxr_logger *log,
// Init the begin/wait frame semaphore.
os_semaphore_init(&sess->sem, 1);
sess->active_wait_frames = 0;
os_mutex_init(&sess->active_wait_frames_lock);
struct xrt_compositor *xc = sess->compositor;
if (xc != NULL) {
struct xrt_session_prepare_info xspi = {0};