blob: 7996c2b20bbac06a14b67f86f2648351d71f7c3a [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/image_encoding.h"
#include "flutter/lib/ui/painting/image_encoding_impl.h"
#include "flutter/lib/ui/painting/image.h"
namespace flutter {
void ConvertImageToRasterSkia(
const sk_sp<DlImage>& dl_image,
std::function<void(sk_sp<SkImage>)> encode_task,
const fml::RefPtr<fml::TaskRunner>& raster_task_runner,
const fml::RefPtr<fml::TaskRunner>& io_task_runner,
const fml::WeakPtr<GrDirectContext>& resource_context,
const fml::TaskRunnerAffineWeakPtr<SnapshotDelegate>& snapshot_delegate,
const std::shared_ptr<const fml::SyncSwitch>& is_gpu_disabled_sync_switch) {
// If the owning_context is kRaster, we can't access it on this task runner.
if (dl_image->owning_context() != DlImage::OwningContext::kRaster) {
auto image = dl_image->skia_image();
// Check validity of the image.
if (image == nullptr) {
FML_LOG(ERROR) << "Image was null.";
encode_task(nullptr);
return;
}
auto dimensions = image->dimensions();
if (dimensions.isEmpty()) {
FML_LOG(ERROR) << "Image dimensions were empty.";
encode_task(nullptr);
return;
}
SkPixmap pixmap;
if (image->peekPixels(&pixmap)) {
// This is already a raster image.
encode_task(image);
return;
}
if (sk_sp<SkImage> raster_image = image->makeRasterImage()) {
// The image can be converted to a raster image.
encode_task(raster_image);
return;
}
}
if (!raster_task_runner) {
FML_LOG(ERROR) << "Raster task runner was null.";
encode_task(nullptr);
return;
}
if (!io_task_runner) {
FML_LOG(ERROR) << "IO task runner was null.";
encode_task(nullptr);
return;
}
// Cross-context images do not support makeRasterImage. Convert these images
// by drawing them into a surface. This must be done on the raster thread
// to prevent concurrent usage of the image on both the IO and raster threads.
raster_task_runner->PostTask([dl_image, encode_task = std::move(encode_task),
resource_context, snapshot_delegate,
io_task_runner, is_gpu_disabled_sync_switch,
raster_task_runner]() {
auto image = dl_image->skia_image();
if (!image || !snapshot_delegate) {
io_task_runner->PostTask(
[encode_task = encode_task]() mutable { encode_task(nullptr); });
return;
}
sk_sp<SkImage> raster_image =
snapshot_delegate->ConvertToRasterImage(image);
io_task_runner->PostTask([image, encode_task = encode_task,
raster_image = std::move(raster_image),
resource_context, is_gpu_disabled_sync_switch,
owning_context = dl_image->owning_context(),
raster_task_runner]() mutable {
if (!raster_image) {
// The rasterizer was unable to render the cross-context image
// (presumably because it does not have a GrContext). In that case,
// convert the image on the IO thread using the resource context.
raster_image = ConvertToRasterUsingResourceContext(
image, resource_context, is_gpu_disabled_sync_switch);
}
encode_task(raster_image);
if (owning_context == DlImage::OwningContext::kRaster) {
raster_task_runner->PostTask([image = std::move(image)]() {});
}
});
});
}
} // namespace flutter