Flutter Impeller
impeller::ContentContextOptions Struct Reference

#include <content_context.h>

Public Types

enum class  StencilMode : uint8_t {
  kIgnore ,
  kStencilNonZeroFill ,
  kStencilEvenOddFill ,
  kCoverCompare ,
  kCoverCompareInverted ,
  kOverdrawPreventionIncrement ,
  kOverdrawPreventionRestore
}
 

Public Member Functions

constexpr uint64_t ToKey () const
 
void ApplyToPipelineDescriptor (PipelineDescriptor &desc) const
 

Public Attributes

SampleCount sample_count = SampleCount::kCount1
 
BlendMode blend_mode = BlendMode::kSrcOver
 
CompareFunction depth_compare = CompareFunction::kAlways
 
StencilMode stencil_mode = ContentContextOptions::StencilMode::kIgnore
 
PrimitiveType primitive_type = PrimitiveType::kTriangle
 
PixelFormat color_attachment_pixel_format = PixelFormat::kUnknown
 
bool has_depth_stencil_attachments = true
 
bool depth_write_enabled = false
 
bool is_for_rrect_blur_clear = false
 

Detailed Description

Pipeline state configuration.

Each unique combination of these options requires a different pipeline state object to be built. This struct is used as a key for the per-pipeline variant cache.

When adding fields to this key, reliant features should take care to limit the combinatorical explosion of variations. A sufficiently complicated Flutter application may easily require building hundreds of PSOs in total, but they shouldn't require e.g. 10s of thousands.

Definition at line 40 of file content_context.h.

Member Enumeration Documentation

◆ StencilMode

Enumerator
kIgnore 

Turn the stencil test off. Used when drawing without stencil-then-cover or overdraw prevention.

kStencilNonZeroFill 

Draw the stencil for the NonZero fill path rule.

The stencil ref should always be 0 on commands using this mode. 
kStencilEvenOddFill 

Draw the stencil for the EvenOdd fill path rule.

The stencil ref should always be 0 on commands using this mode. 
kCoverCompare 

Used for draw calls which fill in the stenciled area. Intended to be used after kStencilNonZeroFill or kStencilEvenOddFill is used to set up the stencil buffer. Also cleans up the stencil buffer by resetting everything to zero.

The stencil ref should always be 0 on commands using this mode.

kCoverCompareInverted 

The opposite of kCoverCompare. Used for draw calls which fill in the non-stenciled area (intersection clips). Intended to be used after kStencilNonZeroFill or kStencilEvenOddFill is used to set up the stencil buffer. Also cleans up the stencil buffer by resetting everything to zero.

The stencil ref should always be 0 on commands using this mode.

kOverdrawPreventionIncrement 

For each fragment, increment the stencil value if it's currently zero. Discard fragments when the value is non-zero. This prevents self-overlapping strokes from drawing over themselves.

Note that this is done for rendering correctness, not performance. If a stroke is drawn with a backdrop-reliant blend and self-intersects, then the intersected geometry will render incorrectly when overdrawn because we don't adjust the geometry prevent self-intersection.

The stencil ref should always be 0 on commands using this mode.

kOverdrawPreventionRestore 

Reset the stencil to a new maximum value specified by the ref (currently always 0).

The stencil ref should always be 0 on commands using this mode.

Definition at line 41 of file content_context.h.

41  : 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.
51  kStencilNonZeroFill,
52  /// Draw the stencil for the EvenOdd fill path rule.
53  ///
54  /// The stencil ref should always be 0 on commands using this mode.
55  kStencilEvenOddFill,
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.
62  kCoverCompare,
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.
70  kCoverCompareInverted,
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.
85  kOverdrawPreventionIncrement,
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.
90  kOverdrawPreventionRestore,
91  };

Member Function Documentation

◆ ApplyToPipelineDescriptor()

void impeller::ContentContextOptions::ApplyToPipelineDescriptor ( PipelineDescriptor desc) const

