23static bool IsDepthStencilFormat(
PixelFormat format) {
66 const TextureDescriptor& desc,
67 const std::shared_ptr<const CapabilitiesGLES>& capabilities) {
71 if (usage == render_target && IsDepthStencilFormat(desc.format)) {
75 return is_msaa ? (capabilities->SupportsImplicitResolvingMSAA()
96 std::shared_ptr<ReactorGLES>
reactor,
99 auto texture = std::shared_ptr<TextureGLES>(
108 std::shared_ptr<ReactorGLES>
reactor,
111 if (external_handle.
IsDead()) {
120 std::move(
reactor), desc,
false, std::nullopt, external_handle));
128 std::shared_ptr<ReactorGLES>
reactor,
146 std::optional<GLuint> fbo,
147 std::optional<HandleGLES> external_handle)
150 type_(GetTextureTypeFromDescriptor(
151 GetTextureDescriptor(),
152 reactor_->GetProcTable().GetCapabilities())),
154 external_handle.has_value()
160 is_wrapped_(fbo.has_value() || external_handle.has_value()),
168 const auto max_size =
169 reactor_->GetProcTable().GetCapabilities()->max_texture_size;
170 if (tex_size.Max(max_size) != max_size) {
172 <<
" would exceed max supported size of " << max_size <<
".";
189void TextureGLES::SetLabel(std::string_view label) {
191 reactor_->SetDebugLabel(handle_.
Get(), label);
196void TextureGLES::SetLabel(std::string_view label, std::string_view trailing) {
198 if (reactor_->CanSetDebugLabels()) {
199 reactor_->SetDebugLabel(handle_.
Get(),
200 std::format(
"{} {}", label, trailing));
206bool TextureGLES::OnSetContents(
const uint8_t* contents,
213bool TextureGLES::OnSetContents(std::shared_ptr<const fml::Mapping> mapping,
219 if (mapping->GetSize() == 0u) {
223 if (mapping->GetMapping() ==
nullptr) {
228 VALIDATION_LOG <<
"Incorrect texture usage flags for setting contents on "
229 "this texture object.";
234 VALIDATION_LOG <<
"Cannot set the contents of a wrapped texture.";
240 if (tex_descriptor.size.IsEmpty()) {
244 if (!tex_descriptor.IsValid() ||
245 mapping->GetSize() < tex_descriptor.GetByteSizeOfBaseMipLevel()) {
250 GLenum texture_target;
251 switch (tex_descriptor.type) {
253 texture_type = GL_TEXTURE_2D;
254 texture_target = GL_TEXTURE_2D;
257 VALIDATION_LOG <<
"Multisample texture uploading is not supported for "
258 "the OpenGLES backend.";
261 texture_type = GL_TEXTURE_CUBE_MAP;
262 texture_target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + slice;
265 texture_type = GL_TEXTURE_EXTERNAL_OES;
266 texture_target = GL_TEXTURE_EXTERNAL_OES;
270 std::optional<PixelFormatGLES> gles_format =
273 reactor_->GetProcTable().GetDescription()->HasExtension(
274 "GL_EXT_texture_format_BGRA8888"));
275 if (!gles_format.has_value()) {
281 [handle = handle_.
Get(),
283 format = gles_format.value(),
284 size = tex_descriptor.size,
285 image_size = tex_descriptor.GetByteSizeOfBaseMipLevel(),
289 auto gl_handle =
reactor.GetGLHandle(handle);
290 if (!gl_handle.has_value()) {
291 VALIDATION_LOG <<
"Texture was collected before it could be uploaded "
295 const auto& gl =
reactor.GetProcTable();
296 gl.BindTexture(texture_type, gl_handle.value());
297 const GLvoid* tex_data =
nullptr;
299 tex_data = mapping->GetMapping();
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,
316 gl.TexImage2D(texture_target,
329 const bool added = reactor_->AddOperation(texture_upload);
337ISize TextureGLES::GetSize()
const {
351 return GL_STENCIL_INDEX8;
353 return GL_DEPTH24_STENCIL8;
355 return GL_DEPTH32F_STENCIL8;
397void TextureGLES::InitializeContentsIfNecessary() {
408 auto size = GetSize();
410 if (
size.IsEmpty()) {
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.";
429 reactor_->GetProcTable().GetDescription()->HasExtension(
430 "GL_EXT_texture_format_BGRA8888"));
431 if (!gles_format.has_value()) {
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,
446 gles_format->internal_format,
450 gles_format->external_format,
463 gl.BindTexture(GL_TEXTURE_2D, handle.value());
464 gl.TexImage2D(GL_TEXTURE_2D,
466 gles_format->internal_format,
470 gles_format->external_format,
479 auto render_buffer_format =
481 if (!render_buffer_format.has_value()) {
485 gl.BindRenderbuffer(GL_RENDERBUFFER, handle.value());
491 if (gl.GetCapabilities()->SupportsImplicitResolvingMSAA()) {
492 gl.RenderbufferStorageMultisampleEXT(
495 render_buffer_format.value(),
500 gl.RenderbufferStorageMultisample(
503 render_buffer_format.value(),
509 gl.RenderbufferStorage(
511 render_buffer_format.value(),
529 return reactor_->GetGLHandle(handle_.
Get());
534 if (!handle.has_value()) {
537 const auto& gl = reactor_->GetProcTable();
540 std::optional<GLsync> fence = reactor_->GetGLFence(fence_.
Get());
541 if (fence.has_value()) {
542 gl.WaitSync(fence.value(), 0, GL_TIMEOUT_IGNORED);
551 if (!
target.has_value()) {
555 gl.BindTexture(
target.value(), handle.value());
559 gl.BindRenderbuffer(GL_RENDERBUFFER, handle.value());
562 InitializeContentsIfNecessary();
567 for (
auto& slice_mips : slice_mip_initialized_) {
581 if (slice >= slice_mip_initialized_.size() ||
582 mip_level >= kMaxTrackedMipLevels) {
585 slice_mip_initialized_[slice].set(mip_level);
589 size_t mip_level)
const {
590 if (slice >= slice_mip_initialized_.size() ||
591 mip_level >= kMaxTrackedMipLevels) {
594 return slice_mip_initialized_[slice].test(mip_level);
607 VALIDATION_LOG <<
"Generating mipmaps for multisample textures is not "
608 "supported in the GLES backend.";
621 if (!handle.has_value()) {
625 const auto& gl = reactor_->GetProcTable();
638 return GL_COLOR_ATTACHMENT0;
640 return GL_DEPTH_ATTACHMENT;
642 return GL_STENCIL_ATTACHMENT;
646bool TextureGLES::EnsureSliceMipLevelStorage(
size_t slice,
size_t mip_level) {
656 if (!handle.has_value()) {
659 const auto& gl = reactor_->GetProcTable();
663 gl.GetDescription()->HasExtension(
"GL_EXT_texture_format_BGRA8888"));
664 if (!gles_format.has_value()) {
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,
673 static_cast<GLint
>(mip_level),
674 gles_format->internal_format,
675 static_cast<GLsizei
>(
676 std::max<int64_t>(1,
size.width >> mip_level)),
677 static_cast<GLsizei
>(
678 std::max<int64_t>(1,
size.height >> mip_level)),
680 gles_format->external_format,
695 InitializeContentsIfNecessary();
696 const auto& gl = reactor_->GetProcTable();
698 !gl.GetCapabilities()->SupportsFramebufferRenderMipmap()) {
699 VALIDATION_LOG <<
"Rendering into a non-zero mip level is not supported on "
703 if (!EnsureSliceMipLevelStorage(slice, mip_level)) {
707 if (!handle.has_value()) {
710 const GLint level =
static_cast<GLint
>(mip_level);
717 ? GL_TEXTURE_CUBE_MAP_POSITIVE_X + slice
719 gl.FramebufferTexture2D(
target,
728 gl.FramebufferTexture2DMultisampleEXT(
739 gl.FramebufferRenderbuffer(
766 return fence_.
IsValid() ? std::optional(fence_.
Get()) : std::nullopt;
774 return cached_fbo_.
Get();
778 cached_fbo_mip_level_ = mip_level;
779 cached_fbo_slice_ = slice;
783 uint32_t slice)
const {
784 return cached_fbo_mip_level_ == mip_level && cached_fbo_slice_ == slice;
Represents a handle to an underlying OpenGL object. Unlike OpenGL object handles, these handles can b...
constexpr bool IsDead() const
Determines if the handle is dead.
HandleType GetType() const
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.
@ kRenderBufferMultisampled
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
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.
uint32_t uint32_t * format
#define FML_UNREACHABLE()
#define FML_DCHECK(condition)
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.
AllocationSize< 1u > Bytes
PixelFormat
The Pixel formats supported by Impeller. The naming convention denotes the usage of the component,...
constexpr GLenum ToTextureType(TextureType type)
static std::optional< GLenum > ToRenderBufferFormat(PixelFormat format)
static GLenum ToAttachmentType(TextureGLES::AttachmentType point)
Mask< TextureUsage > TextureUsageMask
HandleType ToHandleType(TextureGLES::Type type)
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)