Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
Public Member Functions | Static Public Member Functions | List of all members
flutter::ImageDecoderSkia Class Referencefinal

#include <image_decoder_skia.h>

Inheritance diagram for flutter::ImageDecoderSkia:
flutter::ImageDecoder

Public Member Functions

 ImageDecoderSkia (const TaskRunners &runners, std::shared_ptr< fml::ConcurrentTaskRunner > concurrent_task_runner, fml::WeakPtr< IOManager > io_manager)
 
 ~ImageDecoderSkia () override
 
void Decode (fml::RefPtr< ImageDescriptor > descriptor, uint32_t target_width, uint32_t target_height, const ImageResult &result) override
 
- Public Member Functions inherited from flutter::ImageDecoder
virtual ~ImageDecoder ()
 
fml::WeakPtr< ImageDecoderGetWeakPtr () const
 

Static Public Member Functions

static sk_sp< SkImageImageFromCompressedData (ImageDescriptor *descriptor, uint32_t target_width, uint32_t target_height, const fml::tracing::TraceFlow &flow)
 
- Static Public Member Functions inherited from flutter::ImageDecoder
static std::unique_ptr< ImageDecoderMake (const Settings &settings, const TaskRunners &runners, std::shared_ptr< fml::ConcurrentTaskRunner > concurrent_task_runner, fml::WeakPtr< IOManager > io_manager, const std::shared_ptr< fml::SyncSwitch > &gpu_disabled_switch)
 

Additional Inherited Members

- Public Types inherited from flutter::ImageDecoder
using ImageResult = std::function< void(sk_sp< DlImage >, std::string)>
 
- Protected Member Functions inherited from flutter::ImageDecoder
 ImageDecoder (const TaskRunners &runners, std::shared_ptr< fml::ConcurrentTaskRunner > concurrent_task_runner, fml::WeakPtr< IOManager > io_manager)
 
- Protected Attributes inherited from flutter::ImageDecoder
TaskRunners runners_
 
std::shared_ptr< fml::ConcurrentTaskRunnerconcurrent_task_runner_
 
fml::WeakPtr< IOManagerio_manager_
 

Detailed Description

Definition at line 13 of file image_decoder_skia.h.

Constructor & Destructor Documentation

◆ ImageDecoderSkia()

flutter::ImageDecoderSkia::ImageDecoderSkia ( const TaskRunners runners,
std::shared_ptr< fml::ConcurrentTaskRunner concurrent_task_runner,
fml::WeakPtr< IOManager io_manager 
)

Definition at line 18 of file image_decoder_skia.cc.

22 : ImageDecoder(runners,
23 std::move(concurrent_task_runner),
24 std::move(io_manager)) {}
ImageDecoder(const TaskRunners &runners, std::shared_ptr< fml::ConcurrentTaskRunner > concurrent_task_runner, fml::WeakPtr< IOManager > io_manager)

◆ ~ImageDecoderSkia()

flutter::ImageDecoderSkia::~ImageDecoderSkia ( )
overridedefault

Member Function Documentation

◆ Decode()

void flutter::ImageDecoderSkia::Decode ( fml::RefPtr< ImageDescriptor descriptor,
uint32_t  target_width,
uint32_t  target_height,
const ImageResult result 
)
overridevirtual

Implements flutter::ImageDecoder.

Definition at line 220 of file image_decoder_skia.cc.

