// 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 "gpu/command_buffer/service/program_manager.h"

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

#include <algorithm>
#include <limits>
#include <memory>
#include <set>
#include <utility>
#include <vector>

#include "base/command_line.h"
#include "base/containers/hash_tables.h"
#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
#include "base/numerics/safe_math.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/time/time.h"
#include "gpu/command_buffer/common/gles2_cmd_format.h"
#include "gpu/command_buffer/common/gles2_cmd_utils.h"
#include "gpu/command_buffer/service/decoder_context.h"
#include "gpu/command_buffer/service/feature_info.h"
#include "gpu/command_buffer/service/gpu_preferences.h"
#include "gpu/command_buffer/service/program_cache.h"
#include "gpu/command_buffer/service/progress_reporter.h"
#include "gpu/command_buffer/service/shader_manager.h"
#include "third_party/re2/src/re2/re2.h"
#include "ui/gl/gl_version_info.h"

using base::TimeDelta;
using base::TimeTicks;

namespace gpu {
namespace gles2 {

namespace {

int ShaderTypeToIndex(GLenum shader_type) {
  switch (shader_type) {
    case GL_VERTEX_SHADER:
      return 0;
    case GL_FRAGMENT_SHADER:
      return 1;
    default:
      NOTREACHED();
      return 0;
  }
}

// Given a name like "foo.bar[123].moo[456]" sets new_name to "foo.bar[123].moo"
// and sets element_index to 456. returns false if element expression was not a
// whole decimal number. For example: "foo[1b2]"
bool GetUniformNameSansElement(
    const std::string& name, int* element_index, std::string* new_name) {
  DCHECK(element_index);
  DCHECK(new_name);
  if (name.size() < 3 || name.back() != ']') {
    *element_index = 0;
    *new_name = name;
    return true;
  }

  // Look for an array specification.
  size_t open_pos = name.find_last_of('[');
  if (open_pos == std::string::npos ||
      open_pos >= name.size() - 2) {
    return false;
  }

  base::CheckedNumeric<GLint> index = 0;
  size_t last = name.size() - 1;
  for (size_t pos = open_pos + 1; pos < last; ++pos) {
    int8_t digit = name[pos] - '0';
    if (digit < 0 || digit > 9) {
      return false;
    }
    index = index * 10 + digit;
  }
  if (!index.IsValid()) {
    return false;
  }

  *element_index = index.ValueOrDie();
  *new_name = name.substr(0, open_pos);
  return true;
}

bool IsBuiltInFragmentVarying(const std::string& name) {
  // Built-in variables for fragment shaders.
  const char* kBuiltInVaryings[] = {
      "gl_FragCoord",
      "gl_FrontFacing",
      "gl_PointCoord"
  };
  for (size_t ii = 0; ii < arraysize(kBuiltInVaryings); ++ii) {
    if (name == kBuiltInVaryings[ii])
      return true;
  }
  return false;
}

bool IsBuiltInInvariant(
    const VaryingMap& varyings, const std::string& name) {
  VaryingMap::const_iterator hit = varyings.find(name);
  if (hit == varyings.end())
    return false;
  return hit->second.isInvariant;
}

uint32_t ComputeOffset(const void* start, const void* position) {
  return static_cast<const uint8_t*>(position) -
         static_cast<const uint8_t*>(start);
}

// This is used for vertex shader input variables and fragment shader output
// variables.
ShaderVariableBaseType InputOutputTypeToBaseType(bool is_input, GLenum type) {
  switch (type) {
    case GL_INT:
    case GL_INT_VEC2:
    case GL_INT_VEC3:
    case GL_INT_VEC4:
      return SHADER_VARIABLE_INT;
    case GL_UNSIGNED_INT:
    case GL_UNSIGNED_INT_VEC2:
    case GL_UNSIGNED_INT_VEC3:
    case GL_UNSIGNED_INT_VEC4:
      return SHADER_VARIABLE_UINT;
    case GL_FLOAT:
    case GL_FLOAT_VEC2:
    case GL_FLOAT_VEC3:
    case GL_FLOAT_VEC4:
      return SHADER_VARIABLE_FLOAT;
    case GL_FLOAT_MAT2:
    case GL_FLOAT_MAT3:
    case GL_FLOAT_MAT4:
    case GL_FLOAT_MAT2x3:
    case GL_FLOAT_MAT3x2:
    case GL_FLOAT_MAT2x4:
    case GL_FLOAT_MAT4x2:
    case GL_FLOAT_MAT3x4:
    case GL_FLOAT_MAT4x3:
      DCHECK(is_input);
      return SHADER_VARIABLE_FLOAT;
    default:
      NOTREACHED();
      return SHADER_VARIABLE_UNDEFINED_TYPE;
  }
}

GLsizeiptr VertexShaderOutputBaseTypeToSize(GLenum type) {
  switch (type) {
    case GL_INT:
      return 4;
    case GL_INT_VEC2:
      return 8;
    case GL_INT_VEC3:
      return 12;
    case GL_INT_VEC4:
      return 16;
    case GL_UNSIGNED_INT:
      return 4;
    case GL_UNSIGNED_INT_VEC2:
      return 8;
    case GL_UNSIGNED_INT_VEC3:
      return 12;
    case GL_UNSIGNED_INT_VEC4:
      return 16;
    case GL_FLOAT:
      return 4;
    case GL_FLOAT_VEC2:
      return 8;
    case GL_FLOAT_VEC3:
      return 12;
    case GL_FLOAT_VEC4:
      return 16;
    case GL_FLOAT_MAT2:
      return 16;
    case GL_FLOAT_MAT3:
      return 36;
    case GL_FLOAT_MAT4:
      return 64;
    case GL_FLOAT_MAT2x3:
      return 24;
    case GL_FLOAT_MAT3x2:
      return 24;
    case GL_FLOAT_MAT2x4:
      return 32;
    case GL_FLOAT_MAT4x2:
      return 32;
    case GL_FLOAT_MAT3x4:
      return 48;
    case GL_FLOAT_MAT4x3:
      return 48;
    default:
      NOTREACHED();
      return 0;
  }
}

GLsizeiptr VertexShaderOutputTypeToSize(const sh::Varying& varying) {
  base::CheckedNumeric<GLsizeiptr> total = 0;
  if (varying.fields.size()) {  // struct case.
    for (auto const& field : varying.fields) {
      // struct field for vertex shader outputs can only be basic types.
      GLsizeiptr size = VertexShaderOutputBaseTypeToSize(field.type);
      DCHECK(size);
      total += size;
    }
  } else {
    GLsizeiptr size = VertexShaderOutputBaseTypeToSize(varying.type);
    DCHECK(size);
    total = size;
    if (varying.isArray()) {  // array case.
      total *= varying.getOutermostArraySize();
    }
  }
  return total.ValueOrDefault(std::numeric_limits<GLsizeiptr>::max());
}

size_t LocationCountForAttribType(GLenum type) {
  switch (type) {
    case GL_FLOAT_MAT2:
    case GL_FLOAT_MAT2x3:
    case GL_FLOAT_MAT2x4:
      return 2;
    case GL_FLOAT_MAT3x2:
    case GL_FLOAT_MAT3:
    case GL_FLOAT_MAT3x4:
      return 3;
      break;
    case GL_FLOAT_MAT4x2:
    case GL_FLOAT_MAT4x3:
    case GL_FLOAT_MAT4:
      return 4;
    default:
      return 1;
  }
}

}  // anonymous namespace.

Program::UniformInfo::UniformInfo()
    : size(0),
      type(GL_NONE),
      accepts_api_type(0),
      fake_location_base(0),
      is_array(false) {}

Program::UniformInfo::UniformInfo(const std::string& client_name,
                                  int client_location_base,
                                  GLenum _type,
                                  bool _is_array,
                                  const std::vector<GLint>& service_locations)
    : size(service_locations.size()),
      type(_type),
      accepts_api_type(0),
      fake_location_base(client_location_base),
      is_array(_is_array),
      name(client_name),
      element_locations(service_locations) {
  switch (type) {
    case GL_INT:
      accepts_api_type = kUniform1i;
      break;
    case GL_INT_VEC2:
      accepts_api_type = kUniform2i;
      break;
    case GL_INT_VEC3:
      accepts_api_type = kUniform3i;
      break;
    case GL_INT_VEC4:
      accepts_api_type = kUniform4i;
      break;

    case GL_UNSIGNED_INT:
      accepts_api_type = kUniform1ui;
      break;
    case GL_UNSIGNED_INT_VEC2:
      accepts_api_type = kUniform2ui;
      break;
    case GL_UNSIGNED_INT_VEC3:
      accepts_api_type = kUniform3ui;
      break;
    case GL_UNSIGNED_INT_VEC4:
      accepts_api_type = kUniform4ui;
      break;

    case GL_BOOL:
      accepts_api_type = kUniform1i | kUniform1ui | kUniform1f;
      break;
    case GL_BOOL_VEC2:
      accepts_api_type = kUniform2i | kUniform2ui | kUniform2f;
      break;
    case GL_BOOL_VEC3:
      accepts_api_type = kUniform3i | kUniform3ui | kUniform3f;
      break;
    case GL_BOOL_VEC4:
      accepts_api_type = kUniform4i | kUniform4ui | kUniform4f;
      break;

    case GL_FLOAT:
      accepts_api_type = kUniform1f;
      break;
    case GL_FLOAT_VEC2:
      accepts_api_type = kUniform2f;
      break;
    case GL_FLOAT_VEC3:
      accepts_api_type = kUniform3f;
      break;
    case GL_FLOAT_VEC4:
      accepts_api_type = kUniform4f;
      break;

    case GL_FLOAT_MAT2:
      accepts_api_type = kUniformMatrix2f;
      break;
    case GL_FLOAT_MAT3:
      accepts_api_type = kUniformMatrix3f;
      break;
    case GL_FLOAT_MAT4:
      accepts_api_type = kUniformMatrix4f;
      break;

    case GL_FLOAT_MAT2x3:
      accepts_api_type = kUniformMatrix2x3f;
      break;
    case GL_FLOAT_MAT2x4:
      accepts_api_type = kUniformMatrix2x4f;
      break;
    case GL_FLOAT_MAT3x2:
      accepts_api_type = kUniformMatrix3x2f;
      break;
    case GL_FLOAT_MAT3x4:
      accepts_api_type = kUniformMatrix3x4f;
      break;
    case GL_FLOAT_MAT4x2:
      accepts_api_type = kUniformMatrix4x2f;
      break;
    case GL_FLOAT_MAT4x3:
      accepts_api_type = kUniformMatrix4x3f;
      break;

    case GL_SAMPLER_2D:
    case GL_SAMPLER_2D_RECT_ARB:
    case GL_SAMPLER_CUBE:
    case GL_SAMPLER_3D_OES:
    case GL_SAMPLER_EXTERNAL_OES:
    case GL_SAMPLER_2D_ARRAY:
    case GL_SAMPLER_2D_SHADOW:
    case GL_SAMPLER_2D_ARRAY_SHADOW:
    case GL_SAMPLER_CUBE_SHADOW:
    case GL_INT_SAMPLER_2D:
    case GL_INT_SAMPLER_3D:
    case GL_INT_SAMPLER_CUBE:
    case GL_INT_SAMPLER_2D_ARRAY:
    case GL_UNSIGNED_INT_SAMPLER_2D:
    case GL_UNSIGNED_INT_SAMPLER_3D:
    case GL_UNSIGNED_INT_SAMPLER_CUBE:
    case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
      accepts_api_type = kUniform1i;
      break;

    default:
      NOTREACHED() << "Unhandled UniformInfo type " << type;
      break;
  }
  DCHECK_LT(0, size);
  DCHECK(is_array || size == 1);

  size_t num_texture_units = IsSampler() ? static_cast<size_t>(size) : 0u;
  texture_units.clear();
  texture_units.resize(num_texture_units, 0);
}

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

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

bool ProgramManager::HasBuiltInPrefix(const std::string& name) {
  return name.length() >= 3 && name[0] == 'g' && name[1] == 'l' &&
         name[2] == '_';
}

Program::Program(ProgramManager* manager, GLuint service_id)
    : manager_(manager),
      use_count_(0),
      max_attrib_name_length_(0),
      max_uniform_name_length_(0),
      service_id_(service_id),
      deleted_(false),
      valid_(false),
      link_status_(false),
      uniforms_cleared_(false),
      transform_feedback_buffer_mode_(GL_NONE),
      effective_transform_feedback_buffer_mode_(GL_NONE),
      fragment_output_type_mask_(0u),
      fragment_output_written_mask_(0u) {
  DCHECK(manager_);
  manager_->StartTracking(this);
  uint32_t packed_size = (manager_->max_vertex_attribs() + 15) / 16;
  vertex_input_base_type_mask_.resize(packed_size);
  vertex_input_active_mask_.resize(packed_size);
  ClearVertexInputMasks();
}

void Program::Reset() {
  valid_ = false;
  link_status_ = false;
  max_uniform_name_length_ = 0;
  max_attrib_name_length_ = 0;
  attrib_infos_.clear();
  uniform_infos_.clear();
  uniform_locations_.clear();
  fragment_input_infos_.clear();
  fragment_input_locations_.clear();
  program_output_infos_.clear();
  sampler_indices_.clear();
  attrib_location_to_index_map_.clear();
  fragment_output_type_mask_ = 0u;
  fragment_output_written_mask_ = 0u;
  ClearVertexInputMasks();
}

void Program::ClearVertexInputMasks() {
  for (uint32_t ii = 0; ii < vertex_input_base_type_mask_.size(); ++ii) {
    vertex_input_base_type_mask_[ii] = 0u;
    vertex_input_active_mask_[ii] = 0u;
  }
}

void Program::UpdateFragmentOutputBaseTypes() {
  fragment_output_type_mask_ = 0u;
  fragment_output_written_mask_ = 0u;
  Shader* fragment_shader =
      shaders_from_last_successful_link_[ShaderTypeToIndex(GL_FRAGMENT_SHADER)]
          .get();
  DCHECK(fragment_shader);
  for (auto const& output : fragment_shader->output_variable_list()) {
    int location = output.location;
    DCHECK(location == -1 ||
           (location >= 0 &&
            location < static_cast<int>(manager_->max_draw_buffers())));
    if (location == -1)
      location = 0;
    if (ProgramManager::HasBuiltInPrefix(output.name)) {
      if (output.name != "gl_FragColor" && output.name != "gl_FragData")
        continue;
    }
    int count =
        static_cast<int>(output.isArray() ? output.getOutermostArraySize() : 1);
    // TODO(zmo): Handle the special case in ES2 where gl_FragColor could
    // be broadcasting to all draw buffers.
    DCHECK_LE(location + count,
              static_cast<int>(manager_->max_draw_buffers()));
    for (int ii = location; ii < location + count; ++ii) {
      // TODO(zmo): This does not work with glBindFragDataLocationIndexed.
      // crbug.com/628010
      // For example:
      //    glBindFragDataLocationIndexed(program, loc, 0, "FragData0");
      //    glBindFragDataLocationIndexed(program, loc, 1, "FragData1");
      // The program links OK, but both calling glGetFragDataLocation on both
      // "FragData0" and "FragData1" returns 0.
      int shift_bits = ii * 2;
      fragment_output_written_mask_ |= 0x3 << shift_bits;
      fragment_output_type_mask_ |=
          InputOutputTypeToBaseType(false, output.type) << shift_bits;
    }
  }
}

void Program::UpdateVertexInputBaseTypes() {
  ClearVertexInputMasks();
  for (size_t ii = 0; ii < attrib_infos_.size(); ++ii) {
    const VertexAttrib& input = attrib_infos_[ii];
    if (ProgramManager::HasBuiltInPrefix(input.name)) {
      continue;
    }

    DCHECK_LE(input.location + input.location_count,
              manager_->max_vertex_attribs());
    for (size_t location = input.location;
         location < input.location + input.location_count; ++location) {
      int shift_bits = (location % 16) * 2;
      vertex_input_active_mask_[location / 16] |= 0x3 << shift_bits;
      vertex_input_base_type_mask_[location / 16] |=
          InputOutputTypeToBaseType(true, input.type) << shift_bits;
    }
  }
}

void Program::UpdateUniformBlockSizeInfo() {
  if (feature_info().IsWebGL1OrES2Context()) {
    // Uniform blocks do not exist in ES2.
    return;
  }

  uniform_block_size_info_.clear();

  GLint num_uniform_blocks = 0;
  glGetProgramiv(service_id_, GL_ACTIVE_UNIFORM_BLOCKS, &num_uniform_blocks);
  uniform_block_size_info_.resize(num_uniform_blocks);
  for (GLint ii = 0; ii < num_uniform_blocks; ++ii) {
    GLint binding = 0;
    glGetActiveUniformBlockiv(
        service_id_, ii, GL_UNIFORM_BLOCK_BINDING, &binding);
    uniform_block_size_info_[ii].binding = static_cast<GLuint>(binding);

    GLint size = 0;
    glGetActiveUniformBlockiv(
        service_id_, ii, GL_UNIFORM_BLOCK_DATA_SIZE, &size);
    uniform_block_size_info_[ii].data_size = static_cast<GLuint>(size);
  }
}

void Program::SetUniformBlockBinding(GLuint index, GLuint binding) {
  DCHECK_GT(uniform_block_size_info_.size(), index);
  uniform_block_size_info_[index].binding = binding;
}

void Program::UpdateTransformFeedbackInfo() {
  effective_transform_feedback_buffer_mode_ = transform_feedback_buffer_mode_;
  effective_transform_feedback_varyings_ = transform_feedback_varyings_;

  Shader* vertex_shader = shaders_from_last_successful_link_[0].get();
  DCHECK(vertex_shader);

  if (effective_transform_feedback_buffer_mode_ == GL_INTERLEAVED_ATTRIBS) {
    transform_feedback_data_size_per_vertex_.resize(1);
  } else {
    transform_feedback_data_size_per_vertex_.resize(
        effective_transform_feedback_varyings_.size());
  }

  base::CheckedNumeric<GLsizeiptr> total = 0;
  for (size_t ii = 0; ii < effective_transform_feedback_varyings_.size();
       ++ii) {
    const std::string& client_name = effective_transform_feedback_varyings_[ii];
    const std::string* service_name =
        vertex_shader->GetVaryingMappedName(client_name);
    DCHECK(service_name);
    const sh::Varying* varying = vertex_shader->GetVaryingInfo(*service_name);
    DCHECK(varying);
    GLsizeiptr size = VertexShaderOutputTypeToSize(*varying);
    DCHECK(size);
    if (effective_transform_feedback_buffer_mode_ == GL_INTERLEAVED_ATTRIBS) {
      total += size;
    } else {
      transform_feedback_data_size_per_vertex_[ii] = size;
    }
  }
  if (effective_transform_feedback_buffer_mode_ == GL_INTERLEAVED_ATTRIBS) {
    transform_feedback_data_size_per_vertex_[0] =
        total.ValueOrDefault(std::numeric_limits<GLsizeiptr>::max());
  }
}

std::string Program::ProcessLogInfo(const std::string& log) {
  std::string output;
  re2::StringPiece input(log);
  std::string prior_log;
  std::string hashed_name;
  while (RE2::Consume(&input,
                      "(.*?)(webgl_[0123456789abcdefABCDEF]+)",
                      &prior_log,
                      &hashed_name)) {
    output += prior_log;

    const std::string* original_name =
        GetOriginalNameFromHashedName(hashed_name);
    if (original_name)
      output += *original_name;
    else
      output += hashed_name;
  }

  return output + input.as_string();
}

void Program::UpdateLogInfo() {
  GLint max_len = 0;
  glGetProgramiv(service_id_, GL_INFO_LOG_LENGTH, &max_len);
  if (max_len == 0) {
    set_log_info(nullptr);
    return;
  }
  std::unique_ptr<char[]> temp(new char[max_len]);
  GLint len = 0;
  glGetProgramInfoLog(service_id_, max_len, &len, temp.get());
  DCHECK(max_len == 0 || len < max_len);
  DCHECK(len == 0 || temp[len] == '\0');
  std::string log(temp.get(), len);
  log = ProcessLogInfo(log);
  set_log_info(log.empty() ? nullptr : log.c_str());
}

void Program::ClearUniforms(std::vector<uint8_t>* zero_buffer) {
  DCHECK(zero_buffer);
  if (uniforms_cleared_) {
    return;
  }
  uniforms_cleared_ = true;
  for (const UniformInfo& uniform_info : uniform_infos_) {
    GLint location = uniform_info.element_locations[0];
    GLsizei size = uniform_info.size;
    uint32_t unit_size =
        GLES2Util::GetElementCountForUniformType(uniform_info.type) *
        GLES2Util::GetElementSizeForUniformType(uniform_info.type);
    DCHECK_LT(0u, unit_size);
    uint32_t size_needed = size * unit_size;
    if (size_needed > zero_buffer->size()) {
      zero_buffer->resize(size_needed, 0u);
    }
    const void* zero = &(*zero_buffer)[0];
    switch (uniform_info.type) {
    case GL_FLOAT:
      glUniform1fv(location, size, reinterpret_cast<const GLfloat*>(zero));
      break;
    case GL_FLOAT_VEC2:
      glUniform2fv(location, size, reinterpret_cast<const GLfloat*>(zero));
      break;
    case GL_FLOAT_VEC3:
      glUniform3fv(location, size, reinterpret_cast<const GLfloat*>(zero));
      break;
    case GL_FLOAT_VEC4:
      glUniform4fv(location, size, reinterpret_cast<const GLfloat*>(zero));
      break;
    case GL_INT:
    case GL_BOOL:
    case GL_SAMPLER_2D:
    case GL_SAMPLER_CUBE:
    case GL_SAMPLER_EXTERNAL_OES:  // extension.
    case GL_SAMPLER_2D_RECT_ARB:  // extension.
      glUniform1iv(location, size, reinterpret_cast<const GLint*>(zero));
      break;
    case GL_INT_VEC2:
    case GL_BOOL_VEC2:
      glUniform2iv(location, size, reinterpret_cast<const GLint*>(zero));
      break;
    case GL_INT_VEC3:
    case GL_BOOL_VEC3:
      glUniform3iv(location, size, reinterpret_cast<const GLint*>(zero));
      break;
    case GL_INT_VEC4:
    case GL_BOOL_VEC4:
      glUniform4iv(location, size, reinterpret_cast<const GLint*>(zero));
      break;
    case GL_FLOAT_MAT2:
      glUniformMatrix2fv(
          location, size, false, reinterpret_cast<const GLfloat*>(zero));
      break;
    case GL_FLOAT_MAT3:
      glUniformMatrix3fv(
          location, size, false, reinterpret_cast<const GLfloat*>(zero));
      break;
    case GL_FLOAT_MAT4:
      glUniformMatrix4fv(
          location, size, false, reinterpret_cast<const GLfloat*>(zero));
      break;

    // ES3 types.
    case GL_UNSIGNED_INT:
      glUniform1uiv(location, size, reinterpret_cast<const GLuint*>(zero));
      break;
    case GL_SAMPLER_3D:
    case GL_SAMPLER_2D_SHADOW:
    case GL_SAMPLER_2D_ARRAY:
    case GL_SAMPLER_2D_ARRAY_SHADOW:
    case GL_SAMPLER_CUBE_SHADOW:
    case GL_INT_SAMPLER_2D:
    case GL_INT_SAMPLER_3D:
    case GL_INT_SAMPLER_CUBE:
    case GL_INT_SAMPLER_2D_ARRAY:
    case GL_UNSIGNED_INT_SAMPLER_2D:
    case GL_UNSIGNED_INT_SAMPLER_3D:
    case GL_UNSIGNED_INT_SAMPLER_CUBE:
    case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
      glUniform1iv(location, size, reinterpret_cast<const GLint*>(zero));
      break;
    case GL_UNSIGNED_INT_VEC2:
      glUniform2uiv(location, size, reinterpret_cast<const GLuint*>(zero));
      break;
    case GL_UNSIGNED_INT_VEC3:
      glUniform3uiv(location, size, reinterpret_cast<const GLuint*>(zero));
      break;
    case GL_UNSIGNED_INT_VEC4:
      glUniform4uiv(location, size, reinterpret_cast<const GLuint*>(zero));
      break;
    case GL_FLOAT_MAT2x3:
      glUniformMatrix2x3fv(
          location, size, false, reinterpret_cast<const GLfloat*>(zero));
      break;
    case GL_FLOAT_MAT3x2:
      glUniformMatrix3x2fv(
          location, size, false, reinterpret_cast<const GLfloat*>(zero));
      break;
    case GL_FLOAT_MAT2x4:
      glUniformMatrix2x4fv(
          location, size, false, reinterpret_cast<const GLfloat*>(zero));
      break;
    case GL_FLOAT_MAT4x2:
      glUniformMatrix4x2fv(
          location, size, false, reinterpret_cast<const GLfloat*>(zero));
      break;
    case GL_FLOAT_MAT3x4:
      glUniformMatrix3x4fv(
          location, size, false, reinterpret_cast<const GLfloat*>(zero));
      break;
    case GL_FLOAT_MAT4x3:
      glUniformMatrix4x3fv(
          location, size, false, reinterpret_cast<const GLfloat*>(zero));
      break;

    default:
      NOTREACHED();
      break;
    }
  }
}

void Program::Update() {
  Reset();
  UpdateLogInfo();
  link_status_ = true;
  uniforms_cleared_ = false;
  GLint num_attribs = 0;
  GLint max_len = 0;
  size_t num_locations = 0;
  glGetProgramiv(service_id_, GL_ACTIVE_ATTRIBUTES, &num_attribs);
  glGetProgramiv(service_id_, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &max_len);
  // TODO(gman): Should we check for error?
  std::unique_ptr<char[]> name_buffer(new char[max_len]);
  for (GLint ii = 0; ii < num_attribs; ++ii) {
    GLsizei length = 0;
    GLsizei size = 0;
    GLenum type = 0;
    glGetActiveAttrib(
        service_id_, ii, max_len, &length, &size, &type, name_buffer.get());
    DCHECK(max_len == 0 || length < max_len);
    DCHECK(length == 0 || name_buffer[length] == '\0');
    std::string original_name;
    GetVertexAttribData(name_buffer.get(), &original_name, &type);
    size_t location_count = size * LocationCountForAttribType(type);
    // TODO(gman): Should we check for error?
    GLint location = glGetAttribLocation(service_id_, name_buffer.get());
    num_locations = std::max(num_locations, location + location_count);
    attrib_infos_.push_back(
        VertexAttrib(1, type, original_name, location, location_count));
    max_attrib_name_length_ = std::max(
        max_attrib_name_length_, static_cast<GLsizei>(original_name.size()));
  }

  // Create attrib location to index map.
  attrib_location_to_index_map_.resize(num_locations, -1);
  for (size_t ii = 0; ii < attrib_infos_.size(); ++ii) {
    const VertexAttrib& info = attrib_infos_[ii];
    if (info.location < 0)
      continue;
    DCHECK_LE(info.location + info.location_count, num_locations);
    for (size_t j = 0; j < info.location_count; ++j)
      attrib_location_to_index_map_[info.location + j] = ii;
  }

  if (manager_->gpu_preferences_.enable_gpu_service_logging_gpu) {
    DVLOG(1) << "----: attribs for service_id: " << service_id();
    for (size_t ii = 0; ii < attrib_infos_.size(); ++ii) {
      const VertexAttrib& info = attrib_infos_[ii];
      DVLOG(1) << ii << ": loc = " << info.location
               << ", size = " << info.size
               << ", type = " << GLES2Util::GetStringEnum(info.type)
               << ", name = " << info.name;
    }
  }

  if (!UpdateUniforms())
    return;

  if (manager_->gpu_preferences_.enable_gpu_service_logging_gpu) {
    DVLOG(1) << "----: uniforms for service_id: " << service_id();
    size_t ii = 0;
    for (const UniformInfo& info : uniform_infos_) {
      DVLOG(1) << ii++ << ": loc = " << info.element_locations[0]
               << ", size = " << info.size
               << ", type = " << GLES2Util::GetStringEnum(info.type)
               << ", name = " << info.name;
    }
  }

  UpdateFragmentInputs();
  UpdateProgramOutputs();
  UpdateFragmentOutputBaseTypes();
  UpdateVertexInputBaseTypes();
  UpdateUniformBlockSizeInfo();
  UpdateTransformFeedbackInfo();

  valid_ = true;
}

bool Program::UpdateUniforms() {
  // Reserve each client-bound uniform location. This way unbound uniforms will
  // not be allocated to locations that user expects bound uniforms to be, even
  // if the expected uniforms are optimized away by the driver.
  for (const auto& binding : bind_uniform_location_map_) {
    if (binding.second < 0)
      continue;
    size_t client_location = static_cast<size_t>(binding.second);
    if (uniform_locations_.size() <= client_location)
      uniform_locations_.resize(client_location + 1);
    uniform_locations_[client_location].SetInactive();
  }

  GLint num_uniforms = 0;
  glGetProgramiv(service_id_, GL_ACTIVE_UNIFORMS, &num_uniforms);
  if (num_uniforms <= 0)
    return true;

  uniform_infos_.resize(num_uniforms);

  GLint name_buffer_length = 0;
  glGetProgramiv(service_id_, GL_ACTIVE_UNIFORM_MAX_LENGTH,
                 &name_buffer_length);
  DCHECK(name_buffer_length > 0);
  std::unique_ptr<char[]> name_buffer(new char[name_buffer_length]);

  size_t unused_client_location_cursor = 0;

  for (GLint uniform_index = 0; uniform_index < num_uniforms; ++uniform_index) {
    GLsizei name_length = 0;
    GLsizei size = 0;
    GLenum type = GL_NONE;
    glGetActiveUniform(service_id_, uniform_index, name_buffer_length,
                       &name_length, &size, &type, name_buffer.get());
    // Avoid immediately crashing if glGetActiveUniform misbehaves.
    if (!size)
      return false;
    DCHECK(name_length < name_buffer_length);
    DCHECK(name_length == 0 || name_buffer[name_length] == '\0');
    std::string service_name(name_buffer.get(), name_length);

    GLint service_location = -1;
    // Force builtin uniforms (gl_DepthRange) to have invalid location.
    if (!ProgramManager::HasBuiltInPrefix(service_name)) {
      service_location =
          glGetUniformLocation(service_id_, service_name.c_str());
    }

    // Determine the client name of the uniform and whether it is an array
    // or not.
    bool is_array = false;
    std::string client_name;
    for (size_t i = 0; i < kMaxAttachedShaders && client_name.empty(); ++i) {
      const auto& shader = shaders_from_last_successful_link_[i];
      if (!shader)
        continue;
      const sh::ShaderVariable* info = nullptr;
      const sh::Uniform* uniform = shader->GetUniformInfo(service_name);
      if (uniform &&
          uniform->findInfoByMappedName(service_name, &info, &client_name)) {
        DCHECK(!client_name.empty());
        is_array = info->isArray();
        type = info->type;
        size = std::max(1u, info->getOutermostArraySize());
      } else {
        const InterfaceBlockMap& interface_block_map =
            shader->interface_block_map();
        for (const auto& key_value : interface_block_map) {
          const sh::InterfaceBlock& block = key_value.second;
          bool find = false;
          if (block.instanceName.empty()) {
            for (const auto& value : block.fields) {
              if (value.findInfoByMappedName(service_name, &info,
                      &client_name)) {
                find = true;
                break;
              }
            }
          } else {
            size_t pos = service_name.find_first_of('.');
            std::string top_variable_name = service_name.substr(0, pos);
            if (block.mappedName == top_variable_name) {
              DCHECK(pos != std::string::npos);
              for (const auto& field : block.fields) {
                if (field.findInfoByMappedName(service_name.substr(
                    pos + 1), &info, &client_name)) {
                  find = true;
                  client_name = block.name + "." + client_name;
                  break;
                }
              }
            }
          }
          if (find) {
            DCHECK(!client_name.empty());
            is_array = info->isArray();
            type = info->type;
            size = std::max(1u, info->getOutermostArraySize());
            break;
          }
        }
      }
    }

    if (client_name.empty()) {
      // This happens only in cases where we do not have ANGLE or run unit tests
      // (or ANGLE has a severe bug).
      client_name = service_name;
      GLSLArrayName parsed_service_name(service_name);
      is_array = size > 1 || parsed_service_name.IsArrayName();
    }

    std::string service_base_name = service_name;
    std::string client_base_name = client_name;
    if (is_array) {
      // Some drivers incorrectly return an uniform name of size-1 array without
      // "[0]". In this case, we correct the service name by appending "[0]" to
      // it.
      GLSLArrayName parsed_service_name(service_name);
      if (parsed_service_name.IsArrayName()) {
        service_base_name = parsed_service_name.base_name();
        GLSLArrayName parsed_client_name(client_name);
        client_base_name = parsed_client_name.base_name();
      } else {
        service_name += "[0]";
        client_name += "[0]";
      }
    }

    // Assign a location for the uniform: use either client-bound
    // location or automatically assigned to an unused location.
    size_t client_location_base = 0;
    LocationMap::const_iterator it =
        bind_uniform_location_map_.find(client_base_name);
    if (it != bind_uniform_location_map_.end()) {
      client_location_base = it->second;
    } else {
      while (unused_client_location_cursor < uniform_locations_.size() &&
             !uniform_locations_[unused_client_location_cursor].IsUnused())
        unused_client_location_cursor++;
      if (unused_client_location_cursor == uniform_locations_.size())
        uniform_locations_.resize(unused_client_location_cursor + 1);
      client_location_base = unused_client_location_cursor;
      unused_client_location_cursor++;
    }

    // Populate the uniform list entry.
    std::vector<GLint> service_locations;
    service_locations.resize(size);
    service_locations[0] = service_location;

    if (size > 1) {
      for (GLsizei ii = 1; ii < size; ++ii) {
        std::string element_name(service_base_name + "[" +
                                 base::IntToString(ii) + "]");
        service_locations[ii] =
            glGetUniformLocation(service_id_, element_name.c_str());
      }
    }

    UniformInfo& info = uniform_infos_[uniform_index];
    info = UniformInfo(client_name, client_location_base, type, is_array,
                       service_locations);
    if (info.IsSampler()) {
      sampler_indices_.push_back(uniform_index);
    }

    // Populate the uniform location list entry.
    // Before linking, we already validated that no two statically used uniforms
    // are bound to the same location.
    DCHECK(!uniform_locations_[client_location_base].IsActive());
    uniform_locations_[client_location_base].SetActive(&info);

    max_uniform_name_length_ = std::max(max_uniform_name_length_,
                                        static_cast<GLsizei>(info.name.size()));
  }
  return true;
}

void Program::UpdateFragmentInputs() {
  if (!feature_info().feature_flags().chromium_path_rendering)
    return;
  for (const auto& binding : bind_fragment_input_location_map_) {
    if (binding.second < 0)
      continue;
    size_t client_location = static_cast<size_t>(binding.second);
    if (fragment_input_locations_.size() <= client_location)
      fragment_input_locations_.resize(client_location + 1);
    fragment_input_locations_[client_location].SetInactive();
  }

  GLint num_fragment_inputs = 0;
  glGetProgramInterfaceiv(service_id_, GL_FRAGMENT_INPUT_NV,
                          GL_ACTIVE_RESOURCES, &num_fragment_inputs);
  if (num_fragment_inputs <= 0)
    return;

  GLint max_len = 0;
  glGetProgramInterfaceiv(service_id_, GL_FRAGMENT_INPUT_NV, GL_MAX_NAME_LENGTH,
                          &max_len);
  DCHECK(max_len > 0);

  std::unique_ptr<char[]> name_buffer(new char[max_len]);

  Shader* fragment_shader =
      shaders_from_last_successful_link_[ShaderTypeToIndex(GL_FRAGMENT_SHADER)]
          .get();

  const GLenum kQueryProperties[] = {GL_LOCATION, GL_TYPE, GL_ARRAY_SIZE};

  std::vector<size_t> client_location_indices;
  for (GLint ii = 0; ii < num_fragment_inputs; ++ii) {
    GLsizei name_length = 0;
    glGetProgramResourceName(service_id_, GL_FRAGMENT_INPUT_NV, ii, max_len,
                             &name_length, name_buffer.get());
    DCHECK(name_length < max_len);
    DCHECK(name_length == 0 || name_buffer[name_length] == '\0');
    // A fragment shader can have gl_FragCoord, gl_FrontFacing or gl_PointCoord
    // built-ins as its input, as well as custom varyings. We are interested in
    // custom varyings, client is allowed to bind only them.
    std::string service_name(name_buffer.get(), name_length);
    if (ProgramManager::HasBuiltInPrefix(service_name))
      continue;
    // Unlike when binding uniforms, we expect the driver to give correct
    // names: "name" for simple variable, "name[0]" for an array.
    GLsizei query_length = 0;
    GLint query_results[arraysize(kQueryProperties)] = {
        0,
    };
    glGetProgramResourceiv(service_id_, GL_FRAGMENT_INPUT_NV, ii,
                           arraysize(kQueryProperties), kQueryProperties,
                           arraysize(query_results), &query_length,
                           query_results);
    DCHECK(query_length == arraysize(kQueryProperties));

    GLenum type = static_cast<GLenum>(query_results[1]);
    GLsizei size = static_cast<GLsizei>(query_results[2]);
    std::string client_name;

    const sh::Varying* varying = fragment_shader->GetVaryingInfo(service_name);
    const sh::ShaderVariable* info = nullptr;
    if (varying &&
        varying->findInfoByMappedName(service_name, &info, &client_name)) {
      type = info->type;
      size = std::max(1u, info->getOutermostArraySize());
    } else {
      // Should only happen if there are major bugs in the driver, ANGLE or if
      // the shader translator is disabled.
      DCHECK(feature_info().disable_shader_translator());
      client_name = service_name;
      if (size <= 0)
        continue;
    }

    auto it = bind_fragment_input_location_map_.find(client_name);
    if (it != bind_fragment_input_location_map_.end() && it->second >= 0 &&
        query_results[0] >= 0) {
      size_t client_location = static_cast<size_t>(it->second);
      GLuint service_location = static_cast<GLuint>(query_results[0]);
      fragment_input_infos_.push_back(
          FragmentInputInfo(type, service_location));
      client_location_indices.push_back(client_location);
    }

    if (size <= 1)
      continue;
    GLSLArrayName parsed_client_name(client_name);
    GLSLArrayName parsed_service_name(service_name);
    if (!parsed_client_name.IsArrayName() ||
        parsed_client_name.element_index() != 0 ||
        !parsed_service_name.IsArrayName() ||
        parsed_service_name.element_index() != 0) {
      NOTREACHED() << "GLSL array variable names should end with \"[0]\". "
                      "Likely driver or ANGLE error.";
      continue;
    }

    for (GLsizei jj = 1; jj < size; ++jj) {
      std::string array_spec(std::string("[") + base::IntToString(jj) + "]");
      std::string client_element_name =
          parsed_client_name.base_name() + array_spec;

      auto it = bind_fragment_input_location_map_.find(client_element_name);
      if (it != bind_fragment_input_location_map_.end() && it->second >= 0) {
        size_t client_location = static_cast<size_t>(it->second);
        std::string service_element_name =
            parsed_service_name.base_name() + array_spec;
        GLint service_location = glGetProgramResourceLocation(
            service_id_, GL_FRAGMENT_INPUT_NV, service_element_name.c_str());
        if (service_location >= 0) {
          fragment_input_infos_.push_back(
              FragmentInputInfo(type, static_cast<GLuint>(service_location)));
          client_location_indices.push_back(client_location);
        }
      }
    }
  }
  for (size_t i = 0; i < client_location_indices.size(); ++i) {
    size_t client_location = client_location_indices[i];
    // Before linking, we already validated that no two statically used fragment
    // inputs are bound to the same location.
    DCHECK(!fragment_input_locations_[client_location].IsActive());
    fragment_input_locations_[client_location].SetActive(
        &fragment_input_infos_[i]);
  }
}

void Program::UpdateProgramOutputs() {
  if (!feature_info().gl_version_info().is_es3_capable ||
      feature_info().disable_shader_translator())
    return;

  Shader* fragment_shader =
      shaders_from_last_successful_link_[ShaderTypeToIndex(GL_FRAGMENT_SHADER)]
          .get();

  for (auto const& output_var : fragment_shader->output_variable_list()) {
    const std::string& service_name = output_var.mappedName;
    // A fragment shader can have gl_FragColor, gl_SecondaryFragColor, etc
    // built-ins as its output, as well as custom varyings. We are interested
    // only in custom varyings, client is allowed to bind only them.
    if (ProgramManager::HasBuiltInPrefix(service_name))
      continue;

    std::string client_name = output_var.name;
    if (!output_var.isArray()) {
      GLint color_name =
          glGetFragDataLocation(service_id_, service_name.c_str());
      if (color_name < 0)
        continue;
      GLint index = 0;
      if (feature_info().feature_flags().ext_blend_func_extended)
        index = glGetFragDataIndex(service_id_, service_name.c_str());
      if (index < 0)
        continue;
      program_output_infos_.push_back(
          ProgramOutputInfo(color_name, index, client_name));
    } else if (feature_info().workarounds().get_frag_data_info_bug) {
      DCHECK(!feature_info().feature_flags().ext_blend_func_extended);
      GLint color_name =
          glGetFragDataLocation(service_id_, service_name.c_str());
      if (color_name >= 0) {
        GLint index = 0;
        for (size_t ii = 0; ii < output_var.getOutermostArraySize(); ++ii) {
          std::string array_spec(
              std::string("[") + base::IntToString(ii) + "]");
          program_output_infos_.push_back(ProgramOutputInfo(
              color_name + ii, index, client_name + array_spec));
        }
      }
    } else {
      for (size_t ii = 0; ii < output_var.getOutermostArraySize(); ++ii) {
        std::string array_spec(std::string("[") + base::IntToString(ii) + "]");
        std::string service_element_name(service_name + array_spec);
        GLint color_name =
            glGetFragDataLocation(service_id_, service_element_name.c_str());
        if (color_name < 0)
          continue;
        GLint index = 0;
        if (feature_info().feature_flags().ext_blend_func_extended)
          index = glGetFragDataIndex(service_id_, service_element_name.c_str());
        if (index < 0)
          continue;
        program_output_infos_.push_back(
            ProgramOutputInfo(color_name, index, client_name + array_spec));
      }
    }
  }
}

void Program::ExecuteBindAttribLocationCalls() {
  for (const auto& key_value : bind_attrib_location_map_) {
    const std::string* mapped_name = GetAttribMappedName(key_value.first);
    if (mapped_name)
      glBindAttribLocation(service_id_, key_value.second, mapped_name->c_str());
  }
}

bool Program::ExecuteTransformFeedbackVaryingsCall() {
  if (!transform_feedback_varyings_.empty()) {
    // This is called before program linking, so refer to attached_shaders_.
    Shader* vertex_shader = attached_shaders_[0].get();
    if (!vertex_shader) {
      set_log_info("TransformFeedbackVaryings: missing vertex shader");
      return false;
    }

    std::vector<const char*> mapped_names;
    mapped_names.reserve(transform_feedback_varyings_.size());
    for (StringVector::const_iterator it =
             transform_feedback_varyings_.begin();
         it != transform_feedback_varyings_.end(); ++it) {
      const std::string& orig = *it;
      const std::string* mapped = vertex_shader->GetVaryingMappedName(orig);
      if (!mapped) {
        std::string log = "TransformFeedbackVaryings: no varying named " + orig;
        set_log_info(log.c_str());
        return false;
      }
      mapped_names.push_back(mapped->c_str());
    }
    glTransformFeedbackVaryings(service_id_,
                                mapped_names.size(),
                                &mapped_names.front(),
                                transform_feedback_buffer_mode_);
  }

  return true;
}

void Program::ExecuteProgramOutputBindCalls() {
  if (feature_info().disable_shader_translator()) {
    return;
  }

  // This is called before program linking, so refer to attached_shaders_.
  Shader* fragment_shader =
      attached_shaders_[ShaderTypeToIndex(GL_FRAGMENT_SHADER)].get();
  DCHECK(fragment_shader && fragment_shader->valid());

  if (fragment_shader->shader_version() != 100) {
    // ES SL 1.00 does not have mechanism for introducing variables that could
    // be bound. This means that ES SL 1.00 binding calls would be to
    // non-existing variable names.  Binding calls are only executed with ES SL
    // 3.00 and higher.
    for (auto const& output_var : fragment_shader->output_variable_list()) {
      size_t count = std::max(output_var.getOutermostArraySize(), 1u);
      bool is_array = output_var.isArray();

      for (size_t jj = 0; jj < count; ++jj) {
        std::string name = output_var.name;
        std::string array_spec;
        if (is_array) {
          array_spec = std::string("[") + base::IntToString(jj) + "]";
          name += array_spec;
        }
        auto it = bind_program_output_location_index_map_.find(name);
        if (it == bind_program_output_location_index_map_.end())
          continue;

        std::string mapped_name = output_var.mappedName;
        if (is_array) {
          mapped_name += array_spec;
        }
        const auto& binding = it->second;
        if (binding.second == 0) {
          // Handles the cases where client called glBindFragDataLocation as
          // well as glBindFragDataLocationIndexed with index == 0.
          glBindFragDataLocation(service_id_, binding.first,
                                 mapped_name.c_str());
        } else {
          DCHECK(feature_info().feature_flags().ext_blend_func_extended);
          glBindFragDataLocationIndexed(service_id_, binding.first,
                                        binding.second, mapped_name.c_str());
        }
      }
    }
    return;
  }

  // Support for EXT_blend_func_extended when used with ES SL 1.00 client
  // shader.

  if (feature_info().gl_version_info().is_es ||
      !feature_info().feature_flags().ext_blend_func_extended)
    return;

  // The underlying context does not support EXT_blend_func_extended
  // natively, need to emulate it.

  // ES SL 1.00 is the only language which contains GLSL built-ins
  // that need to be bound to color indices. If clients use other
  // languages, they also bind the output variables themselves.
  // Map gl_SecondaryFragColorEXT / gl_SecondaryFragDataEXT of
  // EXT_blend_func_extended to real color indexes.
  for (auto const& output_var : fragment_shader->output_variable_list()) {
    const std::string& name = output_var.mappedName;
    if (name == "gl_FragColor") {
      DCHECK_EQ(-1, output_var.location);
      DCHECK_EQ(false, output_var.isArray());
      // We leave these unbound by not giving a binding name. The driver will
      // bind this.
    } else if (name == "gl_FragData") {
      DCHECK_EQ(-1, output_var.location);
      DCHECK_NE(0u, output_var.getOutermostArraySize());
      // We leave these unbound by not giving a binding name. The driver will
      // bind this.
    } else if (name == "gl_SecondaryFragColorEXT") {
      DCHECK_EQ(-1, output_var.location);
      DCHECK_EQ(false, output_var.isArray());
      glBindFragDataLocationIndexed(service_id_, 0, 1,
                                    "angle_SecondaryFragColor");
    } else if (name == "gl_SecondaryFragDataEXT") {
      DCHECK_EQ(-1, output_var.location);
      DCHECK_NE(0u, output_var.getOutermostArraySize());
      glBindFragDataLocationIndexed(service_id_, 0, 1,
                                    "angle_SecondaryFragData");
    }
  }
}

bool Program::Link(ShaderManager* manager,
                   Program::VaryingsPackingOption varyings_packing_option,
                   DecoderClient* client) {
  ClearLinkStatus();

  if (!AttachedShadersExist()) {
    set_log_info("missing shaders");
    return false;
  }

  TimeTicks before_time = TimeTicks::Now();
  bool link = true;
  ProgramCache* cache = manager_->program_cache_;
  // This is called before program linking, so refer to attached_shaders_.
  if (cache &&
      !attached_shaders_[0]->last_compiled_source().empty() &&
      !attached_shaders_[1]->last_compiled_source().empty()) {
    ProgramCache::LinkedProgramStatus status = cache->GetLinkedProgramStatus(
        attached_shaders_[0]->last_compiled_signature(),
        attached_shaders_[1]->last_compiled_signature(),
        &bind_attrib_location_map_,
        transform_feedback_varyings_,
        transform_feedback_buffer_mode_);

    bool cache_hit = status == ProgramCache::LINK_SUCCEEDED;
    UMA_HISTOGRAM_BOOLEAN("GPU.ProgramCache.CacheHit", cache_hit);

    if (cache_hit) {
      ProgramCache::ProgramLoadResult success = cache->LoadLinkedProgram(
          service_id(), attached_shaders_[0].get(), attached_shaders_[1].get(),
          &bind_attrib_location_map_, transform_feedback_varyings_,
          transform_feedback_buffer_mode_, client);
      link = success != ProgramCache::PROGRAM_LOAD_SUCCESS;
      UMA_HISTOGRAM_BOOLEAN("GPU.ProgramCache.LoadBinarySuccess", !link);
    }
  }

  if (link) {
    CompileAttachedShaders();

    if (!CanLink()) {
      set_log_info("invalid shaders");
      return false;
    }
    if (DetectShaderVersionMismatch()) {
      set_log_info("Versions of linked shaders have to match.");
      return false;
    }
    if (DetectAttribLocationBindingConflicts()) {
      set_log_info("glBindAttribLocation() conflicts");
      return false;
    }
    std::string conflicting_name;
    if (DetectUniformsMismatch(&conflicting_name)) {
      std::string info_log = "Uniforms with the same name but different "
                             "type/precision: " + conflicting_name;
      set_log_info(ProcessLogInfo(info_log).c_str());
      return false;
    }
    if (DetectUniformLocationBindingConflicts()) {
      set_log_info("glBindUniformLocationCHROMIUM() conflicts");
      return false;
    }
    if (DetectInterfaceBlocksMismatch(&conflicting_name)) {
      std::string info_log =
          "Interface blocks with the same name but different"
          " fields/layout: " +
          conflicting_name;
      set_log_info(ProcessLogInfo(info_log).c_str());
      return false;
    }
    if (DetectVaryingsMismatch(&conflicting_name)) {
      std::string info_log = "Varyings with the same name but different type, "
                             "or statically used varyings in fragment shader "
                             "are not declared in vertex shader: " +
                             conflicting_name;
      set_log_info(ProcessLogInfo(info_log).c_str());
      return false;
    }
    if (DetectFragmentInputLocationBindingConflicts()) {
      set_log_info("glBindFragmentInputLocationCHROMIUM() conflicts");
      return false;
    }
    if (DetectProgramOutputLocationBindingConflicts()) {
      set_log_info("glBindFragDataLocation() conflicts");
      return false;
    }
    if (DetectBuiltInInvariantConflicts()) {
      set_log_info("Invariant settings for certain built-in varyings "
                   "have to match");
      return false;
    }
    if (DetectGlobalNameConflicts(&conflicting_name)) {
      std::string info_log = "Name conflicts between an uniform and an "
                             "attribute: " + conflicting_name;
      set_log_info(ProcessLogInfo(info_log).c_str());
      return false;
    }
    if (!CheckVaryingsPacking(varyings_packing_option)) {
      set_log_info("Varyings over maximum register limit");
      return false;
    }

    ExecuteBindAttribLocationCalls();
    if (!ExecuteTransformFeedbackVaryingsCall()) {
      return false;
    }

    ExecuteProgramOutputBindCalls();

    if (cache && gl::g_current_gl_driver->ext.b_GL_ARB_get_program_binary) {
      glProgramParameteri(service_id(),
                          PROGRAM_BINARY_RETRIEVABLE_HINT,
                          GL_TRUE);
    }
    glLinkProgram(service_id());
  }

  GLint success = 0;
  glGetProgramiv(service_id(), GL_LINK_STATUS, &success);
  if (success == GL_TRUE) {
    for (size_t ii = 0; ii < kMaxAttachedShaders; ++ii)
      shaders_from_last_successful_link_[ii] = attached_shaders_[ii];
    Update();
    if (link) {
      // Here it makes no difference because attached_shaders_ and
      // shaders_from_last_successful_link_ are still the same.
      // ANGLE updates the translated shader sources on link.
      for (auto shader : attached_shaders_) {
        shader->RefreshTranslatedShaderSource();
      }
      if (cache) {
        cache->SaveLinkedProgram(
            service_id(), attached_shaders_[0].get(),
            attached_shaders_[1].get(), &bind_attrib_location_map_,
            effective_transform_feedback_varyings_,
            effective_transform_feedback_buffer_mode_, client);
      }
      UMA_HISTOGRAM_CUSTOM_COUNTS(
          "GPU.ProgramCache.BinaryCacheMissTime",
          static_cast<base::HistogramBase::Sample>(
              (TimeTicks::Now() - before_time).InMicroseconds()),
          1,
          static_cast<base::HistogramBase::Sample>(
              TimeDelta::FromSeconds(10).InMicroseconds()),
          50);
    } else {
      UMA_HISTOGRAM_CUSTOM_COUNTS(
          "GPU.ProgramCache.BinaryCacheHitTime",
          static_cast<base::HistogramBase::Sample>(
              (TimeTicks::Now() - before_time).InMicroseconds()),
          1,
          static_cast<base::HistogramBase::Sample>(
              TimeDelta::FromSeconds(1).InMicroseconds()),
          50);
    }
  } else {
    UpdateLogInfo();
  }
  return success == GL_TRUE;
}

void Program::Validate() {
  if (!IsValid()) {
    set_log_info("program not linked");
    return;
  }
  glValidateProgram(service_id());
  UpdateLogInfo();
}

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

