blob: 6005117f1b2e865b5f5861f5e77335e04932c59f [file] [log] [blame]
// Copyright 2016 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_SHELL_VR_SHELL_GL_H_
#define CHROME_BROWSER_ANDROID_VR_SHELL_VR_SHELL_GL_H_
#include <memory>
#include <utility>
#include <vector>
#include "base/cancelable_callback.h"
#include "base/containers/queue.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/single_thread_task_runner.h"
#include "chrome/browser/android/vr_shell/android_vsync_helper.h"
#include "chrome/browser/android/vr_shell/vr_controller.h"
#include "chrome/browser/vr/assets_load_status.h"
#include "chrome/browser/vr/content_input_delegate.h"
#include "chrome/browser/vr/controller_mesh.h"
#include "chrome/browser/vr/fps_meter.h"
#include "chrome/browser/vr/model/controller_model.h"
#include "chrome/browser/vr/sliding_average.h"
#include "chrome/browser/vr/ui_input_manager.h"
#include "chrome/browser/vr/ui_renderer.h"
#include "device/vr/vr_service.mojom.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "third_party/gvr-android-sdk/src/libraries/headers/vr/gvr/capi/include/gvr.h"
#include "third_party/gvr-android-sdk/src/libraries/headers/vr/gvr/capi/include/gvr_types.h"
#include "ui/gfx/geometry/quaternion.h"
#include "ui/gfx/geometry/rect_f.h"
#include "ui/gfx/geometry/size_f.h"
#include "ui/gfx/native_widget_types.h"
namespace base {
class Version;
} // namespace base
namespace gl {
class GLContext;
class GLFenceEGL;
class GLSurface;
class ScopedJavaSurface;
class SurfaceTexture;
} // namespace gl
namespace gpu {
struct MailboxHolder;
} // namespace gpu
namespace vr {
class BrowserUiInterface;
class FPSMeter;
class SlidingTimeDeltaAverage;
class Ui;
struct Assets;
} // namespace vr
namespace vr_shell {
class MailboxToSurfaceBridge;
class GlBrowserInterface;
class VrController;
class VrShell;
struct WebVrBounds {
WebVrBounds(const gfx::RectF& left,
const gfx::RectF& right,
const gfx::Size& size)
: left_bounds(left), right_bounds(right), source_size(size) {}
gfx::RectF left_bounds;
gfx::RectF right_bounds;
gfx::Size source_size;
};
// This class manages all GLThread owned objects and GL rendering for VrShell.
// It is not threadsafe and must only be used on the GL thread.
class VrShellGl : public device::mojom::VRPresentationProvider {
public:
VrShellGl(GlBrowserInterface* browser_interface,
std::unique_ptr<vr::Ui> ui,
gvr_context* gvr_api,
bool reprojected_rendering,
bool daydream_support,
bool start_in_web_vr_mode);
~VrShellGl() override;
void Initialize();
void InitializeGl(gfx::AcceleratedWidget window);
void OnTriggerEvent();
void OnPause();
void OnResume();
void OnExitPresent();
base::WeakPtr<vr::BrowserUiInterface> GetBrowserUiWeakPtr();
scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner() {
return task_runner_;
}
void SetWebVrMode(bool enabled);
void CreateOrResizeWebVRSurface(const gfx::Size& size);
void CreateContentSurface();
void ContentBoundsChanged(int width, int height);
void ContentPhysicalBoundsChanged(int width, int height);
void UIBoundsChanged(int width, int height);
void UIPhysicalBoundsChanged(int width, int height);
base::WeakPtr<VrShellGl> GetWeakPtr();
void SetControllerMesh(std::unique_ptr<vr::ControllerMesh> mesh);
void ConnectPresentingService(
device::mojom::VRSubmitFrameClientPtrInfo submit_client_info,
device::mojom::VRPresentationProviderRequest request,
device::mojom::VRDisplayInfoPtr display_info,
device::mojom::VRRequestPresentOptionsPtr present_options);
void set_is_exiting(bool exiting) { is_exiting_ = exiting; }
void OnSwapContents(int new_content_id);
void OnAssetsLoaded(vr::AssetsLoadStatus status,
std::unique_ptr<vr::Assets> assets,
const base::Version& component_version);
private:
void GvrInit(gvr_context* gvr_api);
device::mojom::VRDisplayFrameTransportOptionsPtr
GetWebVrFrameTransportOptions();
void InitializeRenderer();
// Returns true if successfully resized.
bool ResizeForWebVR(int16_t frame_index);
void UpdateSamples();
void UpdateEyeInfos(const gfx::Transform& head_pose,
int viewport_offset,
const gfx::Size& render_size,
vr::RenderInfo* out_render_info);
void DrawFrame(int16_t frame_index, base::TimeTicks current_time);
void DrawIntoAcquiredFrame(int16_t frame_index, base::TimeTicks current_time);
void DrawFrameSubmitWhenReady(int16_t frame_index,
const gfx::Transform& head_pose,
std::unique_ptr<gl::GLFenceEGL> fence);
void DrawFrameSubmitNow(int16_t frame_index, const gfx::Transform& head_pose);
bool ShouldDrawWebVr();
void DrawWebVr();
bool WebVrPoseByteIsValid(int pose_index_byte);
void UpdateController(const gfx::Transform& head_pose,
base::TimeTicks current_time);
void SendImmediateExitRequestIfNecessary();
void HandleControllerInput(const gfx::Point3F& laser_origin,
const gfx::Vector3dF& head_direction,
base::TimeTicks current_time);
void HandleControllerAppButtonActivity(
const gfx::Vector3dF& controller_direction);
void OnContentFrameAvailable();
void OnWebVRFrameAvailable();
void ScheduleOrCancelWebVrFrameTimeout();
void OnWebVrTimeoutImminent();
void OnWebVrFrameTimedOut();
base::TimeDelta GetPredictedFrameTime();
void AddWebVrRenderTimeEstimate(int16_t frame_index,
base::TimeTicks submit_start,
base::TimeTicks submit_done);
void OnVSync(base::TimeTicks frame_time);
// VRPresentationProvider
void GetVSync(GetVSyncCallback callback) 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 UpdateLayerBounds(int16_t frame_index,
const gfx::RectF& left_bounds,
const gfx::RectF& right_bounds,
const gfx::Size& source_size) override;
void ForceExitVr();
bool ShouldSkipVSync();
void SendVSync(base::TimeTicks time, GetVSyncCallback callback);
void ClosePresentationBindings();
// samplerExternalOES texture data for WebVR content image.
int webvr_texture_id_ = 0;
// Set from feature flags.
bool webvr_vsync_align_;
scoped_refptr<gl::GLSurface> surface_;
scoped_refptr<gl::GLContext> context_;
scoped_refptr<gl::SurfaceTexture> content_surface_texture_;
scoped_refptr<gl::SurfaceTexture> webvr_surface_texture_;
std::unique_ptr<gl::ScopedJavaSurface> content_surface_;
std::unique_ptr<gvr::GvrApi> gvr_api_;
std::unique_ptr<gvr::BufferViewportList> buffer_viewport_list_;
std::unique_ptr<gvr::BufferViewport> buffer_viewport_;
std::unique_ptr<gvr::BufferViewport> webvr_browser_ui_left_viewport_;
std::unique_ptr<gvr::BufferViewport> webvr_browser_ui_right_viewport_;
std::unique_ptr<gvr::BufferViewport> webvr_left_viewport_;
std::unique_ptr<gvr::BufferViewport> webvr_right_viewport_;
std::unique_ptr<gvr::SwapChain> swap_chain_;
gvr::Frame acquired_frame_;
base::queue<std::pair<uint8_t, WebVrBounds>> pending_bounds_;
int premature_received_frames_ = 0;
base::queue<uint16_t> pending_frames_;
std::unique_ptr<MailboxToSurfaceBridge> mailbox_bridge_;
// The default size for the render buffers.
gfx::Size render_size_default_;
gfx::Size render_size_webvr_ui_;
// WebVR currently supports multiple render path choices, with runtime
// selection based on underlying support being available and feature flags.
// The webvr_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 webvr_use_gpu_fence_ = false;
int webvr_unstuff_ratelimit_frames_ = 0;
bool cardboard_ = false;
gfx::Quaternion controller_quat_;
gfx::Size content_tex_physical_size_ = {0, 0};
gfx::Size webvr_surface_size_ = {0, 0};
std::vector<base::TimeTicks> webvr_time_pose_;
std::vector<base::TimeTicks> webvr_time_js_submit_;
std::vector<bool> webvr_frame_oustanding_;
std::vector<gfx::Transform> webvr_head_pose_;
std::unique_ptr<vr::Ui> ui_;
bool web_vr_mode_ = false;
bool ready_to_draw_ = false;
bool paused_ = true;
const bool surfaceless_rendering_;
bool daydream_support_;
bool is_exiting_ = false;
std::unique_ptr<VrController> controller_;
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
// Attributes tracking WebVR rAF/VSync animation loop state. Blink schedules
// a callback using the GetVSync mojo call, and the callback is either passed
// to SendVSync immediately, or deferred until the next OnVSync call.
//
// pending_vsync_ is set to true in OnVSync if there is no current
// outstanding callback, and this means that a future GetVSync is permitted
// to execute SendVSync immediately. If it is false, GetVSync must store the
// pending callback in callback_ for later execution.
base::TimeTicks pending_time_;
bool pending_vsync_ = false;
GetVSyncCallback callback_;
mojo::Binding<device::mojom::VRPresentationProvider> binding_;
device::mojom::VRSubmitFrameClientPtr submit_client_;
GlBrowserInterface* browser_;
uint8_t frame_index_ = 0;
// Larger than frame_index_ so it can be initialized out-of-band.
uint16_t last_frame_index_ = -1;
uint64_t webvr_frames_received_ = 0;
// Attributes for gesture detection while holding app button.
gfx::Vector3dF controller_start_direction_;
vr::FPSMeter fps_meter_;
// JS time is from SendVSync (pose time) to incoming JS submitFrame.
vr::SlidingTimeDeltaAverage webvr_js_time_;
// 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.
vr::SlidingTimeDeltaAverage webvr_render_time_;
// JS wait time is spent waiting for the previous frame to complete
// rendering, as reported from the Renderer via mojo.
vr::SlidingTimeDeltaAverage webvr_js_wait_time_;
// GVR acquire/submit times for scheduling heuristics.
vr::SlidingTimeDeltaAverage webvr_acquire_time_;
vr::SlidingTimeDeltaAverage webvr_submit_time_;
gfx::Point3F pointer_start_;
vr::RenderInfo render_info_primary_;
AndroidVSyncHelper vsync_helper_;
base::CancelableCallback<void()> webvr_frame_timeout_;
base::CancelableCallback<void()> webvr_spinner_timeout_;
base::CancelableCallback<
void(int16_t, const gfx::Transform&, std::unique_ptr<gl::GLFenceEGL>)>
webvr_delayed_frame_submit_;
std::vector<gvr::BufferSpec> specs_;
bool content_frame_available_ = false;
gfx::Transform last_used_head_pose_;
vr::ControllerModel controller_model_;
base::WeakPtrFactory<VrShellGl> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(VrShellGl);
};
} // namespace vr_shell
#endif // CHROME_BROWSER_ANDROID_VR_SHELL_VR_SHELL_GL_H_