Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Wire up Opacity on Fuchsia, round 2 #14024

Merged
merged 6 commits into from
Dec 5, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions ci/licenses_golden/licenses_flutter
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ 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/layer.cc
FILE: ../../../flutter/flow/layers/layer.h
FILE: ../../../flutter/flow/layers/layer_tree.cc
Expand Down
4 changes: 4 additions & 0 deletions flow/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ 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/layer.cc",
"layers/layer.h",
"layers/layer_tree.cc",
Expand Down Expand Up @@ -76,6 +78,8 @@ 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",
Expand Down
17 changes: 16 additions & 1 deletion flow/layers/child_scene_layer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
3 changes: 1 addition & 2 deletions flow/layers/container_layer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@ namespace flutter {
ContainerLayer::ContainerLayer() {}

void ContainerLayer::Add(std::shared_ptr<Layer> layer) {
layer->set_parent(this);
layers_.push_back(std::move(layer));
layers_.emplace_back(std::move(layer));
}

void ContainerLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) {
Expand Down
2 changes: 1 addition & 1 deletion flow/layers/container_layer.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class ContainerLayer : public Layer {
public:
ContainerLayer();

void Add(std::shared_ptr<Layer> layer);
virtual void Add(std::shared_ptr<Layer> layer);

void Preroll(PrerollContext* context, const SkMatrix& matrix) override;
void Paint(PaintContext& context) const override;
Expand Down
49 changes: 49 additions & 0 deletions flow/layers/elevated_container_layer.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// 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
34 changes: 34 additions & 0 deletions flow/layers/elevated_container_layer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// 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_
55 changes: 55 additions & 0 deletions flow/layers/fuchsia_system_composited_layer.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// 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
37 changes: 37 additions & 0 deletions flow/layers/fuchsia_system_composited_layer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// 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_
7 changes: 3 additions & 4 deletions flow/layers/layer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,9 @@
namespace flutter {

Layer::Layer()
: parent_(nullptr),
needs_system_composite_(false),
paint_bounds_(SkRect::MakeEmpty()),
unique_id_(NextUniqueID()) {}
: paint_bounds_(SkRect::MakeEmpty()),
unique_id_(NextUniqueID()),
needs_system_composite_(false) {}

Layer::~Layer() = default;

Expand Down
23 changes: 14 additions & 9 deletions flow/layers/layer.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,6 @@ static constexpr SkRect kGiantRect = SkRect::MakeLTRB(-1E9F, -1E9F, 1E9F, 1E9F);
// This should be an exact copy of the Clip enum in painting.dart.
enum Clip { none, hardEdge, antiAlias, antiAliasWithSaveLayer };

class ContainerLayer;

struct PrerollContext {
RasterCache* raster_cache;
GrContext* gr_context;
Expand All @@ -52,13 +50,21 @@ struct PrerollContext {
SkColorSpace* dst_color_space;
SkRect cull_rect;

// The following allows us to paint in the end of subtree preroll
// These allow us to paint in the end of subtree Preroll.
const Stopwatch& raster_time;
const Stopwatch& ui_time;
TextureRegistry& texture_registry;
const bool checkerboard_offscreen_layers;

// These allow us to make use of the scene metrics during Preroll.
float frame_physical_depth;
float frame_device_pixel_ratio;

// 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
Expand Down Expand Up @@ -90,6 +96,10 @@ class Layer {
TextureRegistry& texture_registry;
const RasterCache* raster_cache;
const bool checkerboard_offscreen_layers;

// These allow us to make use of the scene metrics during Paint.
float frame_physical_depth;
float frame_device_pixel_ratio;
};

// Calls SkCanvas::saveLayer and restores the layer upon destruction. Also
Expand Down Expand Up @@ -126,10 +136,6 @@ class Layer {
virtual void UpdateScene(SceneUpdateContext& context);
#endif

ContainerLayer* parent() const { return parent_; }

void set_parent(ContainerLayer* parent) { parent_ = parent; }

bool needs_system_composite() const { return needs_system_composite_; }
void set_needs_system_composite(bool value) {
needs_system_composite_ = value;
Expand All @@ -148,10 +154,9 @@ class Layer {
uint64_t unique_id() const { return unique_id_; }

private:
ContainerLayer* parent_;
bool needs_system_composite_;
SkRect paint_bounds_;
uint64_t unique_id_;
bool needs_system_composite_;

static uint64_t NextUniqueID();

Expand Down
Loading