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
42// Returns the size in pixels of the given dimension at `mip_level`, clamped
43// at 1, matching standard mip-chain semantics. The Dart-side helper
44// `Texture.getMipLevelSizeInBytes` uses the same `max(1, dim >> level)`
45// formula in pixel-count form; if either is updated, both must be kept in
46// sync.
47static int32_t MipDimensionAtLevel(int32_t base_dimension, uint32_t mip_level) {
48 const int32_t shifted = base_dimension >> mip_level;
49 return shifted > 0 ? shifted : 1;
50}
51
52// Records a blit-pass that copies `source_bytes` into the given mip level and
53// slice of `texture` on `context`, then submits the command buffer. Returns
54// true if the encode and submit both succeed. The actual GPU upload may
55// complete asynchronously after this call returns.
58 const std::shared_ptr<impeller::Texture>& texture,
59 const std::shared_ptr<impeller::DeviceBuffer>& staging_buffer,
60 size_t source_length,
61 impeller::IRect destination_region,
62 uint32_t mip_level,
63 uint32_t slice) {
64 auto command_buffer = context.CreateCommandBuffer();
65 if (!command_buffer) {
66 FML_LOG(ERROR) << "Failed to create command buffer for texture overwrite.";
67 return false;
68 }
69 auto blit_pass = command_buffer->CreateBlitPass();
70 if (!blit_pass) {
71 FML_LOG(ERROR) << "Failed to create blit pass for texture overwrite.";
72 return false;
73 }
74 impeller::BufferView buffer_view(staging_buffer,
75 impeller::Range(0, source_length));
76 if (!blit_pass->AddCopy(std::move(buffer_view), texture, destination_region,
77 /*label=*/"Texture.overwrite", mip_level, slice)) {
78 return false;
79 }
80 if (!blit_pass->EncodeCommands()) {
81 return false;
82 }
83 return context.GetCommandQueue()->Submit({std::move(command_buffer)}).ok();
84}
85
86bool Texture::Overwrite(Context& gpu_context,
87 const tonic::DartByteData& source_bytes,
88 uint32_t mip_level,
89 uint32_t slice) {
90 const uint8_t* data = static_cast<const uint8_t*>(source_bytes.data());
91 const size_t length = source_bytes.length_in_bytes();
92
93 auto& impeller_context = gpu_context.GetContext();
94 auto staging_buffer =
95 impeller_context.GetResourceAllocator()->CreateBufferWithCopy(data,
96 length);
97 if (!staging_buffer) {
98 FML_LOG(ERROR) << "Failed to allocate staging buffer for texture "
99 "overwrite.";
100 return false;
101 }
102
103 // Compute the destination region for the requested mip level. The
104 // BlitPass::AddCopy validation requires the region to fit within the base
105 // texture size, and the actual GPU copy uses this rectangle as the
106 // destination on the chosen mip level. The same `max(1, dim >> level)`
107 // formula is used by `Texture.getMipLevelSizeInBytes` on the Dart side; if
108 // either is updated, both must be kept in sync.
109 const impeller::ISize base_size = texture_->GetSize();
110 const impeller::IRect destination_region = impeller::IRect::MakeXYWH(
111 0, 0, MipDimensionAtLevel(base_size.width, mip_level),
112 MipDimensionAtLevel(base_size.height, mip_level));
113
114 // For the GLES backend, command queue submission just flushes the reactor,
115 // which needs to happen on the raster thread.
116 if (impeller_context.GetBackendType() ==
118 auto dart_state = flutter::UIDartState::Current();
119 auto& task_runners = dart_state->GetTaskRunners();
120 auto context_shared = gpu_context.GetContextShared();
121 task_runners.GetRasterTaskRunner()->PostTask(fml::MakeCopyable(
122 [context_shared, texture = texture_, staging_buffer, length,
123 destination_region, mip_level, slice]() mutable {
124 if (!EncodeAndSubmitOverwrite(*context_shared, texture,
125 staging_buffer, length,
126 destination_region, mip_level, slice)) {
127 FML_LOG(ERROR) << "Failed to encode texture overwrite blit on the "
128 "raster thread.";
129 }
130 context_shared->DisposeThreadLocalCachedResources();
131 }));
132 return true;
133 }
134
135 if (!EncodeAndSubmitOverwrite(impeller_context, texture_, staging_buffer,
136 length, destination_region, mip_level, slice)) {
137 return false;
138 }
139 impeller_context.DisposeThreadLocalCachedResources();
140 return true;
141}
142
143Dart_Handle Texture::AsImage() const {
144 // DlImageImpeller isn't compiled in builds with Impeller disabled. If
145 // Impeller is disabled, it's impossible to get here anyhow, so just ifdef it
146 // out.
147#if IMPELLER_SUPPORTS_RENDERING
149 auto dl_image = impeller::DlImageImpeller::Make(texture_);
150 image->set_image(dl_image);
151 auto wrapped = image->CreateOuterWrapping();
152 return wrapped;
153#else
154 return Dart_Null();
155#endif
156}
157
158} // namespace gpu
159} // namespace flutter
160
161//----------------------------------------------------------------------------
162/// Exports
163///
164
166 flutter::gpu::Context* gpu_context,
167 int storage_mode,
168 int format,
169 int width,
170 int height,
171 int sample_count,
172 int texture_type,
173 bool enable_render_target_usage,
174 bool enable_shader_read_usage,
175 bool enable_shader_write_usage,
176 int mip_level_count) {
177 if (mip_level_count < 1) {
178 return false;
179 }
182 desc.size = {width, height};
184 desc.mip_count = static_cast<size_t>(mip_level_count);
185 desc.usage = {};
186 if (enable_render_target_usage) {
188 }
189 if (enable_shader_read_usage) {
191 }
192 if (enable_shader_write_usage) {
194 }
195 switch (sample_count) {
196 case 1:
198 break;
199 case 4:
201 break;
202 default:
203 return false;
204 }
205 desc.type = static_cast<impeller::TextureType>(texture_type);
208 return false;
209 }
210
211 auto texture =
212 gpu_context->GetContext().GetResourceAllocator()->CreateTexture(desc,
213 true);
214 if (!texture) {
215 FML_LOG(ERROR) << "Failed to create texture.";
216 return false;
217 }
218
219 auto res = fml::MakeRefCounted<flutter::gpu::Texture>(std::move(texture));
220 res->AssociateWithDartWrapper(wrapper);
221
222 return true;
223}
224
226 flutter::gpu::Context* gpu_context,
227 Dart_Handle source_byte_data,
228 int mip_level,
229 int slice) {
230 if (mip_level < 0 || slice < 0) {
231 return false;
232 }
233 return texture->Overwrite(*gpu_context, tonic::DartByteData(source_byte_data),
234 static_cast<uint32_t>(mip_level),
235 static_cast<uint32_t>(slice));
236}
237
239 return wrapper->AsImage();
240}
static fml::RefPtr< CanvasImage > Create()
Definition image.h:36
static UIDartState * Current()
std::shared_ptr< impeller::Context > & GetContextShared()
Definition context.cc:91
impeller::Context & GetContext()
Definition context.cc:87
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:86
std::shared_ptr< impeller::Texture > GetTexture()
Definition texture.cc:38
Dart_Handle AsImage() const
Definition texture.cc:143
To do anything rendering related with Impeller, you need a context.
Definition context.h:69
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:225
Dart_Handle InternalFlutterGpu_Texture_AsImage(flutter::gpu::Texture *wrapper)
Definition texture.cc:238
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 texture_type, bool enable_render_target_usage, bool enable_shader_read_usage, bool enable_shader_write_usage, int mip_level_count)
Definition texture.cc:165
FlTexture * texture
constexpr impeller::PixelFormat ToImpellerPixelFormat(FlutterGPUPixelFormat value)
Definition formats.h:104
static int32_t MipDimensionAtLevel(int32_t base_dimension, uint32_t mip_level)
Definition texture.cc:47
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:56
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 bool IsMultisampleCapable(TextureType type)
Definition formats.h:471
Definition ref_ptr.h:261
std::shared_ptr< ContextGLES > context
std::shared_ptr< CommandBuffer > command_buffer
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...