-
Notifications
You must be signed in to change notification settings - Fork 6k
[Impeller] Started throwing errors if dart:ui/Image.toByteData fails #46738
Changes from 1 commit
49eceff
8f5d893
8038a2e
c472696
98f59d4
0c1a1b7
50b344b
7c89a87
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,66 @@ | ||
| // Copyright 2013 The Flutter Authors. All rights reserved. | ||
| // Use of this source code is governed by a BSD-style license that can be | ||
| // found in the LICENSE file. | ||
|
|
||
| #ifndef FLUTTER_FML_STATUS_OR_H_ | ||
| #define FLUTTER_FML_STATUS_OR_H_ | ||
|
|
||
| #include <optional> | ||
|
|
||
| #include "flutter/fml/status.h" | ||
|
|
||
| namespace fml { | ||
|
|
||
| /// TODO(): Replace with absl::StatusOr. | ||
|
||
| template <typename T> | ||
| class StatusOr { | ||
| public: | ||
| StatusOr(const T& value) : status_(), value_(value) {} | ||
| StatusOr(const Status& status) : status_(status), value_() {} | ||
|
|
||
| StatusOr(const StatusOr&) = default; | ||
| StatusOr(StatusOr&&) = default; | ||
|
|
||
| StatusOr& operator=(const StatusOr&) = default; | ||
| StatusOr& operator=(StatusOr&&) = default; | ||
|
|
||
| StatusOr& operator=(const T& value) { | ||
| status_ = Status(); | ||
| value_ = value; | ||
| return *this; | ||
| } | ||
|
|
||
| StatusOr& operator=(const T&& value) { | ||
| status_ = Status(); | ||
| value_ = std::move(value); | ||
| return *this; | ||
| } | ||
|
|
||
| StatusOr& operator=(const Status& value) { | ||
| status_ = value; | ||
| value_ = std::nullopt; | ||
| return *this; | ||
| } | ||
|
|
||
| const Status& status() const { return status_; } | ||
|
|
||
| bool ok() const { return status_.ok(); } | ||
|
|
||
| const T& value() const { | ||
| FML_CHECK(status_.ok()); | ||
| return value_.value(); | ||
| } | ||
|
|
||
| T& value() { | ||
| FML_CHECK(status_.ok()); | ||
| return value_.value(); | ||
| } | ||
|
|
||
| private: | ||
| Status status_; | ||
| std::optional<T> value_; | ||
| }; | ||
|
|
||
| } // namespace fml | ||
|
|
||
| #endif | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1936,16 +1936,23 @@ base class _Image extends NativeFieldWrapperClass1 { | |
| external int get height; | ||
|
|
||
| Future<ByteData?> toByteData({ImageByteFormat format = ImageByteFormat.rawRgba}) { | ||
| return _futurize((_Callback<ByteData> callback) { | ||
| return _toByteData(format.index, (Uint8List? encoded) { | ||
| callback(encoded!.buffer.asByteData()); | ||
| }); | ||
| final Completer<ByteData?> completer = Completer<ByteData?>(); | ||
| final String? syncError = _toByteData(format.index, (Uint8List? encoded, String? error) { | ||
| if (encoded != null) { | ||
| completer.complete(encoded.buffer.asByteData()); | ||
| } else { | ||
| completer.completeError(Exception(error ?? 'unknown error')); | ||
|
||
| } | ||
| }); | ||
| if (syncError != null) { | ||
| completer.completeError(Exception(syncError)); | ||
| } | ||
| return completer.future; | ||
| } | ||
|
|
||
| /// Returns an error message on failure, null on success. | ||
| @Native<Handle Function(Pointer<Void>, Int32, Handle)>(symbol: 'Image::toByteData') | ||
| external String? _toByteData(int format, _Callback<Uint8List?> callback); | ||
| external String? _toByteData(int format, void Function(Uint8List?, String?) callback); | ||
|
|
||
| bool _disposed = false; | ||
| void dispose() { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -58,12 +58,15 @@ sk_sp<SkImage> ConvertBufferToSkImage( | |
|
|
||
| void DoConvertImageToRasterImpeller( | ||
| const sk_sp<DlImage>& dl_image, | ||
| std::function<void(sk_sp<SkImage>)> encode_task, | ||
| std::function<void(fml::StatusOr<sk_sp<SkImage>>)> encode_task, | ||
| const std::shared_ptr<const fml::SyncSwitch>& is_gpu_disabled_sync_switch, | ||
| const std::shared_ptr<impeller::Context>& impeller_context) { | ||
| is_gpu_disabled_sync_switch->Execute( | ||
| fml::SyncSwitch::Handlers() | ||
| .SetIfTrue([&encode_task] { encode_task(nullptr); }) | ||
| .SetIfTrue([&encode_task] { | ||
| encode_task( | ||
| fml::Status(fml::StatusCode::kUnavailable, "gpu unavailable")); | ||
|
||
| }) | ||
| .SetIfFalse([&dl_image, &encode_task, &impeller_context] { | ||
| ImageEncodingImpeller::ConvertDlImageToSkImage( | ||
| dl_image, std::move(encode_task), impeller_context); | ||
|
|
@@ -74,19 +77,21 @@ void DoConvertImageToRasterImpeller( | |
|
|
||
| void ImageEncodingImpeller::ConvertDlImageToSkImage( | ||
| const sk_sp<DlImage>& dl_image, | ||
| std::function<void(sk_sp<SkImage>)> encode_task, | ||
| std::function<void(fml::StatusOr<sk_sp<SkImage>>)> encode_task, | ||
| const std::shared_ptr<impeller::Context>& impeller_context) { | ||
| auto texture = dl_image->impeller_texture(); | ||
|
|
||
| if (impeller_context == nullptr) { | ||
| FML_LOG(ERROR) << "Impeller context was null."; | ||
|
||
| encode_task(nullptr); | ||
| encode_task(fml::Status(fml::StatusCode::kFailedPrecondition, | ||
| "Impeller context was null.")); | ||
| return; | ||
| } | ||
|
|
||
| if (texture == nullptr) { | ||
| FML_LOG(ERROR) << "Image was null."; | ||
| encode_task(nullptr); | ||
| encode_task( | ||
| fml::Status(fml::StatusCode::kFailedPrecondition, "Image was null.")); | ||
| return; | ||
| } | ||
|
|
||
|
|
@@ -95,13 +100,15 @@ void ImageEncodingImpeller::ConvertDlImageToSkImage( | |
|
|
||
| if (dimensions.isEmpty()) { | ||
| FML_LOG(ERROR) << "Image dimensions were empty."; | ||
| encode_task(nullptr); | ||
| encode_task(fml::Status(fml::StatusCode::kFailedPrecondition, | ||
| "Image dimensions were empty.")); | ||
| return; | ||
| } | ||
|
|
||
| if (!color_type.has_value()) { | ||
| FML_LOG(ERROR) << "Failed to get color type from pixel format."; | ||
| encode_task(nullptr); | ||
| encode_task(fml::Status(fml::StatusCode::kUnimplemented, | ||
| "Failed to get color type from pixel format.")); | ||
| return; | ||
| } | ||
|
|
||
|
|
@@ -121,7 +128,7 @@ void ImageEncodingImpeller::ConvertDlImageToSkImage( | |
| encode_task = std::move(encode_task)]( | ||
| impeller::CommandBuffer::Status status) { | ||
| if (status != impeller::CommandBuffer::Status::kCompleted) { | ||
| encode_task(nullptr); | ||
| encode_task(fml::Status(fml::StatusCode::kUnknown, "")); | ||
| return; | ||
| } | ||
| auto sk_image = ConvertBufferToSkImage(buffer, color_type, dimensions); | ||
|
|
@@ -135,14 +142,14 @@ void ImageEncodingImpeller::ConvertDlImageToSkImage( | |
|
|
||
| void ImageEncodingImpeller::ConvertImageToRaster( | ||
| const sk_sp<DlImage>& dl_image, | ||
| std::function<void(sk_sp<SkImage>)> encode_task, | ||
| std::function<void(fml::StatusOr<sk_sp<SkImage>>)> encode_task, | ||
| const fml::RefPtr<fml::TaskRunner>& raster_task_runner, | ||
| const fml::RefPtr<fml::TaskRunner>& io_task_runner, | ||
| const std::shared_ptr<const fml::SyncSwitch>& is_gpu_disabled_sync_switch, | ||
| const std::shared_ptr<impeller::Context>& impeller_context) { | ||
| auto original_encode_task = std::move(encode_task); | ||
| encode_task = [original_encode_task = std::move(original_encode_task), | ||
| io_task_runner](sk_sp<SkImage> image) mutable { | ||
| io_task_runner](fml::StatusOr<sk_sp<SkImage>> image) mutable { | ||
| fml::TaskRunner::RunNowOrPostTask( | ||
| io_task_runner, | ||
| [original_encode_task = std::move(original_encode_task), | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Passer-by comment from updating the internal build - since this is a new file, were we supposed to update BUILD.gn to specify it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm seeing build errors related to being unable to find
status_or.h. sponge2/34a90d3c-29af-45ca-952f-6e9733c86612Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've filed an issue: flutter/flutter#136858