223 {
224 TRACE_EVENT0("flutter", __FUNCTION__);
225 fml::tracing::TraceFlow flow(__FUNCTION__);
226
227 // ImageDescriptors have Dart peers that must be collected on the UI thread.
228 // However, closures in MakeCopyable below capture the descriptor. The
229 // captures of copyable closures may be collected on any of the thread
230 // participating in task execution.
231 //
232 // To avoid this issue, we resort to manually reference counting the
233 // descriptor. Since all task flows invoke the `result` callback, the raw
234 // descriptor is retained in the beginning and released in the `result`
235 // callback.
236 //
237 // `ImageDecoder::Decode` itself is invoked on the UI thread, so the
238 // collection of the smart pointer from which we obtained the raw descriptor
239 // is fine in this scope.
240 auto raw_descriptor = descriptor_ref_ptr.get();
241 raw_descriptor->AddRef();
242
245
246 // Always service the callback (and cleanup the descriptor) on the UI thread.
247 auto result =
248 [callback, raw_descriptor, ui_runner = runners_.GetUITaskRunner()](
249 SkiaGPUObject<SkImage> image, fml::tracing::TraceFlow flow) {
250 ui_runner->PostTask(fml::MakeCopyable(
251 [callback, raw_descriptor, image = std::move(image),
252 flow = std::move(flow)]() mutable {
253 // We are going to terminate the trace flow here. Flows cannot
254 // terminate without a base trace. Add one explicitly.
255 TRACE_EVENT0("flutter", "ImageDecodeCallback");
256 flow.End();
257 callback(DlImageGPU::Make(std::move(image)), {});
258 raw_descriptor->Release();
259 }));
260 };
261
262 if (!raw_descriptor->data() || raw_descriptor->data()->size() == 0) {
263 result({}, std::move(flow));
264 return;
265 }
266
267 concurrent_task_runner_->PostTask(
268 fml::MakeCopyable([raw_descriptor, //
269 io_manager = io_manager_, //
270 io_runner = runners_.GetIOTaskRunner(), //
271 result, //
272 target_width = target_width, //
273 target_height = target_height, //
274 flow = std::move(flow) //
275 ]() mutable {
276 // Step 1: Decompress the image.
277 // On Worker.
278
279 auto decompressed = raw_descriptor->is_compressed()
280 ? ImageFromCompressedData(raw_descriptor, //
281 target_width, //
282 target_height, //
283 flow)
284 : ImageFromDecompressedData(raw_descriptor, //
285 target_width, //
286 target_height, //
287 flow);
288
289 if (!decompressed) {
290 FML_DLOG(ERROR) << "Could not decompress image.";
291 result({}, std::move(flow));
292 return;
293 }
294
295 // Step 2: Update the image to the GPU.
296 // On IO Thread.
297
298 io_runner->PostTask(fml::MakeCopyable([io_manager, decompressed, result,
299 flow =
300 std::move(flow)]() mutable {
301 if (!io_manager) {
302 FML_DLOG(ERROR) << "Could not acquire IO manager.";
303 result({}, std::move(flow));
304 return;
305 }
306
307 // If the IO manager does not have a resource context, the caller
308 // might not have set one or a software backend could be in use.
309 // Either way, just return the image as-is.
310 if (!io_manager->GetResourceContext()) {
311 result({std::move(decompressed), io_manager->GetSkiaUnrefQueue()},
312 std::move(flow));
313 return;
314 }
315
316 auto uploaded =
317 UploadRasterImage(std::move(decompressed), io_manager, flow);
318
319 if (!uploaded.skia_object()) {
320 FML_DLOG(ERROR) << "Could not upload image to the GPU.";
321 result({}, std::move(flow));
322 return;
323 }
324
325 // Finally, all done.
326 result(std::move(uploaded), std::move(flow));
327 }));
328 }));
329}
static sk_sp< DlImageGPU > Make(SkiaGPUObject< SkImage > image)
std::shared_ptr< fml::ConcurrentTaskRunner > concurrent_task_runner_
fml::WeakPtr< IOManager > io_manager_
fml::RefPtr< fml::TaskRunner > GetUITaskRunner() const
fml::RefPtr< fml::TaskRunner > GetIOTaskRunner() const
virtual bool RunsTasksOnCurrentThread()
sk_sp< SkImage > image
Definition examples.cpp:29
if(end==-1)
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
GAsyncResult * result
#define FML_DLOG(severity)
Definition logging.h:102
#define FML_DCHECK(condition)
Definition logging.h:103
static SkiaGPUObject< SkImage > UploadRasterImage(sk_sp< SkImage > image, const fml::WeakPtr< IOManager > &io_manager, const fml::tracing::TraceFlow &flow)
internal::CopyableLambda< T > MakeCopyable(T lambda)
#define ERROR(message)
#define TRACE_EVENT0(category_group, name)

