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::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 85void Shader::IncUseCount() { 86 ++use_count_; 87} 88 89void Shader::DecUseCount() { 90 --use_count_; 91 DCHECK_GE(use_count_, 0); 92} 93 94void Shader::MarkAsDeleted() { 95 DCHECK_NE(service_id_, 0u); 96 service_id_ = 0; 97} 98 99const 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 105const 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 115const 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 123const 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 129const 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 135ShaderManager::ShaderManager() {} 136 137ShaderManager::~ShaderManager() { 138 DCHECK(shaders_.empty()); 139} 140 141void 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 154Shader* 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 166Shader* ShaderManager::GetShader(GLuint client_id) { 167 ShaderMap::iterator it = shaders_.find(client_id); 168 return it != shaders_.end() ? it->second.get() : NULL; 169} 170 171bool 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 183bool 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 193void 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 208void ShaderManager::MarkAsDeleted(Shader* shader) { 209 DCHECK(shader); 210 DCHECK(IsOwned(shader)); 211 shader->MarkAsDeleted(); 212 RemoveShader(shader); 213} 214 215void ShaderManager::UseShader(Shader* shader) { 216 DCHECK(shader); 217 DCHECK(IsOwned(shader)); 218 shader->IncUseCount(); 219} 220 221void 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 232