Flutter Engine
The Flutter Engine
content_context.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 <memory>
8#include <utility>
9
10#include "fml/trace_event.h"
25
26namespace impeller {
27
29 PipelineDescriptor& desc) const {
30 auto pipeline_blend = blend_mode;
32 VALIDATION_LOG << "Cannot use blend mode " << static_cast<int>(blend_mode)
33 << " as a pipeline blend.";
34 pipeline_blend = BlendMode::kSourceOver;
35 }
36
37 desc.SetSampleCount(sample_count);
38
39 ColorAttachmentDescriptor color0 = *desc.GetColorAttachmentDescriptor(0u);
44
45 switch (pipeline_blend) {
54 } else {
59 }
60 break;
62 color0.blending_enabled = false;
67 break;
74 break;
80 break;
86 break;
92 break;
98 break;
104 break;
110 break;
116 break;
122 break;
123 case BlendMode::kXor:
128 break;
129 case BlendMode::kPlus:
134 break;
140 break;
141 default:
143 }
144 desc.SetColorAttachmentDescriptor(0u, color0);
145
147 desc.ClearDepthAttachment();
148 desc.ClearStencilAttachments();
149 }
150
151 auto maybe_stencil = desc.GetFrontStencilAttachmentDescriptor();
152 auto maybe_depth = desc.GetDepthStencilAttachmentDescriptor();
153 FML_DCHECK(has_depth_stencil_attachments == maybe_depth.has_value())
154 << "Depth attachment doesn't match expected pipeline state. "
155 "has_depth_stencil_attachments="
157 FML_DCHECK(has_depth_stencil_attachments == maybe_stencil.has_value())
158 << "Stencil attachment doesn't match expected pipeline state. "
159 "has_depth_stencil_attachments="
161 if (maybe_stencil.has_value()) {
162 StencilAttachmentDescriptor front_stencil = maybe_stencil.value();
163 StencilAttachmentDescriptor back_stencil = front_stencil;
164
165 switch (stencil_mode) {
169 desc.SetStencilAttachmentDescriptors(front_stencil);
170 break;
172 // The stencil ref should be 0 on commands that use this mode.
177 desc.SetStencilAttachmentDescriptors(front_stencil, back_stencil);
178 break;
180 // The stencil ref should be 0 on commands that use this mode.
184 desc.SetStencilAttachmentDescriptors(front_stencil);
185 break;
187 // The stencil ref should be 0 on commands that use this mode.
189 front_stencil.depth_stencil_pass =
191 desc.SetStencilAttachmentDescriptors(front_stencil);
192 break;
194 // The stencil ref should be 0 on commands that use this mode.
197 desc.SetStencilAttachmentDescriptors(front_stencil);
198 break;
202 desc.SetStencilAttachmentDescriptors(front_stencil);
203 break;
206 front_stencil.depth_stencil_pass =
208 desc.SetStencilAttachmentDescriptors(front_stencil);
209 break;
210 }
211 }
212 if (maybe_depth.has_value()) {
213 DepthAttachmentDescriptor depth = maybe_depth.value();
216 desc.SetDepthStencilAttachmentDescriptor(depth);
217 }
218
219 desc.SetPrimitiveType(primitive_type);
220
222}
223
224template <typename PipelineT>
225static std::unique_ptr<PipelineT> CreateDefaultPipeline(
226 const Context& context) {
227 auto desc = PipelineT::Builder::MakeDefaultPipelineDescriptor(context);
228 if (!desc.has_value()) {
229 return nullptr;
230 }
231 // Apply default ContentContextOptions to the descriptor.
232 const auto default_color_format =
233 context.GetCapabilities()->GetDefaultColorFormat();
235 .primitive_type = PrimitiveType::kTriangleStrip,
236 .color_attachment_pixel_format = default_color_format}
237 .ApplyToPipelineDescriptor(*desc);
238 return std::make_unique<PipelineT>(context, desc);
239}
240
242 std::shared_ptr<Context> context,
243 std::shared_ptr<TypographerContext> typographer_context,
244 std::shared_ptr<RenderTargetAllocator> render_target_allocator)
245 : context_(std::move(context)),
246 lazy_glyph_atlas_(
247 std::make_shared<LazyGlyphAtlas>(std::move(typographer_context))),
248 tessellator_(std::make_shared<Tessellator>()),
249#if IMPELLER_ENABLE_3D
250 scene_context_(std::make_shared<scene::SceneContext>(context_)),
251#endif // IMPELLER_ENABLE_3D
252 render_target_cache_(render_target_allocator == nullptr
253 ? std::make_shared<RenderTargetCache>(
254 context_->GetResourceAllocator())
255 : std::move(render_target_allocator)),
256 host_buffer_(HostBuffer::Create(context_->GetResourceAllocator())) {
257 if (!context_ || !context_->IsValid()) {
258 return;
259 }
260
261 {
263 desc.storage_mode = StorageMode::kHostVisible;
265 desc.size = ISize{1, 1};
266 empty_texture_ = GetContext()->GetResourceAllocator()->CreateTexture(desc);
268 auto cmd_buffer = GetContext()->CreateCommandBuffer();
269 auto blit_pass = cmd_buffer->CreateBlitPass();
270 auto& host_buffer = GetTransientsBuffer();
271 auto buffer_view = host_buffer.Emplace(data);
272 blit_pass->AddCopy(buffer_view, empty_texture_);
273
274 if (!blit_pass->EncodeCommands(GetContext()->GetResourceAllocator()) ||
275 !GetContext()
276 ->GetCommandQueue()
277 ->Submit({std::move(cmd_buffer)})
278 .ok()) {
279 VALIDATION_LOG << "Failed to create empty texture.";
280 }
281 }
282
285 .color_attachment_pixel_format =
286 context_->GetCapabilities()->GetDefaultColorFormat()};
287 auto options_trianglestrip = ContentContextOptions{
289 .primitive_type = PrimitiveType::kTriangleStrip,
290 .color_attachment_pixel_format =
291 context_->GetCapabilities()->GetDefaultColorFormat()};
292 const auto supports_decal = static_cast<Scalar>(
293 context_->GetCapabilities()->SupportsDecalSamplerAddressMode());
294
295 {
296 solid_fill_pipelines_.CreateDefault(*context_, options);
297 texture_pipelines_.CreateDefault(*context_, options);
298 fast_gradient_pipelines_.CreateDefault(*context_, options);
299
300 if (context_->GetCapabilities()->SupportsSSBO()) {
301 linear_gradient_ssbo_fill_pipelines_.CreateDefault(*context_, options);
302 radial_gradient_ssbo_fill_pipelines_.CreateDefault(*context_, options);
303 conical_gradient_ssbo_fill_pipelines_.CreateDefault(*context_, options);
304 sweep_gradient_ssbo_fill_pipelines_.CreateDefault(*context_, options);
305 } else {
306 linear_gradient_fill_pipelines_.CreateDefault(*context_, options);
307 radial_gradient_fill_pipelines_.CreateDefault(*context_, options);
308 conical_gradient_fill_pipelines_.CreateDefault(*context_, options);
309 sweep_gradient_fill_pipelines_.CreateDefault(*context_, options);
310 }
311
312 /// Setup default clip pipeline.
313
314 auto clip_pipeline_descriptor =
316 if (!clip_pipeline_descriptor.has_value()) {
317 return;
318 }
321 .color_attachment_pixel_format =
322 context_->GetCapabilities()->GetDefaultColorFormat()}
323 .ApplyToPipelineDescriptor(*clip_pipeline_descriptor);
324 // Disable write to all color attachments.
325 auto clip_color_attachments =
326 clip_pipeline_descriptor->GetColorAttachmentDescriptors();
327 for (auto& color_attachment : clip_color_attachments) {
328 color_attachment.second.write_mask = ColorWriteMaskBits::kNone;
329 }
330 clip_pipeline_descriptor->SetColorAttachmentDescriptors(
331 std::move(clip_color_attachments));
332 clip_pipelines_.SetDefault(
333 options,
334 std::make_unique<ClipPipeline>(*context_, clip_pipeline_descriptor));
335 }
336
337 if (context_->GetCapabilities()->SupportsFramebufferFetch()) {
338 framebuffer_blend_color_pipelines_.CreateDefault(
339 *context_, options_trianglestrip,
340 {static_cast<Scalar>(BlendSelectValues::kColor), supports_decal});
341 framebuffer_blend_colorburn_pipelines_.CreateDefault(
342 *context_, options_trianglestrip,
343 {static_cast<Scalar>(BlendSelectValues::kColorBurn), supports_decal});
344 framebuffer_blend_colordodge_pipelines_.CreateDefault(
345 *context_, options_trianglestrip,
346 {static_cast<Scalar>(BlendSelectValues::kColorDodge), supports_decal});
347 framebuffer_blend_darken_pipelines_.CreateDefault(
348 *context_, options_trianglestrip,
349 {static_cast<Scalar>(BlendSelectValues::kDarken), supports_decal});
350 framebuffer_blend_difference_pipelines_.CreateDefault(
351 *context_, options_trianglestrip,
352 {static_cast<Scalar>(BlendSelectValues::kDifference), supports_decal});
353 framebuffer_blend_exclusion_pipelines_.CreateDefault(
354 *context_, options_trianglestrip,
355 {static_cast<Scalar>(BlendSelectValues::kExclusion), supports_decal});
356 framebuffer_blend_hardlight_pipelines_.CreateDefault(
357 *context_, options_trianglestrip,
358 {static_cast<Scalar>(BlendSelectValues::kHardLight), supports_decal});
359 framebuffer_blend_hue_pipelines_.CreateDefault(
360 *context_, options_trianglestrip,
361 {static_cast<Scalar>(BlendSelectValues::kHue), supports_decal});
362 framebuffer_blend_lighten_pipelines_.CreateDefault(
363 *context_, options_trianglestrip,
364 {static_cast<Scalar>(BlendSelectValues::kLighten), supports_decal});
365 framebuffer_blend_luminosity_pipelines_.CreateDefault(
366 *context_, options_trianglestrip,
367 {static_cast<Scalar>(BlendSelectValues::kLuminosity), supports_decal});
368 framebuffer_blend_multiply_pipelines_.CreateDefault(
369 *context_, options_trianglestrip,
370 {static_cast<Scalar>(BlendSelectValues::kMultiply), supports_decal});
371 framebuffer_blend_overlay_pipelines_.CreateDefault(
372 *context_, options_trianglestrip,
373 {static_cast<Scalar>(BlendSelectValues::kOverlay), supports_decal});
374 framebuffer_blend_saturation_pipelines_.CreateDefault(
375 *context_, options_trianglestrip,
376 {static_cast<Scalar>(BlendSelectValues::kSaturation), supports_decal});
377 framebuffer_blend_screen_pipelines_.CreateDefault(
378 *context_, options_trianglestrip,
379 {static_cast<Scalar>(BlendSelectValues::kScreen), supports_decal});
380 framebuffer_blend_softlight_pipelines_.CreateDefault(
381 *context_, options_trianglestrip,
382 {static_cast<Scalar>(BlendSelectValues::kSoftLight), supports_decal});
383 } else {
384 blend_color_pipelines_.CreateDefault(
385 *context_, options_trianglestrip,
386 {static_cast<Scalar>(BlendSelectValues::kColor), supports_decal});
387 blend_colorburn_pipelines_.CreateDefault(
388 *context_, options_trianglestrip,
389 {static_cast<Scalar>(BlendSelectValues::kColorBurn), supports_decal});
390 blend_colordodge_pipelines_.CreateDefault(
391 *context_, options_trianglestrip,
392 {static_cast<Scalar>(BlendSelectValues::kColorDodge), supports_decal});
393 blend_darken_pipelines_.CreateDefault(
394 *context_, options_trianglestrip,
395 {static_cast<Scalar>(BlendSelectValues::kDarken), supports_decal});
396 blend_difference_pipelines_.CreateDefault(
397 *context_, options_trianglestrip,
398 {static_cast<Scalar>(BlendSelectValues::kDifference), supports_decal});
399 blend_exclusion_pipelines_.CreateDefault(
400 *context_, options_trianglestrip,
401 {static_cast<Scalar>(BlendSelectValues::kExclusion), supports_decal});
402 blend_hardlight_pipelines_.CreateDefault(
403 *context_, options_trianglestrip,
404 {static_cast<Scalar>(BlendSelectValues::kHardLight), supports_decal});
405 blend_hue_pipelines_.CreateDefault(
406 *context_, options_trianglestrip,
407 {static_cast<Scalar>(BlendSelectValues::kHue), supports_decal});
408 blend_lighten_pipelines_.CreateDefault(
409 *context_, options_trianglestrip,
410 {static_cast<Scalar>(BlendSelectValues::kLighten), supports_decal});
411 blend_luminosity_pipelines_.CreateDefault(
412 *context_, options_trianglestrip,
413 {static_cast<Scalar>(BlendSelectValues::kLuminosity), supports_decal});
414 blend_multiply_pipelines_.CreateDefault(
415 *context_, options_trianglestrip,
416 {static_cast<Scalar>(BlendSelectValues::kMultiply), supports_decal});
417 blend_overlay_pipelines_.CreateDefault(
418 *context_, options_trianglestrip,
419 {static_cast<Scalar>(BlendSelectValues::kOverlay), supports_decal});
420 blend_saturation_pipelines_.CreateDefault(
421 *context_, options_trianglestrip,
422 {static_cast<Scalar>(BlendSelectValues::kSaturation), supports_decal});
423 blend_screen_pipelines_.CreateDefault(
424 *context_, options_trianglestrip,
425 {static_cast<Scalar>(BlendSelectValues::kScreen), supports_decal});
426 blend_softlight_pipelines_.CreateDefault(
427 *context_, options_trianglestrip,
428 {static_cast<Scalar>(BlendSelectValues::kSoftLight), supports_decal});
429 }
430
431 rrect_blur_pipelines_.CreateDefault(*context_, options_trianglestrip);
432 texture_strict_src_pipelines_.CreateDefault(*context_, options);
433 tiled_texture_pipelines_.CreateDefault(*context_, options, {supports_decal});
434 gaussian_blur_pipelines_.CreateDefault(*context_, options_trianglestrip,
435 {supports_decal});
436 border_mask_blur_pipelines_.CreateDefault(*context_, options_trianglestrip);
437 morphology_filter_pipelines_.CreateDefault(*context_, options_trianglestrip,
438 {supports_decal});
439 color_matrix_color_filter_pipelines_.CreateDefault(*context_,
440 options_trianglestrip);
441 linear_to_srgb_filter_pipelines_.CreateDefault(*context_,
442 options_trianglestrip);
443 srgb_to_linear_filter_pipelines_.CreateDefault(*context_,
444 options_trianglestrip);
445 glyph_atlas_pipelines_.CreateDefault(
446 *context_, options,
447 {static_cast<Scalar>(
448 GetContext()->GetCapabilities()->GetDefaultGlyphAtlasFormat() ==
450 yuv_to_rgb_filter_pipelines_.CreateDefault(*context_, options_trianglestrip);
451 porter_duff_blend_pipelines_.CreateDefault(*context_, options_trianglestrip,
452 {supports_decal});
453 vertices_uber_shader_.CreateDefault(*context_, options, {supports_decal});
454 // GLES only shader that is unsupported on macOS.
455#if defined(IMPELLER_ENABLE_OPENGLES) && !defined(FML_OS_MACOSX)
456 if (GetContext()->GetBackendType() == Context::BackendType::kOpenGLES) {
457 tiled_texture_external_pipelines_.CreateDefault(*context_, options);
458 }
459#endif // IMPELLER_ENABLE_OPENGLES
460
461 is_valid_ = true;
462 InitializeCommonlyUsedShadersIfNeeded();
463}
464
466
468 return is_valid_;
469}
470
471std::shared_ptr<Texture> ContentContext::GetEmptyTexture() const {
472 return empty_texture_;
473}
474
476 std::string_view label,
477 ISize texture_size,
478 const std::shared_ptr<CommandBuffer>& command_buffer,
479 const SubpassCallback& subpass_callback,
480 bool msaa_enabled,
481 bool depth_stencil_enabled,
482 int32_t mip_count) const {
483 const std::shared_ptr<Context>& context = GetContext();
484 RenderTarget subpass_target;
485
486 std::optional<RenderTarget::AttachmentConfig> depth_stencil_config =
488 : std::optional<RenderTarget::AttachmentConfig>();
489
490 if (context->GetCapabilities()->SupportsOffscreenMSAA() && msaa_enabled) {
491 subpass_target = GetRenderTargetCache()->CreateOffscreenMSAA(
492 *context, texture_size,
493 /*mip_count=*/mip_count, SPrintF("%s Offscreen", label.data()),
495 } else {
496 subpass_target = GetRenderTargetCache()->CreateOffscreen(
497 *context, texture_size,
498 /*mip_count=*/mip_count, SPrintF("%s Offscreen", label.data()),
499 RenderTarget::kDefaultColorAttachmentConfig, depth_stencil_config);
500 }
501 return MakeSubpass(label, subpass_target, command_buffer, subpass_callback);
502}
503
505 std::string_view label,
506 const RenderTarget& subpass_target,
507 const std::shared_ptr<CommandBuffer>& command_buffer,
508 const SubpassCallback& subpass_callback) const {
509 const std::shared_ptr<Context>& context = GetContext();
510
511 auto subpass_texture = subpass_target.GetRenderTargetTexture();
512 if (!subpass_texture) {
514 }
515
516 auto sub_renderpass = command_buffer->CreateRenderPass(subpass_target);
517 if (!sub_renderpass) {
519 }
520 sub_renderpass->SetLabel(SPrintF("%s RenderPass", label.data()));
521
522 if (!subpass_callback(*this, *sub_renderpass)) {
524 }
525
526 if (!sub_renderpass->EncodeCommands()) {
528 }
529
530 const std::shared_ptr<Texture>& target_texture =
531 subpass_target.GetRenderTargetTexture();
532 if (target_texture->GetMipCount() > 1) {
533 fml::Status mipmap_status =
534 AddMipmapGeneration(command_buffer, context, target_texture);
535 if (!mipmap_status.ok()) {
536 return mipmap_status;
537 }
538 }
539
540 return subpass_target;
541}
542
543#if IMPELLER_ENABLE_3D
544std::shared_ptr<scene::SceneContext> ContentContext::GetSceneContext() const {
545 return scene_context_;
546}
547#endif // IMPELLER_ENABLE_3D
548
549std::shared_ptr<Tessellator> ContentContext::GetTessellator() const {
550 return tessellator_;
551}
552
553std::shared_ptr<Context> ContentContext::GetContext() const {
554 return context_;
555}
556
558 return *context_->GetCapabilities();
559}
560
561void ContentContext::SetWireframe(bool wireframe) {
562 wireframe_ = wireframe;
563}
564
565std::shared_ptr<Pipeline<PipelineDescriptor>>
567 const std::string& unique_entrypoint_name,
569 const std::function<std::shared_ptr<Pipeline<PipelineDescriptor>>()>&
570 create_callback) const {
571 RuntimeEffectPipelineKey key{unique_entrypoint_name, options};
572 auto it = runtime_effect_pipelines_.find(key);
573 if (it == runtime_effect_pipelines_.end()) {
574 it = runtime_effect_pipelines_.insert(it, {key, create_callback()});
575 }
576 return it->second;
577}
578
580 const std::string& unique_entrypoint_name) const {
581 for (auto it = runtime_effect_pipelines_.begin();
582 it != runtime_effect_pipelines_.end();) {
583 if (it->first.unique_entrypoint_name == unique_entrypoint_name) {
584 it = runtime_effect_pipelines_.erase(it);
585 } else {
586 it++;
587 }
588 }
589}
590
591void ContentContext::InitializeCommonlyUsedShadersIfNeeded() const {
592 TRACE_EVENT0("flutter", "InitializeCommonlyUsedShadersIfNeeded");
593 GetContext()->InitializeCommonlyUsedShadersIfNeeded();
594}
595
596} // namespace impeller
const char * options
static sk_sp< Effect > Create()
Definition: RefCntTest.cpp:117
static bool ok(int result)
BufferView buffer_view
bool ok() const
Definition: status.h:71
void ClearCachedRuntimeEffectPipeline(const std::string &unique_entrypoint_name) const
std::shared_ptr< Tessellator > GetTessellator() const
std::shared_ptr< Texture > GetEmptyTexture() const
const std::shared_ptr< RenderTargetAllocator > & GetRenderTargetCache() const
ContentContext(std::shared_ptr< Context > context, std::shared_ptr< TypographerContext > typographer_context, std::shared_ptr< RenderTargetAllocator > render_target_allocator=nullptr)
fml::StatusOr< RenderTarget > MakeSubpass(std::string_view label, ISize texture_size, const std::shared_ptr< CommandBuffer > &command_buffer, const SubpassCallback &subpass_callback, bool msaa_enabled=true, bool depth_stencil_enabled=false, int32_t mip_count=1) const
Creates a new texture of size texture_size and calls subpass_callback with a RenderPass for drawing t...
const Capabilities & GetDeviceCapabilities() const
HostBuffer & GetTransientsBuffer() const
Retrieve the currnent host buffer for transient storage.
void SetWireframe(bool wireframe)
std::shared_ptr< Pipeline< PipelineDescriptor > > GetCachedRuntimeEffectPipeline(const std::string &unique_entrypoint_name, const ContentContextOptions &options, const std::function< std::shared_ptr< Pipeline< PipelineDescriptor > >()> &create_callback) const
std::function< bool(const ContentContext &, RenderPass &)> SubpassCallback
std::shared_ptr< Context > GetContext() const
To do anything rendering related with Impeller, you need a context.
Definition: context.h:45
virtual const std::shared_ptr< const Capabilities > & GetCapabilities() const =0
Get the capabilities of Impeller context. All optionally supported feature of the platform,...
static constexpr BlendMode kLastPipelineBlendMode
Definition: entity.h:22
An implementation of the [RenderTargetAllocator] that caches all allocated texture data for one frame...
std::shared_ptr< Texture > GetRenderTargetTexture() const
static constexpr AttachmentConfig kDefaultColorAttachmentConfig
Definition: render_target.h:55
static constexpr AttachmentConfigMSAA kDefaultColorAttachmentConfigMSAA
Definition: render_target.h:61
static constexpr AttachmentConfig kDefaultStencilAttachmentConfig
Definition: render_target.h:68
A utility that generates triangles of the specified fill type given a polyline. This happens on the C...
Definition: tessellator.h:31
if(end==-1)
#define FML_UNREACHABLE()
Definition: logging.h:109
#define FML_DCHECK(condition)
Definition: logging.h:103
Dart_NativeFunction function
Definition: fuchsia.cc:51
float Scalar
Definition: scalar.h:18
std::string SPrintF(const char *format,...)
Definition: strings.cc:12
@ kEqual
Comparison test passes if new_value == current_value.
@ kAlways
Comparison test passes always passes.
@ kLess
Comparison test passes if new_value < current_value.
@ kNotEqual
Comparison test passes if new_value != current_value.
fml::Status AddMipmapGeneration(const std::shared_ptr< CommandBuffer > &command_buffer, const std::shared_ptr< Context > &context, const std::shared_ptr< Texture > &texture)
Adds a blit command to the render pass.
@ kDecrementWrap
Decrement the current stencil value by 1. If at zero, set to maximum.
@ kSetToReferenceValue
Reset the stencil value to the reference value.
@ kIncrementClamp
Increment the current stencil value by 1. Clamp it to the maximum.
@ kIncrementWrap
Increment the current stencil value by 1. If at maximum, set to zero.
@ kKeep
Don't modify the current stencil value.
static std::unique_ptr< PipelineT > CreateDefaultPipeline(const Context &context)
Task::Status Status
Definition: TaskList.cpp:15
Definition: ref_ptr.h:256
Describe the color attachment that will be used with this pipeline.
Definition: formats.h:512
constexpr std::array< uint8_t, 4 > ToR8G8B8A8() const
Convert to R8G8B8A8 representation.
Definition: color.h:248
static constexpr Color BlackTransparent()
Definition: color.h:272
void ApplyToPipelineDescriptor(PipelineDescriptor &desc) const
static std::optional< PipelineDescriptor > MakeDefaultPipelineDescriptor(const Context &context, const std::vector< Scalar > &constants={})
Create a default pipeline descriptor using the combination reflected shader information....
StencilOperation depth_stencil_pass
Definition: formats.h:623
A lightweight object that describes the attributes of a texture that can then used an allocator to cr...
std::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:63
#define TRACE_EVENT0(category_group, name)
Definition: trace_event.h:131
#define VALIDATION_LOG
Definition: validation.h:73