@@ -107,16 +107,17 @@ static SkAlphaType ChooseCompatibleAlphaType(SkAlphaType type) {
107107 return type;
108108}
109109
110- std::optional< DecompressResult> ImageDecoderImpeller::DecompressTexture (
110+ DecompressResult ImageDecoderImpeller::DecompressTexture (
111111 ImageDescriptor* descriptor,
112112 SkISize target_size,
113113 impeller::ISize max_texture_size,
114114 bool supports_wide_gamut,
115115 const std::shared_ptr<impeller::Allocator>& allocator) {
116116 TRACE_EVENT0 (" impeller" , __FUNCTION__);
117117 if (!descriptor) {
118- FML_DLOG (ERROR) << " Invalid descriptor." ;
119- return std::nullopt ;
118+ std::string decode_error (" Invalid descriptor (should never happen)" );
119+ FML_DLOG (ERROR) << decode_error;
120+ return DecompressResult{.decode_error = decode_error};
120121 }
121122
122123 target_size.set (std::min (static_cast <int32_t >(max_texture_size.width ),
@@ -162,8 +163,11 @@ std::optional<DecompressResult> ImageDecoderImpeller::DecompressTexture(
162163 const auto pixel_format =
163164 impeller::skia_conversions::ToPixelFormat (image_info.colorType ());
164165 if (!pixel_format.has_value ()) {
165- FML_DLOG (ERROR) << " Codec pixel format not supported by Impeller." ;
166- return std::nullopt ;
166+ std::string decode_error (impeller::SPrintF (
167+ " Codec pixel format is not supported (SkColorType=%d)" ,
168+ image_info.colorType ()));
169+ FML_DLOG (ERROR) << decode_error;
170+ return DecompressResult{.decode_error = decode_error};
167171 }
168172
169173 auto bitmap = std::make_shared<SkBitmap>();
@@ -172,14 +176,16 @@ std::optional<DecompressResult> ImageDecoderImpeller::DecompressTexture(
172176
173177 if (descriptor->is_compressed ()) {
174178 if (!bitmap->tryAllocPixels (bitmap_allocator.get ())) {
175- FML_DLOG (ERROR)
176- << " Could not allocate intermediate for image decompression." ;
177- return std::nullopt ;
179+ std::string decode_error (
180+ " Could not allocate intermediate for image decompression." );
181+ FML_DLOG (ERROR) << decode_error;
182+ return DecompressResult{.decode_error = decode_error};
178183 }
179184 // Decode the image into the image generator's closest supported size.
180185 if (!descriptor->get_pixels (bitmap->pixmap ())) {
181- FML_DLOG (ERROR) << " Could not decompress image." ;
182- return std::nullopt ;
186+ std::string decode_error (" Could not decompress image." );
187+ FML_DLOG (ERROR) << decode_error;
188+ return DecompressResult{.decode_error = decode_error};
183189 }
184190 } else {
185191 auto temp_bitmap = std::make_shared<SkBitmap>();
@@ -189,9 +195,10 @@ std::optional<DecompressResult> ImageDecoderImpeller::DecompressTexture(
189195 temp_bitmap->setPixelRef (pixel_ref, 0 , 0 );
190196
191197 if (!bitmap->tryAllocPixels (bitmap_allocator.get ())) {
192- FML_DLOG (ERROR)
193- << " Could not allocate intermediate for pixel conversion." ;
194- return std::nullopt ;
198+ std::string decode_error (
199+ " Could not allocate intermediate for pixel conversion." );
200+ FML_DLOG (ERROR) << decode_error;
201+ return DecompressResult{.decode_error = decode_error};
195202 }
196203 temp_bitmap->readPixels (bitmap->pixmap ());
197204 bitmap->setImmutable ();
@@ -200,7 +207,7 @@ std::optional<DecompressResult> ImageDecoderImpeller::DecompressTexture(
200207 if (bitmap->dimensions () == target_size) {
201208 auto buffer = bitmap_allocator->GetDeviceBuffer ();
202209 if (!buffer.has_value ()) {
203- return std:: nullopt ;
210+ return DecompressResult{. decode_error = " Unable to get device buffer " } ;
204211 }
205212 return DecompressResult{.device_buffer = buffer.value (),
206213 .sk_bitmap = bitmap,
@@ -218,9 +225,10 @@ std::optional<DecompressResult> ImageDecoderImpeller::DecompressTexture(
218225 auto scaled_allocator = std::make_shared<ImpellerAllocator>(allocator);
219226 scaled_bitmap->setInfo (scaled_image_info);
220227 if (!scaled_bitmap->tryAllocPixels (scaled_allocator.get ())) {
221- FML_LOG (ERROR)
222- << " Could not allocate scaled bitmap for image decompression." ;
223- return std::nullopt ;
228+ std::string decode_error (
229+ " Could not allocate scaled bitmap for image decompression." );
230+ FML_DLOG (ERROR) << decode_error;
231+ return DecompressResult{.decode_error = decode_error};
224232 }
225233 if (!bitmap->pixmap ().scalePixels (
226234 scaled_bitmap->pixmap (),
@@ -231,26 +239,32 @@ std::optional<DecompressResult> ImageDecoderImpeller::DecompressTexture(
231239
232240 auto buffer = scaled_allocator->GetDeviceBuffer ();
233241 if (!buffer.has_value ()) {
234- return std:: nullopt ;
242+ return DecompressResult{. decode_error = " Unable to get device buffer " } ;
235243 }
236244 return DecompressResult{.device_buffer = buffer.value (),
237245 .sk_bitmap = scaled_bitmap,
238246 .image_info = scaled_bitmap->info ()};
239247}
240248
241- sk_sp<DlImage> ImageDecoderImpeller::UploadTextureToPrivate (
249+ std::pair<sk_sp<DlImage>, std::string>
250+ ImageDecoderImpeller::UploadTextureToPrivate (
242251 const std::shared_ptr<impeller::Context>& context,
243252 const std::shared_ptr<impeller::DeviceBuffer>& buffer,
244253 const SkImageInfo& image_info) {
245254 TRACE_EVENT0 (" impeller" , __FUNCTION__);
246- if (!context || !buffer) {
247- return nullptr ;
255+ if (!context) {
256+ return std::make_pair (nullptr , " No Impeller context is available" );
257+ }
258+ if (!buffer) {
259+ return std::make_pair (nullptr , " No Impeller device buffer is available" );
248260 }
249261 const auto pixel_format =
250262 impeller::skia_conversions::ToPixelFormat (image_info.colorType ());
251263 if (!pixel_format) {
252- FML_DLOG (ERROR) << " Pixel format unsupported by Impeller." ;
253- return nullptr ;
264+ std::string decode_error (impeller::SPrintF (
265+ " Unsupported pixel format (SkColorType=%d)" , image_info.colorType ()));
266+ FML_DLOG (ERROR) << decode_error;
267+ return std::make_pair (nullptr , decode_error);
254268 }
255269
256270 impeller::TextureDescriptor texture_descriptor;
@@ -263,24 +277,29 @@ sk_sp<DlImage> ImageDecoderImpeller::UploadTextureToPrivate(
263277 auto dest_texture =
264278 context->GetResourceAllocator ()->CreateTexture (texture_descriptor);
265279 if (!dest_texture) {
266- FML_DLOG (ERROR) << " Could not create Impeller texture." ;
267- return nullptr ;
280+ std::string decode_error (" Could not create Impeller texture." );
281+ FML_DLOG (ERROR) << decode_error;
282+ return std::make_pair (nullptr , decode_error);
268283 }
269284
270285 dest_texture->SetLabel (
271286 impeller::SPrintF (" ui.Image(%p)" , dest_texture.get ()).c_str ());
272287
273288 auto command_buffer = context->CreateCommandBuffer ();
274289 if (!command_buffer) {
275- FML_DLOG (ERROR) << " Could not create command buffer for mipmap generation." ;
276- return nullptr ;
290+ std::string decode_error (
291+ " Could not create command buffer for mipmap generation." );
292+ FML_DLOG (ERROR) << decode_error;
293+ return std::make_pair (nullptr , decode_error);
277294 }
278295 command_buffer->SetLabel (" Mipmap Command Buffer" );
279296
280297 auto blit_pass = command_buffer->CreateBlitPass ();
281298 if (!blit_pass) {
282- FML_DLOG (ERROR) << " Could not create blit pass for mipmap generation." ;
283- return nullptr ;
299+ std::string decode_error (
300+ " Could not create blit pass for mipmap generation." );
301+ FML_DLOG (ERROR) << decode_error;
302+ return std::make_pair (nullptr , decode_error);
284303 }
285304 blit_pass->SetLabel (" Mipmap Blit Pass" );
286305 blit_pass->AddCopy (buffer->AsBufferView (), dest_texture);
@@ -290,27 +309,35 @@ sk_sp<DlImage> ImageDecoderImpeller::UploadTextureToPrivate(
290309
291310 blit_pass->EncodeCommands (context->GetResourceAllocator ());
292311 if (!command_buffer->SubmitCommands ()) {
293- FML_DLOG (ERROR) << " Failed to submit blit pass command buffer." ;
294- return nullptr ;
312+ std::string decode_error (" Failed to submit blit pass command buffer." );
313+ FML_DLOG (ERROR) << decode_error;
314+ return std::make_pair (nullptr , decode_error);
295315 }
296316
297- return impeller::DlImageImpeller::Make (std::move (dest_texture));
317+ return std::make_pair (
318+ impeller::DlImageImpeller::Make (std::move (dest_texture)), std::string ());
298319}
299320
300- sk_sp<DlImage> ImageDecoderImpeller::UploadTextureToShared (
321+ std::pair<sk_sp<DlImage>, std::string>
322+ ImageDecoderImpeller::UploadTextureToShared (
301323 const std::shared_ptr<impeller::Context>& context,
302324 std::shared_ptr<SkBitmap> bitmap,
303325 bool create_mips) {
304326 TRACE_EVENT0 (" impeller" , __FUNCTION__);
305- if (!context || !bitmap) {
306- return nullptr ;
327+ if (!context) {
328+ return std::make_pair (nullptr , " No Impeller context is available" );
329+ }
330+ if (!bitmap) {
331+ return std::make_pair (nullptr , " No texture bitmap is available" );
307332 }
308333 const auto image_info = bitmap->info ();
309334 const auto pixel_format =
310335 impeller::skia_conversions::ToPixelFormat (image_info.colorType ());
311336 if (!pixel_format) {
312- FML_DLOG (ERROR) << " Pixel format unsupported by Impeller." ;
313- return nullptr ;
337+ std::string decode_error (impeller::SPrintF (
338+ " Unsupported pixel format (SkColorType=%d)" , image_info.colorType ()));
339+ FML_DLOG (ERROR) << decode_error;
340+ return std::make_pair (nullptr , decode_error);
314341 }
315342
316343 impeller::TextureDescriptor texture_descriptor;
@@ -323,8 +350,9 @@ sk_sp<DlImage> ImageDecoderImpeller::UploadTextureToShared(
323350 auto texture =
324351 context->GetResourceAllocator ()->CreateTexture (texture_descriptor);
325352 if (!texture) {
326- FML_DLOG (ERROR) << " Could not create Impeller texture." ;
327- return nullptr ;
353+ std::string decode_error (" Could not create Impeller texture." );
354+ FML_DLOG (ERROR) << decode_error;
355+ return std::make_pair (nullptr , decode_error);
328356 }
329357
330358 auto mapping = std::make_shared<fml::NonOwnedMapping>(
@@ -334,38 +362,44 @@ sk_sp<DlImage> ImageDecoderImpeller::UploadTextureToShared(
334362 );
335363
336364 if (!texture->SetContents (mapping)) {
337- FML_DLOG (ERROR) << " Could not copy contents into Impeller texture." ;
338- return nullptr ;
365+ std::string decode_error (" Could not copy contents into Impeller texture." );
366+ FML_DLOG (ERROR) << decode_error;
367+ return std::make_pair (nullptr , decode_error);
339368 }
340369
341370 texture->SetLabel (impeller::SPrintF (" ui.Image(%p)" , texture.get ()).c_str ());
342371
343372 if (texture_descriptor.mip_count > 1u && create_mips) {
344373 auto command_buffer = context->CreateCommandBuffer ();
345374 if (!command_buffer) {
346- FML_DLOG (ERROR)
347- << " Could not create command buffer for mipmap generation." ;
348- return nullptr ;
375+ std::string decode_error (
376+ " Could not create command buffer for mipmap generation." );
377+ FML_DLOG (ERROR) << decode_error;
378+ return std::make_pair (nullptr , decode_error);
349379 }
350380 command_buffer->SetLabel (" Mipmap Command Buffer" );
351381
352382 auto blit_pass = command_buffer->CreateBlitPass ();
353383 if (!blit_pass) {
354- FML_DLOG (ERROR) << " Could not create blit pass for mipmap generation." ;
355- return nullptr ;
384+ std::string decode_error (
385+ " Could not create blit pass for mipmap generation." );
386+ FML_DLOG (ERROR) << decode_error;
387+ return std::make_pair (nullptr , decode_error);
356388 }
357389 blit_pass->SetLabel (" Mipmap Blit Pass" );
358390 blit_pass->GenerateMipmap (texture);
359391
360392 blit_pass->EncodeCommands (context->GetResourceAllocator ());
361393 if (!command_buffer->SubmitCommands ()) {
362- FML_DLOG (ERROR) << " Failed to submit blit pass command buffer." ;
363- return nullptr ;
394+ std::string decode_error (" Failed to submit blit pass command buffer." );
395+ FML_DLOG (ERROR) << decode_error;
396+ return std::make_pair (nullptr , decode_error);
364397 }
365398 command_buffer->WaitUntilScheduled ();
366399 }
367400
368- return impeller::DlImageImpeller::Make (std::move (texture));
401+ return std::make_pair (impeller::DlImageImpeller::Make (std::move (texture)),
402+ std::string ());
369403}
370404
371405// |ImageDecoder|
@@ -382,10 +416,10 @@ void ImageDecoderImpeller::Decode(fml::RefPtr<ImageDescriptor> descriptor,
382416 ImageResult result = [p_result, //
383417 raw_descriptor, //
384418 ui_runner = runners_.GetUITaskRunner () //
385- ](auto image) {
386- ui_runner->PostTask ([raw_descriptor, p_result, image]() {
419+ ](auto image, auto decode_error ) {
420+ ui_runner->PostTask ([raw_descriptor, p_result, image, decode_error ]() {
387421 raw_descriptor->Release ();
388- p_result (std::move (image));
422+ p_result (std::move (image), decode_error );
389423 });
390424 };
391425
@@ -398,7 +432,7 @@ void ImageDecoderImpeller::Decode(fml::RefPtr<ImageDescriptor> descriptor,
398432 supports_wide_gamut = supports_wide_gamut_ //
399433 ]() {
400434 if (!context) {
401- result (nullptr );
435+ result (nullptr , " No Impeller context is available " );
402436 return ;
403437 }
404438 auto max_size_supported =
@@ -408,21 +442,24 @@ void ImageDecoderImpeller::Decode(fml::RefPtr<ImageDescriptor> descriptor,
408442 auto bitmap_result = DecompressTexture (
409443 raw_descriptor, target_size, max_size_supported,
410444 supports_wide_gamut, context->GetResourceAllocator ());
411- if (!bitmap_result.has_value () ) {
412- result (nullptr );
445+ if (!bitmap_result.device_buffer ) {
446+ result (nullptr , bitmap_result. decode_error );
413447 return ;
414448 }
415449 auto upload_texture_and_invoke_result = [result, context,
416- bitmap_result =
417- bitmap_result.value ()]() {
418- // TODO(jonahwilliams): remove ifdef once blit from buffer to texture is
419- // implemented on other platforms.
450+ bitmap_result]() {
451+ // TODO(jonahwilliams): remove ifdef once blit from buffer to
452+ // texture is implemented on other platforms.
453+ sk_sp<DlImage> image;
454+ std::string decode_error;
420455#if (FML_OS_IOS && !TARGET_IPHONE_SIMULATOR)
421- result ( UploadTextureToPrivate (context, bitmap_result. device_buffer ,
422- bitmap_result.image_info ) );
456+ std::tie (image, decode_error) = UploadTextureToPrivate (
457+ context, bitmap_result. device_buffer , bitmap_result.image_info );
423458#else
424- result (UploadTextureToShared (context, bitmap_result.sk_bitmap ));
459+ std::tie (image, decode_error) =
460+ UploadTextureToShared (context, bitmap_result.sk_bitmap );
425461#endif
462+ result (image, decode_error);
426463 };
427464 // TODO(jonahwilliams): https://github.com/flutter/flutter/issues/123058
428465 // Technically we don't need to post tasks to the io runner, but without
0 commit comments