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

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

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

#include <string_view>

#include "base/compiler_specific.h"
#include "base/memory/raw_span.h"

namespace {

// Loads a value from type `T` from `data` at `offset`. The location need not be
// aligned for `T`.
template <typename T>
T Load(base::span<const int8_t> data, size_t offset) {
  auto subspan = data.subspan(offset, sizeof(T));
  T ret;
  UNSAFE_TODO(memcpy(&ret, subspan.data(), sizeof(T)));
  return ret;
}

std::string_view ToStringView(base::span<const int8_t> data) {
  return std::string_view(reinterpret_cast<const char*>(data.data()),
                          data.size());
}

// A convenience class to load a series of objects and spans.
class DataIterator {
 public:
  explicit DataIterator(base::span<const int8_t> data) : data_(data) {}

  bool empty() const { return data_.empty(); }

  // Consumes `n` bytes and returns them.
  base::span<const int8_t> GetBytes(size_t n) {
    base::span<const int8_t> ret = data_.first(n);
    data_ = data_.subspan(n);
    return ret;
  }

  // Consumes `sizeof(T)` bytes and interprets the result as a `T`.
  template <typename T>
  T Get() {
    return Load<T>(GetBytes(sizeof(T)), 0);
  }

 private:
  base::raw_span<const int8_t> data_;
};

// Writes the string pointed by name and of maximum size buffsize. If length is
// !null, it receives the number of characters written (excluding the final \0).
// This is a helper function for GetActive*Helper functions that return names.
void FillNameAndLength(GLsizei bufsize,
                       GLsizei* length,
                       char* name,
                       const std::string& string) {
  // Length of string (without final \0) that we will write to the
  // buffer.
  GLsizei max_length = 0;
  if (name && (bufsize > 0)) {
    DCHECK_LE(string.size(), static_cast<size_t>(INT_MAX));
    // Note: bufsize counts the terminating \0, but not string.size().
    max_length = std::min(bufsize - 1, static_cast<GLsizei>(string.size()));
    UNSAFE_TODO(memcpy(name, string.data(), max_length));
    UNSAFE_TODO(name[max_length]) = '\0';
  }
  if (length) {
    *length = max_length;
  }
}

}  // 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]
             : nullptr;
}

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

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

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 {
  std::unordered_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();
  }
}

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]
             : nullptr;
}

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 (UNSAFE_TODO(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) {
        UNSAFE_TODO(params[ii]) =
            static_cast<GLint>(uniform_infos_[UNSAFE_TODO(indices[ii])].size);
      }
      return true;
    case GL_UNIFORM_TYPE:
      DCHECK_EQ(num_uniforms, uniform_infos_.size());
      for (GLsizei ii = 0; ii < count; ++ii) {
        UNSAFE_TODO(params[ii]) =
            static_cast<GLint>(uniform_infos_[UNSAFE_TODO(indices[ii])].type);
      }
      return true;
    case GL_UNIFORM_NAME_LENGTH:
      DCHECK_EQ(num_uniforms, uniform_infos_.size());
      for (GLsizei ii = 0; ii < count; ++ii) {
        UNSAFE_TODO(params[ii]) = static_cast<GLint>(
            uniform_infos_[UNSAFE_TODO(indices[ii])].name.length() + 1);
      }
      return true;
  }
  if (num_uniforms != uniforms_es3_.size()) {
    return false;
  }
  switch (pname) {
    case GL_UNIFORM_BLOCK_INDEX:
      for (GLsizei ii = 0; ii < count; ++ii) {
        UNSAFE_TODO(params[ii]) =
            uniforms_es3_[UNSAFE_TODO(indices[ii])].block_index;
      }
      return true;
    case GL_UNIFORM_OFFSET:
      for (GLsizei ii = 0; ii < count; ++ii) {
        UNSAFE_TODO(params[ii]) =
            uniforms_es3_[UNSAFE_TODO(indices[ii])].offset;
      }
      return true;
    case GL_UNIFORM_ARRAY_STRIDE:
      for (GLsizei ii = 0; ii < count; ++ii) {
        UNSAFE_TODO(params[ii]) =
            uniforms_es3_[UNSAFE_TODO(indices[ii])].array_stride;
      }
      return true;
    case GL_UNIFORM_MATRIX_STRIDE:
      for (GLsizei ii = 0; ii < count; ++ii) {
        UNSAFE_TODO(params[ii]) =
            uniforms_es3_[UNSAFE_TODO(indices[ii])].matrix_stride;
      }
      return true;
    case GL_UNIFORM_IS_ROW_MAJOR:
      for (GLsizei ii = 0; ii < count; ++ii) {
        UNSAFE_TODO(params[ii]) =
            uniforms_es3_[UNSAFE_TODO(indices[ii])].is_row_major;
      }
      return true;
    default:
      NOTREACHED();
  }
}

