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

#include <stddef.h>

#include <memory>
#include <string>

#include "base/metrics/histogram_macros.h"
#include "gpu/command_buffer/service/shader_manager.h"
#include "third_party/angle/src/common/angle_version_info.h"

namespace gpu {
namespace gles2 {

ProgramCache::ScopedCacheUse::ScopedCacheUse(ProgramCache* cache,
                                             CacheProgramCallback callback)
    : cache_(cache) {
  cache_->cache_program_callback_ = callback;
}

ProgramCache::ScopedCacheUse::~ScopedCacheUse() {
  cache_->cache_program_callback_.Reset();
}

ProgramCache::ProgramCache(size_t max_cache_size_bytes)
    : max_size_bytes_(max_cache_size_bytes) {}
ProgramCache::~ProgramCache() = default;

void ProgramCache::Clear() {
  ClearBackend();
  link_status_.clear();
  compiled_shaders_.clear();
}

bool ProgramCache::HasSuccessfullyCompiledShader(
    const std::string& shader_signature) const {
  char sha[kHashLength];
  ComputeShaderHash(shader_signature, sha);
  const std::string sha_string(sha, kHashLength);

  if (compiled_shaders_.find(sha_string) != compiled_shaders_.end()) {
    return true;
  }
  return false;
}

ProgramCache::LinkedProgramStatus ProgramCache::GetLinkedProgramStatus(
    const std::string& shader_signature_a,
    const std::string& shader_signature_b,
    const std::map<std::string, GLint>* bind_attrib_location_map,
    const std::vector<std::string>& transform_feedback_varyings,
    GLenum transform_feedback_buffer_mode) const {
  char a_sha[kHashLength];
  char b_sha[kHashLength];
  ComputeShaderHash(shader_signature_a, a_sha);
  ComputeShaderHash(shader_signature_b, b_sha);

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

  LinkStatusMap::const_iterator found = link_status_.find(sha_string);
  if (found == link_status_.end()) {
    return ProgramCache::LINK_UNKNOWN;
  } else {
    return found->second;
  }
}

void ProgramCache::LinkedProgramCacheSuccess(
    const std::string& shader_signature_a,
    const std::string& shader_signature_b,
    const LocationMap* bind_attrib_location_map,
    const std::vector<std::string>& transform_feedback_varyings,
    GLenum transform_feedback_buffer_mode) {
  char a_sha[kHashLength];
  char b_sha[kHashLength];
  ComputeShaderHash(shader_signature_a, a_sha);
  ComputeShaderHash(shader_signature_b, b_sha);
  char sha[kHashLength];
  ComputeProgramHash(a_sha,
                     b_sha,
                     bind_attrib_location_map,
                     transform_feedback_varyings,
                     transform_feedback_buffer_mode,
                     sha);
  const std::string a_sha_string(a_sha, kHashLength);
  const std::string b_sha_string(b_sha, kHashLength);
  const std::string sha_string(sha, kHashLength);

  CompiledShaderCacheSuccess(a_sha_string);
  CompiledShaderCacheSuccess(b_sha_string);
  LinkedProgramCacheSuccess(sha_string);
}

void ProgramCache::LinkedProgramCacheSuccess(const std::string& program_hash) {
  link_status_[program_hash] = LINK_SUCCEEDED;
}

void ProgramCache::CompiledShaderCacheSuccess(const std::string& shader_hash) {
  compiled_shaders_.insert(shader_hash);
}

void ProgramCache::ComputeShaderHash(
    const std::string& str,
    char* result) const {
  base::SHA1HashBytes(reinterpret_cast<const unsigned char*>(str.c_str()),
                      str.length(), reinterpret_cast<unsigned char*>(result));
}

void ProgramCache::Evict(const std::string& program_hash,
                         const std::string& shader_0_hash,
                         const std::string& shader_1_hash) {
  link_status_.erase(program_hash);
  compiled_shaders_.erase(shader_0_hash);
  compiled_shaders_.erase(shader_1_hash);
}

namespace {
size_t CalculateMapSize(const std::map<std::string, GLint>* map) {
  if (!map) {
    return 0;
  }
  size_t total = 0;
  for (auto it = map->begin(); it != map->end(); ++it) {
    total += 4 + it->first.length();
  }
  return total;
}

size_t CalculateVaryingsSize(const std::vector<std::string>& varyings) {
  size_t total = 0;
  for (auto& varying : varyings) {
    total += 1 + varying.length();
  }
  return total;
}
}  // anonymous namespace

void ProgramCache::ComputeProgramHash(
    const char* hashed_shader_0,
    const char* hashed_shader_1,
    const std::map<std::string, GLint>* bind_attrib_location_map,
    const std::vector<std::string>& transform_feedback_varyings,
    GLenum transform_feedback_buffer_mode,
    char* result) const {
  const size_t shader0_size = kHashLength;
  const size_t shader1_size = kHashLength;
  const size_t angle_commit_size = angle::GetANGLECommitHashSize();
  const size_t map_size = CalculateMapSize(bind_attrib_location_map);
  const size_t var_size = CalculateVaryingsSize(transform_feedback_varyings);
  const size_t total_size = shader0_size + shader1_size + angle_commit_size
      + map_size + var_size + sizeof(transform_feedback_buffer_mode);

  std::unique_ptr<unsigned char[]> buffer(new unsigned char[total_size]);
  memcpy(buffer.get(), hashed_shader_0, shader0_size);
  memcpy(&buffer[shader0_size], hashed_shader_1, shader1_size);
  size_t current_pos = shader0_size + shader1_size;
  memcpy(&buffer[current_pos], angle::GetANGLECommitHash(), angle_commit_size);
  current_pos += angle_commit_size;
  if (map_size != 0) {
    // copy our map
    for (auto it = bind_attrib_location_map->begin();
         it != bind_attrib_location_map->end();
         ++it) {
      const size_t name_size = it->first.length();
      memcpy(&buffer.get()[current_pos], it->first.c_str(), name_size);
      current_pos += name_size;
      const GLint value = it->second;
      buffer[current_pos++] = value >> 24;
      buffer[current_pos++] = static_cast<unsigned char>(value >> 16);
      buffer[current_pos++] = static_cast<unsigned char>(value >> 8);
      buffer[current_pos++] = static_cast<unsigned char>(value);
    }
  }

  if (var_size != 0) {
    // copy transform feedback varyings
    for (auto& varying : transform_feedback_varyings) {
      const size_t name_size = varying.length();
      memcpy(&buffer.get()[current_pos], varying.c_str(), name_size);
      current_pos += name_size;
      buffer[current_pos++] = ' ';
    }
  }
  memcpy(&buffer[current_pos], &transform_feedback_buffer_mode,
      sizeof(transform_feedback_buffer_mode));
  base::SHA1HashBytes(buffer.get(),
                      total_size, reinterpret_cast<unsigned char*>(result));
}

void ProgramCache::HandleMemoryPressure(
    base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level) {
  if (memory_pressure_level ==
      base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE) {
    return;
  }

  // Set a low limit on cache size for MEMORY_PRESSURE_LEVEL_MODERATE.
  size_t limit = max_size_bytes_ / 4;
  if (memory_pressure_level ==
      base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL) {
    limit = 0;
  }

  Trim(limit);
}

}  // namespace gles2
}  // namespace gpu