  for (const UniformInfo& info : uniform_infos_) {
    if (info.name == name ||
        (info.is_array &&
         info.name.compare(0, info.name.size() - 3, name) == 0)) {
      return info.fake_location_base;
    } 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) {
          DCHECK_GT(static_cast<int>(info.element_locations.size()), index);
          if (info.element_locations[index] == -1)
            return -1;
          return ProgramManager::MakeFakeLocation(
              info.fake_location_base, index);
        }
      }
    }
  }
  return -1;
}

GLint Program::GetAttribLocation(
    const std::string& original_name) const {
  for (GLuint ii = 0; ii < attrib_infos_.size(); ++ii) {
    const VertexAttrib& info = attrib_infos_[ii];
    if (info.name == original_name) {
      return info.location;
    }
  }
  return -1;
}

const Program::UniformInfo*
    Program::GetUniformInfoByFakeLocation(
        GLint fake_location, GLint* real_location, GLint* array_index) const {
  DCHECK(real_location);
  DCHECK(array_index);
  if (fake_location < 0)
    return nullptr;
  size_t location_index =
      GetUniformLocationIndexFromFakeLocation(fake_location);
  if (location_index >= uniform_locations_.size())
    return nullptr;

  if (!uniform_locations_[location_index].IsActive())
    return nullptr;

  const UniformInfo* info =
      uniform_locations_[location_index].shader_variable();
  size_t element_index = GetArrayElementIndexFromFakeLocation(fake_location);
  if (static_cast<GLsizei>(element_index) >= info->size)
    return nullptr;
  *real_location = info->element_locations[element_index];
  *array_index = element_index;
  return info;
}