Definition at line 310 of file content_context.cc.

311  {
312  auto pipeline_blend = blend_mode;
314  VALIDATION_LOG << "Cannot use blend mode " << static_cast<int>(blend_mode)
315  << " as a pipeline blend.";
316  pipeline_blend = BlendMode::kSrcOver;
317  }
318 
319  desc.SetSampleCount(sample_count);
320 
321  ColorAttachmentDescriptor color0 = *desc.GetColorAttachmentDescriptor(0u);
322  color0.format = color_attachment_pixel_format;
323  color0.alpha_blend_op = BlendOperation::kAdd;
324  color0.color_blend_op = BlendOperation::kAdd;
325  color0.write_mask = ColorWriteMaskBits::kAll;
326 
327  switch (pipeline_blend) {
328  case BlendMode::kClear:
330  color0.alpha_blend_op = BlendOperation::kReverseSubtract;
331  color0.color_blend_op = BlendOperation::kReverseSubtract;
332  color0.dst_alpha_blend_factor = BlendFactor::kOne;
333  color0.dst_color_blend_factor = BlendFactor::kOne;
334  color0.src_alpha_blend_factor = BlendFactor::kDestinationColor;
335  color0.src_color_blend_factor = BlendFactor::kDestinationColor;
336  } else {
337  color0.dst_alpha_blend_factor = BlendFactor::kZero;
338  color0.dst_color_blend_factor = BlendFactor::kZero;
339  color0.src_alpha_blend_factor = BlendFactor::kZero;
340  color0.src_color_blend_factor = BlendFactor::kZero;
341  }
342  break;
343  case BlendMode::kSrc:
344  color0.blending_enabled = false;
345  color0.dst_alpha_blend_factor = BlendFactor::kZero;
346  color0.dst_color_blend_factor = BlendFactor::kZero;
347  color0.src_alpha_blend_factor = BlendFactor::kOne;
348  color0.src_color_blend_factor = BlendFactor::kOne;
349  break;
350  case BlendMode::kDst:
351  color0.dst_alpha_blend_factor = BlendFactor::kOne;
352  color0.dst_color_blend_factor = BlendFactor::kOne;
353  color0.src_alpha_blend_factor = BlendFactor::kZero;
354  color0.src_color_blend_factor = BlendFactor::kZero;
355  color0.write_mask = ColorWriteMaskBits::kNone;
356  break;
357  case BlendMode::kSrcOver:
358  color0.dst_alpha_blend_factor = BlendFactor::kOneMinusSourceAlpha;
359  color0.dst_color_blend_factor = BlendFactor::kOneMinusSourceAlpha;
360  color0.src_alpha_blend_factor = BlendFactor::kOne;
361  color0.src_color_blend_factor = BlendFactor::kOne;
362  break;
363  case BlendMode::kDstOver:
364  color0.dst_alpha_blend_factor = BlendFactor::kOne;
365  color0.dst_color_blend_factor = BlendFactor::kOne;
366  color0.src_alpha_blend_factor = BlendFactor::kOneMinusDestinationAlpha;
367  color0.src_color_blend_factor = BlendFactor::kOneMinusDestinationAlpha;
368  break;
369  case BlendMode::kSrcIn:
370  color0.dst_alpha_blend_factor = BlendFactor::kZero;
371  color0.dst_color_blend_factor = BlendFactor::kZero;
372  color0.src_alpha_blend_factor = BlendFactor::kDestinationAlpha;
373  color0.src_color_blend_factor = BlendFactor::kDestinationAlpha;
374  break;
375  case BlendMode::kDstIn:
376  color0.dst_alpha_blend_factor = BlendFactor::kSourceAlpha;
377  color0.dst_color_blend_factor = BlendFactor::kSourceAlpha;
378  color0.src_alpha_blend_factor = BlendFactor::kZero;
379  color0.src_color_blend_factor = BlendFactor::kZero;
380  break;
381  case BlendMode::kSrcOut:
382  color0.dst_alpha_blend_factor = BlendFactor::kZero;
383  color0.dst_color_blend_factor = BlendFactor::kZero;
384  color0.src_alpha_blend_factor = BlendFactor::kOneMinusDestinationAlpha;
385  color0.src_color_blend_factor = BlendFactor::kOneMinusDestinationAlpha;
386  break;
387  case BlendMode::kDstOut:
388  color0.dst_alpha_blend_factor = BlendFactor::kOneMinusSourceAlpha;
389  color0.dst_color_blend_factor = BlendFactor::kOneMinusSourceAlpha;
390  color0.src_alpha_blend_factor = BlendFactor::kZero;
391  color0.src_color_blend_factor = BlendFactor::kZero;
392  break;
393  case BlendMode::kSrcATop:
394  color0.dst_alpha_blend_factor = BlendFactor::kOneMinusSourceAlpha;
395  color0.dst_color_blend_factor = BlendFactor::kOneMinusSourceAlpha;
396  color0.src_alpha_blend_factor = BlendFactor::kDestinationAlpha;
397  color0.src_color_blend_factor = BlendFactor::kDestinationAlpha;
398  break;
399  case BlendMode::kDstATop:
400  color0.dst_alpha_blend_factor = BlendFactor::kSourceAlpha;
401  color0.dst_color_blend_factor = BlendFactor::kSourceAlpha;
402  color0.src_alpha_blend_factor = BlendFactor::kOneMinusDestinationAlpha;
403  color0.src_color_blend_factor = BlendFactor::kOneMinusDestinationAlpha;
404  break;
405  case BlendMode::kXor:
406  color0.dst_alpha_blend_factor = BlendFactor::kOneMinusSourceAlpha;
407  color0.dst_color_blend_factor = BlendFactor::kOneMinusSourceAlpha;
408  color0.src_alpha_blend_factor = BlendFactor::kOneMinusDestinationAlpha;
409  color0.src_color_blend_factor = BlendFactor::kOneMinusDestinationAlpha;
410  break;
411  case BlendMode::kPlus:
412  color0.dst_alpha_blend_factor = BlendFactor::kOne;
413  color0.dst_color_blend_factor = BlendFactor::kOne;
414  color0.src_alpha_blend_factor = BlendFactor::kOne;
415  color0.src_color_blend_factor = BlendFactor::kOne;
416  break;
418  color0.dst_alpha_blend_factor = BlendFactor::kSourceAlpha;
419  color0.dst_color_blend_factor = BlendFactor::kSourceColor;
420  color0.src_alpha_blend_factor = BlendFactor::kZero;
421  color0.src_color_blend_factor = BlendFactor::kZero;
422  break;
423  default:
424  FML_UNREACHABLE();
425  }
426  desc.SetColorAttachmentDescriptor(0u, color0);
427 
429  desc.ClearDepthAttachment();
430  desc.ClearStencilAttachments();
431  }
432 
433  auto maybe_stencil = desc.GetFrontStencilAttachmentDescriptor();
434  auto maybe_depth = desc.GetDepthStencilAttachmentDescriptor();
435  FML_DCHECK(has_depth_stencil_attachments == maybe_depth.has_value())
436  << "Depth attachment doesn't match expected pipeline state. "
437  "has_depth_stencil_attachments="
439  FML_DCHECK(has_depth_stencil_attachments == maybe_stencil.has_value())
440  << "Stencil attachment doesn't match expected pipeline state. "
441  "has_depth_stencil_attachments="
443  if (maybe_stencil.has_value()) {
444  StencilAttachmentDescriptor front_stencil = maybe_stencil.value();
445  StencilAttachmentDescriptor back_stencil = front_stencil;
446 
447  switch (stencil_mode) {
449  front_stencil.stencil_compare = CompareFunction::kAlways;
450  front_stencil.depth_stencil_pass = StencilOperation::kKeep;
451  desc.SetStencilAttachmentDescriptors(front_stencil);
452  break;
454  // The stencil ref should be 0 on commands that use this mode.
455  front_stencil.stencil_compare = CompareFunction::kAlways;
456  front_stencil.depth_stencil_pass = StencilOperation::kIncrementWrap;
457  back_stencil.stencil_compare = CompareFunction::kAlways;
458  back_stencil.depth_stencil_pass = StencilOperation::kDecrementWrap;
459  desc.SetStencilAttachmentDescriptors(front_stencil, back_stencil);
460  break;
462  // The stencil ref should be 0 on commands that use this mode.
463  front_stencil.stencil_compare = CompareFunction::kEqual;
464  front_stencil.depth_stencil_pass = StencilOperation::kIncrementWrap;
465  front_stencil.stencil_failure = StencilOperation::kDecrementWrap;
466  desc.SetStencilAttachmentDescriptors(front_stencil);
467  break;
469  // The stencil ref should be 0 on commands that use this mode.
470  front_stencil.stencil_compare = CompareFunction::kNotEqual;
471  front_stencil.depth_stencil_pass =
473  desc.SetStencilAttachmentDescriptors(front_stencil);
474  break;
476  // The stencil ref should be 0 on commands that use this mode.
477  front_stencil.stencil_compare = CompareFunction::kEqual;
478  front_stencil.stencil_failure = StencilOperation::kSetToReferenceValue;
479  desc.SetStencilAttachmentDescriptors(front_stencil);
480  break;
482  front_stencil.stencil_compare = CompareFunction::kEqual;
483  front_stencil.depth_stencil_pass = StencilOperation::kIncrementClamp;
484  desc.SetStencilAttachmentDescriptors(front_stencil);
485  break;
487  front_stencil.stencil_compare = CompareFunction::kLess;
488  front_stencil.depth_stencil_pass =
490  desc.SetStencilAttachmentDescriptors(front_stencil);
491  break;
492  }
493  }
494  if (maybe_depth.has_value()) {
495  DepthAttachmentDescriptor depth = maybe_depth.value();
496  depth.depth_write_enabled = depth_write_enabled;
497  depth.depth_compare = depth_compare;
498  desc.SetDepthStencilAttachmentDescriptor(depth);
499  }
500 
501  desc.SetPrimitiveType(primitive_type);
502  desc.SetPolygonMode(PolygonMode::kFill);
503 }
static constexpr BlendMode kLastPipelineBlendMode
Definition: entity.h:28
@ 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.
@ 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.
#define VALIDATION_LOG
Definition: validation.h:91

