// 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/shader_manager.h"

#include <stddef.h>

#include <utility>

#include "base/logging.h"
#include "base/strings/string_util.h"

namespace gpu {
namespace gles2 {

namespace {

// Given a variable name | a[0].b.c[0] |, return |a|.
std::string GetTopVariableName(const std::string& fullname) {
  size_t pos = fullname.find_first_of("[.");
  if (pos == std::string::npos)
    return fullname;
  return fullname.substr(0, pos);
}

}  // namespace anonymous

Shader::Shader(GLuint service_id, GLenum shader_type)
      : use_count_(0),
        shader_state_(kShaderStateWaiting),
        marked_for_deletion_(false),
        service_id_(service_id),
        shader_type_(shader_type),
        shader_version_(kUndefinedShaderVersion),
        source_type_(kANGLE),
        valid_(false) {
}

Shader::~Shader() {
}

void Shader::Destroy() {
  if (service_id_) {
    DeleteServiceID();
  }
}

void Shader::RequestCompile(scoped_refptr<ShaderTranslatorInterface> translator,
                            TranslatedShaderSourceType type) {
  shader_state_ = kShaderStateCompileRequested;
  translator_ = translator;
  source_type_ = type;
  last_compiled_source_ = source_;
}

void Shader::DoCompile() {
  // We require that RequestCompile() must be called before DoCompile(),
  // so we can return early if the shader state is not what we expect.
  if (shader_state_ != kShaderStateCompileRequested) {
    return;
  }

  // Signify the shader has been compiled, whether or not it is valid
  // is dependent on the |valid_| member variable.
  shader_state_ = kShaderStateCompiled;
  valid_ = false;

  // Translate GL ES 2.0 shader to Desktop GL shader and pass that to
  // glShaderSource and then glCompileShader.
  const char* source_for_driver = last_compiled_source_.c_str();
  ShaderTranslatorInterface* translator = translator_.get();
  if (translator) {
    bool success = translator->Translate(
        last_compiled_source_, &log_info_, &translated_source_,
        &shader_version_, &attrib_map_, &uniform_map_, &varying_map_,
        &interface_block_map_, &output_variable_list_, &name_map_);
    if (!success) {
      return;
    }
    source_for_driver = translated_source_.c_str();
  }

  glShaderSource(service_id_, 1, &source_for_driver, NULL);
  glCompileShader(service_id_);

  if (source_type_ == kANGLE) {
    RefreshTranslatedShaderSource();
    source_for_driver = translated_source_.c_str();
  }

  GLint status = GL_FALSE;
  glGetShaderiv(service_id_, GL_COMPILE_STATUS, &status);
  if (status == GL_TRUE) {
    valid_ = true;
  } else {
    valid_ = false;

    // We cannot reach here if we are using the shader translator.
    // All invalid shaders must be rejected by the translator.
    // All translated shaders must compile.
    std::string translator_log = log_info_;

    GLint max_len = 0;
    glGetShaderiv(service_id_, GL_INFO_LOG_LENGTH, &max_len);
    log_info_.resize(max_len);
    if (max_len) {
      GLint len = 0;
      glGetShaderInfoLog(service_id_, log_info_.size(), &len, &log_info_.at(0));
      DCHECK(max_len == 0 || len < max_len);
      DCHECK(len == 0 || log_info_[len] == '\0');
      log_info_.resize(len);
    }

    LOG_IF(ERROR, translator)
        << "Shader translator allowed/produced an invalid shader "
        << "unless the driver is buggy:"
        << "\n--Log from shader translator--\n" << translator_log
        << "\n--original-shader--\n" << last_compiled_source_
        << "\n--translated-shader--\n" << source_for_driver
        << "\n--info-log--\n" << log_info_;
  }
}

void Shader::RefreshTranslatedShaderSource() {
  if (source_type_ == kANGLE) {
    GLint max_len = 0;
    glGetShaderiv(service_id_, GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE,
                  &max_len);
    translated_source_.resize(max_len);
    if (max_len) {
      GLint len = 0;
      glGetTranslatedShaderSourceANGLE(service_id_, translated_source_.size(),
                                       &len, &translated_source_.at(0));
      DCHECK(max_len == 0 || len < max_len);
      DCHECK(len == 0 || translated_source_[len] == '\0');
      translated_source_.resize(len);
    }
  }
}

void Shader::IncUseCount() {
  ++use_count_;
}

void Shader::DecUseCount() {
  --use_count_;
  DCHECK_GE(use_count_, 0);
  if (service_id_ && use_count_ == 0 && marked_for_deletion_) {
    DeleteServiceID();
  }
}

void Shader::MarkForDeletion() {
  DCHECK(!marked_for_deletion_);
  DCHECK_NE(service_id_, 0u);

  marked_for_deletion_ = true;
  if (use_count_ == 0) {
    DeleteServiceID();
  }
}

void Shader::DeleteServiceID() {
  DCHECK_NE(service_id_, 0u);
  glDeleteShader(service_id_);
  service_id_ = 0;
}

const sh::Attribute* Shader::GetAttribInfo(const std::string& name) const {
  // Vertex attributes can't be arrays or structs (GLSL ES 3.00.4, section
  // 4.3.4, "Input Variables"), so |name| is the top level name used as
  // the AttributeMap key.
  AttributeMap::const_iterator it = attrib_map_.find(name);
  return it != attrib_map_.end() ? &it->second : NULL;
}

const std::string* Shader::GetAttribMappedName(
    const std::string& original_name) const {
  for (const auto& key_value : attrib_map_) {
    if (key_value.second.name == original_name)
      return &(key_value.first);
  }
  return nullptr;
}

const std::string* Shader::GetUniformMappedName(
    const std::string& original_name) const {
  for (const auto& key_value : uniform_map_) {
    if (key_value.second.name == original_name)
      return &(key_value.first);
  }
  return nullptr;
}

const std::string* Shader::GetVaryingMappedName(
    const std::string& original_name) const {
  for (VaryingMap::const_iterator it = varying_map_.begin();
       it != varying_map_.end(); ++it) {
    if (it->second.name == original_name)
      return &(it->first);
  }
  return NULL;
}

const std::string* Shader::GetInterfaceBlockMappedName(
    const std::string& original_name) const {
  for (const auto& key_value : interface_block_map_) {
    if (key_value.second.name == original_name)
      return &(key_value.first);
  }
  return NULL;
}

const std::string* Shader::GetOutputVariableMappedName(
    const std::string& original_name) const {
  for (const auto& value : output_variable_list_) {
    if (value.name == original_name)
      return &value.mappedName;
  }
  return nullptr;
}

const std::string* Shader::GetOriginalNameFromHashedName(
    const std::string& hashed_name) const {
  NameMap::const_iterator it = name_map_.find(hashed_name);
  if (it != name_map_.end())
    return &(it->second);
  return NULL;
}

const std::string* Shader::GetMappedName(
    const std::string& original_name) const {
  for (const auto& key_value : name_map_) {
    if (key_value.second == original_name)
      return &(key_value.first);
  }
  return NULL;
}

const sh::Uniform* Shader::GetUniformInfo(const std::string& name) const {
  UniformMap::const_iterator it = uniform_map_.find(GetTopVariableName(name));
  return it != uniform_map_.end() ? &it->second : NULL;
}

const sh::Varying* Shader::GetVaryingInfo(const std::string& name) const {
  VaryingMap::const_iterator it = varying_map_.find(GetTopVariableName(name));
  return it != varying_map_.end() ? &it->second : NULL;
}

const sh::InterfaceBlock* Shader::GetInterfaceBlockInfo(
    const std::string& name) const {
  InterfaceBlockMap::const_iterator it =
      interface_block_map_.find(GetTopVariableName(name));
  return it != interface_block_map_.end() ? &it->second : NULL;
}

const sh::OutputVariable* Shader::GetOutputVariableInfo(
    const std::string& name) const {
  std::string mapped_name = GetTopVariableName(name);
  // Number of output variables is expected to be so low that
  // a linear search of a list should be faster than using a map.
  for (const auto& value : output_variable_list_) {
    if (value.mappedName == mapped_name)
      return &value;
  }
  return nullptr;
}

ShaderManager::ShaderManager() {}

ShaderManager::~ShaderManager() {
  DCHECK(shaders_.empty());
}

void ShaderManager::Destroy(bool have_context) {
  while (!shaders_.empty()) {
    if (have_context) {
      Shader* shader = shaders_.begin()->second.get();
      shader->Destroy();
    }
    shaders_.erase(shaders_.begin());
  }
}

Shader* ShaderManager::CreateShader(
    GLuint client_id,
    GLuint service_id,
    GLenum shader_type) {
  std::pair<ShaderMap::iterator, bool> result =
      shaders_.insert(std::make_pair(
          client_id, scoped_refptr<Shader>(
              new Shader(service_id, shader_type))));
  DCHECK(result.second);
  return result.first->second.get();
}

Shader* ShaderManager::GetShader(GLuint client_id) {
  ShaderMap::iterator it = shaders_.find(client_id);
  return it != shaders_.end() ? it->second.get() : NULL;
}

bool ShaderManager::GetClientId(GLuint service_id, GLuint* client_id) const {
  // This doesn't need to be fast. It's only used during slow queries.
  for (ShaderMap::const_iterator it = shaders_.begin();
       it != shaders_.end(); ++it) {
    if (it->second->service_id() == service_id) {
      *client_id = it->first;
      return true;
    }
  }
  return false;
}

bool ShaderManager::IsOwned(Shader* shader) {
  for (ShaderMap::iterator it = shaders_.begin();
       it != shaders_.end(); ++it) {
    if (it->second.get() == shader) {
      return true;
    }
  }
  return false;
}

void ShaderManager::RemoveShader(Shader* shader) {
  DCHECK(shader);
  DCHECK(IsOwned(shader));
  if (shader->IsDeleted() && !shader->InUse()) {
    for (ShaderMap::iterator it = shaders_.begin();
         it != shaders_.end(); ++it) {
      if (it->second.get() == shader) {
        shaders_.erase(it);
        return;
      }
    }
    NOTREACHED();
  }
}

void ShaderManager::Delete(Shader* shader) {
  DCHECK(shader);
  DCHECK(IsOwned(shader));
  shader->MarkForDeletion();
  RemoveShader(shader);
}

void ShaderManager::UseShader(Shader* shader) {
  DCHECK(shader);
  DCHECK(IsOwned(shader));
  shader->IncUseCount();
}

void ShaderManager::UnuseShader(Shader* shader) {
  DCHECK(shader);
  DCHECK(IsOwned(shader));
  shader->DecUseCount();
  RemoveShader(shader);
}

}  // namespace gles2
}  // namespace gpu