bool Program::IsInactiveUniformLocationByFakeLocation(
    GLint fake_location) const {
  if (fake_location < 0)
    return true;
  size_t location_index =
      GetUniformLocationIndexFromFakeLocation(fake_location);
  if (location_index >= uniform_locations_.size())
    return false;
  return uniform_locations_[location_index].IsInactive();
}

const std::string* Program::GetAttribMappedName(
    const std::string& original_name) const {
  // This is called by DetectAttribLocationBindingConflicts() and
  // ExecuteBindAttribLocationCalls(). Both are called before program linking,
  // so refer to attached_shaders_.
  for (auto shader : attached_shaders_) {
    if (shader) {
      const std::string* mapped_name =
          shader->GetAttribMappedName(original_name);
      if (mapped_name)
        return mapped_name;
    }
  }
  return nullptr;
}

const std::string* Program::GetUniformMappedName(
    const std::string& original_name) const {
  // This is called by DetectUniformLocationBindingConflicts(), which is called
  // before program linking, so refer to attached_shaders_.
  for (auto shader : attached_shaders_) {
    if (shader) {
      const std::string* mapped_name =
          shader->GetUniformMappedName(original_name);
      if (mapped_name)
        return mapped_name;
    }
  }
  return nullptr;
}

const std::string* Program::GetOriginalNameFromHashedName(
    const std::string& hashed_name) const {
  // This is called by ProcessLogInfo(), which could in turn be called by
  // UpdateLogInfo(). All these cases are either before program linking, or
  // right after program linking and shader attachments haven't been changed,
  // so refer to attached_shaders_.
  // TODO(zmo): The only exception is for Validate(), for which
  // shaders_from_last_successful_link_ should be used. This is minor issue
  // though, leading to log information from ValidateProgram() could end up
  // with hashed variable names.
  for (auto shader : attached_shaders_) {
    if (shader) {
      const std::string* original_name =
          shader->GetOriginalNameFromHashedName(hashed_name);
      if (original_name)
        return original_name;
    }
  }
  return nullptr;
}