References impeller::ColorAttachmentDescriptor::alpha_blend_op, blend_mode, impeller::ColorAttachmentDescriptor::blending_enabled, impeller::PipelineDescriptor::ClearDepthAttachment(), impeller::PipelineDescriptor::ClearStencilAttachments(), color_attachment_pixel_format, impeller::ColorAttachmentDescriptor::color_blend_op, impeller::DepthAttachmentDescriptor::depth_compare, depth_compare, impeller::StencilAttachmentDescriptor::depth_stencil_pass, impeller::DepthAttachmentDescriptor::depth_write_enabled, depth_write_enabled, impeller::ColorAttachmentDescriptor::dst_alpha_blend_factor, impeller::ColorAttachmentDescriptor::dst_color_blend_factor, impeller::ColorAttachmentDescriptor::format, impeller::PipelineDescriptor::GetColorAttachmentDescriptor(), impeller::PipelineDescriptor::GetDepthStencilAttachmentDescriptor(), impeller::PipelineDescriptor::GetFrontStencilAttachmentDescriptor(), has_depth_stencil_attachments, is_for_rrect_blur_clear, impeller::kAdd, impeller::kAll, impeller::kAlways, impeller::kClear, kCoverCompare, kCoverCompareInverted, impeller::kDecrementWrap, impeller::kDestinationAlpha, impeller::kDestinationColor, impeller::kDst, impeller::kDstATop, impeller::kDstIn, impeller::kDstOut, impeller::kDstOver, impeller::kEqual, impeller::kFill, kIgnore, impeller::kIncrementClamp, impeller::kIncrementWrap, impeller::kKeep, impeller::Entity::kLastPipelineBlendMode, impeller::kLess, impeller::kModulate, impeller::kNone, impeller::kNotEqual, impeller::kOne, impeller::kOneMinusDestinationAlpha, impeller::kOneMinusSourceAlpha, kOverdrawPreventionIncrement, kOverdrawPreventionRestore, impeller::kPlus, impeller::kReverseSubtract, impeller::kSetToReferenceValue, impeller::kSourceAlpha, impeller::kSourceColor, impeller::kSrc, impeller::kSrcATop, impeller::kSrcIn, impeller::kSrcOut, impeller::kSrcOver, kStencilEvenOddFill, kStencilNonZeroFill, impeller::kXor, impeller::kZero, primitive_type, sample_count, impeller::PipelineDescriptor::SetColorAttachmentDescriptor(), impeller::PipelineDescriptor::SetDepthStencilAttachmentDescriptor(), impeller::PipelineDescriptor::SetPolygonMode(), impeller::PipelineDescriptor::SetPrimitiveType(), impeller::PipelineDescriptor::SetSampleCount(), impeller::PipelineDescriptor::SetStencilAttachmentDescriptors(), impeller::ColorAttachmentDescriptor::src_alpha_blend_factor, impeller::ColorAttachmentDescriptor::src_color_blend_factor, impeller::StencilAttachmentDescriptor::stencil_compare, impeller::StencilAttachmentDescriptor::stencil_failure, stencil_mode, VALIDATION_LOG, and impeller::ColorAttachmentDescriptor::write_mask.

