Commit c5c5ea87 authored by bajones's avatar bajones Committed by Commit bot

Added WebVR Render path to VrShell

This render path isn't used for WebVR just yet because VrShell has not been
added to the main browser activity.

BUG=389343

Review-Url: https://codereview.chromium.org/2308683004
Cr-Commit-Position: refs/heads/master@{#417424}
parent 4a8849f8
...@@ -20,6 +20,7 @@ static_library("vr_shell") { ...@@ -20,6 +20,7 @@ static_library("vr_shell") {
deps = [ deps = [
":vr_shell_jni_headers", ":vr_shell_jni_headers",
"//base", "//base",
"//device/vr",
"//third_party/gvr-android-sdk:gvr_base_java", "//third_party/gvr-android-sdk:gvr_base_java",
"//third_party/gvr-android-sdk:gvr_common_java", "//third_party/gvr-android-sdk:gvr_common_java",
"//third_party/gvr-android-sdk:libgvr", "//third_party/gvr-android-sdk:libgvr",
......
include_rules = [ include_rules = [
"+third_party/gvr-android-sdk/src", "+third_party/gvr-android-sdk/src",
"+device/vr",
] ]
...@@ -56,7 +56,8 @@ void ContentRect::Translate(float x, float y, float z) { ...@@ -56,7 +56,8 @@ void ContentRect::Translate(float x, float y, float z) {
transfrom_to_world.m[2][3] += z; transfrom_to_world.m[2][3] += z;
} }
VrShell::VrShell(JNIEnv* env, jobject obj) { VrShell::VrShell(JNIEnv* env, jobject obj) :
webvr_mode_(false) {
j_vr_shell_.Reset(env, obj); j_vr_shell_.Reset(env, obj);
} }
...@@ -69,13 +70,17 @@ bool RegisterVrShell(JNIEnv* env) { ...@@ -69,13 +70,17 @@ bool RegisterVrShell(JNIEnv* env) {
return RegisterNativesImpl(env); return RegisterNativesImpl(env);
} }
VrShell::~VrShell() {} VrShell::~VrShell() {
device::GvrDelegateManager::GetInstance()->Shutdown();
}
void VrShell::GvrInit(JNIEnv* env, void VrShell::GvrInit(JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj, const base::android::JavaParamRef<jobject>& obj,
jlong native_gvr_api) { jlong native_gvr_api) {
gvr_api_ = gvr_api_ =
gvr::GvrApi::WrapNonOwned(reinterpret_cast<gvr_context*>(native_gvr_api)); gvr::GvrApi::WrapNonOwned(reinterpret_cast<gvr_context*>(native_gvr_api));
device::GvrDelegateManager::GetInstance()->Initialize(this);
} }
void VrShell::InitializeGl(JNIEnv* env, void VrShell::InitializeGl(JNIEnv* env,
...@@ -105,6 +110,20 @@ void VrShell::DrawFrame(JNIEnv* env, ...@@ -105,6 +110,20 @@ void VrShell::DrawFrame(JNIEnv* env,
target_time.monotonic_system_time_nanos += kPredictionTimeWithoutVsyncNanos; target_time.monotonic_system_time_nanos += kPredictionTimeWithoutVsyncNanos;
head_pose_ = gvr_api_->GetHeadPoseInStartSpace(target_time); head_pose_ = gvr_api_->GetHeadPoseInStartSpace(target_time);
// Bind back to the default framebuffer.
frame.BindBuffer(0);
if (webvr_mode_) {
DrawWebVr();
} else {
DrawVrShell();
}
frame.Unbind();
frame.Submit(*buffer_viewport_list_, head_pose_);
}
void VrShell::DrawVrShell() {
// Content area positioning. // Content area positioning.
content_rect_->SetIdentity(); content_rect_->SetIdentity();
content_rect_->Translate(kContentRectPositionDefault.x, content_rect_->Translate(kContentRectPositionDefault.x,
...@@ -112,13 +131,10 @@ void VrShell::DrawFrame(JNIEnv* env, ...@@ -112,13 +131,10 @@ void VrShell::DrawFrame(JNIEnv* env,
kContentRectPositionDefault.z); kContentRectPositionDefault.z);
gvr::Mat4f left_eye_view_matrix = gvr::Mat4f left_eye_view_matrix =
MatrixMul(gvr_api_->GetEyeFromHeadMatrix(GVR_LEFT_EYE), head_pose_); MatrixMul(gvr_api_->GetEyeFromHeadMatrix(GVR_LEFT_EYE), head_pose_);
gvr::Mat4f right_eye_view_matrix = gvr::Mat4f right_eye_view_matrix =
MatrixMul(gvr_api_->GetEyeFromHeadMatrix(GVR_RIGHT_EYE), head_pose_); MatrixMul(gvr_api_->GetEyeFromHeadMatrix(GVR_RIGHT_EYE), head_pose_);
// Bind back to the default framebuffer.
frame.BindBuffer(0);
// Use culling to remove back faces. // Use culling to remove back faces.
glEnable(GL_CULL_FACE); glEnable(GL_CULL_FACE);
...@@ -138,9 +154,6 @@ void VrShell::DrawFrame(JNIEnv* env, ...@@ -138,9 +154,6 @@ void VrShell::DrawFrame(JNIEnv* env,
buffer_viewport_list_->GetBufferViewport(GVR_RIGHT_EYE, buffer_viewport_list_->GetBufferViewport(GVR_RIGHT_EYE,
buffer_viewport_.get()); buffer_viewport_.get());
DrawEye(right_eye_view_matrix, *buffer_viewport_); DrawEye(right_eye_view_matrix, *buffer_viewport_);
frame.Unbind();
frame.Submit(*buffer_viewport_list_, head_pose_);
} }
void VrShell::DrawEye(const gvr::Mat4f& view_matrix, void VrShell::DrawEye(const gvr::Mat4f& view_matrix,
...@@ -172,6 +185,22 @@ void VrShell::DrawContentRect() { ...@@ -172,6 +185,22 @@ void VrShell::DrawContentRect() {
content_rect_->content_texture_handle, content_rect_combined_matrix); content_rect_->content_texture_handle, content_rect_combined_matrix);
} }
void VrShell::DrawWebVr() {
// Don't need face culling, depth testing, blending, etc. Turn it all off.
glDisable(GL_CULL_FACE);
glDepthMask(GL_FALSE);
glDisable(GL_DEPTH_TEST);
glDisable(GL_SCISSOR_TEST);
glDisable(GL_BLEND);
glDisable(GL_POLYGON_OFFSET_FILL);
// Don't need to clear, since we're drawing over the entire render target.
glViewport(0, 0, render_size_.width, render_size_.height);
vr_shell_renderer_->GetWebVrRenderer()->Draw(
reinterpret_cast<int>(content_rect_->content_texture_handle));
}
void VrShell::OnPause(JNIEnv* env, void VrShell::OnPause(JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj) { const base::android::JavaParamRef<jobject>& obj) {
if (gvr_api_ == nullptr) if (gvr_api_ == nullptr)
...@@ -187,6 +216,27 @@ void VrShell::OnResume(JNIEnv* env, ...@@ -187,6 +216,27 @@ void VrShell::OnResume(JNIEnv* env,
gvr_api_->ResumeTracking(); gvr_api_->ResumeTracking();
} }
void VrShell::RequestWebVRPresent() {
webvr_mode_ = true;
}
void VrShell::ExitWebVRPresent() {
webvr_mode_ = false;
}
void VrShell::SubmitWebVRFrame() {
}
void VrShell::UpdateWebVRTextureBounds(
int eye, float left, float top, float width, float height) {
gvr::Rectf bounds = { left, top, width, height };
vr_shell_renderer_->GetWebVrRenderer()->UpdateTextureBounds(eye, bounds);
}
gvr::GvrApi* VrShell::gvr_api() {
return gvr_api_.get();
}
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Native JNI methods // Native JNI methods
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "base/android/jni_weak_ref.h" #include "base/android/jni_weak_ref.h"
#include "base/macros.h" #include "base/macros.h"
#include "device/vr/android/gvr/gvr_delegate.h"
#include "third_party/gvr-android-sdk/src/ndk-beta/include/vr/gvr/capi/include/gvr.h" #include "third_party/gvr-android-sdk/src/ndk-beta/include/vr/gvr/capi/include/gvr.h"
#include "third_party/gvr-android-sdk/src/ndk-beta/include/vr/gvr/capi/include/gvr_types.h" #include "third_party/gvr-android-sdk/src/ndk-beta/include/vr/gvr/capi/include/gvr_types.h"
...@@ -27,7 +28,7 @@ class ContentRect { ...@@ -27,7 +28,7 @@ class ContentRect {
int content_texture_handle; int content_texture_handle;
}; };
class VrShell { class VrShell : public device::GvrDelegate {
public: public:
VrShell(JNIEnv* env, jobject obj); VrShell(JNIEnv* env, jobject obj);
...@@ -43,12 +44,22 @@ class VrShell { ...@@ -43,12 +44,22 @@ class VrShell {
void OnPause(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj); void OnPause(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
void OnResume(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj); void OnResume(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
// GvrDelegate
void RequestWebVRPresent() override;
void ExitWebVRPresent() override;
void SubmitWebVRFrame() override;
void UpdateWebVRTextureBounds(
int eye, float left, float top, float width, float height) override;
gvr::GvrApi* gvr_api() override;
private: private:
~VrShell(); virtual ~VrShell();
void DrawVrShell();
void DrawEye(const gvr::Mat4f& view_matrix, void DrawEye(const gvr::Mat4f& view_matrix,
const gvr::BufferViewport& params); const gvr::BufferViewport& params);
void DrawContentRect(); void DrawContentRect();
void DrawWebVr();
std::unique_ptr<ContentRect> content_rect_; std::unique_ptr<ContentRect> content_rect_;
std::unique_ptr<gvr::GvrApi> gvr_api_; std::unique_ptr<gvr::GvrApi> gvr_api_;
...@@ -67,6 +78,8 @@ class VrShell { ...@@ -67,6 +78,8 @@ class VrShell {
base::android::ScopedJavaGlobalRef<jobject> j_vr_shell_; base::android::ScopedJavaGlobalRef<jobject> j_vr_shell_;
bool webvr_mode_;
DISALLOW_COPY_AND_ASSIGN(VrShell); DISALLOW_COPY_AND_ASSIGN(VrShell);
}; };
......
...@@ -25,8 +25,22 @@ const float kTexturedQuadTextureCoordinates[12] = { ...@@ -25,8 +25,22 @@ const float kTexturedQuadTextureCoordinates[12] = {
0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f}; 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f};
const int kTextureCoordinateDataSize = 2; const int kTextureCoordinateDataSize = 2;
const float kWebVrVertices[32] = {
// x y u, v
-1.f, 1.f, 0.f, 0.f, // Left Eye
-1.f, -1.f, 0.f, 1.f,
0.f, -1.f, 1.f, 1.f,
0.f, 1.f, 1.f, 0.f,
0.f, 1.f, 0.f, 0.f, // Right Eye
0.f, -1.f, 0.f, 1.f,
1.f, -1.f, 1.f, 1.f,
1.f, 1.f, 1.f, 0.f };
const int kWebVrVerticesSize = sizeof(float) * 32;
#define SHADER(Src) #Src #define SHADER(Src) #Src
#define OEIE_SHADER(Src) "#extension GL_OES_EGL_image_external : require\n" #Src #define OEIE_SHADER(Src) "#extension GL_OES_EGL_image_external : require\n" #Src
#define VOID_OFFSET(x) reinterpret_cast<void*>(x)
const char* GetShaderSource(ShaderID shader) { const char* GetShaderSource(ShaderID shader) {
switch (shader) { switch (shader) {
...@@ -44,6 +58,26 @@ const char* GetShaderSource(ShaderID shader) { ...@@ -44,6 +58,26 @@ const char* GetShaderSource(ShaderID shader) {
vec4 texture = texture2D(u_Texture, v_TexCoordinate); vec4 texture = texture2D(u_Texture, v_TexCoordinate);
gl_FragColor = vec4(texture.r, texture.g, texture.b, 1.0); gl_FragColor = vec4(texture.r, texture.g, texture.b, 1.0);
}); });
case vr_shell::ShaderID::WEBVR_VERTEX_SHADER:
return SHADER(
attribute vec2 a_Position;
attribute vec2 a_TexCoordinate;
uniform vec4 u_SrcRect;
varying vec2 v_TexCoordinate;
void main() {
v_TexCoordinate = u_SrcRect.xy + (a_TexCoordinate * u_SrcRect.zw);
gl_Position = vec4(a_Position, 0.0, 1.0);
});
case vr_shell::ShaderID::WEBVR_FRAGMENT_SHADER:
return OEIE_SHADER(
precision highp float;
uniform samplerExternalOES u_Texture;
varying vec2 v_TexCoordinate;
void main() {
gl_FragColor = texture2D(u_Texture, v_TexCoordinate);
});
default: default:
LOG(ERROR) << "Shader source requested for unknown shader"; LOG(ERROR) << "Shader source requested for unknown shader";
return ""; return "";
...@@ -56,23 +90,16 @@ TexturedQuadRenderer::TexturedQuadRenderer() { ...@@ -56,23 +90,16 @@ TexturedQuadRenderer::TexturedQuadRenderer() {
std::string error; std::string error;
vertex_shader_handle_ = CompileShader( vertex_shader_handle_ = CompileShader(
GL_VERTEX_SHADER, GetShaderSource(TEXTURE_QUAD_VERTEX_SHADER), error); GL_VERTEX_SHADER, GetShaderSource(TEXTURE_QUAD_VERTEX_SHADER), error);
if (vertex_shader_handle_ == 0) { CHECK(vertex_shader_handle_) << error;
LOG(ERROR) << error;
exit(1);
}
fragment_shader_handle_ = CompileShader( fragment_shader_handle_ = CompileShader(
GL_FRAGMENT_SHADER, GetShaderSource(TEXTURE_QUAD_FRAGMENT_SHADER), error); GL_FRAGMENT_SHADER, GetShaderSource(TEXTURE_QUAD_FRAGMENT_SHADER), error);
if (fragment_shader_handle_ == 0) { CHECK(fragment_shader_handle_) << error;
LOG(ERROR) << error;
exit(1);
}
program_handle_ = CreateAndLinkProgram( program_handle_ = CreateAndLinkProgram(
vertex_shader_handle_, fragment_shader_handle_, 4, nullptr, error); vertex_shader_handle_, fragment_shader_handle_, 4, nullptr, error);
if (program_handle_ == 0) { CHECK(program_handle_) << error;
LOG(ERROR) << error;
exit(1);
}
combined_matrix_handle_ = combined_matrix_handle_ =
glGetUniformLocation(program_handle_, "u_CombinedMatrix"); glGetUniformLocation(program_handle_, "u_CombinedMatrix");
texture_uniform_handle_ = glGetUniformLocation(program_handle_, "u_Texture"); texture_uniform_handle_ = glGetUniformLocation(program_handle_, "u_Texture");
...@@ -118,8 +145,99 @@ TexturedQuadRenderer::~TexturedQuadRenderer() { ...@@ -118,8 +145,99 @@ TexturedQuadRenderer::~TexturedQuadRenderer() {
glDeleteShader(fragment_shader_handle_); glDeleteShader(fragment_shader_handle_);
} }
WebVrRenderer::WebVrRenderer() {
left_bounds_ = { 0.0f, 0.0f, 0.5f, 1.0f };
right_bounds_ = { 0.5f, 0.0f, 0.5f, 1.0f };
std::string error;
GLuint vertex_shader_handle = CompileShader(
GL_VERTEX_SHADER, GetShaderSource(WEBVR_VERTEX_SHADER), error);
CHECK(vertex_shader_handle) << error;
GLuint fragment_shader_handle = CompileShader(
GL_FRAGMENT_SHADER, GetShaderSource(WEBVR_FRAGMENT_SHADER), error);
CHECK(fragment_shader_handle) << error;
program_handle_ = CreateAndLinkProgram(
vertex_shader_handle, fragment_shader_handle, 2, nullptr, error);
CHECK(program_handle_) << error;
// Once the program is linked the shader objects are no longer needed
glDeleteShader(vertex_shader_handle);
glDeleteShader(fragment_shader_handle);
tex_uniform_handle_ = glGetUniformLocation(program_handle_, "u_Texture");
src_rect_uniform_handle_ = glGetUniformLocation(program_handle_, "u_SrcRect");
position_handle_ = glGetAttribLocation(program_handle_, "a_Position");
texcoord_handle_ = glGetAttribLocation(program_handle_, "a_TexCoordinate");
// TODO(bajones): Figure out why this need to be restored.
GLint old_buffer;
glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &old_buffer);
glGenBuffersARB(1, &vertex_buffer_);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_);
glBufferData(GL_ARRAY_BUFFER, kWebVrVerticesSize, kWebVrVertices,
GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, old_buffer);
}
// Draw the stereo WebVR frame
void WebVrRenderer::Draw(int texture_handle) {
// TODO(bajones): Figure out why this need to be restored.
GLint old_buffer;
glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &old_buffer);
glUseProgram(program_handle_);
// Bind vertex attributes
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_);
glEnableVertexAttribArray(position_handle_);
glEnableVertexAttribArray(texcoord_handle_);
glVertexAttribPointer(position_handle_, POSITION_ELEMENTS, GL_FLOAT, false,
VERTEX_STRIDE, VOID_OFFSET(POSITION_OFFSET));
glVertexAttribPointer(texcoord_handle_, TEXCOORD_ELEMENTS, GL_FLOAT, false,
VERTEX_STRIDE, VOID_OFFSET(TEXCOORD_OFFSET));
// Bind texture.
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture_handle);
glUniform1i(tex_uniform_handle_, 0);
// TODO(bajones): Should be able handle both eyes in a single draw call.
// Left eye
glUniform4fv(src_rect_uniform_handle_, 1, (float*)(&left_bounds_));
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
// Right eye
glUniform4fv(src_rect_uniform_handle_, 1, (float*)(&right_bounds_));
glDrawArrays(GL_TRIANGLE_FAN, 4, 4);
glDisableVertexAttribArray(position_handle_);
glDisableVertexAttribArray(texcoord_handle_);
glBindBuffer(GL_ARRAY_BUFFER, old_buffer);
}
void WebVrRenderer::UpdateTextureBounds(int eye, const gvr::Rectf& bounds) {
if (eye == 0) {
left_bounds_ = bounds;
} else if (eye == 1) {
right_bounds_ = bounds;
}
}
WebVrRenderer::~WebVrRenderer() {
glDeleteBuffersARB(1, &vertex_buffer_);
glDeleteProgram(program_handle_);
}
VrShellRenderer::VrShellRenderer() VrShellRenderer::VrShellRenderer()
: textured_quad_renderer_(new TexturedQuadRenderer) {} : textured_quad_renderer_(new TexturedQuadRenderer),
webvr_renderer_(new WebVrRenderer) {}
VrShellRenderer::~VrShellRenderer() {} VrShellRenderer::~VrShellRenderer() {}
......
...@@ -21,6 +21,8 @@ enum ShaderID { ...@@ -21,6 +21,8 @@ enum ShaderID {
SHADER_UNRECOGNIZED = 0, SHADER_UNRECOGNIZED = 0,
TEXTURE_QUAD_VERTEX_SHADER, TEXTURE_QUAD_VERTEX_SHADER,
TEXTURE_QUAD_FRAGMENT_SHADER, TEXTURE_QUAD_FRAGMENT_SHADER,
WEBVR_VERTEX_SHADER,
WEBVR_FRAGMENT_SHADER,
SHADER_ID_MAX SHADER_ID_MAX
}; };
...@@ -44,6 +46,36 @@ class TexturedQuadRenderer { ...@@ -44,6 +46,36 @@ class TexturedQuadRenderer {
DISALLOW_COPY_AND_ASSIGN(TexturedQuadRenderer); DISALLOW_COPY_AND_ASSIGN(TexturedQuadRenderer);
}; };
// Renders a page-generated stereo VR view.
class WebVrRenderer {
public:
WebVrRenderer();
~WebVrRenderer();
void Draw(int texture_handle);
void UpdateTextureBounds(int eye, const gvr::Rectf& bounds);
private:
static constexpr size_t VERTEX_STRIDE = sizeof(float) * 4;
static constexpr size_t POSITION_ELEMENTS = 2;
static constexpr size_t TEXCOORD_ELEMENTS = 2;
static constexpr size_t POSITION_OFFSET = 0;
static constexpr size_t TEXCOORD_OFFSET = sizeof(float) * 2;
GLuint program_handle_;
GLuint tex_uniform_handle_;
GLuint src_rect_uniform_handle_;
GLuint position_handle_;
GLuint texcoord_handle_;
GLuint vertex_buffer_;
gvr::Rectf left_bounds_;
gvr::Rectf right_bounds_;
DISALLOW_COPY_AND_ASSIGN(WebVrRenderer);
};
class VrShellRenderer { class VrShellRenderer {
public: public:
VrShellRenderer(); VrShellRenderer();
...@@ -53,8 +85,13 @@ class VrShellRenderer { ...@@ -53,8 +85,13 @@ class VrShellRenderer {
return textured_quad_renderer_.get(); return textured_quad_renderer_.get();
} }
WebVrRenderer* GetWebVrRenderer() {
return webvr_renderer_.get();
}
private: private:
std::unique_ptr<TexturedQuadRenderer> textured_quad_renderer_; std::unique_ptr<TexturedQuadRenderer> textured_quad_renderer_;
std::unique_ptr<WebVrRenderer> webvr_renderer_;
DISALLOW_COPY_AND_ASSIGN(VrShellRenderer); DISALLOW_COPY_AND_ASSIGN(VrShellRenderer);
}; };
......
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