| Index: gpu/command_buffer/client/program_info_manager.cc
 | 
| diff --git a/gpu/command_buffer/client/program_info_manager.cc b/gpu/command_buffer/client/program_info_manager.cc
 | 
| index f667d6dbdcc3736708c6723d4ca607588f73bf08..e167e38d91a8aa2f70b62ff8e379babff3afa42c 100644
 | 
| --- a/gpu/command_buffer/client/program_info_manager.cc
 | 
| +++ b/gpu/command_buffer/client/program_info_manager.cc
 | 
| @@ -4,9 +4,10 @@
 | 
|  
 | 
|  #include "gpu/command_buffer/client/program_info_manager.h"
 | 
|  
 | 
| -#include <map>
 | 
| +#include <string>
 | 
|  
 | 
|  #include "base/compiler_specific.h"
 | 
| +#include "base/containers/hash_tables.h"
 | 
|  #include "base/synchronization/lock.h"
 | 
|  #include "gpu/command_buffer/client/gles2_implementation.h"
 | 
|  #include "gpu/command_buffer/common/gles2_cmd_utils.h"
 | 
| @@ -36,6 +37,10 @@ class NonCachedProgramInfoManager : public ProgramInfoManager {
 | 
|                             GLuint program,
 | 
|                             const char* name) override;
 | 
|  
 | 
| +  GLint GetFragDataLocation(GLES2Implementation* gl,
 | 
| +                            GLuint program,
 | 
| +                            const char* name) override;
 | 
| +
 | 
|    bool GetActiveAttrib(GLES2Implementation* gl,
 | 
|                         GLuint program,
 | 
|                         GLuint index,
 | 
| @@ -85,6 +90,11 @@ GLint NonCachedProgramInfoManager::GetUniformLocation(
 | 
|    return gl->GetUniformLocationHelper(program, name);
 | 
|  }
 | 
|  
 | 
| +GLint NonCachedProgramInfoManager::GetFragDataLocation(
 | 
| +    GLES2Implementation* gl, GLuint program, const char* name) {
 | 
| +  return gl->GetFragDataLocationHelper(program, name);
 | 
| +}
 | 
| +
 | 
|  bool NonCachedProgramInfoManager::GetActiveAttrib(
 | 
|      GLES2Implementation* gl,
 | 
|      GLuint program, GLuint index, GLsizei bufsize, GLsizei* length,
 | 
| @@ -123,6 +133,10 @@ class CachedProgramInfoManager : public ProgramInfoManager {
 | 
|                             GLuint program,
 | 
|                             const char* name) override;
 | 
|  
 | 
| +  GLint GetFragDataLocation(GLES2Implementation* gl,
 | 
| +                            GLuint program,
 | 
| +                            const char* name) override;
 | 
| +
 | 
|    bool GetActiveAttrib(GLES2Implementation* gl,
 | 
|                         GLuint program,
 | 
|                         GLuint index,
 | 
| @@ -191,6 +205,9 @@ class CachedProgramInfoManager : public ProgramInfoManager {
 | 
|      // Gets the location of a uniform by name.
 | 
|      GLint GetUniformLocation(const std::string& name) const;
 | 
|  
 | 
| +    GLint GetFragDataLocation(const std::string& name) const;
 | 
| +    void CacheFragDataLocation(const std::string& name, GLint loc);
 | 
| +
 | 
|      bool GetProgramiv(GLenum pname, GLint* params);
 | 
|  
 | 
|      // Updates the program info after a successful link.
 | 
| @@ -213,14 +230,15 @@ class CachedProgramInfoManager : public ProgramInfoManager {
 | 
|      // Uniform info by index.
 | 
|      UniformInfoVector uniform_infos_;
 | 
|  
 | 
| +    base::hash_map<std::string, GLint> frag_data_locations_;
 | 
| +
 | 
|      // This is true if glLinkProgram was successful last time it was called.
 | 
|      bool link_status_;
 | 
|    };
 | 
|  
 | 
|    Program* GetProgramInfo(GLES2Implementation* gl, GLuint program);
 | 
|  
 | 
| -  // TODO(gman): Switch to a faster container.
 | 
| -  typedef std::map<GLuint, Program> ProgramInfoMap;
 | 
| +  typedef base::hash_map<GLuint, Program> ProgramInfoMap;
 | 
|  
 | 
|    ProgramInfoMap program_infos_;
 | 
|  
 | 
| @@ -284,6 +302,20 @@ GLint CachedProgramInfoManager::Program::GetUniformLocation(
 | 
|    return -1;
 | 
|  }
 | 
|  
 | 
| +GLint CachedProgramInfoManager::Program::GetFragDataLocation(
 | 
| +    const std::string& name) const {
 | 
| +  base::hash_map<std::string, GLint>::const_iterator iter =
 | 
| +      frag_data_locations_.find(name);
 | 
| +  if (iter == frag_data_locations_.end())
 | 
| +    return -1;
 | 
| +  return iter->second;
 | 
| +}
 | 
| +
 | 
| +void CachedProgramInfoManager::Program::CacheFragDataLocation(
 | 
| +    const std::string& name, GLint loc) {
 | 
| +  frag_data_locations_[name] = loc;
 | 
| +}
 | 
| +
 | 
|  bool CachedProgramInfoManager::Program::GetProgramiv(
 | 
|      GLenum pname, GLint* params) {
 | 
|    switch (pname) {
 | 
| @@ -338,6 +370,7 @@ void CachedProgramInfoManager::Program::Update(
 | 
|    }
 | 
|    attrib_infos_.clear();
 | 
|    uniform_infos_.clear();
 | 
| +  frag_data_locations_.clear();
 | 
|    max_attrib_name_length_ = 0;
 | 
|    max_uniform_name_length_ = 0;
 | 
|    const ProgramInput* inputs = LocalGetAs<const ProgramInput*>(
 | 
| @@ -459,6 +492,30 @@ GLint CachedProgramInfoManager::GetUniformLocation(
 | 
|    return gl->GetUniformLocationHelper(program, name);
 | 
|  }
 | 
|  
 | 
| +GLint CachedProgramInfoManager::GetFragDataLocation(
 | 
| +    GLES2Implementation* gl, GLuint program, const char* name) {
 | 
| +  // TODO(zmo): make FragData locations part of the ProgramInfo that are
 | 
| +  // fetched altogether from the service side.  See crbug.com/452104.
 | 
| +  {
 | 
| +    base::AutoLock auto_lock(lock_);
 | 
| +    Program* info = GetProgramInfo(gl, program);
 | 
| +    if (info) {
 | 
| +      GLint possible_loc = info->GetFragDataLocation(name);
 | 
| +      if (possible_loc != -1)
 | 
| +        return possible_loc;
 | 
| +    }
 | 
| +  }
 | 
| +  GLint loc = gl->GetFragDataLocationHelper(program, name);
 | 
| +  if (loc != -1) {
 | 
| +    base::AutoLock auto_lock(lock_);
 | 
| +    Program* info = GetProgramInfo(gl, program);
 | 
| +    if (info) {
 | 
| +      info->CacheFragDataLocation(name, loc);
 | 
| +    }
 | 
| +  }
 | 
| +  return loc;
 | 
| +}
 | 
| +
 | 
|  bool CachedProgramInfoManager::GetActiveAttrib(
 | 
|      GLES2Implementation* gl,
 | 
|      GLuint program, GLuint index, GLsizei bufsize, GLsizei* length,
 | 
| 
 |