mirror of
https://github.com/encounter/engine.git
synced 2026-03-30 11:09:55 -07:00
Wire up OpacityLayer to Scenic
This commit is contained in:
@@ -20,10 +20,25 @@ ChildSceneLayer::ChildSceneLayer(zx_koid_t layer_id,
|
||||
void ChildSceneLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) {
|
||||
TRACE_EVENT0("flutter", "ChildSceneLayer::Preroll");
|
||||
set_needs_system_composite(true);
|
||||
|
||||
// An alpha "hole punch" is required if the frame behind us is not opaque.
|
||||
if (!context->is_opaque) {
|
||||
set_paint_bounds(
|
||||
SkRect::MakeXYWH(offset_.fX, offset_.fY, size_.fWidth, size_.fHeight));
|
||||
}
|
||||
}
|
||||
|
||||
void ChildSceneLayer::Paint(PaintContext& context) const {
|
||||
FML_NOTREACHED() << "This layer never needs painting.";
|
||||
TRACE_EVENT0("flutter", "ChildSceneLayer::Paint");
|
||||
FML_DCHECK(needs_painting());
|
||||
|
||||
// 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
|
||||
// that group opacity looks correct.
|
||||
SkPaint paint;
|
||||
paint.setColor(SK_ColorTRANSPARENT);
|
||||
paint.setBlendMode(SkBlendMode::kSrc);
|
||||
context.leaf_nodes_canvas->drawRect(paint_bounds(), paint);
|
||||
}
|
||||
|
||||
void ChildSceneLayer::UpdateScene(SceneUpdateContext& context) {
|
||||
|
||||
@@ -7,8 +7,21 @@
|
||||
namespace flutter {
|
||||
|
||||
FuchsiaSystemCompositedLayer::FuchsiaSystemCompositedLayer(SkColor color,
|
||||
SkAlpha opacity,
|
||||
float elevation)
|
||||
: ElevatedContainerLayer(elevation), color_(color) {}
|
||||
: 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());
|
||||
@@ -28,14 +41,15 @@ void FuchsiaSystemCompositedLayer::UpdateScene(SceneUpdateContext& context) {
|
||||
|
||||
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_, elevation(), this);
|
||||
SceneUpdateContext::Frame frame(context, rrect_, color_, opacity_ / 255.0f,
|
||||
elevation(), this);
|
||||
for (auto& layer : layers()) {
|
||||
if (layer->needs_painting()) {
|
||||
frame.AddPaintLayer(layer.get());
|
||||
}
|
||||
}
|
||||
|
||||
ContainerLayer::UpdateScene(context);
|
||||
ElevatedContainerLayer::UpdateScene(context);
|
||||
}
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
@@ -14,17 +14,20 @@ class FuchsiaSystemCompositedLayer : public ElevatedContainerLayer {
|
||||
public:
|
||||
static bool can_system_composite() { return true; }
|
||||
|
||||
FuchsiaSystemCompositedLayer(SkColor color, float elevation);
|
||||
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);
|
||||
};
|
||||
|
||||
+3
-2
@@ -60,10 +60,11 @@ struct PrerollContext {
|
||||
float frame_physical_depth;
|
||||
float frame_device_pixel_ratio;
|
||||
|
||||
// These allow us to track properties like elevation and opacity which stack
|
||||
// with each other during Preroll.
|
||||
// These allow us to track properties like elevation, opacity, and the
|
||||
// prescence of a platform view during Preroll.
|
||||
float total_elevation = 0.0f;
|
||||
bool has_platform_view = false;
|
||||
bool is_opaque = true;
|
||||
};
|
||||
|
||||
// Represents a single composited layer. Created on the UI thread but then
|
||||
|
||||
@@ -9,8 +9,29 @@
|
||||
|
||||
namespace flutter {
|
||||
|
||||
OpacityLayer::OpacityLayer(int alpha, const SkPoint& offset)
|
||||
: alpha_(alpha), offset_(offset) {
|
||||
// The OpacityLayer has no real "elevation", but we want to avoid Z-fighting
|
||||
// when using the system compositor. Choose a small but non-zero value for
|
||||
// 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) {
|
||||
// Ensure OpacityLayer has only one direct child.
|
||||
//
|
||||
// This is needed to ensure that retained rendering can always be applied to
|
||||
@@ -31,32 +52,53 @@ 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.
|
||||
SkMatrix child_matrix = matrix;
|
||||
child_matrix.postTranslate(offset_.fX, offset_.fY);
|
||||
context->mutators_stack.PushTransform(
|
||||
SkMatrix::MakeTrans(offset_.fX, offset_.fY));
|
||||
context->mutators_stack.PushOpacity(alpha_);
|
||||
ContainerLayer::Preroll(context, child_matrix);
|
||||
OpacityLayerBase::Preroll(context, child_matrix);
|
||||
context->mutators_stack.Pop();
|
||||
context->mutators_stack.Pop();
|
||||
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;
|
||||
// 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()) {
|
||||
set_dimensions(SkRRect::MakeRect(paint_bounds()));
|
||||
set_needs_system_composite(true);
|
||||
} else {
|
||||
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;
|
||||
#ifndef SUPPORT_FRACTIONAL_TRANSLATION
|
||||
ctm = RasterCache::GetIntegralTransCTM(ctm);
|
||||
ctm = RasterCache::GetIntegralTransCTM(ctm);
|
||||
#endif
|
||||
context->raster_cache->Prepare(context, container, ctm);
|
||||
context->raster_cache->Prepare(context, container, ctm);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#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(alpha_);
|
||||
paint.setAlpha(opacity());
|
||||
|
||||
SkAutoCanvasRestore save(context.internal_nodes_canvas, true);
|
||||
context.internal_nodes_canvas->translate(offset_.fX, offset_.fY);
|
||||
@@ -83,8 +125,7 @@ void OpacityLayer::Paint(PaintContext& context) const {
|
||||
// RasterCache::GetIntegralTransCTM optimization.
|
||||
//
|
||||
// Note that the following lines are only accessible when the raster cache is
|
||||
// not available (e.g., when we're using the software backend in golden
|
||||
// tests).
|
||||
// not available, or when a cache miss occurs.
|
||||
SkRect saveLayerBounds;
|
||||
paint_bounds()
|
||||
.makeOffset(-offset_.fX, -offset_.fY)
|
||||
@@ -92,7 +133,7 @@ void OpacityLayer::Paint(PaintContext& context) const {
|
||||
|
||||
Layer::AutoSaveLayer save_layer =
|
||||
Layer::AutoSaveLayer::Create(context, saveLayerBounds, &paint);
|
||||
PaintChildren(context);
|
||||
OpacityLayerBase::Paint(context);
|
||||
}
|
||||
|
||||
ContainerLayer* OpacityLayer::GetChildContainer() const {
|
||||
|
||||
@@ -5,15 +5,42 @@
|
||||
#ifndef FLUTTER_FLOW_LAYERS_OPACITY_LAYER_H_
|
||||
#define FLUTTER_FLOW_LAYERS_OPACITY_LAYER_H_
|
||||
|
||||
#include "flutter/flow/layers/container_layer.h"
|
||||
#include "flutter/flow/layers/elevated_container_layer.h"
|
||||
#if defined(OS_FUCHSIA)
|
||||
#include "flutter/flow/layers/fuchsia_system_composited_layer.h"
|
||||
#endif
|
||||
|
||||
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 ContainerLayer {
|
||||
class OpacityLayer : public OpacityLayerBase {
|
||||
public:
|
||||
// An offset is provided here because OpacityLayer.addToScene method in the
|
||||
// Flutter framework can take an optional offset argument.
|
||||
@@ -25,21 +52,19 @@ class OpacityLayer : public ContainerLayer {
|
||||
// the retained rendering inefficient as a small offset change could propagate
|
||||
// to many leaf layers. Therefore we try to capture that offset here to stop
|
||||
// the propagation as repainting the OpacityLayer is expensive.
|
||||
OpacityLayer(int alpha, const SkPoint& offset);
|
||||
OpacityLayer(SkAlpha alpha, const SkPoint& offset);
|
||||
|
||||
void Add(std::shared_ptr<Layer> layer) override;
|
||||
|
||||
void Preroll(PrerollContext* context, const SkMatrix& matrix) override;
|
||||
|
||||
#if defined(OS_FUCHSIA)
|
||||
void UpdateScene(SceneUpdateContext& context) override;
|
||||
#endif
|
||||
void Paint(PaintContext& context) const override;
|
||||
|
||||
// TODO(chinmaygarde): Once SCN-139 is addressed, introduce a new node in the
|
||||
// session scene hierarchy.
|
||||
|
||||
private:
|
||||
ContainerLayer* GetChildContainer() const;
|
||||
|
||||
int alpha_;
|
||||
SkPoint offset_;
|
||||
|
||||
FML_DISALLOW_COPY_AND_ASSIGN(OpacityLayer);
|
||||
|
||||
@@ -17,7 +17,7 @@ PhysicalShapeLayer::PhysicalShapeLayer(SkColor color,
|
||||
float elevation,
|
||||
const SkPath& path,
|
||||
Clip clip_behavior)
|
||||
: PhysicalShapeLayerBase(color, elevation),
|
||||
: PhysicalShapeLayerBase(color, SK_AlphaOPAQUE, elevation),
|
||||
shadow_color_(shadow_color),
|
||||
path_(path),
|
||||
isRect_(false),
|
||||
@@ -58,53 +58,15 @@ void PhysicalShapeLayer::Preroll(PrerollContext* context,
|
||||
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
|
||||
|
||||
// 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(),
|
||||
context->frame_device_pixel_ratio));
|
||||
//#endif // defined(OS_FUCHSIA)
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(OS_FUCHSIA)
|
||||
|
||||
void PhysicalShapeLayer::UpdateScene(SceneUpdateContext& context) {
|
||||
FML_DCHECK(needs_system_composite());
|
||||
TRACE_EVENT0("flutter", "PhysicalShapeLayer::UpdateScene");
|
||||
|
||||
// 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()->entity_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_, color(), elevation(),
|
||||
this);
|
||||
for (auto& layer : layers()) {
|
||||
if (layer->needs_painting()) {
|
||||
frame.AddPaintLayer(layer.get());
|
||||
}
|
||||
}
|
||||
|
||||
UpdateSceneChildren(context);
|
||||
}
|
||||
|
||||
#endif // defined(OS_FUCHSIA)
|
||||
|
||||
void PhysicalShapeLayer::Paint(PaintContext& context) const {
|
||||
TRACE_EVENT0("flutter", "PhysicalShapeLayer::Paint");
|
||||
FML_DCHECK(needs_painting());
|
||||
|
||||
@@ -6,29 +6,24 @@
|
||||
#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
|
||||
|
||||
namespace flutter {
|
||||
|
||||
#if !defined(OS_FUCHSIA)
|
||||
class PhysicalShapeLayerBase : public ElevatedContainerLayer {
|
||||
public:
|
||||
static bool can_system_composite() { return false; }
|
||||
|
||||
PhysicalShapeLayerBase(SkColor color, float elevation)
|
||||
PhysicalShapeLayerBase(SkColor color, SkAlpha opacity, float elevation)
|
||||
: ElevatedContainerLayer(elevation), color_(color) {}
|
||||
|
||||
void set_dimensions(SkRRect rrect) { }
|
||||
void set_dimensions(SkRRect rrect) {}
|
||||
|
||||
SkColor color() const { return color_; }
|
||||
SkAlpha opacity() const { return SK_AlphaOPAQUE; }
|
||||
|
||||
private:
|
||||
SkColor color_;
|
||||
};
|
||||
#else
|
||||
using PhysicalShapeLayerBase = FuchsiaSystemCompositedLayer;
|
||||
#endif
|
||||
|
||||
class PhysicalShapeLayer : public PhysicalShapeLayerBase {
|
||||
public:
|
||||
@@ -42,7 +37,7 @@ class PhysicalShapeLayer : public PhysicalShapeLayerBase {
|
||||
bool transparentOccluder,
|
||||
SkScalar dpr);
|
||||
|
||||
PhysicalShapeLayer(SkColor color,
|
||||
PhysicalShapeLayer(SkColor color,
|
||||
SkColor shadow_color,
|
||||
float elevation,
|
||||
const SkPath& path,
|
||||
@@ -51,10 +46,6 @@ PhysicalShapeLayer(SkColor color,
|
||||
void Preroll(PrerollContext* context, const SkMatrix& matrix) override;
|
||||
void Paint(PaintContext& context) const override;
|
||||
|
||||
#if defined(OS_FUCHSIA)
|
||||
void UpdateScene(SceneUpdateContext& context) override;
|
||||
#endif // defined(OS_FUCHSIA)
|
||||
|
||||
private:
|
||||
SkColor shadow_color_;
|
||||
SkPath path_;
|
||||
|
||||
@@ -124,24 +124,13 @@ TEST_F(PhysicalShapeLayerTest, ElevationSimple) {
|
||||
SK_ColorGREEN, SK_ColorBLACK, initial_elevation, layer_path, Clip::none);
|
||||
|
||||
layer->Preroll(preroll_context(), SkMatrix());
|
||||
// The Fuchsia system compositor handles all elevated PhysicalShapeLayers and
|
||||
// their shadows , so we do not do any painting there.
|
||||
#if defined(OS_FUCHSIA)
|
||||
EXPECT_EQ(layer->paint_bounds(), kEmptyRect);
|
||||
EXPECT_FALSE(layer->needs_painting());
|
||||
EXPECT_TRUE(layer->needs_system_composite());
|
||||
#else
|
||||
EXPECT_EQ(layer->paint_bounds(),
|
||||
PhysicalShapeLayer::ComputeShadowBounds(layer_path.getBounds(),
|
||||
initial_elevation, 1.0f));
|
||||
EXPECT_TRUE(layer->needs_painting());
|
||||
EXPECT_FALSE(layer->needs_system_composite());
|
||||
#endif
|
||||
EXPECT_EQ(layer->total_elevation(), initial_elevation);
|
||||
|
||||
// The Fuchsia system compositor handles all elevated PhysicalShapeLayers and
|
||||
// their shadows , so we do not use the direct |Paint()| path there.
|
||||
#if !defined(OS_FUCHSIA)
|
||||
SkPaint layer_paint;
|
||||
layer_paint.setColor(SK_ColorGREEN);
|
||||
layer_paint.setAntiAlias(true);
|
||||
@@ -152,7 +141,6 @@ TEST_F(PhysicalShapeLayerTest, ElevationSimple) {
|
||||
{MockCanvas::DrawCall{0, MockCanvas::DrawShadowData{layer_path}},
|
||||
MockCanvas::DrawCall{
|
||||
0, MockCanvas::DrawPathData{layer_path, layer_paint}}}));
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST_F(PhysicalShapeLayerTest, ElevationComplex) {
|
||||
@@ -184,27 +172,15 @@ TEST_F(PhysicalShapeLayerTest, ElevationComplex) {
|
||||
|
||||
layers[0]->Preroll(preroll_context(), SkMatrix());
|
||||
for (int i = 0; i < 4; i += 1) {
|
||||
// On Fuchsia, the system compositor handles all elevated
|
||||
// PhysicalShapeLayers and their shadows , so we do not do any painting
|
||||
// there.
|
||||
#if defined(OS_FUCHSIA)
|
||||
EXPECT_EQ(layers[i]->paint_bounds(), kEmptyRect);
|
||||
EXPECT_FALSE(layers[i]->needs_painting());
|
||||
EXPECT_TRUE(layers[i]->needs_system_composite());
|
||||
#else
|
||||
EXPECT_EQ(layers[i]->paint_bounds(),
|
||||
(PhysicalShapeLayer::ComputeShadowBounds(
|
||||
layer_path.getBounds(), initial_elevations[i],
|
||||
1.0f /* pixel_ratio */)));
|
||||
EXPECT_TRUE(layers[i]->needs_painting());
|
||||
EXPECT_FALSE(layers[i]->needs_system_composite());
|
||||
#endif
|
||||
EXPECT_EQ(layers[i]->total_elevation(), total_elevations[i]);
|
||||
}
|
||||
|
||||
// The Fuchsia system compositor handles all elevated PhysicalShapeLayers and
|
||||
// their shadows , so we do not use the direct |Paint()| path there.
|
||||
#if !defined(OS_FUCHSIA)
|
||||
SkPaint layer_paint;
|
||||
layer_paint.setColor(SK_ColorBLACK);
|
||||
layer_paint.setAntiAlias(true);
|
||||
@@ -224,7 +200,6 @@ TEST_F(PhysicalShapeLayerTest, ElevationComplex) {
|
||||
MockCanvas::DrawCall{0, MockCanvas::DrawShadowData{layer_path}},
|
||||
MockCanvas::DrawCall{
|
||||
0, MockCanvas::DrawPathData{layer_path, layer_paint}}}));
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace testing
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "flutter/flow/layers/layer.h"
|
||||
#include "flutter/flow/matrix_decomposition.h"
|
||||
#include "flutter/fml/trace_event.h"
|
||||
#include "include/core/SkColor.h"
|
||||
|
||||
namespace flutter {
|
||||
|
||||
@@ -59,18 +60,16 @@ void SceneUpdateContext::CreateFrame(scenic::EntityNode entity_node,
|
||||
scenic::ShapeNode shape_node,
|
||||
const SkRRect& rrect,
|
||||
SkColor color,
|
||||
float opacity,
|
||||
const SkRect& paint_bounds,
|
||||
std::vector<Layer*> paint_layers,
|
||||
Layer* layer) {
|
||||
// Frames always clip their children.
|
||||
SetEntityNodeClipPlanes(entity_node, rrect.getBounds());
|
||||
// TODO(SCN-1274): SetClip() will be deleted.
|
||||
entity_node.SetClip(0u, true /* clip to self */);
|
||||
|
||||
// We don't need a shape if the frame is zero size.
|
||||
if (rrect.isEmpty())
|
||||
return;
|
||||
|
||||
SetEntityNodeClipPlanes(entity_node, rrect.getBounds());
|
||||
|
||||
// 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())) {
|
||||
@@ -102,7 +101,9 @@ void SceneUpdateContext::CreateFrame(scenic::EntityNode entity_node,
|
||||
|
||||
// Check whether a solid color will suffice.
|
||||
if (paint_layers.empty()) {
|
||||
SetShapeColor(shape_node, color);
|
||||
scenic::Material material(session_);
|
||||
SetMaterialColor(material, color, opacity);
|
||||
shape_node.SetMaterial(material);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -110,43 +111,38 @@ void SceneUpdateContext::CreateFrame(scenic::EntityNode entity_node,
|
||||
const float scale_x = ScaleX();
|
||||
const float scale_y = ScaleY();
|
||||
|
||||
// Apply a texture to the whole shape.
|
||||
SetShapeTextureAndColor(shape_node, color, scale_x, scale_y, shape_bounds,
|
||||
std::move(paint_layers), layer,
|
||||
std::move(entity_node));
|
||||
}
|
||||
|
||||
void SceneUpdateContext::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) {
|
||||
scenic::Image* image = GenerateImageIfNeeded(
|
||||
color, scale_x, scale_y, paint_bounds, std::move(paint_layers), layer,
|
||||
color, scale_x, scale_y, shape_bounds, std::move(paint_layers), layer,
|
||||
std::move(entity_node));
|
||||
if (image != nullptr) {
|
||||
scenic::Material material(session_);
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
SetShapeColor(shape_node, color);
|
||||
// No texture was needed, so apply a solid color to the whole shape.
|
||||
if (SkColorGetA(color) != 0 && opacity != 0.0f) {
|
||||
scenic::Material material(session_);
|
||||
|
||||
SetMaterialColor(material, color, opacity);
|
||||
shape_node.SetMaterial(material);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void SceneUpdateContext::SetShapeColor(scenic::ShapeNode& shape_node,
|
||||
SkColor color) {
|
||||
if (SkColorGetA(color) == 0)
|
||||
return;
|
||||
|
||||
scenic::Material material(session_);
|
||||
void SceneUpdateContext::SetMaterialColor(scenic::Material& material,
|
||||
SkColor color,
|
||||
float opacity) {
|
||||
const SkAlpha color_alpha = (SkAlpha)(SkColorGetA(color) * opacity);
|
||||
material.SetColor(SkColorGetR(color), SkColorGetG(color), SkColorGetB(color),
|
||||
SkColorGetA(color));
|
||||
shape_node.SetMaterial(material);
|
||||
color_alpha);
|
||||
}
|
||||
|
||||
scenic::Image* SceneUpdateContext::GenerateImageIfNeeded(
|
||||
@@ -235,6 +231,7 @@ SceneUpdateContext::Entity::Entity(SceneUpdateContext& context)
|
||||
entity_node_(context.session()) {
|
||||
if (previous_entity_)
|
||||
previous_entity_->embedder_node().AddChild(entity_node_);
|
||||
|
||||
context.top_entity_ = this;
|
||||
}
|
||||
|
||||
@@ -293,28 +290,37 @@ SceneUpdateContext::Transform::~Transform() {
|
||||
context().top_scale_y_ = previous_scale_y_;
|
||||
}
|
||||
|
||||
SceneUpdateContext::Shape::Shape(SceneUpdateContext& context)
|
||||
: Entity(context), shape_node_(context.session()) {
|
||||
entity_node().AddChild(shape_node_);
|
||||
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,
|
||||
Layer* layer)
|
||||
: Shape(context),
|
||||
: Entity(context),
|
||||
opacity_node_(context.session()),
|
||||
shape_node_(context.session()),
|
||||
layer_(layer),
|
||||
rrect_(rrect),
|
||||
color_(color),
|
||||
paint_bounds_(SkRect::MakeEmpty()),
|
||||
layer_(layer) {
|
||||
color_(color),
|
||||
opacity_(opacity) {
|
||||
entity_node().SetTranslation(0.f, 0.f, -elevation);
|
||||
|
||||
entity_node().AddChild(shape_node_);
|
||||
entity_node().AddChild(opacity_node_);
|
||||
opacity_node_.SetOpacity(opacity_);
|
||||
}
|
||||
|
||||
SceneUpdateContext::Frame::~Frame() {
|
||||
context().CreateFrame(std::move(entity_node()), std::move(shape_node()),
|
||||
rrect_, color_, paint_bounds_, std::move(paint_layers_),
|
||||
layer_);
|
||||
context().CreateFrame(std::move(entity_node()), std::move(shape_node_),
|
||||
rrect_, color_, opacity_, paint_bounds_,
|
||||
std::move(paint_layers_), layer_);
|
||||
}
|
||||
|
||||
void SceneUpdateContext::Frame::AddPaintLayer(Layer* layer) {
|
||||
@@ -323,10 +329,4 @@ 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
|
||||
|
||||
+18
-20
@@ -89,25 +89,20 @@ class SceneUpdateContext {
|
||||
float scale_x,
|
||||
float scale_y,
|
||||
float scale_z);
|
||||
virtual ~Transform();
|
||||
~Transform() override;
|
||||
|
||||
private:
|
||||
float const previous_scale_x_;
|
||||
float const previous_scale_y_;
|
||||
};
|
||||
|
||||
class Shape : public Entity {
|
||||
class Clip : public Entity {
|
||||
public:
|
||||
Shape(SceneUpdateContext& context);
|
||||
virtual ~Shape() = default;
|
||||
|
||||
scenic::ShapeNode& shape_node() { return shape_node_; }
|
||||
|
||||
private:
|
||||
scenic::ShapeNode shape_node_;
|
||||
Clip(SceneUpdateContext& context, const SkRect& shape_bounds);
|
||||
~Clip() override = default;
|
||||
};
|
||||
|
||||
class Frame : public Shape {
|
||||
class Frame : public Entity {
|
||||
public:
|
||||
// When layer is not nullptr, the frame is associated with a layer subtree
|
||||
// rooted with that layer. The frame may then create a surface that will be
|
||||
@@ -115,25 +110,25 @@ class SceneUpdateContext {
|
||||
Frame(SceneUpdateContext& context,
|
||||
const SkRRect& rrect,
|
||||
SkColor color,
|
||||
float opacity = 1.0f,
|
||||
float elevation = 0.0f,
|
||||
Layer* layer = nullptr);
|
||||
virtual ~Frame();
|
||||
~Frame() override;
|
||||
|
||||
scenic::ContainerNode& embedder_node() override { return opacity_node_; }
|
||||
void AddPaintLayer(Layer* layer);
|
||||
|
||||
private:
|
||||
const SkRRect rrect_;
|
||||
SkColor const color_;
|
||||
scenic::OpacityNodeHACK opacity_node_;
|
||||
scenic::ShapeNode shape_node_;
|
||||
|
||||
std::vector<Layer*> paint_layers_;
|
||||
SkRect paint_bounds_;
|
||||
Layer* layer_;
|
||||
};
|
||||
|
||||
class Clip : public Entity {
|
||||
public:
|
||||
Clip(SceneUpdateContext& context, const SkRect& shape_bounds);
|
||||
~Clip() = default;
|
||||
SkRRect rrect_;
|
||||
SkRect paint_bounds_;
|
||||
SkColor color_;
|
||||
float opacity_;
|
||||
};
|
||||
|
||||
SceneUpdateContext(scenic::Session* session,
|
||||
@@ -206,6 +201,7 @@ class SceneUpdateContext {
|
||||
scenic::ShapeNode shape_node,
|
||||
const SkRRect& rrect,
|
||||
SkColor color,
|
||||
float opacity,
|
||||
const SkRect& paint_bounds,
|
||||
std::vector<Layer*> paint_layers,
|
||||
Layer* layer);
|
||||
@@ -217,7 +213,9 @@ class SceneUpdateContext {
|
||||
std::vector<Layer*> paint_layers,
|
||||
Layer* layer,
|
||||
scenic::EntityNode entity_node);
|
||||
void SetShapeColor(scenic::ShapeNode& shape_node, SkColor color);
|
||||
void SetMaterialColor(scenic::Material& material,
|
||||
SkColor color,
|
||||
float opacity);
|
||||
scenic::Image* GenerateImageIfNeeded(SkColor color,
|
||||
SkScalar scale_x,
|
||||
SkScalar scale_y,
|
||||
|
||||
Reference in New Issue
Block a user