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

#include "base/base64.h"
#include "base/command_line.h"
#include "base/metrics/histogram.h"
#include "base/sha1.h"
#include "base/strings/string_number_conversions.h"
#include "gpu/command_buffer/common/constants.h"
#include "gpu/command_buffer/service/disk_cache_proto.pb.h"
#include "gpu/command_buffer/service/gl_utils.h"
#include "gpu/command_buffer/service/gles2_cmd_decoder.h"
#include "gpu/command_buffer/service/gpu_switches.h"
#include "gpu/command_buffer/service/shader_manager.h"
#include "gpu/command_buffer/service/shader_translator.h"
#include "ui/gl/gl_bindings.h"

namespace {

size_t GetCacheSizeBytes() {
  const base::CommandLine* command_line =
      base::CommandLine::ForCurrentProcess();
  if (command_line->HasSwitch(switches::kGpuProgramCacheSizeKb)) {
    size_t size;
    if (base::StringToSizeT(
        command_line->GetSwitchValueNative(switches::kGpuProgramCacheSizeKb),
        &size))
      return size * 1024;
  }
  return gpu::kDefaultMaxProgramCacheMemoryBytes;
}

}  // anonymous namespace

namespace gpu {
namespace gles2 {

namespace {

enum ShaderMapType {
  ATTRIB_MAP = 0,
  UNIFORM_MAP,
  VARYING_MAP
};

void FillShaderVariableProto(
    ShaderVariableProto* proto, const sh::ShaderVariable& variable) {
  proto->set_type(variable.type);
  proto->set_precision(variable.precision);
  proto->set_name(variable.name);
  proto->set_mapped_name(variable.mappedName);
  proto->set_array_size(variable.arraySize);
  proto->set_static_use(variable.staticUse);
  for (size_t ii = 0; ii < variable.fields.size(); ++ii) {
    ShaderVariableProto* field = proto->add_fields();
    FillShaderVariableProto(field, variable.fields[ii]);
  }
  proto->set_struct_name(variable.structName);
}

void FillShaderAttributeProto(
    ShaderAttributeProto* proto, const sh::Attribute& attrib) {
  FillShaderVariableProto(proto->mutable_basic(), attrib);
  proto->set_location(attrib.location);
}

void FillShaderUniformProto(
    ShaderUniformProto* proto, const sh::Uniform& uniform) {
  FillShaderVariableProto(proto->mutable_basic(), uniform);
}

void FillShaderVaryingProto(
    ShaderVaryingProto* proto, const sh::Varying& varying) {
  FillShaderVariableProto(proto->mutable_basic(), varying);
  proto->set_interpolation(varying.interpolation);
  proto->set_is_invariant(varying.isInvariant);
}

void FillShaderProto(ShaderProto* proto, const char* sha,
                     const Shader* shader) {
  proto->set_sha(sha, gpu::gles2::ProgramCache::kHashLength);
  for (AttributeMap::const_iterator iter = shader->attrib_map().begin();
       iter != shader->attrib_map().end(); ++iter) {
    ShaderAttributeProto* info = proto->add_attribs();
    FillShaderAttributeProto(info, iter->second);
  }
  for (UniformMap::const_iterator iter = shader->uniform_map().begin();
       iter != shader->uniform_map().end(); ++iter) {
    ShaderUniformProto* info = proto->add_uniforms();
    FillShaderUniformProto(info, iter->second);
  }
  for (VaryingMap::const_iterator iter = shader->varying_map().begin();
       iter != shader->varying_map().end(); ++iter) {
    ShaderVaryingProto* info = proto->add_varyings();
    FillShaderVaryingProto(info, iter->second);
  }
}

void RetrieveShaderVariableInfo(
    const ShaderVariableProto& proto, sh::ShaderVariable* variable) {
  variable->type = proto.type();
  variable->precision = proto.precision();
  variable->name = proto.name();
  variable->mappedName = proto.mapped_name();
  variable->arraySize = proto.array_size();
  variable->staticUse = proto.static_use();
  variable->fields.resize(proto.fields_size());
  for (int ii = 0; ii < proto.fields_size(); ++ii)
    RetrieveShaderVariableInfo(proto.fields(ii), &(variable->fields[ii]));
  variable->structName = proto.struct_name();
}

void RetrieveShaderAttributeInfo(
    const ShaderAttributeProto& proto, AttributeMap* map) {
  sh::Attribute attrib;
  RetrieveShaderVariableInfo(proto.basic(), &attrib);
  attrib.location = proto.location();
  (*map)[proto.basic().mapped_name()] = attrib;
}

void RetrieveShaderUniformInfo(
    const ShaderUniformProto& proto, UniformMap* map) {
  sh::Uniform uniform;
  RetrieveShaderVariableInfo(proto.basic(), &uniform);
  (*map)[proto.basic().mapped_name()] = uniform;
}

void RetrieveShaderVaryingInfo(
    const ShaderVaryingProto& proto, VaryingMap* map) {
  sh::Varying varying;
  RetrieveShaderVariableInfo(proto.basic(), &varying);
  varying.interpolation = static_cast<sh::InterpolationType>(
      proto.interpolation());
  varying.isInvariant = proto.is_invariant();
  (*map)[proto.basic().mapped_name()] = varying;
}

void RunShaderCallback(const ShaderCacheCallback& callback,
                       GpuProgramProto* proto,
                       std::string sha_string) {
  std::string shader;
  proto->SerializeToString(&shader);

  std::string key;
  base::Base64Encode(sha_string, &key);
  callback.Run(key, shader);
}

}  // namespace

MemoryProgramCache::MemoryProgramCache()
    : max_size_bytes_(GetCacheSizeBytes()),
      curr_size_bytes_(0),
      store_(ProgramMRUCache::NO_AUTO_EVICT) {
}

MemoryProgramCache::MemoryProgramCache(const size_t max_cache_size_bytes)
    : max_size_bytes_(max_cache_size_bytes),
      curr_size_bytes_(0),
      store_(ProgramMRUCache::NO_AUTO_EVICT) {
}

MemoryProgramCache::~MemoryProgramCache() {}

void MemoryProgramCache::ClearBackend() {
  store_.Clear();
  DCHECK_EQ(0U, curr_size_bytes_);
}

ProgramCache::ProgramLoadResult MemoryProgramCache::LoadLinkedProgram(
    GLuint program,
    Shader* shader_a,
    const ShaderTranslatorInterface* translator_a,
    Shader* shader_b,
    const ShaderTranslatorInterface* translator_b,
    const LocationMap* bind_attrib_location_map,
    const ShaderCacheCallback& shader_callback) {
  char a_sha[kHashLength];
  char b_sha[kHashLength];
  DCHECK(shader_a && !shader_a->last_compiled_source().empty() &&
         shader_b && !shader_b->last_compiled_source().empty());
  ComputeShaderHash(
      shader_a->last_compiled_source(), translator_a, a_sha);
  ComputeShaderHash(
      shader_b->last_compiled_source(), translator_b, b_sha);

  char sha[kHashLength];
  ComputeProgramHash(a_sha,
                     b_sha,
                     bind_attrib_location_map,
                     sha);
  const std::string sha_string(sha, kHashLength);

  ProgramMRUCache::iterator found = store_.Get(sha_string);
  if (found == store_.end()) {
    return PROGRAM_LOAD_FAILURE;
  }
  const scoped_refptr<ProgramCacheValue> value = found->second;
  glProgramBinary(program,
                  value->format(),
                  static_cast<const GLvoid*>(value->data()),
                  value->length());
  GLint success = 0;
  glGetProgramiv(program, GL_LINK_STATUS, &success);
  if (success == GL_FALSE) {
    return PROGRAM_LOAD_FAILURE;
  }
  shader_a->set_attrib_map(value->attrib_map_0());
  shader_a->set_uniform_map(value->uniform_map_0());
  shader_a->set_varying_map(value->varying_map_0());
  shader_b->set_attrib_map(value->attrib_map_1());
  shader_b->set_uniform_map(value->uniform_map_1());
  shader_b->set_varying_map(value->varying_map_1());

  if (!shader_callback.is_null() &&
      !base::CommandLine::ForCurrentProcess()->HasSwitch(
          switches::kDisableGpuShaderDiskCache)) {
    scoped_ptr<GpuProgramProto> proto(
        GpuProgramProto::default_instance().New());
    proto->set_sha(sha, kHashLength);
    proto->set_format(value->format());
    proto->set_program(value->data(), value->length());

    FillShaderProto(proto->mutable_vertex_shader(), a_sha, shader_a);
    FillShaderProto(proto->mutable_fragment_shader(), b_sha, shader_b);
    RunShaderCallback(shader_callback, proto.get(), sha_string);
  }

  return PROGRAM_LOAD_SUCCESS;
}

void MemoryProgramCache::SaveLinkedProgram(
    GLuint program,
    const Shader* shader_a,
    const ShaderTranslatorInterface* translator_a,
    const Shader* shader_b,
    const ShaderTranslatorInterface* translator_b,
    const LocationMap* bind_attrib_location_map,
    const ShaderCacheCallback& shader_callback) {
  GLenum format;
  GLsizei length = 0;
  glGetProgramiv(program, GL_PROGRAM_BINARY_LENGTH_OES, &length);
  if (length == 0 || static_cast<unsigned int>(length) > max_size_bytes_) {
    return;
  }
  scoped_ptr<char[]> binary(new char[length]);
  glGetProgramBinary(program,
                     length,
                     NULL,
                     &format,
                     binary.get());
  UMA_HISTOGRAM_COUNTS("GPU.ProgramCache.ProgramBinarySizeBytes", length);

  char a_sha[kHashLength];
  char b_sha[kHashLength];
  DCHECK(shader_a && !shader_a->last_compiled_source().empty() &&
         shader_b && !shader_b->last_compiled_source().empty());
  ComputeShaderHash(
      shader_a->last_compiled_source(), translator_a, a_sha);
  ComputeShaderHash(
      shader_b->last_compiled_source(), translator_b, b_sha);

  char sha[kHashLength];
  ComputeProgramHash(a_sha,
                     b_sha,
                     bind_attrib_location_map,
                     sha);
  const std::string sha_string(sha, sizeof(sha));

  UMA_HISTOGRAM_COUNTS("GPU.ProgramCache.MemorySizeBeforeKb",
                       curr_size_bytes_ / 1024);

  // Evict any cached program with the same key in favor of the least recently
  // accessed.
  ProgramMRUCache::iterator existing = store_.Peek(sha_string);
  if(existing != store_.end())
    store_.Erase(existing);

  while (curr_size_bytes_ + length > max_size_bytes_) {
    DCHECK(!store_.empty());
    store_.Erase(store_.rbegin());
  }

  if (!shader_callback.is_null() &&
      !base::CommandLine::ForCurrentProcess()->HasSwitch(
          switches::kDisableGpuShaderDiskCache)) {
    scoped_ptr<GpuProgramProto> proto(
        GpuProgramProto::default_instance().New());
    proto->set_sha(sha, kHashLength);
    proto->set_format(format);
    proto->set_program(binary.get(), length);

    FillShaderProto(proto->mutable_vertex_shader(), a_sha, shader_a);
    FillShaderProto(proto->mutable_fragment_shader(), b_sha, shader_b);
    RunShaderCallback(shader_callback, proto.get(), sha_string);
  }

  store_.Put(sha_string,
             new ProgramCacheValue(length,
                                   format,
                                   binary.release(),
                                   sha_string,
                                   a_sha,
                                   shader_a->attrib_map(),
                                   shader_a->uniform_map(),
                                   shader_a->varying_map(),
                                   b_sha,
                                   shader_b->attrib_map(),
                                   shader_b->uniform_map(),
                                   shader_b->varying_map(),
                                   this));

  UMA_HISTOGRAM_COUNTS("GPU.ProgramCache.MemorySizeAfterKb",
                       curr_size_bytes_ / 1024);
}

void MemoryProgramCache::LoadProgram(const std::string& program) {
  scoped_ptr<GpuProgramProto> proto(GpuProgramProto::default_instance().New());
  if (proto->ParseFromString(program)) {
    AttributeMap vertex_attribs;
    UniformMap vertex_uniforms;
    VaryingMap vertex_varyings;
    for (int i = 0; i < proto->vertex_shader().attribs_size(); i++) {
      RetrieveShaderAttributeInfo(proto->vertex_shader().attribs(i),
                                  &vertex_attribs);
    }
    for (int i = 0; i < proto->vertex_shader().uniforms_size(); i++) {
      RetrieveShaderUniformInfo(proto->vertex_shader().uniforms(i),
                                &vertex_uniforms);
    }
    for (int i = 0; i < proto->vertex_shader().varyings_size(); i++) {
      RetrieveShaderVaryingInfo(proto->vertex_shader().varyings(i),
                                &vertex_varyings);
    }

    AttributeMap fragment_attribs;
    UniformMap fragment_uniforms;
    VaryingMap fragment_varyings;
    for (int i = 0; i < proto->fragment_shader().attribs_size(); i++) {
      RetrieveShaderAttributeInfo(proto->fragment_shader().attribs(i),
                                  &fragment_attribs);
    }
    for (int i = 0; i < proto->fragment_shader().uniforms_size(); i++) {
      RetrieveShaderUniformInfo(proto->fragment_shader().uniforms(i),
                                &fragment_uniforms);
    }
    for (int i = 0; i < proto->fragment_shader().varyings_size(); i++) {
      RetrieveShaderVaryingInfo(proto->fragment_shader().varyings(i),
                                &fragment_varyings);
    }

    scoped_ptr<char[]> binary(new char[proto->program().length()]);
    memcpy(binary.get(), proto->program().c_str(), proto->program().length());

    store_.Put(proto->sha(),
               new ProgramCacheValue(proto->program().length(),
                                     proto->format(),
                                     binary.release(),
                                     proto->sha(),
                                     proto->vertex_shader().sha().c_str(),
                                     vertex_attribs,
                                     vertex_uniforms,
                                     vertex_varyings,
                                     proto->fragment_shader().sha().c_str(),
                                     fragment_attribs,
                                     fragment_uniforms,
                                     fragment_varyings,
                                     this));

    UMA_HISTOGRAM_COUNTS("GPU.ProgramCache.MemorySizeAfterKb",
                         curr_size_bytes_ / 1024);
  } else {
    LOG(ERROR) << "Failed to parse proto file.";
  }
}

MemoryProgramCache::ProgramCacheValue::ProgramCacheValue(
    GLsizei length,
    GLenum format,
    const char* data,
    const std::string& program_hash,
    const char* shader_0_hash,
    const AttributeMap& attrib_map_0,
    const UniformMap& uniform_map_0,
    const VaryingMap& varying_map_0,
    const char* shader_1_hash,
    const AttributeMap& attrib_map_1,
    const UniformMap& uniform_map_1,
    const VaryingMap& varying_map_1,
    MemoryProgramCache* program_cache)
    : length_(length),
      format_(format),
      data_(data),
      program_hash_(program_hash),
      shader_0_hash_(shader_0_hash, kHashLength),
      attrib_map_0_(attrib_map_0),
      uniform_map_0_(uniform_map_0),
      varying_map_0_(varying_map_0),
      shader_1_hash_(shader_1_hash, kHashLength),
      attrib_map_1_(attrib_map_1),
      uniform_map_1_(uniform_map_1),
      varying_map_1_(varying_map_1),
      program_cache_(program_cache) {
  program_cache_->curr_size_bytes_ += length_;
  program_cache_->LinkedProgramCacheSuccess(program_hash);
}

MemoryProgramCache::ProgramCacheValue::~ProgramCacheValue() {
  program_cache_->curr_size_bytes_ -= length_;
  program_cache_->Evict(program_hash_);
}

}  // namespace gles2
}  // namespace gpu
