@@ -107,16 +107,17 @@ static SkAlphaType ChooseCompatibleAlphaType(SkAlphaType type) {
107
107
return type;
108
108
}
109
109
110
- std::optional< DecompressResult> ImageDecoderImpeller::DecompressTexture (
110
+ DecompressResult ImageDecoderImpeller::DecompressTexture (
111
111
ImageDescriptor* descriptor,
112
112
SkISize target_size,
113
113
impeller::ISize max_texture_size,
114
114
bool supports_wide_gamut,
115
115
const std::shared_ptr<impeller::Allocator>& allocator) {
116
116
TRACE_EVENT0 (" impeller" , __FUNCTION__);
117
117
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};
120
121
}
121
122
122
123
target_size.set (std::min (static_cast <int32_t >(max_texture_size.width ),
@@ -162,8 +163,11 @@ std::optional<DecompressResult> ImageDecoderImpeller::DecompressTexture(
162
163
const auto pixel_format =
163
164
impeller::skia_conversions::ToPixelFormat (image_info.colorType ());
164
165
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};
167
171
}
168
172
169
173
auto bitmap = std::make_shared<SkBitmap>();
@@ -172,14 +176,16 @@ std::optional<DecompressResult> ImageDecoderImpeller::DecompressTexture(
172
176
173
177
if (descriptor->is_compressed ()) {
174
178
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};
178
183
}
179
184
// Decode the image into the image generator's closest supported size.
180
185
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};
183
189
}
184
190
} else {
185
191
auto temp_bitmap = std::make_shared<SkBitmap>();
@@ -189,9 +195,10 @@ std::optional<DecompressResult> ImageDecoderImpeller::DecompressTexture(
189
195
temp_bitmap->setPixelRef (pixel_ref, 0 , 0 );
190
196
191
197
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};
195
202
}
196
203
temp_bitmap->readPixels (bitmap->pixmap ());
197
204
bitmap->setImmutable ();
@@ -200,7 +207,7 @@ std::optional<DecompressResult> ImageDecoderImpeller::DecompressTexture(
200
207
if (bitmap->dimensions () == target_size) {
201
208
auto buffer = bitmap_allocator->GetDeviceBuffer ();
202
209
if (!buffer.has_value ()) {
203
- return std::nullopt ;
210
+ return DecompressResult{. decode_error = " Unable to get device buffer " } ;
204
211
}
205
212
return DecompressResult{.device_buffer = buffer.value (),
206
213
.sk_bitmap = bitmap,
@@ -218,9 +225,10 @@ std::optional<DecompressResult> ImageDecoderImpeller::DecompressTexture(
218
225
auto scaled_allocator = std::make_shared<ImpellerAllocator>(allocator);
219
226
scaled_bitmap->setInfo (scaled_image_info);
220
227
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};
224
232
}
225
233
if (!bitmap->pixmap ().scalePixels (
226
234
scaled_bitmap->pixmap (),
@@ -231,26 +239,32 @@ std::optional<DecompressResult> ImageDecoderImpeller::DecompressTexture(
231
239
232
240
auto buffer = scaled_allocator->GetDeviceBuffer ();
233
241
if (!buffer.has_value ()) {
234
- return std::nullopt ;
242
+ return DecompressResult{. decode_error = " Unable to get device buffer " } ;
235
243
}
236
244
return DecompressResult{.device_buffer = buffer.value (),
237
245
.sk_bitmap = scaled_bitmap,
238
246
.image_info = scaled_bitmap->info ()};
239
247
}
240
248
241
- sk_sp<DlImage> ImageDecoderImpeller::UploadTextureToPrivate (
249
+ std::pair<sk_sp<DlImage>, std::string>
250
+ ImageDecoderImpeller::UploadTextureToPrivate (
242
251
const std::shared_ptr<impeller::Context>& context,
243
252
const std::shared_ptr<impeller::DeviceBuffer>& buffer,
244
253
const SkImageInfo& image_info) {
245
254
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" );
248
260
}
249
261
const auto pixel_format =
250
262
impeller::skia_conversions::ToPixelFormat (image_info.colorType ());
251
263
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);
254
268
}
255
269
256
270
impeller::TextureDescriptor texture_descriptor;
@@ -263,24 +277,29 @@ sk_sp<DlImage> ImageDecoderImpeller::UploadTextureToPrivate(
263
277
auto dest_texture =
264
278
context->GetResourceAllocator ()->CreateTexture (texture_descriptor);
265
279
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);
268
283
}
269
284
270
285
dest_texture->SetLabel (
271
286
impeller::SPrintF (" ui.Image(%p)" , dest_texture.get ()).c_str ());
272
287
273
288
auto command_buffer = context->CreateCommandBuffer ();
274
289
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);
277
294
}
278
295
command_buffer->SetLabel (" Mipmap Command Buffer" );
279
296
280
297
auto blit_pass = command_buffer->CreateBlitPass ();
281
298
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);
284
303
}
285
304
blit_pass->SetLabel (" Mipmap Blit Pass" );
286
305
blit_pass->AddCopy (buffer->AsBufferView (), dest_texture);
@@ -290,27 +309,35 @@ sk_sp<DlImage> ImageDecoderImpeller::UploadTextureToPrivate(
290
309
291
310
blit_pass->EncodeCommands (context->GetResourceAllocator ());
292
311
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);
295
315
}
296
316
297
- return impeller::DlImageImpeller::Make (std::move (dest_texture));
317
+ return std::make_pair (
318
+ impeller::DlImageImpeller::Make (std::move (dest_texture)), std::string ());
298
319
}
299
320
300
- sk_sp<DlImage> ImageDecoderImpeller::UploadTextureToShared (
321
+ std::pair<sk_sp<DlImage>, std::string>
322
+ ImageDecoderImpeller::UploadTextureToShared (
301
323
const std::shared_ptr<impeller::Context>& context,
302
324
std::shared_ptr<SkBitmap> bitmap,
303
325
bool create_mips) {
304
326
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" );
307
332
}
308
333
const auto image_info = bitmap->info ();
309
334
const auto pixel_format =
310
335
impeller::skia_conversions::ToPixelFormat (image_info.colorType ());
311
336
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);
314
341
}
315
342
316
343
impeller::TextureDescriptor texture_descriptor;
@@ -323,8 +350,9 @@ sk_sp<DlImage> ImageDecoderImpeller::UploadTextureToShared(
323
350
auto texture =
324
351
context->GetResourceAllocator ()->CreateTexture (texture_descriptor);
325
352
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);
328
356
}
329
357
330
358
auto mapping = std::make_shared<fml::NonOwnedMapping>(
@@ -334,38 +362,44 @@ sk_sp<DlImage> ImageDecoderImpeller::UploadTextureToShared(
334
362
);
335
363
336
364
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);
339
368
}
340
369
341
370
texture->SetLabel (impeller::SPrintF (" ui.Image(%p)" , texture.get ()).c_str ());
342
371
343
372
if (texture_descriptor.mip_count > 1u && create_mips) {
344
373
auto command_buffer = context->CreateCommandBuffer ();
345
374
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);
349
379
}
350
380
command_buffer->SetLabel (" Mipmap Command Buffer" );
351
381
352
382
auto blit_pass = command_buffer->CreateBlitPass ();
353
383
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);
356
388
}
357
389
blit_pass->SetLabel (" Mipmap Blit Pass" );
358
390
blit_pass->GenerateMipmap (texture);
359
391
360
392
blit_pass->EncodeCommands (context->GetResourceAllocator ());
361
393
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);
364
397
}
365
398
command_buffer->WaitUntilScheduled ();
366
399
}
367
400
368
- return impeller::DlImageImpeller::Make (std::move (texture));
401
+ return std::make_pair (impeller::DlImageImpeller::Make (std::move (texture)),
402
+ std::string ());
369
403
}
370
404
371
405
// |ImageDecoder|
@@ -382,10 +416,10 @@ void ImageDecoderImpeller::Decode(fml::RefPtr<ImageDescriptor> descriptor,
382
416
ImageResult result = [p_result, //
383
417
raw_descriptor, //
384
418
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 ]() {
387
421
raw_descriptor->Release ();
388
- p_result (std::move (image));
422
+ p_result (std::move (image), decode_error );
389
423
});
390
424
};
391
425
@@ -398,7 +432,7 @@ void ImageDecoderImpeller::Decode(fml::RefPtr<ImageDescriptor> descriptor,
398
432
supports_wide_gamut = supports_wide_gamut_ //
399
433
]() {
400
434
if (!context) {
401
- result (nullptr );
435
+ result (nullptr , " No Impeller context is available " );
402
436
return ;
403
437
}
404
438
auto max_size_supported =
@@ -408,21 +442,24 @@ void ImageDecoderImpeller::Decode(fml::RefPtr<ImageDescriptor> descriptor,
408
442
auto bitmap_result = DecompressTexture (
409
443
raw_descriptor, target_size, max_size_supported,
410
444
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 );
413
447
return ;
414
448
}
415
449
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;
420
455
#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 );
423
458
#else
424
- result (UploadTextureToShared (context, bitmap_result.sk_bitmap ));
459
+ std::tie (image, decode_error) =
460
+ UploadTextureToShared (context, bitmap_result.sk_bitmap );
425
461
#endif
462
+ result (image, decode_error);
426
463
};
427
464
// TODO(jonahwilliams): https://github.com/flutter/flutter/issues/123058
428
465
// Technically we don't need to post tasks to the io runner, but without
0 commit comments