Rewrite AndroidSyncSettings to be significantly simpler.
[chromium-blink-merge.git] / gpu / command_buffer / service / shader_manager.cc
blobfa071805eef226d9189e0ee640e0ea53b66ab80d
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 service_id_(service_id),
31 shader_type_(shader_type),
32 source_type_(kANGLE),
33 valid_(false) {
36 Shader::~Shader() {
39 void Shader::RequestCompile(scoped_refptr<ShaderTranslatorInterface> translator,
40 TranslatedShaderSourceType type) {
41 shader_state_ = kShaderStateCompileRequested;
42 translator_ = translator;
43 source_type_ = type;
44 last_compiled_source_ = source_;
47 void Shader::DoCompile() {
48 // We require that RequestCompile() must be called before DoCompile(),
49 // so we can return early if the shader state is not what we expect.
50 if (shader_state_ != kShaderStateCompileRequested) {
51 return;
54 // Signify the shader has been compiled, whether or not it is valid
55 // is dependent on the |valid_| member variable.
56 shader_state_ = kShaderStateCompiled;
57 valid_ = false;
59 // Translate GL ES 2.0 shader to Desktop GL shader and pass that to
60 // glShaderSource and then glCompileShader.
61 const char* source_for_driver = last_compiled_source_.c_str();
62 ShaderTranslatorInterface* translator = translator_.get();
63 if (translator) {
64 bool success = translator->Translate(last_compiled_source_,
65 &log_info_,
66 &translated_source_,
67 &attrib_map_,
68 &uniform_map_,
69 &varying_map_,
70 &name_map_);
71 if (!success) {
72 return;
74 source_for_driver = translated_source_.c_str();
77 glShaderSource(service_id_, 1, &source_for_driver, NULL);
78 glCompileShader(service_id_);
79 if (source_type_ == kANGLE) {
80 GLint max_len = 0;
81 glGetShaderiv(service_id_,
82 GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE,
83 &max_len);
84 source_for_driver = "\0";
85 translated_source_.resize(max_len);
86 if (max_len) {
87 GLint len = 0;
88 glGetTranslatedShaderSourceANGLE(
89 service_id_, translated_source_.size(),
90 &len, &translated_source_.at(0));
91 DCHECK(max_len == 0 || len < max_len);
92 DCHECK(len == 0 || translated_source_[len] == '\0');
93 translated_source_.resize(len);
94 source_for_driver = translated_source_.c_str();
98 GLint status = GL_FALSE;
99 glGetShaderiv(service_id_, GL_COMPILE_STATUS, &status);
100 if (status == GL_TRUE) {
101 valid_ = true;
102 } else {
103 valid_ = false;
105 // We cannot reach here if we are using the shader translator.
106 // All invalid shaders must be rejected by the translator.
107 // All translated shaders must compile.
108 GLint max_len = 0;
109 glGetShaderiv(service_id_, GL_INFO_LOG_LENGTH, &max_len);
110 log_info_.resize(max_len);
111 if (max_len) {
112 GLint len = 0;
113 glGetShaderInfoLog(service_id_, log_info_.size(), &len, &log_info_.at(0));
114 DCHECK(max_len == 0 || len < max_len);
115 DCHECK(len == 0 || log_info_[len] == '\0');
116 log_info_.resize(len);
118 LOG_IF(ERROR, translator)
119 << "Shader translator allowed/produced an invalid shader "
120 << "unless the driver is buggy:"
121 << "\n--original-shader--\n" << last_compiled_source_
122 << "\n--translated-shader--\n" << source_for_driver
123 << "\n--info-log--\n" << log_info_;
127 void Shader::IncUseCount() {
128 ++use_count_;
131 void Shader::DecUseCount() {
132 --use_count_;
133 DCHECK_GE(use_count_, 0);
136 void Shader::Delete() {
137 if (use_count_ > 0) {
138 // If attached, compile the shader before we delete it.
139 DoCompile();
141 DCHECK_NE(service_id_, 0u);
142 glDeleteShader(service_id_);
143 service_id_ = 0;
146 const sh::Attribute* Shader::GetAttribInfo(const std::string& name) const {
147 // Vertex attributes can't be arrays or structs (GLSL ES 3.00.4, section
148 // 4.3.4, "Input Variables"), so |name| is the top level name used as
149 // the AttributeMap key.
150 AttributeMap::const_iterator it = attrib_map_.find(name);
151 return it != attrib_map_.end() ? &it->second : NULL;
154 const std::string* Shader::GetAttribMappedName(
155 const std::string& original_name) const {
156 for (AttributeMap::const_iterator it = attrib_map_.begin();
157 it != attrib_map_.end(); ++it) {
158 if (it->second.name == original_name)
159 return &(it->first);
161 return NULL;
164 const std::string* Shader::GetOriginalNameFromHashedName(
165 const std::string& hashed_name) const {
166 NameMap::const_iterator it = name_map_.find(hashed_name);
167 if (it != name_map_.end())
168 return &(it->second);
169 return NULL;
172 const sh::Uniform* Shader::GetUniformInfo(const std::string& name) const {
173 UniformMap::const_iterator it = uniform_map_.find(GetTopVariableName(name));
174 return it != uniform_map_.end() ? &it->second : NULL;
177 const sh::Varying* Shader::GetVaryingInfo(const std::string& name) const {
178 VaryingMap::const_iterator it = varying_map_.find(GetTopVariableName(name));
179 return it != varying_map_.end() ? &it->second : NULL;
182 ShaderManager::ShaderManager() {}
184 ShaderManager::~ShaderManager() {
185 DCHECK(shaders_.empty());
188 void ShaderManager::Destroy(bool have_context) {
189 while (!shaders_.empty()) {
190 if (have_context) {
191 Shader* shader = shaders_.begin()->second.get();
192 if (!shader->IsDeleted()) {
193 shader->Delete();
196 shaders_.erase(shaders_.begin());
200 Shader* ShaderManager::CreateShader(
201 GLuint client_id,
202 GLuint service_id,
203 GLenum shader_type) {
204 std::pair<ShaderMap::iterator, bool> result =
205 shaders_.insert(std::make_pair(
206 client_id, scoped_refptr<Shader>(
207 new Shader(service_id, shader_type))));
208 DCHECK(result.second);
209 return result.first->second.get();
212 Shader* ShaderManager::GetShader(GLuint client_id) {
213 ShaderMap::iterator it = shaders_.find(client_id);
214 return it != shaders_.end() ? it->second.get() : NULL;
217 bool ShaderManager::GetClientId(GLuint service_id, GLuint* client_id) const {
218 // This doesn't need to be fast. It's only used during slow queries.
219 for (ShaderMap::const_iterator it = shaders_.begin();
220 it != shaders_.end(); ++it) {
221 if (it->second->service_id() == service_id) {
222 *client_id = it->first;
223 return true;
226 return false;
229 bool ShaderManager::IsOwned(Shader* shader) {
230 for (ShaderMap::iterator it = shaders_.begin();
231 it != shaders_.end(); ++it) {
232 if (it->second.get() == shader) {
233 return true;
236 return false;
239 void ShaderManager::RemoveShader(Shader* shader) {
240 DCHECK(shader);
241 DCHECK(IsOwned(shader));
242 if (shader->IsDeleted() && !shader->InUse()) {
243 for (ShaderMap::iterator it = shaders_.begin();
244 it != shaders_.end(); ++it) {
245 if (it->second.get() == shader) {
246 shaders_.erase(it);
247 return;
250 NOTREACHED();
254 void ShaderManager::Delete(Shader* shader) {
255 DCHECK(shader);
256 DCHECK(IsOwned(shader));
257 shader->Delete();
258 RemoveShader(shader);
261 void ShaderManager::UseShader(Shader* shader) {
262 DCHECK(shader);
263 DCHECK(IsOwned(shader));
264 shader->IncUseCount();
267 void ShaderManager::UnuseShader(Shader* shader) {
268 DCHECK(shader);
269 DCHECK(IsOwned(shader));
270 shader->DecUseCount();
271 RemoveShader(shader);
274 } // namespace gles2
275 } // namespace gpu