Commit a188d8cb authored by Aldo Culquicondor's avatar Aldo Culquicondor Committed by Commit Bot

VR: Add a BaseSchedulerDelegate

Extract platform independent code from the GvrSchedulerDelegate for
reusability and testing.

Bug: 875291
Cq-Include-Trybots: luci.chromium.try:android_optional_gpu_tests_rel;luci.chromium.try:linux_optional_gpu_tests_rel;luci.chromium.try:linux_vr;luci.chromium.try:mac_optional_gpu_tests_rel;luci.chromium.try:win_optional_gpu_tests_rel
Change-Id: Iaa90b42ea7e81995c32344c9da083c96bdc55a71
Reviewed-on: https://chromium-review.googlesource.com/1195711
Commit-Queue: Aldo Culquicondor <acondor@chromium.org>
Reviewed-by: default avatarMichael Thiessen <mthiesse@chromium.org>
Cr-Commit-Position: refs/heads/master@{#590454}
parent 4f1ed2c0
......@@ -64,19 +64,20 @@ GvrSchedulerDelegate::GvrSchedulerDelegate(GlBrowserInterface* browser,
SchedulerUiInterface* ui,
gvr::GvrApi* gvr_api,
GvrGraphicsDelegate* graphics,
bool start_in_web_xr_mode,
bool start_in_webxr_mode,
bool cardboard_gamepad,
size_t sliding_time_size)
: browser_(browser),
: BaseSchedulerDelegate(ui,
start_in_webxr_mode,
kWebVrSpinnerTimeoutSeconds,
kWebVrInitialFrameTimeoutSeconds),
browser_(browser),
gvr_api_(gvr_api),
ui_(ui),
webvr_vsync_align_(
base::FeatureList::IsEnabled(features::kWebVrVsyncAlign)),
web_xr_mode_(start_in_web_xr_mode),
cardboard_gamepad_(cardboard_gamepad),
vsync_helper_(base::BindRepeating(&GvrSchedulerDelegate::OnVSync,
base::Unretained(this))),
task_runner_(base::ThreadTaskRunnerHandle::Get()),
presentation_binding_(this),
frame_data_binding_(this),
graphics_(graphics),
......@@ -84,7 +85,7 @@ GvrSchedulerDelegate::GvrSchedulerDelegate(GlBrowserInterface* browser,
webvr_js_time_(sliding_time_size),
webvr_js_wait_time_(sliding_time_size),
weak_ptr_factory_(this) {
if (cardboard_gamepad_ && web_xr_mode_)
if (cardboard_gamepad_ && webxr_mode())
browser_->ToggleCardboardGamepad(true);
}
......@@ -110,23 +111,17 @@ void GvrSchedulerDelegate::AddInputSourceState(
void GvrSchedulerDelegate::OnPause() {
vsync_helper_.CancelVSyncRequest();
gvr_api_->PauseTracking();
webvr_frame_timeout_.Cancel();
webvr_spinner_timeout_.Cancel();
CancelWebXrFrameTimeout();
}
void GvrSchedulerDelegate::OnResume() {
gvr_api_->RefreshViewerProfile();
gvr_api_->ResumeTracking();
OnVSync(base::TimeTicks::Now());
if (web_xr_mode_)
if (webxr_mode())
ScheduleOrCancelWebVrFrameTimeout();
}
void GvrSchedulerDelegate::OnExitPresent() {
webvr_frame_timeout_.Cancel();
webvr_spinner_timeout_.Cancel();
}
void GvrSchedulerDelegate::OnTriggerEvent(bool pressed) {
if (pressed) {
cardboard_trigger_pressed_ = true;
......@@ -137,19 +132,12 @@ void GvrSchedulerDelegate::OnTriggerEvent(bool pressed) {
}
void GvrSchedulerDelegate::SetWebXrMode(bool enabled) {
web_xr_mode_ = enabled;
if (web_xr_mode_ && submit_client_) {
ScheduleOrCancelWebVrFrameTimeout();
} else {
webvr_frame_timeout_.Cancel();
webvr_frames_received_ = 0;
}
BaseSchedulerDelegate::SetWebXrMode(enabled);
if (cardboard_gamepad_)
browser_->ToggleCardboardGamepad(enabled);
if (!web_xr_mode_) {
if (!webxr_mode()) {
// Closing presentation bindings ensures we won't get any mojo calls such
// as SubmitFrame from this session anymore. This makes it legal to cancel
// an outstanding animating frame (if any).
......@@ -218,7 +206,8 @@ void GvrSchedulerDelegate::ConnectPresentingService(
session->submit_frame_sink = std::move(submit_frame_sink);
session->display_info = std::move(display_info);
ScheduleOrCancelWebVrFrameTimeout();
if (CanSendWebXrVSync())
ScheduleWebXrFrameTimeout();
browser_->SendRequestPresentReply(std::move(session));
}
......@@ -360,7 +349,7 @@ void GvrSchedulerDelegate::OnWebXrFrameAvailable() {
// due to an active exclusive UI such as a permission prompt, or after
// exiting a presentation session when a pending frame arrives late.
DVLOG(1) << __func__ << ": discarding frame, "
<< (web_xr_mode_ ? "UI is active" : "not presenting");
<< (webxr_mode() ? "UI is active" : "not presenting");
WebXrCancelProcessingFrameAfterTransfer();
// We're no longer in processing state, unblock pending processing frames.
webxr_.TryDeferredProcessing();
......@@ -383,39 +372,16 @@ void GvrSchedulerDelegate::ScheduleOrCancelWebVrFrameTimeout() {
// TODO(mthiesse): We should also timeout after the initial frame to prevent
// bad experiences, but we have to be careful to handle things like splash
// screens correctly. For now just ensure we receive a first frame.
if (!web_xr_mode_ || webvr_frames_received_ > 0) {
if (!webvr_frame_timeout_.IsCancelled())
webvr_frame_timeout_.Cancel();
if (!webvr_spinner_timeout_.IsCancelled())
webvr_spinner_timeout_.Cancel();
if (!webxr_mode() || webxr_frames_received() > 0) {
CancelWebXrFrameTimeout();
return;
}
if (CanSendWebXrVSync() && submit_client_) {
webvr_spinner_timeout_.Reset(base::BindOnce(
&GvrSchedulerDelegate::OnWebXrTimeoutImminent, base::Unretained(this)));
task_runner_->PostDelayedTask(
FROM_HERE, webvr_spinner_timeout_.callback(),
base::TimeDelta::FromSeconds(kWebVrSpinnerTimeoutSeconds));
webvr_frame_timeout_.Reset(base::BindOnce(
&GvrSchedulerDelegate::OnWebXrFrameTimedOut, base::Unretained(this)));
task_runner_->PostDelayedTask(
FROM_HERE, webvr_frame_timeout_.callback(),
base::TimeDelta::FromSeconds(kWebVrInitialFrameTimeoutSeconds));
}
if (CanSendWebXrVSync() && submit_client_)
ScheduleWebXrFrameTimeout();
}
bool GvrSchedulerDelegate::CanSendWebXrVSync() const {
return web_xr_mode_ && !showing_vr_dialog_;
}
void GvrSchedulerDelegate::OnWebXrFrameTimedOut() {
DCHECK(ui_);
ui_->OnWebXrTimedOut();
}
void GvrSchedulerDelegate::OnWebXrTimeoutImminent() {
DCHECK(ui_);
ui_->OnWebXrTimeoutImminent();
return webxr_mode() && !showing_vr_dialog_;
}
void GvrSchedulerDelegate::OnVSync(base::TimeTicks frame_time) {
......@@ -468,7 +434,7 @@ void GvrSchedulerDelegate::DrawFrame(int16_t frame_index,
}
DCHECK(browser_renderer_);
if (web_xr_mode_ && !ShouldDrawWebVr()) {
if (webxr_mode() && !ShouldDrawWebVr()) {
// We're in a WebVR session, but don't want to draw WebVR frames, i.e.
// because UI has taken over for a permissions prompt. Do state cleanup if
// needed.
......@@ -597,7 +563,7 @@ void GvrSchedulerDelegate::SubmitDrawnFrame(bool is_webxr_frame) {
webxr_delayed_gvr_submit_.Reset(
base::BindRepeating(&GvrSchedulerDelegate::DrawFrameSubmitWhenReady,
base::Unretained(this)));
task_runner_->PostTask(
task_runner()->PostTask(
FROM_HERE,
base::BindOnce(webxr_delayed_gvr_submit_.callback(), is_webxr_frame,
submit_head_pose, base::Passed(&fence)));
......@@ -632,13 +598,13 @@ void GvrSchedulerDelegate::DrawFrameSubmitWhenReady(
// avoids excessive waiting on devices which don't handle timeouts
// correctly. Downside is that the completion status is only detected
// with a delay of up to one polling interval.
task_runner_->PostDelayedTask(
task_runner()->PostDelayedTask(
FROM_HERE,
base::BindOnce(webxr_delayed_gvr_submit_.callback(), is_webxr_frame,
head_pose, base::Passed(&fence)),
kWebVRFenceCheckPollInterval);
} else {
task_runner_->PostTask(
task_runner()->PostTask(
FROM_HERE,
base::BindOnce(webxr_delayed_gvr_submit_.callback(), is_webxr_frame,
head_pose, base::Passed(&fence)));
......@@ -771,7 +737,7 @@ bool GvrSchedulerDelegate::WebVrCanAnimateFrame(bool is_from_onvsync) {
return false;
}
if (!web_xr_mode_) {
if (!webxr_mode()) {
DVLOG(2) << __func__ << ": no active session, ignore";
return false;
}
......@@ -835,7 +801,7 @@ void GvrSchedulerDelegate::WebXrTryStartAnimatingFrame(bool is_from_onvsync) {
}
bool GvrSchedulerDelegate::ShouldDrawWebVr() {
return web_xr_mode_ && !showing_vr_dialog_ && webvr_frames_received_ > 0;
return webxr_mode() && !showing_vr_dialog_ && webxr_frames_received() > 0;
}
void GvrSchedulerDelegate::WebXrCancelAnimatingFrame() {
......@@ -1132,7 +1098,7 @@ GvrSchedulerDelegate::GetGazeInputSourceState() {
}
void GvrSchedulerDelegate::ClosePresentationBindings() {
webvr_frame_timeout_.Cancel();
CancelWebXrFrameTimeout();
submit_client_.reset();
if (!get_frame_data_callback_.is_null()) {
// When this Presentation provider is going away we have to respond to
......@@ -1302,19 +1268,6 @@ bool GvrSchedulerDelegate::SubmitFrameCommon(int16_t frame_index,
return true;
}
void GvrSchedulerDelegate::OnNewWebXrFrame() {
ui_->OnWebXrFrameAvailable();
if (web_xr_mode_) {
++webvr_frames_received_;
webxr_fps_meter_.AddFrame(base::TimeTicks::Now());
TRACE_COUNTER1("gpu", "WebVR FPS", webxr_fps_meter_.GetFPS());
}
ScheduleOrCancelWebVrFrameTimeout();
}
void GvrSchedulerDelegate::ProcessWebVrFrameFromMailbox(
int16_t frame_index,
const gpu::MailboxHolder& mailbox) {
......
......@@ -17,17 +17,12 @@
#include "chrome/browser/android/vr/android_vsync_helper.h"
#include "chrome/browser/android/vr/gvr_graphics_delegate.h"
#include "chrome/browser/android/vr/web_xr_presentation_state.h"
#include "chrome/browser/vr/fps_meter.h"
#include "chrome/browser/vr/scheduler_delegate.h"
#include "chrome/browser/vr/base_scheduler_delegate.h"
#include "chrome/browser/vr/sliding_average.h"
#include "device/vr/public/mojom/vr_service.mojom.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "ui/gfx/transform.h"
namespace base {
class SingleThreadTaskRunner;
}
namespace gfx {
class GpuFence;
}
......@@ -52,15 +47,15 @@ class SlidingTimeDeltaAverage;
// Apart from scheduling, this class implements the XR providers and the
// transport logic.
class GvrSchedulerDelegate : public SchedulerDelegate,
device::mojom::XRPresentationProvider,
device::mojom::XRFrameDataProvider {
class GvrSchedulerDelegate : public BaseSchedulerDelegate,
public device::mojom::XRPresentationProvider,
public device::mojom::XRFrameDataProvider {
public:
GvrSchedulerDelegate(GlBrowserInterface* browser,
SchedulerUiInterface* ui,
gvr::GvrApi* gvr_api,
GvrGraphicsDelegate* graphics,
bool start_in_web_xr_mode,
bool start_in_webxr_mode,
bool cardboard_gamepad,
size_t sliding_time_size);
~GvrSchedulerDelegate() override;
......@@ -73,7 +68,6 @@ class GvrSchedulerDelegate : public SchedulerDelegate,
void AddInputSourceState(device::mojom::XRInputSourceStatePtr state) override;
void OnPause() override;
void OnResume() override;
void OnExitPresent() override;
void OnTriggerEvent(bool pressed) override;
void SetWebXrMode(bool enabled) override;
void SetShowingVrDialog(bool showing) override;
......@@ -86,8 +80,6 @@ class GvrSchedulerDelegate : public SchedulerDelegate,
void GvrInit();
void ScheduleOrCancelWebVrFrameTimeout();
bool CanSendWebXrVSync() const;
void OnWebXrTimeoutImminent();
void OnWebXrFrameTimedOut();
void OnVSync(base::TimeTicks frame_time);
void DrawFrame(int16_t frame_index, base::TimeTicks current_time);
void WebVrSendRenderNotification(bool was_rendered);
......@@ -164,7 +156,6 @@ class GvrSchedulerDelegate : public SchedulerDelegate,
bool SubmitFrameCommon(int16_t frame_index, base::TimeDelta time_waited);
bool IsSubmitFrameExpected(int16_t frame_index);
void OnNewWebXrFrame();
void OnWebXrTokenSignaled(int16_t frame_index,
std::unique_ptr<gfx::GpuFence> gpu_fence);
......@@ -179,14 +170,12 @@ class GvrSchedulerDelegate : public SchedulerDelegate,
GlBrowserInterface* browser_;
gvr::GvrApi* gvr_api_;
SchedulerUiInterface* ui_ = nullptr;
SchedulerBrowserRendererInterface* browser_renderer_ = nullptr;
// Set from feature flags.
const bool webvr_vsync_align_;
WebXrPresentationState webxr_;
bool web_xr_mode_ = false;
bool showing_vr_dialog_ = false;
bool cardboard_gamepad_ = false;
// TODO(acondor): Move trigger data to controller delegate.
......@@ -202,10 +191,6 @@ class GvrSchedulerDelegate : public SchedulerDelegate,
bool webxr_use_shared_buffer_draw_ = false;
AndroidVSyncHelper vsync_helper_;
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
base::CancelableOnceClosure webvr_frame_timeout_;
base::CancelableOnceClosure webvr_spinner_timeout_;
gfx::Transform head_pose_;
......@@ -214,7 +199,6 @@ class GvrSchedulerDelegate : public SchedulerDelegate,
std::vector<device::mojom::XRInputSourceStatePtr> input_states_;
device::mojom::XRPresentationClientPtr submit_client_;
uint64_t webvr_frames_received_ = 0;
base::queue<uint16_t> pending_frames_;
base::queue<std::pair<WebXrPresentationState::FrameIndexType, WebVrBounds>>
......@@ -252,7 +236,6 @@ class GvrSchedulerDelegate : public SchedulerDelegate,
std::unique_ptr<ScopedGpuTrace> gpu_trace_;
FPSMeter vr_ui_fps_meter_;
FPSMeter webxr_fps_meter_;
// Render time is from JS submitFrame to estimated render completion.
// This is an estimate when submitting incomplete frames to GVR.
......
......@@ -198,6 +198,8 @@ component("vr_common") {
sources = [
"base_graphics_delegate.cc",
"base_graphics_delegate.h",
"base_scheduler_delegate.cc",
"base_scheduler_delegate.h",
"browser_renderer.cc",
"browser_renderer.h",
"browser_renderer_browser_interface.h",
......
// Copyright 2018 The Chromium 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 "chrome/browser/vr/base_scheduler_delegate.h"
#include "chrome/browser/vr/scheduler_ui_interface.h"
namespace vr {
BaseSchedulerDelegate::BaseSchedulerDelegate(SchedulerUiInterface* ui,
bool start_in_webxr_mode,
int webxr_spinner_timeout,
int webxr_initial_frame_timeout)
: ui_(ui),
webxr_mode_(start_in_webxr_mode),
webxr_spinner_timeout_seconds_(webxr_spinner_timeout),
webxr_initial_frame_timeout_seconds_(webxr_initial_frame_timeout),
task_runner_(base::ThreadTaskRunnerHandle::Get()) {}
BaseSchedulerDelegate::~BaseSchedulerDelegate() = default;
void BaseSchedulerDelegate::OnExitPresent() {
CancelWebXrFrameTimeout();
}
void BaseSchedulerDelegate::SetWebXrMode(bool enabled) {
if (webxr_mode_ == enabled)
return;
webxr_mode_ = enabled;
if (webxr_mode_)
ResetWebXrFramesReceived();
else
CancelWebXrFrameTimeout();
}
void BaseSchedulerDelegate::ScheduleWebXrFrameTimeout() {
DCHECK(ui_);
webxr_spinner_timeout_closure_.Reset(base::BindOnce(
&SchedulerUiInterface::OnWebXrTimeoutImminent, base::Unretained(ui_)));
task_runner_->PostDelayedTask(
FROM_HERE, webxr_spinner_timeout_closure_.callback(),
base::TimeDelta::FromSeconds(webxr_spinner_timeout_seconds_));
webxr_frame_timeout_closure_.Reset(base::BindOnce(
&SchedulerUiInterface::OnWebXrTimedOut, base::Unretained(ui_)));
task_runner_->PostDelayedTask(
FROM_HERE, webxr_frame_timeout_closure_.callback(),
base::TimeDelta::FromSeconds(webxr_initial_frame_timeout_seconds_));
}
void BaseSchedulerDelegate::CancelWebXrFrameTimeout() {
if (!webxr_spinner_timeout_closure_.IsCancelled())
webxr_spinner_timeout_closure_.Cancel();
if (!webxr_frame_timeout_closure_.IsCancelled())
webxr_frame_timeout_closure_.Cancel();
}
void BaseSchedulerDelegate::OnNewWebXrFrame() {
ui_->OnWebXrFrameAvailable();
if (webxr_mode_) {
TickWebXrFramesReceived();
webxr_fps_meter_.AddFrame(base::TimeTicks::Now());
TRACE_COUNTER1("gpu", "WebVR FPS", webxr_fps_meter_.GetFPS());
}
CancelWebXrFrameTimeout();
}
} // namespace vr
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_VR_BASE_SCHEDULER_DELEGATE_H_
#define CHROME_BROWSER_VR_BASE_SCHEDULER_DELEGATE_H_
#include "base/cancelable_callback.h"
#include "chrome/browser/vr/fps_meter.h"
#include "chrome/browser/vr/scheduler_delegate.h"
#include "chrome/browser/vr/vr_export.h"
namespace base {
class TaskRunner;
}
namespace vr {
class SchedulerUiInterface;
class VR_EXPORT BaseSchedulerDelegate : public SchedulerDelegate {
public:
BaseSchedulerDelegate(SchedulerUiInterface* ui,
bool start_in_webxr_mode,
int webxr_spinner_timeout,
int webxr_initial_frame_timeout);
~BaseSchedulerDelegate() override;
// SchedulerDelegate implementations.
void OnExitPresent() override;
void SetWebXrMode(bool enabled) override;
protected:
void ScheduleWebXrFrameTimeout();
void CancelWebXrFrameTimeout();
void OnNewWebXrFrame();
bool webxr_mode() const { return webxr_mode_; }
uint64_t webxr_frames_received() const { return webxr_frames_received_; }
void TickWebXrFramesReceived() { ++webxr_frames_received_; }
void ResetWebXrFramesReceived() { webxr_frames_received_ = 0; }
base::TaskRunner* task_runner() { return task_runner_.get(); }
private:
SchedulerUiInterface* ui_;
bool webxr_mode_ = false;
int webxr_frames_received_ = 0;
int webxr_spinner_timeout_seconds_;
int webxr_initial_frame_timeout_seconds_;
FPSMeter webxr_fps_meter_;
base::CancelableOnceClosure webxr_frame_timeout_closure_;
base::CancelableOnceClosure webxr_spinner_timeout_closure_;
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
DISALLOW_COPY_AND_ASSIGN(BaseSchedulerDelegate);
};
} // namespace vr
#endif // CHROME_BROWSER_VR_BASE_SCHEDULER_DELEGATE_H_
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