Index: chrome/browser/android/vr_shell/vr_shell_renderer.cc |
diff --git a/chrome/browser/android/vr_shell/vr_shell_renderer.cc b/chrome/browser/android/vr_shell/vr_shell_renderer.cc |
index 7fb405fdd5b3717c19ce424240913e5adc7455bb..6f21d120f66a6b7e2127fc2ce763a7c49e844745 100644 |
--- a/chrome/browser/android/vr_shell/vr_shell_renderer.cc |
+++ b/chrome/browser/android/vr_shell/vr_shell_renderer.cc |
@@ -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}; |
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 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) { |
switch (shader) { |
@@ -44,6 +58,26 @@ const char* GetShaderSource(ShaderID shader) { |
vec4 texture = texture2D(u_Texture, v_TexCoordinate); |
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: |
LOG(ERROR) << "Shader source requested for unknown shader"; |
return ""; |
@@ -56,23 +90,16 @@ TexturedQuadRenderer::TexturedQuadRenderer() { |
std::string error; |
vertex_shader_handle_ = CompileShader( |
GL_VERTEX_SHADER, GetShaderSource(TEXTURE_QUAD_VERTEX_SHADER), error); |
- if (vertex_shader_handle_ == 0) { |
- LOG(ERROR) << error; |
- exit(1); |
- } |
+ CHECK(vertex_shader_handle_) << error; |
+ |
fragment_shader_handle_ = CompileShader( |
GL_FRAGMENT_SHADER, GetShaderSource(TEXTURE_QUAD_FRAGMENT_SHADER), error); |
- if (fragment_shader_handle_ == 0) { |
- LOG(ERROR) << error; |
- exit(1); |
- } |
+ CHECK(fragment_shader_handle_) << error; |
program_handle_ = CreateAndLinkProgram( |
vertex_shader_handle_, fragment_shader_handle_, 4, nullptr, error); |
- if (program_handle_ == 0) { |
- LOG(ERROR) << error; |
- exit(1); |
- } |
+ CHECK(program_handle_) << error; |
+ |
combined_matrix_handle_ = |
glGetUniformLocation(program_handle_, "u_CombinedMatrix"); |
texture_uniform_handle_ = glGetUniformLocation(program_handle_, "u_Texture"); |
@@ -118,8 +145,99 @@ TexturedQuadRenderer::~TexturedQuadRenderer() { |
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() |
- : textured_quad_renderer_(new TexturedQuadRenderer) {} |
+ : textured_quad_renderer_(new TexturedQuadRenderer), |
+ webvr_renderer_(new WebVrRenderer) {} |
VrShellRenderer::~VrShellRenderer() {} |