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 
6 
7 #include <format>
8 #include <memory>
9 
10 #include "impeller/base/strings.h"
12 #include "impeller/core/formats.h"
14 
15 namespace impeller {
16 
17 std::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 
44 std::shared_ptr<TextureMTL> TextureMTL::Wrapper(
45  TextureDescriptor desc,
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 
61 std::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 
78 void 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 
87 void 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|
98 bool 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
106 void TextureMTL::SetDebugAllocator(
107  const std::shared_ptr<DebugAllocatorStats>& debug_allocator) {
108  debug_allocator_ = debug_allocator;
109 }
110 #endif // IMPELLER_DEBUG
111 
112 // |Texture|
113 bool 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 
140 ISize 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 
149 id<MTLTexture> TextureMTL::GetMTLTexture() const {
150  return aquire_proc_();
151 }
152 
153 bool TextureMTL::IsValid() const {
154  return is_valid_;
155 }
156 
157 bool TextureMTL::IsWrapped() const {
158  return is_wrapped_;
159 }
160 
162  return is_drawable_;
163 }
164 
165 bool 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
Definition: texture_mtl.mm:149
~TextureMTL() override
Definition: texture_mtl.mm:66
TextureMTL(TextureDescriptor desc, const AcquireTextureProc &aquire_proc, bool wrapped=false, bool drawable=false)
Definition: texture_mtl.mm:24
bool IsDrawable() const
Whether or not this texture is wrapping a Metal drawable.
Definition: texture_mtl.mm:161
bool IsValid() const override
Definition: texture_mtl.mm:153
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
Definition: texture_mtl.mm:157
bool GenerateMipmap(id< MTLBlitCommandEncoder > encoder)
Definition: texture_mtl.mm:165
static std::shared_ptr< TextureMTL > Wrapper(TextureDescriptor desc, id< MTLTexture > texture, std::function< void()> deletion_proc=nullptr)
Definition: texture_mtl.mm:44
static std::shared_ptr< TextureMTL > Create(TextureDescriptor desc, id< MTLTexture > texture)
Definition: texture_mtl.mm:61
std::shared_ptr< Texture > WrapperMTL(TextureDescriptor desc, const void *mtl_texture, std::function< void()> deletion_proc)
Definition: texture_mtl.mm:17
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
Definition: texture_gles.cc:68
#define VALIDATION_LOG
Definition: validation.h:91