mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Fix Opacity performance regression on Fuchsia (flutter/engine#15573)
* Add more profile markers * Revert FuchsiaSystemCompistedLayer changes * Re-add opacity w/o elevation changes * Fix formatting
This commit is contained in:
parent
8ca3dd95d8
commit
ec3aedb2f2
@ -48,10 +48,6 @@ FILE: ../../../flutter/flow/layers/color_filter_layer_unittests.cc
|
||||
FILE: ../../../flutter/flow/layers/container_layer.cc
|
||||
FILE: ../../../flutter/flow/layers/container_layer.h
|
||||
FILE: ../../../flutter/flow/layers/container_layer_unittests.cc
|
||||
FILE: ../../../flutter/flow/layers/elevated_container_layer.cc
|
||||
FILE: ../../../flutter/flow/layers/elevated_container_layer.h
|
||||
FILE: ../../../flutter/flow/layers/fuchsia_system_composited_layer.cc
|
||||
FILE: ../../../flutter/flow/layers/fuchsia_system_composited_layer.h
|
||||
FILE: ../../../flutter/flow/layers/image_filter_layer.cc
|
||||
FILE: ../../../flutter/flow/layers/image_filter_layer.h
|
||||
FILE: ../../../flutter/flow/layers/image_filter_layer_unittests.cc
|
||||
|
||||
@ -28,8 +28,6 @@ source_set("flow") {
|
||||
"layers/color_filter_layer.h",
|
||||
"layers/container_layer.cc",
|
||||
"layers/container_layer.h",
|
||||
"layers/elevated_container_layer.cc",
|
||||
"layers/elevated_container_layer.h",
|
||||
"layers/image_filter_layer.cc",
|
||||
"layers/image_filter_layer.h",
|
||||
"layers/layer.cc",
|
||||
@ -80,8 +78,6 @@ source_set("flow") {
|
||||
sources += [
|
||||
"layers/child_scene_layer.cc",
|
||||
"layers/child_scene_layer.h",
|
||||
"layers/fuchsia_system_composited_layer.cc",
|
||||
"layers/fuchsia_system_composited_layer.h",
|
||||
"scene_update_context.cc",
|
||||
"scene_update_context.h",
|
||||
"view_holder.cc",
|
||||
|
||||
@ -31,6 +31,7 @@ void ChildSceneLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) {
|
||||
void ChildSceneLayer::Paint(PaintContext& context) const {
|
||||
TRACE_EVENT0("flutter", "ChildSceneLayer::Paint");
|
||||
FML_DCHECK(needs_painting());
|
||||
FML_DCHECK(needs_system_composite());
|
||||
|
||||
// If we are being rendered into our own frame using the system compositor,
|
||||
// then it is neccesary to "punch a hole" in the canvas/frame behind us so
|
||||
@ -42,6 +43,7 @@ void ChildSceneLayer::Paint(PaintContext& context) const {
|
||||
}
|
||||
|
||||
void ChildSceneLayer::UpdateScene(SceneUpdateContext& context) {
|
||||
TRACE_EVENT0("flutter", "ChildSceneLayer::UpdateScene");
|
||||
FML_DCHECK(needs_system_composite());
|
||||
|
||||
auto* view_holder = ViewHolder::FromId(layer_id_);
|
||||
|
||||
@ -18,10 +18,14 @@ ClipPathLayer::ClipPathLayer(const SkPath& clip_path, Clip clip_behavior)
|
||||
}
|
||||
|
||||
void ClipPathLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) {
|
||||
TRACE_EVENT0("flutter", "ClipPathLayer::Preroll");
|
||||
|
||||
SkRect previous_cull_rect = context->cull_rect;
|
||||
SkRect clip_path_bounds = clip_path_.getBounds();
|
||||
children_inside_clip_ = context->cull_rect.intersect(clip_path_bounds);
|
||||
if (children_inside_clip_) {
|
||||
TRACE_EVENT_INSTANT0("flutter", "children inside clip rect");
|
||||
|
||||
Layer::AutoPrerollSaveLayerState save =
|
||||
Layer::AutoPrerollSaveLayerState::Create(context, UsesSaveLayer());
|
||||
context->mutators_stack.PushClipPath(clip_path_);
|
||||
@ -39,6 +43,7 @@ void ClipPathLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) {
|
||||
#if defined(OS_FUCHSIA)
|
||||
|
||||
void ClipPathLayer::UpdateScene(SceneUpdateContext& context) {
|
||||
TRACE_EVENT0("flutter", "ClipPathLayer::UpdateScene");
|
||||
FML_DCHECK(needs_system_composite());
|
||||
|
||||
// TODO(liyuqian): respect clip_behavior_
|
||||
@ -52,8 +57,10 @@ void ClipPathLayer::Paint(PaintContext& context) const {
|
||||
TRACE_EVENT0("flutter", "ClipPathLayer::Paint");
|
||||
FML_DCHECK(needs_painting());
|
||||
|
||||
if (!children_inside_clip_)
|
||||
if (!children_inside_clip_) {
|
||||
TRACE_EVENT_INSTANT0("flutter", "children not inside clip rect, skipping");
|
||||
return;
|
||||
}
|
||||
|
||||
SkAutoCanvasRestore save(context.internal_nodes_canvas, true);
|
||||
context.internal_nodes_canvas->clipPath(clip_path_,
|
||||
|
||||
@ -12,9 +12,13 @@ ClipRectLayer::ClipRectLayer(const SkRect& clip_rect, Clip clip_behavior)
|
||||
}
|
||||
|
||||
void ClipRectLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) {
|
||||
TRACE_EVENT0("flutter", "ClipRectLayer::Preroll");
|
||||
|
||||
SkRect previous_cull_rect = context->cull_rect;
|
||||
children_inside_clip_ = context->cull_rect.intersect(clip_rect_);
|
||||
if (children_inside_clip_) {
|
||||
TRACE_EVENT_INSTANT0("flutter", "children inside clip rect");
|
||||
|
||||
Layer::AutoPrerollSaveLayerState save =
|
||||
Layer::AutoPrerollSaveLayerState::Create(context, UsesSaveLayer());
|
||||
context->mutators_stack.PushClipRect(clip_rect_);
|
||||
@ -32,6 +36,7 @@ void ClipRectLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) {
|
||||
#if defined(OS_FUCHSIA)
|
||||
|
||||
void ClipRectLayer::UpdateScene(SceneUpdateContext& context) {
|
||||
TRACE_EVENT0("flutter", "ClipRectLayer::UpdateScene");
|
||||
FML_DCHECK(needs_system_composite());
|
||||
|
||||
// TODO(liyuqian): respect clip_behavior_
|
||||
@ -45,8 +50,10 @@ void ClipRectLayer::Paint(PaintContext& context) const {
|
||||
TRACE_EVENT0("flutter", "ClipRectLayer::Paint");
|
||||
FML_DCHECK(needs_painting());
|
||||
|
||||
if (!children_inside_clip_)
|
||||
if (!children_inside_clip_) {
|
||||
TRACE_EVENT_INSTANT0("flutter", "children not inside clip rect, skipping");
|
||||
return;
|
||||
}
|
||||
|
||||
SkAutoCanvasRestore save(context.internal_nodes_canvas, true);
|
||||
context.internal_nodes_canvas->clipRect(clip_rect_,
|
||||
|
||||
@ -12,10 +12,14 @@ ClipRRectLayer::ClipRRectLayer(const SkRRect& clip_rrect, Clip clip_behavior)
|
||||
}
|
||||
|
||||
void ClipRRectLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) {
|
||||
TRACE_EVENT0("flutter", "ClipRRectLayer::Preroll");
|
||||
|
||||
SkRect previous_cull_rect = context->cull_rect;
|
||||
SkRect clip_rrect_bounds = clip_rrect_.getBounds();
|
||||
children_inside_clip_ = context->cull_rect.intersect(clip_rrect_bounds);
|
||||
if (children_inside_clip_) {
|
||||
TRACE_EVENT_INSTANT0("flutter", "children inside clip rect");
|
||||
|
||||
Layer::AutoPrerollSaveLayerState save =
|
||||
Layer::AutoPrerollSaveLayerState::Create(context, UsesSaveLayer());
|
||||
context->mutators_stack.PushClipRRect(clip_rrect_);
|
||||
@ -33,6 +37,7 @@ void ClipRRectLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) {
|
||||
#if defined(OS_FUCHSIA)
|
||||
|
||||
void ClipRRectLayer::UpdateScene(SceneUpdateContext& context) {
|
||||
TRACE_EVENT0("flutter", "ClipRRectLayer::UpdateScene");
|
||||
FML_DCHECK(needs_system_composite());
|
||||
|
||||
// TODO(liyuqian): respect clip_behavior_
|
||||
@ -46,8 +51,10 @@ void ClipRRectLayer::Paint(PaintContext& context) const {
|
||||
TRACE_EVENT0("flutter", "ClipRRectLayer::Paint");
|
||||
FML_DCHECK(needs_painting());
|
||||
|
||||
if (!children_inside_clip_)
|
||||
if (!children_inside_clip_) {
|
||||
TRACE_EVENT_INSTANT0("flutter", "children not inside clip rect, skipping");
|
||||
return;
|
||||
}
|
||||
|
||||
SkAutoCanvasRestore save(context.internal_nodes_canvas, true);
|
||||
context.internal_nodes_canvas->clipRRect(clip_rrect_,
|
||||
|
||||
@ -1,49 +0,0 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "flutter/flow/layers/elevated_container_layer.h"
|
||||
|
||||
namespace flutter {
|
||||
namespace {
|
||||
|
||||
float ClampElevation(float elevation,
|
||||
float parent_elevation,
|
||||
float max_elevation) {
|
||||
// TODO(mklim): Deal with bounds overflow more elegantly. We'd like to be
|
||||
// able to have developers specify the behavior here to alternatives besides
|
||||
// clamping, like normalization on some arbitrary curve.
|
||||
float clamped_elevation = elevation;
|
||||
if (max_elevation > -1 && (parent_elevation + elevation) > max_elevation) {
|
||||
// Clamp the local z coordinate at our max bound. Take into account the
|
||||
// parent z position here to fix clamping in cases where the child is
|
||||
// overflowing because of its parents.
|
||||
clamped_elevation = max_elevation - parent_elevation;
|
||||
}
|
||||
|
||||
return clamped_elevation;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
ElevatedContainerLayer::ElevatedContainerLayer(float elevation)
|
||||
: elevation_(elevation), clamped_elevation_(elevation) {}
|
||||
|
||||
void ElevatedContainerLayer::Preroll(PrerollContext* context,
|
||||
const SkMatrix& matrix) {
|
||||
TRACE_EVENT0("flutter", "ElevatedContainerLayer::Preroll");
|
||||
|
||||
// Track total elevation as we walk the tree, in order to deal with bounds
|
||||
// overflow in z.
|
||||
parent_elevation_ = context->total_elevation;
|
||||
clamped_elevation_ = ClampElevation(elevation_, parent_elevation_,
|
||||
context->frame_physical_depth);
|
||||
context->total_elevation += clamped_elevation_;
|
||||
|
||||
ContainerLayer::Preroll(context, matrix);
|
||||
|
||||
// Restore the elevation for our parent.
|
||||
context->total_elevation = parent_elevation_;
|
||||
}
|
||||
|
||||
} // namespace flutter
|
||||
@ -1,34 +0,0 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef FLUTTER_FLOW_LAYERS_ELEVATED_CONTAINER_LAYER_H_
|
||||
#define FLUTTER_FLOW_LAYERS_ELEVATED_CONTAINER_LAYER_H_
|
||||
|
||||
#include "flutter/flow/layers/container_layer.h"
|
||||
|
||||
namespace flutter {
|
||||
|
||||
class ElevatedContainerLayer : public ContainerLayer {
|
||||
public:
|
||||
ElevatedContainerLayer(float elevation);
|
||||
~ElevatedContainerLayer() override = default;
|
||||
|
||||
void Preroll(PrerollContext* context, const SkMatrix& matrix) override;
|
||||
|
||||
float elevation() const { return clamped_elevation_; }
|
||||
float total_elevation() const {
|
||||
return parent_elevation_ + clamped_elevation_;
|
||||
}
|
||||
|
||||
private:
|
||||
float parent_elevation_ = 0.0f;
|
||||
float elevation_ = 0.0f;
|
||||
float clamped_elevation_ = 0.0f;
|
||||
|
||||
FML_DISALLOW_COPY_AND_ASSIGN(ElevatedContainerLayer);
|
||||
};
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
#endif // FLUTTER_FLOW_LAYERS_ELEVATED_CONTAINER_LAYER_H_
|
||||
@ -1,55 +0,0 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "flutter/flow/layers/fuchsia_system_composited_layer.h"
|
||||
|
||||
namespace flutter {
|
||||
|
||||
FuchsiaSystemCompositedLayer::FuchsiaSystemCompositedLayer(SkColor color,
|
||||
SkAlpha opacity,
|
||||
float elevation)
|
||||
: ElevatedContainerLayer(elevation), color_(color), opacity_(opacity) {}
|
||||
|
||||
void FuchsiaSystemCompositedLayer::Preroll(PrerollContext* context,
|
||||
const SkMatrix& matrix) {
|
||||
TRACE_EVENT0("flutter", "FuchsiaSystemCompositedLayer::Preroll");
|
||||
|
||||
const float parent_is_opaque = context->is_opaque;
|
||||
context->mutators_stack.PushOpacity(opacity_);
|
||||
context->is_opaque = parent_is_opaque && (opacity_ == SK_AlphaOPAQUE);
|
||||
ElevatedContainerLayer::Preroll(context, matrix);
|
||||
context->is_opaque = parent_is_opaque;
|
||||
context->mutators_stack.Pop();
|
||||
}
|
||||
|
||||
void FuchsiaSystemCompositedLayer::UpdateScene(SceneUpdateContext& context) {
|
||||
FML_DCHECK(needs_system_composite());
|
||||
|
||||
// Retained rendering: speedup by reusing a retained entity node if
|
||||
// possible. When an entity node is reused, no paint layer is added to the
|
||||
// frame so we won't call Paint.
|
||||
LayerRasterCacheKey key(unique_id(), context.Matrix());
|
||||
if (context.HasRetainedNode(key)) {
|
||||
TRACE_EVENT_INSTANT0("flutter", "retained layer cache hit");
|
||||
const scenic::EntityNode& retained_node = context.GetRetainedNode(key);
|
||||
FML_DCHECK(context.top_entity());
|
||||
FML_DCHECK(retained_node.session() == context.session());
|
||||
context.top_entity()->embedder_node().AddChild(retained_node);
|
||||
return;
|
||||
}
|
||||
|
||||
TRACE_EVENT_INSTANT0("flutter", "retained cache miss, creating");
|
||||
// If we can't find an existing retained surface, create one.
|
||||
SceneUpdateContext::Frame frame(context, rrect_, color_, opacity_ / 255.0f,
|
||||
elevation(), this);
|
||||
for (auto& layer : layers()) {
|
||||
if (layer->needs_painting()) {
|
||||
frame.AddPaintLayer(layer.get());
|
||||
}
|
||||
}
|
||||
|
||||
ElevatedContainerLayer::UpdateScene(context);
|
||||
}
|
||||
|
||||
} // namespace flutter
|
||||
@ -1,37 +0,0 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef FLUTTER_FLOW_LAYERS_FUCHSIA_SYSTEM_COMPOSITED_LAYER_H_
|
||||
#define FLUTTER_FLOW_LAYERS_FUCHSIA_SYSTEM_COMPOSITED_LAYER_H_
|
||||
|
||||
#include "flutter/flow/layers/elevated_container_layer.h"
|
||||
#include "flutter/flow/scene_update_context.h"
|
||||
|
||||
namespace flutter {
|
||||
|
||||
class FuchsiaSystemCompositedLayer : public ElevatedContainerLayer {
|
||||
public:
|
||||
static bool can_system_composite() { return true; }
|
||||
|
||||
FuchsiaSystemCompositedLayer(SkColor color, SkAlpha opacity, float elevation);
|
||||
|
||||
void Preroll(PrerollContext* context, const SkMatrix& matrix) override;
|
||||
void UpdateScene(SceneUpdateContext& context) override;
|
||||
|
||||
void set_dimensions(SkRRect rrect) { rrect_ = rrect; }
|
||||
|
||||
SkColor color() const { return color_; }
|
||||
SkAlpha opacity() const { return opacity_; }
|
||||
|
||||
private:
|
||||
SkRRect rrect_ = SkRRect::MakeEmpty();
|
||||
SkColor color_ = SK_ColorTRANSPARENT;
|
||||
SkAlpha opacity_ = SK_AlphaOPAQUE;
|
||||
|
||||
FML_DISALLOW_COPY_AND_ASSIGN(FuchsiaSystemCompositedLayer);
|
||||
};
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
#endif // FLUTTER_FLOW_LAYERS_FUCHSIA_SYSTEM_COMPOSITED_LAYER_H_
|
||||
@ -83,7 +83,7 @@ void LayerTree::UpdateScene(SceneUpdateContext& context,
|
||||
context,
|
||||
SkRRect::MakeRect(
|
||||
SkRect::MakeWH(frame_size_.width(), frame_size_.height())),
|
||||
SK_ColorTRANSPARENT);
|
||||
SK_ColorTRANSPARENT, SK_AlphaOPAQUE);
|
||||
if (root_layer_->needs_system_composite()) {
|
||||
root_layer_->UpdateScene(context);
|
||||
}
|
||||
|
||||
@ -14,6 +14,7 @@
|
||||
#include "flutter/fml/macros.h"
|
||||
#include "flutter/fml/time/time_delta.h"
|
||||
#include "third_party/skia/include/core/SkPicture.h"
|
||||
#include "third_party/skia/include/core/SkSize.h"
|
||||
|
||||
namespace flutter {
|
||||
|
||||
|
||||
@ -14,24 +14,8 @@ namespace flutter {
|
||||
// this.
|
||||
constexpr float kOpacityElevationWhenUsingSystemCompositor = 0.01f;
|
||||
|
||||
#if !defined(OS_FUCHSIA)
|
||||
void OpacityLayerBase::Preroll(PrerollContext* context,
|
||||
const SkMatrix& matrix) {
|
||||
const float parent_is_opaque = context->is_opaque;
|
||||
|
||||
context->mutators_stack.PushOpacity(opacity_);
|
||||
context->is_opaque = parent_is_opaque && (opacity_ == SK_AlphaOPAQUE);
|
||||
ContainerLayer::Preroll(context, matrix);
|
||||
context->is_opaque = parent_is_opaque;
|
||||
context->mutators_stack.Pop();
|
||||
}
|
||||
#endif
|
||||
|
||||
OpacityLayer::OpacityLayer(SkAlpha opacity, const SkPoint& offset)
|
||||
: OpacityLayerBase(SK_ColorTRANSPARENT,
|
||||
opacity,
|
||||
kOpacityElevationWhenUsingSystemCompositor),
|
||||
offset_(offset) {
|
||||
OpacityLayer::OpacityLayer(SkAlpha alpha, const SkPoint& offset)
|
||||
: alpha_(alpha), offset_(offset) {
|
||||
// Ensure OpacityLayer has only one direct child.
|
||||
//
|
||||
// This is needed to ensure that retained rendering can always be applied to
|
||||
@ -52,25 +36,35 @@ void OpacityLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) {
|
||||
ContainerLayer* container = GetChildContainer();
|
||||
FML_DCHECK(!container->layers().empty()); // OpacityLayer can't be a leaf.
|
||||
|
||||
// Factor in the offset during Preroll. |OpacityLayerBase| will handle the
|
||||
// opacity.
|
||||
const bool parent_is_opaque = context->is_opaque;
|
||||
SkMatrix child_matrix = matrix;
|
||||
child_matrix.postTranslate(offset_.fX, offset_.fY);
|
||||
|
||||
total_elevation_ = context->total_elevation;
|
||||
context->total_elevation += kOpacityElevationWhenUsingSystemCompositor;
|
||||
context->is_opaque = parent_is_opaque && (alpha_ == SK_AlphaOPAQUE);
|
||||
context->mutators_stack.PushTransform(
|
||||
SkMatrix::MakeTrans(offset_.fX, offset_.fY));
|
||||
context->mutators_stack.PushOpacity(alpha_);
|
||||
Layer::AutoPrerollSaveLayerState save =
|
||||
Layer::AutoPrerollSaveLayerState::Create(context);
|
||||
OpacityLayerBase::Preroll(context, child_matrix);
|
||||
ContainerLayer::Preroll(context, child_matrix);
|
||||
context->mutators_stack.Pop();
|
||||
context->mutators_stack.Pop();
|
||||
context->is_opaque = parent_is_opaque;
|
||||
context->total_elevation = total_elevation_;
|
||||
|
||||
// When using the system compositor, do not include the offset since we are
|
||||
// rendering as a separate piece of geometry and the offset will be baked into
|
||||
// that geometry's transform.
|
||||
if (OpacityLayerBase::can_system_composite() && needs_system_composite()) {
|
||||
set_dimensions(SkRRect::MakeRect(paint_bounds()));
|
||||
} else {
|
||||
#if defined(OS_FUCHSIA)
|
||||
if (needs_system_composite()) {
|
||||
// When using the system compositor, do not include the offset since we
|
||||
// are rendering as a separate piece of geometry and the offset will be
|
||||
// baked into that geometry's transform.
|
||||
frameRRect_ = SkRRect::MakeRect(paint_bounds());
|
||||
set_paint_bounds(SkRect::MakeEmpty());
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
set_paint_bounds(paint_bounds().makeOffset(offset_.fX, offset_.fY));
|
||||
|
||||
if (!context->has_platform_view && context->raster_cache &&
|
||||
SkRect::Intersects(context->cull_rect, paint_bounds())) {
|
||||
SkMatrix ctm = child_matrix;
|
||||
@ -82,24 +76,12 @@ void OpacityLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) {
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(OS_FUCHSIA)
|
||||
|
||||
void OpacityLayer::UpdateScene(SceneUpdateContext& context) {
|
||||
SceneUpdateContext::Transform transform(
|
||||
context, SkMatrix::MakeTrans(offset_.fX, offset_.fY));
|
||||
|
||||
// OpacityLayerBase will handle applying the opacity itself.
|
||||
OpacityLayerBase::UpdateScene(context);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void OpacityLayer::Paint(PaintContext& context) const {
|
||||
TRACE_EVENT0("flutter", "OpacityLayer::Paint");
|
||||
FML_DCHECK(needs_painting());
|
||||
|
||||
SkPaint paint;
|
||||
paint.setAlpha(opacity());
|
||||
paint.setAlpha(alpha_);
|
||||
|
||||
SkAutoCanvasRestore save(context.internal_nodes_canvas, true);
|
||||
context.internal_nodes_canvas->translate(offset_.fX, offset_.fY);
|
||||
@ -126,7 +108,8 @@ void OpacityLayer::Paint(PaintContext& context) const {
|
||||
// RasterCache::GetIntegralTransCTM optimization.
|
||||
//
|
||||
// Note that the following lines are only accessible when the raster cache is
|
||||
// not available, or when a cache miss occurs.
|
||||
// not available (e.g., when we're using the software backend in golden
|
||||
// tests).
|
||||
SkRect saveLayerBounds;
|
||||
paint_bounds()
|
||||
.makeOffset(-offset_.fX, -offset_.fY)
|
||||
@ -134,9 +117,46 @@ void OpacityLayer::Paint(PaintContext& context) const {
|
||||
|
||||
Layer::AutoSaveLayer save_layer =
|
||||
Layer::AutoSaveLayer::Create(context, saveLayerBounds, &paint);
|
||||
OpacityLayerBase::Paint(context);
|
||||
PaintChildren(context);
|
||||
}
|
||||
|
||||
#if defined(OS_FUCHSIA)
|
||||
|
||||
void OpacityLayer::UpdateScene(SceneUpdateContext& context) {
|
||||
FML_DCHECK(needs_system_composite());
|
||||
TRACE_EVENT0("flutter", "OpacityLayer::UpdateScene");
|
||||
|
||||
ContainerLayer* container = GetChildContainer();
|
||||
FML_DCHECK(!container->layers().empty()); // OpacityLayer can't be a leaf.
|
||||
|
||||
SceneUpdateContext::Transform transform(
|
||||
context, SkMatrix::MakeTrans(offset_.fX, offset_.fY));
|
||||
|
||||
// Retained rendering: speedup by reusing a retained entity node if possible.
|
||||
// When an entity node is reused, no paint layer is added to the frame so we
|
||||
// won't call PhysicalShapeLayer::Paint.
|
||||
LayerRasterCacheKey key(unique_id(), context.Matrix());
|
||||
if (context.HasRetainedNode(key)) {
|
||||
TRACE_EVENT_INSTANT0("flutter", "retained layer cache hit");
|
||||
const scenic::EntityNode& retained_node = context.GetRetainedNode(key);
|
||||
FML_DCHECK(context.top_entity());
|
||||
FML_DCHECK(retained_node.session() == context.session());
|
||||
context.top_entity()->embedder_node().AddChild(retained_node);
|
||||
return;
|
||||
}
|
||||
|
||||
TRACE_EVENT_INSTANT0("flutter", "cache miss, creating");
|
||||
// If we can't find an existing retained surface, create one.
|
||||
SceneUpdateContext::Frame frame(
|
||||
context, frameRRect_, SK_ColorTRANSPARENT, alpha_,
|
||||
kOpacityElevationWhenUsingSystemCompositor, total_elevation_, this);
|
||||
frame.AddPaintLayer(container);
|
||||
|
||||
UpdateSceneChildren(context);
|
||||
}
|
||||
|
||||
#endif // defined(OS_FUCHSIA)
|
||||
|
||||
ContainerLayer* OpacityLayer::GetChildContainer() const {
|
||||
FML_DCHECK(layers().size() == 1);
|
||||
|
||||
|
||||
@ -5,42 +5,15 @@
|
||||
#ifndef FLUTTER_FLOW_LAYERS_OPACITY_LAYER_H_
|
||||
#define FLUTTER_FLOW_LAYERS_OPACITY_LAYER_H_
|
||||
|
||||
#include "flutter/flow/layers/elevated_container_layer.h"
|
||||
#if defined(OS_FUCHSIA)
|
||||
#include "flutter/flow/layers/fuchsia_system_composited_layer.h"
|
||||
#endif
|
||||
#include "flutter/flow/layers/container_layer.h"
|
||||
|
||||
namespace flutter {
|
||||
|
||||
#if !defined(OS_FUCHSIA)
|
||||
class OpacityLayerBase : public ContainerLayer {
|
||||
public:
|
||||
static bool can_system_composite() { return false; }
|
||||
|
||||
OpacityLayerBase(SkColor color, SkAlpha opacity, float elevation)
|
||||
: color_(color), opacity_(opacity) {}
|
||||
|
||||
void Preroll(PrerollContext* context, const SkMatrix& matrix) override;
|
||||
|
||||
void set_dimensions(SkRRect rrect) {}
|
||||
|
||||
SkColor color() const { return color_; }
|
||||
SkAlpha opacity() const { return opacity_; }
|
||||
float elevation() const { return 0; }
|
||||
|
||||
private:
|
||||
SkColor color_;
|
||||
SkAlpha opacity_;
|
||||
};
|
||||
#else
|
||||
using OpacityLayerBase = FuchsiaSystemCompositedLayer;
|
||||
#endif
|
||||
|
||||
// Don't add an OpacityLayer with no children to the layer tree. Painting an
|
||||
// OpacityLayer is very costly due to the saveLayer call. If there's no child,
|
||||
// having the OpacityLayer or not has the same effect. In debug_unopt build,
|
||||
// |Preroll| will assert if there are no children.
|
||||
class OpacityLayer : public OpacityLayerBase {
|
||||
class OpacityLayer : public ContainerLayer {
|
||||
public:
|
||||
// An offset is provided here because OpacityLayer.addToScene method in the
|
||||
// Flutter framework can take an optional offset argument.
|
||||
@ -57,15 +30,20 @@ class OpacityLayer : public OpacityLayerBase {
|
||||
void Add(std::shared_ptr<Layer> layer) override;
|
||||
|
||||
void Preroll(PrerollContext* context, const SkMatrix& matrix) override;
|
||||
|
||||
void Paint(PaintContext& context) const override;
|
||||
|
||||
#if defined(OS_FUCHSIA)
|
||||
void UpdateScene(SceneUpdateContext& context) override;
|
||||
#endif
|
||||
void Paint(PaintContext& context) const override;
|
||||
#endif // defined(OS_FUCHSIA)
|
||||
|
||||
private:
|
||||
ContainerLayer* GetChildContainer() const;
|
||||
|
||||
SkAlpha alpha_;
|
||||
SkPoint offset_;
|
||||
SkRRect frameRRect_;
|
||||
float total_elevation_ = 0.0f;
|
||||
|
||||
FML_DISALLOW_COPY_AND_ASSIGN(OpacityLayer);
|
||||
};
|
||||
|
||||
@ -17,12 +17,9 @@ PhysicalShapeLayer::PhysicalShapeLayer(SkColor color,
|
||||
float elevation,
|
||||
const SkPath& path,
|
||||
Clip clip_behavior)
|
||||
#if !defined(OS_FUCHSIA)
|
||||
: PhysicalShapeLayerBase(color, elevation),
|
||||
#else
|
||||
: PhysicalShapeLayerBase(color, /*opacity=*/1.f, elevation),
|
||||
#endif
|
||||
: color_(color),
|
||||
shadow_color_(shadow_color),
|
||||
elevation_(elevation),
|
||||
path_(path),
|
||||
isRect_(false),
|
||||
clip_behavior_(clip_behavior) {
|
||||
@ -45,35 +42,33 @@ PhysicalShapeLayer::PhysicalShapeLayer(SkColor color,
|
||||
// an SkPath.
|
||||
frameRRect_ = SkRRect::MakeRect(path.getBounds());
|
||||
}
|
||||
|
||||
set_dimensions(frameRRect_);
|
||||
}
|
||||
|
||||
void PhysicalShapeLayer::Preroll(PrerollContext* context,
|
||||
const SkMatrix& matrix) {
|
||||
TRACE_EVENT0("flutter", "PhysicalShapeLayer::Preroll");
|
||||
|
||||
Layer::AutoPrerollSaveLayerState save =
|
||||
Layer::AutoPrerollSaveLayerState::Create(context, UsesSaveLayer());
|
||||
PhysicalShapeLayerBase::Preroll(context, matrix);
|
||||
|
||||
if (elevation() == 0) {
|
||||
context->total_elevation += elevation_;
|
||||
total_elevation_ = context->total_elevation;
|
||||
SkRect child_paint_bounds;
|
||||
PrerollChildren(context, matrix, &child_paint_bounds);
|
||||
context->total_elevation -= elevation_;
|
||||
|
||||
if (elevation_ == 0) {
|
||||
set_paint_bounds(path_.getBounds());
|
||||
} else {
|
||||
if (PhysicalShapeLayerBase::can_system_composite()) {
|
||||
set_needs_system_composite(true);
|
||||
return;
|
||||
}
|
||||
//#if defined(OS_FUCHSIA)
|
||||
// // Let the system compositor draw all shadows for us.
|
||||
// set_needs_system_composite(true);
|
||||
//#else
|
||||
#if defined(OS_FUCHSIA)
|
||||
// Let the system compositor draw all shadows for us.
|
||||
set_needs_system_composite(true);
|
||||
#else
|
||||
// We will draw the shadow in Paint(), so add some margin to the paint
|
||||
// bounds to leave space for the shadow. We fill this whole region and clip
|
||||
// children to it so we don't need to join the child paint bounds.
|
||||
set_paint_bounds(ComputeShadowBounds(path_.getBounds(), elevation(),
|
||||
set_paint_bounds(ComputeShadowBounds(path_.getBounds(), elevation_,
|
||||
context->frame_device_pixel_ratio));
|
||||
//#endif // defined(OS_FUCHSIA)
|
||||
#endif // defined(OS_FUCHSIA)
|
||||
}
|
||||
}
|
||||
|
||||
@ -98,9 +93,8 @@ void PhysicalShapeLayer::UpdateScene(SceneUpdateContext& context) {
|
||||
|
||||
TRACE_EVENT_INSTANT0("flutter", "cache miss, creating");
|
||||
// If we can't find an existing retained surface, create one.
|
||||
SceneUpdateContext::Frame frame(context, frameRRect_, color(), opacity(),
|
||||
elevation(), this);
|
||||
|
||||
SceneUpdateContext::Frame frame(context, frameRRect_, color_, SK_AlphaOPAQUE,
|
||||
elevation_, total_elevation_, this);
|
||||
for (auto& layer : layers()) {
|
||||
if (layer->needs_painting()) {
|
||||
frame.AddPaintLayer(layer.get());
|
||||
@ -116,14 +110,14 @@ void PhysicalShapeLayer::Paint(PaintContext& context) const {
|
||||
TRACE_EVENT0("flutter", "PhysicalShapeLayer::Paint");
|
||||
FML_DCHECK(needs_painting());
|
||||
|
||||
if (elevation() != 0) {
|
||||
DrawShadow(context.leaf_nodes_canvas, path_, shadow_color_, elevation(),
|
||||
SkColorGetA(color()) != 0xff, context.frame_device_pixel_ratio);
|
||||
if (elevation_ != 0) {
|
||||
DrawShadow(context.leaf_nodes_canvas, path_, shadow_color_, elevation_,
|
||||
SkColorGetA(color_) != 0xff, context.frame_device_pixel_ratio);
|
||||
}
|
||||
|
||||
// Call drawPath without clip if possible for better performance.
|
||||
SkPaint paint;
|
||||
paint.setColor(color());
|
||||
paint.setColor(color_);
|
||||
paint.setAntiAlias(true);
|
||||
if (clip_behavior_ != Clip::antiAliasWithSaveLayer) {
|
||||
context.leaf_nodes_canvas->drawPath(path_, paint);
|
||||
|
||||
@ -5,33 +5,18 @@
|
||||
#ifndef FLUTTER_FLOW_LAYERS_PHYSICAL_SHAPE_LAYER_H_
|
||||
#define FLUTTER_FLOW_LAYERS_PHYSICAL_SHAPE_LAYER_H_
|
||||
|
||||
#include "flutter/flow/layers/elevated_container_layer.h"
|
||||
#if defined(OS_FUCHSIA)
|
||||
#include "flutter/flow/layers/fuchsia_system_composited_layer.h"
|
||||
#endif
|
||||
#include "flutter/flow/layers/container_layer.h"
|
||||
|
||||
namespace flutter {
|
||||
|
||||
#if !defined(OS_FUCHSIA)
|
||||
class PhysicalShapeLayerBase : public ElevatedContainerLayer {
|
||||
class PhysicalShapeLayer : public ContainerLayer {
|
||||
public:
|
||||
static bool can_system_composite() { return false; }
|
||||
PhysicalShapeLayer(SkColor color,
|
||||
SkColor shadow_color,
|
||||
float elevation,
|
||||
const SkPath& path,
|
||||
Clip clip_behavior);
|
||||
|
||||
PhysicalShapeLayerBase(SkColor color, float elevation)
|
||||
: ElevatedContainerLayer(elevation), color_(color) {}
|
||||
|
||||
void set_dimensions(SkRRect rrect) {}
|
||||
SkColor color() const { return color_; }
|
||||
|
||||
private:
|
||||
SkColor color_;
|
||||
};
|
||||
#else
|
||||
using PhysicalShapeLayerBase = FuchsiaSystemCompositedLayer;
|
||||
#endif
|
||||
|
||||
class PhysicalShapeLayer : public PhysicalShapeLayerBase {
|
||||
public:
|
||||
static SkRect ComputeShadowBounds(const SkRect& bounds,
|
||||
float elevation,
|
||||
float pixel_ratio);
|
||||
@ -42,13 +27,8 @@ class PhysicalShapeLayer : public PhysicalShapeLayerBase {
|
||||
bool transparentOccluder,
|
||||
SkScalar dpr);
|
||||
|
||||
PhysicalShapeLayer(SkColor color,
|
||||
SkColor shadow_color,
|
||||
float elevation,
|
||||
const SkPath& path,
|
||||
Clip clip_behavior);
|
||||
|
||||
void Preroll(PrerollContext* context, const SkMatrix& matrix) override;
|
||||
|
||||
void Paint(PaintContext& context) const override;
|
||||
|
||||
bool UsesSaveLayer() const {
|
||||
@ -59,8 +39,13 @@ class PhysicalShapeLayer : public PhysicalShapeLayerBase {
|
||||
void UpdateScene(SceneUpdateContext& context) override;
|
||||
#endif // defined(OS_FUCHSIA)
|
||||
|
||||
float total_elevation() const { return total_elevation_; }
|
||||
|
||||
private:
|
||||
SkColor color_;
|
||||
SkColor shadow_color_;
|
||||
float elevation_ = 0.0f;
|
||||
float total_elevation_ = 0.0f;
|
||||
SkPath path_;
|
||||
bool isRect_;
|
||||
SkRRect frameRRect_;
|
||||
|
||||
@ -18,9 +18,12 @@ PictureLayer::PictureLayer(const SkPoint& offset,
|
||||
will_change_(will_change) {}
|
||||
|
||||
void PictureLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) {
|
||||
TRACE_EVENT0("flutter", "PictureLayer::Preroll");
|
||||
SkPicture* sk_picture = picture();
|
||||
|
||||
if (auto* cache = context->raster_cache) {
|
||||
TRACE_EVENT0("flutter", "PictureLayer::RasterCache (Preroll)");
|
||||
|
||||
SkMatrix ctm = matrix;
|
||||
ctm.postTranslate(offset_.x(), offset_.y());
|
||||
#ifndef SUPPORT_FRACTIONAL_TRANSLATION
|
||||
@ -50,6 +53,8 @@ void PictureLayer::Paint(PaintContext& context) const {
|
||||
const SkMatrix& ctm = context.leaf_nodes_canvas->getTotalMatrix();
|
||||
RasterCacheResult result = context.raster_cache->Get(*picture(), ctm);
|
||||
if (result.is_valid()) {
|
||||
TRACE_EVENT_INSTANT0("flutter", "raster cache hit");
|
||||
|
||||
result.draw(*context.leaf_nodes_canvas);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -15,14 +15,19 @@ TextureLayer::TextureLayer(const SkPoint& offset,
|
||||
: offset_(offset), size_(size), texture_id_(texture_id), freeze_(freeze) {}
|
||||
|
||||
void TextureLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) {
|
||||
TRACE_EVENT0("flutter", "TextureLayer::Preroll");
|
||||
|
||||
set_paint_bounds(SkRect::MakeXYWH(offset_.x(), offset_.y(), size_.width(),
|
||||
size_.height()));
|
||||
}
|
||||
|
||||
void TextureLayer::Paint(PaintContext& context) const {
|
||||
TRACE_EVENT0("flutter", "TextureLayer::Paint");
|
||||
|
||||
std::shared_ptr<Texture> texture =
|
||||
context.texture_registry.GetTexture(texture_id_);
|
||||
if (!texture) {
|
||||
TRACE_EVENT_INSTANT0("flutter", "null texture");
|
||||
return;
|
||||
}
|
||||
texture->Paint(*context.leaf_nodes_canvas, paint_bounds(), freeze_,
|
||||
|
||||
@ -25,6 +25,8 @@ TransformLayer::TransformLayer(const SkMatrix& transform)
|
||||
}
|
||||
|
||||
void TransformLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) {
|
||||
TRACE_EVENT0("flutter", "TransformLayer::Preroll");
|
||||
|
||||
SkMatrix child_matrix;
|
||||
child_matrix.setConcat(matrix, transform_);
|
||||
context->mutators_stack.PushTransform(transform_);
|
||||
@ -51,6 +53,7 @@ void TransformLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) {
|
||||
#if defined(OS_FUCHSIA)
|
||||
|
||||
void TransformLayer::UpdateScene(SceneUpdateContext& context) {
|
||||
TRACE_EVENT0("flutter", "TransformLayer::UpdateScene");
|
||||
FML_DCHECK(needs_system_composite());
|
||||
|
||||
SceneUpdateContext::Transform transform(context, transform_);
|
||||
|
||||
@ -57,30 +57,21 @@ SceneUpdateContext::SceneUpdateContext(scenic::Session* session,
|
||||
}
|
||||
|
||||
void SceneUpdateContext::CreateFrame(scenic::EntityNode entity_node,
|
||||
scenic::ShapeNode shape_node,
|
||||
const SkRRect& rrect,
|
||||
SkColor color,
|
||||
float opacity,
|
||||
SkAlpha opacity,
|
||||
const SkRect& paint_bounds,
|
||||
std::vector<Layer*> paint_layers,
|
||||
Layer* layer) {
|
||||
// We don't need a shape if the frame is zero size.
|
||||
if (rrect.isEmpty())
|
||||
return;
|
||||
FML_DCHECK(!rrect.isEmpty());
|
||||
|
||||
SetEntityNodeClipPlanes(entity_node, rrect.getBounds());
|
||||
// Frames always clip their children.
|
||||
SkRect shape_bounds = rrect.getBounds();
|
||||
SetEntityNodeClipPlanes(entity_node, shape_bounds);
|
||||
|
||||
// isEmpty should account for this, but we are adding these experimental
|
||||
// checks to validate if this is the root cause for b/144933519.
|
||||
if (std::isnan(rrect.width()) || std::isnan(rrect.height())) {
|
||||
FML_LOG(ERROR) << "Invalid RoundedRectangle";
|
||||
return;
|
||||
}
|
||||
|
||||
// Add a part which represents the frame's geometry for clipping purposes
|
||||
// and possibly for its texture.
|
||||
// TODO(SCN-137): Need to be able to express the radii as vectors.
|
||||
SkRect shape_bounds = rrect.getBounds();
|
||||
scenic::ShapeNode shape_node(session());
|
||||
scenic::RoundedRectangle shape(
|
||||
session_, // session
|
||||
rrect.width(), // width
|
||||
@ -99,48 +90,57 @@ void SceneUpdateContext::CreateFrame(scenic::EntityNode entity_node,
|
||||
if (paint_bounds.isEmpty() || !paint_bounds.intersects(shape_bounds))
|
||||
paint_layers.clear();
|
||||
|
||||
scenic::Material material(session());
|
||||
shape_node.SetMaterial(material);
|
||||
entity_node.AddChild(shape_node);
|
||||
|
||||
// Check whether a solid color will suffice.
|
||||
if (paint_layers.empty()) {
|
||||
scenic::Material material(session_);
|
||||
SetMaterialColor(material, color, opacity);
|
||||
shape_node.SetMaterial(material);
|
||||
return;
|
||||
} else {
|
||||
// Apply current metrics and transformation scale factors.
|
||||
const float scale_x = ScaleX();
|
||||
const float scale_y = ScaleY();
|
||||
|
||||
// Apply a texture to the whole shape.
|
||||
SetMaterialTextureAndColor(material, color, opacity, scale_x, scale_y,
|
||||
shape_bounds, std::move(paint_layers), layer,
|
||||
std::move(entity_node));
|
||||
}
|
||||
}
|
||||
|
||||
// Apply current metrics and transformation scale factors.
|
||||
const float scale_x = ScaleX();
|
||||
const float scale_y = ScaleY();
|
||||
|
||||
void SceneUpdateContext::SetMaterialTextureAndColor(
|
||||
scenic::Material& material,
|
||||
SkColor color,
|
||||
SkAlpha opacity,
|
||||
SkScalar scale_x,
|
||||
SkScalar scale_y,
|
||||
const SkRect& paint_bounds,
|
||||
std::vector<Layer*> paint_layers,
|
||||
Layer* layer,
|
||||
scenic::EntityNode entity_node) {
|
||||
scenic::Image* image = GenerateImageIfNeeded(
|
||||
color, scale_x, scale_y, shape_bounds, std::move(paint_layers), layer,
|
||||
color, scale_x, scale_y, paint_bounds, std::move(paint_layers), layer,
|
||||
std::move(entity_node));
|
||||
if (image != nullptr) {
|
||||
scenic::Material material(session_);
|
||||
|
||||
if (image != nullptr) {
|
||||
// The final shape's color is material_color * texture_color. The passed in
|
||||
// material color was already used as a background when generating the
|
||||
// texture, so set the model color to |SK_ColorWHITE| in order to allow
|
||||
// using the texture's color unmodified.
|
||||
SetMaterialColor(material, SK_ColorWHITE, opacity);
|
||||
material.SetTexture(*image);
|
||||
shape_node.SetMaterial(material);
|
||||
return;
|
||||
}
|
||||
|
||||
// No texture was needed, so apply a solid color to the whole shape.
|
||||
if (SkColorGetA(color) != 0 && opacity != 0.0f) {
|
||||
scenic::Material material(session_);
|
||||
|
||||
} else {
|
||||
// No texture was needed, so apply a solid color to the whole shape.
|
||||
SetMaterialColor(material, color, opacity);
|
||||
shape_node.SetMaterial(material);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void SceneUpdateContext::SetMaterialColor(scenic::Material& material,
|
||||
SkColor color,
|
||||
float opacity) {
|
||||
const SkAlpha color_alpha = (SkAlpha)(SkColorGetA(color) * opacity);
|
||||
SkAlpha opacity) {
|
||||
const SkAlpha color_alpha = static_cast<SkAlpha>(
|
||||
((float)SkColorGetA(color) * (float)opacity) / 255.0f);
|
||||
material.SetColor(SkColorGetR(color), SkColorGetG(color), SkColorGetB(color),
|
||||
color_alpha);
|
||||
}
|
||||
@ -231,7 +231,6 @@ SceneUpdateContext::Entity::Entity(SceneUpdateContext& context)
|
||||
entity_node_(context.session()) {
|
||||
if (previous_entity_)
|
||||
previous_entity_->embedder_node().AddChild(entity_node_);
|
||||
|
||||
context.top_entity_ = this;
|
||||
}
|
||||
|
||||
@ -290,37 +289,54 @@ SceneUpdateContext::Transform::~Transform() {
|
||||
context().top_scale_y_ = previous_scale_y_;
|
||||
}
|
||||
|
||||
SceneUpdateContext::Clip::Clip(SceneUpdateContext& context,
|
||||
const SkRect& shape_bounds)
|
||||
: Entity(context) {
|
||||
SetEntityNodeClipPlanes(entity_node(), shape_bounds);
|
||||
}
|
||||
|
||||
SceneUpdateContext::Frame::Frame(SceneUpdateContext& context,
|
||||
const SkRRect& rrect,
|
||||
SkColor color,
|
||||
float opacity,
|
||||
float elevation,
|
||||
SkAlpha opacity,
|
||||
float local_elevation,
|
||||
float world_elevation,
|
||||
Layer* layer)
|
||||
: Entity(context),
|
||||
opacity_node_(context.session()),
|
||||
shape_node_(context.session()),
|
||||
layer_(layer),
|
||||
rrect_(rrect),
|
||||
paint_bounds_(SkRect::MakeEmpty()),
|
||||
color_(color),
|
||||
opacity_(opacity) {
|
||||
entity_node().SetTranslation(0.f, 0.f, -elevation);
|
||||
opacity_(opacity),
|
||||
opacity_node_(context.session()),
|
||||
paint_bounds_(SkRect::MakeEmpty()),
|
||||
layer_(layer) {
|
||||
const float depth = context.frame_physical_depth();
|
||||
if (depth > -1 && world_elevation > depth) {
|
||||
// TODO(mklim): Deal with bounds overflow more elegantly. We'd like to be
|
||||
// able to have developers specify the behavior here to alternatives besides
|
||||
// clamping, like normalization on some arbitrary curve.
|
||||
|
||||
entity_node().AddChild(shape_node_);
|
||||
// Clamp the local z coordinate at our max bound. Take into account the
|
||||
// parent z position here to fix clamping in cases where the child is
|
||||
// overflowing because of its parents.
|
||||
const float parent_elevation = world_elevation - local_elevation;
|
||||
local_elevation = depth - parent_elevation;
|
||||
}
|
||||
if (local_elevation != 0.0) {
|
||||
entity_node().SetTranslation(0.f, 0.f, -local_elevation);
|
||||
}
|
||||
entity_node().AddChild(opacity_node_);
|
||||
opacity_node_.SetOpacity(opacity_);
|
||||
opacity_node_.SetOpacity(opacity_ / 255.0f);
|
||||
}
|
||||
|
||||
SceneUpdateContext::Frame::~Frame() {
|
||||
context().CreateFrame(std::move(entity_node()), std::move(shape_node_),
|
||||
rrect_, color_, opacity_, paint_bounds_,
|
||||
std::move(paint_layers_), layer_);
|
||||
// We don't need a shape if the frame is zero size.
|
||||
if (rrect_.isEmpty())
|
||||
return;
|
||||
|
||||
// isEmpty should account for this, but we are adding these experimental
|
||||
// checks to validate if this is the root cause for b/144933519.
|
||||
if (std::isnan(rrect_.width()) || std::isnan(rrect_.height())) {
|
||||
FML_LOG(ERROR) << "Invalid RoundedRectangle";
|
||||
return;
|
||||
}
|
||||
|
||||
// Add a part which represents the frame's geometry for clipping purposes
|
||||
context().CreateFrame(std::move(entity_node()), rrect_, color_, opacity_,
|
||||
paint_bounds_, std::move(paint_layers_), layer_);
|
||||
}
|
||||
|
||||
void SceneUpdateContext::Frame::AddPaintLayer(Layer* layer) {
|
||||
@ -329,4 +345,10 @@ void SceneUpdateContext::Frame::AddPaintLayer(Layer* layer) {
|
||||
paint_bounds_.join(layer->paint_bounds());
|
||||
}
|
||||
|
||||
SceneUpdateContext::Clip::Clip(SceneUpdateContext& context,
|
||||
const SkRect& shape_bounds)
|
||||
: Entity(context) {
|
||||
SetEntityNodeClipPlanes(entity_node(), shape_bounds);
|
||||
}
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
@ -89,19 +89,13 @@ class SceneUpdateContext {
|
||||
float scale_x,
|
||||
float scale_y,
|
||||
float scale_z);
|
||||
~Transform() override;
|
||||
virtual ~Transform();
|
||||
|
||||
private:
|
||||
float const previous_scale_x_;
|
||||
float const previous_scale_y_;
|
||||
};
|
||||
|
||||
class Clip : public Entity {
|
||||
public:
|
||||
Clip(SceneUpdateContext& context, const SkRect& shape_bounds);
|
||||
~Clip() override = default;
|
||||
};
|
||||
|
||||
class Frame : public Entity {
|
||||
public:
|
||||
// When layer is not nullptr, the frame is associated with a layer subtree
|
||||
@ -110,25 +104,31 @@ class SceneUpdateContext {
|
||||
Frame(SceneUpdateContext& context,
|
||||
const SkRRect& rrect,
|
||||
SkColor color,
|
||||
float opacity = 1.0f,
|
||||
float elevation = 0.0f,
|
||||
SkAlpha opacity,
|
||||
float local_elevation = 0.0f,
|
||||
float parent_elevation = 0.0f,
|
||||
Layer* layer = nullptr);
|
||||
~Frame() override;
|
||||
virtual ~Frame();
|
||||
|
||||
scenic::ContainerNode& embedder_node() override { return opacity_node_; }
|
||||
|
||||
void AddPaintLayer(Layer* layer);
|
||||
|
||||
private:
|
||||
const SkRRect rrect_;
|
||||
SkColor const color_;
|
||||
SkAlpha const opacity_;
|
||||
|
||||
scenic::OpacityNodeHACK opacity_node_;
|
||||
scenic::ShapeNode shape_node_;
|
||||
|
||||
std::vector<Layer*> paint_layers_;
|
||||
Layer* layer_;
|
||||
|
||||
SkRRect rrect_;
|
||||
SkRect paint_bounds_;
|
||||
SkColor color_;
|
||||
float opacity_;
|
||||
Layer* layer_;
|
||||
};
|
||||
|
||||
class Clip : public Entity {
|
||||
public:
|
||||
Clip(SceneUpdateContext& context, const SkRect& shape_bounds);
|
||||
~Clip() = default;
|
||||
};
|
||||
|
||||
SceneUpdateContext(scenic::Session* session,
|
||||
@ -198,24 +198,24 @@ class SceneUpdateContext {
|
||||
// surface (and thus the entity_node) will be retained for that layer to
|
||||
// improve the performance.
|
||||
void CreateFrame(scenic::EntityNode entity_node,
|
||||
scenic::ShapeNode shape_node,
|
||||
const SkRRect& rrect,
|
||||
SkColor color,
|
||||
float opacity,
|
||||
SkAlpha opacity,
|
||||
const SkRect& paint_bounds,
|
||||
std::vector<Layer*> paint_layers,
|
||||
Layer* layer);
|
||||
void SetShapeTextureAndColor(scenic::ShapeNode& shape_node,
|
||||
SkColor color,
|
||||
SkScalar scale_x,
|
||||
SkScalar scale_y,
|
||||
const SkRect& paint_bounds,
|
||||
std::vector<Layer*> paint_layers,
|
||||
Layer* layer,
|
||||
scenic::EntityNode entity_node);
|
||||
void SetMaterialTextureAndColor(scenic::Material& material,
|
||||
SkColor color,
|
||||
SkAlpha opacity,
|
||||
SkScalar scale_x,
|
||||
SkScalar scale_y,
|
||||
const SkRect& paint_bounds,
|
||||
std::vector<Layer*> paint_layers,
|
||||
Layer* layer,
|
||||
scenic::EntityNode entity_node);
|
||||
void SetMaterialColor(scenic::Material& material,
|
||||
SkColor color,
|
||||
float opacity);
|
||||
SkAlpha opacity);
|
||||
scenic::Image* GenerateImageIfNeeded(SkColor color,
|
||||
SkScalar scale_x,
|
||||
SkScalar scale_y,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user