Chromium Code Reviews| Index: gpu/command_buffer/client/program_info_manager_program.cc |
| diff --git a/gpu/command_buffer/client/program_info_manager_program.cc b/gpu/command_buffer/client/program_info_manager_program.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..3bfa88ea36abb00ecb8b31ab69b554b53fddcd8d |
| --- /dev/null |
| +++ b/gpu/command_buffer/client/program_info_manager_program.cc |
| @@ -0,0 +1,180 @@ |
| +// Copyright (c) 2015 The Chromium Authors. All rights reserved. |
|
piman
2015/01/30 21:55:39
Why separate this into another file?
Zhenyao Mo
2015/01/30 22:11:38
Because I am planning to add UniformBlock related
piman
2015/01/30 22:18:23
I disagree :) If a class is defined in foo.h, the
|
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "gpu/command_buffer/client/program_info_manager.h" |
| + |
| +namespace { |
| + |
| +template<typename T> static T LocalGetAs( |
| + const std::vector<int8>& data, uint32 offset, size_t size) { |
| + const int8* p = &data[0] + offset; |
| + if (offset + size > data.size()) { |
| + NOTREACHED(); |
| + return NULL; |
| + } |
| + return static_cast<T>(static_cast<const void*>(p)); |
| +} |
| + |
| +} // namespace anonymous |
| + |
| +namespace gpu { |
| +namespace gles2 { |
| + |
| +ProgramInfoManager::Program::UniformInfo::UniformInfo( |
| + GLsizei _size, GLenum _type, const std::string& _name) |
| + : size(_size), |
| + type(_type), |
| + name(_name) { |
| + is_array = (!name.empty() && name[name.size() - 1] == ']'); |
| + DCHECK(!(size > 1 && !is_array)); |
| +} |
| + |
| +ProgramInfoManager::Program::Program() |
| + : cached_(false), |
| + max_attrib_name_length_(0), |
| + max_uniform_name_length_(0), |
| + link_status_(false) { |
| +} |
| + |
| +// TODO(gman): Add a faster lookup. |
| +GLint ProgramInfoManager::Program::GetAttribLocation( |
| + const std::string& name) const { |
| + for (GLuint ii = 0; ii < attrib_infos_.size(); ++ii) { |
| + const VertexAttrib& info = attrib_infos_[ii]; |
| + if (info.name == name) { |
| + return info.location; |
| + } |
| + } |
| + return -1; |
| +} |
| + |
| +GLint ProgramInfoManager::Program::GetUniformLocation( |
| + const std::string& name) const { |
| + bool getting_array_location = false; |
| + size_t open_pos = std::string::npos; |
| + int index = 0; |
| + if (!GLES2Util::ParseUniformName( |
| + name, &open_pos, &index, &getting_array_location)) { |
| + return -1; |
| + } |
| + for (GLuint ii = 0; ii < uniform_infos_.size(); ++ii) { |
| + const UniformInfo& info = uniform_infos_[ii]; |
| + if (info.name == name || |
| + (info.is_array && |
| + info.name.compare(0, info.name.size() - 3, name) == 0)) { |
| + return info.element_locations[0]; |
| + } else if (getting_array_location && info.is_array) { |
| + // Look for an array specification. |
| + size_t open_pos_2 = info.name.find_last_of('['); |
| + if (open_pos_2 == open_pos && |
| + name.compare(0, open_pos, info.name, 0, open_pos) == 0) { |
| + if (index >= 0 && index < info.size) { |
| + return info.element_locations[index]; |
| + } |
| + } |
| + } |
| + } |
| + return -1; |
| +} |
| + |
| +GLint ProgramInfoManager::Program::GetFragDataLocation( |
| + const std::string& name) const { |
| + base::hash_map<std::string, GLint>::const_iterator iter = |
| + frag_data_locations_.find(name); |
| + if (iter == frag_data_locations_.end()) |
| + return -1; |
| + return iter->second; |
| +} |
| + |
| +void ProgramInfoManager::Program::CacheFragDataLocation( |
| + const std::string& name, GLint loc) { |
| + frag_data_locations_[name] = loc; |
| +} |
| + |
| +bool ProgramInfoManager::Program::GetProgramiv( |
| + GLenum pname, GLint* params) { |
| + switch (pname) { |
| + case GL_LINK_STATUS: |
| + *params = link_status_; |
| + return true; |
| + case GL_ACTIVE_ATTRIBUTES: |
| + *params = attrib_infos_.size(); |
| + return true; |
| + case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH: |
| + *params = max_attrib_name_length_; |
| + return true; |
| + case GL_ACTIVE_UNIFORMS: |
| + *params = uniform_infos_.size(); |
| + return true; |
| + case GL_ACTIVE_UNIFORM_MAX_LENGTH: |
| + *params = max_uniform_name_length_; |
| + return true; |
| + default: |
| + break; |
| + } |
| + return false; |
| +} |
| + |
| +void ProgramInfoManager::Program::Update( |
| + GLES2Implementation* gl, |
| + GLuint program, |
| + const std::vector<int8>& result) { |
| + if (cached_) { |
| + return; |
| + } |
| + if (result.empty()) { |
| + // This should only happen on a lost context. |
| + return; |
| + } |
| + DCHECK_GE(result.size(), sizeof(ProgramInfoHeader)); |
| + const ProgramInfoHeader* header = LocalGetAs<const ProgramInfoHeader*>( |
| + result, 0, sizeof(header)); |
| + link_status_ = header->link_status != 0; |
| + if (!link_status_) { |
| + return; |
| + } |
| + attrib_infos_.clear(); |
| + uniform_infos_.clear(); |
| + frag_data_locations_.clear(); |
| + max_attrib_name_length_ = 0; |
| + max_uniform_name_length_ = 0; |
| + const ProgramInput* inputs = LocalGetAs<const ProgramInput*>( |
| + result, sizeof(*header), |
| + sizeof(ProgramInput) * (header->num_attribs + header->num_uniforms)); |
| + const ProgramInput* input = inputs; |
| + for (uint32 ii = 0; ii < header->num_attribs; ++ii) { |
| + const int32* location = LocalGetAs<const int32*>( |
| + result, input->location_offset, sizeof(int32)); |
| + const char* name_buf = LocalGetAs<const char*>( |
| + result, input->name_offset, input->name_length); |
| + std::string name(name_buf, input->name_length); |
| + attrib_infos_.push_back( |
| + VertexAttrib(input->size, input->type, name, *location)); |
| + max_attrib_name_length_ = std::max( |
| + static_cast<GLsizei>(name.size() + 1), max_attrib_name_length_); |
| + ++input; |
| + } |
| + for (uint32 ii = 0; ii < header->num_uniforms; ++ii) { |
| + const int32* locations = LocalGetAs<const int32*>( |
| + result, input->location_offset, sizeof(int32) * input->size); |
| + const char* name_buf = LocalGetAs<const char*>( |
| + result, input->name_offset, input->name_length); |
| + std::string name(name_buf, input->name_length); |
| + UniformInfo info(input->size, input->type, name); |
| + max_uniform_name_length_ = std::max( |
| + static_cast<GLsizei>(name.size() + 1), max_uniform_name_length_); |
| + for (int32 jj = 0; jj < input->size; ++jj) { |
| + info.element_locations.push_back(locations[jj]); |
| + } |
| + uniform_infos_.push_back(info); |
| + ++input; |
| + } |
| + DCHECK_EQ(header->num_attribs + header->num_uniforms, |
| + static_cast<uint32>(input - inputs)); |
| + cached_ = true; |
| +} |
| + |
| +} // namespace gles2 |
| +} // namespace gpu |
| + |