chromium/android_webview/test/shell/src/draw_fn/allocator.cc

// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "android_webview/test/shell/src/draw_fn/allocator.h"

#include "android_webview/public/browser/draw_fn.h"
#include "base/logging.h"
#include "base/no_destructor.h"
#include "base/notreached.h"

namespace draw_fn {

namespace {

bool g_use_vulkan = false;

AwDrawFnRenderMode QueryRenderMode() {
  return g_use_vulkan ? AW_DRAW_FN_RENDER_MODE_VULKAN
                      : AW_DRAW_FN_RENDER_MODE_OPENGL_ES;
}

int CreateFunctor(void* data, AwDrawFnFunctorCallbacks* functor_callbacks) {
  NOTREACHED();
}

int CreateFunctor_v3(void* data,
                     int version,
                     AwDrawFnFunctorCallbacks* functor_callbacks) {
  DCHECK_GE(version, 3);
  return Allocator::Get()->allocate(data, functor_callbacks);
}

void ReleaseFunctor(int functor) {
  Allocator::Get()->MarkReleasedByFunctor(functor);
}

void ReportRenderingThreads(int functor, const pid_t* thread_ids, size_t size) {
}

}  // namespace

void SetDrawFnUseVulkan(bool use_vulkan) {
  g_use_vulkan = use_vulkan;
}

AwDrawFnFunctionTable* GetDrawFnFunctionTable() {
  static AwDrawFnFunctionTable table{
      kAwDrawFnVersion, &QueryRenderMode,  &CreateFunctor,
      &ReleaseFunctor,  &CreateFunctor_v3, &ReportRenderingThreads};
  return &table;
}

FunctorData::FunctorData() = default;
FunctorData::~FunctorData() = default;
FunctorData::FunctorData(FunctorData&&) = default;
FunctorData& FunctorData::operator=(FunctorData&&) = default;

FunctorData::FunctorData(int functor,
                         void* data,
                         AwDrawFnFunctorCallbacks* functor_callbacks)
    : functor(functor), data(data), functor_callbacks(functor_callbacks) {}

// static
Allocator* Allocator::Get() {
  static base::NoDestructor<Allocator> map;
  return map.get();
}

Allocator::Allocator() = default;
Allocator::~Allocator() = default;

int Allocator::allocate(void* data,
                        AwDrawFnFunctorCallbacks* functor_callbacks) {
  base::AutoLock lock(lock_);
  int functor = next_functor_++;
  map_.emplace(functor, FunctorData(functor, data, functor_callbacks));
  return functor;
}

FunctorData& Allocator::get(int functor) {
  base::AutoLock lock(lock_);
  auto itr = map_.find(functor);
  CHECK(itr != map_.end());
  return itr->second;
}

void Allocator::MarkReleasedByFunctor(int functor) {
  base::AutoLock lock(lock_);
  auto itr = map_.find(functor);
  CHECK(itr != map_.end());
  DCHECK(!itr->second.released_by_functor);
  itr->second.released_by_functor = true;
  MaybeReleaseFunctorAlreadyLocked(functor);
}

void Allocator::MarkReleasedByManager(int functor) {
  base::AutoLock lock(lock_);
  auto itr = map_.find(functor);
  CHECK(itr != map_.end());
  DCHECK(!itr->second.released_by_manager);
  MaybeReleaseFunctorAlreadyLocked(functor);
}

void Allocator::MaybeReleaseFunctorAlreadyLocked(int functor) {
  lock_.AssertAcquired();
  auto itr = map_.find(functor);
  const FunctorData& data = itr->second;
  if (data.released_by_functor && data.released_by_manager) {
    data.functor_callbacks->on_destroyed(data.functor, data.data);
    map_.erase(itr);
  }
}

}  // namespace draw_fn