Flutter Impeller
content_context.h
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 
5 #ifndef FLUTTER_IMPELLER_ENTITY_CONTENTS_CONTENT_CONTEXT_H_
6 #define FLUTTER_IMPELLER_ENTITY_CONTENTS_CONTENT_CONTEXT_H_
7 
8 #include <initializer_list>
9 #include <memory>
10 #include <optional>
11 #include <unordered_map>
12 #include <utility>
13 
14 #include "flutter/fml/logging.h"
15 #include "flutter/fml/status_or.h"
17 #include "impeller/core/formats.h"
28 
29 namespace impeller {
30 /// Pipeline state configuration.
31 ///
32 /// Each unique combination of these options requires a different pipeline state
33 /// object to be built. This struct is used as a key for the per-pipeline
34 /// variant cache.
35 ///
36 /// When adding fields to this key, reliant features should take care to limit
37 /// the combinatorical explosion of variations. A sufficiently complicated
38 /// Flutter application may easily require building hundreds of PSOs in total,
39 /// but they shouldn't require e.g. 10s of thousands.
41  enum class StencilMode : uint8_t {
42  /// Turn the stencil test off. Used when drawing without stencil-then-cover
43  /// or overdraw prevention.
44  kIgnore,
45 
46  // Operations used for stencil-then-cover.
47 
48  /// Draw the stencil for the NonZero fill path rule.
49  ///
50  /// The stencil ref should always be 0 on commands using this mode.
52  /// Draw the stencil for the EvenOdd fill path rule.
53  ///
54  /// The stencil ref should always be 0 on commands using this mode.
56  /// Used for draw calls which fill in the stenciled area. Intended to be
57  /// used after `kStencilNonZeroFill` or `kStencilEvenOddFill` is used to set
58  /// up the stencil buffer. Also cleans up the stencil buffer by resetting
59  /// everything to zero.
60  ///
61  /// The stencil ref should always be 0 on commands using this mode.
63  /// The opposite of `kCoverCompare`. Used for draw calls which fill in the
64  /// non-stenciled area (intersection clips). Intended to be used after
65  /// `kStencilNonZeroFill` or `kStencilEvenOddFill` is used to set up the
66  /// stencil buffer. Also cleans up the stencil buffer by resetting
67  /// everything to zero.
68  ///
69  /// The stencil ref should always be 0 on commands using this mode.
71 
72  // Operations used for the "overdraw prevention" mechanism. This is used for
73  // drawing strokes.
74 
75  /// For each fragment, increment the stencil value if it's currently zero.
76  /// Discard fragments when the value is non-zero. This prevents
77  /// self-overlapping strokes from drawing over themselves.
78  ///
79  /// Note that this is done for rendering correctness, not performance. If a
80  /// stroke is drawn with a backdrop-reliant blend and self-intersects, then
81  /// the intersected geometry will render incorrectly when overdrawn because
82  /// we don't adjust the geometry prevent self-intersection.
83  ///
84  /// The stencil ref should always be 0 on commands using this mode.
86  /// Reset the stencil to a new maximum value specified by the ref (currently
87  /// always 0).
88  ///
89  /// The stencil ref should always be 0 on commands using this mode.
91  };
92 
100  bool depth_write_enabled = false;
102 
103  constexpr uint64_t ToKey() const {
104  static_assert(sizeof(sample_count) == 1);
105  static_assert(sizeof(blend_mode) == 1);
106  static_assert(sizeof(sample_count) == 1);
107  static_assert(sizeof(depth_compare) == 1);
108  static_assert(sizeof(stencil_mode) == 1);
109  static_assert(sizeof(primitive_type) == 1);
110  static_assert(sizeof(color_attachment_pixel_format) == 1);
111 
112  return (is_for_rrect_blur_clear ? 1llu : 0llu) << 0 |
113  (0) << 1 | // // Unused, previously wireframe.
114  (has_depth_stencil_attachments ? 1llu : 0llu) << 2 |
115  (depth_write_enabled ? 1llu : 0llu) << 3 |
116  // enums
117  static_cast<uint64_t>(color_attachment_pixel_format) << 8 |
118  static_cast<uint64_t>(primitive_type) << 16 |
119  static_cast<uint64_t>(stencil_mode) << 24 |
120  static_cast<uint64_t>(depth_compare) << 32 |
121  static_cast<uint64_t>(blend_mode) << 40 |
122  static_cast<uint64_t>(sample_count) << 48;
123  }
124 
126 };
127 
133 };
134 
135 class Tessellator;
136 class RenderTargetCache;
137 
139  public:
140  explicit ContentContext(
141  std::shared_ptr<Context> context,
142  std::shared_ptr<TypographerContext> typographer_context,
143  std::shared_ptr<RenderTargetAllocator> render_target_allocator = nullptr);
144 
146 
147  bool IsValid() const;
148 
149  Tessellator& GetTessellator() const;
150 
151  // clang-format off
228 #ifdef IMPELLER_ENABLE_OPENGLES
229  PipelineRef GetDownsampleTextureGlesPipeline(ContentContextOptions opts) const;
230  PipelineRef GetTiledTextureExternalPipeline(ContentContextOptions opts) const;
231  PipelineRef GetTiledTextureUvExternalPipeline(ContentContextOptions opts) const;
232 #endif // IMPELLER_ENABLE_OPENGLES
233  // clang-format on
234 
235  // An empty 1x1 texture for binding drawVertices/drawAtlas or other cases
236  // that don't always have a texture (due to blending).
237  std::shared_ptr<Texture> GetEmptyTexture() const;
238 
239  std::shared_ptr<Context> GetContext() const;
240 
241  const Capabilities& GetDeviceCapabilities() const;
242 
244  std::function<bool(const ContentContext&, RenderPass&)>;
245 
246  /// @brief Creates a new texture of size `texture_size` and calls
247  /// `subpass_callback` with a `RenderPass` for drawing to the texture.
248  fml::StatusOr<RenderTarget> MakeSubpass(
249  std::string_view label,
250  ISize texture_size,
251  const std::shared_ptr<CommandBuffer>& command_buffer,
252  const SubpassCallback& subpass_callback,
253  bool msaa_enabled = true,
254  bool depth_stencil_enabled = false,
255  int32_t mip_count = 1) const;
256 
257  /// Makes a subpass that will render to `subpass_target`.
258  fml::StatusOr<RenderTarget> MakeSubpass(
259  std::string_view label,
260  const RenderTarget& subpass_target,
261  const std::shared_ptr<CommandBuffer>& command_buffer,
262  const SubpassCallback& subpass_callback) const;
263 
264  const std::shared_ptr<LazyGlyphAtlas>& GetLazyGlyphAtlas() const {
265  return lazy_glyph_atlas_;
266  }
267 
268  const std::shared_ptr<RenderTargetAllocator>& GetRenderTargetCache() const {
269  return render_target_cache_;
270  }
271 
272  /// RuntimeEffect pipelines must be obtained via this method to avoid
273  /// re-creating them every frame.
274  ///
275  /// The unique_entrypoint_name comes from RuntimeEffect::GetEntrypoint.
276  /// Impellerc generates a unique entrypoint name for runtime effect shaders
277  /// based on the input file name and shader stage.
278  ///
279  /// The create_callback is synchronously invoked exactly once if a cached
280  /// pipeline is not found.
282  const std::string& unique_entrypoint_name,
283  const ContentContextOptions& options,
284  const std::function<std::shared_ptr<Pipeline<PipelineDescriptor>>()>&
285  create_callback) const;
286 
287  /// Used by hot reload/hot restart to clear a cached pipeline from
288  /// GetCachedRuntimeEffectPipeline.
290  const std::string& unique_entrypoint_name) const;
291 
292  /// @brief Retrieve the currnent host buffer for transient storage.
293  ///
294  /// This is only safe to use from the raster threads. Other threads should
295  /// allocate their own device buffers.
296  HostBuffer& GetTransientsBuffer() const { return *host_buffer_; }
297 
298  TextShadowCache& GetTextShadowCache() const { return *text_shadow_cache_; }
299 
300  private:
301  std::shared_ptr<Context> context_;
302  std::shared_ptr<LazyGlyphAtlas> lazy_glyph_atlas_;
303 
304  /// Run backend specific additional setup and create common shader variants.
305  ///
306  /// This bootstrap is intended to improve the performance of several
307  /// first frame benchmarks that are tracked in the flutter device lab.
308  /// The workload includes initializing commonly used but not default
309  /// shader variants, as well as forcing driver initialization.
310  void InitializeCommonlyUsedShadersIfNeeded() const;
311 
312  struct RuntimeEffectPipelineKey {
313  std::string unique_entrypoint_name;
314  ContentContextOptions options;
315 
316  struct Hash {
317  std::size_t operator()(const RuntimeEffectPipelineKey& key) const {
318  return fml::HashCombine(key.unique_entrypoint_name,
319  key.options.ToKey());
320  }
321  };
322 
323  struct Equal {
324  constexpr bool operator()(const RuntimeEffectPipelineKey& lhs,
325  const RuntimeEffectPipelineKey& rhs) const {
326  return lhs.unique_entrypoint_name == rhs.unique_entrypoint_name &&
327  lhs.options.ToKey() == rhs.options.ToKey();
328  }
329  };
330  };
331 
332  mutable std::unordered_map<RuntimeEffectPipelineKey,
333  std::shared_ptr<Pipeline<PipelineDescriptor>>,
334  RuntimeEffectPipelineKey::Hash,
335  RuntimeEffectPipelineKey::Equal>
336  runtime_effect_pipelines_;
337 
338  struct Pipelines;
339  std::unique_ptr<Pipelines> pipelines_;
340 
341  bool is_valid_ = false;
342  std::shared_ptr<Tessellator> tessellator_;
343  std::shared_ptr<RenderTargetAllocator> render_target_cache_;
344  std::shared_ptr<HostBuffer> host_buffer_;
345  std::shared_ptr<Texture> empty_texture_;
346  std::unique_ptr<TextShadowCache> text_shadow_cache_;
347 
348  ContentContext(const ContentContext&) = delete;
349 
350  ContentContext& operator=(const ContentContext&) = delete;
351 };
352 
353 } // namespace impeller
354 
355 #endif // FLUTTER_IMPELLER_ENTITY_CONTENTS_CONTENT_CONTEXT_H_
PipelineRef GetBlendLuminosityPipeline(ContentContextOptions opts) const
HostBuffer & GetTransientsBuffer() const
Retrieve the currnent host buffer for transient storage.
PipelineRef GetTiledTexturePipeline(ContentContextOptions opts) const
PipelineRef GetFramebufferBlendColorPipeline(ContentContextOptions opts) const
PipelineRef GetDownsamplePipeline(ContentContextOptions opts) const
PipelineRef GetSourceInBlendPipeline(ContentContextOptions opts) const
void ClearCachedRuntimeEffectPipeline(const std::string &unique_entrypoint_name) const
PipelineRef GetLinearGradientFillPipeline(ContentContextOptions opts) const
PipelineRef GetFramebufferBlendOverlayPipeline(ContentContextOptions opts) const
PipelineRef GetBlendColorDodgePipeline(ContentContextOptions opts) const
PipelineRef GetFramebufferBlendColorBurnPipeline(ContentContextOptions opts) const
PipelineRef GetPorterDuffPipeline(BlendMode mode, ContentContextOptions opts) const
std::shared_ptr< Texture > GetEmptyTexture() const
PipelineRef GetSourceOutBlendPipeline(ContentContextOptions opts) const
PipelineRef GetScreenBlendPipeline(ContentContextOptions opts) const
PipelineRef GetBlendColorPipeline(ContentContextOptions opts) const
PipelineRef GetLinePipeline(ContentContextOptions opts) const
PipelineRef GetFramebufferBlendLuminosityPipeline(ContentContextOptions opts) const
PipelineRef GetPlusBlendPipeline(ContentContextOptions opts) const
PipelineRef GetFastGradientPipeline(ContentContextOptions opts) const
const std::shared_ptr< LazyGlyphAtlas > & GetLazyGlyphAtlas() const
ContentContext(std::shared_ptr< Context > context, std::shared_ptr< TypographerContext > typographer_context, std::shared_ptr< RenderTargetAllocator > render_target_allocator=nullptr)
PipelineRef GetSolidFillPipeline(ContentContextOptions opts) const
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
PipelineRef GetModulateBlendPipeline(ContentContextOptions opts) const
PipelineRef GetFramebufferBlendHardLightPipeline(ContentContextOptions opts) const
PipelineRef GetFramebufferBlendColorDodgePipeline(ContentContextOptions opts) const
PipelineRef GetSweepGradientUniformFillPipeline(ContentContextOptions opts) const
PipelineRef GetBlendSoftLightPipeline(ContentContextOptions opts) const
PipelineRef GetDestinationATopBlendPipeline(ContentContextOptions opts) const
PipelineRef GetTextureStrictSrcPipeline(ContentContextOptions opts) const
PipelineRef GetCachedRuntimeEffectPipeline(const std::string &unique_entrypoint_name, const ContentContextOptions &options, const std::function< std::shared_ptr< Pipeline< PipelineDescriptor >>()> &create_callback) const
PipelineRef GetRadialGradientSSBOFillPipeline(ContentContextOptions opts) const
PipelineRef GetBlendColorBurnPipeline(ContentContextOptions opts) const
PipelineRef GetSweepGradientSSBOFillPipeline(ContentContextOptions opts) const
PipelineRef GetLinearGradientUniformFillPipeline(ContentContextOptions opts) const
PipelineRef GetFramebufferBlendScreenPipeline(ContentContextOptions opts) const
PipelineRef GetLinearGradientSSBOFillPipeline(ContentContextOptions opts) const
PipelineRef GetRadialGradientFillPipeline(ContentContextOptions opts) const
PipelineRef GetTexturePipeline(ContentContextOptions opts) const
PipelineRef GetBlendHardLightPipeline(ContentContextOptions opts) const
PipelineRef GetClearBlendPipeline(ContentContextOptions opts) const
PipelineRef GetConicalGradientUniformFillPipeline(ContentContextOptions opts, ConicalKind kind) const
PipelineRef GetRadialGradientUniformFillPipeline(ContentContextOptions opts) const
PipelineRef GetSweepGradientFillPipeline(ContentContextOptions opts) const
PipelineRef GetFramebufferBlendExclusionPipeline(ContentContextOptions opts) const
PipelineRef GetFramebufferBlendDarkenPipeline(ContentContextOptions opts) const
PipelineRef GetBlendSaturationPipeline(ContentContextOptions opts) const
PipelineRef GetFramebufferBlendSoftLightPipeline(ContentContextOptions opts) const
PipelineRef GetFramebufferBlendLightenPipeline(ContentContextOptions opts) const
PipelineRef GetMorphologyFilterPipeline(ContentContextOptions opts) const
PipelineRef GetFramebufferBlendSaturationPipeline(ContentContextOptions opts) const
PipelineRef GetBlendDifferencePipeline(ContentContextOptions opts) const
PipelineRef GetGaussianBlurPipeline(ContentContextOptions opts) const
PipelineRef GetBlendHuePipeline(ContentContextOptions opts) const
PipelineRef GetSrgbToLinearFilterPipeline(ContentContextOptions opts) const
PipelineRef GetDestinationOutBlendPipeline(ContentContextOptions opts) const
PipelineRef GetYUVToRGBFilterPipeline(ContentContextOptions opts) const
PipelineRef GetFramebufferBlendDifferencePipeline(ContentContextOptions opts) const
PipelineRef GetFramebufferBlendHuePipeline(ContentContextOptions opts) const
PipelineRef GetSourceATopBlendPipeline(ContentContextOptions opts) const
PipelineRef GetXorBlendPipeline(ContentContextOptions opts) const
PipelineRef GetGlyphAtlasPipeline(ContentContextOptions opts) const
PipelineRef GetClipPipeline(ContentContextOptions opts) const
const std::shared_ptr< RenderTargetAllocator > & GetRenderTargetCache() const
PipelineRef GetRRectBlurPipeline(ContentContextOptions opts) const
PipelineRef GetBlendScreenPipeline(ContentContextOptions opts) const
std::function< bool(const ContentContext &, RenderPass &)> SubpassCallback
PipelineRef GetBlendDarkenPipeline(ContentContextOptions opts) const
PipelineRef GetSourceBlendPipeline(ContentContextOptions opts) const
PipelineRef GetLinearToSrgbFilterPipeline(ContentContextOptions opts) const
TextShadowCache & GetTextShadowCache() const
PipelineRef GetBlendOverlayPipeline(ContentContextOptions opts) const
PipelineRef GetDestinationBlendPipeline(ContentContextOptions opts) const
PipelineRef GetDestinationOverBlendPipeline(ContentContextOptions opts) const
PipelineRef GetFramebufferBlendMultiplyPipeline(ContentContextOptions opts) const
PipelineRef GetConicalGradientSSBOFillPipeline(ContentContextOptions opts, ConicalKind kind) const
Tessellator & GetTessellator() const
PipelineRef GetBlendLightenPipeline(ContentContextOptions opts) const
PipelineRef GetBlendMultiplyPipeline(ContentContextOptions opts) const
PipelineRef GetSourceOverBlendPipeline(ContentContextOptions opts) const
PipelineRef GetBlendExclusionPipeline(ContentContextOptions opts) const
PipelineRef GetColorMatrixColorFilterPipeline(ContentContextOptions opts) const
PipelineRef GetConicalGradientFillPipeline(ContentContextOptions opts, ConicalKind kind) const
std::shared_ptr< Context > GetContext() const
PipelineRef GetDestinationInBlendPipeline(ContentContextOptions opts) const
PipelineRef GetBorderMaskBlurPipeline(ContentContextOptions opts) const
PipelineRef GetDrawVerticesUberPipeline(BlendMode blend_mode, ContentContextOptions opts) const
Render passes encode render commands directed as one specific render target into an underlying comman...
Definition: render_pass.h:30
A utility that generates triangles of the specified fill type given a polyline. This happens on the C...
Definition: tessellator.h:34
A cache for blurred text that re-uses these across frames.
PrimitiveType
Decides how backend draws pixels based on input vertices.
Definition: formats.h:352
PixelFormat
The Pixel formats supported by Impeller. The naming convention denotes the usage of the component,...
Definition: formats.h:99
CompareFunction
Definition: formats.h:552
@ kAlways
Comparison test passes always passes.
BlendMode
Definition: color.h:58
SampleCount
Definition: formats.h:295
constexpr bool operator()(const RuntimeEffectPipelineKey &lhs, const RuntimeEffectPipelineKey &rhs) const
std::size_t operator()(const RuntimeEffectPipelineKey &key) const
void ApplyToPipelineDescriptor(PipelineDescriptor &desc) const
constexpr uint64_t ToKey() const