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