@@ -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" );
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,9 @@ 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 (" Codec pixel format not supported by Impeller." );
167+ FML_DLOG (ERROR) << decode_error;
168+ return DecompressResult{.decode_error = decode_error};
167169 }
168170
169171 auto bitmap = std::make_shared<SkBitmap>();
@@ -172,14 +174,16 @@ std::optional<DecompressResult> ImageDecoderImpeller::DecompressTexture(
172174
173175 if (descriptor->is_compressed ()) {
174176 if (!bitmap->tryAllocPixels (bitmap_allocator.get ())) {
175- FML_DLOG (ERROR)
176- << " Could not allocate intermediate for image decompression." ;
177- return std::nullopt ;
177+ std::string decode_error (
178+ " Could not allocate intermediate for image decompression." );
179+ FML_DLOG (ERROR) << decode_error;
180+ return DecompressResult{.decode_error = decode_error};
178181 }
179182 // Decode the image into the image generator's closest supported size.
180183 if (!descriptor->get_pixels (bitmap->pixmap ())) {
181- FML_DLOG (ERROR) << " Could not decompress image." ;
182- return std::nullopt ;
184+ std::string decode_error (" Could not decompress image." );
185+ FML_DLOG (ERROR) << decode_error;
186+ return DecompressResult{.decode_error = decode_error};
183187 }
184188 } else {
185189 auto temp_bitmap = std::make_shared<SkBitmap>();
@@ -189,9 +193,10 @@ std::optional<DecompressResult> ImageDecoderImpeller::DecompressTexture(
189193 temp_bitmap->setPixelRef (pixel_ref, 0 , 0 );
190194
191195 if (!bitmap->tryAllocPixels (bitmap_allocator.get ())) {
192- FML_DLOG (ERROR)
193- << " Could not allocate intermediate for pixel conversion." ;
194- return std::nullopt ;
196+ std::string decode_error (
197+ " Could not allocate intermediate for pixel conversion." );
198+ FML_DLOG (ERROR) << decode_error;
199+ return DecompressResult{.decode_error = decode_error};
195200 }
196201 temp_bitmap->readPixels (bitmap->pixmap ());
197202 bitmap->setImmutable ();
@@ -200,7 +205,7 @@ std::optional<DecompressResult> ImageDecoderImpeller::DecompressTexture(
200205 if (bitmap->dimensions () == target_size) {
201206 auto buffer = bitmap_allocator->GetDeviceBuffer ();
202207 if (!buffer.has_value ()) {
203- return std:: nullopt ;
208+ return DecompressResult{. decode_error = " Unable to get device buffer " } ;
204209 }
205210 return DecompressResult{.device_buffer = buffer.value (),
206211 .sk_bitmap = bitmap,
@@ -218,9 +223,10 @@ std::optional<DecompressResult> ImageDecoderImpeller::DecompressTexture(
218223 auto scaled_allocator = std::make_shared<ImpellerAllocator>(allocator);
219224 scaled_bitmap->setInfo (scaled_image_info);
220225 if (!scaled_bitmap->tryAllocPixels (scaled_allocator.get ())) {
221- FML_LOG (ERROR)
222- << " Could not allocate scaled bitmap for image decompression." ;
223- return std::nullopt ;
226+ std::string decode_error (
227+ " Could not allocate scaled bitmap for image decompression." );
228+ FML_DLOG (ERROR) << decode_error;
229+ return DecompressResult{.decode_error = decode_error};
224230 }
225231 if (!bitmap->pixmap ().scalePixels (
226232 scaled_bitmap->pixmap (),
@@ -231,26 +237,28 @@ std::optional<DecompressResult> ImageDecoderImpeller::DecompressTexture(
231237
232238 auto buffer = scaled_allocator->GetDeviceBuffer ();
233239 if (!buffer.has_value ()) {
234- return std:: nullopt ;
240+ return DecompressResult{. decode_error = " Unable to get device buffer " } ;
235241 }
236242 return DecompressResult{.device_buffer = buffer.value (),
237243 .sk_bitmap = scaled_bitmap,
238244 .image_info = scaled_bitmap->info ()};
239245}
240246
241- sk_sp<DlImage> ImageDecoderImpeller::UploadTextureToPrivate (
247+ std::pair<sk_sp<DlImage>, std::string>
248+ ImageDecoderImpeller::UploadTextureToPrivate (
242249 const std::shared_ptr<impeller::Context>& context,
243250 const std::shared_ptr<impeller::DeviceBuffer>& buffer,
244251 const SkImageInfo& image_info) {
245252 TRACE_EVENT0 (" impeller" , __FUNCTION__);
246253 if (!context || !buffer) {
247- return nullptr ;
254+ return std::make_pair ( nullptr , " No Impeller context or buffer available " ) ;
248255 }
249256 const auto pixel_format =
250257 impeller::skia_conversions::ToPixelFormat (image_info.colorType ());
251258 if (!pixel_format) {
252- FML_DLOG (ERROR) << " Pixel format unsupported by Impeller." ;
253- return nullptr ;
259+ std::string decode_error (" Pixel format unsupported by Impeller." );
260+ FML_DLOG (ERROR) << decode_error;
261+ return std::make_pair (nullptr , decode_error);
254262 }
255263
256264 impeller::TextureDescriptor texture_descriptor;
@@ -263,24 +271,29 @@ sk_sp<DlImage> ImageDecoderImpeller::UploadTextureToPrivate(
263271 auto dest_texture =
264272 context->GetResourceAllocator ()->CreateTexture (texture_descriptor);
265273 if (!dest_texture) {
266- FML_DLOG (ERROR) << " Could not create Impeller texture." ;
267- return nullptr ;
274+ std::string decode_error (" Could not create Impeller texture." );
275+ FML_DLOG (ERROR) << decode_error;
276+ return std::make_pair (nullptr , decode_error);
268277 }
269278
270279 dest_texture->SetLabel (
271280 impeller::SPrintF (" ui.Image(%p)" , dest_texture.get ()).c_str ());
272281
273282 auto command_buffer = context->CreateCommandBuffer ();
274283 if (!command_buffer) {
275- FML_DLOG (ERROR) << " Could not create command buffer for mipmap generation." ;
276- return nullptr ;
284+ std::string decode_error (
285+ " Could not create command buffer for mipmap generation." );
286+ FML_DLOG (ERROR) << decode_error;
287+ return std::make_pair (nullptr , decode_error);
277288 }
278289 command_buffer->SetLabel (" Mipmap Command Buffer" );
279290
280291 auto blit_pass = command_buffer->CreateBlitPass ();
281292 if (!blit_pass) {
282- FML_DLOG (ERROR) << " Could not create blit pass for mipmap generation." ;
283- return nullptr ;
293+ std::string decode_error (
294+ " Could not create blit pass for mipmap generation." );
295+ FML_DLOG (ERROR) << decode_error;
296+ return std::make_pair (nullptr , decode_error);
284297 }
285298 blit_pass->SetLabel (" Mipmap Blit Pass" );
286299 blit_pass->AddCopy (buffer->AsBufferView (), dest_texture);
@@ -290,27 +303,31 @@ sk_sp<DlImage> ImageDecoderImpeller::UploadTextureToPrivate(
290303
291304 blit_pass->EncodeCommands (context->GetResourceAllocator ());
292305 if (!command_buffer->SubmitCommands ()) {
293- FML_DLOG (ERROR) << " Failed to submit blit pass command buffer." ;
294- return nullptr ;
306+ std::string decode_error (" Failed to submit blit pass command buffer." );
307+ FML_DLOG (ERROR) << decode_error;
308+ return std::make_pair (nullptr , decode_error);
295309 }
296310
297- return impeller::DlImageImpeller::Make (std::move (dest_texture));
311+ return std::make_pair (
312+ impeller::DlImageImpeller::Make (std::move (dest_texture)), std::string ());
298313}
299314
300- sk_sp<DlImage> ImageDecoderImpeller::UploadTextureToShared (
315+ std::pair<sk_sp<DlImage>, std::string>
316+ ImageDecoderImpeller::UploadTextureToShared (
301317 const std::shared_ptr<impeller::Context>& context,
302318 std::shared_ptr<SkBitmap> bitmap,
303319 bool create_mips) {
304320 TRACE_EVENT0 (" impeller" , __FUNCTION__);
305321 if (!context || !bitmap) {
306- return nullptr ;
322+ return std::make_pair ( nullptr , " No Impeller context or buffer available " ) ;
307323 }
308324 const auto image_info = bitmap->info ();
309325 const auto pixel_format =
310326 impeller::skia_conversions::ToPixelFormat (image_info.colorType ());
311327 if (!pixel_format) {
312- FML_DLOG (ERROR) << " Pixel format unsupported by Impeller." ;
313- return nullptr ;
328+ std::string decode_error (" Pixel format unsupported by Impeller." );
329+ FML_DLOG (ERROR) << decode_error;
330+ return std::make_pair (nullptr , decode_error);
314331 }
315332
316333 impeller::TextureDescriptor texture_descriptor;
@@ -323,8 +340,9 @@ sk_sp<DlImage> ImageDecoderImpeller::UploadTextureToShared(
323340 auto texture =
324341 context->GetResourceAllocator ()->CreateTexture (texture_descriptor);
325342 if (!texture) {
326- FML_DLOG (ERROR) << " Could not create Impeller texture." ;
327- return nullptr ;
343+ std::string decode_error (" Could not create Impeller texture." );
344+ FML_DLOG (ERROR) << decode_error;
345+ return std::make_pair (nullptr , decode_error);
328346 }
329347
330348 auto mapping = std::make_shared<fml::NonOwnedMapping>(
@@ -334,38 +352,44 @@ sk_sp<DlImage> ImageDecoderImpeller::UploadTextureToShared(
334352 );
335353
336354 if (!texture->SetContents (mapping)) {
337- FML_DLOG (ERROR) << " Could not copy contents into Impeller texture." ;
338- return nullptr ;
355+ std::string decode_error (" Could not copy contents into Impeller texture." );
356+ FML_DLOG (ERROR) << decode_error;
357+ return std::make_pair (nullptr , decode_error);
339358 }
340359
341360 texture->SetLabel (impeller::SPrintF (" ui.Image(%p)" , texture.get ()).c_str ());
342361
343362 if (texture_descriptor.mip_count > 1u && create_mips) {
344363 auto command_buffer = context->CreateCommandBuffer ();
345364 if (!command_buffer) {
346- FML_DLOG (ERROR)
347- << " Could not create command buffer for mipmap generation." ;
348- return nullptr ;
365+ std::string decode_error (
366+ " Could not create command buffer for mipmap generation." );
367+ FML_DLOG (ERROR) << decode_error;
368+ return std::make_pair (nullptr , decode_error);
349369 }
350370 command_buffer->SetLabel (" Mipmap Command Buffer" );
351371
352372 auto blit_pass = command_buffer->CreateBlitPass ();
353373 if (!blit_pass) {
354- FML_DLOG (ERROR) << " Could not create blit pass for mipmap generation." ;
355- return nullptr ;
374+ std::string decode_error (
375+ " Could not create blit pass for mipmap generation." );
376+ FML_DLOG (ERROR) << decode_error;
377+ return std::make_pair (nullptr , decode_error);
356378 }
357379 blit_pass->SetLabel (" Mipmap Blit Pass" );
358380 blit_pass->GenerateMipmap (texture);
359381
360382 blit_pass->EncodeCommands (context->GetResourceAllocator ());
361383 if (!command_buffer->SubmitCommands ()) {
362- FML_DLOG (ERROR) << " Failed to submit blit pass command buffer." ;
363- return nullptr ;
384+ std::string decode_error (" Failed to submit blit pass command buffer." );
385+ FML_DLOG (ERROR) << decode_error;
386+ return std::make_pair (nullptr , decode_error);
364387 }
365388 command_buffer->WaitUntilScheduled ();
366389 }
367390
368- return impeller::DlImageImpeller::Make (std::move (texture));
391+ return std::make_pair (impeller::DlImageImpeller::Make (std::move (texture)),
392+ std::string ());
369393}
370394
371395// |ImageDecoder|
@@ -382,10 +406,10 @@ void ImageDecoderImpeller::Decode(fml::RefPtr<ImageDescriptor> descriptor,
382406 ImageResult result = [p_result, //
383407 raw_descriptor, //
384408 ui_runner = runners_.GetUITaskRunner () //
385- ](auto image) {
386- ui_runner->PostTask ([raw_descriptor, p_result, image]() {
409+ ](auto image, std::string decode_error ) {
410+ ui_runner->PostTask ([raw_descriptor, p_result, image, decode_error ]() {
387411 raw_descriptor->Release ();
388- p_result (std::move (image));
412+ p_result (std::move (image), std::move (decode_error) );
389413 });
390414 };
391415
@@ -398,7 +422,7 @@ void ImageDecoderImpeller::Decode(fml::RefPtr<ImageDescriptor> descriptor,
398422 supports_wide_gamut = supports_wide_gamut_ //
399423 ]() {
400424 if (!context) {
401- result (nullptr );
425+ result (nullptr , " No Impeller context is available " );
402426 return ;
403427 }
404428 auto max_size_supported =
@@ -408,21 +432,24 @@ void ImageDecoderImpeller::Decode(fml::RefPtr<ImageDescriptor> descriptor,
408432 auto bitmap_result = DecompressTexture (
409433 raw_descriptor, target_size, max_size_supported,
410434 supports_wide_gamut, context->GetResourceAllocator ());
411- if (!bitmap_result.has_value () ) {
412- result (nullptr );
435+ if (!bitmap_result.device_buffer ) {
436+ result (nullptr , bitmap_result. decode_error );
413437 return ;
414438 }
415439 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.
440+ bitmap_result]() {
441+ // TODO(jonahwilliams): remove ifdef once blit from buffer to
442+ // texture is implemented on other platforms.
443+ sk_sp<DlImage> image;
444+ std::string decode_error;
420445#if (FML_OS_IOS && !TARGET_IPHONE_SIMULATOR)
421- result ( UploadTextureToPrivate (context, bitmap_result. device_buffer ,
422- bitmap_result.image_info ) );
446+ std::tie (image, decode_error) = UploadTextureToPrivate (
447+ context, bitmap_result. device_buffer , bitmap_result.image_info );
423448#else
424- result (UploadTextureToShared (context, bitmap_result.sk_bitmap ));
449+ std::tie (image, decode_error) =
450+ UploadTextureToShared (context, bitmap_result.sk_bitmap );
425451#endif
452+ result (image, decode_error);
426453 };
427454 // TODO(jonahwilliams): https://github.com/flutter/flutter/issues/123058
428455 // Technically we don't need to post tasks to the io runner, but without
0 commit comments