// Copyright 2017 The Chromium Authors
// 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/passthrough_program_cache.h"

#include <stddef.h>

#include "base/base64.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/string_piece.h"
#include "ui/gl/gl_bindings.h"

#if defined(USE_EGL)
#include "ui/gl/gl_display.h"
#include "ui/gl/gl_surface_egl.h"
#endif  // defined(USE_EGL)

namespace gpu {
namespace gles2 {

namespace {

#if defined(USE_EGL)
bool BlobCacheExtensionAvailable(gl::GLDisplayEGL* gl_display) {
  // The display should be initialized if the extension is available.
  return gl_display->ext->b_EGL_ANDROID_blob_cache;
}
#endif  // defined(USE_EGL)

// EGL_ANDROID_blob_cache doesn't give user pointer to the callbacks so we are
// forced to have this be global.
PassthroughProgramCache* g_program_cache = nullptr;

}  // namespace

PassthroughProgramCache::PassthroughProgramCache(
    size_t max_cache_size_bytes,
    bool disable_gpu_shader_disk_cache)
    : ProgramCache(max_cache_size_bytes),
      disable_gpu_shader_disk_cache_(disable_gpu_shader_disk_cache),
      curr_size_bytes_(0),
      store_(ProgramLRUCache::NO_AUTO_EVICT) {
#if defined(USE_EGL)
  gl::GLDisplayEGL* gl_display = gl::GLSurfaceEGL::GetGLDisplayEGL();
  EGLDisplay egl_display = gl_display->GetDisplay();

  DCHECK(!g_program_cache);
  g_program_cache = this;

  // display is EGL_NO_DISPLAY during unittests.
  if (egl_display != EGL_NO_DISPLAY &&
      BlobCacheExtensionAvailable(gl_display)) {
    // Register the blob cache callbacks.
    eglSetBlobCacheFuncsANDROID(egl_display, BlobCacheSet, BlobCacheGet);
  }
#endif  // defined(USE_EGL)
}

PassthroughProgramCache::~PassthroughProgramCache() {
#if defined(USE_EGL)
  // Clear up the blob cache callbacks.  Note that this not allowed by the
  // EGL_ANDROID_blob_cache spec, so we just set the pointer to this object to
  // nullptr as a workaround.  The callbacks don't work with this pointer
  // missing.
  g_program_cache = nullptr;
#endif  // defined(USE_EGL)
}

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

ProgramCache::ProgramLoadResult PassthroughProgramCache::LoadLinkedProgram(
    GLuint program,
    Shader* shader_a,
    Shader* shader_b,
    const LocationMap* bind_attrib_location_map,
    const std::vector<std::string>& transform_feedback_varyings,
    GLenum transform_feedback_buffer_mode,
    DecoderClient* client) {
  NOTREACHED();
  return PROGRAM_LOAD_FAILURE;
}

void PassthroughProgramCache::SaveLinkedProgram(
    GLuint program,
    const Shader* shader_a,
    const Shader* shader_b,
    const LocationMap* bind_attrib_location_map,
    const std::vector<std::string>& transform_feedback_varyings,
    GLenum transform_feedback_buffer_mode,
    DecoderClient* client) {
  NOTREACHED();
}

void PassthroughProgramCache::LoadProgram(const std::string& key,
                                          const std::string& program) {
  if (!CacheEnabled()) {
    return;
  }

  std::string key_decoded;
  std::string program_decoded;
  base::Base64Decode(key, &key_decoded);
  base::Base64Decode(program, &program_decoded);

  Key entry_key(key_decoded.begin(), key_decoded.end());
  Value entry_value(program_decoded.begin(), program_decoded.end());

  store_.Put(entry_key, ProgramCacheValue(std::move(entry_value), this));
}

size_t PassthroughProgramCache::Trim(size_t limit) {
  size_t initial_size = curr_size_bytes_;
  while (curr_size_bytes_ > limit) {
    DCHECK(!store_.empty());
    store_.Erase(store_.rbegin());
  }
  return initial_size - curr_size_bytes_;
}

bool PassthroughProgramCache::CacheEnabled() const {
  return !disable_gpu_shader_disk_cache_;
}

void PassthroughProgramCache::Set(Key&& key, Value&& value) {
  // If the value is so big it will never fit in the cache, throw it away.
  if (value.size() > max_size_bytes())
    return;

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

  // If the cache is overflowing, remove some old entries.
  DCHECK(max_size_bytes() >= value.size());
  Trim(max_size_bytes() - value.size());

  // If callback is set, notify that there was a new/updated blob entry so it
  // can be soted in disk.  Note that this is done before the Put() call as that
  // consumes `value`.
  if (cache_program_callback_) {
    // Convert the key and binary to string form.
    base::StringPiece key_string(reinterpret_cast<const char*>(key.data()),
                                 key.size());
    base::StringPiece value_string(reinterpret_cast<const char*>(value.data()),
                                   value.size());
    std::string key_string_64;
    std::string value_string_64;
    base::Base64Encode(key_string, &key_string_64);
    base::Base64Encode(value_string, &value_string_64);
    cache_program_callback_.Run(key_string_64, value_string_64);
  }

  store_.Put(key, ProgramCacheValue(std::move(value), this));
}

const PassthroughProgramCache::ProgramCacheValue* PassthroughProgramCache::Get(
    const Key& key) {
  ProgramLRUCache::iterator found = store_.Get(key);
  return found == store_.end() ? nullptr : &found->second;
}

void PassthroughProgramCache::BlobCacheSet(const void* key,
                                           EGLsizeiANDROID key_size,
                                           const void* value,
                                           EGLsizeiANDROID value_size) {
  if (!g_program_cache)
    return;

  if (key_size < 0 || value_size < 0)
    return;

  const uint8_t* key_begin = reinterpret_cast<const uint8_t*>(key);
  PassthroughProgramCache::Key entry_key(key_begin, key_begin + key_size);

  const uint8_t* value_begin = reinterpret_cast<const uint8_t*>(value);
  PassthroughProgramCache::Value entry_value(value_begin,
                                             value_begin + value_size);

  g_program_cache->Set(std::move(entry_key), std::move(entry_value));
}

EGLsizeiANDROID PassthroughProgramCache::BlobCacheGet(
    const void* key,
    EGLsizeiANDROID key_size,
    void* value,
    EGLsizeiANDROID value_size) {
  if (!g_program_cache)
    return 0;

  if (key_size < 0)
    return 0;

  const uint8_t* key_begin = reinterpret_cast<const uint8_t*>(key);
  PassthroughProgramCache::Key entry_key(key_begin, key_begin + key_size);

  const PassthroughProgramCache::ProgramCacheValue* cacheValue =
      g_program_cache->Get(std::move(entry_key));

  if (!cacheValue)
    return 0;

  const PassthroughProgramCache::Value& entry_value = cacheValue->data();

  if (value_size > 0) {
    if (static_cast<size_t>(value_size) >= entry_value.size())
      memcpy(value, entry_value.data(), entry_value.size());
  }

  return entry_value.size();
}

PassthroughProgramCache::ProgramCacheValue::ProgramCacheValue(
    PassthroughProgramCache::Value&& program_blob,
    PassthroughProgramCache* program_cache)
    : program_blob_(std::move(program_blob)), program_cache_(program_cache) {
  program_cache_->curr_size_bytes_ += program_blob_.size();
}

PassthroughProgramCache::ProgramCacheValue::~ProgramCacheValue() {
  program_cache_->curr_size_bytes_ -= program_blob_.size();
}

PassthroughProgramCache::ProgramCacheValue::ProgramCacheValue(
    ProgramCacheValue&& other) = default;

PassthroughProgramCache::ProgramCacheValue&
PassthroughProgramCache::ProgramCacheValue::operator=(
    ProgramCacheValue&& other) = default;

}  // namespace gles2
}  // namespace gpu
