// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <stddef.h>
#include <stdint.h>

#include "gpu/command_buffer/client/program_info_manager.h"

namespace {

template <typename T>
static T LocalGetAs(const std::vector<int8_t>& data,
                    uint32_t offset,
                    size_t size) {
  const int8_t* p = &data[0] + offset;
  if (offset + size > data.size()) {
    NOTREACHED();
    return NULL;
  }
  return static_cast<T>(static_cast<const void*>(p));
}

}  // namespace

namespace gpu {
namespace gles2 {

ProgramInfoManager::Program::VertexAttrib::VertexAttrib(
    GLsizei _size, GLenum _type, const std::string& _name, GLint _location)
    : size(_size),
      type(_type),
      location(_location),
      name(_name) {
}

ProgramInfoManager::Program::VertexAttrib::~VertexAttrib() = default;

ProgramInfoManager::Program::UniformInfo::UniformInfo(
    GLsizei _size, GLenum _type, const std::string& _name)
    : size(_size),
      type(_type),
      name(_name) {
  is_array = (!name.empty() && name.back() == ']');
  DCHECK(!(size > 1 && !is_array));
}

ProgramInfoManager::Program::UniformInfo::UniformInfo(
    const UniformInfo& other) = default;

ProgramInfoManager::Program::UniformInfo::~UniformInfo() = default;

ProgramInfoManager::Program::UniformES3::UniformES3()
    : block_index(-1),
      offset(-1),
      array_stride(-1),
      matrix_stride(-1),
      is_row_major(0) {
}

ProgramInfoManager::Program::UniformES3::~UniformES3() = default;

ProgramInfoManager::Program::UniformBlock::UniformBlock()
    : binding(0),
      data_size(0),
      referenced_by_vertex_shader(false),
      referenced_by_fragment_shader(false) {
}

ProgramInfoManager::Program::UniformBlock::UniformBlock(
    const UniformBlock& other) = default;

ProgramInfoManager::Program::UniformBlock::~UniformBlock() = default;

ProgramInfoManager::Program::TransformFeedbackVarying::
TransformFeedbackVarying()
    : size(0),
      type(0) {
}

ProgramInfoManager::Program::TransformFeedbackVarying::
    ~TransformFeedbackVarying() = default;

ProgramInfoManager::Program::Program()
    : cached_es2_(false),
      max_attrib_name_length_(0),
      max_uniform_name_length_(0),
      link_status_(false),
      cached_es3_uniform_blocks_(false),
      active_uniform_block_max_name_length_(0),
      cached_es3_transform_feedback_varyings_(false),
      transform_feedback_varying_max_length_(0),
      transform_feedback_buffer_mode_(0),
      cached_es3_uniformsiv_(false) {
}

ProgramInfoManager::Program::Program(const Program& other) = default;

ProgramInfoManager::Program::~Program() = default;

// TODO(gman): Add a faster lookup.
GLint ProgramInfoManager::Program::GetAttribLocation(
    const std::string& name) const {
  for (GLuint ii = 0; ii < attrib_infos_.size(); ++ii) {
    const VertexAttrib& info = attrib_infos_[ii];
    if (info.name == name) {
      return info.location;
    }
  }
  return -1;
}

const ProgramInfoManager::Program::VertexAttrib*
ProgramInfoManager::Program::GetAttribInfo(GLint index) const {
  return (static_cast<size_t>(index) < attrib_infos_.size()) ?
      &attrib_infos_[index] : NULL;
}

const ProgramInfoManager::Program::UniformInfo*
ProgramInfoManager::Program::GetUniformInfo(GLint index) const {
  return (static_cast<size_t>(index) < uniform_infos_.size()) ?
      &uniform_infos_[index] : NULL;
}

const ProgramInfoManager::Program::UniformBlock*
ProgramInfoManager::Program::GetUniformBlock(GLuint index) const {
  return (index < uniform_blocks_.size()) ? &uniform_blocks_[index] : NULL;
}

GLint ProgramInfoManager::Program::GetUniformLocation(
    const std::string& name) const {
  GLSLArrayName parsed_name(name);

  for (GLuint ii = 0; ii < uniform_infos_.size(); ++ii) {
    const UniformInfo& info = uniform_infos_[ii];
    if (info.name == name ||
        (info.is_array &&
         info.name.compare(0, info.name.size() - 3, name) == 0)) {
      return info.element_locations[0];
    } else if (parsed_name.IsArrayName() && info.is_array) {
      // Look for an array specification.
      size_t open_pos = info.name.find_last_of('[');
      if (info.name.compare(0, open_pos, parsed_name.base_name()) == 0) {
        int index = parsed_name.element_index();
        if (index < info.size) {
          return info.element_locations[index];
        }
      }
    }
  }
  return -1;
}

GLuint ProgramInfoManager::Program::GetUniformIndex(
    const std::string& name) const {
  // TODO(zmo): Maybe build a hashed_map for faster lookup.
  for (GLuint ii = 0; ii < uniform_infos_.size(); ++ii) {
    const UniformInfo& info = uniform_infos_[ii];
    // For an array, either "var" or "var[0]" is considered as a match.
    // See "OpenGL ES 3.0.0, Section 2.11.3 Program Objects."
    if (info.name == name ||
        (info.is_array &&
         info.name.compare(0, info.name.size() - 3, name) == 0)) {
      return ii;
    }
  }
  return GL_INVALID_INDEX;
}

GLint ProgramInfoManager::Program::GetFragDataIndex(
    const std::string& name) const {
  auto iter = frag_data_indices_.find(name);
  if (iter == frag_data_indices_.end())
    return -1;
  return iter->second;
}

void ProgramInfoManager::Program::CacheFragDataIndex(const std::string& name,
                                                     GLint index) {
  frag_data_indices_[name] = index;
}

GLint ProgramInfoManager::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 ProgramInfoManager::Program::CacheFragDataLocation(
    const std::string& name, GLint loc) {
  frag_data_locations_[name] = loc;
}

bool ProgramInfoManager::Program::GetProgramiv(
    GLenum pname, GLint* params) {
  switch (pname) {
    case GL_LINK_STATUS:
      *params = static_cast<GLint>(link_status_);
      return true;
    case GL_ACTIVE_ATTRIBUTES:
      *params = static_cast<GLint>(attrib_infos_.size());
      return true;
    case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
      *params = static_cast<GLint>(max_attrib_name_length_);
      return true;
    case GL_ACTIVE_UNIFORMS:
      *params = static_cast<GLint>(uniform_infos_.size());
      return true;
    case GL_ACTIVE_UNIFORM_MAX_LENGTH:
      *params = static_cast<GLint>(max_uniform_name_length_);
      return true;
    case GL_ACTIVE_UNIFORM_BLOCKS:
      *params = static_cast<GLint>(uniform_blocks_.size());
      return true;
    case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
      *params = static_cast<GLint>(active_uniform_block_max_name_length_);
      return true;
    case GL_TRANSFORM_FEEDBACK_VARYINGS:
      *params = static_cast<GLint>(transform_feedback_varyings_.size());
      return true;
    case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
      *params = static_cast<GLint>(transform_feedback_varying_max_length_);
      return true;
    case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
      *params = static_cast<GLint>(transform_feedback_buffer_mode_);
      return true;
    default:
      NOTREACHED();
      break;
  }
  return false;
}

GLuint ProgramInfoManager::Program::GetUniformBlockIndex(
    const std::string& name) const {
  for (size_t ii = 0; ii < uniform_blocks_.size(); ++ii) {
    if (uniform_blocks_[ii].name == name) {
      return static_cast<GLuint>(ii);
    }
  }
  return GL_INVALID_INDEX;
}

void ProgramInfoManager::Program::UniformBlockBinding(
    GLuint index , GLuint binding) {
  if (index < uniform_blocks_.size()) {
    uniform_blocks_[index].binding = binding;
  }
}

const ProgramInfoManager::Program::TransformFeedbackVarying*
ProgramInfoManager::Program::GetTransformFeedbackVarying(GLuint index) const {
  return (index < transform_feedback_varyings_.size()) ?
      &transform_feedback_varyings_[index] : NULL;
}

bool ProgramInfoManager::Program::GetUniformsiv(
    GLsizei count, const GLuint* indices, GLenum pname, GLint* params) {
  if (count == 0) {
    // At this point, pname has already been validated.
    return true;
  }
  DCHECK(count > 0 && indices);
  size_t num_uniforms = uniform_infos_.size();
  if (num_uniforms == 0) {
    num_uniforms = uniforms_es3_.size();
  }
  if (static_cast<size_t>(count) > num_uniforms) {
    return false;
  }
  for (GLsizei ii = 0; ii < count; ++ii) {
    if (indices[ii] >= num_uniforms) {
      return false;
    }
  }
  if (!params) {
    return true;
  }
  switch (pname) {
    case GL_UNIFORM_SIZE:
      DCHECK_EQ(num_uniforms, uniform_infos_.size());
      for (GLsizei ii = 0; ii < count; ++ii) {
        params[ii] = static_cast<GLint>(uniform_infos_[indices[ii]].size);
      }
      return true;
    case GL_UNIFORM_TYPE:
      DCHECK_EQ(num_uniforms, uniform_infos_.size());
      for (GLsizei ii = 0; ii < count; ++ii) {
        params[ii] = static_cast<GLint>(uniform_infos_[indices[ii]].type);
      }
      return true;
    case GL_UNIFORM_NAME_LENGTH:
      DCHECK_EQ(num_uniforms, uniform_infos_.size());
      for (GLsizei ii = 0; ii < count; ++ii) {
        params[ii] = static_cast<GLint>(
            uniform_infos_[indices[ii]].name.length() + 1);
      }
      return true;
    case GL_UNIFORM_BLOCK_INDEX:
      DCHECK_EQ(num_uniforms, uniforms_es3_.size());
      for (GLsizei ii = 0; ii < count; ++ii) {
        params[ii] = uniforms_es3_[indices[ii]].block_index;
      }
      return true;
    case GL_UNIFORM_OFFSET:
      DCHECK_EQ(num_uniforms, uniforms_es3_.size());
      for (GLsizei ii = 0; ii < count; ++ii) {
        params[ii] = uniforms_es3_[indices[ii]].offset;
      }
      return true;
    case GL_UNIFORM_ARRAY_STRIDE:
      DCHECK_EQ(num_uniforms, uniforms_es3_.size());
      for (GLsizei ii = 0; ii < count; ++ii) {
        params[ii] = uniforms_es3_[indices[ii]].array_stride;
      }
      return true;
    case GL_UNIFORM_MATRIX_STRIDE:
      DCHECK_EQ(num_uniforms, uniforms_es3_.size());
      for (GLsizei ii = 0; ii < count; ++ii) {
        params[ii] = uniforms_es3_[indices[ii]].matrix_stride;
      }
      return true;
    case GL_UNIFORM_IS_ROW_MAJOR:
      DCHECK_EQ(num_uniforms, uniforms_es3_.size());
      for (GLsizei ii = 0; ii < count; ++ii) {
        params[ii] = uniforms_es3_[indices[ii]].is_row_major;
      }
      return true;
    default:
      NOTREACHED();
      break;
  }
  return false;
}

void ProgramInfoManager::Program::UpdateES2(const std::vector<int8_t>& result) {
  if (cached_es2_) {
    return;
  }
  if (result.empty()) {
    // This should only happen on a lost context.
    return;
  }
  DCHECK_GE(result.size(), sizeof(ProgramInfoHeader));
  const ProgramInfoHeader* header = LocalGetAs<const ProgramInfoHeader*>(
      result, 0, sizeof(header));
  link_status_ = header->link_status != 0;
  if (!link_status_) {
    return;
  }
  DCHECK_EQ(0u, attrib_infos_.size());
  DCHECK_EQ(0u, uniform_infos_.size());
  DCHECK_EQ(0, max_attrib_name_length_);
  DCHECK_EQ(0, max_uniform_name_length_);
  const ProgramInput* inputs = LocalGetAs<const ProgramInput*>(
      result, sizeof(*header),
      sizeof(ProgramInput) * (header->num_attribs + header->num_uniforms));
  const ProgramInput* input = inputs;
  for (uint32_t ii = 0; ii < header->num_attribs; ++ii) {
    const int32_t* location = LocalGetAs<const int32_t*>(
        result, input->location_offset, sizeof(int32_t));
    const char* name_buf = LocalGetAs<const char*>(
        result, input->name_offset, input->name_length);
    std::string name(name_buf, input->name_length);
    attrib_infos_.push_back(
        VertexAttrib(input->size, input->type, name, *location));
    max_attrib_name_length_ = std::max(
        static_cast<GLsizei>(name.size() + 1), max_attrib_name_length_);
    ++input;
  }
  for (uint32_t ii = 0; ii < header->num_uniforms; ++ii) {
    const int32_t* locations = LocalGetAs<const int32_t*>(
        result, input->location_offset, sizeof(int32_t) * input->size);
    const char* name_buf = LocalGetAs<const char*>(
        result, input->name_offset, input->name_length);
    std::string name(name_buf, input->name_length);
    UniformInfo info(input->size, input->type, name);
    max_uniform_name_length_ = std::max(
        static_cast<GLsizei>(name.size() + 1), max_uniform_name_length_);
    for (int32_t jj = 0; jj < input->size; ++jj) {
      info.element_locations.push_back(locations[jj]);
    }
    uniform_infos_.push_back(info);
    ++input;
  }
  DCHECK_EQ(header->num_attribs + header->num_uniforms,
            static_cast<uint32_t>(input - inputs));
  cached_es2_ = true;
}

void ProgramInfoManager::Program::UpdateES3UniformBlocks(
    const std::vector<int8_t>& result) {
  if (cached_es3_uniform_blocks_) {
    return;
  }
  if (result.empty()) {
    // This should only happen on a lost context.
    return;
  }
  DCHECK_EQ(0u, uniform_blocks_.size());
  DCHECK_EQ(0u, active_uniform_block_max_name_length_);

  // |result| comes from GPU process. We consider it trusted data. Therefore,
  // no need to check for overflows as the GPU side did the checks already.
  uint32_t header_size = sizeof(UniformBlocksHeader);
  DCHECK_GE(result.size(), header_size);
  const UniformBlocksHeader* header = LocalGetAs<const UniformBlocksHeader*>(
      result, 0, header_size);
  DCHECK(header);
  if (header->num_uniform_blocks == 0) {
    DCHECK_EQ(result.size(), header_size);
    // TODO(zmo): Here we can't tell if no uniform blocks are defined, or
    // the previous link failed.
    return;
  }
  uniform_blocks_.resize(header->num_uniform_blocks);

  uint32_t entry_size = sizeof(UniformBlockInfo) * header->num_uniform_blocks;
  DCHECK_GE(result.size(), header_size + entry_size);
  uint32_t data_size = result.size() - header_size - entry_size;
  DCHECK_LT(0u, data_size);
  const UniformBlockInfo* entries = LocalGetAs<const UniformBlockInfo*>(
      result, header_size, entry_size);
  DCHECK(entries);
  const char* data = LocalGetAs<const char*>(
      result, header_size + entry_size, data_size);
  DCHECK(data);

  uint32_t size = 0;
  for (uint32_t ii = 0; ii < header->num_uniform_blocks; ++ii) {
    uniform_blocks_[ii].binding = static_cast<GLuint>(entries[ii].binding);
    uniform_blocks_[ii].data_size = static_cast<GLuint>(entries[ii].data_size);
    uniform_blocks_[ii].active_uniform_indices.resize(
        entries[ii].active_uniforms);
    uniform_blocks_[ii].referenced_by_vertex_shader = static_cast<GLboolean>(
        entries[ii].referenced_by_vertex_shader);
    uniform_blocks_[ii].referenced_by_fragment_shader = static_cast<GLboolean>(
        entries[ii].referenced_by_fragment_shader);
    // Uniform block names can't be empty strings.
    DCHECK_LT(1u, entries[ii].name_length);
    if (entries[ii].name_length > active_uniform_block_max_name_length_) {
      active_uniform_block_max_name_length_ = entries[ii].name_length;
    }
    size += entries[ii].name_length;
    DCHECK_GE(data_size, size);
    uniform_blocks_[ii].name = std::string(data, entries[ii].name_length - 1);
    data += entries[ii].name_length;
    size += entries[ii].active_uniforms * sizeof(uint32_t);
    DCHECK_GE(data_size, size);
    const uint32_t* indices = reinterpret_cast<const uint32_t*>(data);
    for (uint32_t uu = 0; uu < entries[ii].active_uniforms; ++uu) {
      uniform_blocks_[ii].active_uniform_indices[uu] =
          static_cast<GLuint>(indices[uu]);
    }
    indices += entries[ii].active_uniforms;
    data = reinterpret_cast<const char*>(indices);
  }
  DCHECK_EQ(data_size, size);
  cached_es3_uniform_blocks_ = true;
}

void ProgramInfoManager::Program::UpdateES3Uniformsiv(
    const std::vector<int8_t>& result) {
  if (cached_es3_uniformsiv_) {
    return;
  }
  if (result.empty()) {
    // This should only happen on a lost context.
    return;
  }
  DCHECK_EQ(0u, uniforms_es3_.size());

  // |result| comes from GPU process. We consider it trusted data. Therefore,
  // no need to check for overflows as the GPU side did the checks already.
  uint32_t header_size = sizeof(UniformsES3Header);
  DCHECK_GE(result.size(), header_size);
  const UniformsES3Header* header = LocalGetAs<const UniformsES3Header*>(
      result, 0, header_size);
  DCHECK(header);
  if (header->num_uniforms == 0) {
    DCHECK_EQ(result.size(), header_size);
    // TODO(zmo): Here we can't tell if no uniforms are defined, or
    // the previous link failed.
    return;
  }
  uniforms_es3_.resize(header->num_uniforms);

  uint32_t entry_size = sizeof(UniformES3Info) * header->num_uniforms;
  DCHECK_EQ(result.size(), header_size + entry_size);
  const UniformES3Info* entries = LocalGetAs<const UniformES3Info*>(
      result, header_size, entry_size);
  DCHECK(entries);

  for (uint32_t ii = 0; ii < header->num_uniforms; ++ii) {
    uniforms_es3_[ii].block_index = entries[ii].block_index;
    uniforms_es3_[ii].offset = entries[ii].offset;
    uniforms_es3_[ii].array_stride = entries[ii].array_stride;
    uniforms_es3_[ii].matrix_stride = entries[ii].matrix_stride;
    uniforms_es3_[ii].is_row_major = entries[ii].is_row_major;
  }
  cached_es3_uniformsiv_ = true;
}

void ProgramInfoManager::Program::UpdateES3TransformFeedbackVaryings(
    const std::vector<int8_t>& result) {
  if (cached_es3_transform_feedback_varyings_) {
    return;
  }
  if (result.empty()) {
    // This should only happen on a lost context.
    return;
  }
  DCHECK_EQ(0u, transform_feedback_buffer_mode_);
  DCHECK_EQ(0u, transform_feedback_varyings_.size());
  DCHECK_EQ(0u, transform_feedback_varying_max_length_);

  // |result| comes from GPU process. We consider it trusted data. Therefore,
  // no need to check for overflows as the GPU side did the checks already.
  uint32_t header_size = sizeof(TransformFeedbackVaryingsHeader);
  DCHECK_GE(result.size(), header_size);
  const TransformFeedbackVaryingsHeader* header =
      LocalGetAs<const TransformFeedbackVaryingsHeader*>(
          result, 0, header_size);
  DCHECK(header);
  if (header->num_transform_feedback_varyings == 0) {
    DCHECK_EQ(result.size(), header_size);
    // TODO(zmo): Here we can't tell if no TransformFeedback varyings are
    // defined, or the previous link failed.
    return;
  }
  transform_feedback_varyings_.resize(header->num_transform_feedback_varyings);
  transform_feedback_buffer_mode_ = header->transform_feedback_buffer_mode;

  uint32_t entry_size = sizeof(TransformFeedbackVaryingInfo) *
      header->num_transform_feedback_varyings;
  DCHECK_GE(result.size(), header_size + entry_size);
  uint32_t data_size = result.size() - header_size - entry_size;
  DCHECK_LT(0u, data_size);
  const TransformFeedbackVaryingInfo* entries =
      LocalGetAs<const TransformFeedbackVaryingInfo*>(
          result, header_size, entry_size);
  DCHECK(entries);
  const char* data = LocalGetAs<const char*>(
      result, header_size + entry_size, data_size);
  DCHECK(data);

  uint32_t size = 0;
  for (uint32_t ii = 0; ii < header->num_transform_feedback_varyings; ++ii) {
    transform_feedback_varyings_[ii].size =
        static_cast<GLsizei>(entries[ii].size);
    transform_feedback_varyings_[ii].type =
        static_cast<GLenum>(entries[ii].type);
    DCHECK_LE(1u, entries[ii].name_length);
    if (entries[ii].name_length > transform_feedback_varying_max_length_) {
      transform_feedback_varying_max_length_ = entries[ii].name_length;
    }
    size += entries[ii].name_length;
    DCHECK_GE(data_size, size);
    transform_feedback_varyings_[ii].name =
        std::string(data, entries[ii].name_length - 1);
    data += entries[ii].name_length;
  }
  DCHECK_EQ(data_size, size);
  cached_es3_transform_feedback_varyings_ = true;
}

bool ProgramInfoManager::Program::IsCached(ProgramInfoType type) const {
  switch (type) {
    case kES2:
      return cached_es2_;
    case kES3UniformBlocks:
      return cached_es3_uniform_blocks_;
    case kES3TransformFeedbackVaryings:
      return cached_es3_transform_feedback_varyings_;
    case kES3Uniformsiv:
      return cached_es3_uniformsiv_;
    case kNone:
      return true;
    default:
      NOTREACHED();
      return true;
  }
}

ProgramInfoManager::ProgramInfoManager() = default;

ProgramInfoManager::~ProgramInfoManager() = default;

ProgramInfoManager::Program* ProgramInfoManager::GetProgramInfo(
    GLES2Implementation* gl, GLuint program, ProgramInfoType type) {
  lock_.AssertAcquired();
  ProgramInfoMap::iterator it = program_infos_.find(program);
  if (it == program_infos_.end()) {
    return NULL;
  }
  Program* info = &it->second;
  if (info->IsCached(type))
    return info;

  std::vector<int8_t> result;
  switch (type) {
    case kES2:
      {
        base::AutoUnlock unlock(lock_);
        // lock_ can't be held across IPC call or else it may deadlock in
        // pepper. http://crbug.com/418651
        gl->GetProgramInfoCHROMIUMHelper(program, &result);
      }
      info->UpdateES2(result);
      break;
    case kES3UniformBlocks:
      {
        base::AutoUnlock unlock(lock_);
        // lock_ can't be held across IPC call or else it may deadlock in
        // pepper. http://crbug.com/418651
        gl->GetUniformBlocksCHROMIUMHelper(program, &result);
      }
      info->UpdateES3UniformBlocks(result);
      break;
    case kES3TransformFeedbackVaryings:
      {
        base::AutoUnlock unlock(lock_);
        // lock_ can't be held across IPC call or else it may deadlock in
        // pepper. http://crbug.com/418651
        gl->GetTransformFeedbackVaryingsCHROMIUMHelper(program, &result);
      }
      info->UpdateES3TransformFeedbackVaryings(result);
      break;
    case kES3Uniformsiv:
      {
        base::AutoUnlock unlock(lock_);
        // lock_ can't be held across IPC call or else it may deadlock in
        // pepper. http://crbug.com/418651
        gl->GetUniformsES3CHROMIUMHelper(program, &result);
      }
      info->UpdateES3Uniformsiv(result);
      break;
    default:
      NOTREACHED();
      return NULL;
  }
  return info;
}

void ProgramInfoManager::CreateInfo(GLuint program) {
  base::AutoLock auto_lock(lock_);
  program_infos_.erase(program);
  std::pair<ProgramInfoMap::iterator, bool> result =
      program_infos_.insert(std::make_pair(program, Program()));

  DCHECK(result.second);
}

void ProgramInfoManager::DeleteInfo(GLuint program) {
  base::AutoLock auto_lock(lock_);
  program_infos_.erase(program);
}

bool ProgramInfoManager::GetProgramiv(
    GLES2Implementation* gl, GLuint program, GLenum pname, GLint* params) {
  base::AutoLock auto_lock(lock_);
  ProgramInfoType type = kNone;
  switch (pname) {
    case GL_ACTIVE_ATTRIBUTES:
    case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
    case GL_ACTIVE_UNIFORMS:
    case GL_ACTIVE_UNIFORM_MAX_LENGTH:
    case GL_LINK_STATUS:
      type = kES2;
      break;
    case GL_ACTIVE_UNIFORM_BLOCKS:
    case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
      type = kES3UniformBlocks;
      break;
    case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
    case GL_TRANSFORM_FEEDBACK_VARYINGS:
    case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
      type = kES3TransformFeedbackVaryings;
      break;
    default:
      return false;
  }
  Program* info = GetProgramInfo(gl, program, type);
  if (!info) {
    return false;
  }
  return info->GetProgramiv(pname, params);
}

bool ProgramInfoManager::GetActiveUniformsiv(
    GLES2Implementation* gl, GLuint program, GLsizei count,
    const GLuint* indices, GLenum pname, GLint* params) {
  base::AutoLock auto_lock(lock_);
  ProgramInfoType type = kNone;
  switch (pname) {
    case GL_UNIFORM_SIZE:
    case GL_UNIFORM_TYPE:
    case GL_UNIFORM_NAME_LENGTH:
      type = kES2;
      break;
    case GL_UNIFORM_BLOCK_INDEX:
    case GL_UNIFORM_OFFSET:
    case GL_UNIFORM_ARRAY_STRIDE:
    case GL_UNIFORM_MATRIX_STRIDE:
    case GL_UNIFORM_IS_ROW_MAJOR:
      type = kES3Uniformsiv;
      break;
    default:
      break;
  }
  if (type != kNone) {
    Program* info = GetProgramInfo(gl, program, type);
    if (info) {
      return info->GetUniformsiv(count, indices, pname, params);
    }
  }
  return gl->GetActiveUniformsivHelper(program, count, indices, pname, params);
}

GLint ProgramInfoManager::GetAttribLocation(
    GLES2Implementation* gl, GLuint program, const char* name) {
  {
    base::AutoLock auto_lock(lock_);
    Program* info = GetProgramInfo(gl, program, kES2);
    if (info) {
      return info->GetAttribLocation(name);
    }
  }
  return gl->GetAttribLocationHelper(program, name);
}

GLint ProgramInfoManager::GetUniformLocation(
    GLES2Implementation* gl, GLuint program, const char* name) {
  {
    base::AutoLock auto_lock(lock_);
    Program* info = GetProgramInfo(gl, program, kES2);
    if (info) {
      return info->GetUniformLocation(name);
    }
  }
  return gl->GetUniformLocationHelper(program, name);
}

GLint ProgramInfoManager::GetFragDataIndex(GLES2Implementation* gl,
                                           GLuint program,
                                           const char* name) {
  // TODO(zmo): make FragData indexes part of the ProgramInfo that are
  // fetched from the service side.  See crbug.com/452104.
  {
    base::AutoLock auto_lock(lock_);
    Program* info = GetProgramInfo(gl, program, kNone);
    if (info) {
      GLint possible_index = info->GetFragDataIndex(name);
      if (possible_index != -1)
        return possible_index;
    }
  }
  GLint index = gl->GetFragDataIndexEXTHelper(program, name);
  if (index != -1) {
    base::AutoLock auto_lock(lock_);
    Program* info = GetProgramInfo(gl, program, kNone);
    if (info) {
      info->CacheFragDataIndex(name, index);
    }
  }
  return index;
}

GLint ProgramInfoManager::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, kNone);
    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, kNone);
    if (info) {
      info->CacheFragDataLocation(name, loc);
    }
  }
  return loc;
}

