Home | History | Annotate | Download | only in service
      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 
    232