Flutter Engine Uber Docs
Docs for the entire Flutter Engine repo.
 
Loading...
Searching...
No Matches
texture_gles.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
6
7#include <format>
8#include <optional>
9#include <utility>
10
11#include "flutter/fml/logging.h"
12#include "flutter/fml/mapping.h"
19
20namespace impeller {
21
22namespace {
23static bool IsDepthStencilFormat(PixelFormat format) {
24 switch (format) {
28 return true;
60 return false;
61 }
63}
64
65static TextureGLES::Type GetTextureTypeFromDescriptor(
66 const TextureDescriptor& desc,
67 const std::shared_ptr<const CapabilitiesGLES>& capabilities) {
68 const auto usage = static_cast<TextureUsageMask>(desc.usage);
69 const auto render_target = TextureUsage::kRenderTarget;
70 const auto is_msaa = desc.sample_count == SampleCount::kCount4;
71 if (usage == render_target && IsDepthStencilFormat(desc.format)) {
74 }
75 return is_msaa ? (capabilities->SupportsImplicitResolvingMSAA()
78 : TextureGLES::Type::kTexture;
79}
80
81} // namespace
82
94
95std::shared_ptr<TextureGLES> TextureGLES::WrapFBO(
96 std::shared_ptr<ReactorGLES> reactor,
98 GLuint fbo) {
99 auto texture = std::shared_ptr<TextureGLES>(
100 new TextureGLES(std::move(reactor), desc, false, fbo, std::nullopt));
101 if (!texture->IsValid()) {
102 return nullptr;
103 }
104 return texture;
105}
106
107std::shared_ptr<TextureGLES> TextureGLES::WrapTexture(
108 std::shared_ptr<ReactorGLES> reactor,
110 HandleGLES external_handle) {
111 if (external_handle.IsDead()) {
112 VALIDATION_LOG << "Cannot wrap a dead handle.";
113 return nullptr;
114 }
115 if (external_handle.GetType() != HandleType::kTexture) {
116 VALIDATION_LOG << "Cannot wrap a non-texture handle.";
117 return nullptr;
118 }
119 auto texture = std::shared_ptr<TextureGLES>(new TextureGLES(
120 std::move(reactor), desc, false, std::nullopt, external_handle));
121 if (!texture->IsValid()) {
122 return nullptr;
123 }
124 return texture;
125}
126
127std::shared_ptr<TextureGLES> TextureGLES::CreatePlaceholder(
128 std::shared_ptr<ReactorGLES> reactor,
129 TextureDescriptor desc) {
130 return TextureGLES::WrapFBO(std::move(reactor), desc, 0u);
131}
132
133TextureGLES::TextureGLES(std::shared_ptr<ReactorGLES> reactor,
135 bool threadsafe)
136 : TextureGLES(std::move(reactor), //
137 desc, //
138 threadsafe, //
139 std::nullopt, //
140 std::nullopt //
141 ) {}
142
143TextureGLES::TextureGLES(std::shared_ptr<ReactorGLES> reactor,
145 bool threadsafe,
146 std::optional<GLuint> fbo,
147 std::optional<HandleGLES> external_handle)
148 : Texture(desc),
149 reactor_(std::move(reactor)),
150 type_(GetTextureTypeFromDescriptor(
151 GetTextureDescriptor(),
152 reactor_->GetProcTable().GetCapabilities())),
153 handle_(
154 external_handle.has_value()
155 ? UniqueHandleGLES(reactor_, external_handle.value())
156 : (threadsafe
157 ? UniqueHandleGLES(reactor_, ToHandleType(type_))
158 : UniqueHandleGLES::MakeUntracked(reactor_,
159 ToHandleType(type_)))),
160 is_wrapped_(fbo.has_value() || external_handle.has_value()),
161 wrapped_fbo_(fbo) {
162 // Ensure the texture descriptor itself is valid.
163 if (!GetTextureDescriptor().IsValid()) {
164 return;
165 }
166 // Ensure the texture doesn't exceed device capabilities.
167 const auto tex_size = GetTextureDescriptor().size;
168 const auto max_size =
169 reactor_->GetProcTable().GetCapabilities()->max_texture_size;
170 if (tex_size.Max(max_size) != max_size) {
171 VALIDATION_LOG << "Texture of size " << tex_size
172 << " would exceed max supported size of " << max_size << ".";
173 return;
174 }
175
176 is_valid_ = true;
177}
178
180 handle_.Release();
181}
182
183// |Texture|
185 return is_valid_;
186}
187
188// |Texture|
189void TextureGLES::SetLabel(std::string_view label) {
190#ifdef IMPELLER_DEBUG
191 reactor_->SetDebugLabel(handle_.Get(), label);
192#endif // IMPELLER_DEBUG
193}
194
195// |Texture|
196void TextureGLES::SetLabel(std::string_view label, std::string_view trailing) {
197#ifdef IMPELLER_DEBUG
198 if (reactor_->CanSetDebugLabels()) {
199 reactor_->SetDebugLabel(handle_.Get(),
200 std::format("{} {}", label, trailing));
201 }
202#endif // IMPELLER_DEBUG
203}
204
205// |Texture|
206bool TextureGLES::OnSetContents(const uint8_t* contents,
207 size_t length,
208 size_t slice) {
209 return OnSetContents(CreateMappingWithCopy(contents, Bytes{length}), slice);
210}
211
212// |Texture|
213bool TextureGLES::OnSetContents(std::shared_ptr<const fml::Mapping> mapping,
214 size_t slice) {
215 if (!mapping) {
216 return false;
217 }
218
219 if (mapping->GetSize() == 0u) {
220 return true;
221 }
222
223 if (mapping->GetMapping() == nullptr) {
224 return false;
225 }
226
227 if (GetType() != Type::kTexture) {
228 VALIDATION_LOG << "Incorrect texture usage flags for setting contents on "
229 "this texture object.";
230 return false;
231 }
232
233 if (is_wrapped_) {
234 VALIDATION_LOG << "Cannot set the contents of a wrapped texture.";
235 return false;
236 }
237
238 const auto& tex_descriptor = GetTextureDescriptor();
239
240 if (tex_descriptor.size.IsEmpty()) {
241 return true;
242 }
243
244 if (!tex_descriptor.IsValid() ||
245 mapping->GetSize() < tex_descriptor.GetByteSizeOfBaseMipLevel()) {
246 return false;
247 }
248
249 GLenum texture_type;
250 GLenum texture_target;
251 switch (tex_descriptor.type) {
253 texture_type = GL_TEXTURE_2D;
254 texture_target = GL_TEXTURE_2D;
255 break;
257 VALIDATION_LOG << "Multisample texture uploading is not supported for "
258 "the OpenGLES backend.";
259 return false;
261 texture_type = GL_TEXTURE_CUBE_MAP;
262 texture_target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + slice;
263 break;
265 texture_type = GL_TEXTURE_EXTERNAL_OES;
266 texture_target = GL_TEXTURE_EXTERNAL_OES;
267 break;
268 }
269
270 std::optional<PixelFormatGLES> gles_format =
271 ToPixelFormatGLES(tex_descriptor.format,
272 /*supports_bgra=*/
273 reactor_->GetProcTable().GetDescription()->HasExtension(
274 "GL_EXT_texture_format_BGRA8888"));
275 if (!gles_format.has_value()) {
276 VALIDATION_LOG << "Invalid texture format.";
277 return false;
278 }
279
280 ReactorGLES::Operation texture_upload =
281 [handle = handle_.Get(), //
282 mapping, //
283 format = gles_format.value(), //
284 size = tex_descriptor.size, //
285 image_size = tex_descriptor.GetByteSizeOfBaseMipLevel(), //
286 texture_type, //
287 texture_target //
288 ](const auto& reactor) {
289 auto gl_handle = reactor.GetGLHandle(handle);
290 if (!gl_handle.has_value()) {
291 VALIDATION_LOG << "Texture was collected before it could be uploaded "
292 "to the GPU.";
293 return;
294 }
295 const auto& gl = reactor.GetProcTable();
296 gl.BindTexture(texture_type, gl_handle.value());
297 const GLvoid* tex_data = nullptr;
298 if (mapping) {
299 tex_data = mapping->GetMapping();
300 }
301
302 {
303 TRACE_EVENT1("impeller", "TexImage2DUpload", "Bytes",
304 std::to_string(mapping->GetSize()).c_str());
305 gl.PixelStorei(GL_UNPACK_ALIGNMENT, 1);
306 if (format.is_compressed) {
307 gl.CompressedTexImage2D(texture_target, // target
308 0u, // LOD level
309 format.internal_format, // internal format
310 size.width, // width
311 size.height, // height
312 0u, // border
313 image_size, // image size
314 tex_data); // data
315 } else {
316 gl.TexImage2D(texture_target, // target
317 0u, // LOD level
318 format.internal_format, // internal format
319 size.width, // width
320 size.height, // height
321 0u, // border
322 format.external_format, // format
323 format.type, // type
324 tex_data); // data
325 }
326 }
327 };
328
329 const bool added = reactor_->AddOperation(texture_upload);
330 if (added) {
332 }
333 return added;
334}
335
336// |Texture|
337ISize TextureGLES::GetSize() const {
338 return GetTextureDescriptor().size;
339}
340
341static std::optional<GLenum> ToRenderBufferFormat(PixelFormat format) {
342 switch (format) {
345 return GL_RGBA8;
347 return GL_RGBA32F;
349 return GL_RGBA16F;
351 return GL_STENCIL_INDEX8;
353 return GL_DEPTH24_STENCIL8;
355 return GL_DEPTH32F_STENCIL8;
383 return std::nullopt;
384 }
386}
387
389 // When binding to a GL_READ_FRAMEBUFFER, any multisampled
390 // textures must be bound as single sampled.
391 if (target == GL_READ_FRAMEBUFFER && type_ == Type::kTextureMultisampled) {
392 return Type::kTexture;
393 }
394 return type_;
395}
396
397void TextureGLES::InitializeContentsIfNecessary() {
398 if (!IsValid() || IsSliceMipLevelInitialized(0, 0)) {
399 return;
400 }
401
402 if (is_wrapped_) {
403 // Storage is owned externally; mark it covered so we don't re-enter.
405 return;
406 }
407
408 auto size = GetSize();
409
410 if (size.IsEmpty()) {
412 return;
413 }
414
415 const auto& gl = reactor_->GetProcTable();
416 std::optional<GLuint> handle = reactor_->GetGLHandle(handle_.Get());
417 if (!handle.has_value()) {
418 VALIDATION_LOG << "Could not initialize the contents of texture.";
419 return;
420 }
421
422 switch (type_) {
423 case Type::kTexture:
425 const auto& desc = GetTextureDescriptor();
426 std::optional<PixelFormatGLES> gles_format = ToPixelFormatGLES(
427 desc.format,
428 /*supports_bgra=*/
429 reactor_->GetProcTable().GetDescription()->HasExtension(
430 "GL_EXT_texture_format_BGRA8888"));
431 if (!gles_format.has_value()) {
432 VALIDATION_LOG << "Invalid format for texture image.";
433 return;
434 }
435 TRACE_EVENT0("impeller", "TexImage2DInitialization");
436 if (desc.type == TextureType::kTextureCube) {
437 // Cubemap handles must be bound to GL_TEXTURE_CUBE_MAP and each face
438 // target must be defined independently before sampling. Allocate the
439 // base mip level for every face here so the cubemap is sample-ready
440 // even before any face has been uploaded; non-zero mip levels are
441 // still allocated lazily on first per-level write in the blit path.
442 gl.BindTexture(GL_TEXTURE_CUBE_MAP, handle.value());
443 for (size_t face = 0; face < 6; ++face) {
444 gl.TexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, // target
445 0u, // LOD level
446 gles_format->internal_format, // internal
447 size.width, // width
448 size.height, // height
449 0u, // border
450 gles_format->external_format, // format
451 gles_format->type, // type
452 nullptr // data
453 );
455 }
456 } else {
457 // 2D / multisampled. External-OES textures are always wrapped, so
458 // they returned at the is_wrapped_ check above. Only the base mip
459 // is allocated here. `glGenerateMipmap` (used by the snapshot
460 // pipeline) implicitly allocates and fills the rest, and per-level
461 // uploads from the blit path allocate non-zero levels lazily on
462 // first write.
463 gl.BindTexture(GL_TEXTURE_2D, handle.value());
464 gl.TexImage2D(GL_TEXTURE_2D, // target
465 0u, // LOD level
466 gles_format->internal_format, // internal
467 size.width, // width
468 size.height, // height
469 0u, // border
470 gles_format->external_format, // format
471 gles_format->type, // type
472 nullptr // data
473 );
475 }
476 } break;
479 auto render_buffer_format =
481 if (!render_buffer_format.has_value()) {
482 VALIDATION_LOG << "Invalid format for render-buffer image.";
483 return;
484 }
485 gl.BindRenderbuffer(GL_RENDERBUFFER, handle.value());
486 {
487 if (type_ == Type::kRenderBufferMultisampled) {
488 // BEWARE: these functions are not at all equivalent! the extensions
489 // are from EXT_multisampled_render_to_texture and cannot be used
490 // with regular GLES 3.0 multisampled renderbuffers/textures.
491 if (gl.GetCapabilities()->SupportsImplicitResolvingMSAA()) {
492 gl.RenderbufferStorageMultisampleEXT(
493 /*target=*/GL_RENDERBUFFER, //
494 /*samples=*/4, //
495 /*internal_format=*/render_buffer_format.value(), //
496 /*width=*/size.width, //
497 /*height=*/size.height //
498 );
499 } else {
500 gl.RenderbufferStorageMultisample(
501 /*target=*/GL_RENDERBUFFER, //
502 /*samples=*/4, //
503 /*internal_format=*/render_buffer_format.value(), //
504 /*width=*/size.width, //
505 /*height=*/size.height //
506 );
507 }
508 } else {
509 gl.RenderbufferStorage(
510 /*target=*/GL_RENDERBUFFER, //
511 /*internal_format=*/render_buffer_format.value(), //
512 /*width=*/size.width, //
513 /*height=*/size.height //
514 );
515 }
516 }
517 // Renderbuffers don't have mip levels, but we still mark slot (0, 0)
518 // so the early-out guard at the top of this function fires on subsequent
519 // calls.
521 } break;
522 }
523}
524
525std::optional<GLuint> TextureGLES::GetGLHandle() const {
526 if (!IsValid()) {
527 return std::nullopt;
528 }
529 return reactor_->GetGLHandle(handle_.Get());
530}
531
533 auto handle = GetGLHandle();
534 if (!handle.has_value()) {
535 return false;
536 }
537 const auto& gl = reactor_->GetProcTable();
538
539 if (fence_.IsValid()) {
540 std::optional<GLsync> fence = reactor_->GetGLFence(fence_.Get());
541 if (fence.has_value()) {
542 gl.WaitSync(fence.value(), 0, GL_TIMEOUT_IGNORED);
543 }
544 fence_.Reset();
545 }
546
547 switch (type_) {
548 case Type::kTexture:
551 if (!target.has_value()) {
552 VALIDATION_LOG << "Could not bind texture of this type.";
553 return false;
554 }
555 gl.BindTexture(target.value(), handle.value());
556 } break;
559 gl.BindRenderbuffer(GL_RENDERBUFFER, handle.value());
560 break;
561 }
562 InitializeContentsIfNecessary();
563 return true;
564}
565
567 for (auto& slice_mips : slice_mip_initialized_) {
568 slice_mips.set();
569 }
570}
571
575
576bool TextureGLES::IsSliceInitialized(size_t slice) const {
577 return IsSliceMipLevelInitialized(slice, 0);
578}
579
580void TextureGLES::MarkSliceMipLevelInitialized(size_t slice, size_t mip_level) {
581 if (slice >= slice_mip_initialized_.size() ||
582 mip_level >= kMaxTrackedMipLevels) {
583 return;
584 }
585 slice_mip_initialized_[slice].set(mip_level);
586}
587
589 size_t mip_level) const {
590 if (slice >= slice_mip_initialized_.size() ||
591 mip_level >= kMaxTrackedMipLevels) {
592 return false;
593 }
594 return slice_mip_initialized_[slice].test(mip_level);
595}
596
598 if (!IsValid()) {
599 return false;
600 }
601
603 switch (type) {
605 break;
607 VALIDATION_LOG << "Generating mipmaps for multisample textures is not "
608 "supported in the GLES backend.";
609 return false;
611 break;
613 break;
614 }
615
616 if (!Bind()) {
617 return false;
618 }
619
620 auto handle = GetGLHandle();
621 if (!handle.has_value()) {
622 return false;
623 }
624
625 const auto& gl = reactor_->GetProcTable();
626 gl.GenerateMipmap(ToTextureType(type));
627 mipmap_generated_ = true;
628 return true;
629}
630
632 return type_;
633}
634
636 switch (point) {
638 return GL_COLOR_ATTACHMENT0;
640 return GL_DEPTH_ATTACHMENT;
642 return GL_STENCIL_ATTACHMENT;
643 }
644}
645
646bool TextureGLES::EnsureSliceMipLevelStorage(size_t slice, size_t mip_level) {
647 if (IsSliceMipLevelInitialized(slice, mip_level)) {
648 return true;
649 }
650 // Renderbuffers and multisampled textures only have their single level
651 // allocated at init; only sampled 2D and cube textures allocate per-level.
652 if (type_ != Type::kTexture) {
653 return true;
654 }
655 auto handle = GetGLHandle();
656 if (!handle.has_value()) {
657 return false;
658 }
659 const auto& gl = reactor_->GetProcTable();
660 const auto& desc = GetTextureDescriptor();
661 std::optional<PixelFormatGLES> gles_format = ToPixelFormatGLES(
662 desc.format,
663 gl.GetDescription()->HasExtension("GL_EXT_texture_format_BGRA8888"));
664 if (!gles_format.has_value()) {
665 return false;
666 }
667 ISize size = GetSize();
668 bool is_cube = desc.type == TextureType::kTextureCube;
669 GLenum image_target =
670 is_cube ? GL_TEXTURE_CUBE_MAP_POSITIVE_X + slice : GL_TEXTURE_2D;
671 gl.BindTexture(is_cube ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D, handle.value());
672 gl.TexImage2D(image_target, // target
673 static_cast<GLint>(mip_level), // LOD level
674 gles_format->internal_format, // internal
675 static_cast<GLsizei>(
676 std::max<int64_t>(1, size.width >> mip_level)), // width
677 static_cast<GLsizei>(
678 std::max<int64_t>(1, size.height >> mip_level)), // height
679 0u, // border
680 gles_format->external_format, // format
681 gles_format->type, // type
682 nullptr // data
683 );
684 MarkSliceMipLevelInitialized(slice, mip_level);
685 return true;
686}
687
689 AttachmentType attachment_type,
690 uint32_t mip_level,
691 uint32_t slice) {
692 if (!IsValid()) {
693 return false;
694 }
695 InitializeContentsIfNecessary();
696 const auto& gl = reactor_->GetProcTable();
697 if (mip_level > 0 &&
698 !gl.GetCapabilities()->SupportsFramebufferRenderMipmap()) {
699 VALIDATION_LOG << "Rendering into a non-zero mip level is not supported on "
700 "the GLES backend.";
701 return false;
702 }
703 if (!EnsureSliceMipLevelStorage(slice, mip_level)) {
704 return false;
705 }
706 auto handle = GetGLHandle();
707 if (!handle.has_value()) {
708 return false;
709 }
710 const GLint level = static_cast<GLint>(mip_level);
711
712 switch (ComputeTypeForBinding(target)) {
713 case Type::kTexture: {
714 // Cube maps attach a specific face; 2D textures attach the 2D target.
715 GLenum textarget =
717 ? GL_TEXTURE_CUBE_MAP_POSITIVE_X + slice
718 : GL_TEXTURE_2D;
719 gl.FramebufferTexture2D(target, // target
720 ToAttachmentType(attachment_type), // attachment
721 textarget, // textarget
722 handle.value(), // texture
723 level // level
724 );
725 break;
726 }
728 gl.FramebufferTexture2DMultisampleEXT(
729 target, // target
730 ToAttachmentType(attachment_type), // attachment
731 GL_TEXTURE_2D, // textarget
732 handle.value(), // texture
733 level, // level
734 4 // samples
735 );
736 break;
739 gl.FramebufferRenderbuffer(
740 target, // target
741 ToAttachmentType(attachment_type), // attachment
742 GL_RENDERBUFFER, // render-buffer target
743 handle.value() // render-buffer
744 );
745 break;
746 }
747
748 return true;
749}
750
752 return is_wrapped_;
753}
754
755std::optional<GLuint> TextureGLES::GetFBO() const {
756 return wrapped_fbo_;
757}
758
760 FML_DCHECK(!fence_.IsValid());
761 fence_ = UniqueHandleGLES(reactor_, fence);
762}
763
764// Visible for testing.
765std::optional<HandleGLES> TextureGLES::GetSyncFence() const {
766 return fence_.IsValid() ? std::optional(fence_.Get()) : std::nullopt;
767}
768
770 cached_fbo_ = UniqueHandleGLES(reactor_, fbo);
771}
772
774 return cached_fbo_.Get();
775}
776
777void TextureGLES::SetCachedFBOSubresource(uint32_t mip_level, uint32_t slice) {
778 cached_fbo_mip_level_ = mip_level;
779 cached_fbo_slice_ = slice;
780}
781
783 uint32_t slice) const {
784 return cached_fbo_mip_level_ == mip_level && cached_fbo_slice_ == slice;
785}
786
787} // namespace impeller
Represents a handle to an underlying OpenGL object. Unlike OpenGL object handles, these handles can b...
Definition handle_gles.h:42
constexpr bool IsDead() const
Determines if the handle is dead.
Definition handle_gles.h:58
HandleType GetType() const
Definition handle_gles.h:79
std::function< void(const ReactorGLES &reactor)> Operation
void MarkSliceInitialized(size_t slice)
Indicates that a specific texture slice has been initialized.
static std::shared_ptr< TextureGLES > WrapFBO(std::shared_ptr< ReactorGLES > reactor, TextureDescriptor desc, GLuint fbo)
Create a texture by wrapping an external framebuffer object whose lifecycle is owned by the caller.
void MarkContentsInitialized()
Indicates that all texture storage has already been allocated and contents initialized.
const HandleGLES & GetCachedFBO() const
Retrieve the cached FBO object, or a dead handle if there is no object.
std::optional< HandleGLES > GetSyncFence() const
bool IsSliceMipLevelInitialized(size_t slice, size_t mip_level) const
bool CachedFBOMatchesSubresource(uint32_t mip_level, uint32_t slice) const
bool IsSliceInitialized(size_t slice) const
void SetCachedFBOSubresource(uint32_t mip_level, uint32_t slice)
Records the subresource the cached FBO is currently bound to.
void MarkSliceMipLevelInitialized(size_t slice, size_t mip_level)
Indicates that storage for mip_level of slice has been allocated by a glTexImage2D call (or equivalen...
bool IsValid() const override
void SetFence(HandleGLES fence)
Attach a sync fence to this texture that will be waited on before encoding a rendering operation that...
void Leak()
Reset the internal texture state so that the reactor will not free the associated handle.
void SetCachedFBO(HandleGLES fbo)
TextureGLES(std::shared_ptr< ReactorGLES > reactor, TextureDescriptor desc, bool threadsafe=false)
static std::shared_ptr< TextureGLES > CreatePlaceholder(std::shared_ptr< ReactorGLES > reactor, TextureDescriptor desc)
Create a "texture" that is never expected to be bound/unbound explicitly or initialized in any way....
bool SetAsFramebufferAttachment(GLenum target, AttachmentType attachment_type, uint32_t mip_level=0, uint32_t slice=0)
std::optional< GLuint > GetFBO() const
Type ComputeTypeForBinding(GLenum target) const
std::optional< GLuint > GetGLHandle() const
static std::shared_ptr< TextureGLES > WrapTexture(std::shared_ptr< ReactorGLES > reactor, TextureDescriptor desc, HandleGLES external_handle)
Create a texture by wrapping an external OpenGL texture handle. Ownership of the texture handle is as...
const TextureDescriptor & GetTextureDescriptor() const
Definition texture.cc:55
bool mipmap_generated_
Definition texture.h:69
A unique handle to an OpenGL object. The collection of this handle scheduled the destruction of the a...
const HandleGLES & Get() const
void Reset()
Collect the managed handle and replace it with a dead handle.
HandleGLES Release()
Release ownership of the handle.
int32_t value
uint32_t uint32_t * format
uint32_t * target
#define FML_UNREACHABLE()
Definition logging.h:128
#define FML_DCHECK(condition)
Definition logging.h:122
size_t length
FlTexture * texture
it will be possible to load the file into Perfetto s trace viewer use test Running tests that layout and measure text will not yield consistent results across various platforms Enabling this option will make font resolution default to the Ahem test font on all disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
std::optional< PixelFormatGLES > ToPixelFormatGLES(PixelFormat pixel_format, bool supports_bgra)
constexpr std::optional< GLenum > ToTextureTarget(TextureType type)
std::shared_ptr< fml::Mapping > CreateMappingWithCopy(const uint8_t *contents, Bytes length)
Creates a mapping with copy of the bytes.
Definition allocation.cc:83
AllocationSize< 1u > Bytes
PixelFormat
The Pixel formats supported by Impeller. The naming convention denotes the usage of the component,...
Definition formats.h:99
constexpr GLenum ToTextureType(TextureType type)
static std::optional< GLenum > ToRenderBufferFormat(PixelFormat format)
ISize64 ISize
Definition size.h:162
static GLenum ToAttachmentType(TextureGLES::AttachmentType point)
Mask< TextureUsage > TextureUsageMask
Definition formats.h:496
HandleType ToHandleType(TextureGLES::Type type)
Definition ref_ptr.h:261
fuchsia::ui::composition::ParentViewportWatcherHandle handle_
std::shared_ptr< ReactorGLES > reactor
impeller::ShaderType type
A lightweight object that describes the attributes of a texture that can then used an allocator to cr...
#define TRACE_EVENT0(category_group, name)
#define TRACE_EVENT1(category_group, name, arg1_name, arg1_val)
#define VALIDATION_LOG
Definition validation.h:91