Handle account removal correctly on all platforms.
[chromium-blink-merge.git] / gpu / command_buffer / service / shader_manager.cc
blob189d78bf0a2c4d94a941e0fb062465a18a0a2850
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 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) {
22 Shader::~Shader() {
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;
41 signature_source_ = source_;
42 source_for_driver = translated_source_.c_str();
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);
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_;
85 void Shader::IncUseCount() {
86 ++use_count_;
89 void Shader::DecUseCount() {
90 --use_count_;
91 DCHECK_GE(use_count_, 0);
94 void Shader::MarkAsDeleted() {
95 DCHECK_NE(service_id_, 0u);
96 service_id_ = 0;
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;
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);
112 return NULL;
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;
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;
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;
135 ShaderManager::ShaderManager() {}
137 ShaderManager::~ShaderManager() {
138 DCHECK(shaders_.empty());
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();
150 shaders_.erase(shaders_.begin());
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();
166 Shader* ShaderManager::GetShader(GLuint client_id) {
167 ShaderMap::iterator it = shaders_.find(client_id);
168 return it != shaders_.end() ? it->second.get() : NULL;
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;
180 return false;
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;
190 return false;
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;
204 NOTREACHED();
208 void ShaderManager::MarkAsDeleted(Shader* shader) {
209 DCHECK(shader);
210 DCHECK(IsOwned(shader));
211 shader->MarkAsDeleted();
212 RemoveShader(shader);
215 void ShaderManager::UseShader(Shader* shader) {
216 DCHECK(shader);
217 DCHECK(IsOwned(shader));
218 shader->IncUseCount();
221 void ShaderManager::UnuseShader(Shader* shader) {
222 DCHECK(shader);
223 DCHECK(IsOwned(shader));
224 shader->DecUseCount();
225 RemoveShader(shader);
228 } // namespace gles2
229 } // namespace gpu