1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97

cc / trees / raster_context_provider_wrapper.cc [blame]

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

#include "cc/trees/raster_context_provider_wrapper.h"

#include "base/functional/bind.h"
#include "cc/tiles/gpu_image_decode_cache.h"
#include "components/viz/common/gpu/raster_context_provider.h"

namespace cc {

RasterContextProviderWrapper::RasterContextProviderWrapper(
    scoped_refptr<viz::RasterContextProvider> context,
    RasterDarkModeFilter* dark_mode_filter,
    size_t max_working_set_bytes)
    : context_(context),
      context_supports_locking_(!!context_->GetLock()),
      dark_mode_filter_(dark_mode_filter),
      max_working_set_bytes_(max_working_set_bytes) {
  CheckValidThreadOrLockSupported();

  viz::RasterContextProvider::ScopedRasterContextLock scoped_context(
      context.get());
  // This callback can use a raw ptr for the cb as the wrapper outlive the cache
  // controller.
  context_->CacheController()->SetNotifyAllClientsVisibilityChangedCb(
      base::BindRepeating(
          &RasterContextProviderWrapper::OnAllClientsVisibilityChanged,
          base::Unretained(this)));
}

RasterContextProviderWrapper::~RasterContextProviderWrapper() {
  CheckValidThreadOrLockSupported();
}

void RasterContextProviderWrapper::CheckValidThreadOrLockSupported() const {
#if DCHECK_IS_ON()
  // If the context supports lock, no need to check for a thread.
  if (context_supports_locking_)
    return;
  DCHECK_CALLED_ON_VALID_THREAD(bound_context_thread_checker_);
#endif
}

void RasterContextProviderWrapper::OnAllClientsVisibilityChanged(bool visible) {
  // Once all the clients are invisible, we should aggressively free resources
  // from the image decode caches. This what ContextCacheController also does -
  // it notifies the context support it must aggressively free resources if
  // all clients that share the same context became invisible.
  const bool should_aggressively_free_resources = !visible;

  // The caller of
  // ContextCacheController::ClientBecomeVisible/ClientBecomeNotVisible must
  // acquire lock. Thus, we are called with lock acquired. Unfortunately, we
  // have to either make ImageDecodeCache require acquiring lock or provide it
  // with information that lock has been acquired. Otherwise, a deadlock
  // happens.
  //
  // If lock is not supported, lock has not been acquired.
  const bool context_lock_acquired = context_supports_locking_;
  if (context_supports_locking_)
    context_->GetLock()->AssertAcquired();

  base::AutoLock scoped_lock(lock_);
  for (const auto& item : gpu_image_decode_cache_map_) {
    item.second->SetShouldAggressivelyFreeResources(
        should_aggressively_free_resources, context_lock_acquired);
  }
}

const scoped_refptr<viz::RasterContextProvider>&
RasterContextProviderWrapper::GetContext() const {
  return context_;
}

GpuImageDecodeCache& RasterContextProviderWrapper::GetGpuImageDecodeCache(
    SkColorType color_type,
    const RasterCapabilities& raster_caps) {
  DCHECK(raster_caps.use_gpu_rasterization);
  base::AutoLock scoped_lock(lock_);

  auto cache_iterator = gpu_image_decode_cache_map_.find(color_type);
  if (cache_iterator != gpu_image_decode_cache_map_.end())
    return *cache_iterator->second.get();

  auto insertion_result = gpu_image_decode_cache_map_.emplace(
      color_type, std::make_unique<GpuImageDecodeCache>(
                      GetContext().get(), /*use_transfer_cache=*/true,
                      color_type, max_working_set_bytes_,
                      raster_caps.max_texture_size, dark_mode_filter_));
  DCHECK(insertion_result.second);
  cache_iterator = insertion_result.first;
  return *cache_iterator->second.get();
}

}  // namespace cc