bool ProgramInfoManager::GetActiveAttrib(
    GLES2Implementation* gl,
    GLuint program, GLuint index, GLsizei bufsize, GLsizei* length,
    GLint* size, GLenum* type, char* name) {
  {
    base::AutoLock auto_lock(lock_);
    Program* info = GetProgramInfo(gl, program, kES2);
    if (info) {
      const Program::VertexAttrib* attrib_info = info->GetAttribInfo(index);
      if (attrib_info) {
        if (size) {
          *size = attrib_info->size;
        }
        if (type) {
          *type = attrib_info->type;
        }
        if (length || name) {
          GLsizei max_size = std::min(
              static_cast<size_t>(bufsize) - 1,
              std::max(static_cast<size_t>(0), attrib_info->name.size()));
          if (length) {
            *length = max_size;
          }
          if (name && bufsize > 0) {
            memcpy(name, attrib_info->name.c_str(), max_size);
            name[max_size] = '\0';
          }
        }
        return true;
      }
    }
  }
  return gl->GetActiveAttribHelper(
      program, index, bufsize, length, size, type, name);
}

bool ProgramInfoManager::GetActiveUniform(
    GLES2Implementation* gl,
    GLuint program, GLuint index, GLsizei bufsize, GLsizei* length,
    GLint* size, GLenum* type, char* name) {
  {
    base::AutoLock auto_lock(lock_);
    Program* info = GetProgramInfo(gl, program, kES2);
    if (info) {
      const Program::UniformInfo* uniform_info = info->GetUniformInfo(index);
      if (uniform_info) {
        if (size) {
          *size = uniform_info->size;
        }
        if (type) {
          *type = uniform_info->type;
        }
        if (length || name) {
          GLsizei max_size = std::min(
              static_cast<size_t>(bufsize) - 1,
              std::max(static_cast<size_t>(0), uniform_info->name.size()));
          if (length) {
            *length = max_size;
          }
          if (name && bufsize > 0) {
            memcpy(name, uniform_info->name.c_str(), max_size);
            name[max_size] = '\0';
          }
        }
        return true;
      }
    }
  }
  return gl->GetActiveUniformHelper(
      program, index, bufsize, length, size, type, name);
}