const sh::Varying* Program::GetVaryingInfo(
    const std::string& hashed_name) const {
  for (auto shader : shaders_from_last_successful_link_) {
    if (shader) {
      const sh::Varying* info = shader->GetVaryingInfo(hashed_name);
      if (info)
        return info;
    }
  }
  return nullptr;
}

const sh::InterfaceBlock* Program::GetInterfaceBlockInfo(
    const std::string& hashed_name) const {
  for (auto shader : shaders_from_last_successful_link_) {
    if (shader) {
      const sh::InterfaceBlock* info =
          shader->GetInterfaceBlockInfo(hashed_name);
      if (info)
        return info;
    }
  }
  return nullptr;
}

const Program::FragmentInputInfo* Program::GetFragmentInputInfoByFakeLocation(
    GLint fake_location) const {
  if (fake_location < 0)
    return nullptr;
  size_t location_index = static_cast<size_t>(fake_location);
  if (location_index >= fragment_input_locations_.size())
    return nullptr;
  if (!fragment_input_locations_[location_index].IsActive())
    return nullptr;
  return fragment_input_locations_[location_index].shader_variable();
}

bool Program::IsInactiveFragmentInputLocationByFakeLocation(
    GLint fake_location) const {
  if (fake_location < 0)
    return true;
  size_t location_index = static_cast<size_t>(fake_location);
  if (location_index >= fragment_input_locations_.size())
    return false;
  return fragment_input_locations_[location_index].IsInactive();
}

