Commit cee3abc6 authored by Bill Orr's avatar Bill Orr Committed by Commit Bot

Implement stub BrowserRenderer delegates and start up BrowserRenderer

This change defines Graphics, Input, and Scheduler delegates that can
interact with BrowerRenderer to render in-headset VR UI.

With this change, the delegates are mostly defined and parts necessary
to render are implemented, but VR UI doesn't yet actually render any UI
on desktop.

BUG=819448

Change-Id: I8d50e200e2380ae2113454eaf77cd1c53f369554
Reviewed-on: https://chromium-review.googlesource.com/c/1306402
Commit-Queue: Bill Orr <billorr@chromium.org>
Reviewed-by: default avatarKlaus Weidner <klausw@chromium.org>
Cr-Commit-Position: refs/heads/master@{#605897}
parent 1e054843
...@@ -738,10 +738,6 @@ void GvrGraphicsDelegate::SubmitToGvr(const gfx::Transform& head_pose) { ...@@ -738,10 +738,6 @@ void GvrGraphicsDelegate::SubmitToGvr(const gfx::Transform& head_pose) {
} }
} }
void GvrGraphicsDelegate::OnResume() {
viewports_need_updating_ = true;
}
void GvrGraphicsDelegate::BufferBoundsChanged( void GvrGraphicsDelegate::BufferBoundsChanged(
const gfx::Size& content_buffer_size, const gfx::Size& content_buffer_size,
const gfx::Size& overlay_buffer_size) { const gfx::Size& overlay_buffer_size) {
......
...@@ -115,7 +115,6 @@ class GvrGraphicsDelegate : public BaseGraphicsDelegate { ...@@ -115,7 +115,6 @@ class GvrGraphicsDelegate : public BaseGraphicsDelegate {
private: private:
// GraphicsDelegate overrides. // GraphicsDelegate overrides.
void OnResume() override;
FovRectangles GetRecommendedFovs() override; FovRectangles GetRecommendedFovs() override;
float GetZNear() override; float GetZNear() override;
RenderInfo GetRenderInfo(FrameType frame_type, RenderInfo GetRenderInfo(FrameType frame_type,
......
...@@ -296,8 +296,12 @@ component("vr_common") { ...@@ -296,8 +296,12 @@ component("vr_common") {
sources += [ sources += [
"service/isolated_device_provider.cc", "service/isolated_device_provider.cc",
"service/isolated_device_provider.h", "service/isolated_device_provider.h",
"win/simple_overlay_renderer_win.cc", "win/graphics_delegate_win.cc",
"win/simple_overlay_renderer_win.h", "win/graphics_delegate_win.h",
"win/input_delegate_win.cc",
"win/input_delegate_win.h",
"win/scheduler_delegate_win.cc",
"win/scheduler_delegate_win.h",
"win/vr_browser_renderer_thread_win.cc", "win/vr_browser_renderer_thread_win.cc",
"win/vr_browser_renderer_thread_win.h", "win/vr_browser_renderer_thread_win.h",
"win/vr_renderloop_host_win.cc", "win/vr_renderloop_host_win.cc",
......
...@@ -28,13 +28,13 @@ BrowserRenderer::BrowserRenderer( ...@@ -28,13 +28,13 @@ BrowserRenderer::BrowserRenderer(
std::unique_ptr<InputDelegate> input_delegate, std::unique_ptr<InputDelegate> input_delegate,
BrowserRendererBrowserInterface* browser, BrowserRendererBrowserInterface* browser,
size_t sliding_time_size) size_t sliding_time_size)
: ui_(std::move(ui)), : scheduler_delegate_(std::move(scheduler_delegate)),
scheduler_delegate_(std::move(scheduler_delegate)),
graphics_delegate_(std::move(graphics_delegate)), graphics_delegate_(std::move(graphics_delegate)),
input_delegate_(std::move(input_delegate)), input_delegate_(std::move(input_delegate)),
browser_(browser), browser_(browser),
ui_processing_time_(sliding_time_size), ui_processing_time_(sliding_time_size),
ui_controller_update_time_(sliding_time_size), ui_controller_update_time_(sliding_time_size),
ui_(std::move(ui)),
weak_ptr_factory_(this) { weak_ptr_factory_(this) {
scheduler_delegate_->SetBrowserRenderer(this); scheduler_delegate_->SetBrowserRenderer(this);
} }
......
...@@ -112,7 +112,6 @@ class VR_EXPORT BrowserRenderer : public SchedulerBrowserRendererInterface { ...@@ -112,7 +112,6 @@ class VR_EXPORT BrowserRenderer : public SchedulerBrowserRendererInterface {
const base::TimeTicks& current_time); const base::TimeTicks& current_time);
void ReportElementVisibilityResultForTesting(UiTestOperationResult result); void ReportElementVisibilityResultForTesting(UiTestOperationResult result);
std::unique_ptr<UiInterface> ui_;
std::unique_ptr<SchedulerDelegate> scheduler_delegate_; std::unique_ptr<SchedulerDelegate> scheduler_delegate_;
std::unique_ptr<GraphicsDelegate> graphics_delegate_; std::unique_ptr<GraphicsDelegate> graphics_delegate_;
std::unique_ptr<InputDelegate> input_delegate_; std::unique_ptr<InputDelegate> input_delegate_;
...@@ -129,6 +128,10 @@ class VR_EXPORT BrowserRenderer : public SchedulerBrowserRendererInterface { ...@@ -129,6 +128,10 @@ class VR_EXPORT BrowserRenderer : public SchedulerBrowserRendererInterface {
SlidingTimeDeltaAverage ui_processing_time_; SlidingTimeDeltaAverage ui_processing_time_;
SlidingTimeDeltaAverage ui_controller_update_time_; SlidingTimeDeltaAverage ui_controller_update_time_;
// ui_ is using gl contexts during destruction (skia context specifically), so
// it must be destroyed before graphics_delegate_.
std::unique_ptr<UiInterface> ui_;
base::WeakPtrFactory<BrowserRenderer> weak_ptr_factory_; base::WeakPtrFactory<BrowserRenderer> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(BrowserRenderer); DISALLOW_COPY_AND_ASSIGN(BrowserRenderer);
......
...@@ -5,7 +5,10 @@ ...@@ -5,7 +5,10 @@
#ifndef CHROME_BROWSER_VR_GRAPHICS_DELEGATE_H_ #ifndef CHROME_BROWSER_VR_GRAPHICS_DELEGATE_H_
#define CHROME_BROWSER_VR_GRAPHICS_DELEGATE_H_ #define CHROME_BROWSER_VR_GRAPHICS_DELEGATE_H_
#include <string>
#include "base/callback_forward.h" #include "base/callback_forward.h"
#include "base/memory/scoped_refptr.h"
#include "chrome/browser/vr/fov_rectangle.h" #include "chrome/browser/vr/fov_rectangle.h"
#include "chrome/browser/vr/frame_type.h" #include "chrome/browser/vr/frame_type.h"
#include "chrome/browser/vr/gl_texture_location.h" #include "chrome/browser/vr/gl_texture_location.h"
...@@ -34,8 +37,6 @@ class VR_EXPORT GraphicsDelegate { ...@@ -34,8 +37,6 @@ class VR_EXPORT GraphicsDelegate {
void(GlTextureLocation, unsigned int, unsigned int, unsigned int)>; void(GlTextureLocation, unsigned int, unsigned int, unsigned int)>;
virtual ~GraphicsDelegate() {} virtual ~GraphicsDelegate() {}
virtual void OnResume() = 0;
virtual FovRectangles GetRecommendedFovs() = 0; virtual FovRectangles GetRecommendedFovs() = 0;
virtual float GetZNear() = 0; virtual float GetZNear() = 0;
virtual RenderInfo GetRenderInfo(FrameType frame_type, virtual RenderInfo GetRenderInfo(FrameType frame_type,
......
...@@ -42,6 +42,11 @@ void BrowserXRRuntime::OnDisplayInfoChanged( ...@@ -42,6 +42,11 @@ void BrowserXRRuntime::OnDisplayInfoChanged(
for (XRDeviceImpl* device : renderer_device_connections_) { for (XRDeviceImpl* device : renderer_device_connections_) {
device->RuntimesChanged(); device->RuntimesChanged();
} }
// Notify observers of the new display info.
for (BrowserXRRuntimeObserver& observer : observers_) {
observer.SetVRDisplayInfo(display_info_.Clone());
}
} }
void BrowserXRRuntime::StopImmersiveSession() { void BrowserXRRuntime::StopImmersiveSession() {
......
...@@ -27,6 +27,8 @@ class XRDeviceImpl; ...@@ -27,6 +27,8 @@ class XRDeviceImpl;
// browser thread. Currently this is used on Windows to drive overlays. // browser thread. Currently this is used on Windows to drive overlays.
class BrowserXRRuntimeObserver : public base::CheckedObserver { class BrowserXRRuntimeObserver : public base::CheckedObserver {
public: public:
virtual void SetVRDisplayInfo(
device::mojom::VRDisplayInfoPtr display_info) = 0;
virtual void SetWebXRWebContents(content::WebContents* contents) = 0; virtual void SetWebXRWebContents(content::WebContents* contents) = 0;
}; };
...@@ -62,6 +64,7 @@ class BrowserXRRuntime : public device::mojom::XRRuntimeEventListener { ...@@ -62,6 +64,7 @@ class BrowserXRRuntime : public device::mojom::XRRuntimeEventListener {
// Methods called to support metrics/overlays on Windows. // Methods called to support metrics/overlays on Windows.
void AddObserver(BrowserXRRuntimeObserver* observer) { void AddObserver(BrowserXRRuntimeObserver* observer) {
observers_.AddObserver(observer); observers_.AddObserver(observer);
observer->SetVRDisplayInfo(display_info_.Clone());
} }
void RemoveObserver(BrowserXRRuntimeObserver* observer) { void RemoveObserver(BrowserXRRuntimeObserver* observer) {
observers_.RemoveObserver(observer); observers_.RemoveObserver(observer);
......
...@@ -41,7 +41,6 @@ bool GlRenderer::Initialize(const scoped_refptr<gl::GLSurface>& surface) { ...@@ -41,7 +41,6 @@ bool GlRenderer::Initialize(const scoped_refptr<gl::GLSurface>& surface) {
} }
// TODO(crbug/895313): Provide actual implementation for the methods. // TODO(crbug/895313): Provide actual implementation for the methods.
void GlRenderer::OnResume() {}
FovRectangles GlRenderer::GetRecommendedFovs() { FovRectangles GlRenderer::GetRecommendedFovs() {
return {{}, {}}; return {{}, {}};
} }
......
...@@ -27,7 +27,6 @@ class GlRenderer : public BaseGraphicsDelegate { ...@@ -27,7 +27,6 @@ class GlRenderer : public BaseGraphicsDelegate {
// GraphicsDelegate implementation. // GraphicsDelegate implementation.
bool Initialize(const scoped_refptr<gl::GLSurface>& surface) override; bool Initialize(const scoped_refptr<gl::GLSurface>& surface) override;
void OnResume() override;
FovRectangles GetRecommendedFovs() override; FovRectangles GetRecommendedFovs() override;
float GetZNear() override; float GetZNear() override;
RenderInfo GetRenderInfo(FrameType frame_type, RenderInfo GetRenderInfo(FrameType frame_type,
......
...@@ -720,6 +720,8 @@ void Ui::DrawContent(const float (&uv_transform)[16], ...@@ -720,6 +720,8 @@ void Ui::DrawContent(const float (&uv_transform)[16],
} }
void Ui::DrawWebXr(int texture_data_handle, const float (&uv_transform)[16]) { void Ui::DrawWebXr(int texture_data_handle, const float (&uv_transform)[16]) {
if (!texture_data_handle)
return;
ui_element_renderer_->DrawTextureCopy(texture_data_handle, uv_transform, 0, ui_element_renderer_->DrawTextureCopy(texture_data_handle, uv_transform, 0,
0); 0);
} }
......
This diff is collapsed.
...@@ -2,9 +2,15 @@ ...@@ -2,9 +2,15 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#ifndef CHROME_BROWSER_VR_WIN_SIMPLE_OVERLAY_RENDERER_WIN_H_ #ifndef CHROME_BROWSER_VR_WIN_GRAPHICS_DELEGATE_WIN_H_
#define CHROME_BROWSER_VR_WIN_SIMPLE_OVERLAY_RENDERER_WIN_H_ #define CHROME_BROWSER_VR_WIN_GRAPHICS_DELEGATE_WIN_H_
#include <string>
#include "base/callback.h"
#include "base/memory/scoped_refptr.h"
#include "chrome/browser/vr/graphics_delegate.h"
#include "chrome/browser/vr/render_info.h"
#include "device/vr/public/mojom/vr_service.mojom.h"
#include "gpu/GLES2/gl2extchromium.h" #include "gpu/GLES2/gl2extchromium.h"
#include "gpu/command_buffer/client/gles2_interface.h" #include "gpu/command_buffer/client/gles2_interface.h"
#include "gpu/command_buffer/client/gpu_memory_buffer_manager.h" #include "gpu/command_buffer/client/gpu_memory_buffer_manager.h"
...@@ -14,41 +20,94 @@ ...@@ -14,41 +20,94 @@
#include "services/ws/public/cpp/gpu/context_provider_command_buffer.h" #include "services/ws/public/cpp/gpu/context_provider_command_buffer.h"
#include "ui/gfx/geometry/rect_f.h" #include "ui/gfx/geometry/rect_f.h"
namespace gpu {
namespace gles2 {
class GLES2Interface;
}
} // namespace gpu
namespace vr { namespace vr {
// This class renders an simple solid-color overlay that can be submitted to class GraphicsDelegateWin : public GraphicsDelegate {
// be composited on top of WebXR content. Note that it is not used outside
// manual testing (requires build changes to enable), and will be replaced with
// VR-UI overlays.
class SimpleOverlayRenderer {
public: public:
SimpleOverlayRenderer(); using Transform = float[16];
~SimpleOverlayRenderer(); using TexturesInitializedCallback = base::OnceCallback<
void(GlTextureLocation, unsigned int, unsigned int, unsigned int)>;
GraphicsDelegateWin();
~GraphicsDelegateWin() override;
// Called on main UI thread. // Called on main UI thread.
bool InitializeOnMainThread(); bool InitializeOnMainThread();
// Called on background GL thread. // Called on background GL thread.
void InitializeOnGLThread(); void InitializeOnGLThread();
void SetVRDisplayInfo(device::mojom::VRDisplayInfoPtr info);
void Cleanup(); void Cleanup();
void Render(); void PreRender();
void PostRender();
mojo::ScopedHandle GetTexture(); mojo::ScopedHandle GetTexture();
gfx::RectF GetLeft(); gfx::RectF GetLeft();
gfx::RectF GetRight(); gfx::RectF GetRight();
void ResetMemoryBuffer(); void ResetMemoryBuffer();
bool BindContext();
void ClearContext();
private: private:
// GraphicsDelegate:
FovRectangles GetRecommendedFovs() override;
float GetZNear() override;
RenderInfo GetRenderInfo(FrameType frame_type,
const gfx::Transform& head_pose) override;
RenderInfo GetOptimizedRenderInfoForFovs(const FovRectangles& fovs) override;
void InitializeBuffers() override;
void PrepareBufferForWebXr() override;
void PrepareBufferForWebXrOverlayElements() override;
void PrepareBufferForContentQuadLayer(
const gfx::Transform& quad_transform) override;
void PrepareBufferForBrowserUi() override;
void OnFinishedDrawingBuffer() override;
void GetWebXrDrawParams(int* texture_id, Transform* uv_transform) override;
bool IsContentQuadReady() override;
void ResumeContentRendering() override;
void BufferBoundsChanged(const gfx::Size& content_buffer_size,
const gfx::Size& overlay_buffer_size) override;
void GetContentQuadDrawParams(Transform* uv_transform,
float* border_x,
float* border_y) override;
int GetContentBufferWidth() override;
bool Initialize(const scoped_refptr<gl::GLSurface>& surface) override;
bool RunInSkiaContext(base::OnceClosure callback) override;
void SetFrameDumpFilepathBase(std::string& filepath_base) override;
// Helpers:
bool EnsureMemoryBuffer(int width, int height); bool EnsureMemoryBuffer(int width, int height);
gfx::Rect GetTextureSize();
device::mojom::VRDisplayInfoPtr info_;
scoped_refptr<ws::ContextProviderCommandBuffer> context_provider_; scoped_refptr<ws::ContextProviderCommandBuffer> context_provider_;
gpu::gles2::GLES2Interface* gl_ = nullptr; gpu::gles2::GLES2Interface* gl_ = nullptr;
int last_width_ = 0; int last_width_ = 0;
int last_height_ = 0; int last_height_ = 0;
GLuint image_id_ = 0; GLuint image_id_ = 0; // Image corresponding to our target GpuMemoryBuffer.
GLuint dest_texture_id_ = 0;
GLuint draw_frame_buffer_ = 0;
std::unique_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer_; std::unique_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer_;
gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager_ = nullptr; gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager_ = nullptr;
RenderInfo cached_info_ = {};
enum class DrawingBufferMode {
kWebXr,
kWebXrOverlayElements,
kContentQuad,
kBrowserUi,
kNone,
};
DrawingBufferMode prepared_drawing_buffer_ = DrawingBufferMode::kNone;
}; };
} // namespace vr } // namespace vr
#endif // CHROME_BROWSER_VR_WIN_SIMPLE_OVERLAY_RENDERER_WIN_H_ #endif // CHROME_BROWSER_VR_WIN_GRAPHICS_DELEGATE_WIN_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/win/input_delegate_win.h"
#include "chrome/browser/vr/input_event.h"
#include "chrome/browser/vr/model/controller_model.h"
namespace vr {
InputDelegateWin::~InputDelegateWin() {}
gfx::Transform InputDelegateWin::GetHeadPose() {
return head_pose_for_current_frame_;
}
void InputDelegateWin::OnTriggerEvent(bool pressed) {
// No input currently processed for desktop.
}
void InputDelegateWin::UpdateController(const gfx::Transform& head_pose,
base::TimeTicks current_time,
bool is_webxr_frame) {
// No input currently processed for desktop.
}
ControllerModel InputDelegateWin::GetControllerModel(
const gfx::Transform& head_pose) {
return {};
}
InputEventList InputDelegateWin::GetGestures(base::TimeTicks current_time) {
return {};
}
device::mojom::XRInputSourceStatePtr InputDelegateWin::GetInputSourceState() {
NOTREACHED();
device::mojom::XRInputSourceStatePtr state;
return state;
}
void InputDelegateWin::OnResume() {
NOTREACHED();
}
void InputDelegateWin::OnPause() {
NOTREACHED();
}
} // 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_WIN_INPUT_DELEGATE_WIN_H_
#define CHROME_BROWSER_VR_WIN_INPUT_DELEGATE_WIN_H_
#include "chrome/browser/vr/input_delegate.h"
namespace vr {
class InputDelegateWin : public InputDelegate {
public:
~InputDelegateWin() override;
// Push input state (head pose, current_time)
void OnPose(gfx::Transform head_pose_for_current_frame) {
head_pose_for_current_frame_ = head_pose_for_current_frame;
}
private:
gfx::Transform GetHeadPose() override;
void OnTriggerEvent(bool pressed) override;
void UpdateController(const gfx::Transform& head_pose,
base::TimeTicks current_time,
bool is_webxr_frame) override;
ControllerModel GetControllerModel(const gfx::Transform& head_pose) override;
InputEventList GetGestures(base::TimeTicks current_time) override;
device::mojom::XRInputSourceStatePtr GetInputSourceState() override;
void OnResume() override;
void OnPause() override;
gfx::Transform head_pose_for_current_frame_;
};
} // namespace vr
#endif // CHROME_BROWSER_VR_WIN_INPUT_DELEGATE_WIN_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/win/scheduler_delegate_win.h"
#include "chrome/browser/vr/scheduler_browser_renderer_interface.h"
namespace vr {
SchedulerDelegateWin::SchedulerDelegateWin() = default;
SchedulerDelegateWin::~SchedulerDelegateWin() {}
void SchedulerDelegateWin::OnPose(base::OnceCallback<void()> on_frame_ended,
gfx::Transform head_pose) {
on_frame_ended_ = std::move(on_frame_ended);
base::TimeTicks now = base::TimeTicks::Now();
browser_renderer_->DrawWebXrFrame(now, head_pose);
}
void SchedulerDelegateWin::OnPause() {
NOTREACHED();
}
void SchedulerDelegateWin::OnResume() {
NOTREACHED();
}
void SchedulerDelegateWin::OnExitPresent() {
NOTREACHED();
}
void SchedulerDelegateWin::SetWebXrMode(bool enabled) {
NOTREACHED();
}
void SchedulerDelegateWin::SetShowingVrDialog(bool showing) {
NOTREACHED();
}
void SchedulerDelegateWin::SetBrowserRenderer(
SchedulerBrowserRendererInterface* browser_renderer) {
browser_renderer_ = browser_renderer;
}
void SchedulerDelegateWin::SubmitDrawnFrame(FrameType frame_type,
const gfx::Transform& head_pose) {
DCHECK(frame_type == FrameType::kWebXrFrame);
std::move(on_frame_ended_).Run();
}
void SchedulerDelegateWin::AddInputSourceState(
device::mojom::XRInputSourceStatePtr state) {
NOTREACHED();
}
void SchedulerDelegateWin::ConnectPresentingService(
device::mojom::VRDisplayInfoPtr display_info,
device::mojom::XRRuntimeSessionOptionsPtr options) {
NOTREACHED();
}
} // 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_WIN_SCHEDULER_DELEGATE_WIN_H_
#define CHROME_BROWSER_VR_WIN_SCHEDULER_DELEGATE_WIN_H_
#include "chrome/browser/vr/scheduler_delegate.h"
namespace vr {
class SchedulerDelegateWin : public SchedulerDelegate {
public:
SchedulerDelegateWin();
~SchedulerDelegateWin() override;
// Tell browser when poses available, when we rendered, etc.
void OnPose(base::OnceCallback<void()> on_frame_ended,
gfx::Transform head_pose);
private:
void OnPause() override;
void OnResume() override;
void OnExitPresent() override;
void SetWebXrMode(bool enabled) override;
void SetShowingVrDialog(bool showing) override;
void SetBrowserRenderer(
SchedulerBrowserRendererInterface* browser_renderer) override;
void SubmitDrawnFrame(FrameType frame_type,
const gfx::Transform& head_pose) override;
void AddInputSourceState(device::mojom::XRInputSourceStatePtr state) override;
void ConnectPresentingService(
device::mojom::VRDisplayInfoPtr display_info,
device::mojom::XRRuntimeSessionOptionsPtr options) override;
private:
SchedulerBrowserRendererInterface* browser_renderer_ = nullptr;
base::OnceCallback<void()> on_frame_ended_;
};
} // namespace vr
#endif // CHROME_BROWSER_VR_WIN_SCHEDULER_DELEGATE_WIN_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 <dxgi1_2.h>
#include "chrome/browser/vr/win/simple_overlay_renderer_win.h"
#include "content/public/browser/gpu_utils.h"
#include "content/public/common/gpu_stream_constants.h"
#include "gpu/command_buffer/client/gles2_interface.h"
#include "mojo/public/cpp/system/platform_handle.h"
namespace vr {
SimpleOverlayRenderer::SimpleOverlayRenderer() {}
SimpleOverlayRenderer::~SimpleOverlayRenderer() {}
bool SimpleOverlayRenderer::InitializeOnMainThread() {
gpu::GpuChannelEstablishFactory* factory =
content::GetGpuChannelEstablishFactory();
scoped_refptr<gpu::GpuChannelHost> host = factory->EstablishGpuChannelSync();
gpu::ContextCreationAttribs attributes;
attributes.alpha_size = -1;
attributes.red_size = 8;
attributes.green_size = 8;
attributes.blue_size = 8;
attributes.stencil_size = 0;
attributes.depth_size = 0;
attributes.samples = 0;
attributes.sample_buffers = 0;
attributes.bind_generates_resource = false;
context_provider_ = base::MakeRefCounted<ws::ContextProviderCommandBuffer>(
host, factory->GetGpuMemoryBufferManager(), content::kGpuStreamIdDefault,
content::kGpuStreamPriorityUI, gpu::kNullSurfaceHandle,
GURL(std::string("chrome://gpu/SimpleOverlayRendererWin")),
false /* automatic flushes */, false /* support locking */,
false /* support grcontext */,
gpu::SharedMemoryLimits::ForMailboxContext(), attributes,
ws::command_buffer_metrics::ContextType::XR_COMPOSITING);
gpu_memory_buffer_manager_ = factory->GetGpuMemoryBufferManager();
return true;
}
void SimpleOverlayRenderer::InitializeOnGLThread() {
DCHECK(context_provider_);
if (context_provider_->BindToCurrentThread() == gpu::ContextResult::kSuccess)
gl_ = context_provider_->ContextGL();
}
void SimpleOverlayRenderer::Render() {
if (!gl_)
return;
int width = 512;
int height = 512;
// Create a memory buffer, and an image referencing that memory buffer.
if (!EnsureMemoryBuffer(width, height))
return;
// Create a texture id, and associate it with our image.
GLuint dest_texture_id;
gl_->GenTextures(1, &dest_texture_id);
GLenum target = GL_TEXTURE_2D;
gl_->BindTexture(target, dest_texture_id);
gl_->TexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
gl_->TexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
gl_->TexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
gl_->TexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
gl_->BindTexImage2DCHROMIUM(target, image_id_);
gl_->BindTexture(GL_TEXTURE_2D, 0);
// Bind our image/texture/memory buffer as the draw framebuffer.
GLuint draw_frame_buffer_;
gl_->GenFramebuffers(1, &draw_frame_buffer_);
gl_->BindFramebuffer(GL_DRAW_FRAMEBUFFER, draw_frame_buffer_);
gl_->FramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target,
dest_texture_id, 0);
// Do some drawing.
gl_->ClearColor(0, 1, 0, 0.5f);
gl_->Clear(GL_COLOR_BUFFER_BIT);
// Unbind the drawing buffer.
gl_->BindFramebuffer(GL_FRAMEBUFFER, 0);
gl_->DeleteFramebuffers(1, &draw_frame_buffer_);
gl_->BindTexture(target, dest_texture_id);
gl_->ReleaseTexImage2DCHROMIUM(target, image_id_);
gl_->DeleteTextures(1, &dest_texture_id);
gl_->BindTexture(target, 0);
// Flush.
gl_->ShallowFlushCHROMIUM();
}
mojo::ScopedHandle SimpleOverlayRenderer::GetTexture() {
// Hand out the gpu memory buffer.
mojo::ScopedHandle handle;
if (!gpu_memory_buffer_) {
return handle;
}
gfx::GpuMemoryBufferHandle gpu_handle = gpu_memory_buffer_->CloneHandle();
return mojo::WrapPlatformFile(gpu_handle.dxgi_handle.GetHandle());
}
gfx::RectF SimpleOverlayRenderer::GetLeft() {
return gfx::RectF(0, 0, 0.5, 1);
}
gfx::RectF SimpleOverlayRenderer::GetRight() {
return gfx::RectF(0.5, 0, 0.5, 1);
}
void SimpleOverlayRenderer::Cleanup() {
context_provider_ = nullptr;
}
bool SimpleOverlayRenderer::EnsureMemoryBuffer(int width, int height) {
if (last_width_ != width || last_height_ != height || !gpu_memory_buffer_) {
if (!gpu_memory_buffer_manager_)
return false;
if (image_id_) {
gl_->DestroyImageCHROMIUM(image_id_);
image_id_ = 0;
}
gpu_memory_buffer_ = gpu_memory_buffer_manager_->CreateGpuMemoryBuffer(
gfx::Size(width, height), gfx::BufferFormat::RGBA_8888,
gfx::BufferUsage::SCANOUT, gpu::kNullSurfaceHandle);
if (!gpu_memory_buffer_)
return false;
last_width_ = width;
last_height_ = height;
image_id_ = gl_->CreateImageCHROMIUM(gpu_memory_buffer_->AsClientBuffer(),
width, height, GL_RGBA);
if (!image_id_) {
gpu_memory_buffer_ = nullptr;
return false;
}
}
return true;
}
void SimpleOverlayRenderer::ResetMemoryBuffer() {
// Stop using a memory buffer if we had an error submitting with it.
gpu_memory_buffer_ = nullptr;
}
} // namespace vr
...@@ -4,26 +4,53 @@ ...@@ -4,26 +4,53 @@
#include "chrome/browser/vr/win/vr_browser_renderer_thread_win.h" #include "chrome/browser/vr/win/vr_browser_renderer_thread_win.h"
#include "chrome/browser/vr/audio_delegate.h"
#include "chrome/browser/vr/browser_renderer.h"
#include "chrome/browser/vr/content_input_delegate.h"
#include "chrome/browser/vr/keyboard_delegate.h"
#include "chrome/browser/vr/text_input_delegate.h"
#include "chrome/browser/vr/ui.h"
#include "chrome/browser/vr/ui_browser_interface.h"
#include "chrome/browser/vr/ui_initial_state.h"
#include "chrome/browser/vr/win/graphics_delegate_win.h"
#include "chrome/browser/vr/win/input_delegate_win.h"
#include "chrome/browser/vr/win/scheduler_delegate_win.h"
#include "gpu/command_buffer/client/gles2_interface.h"
#include "gpu/command_buffer/client/gles2_lib.h"
#include "ui/gfx/geometry/quaternion.h"
namespace vr { namespace vr {
VRBrowserRendererThreadWin::VRBrowserRendererThreadWin() VRBrowserRendererThreadWin::VRBrowserRendererThreadWin()
: base::Thread("VRBrowserRenderThread") {} : MaybeThread("VRBrowserRenderThread") {}
VRBrowserRendererThreadWin::~VRBrowserRendererThreadWin() { VRBrowserRendererThreadWin::~VRBrowserRendererThreadWin() {
Stop(); Stop();
} }
void VRBrowserRendererThreadWin::SetVRDisplayInfo(
device::mojom::VRDisplayInfoPtr display_info) {
task_runner()->PostTask(
FROM_HERE,
base::BindOnce(&VRBrowserRendererThreadWin::SetDisplayInfoOnRenderThread,
base::Unretained(this), std::move(display_info)));
}
void VRBrowserRendererThreadWin::SetDisplayInfoOnRenderThread(
device::mojom::VRDisplayInfoPtr display_info) {
display_info_ = std::move(display_info);
if (graphics_)
graphics_->SetVRDisplayInfo(display_info_.Clone());
}
void VRBrowserRendererThreadWin::StartOverlay( void VRBrowserRendererThreadWin::StartOverlay(
device::mojom::XRCompositorHost* compositor) { device::mojom::XRCompositorHost* compositor) {
device::mojom::ImmersiveOverlayPtrInfo overlay_info; device::mojom::ImmersiveOverlayPtrInfo overlay_info;
compositor->CreateImmersiveOverlay(mojo::MakeRequest(&overlay_info)); compositor->CreateImmersiveOverlay(mojo::MakeRequest(&overlay_info));
if (!IsRunning()) { initializing_graphics_ = std::make_unique<GraphicsDelegateWin>();
if (!renderer_.InitializeOnMainThread()) { if (!initializing_graphics_->InitializeOnMainThread()) {
return; return;
}
Start();
} }
// Post a task to the thread to start an overlay. // Post a task to the thread to start an overlay.
...@@ -34,33 +61,146 @@ void VRBrowserRendererThreadWin::StartOverlay( ...@@ -34,33 +61,146 @@ void VRBrowserRendererThreadWin::StartOverlay(
} }
void VRBrowserRendererThreadWin::CleanUp() { void VRBrowserRendererThreadWin::CleanUp() {
renderer_.Cleanup(); browser_renderer_ = nullptr;
initializing_graphics_ = nullptr;
overlay_ = nullptr; overlay_ = nullptr;
} }
namespace {
// Number of frames to use for sliding averages for pose timings,
// as used for estimating prediction times.
constexpr unsigned kSlidingAverageSize = 5;
} // namespace
class VRUiBrowserInterface : public UiBrowserInterface {
public:
~VRUiBrowserInterface() override = default;
void ExitPresent() override {}
void ExitFullscreen() override {}
void Navigate(GURL gurl, NavigationMethod method) override {}
void NavigateBack() override {}
void NavigateForward() override {}
void ReloadTab() override {}
void OpenNewTab(bool incognito) override {}
void SelectTab(int id, bool incognito) override {}
void OpenBookmarks() override {}
void OpenRecentTabs() override {}
void OpenHistory() override {}
void OpenDownloads() override {}
void OpenShare() override {}
void OpenSettings() override {}
void CloseTab(int id, bool incognito) override {}
void CloseAllTabs() override {}
void CloseAllIncognitoTabs() override {}
void OpenFeedback() override {}
void CloseHostedDialog() override {}
void OnUnsupportedMode(UiUnsupportedMode mode) override {}
void OnExitVrPromptResult(ExitVrPromptChoice choice,
UiUnsupportedMode reason) override {}
void OnContentScreenBoundsChanged(const gfx::SizeF& bounds) override {}
void SetVoiceSearchActive(bool active) override {}
void StartAutocomplete(const AutocompleteRequest& request) override {}
void StopAutocomplete() override {}
void ShowPageInfo() override {}
};
void VRBrowserRendererThreadWin::StartOverlayOnRenderThread( void VRBrowserRendererThreadWin::StartOverlayOnRenderThread(
device::mojom::ImmersiveOverlayPtrInfo overlay) { device::mojom::ImmersiveOverlayPtrInfo overlay) {
overlay_.Bind(std::move(overlay)); overlay_.Bind(std::move(overlay));
initializing_graphics_->InitializeOnGLThread();
initializing_graphics_->BindContext();
renderer_.InitializeOnGLThread(); // Create a vr::Ui
BrowserRendererBrowserInterface* browser_renderer_interface = nullptr;
ui_browser_interface_ = std::make_unique<VRUiBrowserInterface>();
PlatformInputHandler* input = nullptr;
std::unique_ptr<KeyboardDelegate> keyboard_delegate;
std::unique_ptr<TextInputDelegate> text_input_delegate;
std::unique_ptr<AudioDelegate> audio_delegate;
UiInitialState ui_initial_state = {};
ui_initial_state.in_web_vr = true;
ui_initial_state.browsing_disabled = true;
ui_initial_state.supports_selection = false;
std::unique_ptr<Ui> ui = std::make_unique<Ui>(
ui_browser_interface_.get(), input, std::move(keyboard_delegate),
std::move(text_input_delegate), std::move(audio_delegate),
ui_initial_state);
static_cast<UiInterface*>(ui.get())->OnGlInitialized(
kGlTextureLocationLocal,
0 /* content_texture_id - we don't support content */,
0 /* content_overlay_texture_id - we don't support content overlays */,
0 /* platform_ui_texture_id - we don't support platform UI */);
static_cast<BrowserUiInterface*>(ui.get())->SetWebVrMode(true);
// Create the delegates, and keep raw pointers to them. They are owned by
// browser_renderer_.
std::unique_ptr<SchedulerDelegateWin> scheduler_delegate =
std::make_unique<SchedulerDelegateWin>();
scheduler_ = scheduler_delegate.get();
graphics_ = initializing_graphics_.get();
graphics_->SetVRDisplayInfo(display_info_.Clone());
std::unique_ptr<InputDelegateWin> input_delegate =
std::make_unique<InputDelegateWin>();
input_ = input_delegate.get();
// Create the BrowserRenderer to drive UI rendering based on the delegates.
browser_renderer_ = std::make_unique<BrowserRenderer>(
std::move(ui), std::move(scheduler_delegate),
std::move(initializing_graphics_), std::move(input_delegate),
browser_renderer_interface, kSlidingAverageSize);
overlay_->SetOverlayAndWebXRVisibility(true, true); overlay_->SetOverlayAndWebXRVisibility(true, true);
overlay_->RequestNextOverlayPose(base::BindOnce( overlay_->RequestNextOverlayPose(base::BindOnce(
&VRBrowserRendererThreadWin::OnPose, base::Unretained(this))); &VRBrowserRendererThreadWin::OnPose, base::Unretained(this)));
graphics_->ClearContext();
} }
void VRBrowserRendererThreadWin::OnPose(device::mojom::XRFrameDataPtr data) { void VRBrowserRendererThreadWin::OnPose(device::mojom::XRFrameDataPtr data) {
renderer_.Render(); // Deliver pose to input and scheduler.
const std::vector<float>& quat = *data->pose->orientation;
const std::vector<float>& pos = *data->pose->position;
// The incoming pose represents where the headset is in "world space". So
// we'll need to invert to get the view transform.
// Negating the w component will invert the rotation.
gfx::Transform head_from_unoriented_head(
gfx::Quaternion(quat[0], quat[1], quat[2], -quat[3]));
// Negating all components will invert the translation.
gfx::Transform unoriented_head_from_world;
unoriented_head_from_world.Translate3d(-pos[0], -pos[1], -pos[2]);
// Compose these to get the base "view" matrix (before accounting for per-eye
// transforms).
gfx::Transform head_from_world =
head_from_unoriented_head * unoriented_head_from_world;
input_->OnPose(head_from_world);
graphics_->PreRender();
// base::Unretained is safe because scheduler_ will be destroyed without
// calling the callback if we are destroyed.
scheduler_->OnPose(base::BindOnce(&VRBrowserRendererThreadWin::SubmitFrame,
base::Unretained(this), std::move(data)),
head_from_world);
}
void VRBrowserRendererThreadWin::SubmitFrame(
device::mojom::XRFrameDataPtr data) {
graphics_->PostRender();
overlay_->SubmitOverlayTexture( overlay_->SubmitOverlayTexture(
data->frame_id, renderer_.GetTexture(), renderer_.GetLeft(), data->frame_id, graphics_->GetTexture(), graphics_->GetLeft(),
renderer_.GetRight(), graphics_->GetRight(),
base::BindOnce(&VRBrowserRendererThreadWin::SubmitResult, base::BindOnce(&VRBrowserRendererThreadWin::SubmitResult,
base::Unretained(this))); base::Unretained(this)));
} }
void VRBrowserRendererThreadWin::SubmitResult(bool success) { void VRBrowserRendererThreadWin::SubmitResult(bool success) {
if (!success) { if (!success) {
renderer_.ResetMemoryBuffer(); graphics_->ResetMemoryBuffer();
} }
overlay_->RequestNextOverlayPose(base::BindOnce( overlay_->RequestNextOverlayPose(base::BindOnce(
&VRBrowserRendererThreadWin::OnPose, base::Unretained(this))); &VRBrowserRendererThreadWin::OnPose, base::Unretained(this)));
......
...@@ -6,36 +6,82 @@ ...@@ -6,36 +6,82 @@
#define CHROME_BROWSER_VR_WIN_VR_BROWSER_RENDERER_THREAD_WIN_H_ #define CHROME_BROWSER_VR_WIN_VR_BROWSER_RENDERER_THREAD_WIN_H_
#include "base/threading/thread.h" #include "base/threading/thread.h"
#include "chrome/browser/vr/browser_renderer.h"
#include "chrome/browser/vr/service/browser_xr_runtime.h"
#include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents.h"
#include "device/vr/public/mojom/isolated_xr_service.mojom.h" #include "device/vr/public/mojom/isolated_xr_service.mojom.h"
#include "device/vr/public/mojom/vr_service.mojom.h" #include "device/vr/public/mojom/vr_service.mojom.h"
#include "chrome/browser/vr/win/simple_overlay_renderer_win.h" namespace vr {
#include "chrome/browser/vr/service/browser_xr_runtime.h" class InputDelegateWin;
class GraphicsDelegateWin;
class SchedulerDelegateWin;
class VRUiBrowserInterface;
namespace vr { // TODO(https://crbug.com/902576) There were issues initializing gfx::FontList
// on a background thread, so run UI on the main thread.
#define VR_UI_ON_MAIN_THREAD
#ifdef VR_UI_ON_MAIN_THREAD
class MaybeThread {
public:
explicit MaybeThread(std::string) {}
virtual ~MaybeThread() = default;
virtual void CleanUp() {}
void Start() {}
void Stop() { CleanUp(); }
scoped_refptr<base::SingleThreadTaskRunner> task_runner() {
return scoped_refptr<base::SingleThreadTaskRunner>(
base::ThreadTaskRunnerHandle::Get());
}
};
#else
class MaybeThread : public base::Thread {
explicit MaybeThread(std::string name) : base::Thread(name) {}
};
#endif
class VRBrowserRendererThreadWin : base::Thread { class VRBrowserRendererThreadWin : public MaybeThread {
public: public:
VRBrowserRendererThreadWin(); VRBrowserRendererThreadWin();
~VRBrowserRendererThreadWin() override; ~VRBrowserRendererThreadWin() override;
// base::Thread overrides // Methods called on the browser's main thread.
void CleanUp() override;
// Initially we are just rendering a solid-color rectangle overlay as a
// proof-of-concept. Eventually, this will draw real content.
void StartOverlay(device::mojom::XRCompositorHost* host); void StartOverlay(device::mojom::XRCompositorHost* host);
void SetVRDisplayInfo(device::mojom::VRDisplayInfoPtr display_info);
private: private:
// base::Thread overrides
void CleanUp() override;
// Methods called on render thread.
void StartOverlayOnRenderThread( void StartOverlayOnRenderThread(
device::mojom::ImmersiveOverlayPtrInfo overlay); device::mojom::ImmersiveOverlayPtrInfo overlay);
void SetDisplayInfoOnRenderThread(
device::mojom::VRDisplayInfoPtr display_info);
void OnPose(device::mojom::XRFrameDataPtr data); void OnPose(device::mojom::XRFrameDataPtr data);
void SubmitResult(bool success); void SubmitResult(bool success);
void SubmitFrame(device::mojom::XRFrameDataPtr data);
// We need to do some initialization of GraphicsDelegateWin before
// browser_renderer_, so we first store it in a unique_ptr, then transition
// ownership to browser_renderer_.
std::unique_ptr<GraphicsDelegateWin> initializing_graphics_;
std::unique_ptr<VRUiBrowserInterface> ui_browser_interface_;
std::unique_ptr<BrowserRenderer> browser_renderer_;
// Raw pointers to objects owned by browser_renderer_:
InputDelegateWin* input_ = nullptr;
GraphicsDelegateWin* graphics_ = nullptr;
SchedulerDelegateWin* scheduler_ = nullptr;
SimpleOverlayRenderer renderer_;
device::mojom::ImmersiveOverlayPtr overlay_; device::mojom::ImmersiveOverlayPtr overlay_;
device::mojom::VRDisplayInfoPtr display_info_;
}; };
} // namespace vr } // namespace vr
......
...@@ -40,6 +40,14 @@ void VRBrowserRendererHostWin::SetWebXRWebContents( ...@@ -40,6 +40,14 @@ void VRBrowserRendererHostWin::SetWebXRWebContents(
StopBrowserRenderer(); StopBrowserRenderer();
} }
void VRBrowserRendererHostWin::SetVRDisplayInfo(
device::mojom::VRDisplayInfoPtr display_info) {
info_ = std::move(display_info);
if (render_thread_) {
render_thread_->SetVRDisplayInfo(info_.Clone());
}
}
void VRBrowserRendererHostWin::AddCompositor( void VRBrowserRendererHostWin::AddCompositor(
device::mojom::VRDisplayInfoPtr info, device::mojom::VRDisplayInfoPtr info,
device::mojom::XRCompositorHostPtr compositor) { device::mojom::XRCompositorHostPtr compositor) {
...@@ -58,9 +66,11 @@ void VRBrowserRendererHostWin::RemoveCompositor(device::mojom::XRDeviceId id) { ...@@ -58,9 +66,11 @@ void VRBrowserRendererHostWin::RemoveCompositor(device::mojom::XRDeviceId id) {
void VRBrowserRendererHostWin::StartBrowserRenderer() { void VRBrowserRendererHostWin::StartBrowserRenderer() {
// Only used for testing currently. To see an example overlay, enable the // Only used for testing currently. To see an example overlay, enable the
// following two lines. // following few lines.
#if 0 #if 0
render_thread_ = std::make_unique<VRBrowserRendererThreadWin>(); render_thread_ = std::make_unique<VRBrowserRendererThreadWin>();
render_thread_->Start();
render_thread_->SetVRDisplayInfo(info_.Clone());
render_thread_->StartOverlay(compositor_.get()); render_thread_->StartOverlay(compositor_.get());
#endif #endif
} }
......
...@@ -32,6 +32,7 @@ class VRBrowserRendererHostWin : public BrowserXRRuntimeObserver { ...@@ -32,6 +32,7 @@ class VRBrowserRendererHostWin : public BrowserXRRuntimeObserver {
// The parameter contents indicate which page is rendering with WebXR or WebVR // The parameter contents indicate which page is rendering with WebXR or WebVR
// presentation. When null, no page is presenting. // presentation. When null, no page is presenting.
void SetWebXRWebContents(content::WebContents* contents) override; void SetWebXRWebContents(content::WebContents* contents) override;
void SetVRDisplayInfo(device::mojom::VRDisplayInfoPtr display_info) override;
void StartBrowserRenderer(); void StartBrowserRenderer();
void StopBrowserRenderer(); void StopBrowserRenderer();
......
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