189d78bf0a2c4d94a941e0fb062465a18a0a2850
[platform/framework/web/crosswalk.git] / src / gpu / command_buffer / service / shader_manager.cc
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.
4
5 #include "gpu/command_buffer/service/shader_manager.h"
6
7 #include <utility>
8
9 #include "base/logging.h"
10 #include "base/strings/string_util.h"
11
12 namespace gpu {
13 namespace gles2 {
14
15 Shader::Shader(GLuint service_id, GLenum shader_type)
16       : use_count_(0),
17         service_id_(service_id),
18         shader_type_(shader_type),
19         valid_(false) {
20 }
21
22 Shader::~Shader() {
23 }
24
25 void Shader::DoCompile(ShaderTranslatorInterface* translator,
26                        TranslatedShaderSourceType type) {
27   // Translate GL ES 2.0 shader to Desktop GL shader and pass that to
28   // glShaderSource and then glCompileShader.
29   const char* source_for_driver = source_.c_str();
30   if (translator) {
31     valid_ = translator->Translate(source_,
32                                    &log_info_,
33                                    &translated_source_,
34                                    &attrib_map_,
35                                    &uniform_map_,
36                                    &varying_map_,
37                                    &name_map_);
38     if (!valid_) {
39       return;
40     }
41     signature_source_ = source_;
42     source_for_driver = translated_source_.c_str();
43   }
44
45   glShaderSource(service_id_, 1, &source_for_driver, NULL);
46   glCompileShader(service_id_);
47   if (type == kANGLE) {
48     GLint max_len = 0;
49     glGetShaderiv(service_id_,
50                   GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE,
51                   &max_len);
52     scoped_ptr<char[]> buffer(new char[max_len]);
53     GLint len = 0;
54     glGetTranslatedShaderSourceANGLE(
55         service_id_, max_len, &len, buffer.get());
56     DCHECK(max_len == 0 || len < max_len);
57     DCHECK(len == 0 || buffer[len] == '\0');
58     translated_source_ = std::string(buffer.get(), len);
59   }
60
61   GLint status = GL_FALSE;
62   glGetShaderiv(service_id_, GL_COMPILE_STATUS, &status);
63   if (status != GL_TRUE) {
64     // We cannot reach here if we are using the shader translator.
65     // All invalid shaders must be rejected by the translator.
66     // All translated shaders must compile.
67     GLint max_len = 0;
68     glGetShaderiv(service_id_, GL_INFO_LOG_LENGTH, &max_len);
69     scoped_ptr<char[]> buffer(new char[max_len]);
70     GLint len = 0;
71     glGetShaderInfoLog(service_id_, max_len, &len, buffer.get());
72     DCHECK(max_len == 0 || len < max_len);
73     DCHECK(len == 0 || buffer[len] == '\0');
74     valid_ = false;
75     log_info_ = std::string(buffer.get(), len);
76     LOG_IF(ERROR, translator)
77         << "Shader translator allowed/produced an invalid shader "
78         << "unless the driver is buggy:"
79         << "\n--original-shader--\n" << source_
80         << "\n--translated-shader--\n" << source_for_driver
81         << "\n--info-log--\n" << log_info_;
82   }
83 }
84
85 void Shader::IncUseCount() {
86   ++use_count_;
87 }
88
89 void Shader::DecUseCount() {
90   --use_count_;
91   DCHECK_GE(use_count_, 0);
92 }
93
94 void Shader::MarkAsDeleted() {
95   DCHECK_NE(service_id_, 0u);
96   service_id_ = 0;
97 }
98
99 const Shader::VariableInfo* Shader::GetAttribInfo(
100     const std::string& name) const {
101   VariableMap::const_iterator it = attrib_map_.find(name);
102   return it != attrib_map_.end() ? &it->second : NULL;
103 }
104
105 const std::string* Shader::GetAttribMappedName(
106     const std::string& original_name) const {
107   for (VariableMap::const_iterator it = attrib_map_.begin();
108        it != attrib_map_.end(); ++it) {
109     if (it->second.name == original_name)
110       return &(it->first);
111   }
112   return NULL;
113 }
114
115 const std::string* Shader::GetOriginalNameFromHashedName(
116     const std::string& hashed_name) const {
117   NameMap::const_iterator it = name_map_.find(hashed_name);
118   if (it != name_map_.end())
119     return &(it->second);
120   return NULL;
121 }
122
123 const Shader::VariableInfo* Shader::GetUniformInfo(
124     const std::string& name) const {
125   VariableMap::const_iterator it = uniform_map_.find(name);
126   return it != uniform_map_.end() ? &it->second : NULL;
127 }
128
129 const Shader::VariableInfo* Shader::GetVaryingInfo(
130     const std::string& name) const {
131   VariableMap::const_iterator it = varying_map_.find(name);
132   return it != varying_map_.end() ? &it->second : NULL;
133 }
134
135 ShaderManager::ShaderManager() {}
136
137 ShaderManager::~ShaderManager() {
138   DCHECK(shaders_.empty());
139 }
140
141 void ShaderManager::Destroy(bool have_context) {
142   while (!shaders_.empty()) {
143     if (have_context) {
144       Shader* shader = shaders_.begin()->second.get();
145       if (!shader->IsDeleted()) {
146         glDeleteShader(shader->service_id());
147         shader->MarkAsDeleted();
148       }
149     }
150     shaders_.erase(shaders_.begin());
151   }
152 }
153
154 Shader* ShaderManager::CreateShader(
155     GLuint client_id,
156     GLuint service_id,
157     GLenum shader_type) {
158   std::pair<ShaderMap::iterator, bool> result =
159       shaders_.insert(std::make_pair(
160           client_id, scoped_refptr<Shader>(
161               new Shader(service_id, shader_type))));
162   DCHECK(result.second);
163   return result.first->second.get();
164 }
165
166 Shader* ShaderManager::GetShader(GLuint client_id) {
167   ShaderMap::iterator it = shaders_.find(client_id);
168   return it != shaders_.end() ? it->second.get() : NULL;
169 }
170
171 bool ShaderManager::GetClientId(GLuint service_id, GLuint* client_id) const {
172   // This doesn't need to be fast. It's only used during slow queries.
173   for (ShaderMap::const_iterator it = shaders_.begin();
174        it != shaders_.end(); ++it) {
175     if (it->second->service_id() == service_id) {
176       *client_id = it->first;
177       return true;
178     }
179   }
180   return false;
181 }
182
183 bool ShaderManager::IsOwned(Shader* shader) {
184   for (ShaderMap::iterator it = shaders_.begin();
185        it != shaders_.end(); ++it) {
186     if (it->second.get() == shader) {
187       return true;
188     }
189   }
190   return false;
191 }
192
193 void ShaderManager::RemoveShader(Shader* shader) {
194   DCHECK(shader);
195   DCHECK(IsOwned(shader));
196   if (shader->IsDeleted() && !shader->InUse()) {
197     for (ShaderMap::iterator it = shaders_.begin();
198          it != shaders_.end(); ++it) {
199       if (it->second.get() == shader) {
200         shaders_.erase(it);
201         return;
202       }
203     }
204     NOTREACHED();
205   }
206 }
207
208 void ShaderManager::MarkAsDeleted(Shader* shader) {
209   DCHECK(shader);
210   DCHECK(IsOwned(shader));
211   shader->MarkAsDeleted();
212   RemoveShader(shader);
213 }
214
215 void ShaderManager::UseShader(Shader* shader) {
216   DCHECK(shader);
217   DCHECK(IsOwned(shader));
218   shader->IncUseCount();
219 }
220
221 void ShaderManager::UnuseShader(Shader* shader) {
222   DCHECK(shader);
223   DCHECK(IsOwned(shader));
224   shader->DecUseCount();
225   RemoveShader(shader);
226 }
227
228 }  // namespace gles2
229 }  // namespace gpu
230
231