Commit ab9f7839 authored by Patrick To's avatar Patrick To Committed by Commit Bot

Don't start an OpenXR frame before the session is running

When a session is created in OpenXR, it is not started until an OpenXR
event indicates that the session is ready to begin. However, WebXR
starts requesting frames as soon as the runtime is created. This calls
xrWaitFrame before the session has begun, which generates an OpenXR
error. This change keeps track of when the session is running, and only
calls xrWaitFrame when the session has begun. Otherwise, an empty frame
is returned to WebXR.

Bug: 1050729
Change-Id: I990457a349ba90395404b2adb3f14b3c21883bb6
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2275370Reviewed-by: default avatarAlexander Cooper <alcooper@chromium.org>
Reviewed-by: default avatarBrandon Jones <bajones@chromium.org>
Commit-Queue: Patrick To <patrto@microsoft.com>
Cr-Commit-Position: refs/heads/master@{#786024}
parent a65e3e61
......@@ -78,7 +78,7 @@ void OpenXrApiWrapper::Reset() {
bool OpenXrApiWrapper::Initialize() {
Reset();
session_ended_ = false;
session_running_ = false;
pending_frame_ = false;
// Set to min so that the first call to EnsureEventPolling is guaranteed to
// call ProcessEvents, which will update this variable from there on.
......@@ -128,7 +128,7 @@ void OpenXrApiWrapper::Uninitialize() {
test_hook_->DetachCurrentThread();
Reset();
session_ended_ = true;
session_running_ = false;
pending_frame_ = false;
// Set to max so events are no longer polled in the EnsureEventPolling loop.
......@@ -241,9 +241,13 @@ XrResult OpenXrApiWrapper::PickEnvironmentBlendMode(XrSystemId system) {
bool OpenXrApiWrapper::UpdateAndGetSessionEnded() {
// Ensure we have the latest state from the OpenXR runtime.
if (XR_FAILED(ProcessEvents())) {
DCHECK(session_ended_);
DCHECK(!session_running_);
}
return session_ended_;
// This object is initialized at creation and uninitialized when the OpenXR
// session has ended. Once uninitialized, this object is never re-initialized.
// If a new session is requested by WebXR, a new object is created.
return !IsInitialized();
}
// Callers of this function must check the XrResult return value and destroy
......@@ -387,7 +391,11 @@ XrResult OpenXrApiWrapper::BeginSession() {
XrSessionBeginInfo session_begin_info = {XR_TYPE_SESSION_BEGIN_INFO};
session_begin_info.primaryViewConfigurationType = kSupportedViewConfiguration;
return xrBeginSession(session_, &session_begin_info);
XrResult xr_result = xrBeginSession(session_, &session_begin_info);
if (XR_SUCCEEDED(xr_result))
session_running_ = true;
return xr_result;
}
XrResult OpenXrApiWrapper::BeginFrame(
......@@ -395,7 +403,8 @@ XrResult OpenXrApiWrapper::BeginFrame(
DCHECK(HasSession());
DCHECK(HasColorSwapChain());
DCHECK(!session_ended_);
if (!session_running_)
return XR_ERROR_SESSION_NOT_RUNNING;
XrFrameWaitInfo wait_frame_info = {XR_TYPE_FRAME_WAIT_INFO};
XrFrameState frame_state = {XR_TYPE_FRAME_STATE};
......@@ -610,17 +619,17 @@ XrResult OpenXrApiWrapper::GetLuid(LUID* luid) const {
void OpenXrApiWrapper::EnsureEventPolling() {
// Events are usually processed at the beginning of a frame. When frames
// aren't being requested, this timer loop ensures OpenXR events are
// occasionally polled while the session is active.
if (!session_ended_) {
// occasionally polled while OpenXR is active.
if (IsInitialized()) {
if (base::TimeTicks::Now() - last_process_events_time_ >
kTimeBetweenPollingEvents) {
if (XR_FAILED(ProcessEvents())) {
DCHECK(session_ended_);
DCHECK(!session_running_);
}
}
// Verify that the session is still active after processing events.
if (!session_ended_) {
// Verify that OpenXR is still active after processing events.
if (IsInitialized()) {
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE,
base::BindOnce(&OpenXrApiWrapper::EnsureEventPolling,
......@@ -646,9 +655,10 @@ XrResult OpenXrApiWrapper::ProcessEvents() {
xr_result = BeginSession();
break;
case XR_SESSION_STATE_STOPPING:
session_ended_ = true;
session_running_ = false;
xr_result = xrEndSession(session_);
break;
Uninitialize();
return xr_result;
case XR_SESSION_STATE_SYNCHRONIZED:
visibility_changed_callback_.Run(
device::mojom::XRVisibilityState::HIDDEN);
......
......@@ -105,7 +105,9 @@ class OpenXrApiWrapper {
uint32_t GetRecommendedSwapchainSampleCount() const;
XrResult UpdateStageBounds();
bool session_ended_;
// The session is running only after xrBeginSession and before xrEndSession.
// It is not considered running after creation but before xrBeginSession.
bool session_running_;
bool pending_frame_;
base::TimeTicks last_process_events_time_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment