Linux: Depend on liberation-fonts package for RPMs.
[chromium-blink-merge.git] / gpu / command_buffer / service / shader_manager.cc
blob0ad8bf09bb71b03ba4a3cecbd954df7fa0662de2
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
3 // found in the LICENSE file.
5 #include "gpu/command_buffer/service/shader_manager.h"
7 #include <utility>
9 #include "base/logging.h"
10 #include "base/strings/string_util.h"
12 namespace gpu {
13 namespace gles2 {
15 namespace {
17 // Given a variable name | a[0].b.c[0] |, return |a|.
18 std::string GetTopVariableName(const std::string& fullname) {
19 size_t pos = fullname.find_first_of("[.");
20 if (pos == std::string::npos)
21 return fullname;
22 return fullname.substr(0, pos);
25 } // namespace anonymous
27 Shader::Shader(GLuint service_id, GLenum shader_type)
28 : use_count_(0),
29 shader_state_(kShaderStateWaiting),
30 marked_for_deletion_(false),
31 service_id_(service_id),
32 shader_type_(shader_type),
33 shader_version_(kUndefinedShaderVersion),
34 source_type_(kANGLE),
35 valid_(false) {
38 Shader::~Shader() {
41 void Shader::Destroy() {
42 if (service_id_) {
43 DeleteServiceID();
47 void Shader::RequestCompile(scoped_refptr<ShaderTranslatorInterface> translator,
48 TranslatedShaderSourceType type) {
49 shader_state_ = kShaderStateCompileRequested;
50 translator_ = translator;
51 source_type_ = type;
52 last_compiled_source_ = source_;
55 void Shader::DoCompile() {
56 // We require that RequestCompile() must be called before DoCompile(),
57 // so we can return early if the shader state is not what we expect.
58 if (shader_state_ != kShaderStateCompileRequested) {
59 return;
62 // Signify the shader has been compiled, whether or not it is valid
63 // is dependent on the |valid_| member variable.
64 shader_state_ = kShaderStateCompiled;
65 valid_ = false;
67 // Translate GL ES 2.0 shader to Desktop GL shader and pass that to
68 // glShaderSource and then glCompileShader.
69 const char* source_for_driver = last_compiled_source_.c_str();
70 ShaderTranslatorInterface* translator = translator_.get();
71 if (translator) {
72 bool success = translator->Translate(last_compiled_source_,
73 &log_info_,
74 &translated_source_,
75 &shader_version_,
76 &attrib_map_,
77 &uniform_map_,
78 &varying_map_,
79 &name_map_);
80 if (!success) {
81 return;
83 source_for_driver = translated_source_.c_str();
86 glShaderSource(service_id_, 1, &source_for_driver, NULL);
87 glCompileShader(service_id_);
88 if (source_type_ == kANGLE) {
89 GLint max_len = 0;
90 glGetShaderiv(service_id_,
91 GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE,
92 &max_len);
93 source_for_driver = "\0";
94 translated_source_.resize(max_len);
95 if (max_len) {
96 GLint len = 0;
97 glGetTranslatedShaderSourceANGLE(
98 service_id_, translated_source_.size(),
99 &len, &translated_source_.at(0));
100 DCHECK(max_len == 0 || len < max_len);
101 DCHECK(len == 0 || translated_source_[len] == '\0');
102 translated_source_.resize(len);
103 source_for_driver = translated_source_.c_str();
107 GLint status = GL_FALSE;
108 glGetShaderiv(service_id_, GL_COMPILE_STATUS, &status);
109 if (status == GL_TRUE) {
110 valid_ = true;
111 } else {
112 valid_ = false;
114 // We cannot reach here if we are using the shader translator.
115 // All invalid shaders must be rejected by the translator.
116 // All translated shaders must compile.
117 std::string translator_log = log_info_;
119 GLint max_len = 0;
120 glGetShaderiv(service_id_, GL_INFO_LOG_LENGTH, &max_len);
121 log_info_.resize(max_len);
122 if (max_len) {
123 GLint len = 0;
124 glGetShaderInfoLog(service_id_, log_info_.size(), &len, &log_info_.at(0));
125 DCHECK(max_len == 0 || len < max_len);
126 DCHECK(len == 0 || log_info_[len] == '\0');
127 log_info_.resize(len);
130 LOG_IF(ERROR, translator)
131 << "Shader translator allowed/produced an invalid shader "
132 << "unless the driver is buggy:"
133 << "\n--Log from shader translator--\n" << translator_log
134 << "\n--original-shader--\n" << last_compiled_source_
135 << "\n--translated-shader--\n" << source_for_driver
136 << "\n--info-log--\n" << log_info_;
140 void Shader::IncUseCount() {
141 ++use_count_;
144 void Shader::DecUseCount() {
145 --use_count_;
146 DCHECK_GE(use_count_, 0);
147 if (service_id_ && use_count_ == 0 && marked_for_deletion_) {
148 DeleteServiceID();
152 void Shader::MarkForDeletion() {
153 DCHECK(!marked_for_deletion_);
154 DCHECK_NE(service_id_, 0u);
156 marked_for_deletion_ = true;
157 if (use_count_ == 0) {
158 DeleteServiceID();
162 void Shader::DeleteServiceID() {
163 DCHECK_NE(service_id_, 0u);
164 glDeleteShader(service_id_);
165 service_id_ = 0;
168 const sh::Attribute* Shader::GetAttribInfo(const std::string& name) const {
169 // Vertex attributes can't be arrays or structs (GLSL ES 3.00.4, section
170 // 4.3.4, "Input Variables"), so |name| is the top level name used as
171 // the AttributeMap key.
172 AttributeMap::const_iterator it = attrib_map_.find(name);
173 return it != attrib_map_.end() ? &it->second : NULL;
176 const std::string* Shader::GetAttribMappedName(
177 const std::string& original_name) const {
178 for (const auto& key_value : attrib_map_) {
179 if (key_value.second.name == original_name)
180 return &(key_value.first);
182 return nullptr;
185 const std::string* Shader::GetUniformMappedName(
186 const std::string& original_name) const {
187 for (const auto& key_value : uniform_map_) {
188 if (key_value.second.name == original_name)
189 return &(key_value.first);
191 return nullptr;
194 const std::string* Shader::GetVaryingMappedName(
195 const std::string& original_name) const {
196 for (VaryingMap::const_iterator it = varying_map_.begin();
197 it != varying_map_.end(); ++it) {
198 if (it->second.name == original_name)
199 return &(it->first);
201 return NULL;
204 const std::string* Shader::GetOriginalNameFromHashedName(
205 const std::string& hashed_name) const {
206 NameMap::const_iterator it = name_map_.find(hashed_name);
207 if (it != name_map_.end())
208 return &(it->second);
209 return NULL;
212 const sh::Uniform* Shader::GetUniformInfo(const std::string& name) const {
213 UniformMap::const_iterator it = uniform_map_.find(GetTopVariableName(name));
214 return it != uniform_map_.end() ? &it->second : NULL;
217 const sh::Varying* Shader::GetVaryingInfo(const std::string& name) const {
218 VaryingMap::const_iterator it = varying_map_.find(GetTopVariableName(name));
219 return it != varying_map_.end() ? &it->second : NULL;
222 ShaderManager::ShaderManager() {}
224 ShaderManager::~ShaderManager() {
225 DCHECK(shaders_.empty());
228 void ShaderManager::Destroy(bool have_context) {
229 while (!shaders_.empty()) {
230 if (have_context) {
231 Shader* shader = shaders_.begin()->second.get();
232 shader->Destroy();
234 shaders_.erase(shaders_.begin());
238 Shader* ShaderManager::CreateShader(
239 GLuint client_id,
240 GLuint service_id,
241 GLenum shader_type) {
242 std::pair<ShaderMap::iterator, bool> result =
243 shaders_.insert(std::make_pair(
244 client_id, scoped_refptr<Shader>(
245 new Shader(service_id, shader_type))));
246 DCHECK(result.second);
247 return result.first->second.get();
250 Shader* ShaderManager::GetShader(GLuint client_id) {
251 ShaderMap::iterator it = shaders_.find(client_id);
252 return it != shaders_.end() ? it->second.get() : NULL;
255 bool ShaderManager::GetClientId(GLuint service_id, GLuint* client_id) const {
256 // This doesn't need to be fast. It's only used during slow queries.
257 for (ShaderMap::const_iterator it = shaders_.begin();
258 it != shaders_.end(); ++it) {
259 if (it->second->service_id() == service_id) {
260 *client_id = it->first;
261 return true;
264 return false;
267 bool ShaderManager::IsOwned(Shader* shader) {
268 for (ShaderMap::iterator it = shaders_.begin();
269 it != shaders_.end(); ++it) {
270 if (it->second.get() == shader) {
271 return true;
274 return false;
277 void ShaderManager::RemoveShader(Shader* shader) {
278 DCHECK(shader);
279 DCHECK(IsOwned(shader));
280 if (shader->IsDeleted() && !shader->InUse()) {
281 for (ShaderMap::iterator it = shaders_.begin();
282 it != shaders_.end(); ++it) {
283 if (it->second.get() == shader) {
284 shaders_.erase(it);
285 return;
288 NOTREACHED();
292 void ShaderManager::Delete(Shader* shader) {
293 DCHECK(shader);
294 DCHECK(IsOwned(shader));
295 shader->MarkForDeletion();
296 RemoveShader(shader);
299 void ShaderManager::UseShader(Shader* shader) {
300 DCHECK(shader);
301 DCHECK(IsOwned(shader));
302 shader->IncUseCount();
305 void ShaderManager::UnuseShader(Shader* shader) {
306 DCHECK(shader);
307 DCHECK(IsOwned(shader));
308 shader->DecUseCount();
309 RemoveShader(shader);
312 } // namespace gles2
313 } // namespace gpu