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 #include <memory>
7 
10 #include "impeller/core/formats.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 
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 
65 #ifdef IMPELLER_DEBUG
66  if (debug_allocator_) {
67  auto desc = GetTextureDescriptor();
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 
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
const TextureDescriptor & GetTextureDescriptor() const
Definition: texture.cc:57
bool mipmap_generated_
Definition: texture.h:79
id< MTLTexture > GetMTLTexture() const
Definition: texture_mtl.mm:147
~TextureMTL() override
Definition: texture_mtl.mm:64
TextureMTL(TextureDescriptor desc, const AcquireTextureProc &aquire_proc, bool wrapped=false, bool drawable=false)
Definition: texture_mtl.mm:22
bool IsDrawable() const
Whether or not this texture is wrapping a Metal drawable.
Definition: texture_mtl.mm:159
bool IsValid() const override
Definition: texture_mtl.mm:151
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:155
bool GenerateMipmap(id< MTLBlitCommandEncoder > encoder)
Definition: texture_mtl.mm:163
static std::shared_ptr< TextureMTL > Wrapper(TextureDescriptor desc, id< MTLTexture > texture, std::function< void()> deletion_proc=nullptr)
Definition: texture_mtl.mm:42
static std::shared_ptr< TextureMTL > Create(TextureDescriptor desc, id< MTLTexture > texture)
Definition: texture_mtl.mm:59
std::string SPrintF(const char *format,...)
Definition: strings.cc:12
std::shared_ptr< Texture > WrapperMTL(TextureDescriptor desc, const void *mtl_texture, std::function< void()> deletion_proc)
Definition: texture_mtl.mm:15
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