Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
image_decoder_impeller.cc
Go to the documentation of this file.
1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "flutter/lib/ui/painting/image_decoder_impeller.h"
6
7#include <memory>
8
9#include "flutter/fml/closure.h"
10#include "flutter/fml/make_copyable.h"
11#include "flutter/fml/trace_event.h"
12#include "flutter/impeller/core/allocator.h"
13#include "flutter/impeller/core/texture.h"
14#include "flutter/impeller/display_list/dl_image_impeller.h"
15#include "flutter/impeller/renderer/command_buffer.h"
16#include "flutter/impeller/renderer/context.h"
17#include "flutter/lib/ui/painting/image_decoder_skia.h"
33
34namespace flutter {
35
36namespace {
37/**
38 * Loads the gamut as a set of three points (triangle).
39 */
40void LoadGamut(SkPoint abc[3], const skcms_Matrix3x3& xyz) {
41 // rx = rX / (rX + rY + rZ)
42 // ry = rY / (rX + rY + rZ)
43 // gx, gy, bx, and gy are calculated similarly.
44 for (int index = 0; index < 3; index++) {
45 float sum = xyz.vals[index][0] + xyz.vals[index][1] + xyz.vals[index][2];
46 abc[index].fX = xyz.vals[index][0] / sum;
47 abc[index].fY = xyz.vals[index][1] / sum;
48 }
49}
50
51/**
52 * Calculates the area of the triangular gamut.
53 */
54float CalculateArea(SkPoint abc[3]) {
55 const SkPoint& a = abc[0];
56 const SkPoint& b = abc[1];
57 const SkPoint& c = abc[2];
58 return 0.5f * fabsf(a.fX * b.fY + b.fX * c.fY - a.fX * c.fY - c.fX * b.fY -
59 b.fX * a.fY);
60}
61
62// Note: This was calculated from SkColorSpace::MakeSRGB().
63static constexpr float kSrgbGamutArea = 0.0982f;
64
65// Source:
66// https://source.chromium.org/chromium/_/skia/skia.git/+/393fb1ec80f41d8ad7d104921b6920e69749fda1:src/codec/SkAndroidCodec.cpp;l=67;drc=46572b4d445f41943059d0e377afc6d6748cd5ca;bpv=1;bpt=0
67bool IsWideGamut(const SkColorSpace* color_space) {
68 if (!color_space) {
69 return false;
70 }
71 skcms_Matrix3x3 xyzd50;
72 color_space->toXYZD50(&xyzd50);
73 SkPoint rgb[3];
74 LoadGamut(rgb, xyzd50);
75 float area = CalculateArea(rgb);
76 return area > kSrgbGamutArea;
77}
78} // namespace
79
81 const TaskRunners& runners,
82 std::shared_ptr<fml::ConcurrentTaskRunner> concurrent_task_runner,
83 const fml::WeakPtr<IOManager>& io_manager,
84 bool supports_wide_gamut,
85 const std::shared_ptr<fml::SyncSwitch>& gpu_disabled_switch)
86 : ImageDecoder(runners, std::move(concurrent_task_runner), io_manager),
87 supports_wide_gamut_(supports_wide_gamut),
88 gpu_disabled_switch_(gpu_disabled_switch) {
89 std::promise<std::shared_ptr<impeller::Context>> context_promise;
90 context_ = context_promise.get_future();
92 [promise = std::move(context_promise), io_manager]() mutable {
93 promise.set_value(io_manager ? io_manager->GetImpellerContext()
94 : nullptr);
95 }));
96}
97
99
101 switch (type) {
104 default:
106 }
107}
108
112
114 ImageDescriptor* descriptor,
115 SkISize target_size,
116 impeller::ISize max_texture_size,
117 bool supports_wide_gamut,
118 const std::shared_ptr<impeller::Allocator>& allocator) {
119 TRACE_EVENT0("impeller", __FUNCTION__);
120 if (!descriptor) {
121 std::string decode_error("Invalid descriptor (should never happen)");
122 FML_DLOG(ERROR) << decode_error;
123 return DecompressResult{.decode_error = decode_error};
124 }
125
126 target_size.set(std::min(static_cast<int32_t>(max_texture_size.width),
127 target_size.width()),
128 std::min(static_cast<int32_t>(max_texture_size.height),
129 target_size.height()));
130
131 const SkISize source_size = descriptor->image_info().dimensions();
132 auto decode_size = source_size;
133 if (descriptor->is_compressed()) {
134 decode_size = descriptor->get_scaled_dimensions(std::max(
135 static_cast<float>(target_size.width()) / source_size.width(),
136 static_cast<float>(target_size.height()) / source_size.height()));
137 }
138
139 //----------------------------------------------------------------------------
140 /// 1. Decode the image.
141 ///
142
143 const auto base_image_info = descriptor->image_info();
144 const bool is_wide_gamut =
145 supports_wide_gamut ? IsWideGamut(base_image_info.colorSpace()) : false;
147 ChooseCompatibleAlphaType(base_image_info.alphaType());
148 SkImageInfo image_info;
149 if (is_wide_gamut) {
153 image_info =
154 base_image_info.makeWH(decode_size.width(), decode_size.height())
158 } else {
159 image_info =
160 base_image_info.makeWH(decode_size.width(), decode_size.height())
162 ChooseCompatibleColorType(base_image_info.colorType()))
164 }
165
166 const auto pixel_format =
168 if (!pixel_format.has_value()) {
169 std::string decode_error(impeller::SPrintF(
170 "Codec pixel format is not supported (SkColorType=%d)",
171 image_info.colorType()));
172 FML_DLOG(ERROR) << decode_error;
173 return DecompressResult{.decode_error = decode_error};
174 }
175
176 auto bitmap = std::make_shared<SkBitmap>();
177 bitmap->setInfo(image_info);
178 auto bitmap_allocator = std::make_shared<ImpellerAllocator>(allocator);
179
180 if (descriptor->is_compressed()) {
181 if (!bitmap->tryAllocPixels(bitmap_allocator.get())) {
182 std::string decode_error(
183 "Could not allocate intermediate for image decompression.");
184 FML_DLOG(ERROR) << decode_error;
185 return DecompressResult{.decode_error = decode_error};
186 }
187 // Decode the image into the image generator's closest supported size.
188 if (!descriptor->get_pixels(bitmap->pixmap())) {
189 std::string decode_error("Could not decompress image.");
190 FML_DLOG(ERROR) << decode_error;
191 return DecompressResult{.decode_error = decode_error};
192 }
193 } else {
194 auto temp_bitmap = std::make_shared<SkBitmap>();
195 temp_bitmap->setInfo(base_image_info);
196 auto pixel_ref = SkMallocPixelRef::MakeWithData(
197 base_image_info, descriptor->row_bytes(), descriptor->data());
198 temp_bitmap->setPixelRef(pixel_ref, 0, 0);
199
200 if (!bitmap->tryAllocPixels(bitmap_allocator.get())) {
201 std::string decode_error(
202 "Could not allocate intermediate for pixel conversion.");
203 FML_DLOG(ERROR) << decode_error;
204 return DecompressResult{.decode_error = decode_error};
205 }
206 temp_bitmap->readPixels(bitmap->pixmap());
207 bitmap->setImmutable();
208 }
209
210 if (bitmap->dimensions() == target_size) {
211 std::shared_ptr<impeller::DeviceBuffer> buffer =
212 bitmap_allocator->GetDeviceBuffer();
213 if (!buffer) {
214 return DecompressResult{.decode_error = "Unable to get device buffer"};
215 }
216 buffer->Flush();
217
218 return DecompressResult{.device_buffer = std::move(buffer),
219 .sk_bitmap = bitmap,
220 .image_info = bitmap->info()};
221 }
222
223 //----------------------------------------------------------------------------
224 /// 2. If the decoded image isn't the requested target size, resize it.
225 ///
226
227 TRACE_EVENT0("impeller", "DecodeScale");
228 const auto scaled_image_info = image_info.makeDimensions(target_size);
229
230 auto scaled_bitmap = std::make_shared<SkBitmap>();
231 auto scaled_allocator = std::make_shared<ImpellerAllocator>(allocator);
232 scaled_bitmap->setInfo(scaled_image_info);
233 if (!scaled_bitmap->tryAllocPixels(scaled_allocator.get())) {
234 std::string decode_error(
235 "Could not allocate scaled bitmap for image decompression.");
236 FML_DLOG(ERROR) << decode_error;
237 return DecompressResult{.decode_error = decode_error};
238 }
239 if (!bitmap->pixmap().scalePixels(
240 scaled_bitmap->pixmap(),
242 FML_LOG(ERROR) << "Could not scale decoded bitmap data.";
243 }
244 scaled_bitmap->setImmutable();
245
246 std::shared_ptr<impeller::DeviceBuffer> buffer =
247 scaled_allocator->GetDeviceBuffer();
248 buffer->Flush();
249
250 if (!buffer) {
251 return DecompressResult{.decode_error = "Unable to get device buffer"};
252 }
253 return DecompressResult{.device_buffer = std::move(buffer),
254 .sk_bitmap = scaled_bitmap,
255 .image_info = scaled_bitmap->info()};
256}
257
258/// Only call this method if the GPU is available.
259static std::pair<sk_sp<DlImage>, std::string> UnsafeUploadTextureToPrivate(
260 const std::shared_ptr<impeller::Context>& context,
261 const std::shared_ptr<impeller::DeviceBuffer>& buffer,
262 const SkImageInfo& image_info) {
263 const auto pixel_format =
265 if (!pixel_format) {
266 std::string decode_error(impeller::SPrintF(
267 "Unsupported pixel format (SkColorType=%d)", image_info.colorType()));
268 FML_DLOG(ERROR) << decode_error;
269 return std::make_pair(nullptr, decode_error);
270 }
271
272 impeller::TextureDescriptor texture_descriptor;
274 texture_descriptor.format = pixel_format.value();
275 texture_descriptor.size = {image_info.width(), image_info.height()};
276 texture_descriptor.mip_count = texture_descriptor.size.MipCount();
278
279 auto dest_texture =
280 context->GetResourceAllocator()->CreateTexture(texture_descriptor);
281 if (!dest_texture) {
282 std::string decode_error("Could not create Impeller texture.");
283 FML_DLOG(ERROR) << decode_error;
284 return std::make_pair(nullptr, decode_error);
285 }
286
287 dest_texture->SetLabel(
288 impeller::SPrintF("ui.Image(%p)", dest_texture.get()).c_str());
289
290 auto command_buffer = context->CreateCommandBuffer();
291 if (!command_buffer) {
292 std::string decode_error(
293 "Could not create command buffer for mipmap generation.");
294 FML_DLOG(ERROR) << decode_error;
295 return std::make_pair(nullptr, decode_error);
296 }
297 command_buffer->SetLabel("Mipmap Command Buffer");
298
299 auto blit_pass = command_buffer->CreateBlitPass();
300 if (!blit_pass) {
301 std::string decode_error(
302 "Could not create blit pass for mipmap generation.");
303 FML_DLOG(ERROR) << decode_error;
304 return std::make_pair(nullptr, decode_error);
305 }
306 blit_pass->SetLabel("Mipmap Blit Pass");
308 dest_texture);
309 if (texture_descriptor.size.MipCount() > 1) {
310 blit_pass->GenerateMipmap(dest_texture);
311 }
312
313 blit_pass->EncodeCommands(context->GetResourceAllocator());
314 if (!context->GetCommandQueue()->Submit({command_buffer}).ok()) {
315 std::string decode_error("Failed to submit blit pass command buffer.");
316 FML_DLOG(ERROR) << decode_error;
317 return std::make_pair(nullptr, decode_error);
318 }
319
320 return std::make_pair(
321 impeller::DlImageImpeller::Make(std::move(dest_texture)), std::string());
322}
323
324std::pair<sk_sp<DlImage>, std::string>
326 const std::shared_ptr<impeller::Context>& context,
327 const std::shared_ptr<impeller::DeviceBuffer>& buffer,
328 const SkImageInfo& image_info,
329 const std::shared_ptr<SkBitmap>& bitmap,
330 const std::shared_ptr<fml::SyncSwitch>& gpu_disabled_switch) {
331 TRACE_EVENT0("impeller", __FUNCTION__);
332 if (!context) {
333 return std::make_pair(nullptr, "No Impeller context is available");
334 }
335 if (!buffer) {
336 return std::make_pair(nullptr, "No Impeller device buffer is available");
337 }
338
339 std::pair<sk_sp<DlImage>, std::string> result;
340 gpu_disabled_switch->Execute(
342 .SetIfFalse([&result, context, buffer, image_info] {
343 result = UnsafeUploadTextureToPrivate(context, buffer, image_info);
344 })
345 .SetIfTrue([&result, context, bitmap, gpu_disabled_switch] {
346 // create_mips is false because we already know the GPU is disabled.
347 result =
348 UploadTextureToStorage(context, bitmap, gpu_disabled_switch,
350 /*create_mips=*/false);
351 }));
352 return result;
353}
354
355std::pair<sk_sp<DlImage>, std::string>
357 const std::shared_ptr<impeller::Context>& context,
358 std::shared_ptr<SkBitmap> bitmap,
359 const std::shared_ptr<fml::SyncSwitch>& gpu_disabled_switch,
360 impeller::StorageMode storage_mode,
361 bool create_mips) {
362 TRACE_EVENT0("impeller", __FUNCTION__);
363 if (!context) {
364 return std::make_pair(nullptr, "No Impeller context is available");
365 }
366 if (!bitmap) {
367 return std::make_pair(nullptr, "No texture bitmap is available");
368 }
369 const auto image_info = bitmap->info();
370 const auto pixel_format =
371 impeller::skia_conversions::ToPixelFormat(image_info.colorType());
372 if (!pixel_format) {
373 std::string decode_error(impeller::SPrintF(
374 "Unsupported pixel format (SkColorType=%d)", image_info.colorType()));
375 FML_DLOG(ERROR) << decode_error;
376 return std::make_pair(nullptr, decode_error);
377 }
378
379 impeller::TextureDescriptor texture_descriptor;
380 texture_descriptor.storage_mode = storage_mode;
381 texture_descriptor.format = pixel_format.value();
382 texture_descriptor.size = {image_info.width(), image_info.height()};
383 texture_descriptor.mip_count =
384 create_mips ? texture_descriptor.size.MipCount() : 1;
385
386 auto texture =
387 context->GetResourceAllocator()->CreateTexture(texture_descriptor);
388 if (!texture) {
389 std::string decode_error("Could not create Impeller texture.");
390 FML_DLOG(ERROR) << decode_error;
391 return std::make_pair(nullptr, decode_error);
392 }
393
394 auto mapping = std::make_shared<fml::NonOwnedMapping>(
395 reinterpret_cast<const uint8_t*>(bitmap->getAddr(0, 0)), // data
396 texture_descriptor.GetByteSizeOfBaseMipLevel(), // size
397 [bitmap](auto, auto) mutable { bitmap.reset(); } // proc
398 );
399
400 if (!texture->SetContents(mapping)) {
401 std::string decode_error("Could not copy contents into Impeller texture.");
402 FML_DLOG(ERROR) << decode_error;
403 return std::make_pair(nullptr, decode_error);
404 }
405
406 texture->SetLabel(impeller::SPrintF("ui.Image(%p)", texture.get()).c_str());
407
408 if (texture_descriptor.mip_count > 1u && create_mips) {
409 std::optional<std::string> decode_error;
410
411 // The only platform that needs mipmapping unconditionally is GL.
412 // GL based platforms never disable GPU access.
413 // This is only really needed for iOS.
414 gpu_disabled_switch->Execute(fml::SyncSwitch::Handlers().SetIfFalse(
415 [context, &texture, &decode_error] {
416 auto command_buffer = context->CreateCommandBuffer();
417 if (!command_buffer) {
418 decode_error =
419 "Could not create command buffer for mipmap generation.";
420 return;
421 }
422 command_buffer->SetLabel("Mipmap Command Buffer");
423
424 auto blit_pass = command_buffer->CreateBlitPass();
425 if (!blit_pass) {
426 decode_error = "Could not create blit pass for mipmap generation.";
427 return;
428 }
429 blit_pass->SetLabel("Mipmap Blit Pass");
430 blit_pass->GenerateMipmap(texture);
431 blit_pass->EncodeCommands(context->GetResourceAllocator());
432 if (!context->GetCommandQueue()->Submit({command_buffer}).ok()) {
433 decode_error = "Failed to submit blit pass command buffer.";
434 return;
435 }
436 command_buffer->WaitUntilScheduled();
437 }));
438 if (decode_error.has_value()) {
439 FML_DLOG(ERROR) << decode_error.value();
440 return std::make_pair(nullptr, decode_error.value());
441 }
442 }
443
444 return std::make_pair(impeller::DlImageImpeller::Make(std::move(texture)),
445 std::string());
446}
447
448// |ImageDecoder|
450 uint32_t target_width,
451 uint32_t target_height,
452 const ImageResult& p_result) {
453 FML_DCHECK(descriptor);
454 FML_DCHECK(p_result);
455
456 // Wrap the result callback so that it can be invoked from any thread.
457 auto raw_descriptor = descriptor.get();
458 raw_descriptor->AddRef();
459 ImageResult result = [p_result, //
460 raw_descriptor, //
461 ui_runner = runners_.GetUITaskRunner() //
462 ](auto image, auto decode_error) {
463 ui_runner->PostTask([raw_descriptor, p_result, image, decode_error]() {
464 raw_descriptor->Release();
465 p_result(std::move(image), decode_error);
466 });
467 };
468
469 concurrent_task_runner_->PostTask(
470 [raw_descriptor, //
471 context = context_.get(), //
472 target_size = SkISize::Make(target_width, target_height), //
473 io_runner = runners_.GetIOTaskRunner(), //
474 result,
475 supports_wide_gamut = supports_wide_gamut_, //
476 gpu_disabled_switch = gpu_disabled_switch_]() {
477 if (!context) {
478 result(nullptr, "No Impeller context is available");
479 return;
480 }
481 auto max_size_supported =
482 context->GetResourceAllocator()->GetMaxTextureSizeSupported();
483
484 // Always decompress on the concurrent runner.
485 auto bitmap_result = DecompressTexture(
486 raw_descriptor, target_size, max_size_supported,
487 supports_wide_gamut, context->GetResourceAllocator());
488 if (!bitmap_result.device_buffer) {
489 result(nullptr, bitmap_result.decode_error);
490 return;
491 }
492 auto upload_texture_and_invoke_result = [result, context, bitmap_result,
493 gpu_disabled_switch]() {
495 std::string decode_error;
496 if (context->GetCapabilities()->SupportsBufferToTextureBlits()) {
497 std::tie(image, decode_error) = UploadTextureToPrivate(
498 context, bitmap_result.device_buffer, bitmap_result.image_info,
499 bitmap_result.sk_bitmap, gpu_disabled_switch);
500 result(image, decode_error);
501 } else {
502 std::tie(image, decode_error) = UploadTextureToStorage(
503 context, bitmap_result.sk_bitmap, gpu_disabled_switch,
505 /*create_mips=*/true);
506 result(image, decode_error);
507 }
508 };
509 // TODO(jonahwilliams):
510 // https://github.com/flutter/flutter/issues/123058 Technically we
511 // don't need to post tasks to the io runner, but without this
512 // forced serialization we can end up overloading the GPU and/or
513 // competing with raster workloads.
514 io_runner->PostTask(upload_texture_and_invoke_result);
515 });
516}
517
519 std::shared_ptr<impeller::Allocator> allocator)
520 : allocator_(std::move(allocator)) {}
521
522std::shared_ptr<impeller::DeviceBuffer> ImpellerAllocator::GetDeviceBuffer()
523 const {
524 return buffer_;
525}
526
528 if (!bitmap) {
529 return false;
530 }
531 const SkImageInfo& info = bitmap->info();
532 if (kUnknown_SkColorType == info.colorType() || info.width() < 0 ||
533 info.height() < 0 || !info.validRowBytes(bitmap->rowBytes())) {
534 return false;
535 }
536
539 descriptor.size = ((bitmap->height() - 1) * bitmap->rowBytes()) +
540 (bitmap->width() * bitmap->bytesPerPixel());
541
542 std::shared_ptr<impeller::DeviceBuffer> device_buffer =
543 allocator_->CreateBuffer(descriptor);
544 if (!device_buffer) {
545 return false;
546 }
547
548 struct ImpellerPixelRef final : public SkPixelRef {
549 ImpellerPixelRef(int w, int h, void* s, size_t r)
550 : SkPixelRef(w, h, s, r) {}
551
552 ~ImpellerPixelRef() override {}
553 };
554
555 auto pixel_ref = sk_sp<SkPixelRef>(
556 new ImpellerPixelRef(info.width(), info.height(),
557 device_buffer->OnGetContents(), bitmap->rowBytes()));
558
559 bitmap->setPixelRef(std::move(pixel_ref), 0, 0);
560 buffer_ = std::move(device_buffer);
561 return true;
562}
563
564} // namespace flutter
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition DM.cpp:213
SkAlphaType
Definition SkAlphaType.h:26
@ kOpaque_SkAlphaType
pixel is opaque
Definition SkAlphaType.h:28
SkColorType
Definition SkColorType.h:19
@ kRGBA_F16_SkColorType
pixel with half floats for red, green, blue, alpha;
Definition SkColorType.h:38
@ kRGBA_8888_SkColorType
pixel with 8 bits for red, green, blue, alpha; in 32-bit word
Definition SkColorType.h:24
@ kRGBA_F32_SkColorType
pixel using C float for red, green, blue, alpha; in 128-bit word
Definition SkColorType.h:40
@ kBGR_101010x_XR_SkColorType
pixel with 10 bits each for blue, green, red; in 32-bit word, extended range
Definition SkColorType.h:31
@ kUnknown_SkColorType
uninitialized
Definition SkColorType.h:20
bool toXYZD50(skcms_Matrix3x3 *toXYZD50) const
static sk_sp< SkColorSpace > MakeSRGB()
void Decode(fml::RefPtr< ImageDescriptor > descriptor, uint32_t target_width, uint32_t target_height, const ImageResult &result) override
static std::pair< sk_sp< DlImage >, std::string > UploadTextureToStorage(const std::shared_ptr< impeller::Context > &context, std::shared_ptr< SkBitmap > bitmap, const std::shared_ptr< fml::SyncSwitch > &gpu_disabled_switch, impeller::StorageMode storage_mode, bool create_mips=true)
Create a host visible texture from the provided bitmap.
ImageDecoderImpeller(const TaskRunners &runners, std::shared_ptr< fml::ConcurrentTaskRunner > concurrent_task_runner, const fml::WeakPtr< IOManager > &io_manager, bool supports_wide_gamut, const std::shared_ptr< fml::SyncSwitch > &gpu_disabled_switch)
static std::pair< sk_sp< DlImage >, std::string > UploadTextureToPrivate(const std::shared_ptr< impeller::Context > &context, const std::shared_ptr< impeller::DeviceBuffer > &buffer, const SkImageInfo &image_info, const std::shared_ptr< SkBitmap > &bitmap, const std::shared_ptr< fml::SyncSwitch > &gpu_disabled_switch)
Create a device private texture from the provided host buffer. This method is only suported on the me...
static DecompressResult DecompressTexture(ImageDescriptor *descriptor, SkISize target_size, impeller::ISize max_texture_size, bool supports_wide_gamut, const std::shared_ptr< impeller::Allocator > &allocator)
std::function< void(sk_sp< DlImage >, std::string)> ImageResult
std::shared_ptr< fml::ConcurrentTaskRunner > concurrent_task_runner_
Creates an image descriptor for encoded or decoded image data, describing the width,...
const SkImageInfo & image_info() const
The orientation corrected image info for this image.
SkISize get_scaled_dimensions(float scale)
Gets the scaled dimensions of this image, if backed by an ImageGenerator that can perform efficient s...
int row_bytes() const
The byte length of the first row of the image. Defaults to width() * 4.
bool get_pixels(const SkPixmap &pixmap) const
Gets pixels for this image transformed based on the EXIF orientation tag, if applicable.
bool is_compressed() const
Whether this descriptor represents compressed (encoded) data or not.
sk_sp< SkData > data() const
The underlying buffer for this image.
bool allocPixelRef(SkBitmap *bitmap) override
ImpellerAllocator(std::shared_ptr< impeller::Allocator > allocator)
std::shared_ptr< impeller::DeviceBuffer > GetDeviceBuffer() const
fml::RefPtr< fml::TaskRunner > GetUITaskRunner() const
fml::RefPtr< fml::TaskRunner > GetIOTaskRunner() const
T * get() const
Definition ref_ptr.h:116
virtual void PostTask(const fml::closure &task) override
static BufferView AsBufferView(std::shared_ptr< DeviceBuffer > buffer)
Create a buffer view of this entire buffer.
static sk_sp< DlImageImpeller > Make(std::shared_ptr< Texture > texture, OwningContext owning_context=OwningContext::kIO)
sk_sp< SkImage > image
Definition examples.cpp:29
static bool b
struct MyStruct s
struct MyStruct a[10]
GAsyncResult * result
#define FML_DLOG(severity)
Definition logging.h:102
#define FML_LOG(severity)
Definition logging.h:82
#define FML_DCHECK(condition)
Definition logging.h:103
FlTexture * texture
SK_API sk_sp< SkPixelRef > MakeWithData(const SkImageInfo &, size_t rowBytes, sk_sp< SkData > data)
static std::pair< sk_sp< DlImage >, std::string > UnsafeUploadTextureToPrivate(const std::shared_ptr< impeller::Context > &context, const std::shared_ptr< impeller::DeviceBuffer > &buffer, const SkImageInfo &image_info)
Only call this method if the GPU is available.
static SkAlphaType ChooseCompatibleAlphaType(SkAlphaType type)
static SkColorType ChooseCompatibleColorType(SkColorType type)
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace buffer
Definition switches.h:126
internal::CopyableLambda< T > MakeCopyable(T lambda)
std::optional< impeller::PixelFormat > ToPixelFormat(SkColorType type)
StorageMode
Specified where the allocation resides and how it is used.
Definition formats.h:33
std::string SPrintF(const char *format,...)
Definition strings.cc:12
Definition ref_ptr.h:256
SkScalar w
SkScalar h
uint32_t color_type
uint32_t alpha_type
static constexpr SkISize Make(int32_t w, int32_t h)
Definition SkSize.h:20
constexpr int32_t width() const
Definition SkSize.h:36
void set(int32_t w, int32_t h)
Definition SkSize.h:24
constexpr int32_t height() const
Definition SkSize.h:37
SkImageInfo makeWH(int newWidth, int newHeight) const
SkImageInfo makeAlphaType(SkAlphaType newAlphaType) const
SkImageInfo makeDimensions(SkISize newSize) const
SkISize dimensions() const
SkImageInfo makeColorSpace(sk_sp< SkColorSpace > cs) const
int width() const
SkColorType colorType() const
int height() const
SkImageInfo makeColorType(SkColorType newColorType) const
float fX
x-axis value
float fY
y-axis value
std::shared_ptr< impeller::DeviceBuffer > device_buffer
Represents the 2 code paths available when calling |SyncSwitchExecute|.
Definition sync_switch.h:35
Type height
Definition size.h:23
Type width
Definition size.h:22
constexpr size_t MipCount() const
Definition size.h:115
A lightweight object that describes the attributes of a texture that can then used an allocator to cr...
constexpr size_t GetByteSizeOfBaseMipLevel() const
float vals[3][3]
#define ERROR(message)
#define TRACE_EVENT0(category_group, name)