scene_update_context.cc 12.2 KB
Newer Older
M
Michael Goderbauer 已提交
1
// Copyright 2013 The Flutter Authors. All rights reserved.
2 3 4 5 6 7
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "flutter/flow/scene_update_context.h"

#include "flutter/flow/layers/layer.h"
8
#include "flutter/flow/matrix_decomposition.h"
9
#include "flutter/fml/trace_event.h"
10
#include "flutter/lib/ui/window/viewport_metrics.h"
11

12
namespace flutter {
13

14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
// Helper function to generate clip planes for a scenic::EntityNode.
static void SetEntityNodeClipPlanes(scenic::EntityNode* entity_node,
                                    const SkRect& bounds) {
  const float top = bounds.top();
  const float bottom = bounds.bottom();
  const float left = bounds.left();
  const float right = bounds.right();

  // We will generate 4 oriented planes, one for each edge of the bounding rect.
  std::vector<fuchsia::ui::gfx::Plane3> clip_planes;
  clip_planes.resize(4);

  // Top plane.
  clip_planes[0].dist = top;
  clip_planes[0].dir.x = 0.f;
  clip_planes[0].dir.y = 1.f;
  clip_planes[0].dir.z = 0.f;

  // Bottom plane.
  clip_planes[1].dist = -bottom;
  clip_planes[1].dir.x = 0.f;
  clip_planes[1].dir.y = -1.f;
  clip_planes[1].dir.z = 0.f;

  // Left plane.
  clip_planes[2].dist = left;
  clip_planes[2].dir.x = 1.f;
  clip_planes[2].dir.y = 0.f;
  clip_planes[2].dir.z = 0.f;

  // Right plane.
  clip_planes[3].dist = -right;
  clip_planes[3].dir.x = -1.f;
  clip_planes[3].dir.y = 0.f;
  clip_planes[3].dir.z = 0.f;

  entity_node->SetClipPlanes(std::move(clip_planes));
}

53 54 55 56 57 58
SceneUpdateContext::SceneUpdateContext(scenic::Session* session,
                                       SurfaceProducer* surface_producer)
    : session_(session), surface_producer_(surface_producer) {
  FML_DCHECK(surface_producer_ != nullptr);
}

59 60
void SceneUpdateContext::CreateFrame(
    std::unique_ptr<scenic::EntityNode> entity_node,
61
    std::unique_ptr<scenic::ShapeNode> shape_node,
62 63 64 65 66
    const SkRRect& rrect,
    SkColor color,
    const SkRect& paint_bounds,
    std::vector<Layer*> paint_layers,
    Layer* layer) {
67
  // Frames always clip their children.
68 69
  SetEntityNodeClipPlanes(entity_node.get(), rrect.getBounds());
  // TODO(SCN-1274): AddPart() and SetClip() will be deleted.
70
  entity_node->SetClip(0u, true /* clip to self */);
71

72 73 74
  // We don't need a shape if the frame is zero size.
  if (rrect.isEmpty())
    return;
75

76 77
  // Add a part which represents the frame's geometry for clipping purposes
  // and possibly for its texture.
78
  // TODO(SCN-137): Need to be able to express the radii as vectors.
79
  SkRect shape_bounds = rrect.getBounds();
80
  scenic::RoundedRectangle shape(
81 82 83 84 85 86 87
      session_,                                      // session
      rrect.width(),                                 // width
      rrect.height(),                                // height
      rrect.radii(SkRRect::kUpperLeft_Corner).x(),   // top_left_radius
      rrect.radii(SkRRect::kUpperRight_Corner).x(),  // top_right_radius
      rrect.radii(SkRRect::kLowerRight_Corner).x(),  // bottom_right_radius
      rrect.radii(SkRRect::kLowerLeft_Corner).x()    // bottom_left_radius
88
  );
89
  shape_node->SetShape(shape);
90 91 92
  shape_node->SetTranslation(shape_bounds.width() * 0.5f + shape_bounds.left(),
                             shape_bounds.height() * 0.5f + shape_bounds.top(),
                             0.f);
93

94 95 96
  // Check whether the painted layers will be visible.
  if (paint_bounds.isEmpty() || !paint_bounds.intersects(shape_bounds))
    paint_layers.clear();
97

98 99
  // Check whether a solid color will suffice.
  if (paint_layers.empty()) {
100
    SetShapeColor(*shape_node, color);
101 102 103
    return;
  }

104
  // Apply current metrics and transformation scale factors.
105 106
  const float scale_x = ScaleX();
  const float scale_y = ScaleY();
107

108
  // Apply a texture to the whole shape.
109
  SetShapeTextureOrColor(*shape_node, color, scale_x, scale_y, shape_bounds,
110 111
                         std::move(paint_layers), layer,
                         std::move(entity_node));
112 113
}

114
void SceneUpdateContext::SetShapeTextureOrColor(
115
    scenic::ShapeNode& shape_node,
116 117 118 119
    SkColor color,
    SkScalar scale_x,
    SkScalar scale_y,
    const SkRect& paint_bounds,
120 121 122
    std::vector<Layer*> paint_layers,
    Layer* layer,
    std::unique_ptr<scenic::EntityNode> entity_node) {
123
  scenic::Image* image = GenerateImageIfNeeded(
124 125
      color, scale_x, scale_y, paint_bounds, std::move(paint_layers), layer,
      std::move(entity_node));
126
  if (image != nullptr) {
127
    scenic::Material material(session_);
128 129 130 131 132 133
    material.SetTexture(*image);
    shape_node.SetMaterial(material);
    return;
  }

  SetShapeColor(shape_node, color);
134 135
}

136
void SceneUpdateContext::SetShapeColor(scenic::ShapeNode& shape_node,
137 138 139 140
                                       SkColor color) {
  if (SkColorGetA(color) == 0)
    return;

141
  scenic::Material material(session_);
142 143 144
  material.SetColor(SkColorGetR(color), SkColorGetG(color), SkColorGetB(color),
                    SkColorGetA(color));
  shape_node.SetMaterial(material);
145 146
}

147
scenic::Image* SceneUpdateContext::GenerateImageIfNeeded(
148 149 150 151
    SkColor color,
    SkScalar scale_x,
    SkScalar scale_y,
    const SkRect& paint_bounds,
152 153 154
    std::vector<Layer*> paint_layers,
    Layer* layer,
    std::unique_ptr<scenic::EntityNode> entity_node) {
155 156 157 158 159 160 161 162 163
  // Bail if there's nothing to paint.
  if (paint_layers.empty())
    return nullptr;

  // Bail if the physical bounds are empty after rounding.
  SkISize physical_size = SkISize::Make(paint_bounds.width() * scale_x,
                                        paint_bounds.height() * scale_y);
  if (physical_size.isEmpty())
    return nullptr;
164

165
  // Acquire a surface from the surface producer and register the paint tasks.
166
  std::unique_ptr<SurfaceProducerSurface> surface =
167 168 169 170 171 172
      surface_producer_->ProduceSurface(
          physical_size,
          LayerRasterCacheKey(
              // Root frame has a nullptr layer
              layer ? layer->unique_id() : 0, Matrix()),
          std::move(entity_node));
173 174

  if (!surface) {
175
    FML_LOG(ERROR) << "Could not acquire a surface from the surface producer "
176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193
                      "of size: "
                   << physical_size.width() << "x" << physical_size.height();
    return nullptr;
  }

  auto image = surface->GetImage();

  // Enqueue the paint task.
  paint_tasks_.push_back({.surface = std::move(surface),
                          .left = paint_bounds.left(),
                          .top = paint_bounds.top(),
                          .scale_x = scale_x,
                          .scale_y = scale_y,
                          .background_color = color,
                          .layers = std::move(paint_layers)});
  return image;
}

194 195
std::vector<
    std::unique_ptr<flutter::SceneUpdateContext::SurfaceProducerSurface>>
196 197 198
SceneUpdateContext::ExecutePaintTasks(CompositorContext::ScopedFrame& frame) {
  TRACE_EVENT0("flutter", "SceneUpdateContext::ExecutePaintTasks");
  std::vector<std::unique_ptr<SurfaceProducerSurface>> surfaces_to_submit;
199
  for (auto& task : paint_tasks_) {
200
    FML_DCHECK(task.surface);
201
    SkCanvas* canvas = task.surface->GetSkiaSurface()->getCanvas();
202
    Layer::PaintContext context = {canvas,
203
                                   canvas,
204
                                   frame.gr_context(),
205
                                   nullptr,
206
                                   frame.context().frame_time(),
A
Adam Barth 已提交
207
                                   frame.context().engine_time(),
208 209 210
                                   frame.context().texture_registry(),
                                   &frame.context().raster_cache(),
                                   false};
211 212 213 214
    canvas->restoreToCount(1);
    canvas->save();
    canvas->clear(task.background_color);
    canvas->scale(task.scale_x, task.scale_y);
215
    canvas->translate(-task.left, -task.top);
216
    for (Layer* layer : task.layers) {
217
      layer->Paint(context);
218 219
    }
    surfaces_to_submit.emplace_back(std::move(task.surface));
220 221
  }
  paint_tasks_.clear();
222
  return surfaces_to_submit;
223 224
}

225
SceneUpdateContext::Entity::Entity(SceneUpdateContext& context)
226 227
    : context_(context), previous_entity_(context.top_entity_) {
  entity_node_ptr_ = std::make_unique<scenic::EntityNode>(context.session());
228 229 230
  shape_node_ptr_ = std::make_unique<scenic::ShapeNode>(context.session());
  // TODO(SCN-1274): AddPart() and SetClip() will be deleted.
  entity_node_ptr_->AddPart(*shape_node_ptr_);
231
  if (previous_entity_)
232
    previous_entity_->entity_node_ptr_->AddChild(*entity_node_ptr_);
233 234 235 236
  context.top_entity_ = this;
}

SceneUpdateContext::Entity::~Entity() {
237
  FML_DCHECK(context_.top_entity_ == this);
238 239 240 241 242
  context_.top_entity_ = previous_entity_;
}

SceneUpdateContext::Transform::Transform(SceneUpdateContext& context,
                                         const SkMatrix& transform)
243 244 245 246
    : Entity(context),
      previous_scale_x_(context.top_scale_x_),
      previous_scale_y_(context.top_scale_y_) {
  if (!transform.isIdentity()) {
247
    // TODO(SCN-192): The perspective and shear components in the matrix
248 249 250
    // are not handled correctly.
    MatrixDecomposition decomposition(transform);
    if (decomposition.IsValid()) {
251 252
      entity_node().SetTranslation(decomposition.translation().x(),  //
                                   decomposition.translation().y(),  //
253
                                   -decomposition.translation().z()  //
254
      );
255 256 257 258

      entity_node().SetScale(decomposition.scale().x(),  //
                             decomposition.scale().y(),  //
                             decomposition.scale().z()   //
259
      );
260 261 262 263 264 265 266
      context.top_scale_x_ *= decomposition.scale().x();
      context.top_scale_y_ *= decomposition.scale().y();

      entity_node().SetRotation(decomposition.rotation().fData[0],  //
                                decomposition.rotation().fData[1],  //
                                decomposition.rotation().fData[2],  //
                                decomposition.rotation().fData[3]   //
267
      );
268 269 270 271 272 273 274 275 276 277 278 279 280 281 282
    }
  }
}

SceneUpdateContext::Transform::Transform(SceneUpdateContext& context,
                                         float scale_x,
                                         float scale_y,
                                         float scale_z)
    : Entity(context),
      previous_scale_x_(context.top_scale_x_),
      previous_scale_y_(context.top_scale_y_) {
  if (scale_x != 1.f || scale_y != 1.f || scale_z != 1.f) {
    entity_node().SetScale(scale_x, scale_y, scale_z);
    context.top_scale_x_ *= scale_x;
    context.top_scale_y_ *= scale_y;
283 284 285
  }
}

286 287 288 289
SceneUpdateContext::Transform::~Transform() {
  context().top_scale_x_ = previous_scale_x_;
  context().top_scale_y_ = previous_scale_y_;
}
290 291 292 293

SceneUpdateContext::Frame::Frame(SceneUpdateContext& context,
                                 const SkRRect& rrect,
                                 SkColor color,
294 295 296
                                 float local_elevation,
                                 float world_elevation,
                                 float depth,
297
                                 Layer* layer)
298 299 300
    : Entity(context),
      rrect_(rrect),
      color_(color),
301 302
      paint_bounds_(SkRect::MakeEmpty()),
      layer_(layer) {
303 304 305 306 307 308 309 310
  if (local_elevation != 0.0) {
    if (depth > flutter::kUnsetDepth && world_elevation >= depth) {
      // TODO(mklim): Deal with bounds overflow correctly.
      FML_LOG(ERROR) << "Elevation " << world_elevation << " is outside of "
                     << depth;
    }
    entity_node().SetTranslation(0.f, 0.f, -local_elevation);
  }
311 312 313
}

SceneUpdateContext::Frame::~Frame() {
314 315
  context().CreateFrame(std::move(entity_node_ptr()),
                        std::move(shape_node_ptr()), rrect_, color_,
316
                        paint_bounds_, std::move(paint_layers_), layer_);
317 318
}

319
void SceneUpdateContext::Frame::AddPaintLayer(Layer* layer) {
320
  FML_DCHECK(layer->needs_painting());
321 322 323 324
  paint_layers_.push_back(layer);
  paint_bounds_.join(layer->paint_bounds());
}

325 326 327 328 329
SceneUpdateContext::Clip::Clip(SceneUpdateContext& context,
                               scenic::Shape& shape,
                               const SkRect& shape_bounds)
    : Entity(context) {
  shape_node().SetShape(shape);
330 331 332
  shape_node().SetTranslation(shape_bounds.width() * 0.5f + shape_bounds.left(),
                              shape_bounds.height() * 0.5f + shape_bounds.top(),
                              0.f);
333 334 335 336 337
  entity_node().SetClip(0u, true /* clip to self */);

  SetEntityNodeClipPlanes(&entity_node(), shape_bounds);
}

338
}  // namespace flutter