Flutter Engine
 
Loading...
Searching...
No Matches
texture_mtl.mm
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 <memory>
9
14
15namespace impeller {
16
17std::shared_ptr<Texture> WrapperMTL(TextureDescriptor desc,
18 const void* mtl_texture,
19 std::function<void()> deletion_proc) {
20 return TextureMTL::Wrapper(desc, (__bridge id<MTLTexture>)mtl_texture,
21 std::move(deletion_proc));
22}
23
25 const AcquireTextureProc& aquire_proc,
26 bool wrapped,
27 bool drawable)
28 : Texture(p_desc), aquire_proc_(aquire_proc), is_drawable_(drawable) {
29 const auto& desc = GetTextureDescriptor();
30
31 if (!desc.IsValid() || !aquire_proc) {
32 return;
33 }
34
35 if (desc.size != GetSize()) {
36 VALIDATION_LOG << "The texture and its descriptor disagree about its size.";
37 return;
38 }
39
40 is_wrapped_ = wrapped;
41 is_valid_ = true;
42}
43
44std::shared_ptr<TextureMTL> TextureMTL::Wrapper(
46 id<MTLTexture> texture,
47 std::function<void()> deletion_proc) {
48 if (deletion_proc) {
49 return std::shared_ptr<TextureMTL>(
50 new TextureMTL(
51 desc, [texture]() { return texture; }, true),
52 [deletion_proc = std::move(deletion_proc)](TextureMTL* t) {
53 deletion_proc();
54 delete t;
55 });
56 }
57 return std::shared_ptr<TextureMTL>(
58 new TextureMTL(desc, [texture]() { return texture; }, true));
59}
60
61std::shared_ptr<TextureMTL> TextureMTL::Create(TextureDescriptor desc,
62 id<MTLTexture> texture) {
63 return std::make_shared<TextureMTL>(desc, [texture]() { return texture; });
64}
65
67#ifdef IMPELLER_DEBUG
68 if (debug_allocator_) {
69 auto desc = GetTextureDescriptor();
71 return;
72 }
73 debug_allocator_->Decrement(desc.GetByteSizeOfBaseMipLevel());
74 }
75#endif // IMPELLER_DEBUG
76}
77
78void TextureMTL::SetLabel(std::string_view label) {
79#ifdef IMPELLER_DEBUG
80 if (is_drawable_) {
81 return;
82 }
83 [aquire_proc_() setLabel:@(label.data())];
84#endif // IMPELLER_DEBUG
85}
86
87void TextureMTL::SetLabel(std::string_view label, std::string_view trailing) {
88#ifdef IMPELLER_DEBUG
89 if (is_drawable_) {
90 return;
91 }
92 std::string combined = std::format("{} {}", label, trailing);
93 [aquire_proc_() setLabel:@(combined.data())];
94#endif // IMPELLER_DEBUG
95}
96
97// |Texture|
98bool TextureMTL::OnSetContents(std::shared_ptr<const fml::Mapping> mapping,
99 size_t slice) {
100 // Metal has no threading restrictions. So we can pass this data along to the
101 // client rendering API immediately.
102 return OnSetContents(mapping->GetMapping(), mapping->GetSize(), slice);
103}
104
105#ifdef IMPELLER_DEBUG
106void TextureMTL::SetDebugAllocator(
107 const std::shared_ptr<DebugAllocatorStats>& debug_allocator) {
108 debug_allocator_ = debug_allocator;
109}
110#endif // IMPELLER_DEBUG
111
112// |Texture|
113bool TextureMTL::OnSetContents(const uint8_t* contents,
114 size_t length,
115 size_t slice) {
116 if (!IsValid() || !contents || is_wrapped_ || is_drawable_) {
117 return false;
118 }
119
120 const auto& desc = GetTextureDescriptor();
121
122 // Out of bounds access.
123 if (length != desc.GetByteSizeOfBaseMipLevel()) {
124 return false;
125 }
126
127 const auto region =
128 MTLRegionMake2D(0u, 0u, desc.size.width, desc.size.height);
129 [aquire_proc_() replaceRegion:region //
130 mipmapLevel:0u //
131 slice:slice //
132 withBytes:contents //
133 bytesPerRow:desc.GetBytesPerRow() //
134 bytesPerImage:desc.GetByteSizeOfBaseMipLevel() //
135 ];
136
137 return true;
138}
139
140ISize TextureMTL::GetSize() const {
141 if (is_drawable_) {
142 return GetTextureDescriptor().size;
143 }
144 const auto& texture = aquire_proc_();
145 return {static_cast<ISize::Type>(texture.width),
146 static_cast<ISize::Type>(texture.height)};
147}
148
149id<MTLTexture> TextureMTL::GetMTLTexture() const {
150 return aquire_proc_();
151}
152
154 return is_valid_;
155}
156
158 return is_wrapped_;
159}
160
162 return is_drawable_;
163}
164
165bool TextureMTL::GenerateMipmap(id<MTLBlitCommandEncoder> encoder) {
166 if (is_drawable_) {
167 return false;
168 }
169
170 auto texture = aquire_proc_();
171 if (!texture) {
172 return false;
173 }
174
175 [encoder generateMipmapsForTexture:texture];
176 mipmap_generated_ = true;
177
178 return true;
179}
180
181} // namespace impeller
const TextureDescriptor & GetTextureDescriptor() const
Definition texture.cc:57
bool mipmap_generated_
Definition texture.h:79
id< MTLTexture > GetMTLTexture() const
TextureMTL(TextureDescriptor desc, const AcquireTextureProc &aquire_proc, bool wrapped=false, bool drawable=false)
bool IsDrawable() const
Whether or not this texture is wrapping a Metal drawable.
bool IsValid() const override
std::function< id< MTLTexture >()> AcquireTextureProc
This callback needs to always return the same texture when called multiple times.
Definition texture_mtl.h:21
bool IsWrapped() const
bool GenerateMipmap(id< MTLBlitCommandEncoder > encoder)
static std::shared_ptr< TextureMTL > Wrapper(TextureDescriptor desc, id< MTLTexture > texture, std::function< void()> deletion_proc=nullptr)
static std::shared_ptr< TextureMTL > Create(TextureDescriptor desc, id< MTLTexture > texture)
size_t length
FlTexture * texture
std::shared_ptr< Texture > WrapperMTL(TextureDescriptor desc, const void *mtl_texture, std::function< void()> deletion_proc)
ISize64 ISize
Definition size.h:162
Type height
Definition size.h:29
Type width
Definition size.h:28
A lightweight object that describes the attributes of a texture that can then used an allocator to cr...
constexpr size_t GetByteSizeOfBaseMipLevel() const
constexpr bool IsValid() const
std::shared_ptr< const fml::Mapping > data
#define VALIDATION_LOG
Definition validation.h:91