GLuint ProgramInfoManager::GetUniformBlockIndex(
    GLES2Implementation* gl, GLuint program, const char* name) {
  {
    base::AutoLock auto_lock(lock_);
    Program* info = GetProgramInfo(gl, program, kES3UniformBlocks);
    if (info) {
      return info->GetUniformBlockIndex(name);
    }
  }
  return gl->GetUniformBlockIndexHelper(program, name);
}

bool ProgramInfoManager::GetActiveUniformBlockName(
    GLES2Implementation* gl, GLuint program, GLuint index,
    GLsizei buf_size, GLsizei* length, char* name) {
  DCHECK_LE(0, buf_size);
  if (!name) {
    buf_size = 0;
  }
  {
    base::AutoLock auto_lock(lock_);
    Program* info = GetProgramInfo(gl, program, kES3UniformBlocks);
    if (info) {
      const Program::UniformBlock* uniform_block = info->GetUniformBlock(index);
      if (uniform_block) {
        if (buf_size == 0) {
          if (length) {
            *length = 0;
          }
        } else if (length || name) {
          GLsizei max_size = std::min(
              buf_size - 1, static_cast<GLsizei>(uniform_block->name.size()));
          if (length) {
            *length = max_size;
          }
          if (name) {
            memcpy(name, uniform_block->name.data(), max_size);
            name[max_size] = '\0';
          }
        }
        return true;
      }
    }
  }
  return gl->GetActiveUniformBlockNameHelper(
      program, index, buf_size, length, name);
}