void ProgramInfoManager::Program::UpdateES2(base::span<const int8_t> result) {
  if (cached_es2_) {
    return;
  }
  if (result.empty()) {
    // This should only happen on a lost context.
    return;
  }
  auto header = Load<ProgramInfoHeader>(result, 0);
  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_);
  DataIterator inputs(result.subspan(
      sizeof(header),
      sizeof(ProgramInput) * (header.num_attribs + header.num_uniforms)));
  for (uint32_t ii = 0; ii < header.num_attribs; ++ii) {
    auto input = inputs.Get<ProgramInput>();
    uint32_t location = Load<uint32_t>(result, input.location_offset);
    std::string name(
        ToStringView(result.subspan(input.name_offset, 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_);
  }
  for (uint32_t ii = 0; ii < header.num_uniforms; ++ii) {
    auto input = inputs.Get<ProgramInput>();
    DataIterator locations(
        result.subspan(input.location_offset, sizeof(int32_t) * input.size));
    std::string name(
        ToStringView(result.subspan(input.name_offset, 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.Get<uint32_t>());
    }
    uniform_infos_.push_back(info);
  }
  DCHECK(inputs.empty());
  cached_es2_ = true;
}

void ProgramInfoManager::Program::UpdateES3UniformBlocks(
    base::span<const 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);
  UniformBlocksHeader header = Load<UniformBlocksHeader>(result, 0);
  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);
  DataIterator entries(result.subspan(header_size, entry_size));
  DataIterator data(result.subspan(header_size + entry_size));

  for (uint32_t ii = 0; ii < header.num_uniform_blocks; ++ii) {
    auto entry = entries.Get<UniformBlockInfo>();
    uniform_blocks_[ii].binding = static_cast<GLuint>(entry.binding);
    uniform_blocks_[ii].data_size = static_cast<GLuint>(entry.data_size);
    uniform_blocks_[ii].active_uniform_indices.resize(entry.active_uniforms);
    uniform_blocks_[ii].referenced_by_vertex_shader =
        static_cast<GLboolean>(entry.referenced_by_vertex_shader);
    uniform_blocks_[ii].referenced_by_fragment_shader =
        static_cast<GLboolean>(entry.referenced_by_fragment_shader);
    // Uniform block names can't be empty strings.
    DCHECK_LT(1u, entry.name_length);
    if (entry.name_length > active_uniform_block_max_name_length_) {
      active_uniform_block_max_name_length_ = entry.name_length;
    }
    base::span<const int8_t> name = data.GetBytes(entry.name_length);
    uniform_blocks_[ii].name = ToStringView(name.first(entry.name_length - 1));
    for (uint32_t uu = 0; uu < entry.active_uniforms; ++uu) {
      uniform_blocks_[ii].active_uniform_indices[uu] =
          static_cast<GLuint>(data.Get<uint32_t>());
    }
  }
  DCHECK(data.empty());
  cached_es3_uniform_blocks_ = true;
}

void ProgramInfoManager::Program::UpdateES3Uniformsiv(
    base::span<const 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);
  auto header = Load<UniformsES3Header>(result, 0);
  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);
  DataIterator entries(result.subspan(header_size, entry_size));

  for (uint32_t ii = 0; ii < header.num_uniforms; ++ii) {
    auto entry = entries.Get<UniformES3Info>();
    uniforms_es3_[ii].block_index = entry.block_index;
    uniforms_es3_[ii].offset = entry.offset;
    uniforms_es3_[ii].array_stride = entry.array_stride;
    uniforms_es3_[ii].matrix_stride = entry.matrix_stride;
    uniforms_es3_[ii].is_row_major = entry.is_row_major;
  }
  DCHECK(entries.empty());
  cached_es3_uniformsiv_ = true;
}

void ProgramInfoManager::Program::UpdateES3TransformFeedbackVaryings(
    base::span<const 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);
  auto header = Load<TransformFeedbackVaryingsHeader>(result, 0);
  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;
  DataIterator entries(result.subspan(header_size, entry_size));
  DataIterator data(result.subspan(header_size + entry_size));

  for (uint32_t ii = 0; ii < header.num_transform_feedback_varyings; ++ii) {
    auto entry = entries.Get<TransformFeedbackVaryingInfo>();
    transform_feedback_varyings_[ii].size = static_cast<GLsizei>(entry.size);
    transform_feedback_varyings_[ii].type = static_cast<GLenum>(entry.type);
    DCHECK_LE(1u, entry.name_length);
    if (entry.name_length > transform_feedback_varying_max_length_) {
      transform_feedback_varying_max_length_ = entry.name_length;
    }
    base::span<const int8_t> name = data.GetBytes(entry.name_length);
    transform_feedback_varyings_[ii].name =
        ToStringView(name.first(entry.name_length - 1));
  }
  DCHECK(data.empty());
  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();
  }
}

