|
4 | 4 |
|
5 | 5 | #include "flutter/lib/ui/painting/image.h" |
6 | 6 |
|
7 | | -#include <algorithm> |
8 | | -#include <limits> |
9 | 7 | #include "tonic/logging/dart_invoke.h" |
10 | 8 |
|
11 | 9 | #if IMPELLER_SUPPORTS_RENDERING |
12 | 10 | #include "flutter/lib/ui/painting/image_encoding_impeller.h" |
| 11 | +#include "flutter/lib/ui/painting/pixel_deferred_image_gpu_impeller.h" |
13 | 12 | #endif |
| 13 | +#include "flutter/display_list/image/dl_image.h" |
14 | 14 | #include "flutter/lib/ui/painting/image_encoding.h" |
| 15 | +#include "flutter/lib/ui/ui_dart_state.h" |
15 | 16 | #include "third_party/tonic/converter/dart_converter.h" |
16 | | -#include "third_party/tonic/dart_args.h" |
17 | | -#include "third_party/tonic/dart_binding_macros.h" |
18 | | -#include "third_party/tonic/dart_library_natives.h" |
19 | 17 |
|
20 | 18 | namespace flutter { |
21 | 19 |
|
@@ -56,3 +54,119 @@ int CanvasImage::colorSpace() { |
56 | 54 | } |
57 | 55 |
|
58 | 56 | } // namespace flutter |
| 57 | + |
| 58 | +namespace flutter { |
| 59 | + |
| 60 | +namespace { |
| 61 | + |
| 62 | +int BytesPerPixel(PixelFormat pixel_format) { |
| 63 | + switch (pixel_format) { |
| 64 | + case PixelFormat::kRgba8888: |
| 65 | + case PixelFormat::kBgra8888: |
| 66 | + case PixelFormat::kRFloat32: |
| 67 | + return 4; |
| 68 | + case PixelFormat::kRgbaFloat32: |
| 69 | + return 16; |
| 70 | + } |
| 71 | + return 4; |
| 72 | +} |
| 73 | + |
| 74 | +SkColorType PixelFormatToSkColorType(PixelFormat pixel_format) { |
| 75 | + switch (pixel_format) { |
| 76 | + case PixelFormat::kRgba8888: |
| 77 | + return kRGBA_8888_SkColorType; |
| 78 | + case PixelFormat::kBgra8888: |
| 79 | + return kBGRA_8888_SkColorType; |
| 80 | + case PixelFormat::kRgbaFloat32: |
| 81 | + return kRGBA_F32_SkColorType; |
| 82 | + case PixelFormat::kRFloat32: |
| 83 | + return kUnknown_SkColorType; |
| 84 | + } |
| 85 | + return kUnknown_SkColorType; |
| 86 | +} |
| 87 | + |
| 88 | +// Returns only static strings. |
| 89 | +const char* DoDecodeImageFromPixelsSync(Dart_Handle pixels_handle, |
| 90 | + uint32_t width, |
| 91 | + uint32_t height, |
| 92 | + int32_t pixel_format, |
| 93 | + Dart_Handle raw_image_handle) { |
| 94 | + auto* dart_state = UIDartState::Current(); |
| 95 | + if (!dart_state) { |
| 96 | + return "Dart state is null."; |
| 97 | + } |
| 98 | + |
| 99 | + if (!dart_state->IsImpellerEnabled()) { |
| 100 | + return "decodeImageFromPixelsSync is not implemented on Skia."; |
| 101 | + } |
| 102 | + |
| 103 | + if (width == 0 || height == 0) { |
| 104 | + return "Image dimensions must be greater than zero."; |
| 105 | + } |
| 106 | + |
| 107 | + if (pixel_format < 0 || |
| 108 | + pixel_format > static_cast<int32_t>(kLastPixelFormat)) { |
| 109 | + return "Invalid pixel format."; |
| 110 | + } |
| 111 | + PixelFormat format = static_cast<PixelFormat>(pixel_format); |
| 112 | + |
| 113 | + sk_sp<SkData> sk_data; |
| 114 | + sk_sp<SkImage> sk_image; |
| 115 | + { |
| 116 | + tonic::Uint8List pixels(pixels_handle); |
| 117 | + if (!pixels.data()) { |
| 118 | + return "Pixels must not be null."; |
| 119 | + } |
| 120 | + |
| 121 | + int32_t row_bytes = width * BytesPerPixel(format); |
| 122 | + SkColorType color_type = PixelFormatToSkColorType(format); |
| 123 | + if (color_type == kUnknown_SkColorType) { |
| 124 | + return "Unsupported pixel format."; |
| 125 | + } |
| 126 | + |
| 127 | + SkImageInfo image_info = |
| 128 | + SkImageInfo::Make(width, height, color_type, kUnpremul_SkAlphaType); |
| 129 | + if (pixel_format == 2) { // rgbaFloat32 |
| 130 | + image_info = image_info.makeAlphaType(kUnpremul_SkAlphaType); |
| 131 | + } else { |
| 132 | + image_info = image_info.makeAlphaType(kPremul_SkAlphaType); |
| 133 | + } |
| 134 | + |
| 135 | + sk_data = SkData::MakeWithCopy(pixels.data(), pixels.num_elements()); |
| 136 | + sk_image = SkImages::RasterFromData(image_info, sk_data, row_bytes); |
| 137 | + if (!sk_image) { |
| 138 | + return "Failed to create image from pixels."; |
| 139 | + } |
| 140 | + } |
| 141 | + |
| 142 | + auto snapshot_delegate = dart_state->GetSnapshotDelegate(); |
| 143 | + auto raster_task_runner = dart_state->GetTaskRunners().GetRasterTaskRunner(); |
| 144 | + |
| 145 | + auto result_image = CanvasImage::Create(); |
| 146 | + sk_sp<DlImage> deferred_image; |
| 147 | + |
| 148 | +#if IMPELLER_SUPPORTS_RENDERING |
| 149 | + deferred_image = PixelDeferredImageGPUImpeller::Make( |
| 150 | + sk_image, std::move(snapshot_delegate), std::move(raster_task_runner)); |
| 151 | +#endif // IMPELLER_SUPPORTS_RENDERING |
| 152 | + |
| 153 | + result_image->set_image(deferred_image); |
| 154 | + result_image->AssociateWithDartWrapper(raw_image_handle); |
| 155 | + |
| 156 | + return nullptr; |
| 157 | +} |
| 158 | +} // namespace |
| 159 | + |
| 160 | +void CanvasImage::decodeImageFromPixelsSync(Dart_Handle pixels_handle, |
| 161 | + uint32_t width, |
| 162 | + uint32_t height, |
| 163 | + int32_t pixel_format, |
| 164 | + Dart_Handle raw_image_handle) { |
| 165 | + const char* error = DoDecodeImageFromPixelsSync( |
| 166 | + pixels_handle, width, height, pixel_format, raw_image_handle); |
| 167 | + if (error) { |
| 168 | + Dart_ThrowException(tonic::ToDart(error)); |
| 169 | + } |
| 170 | +} |
| 171 | + |
| 172 | +} // namespace flutter |
0 commit comments