bool ProgramInfoManager::GetActiveUniformBlockiv(
    GLES2Implementation* gl, GLuint program, GLuint index,
    GLenum pname, GLint* params) {
  {
    base::AutoLock auto_lock(lock_);
    Program* info = GetProgramInfo(gl, program, kES3UniformBlocks);
    if (info) {
      const Program::UniformBlock* uniform_block = info->GetUniformBlock(index);
      bool valid_pname;
      switch (pname) {
        case GL_UNIFORM_BLOCK_BINDING:
        case GL_UNIFORM_BLOCK_DATA_SIZE:
        case GL_UNIFORM_BLOCK_NAME_LENGTH:
        case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
        case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
        case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
        case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
          valid_pname = true;
          break;
        default:
          valid_pname = false;
          break;
      }
      if (uniform_block && valid_pname && params) {
        switch (pname) {
          case GL_UNIFORM_BLOCK_BINDING:
            *params = static_cast<GLint>(uniform_block->binding);
            break;
          case GL_UNIFORM_BLOCK_DATA_SIZE:
            *params = static_cast<GLint>(uniform_block->data_size);
            break;
          case GL_UNIFORM_BLOCK_NAME_LENGTH:
            *params = static_cast<GLint>(uniform_block->name.size()) + 1;
            break;
          case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
            *params = static_cast<GLint>(
                uniform_block->active_uniform_indices.size());
            break;
          case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
            for (size_t ii = 0;
                 ii < uniform_block->active_uniform_indices.size(); ++ii) {
              params[ii] = static_cast<GLint>(
                  uniform_block->active_uniform_indices[ii]);
            }
            break;
          case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
            *params = static_cast<GLint>(
                uniform_block->referenced_by_vertex_shader);
            break;
          case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
            *params = static_cast<GLint>(
                uniform_block->referenced_by_fragment_shader);
            break;
          default:
            NOTREACHED();
        }
        return true;
      }
    }
  }
  return gl->GetActiveUniformBlockivHelper(program, index, pname, params);
}