bool Program::SetUniformLocationBinding(
    const std::string& name, GLint location) {
  std::string short_name;
  int element_index = 0;
  if (!GetUniformNameSansElement(name, &element_index, &short_name) ||
      element_index != 0) {
    return false;
  }
  bind_uniform_location_map_[short_name] = location;
  return true;
}

void Program::SetFragmentInputLocationBinding(const std::string& name,
                                              GLint location) {
  // The client wants to bind either "name" or "name[0]".
  // GL ES 3.1 spec refers to active array names with language such as:
  // "if the string identifies the base name of an active array, where the
  // string would exactly match the name of the variable if the suffix "[0]"
  // were appended to the string".

  // At this point we can not know if the string identifies a simple variable,
  // a base name of an array, or nothing.  Store both, so if user overwrites
  // either, both still work correctly.
  bind_fragment_input_location_map_[name] = location;
  bind_fragment_input_location_map_[name + "[0]"] = location;
}

void Program::SetProgramOutputLocationBinding(const std::string& name,
                                              GLuint color_name) {
  SetProgramOutputLocationIndexedBinding(name, color_name, 0);
}

void Program::SetProgramOutputLocationIndexedBinding(const std::string& name,
                                                     GLuint color_name,
                                                     GLuint index) {
  bind_program_output_location_index_map_[name] =
      std::make_pair(color_name, index);
  bind_program_output_location_index_map_[name + "[0]"] =
      std::make_pair(color_name, index);
}

