mirror of
https://github.com/encounter/engine.git
synced 2026-03-30 11:09:55 -07:00
Retained rendering in Fuchsia PhysicalShapeLayer (#6558)
For flutter/flutter#23535 When this lands/rolls into Fuchsia, a manual roll with https://fuchsia-review.googlesource.com/c/topaz/+/241557 is needed.
This commit is contained in:
@@ -66,7 +66,21 @@ void PhysicalShapeLayer::Preroll(PrerollContext* context,
|
||||
void PhysicalShapeLayer::UpdateScene(SceneUpdateContext& context) {
|
||||
FML_DCHECK(needs_system_composite());
|
||||
|
||||
SceneUpdateContext::Frame frame(context, frameRRect_, color_, elevation_);
|
||||
// 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(this, context.Matrix());
|
||||
if (context.HasRetainedNode(key)) {
|
||||
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;
|
||||
}
|
||||
|
||||
// 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());
|
||||
|
||||
@@ -40,13 +40,15 @@ void SceneUpdateContext::RemoveExportNode(ExportNode* export_node) {
|
||||
export_nodes_.erase(export_node);
|
||||
}
|
||||
|
||||
void SceneUpdateContext::CreateFrame(scenic::EntityNode& entity_node,
|
||||
const SkRRect& rrect,
|
||||
SkColor color,
|
||||
const SkRect& paint_bounds,
|
||||
std::vector<Layer*> paint_layers) {
|
||||
void SceneUpdateContext::CreateFrame(
|
||||
std::unique_ptr<scenic::EntityNode> entity_node,
|
||||
const SkRRect& rrect,
|
||||
SkColor color,
|
||||
const SkRect& paint_bounds,
|
||||
std::vector<Layer*> paint_layers,
|
||||
Layer* layer) {
|
||||
// Frames always clip their children.
|
||||
entity_node.SetClip(0u, true /* clip to self */);
|
||||
entity_node->SetClip(0u, true /* clip to self */);
|
||||
|
||||
// We don't need a shape if the frame is zero size.
|
||||
if (rrect.isEmpty())
|
||||
@@ -70,7 +72,7 @@ void SceneUpdateContext::CreateFrame(scenic::EntityNode& entity_node,
|
||||
shape_node.SetTranslation(shape_bounds.width() * 0.5f + shape_bounds.left(),
|
||||
shape_bounds.height() * 0.5f + shape_bounds.top(),
|
||||
0.f);
|
||||
entity_node.AddPart(shape_node);
|
||||
entity_node->AddPart(shape_node);
|
||||
|
||||
// Check whether the painted layers will be visible.
|
||||
if (paint_bounds.isEmpty() || !paint_bounds.intersects(shape_bounds))
|
||||
@@ -83,8 +85,8 @@ void SceneUpdateContext::CreateFrame(scenic::EntityNode& entity_node,
|
||||
}
|
||||
|
||||
// Apply current metrics and transformation scale factors.
|
||||
const float scale_x = metrics_->scale_x * top_scale_x_;
|
||||
const float scale_y = metrics_->scale_y * top_scale_y_;
|
||||
const float scale_x = ScaleX();
|
||||
const float scale_y = ScaleY();
|
||||
|
||||
// If the painted area only covers a portion of the frame then we can
|
||||
// reduce the texture size by drawing just that smaller area.
|
||||
@@ -100,15 +102,17 @@ void SceneUpdateContext::CreateFrame(scenic::EntityNode& entity_node,
|
||||
inner_node.SetTranslation(inner_bounds.width() * 0.5f + inner_bounds.left(),
|
||||
inner_bounds.height() * 0.5f + inner_bounds.top(),
|
||||
0.f);
|
||||
entity_node.AddPart(inner_node);
|
||||
entity_node->AddPart(inner_node);
|
||||
SetShapeTextureOrColor(inner_node, color, scale_x, scale_y, inner_bounds,
|
||||
std::move(paint_layers));
|
||||
std::move(paint_layers), layer,
|
||||
std::move(entity_node));
|
||||
return;
|
||||
}
|
||||
|
||||
// Apply a texture to the whole shape.
|
||||
SetShapeTextureOrColor(shape_node, color, scale_x, scale_y, shape_bounds,
|
||||
std::move(paint_layers));
|
||||
std::move(paint_layers), layer,
|
||||
std::move(entity_node));
|
||||
}
|
||||
|
||||
void SceneUpdateContext::SetShapeTextureOrColor(
|
||||
@@ -117,9 +121,12 @@ void SceneUpdateContext::SetShapeTextureOrColor(
|
||||
SkScalar scale_x,
|
||||
SkScalar scale_y,
|
||||
const SkRect& paint_bounds,
|
||||
std::vector<Layer*> paint_layers) {
|
||||
std::vector<Layer*> paint_layers,
|
||||
Layer* layer,
|
||||
std::unique_ptr<scenic::EntityNode> entity_node) {
|
||||
scenic::Image* image = GenerateImageIfNeeded(
|
||||
color, scale_x, scale_y, paint_bounds, std::move(paint_layers));
|
||||
color, scale_x, scale_y, paint_bounds, std::move(paint_layers), layer,
|
||||
std::move(entity_node));
|
||||
if (image != nullptr) {
|
||||
scenic::Material material(session_);
|
||||
material.SetTexture(*image);
|
||||
@@ -146,7 +153,9 @@ scenic::Image* SceneUpdateContext::GenerateImageIfNeeded(
|
||||
SkScalar scale_x,
|
||||
SkScalar scale_y,
|
||||
const SkRect& paint_bounds,
|
||||
std::vector<Layer*> paint_layers) {
|
||||
std::vector<Layer*> paint_layers,
|
||||
Layer* layer,
|
||||
std::unique_ptr<scenic::EntityNode> entity_node) {
|
||||
// Bail if there's nothing to paint.
|
||||
if (paint_layers.empty())
|
||||
return nullptr;
|
||||
@@ -158,7 +167,10 @@ scenic::Image* SceneUpdateContext::GenerateImageIfNeeded(
|
||||
return nullptr;
|
||||
|
||||
// Acquire a surface from the surface producer and register the paint tasks.
|
||||
auto surface = surface_producer_->ProduceSurface(physical_size);
|
||||
std::unique_ptr<SurfaceProducerSurface> surface =
|
||||
surface_producer_->ProduceSurface(physical_size,
|
||||
LayerRasterCacheKey(layer, Matrix()),
|
||||
std::move(entity_node));
|
||||
|
||||
if (!surface) {
|
||||
FML_LOG(ERROR) << "Could not acquire a surface from the surface producer "
|
||||
@@ -210,11 +222,10 @@ SceneUpdateContext::ExecutePaintTasks(CompositorContext::ScopedFrame& frame) {
|
||||
}
|
||||
|
||||
SceneUpdateContext::Entity::Entity(SceneUpdateContext& context)
|
||||
: context_(context),
|
||||
previous_entity_(context.top_entity_),
|
||||
entity_node_(context.session()) {
|
||||
: context_(context), previous_entity_(context.top_entity_) {
|
||||
entity_node_ptr_ = std::make_unique<scenic::EntityNode>(context.session());
|
||||
if (previous_entity_)
|
||||
previous_entity_->entity_node_.AddChild(entity_node_);
|
||||
previous_entity_->entity_node_ptr_->AddChild(*entity_node_ptr_);
|
||||
context.top_entity_ = this;
|
||||
}
|
||||
|
||||
@@ -292,18 +303,20 @@ SceneUpdateContext::Transform::~Transform() {
|
||||
SceneUpdateContext::Frame::Frame(SceneUpdateContext& context,
|
||||
const SkRRect& rrect,
|
||||
SkColor color,
|
||||
float elevation)
|
||||
float elevation,
|
||||
Layer* layer)
|
||||
: Entity(context),
|
||||
rrect_(rrect),
|
||||
color_(color),
|
||||
paint_bounds_(SkRect::MakeEmpty()) {
|
||||
paint_bounds_(SkRect::MakeEmpty()),
|
||||
layer_(layer) {
|
||||
if (elevation != 0.0)
|
||||
entity_node().SetTranslation(0.f, 0.f, elevation);
|
||||
}
|
||||
|
||||
SceneUpdateContext::Frame::~Frame() {
|
||||
context().CreateFrame(entity_node(), rrect_, color_, paint_bounds_,
|
||||
std::move(paint_layers_));
|
||||
context().CreateFrame(std::move(entity_node_ptr()), rrect_, color_,
|
||||
paint_bounds_, std::move(paint_layers_), layer_);
|
||||
}
|
||||
|
||||
void SceneUpdateContext::Frame::AddPaintLayer(Layer* layer) {
|
||||
|
||||
+61
-12
@@ -10,6 +10,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "flutter/flow/compositor_context.h"
|
||||
#include "flutter/flow/raster_cache_key.h"
|
||||
#include "flutter/fml/build_config.h"
|
||||
#include "flutter/fml/compiler_specific.h"
|
||||
#include "flutter/fml/logging.h"
|
||||
@@ -50,8 +51,19 @@ class SceneUpdateContext {
|
||||
public:
|
||||
virtual ~SurfaceProducer() = default;
|
||||
|
||||
// The produced surface owns the entity_node and has a layer_key for
|
||||
// retained rendering. The surface will only be retained if the layer_key
|
||||
// has a non-null layer pointer (layer_key.id()).
|
||||
virtual std::unique_ptr<SurfaceProducerSurface> ProduceSurface(
|
||||
const SkISize& size) = 0;
|
||||
const SkISize& size,
|
||||
const LayerRasterCacheKey& layer_key,
|
||||
std::unique_ptr<scenic::EntityNode> entity_node) = 0;
|
||||
|
||||
// Query a retained entity node (owned by a retained surface) for retained
|
||||
// rendering.
|
||||
virtual bool HasRetainedNode(const LayerRasterCacheKey& key) const = 0;
|
||||
virtual const scenic::EntityNode& GetRetainedNode(
|
||||
const LayerRasterCacheKey& key) = 0;
|
||||
|
||||
virtual void SubmitSurface(
|
||||
std::unique_ptr<SurfaceProducerSurface> surface) = 0;
|
||||
@@ -63,13 +75,16 @@ class SceneUpdateContext {
|
||||
~Entity();
|
||||
|
||||
SceneUpdateContext& context() { return context_; }
|
||||
scenic::EntityNode& entity_node() { return entity_node_; }
|
||||
scenic::EntityNode& entity_node() { return *entity_node_ptr_; }
|
||||
std::unique_ptr<scenic::EntityNode>& entity_node_ptr() {
|
||||
return entity_node_ptr_;
|
||||
}
|
||||
|
||||
private:
|
||||
SceneUpdateContext& context_;
|
||||
Entity* const previous_entity_;
|
||||
|
||||
scenic::EntityNode entity_node_;
|
||||
std::unique_ptr<scenic::EntityNode> entity_node_ptr_;
|
||||
};
|
||||
|
||||
class Clip : public Entity {
|
||||
@@ -96,10 +111,15 @@ class SceneUpdateContext {
|
||||
|
||||
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
|
||||
// retained for that layer.
|
||||
Frame(SceneUpdateContext& context,
|
||||
const SkRRect& rrect,
|
||||
SkColor color,
|
||||
float elevation);
|
||||
float elevation,
|
||||
Layer* layer = nullptr);
|
||||
|
||||
~Frame();
|
||||
|
||||
void AddPaintLayer(Layer* layer);
|
||||
@@ -110,6 +130,7 @@ class SceneUpdateContext {
|
||||
|
||||
std::vector<Layer*> paint_layers_;
|
||||
SkRect paint_bounds_;
|
||||
Layer* layer_;
|
||||
};
|
||||
|
||||
SceneUpdateContext(scenic::Session* session,
|
||||
@@ -119,6 +140,8 @@ class SceneUpdateContext {
|
||||
|
||||
scenic::Session* session() { return session_; }
|
||||
|
||||
Entity* top_entity() { return top_entity_; }
|
||||
|
||||
bool has_metrics() const { return !!metrics_; }
|
||||
void set_metrics(fuchsia::ui::gfx::MetricsPtr metrics) {
|
||||
metrics_ = std::move(metrics);
|
||||
@@ -147,6 +170,20 @@ class SceneUpdateContext {
|
||||
std::vector<std::unique_ptr<SurfaceProducerSurface>> ExecutePaintTasks(
|
||||
CompositorContext::ScopedFrame& frame);
|
||||
|
||||
float ScaleX() const { return metrics_->scale_x * top_scale_x_; }
|
||||
float ScaleY() const { return metrics_->scale_y * top_scale_y_; }
|
||||
|
||||
// The transformation matrix of the current context. It's used to construct
|
||||
// the LayerRasterCacheKey for a given layer.
|
||||
SkMatrix Matrix() const { return SkMatrix::MakeScale(ScaleX(), ScaleY()); }
|
||||
|
||||
bool HasRetainedNode(const LayerRasterCacheKey& key) const {
|
||||
return surface_producer_->HasRetainedNode(key);
|
||||
}
|
||||
const scenic::EntityNode& GetRetainedNode(const LayerRasterCacheKey& key) {
|
||||
return surface_producer_->GetRetainedNode(key);
|
||||
}
|
||||
|
||||
private:
|
||||
struct PaintTask {
|
||||
std::unique_ptr<SurfaceProducerSurface> surface;
|
||||
@@ -158,23 +195,35 @@ class SceneUpdateContext {
|
||||
std::vector<Layer*> layers;
|
||||
};
|
||||
|
||||
void CreateFrame(scenic::EntityNode& entity_node,
|
||||
// Setup the entity_node as a frame that materialize all the paint_layers. In
|
||||
// most cases, this creates a VulkanSurface (SurfaceProducerSurface) by
|
||||
// calling SetShapeTextureOrColor and GenerageImageIfNeeded. Such surface will
|
||||
// own the associated entity_node. If the layer pointer isn't nullptr, the
|
||||
// surface (and thus the entity_node) will be retained for that layer to
|
||||
// improve the performance.
|
||||
void CreateFrame(std::unique_ptr<scenic::EntityNode> entity_node,
|
||||
const SkRRect& rrect,
|
||||
SkColor color,
|
||||
const SkRect& paint_bounds,
|
||||
std::vector<Layer*> paint_layers);
|
||||
std::vector<Layer*> paint_layers,
|
||||
Layer* layer);
|
||||
void SetShapeTextureOrColor(scenic::ShapeNode& shape_node,
|
||||
SkColor color,
|
||||
SkScalar scale_x,
|
||||
SkScalar scale_y,
|
||||
const SkRect& paint_bounds,
|
||||
std::vector<Layer*> paint_layers);
|
||||
std::vector<Layer*> paint_layers,
|
||||
Layer* layer,
|
||||
std::unique_ptr<scenic::EntityNode> entity_node);
|
||||
void SetShapeColor(scenic::ShapeNode& shape_node, SkColor color);
|
||||
scenic::Image* GenerateImageIfNeeded(SkColor color,
|
||||
SkScalar scale_x,
|
||||
SkScalar scale_y,
|
||||
const SkRect& paint_bounds,
|
||||
std::vector<Layer*> paint_layers);
|
||||
scenic::Image* GenerateImageIfNeeded(
|
||||
SkColor color,
|
||||
SkScalar scale_x,
|
||||
SkScalar scale_y,
|
||||
const SkRect& paint_bounds,
|
||||
std::vector<Layer*> paint_layers,
|
||||
Layer* layer,
|
||||
std::unique_ptr<scenic::EntityNode> entity_node);
|
||||
|
||||
Entity* top_entity_ = nullptr;
|
||||
float top_scale_x_ = 1.f;
|
||||
|
||||
Reference in New Issue
Block a user