void ProgramInfoManager::UniformBlockBinding(
    GLES2Implementation* gl, GLuint program, GLuint index, GLuint binding) {
  GLuint max_bindings =
      static_cast<GLuint>(gl->capabilities().max_uniform_buffer_bindings);
  if (binding < max_bindings) {
    base::AutoLock auto_lock(lock_);
    // If UniformBlock info haven't been cached yet, skip updating the binding.
    Program* info = GetProgramInfo(gl, program, kNone);
    if (info) {
      info->UniformBlockBinding(index, binding);
    }
  }
}

bool ProgramInfoManager::GetTransformFeedbackVarying(
    GLES2Implementation* gl, GLuint program, GLuint index, GLsizei bufsize,
    GLsizei* length, GLsizei* size, GLenum* type, char* name) {
  {
    base::AutoLock auto_lock(lock_);
    Program* info = GetProgramInfo(gl, program, kES3TransformFeedbackVaryings);
    if (info) {
      const Program::TransformFeedbackVarying* varying =
          info->GetTransformFeedbackVarying(index);
      if (varying) {
        if (size) {
          *size = varying->size;
        }
        if (type) {
          *type = varying->type;
        }
        if (length || name) {
          GLsizei max_size = std::min(
              bufsize - 1, static_cast<GLsizei>(varying->name.size()));
          if (length) {
            *length = static_cast<GLsizei>(max_size);
          }
          if (name && bufsize > 0) {
            memcpy(name, varying->name.c_str(), max_size);
            name[max_size] = '\0';
          }
        }
        return true;
      }
    }
  }
  return gl->GetTransformFeedbackVaryingHelper(
      program, index, bufsize, length, size, type, name);
}

bool ProgramInfoManager::GetUniformIndices(GLES2Implementation* gl,
    GLuint program, GLsizei count, const char* const* names, GLuint* indices) {
  {
    base::AutoLock auto_lock(lock_);
    Program* info = GetProgramInfo(gl, program, kES2);
    if (info) {
      DCHECK_LT(0, count);
      DCHECK(names && indices);
      for (GLsizei ii = 0; ii < count; ++ii) {
        indices[ii] = info->GetUniformIndex(names[ii]);
      }
      return true;
    }
  }
  return gl->GetUniformIndicesHelper(program, count, names, indices);
}

}  // namespace gles2
}  // namespace gpu

