Flutter Engine
opacity_layer.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 
5 #include "flutter/flow/layers/opacity_layer.h"
6 
7 #include "flutter/fml/trace_event.h"
8 #include "third_party/skia/include/core/SkPaint.h"
9 
10 namespace flutter {
11 
12 OpacityLayer::OpacityLayer(SkAlpha alpha, const SkPoint& offset)
13  : alpha_(alpha), offset_(offset) {}
14 
15 #ifdef FLUTTER_ENABLE_DIFF_CONTEXT
16 
17 void OpacityLayer::Diff(DiffContext* context, const Layer* old_layer) {
18  DiffContext::AutoSubtreeRestore subtree(context);
19  auto* prev = static_cast<const OpacityLayer*>(old_layer);
20  if (!context->IsSubtreeDirty()) {
21  FML_DCHECK(prev);
22  if (alpha_ != prev->alpha_ || offset_ != prev->offset_) {
23  context->MarkSubtreeDirty(context->GetOldLayerPaintRegion(old_layer));
24  }
25  }
26  context->PushTransform(SkMatrix::Translate(offset_.fX, offset_.fY));
27 #ifndef SUPPORT_FRACTIONAL_TRANSLATION
28  context->SetTransform(
29  RasterCache::GetIntegralTransCTM(context->GetTransform()));
30 #endif
31  DiffChildren(context, prev);
32  context->SetLayerPaintRegion(this, context->CurrentSubtreeRegion());
33 }
34 
35 #endif // FLUTTER_ENABLE_DIFF_CONTEXT
36 
37 void OpacityLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) {
38  TRACE_EVENT0("flutter", "OpacityLayer::Preroll");
39  FML_DCHECK(!GetChildContainer()->layers().empty()); // We can't be a leaf.
40 
41  SkMatrix child_matrix = matrix;
42  child_matrix.preTranslate(offset_.fX, offset_.fY);
43 
44  // Similar to what's done in TransformLayer::Preroll, we have to apply the
45  // reverse transformation to the cull rect to properly cull child layers.
46  context->cull_rect = context->cull_rect.makeOffset(-offset_.fX, -offset_.fY);
47 
49  SkMatrix::Translate(offset_.fX, offset_.fY));
50  context->mutators_stack.PushOpacity(alpha_);
53  ContainerLayer::Preroll(context, child_matrix);
54  context->mutators_stack.Pop();
55  context->mutators_stack.Pop();
56 
57  {
58  set_paint_bounds(paint_bounds().makeOffset(offset_.fX, offset_.fY));
59 #ifndef SUPPORT_FRACTIONAL_TRANSLATION
60  child_matrix = RasterCache::GetIntegralTransCTM(child_matrix);
61 #endif
62  TryToPrepareRasterCache(context, GetCacheableChild(), child_matrix);
63  }
64 
65  // Restore cull_rect
66  context->cull_rect = context->cull_rect.makeOffset(offset_.fX, offset_.fY);
67 }
68 
69 void OpacityLayer::Paint(PaintContext& context) const {
70  TRACE_EVENT0("flutter", "OpacityLayer::Paint");
71  FML_DCHECK(needs_painting(context));
72 
73  SkPaint paint;
74  paint.setAlpha(alpha_);
75 
76  SkAutoCanvasRestore save(context.internal_nodes_canvas, true);
77  context.internal_nodes_canvas->translate(offset_.fX, offset_.fY);
78 
79 #ifndef SUPPORT_FRACTIONAL_TRANSLATION
81  context.leaf_nodes_canvas->getTotalMatrix()));
82 #endif
83 
84  if (context.raster_cache &&
86  *context.leaf_nodes_canvas, &paint)) {
87  return;
88  }
89 
90  // Skia may clip the content with saveLayerBounds (although it's not a
91  // guaranteed clip). So we have to provide a big enough saveLayerBounds. To do
92  // so, we first remove the offset from paint bounds since it's already in the
93  // matrix. Then we round out the bounds.
94  //
95  // Note that the following lines are only accessible when the raster cache is
96  // not available (e.g., when we're using the software backend in golden
97  // tests).
98  SkRect saveLayerBounds;
99  paint_bounds()
100  .makeOffset(-offset_.fX, -offset_.fY)
101  .roundOut(&saveLayerBounds);
102 
103  Layer::AutoSaveLayer save_layer =
104  Layer::AutoSaveLayer::Create(context, saveLayerBounds, &paint);
105  PaintChildren(context);
106 }
107 
108 } // namespace flutter
void Paint(PaintContext &context) const override
#define TRACE_EVENT0(category_group, name)
Definition: trace_event.h:90
#define FML_DCHECK(condition)
Definition: logging.h:86
OpacityLayer(SkAlpha alpha, const SkPoint &offset)
void PushTransform(const SkMatrix &matrix)
const std::vector< std::shared_ptr< Layer > > & layers() const
bool needs_painting(PaintContext &context) const
Definition: layer.h:249
void PushOpacity(const int &alpha)
Layer * GetCacheableChild() const
Returns the best choice for a Layer object that can be used in RasterCache operations to cache the ch...
const RasterCache * raster_cache
Definition: layer.h:151
ContainerLayer * GetChildContainer() const
Returns the ContainerLayer used to hold all of the children of the MergedContainerLayer. Note that this may not be the best layer to use for caching the children.
bool Draw(const SkPicture &picture, SkCanvas &canvas) const
static AutoPrerollSaveLayerState Create(PrerollContext *preroll_context, bool save_layer_is_active=true, bool layer_itself_performs_readback=false)
Definition: layer.cc:44
const SkRect & paint_bounds() const
Definition: layer.h:227
void Preroll(PrerollContext *context, const SkMatrix &matrix) override
SkCanvas * leaf_nodes_canvas
Definition: layer.h:145
void set_paint_bounds(const SkRect &paint_bounds)
Definition: layer.h:240
void Preroll(PrerollContext *context, const SkMatrix &matrix) override
SkCanvas * internal_nodes_canvas
Definition: layer.h:144
static SkMatrix GetIntegralTransCTM(const SkMatrix &ctm)
Snap the translation components of the matrix to integers.
Definition: raster_cache.h:122
MutatorsStack & mutators_stack
Definition: layer.h:46
static void TryToPrepareRasterCache(PrerollContext *context, Layer *layer, const SkMatrix &matrix)
void PaintChildren(PaintContext &context) const
static AutoSaveLayer Create(const PaintContext &paint_context, const SkRect &bounds, const SkPaint *paint, SaveMode save_mode=SaveMode::kInternalNodesCanvas)
Definition: layer.cc:82