Chromium Code Reviews| 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 33e87fc6059a4fcb0206815df610fbed170a001f..e790bf837b709617076909ddcfe7986c80b72db9 100644 |
| --- a/chrome/browser/android/vr_shell/vr_shell_renderer.cc |
| +++ b/chrome/browser/android/vr_shell/vr_shell_renderer.cc |
| @@ -5,6 +5,9 @@ |
| #include "chrome/browser/android/vr_shell/vr_shell_renderer.h" |
| #include "chrome/browser/android/vr_shell/vr_gl_util.h" |
| +#include "chrome/grit/browser_resources.h" |
| +#include "ui/base/resource/resource_bundle.h" |
| +#include "ui/gfx/codec/png_codec.h" |
| #include "ui/gl/gl_bindings.h" |
| namespace { |
| @@ -41,6 +44,14 @@ const float kWebVrVertices[32] = { |
| 1.f, 1.f, 1.f, 0.f }; |
| const int kWebVrVerticesSize = sizeof(float) * 32; |
| +const float kOverlayIconVertices[32] = { |
| + // x y u, v |
| + -1.f, 1.f, 0.f, 0.f, |
| + -1.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 kOverlayIconVerticesSize = sizeof(float) * 16; |
| + |
| // Reticle constants |
| static constexpr float kRingDiameter = 1.0f; |
| static constexpr float kInnerHole = 0.0f; |
| @@ -174,6 +185,27 @@ const char* GetShaderSource(vr_shell::ShaderID shader) { |
| lowp vec4 final_color = color * texture_color; |
| gl_FragColor = vec4(final_color.xyz, final_color.w * total_fade); |
| }); |
| + case vr_shell::ShaderID::OVERLAY_ICON_VERTEX_SHADER: |
| + return SHADER( |
| + uniform mat4 u_CombinedMatrix; |
| + 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 = u_CombinedMatrix * vec4(a_Position, 0.0, 1.0); |
| + }); |
| + case vr_shell::ShaderID::OVERLAY_ICON_FRAGMENT_SHADER: |
| + return SHADER( |
| + precision highp float; |
| + uniform sampler2D 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 ""; |
| @@ -439,11 +471,129 @@ void LaserRenderer::Draw(const gvr::Mat4f& combined_matrix) { |
| LaserRenderer::~LaserRenderer() = default; |
| +void MakeTexImage(int resource_id, |
| + GLuint texture_data_handles[], |
| + int icon_id) { |
| + std::string data_str = ResourceBundle::GetSharedInstance().GetRawDataResource( |
| + resource_id).as_string(); |
| + std::vector<unsigned char> data(data_str.begin(), data_str.end()); |
|
billorr
2016/09/23 17:52:11
this is doing a copy, right? do we need to copy?
|
| + std::vector<unsigned char> decoded; |
| + int width, height; |
| + |
| + // This decoder isn't suitable for externally-supplied data, but in |
| + // this case we're using it to decode a built-in resource supplied |
| + // at build time. Don't use this for untrusted images. |
| + gfx::PNGCodec::Decode(&data[0], data.size(), |
|
billorr
2016/09/23 17:52:11
why not data.data()? I believe our coding convent
|
| + gfx::PNGCodec::FORMAT_RGBA, |
| + &decoded, &width, &height); |
| + |
| + glBindTexture(GL_TEXTURE_2D, texture_data_handles[icon_id]); |
| + |
| + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, |
| + 0, GL_RGBA, GL_UNSIGNED_BYTE, &decoded[0]); |
| + |
| + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
| + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
| + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
| + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
| +} |
| + |
| +OverlayIconRenderer::OverlayIconRenderer() { |
| + bounds_ = { 0.0f, 0.0f, 1.0f, 1.0f }; |
| + |
| + std::string error; |
| + GLuint vertex_shader_handle = CompileShader( |
| + GL_VERTEX_SHADER, GetShaderSource(OVERLAY_ICON_VERTEX_SHADER), error); |
| + CHECK(vertex_shader_handle) << error; |
| + |
| + GLuint fragment_shader_handle = CompileShader( |
| + GL_FRAGMENT_SHADER, GetShaderSource(OVERLAY_ICON_FRAGMENT_SHADER), error); |
| + CHECK(fragment_shader_handle) << error; |
| + |
| + program_handle_ = CreateAndLinkProgram( |
| + vertex_shader_handle, fragment_shader_handle, 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); |
| + |
| + combined_matrix_handle_ = |
| + glGetUniformLocation(program_handle_, "u_CombinedMatrix"); |
| + 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, kOverlayIconVerticesSize, kOverlayIconVertices, |
| + GL_STATIC_DRAW); |
| + |
| + glBindBuffer(GL_ARRAY_BUFFER, old_buffer); |
| + |
| + glGenTextures(ICON_ID_MAX, texture_data_handles_); |
| + |
| + MakeTexImage(IDR_VR_SHELL_WEBVR_NOT_SECURE_PERMANENT_PNG, |
| + texture_data_handles_, |
| + ICON_INSECURE_PERMANENT); |
| + MakeTexImage(IDR_VR_SHELL_WEBVR_NOT_SECURE_TRANSIENT_PNG, |
| + texture_data_handles_, |
| + ICON_INSECURE_TRANSIENT); |
| +} |
| + |
| +void OverlayIconRenderer::Draw(const gvr::Mat4f& combined_matrix, |
| + int icon_num) { |
| + // 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_); |
| + |
| + // Pass in model view project matrix. |
| + glUniformMatrix4fv(combined_matrix_handle_, 1, false, |
| + MatrixToGLArray(combined_matrix).data()); |
| + |
| + 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_2D, texture_data_handles_[icon_num]); |
| + glUniform1i(tex_uniform_handle_, 0); |
| + |
| + glEnable(GL_BLEND); |
| + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); |
| + |
| + glUniform4fv(src_rect_uniform_handle_, 1, (float*)(&bounds_)); |
| + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); |
| + |
| + glDisableVertexAttribArray(position_handle_); |
| + glDisableVertexAttribArray(texcoord_handle_); |
| + |
| + glBindBuffer(GL_ARRAY_BUFFER, old_buffer); |
| +} |
| + |
| +OverlayIconRenderer::~OverlayIconRenderer() = default; |
| + |
| VrShellRenderer::VrShellRenderer() |
| : textured_quad_renderer_(new TexturedQuadRenderer), |
| webvr_renderer_(new WebVrRenderer), |
| reticle_renderer_(new ReticleRenderer), |
| - laser_renderer_(new LaserRenderer) {} |
| + laser_renderer_(new LaserRenderer), |
| + overlay_icon_renderer_(new OverlayIconRenderer) {} |
| VrShellRenderer::~VrShellRenderer() = default; |