void Program::GetVertexAttribData(
    const std::string& name, std::string* original_name, GLenum* type) const {
  DCHECK(original_name);
  DCHECK(type);
  Shader* shader =
      shaders_from_last_successful_link_[ShaderTypeToIndex(GL_VERTEX_SHADER)]
          .get();
  if (shader) {
    // Vertex attributes can not be arrays or structs (GLSL ES 3.00.4, section
    // 4.3.4, "Input Variables"), so the top level sh::Attribute returns the
    // information we need.
    const sh::Attribute* info = shader->GetAttribInfo(name);
    if (info) {
      *original_name = info->name;
      *type = info->type;
      return;
    }
  }
  // TODO(zmo): this path should never be reached unless there is a serious
  // bug in the driver or in ANGLE translator.
  *original_name = name;
}

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

bool Program::SetSamplers(
    GLint num_texture_units, GLint fake_location,
    GLsizei count, const GLint* value) {
  // The caller has checked that the location is active and valid.
  DCHECK(fake_location >= 0);
  size_t location_index =
      GetUniformLocationIndexFromFakeLocation(fake_location);
  DCHECK(location_index < uniform_locations_.size());
  DCHECK(uniform_locations_[location_index].IsActive());

  UniformInfo* info = uniform_locations_[location_index].shader_variable();

  size_t element_index = GetArrayElementIndexFromFakeLocation(fake_location);
  if (static_cast<GLsizei>(element_index) >= info->size)
    return true;
  count = std::min(info->size - static_cast<GLsizei>(element_index), count);
  if (info->IsSampler() && count > 0) {
    for (GLsizei ii = 0; ii < count; ++ii) {
      if (value[ii] < 0 || value[ii] >= num_texture_units) {
        return false;
      }
    }
    std::copy(value, value + count,
              info->texture_units.begin() + element_index);
    return true;
  }
  return true;
}

void Program::GetProgramiv(GLenum pname, GLint* params) {
  switch (pname) {
    case GL_ACTIVE_ATTRIBUTES:
      *params = attrib_infos_.size();
      break;
    case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
      // Notice +1 to accomodate NULL terminator.
      *params = max_attrib_name_length_ + 1;
      break;
    case GL_ACTIVE_UNIFORMS:
      *params = uniform_infos_.size();
      break;
    case GL_ACTIVE_UNIFORM_MAX_LENGTH:
      // Notice +1 to accomodate NULL terminator.
      *params = max_uniform_name_length_ + 1;
      break;
    case GL_LINK_STATUS:
      *params = link_status_;
      break;
    case GL_INFO_LOG_LENGTH:
      // Notice +1 to accomodate NULL terminator.
      *params = log_info_.get() ? (log_info_->size() + 1) : 0;
      break;
    case GL_DELETE_STATUS:
      *params = deleted_;
      break;
    case GL_VALIDATE_STATUS:
      if (!IsValid()) {
        *params = GL_FALSE;
      } else {
        glGetProgramiv(service_id_, pname, params);
      }
      break;
    default:
      glGetProgramiv(service_id_, pname, params);
      break;
  }
}

bool Program::AttachShader(
    ShaderManager* shader_manager,
    Shader* shader) {
  DCHECK(shader_manager);
  DCHECK(shader);
  int index = ShaderTypeToIndex(shader->shader_type());
  if (attached_shaders_[index].get() != NULL) {
    return false;
  }
  attached_shaders_[index] = scoped_refptr<Shader>(shader);
  shader_manager->UseShader(shader);
  return true;
}

bool Program::IsShaderAttached(Shader* shader) {
  return attached_shaders_[ShaderTypeToIndex(shader->shader_type())].get() ==
         shader;
}

void Program::DetachShader(
    ShaderManager* shader_manager,
    Shader* shader) {
  DCHECK(shader_manager);
  DCHECK(shader);
  DCHECK(IsShaderAttached(shader));
  attached_shaders_[ShaderTypeToIndex(shader->shader_type())] = NULL;
  shader_manager->UnuseShader(shader);
}

void Program::DetachShaders(ShaderManager* shader_manager) {
  DCHECK(shader_manager);
  for (auto shader : attached_shaders_) {
    if (shader) {
      DetachShader(shader_manager, shader.get());
    }
  }
}

void Program::CompileAttachedShaders() {
  for (auto shader : attached_shaders_) {
    if (shader) {
      shader->DoCompile();
    }
  }
}

bool Program::AttachedShadersExist() const {
  for (auto shader : attached_shaders_) {
    if (!shader)
      return false;
  }
  return true;
}

bool Program::CanLink() const {
  for (auto shader : attached_shaders_) {
    if (!shader || !shader->valid()) {
      return false;
    }
  }
  return true;
}

bool Program::DetectShaderVersionMismatch() const {
  int version = Shader::kUndefinedShaderVersion;
  // This is called before program linking, so refer to attached_shaders_.
  for (auto shader : attached_shaders_) {
    if (shader) {
      if (version != Shader::kUndefinedShaderVersion &&
          shader->shader_version() != version) {
        return true;
      }
      version = shader->shader_version();
      DCHECK(version != Shader::kUndefinedShaderVersion);
    }
  }
  return false;
}

bool Program::DetectAttribLocationBindingConflicts() const {
  std::set<GLint> location_binding_used;
  for (const auto& key_value : bind_attrib_location_map_) {
    // Find out if an attribute is statically used in this program's shaders.
    const sh::Attribute* attrib = NULL;
    const std::string* mapped_name = GetAttribMappedName(key_value.first);
    if (!mapped_name)
      continue;
    for (auto shader : attached_shaders_) {
      if (!shader || !shader->valid())
        continue;
      attrib = shader->GetAttribInfo(*mapped_name);
      if (attrib) {
        if (attrib->staticUse)
          break;
        else
          attrib = NULL;
      }
    }
    if (attrib) {
      size_t num_of_locations = LocationCountForAttribType(attrib->type);
      for (size_t ii = 0; ii < num_of_locations; ++ii) {
        GLint loc = key_value.second + ii;
        auto result = location_binding_used.insert(loc);
        if (!result.second)
          return true;
      }
    }
  }
  return false;
}

bool Program::DetectUniformLocationBindingConflicts() const {
  std::set<GLint> location_binding_used;
  for (auto it : bind_uniform_location_map_) {
    // Find out if an attribute is statically used in this program's shaders.
    const sh::Uniform* uniform = nullptr;
    const std::string* mapped_name = GetUniformMappedName(it.first);
    if (!mapped_name)
      continue;
    for (auto shader : attached_shaders_) {
      if (!shader || !shader->valid())
        continue;
      uniform = shader->GetUniformInfo(*mapped_name);
      if (uniform) {
        if (uniform->staticUse)
          break;
        else
          uniform = nullptr;
      }
    }
    if (uniform) {
      auto result = location_binding_used.insert(it.second);
      if (!result.second)
        return true;
    }
  }
  return false;
}

bool Program::DetectUniformsMismatch(std::string* conflicting_name) const {
  typedef std::map<std::string, const sh::Uniform*> UniformPointerMap;
  UniformPointerMap uniform_pointer_map;
  for (auto shader : attached_shaders_) {
    const UniformMap& shader_uniforms = shader->uniform_map();
    for (const auto& key_value : shader_uniforms) {
      const std::string& name = key_value.first;
      UniformPointerMap::iterator hit = uniform_pointer_map.find(name);
      if (hit == uniform_pointer_map.end()) {
        uniform_pointer_map[name] = &(key_value.second);
      } else {
        // If a uniform is in the map, i.e., it has already been declared by
        // another shader, then the type, precision, etc. must match.
        if (hit->second->isSameUniformAtLinkTime(key_value.second))
          continue;
        *conflicting_name = name;
        return true;
      }
    }
  }
  return false;
}

bool Program::DetectInterfaceBlocksMismatch(
    std::string* conflicting_name) const {
  std::map<std::string, const sh::InterfaceBlock*> interface_pointer_map;
  for (auto shader : attached_shaders_) {
    const InterfaceBlockMap& shader_interfaces = shader->interface_block_map();
    for (const auto& it : shader_interfaces) {
      const auto& name = it.first;
      auto hit = interface_pointer_map.find(name);
      if (hit == interface_pointer_map.end()) {
        interface_pointer_map[name] = &(it.second);
      } else {
        // If an interface is in the map, i.e., it has already been declared by
        // another shader, then the layout must match.
        if (hit->second->isSameInterfaceBlockAtLinkTime(it.second))
          continue;
        *conflicting_name = name;
        return true;
      }
    }
  }
  return false;
}

bool Program::DetectVaryingsMismatch(std::string* conflicting_name) const {
  DCHECK(attached_shaders_[0].get() &&
         attached_shaders_[0]->shader_type() == GL_VERTEX_SHADER &&
         attached_shaders_[1].get() &&
         attached_shaders_[1]->shader_type() == GL_FRAGMENT_SHADER);
  const VaryingMap* vertex_varyings = &(attached_shaders_[0]->varying_map());
  const VaryingMap* fragment_varyings = &(attached_shaders_[1]->varying_map());

  int shader_version = attached_shaders_[0]->shader_version();

  for (const auto& key_value : *fragment_varyings) {
    const std::string& name = key_value.first;
    if (IsBuiltInFragmentVarying(name))
      continue;

    VaryingMap::const_iterator hit = vertex_varyings->find(name);
    if (hit == vertex_varyings->end()) {
      if (key_value.second.staticUse) {
        *conflicting_name = name;
        return true;
      }
      continue;
    }

    if (!hit->second.isSameVaryingAtLinkTime(key_value.second,
                                             shader_version)) {
      *conflicting_name = name;
      return true;
    }
  }
  return false;
}

bool Program::DetectFragmentInputLocationBindingConflicts() const {
  auto* shader = attached_shaders_[ShaderTypeToIndex(GL_FRAGMENT_SHADER)].get();
  if (!shader || !shader->valid())
    return false;

  std::set<GLint> location_binding_used;
  for (auto it : bind_fragment_input_location_map_) {
    // Find out if an fragment input is statically used in this program's
    // shaders.
    const std::string* mapped_name = shader->GetVaryingMappedName(it.first);
    if (!mapped_name)
      continue;
    const sh::Varying* fragment_input = shader->GetVaryingInfo(*mapped_name);
    if (fragment_input && fragment_input->staticUse) {
      auto result = location_binding_used.insert(it.second);
      if (!result.second)
        return true;
    }
  }
  return false;
}

bool Program::DetectProgramOutputLocationBindingConflicts() const {
  if (feature_info().disable_shader_translator()) {
    return false;
  }

  Shader* shader =
      attached_shaders_[ShaderTypeToIndex(GL_FRAGMENT_SHADER)].get();
  DCHECK(shader && shader->valid());

  if (shader->shader_version() == 100)
    return false;

  std::set<LocationIndexMap::mapped_type> location_binding_used;
  for (auto const& output_var : shader->output_variable_list()) {
    if (!output_var.staticUse)
      continue;

    size_t count = std::max(output_var.getOutermostArraySize(), 1u);
    bool is_array = output_var.isArray();

    for (size_t jj = 0; jj < count; ++jj) {
      std::string name = output_var.name;
      if (is_array)
        name += std::string("[") + base::IntToString(jj) + "]";

      auto it = bind_program_output_location_index_map_.find(name);
      if (it == bind_program_output_location_index_map_.end())
        continue;
      auto result = location_binding_used.insert(it->second);
      if (!result.second)
        return true;
    }
  }
  return false;
}

bool Program::DetectBuiltInInvariantConflicts() const {
  DCHECK(attached_shaders_[0].get() &&
         attached_shaders_[0]->shader_type() == GL_VERTEX_SHADER &&
         attached_shaders_[1].get() &&
         attached_shaders_[1]->shader_type() == GL_FRAGMENT_SHADER);
  const VaryingMap& vertex_varyings = attached_shaders_[0]->varying_map();
  const VaryingMap& fragment_varyings = attached_shaders_[1]->varying_map();

  bool gl_position_invariant = IsBuiltInInvariant(
      vertex_varyings, "gl_Position");
  bool gl_point_size_invariant = IsBuiltInInvariant(
      vertex_varyings, "gl_PointSize");

  bool gl_frag_coord_invariant = IsBuiltInInvariant(
      fragment_varyings, "gl_FragCoord");
  bool gl_point_coord_invariant = IsBuiltInInvariant(
      fragment_varyings, "gl_PointCoord");

  return ((gl_frag_coord_invariant && !gl_position_invariant) ||
          (gl_point_coord_invariant && !gl_point_size_invariant));
}

