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
12namespace gpu {
13namespace gles2 {
14
15Shader::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
22Shader::~Shader() {
23}
24
25void Shader::IncUseCount() {
26  ++use_count_;
27}
28
29void Shader::DecUseCount() {
30  --use_count_;
31  DCHECK_GE(use_count_, 0);
32}
33
34void Shader::MarkAsDeleted() {
35  DCHECK_NE(service_id_, 0u);
36  service_id_ = 0;
37}
38
39void Shader::SetStatus(
40    bool valid, const char* log, ShaderTranslatorInterface* translator) {
41  valid_ = valid;
42  log_info_.reset(log ? new std::string(log) : NULL);
43  if (translator && valid) {
44    attrib_map_ = translator->attrib_map();
45    uniform_map_ = translator->uniform_map();
46    varying_map_ = translator->varying_map();
47    name_map_ = translator->name_map();
48  } else {
49    attrib_map_.clear();
50    uniform_map_.clear();
51    varying_map_.clear();
52    name_map_.clear();
53  }
54  if (valid && source_.get()) {
55    signature_source_.reset(new std::string(source_->c_str()));
56  } else {
57    signature_source_.reset();
58  }
59}
60
61const Shader::VariableInfo*
62    Shader::GetAttribInfo(
63        const std::string& name) const {
64  VariableMap::const_iterator it = attrib_map_.find(name);
65  return it != attrib_map_.end() ? &it->second : NULL;
66}
67
68const std::string* Shader::GetAttribMappedName(
69    const std::string& original_name) const {
70  for (VariableMap::const_iterator it = attrib_map_.begin();
71       it != attrib_map_.end(); ++it) {
72    if (it->second.name == original_name)
73      return &(it->first);
74  }
75  return NULL;
76}
77
78const std::string* Shader::GetOriginalNameFromHashedName(
79    const std::string& hashed_name) const {
80  NameMap::const_iterator it = name_map_.find(hashed_name);
81  if (it != name_map_.end())
82    return &(it->second);
83  return NULL;
84}
85
86const Shader::VariableInfo*
87    Shader::GetUniformInfo(
88        const std::string& name) const {
89  VariableMap::const_iterator it = uniform_map_.find(name);
90  return it != uniform_map_.end() ? &it->second : NULL;
91}
92
93ShaderManager::ShaderManager() {}
94
95ShaderManager::~ShaderManager() {
96  DCHECK(shaders_.empty());
97}
98
99void ShaderManager::Destroy(bool have_context) {
100  while (!shaders_.empty()) {
101    if (have_context) {
102      Shader* shader = shaders_.begin()->second.get();
103      if (!shader->IsDeleted()) {
104        glDeleteShader(shader->service_id());
105        shader->MarkAsDeleted();
106      }
107    }
108    shaders_.erase(shaders_.begin());
109  }
110}
111
112Shader* ShaderManager::CreateShader(
113    GLuint client_id,
114    GLuint service_id,
115    GLenum shader_type) {
116  std::pair<ShaderMap::iterator, bool> result =
117      shaders_.insert(std::make_pair(
118          client_id, scoped_refptr<Shader>(
119              new Shader(service_id, shader_type))));
120  DCHECK(result.second);
121  return result.first->second.get();
122}
123
124Shader* ShaderManager::GetShader(GLuint client_id) {
125  ShaderMap::iterator it = shaders_.find(client_id);
126  return it != shaders_.end() ? it->second.get() : NULL;
127}
128
129bool ShaderManager::GetClientId(GLuint service_id, GLuint* client_id) const {
130  // This doesn't need to be fast. It's only used during slow queries.
131  for (ShaderMap::const_iterator it = shaders_.begin();
132       it != shaders_.end(); ++it) {
133    if (it->second->service_id() == service_id) {
134      *client_id = it->first;
135      return true;
136    }
137  }
138  return false;
139}
140
141bool ShaderManager::IsOwned(Shader* shader) {
142  for (ShaderMap::iterator it = shaders_.begin();
143       it != shaders_.end(); ++it) {
144    if (it->second.get() == shader) {
145      return true;
146    }
147  }
148  return false;
149}
150
151void ShaderManager::RemoveShader(Shader* shader) {
152  DCHECK(shader);
153  DCHECK(IsOwned(shader));
154  if (shader->IsDeleted() && !shader->InUse()) {
155    for (ShaderMap::iterator it = shaders_.begin();
156         it != shaders_.end(); ++it) {
157      if (it->second.get() == shader) {
158        shaders_.erase(it);
159        return;
160      }
161    }
162    NOTREACHED();
163  }
164}
165
166void ShaderManager::MarkAsDeleted(Shader* shader) {
167  DCHECK(shader);
168  DCHECK(IsOwned(shader));
169  shader->MarkAsDeleted();
170  RemoveShader(shader);
171}
172
173void ShaderManager::UseShader(Shader* shader) {
174  DCHECK(shader);
175  DCHECK(IsOwned(shader));
176  shader->IncUseCount();
177}
178
179void ShaderManager::UnuseShader(Shader* shader) {
180  DCHECK(shader);
181  DCHECK(IsOwned(shader));
182  shader->DecUseCount();
183  RemoveShader(shader);
184}
185
186}  // namespace gles2
187}  // namespace gpu
188
189
190