// 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 <string_view>
#include <utility>

#include "base/base64.h"
#include "base/compiler_specific.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/string_view_util.h"
#include "ui/gl/gl_bindings.h"
#include "ui/gl/gl_display.h"
#include "ui/gl/gl_surface_egl.h"

namespace gpu {
namespace gles2 {

namespace {

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;
}

// 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;

// Blob cache function pointers can only be set once per EGLDisplay. Using a
// single bool is not technically correct, but it's acceptable since we only
// have one EGLDisplay in practice.
bool g_blob_cache_funcs_set = false;

}  // 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) {
  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 && !g_blob_cache_funcs_set &&
      BlobCacheExtensionAvailable(gl_display)) {
    // Register the blob cache callbacks.
    eglSetBlobCacheFuncsANDROID(egl_display, BlobCacheSet, BlobCacheGet);
    g_blob_cache_funcs_set = true;
  }
}

PassthroughProgramCache::~PassthroughProgramCache() {
  // 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;
}

void PassthroughProgramCache::ClearBackend() {
  base::AutoLock auto_lock(lock_);
  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();
}

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) {
  base::AutoLock auto_lock(lock_);
  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) {
  base::AutoLock auto_lock(lock_);
  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,
                                  CacheProgramCallback callback) {
  {
    base::AutoLock auto_lock(lock_);
    // 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());

  {
    base::AutoLock auto_lock(lock_);

    // If callback is set, notify that there was a new/updated blob entry so it
    // can be stored in disk.  Note that this is done before the Put() call as
    // that consumes `value`.
    CacheProgramCallback callback_with_fallback =
        callback ? callback : cache_program_callback_;
    if (callback_with_fallback) {
      // Convert the key and binary to base-64 string form.
      std::string key_string_64 = base::Base64Encode(key);
      std::string value_string_64 = base::Base64Encode(value);
      callback_with_fallback.Run(key_string_64, value_string_64);
    }

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

size_t PassthroughProgramCache::Get(const Key& key,
                                    void* out_value,
                                    size_t value_size) {
  // Note that the |lock_| should be held during whole time ProgramCacheValue is
  // being accessed below.
  base::AutoLock auto_lock(lock_);

  ProgramLRUCache::iterator found = store_.Get(key);

  UMA_HISTOGRAM_BOOLEAN("Gpu.PassthroughProgramCacheLoadHitInCache",
                        found != store_.end());

  if (found == store_.end()) {
    return 0;
  }

  const PassthroughProgramCache::Value& entry_value = found->second.data();

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

  return entry_value.size();
}

EGLsizeiANDROID PassthroughProgramCache::BlobCacheGetImpl(
    const void* key,
    EGLsizeiANDROID key_size,
    void* value,
    EGLsizeiANDROID value_size) {
  if (key_size < 0) {
    return 0;
  }

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

  return Get(entry_key, value, value_size);
}

void PassthroughProgramCache::BlobCacheSetImpl(const void* key,
                                               EGLsizeiANDROID key_size,
                                               const void* value,
                                               EGLsizeiANDROID value_size) {
  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,
                                         UNSAFE_TODO(key_begin + key_size));

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

  // Pass a null callback to use the default cache_program_callback_
  Set(std::move(entry_key), std::move(entry_value), CacheProgramCallback());
}

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

  g_program_cache->BlobCacheSetImpl(key, key_size, value, value_size);
}

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

  return g_program_cache->BlobCacheGetImpl(key, key_size, value, 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() {
  if (program_cache_) {
    program_cache_->curr_size_bytes_ -= program_blob_.size();
  }
}

PassthroughProgramCache::ProgramCacheValue::ProgramCacheValue(
    ProgramCacheValue&& other)
    : program_blob_(std::move(other.program_blob_)),
      program_cache_(std::exchange(other.program_cache_, nullptr)) {}

PassthroughProgramCache::ProgramCacheValue&
PassthroughProgramCache::ProgramCacheValue::operator=(
    ProgramCacheValue&& other) {
  program_blob_ = std::move(other.program_blob_);
  program_cache_ = std::exchange(other.program_cache_, nullptr);
  return *this;
}

}  // namespace gles2
}  // namespace gpu