bool Program::DetectGlobalNameConflicts(std::string* conflicting_name) const {
  DCHECK(attached_shaders_[0].get() &&
         attached_shaders_[0]->shader_type() == GL_VERTEX_SHADER &&
         attached_shaders_[1].get() &&
         attached_shaders_[1]->shader_type() == GL_FRAGMENT_SHADER);
  const UniformMap* uniforms[2];
  uniforms[0] = &(attached_shaders_[0]->uniform_map());
  uniforms[1] = &(attached_shaders_[1]->uniform_map());
  const AttributeMap* attribs =
      &(attached_shaders_[0]->attrib_map());

  for (const auto& key_value : *attribs) {
    for (int ii = 0; ii < 2; ++ii) {
      if (uniforms[ii]->find(key_value.first) != uniforms[ii]->end()) {
        *conflicting_name = key_value.first;
        return true;
      }
    }
  }
  return false;
}

bool Program::CheckVaryingsPacking(
    Program::VaryingsPackingOption option) const {
  DCHECK(attached_shaders_[0].get() &&
         attached_shaders_[0]->shader_type() == GL_VERTEX_SHADER &&
         attached_shaders_[1].get() &&
         attached_shaders_[1]->shader_type() == GL_FRAGMENT_SHADER);
  const VaryingMap* vertex_varyings = &(attached_shaders_[0]->varying_map());
  const VaryingMap* fragment_varyings = &(attached_shaders_[1]->varying_map());

  std::map<std::string, const sh::ShaderVariable*> combined_map;

  for (const auto& key_value : *fragment_varyings) {
    if (!key_value.second.staticUse && option == kCountOnlyStaticallyUsed)
      continue;
    if (!IsBuiltInFragmentVarying(key_value.first)) {
      VaryingMap::const_iterator vertex_iter =
          vertex_varyings->find(key_value.first);
      if (vertex_iter == vertex_varyings->end() ||
          (!vertex_iter->second.staticUse &&
           option == kCountOnlyStaticallyUsed))
        continue;
    }

    combined_map[key_value.first] = &key_value.second;
  }

  if (combined_map.size() == 0)
    return true;
  std::vector<sh::ShaderVariable> variables;
  for (const auto& key_value : combined_map) {
    variables.push_back(*key_value.second);
  }
  return sh::CheckVariablesWithinPackingLimits(
      static_cast<int>(manager_->max_varying_vectors()), variables);
}

void Program::GetProgramInfo(
    ProgramManager* manager, CommonDecoder::Bucket* bucket) const {
  // NOTE: It seems to me the math in here does not need check for overflow
  // because the data being calucated from has various small limits. The max
  // number of attribs + uniforms is somewhere well under 1024. The maximum size
  // of an identifier is 256 characters.
  uint32_t num_locations = 0;
  uint32_t total_string_size = 0;

  for (size_t ii = 0; ii < attrib_infos_.size(); ++ii) {
    const VertexAttrib& info = attrib_infos_[ii];
    num_locations += 1;
    total_string_size += info.name.size();
  }

  for (const UniformInfo& info : uniform_infos_) {
    num_locations += info.element_locations.size();
    total_string_size += info.name.size();
  }

  uint32_t num_inputs = attrib_infos_.size() + uniform_infos_.size();
  uint32_t input_size = num_inputs * sizeof(ProgramInput);
  uint32_t location_size = num_locations * sizeof(int32_t);
  uint32_t size = sizeof(ProgramInfoHeader) + input_size + location_size +
                  total_string_size;

  bucket->SetSize(size);
  ProgramInfoHeader* header = bucket->GetDataAs<ProgramInfoHeader*>(0, size);
  ProgramInput* inputs = bucket->GetDataAs<ProgramInput*>(
      sizeof(ProgramInfoHeader), input_size);
  int32_t* locations = bucket->GetDataAs<int32_t*>(
      sizeof(ProgramInfoHeader) + input_size, location_size);
  char* strings = bucket->GetDataAs<char*>(
      sizeof(ProgramInfoHeader) + input_size + location_size,
      total_string_size);
  DCHECK(header);
  DCHECK(inputs);
  DCHECK(locations);
  DCHECK(strings);

  header->link_status = link_status_;
  header->num_attribs = attrib_infos_.size();
  header->num_uniforms = uniform_infos_.size();

  for (size_t ii = 0; ii < attrib_infos_.size(); ++ii) {
    const VertexAttrib& info = attrib_infos_[ii];
    inputs->size = info.size;
    inputs->type = info.type;
    inputs->location_offset = ComputeOffset(header, locations);
    inputs->name_offset = ComputeOffset(header, strings);
    inputs->name_length = info.name.size();
    *locations++ = info.location;
    memcpy(strings, info.name.c_str(), info.name.size());
    strings += info.name.size();
    ++inputs;
  }

  for (const UniformInfo& info : uniform_infos_) {
    inputs->size = info.size;
    inputs->type = info.type;
    inputs->location_offset = ComputeOffset(header, locations);
    inputs->name_offset = ComputeOffset(header, strings);
    inputs->name_length = info.name.size();
    DCHECK(static_cast<size_t>(info.size) == info.element_locations.size());
    for (size_t jj = 0; jj < info.element_locations.size(); ++jj) {
      if (info.element_locations[jj] == -1)
        *locations++ = -1;
      else
        *locations++ =
            ProgramManager::MakeFakeLocation(info.fake_location_base, jj);
    }
    memcpy(strings, info.name.c_str(), info.name.size());
    strings += info.name.size();
    ++inputs;
  }
  // NOTE: currently we do not pass inactive uniform binding locations
  // through the program info call.

  // NOTE: currently we do not pass fragment input infos through the program
  // info call, because they are not exposed through any getter function.

  DCHECK_EQ(ComputeOffset(header, strings), size);
}

bool Program::GetUniformBlocks(CommonDecoder::Bucket* bucket) const {
  // The data is packed into the bucket in the following order
  //   1) header
  //   2) N entries of block data (except for name and indices)
  //   3) name1, indices1, name2, indices2, ..., nameN, indicesN
  //
  // We query all the data directly through GL calls, assuming they are
  // cheap through MANGLE.

  DCHECK(bucket);
  GLuint program = service_id();

  uint32_t header_size = sizeof(UniformBlocksHeader);
  bucket->SetSize(header_size);  // In case we fail.

  uint32_t num_uniform_blocks = 0;
  GLint param = GL_FALSE;
  // We assume program is a valid program service id.
  glGetProgramiv(program, GL_LINK_STATUS, &param);
  if (param == GL_TRUE) {
    param = 0;
    glGetProgramiv(program, GL_ACTIVE_UNIFORM_BLOCKS, &param);
    num_uniform_blocks = static_cast<uint32_t>(param);
  }
  if (num_uniform_blocks == 0) {
    // Although spec allows an implementation to return uniform block info
    // even if a link fails, for consistency, we disallow that.
    return true;
  }

  std::vector<UniformBlockInfo> blocks(num_uniform_blocks);
  base::CheckedNumeric<uint32_t> size = sizeof(UniformBlockInfo);
  size *= num_uniform_blocks;
  uint32_t entry_size = size.ValueOrDefault(0);
  size += header_size;
  std::vector<std::string> names(num_uniform_blocks);
  GLint max_name_length = 0;
  glGetProgramiv(
      program, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, &max_name_length);
  std::vector<GLchar> buffer(max_name_length);
  GLsizei length;
  for (uint32_t ii = 0; ii < num_uniform_blocks; ++ii) {
    param = 0;
    glGetActiveUniformBlockiv(program, ii, GL_UNIFORM_BLOCK_BINDING, &param);
    blocks[ii].binding = static_cast<uint32_t>(param);

    param = 0;
    glGetActiveUniformBlockiv(program, ii, GL_UNIFORM_BLOCK_DATA_SIZE, &param);
    blocks[ii].data_size = static_cast<uint32_t>(param);

    blocks[ii].name_offset = size.ValueOrDefault(0);
    param = 0;
    glGetActiveUniformBlockiv(
        program, ii, GL_UNIFORM_BLOCK_NAME_LENGTH, &param);
    DCHECK_GE(max_name_length, param);
    memset(&buffer[0], 0, param);
    length = 0;
    glGetActiveUniformBlockName(
        program, ii, static_cast<GLsizei>(param), &length, &buffer[0]);
    DCHECK_EQ(param, length + 1);
    names[ii] = std::string(&buffer[0], length);
    size_t pos = names[ii].find_first_of('[');
    const sh::InterfaceBlock* interface_block = nullptr;
    std::string array_index_str = "";
    if (pos != std::string::npos) {
      interface_block = GetInterfaceBlockInfo(names[ii].substr(0, pos));
      array_index_str = names[ii].substr(pos);
    } else {
      interface_block = GetInterfaceBlockInfo(names[ii]);
    }
    if (interface_block)
      names[ii] = interface_block->name + array_index_str;
    blocks[ii].name_length = names[ii].size() + 1;
    size += blocks[ii].name_length;

    param = 0;
    glGetActiveUniformBlockiv(
        program, ii, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, &param);
    blocks[ii].active_uniforms = static_cast<uint32_t>(param);
    blocks[ii].active_uniform_offset = size.ValueOrDefault(0);
    base::CheckedNumeric<uint32_t> indices_size = blocks[ii].active_uniforms;
    indices_size *= sizeof(uint32_t);
    if (!indices_size.IsValid())
      return false;
    size += indices_size.ValueOrDefault(0);

    param = 0;
    glGetActiveUniformBlockiv(
        program, ii, GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER, &param);
    blocks[ii].referenced_by_vertex_shader = static_cast<uint32_t>(param);

    param = 0;
    glGetActiveUniformBlockiv(
        program, ii, GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER, &param);
    blocks[ii].referenced_by_fragment_shader = static_cast<uint32_t>(param);
  }
  if (!size.IsValid())
    return false;
  uint32_t total_size = size.ValueOrDefault(0);
  DCHECK_LE(header_size + entry_size, total_size);
  uint32_t data_size = total_size - header_size - entry_size;

  bucket->SetSize(total_size);
  UniformBlocksHeader* header =
      bucket->GetDataAs<UniformBlocksHeader*>(0, header_size);
  UniformBlockInfo* entries = bucket->GetDataAs<UniformBlockInfo*>(
      header_size, entry_size);
  char* data = bucket->GetDataAs<char*>(header_size + entry_size, data_size);
  DCHECK(header);
  DCHECK(entries);
  DCHECK(data);

  // Copy over data for the header and entries.
  header->num_uniform_blocks = num_uniform_blocks;
  memcpy(entries, &blocks[0], entry_size);

  std::vector<GLint> params;
  for (uint32_t ii = 0; ii < num_uniform_blocks; ++ii) {
    // Get active uniform name.
    memcpy(data, names[ii].c_str(), names[ii].length() + 1);
    data += names[ii].length() + 1;

    // Get active uniform indices.
    if (params.size() < blocks[ii].active_uniforms)
      params.resize(blocks[ii].active_uniforms);
    uint32_t num_bytes = blocks[ii].active_uniforms * sizeof(GLint);
    memset(&params[0], 0, num_bytes);
    glGetActiveUniformBlockiv(
        program, ii, GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, &params[0]);
    uint32_t* indices = reinterpret_cast<uint32_t*>(data);
    for (uint32_t uu = 0; uu < blocks[ii].active_uniforms; ++uu) {
      indices[uu] = static_cast<uint32_t>(params[uu]);
    }
    data += num_bytes;
  }
  DCHECK_EQ(ComputeOffset(header, data), total_size);
  return true;
}

