14#include "third_party/skia/include/core/SkBitmap.h"
15#include "third_party/skia/include/core/SkImage.h"
16#include "third_party/skia/include/gpu/ganesh/SkImageGanesh.h"
22 std::shared_ptr<fml::ConcurrentTaskRunner> concurrent_task_runner,
25 std::move(concurrent_task_runner),
26 std::move(io_manager)) {}
31 const SkISize& resized_dimensions,
36 flow.
Step(__FUNCTION__);
38 if (resized_dimensions.isEmpty()) {
39 FML_LOG(ERROR) <<
"Could not resize to empty dimensions.";
43 if (
image->dimensions() == resized_dimensions) {
44 return image->makeRasterImage(
nullptr);
47 const auto scaled_image_info =
48 image->imageInfo().makeDimensions(resized_dimensions);
50 SkBitmap scaled_bitmap;
51 if (!scaled_bitmap.tryAllocPixels(scaled_image_info)) {
52 FML_LOG(ERROR) <<
"Failed to allocate memory for bitmap of size "
53 << scaled_image_info.computeMinByteSize() <<
"B";
57 if (!
image->scalePixels(
58 scaled_bitmap.pixmap(),
59 SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kNone),
60 SkImage::kDisallow_CachingHint)) {
61 FML_LOG(ERROR) <<
"Could not scale pixels";
67 scaled_bitmap.setImmutable();
69 auto scaled_image = SkImages::RasterFromBitmap(scaled_bitmap);
71 FML_LOG(ERROR) <<
"Could not create a scaled image from a scaled bitmap.";
80 uint32_t target_width,
81 uint32_t target_height,
84 flow.
Step(__FUNCTION__);
85 auto image = SkImages::RasterFromData(
90 FML_LOG(ERROR) <<
"Could not create image from decompressed bytes.";
94 if (!target_width && !target_height) {
96 return image->makeRasterImage(
nullptr);
105 uint32_t target_width,
106 uint32_t target_height,
109 flow.
Step(__FUNCTION__);
111 if (!descriptor->
should_resize(target_width, target_height)) {
114 return image ?
image->makeRasterImage(
nullptr) :
nullptr;
117 const SkImageInfo image_info =
119 const SkISize source_dimensions = image_info.dimensions();
120 const SkISize resized_dimensions = {
static_cast<int32_t
>(target_width),
121 static_cast<int32_t
>(target_height)};
124 std::max(
static_cast<float>(resized_dimensions.width()) /
125 source_dimensions.width(),
126 static_cast<float>(resized_dimensions.height()) /
127 source_dimensions.height()));
131 if (decode_dimensions != source_dimensions) {
132 auto scaled_image_info = image_info.makeDimensions(decode_dimensions);
134 SkBitmap scaled_bitmap;
135 if (!scaled_bitmap.tryAllocPixels(scaled_image_info)) {
136 FML_LOG(ERROR) <<
"Failed to allocate memory for bitmap of size "
137 << scaled_image_info.computeMinByteSize() <<
"B";
141 const auto& pixmap = scaled_bitmap.pixmap();
145 scaled_bitmap.setImmutable();
147 auto decoded_image = SkImages::RasterFromBitmap(scaled_bitmap);
149 if (!decoded_image) {
151 <<
"Could not create a scaled image from a scaled bitmap.";
167 sk_sp<SkImage>
image,
171 flow.
Step(__FUNCTION__);
177 if (!io_manager->GetResourceContext() || !io_manager->GetSkiaUnrefQueue()) {
179 <<
"Could not acquire context of release queue for texture upload.";
184 if (!
image->peekPixels(&pixmap)) {
185 FML_LOG(ERROR) <<
"Could not peek pixels of image for texture upload.";
190 io_manager->GetIsGpuDisabledSyncSwitch()->Execute(
192 .SetIfTrue([&result, &pixmap, &
image] {
193 SkSafeRef(
image.get());
194 sk_sp<SkImage> texture_image = SkImages::RasterFromPixmap(
196 [](
const void* pixels, SkImages::ReleaseContext context) {
197 SkSafeUnref(
static_cast<SkImage*
>(context));
200 result = {std::move(texture_image),
nullptr};
202 .SetIfFalse([&result, context = io_manager->GetResourceContext(),
203 &pixmap,
queue = io_manager->GetSkiaUnrefQueue()] {
204 TRACE_EVENT0(
"flutter",
"MakeCrossContextImageFromPixmap");
205 sk_sp<SkImage> texture_image =
206 SkImages::CrossContextTextureFromPixmap(
212 if (!texture_image) {
213 FML_LOG(ERROR) <<
"Could not make x-context image.";
216 result = {std::move(texture_image),
queue};
243 auto raw_descriptor = descriptor_ref_ptr.
get();
244 raw_descriptor->AddRef();
255 flow = std::move(flow)]()
mutable {
261 raw_descriptor->Release();
265 if (!raw_descriptor->data() || raw_descriptor->data()->size() == 0) {
266 result({}, std::move(flow));
277 flow = std::move(flow)
282 auto decompressed = raw_descriptor->is_compressed()
283 ? ImageFromCompressedData(raw_descriptor,
287 : ImageFromDecompressedData(raw_descriptor,
293 FML_DLOG(ERROR) <<
"Could not decompress image.";
294 result({}, std::move(flow));
303 std::move(flow)]()
mutable {
305 FML_DLOG(ERROR) <<
"Could not acquire IO manager.";
306 result({}, std::move(flow));
313 if (!io_manager->GetResourceContext()) {
314 result({std::move(decompressed), io_manager->GetSkiaUnrefQueue()},
322 if (!uploaded.skia_object()) {
323 FML_DLOG(ERROR) <<
"Could not upload image to the GPU.";
324 result({}, std::move(flow));
329 result(std::move(uploaded), std::move(flow));
static sk_sp< DlImageGPU > Make(SkiaGPUObject< SkImage > image)
std::function< void(sk_sp< DlImage >, std::string)> ImageResult
std::shared_ptr< fml::ConcurrentTaskRunner > concurrent_task_runner_
fml::WeakPtr< IOManager > io_manager_
ImageDecoderSkia(const TaskRunners &runners, std::shared_ptr< fml::ConcurrentTaskRunner > concurrent_task_runner, fml::WeakPtr< IOManager > io_manager)
~ImageDecoderSkia() override
static sk_sp< SkImage > ImageFromCompressedData(ImageDescriptor *descriptor, uint32_t target_width, uint32_t target_height, const fml::tracing::TraceFlow &flow)
void Decode(fml::RefPtr< ImageDescriptor > descriptor, const Options &options, const ImageResult &result) override
Creates an image descriptor for encoded or decoded image data, describing the width,...
sk_sp< SkImage > image() const
SkISize get_scaled_dimensions(float scale)
Gets the scaled dimensions of this image, if backed by an ImageGenerator that can perform efficient s...
static SkImageInfo ToSkImageInfo(const ImageInfo &image_info)
int row_bytes() const
The byte length of the first row of the image. Defaults to width() * 4.
bool should_resize(int target_width, int target_height) const
Whether the given target_width or target_height differ from width() and height() respectively.
bool get_pixels(const SkPixmap &pixmap) const
Gets pixels for this image transformed based on the EXIF orientation tag, if applicable.
const ImageInfo & image_info() const
The orientation corrected image info for this image.
sk_sp< SkData > data() const
The underlying buffer for this image.
fml::RefPtr< fml::TaskRunner > GetUITaskRunner() const
fml::RefPtr< fml::TaskRunner > GetIOTaskRunner() const
virtual bool RunsTasksOnCurrentThread()
void End(const char *label=nullptr)
void Step(const char *label=nullptr) const
FlutterVulkanImage * image
FlutterDesktopBinaryReply callback
#define FML_DLOG(severity)
#define FML_LOG(severity)
#define FML_DCHECK(condition)
static SkiaGPUObject< SkImage > UploadRasterImage(sk_sp< SkImage > image, const fml::WeakPtr< IOManager > &io_manager, const fml::tracing::TraceFlow &flow)
static sk_sp< SkImage > ResizeRasterImage(const sk_sp< SkImage > &image, const SkISize &resized_dimensions, const fml::tracing::TraceFlow &flow)
static sk_sp< SkImage > ImageFromDecompressedData(ImageDescriptor *descriptor, uint32_t target_width, uint32_t target_height, const fml::tracing::TraceFlow &flow)
internal::CopyableLambda< T > MakeCopyable(T lambda)
Represents the 2 code paths available when calling |SyncSwitchExecute|.
#define TRACE_EVENT0(category_group, name)