OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "gpu/command_buffer/service/program_manager.h" | 5 #include "gpu/command_buffer/service/program_manager.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <set> | 8 #include <set> |
9 | 9 |
10 #include "base/basictypes.h" | 10 #include "base/basictypes.h" |
11 #include "base/logging.h" | 11 #include "base/logging.h" |
12 #include "base/memory/scoped_ptr.h" | 12 #include "base/memory/scoped_ptr.h" |
13 #include "base/string_number_conversions.h" | 13 #include "base/string_number_conversions.h" |
14 #include "gpu/command_buffer/common/gles2_cmd_format.h" | 14 #include "gpu/command_buffer/common/gles2_cmd_format.h" |
| 15 #include "gpu/command_buffer/common/gles2_cmd_utils.h" |
15 #include "gpu/command_buffer/service/gles2_cmd_decoder.h" | 16 #include "gpu/command_buffer/service/gles2_cmd_decoder.h" |
16 | 17 |
17 namespace gpu { | 18 namespace gpu { |
18 namespace gles2 { | 19 namespace gles2 { |
19 | 20 |
20 static int ShaderTypeToIndex(GLenum shader_type) { | 21 static int ShaderTypeToIndex(GLenum shader_type) { |
21 switch (shader_type) { | 22 switch (shader_type) { |
22 case GL_VERTEX_SHADER: | 23 case GL_VERTEX_SHADER: |
23 return 0; | 24 return 0; |
24 case GL_FRAGMENT_SHADER: | 25 case GL_FRAGMENT_SHADER: |
(...skipping 26 matching lines...) Expand all Loading... |
51 | 52 |
52 ProgramManager::ProgramInfo::ProgramInfo( | 53 ProgramManager::ProgramInfo::ProgramInfo( |
53 ProgramManager* manager, GLuint service_id) | 54 ProgramManager* manager, GLuint service_id) |
54 : manager_(manager), | 55 : manager_(manager), |
55 use_count_(0), | 56 use_count_(0), |
56 max_attrib_name_length_(0), | 57 max_attrib_name_length_(0), |
57 max_uniform_name_length_(0), | 58 max_uniform_name_length_(0), |
58 service_id_(service_id), | 59 service_id_(service_id), |
59 deleted_(false), | 60 deleted_(false), |
60 valid_(false), | 61 valid_(false), |
61 link_status_(false) { | 62 link_status_(false), |
| 63 uniforms_cleared_(false) { |
62 manager_->StartTracking(this); | 64 manager_->StartTracking(this); |
63 } | 65 } |
64 | 66 |
65 void ProgramManager::ProgramInfo::Reset() { | 67 void ProgramManager::ProgramInfo::Reset() { |
66 valid_ = false; | 68 valid_ = false; |
67 link_status_ = false; | 69 link_status_ = false; |
68 max_uniform_name_length_ = 0; | 70 max_uniform_name_length_ = 0; |
69 max_attrib_name_length_ = 0; | 71 max_attrib_name_length_ = 0; |
70 attrib_infos_.clear(); | 72 attrib_infos_.clear(); |
71 uniform_infos_.clear(); | 73 uniform_infos_.clear(); |
72 sampler_indices_.clear(); | 74 sampler_indices_.clear(); |
73 attrib_location_to_index_map_.clear(); | 75 attrib_location_to_index_map_.clear(); |
74 } | 76 } |
75 | 77 |
76 void ProgramManager::ProgramInfo::UpdateLogInfo() { | 78 void ProgramManager::ProgramInfo::UpdateLogInfo() { |
77 GLint max_len = 0; | 79 GLint max_len = 0; |
78 glGetProgramiv(service_id_, GL_INFO_LOG_LENGTH, &max_len); | 80 glGetProgramiv(service_id_, GL_INFO_LOG_LENGTH, &max_len); |
79 if (max_len == 0) { | 81 if (max_len == 0) { |
80 set_log_info(NULL); | 82 set_log_info(NULL); |
81 return; | 83 return; |
82 } | 84 } |
83 scoped_array<char> temp(new char[max_len]); | 85 scoped_array<char> temp(new char[max_len]); |
84 GLint len = 0; | 86 GLint len = 0; |
85 glGetProgramInfoLog(service_id_, max_len, &len, temp.get()); | 87 glGetProgramInfoLog(service_id_, max_len, &len, temp.get()); |
86 DCHECK(max_len == 0 || len < max_len); | 88 DCHECK(max_len == 0 || len < max_len); |
87 DCHECK(len == 0 || temp[len] == '\0'); | 89 DCHECK(len == 0 || temp[len] == '\0'); |
88 set_log_info(std::string(temp.get(), len).c_str()); | 90 set_log_info(std::string(temp.get(), len).c_str()); |
89 } | 91 } |
90 | 92 |
| 93 void ProgramManager::ProgramInfo::ClearUniforms( |
| 94 std::vector<uint8>* zero_buffer) { |
| 95 DCHECK(zero_buffer); |
| 96 if (uniforms_cleared_) { |
| 97 return; |
| 98 } |
| 99 uniforms_cleared_ = true; |
| 100 for (size_t ii = 0; ii < uniform_infos_.size(); ++ii) { |
| 101 const UniformInfo& uniform_info = uniform_infos_[ii]; |
| 102 GLint location = uniform_info.element_locations[0]; |
| 103 GLsizei size = uniform_info.size; |
| 104 uint32 unit_size = GLES2Util::GetGLDataTypeSizeForUniforms( |
| 105 uniform_info.type); |
| 106 uint32 size_needed = size * unit_size; |
| 107 if (size_needed > zero_buffer->size()) { |
| 108 zero_buffer->resize(size_needed, 0u); |
| 109 } |
| 110 const void* zero = &(*zero_buffer)[0]; |
| 111 switch (uniform_info.type) { |
| 112 case GL_FLOAT: |
| 113 glUniform1fv(location, size, reinterpret_cast<const GLfloat*>(zero)); |
| 114 break; |
| 115 case GL_FLOAT_VEC2: |
| 116 glUniform2fv(location, size, reinterpret_cast<const GLfloat*>(zero)); |
| 117 break; |
| 118 case GL_FLOAT_VEC3: |
| 119 glUniform3fv(location, size, reinterpret_cast<const GLfloat*>(zero)); |
| 120 break; |
| 121 case GL_FLOAT_VEC4: |
| 122 glUniform4fv(location, size, reinterpret_cast<const GLfloat*>(zero)); |
| 123 break; |
| 124 case GL_INT: |
| 125 case GL_BOOL: |
| 126 case GL_SAMPLER_2D: |
| 127 case GL_SAMPLER_CUBE: |
| 128 case GL_SAMPLER_EXTERNAL_OES: |
| 129 glUniform1iv(location, size, reinterpret_cast<const GLint*>(zero)); |
| 130 break; |
| 131 case GL_INT_VEC2: |
| 132 case GL_BOOL_VEC2: |
| 133 glUniform2iv(location, size, reinterpret_cast<const GLint*>(zero)); |
| 134 break; |
| 135 case GL_INT_VEC3: |
| 136 case GL_BOOL_VEC3: |
| 137 glUniform3iv(location, size, reinterpret_cast<const GLint*>(zero)); |
| 138 break; |
| 139 case GL_INT_VEC4: |
| 140 case GL_BOOL_VEC4: |
| 141 glUniform4iv(location, size, reinterpret_cast<const GLint*>(zero)); |
| 142 break; |
| 143 case GL_FLOAT_MAT2: |
| 144 glUniformMatrix2fv( |
| 145 location, size, false, reinterpret_cast<const GLfloat*>(zero)); |
| 146 break; |
| 147 case GL_FLOAT_MAT3: |
| 148 glUniformMatrix3fv( |
| 149 location, size, false, reinterpret_cast<const GLfloat*>(zero)); |
| 150 break; |
| 151 case GL_FLOAT_MAT4: |
| 152 glUniformMatrix4fv( |
| 153 location, size, false, reinterpret_cast<const GLfloat*>(zero)); |
| 154 break; |
| 155 default: |
| 156 NOTREACHED(); |
| 157 break; |
| 158 } |
| 159 } |
| 160 } |
| 161 |
91 void ProgramManager::ProgramInfo::Update() { | 162 void ProgramManager::ProgramInfo::Update() { |
92 Reset(); | 163 Reset(); |
93 UpdateLogInfo(); | 164 UpdateLogInfo(); |
94 link_status_ = true; | 165 link_status_ = true; |
| 166 uniforms_cleared_ = false; |
95 GLint num_attribs = 0; | 167 GLint num_attribs = 0; |
96 GLint max_len = 0; | 168 GLint max_len = 0; |
97 GLint max_location = -1; | 169 GLint max_location = -1; |
98 glGetProgramiv(service_id_, GL_ACTIVE_ATTRIBUTES, &num_attribs); | 170 glGetProgramiv(service_id_, GL_ACTIVE_ATTRIBUTES, &num_attribs); |
99 glGetProgramiv(service_id_, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &max_len); | 171 glGetProgramiv(service_id_, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &max_len); |
100 // TODO(gman): Should we check for error? | 172 // TODO(gman): Should we check for error? |
101 scoped_array<char> name_buffer(new char[max_len]); | 173 scoped_array<char> name_buffer(new char[max_len]); |
102 for (GLint ii = 0; ii < num_attribs; ++ii) { | 174 for (GLint ii = 0; ii < num_attribs; ++ii) { |
103 GLsizei length = 0; | 175 GLsizei length = 0; |
104 GLsizei size = 0; | 176 GLsizei size = 0; |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
170 void ProgramManager::ProgramInfo::ExecuteBindAttribLocationCalls() { | 242 void ProgramManager::ProgramInfo::ExecuteBindAttribLocationCalls() { |
171 for (std::map<std::string, GLint>::const_iterator it = | 243 for (std::map<std::string, GLint>::const_iterator it = |
172 bind_attrib_location_map_.begin(); | 244 bind_attrib_location_map_.begin(); |
173 it != bind_attrib_location_map_.end(); ++it) { | 245 it != bind_attrib_location_map_.end(); ++it) { |
174 const std::string* mapped_name = GetAttribMappedName(it->first); | 246 const std::string* mapped_name = GetAttribMappedName(it->first); |
175 if (mapped_name && *mapped_name != it->first) | 247 if (mapped_name && *mapped_name != it->first) |
176 glBindAttribLocation(service_id_, it->second, mapped_name->c_str()); | 248 glBindAttribLocation(service_id_, it->second, mapped_name->c_str()); |
177 } | 249 } |
178 } | 250 } |
179 | 251 |
180 void ProgramManager::ProgramInfo::Link() { | 252 bool ProgramManager::ProgramInfo::Link() { |
181 ClearLinkStatus(); | 253 ClearLinkStatus(); |
182 if (!CanLink()) { | 254 if (!CanLink()) { |
183 set_log_info("missing shaders"); | 255 set_log_info("missing shaders"); |
184 return; | 256 return false; |
185 } | 257 } |
186 if (DetectAttribLocationBindingConflicts()) { | 258 if (DetectAttribLocationBindingConflicts()) { |
187 set_log_info("glBindAttribLocation() conflicts"); | 259 set_log_info("glBindAttribLocation() conflicts"); |
188 return; | 260 return false; |
189 } | 261 } |
190 ExecuteBindAttribLocationCalls(); | 262 ExecuteBindAttribLocationCalls(); |
191 glLinkProgram(service_id()); | 263 glLinkProgram(service_id()); |
192 GLint success = 0; | 264 GLint success = 0; |
193 glGetProgramiv(service_id(), GL_LINK_STATUS, &success); | 265 glGetProgramiv(service_id(), GL_LINK_STATUS, &success); |
194 if (success) { | 266 if (success == GL_TRUE) { |
195 Update(); | 267 Update(); |
196 } else { | 268 } else { |
197 UpdateLogInfo(); | 269 UpdateLogInfo(); |
198 } | 270 } |
| 271 return success == GL_TRUE; |
199 } | 272 } |
200 | 273 |
201 void ProgramManager::ProgramInfo::Validate() { | 274 void ProgramManager::ProgramInfo::Validate() { |
202 if (!IsValid()) { | 275 if (!IsValid()) { |
203 set_log_info("program not linked"); | 276 set_log_info("program not linked"); |
204 return; | 277 return; |
205 } | 278 } |
206 glValidateProgram(service_id()); | 279 glValidateProgram(service_id()); |
207 UpdateLogInfo(); | 280 UpdateLogInfo(); |
208 } | 281 } |
(...skipping 476 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
685 DCHECK(info); | 758 DCHECK(info); |
686 DCHECK(IsOwned(info)); | 759 DCHECK(IsOwned(info)); |
687 info->MarkAsDeleted(); | 760 info->MarkAsDeleted(); |
688 RemoveProgramInfoIfUnused(shader_manager, info); | 761 RemoveProgramInfoIfUnused(shader_manager, info); |
689 } | 762 } |
690 | 763 |
691 void ProgramManager::UseProgram(ProgramManager::ProgramInfo* info) { | 764 void ProgramManager::UseProgram(ProgramManager::ProgramInfo* info) { |
692 DCHECK(info); | 765 DCHECK(info); |
693 DCHECK(IsOwned(info)); | 766 DCHECK(IsOwned(info)); |
694 info->IncUseCount(); | 767 info->IncUseCount(); |
| 768 ClearUniforms(info); |
695 } | 769 } |
696 | 770 |
697 void ProgramManager::UnuseProgram( | 771 void ProgramManager::UnuseProgram( |
698 ShaderManager* shader_manager, | 772 ShaderManager* shader_manager, |
699 ProgramManager::ProgramInfo* info) { | 773 ProgramManager::ProgramInfo* info) { |
700 DCHECK(shader_manager); | 774 DCHECK(shader_manager); |
701 DCHECK(info); | 775 DCHECK(info); |
702 DCHECK(IsOwned(info)); | 776 DCHECK(IsOwned(info)); |
703 info->DecUseCount(); | 777 info->DecUseCount(); |
704 RemoveProgramInfoIfUnused(shader_manager, info); | 778 RemoveProgramInfoIfUnused(shader_manager, info); |
705 } | 779 } |
706 | 780 |
| 781 void ProgramManager::ClearUniforms(ProgramManager::ProgramInfo* info) { |
| 782 DCHECK(info); |
| 783 info->ClearUniforms(&zero_); |
| 784 } |
| 785 |
707 // Swizzles the locations to prevent developers from assuming they | 786 // Swizzles the locations to prevent developers from assuming they |
708 // can do math on uniforms. According to the OpenGL ES 2.0 spec | 787 // can do math on uniforms. According to the OpenGL ES 2.0 spec |
709 // the location of "someuniform[1]" is not 'n' more than "someuniform[0]". | 788 // the location of "someuniform[1]" is not 'n' more than "someuniform[0]". |
710 static GLint Swizzle(GLint location) { | 789 static GLint Swizzle(GLint location) { |
711 return (location & 0xF0000000U) | | 790 return (location & 0xF0000000U) | |
712 ((location & 0x0AAAAAAAU) >> 1) | | 791 ((location & 0x0AAAAAAAU) >> 1) | |
713 ((location & 0x05555555U) << 1); | 792 ((location & 0x05555555U) << 1); |
714 } | 793 } |
715 | 794 |
716 // Adds uniform_swizzle_ to prevent developers from assuming that locations are | 795 // Adds uniform_swizzle_ to prevent developers from assuming that locations are |
717 // always the same across GPUs and drivers. | 796 // always the same across GPUs and drivers. |
718 GLint ProgramManager::SwizzleLocation(GLint v) const { | 797 GLint ProgramManager::SwizzleLocation(GLint v) const { |
719 return v < 0 ? v : (Swizzle(v) + uniform_swizzle_); | 798 return v < 0 ? v : (Swizzle(v) + uniform_swizzle_); |
720 } | 799 } |
721 | 800 |
722 GLint ProgramManager::UnswizzleLocation(GLint v) const { | 801 GLint ProgramManager::UnswizzleLocation(GLint v) const { |
723 return v < 0 ? v : Swizzle(v - uniform_swizzle_); | 802 return v < 0 ? v : Swizzle(v - uniform_swizzle_); |
724 } | 803 } |
725 | 804 |
726 } // namespace gles2 | 805 } // namespace gles2 |
727 } // namespace gpu | 806 } // namespace gpu |
728 | 807 |
729 | 808 |
OLD | NEW |