blob: 14391c2128a747eb316fcba933e3b7dc48848997 [file] [log] [blame]
// Copyright 2013 The Flutter 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 "flutter/lib/ui/painting/display_list_deferred_image_gpu.h"
#include "display_list_deferred_image_gpu.h"
#include "third_party/skia/include/core/SkColorSpace.h"
namespace flutter {
sk_sp<DlDeferredImageGPU> DlDeferredImageGPU::Make(
const SkImageInfo& image_info,
sk_sp<DisplayList> display_list,
fml::WeakPtr<SnapshotDelegate> snapshot_delegate,
fml::RefPtr<fml::TaskRunner> raster_task_runner,
fml::RefPtr<SkiaUnrefQueue> unref_queue) {
return sk_sp<DlDeferredImageGPU>(new DlDeferredImageGPU(
ImageWrapper::Make(image_info, std::move(display_list),
std::move(snapshot_delegate), raster_task_runner,
std::move(unref_queue)),
raster_task_runner));
}
sk_sp<DlDeferredImageGPU> DlDeferredImageGPU::MakeFromLayerTree(
const SkImageInfo& image_info,
std::shared_ptr<LayerTree> layer_tree,
fml::WeakPtr<SnapshotDelegate> snapshot_delegate,
fml::RefPtr<fml::TaskRunner> raster_task_runner,
fml::RefPtr<SkiaUnrefQueue> unref_queue) {
return sk_sp<DlDeferredImageGPU>(new DlDeferredImageGPU(
ImageWrapper::MakeFromLayerTree(
image_info, std::move(layer_tree), std::move(snapshot_delegate),
raster_task_runner, std::move(unref_queue)),
raster_task_runner));
}
DlDeferredImageGPU::DlDeferredImageGPU(
std::shared_ptr<ImageWrapper> image_wrapper,
fml::RefPtr<fml::TaskRunner> raster_task_runner)
: image_wrapper_(std::move(image_wrapper)),
raster_task_runner_(std::move(raster_task_runner)) {}
// |DlImage|
DlDeferredImageGPU::~DlDeferredImageGPU() {
fml::TaskRunner::RunNowOrPostTask(
raster_task_runner_, [image_wrapper = std::move(image_wrapper_)]() {
if (!image_wrapper) {
return;
}
image_wrapper->Unregister();
image_wrapper->DeleteTexture();
});
}
// |DlImage|
sk_sp<SkImage> DlDeferredImageGPU::skia_image() const {
return image_wrapper_ ? image_wrapper_->CreateSkiaImage() : nullptr;
};
// |DlImage|
std::shared_ptr<impeller::Texture> DlDeferredImageGPU::impeller_texture()
const {
return nullptr;
}
// |DlImage|
bool DlDeferredImageGPU::isOpaque() const {
return image_wrapper_ ? image_wrapper_->image_info().isOpaque() : false;
}
// |DlImage|
bool DlDeferredImageGPU::isTextureBacked() const {
return image_wrapper_ ? image_wrapper_->isTextureBacked() : false;
}
// |DlImage|
SkISize DlDeferredImageGPU::dimensions() const {
return image_wrapper_ ? image_wrapper_->image_info().dimensions()
: SkISize::MakeEmpty();
}
// |DlImage|
size_t DlDeferredImageGPU::GetApproximateByteSize() const {
return sizeof(this) + (image_wrapper_
? image_wrapper_->image_info().computeMinByteSize()
: 0);
}
std::optional<std::string> DlDeferredImageGPU::get_error() const {
return image_wrapper_ ? image_wrapper_->get_error() : std::nullopt;
}
std::shared_ptr<DlDeferredImageGPU::ImageWrapper>
DlDeferredImageGPU::ImageWrapper::Make(
const SkImageInfo& image_info,
sk_sp<DisplayList> display_list,
fml::WeakPtr<SnapshotDelegate> snapshot_delegate,
fml::RefPtr<fml::TaskRunner> raster_task_runner,
fml::RefPtr<SkiaUnrefQueue> unref_queue) {
auto wrapper = std::shared_ptr<ImageWrapper>(new ImageWrapper(
image_info, std::move(display_list), std::move(snapshot_delegate),
std::move(raster_task_runner), std::move(unref_queue)));
wrapper->SnapshotDisplayList();
return wrapper;
}
std::shared_ptr<DlDeferredImageGPU::ImageWrapper>
DlDeferredImageGPU::ImageWrapper::MakeFromLayerTree(
const SkImageInfo& image_info,
std::shared_ptr<LayerTree> layer_tree,
fml::WeakPtr<SnapshotDelegate> snapshot_delegate,
fml::RefPtr<fml::TaskRunner> raster_task_runner,
fml::RefPtr<SkiaUnrefQueue> unref_queue) {
auto wrapper = std::shared_ptr<ImageWrapper>(
new ImageWrapper(image_info, nullptr, std::move(snapshot_delegate),
std::move(raster_task_runner), std::move(unref_queue)));
wrapper->SnapshotDisplayList(std::move(layer_tree));
return wrapper;
}
DlDeferredImageGPU::ImageWrapper::ImageWrapper(
const SkImageInfo& image_info,
sk_sp<DisplayList> display_list,
fml::WeakPtr<SnapshotDelegate> snapshot_delegate,
fml::RefPtr<fml::TaskRunner> raster_task_runner,
fml::RefPtr<SkiaUnrefQueue> unref_queue)
: image_info_(image_info),
display_list_(std::move(display_list)),
snapshot_delegate_(std::move(snapshot_delegate)),
raster_task_runner_(std::move(raster_task_runner)),
unref_queue_(std::move(unref_queue)) {}
void DlDeferredImageGPU::ImageWrapper::OnGrContextCreated() {
FML_DCHECK(raster_task_runner_->RunsTasksOnCurrentThread());
SnapshotDisplayList();
}
void DlDeferredImageGPU::ImageWrapper::OnGrContextDestroyed() {
FML_DCHECK(raster_task_runner_->RunsTasksOnCurrentThread());
DeleteTexture();
}
sk_sp<SkImage> DlDeferredImageGPU::ImageWrapper::CreateSkiaImage() const {
FML_DCHECK(raster_task_runner_->RunsTasksOnCurrentThread());
if (texture_.isValid() && context_) {
return SkImage::MakeFromTexture(
context_.get(), texture_, kTopLeft_GrSurfaceOrigin,
image_info_.colorType(), image_info_.alphaType(),
image_info_.refColorSpace());
}
return image_;
}
bool DlDeferredImageGPU::ImageWrapper::isTextureBacked() const {
return texture_.isValid();
}
void DlDeferredImageGPU::ImageWrapper::SnapshotDisplayList(
std::shared_ptr<LayerTree> layer_tree) {
fml::TaskRunner::RunNowOrPostTask(
raster_task_runner_,
[weak_this = weak_from_this(), layer_tree = std::move(layer_tree)]() {
auto wrapper = weak_this.lock();
if (!wrapper) {
return;
}
auto snapshot_delegate = wrapper->snapshot_delegate_;
if (!snapshot_delegate) {
return;
}
if (layer_tree) {
auto display_list =
layer_tree->Flatten(SkRect::MakeWH(wrapper->image_info_.width(),
wrapper->image_info_.height()),
snapshot_delegate->GetTextureRegistry(),
snapshot_delegate->GetGrContext());
wrapper->display_list_ = std::move(display_list);
}
auto result = snapshot_delegate->MakeGpuImage(wrapper->display_list_,
wrapper->image_info_);
if (result->texture.isValid()) {
wrapper->texture_ = result->texture;
wrapper->context_ = std::move(result->context);
wrapper->texture_registry_ =
wrapper->snapshot_delegate_->GetTextureRegistry();
wrapper->texture_registry_->RegisterContextListener(
reinterpret_cast<uintptr_t>(wrapper.get()), weak_this);
} else if (result->image) {
wrapper->image_ = std::move(result->image);
} else {
std::scoped_lock lock(wrapper->error_mutex_);
wrapper->error_ = std::move(result->error);
}
});
}
std::optional<std::string> DlDeferredImageGPU::ImageWrapper::get_error() {
std::scoped_lock lock(error_mutex_);
return error_;
}
void DlDeferredImageGPU::ImageWrapper::Unregister() {
if (texture_registry_) {
texture_registry_->UnregisterContextListener(
reinterpret_cast<uintptr_t>(this));
}
}
void DlDeferredImageGPU::ImageWrapper::DeleteTexture() {
if (texture_.isValid()) {
unref_queue_->DeleteTexture(std::move(texture_));
texture_ = GrBackendTexture();
}
image_.reset();
context_.reset();
}
} // namespace flutter