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/program_manager.h"
      6 
      7 #include <algorithm>
      8 #include <set>
      9 #include <utility>
     10 #include <vector>
     11 
     12 #include "base/basictypes.h"
     13 #include "base/command_line.h"
     14 #include "base/logging.h"
     15 #include "base/memory/scoped_ptr.h"
     16 #include "base/metrics/histogram.h"
     17 #include "base/strings/string_number_conversions.h"
     18 #include "base/time/time.h"
     19 #include "gpu/command_buffer/common/gles2_cmd_format.h"
     20 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
     21 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
     22 #include "gpu/command_buffer/service/gpu_switches.h"
     23 #include "gpu/command_buffer/service/program_cache.h"
     24 #include "gpu/command_buffer/service/shader_manager.h"
     25 #include "gpu/command_buffer/service/shader_translator.h"
     26 #include "third_party/re2/re2/re2.h"
     27 
     28 using base::TimeDelta;
     29 using base::TimeTicks;
     30 
     31 namespace gpu {
     32 namespace gles2 {
     33 
     34 namespace {
     35 
     36 struct UniformType {
     37   explicit UniformType(const ShaderTranslator::VariableInfo uniform)
     38       : type(uniform.type),
     39         size(uniform.size),
     40         precision(uniform.precision) { }
     41 
     42   UniformType()
     43       : type(0),
     44         size(0),
     45         precision(SH_PRECISION_MEDIUMP) { }
     46 
     47   bool operator==(const UniformType& other) const {
     48     return type == other.type &&
     49         size == other.size &&
     50         precision == other.precision;
     51   }
     52 
     53   int type;
     54   int size;
     55   int precision;
     56 };
     57 
     58 int ShaderTypeToIndex(GLenum shader_type) {
     59   switch (shader_type) {
     60     case GL_VERTEX_SHADER:
     61       return 0;
     62     case GL_FRAGMENT_SHADER:
     63       return 1;
     64     default:
     65       NOTREACHED();
     66       return 0;
     67   }
     68 }
     69 
     70 // Given a name like "foo.bar[123].moo[456]" sets new_name to "foo.bar[123].moo"
     71 // and sets element_index to 456. returns false if element expression was not a
     72 // whole decimal number. For example: "foo[1b2]"
     73 bool GetUniformNameSansElement(
     74     const std::string& name, int* element_index, std::string* new_name) {
     75   DCHECK(element_index);
     76   DCHECK(new_name);
     77   if (name.size() < 3 || name[name.size() - 1] != ']') {
     78     *element_index = 0;
     79     *new_name = name;
     80     return true;
     81   }
     82 
     83   // Look for an array specification.
     84   size_t open_pos = name.find_last_of('[');
     85   if (open_pos == std::string::npos ||
     86       open_pos >= name.size() - 2) {
     87     return false;
     88   }
     89 
     90   GLint index = 0;
     91   size_t last = name.size() - 1;
     92   for (size_t pos = open_pos + 1; pos < last; ++pos) {
     93     int8 digit = name[pos] - '0';
     94     if (digit < 0 || digit > 9) {
     95       return false;
     96     }
     97     index = index * 10 + digit;
     98   }
     99 
    100   *element_index = index;
    101   *new_name = name.substr(0, open_pos);
    102   return true;
    103 }
    104 
    105 bool IsBuiltInVarying(const std::string& name) {
    106   // Built-in variables.
    107   const char* kBuiltInVaryings[] = {
    108       "gl_FragCoord",
    109       "gl_FrontFacing",
    110       "gl_PointCoord"
    111   };
    112   for (size_t ii = 0; ii < arraysize(kBuiltInVaryings); ++ii) {
    113     if (name == kBuiltInVaryings[ii])
    114       return true;
    115   }
    116   return false;
    117 }
    118 
    119 }  // anonymous namespace.
    120 
    121 Program::UniformInfo::UniformInfo()
    122     : size(0),
    123       type(GL_NONE),
    124       fake_location_base(0),
    125       is_array(false) {
    126 }
    127 
    128 Program::UniformInfo::UniformInfo(
    129     GLsizei _size,
    130     GLenum _type,
    131     int _fake_location_base,
    132     const std::string& _name)
    133     : size(_size),
    134       type(_type),
    135       fake_location_base(_fake_location_base),
    136       is_array(false),
    137       name(_name) {
    138 }
    139 
    140 Program::UniformInfo::~UniformInfo() {}
    141 
    142 bool ProgramManager::IsInvalidPrefix(const char* name, size_t length) {
    143   static const char kInvalidPrefix[] = { 'g', 'l', '_' };
    144   return (length >= sizeof(kInvalidPrefix) &&
    145       memcmp(name, kInvalidPrefix, sizeof(kInvalidPrefix)) == 0);
    146 }
    147 
    148 Program::Program(
    149     ProgramManager* manager, GLuint service_id)
    150     : manager_(manager),
    151       use_count_(0),
    152       max_attrib_name_length_(0),
    153       max_uniform_name_length_(0),
    154       service_id_(service_id),
    155       deleted_(false),
    156       valid_(false),
    157       link_status_(false),
    158       uniforms_cleared_(false),
    159       num_uniforms_(0) {
    160   manager_->StartTracking(this);
    161 }
    162 
    163 void Program::Reset() {
    164   valid_ = false;
    165   link_status_ = false;
    166   num_uniforms_ = 0;
    167   max_uniform_name_length_ = 0;
    168   max_attrib_name_length_ = 0;
    169   attrib_infos_.clear();
    170   uniform_infos_.clear();
    171   sampler_indices_.clear();
    172   attrib_location_to_index_map_.clear();
    173 }
    174 
    175 std::string Program::ProcessLogInfo(
    176     const std::string& log) {
    177   std::string output;
    178   re2::StringPiece input(log);
    179   std::string prior_log;
    180   std::string hashed_name;
    181   while (RE2::Consume(&input,
    182                       "(.*)(webgl_[0123456789abcdefABCDEF]+)",
    183                       &prior_log,
    184                       &hashed_name)) {
    185     output += prior_log;
    186 
    187     const std::string* original_name =
    188         GetOriginalNameFromHashedName(hashed_name);
    189     if (original_name)
    190       output += *original_name;
    191     else
    192       output += hashed_name;
    193   }
    194 
    195   return output + input.as_string();
    196 }
    197 
    198 void Program::UpdateLogInfo() {
    199   GLint max_len = 0;
    200   glGetProgramiv(service_id_, GL_INFO_LOG_LENGTH, &max_len);
    201   if (max_len == 0) {
    202     set_log_info(NULL);
    203     return;
    204   }
    205   scoped_ptr<char[]> temp(new char[max_len]);
    206   GLint len = 0;
    207   glGetProgramInfoLog(service_id_, max_len, &len, temp.get());
    208   DCHECK(max_len == 0 || len < max_len);
    209   DCHECK(len == 0 || temp[len] == '\0');
    210   std::string log(temp.get(), len);
    211   set_log_info(ProcessLogInfo(log).c_str());
    212 }
    213 
    214 void Program::ClearUniforms(
    215     std::vector<uint8>* zero_buffer) {
    216   DCHECK(zero_buffer);
    217   if (uniforms_cleared_) {
    218     return;
    219   }
    220   uniforms_cleared_ = true;
    221   for (size_t ii = 0; ii < uniform_infos_.size(); ++ii) {
    222     const UniformInfo& uniform_info = uniform_infos_[ii];
    223     if (!uniform_info.IsValid()) {
    224       continue;
    225     }
    226     GLint location = uniform_info.element_locations[0];
    227     GLsizei size = uniform_info.size;
    228     uint32 unit_size =  GLES2Util::GetGLDataTypeSizeForUniforms(
    229         uniform_info.type);
    230     uint32 size_needed = size * unit_size;
    231     if (size_needed > zero_buffer->size()) {
    232       zero_buffer->resize(size_needed, 0u);
    233     }
    234     const void* zero = &(*zero_buffer)[0];
    235     switch (uniform_info.type) {
    236     case GL_FLOAT:
    237       glUniform1fv(location, size, reinterpret_cast<const GLfloat*>(zero));
    238       break;
    239     case GL_FLOAT_VEC2:
    240       glUniform2fv(location, size, reinterpret_cast<const GLfloat*>(zero));
    241       break;
    242     case GL_FLOAT_VEC3:
    243       glUniform3fv(location, size, reinterpret_cast<const GLfloat*>(zero));
    244       break;
    245     case GL_FLOAT_VEC4:
    246       glUniform4fv(location, size, reinterpret_cast<const GLfloat*>(zero));
    247       break;
    248     case GL_INT:
    249     case GL_BOOL:
    250     case GL_SAMPLER_2D:
    251     case GL_SAMPLER_CUBE:
    252     case GL_SAMPLER_EXTERNAL_OES:
    253     case GL_SAMPLER_3D_OES:
    254     case GL_SAMPLER_2D_RECT_ARB:
    255       glUniform1iv(location, size, reinterpret_cast<const GLint*>(zero));
    256       break;
    257     case GL_INT_VEC2:
    258     case GL_BOOL_VEC2:
    259       glUniform2iv(location, size, reinterpret_cast<const GLint*>(zero));
    260       break;
    261     case GL_INT_VEC3:
    262     case GL_BOOL_VEC3:
    263       glUniform3iv(location, size, reinterpret_cast<const GLint*>(zero));
    264       break;
    265     case GL_INT_VEC4:
    266     case GL_BOOL_VEC4:
    267       glUniform4iv(location, size, reinterpret_cast<const GLint*>(zero));
    268       break;
    269     case GL_FLOAT_MAT2:
    270       glUniformMatrix2fv(
    271           location, size, false, reinterpret_cast<const GLfloat*>(zero));
    272       break;
    273     case GL_FLOAT_MAT3:
    274       glUniformMatrix3fv(
    275           location, size, false, reinterpret_cast<const GLfloat*>(zero));
    276       break;
    277     case GL_FLOAT_MAT4:
    278       glUniformMatrix4fv(
    279           location, size, false, reinterpret_cast<const GLfloat*>(zero));
    280       break;
    281     default:
    282       NOTREACHED();
    283       break;
    284     }
    285   }
    286 }
    287 
    288 namespace {
    289 
    290 struct UniformData {
    291   UniformData() : size(-1), type(GL_NONE), location(0), added(false) {
    292   }
    293   std::string queried_name;
    294   std::string corrected_name;
    295   std::string original_name;
    296   GLsizei size;
    297   GLenum type;
    298   GLint location;
    299   bool added;
    300 };
    301 
    302 struct UniformDataComparer {
    303   bool operator()(const UniformData& lhs, const UniformData& rhs) const {
    304     return lhs.queried_name < rhs.queried_name;
    305   }
    306 };
    307 
    308 }  // anonymous namespace
    309 
    310 void Program::Update() {
    311   Reset();
    312   UpdateLogInfo();
    313   link_status_ = true;
    314   uniforms_cleared_ = false;
    315   GLint num_attribs = 0;
    316   GLint max_len = 0;
    317   GLint max_location = -1;
    318   glGetProgramiv(service_id_, GL_ACTIVE_ATTRIBUTES, &num_attribs);
    319   glGetProgramiv(service_id_, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &max_len);
    320   // TODO(gman): Should we check for error?
    321   scoped_ptr<char[]> name_buffer(new char[max_len]);
    322   for (GLint ii = 0; ii < num_attribs; ++ii) {
    323     GLsizei length = 0;
    324     GLsizei size = 0;
    325     GLenum type = 0;
    326     glGetActiveAttrib(
    327         service_id_, ii, max_len, &length, &size, &type, name_buffer.get());
    328     DCHECK(max_len == 0 || length < max_len);
    329     DCHECK(length == 0 || name_buffer[length] == '\0');
    330     if (!ProgramManager::IsInvalidPrefix(name_buffer.get(), length)) {
    331       std::string name;
    332       std::string original_name;
    333       GetCorrectedVariableInfo(
    334           false, name_buffer.get(), &name, &original_name, &size, &type);
    335       // TODO(gman): Should we check for error?
    336       GLint location = glGetAttribLocation(service_id_, name_buffer.get());
    337       if (location > max_location) {
    338         max_location = location;
    339       }
    340       attrib_infos_.push_back(
    341           VertexAttrib(size, type, original_name, location));
    342       max_attrib_name_length_ = std::max(
    343           max_attrib_name_length_, static_cast<GLsizei>(original_name.size()));
    344     }
    345   }
    346 
    347   // Create attrib location to index map.
    348   attrib_location_to_index_map_.resize(max_location + 1);
    349   for (GLint ii = 0; ii <= max_location; ++ii) {
    350     attrib_location_to_index_map_[ii] = -1;
    351   }
    352   for (size_t ii = 0; ii < attrib_infos_.size(); ++ii) {
    353     const VertexAttrib& info = attrib_infos_[ii];
    354     attrib_location_to_index_map_[info.location] = ii;
    355   }
    356 
    357 #if !defined(NDEBUG)
    358   if (CommandLine::ForCurrentProcess()->HasSwitch(
    359       switches::kEnableGPUServiceLoggingGPU)) {
    360     DLOG(INFO) << "----: attribs for service_id: " << service_id();
    361     for (size_t ii = 0; ii < attrib_infos_.size(); ++ii) {
    362       const VertexAttrib& info = attrib_infos_[ii];
    363       DLOG(INFO) << ii << ": loc = " << info.location
    364                  << ", size = " << info.size
    365                  << ", type = " << GLES2Util::GetStringEnum(info.type)
    366                  << ", name = " << info.name;
    367     }
    368   }
    369 #endif
    370 
    371   max_len = 0;
    372   GLint num_uniforms = 0;
    373   glGetProgramiv(service_id_, GL_ACTIVE_UNIFORMS, &num_uniforms);
    374   glGetProgramiv(service_id_, GL_ACTIVE_UNIFORM_MAX_LENGTH, &max_len);
    375   name_buffer.reset(new char[max_len]);
    376 
    377   // Reads all the names.
    378   std::vector<UniformData> uniform_data;
    379   for (GLint ii = 0; ii < num_uniforms; ++ii) {
    380     GLsizei length = 0;
    381     UniformData data;
    382     glGetActiveUniform(
    383         service_id_, ii, max_len, &length,
    384         &data.size, &data.type, name_buffer.get());
    385     DCHECK(max_len == 0 || length < max_len);
    386     DCHECK(length == 0 || name_buffer[length] == '\0');
    387     if (!ProgramManager::IsInvalidPrefix(name_buffer.get(), length)) {
    388       data.queried_name = std::string(name_buffer.get());
    389       GetCorrectedVariableInfo(
    390           true, name_buffer.get(), &data.corrected_name, &data.original_name,
    391           &data.size, &data.type);
    392       uniform_data.push_back(data);
    393     }
    394   }
    395 
    396   // NOTE: We don't care if 2 uniforms are bound to the same location.
    397   // One of them will take preference. The spec allows this, same as
    398   // BindAttribLocation.
    399   //
    400   // The reason we don't check is if we were to fail we'd have to
    401   // restore the previous program but since we've already linked successfully
    402   // at this point the previous program is gone.
    403 
    404   // Assigns the uniforms with bindings.
    405   size_t next_available_index = 0;
    406   for (size_t ii = 0; ii < uniform_data.size(); ++ii) {
    407     UniformData& data = uniform_data[ii];
    408     data.location = glGetUniformLocation(
    409         service_id_, data.queried_name.c_str());
    410     // remove "[0]"
    411     std::string short_name;
    412     int element_index = 0;
    413     bool good ALLOW_UNUSED = GetUniformNameSansElement(
    414         data.queried_name, &element_index, &short_name);\
    415     DCHECK(good);
    416     LocationMap::const_iterator it = bind_uniform_location_map_.find(
    417         short_name);
    418     if (it != bind_uniform_location_map_.end()) {
    419       data.added = AddUniformInfo(
    420           data.size, data.type, data.location, it->second, data.corrected_name,
    421           data.original_name, &next_available_index);
    422     }
    423   }
    424 
    425   // Assigns the uniforms that were not bound.
    426   for (size_t ii = 0; ii < uniform_data.size(); ++ii) {
    427     const UniformData& data = uniform_data[ii];
    428     if (!data.added) {
    429       AddUniformInfo(
    430           data.size, data.type, data.location, -1, data.corrected_name,
    431           data.original_name, &next_available_index);
    432     }
    433   }
    434 
    435 #if !defined(NDEBUG)
    436   if (CommandLine::ForCurrentProcess()->HasSwitch(
    437       switches::kEnableGPUServiceLoggingGPU)) {
    438     DLOG(INFO) << "----: uniforms for service_id: " << service_id();
    439     for (size_t ii = 0; ii < uniform_infos_.size(); ++ii) {
    440       const UniformInfo& info = uniform_infos_[ii];
    441       if (info.IsValid()) {
    442         DLOG(INFO) << ii << ": loc = " << info.element_locations[0]
    443                    << ", size = " << info.size
    444                    << ", type = " << GLES2Util::GetStringEnum(info.type)
    445                    << ", name = " << info.name;
    446       }
    447     }
    448   }
    449 #endif
    450 
    451   valid_ = true;
    452 }
    453 
    454 void Program::ExecuteBindAttribLocationCalls() {
    455   for (LocationMap::const_iterator it = bind_attrib_location_map_.begin();
    456        it != bind_attrib_location_map_.end(); ++it) {
    457     const std::string* mapped_name = GetAttribMappedName(it->first);
    458     if (mapped_name && *mapped_name != it->first)
    459       glBindAttribLocation(service_id_, it->second, mapped_name->c_str());
    460   }
    461 }
    462 
    463 void ProgramManager::DoCompileShader(
    464     Shader* shader,
    465     ShaderTranslator* translator,
    466     ProgramManager::TranslatedShaderSourceType translated_shader_source_type) {
    467   // Translate GL ES 2.0 shader to Desktop GL shader and pass that to
    468   // glShaderSource and then glCompileShader.
    469   const std::string* source = shader->source();
    470   const char* shader_src = source ? source->c_str() : "";
    471   if (translator) {
    472     if (!translator->Translate(shader_src)) {
    473       shader->SetStatus(false, translator->info_log(), NULL);
    474       return;
    475     }
    476     shader_src = translator->translated_shader();
    477     if (translated_shader_source_type != kANGLE)
    478       shader->UpdateTranslatedSource(shader_src);
    479   }
    480 
    481   glShaderSource(shader->service_id(), 1, &shader_src, NULL);
    482   glCompileShader(shader->service_id());
    483   if (translated_shader_source_type == kANGLE) {
    484     GLint max_len = 0;
    485     glGetShaderiv(shader->service_id(),
    486                   GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE,
    487                   &max_len);
    488     scoped_ptr<char[]> temp(new char[max_len]);
    489     GLint len = 0;
    490     glGetTranslatedShaderSourceANGLE(
    491         shader->service_id(), max_len, &len, temp.get());
    492     DCHECK(max_len == 0 || len < max_len);
    493     DCHECK(len == 0 || temp[len] == '\0');
    494     shader->UpdateTranslatedSource(max_len ? temp.get() : NULL);
    495   }
    496 
    497   GLint status = GL_FALSE;
    498   glGetShaderiv(shader->service_id(), GL_COMPILE_STATUS, &status);
    499   if (status) {
    500     shader->SetStatus(true, "", translator);
    501   } else {
    502     // We cannot reach here if we are using the shader translator.
    503     // All invalid shaders must be rejected by the translator.
    504     // All translated shaders must compile.
    505     GLint max_len = 0;
    506     glGetShaderiv(shader->service_id(), GL_INFO_LOG_LENGTH, &max_len);
    507     scoped_ptr<char[]> temp(new char[max_len]);
    508     GLint len = 0;
    509     glGetShaderInfoLog(shader->service_id(), max_len, &len, temp.get());
    510     DCHECK(max_len == 0 || len < max_len);
    511     DCHECK(len == 0 || temp[len] == '\0');
    512     shader->SetStatus(false, std::string(temp.get(), len).c_str(), NULL);
    513     LOG_IF(ERROR, translator)
    514         << "Shader translator allowed/produced an invalid shader "
    515         << "unless the driver is buggy:"
    516         << "\n--original-shader--\n" << (source ? *source : std::string())
    517         << "\n--translated-shader--\n" << shader_src << "\n--info-log--\n"
    518         << *shader->log_info();
    519   }
    520 }
    521 
    522 bool Program::Link(ShaderManager* manager,
    523                    ShaderTranslator* vertex_translator,
    524                    ShaderTranslator* fragment_translator,
    525                    Program::VaryingsPackingOption varyings_packing_option,
    526                    const ShaderCacheCallback& shader_callback) {
    527   ClearLinkStatus();
    528   if (!CanLink()) {
    529     set_log_info("missing shaders");
    530     return false;
    531   }
    532   if (DetectAttribLocationBindingConflicts()) {
    533     set_log_info("glBindAttribLocation() conflicts");
    534     return false;
    535   }
    536   if (DetectUniformsMismatch()) {
    537     set_log_info("Uniforms with the same name but different type/precision");
    538     return false;
    539   }
    540   if (DetectVaryingsMismatch()) {
    541     set_log_info("Varyings with the same name but different type, "
    542                  "or statically used varyings in fragment shader are not "
    543                  "declared in vertex shader");
    544     return false;
    545   }
    546   if (DetectGlobalNameConflicts()) {
    547     set_log_info("Name conflicts between an uniform and an attribute");
    548     return false;
    549   }
    550   if (!CheckVaryingsPacking(varyings_packing_option)) {
    551     set_log_info("Varyings over maximum register limit");
    552     return false;
    553   }
    554 
    555   TimeTicks before_time = TimeTicks::HighResNow();
    556   bool link = true;
    557   ProgramCache* cache = manager_->program_cache_;
    558   if (cache) {
    559     DCHECK(attached_shaders_[0]->signature_source() &&
    560            attached_shaders_[1]->signature_source());
    561     ProgramCache::LinkedProgramStatus status = cache->GetLinkedProgramStatus(
    562         *attached_shaders_[0]->signature_source(),
    563         vertex_translator,
    564         *attached_shaders_[1]->signature_source(),
    565         fragment_translator,
    566         &bind_attrib_location_map_);
    567 
    568     if (status == ProgramCache::LINK_SUCCEEDED) {
    569       ProgramCache::ProgramLoadResult success =
    570           cache->LoadLinkedProgram(service_id(),
    571                                    attached_shaders_[0].get(),
    572                                    vertex_translator,
    573                                    attached_shaders_[1].get(),
    574                                    fragment_translator,
    575                                    &bind_attrib_location_map_,
    576                                    shader_callback);
    577       link = success != ProgramCache::PROGRAM_LOAD_SUCCESS;
    578       UMA_HISTOGRAM_BOOLEAN("GPU.ProgramCache.LoadBinarySuccess", !link);
    579     }
    580   }
    581 
    582   if (link) {
    583     ExecuteBindAttribLocationCalls();
    584     before_time = TimeTicks::HighResNow();
    585     if (cache && gfx::g_driver_gl.ext.b_GL_ARB_get_program_binary) {
    586       glProgramParameteri(service_id(),
    587                           PROGRAM_BINARY_RETRIEVABLE_HINT,
    588                           GL_TRUE);
    589     }
    590     glLinkProgram(service_id());
    591   }
    592 
    593   GLint success = 0;
    594   glGetProgramiv(service_id(), GL_LINK_STATUS, &success);
    595   if (success == GL_TRUE) {
    596     Update();
    597     if (link) {
    598       if (cache) {
    599         cache->SaveLinkedProgram(service_id(),
    600                                  attached_shaders_[0].get(),
    601                                  vertex_translator,
    602                                  attached_shaders_[1].get(),
    603                                  fragment_translator,
    604                                  &bind_attrib_location_map_,
    605                                  shader_callback);
    606       }
    607       UMA_HISTOGRAM_CUSTOM_COUNTS(
    608           "GPU.ProgramCache.BinaryCacheMissTime",
    609           (TimeTicks::HighResNow() - before_time).InMicroseconds(),
    610           0,
    611           TimeDelta::FromSeconds(10).InMicroseconds(),
    612           50);
    613     } else {
    614       UMA_HISTOGRAM_CUSTOM_COUNTS(
    615           "GPU.ProgramCache.BinaryCacheHitTime",
    616           (TimeTicks::HighResNow() - before_time).InMicroseconds(),
    617           0,
    618           TimeDelta::FromSeconds(1).InMicroseconds(),
    619           50);
    620     }
    621   } else {
    622     UpdateLogInfo();
    623   }
    624   return success == GL_TRUE;
    625 }
    626 
    627 void Program::Validate() {
    628   if (!IsValid()) {
    629     set_log_info("program not linked");
    630     return;
    631   }
    632   glValidateProgram(service_id());
    633   UpdateLogInfo();
    634 }
    635 
    636 GLint Program::GetUniformFakeLocation(
    637     const std::string& name) const {
    638   bool getting_array_location = false;
    639   size_t open_pos = std::string::npos;
    640   int index = 0;
    641   if (!GLES2Util::ParseUniformName(
    642       name, &open_pos, &index, &getting_array_location)) {
    643     return -1;
    644   }
    645   for (GLuint ii = 0; ii < uniform_infos_.size(); ++ii) {
    646     const UniformInfo& info = uniform_infos_[ii];
    647     if (!info.IsValid()) {
    648       continue;
    649     }
    650     if (info.name == name ||
    651         (info.is_array &&
    652          info.name.compare(0, info.name.size() - 3, name) == 0)) {
    653       return info.fake_location_base;
    654     } else if (getting_array_location && info.is_array) {
    655       // Look for an array specification.
    656       size_t open_pos_2 = info.name.find_last_of('[');
    657       if (open_pos_2 == open_pos &&
    658           name.compare(0, open_pos, info.name, 0, open_pos) == 0) {
    659         if (index >= 0 && index < info.size) {
    660           DCHECK_GT(static_cast<int>(info.element_locations.size()), index);
    661           if (info.element_locations[index] == -1)
    662             return -1;
    663           return ProgramManager::MakeFakeLocation(
    664               info.fake_location_base, index);
    665         }
    666       }
    667     }
    668   }
    669   return -1;
    670 }
    671 
    672 GLint Program::GetAttribLocation(
    673     const std::string& name) const {
    674   for (GLuint ii = 0; ii < attrib_infos_.size(); ++ii) {
    675     const VertexAttrib& info = attrib_infos_[ii];
    676     if (info.name == name) {
    677       return info.location;
    678     }
    679   }
    680   return -1;
    681 }
    682 
    683 const Program::UniformInfo*
    684     Program::GetUniformInfoByFakeLocation(
    685         GLint fake_location, GLint* real_location, GLint* array_index) const {
    686   DCHECK(real_location);
    687   DCHECK(array_index);
    688   if (fake_location < 0) {
    689     return NULL;
    690   }
    691 
    692   GLint uniform_index = GetUniformInfoIndexFromFakeLocation(fake_location);
    693   if (uniform_index >= 0 &&
    694       static_cast<size_t>(uniform_index) < uniform_infos_.size()) {
    695     const UniformInfo& uniform_info = uniform_infos_[uniform_index];
    696     if (!uniform_info.IsValid()) {
    697       return NULL;
    698     }
    699     GLint element_index = GetArrayElementIndexFromFakeLocation(fake_location);
    700     if (element_index < uniform_info.size) {
    701       *real_location = uniform_info.element_locations[element_index];
    702       *array_index = element_index;
    703       return &uniform_info;
    704     }
    705   }
    706   return NULL;
    707 }
    708 
    709 const std::string* Program::GetAttribMappedName(
    710     const std::string& original_name) const {
    711   for (int ii = 0; ii < kMaxAttachedShaders; ++ii) {
    712     Shader* shader = attached_shaders_[ii].get();
    713     if (shader) {
    714       const std::string* mapped_name =
    715           shader->GetAttribMappedName(original_name);
    716       if (mapped_name)
    717         return mapped_name;
    718     }
    719   }
    720   return NULL;
    721 }
    722 
    723 const std::string* Program::GetOriginalNameFromHashedName(
    724     const std::string& hashed_name) const {
    725   for (int ii = 0; ii < kMaxAttachedShaders; ++ii) {
    726     Shader* shader = attached_shaders_[ii].get();
    727     if (shader) {
    728       const std::string* original_name =
    729           shader->GetOriginalNameFromHashedName(hashed_name);
    730       if (original_name)
    731         return original_name;
    732     }
    733   }
    734   return NULL;
    735 }
    736 
    737 bool Program::SetUniformLocationBinding(
    738     const std::string& name, GLint location) {
    739   std::string short_name;
    740   int element_index = 0;
    741   if (!GetUniformNameSansElement(name, &element_index, &short_name) ||
    742       element_index != 0) {
    743     return false;
    744   }
    745 
    746   bind_uniform_location_map_[short_name] = location;
    747   return true;
    748 }
    749 
    750 // Note: This is only valid to call right after a program has been linked
    751 // successfully.
    752 void Program::GetCorrectedVariableInfo(
    753     bool use_uniforms,
    754     const std::string& name, std::string* corrected_name,
    755     std::string* original_name,
    756     GLsizei* size, GLenum* type) const {
    757   DCHECK(corrected_name);
    758   DCHECK(original_name);
    759   DCHECK(size);
    760   DCHECK(type);
    761   const char* kArraySpec = "[0]";
    762   for (int jj = 0; jj < 2; ++jj) {
    763     std::string test_name(name + ((jj == 1) ? kArraySpec : ""));
    764     for (int ii = 0; ii < kMaxAttachedShaders; ++ii) {
    765       Shader* shader = attached_shaders_[ii].get();
    766       if (shader) {
    767         const Shader::VariableInfo* variable_info =
    768             use_uniforms ? shader->GetUniformInfo(test_name) :
    769                            shader->GetAttribInfo(test_name);
    770         // Note: There is an assuption here that if an attrib is defined in more
    771         // than 1 attached shader their types and sizes match. Should we check
    772         // for that case?
    773         if (variable_info) {
    774           *corrected_name = test_name;
    775           *original_name = variable_info->name;
    776           *type = variable_info->type;
    777           *size = variable_info->size;
    778           return;
    779         }
    780       }
    781     }
    782   }
    783   *corrected_name = name;
    784   *original_name = name;
    785 }
    786 
    787 bool Program::AddUniformInfo(
    788         GLsizei size, GLenum type, GLint location, GLint fake_base_location,
    789         const std::string& name, const std::string& original_name,
    790         size_t* next_available_index) {
    791   DCHECK(next_available_index);
    792   const char* kArraySpec = "[0]";
    793   size_t uniform_index =
    794       fake_base_location >= 0 ? fake_base_location : *next_available_index;
    795   if (uniform_infos_.size() < uniform_index + 1) {
    796     uniform_infos_.resize(uniform_index + 1);
    797   }
    798 
    799   // return if this location is already in use.
    800   if (uniform_infos_[uniform_index].IsValid()) {
    801     DCHECK_GE(fake_base_location, 0);
    802     return false;
    803   }
    804 
    805   uniform_infos_[uniform_index] = UniformInfo(
    806       size, type, uniform_index, original_name);
    807   ++num_uniforms_;
    808 
    809   UniformInfo& info = uniform_infos_[uniform_index];
    810   info.element_locations.resize(size);
    811   info.element_locations[0] = location;
    812   DCHECK_GE(size, 0);
    813   size_t num_texture_units = info.IsSampler() ? static_cast<size_t>(size) : 0u;
    814   info.texture_units.clear();
    815   info.texture_units.resize(num_texture_units, 0);
    816 
    817   if (size > 1) {
    818     // Go through the array element locations looking for a match.
    819     // We can skip the first element because it's the same as the
    820     // the location without the array operators.
    821     size_t array_pos = name.rfind(kArraySpec);
    822     std::string base_name = name;
    823     if (name.size() > 3) {
    824       if (array_pos != name.size() - 3) {
    825         info.name = name + kArraySpec;
    826       } else {
    827         base_name = name.substr(0, name.size() - 3);
    828       }
    829     }
    830     for (GLsizei ii = 1; ii < info.size; ++ii) {
    831       std::string element_name(base_name + "[" + base::IntToString(ii) + "]");
    832       info.element_locations[ii] =
    833           glGetUniformLocation(service_id_, element_name.c_str());
    834     }
    835   }
    836 
    837   info.is_array =
    838      (size > 1 ||
    839       (info.name.size() > 3 &&
    840        info.name.rfind(kArraySpec) == info.name.size() - 3));
    841 
    842   if (info.IsSampler()) {
    843     sampler_indices_.push_back(info.fake_location_base);
    844   }
    845   max_uniform_name_length_ =
    846       std::max(max_uniform_name_length_,
    847                static_cast<GLsizei>(info.name.size()));
    848 
    849   while (*next_available_index < uniform_infos_.size() &&
    850          uniform_infos_[*next_available_index].IsValid()) {
    851     *next_available_index = *next_available_index + 1;
    852   }
    853 
    854   return true;
    855 }
    856 
    857 const Program::UniformInfo*
    858     Program::GetUniformInfo(
    859         GLint index) const {
    860   if (static_cast<size_t>(index) >= uniform_infos_.size()) {
    861     return NULL;
    862   }
    863 
    864   const UniformInfo& info = uniform_infos_[index];
    865   return info.IsValid() ? &info : NULL;
    866 }
    867 
    868 bool Program::SetSamplers(
    869     GLint num_texture_units, GLint fake_location,
    870     GLsizei count, const GLint* value) {
    871   if (fake_location < 0) {
    872     return true;
    873   }
    874   GLint uniform_index = GetUniformInfoIndexFromFakeLocation(fake_location);
    875   if (uniform_index >= 0 &&
    876       static_cast<size_t>(uniform_index) < uniform_infos_.size()) {
    877     UniformInfo& info = uniform_infos_[uniform_index];
    878     if (!info.IsValid()) {
    879       return false;
    880     }
    881     GLint element_index = GetArrayElementIndexFromFakeLocation(fake_location);
    882     if (element_index < info.size) {
    883       count = std::min(info.size - element_index, count);
    884       if (info.IsSampler() && count > 0) {
    885         for (GLsizei ii = 0; ii < count; ++ii) {
    886           if (value[ii] < 0 || value[ii] >= num_texture_units) {
    887             return false;
    888           }
    889         }
    890         std::copy(value, value + count,
    891                   info.texture_units.begin() + element_index);
    892         return true;
    893       }
    894     }
    895   }
    896   return true;
    897 }
    898 
    899 void Program::GetProgramiv(GLenum pname, GLint* params) {
    900   switch (pname) {
    901     case GL_ACTIVE_ATTRIBUTES:
    902       *params = attrib_infos_.size();
    903       break;
    904     case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
    905       // Notice +1 to accomodate NULL terminator.
    906       *params = max_attrib_name_length_ + 1;
    907       break;
    908     case GL_ACTIVE_UNIFORMS:
    909       *params = num_uniforms_;
    910       break;
    911     case GL_ACTIVE_UNIFORM_MAX_LENGTH:
    912       // Notice +1 to accomodate NULL terminator.
    913       *params = max_uniform_name_length_ + 1;
    914       break;
    915     case GL_LINK_STATUS:
    916       *params = link_status_;
    917       break;
    918     case GL_INFO_LOG_LENGTH:
    919       // Notice +1 to accomodate NULL terminator.
    920       *params = log_info_.get() ? (log_info_->size() + 1) : 0;
    921       break;
    922     case GL_DELETE_STATUS:
    923       *params = deleted_;
    924       break;
    925     case GL_VALIDATE_STATUS:
    926       if (!IsValid()) {
    927         *params = GL_FALSE;
    928       } else {
    929         glGetProgramiv(service_id_, pname, params);
    930       }
    931       break;
    932     default:
    933       glGetProgramiv(service_id_, pname, params);
    934       break;
    935   }
    936 }
    937 
    938 bool Program::AttachShader(
    939     ShaderManager* shader_manager,
    940     Shader* shader) {
    941   DCHECK(shader_manager);
    942   DCHECK(shader);
    943   int index = ShaderTypeToIndex(shader->shader_type());
    944   if (attached_shaders_[index].get() != NULL) {
    945     return false;
    946   }
    947   attached_shaders_[index] = scoped_refptr<Shader>(shader);
    948   shader_manager->UseShader(shader);
    949   return true;
    950 }
    951 
    952 bool Program::DetachShader(
    953     ShaderManager* shader_manager,
    954     Shader* shader) {
    955   DCHECK(shader_manager);
    956   DCHECK(shader);
    957   if (attached_shaders_[ShaderTypeToIndex(shader->shader_type())].get() !=
    958       shader) {
    959     return false;
    960   }
    961   attached_shaders_[ShaderTypeToIndex(shader->shader_type())] = NULL;
    962   shader_manager->UnuseShader(shader);
    963   return true;
    964 }
    965 
    966 void Program::DetachShaders(ShaderManager* shader_manager) {
    967   DCHECK(shader_manager);
    968   for (int ii = 0; ii < kMaxAttachedShaders; ++ii) {
    969     if (attached_shaders_[ii].get()) {
    970       DetachShader(shader_manager, attached_shaders_[ii].get());
    971     }
    972   }
    973 }
    974 
    975 bool Program::CanLink() const {
    976   for (int ii = 0; ii < kMaxAttachedShaders; ++ii) {
    977     if (!attached_shaders_[ii].get() || !attached_shaders_[ii]->IsValid()) {
    978       return false;
    979     }
    980   }
    981   return true;
    982 }
    983 
    984 bool Program::DetectAttribLocationBindingConflicts() const {
    985   std::set<GLint> location_binding_used;
    986   for (LocationMap::const_iterator it = bind_attrib_location_map_.begin();
    987        it != bind_attrib_location_map_.end(); ++it) {
    988     // Find out if an attribute is declared in this program's shaders.
    989     bool active = false;
    990     for (int ii = 0; ii < kMaxAttachedShaders; ++ii) {
    991       if (!attached_shaders_[ii].get() || !attached_shaders_[ii]->IsValid())
    992         continue;
    993       if (attached_shaders_[ii]->GetAttribInfo(it->first)) {
    994         active = true;
    995         break;
    996       }
    997     }
    998     if (active) {
    999       std::pair<std::set<GLint>::iterator, bool> result =
   1000           location_binding_used.insert(it->second);
   1001       if (!result.second)
   1002         return true;
   1003     }
   1004   }
   1005   return false;
   1006 }
   1007 
   1008 bool Program::DetectUniformsMismatch() const {
   1009   typedef std::map<std::string, UniformType> UniformMap;
   1010   UniformMap uniform_map;
   1011   for (int ii = 0; ii < kMaxAttachedShaders; ++ii) {
   1012     const ShaderTranslator::VariableMap& shader_uniforms =
   1013         attached_shaders_[ii]->uniform_map();
   1014     for (ShaderTranslator::VariableMap::const_iterator iter =
   1015              shader_uniforms.begin();
   1016          iter != shader_uniforms.end(); ++iter) {
   1017       const std::string& name = iter->first;
   1018       UniformType type(iter->second);
   1019       UniformMap::iterator map_entry = uniform_map.find(name);
   1020       if (map_entry == uniform_map.end()) {
   1021         uniform_map[name] = type;
   1022       } else {
   1023         // If a uniform is already in the map, i.e., it has already been
   1024         // declared by other shader, then the type and precision must match.
   1025         if (map_entry->second == type)
   1026           continue;
   1027         return true;
   1028       }
   1029     }
   1030   }
   1031   return false;
   1032 }
   1033 
   1034 bool Program::DetectVaryingsMismatch() const {
   1035   DCHECK(attached_shaders_[0] &&
   1036          attached_shaders_[0]->shader_type() == GL_VERTEX_SHADER &&
   1037          attached_shaders_[1] &&
   1038          attached_shaders_[1]->shader_type() == GL_FRAGMENT_SHADER);
   1039   const ShaderTranslator::VariableMap* vertex_varyings =
   1040       &(attached_shaders_[0]->varying_map());
   1041   const ShaderTranslator::VariableMap* fragment_varyings =
   1042       &(attached_shaders_[1]->varying_map());
   1043 
   1044   for (ShaderTranslator::VariableMap::const_iterator iter =
   1045            fragment_varyings->begin();
   1046        iter != fragment_varyings->end(); ++iter) {
   1047     const std::string& name = iter->first;
   1048     if (IsBuiltInVarying(name))
   1049       continue;
   1050 
   1051     ShaderTranslator::VariableMap::const_iterator hit =
   1052         vertex_varyings->find(name);
   1053     if (hit == vertex_varyings->end()) {
   1054       if (iter->second.static_use)
   1055         return true;
   1056       continue;
   1057     }
   1058 
   1059     if (hit->second.type != iter->second.type ||
   1060         hit->second.size != iter->second.size)
   1061       return true;
   1062 
   1063   }
   1064   return false;
   1065 }
   1066 
   1067 bool Program::DetectGlobalNameConflicts() const {
   1068   DCHECK(attached_shaders_[0] &&
   1069          attached_shaders_[0]->shader_type() == GL_VERTEX_SHADER &&
   1070          attached_shaders_[1] &&
   1071          attached_shaders_[1]->shader_type() == GL_FRAGMENT_SHADER);
   1072   const ShaderTranslator::VariableMap* uniforms[2];
   1073   uniforms[0] = &(attached_shaders_[0]->uniform_map());
   1074   uniforms[1] = &(attached_shaders_[1]->uniform_map());
   1075   const ShaderTranslator::VariableMap* attribs =
   1076       &(attached_shaders_[0]->attrib_map());
   1077 
   1078   for (ShaderTranslator::VariableMap::const_iterator iter =
   1079            attribs->begin(); iter != attribs->end(); ++iter) {
   1080     for (int ii = 0; ii < 2; ++ii) {
   1081       if (uniforms[ii]->find(iter->first) != uniforms[ii]->end())
   1082         return true;
   1083     }
   1084   }
   1085   return false;
   1086 }
   1087 
   1088 bool Program::CheckVaryingsPacking(
   1089     Program::VaryingsPackingOption option) const {
   1090   DCHECK(attached_shaders_[0] &&
   1091          attached_shaders_[0]->shader_type() == GL_VERTEX_SHADER &&
   1092          attached_shaders_[1] &&
   1093          attached_shaders_[1]->shader_type() == GL_FRAGMENT_SHADER);
   1094   const ShaderTranslator::VariableMap* vertex_varyings =
   1095       &(attached_shaders_[0]->varying_map());
   1096   const ShaderTranslator::VariableMap* fragment_varyings =
   1097       &(attached_shaders_[1]->varying_map());
   1098 
   1099   std::map<std::string, ShVariableInfo> combined_map;
   1100 
   1101   for (ShaderTranslator::VariableMap::const_iterator iter =
   1102            fragment_varyings->begin();
   1103        iter != fragment_varyings->end(); ++iter) {
   1104     if (!iter->second.static_use && option == kCountOnlyStaticallyUsed)
   1105       continue;
   1106     if (!IsBuiltInVarying(iter->first)) {
   1107       ShaderTranslator::VariableMap::const_iterator vertex_iter =
   1108           vertex_varyings->find(iter->first);
   1109       if (vertex_iter == vertex_varyings->end() ||
   1110           (!vertex_iter->second.static_use &&
   1111            option == kCountOnlyStaticallyUsed))
   1112         continue;
   1113     }
   1114 
   1115     ShVariableInfo var;
   1116     var.type = static_cast<ShDataType>(iter->second.type);
   1117     var.size = iter->second.size;
   1118     combined_map[iter->first] = var;
   1119   }
   1120 
   1121   if (combined_map.size() == 0)
   1122     return true;
   1123   scoped_ptr<ShVariableInfo[]> variables(
   1124       new ShVariableInfo[combined_map.size()]);
   1125   size_t index = 0;
   1126   for (std::map<std::string, ShVariableInfo>::const_iterator iter =
   1127            combined_map.begin();
   1128        iter != combined_map.end(); ++iter) {
   1129     variables[index].type = iter->second.type;
   1130     variables[index].size = iter->second.size;
   1131     ++index;
   1132   }
   1133   return ShCheckVariablesWithinPackingLimits(
   1134       static_cast<int>(manager_->max_varying_vectors()),
   1135       variables.get(),
   1136       combined_map.size()) == 1;
   1137 }
   1138 
   1139 static uint32 ComputeOffset(const void* start, const void* position) {
   1140   return static_cast<const uint8*>(position) -
   1141          static_cast<const uint8*>(start);
   1142 }
   1143 
   1144 void Program::GetProgramInfo(
   1145     ProgramManager* manager, CommonDecoder::Bucket* bucket) const {
   1146   // NOTE: It seems to me the math in here does not need check for overflow
   1147   // because the data being calucated from has various small limits. The max
   1148   // number of attribs + uniforms is somewhere well under 1024. The maximum size
   1149   // of an identifier is 256 characters.
   1150   uint32 num_locations = 0;
   1151   uint32 total_string_size = 0;
   1152 
   1153   for (size_t ii = 0; ii < attrib_infos_.size(); ++ii) {
   1154     const VertexAttrib& info = attrib_infos_[ii];
   1155     num_locations += 1;
   1156     total_string_size += info.name.size();
   1157   }
   1158 
   1159   for (size_t ii = 0; ii < uniform_infos_.size(); ++ii) {
   1160     const UniformInfo& info = uniform_infos_[ii];
   1161     if (info.IsValid()) {
   1162       num_locations += info.element_locations.size();
   1163       total_string_size += info.name.size();
   1164     }
   1165   }
   1166 
   1167   uint32 num_inputs = attrib_infos_.size() + num_uniforms_;
   1168   uint32 input_size = num_inputs * sizeof(ProgramInput);
   1169   uint32 location_size = num_locations * sizeof(int32);
   1170   uint32 size = sizeof(ProgramInfoHeader) +
   1171       input_size + location_size + total_string_size;
   1172 
   1173   bucket->SetSize(size);
   1174   ProgramInfoHeader* header = bucket->GetDataAs<ProgramInfoHeader*>(0, size);
   1175   ProgramInput* inputs = bucket->GetDataAs<ProgramInput*>(
   1176       sizeof(ProgramInfoHeader), input_size);
   1177   int32* locations = bucket->GetDataAs<int32*>(
   1178       sizeof(ProgramInfoHeader) + input_size, location_size);
   1179   char* strings = bucket->GetDataAs<char*>(
   1180       sizeof(ProgramInfoHeader) + input_size + location_size,
   1181       total_string_size);
   1182   DCHECK(header);
   1183   DCHECK(inputs);
   1184   DCHECK(locations);
   1185   DCHECK(strings);
   1186 
   1187   header->link_status = link_status_;
   1188   header->num_attribs = attrib_infos_.size();
   1189   header->num_uniforms = num_uniforms_;
   1190 
   1191   for (size_t ii = 0; ii < attrib_infos_.size(); ++ii) {
   1192     const VertexAttrib& info = attrib_infos_[ii];
   1193     inputs->size = info.size;
   1194     inputs->type = info.type;
   1195     inputs->location_offset = ComputeOffset(header, locations);
   1196     inputs->name_offset = ComputeOffset(header, strings);
   1197     inputs->name_length = info.name.size();
   1198     *locations++ = info.location;
   1199     memcpy(strings, info.name.c_str(), info.name.size());
   1200     strings += info.name.size();
   1201     ++inputs;
   1202   }
   1203 
   1204   for (size_t ii = 0; ii < uniform_infos_.size(); ++ii) {
   1205     const UniformInfo& info = uniform_infos_[ii];
   1206     if (info.IsValid()) {
   1207       inputs->size = info.size;
   1208       inputs->type = info.type;
   1209       inputs->location_offset = ComputeOffset(header, locations);
   1210       inputs->name_offset = ComputeOffset(header, strings);
   1211       inputs->name_length = info.name.size();
   1212       DCHECK(static_cast<size_t>(info.size) == info.element_locations.size());
   1213       for (size_t jj = 0; jj < info.element_locations.size(); ++jj) {
   1214         if (info.element_locations[jj] == -1)
   1215           *locations++ = -1;
   1216         else
   1217           *locations++ = ProgramManager::MakeFakeLocation(ii, jj);
   1218       }
   1219       memcpy(strings, info.name.c_str(), info.name.size());
   1220       strings += info.name.size();
   1221       ++inputs;
   1222     }
   1223   }
   1224 
   1225   DCHECK_EQ(ComputeOffset(header, strings), size);
   1226 }
   1227 
   1228 Program::~Program() {
   1229   if (manager_) {
   1230     if (manager_->have_context_) {
   1231       glDeleteProgram(service_id());
   1232     }
   1233     manager_->StopTracking(this);
   1234     manager_ = NULL;
   1235   }
   1236 }
   1237 
   1238 
   1239 ProgramManager::ProgramManager(ProgramCache* program_cache,
   1240                                uint32 max_varying_vectors)
   1241     : program_count_(0),
   1242       have_context_(true),
   1243       program_cache_(program_cache),
   1244       max_varying_vectors_(max_varying_vectors) { }
   1245 
   1246 ProgramManager::~ProgramManager() {
   1247   DCHECK(programs_.empty());
   1248 }
   1249 
   1250 void ProgramManager::Destroy(bool have_context) {
   1251   have_context_ = have_context;
   1252   programs_.clear();
   1253 }
   1254 
   1255 void ProgramManager::StartTracking(Program* /* program */) {
   1256   ++program_count_;
   1257 }
   1258 
   1259 void ProgramManager::StopTracking(Program* /* program */) {
   1260   --program_count_;
   1261 }
   1262 
   1263 Program* ProgramManager::CreateProgram(
   1264     GLuint client_id, GLuint service_id) {
   1265   std::pair<ProgramMap::iterator, bool> result =
   1266       programs_.insert(
   1267           std::make_pair(client_id,
   1268                          scoped_refptr<Program>(
   1269                              new Program(this, service_id))));
   1270   DCHECK(result.second);
   1271   return result.first->second.get();
   1272 }
   1273 
   1274 Program* ProgramManager::GetProgram(GLuint client_id) {
   1275   ProgramMap::iterator it = programs_.find(client_id);
   1276   return it != programs_.end() ? it->second.get() : NULL;
   1277 }
   1278 
   1279 bool ProgramManager::GetClientId(GLuint service_id, GLuint* client_id) const {
   1280   // This doesn't need to be fast. It's only used during slow queries.
   1281   for (ProgramMap::const_iterator it = programs_.begin();
   1282        it != programs_.end(); ++it) {
   1283     if (it->second->service_id() == service_id) {
   1284       *client_id = it->first;
   1285       return true;
   1286     }
   1287   }
   1288   return false;
   1289 }
   1290 
   1291 ProgramCache* ProgramManager::program_cache() const {
   1292   return program_cache_;
   1293 }
   1294 
   1295 bool ProgramManager::IsOwned(Program* program) {
   1296   for (ProgramMap::iterator it = programs_.begin();
   1297        it != programs_.end(); ++it) {
   1298     if (it->second.get() == program) {
   1299       return true;
   1300     }
   1301   }
   1302   return false;
   1303 }
   1304 
   1305 void ProgramManager::RemoveProgramInfoIfUnused(
   1306     ShaderManager* shader_manager, Program* program) {
   1307   DCHECK(shader_manager);
   1308   DCHECK(program);
   1309   DCHECK(IsOwned(program));
   1310   if (program->IsDeleted() && !program->InUse()) {
   1311     program->DetachShaders(shader_manager);
   1312     for (ProgramMap::iterator it = programs_.begin();
   1313          it != programs_.end(); ++it) {
   1314       if (it->second.get() == program) {
   1315         programs_.erase(it);
   1316         return;
   1317       }
   1318     }
   1319     NOTREACHED();
   1320   }
   1321 }
   1322 
   1323 void ProgramManager::MarkAsDeleted(
   1324     ShaderManager* shader_manager,
   1325     Program* program) {
   1326   DCHECK(shader_manager);
   1327   DCHECK(program);
   1328   DCHECK(IsOwned(program));
   1329   program->MarkAsDeleted();
   1330   RemoveProgramInfoIfUnused(shader_manager, program);
   1331 }
   1332 
   1333 void ProgramManager::UseProgram(Program* program) {
   1334   DCHECK(program);
   1335   DCHECK(IsOwned(program));
   1336   program->IncUseCount();
   1337 }
   1338 
   1339 void ProgramManager::UnuseProgram(
   1340     ShaderManager* shader_manager,
   1341     Program* program) {
   1342   DCHECK(shader_manager);
   1343   DCHECK(program);
   1344   DCHECK(IsOwned(program));
   1345   program->DecUseCount();
   1346   RemoveProgramInfoIfUnused(shader_manager, program);
   1347 }
   1348 
   1349 void ProgramManager::ClearUniforms(Program* program) {
   1350   DCHECK(program);
   1351   program->ClearUniforms(&zero_);
   1352 }
   1353 
   1354 int32 ProgramManager::MakeFakeLocation(int32 index, int32 element) {
   1355   return index + element * 0x10000;
   1356 }
   1357 
   1358 }  // namespace gles2
   1359 }  // namespace gpu
   1360