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(
89 FML_LOG(ERROR) <<
"Could not create image from decompressed bytes.";
93 if (!target_width && !target_height) {
95 return image->makeRasterImage(
nullptr);
104 uint32_t target_width,
105 uint32_t target_height,
108 flow.
Step(__FUNCTION__);
110 if (!descriptor->
should_resize(target_width, target_height)) {
113 return image ?
image->makeRasterImage(
nullptr) :
nullptr;
116 const SkISize source_dimensions = descriptor->
image_info().dimensions();
117 const SkISize resized_dimensions = {
static_cast<int32_t
>(target_width),
118 static_cast<int32_t
>(target_height)};
121 std::max(
static_cast<float>(resized_dimensions.width()) /
122 source_dimensions.width(),
123 static_cast<float>(resized_dimensions.height()) /
124 source_dimensions.height()));
128 if (decode_dimensions != source_dimensions) {
129 auto scaled_image_info =
130 descriptor->
image_info().makeDimensions(decode_dimensions);
132 SkBitmap scaled_bitmap;
133 if (!scaled_bitmap.tryAllocPixels(scaled_image_info)) {
134 FML_LOG(ERROR) <<
"Failed to allocate memory for bitmap of size "
135 << scaled_image_info.computeMinByteSize() <<
"B";
139 const auto& pixmap = scaled_bitmap.pixmap();
143 scaled_bitmap.setImmutable();
145 auto decoded_image = SkImages::RasterFromBitmap(scaled_bitmap);
147 if (!decoded_image) {
149 <<
"Could not create a scaled image from a scaled bitmap.";
165 sk_sp<SkImage>
image,
169 flow.
Step(__FUNCTION__);
175 if (!io_manager->GetResourceContext() || !io_manager->GetSkiaUnrefQueue()) {
177 <<
"Could not acquire context of release queue for texture upload.";
182 if (!
image->peekPixels(&pixmap)) {
183 FML_LOG(ERROR) <<
"Could not peek pixels of image for texture upload.";
188 io_manager->GetIsGpuDisabledSyncSwitch()->Execute(
190 .SetIfTrue([&result, &pixmap, &
image] {
191 SkSafeRef(
image.get());
192 sk_sp<SkImage> texture_image = SkImages::RasterFromPixmap(
194 [](
const void* pixels, SkImages::ReleaseContext context) {
195 SkSafeUnref(
static_cast<SkImage*
>(context));
198 result = {std::move(texture_image),
nullptr};
200 .SetIfFalse([&result, context = io_manager->GetResourceContext(),
201 &pixmap,
queue = io_manager->GetSkiaUnrefQueue()] {
202 TRACE_EVENT0(
"flutter",
"MakeCrossContextImageFromPixmap");
203 sk_sp<SkImage> texture_image =
204 SkImages::CrossContextTextureFromPixmap(
210 if (!texture_image) {
211 FML_LOG(ERROR) <<
"Could not make x-context image.";
214 result = {std::move(texture_image),
queue};
223 uint32_t target_width,
224 uint32_t target_height,
242 auto raw_descriptor = descriptor_ref_ptr.
get();
243 raw_descriptor->AddRef();
254 flow = std::move(flow)]()
mutable {
260 raw_descriptor->Release();
264 if (!raw_descriptor->data() || raw_descriptor->data()->size() == 0) {
265 result({}, std::move(flow));
274 target_width = target_width,
275 target_height = target_height,
276 flow = std::move(flow)
281 auto decompressed = raw_descriptor->is_compressed()
282 ? ImageFromCompressedData(raw_descriptor,
286 : ImageFromDecompressedData(raw_descriptor,
292 FML_DLOG(ERROR) <<
"Could not decompress image.";
293 result({}, std::move(flow));
302 std::move(flow)]()
mutable {
304 FML_DLOG(ERROR) <<
"Could not acquire IO manager.";
305 result({}, std::move(flow));
312 if (!io_manager->GetResourceContext()) {
313 result({std::move(decompressed), io_manager->GetSkiaUnrefQueue()},
321 if (!uploaded.skia_object()) {
322 FML_DLOG(ERROR) <<
"Could not upload image to the GPU.";
323 result({}, std::move(flow));
328 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)
void Decode(fml::RefPtr< ImageDescriptor > descriptor, uint32_t target_width, uint32_t target_height, const ImageResult &result) override
~ImageDecoderSkia() override
static sk_sp< SkImage > ImageFromCompressedData(ImageDescriptor *descriptor, uint32_t target_width, uint32_t target_height, const fml::tracing::TraceFlow &flow)
Creates an image descriptor for encoded or decoded image data, describing the width,...
sk_sp< SkImage > image() const
const SkImageInfo & image_info() const
The orientation corrected image info for this image.
SkISize get_scaled_dimensions(float scale)
Gets the scaled dimensions of this image, if backed by an ImageGenerator that can perform efficient s...
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.
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)