blob: 31a6200844cb4e0627c13ecf5467e88e27c63244 [file] [log] [blame]
// Copyright 2021 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 "components/viz/service/display/display_resource_provider_software.h"
#include <memory>
#include <vector>
#include "components/viz/common/resources/resource_format_utils.h"
#include "components/viz/service/display/shared_bitmap_manager.h"
namespace viz {
DisplayResourceProviderSoftware::DisplayResourceProviderSoftware(
SharedBitmapManager* shared_bitmap_manager)
: DisplayResourceProvider(DisplayResourceProvider::kSoftware),
shared_bitmap_manager_(shared_bitmap_manager) {
DCHECK(shared_bitmap_manager);
}
DisplayResourceProviderSoftware::~DisplayResourceProviderSoftware() {
Destroy();
}
const DisplayResourceProvider::ChildResource*
DisplayResourceProviderSoftware::LockForRead(ResourceId id) {
ChildResource* resource = GetResource(id);
DCHECK(!resource->is_gpu_resource_type());
if (!resource->shared_bitmap) {
const SharedBitmapId& shared_bitmap_id =
resource->transferable.mailbox_holder.mailbox;
std::unique_ptr<SharedBitmap> bitmap =
shared_bitmap_manager_->GetSharedBitmapFromId(
resource->transferable.size, resource->transferable.format,
shared_bitmap_id);
if (bitmap) {
resource->shared_bitmap = std::move(bitmap);
resource->shared_bitmap_tracing_guid =
shared_bitmap_manager_->GetSharedBitmapTracingGUIDFromId(
shared_bitmap_id);
}
}
resource->lock_for_read_count++;
return resource;
}
void DisplayResourceProviderSoftware::UnlockForRead(ResourceId id) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
ChildResource* resource = GetResource(id);
DCHECK(!resource->is_gpu_resource_type());
DCHECK_GT(resource->lock_for_read_count, 0);
resource->lock_for_read_count--;
TryReleaseResource(id, resource);
}
std::vector<ReturnedResource>
DisplayResourceProviderSoftware::DeleteAndReturnUnusedResourcesToChildImpl(
Child& child_info,
DeleteStyle style,
const std::vector<ResourceId>& unused) {
std::vector<ReturnedResource> to_return;
// Reserve enough space to avoid re-allocating, so we can keep item pointers
// for later using.
to_return.reserve(unused.size());
for (ResourceId local_id : unused) {
auto it = resources_.find(local_id);
CHECK(it != resources_.end());
ChildResource& resource = it->second;
DCHECK(!resource.is_gpu_resource_type());
auto sk_image_it = resource_sk_images_.find(local_id);
if (sk_image_it != resource_sk_images_.end()) {
resource_sk_images_.erase(sk_image_it);
}
ResourceId child_id = resource.transferable.id;
DCHECK(child_info.child_to_parent_map.count(child_id));
auto can_delete = CanDeleteNow(child_info, resource, style);
if (can_delete == CanDeleteNowResult::kNo) {
// Defer this resource deletion.
resource.marked_for_deletion = true;
continue;
}
const bool is_lost = can_delete == CanDeleteNowResult::kYesButLoseResource;
to_return.emplace_back(child_id, resource.sync_token(),
resource.imported_count, is_lost);
child_info.child_to_parent_map.erase(child_id);
resource.imported_count = 0;
resources_.erase(it);
}
return to_return;
}
void DisplayResourceProviderSoftware::PopulateSkBitmapWithResource(
SkBitmap* sk_bitmap,
const ChildResource* resource) {
DCHECK(IsBitmapFormatSupported(resource->transferable.format));
SkImageInfo info =
SkImageInfo::MakeN32Premul(resource->transferable.size.width(),
resource->transferable.size.height());
bool pixels_installed = sk_bitmap->installPixels(
info, resource->shared_bitmap->pixels(), info.minRowBytes());
DCHECK(pixels_installed);
}
DisplayResourceProviderSoftware::ScopedReadLockSkImage::ScopedReadLockSkImage(
DisplayResourceProviderSoftware* resource_provider,
ResourceId resource_id,
SkAlphaType alpha_type,
GrSurfaceOrigin origin)
: resource_provider_(resource_provider), resource_id_(resource_id) {
const ChildResource* resource = resource_provider->LockForRead(resource_id);
DCHECK(resource);
DCHECK(!resource->is_gpu_resource_type());
// Use cached SkImage if possible.
auto it = resource_provider_->resource_sk_images_.find(resource_id);
if (it != resource_provider_->resource_sk_images_.end()) {
sk_image_ = it->second;
return;
}
if (!resource->shared_bitmap) {
// If a CompositorFrameSink is destroyed, it destroys all SharedBitmapIds
// that it registered. In this case, a CompositorFrame can be drawn with
// SharedBitmapIds that are not known in the viz service. As well, a
// misbehaved client can use SharedBitampIds that it did not report to
// the service. Then the |shared_bitmap| will be null, and this read lock
// will not be valid. Software-compositing users of this read lock must
// check for valid() to deal with this scenario.
sk_image_ = nullptr;
return;
}
DCHECK(origin == kTopLeft_GrSurfaceOrigin);
SkBitmap sk_bitmap;
resource_provider->PopulateSkBitmapWithResource(&sk_bitmap, resource);
sk_bitmap.setImmutable();
sk_image_ = SkImage::MakeFromBitmap(sk_bitmap);
resource_provider_->resource_sk_images_[resource_id] = sk_image_;
}
DisplayResourceProviderSoftware::ScopedReadLockSkImage::
~ScopedReadLockSkImage() {
resource_provider_->UnlockForRead(resource_id_);
}
} // namespace viz