// 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 "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,
    Shader* shader_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_signature(), a_sha);
  ComputeShaderHash(
      shader_b->last_compiled_signature(), 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 Shader* shader_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_signature(), a_sha);
  ComputeShaderHash(
      shader_b->last_compiled_signature(), 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