bool Program::GetTransformFeedbackVaryings(
    CommonDecoder::Bucket* bucket) const {
  // The data is packed into the bucket in the following order
  //   1) header
  //   2) N entries of varying data (except for name)
  //   3) name1, name2, ..., nameN
  //
  // We query all the data directly through GL calls, assuming they are
  // cheap through MANGLE.

  DCHECK(bucket);
  GLuint program = service_id();

  uint32_t header_size = sizeof(TransformFeedbackVaryingsHeader);
  bucket->SetSize(header_size);  // In case we fail.

  GLenum transform_feedback_buffer_mode = 0;
  GLint param = 0;
  glGetProgramiv(program, GL_TRANSFORM_FEEDBACK_BUFFER_MODE, &param);
  transform_feedback_buffer_mode = static_cast<GLenum>(param);

  uint32_t num_transform_feedback_varyings = 0;
  param = GL_FALSE;
  // We assume program is a valid program service id.
  glGetProgramiv(program, GL_LINK_STATUS, &param);
  if (param == GL_TRUE) {
    param = 0;
    glGetProgramiv(program, GL_TRANSFORM_FEEDBACK_VARYINGS, &param);
    num_transform_feedback_varyings = static_cast<uint32_t>(param);
  }
  if (num_transform_feedback_varyings == 0) {
    TransformFeedbackVaryingsHeader* header =
        bucket->GetDataAs<TransformFeedbackVaryingsHeader*>(0, header_size);
    header->transform_feedback_buffer_mode = transform_feedback_buffer_mode;
    return true;
  }

  std::vector<TransformFeedbackVaryingInfo> varyings(
      num_transform_feedback_varyings);
  base::CheckedNumeric<uint32_t> size = sizeof(TransformFeedbackVaryingInfo);
  size *= num_transform_feedback_varyings;
  uint32_t entry_size = size.ValueOrDefault(0);
  size += header_size;
  std::vector<std::string> names(num_transform_feedback_varyings);
  GLint max_name_length = 0;
  glGetProgramiv(
      program, GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH, &max_name_length);
  if (max_name_length < 1)
    max_name_length = 1;
  std::vector<char> buffer(max_name_length);
  for (uint32_t ii = 0; ii < num_transform_feedback_varyings; ++ii) {
    GLsizei var_size = 0;
    GLsizei var_name_length = 0;
    GLenum var_type = 0;
    glGetTransformFeedbackVarying(
        program, ii, max_name_length,
        &var_name_length, &var_size, &var_type, &buffer[0]);
    varyings[ii].size = static_cast<uint32_t>(var_size);
    varyings[ii].type = static_cast<uint32_t>(var_type);
    varyings[ii].name_offset = static_cast<uint32_t>(size.ValueOrDefault(0));
    DCHECK_GT(max_name_length, var_name_length);
    names[ii] = std::string(&buffer[0], var_name_length);
    const sh::Varying* varying = GetVaryingInfo(names[ii]);
    if (varying)
      names[ii] = varying->name;
    varyings[ii].name_length = names[ii].size() + 1;
    size += names[ii].size();
    size += 1;
  }
  if (!size.IsValid())
    return false;
  uint32_t total_size = size.ValueOrDefault(0);
  DCHECK_LE(header_size + entry_size, total_size);
  uint32_t data_size = total_size - header_size - entry_size;

  bucket->SetSize(total_size);
  TransformFeedbackVaryingsHeader* header =
      bucket->GetDataAs<TransformFeedbackVaryingsHeader*>(0, header_size);
  TransformFeedbackVaryingInfo* entries =
      bucket->GetDataAs<TransformFeedbackVaryingInfo*>(header_size, entry_size);
  char* data = bucket->GetDataAs<char*>(header_size + entry_size, data_size);
  DCHECK(header);
  DCHECK(entries);
  DCHECK(data);

  // Copy over data for the header and entries.
  header->transform_feedback_buffer_mode = transform_feedback_buffer_mode;
  header->num_transform_feedback_varyings = num_transform_feedback_varyings;
  memcpy(entries, &varyings[0], entry_size);

  for (uint32_t ii = 0; ii < num_transform_feedback_varyings; ++ii) {
    memcpy(data, names[ii].c_str(), names[ii].length() + 1);
    data += names[ii].length() + 1;
  }
  DCHECK_EQ(ComputeOffset(header, data), total_size);
  return true;
}

bool Program::GetUniformsES3(CommonDecoder::Bucket* bucket) const {
  // The data is packed into the bucket in the following order
  //   1) header
  //   2) N entries of UniformES3Info
  //
  // We query all the data directly through GL calls, assuming they are
  // cheap through MANGLE.

  DCHECK(bucket);
  GLuint program = service_id();

  uint32_t header_size = sizeof(UniformsES3Header);
  bucket->SetSize(header_size);  // In case we fail.

  GLsizei count = 0;
  GLint param = GL_FALSE;
  // We assume program is a valid program service id.
  glGetProgramiv(program, GL_LINK_STATUS, &param);
  if (param == GL_TRUE) {
    param = 0;
    glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &count);
  }
  if (count == 0) {
    return true;
  }

  base::CheckedNumeric<uint32_t> size = sizeof(UniformES3Info);
  size *= count;
  uint32_t entry_size = size.ValueOrDefault(0);
  size += header_size;
  if (!size.IsValid())
    return false;
  uint32_t total_size = size.ValueOrDefault(0);
  bucket->SetSize(total_size);
  UniformsES3Header* header =
      bucket->GetDataAs<UniformsES3Header*>(0, header_size);
  DCHECK(header);
  header->num_uniforms = static_cast<uint32_t>(count);

  // Instead of GetDataAs<UniformES3Info*>, we do GetDataAs<int32_t>. This is
  // because struct UniformES3Info is defined as five int32_t.
  // By doing this, we can fill the structs through loops.
  int32_t* entries =
      bucket->GetDataAs<int32_t*>(header_size, entry_size);
  DCHECK(entries);
  const size_t kStride = sizeof(UniformES3Info) / sizeof(int32_t);

  const GLenum kPname[] = {
    GL_UNIFORM_BLOCK_INDEX,
    GL_UNIFORM_OFFSET,
    GL_UNIFORM_ARRAY_STRIDE,
    GL_UNIFORM_MATRIX_STRIDE,
    GL_UNIFORM_IS_ROW_MAJOR,
  };
  const GLint kDefaultValue[] = { -1, -1, -1, -1, 0 };
  const size_t kNumPnames = arraysize(kPname);
  std::vector<GLuint> indices(count);
  for (GLsizei ii = 0; ii < count; ++ii) {
    indices[ii] = ii;
  }
  std::vector<GLint> params(count);
  for (size_t pname_index = 0; pname_index < kNumPnames; ++pname_index) {
    for (GLsizei ii = 0; ii < count; ++ii) {
      params[ii] = kDefaultValue[pname_index];
    }
    glGetActiveUniformsiv(
        program, count, &indices[0], kPname[pname_index], &params[0]);
    for (GLsizei ii = 0; ii < count; ++ii) {
      entries[kStride * ii + pname_index] = params[ii];
    }
  }
  return true;
}

const Program::ProgramOutputInfo* Program::GetProgramOutputInfo(
    const std::string& name) const {
  for (const auto& info : program_output_infos_) {
    if (info.name == name) {
      return &info;
    }
  }
  return nullptr;
}

GLint Program::GetFragDataLocation(const std::string& original_name) const {
  DCHECK(IsValid());
  const ProgramOutputInfo* info = GetProgramOutputInfo(original_name);
  if (!info)
    info = GetProgramOutputInfo(original_name + "[0]");
  if (!info)
    return -1;
  return info->color_name;
}

GLint Program::GetFragDataIndex(const std::string& original_name) const {
  DCHECK(IsValid());
  const ProgramOutputInfo* info = GetProgramOutputInfo(original_name);
  if (!info)
    info = GetProgramOutputInfo(original_name + "[0]");
  if (!info)
    return -1;
  return info->index;
}

void Program::TransformFeedbackVaryings(GLsizei count,
                                        const char* const* varyings,
                                        GLenum buffer_mode) {
  transform_feedback_varyings_.clear();
  for (GLsizei i = 0; i < count; ++i) {
    transform_feedback_varyings_.push_back(std::string(varyings[i]));
  }
  transform_feedback_buffer_mode_ = buffer_mode;
}

Program::~Program() {
  if (manager_) {
    if (manager_->have_context_) {
      glDeleteProgram(service_id());
    }
    manager_->StopTracking(this);
    manager_ = NULL;
  }
}

ProgramManager::ProgramManager(ProgramCache* program_cache,
                               uint32_t max_varying_vectors,
                               uint32_t max_draw_buffers,
                               uint32_t max_dual_source_draw_buffers,
                               uint32_t max_vertex_attribs,
                               const GpuPreferences& gpu_preferences,
                               FeatureInfo* feature_info,
                               ProgressReporter* progress_reporter)
    : program_count_(0),
      have_context_(true),
      program_cache_(program_cache),
      max_varying_vectors_(max_varying_vectors),
      max_draw_buffers_(max_draw_buffers),
      max_dual_source_draw_buffers_(max_dual_source_draw_buffers),
      max_vertex_attribs_(max_vertex_attribs),
      gpu_preferences_(gpu_preferences),
      feature_info_(feature_info),
      progress_reporter_(progress_reporter) {}

ProgramManager::~ProgramManager() {
  DCHECK(programs_.empty());
}

void ProgramManager::Destroy(bool have_context) {
  have_context_ = have_context;

  while (!programs_.empty()) {
    programs_.erase(programs_.begin());
    if (progress_reporter_)
      progress_reporter_->ReportProgress();
  }
}

void ProgramManager::StartTracking(Program* /* program */) {
  ++program_count_;
}

void ProgramManager::StopTracking(Program* /* program */) {
  --program_count_;
}

Program* ProgramManager::CreateProgram(
    GLuint client_id, GLuint service_id) {
  std::pair<ProgramMap::iterator, bool> result =
      programs_.insert(
          std::make_pair(client_id,
                         scoped_refptr<Program>(
                             new Program(this, service_id))));
  DCHECK(result.second);
  return result.first->second.get();
}

Program* ProgramManager::GetProgram(GLuint client_id) {
  ProgramMap::iterator it = programs_.find(client_id);
  return it != programs_.end() ? it->second.get() : NULL;
}

bool ProgramManager::GetClientId(GLuint service_id, GLuint* client_id) const {
  // This doesn't need to be fast. It's only used during slow queries.
  for (const auto& key_value : programs_) {
    if (key_value.second->service_id() == service_id) {
      *client_id = key_value.first;
      return true;
    }
  }
  return false;
}

ProgramCache* ProgramManager::program_cache() const {
  return program_cache_;
}

bool ProgramManager::IsOwned(Program* program) const {
  for (const auto& key_value : programs_) {
    if (key_value.second.get() == program) {
      return true;
    }
  }
  return false;
}

void ProgramManager::RemoveProgramInfoIfUnused(
    ShaderManager* shader_manager, Program* program) {
  DCHECK(shader_manager);
  DCHECK(program);
  DCHECK(IsOwned(program));
  if (program->IsDeleted() && !program->InUse()) {
    program->DetachShaders(shader_manager);
    for (ProgramMap::iterator it = programs_.begin();
         it != programs_.end(); ++it) {
      if (it->second.get() == program) {
        programs_.erase(it);
        return;
      }
    }
    NOTREACHED();
  }
}

void ProgramManager::MarkAsDeleted(
    ShaderManager* shader_manager,
    Program* program) {
  DCHECK(shader_manager);
  DCHECK(program);
  DCHECK(IsOwned(program));
  program->MarkAsDeleted();
  RemoveProgramInfoIfUnused(shader_manager, program);
}

void ProgramManager::UseProgram(Program* program) {
  DCHECK(program);
  DCHECK(IsOwned(program));
  program->IncUseCount();
}

void ProgramManager::UnuseProgram(
    ShaderManager* shader_manager,
    Program* program) {
  DCHECK(shader_manager);
  DCHECK(program);
  DCHECK(IsOwned(program));
  program->DecUseCount();
  RemoveProgramInfoIfUnused(shader_manager, program);
}

void ProgramManager::ClearUniforms(Program* program) {
  DCHECK(program);
  program->ClearUniforms(&zero_);
}

int32_t ProgramManager::MakeFakeLocation(int32_t index, int32_t element) {
  return index + element * 0x10000;
}

}  // namespace gles2
}  // namespace gpu
