Flutter Impeller
blit_pass.cc
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 #include <utility>
10 
12 #include "impeller/core/formats.h"
13 
14 namespace impeller {
15 
17 
18 BlitPass::~BlitPass() = default;
19 
20 void BlitPass::SetLabel(std::string_view label) {
21  if (label.empty()) {
22  return;
23  }
24  OnSetLabel(label);
25 }
26 
27 bool BlitPass::AddCopy(std::shared_ptr<Texture> source,
28  std::shared_ptr<Texture> destination,
29  std::optional<IRect> source_region,
30  IPoint destination_origin,
31  std::string_view label) {
32  if (!source) {
33  VALIDATION_LOG << "Attempted to add a texture blit with no source.";
34  return false;
35  }
36  if (!destination) {
37  VALIDATION_LOG << "Attempted to add a texture blit with no destination.";
38  return false;
39  }
40 
41  if (source->GetTextureDescriptor().sample_count !=
42  destination->GetTextureDescriptor().sample_count) {
43  VALIDATION_LOG << std::format(
44  "The source sample count ({}) must match the destination sample count "
45  "({}) for blits.",
46  static_cast<int>(source->GetTextureDescriptor().sample_count),
47  static_cast<int>(destination->GetTextureDescriptor().sample_count));
48  return false;
49  }
50  if (source->GetTextureDescriptor().format !=
51  destination->GetTextureDescriptor().format) {
52  VALIDATION_LOG << std::format(
53  "The source pixel format ({}) must match the destination pixel format "
54  "({}) "
55  "for blits.",
56  PixelFormatToString(source->GetTextureDescriptor().format),
57  PixelFormatToString(destination->GetTextureDescriptor().format));
58  return false;
59  }
60 
61  if (!source_region.has_value()) {
62  source_region = IRect::MakeSize(source->GetSize());
63  }
64 
65  // Clip the source image.
66  source_region =
67  source_region->Intersection(IRect::MakeSize(source->GetSize()));
68  if (!source_region.has_value()) {
69  return true; // Nothing to blit.
70  }
71 
73  std::move(source), std::move(destination), source_region.value(),
74  destination_origin, label);
75 }
76 
77 bool BlitPass::AddCopy(std::shared_ptr<Texture> source,
78  std::shared_ptr<DeviceBuffer> destination,
79  std::optional<IRect> source_region,
80  size_t destination_offset,
81  std::string_view label) {
82  if (!source) {
83  VALIDATION_LOG << "Attempted to add a texture blit with no source.";
84  return false;
85  }
86  if (!destination) {
87  VALIDATION_LOG << "Attempted to add a texture blit with no destination.";
88  return false;
89  }
90 
91  if (!source_region.has_value()) {
92  source_region = IRect::MakeSize(source->GetSize());
93  }
94 
95  auto bytes_per_pixel =
96  BytesPerPixelForPixelFormat(source->GetTextureDescriptor().format);
97  auto bytes_per_image = source_region->Area() * bytes_per_pixel;
98  if (destination_offset + bytes_per_image >
99  destination->GetDeviceBufferDescriptor().size) {
101  << "Attempted to add a texture blit with out of bounds access.";
102  return false;
103  }
104 
105  // Clip the source image.
106  source_region =
107  source_region->Intersection(IRect::MakeSize(source->GetSize()));
108  if (!source_region.has_value()) {
109  return true; // Nothing to blit.
110  }
111 
112  return OnCopyTextureToBufferCommand(std::move(source), std::move(destination),
113  source_region.value(), destination_offset,
114  label);
115 }
116 
118  std::shared_ptr<Texture> destination,
119  std::optional<IRect> destination_region,
120  std::string_view label,
121  uint32_t mip_level,
122  uint32_t slice,
123  bool convert_to_read) {
124  if (!destination) {
125  VALIDATION_LOG << "Attempted to add a texture blit with no destination.";
126  return false;
127  }
128  ISize destination_size = destination->GetSize();
129  IRect destination_region_value =
130  destination_region.value_or(IRect::MakeSize(destination_size));
131  if (destination_region_value.GetX() < 0 ||
132  destination_region_value.GetY() < 0 ||
133  destination_region_value.GetRight() > destination_size.width ||
134  destination_region_value.GetBottom() > destination_size.height) {
135  VALIDATION_LOG << "Blit region cannot be larger than destination texture.";
136  return false;
137  }
138 
139  auto bytes_per_pixel =
140  BytesPerPixelForPixelFormat(destination->GetTextureDescriptor().format);
141  auto bytes_per_region = destination_region_value.Area() * bytes_per_pixel;
142 
143  if (source.GetRange().length != bytes_per_region) {
145  << "Attempted to add a texture blit with out of bounds access.";
146  return false;
147  }
148  if (mip_level >= destination->GetMipCount()) {
149  VALIDATION_LOG << "Invalid value for mip_level: " << mip_level << ". "
150  << "The destination texture has "
151  << destination->GetMipCount() << " mip levels.";
152  return false;
153  }
154  if (slice > 5) {
155  VALIDATION_LOG << "Invalid value for slice: " << slice;
156  return false;
157  }
158 
159  return OnCopyBufferToTextureCommand(std::move(source), std::move(destination),
160  destination_region_value, label,
161  mip_level, slice, convert_to_read);
162 }
163 
165  const std::shared_ptr<Texture>& texture) {
166  return true;
167 }
168 
169 bool BlitPass::GenerateMipmap(std::shared_ptr<Texture> texture,
170  std::string_view label) {
171  if (!texture) {
172  VALIDATION_LOG << "Attempted to add an invalid mipmap generation command "
173  "with no texture.";
174  return false;
175  }
176 
177  return OnGenerateMipmapCommand(std::move(texture), label);
178 }
179 
180 } // namespace impeller
void SetLabel(std::string_view label)
Definition: blit_pass.cc:20
bool AddCopy(std::shared_ptr< Texture > source, std::shared_ptr< Texture > destination, std::optional< IRect > source_region=std::nullopt, IPoint destination_origin={}, std::string_view label="")
Record a command to copy the contents of one texture to another texture. The blit area is limited by ...
Definition: blit_pass.cc:27
virtual bool OnCopyTextureToTextureCommand(std::shared_ptr< Texture > source, std::shared_ptr< Texture > destination, IRect source_region, IPoint destination_origin, std::string_view label)=0
bool GenerateMipmap(std::shared_ptr< Texture > texture, std::string_view label="")
Record a command to generate all mip levels for a texture.
Definition: blit_pass.cc:169
virtual bool OnGenerateMipmapCommand(std::shared_ptr< Texture > texture, std::string_view label)=0
virtual bool ConvertTextureToShaderRead(const std::shared_ptr< Texture > &texture)
If the texture is not already in a shader read internal state, then convert it to that state.
Definition: blit_pass.cc:164
virtual bool OnCopyBufferToTextureCommand(BufferView source, std::shared_ptr< Texture > destination, IRect destination_region, std::string_view label, uint32_t mip_level, uint32_t slice, bool convert_to_read)=0
virtual bool OnCopyTextureToBufferCommand(std::shared_ptr< Texture > source, std::shared_ptr< DeviceBuffer > destination, IRect source_region, size_t destination_offset, std::string_view label)=0
virtual void OnSetLabel(std::string_view label)=0
constexpr size_t BytesPerPixelForPixelFormat(PixelFormat format)
Definition: formats.h:466
constexpr const char * PixelFormatToString(PixelFormat format)
Definition: formats.h:140
Range GetRange() const
Definition: buffer_view.h:27
size_t length
Definition: range.h:15
constexpr auto GetBottom() const
Definition: rect.h:357
constexpr Type GetY() const
Returns the Y coordinate of the upper left corner, equivalent to |GetOrigin().y|.
Definition: rect.h:337
constexpr T Area() const
Get the area of the rectangle, equivalent to |GetSize().Area()|.
Definition: rect.h:376
constexpr Type GetX() const
Returns the X coordinate of the upper left corner, equivalent to |GetOrigin().x|.
Definition: rect.h:333
constexpr auto GetRight() const
Definition: rect.h:355
constexpr static TRect MakeSize(const TSize< U > &size)
Definition: rect.h:150
Type height
Definition: size.h:29
Type width
Definition: size.h:28
#define VALIDATION_LOG
Definition: validation.h:91