blob: 7b733d90e3424568c72e47c34b254cc2197cde98 [file] [log] [blame]
// 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_ANDROID_VR_GVR_SCHEDULER_DELEGATE_H_
#define CHROME_BROWSER_ANDROID_VR_GVR_SCHEDULER_DELEGATE_H_
#include <limits>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "base/cancelable_callback.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#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/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 gfx {
class GpuFence;
}
namespace gl {
class GLFenceAndroidNativeFenceSync;
class GLFenceEGL;
class SurfaceTexture;
} // namespace gl
namespace gvr {
class GvrApi;
}
namespace vr {
class GlBrowserInterface;
class MailboxToSurfaceBridge;
class SchedulerUiInterface;
class ScopedGpuTrace;
class SlidingTimeDeltaAverage;
// Apart from scheduling, this class implements the XR providers and the
// transport logic.
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_webxr_mode,
bool cardboard_gamepad,
size_t sliding_time_size);
~GvrSchedulerDelegate() override;
WebXrPresentationState* webxr() { return &webxr_; }
private:
// SchedulerDelegate overrides.
void AddInputSourceState(device::mojom::XRInputSourceStatePtr state) override;
void OnPause() override;
void OnResume() override;
void SetWebXrMode(bool enabled) override;
void SetShowingVrDialog(bool showing) override;
void SubmitDrawnFrame(FrameType frame_type,
const gfx::Transform& head_pose) override;
void SetBrowserRenderer(
SchedulerBrowserRendererInterface* browser_renderer) override;
void ConnectPresentingService(
device::mojom::VRDisplayInfoPtr display_info,
device::mojom::XRRuntimeSessionOptionsPtr options) override;
void GvrInit();
void ScheduleOrCancelWebVrFrameTimeout();
bool CanSendWebXrVSync() const;
void OnVSync(base::TimeTicks frame_time);
void DrawFrame(int16_t frame_index, base::TimeTicks current_time);
void WebVrSendRenderNotification(bool was_rendered);
void UpdatePendingBounds(int16_t frame_index);
void DrawFrameSubmitWhenReady(FrameType frame_type,
const gfx::Transform& head_pose,
std::unique_ptr<gl::GLFenceEGL> fence);
void DrawFrameSubmitNow(FrameType frame_type,
const gfx::Transform& head_pose);
// Used for discarding unwanted WebXR frames while UI is showing. We can't
// safely cancel frames from processing start until they show up in
// OnWebXrFrameAvailable, so only support cancelling them before or after
// that lifecycle segment.
void WebXrCancelAnimatingFrame();
void WebXrCancelProcessingFrameAfterTransfer();
// Sends a GetFrameData response to the presentation client.
void SendVSync();
void WebXrPrepareSharedBuffer();
void WebXrCreateOrResizeSharedBufferImage(WebXrSharedBuffer* buffer,
const gfx::Size& size);
// Checks if we're in a valid state for starting animation of a new frame.
// Invalid states include a previous animating frame that's not complete
// yet (including deferred processing not having started yet), or timing
// heuristics indicating that it should be retried later.
bool WebVrCanAnimateFrame(bool is_from_onvsync);
// Call this after state changes that could result in WebVrCanAnimateFrame
// becoming true.
void WebXrTryStartAnimatingFrame(bool is_from_onvsync);
bool ShouldDrawWebVr();
// Heuristics to avoid excessive backlogged frames.
bool WebVrHasSlowRenderingFrame();
bool WebVrHasOverstuffedBuffers();
base::TimeDelta GetPredictedFrameTime();
device::mojom::XRPresentationTransportOptionsPtr
GetWebXrFrameTransportOptions(
const device::mojom::XRRuntimeSessionOptionsPtr&);
void CreateOrResizeWebXrSurface(const gfx::Size& size);
void OnWebXrFrameAvailable();
void CreateSurfaceBridge(gl::SurfaceTexture* surface_texture);
void OnGpuProcessConnectionReady();
void ClosePresentationBindings();
// XRFrameDataProvider
void GetFrameData(device::mojom::XRFrameDataProvider::GetFrameDataCallback
callback) override;
void GetEnvironmentIntegrationProvider(
device::mojom::XREnvironmentIntegrationProviderAssociatedRequest
environment_provider) override;
// XRPresentationProvider
void SubmitFrameMissing(int16_t frame_index, const gpu::SyncToken&) override;
void SubmitFrame(int16_t frame_index,
const gpu::MailboxHolder& mailbox,
base::TimeDelta time_waited) override;
void SubmitFrameWithTextureHandle(int16_t frame_index,
mojo::ScopedHandle texture_handle) override;
void SubmitFrameDrawnIntoTexture(int16_t frame_index,
const gpu::SyncToken&,
base::TimeDelta time_waited) override;
void UpdateLayerBounds(int16_t frame_index,
const gfx::RectF& left_bounds,
const gfx::RectF& right_bounds,
const gfx::Size& source_size) override;
// Shared logic for SubmitFrame variants, including sanity checks.
// Returns true if OK to proceed.
bool SubmitFrameCommon(int16_t frame_index, base::TimeDelta time_waited);
bool IsSubmitFrameExpected(int16_t frame_index);
void OnWebXrTokenSignaled(int16_t frame_index,
std::unique_ptr<gfx::GpuFence> gpu_fence);
// Transition a frame from animating to processing.
void ProcessWebVrFrameFromMailbox(int16_t frame_index,
const gpu::MailboxHolder& mailbox);
void ProcessWebVrFrameFromGMB(int16_t frame_index,
const gpu::SyncToken& sync_token);
void AddWebVrRenderTimeEstimate(base::TimeTicks fence_complete_time);
GlBrowserInterface* browser_;
gvr::GvrApi* gvr_api_;
SchedulerBrowserRendererInterface* browser_renderer_ = nullptr;
// Set from feature flags.
const bool webvr_vsync_align_;
WebXrPresentationState webxr_;
bool showing_vr_dialog_ = false;
bool cardboard_gamepad_ = false;
// WebXR currently supports multiple render path choices, with runtime
// selection based on underlying support being available and feature flags.
// The webxr_use_* booleans choose among the implementations. Please don't
// check WebXrRenderPath or other feature flags in individual code paths
// directly to avoid inconsistent logic.
bool webxr_use_gpu_fence_ = false;
bool webxr_use_shared_buffer_draw_ = false;
AndroidVSyncHelper vsync_helper_;
mojo::Binding<device::mojom::XRPresentationProvider> presentation_binding_;
mojo::Binding<device::mojom::XRFrameDataProvider> frame_data_binding_;
std::vector<device::mojom::XRInputSourceStatePtr> input_states_;
device::mojom::XRPresentationClientPtr submit_client_;
base::queue<uint16_t> pending_frames_;
base::queue<std::pair<WebXrPresentationState::FrameIndexType, WebVrBounds>>
pending_bounds_;
int webvr_unstuff_ratelimit_frames_ = 0;
GvrGraphicsDelegate* graphics_;
// Attributes tracking WebVR rAF/VSync animation loop state. Blink schedules
// a callback using the GetFrameData mojo call which is stored in
// get_frame_data_callback_. The callback is executed by SendVSync once
// WebVrCanAnimateFrame returns true.
//
// webxr_vsync_pending_ is set to true in OnVSync and false in SendVSync. It
// throttles animation to no faster than the VSync rate. The pending_time_ is
// updated in OnVSync and used as the rAF animation timer in SendVSync.
base::TimeTicks pending_time_;
bool webxr_vsync_pending_ = false;
device::mojom::XRFrameDataProvider::GetFrameDataCallback
get_frame_data_callback_;
// A fence used to avoid overstuffed GVR buffers in WebVR mode.
std::unique_ptr<gl::GLFenceAndroidNativeFenceSync>
webvr_prev_frame_completion_fence_;
// WebXR defers submitting a frame to GVR by scheduling a closure
// for later. If we exit WebVR before it is executed, we need to
// cancel it to avoid inconsistent state.
base::CancelableOnceCallback<
void(FrameType, const gfx::Transform&, std::unique_ptr<gl::GLFenceEGL>)>
webxr_delayed_gvr_submit_;
std::unique_ptr<MailboxToSurfaceBridge> mailbox_bridge_;
std::unique_ptr<ScopedGpuTrace> gpu_trace_;
FPSMeter vr_ui_fps_meter_;
// Render time is from JS submitFrame to estimated render completion.
// This is an estimate when submitting incomplete frames to GVR.
// If submitFrame blocks, that means the previous frame wasn't done
// rendering yet.
SlidingTimeDeltaAverage webvr_render_time_;
// JS time is from SendVSync (pose time) to incoming JS submitFrame.
SlidingTimeDeltaAverage webvr_js_time_;
// JS wait time is spent waiting for the previous frame to complete
// rendering, as reported from the Renderer via mojo.
SlidingTimeDeltaAverage webvr_js_wait_time_;
base::WeakPtrFactory<GvrSchedulerDelegate> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(GvrSchedulerDelegate);
};
} // namespace vr
#endif // CHROME_BROWSER_ANDROID_VR_GVR_SCHEDULER_DELEGATE_H_