Flutter Engine Uber Docs
Docs for the entire Flutter Engine repo.
 
Loading...
Searching...
No Matches
texture.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
10#include "fml/make_copyable.h"
11#include "fml/mapping.h"
22
23#if IMPELLER_SUPPORTS_RENDERING
25#endif
27
28namespace flutter {
29namespace gpu {
30
32
33Texture::Texture(std::shared_ptr<impeller::Texture> texture)
34 : texture_(std::move(texture)) {}
35
36Texture::~Texture() = default;
37
38std::shared_ptr<impeller::Texture> Texture::GetTexture() {
39 return texture_;
40}
41
43 impeller::TextureCoordinateSystem coordinate_system) {
44 texture_->SetCoordinateSystem(coordinate_system);
45}
46
47// Returns the size in pixels of the given dimension at `mip_level`, clamped
48// at 1, matching standard mip-chain semantics. The Dart-side helper
49// `Texture.getMipLevelSizeInBytes` uses the same `max(1, dim >> level)`
50// formula in pixel-count form; if either is updated, both must be kept in
51// sync.
52static int32_t MipDimensionAtLevel(int32_t base_dimension, uint32_t mip_level) {
53 const int32_t shifted = base_dimension >> mip_level;
54 return shifted > 0 ? shifted : 1;
55}
56
57// Records a blit-pass that copies `source_bytes` into the given mip level and
58// slice of `texture` on `context`, then submits the command buffer. Returns
59// true if the encode and submit both succeed. The actual GPU upload may
60// complete asynchronously after this call returns.
62 impeller::Context& context,
63 const std::shared_ptr<impeller::Texture>& texture,
64 const std::shared_ptr<impeller::DeviceBuffer>& staging_buffer,
65 size_t source_length,
66 impeller::IRect destination_region,
67 uint32_t mip_level,
68 uint32_t slice) {
69 auto command_buffer = context.CreateCommandBuffer();
70 if (!command_buffer) {
71 FML_LOG(ERROR) << "Failed to create command buffer for texture overwrite.";
72 return false;
73 }
74 auto blit_pass = command_buffer->CreateBlitPass();
75 if (!blit_pass) {
76 FML_LOG(ERROR) << "Failed to create blit pass for texture overwrite.";
77 return false;
78 }
79 impeller::BufferView buffer_view(staging_buffer,
80 impeller::Range(0, source_length));
81 if (!blit_pass->AddCopy(std::move(buffer_view), texture, destination_region,
82 /*label=*/"Texture.overwrite", mip_level, slice)) {
83 return false;
84 }
85 if (!blit_pass->EncodeCommands()) {
86 return false;
87 }
88 return context.GetCommandQueue()->Submit({std::move(command_buffer)}).ok();
89}
90
91bool Texture::Overwrite(Context& gpu_context,
92 const tonic::DartByteData& source_bytes,
93 uint32_t mip_level,
94 uint32_t slice) {
95 const uint8_t* data = static_cast<const uint8_t*>(source_bytes.data());
96 const size_t length = source_bytes.length_in_bytes();
97
98 auto& impeller_context = gpu_context.GetContext();
99 auto staging_buffer =
100 impeller_context.GetResourceAllocator()->CreateBufferWithCopy(data,
101 length);
102 if (!staging_buffer) {
103 FML_LOG(ERROR) << "Failed to allocate staging buffer for texture "
104 "overwrite.";
105 return false;
106 }
107
108 // Compute the destination region for the requested mip level. The
109 // BlitPass::AddCopy validation requires the region to fit within the base
110 // texture size, and the actual GPU copy uses this rectangle as the
111 // destination on the chosen mip level. The same `max(1, dim >> level)`
112 // formula is used by `Texture.getMipLevelSizeInBytes` on the Dart side; if
113 // either is updated, both must be kept in sync.
114 const impeller::ISize base_size = texture_->GetSize();
115 const impeller::IRect destination_region = impeller::IRect::MakeXYWH(
116 0, 0, MipDimensionAtLevel(base_size.width, mip_level),
117 MipDimensionAtLevel(base_size.height, mip_level));
118
119 // For the GLES backend, command queue submission just flushes the reactor,
120 // which needs to happen on the raster thread.
121 if (impeller_context.GetBackendType() ==
123 auto dart_state = flutter::UIDartState::Current();
124 auto& task_runners = dart_state->GetTaskRunners();
125 auto context_shared = gpu_context.GetContextShared();
126 task_runners.GetRasterTaskRunner()->PostTask(fml::MakeCopyable(
127 [context_shared, texture = texture_, staging_buffer, length,
128 destination_region, mip_level, slice]() mutable {
129 if (!EncodeAndSubmitOverwrite(*context_shared, texture,
130 staging_buffer, length,
131 destination_region, mip_level, slice)) {
132 FML_LOG(ERROR) << "Failed to encode texture overwrite blit on the "
133 "raster thread.";
134 }
135 context_shared->DisposeThreadLocalCachedResources();
136 }));
137 return true;
138 }
139
140 if (!EncodeAndSubmitOverwrite(impeller_context, texture_, staging_buffer,
141 length, destination_region, mip_level, slice)) {
142 return false;
143 }
144 impeller_context.DisposeThreadLocalCachedResources();
145 return true;
146}
147
150 texture_->GetTextureDescriptor().format);
151}
152
153Dart_Handle Texture::AsImage() const {
154 // DlImageImpeller isn't compiled in builds with Impeller disabled. If
155 // Impeller is disabled, it's impossible to get here anyhow, so just ifdef it
156 // out.
157#if IMPELLER_SUPPORTS_RENDERING
159 auto dl_image = impeller::DlImageImpeller::Make(texture_);
160 image->set_image(dl_image);
161 auto wrapped = image->CreateOuterWrapping();
162 return wrapped;
163#else
164 return Dart_Null();
165#endif
166}
167
168} // namespace gpu
169} // namespace flutter
170
171//----------------------------------------------------------------------------
172/// Exports
173///
174
176 flutter::gpu::Context* gpu_context,
177 int storage_mode,
178 int format,
179 int width,
180 int height,
181 int sample_count,
182 int coordinate_system,
183 int texture_type,
184 bool enable_render_target_usage,
185 bool enable_shader_read_usage,
186 bool enable_shader_write_usage,
187 int mip_level_count) {
188 if (mip_level_count < 1) {
189 return false;
190 }
193 desc.size = {width, height};
195 desc.mip_count = static_cast<size_t>(mip_level_count);
196 desc.usage = {};
197 if (enable_render_target_usage) {
199 }
200 if (enable_shader_read_usage) {
202 }
203 if (enable_shader_write_usage) {
205 }
206 switch (sample_count) {
207 case 1:
209 break;
210 case 4:
212 break;
213 default:
214 return false;
215 }
216 desc.type = static_cast<impeller::TextureType>(texture_type);
219 return false;
220 }
221
222 auto texture =
223 gpu_context->GetContext().GetResourceAllocator()->CreateTexture(desc,
224 true);
225 if (!texture) {
226 FML_LOG(ERROR) << "Failed to create texture.";
227 return false;
228 }
229
230 texture->SetCoordinateSystem(
232
233 auto res = fml::MakeRefCounted<flutter::gpu::Texture>(std::move(texture));
234 res->AssociateWithDartWrapper(wrapper);
235
236 return true;
237}
238
240 flutter::gpu::Texture* wrapper,
241 int coordinate_system) {
242 return wrapper->SetCoordinateSystem(
244}
245
247 flutter::gpu::Context* gpu_context,
248 Dart_Handle source_byte_data,
249 int mip_level,
250 int slice) {
251 if (mip_level < 0 || slice < 0) {
252 return false;
253 }
254 return texture->Overwrite(*gpu_context, tonic::DartByteData(source_byte_data),
255 static_cast<uint32_t>(mip_level),
256 static_cast<uint32_t>(slice));
257}
258
260 flutter::gpu::Texture* wrapper) {
261 return wrapper->GetBytesPerTexel();
262}
263
265 return wrapper->AsImage();
266}
static fml::RefPtr< CanvasImage > Create()
Definition image.h:36
static UIDartState * Current()
std::shared_ptr< impeller::Context > & GetContextShared()
Definition context.cc:88
impeller::Context & GetContext()
Definition context.cc:84
Texture(std::shared_ptr< impeller::Texture > texture)
Definition texture.cc:33
bool Overwrite(Context &gpu_context, const tonic::DartByteData &source_bytes, uint32_t mip_level, uint32_t slice)
Definition texture.cc:91
size_t GetBytesPerTexel()
Definition texture.cc:148
std::shared_ptr< impeller::Texture > GetTexture()
Definition texture.cc:38
Dart_Handle AsImage() const
Definition texture.cc:153
void SetCoordinateSystem(impeller::TextureCoordinateSystem coordinate_system)
Definition texture.cc:42
To do anything rendering related with Impeller, you need a context.
Definition context.h:69
virtual std::shared_ptr< CommandQueue > GetCommandQueue() const =0
Return the graphics queue for submitting command buffers.
virtual std::shared_ptr< CommandBuffer > CreateCommandBuffer() const =0
Create a new command buffer. Command buffers can be used to encode graphics, blit,...
virtual std::shared_ptr< Allocator > GetResourceAllocator() const =0
Returns the allocator used to create textures and buffers on the device.
static sk_sp< DlImageImpeller > Make(std::shared_ptr< Texture > texture, OwningContext owning_context=OwningContext::kIO)
const void * data() const
size_t length_in_bytes() const
#define IMPLEMENT_WRAPPERTYPEINFO(LibraryName, ClassName)
FlutterVulkanImage * image
uint32_t uint32_t * format
#define FML_LOG(severity)
Definition logging.h:101
size_t length
bool InternalFlutterGpu_Texture_Overwrite(flutter::gpu::Texture *texture, flutter::gpu::Context *gpu_context, Dart_Handle source_byte_data, int mip_level, int slice)
Definition texture.cc:246
void InternalFlutterGpu_Texture_SetCoordinateSystem(flutter::gpu::Texture *wrapper, int coordinate_system)
Definition texture.cc:239
Dart_Handle InternalFlutterGpu_Texture_AsImage(flutter::gpu::Texture *wrapper)
Definition texture.cc:264
bool InternalFlutterGpu_Texture_Initialize(Dart_Handle wrapper, flutter::gpu::Context *gpu_context, int storage_mode, int format, int width, int height, int sample_count, int coordinate_system, int texture_type, bool enable_render_target_usage, bool enable_shader_read_usage, bool enable_shader_write_usage, int mip_level_count)
Definition texture.cc:175
int InternalFlutterGpu_Texture_BytesPerTexel(flutter::gpu::Texture *wrapper)
Definition texture.cc:259
FlTexture * texture
constexpr impeller::PixelFormat ToImpellerPixelFormat(FlutterGPUPixelFormat value)
Definition formats.h:60
constexpr impeller::TextureCoordinateSystem ToImpellerTextureCoordinateSystem(FlutterGPUTextureCoordinateSystem value)
Definition formats.h:148
static int32_t MipDimensionAtLevel(int32_t base_dimension, uint32_t mip_level)
Definition texture.cc:52
static bool EncodeAndSubmitOverwrite(impeller::Context &context, const std::shared_ptr< impeller::Texture > &texture, const std::shared_ptr< impeller::DeviceBuffer > &staging_buffer, size_t source_length, impeller::IRect destination_region, uint32_t mip_level, uint32_t slice)
Definition texture.cc:61
constexpr impeller::StorageMode ToImpellerStorageMode(FlutterGPUStorageMode value)
Definition formats.h:25
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot data
Definition switch_defs.h:36
internal::CopyableLambda< T > MakeCopyable(T lambda)
constexpr size_t BytesPerPixelForPixelFormat(PixelFormat format)
Definition formats.h:469
TextureCoordinateSystem
Definition formats.h:330
constexpr bool IsMultisampleCapable(TextureType type)
Definition formats.h:286
Definition ref_ptr.h:261
int32_t height
int32_t width
static constexpr TRect MakeXYWH(Type x, Type y, Type width, Type height)
Definition rect.h:136
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...