| // Copyright 2022 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 "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 { |
| |
| namespace { |
| |
| bool IsGpuRasterizationEnabled( |
| const scoped_refptr<viz::RasterContextProvider>& context) { |
| DCHECK(context); |
| viz::RasterContextProvider::ScopedRasterContextLock scoped_context( |
| context.get()); |
| |
| const gpu::Capabilities& caps = context->ContextCapabilities(); |
| return caps.gpu_rasterization; |
| } |
| |
| bool IsOopRasterSupported( |
| const scoped_refptr<viz::RasterContextProvider>& context) { |
| DCHECK(context); |
| viz::RasterContextProvider::ScopedRasterContextLock scoped_context( |
| context.get()); |
| |
| const gpu::Capabilities& caps = context->ContextCapabilities(); |
| return caps.supports_oop_raster; |
| } |
| |
| size_t GetMaxTextureSize( |
| const scoped_refptr<viz::RasterContextProvider>& context) { |
| DCHECK(context); |
| viz::RasterContextProvider::ScopedRasterContextLock scoped_context( |
| context.get()); |
| |
| const gpu::Capabilities& caps = context->ContextCapabilities(); |
| return caps.max_texture_size; |
| } |
| |
| } // namespace |
| |
| 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), |
| gpu_rasterization_enabled_(IsGpuRasterizationEnabled(context_)), |
| supports_oop_raster_(IsOopRasterSupported(context_)), |
| max_working_set_bytes_(max_working_set_bytes), |
| max_texture_size_(GetMaxTextureSize(context_)) { |
| 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) { |
| DCHECK(gpu_rasterization_enabled_ && supports_oop_raster_); |
| |
| 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_, max_texture_size_, dark_mode_filter_)); |
| DCHECK(insertion_result.second); |
| cache_iterator = insertion_result.first; |
| return *cache_iterator->second.get(); |
| } |
| |
| } // namespace cc |