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 |
+ |