◆ ToKey()

constexpr uint64_t impeller::ContentContextOptions::ToKey ( ) const
inlineconstexpr

Definition at line 103 of file content_context.h.

103  {
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  }

References blend_mode, color_attachment_pixel_format, depth_compare, depth_write_enabled, has_depth_stencil_attachments, is_for_rrect_blur_clear, primitive_type, sample_count, and stencil_mode.

Referenced by impeller::testing::TEST_P().

Member Data Documentation

◆ blend_mode

BlendMode impeller::ContentContextOptions::blend_mode = BlendMode::kSrcOver

◆ color_attachment_pixel_format

PixelFormat impeller::ContentContextOptions::color_attachment_pixel_format = PixelFormat::kUnknown

◆ depth_compare

CompareFunction impeller::ContentContextOptions::depth_compare = CompareFunction::kAlways

Definition at line 95 of file content_context.h.

Referenced by ApplyToPipelineDescriptor(), impeller::OptionsFromPass(), and ToKey().

◆ depth_write_enabled

bool impeller::ContentContextOptions::depth_write_enabled = false

Definition at line 100 of file content_context.h.

Referenced by ApplyToPipelineDescriptor(), and ToKey().

◆ has_depth_stencil_attachments

bool impeller::ContentContextOptions::has_depth_stencil_attachments = true

◆ is_for_rrect_blur_clear

bool impeller::ContentContextOptions::is_for_rrect_blur_clear = false

◆ primitive_type

PrimitiveType impeller::ContentContextOptions::primitive_type = PrimitiveType::kTriangle

◆ sample_count

◆ stencil_mode

StencilMode impeller::ContentContextOptions::stencil_mode = ContentContextOptions::StencilMode::kIgnore

Definition at line 96 of file content_context.h.

Referenced by ApplyToPipelineDescriptor(), impeller::OptionsFromPass(), and ToKey().


The documentation for this struct was generated from the following files: