Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
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);
43
44 switch (pipeline_blend) {
53 } else {
58 }
59 break;
61 color0.blending_enabled = false;
66 break;
72 break;
78 break;
84 break;
90 break;
96 break;
102 break;
108 break;
114 break;
120 break;
121 case BlendMode::kXor:
126 break;
127 case BlendMode::kPlus:
132 break;
138 break;
139 default:
141 }
142 desc.SetColorAttachmentDescriptor(0u, color0);
143
145 desc.ClearDepthAttachment();
146 desc.ClearStencilAttachments();
147 }
148
149 auto maybe_stencil = desc.GetFrontStencilAttachmentDescriptor();
150 auto maybe_depth = desc.GetDepthStencilAttachmentDescriptor();
151 FML_DCHECK(has_depth_stencil_attachments == maybe_depth.has_value())
152 << "Depth attachment doesn't match expected pipeline state. "
153 "has_depth_stencil_attachments="
155 FML_DCHECK(has_depth_stencil_attachments == maybe_stencil.has_value())
156 << "Stencil attachment doesn't match expected pipeline state. "
157 "has_depth_stencil_attachments="
159 if (maybe_stencil.has_value()) {
160 StencilAttachmentDescriptor front_stencil = maybe_stencil.value();
161 StencilAttachmentDescriptor back_stencil = front_stencil;
162
163 switch (stencil_mode) {
167 desc.SetStencilAttachmentDescriptors(front_stencil);
168 break;
170 // The stencil ref should be 0 on commands that use this mode.
175 desc.SetStencilAttachmentDescriptors(front_stencil, back_stencil);
176 break;
178 // The stencil ref should be 0 on commands that use this mode.
182 desc.SetStencilAttachmentDescriptors(front_stencil);
183 break;
185 // The stencil ref should be 0 on commands that use this mode.
187 front_stencil.depth_stencil_pass =
189 desc.SetStencilAttachmentDescriptors(front_stencil);
190 break;
192 // The stencil ref should be 0 on commands that use this mode.
195 desc.SetStencilAttachmentDescriptors(front_stencil);
196 break;
200 desc.SetStencilAttachmentDescriptors(front_stencil);
201 break;
204 front_stencil.depth_stencil_pass =
206 desc.SetStencilAttachmentDescriptors(front_stencil);
207 break;
208 }
209 }
210 if (maybe_depth.has_value()) {
211 DepthAttachmentDescriptor depth = maybe_depth.value();
214 desc.SetDepthStencilAttachmentDescriptor(depth);
215 }
216
217 desc.SetPrimitiveType(primitive_type);
218
219 desc.SetPolygonMode(wireframe ? PolygonMode::kLine : PolygonMode::kFill);
220}
221
222template <typename PipelineT>
223static std::unique_ptr<PipelineT> CreateDefaultPipeline(
224 const Context& context) {
225 auto desc = PipelineT::Builder::MakeDefaultPipelineDescriptor(context);
226 if (!desc.has_value()) {
227 return nullptr;
228 }
229 // Apply default ContentContextOptions to the descriptor.
230 const auto default_color_format =
231 context.GetCapabilities()->GetDefaultColorFormat();
233 .primitive_type = PrimitiveType::kTriangleStrip,
234 .color_attachment_pixel_format = default_color_format}
235 .ApplyToPipelineDescriptor(*desc);
236 return std::make_unique<PipelineT>(context, desc);
237}
238
240 std::shared_ptr<Context> context,
241 std::shared_ptr<TypographerContext> typographer_context,
242 std::shared_ptr<RenderTargetAllocator> render_target_allocator)
243 : context_(std::move(context)),
244 lazy_glyph_atlas_(
245 std::make_shared<LazyGlyphAtlas>(std::move(typographer_context))),
246 tessellator_(std::make_shared<Tessellator>()),
247#if IMPELLER_ENABLE_3D
248 scene_context_(std::make_shared<scene::SceneContext>(context_)),
249#endif // IMPELLER_ENABLE_3D
250 render_target_cache_(render_target_allocator == nullptr
251 ? std::make_shared<RenderTargetCache>(
252 context_->GetResourceAllocator())
253 : std::move(render_target_allocator)),
254 host_buffer_(HostBuffer::Create(context_->GetResourceAllocator())) {
255 if (!context_ || !context_->IsValid()) {
256 return;
257 }
258
259 {
261 desc.storage_mode = StorageMode::kHostVisible;
262 desc.format = PixelFormat::kR8G8B8A8UNormInt;
263 desc.size = ISize{1, 1};
264 empty_texture_ = GetContext()->GetResourceAllocator()->CreateTexture(desc);
265 auto data = Color::BlackTransparent().ToR8G8B8A8();
266 if (!empty_texture_->SetContents(data.data(), 4)) {
267 VALIDATION_LOG << "Failed to create empty texture.";
268 }
269 }
270
273 .color_attachment_pixel_format =
274 context_->GetCapabilities()->GetDefaultColorFormat()};
275 auto options_trianglestrip = ContentContextOptions{
277 .primitive_type = PrimitiveType::kTriangleStrip,
278 .color_attachment_pixel_format =
279 context_->GetCapabilities()->GetDefaultColorFormat()};
280 const auto supports_decal = static_cast<Scalar>(
281 context_->GetCapabilities()->SupportsDecalSamplerAddressMode());
282
283#ifdef IMPELLER_DEBUG
284 checkerboard_pipelines_.CreateDefault(*context_, options);
285#endif // IMPELLER_DEBUG
286
287 {
288 solid_fill_pipelines_.CreateDefault(*context_, options);
289 texture_pipelines_.CreateDefault(*context_, options);
290
291 if (context_->GetCapabilities()->SupportsSSBO()) {
292 linear_gradient_ssbo_fill_pipelines_.CreateDefault(*context_, options);
293 radial_gradient_ssbo_fill_pipelines_.CreateDefault(*context_, options);
294 conical_gradient_ssbo_fill_pipelines_.CreateDefault(*context_, options);
295 sweep_gradient_ssbo_fill_pipelines_.CreateDefault(*context_, options);
296 } else {
297 linear_gradient_fill_pipelines_.CreateDefault(*context_, options);
298 radial_gradient_fill_pipelines_.CreateDefault(*context_, options);
299 conical_gradient_fill_pipelines_.CreateDefault(*context_, options);
300 sweep_gradient_fill_pipelines_.CreateDefault(*context_, options);
301 }
302
303 /// Setup default clip pipeline.
304
305 auto clip_pipeline_descriptor =
306 ClipPipeline::Builder::MakeDefaultPipelineDescriptor(*context_);
307 if (!clip_pipeline_descriptor.has_value()) {
308 return;
309 }
312 .color_attachment_pixel_format =
313 context_->GetCapabilities()->GetDefaultColorFormat()}
314 .ApplyToPipelineDescriptor(*clip_pipeline_descriptor);
315 // Disable write to all color attachments.
316 auto clip_color_attachments =
317 clip_pipeline_descriptor->GetColorAttachmentDescriptors();
318 for (auto& color_attachment : clip_color_attachments) {
319 color_attachment.second.write_mask = ColorWriteMaskBits::kNone;
320 }
321 clip_pipeline_descriptor->SetColorAttachmentDescriptors(
322 std::move(clip_color_attachments));
323 clip_pipelines_.SetDefault(
324 options,
325 std::make_unique<ClipPipeline>(*context_, clip_pipeline_descriptor));
326 }
327
328 if (context_->GetCapabilities()->SupportsFramebufferFetch()) {
329 framebuffer_blend_color_pipelines_.CreateDefault(
330 *context_, options_trianglestrip,
331 {static_cast<Scalar>(BlendSelectValues::kColor), supports_decal});
332 framebuffer_blend_colorburn_pipelines_.CreateDefault(
333 *context_, options_trianglestrip,
334 {static_cast<Scalar>(BlendSelectValues::kColorBurn), supports_decal});
335 framebuffer_blend_colordodge_pipelines_.CreateDefault(
336 *context_, options_trianglestrip,
337 {static_cast<Scalar>(BlendSelectValues::kColorDodge), supports_decal});
338 framebuffer_blend_darken_pipelines_.CreateDefault(
339 *context_, options_trianglestrip,
340 {static_cast<Scalar>(BlendSelectValues::kDarken), supports_decal});
341 framebuffer_blend_difference_pipelines_.CreateDefault(
342 *context_, options_trianglestrip,
343 {static_cast<Scalar>(BlendSelectValues::kDifference), supports_decal});
344 framebuffer_blend_exclusion_pipelines_.CreateDefault(
345 *context_, options_trianglestrip,
346 {static_cast<Scalar>(BlendSelectValues::kExclusion), supports_decal});
347 framebuffer_blend_hardlight_pipelines_.CreateDefault(
348 *context_, options_trianglestrip,
349 {static_cast<Scalar>(BlendSelectValues::kHardLight), supports_decal});
350 framebuffer_blend_hue_pipelines_.CreateDefault(
351 *context_, options_trianglestrip,
352 {static_cast<Scalar>(BlendSelectValues::kHue), supports_decal});
353 framebuffer_blend_lighten_pipelines_.CreateDefault(
354 *context_, options_trianglestrip,
355 {static_cast<Scalar>(BlendSelectValues::kLighten), supports_decal});
356 framebuffer_blend_luminosity_pipelines_.CreateDefault(
357 *context_, options_trianglestrip,
358 {static_cast<Scalar>(BlendSelectValues::kLuminosity), supports_decal});
359 framebuffer_blend_multiply_pipelines_.CreateDefault(
360 *context_, options_trianglestrip,
361 {static_cast<Scalar>(BlendSelectValues::kMultiply), supports_decal});
362 framebuffer_blend_overlay_pipelines_.CreateDefault(
363 *context_, options_trianglestrip,
364 {static_cast<Scalar>(BlendSelectValues::kOverlay), supports_decal});
365 framebuffer_blend_saturation_pipelines_.CreateDefault(
366 *context_, options_trianglestrip,
367 {static_cast<Scalar>(BlendSelectValues::kSaturation), supports_decal});
368 framebuffer_blend_screen_pipelines_.CreateDefault(
369 *context_, options_trianglestrip,
370 {static_cast<Scalar>(BlendSelectValues::kScreen), supports_decal});
371 framebuffer_blend_softlight_pipelines_.CreateDefault(
372 *context_, options_trianglestrip,
373 {static_cast<Scalar>(BlendSelectValues::kSoftLight), supports_decal});
374 } else {
375 blend_color_pipelines_.CreateDefault(
376 *context_, options_trianglestrip,
377 {static_cast<Scalar>(BlendSelectValues::kColor), supports_decal});
378 blend_colorburn_pipelines_.CreateDefault(
379 *context_, options_trianglestrip,
380 {static_cast<Scalar>(BlendSelectValues::kColorBurn), supports_decal});
381 blend_colordodge_pipelines_.CreateDefault(
382 *context_, options_trianglestrip,
383 {static_cast<Scalar>(BlendSelectValues::kColorDodge), supports_decal});
384 blend_darken_pipelines_.CreateDefault(
385 *context_, options_trianglestrip,
386 {static_cast<Scalar>(BlendSelectValues::kDarken), supports_decal});
387 blend_difference_pipelines_.CreateDefault(
388 *context_, options_trianglestrip,
389 {static_cast<Scalar>(BlendSelectValues::kDifference), supports_decal});
390 blend_exclusion_pipelines_.CreateDefault(
391 *context_, options_trianglestrip,
392 {static_cast<Scalar>(BlendSelectValues::kExclusion), supports_decal});
393 blend_hardlight_pipelines_.CreateDefault(
394 *context_, options_trianglestrip,
395 {static_cast<Scalar>(BlendSelectValues::kHardLight), supports_decal});
396 blend_hue_pipelines_.CreateDefault(
397 *context_, options_trianglestrip,
398 {static_cast<Scalar>(BlendSelectValues::kHue), supports_decal});
399 blend_lighten_pipelines_.CreateDefault(
400 *context_, options_trianglestrip,
401 {static_cast<Scalar>(BlendSelectValues::kLighten), supports_decal});
402 blend_luminosity_pipelines_.CreateDefault(
403 *context_, options_trianglestrip,
404 {static_cast<Scalar>(BlendSelectValues::kLuminosity), supports_decal});
405 blend_multiply_pipelines_.CreateDefault(
406 *context_, options_trianglestrip,
407 {static_cast<Scalar>(BlendSelectValues::kMultiply), supports_decal});
408 blend_overlay_pipelines_.CreateDefault(
409 *context_, options_trianglestrip,
410 {static_cast<Scalar>(BlendSelectValues::kOverlay), supports_decal});
411 blend_saturation_pipelines_.CreateDefault(
412 *context_, options_trianglestrip,
413 {static_cast<Scalar>(BlendSelectValues::kSaturation), supports_decal});
414 blend_screen_pipelines_.CreateDefault(
415 *context_, options_trianglestrip,
416 {static_cast<Scalar>(BlendSelectValues::kScreen), supports_decal});
417 blend_softlight_pipelines_.CreateDefault(
418 *context_, options_trianglestrip,
419 {static_cast<Scalar>(BlendSelectValues::kSoftLight), supports_decal});
420 }
421
422 rrect_blur_pipelines_.CreateDefault(*context_, options_trianglestrip);
423 texture_strict_src_pipelines_.CreateDefault(*context_, options);
424 tiled_texture_pipelines_.CreateDefault(*context_, options, {supports_decal});
425 gaussian_blur_pipelines_.CreateDefault(*context_, options_trianglestrip,
426 {supports_decal});
427 border_mask_blur_pipelines_.CreateDefault(*context_, options_trianglestrip);
428 morphology_filter_pipelines_.CreateDefault(*context_, options_trianglestrip,
429 {supports_decal});
430 color_matrix_color_filter_pipelines_.CreateDefault(*context_,
431 options_trianglestrip);
432 linear_to_srgb_filter_pipelines_.CreateDefault(*context_,
433 options_trianglestrip);
434 srgb_to_linear_filter_pipelines_.CreateDefault(*context_,
435 options_trianglestrip);
436 glyph_atlas_pipelines_.CreateDefault(
437 *context_, options,
438 {static_cast<Scalar>(
439 GetContext()->GetCapabilities()->GetDefaultGlyphAtlasFormat() ==
441 yuv_to_rgb_filter_pipelines_.CreateDefault(*context_, options_trianglestrip);
442 porter_duff_blend_pipelines_.CreateDefault(*context_, options_trianglestrip,
443 {supports_decal});
444 vertices_uber_shader_.CreateDefault(*context_, options, {supports_decal});
445 // GLES only shader that is unsupported on macOS.
446#if defined(IMPELLER_ENABLE_OPENGLES) && !defined(FML_OS_MACOSX)
447 if (GetContext()->GetBackendType() == Context::BackendType::kOpenGLES) {
448 tiled_texture_external_pipelines_.CreateDefault(*context_, options);
449 }
450#endif // IMPELLER_ENABLE_OPENGLES
451
452 is_valid_ = true;
453 InitializeCommonlyUsedShadersIfNeeded();
454}
455
457
459 return is_valid_;
460}
461
462std::shared_ptr<Texture> ContentContext::GetEmptyTexture() const {
463 return empty_texture_;
464}
465
467 std::string_view label,
468 ISize texture_size,
469 const std::shared_ptr<CommandBuffer>& command_buffer,
470 const SubpassCallback& subpass_callback,
471 bool msaa_enabled,
472 bool depth_stencil_enabled,
473 int32_t mip_count) const {
474 const std::shared_ptr<Context>& context = GetContext();
475 RenderTarget subpass_target;
476
477 std::optional<RenderTarget::AttachmentConfig> depth_stencil_config =
479 : std::optional<RenderTarget::AttachmentConfig>();
480
481 if (context->GetCapabilities()->SupportsOffscreenMSAA() && msaa_enabled) {
482 subpass_target = GetRenderTargetCache()->CreateOffscreenMSAA(
483 *context, texture_size,
484 /*mip_count=*/mip_count, SPrintF("%s Offscreen", label.data()),
486 } else {
487 subpass_target = GetRenderTargetCache()->CreateOffscreen(
488 *context, texture_size,
489 /*mip_count=*/mip_count, SPrintF("%s Offscreen", label.data()),
490 RenderTarget::kDefaultColorAttachmentConfig, depth_stencil_config);
491 }
492 return MakeSubpass(label, subpass_target, command_buffer, subpass_callback);
493}
494
496 std::string_view label,
497 const RenderTarget& subpass_target,
498 const std::shared_ptr<CommandBuffer>& command_buffer,
499 const SubpassCallback& subpass_callback) const {
500 const std::shared_ptr<Context>& context = GetContext();
501
502 auto subpass_texture = subpass_target.GetRenderTargetTexture();
503 if (!subpass_texture) {
505 }
506
507 auto sub_renderpass = command_buffer->CreateRenderPass(subpass_target);
508 if (!sub_renderpass) {
510 }
511 sub_renderpass->SetLabel(SPrintF("%s RenderPass", label.data()));
512
513 if (!subpass_callback(*this, *sub_renderpass)) {
515 }
516
517 if (!sub_renderpass->EncodeCommands()) {
519 }
520
521 const std::shared_ptr<Texture>& target_texture =
522 subpass_target.GetRenderTargetTexture();
523 if (target_texture->GetMipCount() > 1) {
524 fml::Status mipmap_status =
525 AddMipmapGeneration(command_buffer, context, target_texture);
526 if (!mipmap_status.ok()) {
527 return mipmap_status;
528 }
529 }
530
531 return subpass_target;
532}
533
534#if IMPELLER_ENABLE_3D
535std::shared_ptr<scene::SceneContext> ContentContext::GetSceneContext() const {
536 return scene_context_;
537}
538#endif // IMPELLER_ENABLE_3D
539
540std::shared_ptr<Tessellator> ContentContext::GetTessellator() const {
541 return tessellator_;
542}
543
544std::shared_ptr<Context> ContentContext::GetContext() const {
545 return context_;
546}
547
549 return *context_->GetCapabilities();
550}
551
552void ContentContext::SetWireframe(bool wireframe) {
553 wireframe_ = wireframe;
554}
555
556std::shared_ptr<Pipeline<PipelineDescriptor>>
558 const std::string& unique_entrypoint_name,
560 const std::function<std::shared_ptr<Pipeline<PipelineDescriptor>>()>&
561 create_callback) const {
562 RuntimeEffectPipelineKey key{unique_entrypoint_name, options};
563 auto it = runtime_effect_pipelines_.find(key);
564 if (it == runtime_effect_pipelines_.end()) {
565 it = runtime_effect_pipelines_.insert(it, {key, create_callback()});
566 }
567 return it->second;
568}
569
571 const std::string& unique_entrypoint_name) const {
572 for (auto it = runtime_effect_pipelines_.begin();
573 it != runtime_effect_pipelines_.end();) {
574 if (it->first.unique_entrypoint_name == unique_entrypoint_name) {
575 it = runtime_effect_pipelines_.erase(it);
576 } else {
577 it++;
578 }
579 }
580}
581
582void ContentContext::InitializeCommonlyUsedShadersIfNeeded() const {
583 TRACE_EVENT0("flutter", "InitializeCommonlyUsedShadersIfNeeded");
584 GetContext()->InitializeCommonlyUsedShadersIfNeeded();
585}
586
587} // namespace impeller
const char * options
static sk_sp< Effect > Create()
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
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:46
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:23
Describes the fixed function and programmable aspects of rendering and compute operations performed b...
Definition pipeline.h:49
An implementation of the [RenderTargetAllocator] that caches all allocated texture data for one frame...
std::shared_ptr< Texture > GetRenderTargetTexture() const
static constexpr AttachmentConfig kDefaultColorAttachmentConfig
static constexpr AttachmentConfigMSAA kDefaultColorAttachmentConfigMSAA
static constexpr AttachmentConfig kDefaultStencilAttachmentConfig
A utility that generates triangles of the specified fill type given a polyline. This happens on the C...
Definition tessellator.h:29
if(end==-1)
#define FML_UNREACHABLE()
Definition logging.h:109
#define FML_DCHECK(condition)
Definition logging.h:103
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)
Definition ref_ptr.h:256
Describe the color attachment that will be used with this pipeline.
Definition formats.h:500
constexpr std::array< uint8_t, 4 > ToR8G8B8A8() const
Convert to R8G8B8A8 representation.
Definition color.h:248
static constexpr Color BlackTransparent()
Definition color.h:262
void ApplyToPipelineDescriptor(PipelineDescriptor &desc) const
A lightweight object that describes the attributes of a texture that can then used an allocator to cr...
#define TRACE_EVENT0(category_group, name)
#define VALIDATION_LOG
Definition validation.h:73