ProgramInfoManager::ProgramInfoManager() = default;

ProgramInfoManager::~ProgramInfoManager() = default;

ProgramInfoManager::Program* ProgramInfoManager::GetProgramInfo(
    GLES2Implementation* gl,
    GLuint program,
    ProgramInfoType type) {
  ProgramInfoMap::iterator it = program_infos_.find(program);
  if (it == program_infos_.end()) {
    return nullptr;
  }
  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 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;
        }
        FillNameAndLength(bufsize, length, name, attrib_info->name);
        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;
        }
        FillNameAndLength(bufsize, length, name, uniform_info->name);
        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);
  {
    base::AutoLock auto_lock(lock_);
    Program* info = GetProgramInfo(gl, program, kES3UniformBlocks);
    if (info) {
      const Program::UniformBlock* uniform_block = info->GetUniformBlock(index);
      if (uniform_block) {
        FillNameAndLength(buf_size, length, name, uniform_block->name);
        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) {
              UNSAFE_TODO(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->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;
        }
        FillNameAndLength(bufsize, length, name, varying->name);
        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) {
        UNSAFE_TODO(indices[ii]) =
            info->GetUniformIndex(UNSAFE_TODO(names[ii]));
      }
      return true;
    }
  }
  return gl->GetUniformIndicesHelper(program, count, names, indices);
}

bool ProgramInfoManager::GetProgramInterfaceiv(
    GLES2Implementation* gl, GLuint program, GLenum program_interface,
    GLenum pname, GLint* params) {
  // TODO(jiajie.hu@intel.com): The info is not cached for now, so always
  // fallback to the IPC path.
  return false;
}

GLuint ProgramInfoManager::GetProgramResourceIndex(
    GLES2Implementation* gl, GLuint program, GLenum program_interface,
    const char* name) {
  // TODO(jiajie.hu@intel.com): The info is not cached for now, so always
  // fallback to the IPC path.
  return gl->GetProgramResourceIndexHelper(program, program_interface, name);
}

bool ProgramInfoManager::GetProgramResourceName(
    GLES2Implementation* gl, GLuint program, GLenum program_interface,
    GLuint index, GLsizei bufsize, GLsizei* length, char* name) {
  // TODO(jiajie.hu@intel.com): The info is not cached for now, so always
  // fallback to the IPC path.
  return gl->GetProgramResourceNameHelper(
      program, program_interface, index, bufsize, length, name);
}

bool ProgramInfoManager::GetProgramResourceiv(
    GLES2Implementation* gl, GLuint program, GLenum program_interface,
    GLuint index, GLsizei prop_count, const GLenum* props, GLsizei bufsize,
    GLsizei* length, GLint* params) {
  // TODO(jiajie.hu@intel.com): The info is not cached for now, so always
  // fallback to the IPC path.
  return gl->GetProgramResourceivHelper(
      program, program_interface, index, prop_count, props, bufsize, length,
      params);
}

GLint ProgramInfoManager::GetProgramResourceLocation(
    GLES2Implementation* gl, GLuint program, GLenum program_interface,
    const char* name) {
  // TODO(jiajie.hu@intel.com): The info is not cached for now, so always
  // fallback to the IPC path.
  return gl->GetProgramResourceLocationHelper(program, program_interface, name);
}

void ProgramInfoManager::UpdateProgramInfo(GLuint program,
                                           base::span<const int8_t> data,
                                           ProgramInfoType type) {
  base::AutoLock auto_lock(lock_);
  ProgramInfoMap::iterator it = program_infos_.find(program);
  // It's possible that the program has been deleted already. Imagine the code
  // snippet below:
  //   ...
  //   gl.linkProgram(program);
  //   gl.deleteProgram(program);
  //   ...
  if (it == program_infos_.end())
    return;
  Program* info = &it->second;
  switch (type) {
    case kES2:
      info->UpdateES2(data);
      break;
    case kES3UniformBlocks:
      info->UpdateES3UniformBlocks(data);
      break;
    case kES3TransformFeedbackVaryings:
      info->UpdateES3TransformFeedbackVaryings(data);
      break;
    case kES3Uniformsiv:
      info->UpdateES3Uniformsiv(data);
      break;
    default:
      NOTREACHED();
  }
}

}  // namespace gles2
}  // namespace gpu
