| Flutter Impeller |

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