◆ ImageFromCompressedData()

sk_sp< SkImage > flutter::ImageDecoderSkia::ImageFromCompressedData ( ImageDescriptor descriptor,
uint32_t  target_width,
uint32_t  target_height,
const fml::tracing::TraceFlow flow 
)
static

Definition at line 100 of file image_decoder_skia.cc.

104 {
105 TRACE_EVENT0("flutter", __FUNCTION__);
106 flow.Step(__FUNCTION__);
107
108 if (!descriptor->should_resize(target_width, target_height)) {
109 // No resizing requested. Just decode & rasterize the image.
110 sk_sp<SkImage> image = descriptor->image();
111 return image ? image->makeRasterImage() : nullptr;
112 }
113
114 const SkISize source_dimensions = descriptor->image_info().dimensions();
115 const SkISize resized_dimensions = {static_cast<int32_t>(target_width),
116 static_cast<int32_t>(target_height)};
117
118 auto decode_dimensions = descriptor->get_scaled_dimensions(
119 std::max(static_cast<float>(resized_dimensions.width()) /
120 source_dimensions.width(),
121 static_cast<float>(resized_dimensions.height()) /
122 source_dimensions.height()));
123
124 // If the codec supports efficient sub-pixel decoding, decoded at a resolution
125 // close to the target resolution before resizing.
126 if (decode_dimensions != source_dimensions) {
127 auto scaled_image_info =
128 descriptor->image_info().makeDimensions(decode_dimensions);
129
130 SkBitmap scaled_bitmap;
131 if (!scaled_bitmap.tryAllocPixels(scaled_image_info)) {
132 FML_LOG(ERROR) << "Failed to allocate memory for bitmap of size "
133 << scaled_image_info.computeMinByteSize() << "B";
134 return nullptr;
135 }
136
137 const auto& pixmap = scaled_bitmap.pixmap();
138 if (descriptor->get_pixels(pixmap)) {
139 // Marking this as immutable makes the MakeFromBitmap call share
140 // the pixels instead of copying.
141 scaled_bitmap.setImmutable();
142
143 auto decoded_image = SkImages::RasterFromBitmap(scaled_bitmap);
144 FML_DCHECK(decoded_image);
145 if (!decoded_image) {
147 << "Could not create a scaled image from a scaled bitmap.";
148 return nullptr;
149 }
150 return ResizeRasterImage(decoded_image, resized_dimensions, flow);
151 }
152 }
153
154 auto image = descriptor->image();
155 if (!image) {
156 return nullptr;
157 }
158
159 return ResizeRasterImage(image, resized_dimensions, flow);
160}
void setImmutable()
Definition SkBitmap.cpp:400
const SkPixmap & pixmap() const
Definition SkBitmap.h:133
bool tryAllocPixels(const SkImageInfo &info, size_t rowBytes)
Definition SkBitmap.cpp:271
sk_sp< SkImage > makeRasterImage(GrDirectContext *, CachingHint cachingHint=kDisallow_CachingHint) const
Definition SkImage.cpp:267
void Step(const char *label=nullptr) const
#define FML_LOG(severity)
Definition logging.h:82
SK_API sk_sp< SkImage > RasterFromBitmap(const SkBitmap &bitmap)
static sk_sp< SkImage > ResizeRasterImage(const sk_sp< SkImage > &image, const SkISize &resized_dimensions, const fml::tracing::TraceFlow &flow)
constexpr int32_t width() const
Definition SkSize.h:36
constexpr int32_t height() const
Definition SkSize.h:37

The documentation for this class was generated from the following files: