Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
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
7 changes: 6 additions & 1 deletion flow/embedded_views.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ class EmbeddedViewParams {
public:
SkPoint offsetPixels;
SkSize sizePoints;
SkISize canvasBaseLayerSize;
};

// This is only used on iOS when running in a non headless mode,
Expand All @@ -26,6 +25,12 @@ class ExternalViewEmbedder {
public:
ExternalViewEmbedder() = default;

virtual void SetFrameSize(SkISize frame_size) = 0;

virtual void PrerollCompositeEmbeddedView(int view_id) = 0;

virtual std::vector<SkCanvas*> GetCurrentCanvases() = 0;

// Must be called on the UI thread.
virtual SkCanvas* CompositeEmbeddedView(int view_id,
const EmbeddedViewParams& params) = 0;
Expand Down
17 changes: 17 additions & 0 deletions flow/layers/layer.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include "third_party/skia/include/core/SkPicture.h"
#include "third_party/skia/include/core/SkRRect.h"
#include "third_party/skia/include/core/SkRect.h"
#include "third_party/skia/include/utils/SkNWayCanvas.h"

#if defined(OS_FUCHSIA)

Expand All @@ -44,6 +45,7 @@ class ContainerLayer;
struct PrerollContext {
RasterCache* raster_cache;
GrContext* gr_context;
ExternalViewEmbedder* view_embedder;
SkColorSpace* dst_color_space;
SkRect child_paint_bounds;

Expand All @@ -64,6 +66,21 @@ class Layer {
virtual void Preroll(PrerollContext* context, const SkMatrix& matrix);

struct PaintContext {
// When splitting the scene into multiple canvases (e.g when embedding
// a platform view on iOS) during the paint traversal we apply the non leaf
// flow layers to all canvases, and leaf layers just to the "current"
// canvas. Applying the non leaf layers to all canvases ensures that when
// we switch a canvas (when painting a PlatformViewLayer) the next canvas
// has the exact same state as the current canvas.
// The internal_nodes_canvas is a SkNWayCanvas which is used by non leaf
// and applies the operations to all canvases.
// The leaf_nodes_canvas is the "current" canvas and is used by leaf
// layers.
SkCanvas* internal_nodes_canvas;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you make this an SkNWayCanvas type for clarity?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On Fuchsia I pass in a normal SkCanvas here...

// I'm temporarily leaving the name of this field to be canvas to reduce
// noise in the incremental change. A followup change will rename this
// and use the corrrect canvas in each callsite.
// TODO(amirh) rename canvas to leaf_nodes_canvas.
SkCanvas* canvas;
ExternalViewEmbedder* view_embedder;
const Stopwatch& frame_time;
Expand Down
19 changes: 19 additions & 0 deletions flow/layers/layer_tree.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "flutter/flow/layers/layer.h"
#include "flutter/fml/trace_event.h"
#include "third_party/skia/include/core/SkPictureRecorder.h"
#include "third_party/skia/include/utils/SkNWayCanvas.h"

namespace flow {

Expand All @@ -28,6 +29,7 @@ void LayerTree::Preroll(CompositorContext::ScopedFrame& frame,
PrerollContext context = {
ignore_raster_cache ? nullptr : &frame.context().raster_cache(),
frame.gr_context(),
frame.view_embedder(),
color_space,
SkRect::MakeEmpty(),
frame.context().frame_time(),
Expand Down Expand Up @@ -66,7 +68,18 @@ void LayerTree::UpdateScene(SceneUpdateContext& context,
void LayerTree::Paint(CompositorContext::ScopedFrame& frame,
bool ignore_raster_cache) const {
TRACE_EVENT0("flutter", "LayerTree::Paint");
SkISize canvas_size = frame.canvas()->getBaseLayerSize();
SkNWayCanvas internal_nodes_canvas(canvas_size.width(), canvas_size.height());
internal_nodes_canvas.addCanvas(frame.canvas());
if (frame.view_embedder() != nullptr) {
auto overlay_canvases = frame.view_embedder()->GetCurrentCanvases();
for (size_t i = 0; i < overlay_canvases.size(); i++) {
internal_nodes_canvas.addCanvas(overlay_canvases[i]);
}
}

Layer::PaintContext context = {
(SkCanvas*)&internal_nodes_canvas,
frame.canvas(),
frame.view_embedder(),
frame.context().frame_time(),
Expand Down Expand Up @@ -98,6 +111,7 @@ sk_sp<SkPicture> LayerTree::Flatten(const SkRect& bounds) {
PrerollContext preroll_context{
nullptr, // raster_cache (don't consult the cache)
nullptr, // gr_context (used for the raster cache)
nullptr, // external view embedder
nullptr, // SkColorSpace* dst_color_space
SkRect::MakeEmpty(), // SkRect child_paint_bounds
unused_stopwatch, // frame time (dont care)
Expand All @@ -106,7 +120,12 @@ sk_sp<SkPicture> LayerTree::Flatten(const SkRect& bounds) {
false, // checkerboard_offscreen_layers
};

SkISize canvas_size = canvas->getBaseLayerSize();
SkNWayCanvas internal_nodes_canvas(canvas_size.width(), canvas_size.height());
internal_nodes_canvas.addCanvas(canvas);

Layer::PaintContext paint_context = {
(SkCanvas*)&internal_nodes_canvas,
canvas, // canvas
nullptr,
unused_stopwatch, // frame time (dont care)
Expand Down
10 changes: 7 additions & 3 deletions flow/layers/platform_view_layer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@ void PlatformViewLayer::Preroll(PrerollContext* context,
const SkMatrix& matrix) {
set_paint_bounds(SkRect::MakeXYWH(offset_.x(), offset_.y(), size_.width(),
size_.height()));

if (context->view_embedder == nullptr) {
FML_LOG(ERROR) << "Trying to embed a platform view but the PrerollContext "
"does not support embedding";
return;
}
context->view_embedder->PrerollCompositeEmbeddedView(view_id_);
}

void PlatformViewLayer::Paint(PaintContext& context) const {
Expand All @@ -27,12 +34,9 @@ void PlatformViewLayer::Paint(PaintContext& context) const {
params.offsetPixels =
SkPoint::Make(transform.getTranslateX(), transform.getTranslateY());
params.sizePoints = size_;
params.canvasBaseLayerSize = context.canvas->getBaseLayerSize();

SkCanvas* canvas =
context.view_embedder->CompositeEmbeddedView(view_id_, params);
// TODO(amirh): copy the full canvas state here
canvas->concat(context.canvas->getTotalMatrix());
context.canvas = canvas;
}
} // namespace flow
4 changes: 2 additions & 2 deletions flow/layers/transform_layer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ void TransformLayer::Paint(PaintContext& context) const {
TRACE_EVENT0("flutter", "TransformLayer::Paint");
FML_DCHECK(needs_painting());

SkAutoCanvasRestore save(context.canvas, true);
context.canvas->concat(transform_);
SkAutoCanvasRestore save(context.internal_nodes_canvas, true);
context.internal_nodes_canvas->concat(transform_);
PaintChildren(context);
}

Expand Down
5 changes: 5 additions & 0 deletions flow/raster_cache.cc
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,12 @@ void RasterCache::Prepare(PrerollContext* context,
entry.image = Rasterize(context->gr_context, ctm, context->dst_color_space,
checkerboard_images_, layer->paint_bounds(),
[layer, context](SkCanvas* canvas) {
SkISize canvas_size = canvas->getBaseLayerSize();
SkNWayCanvas internal_nodes_canvas(
canvas_size.width(), canvas_size.height());
internal_nodes_canvas.addCanvas(canvas);
Layer::PaintContext paintContext = {
(SkCanvas*)&internal_nodes_canvas,
canvas,
nullptr,
context->frame_time,
Expand Down
1 change: 1 addition & 0 deletions flow/scene_update_context.cc
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ SceneUpdateContext::ExecutePaintTasks(CompositorContext::ScopedFrame& frame) {
FML_DCHECK(task.surface);
SkCanvas* canvas = task.surface->GetSkiaSurface()->getCanvas();
Layer::PaintContext context = {canvas,
canvas,
nullptr,
frame.context().frame_time(),
frame.context().engine_time(),
Expand Down
5 changes: 5 additions & 0 deletions shell/common/rasterizer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,11 @@ bool Rasterizer::DrawToSurface(flow::LayerTree& layer_tree) {

auto external_view_embedder = surface_->GetExternalViewEmbedder();

// TODO(amirh): uncomment this once external_view_embedder is populated.
// if (external_view_embedder != nullptr) {
// external_view_embedder->SetFrameSize(layer_tree.frame_size());
// }

auto compositor_frame = compositor_context_->AcquireFrame(
surface_->GetContext(), canvas, external_view_embedder,
surface_->GetRootTransformation(), true);
Expand Down
30 changes: 23 additions & 7 deletions shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm
Original file line number Diff line number Diff line change
Expand Up @@ -128,34 +128,50 @@
fml::scoped_nsobject<NSObject<FlutterPlatformViewFactory>>([factory retain]);
}

void FlutterPlatformViewsController::SetFrameSize(SkISize frame_size) {
frame_size_ = frame_size;
}

void FlutterPlatformViewsController::PrerollCompositeEmbeddedView(int view_id) {
EnsureOverlayInitialized(view_id);
composition_frames_[view_id] = (overlays_[view_id]->surface->AcquireFrame(frame_size_));
composition_order_.push_back(view_id);
}

std::vector<SkCanvas*> FlutterPlatformViewsController::GetCurrentCanvases() {
std::vector<SkCanvas*> canvases;
for (size_t i = 0; i < composition_order_.size(); i++) {
int64_t view_id = composition_order_[i];
canvases.push_back(composition_frames_[view_id]->SkiaCanvas());
}
return canvases;
}

SkCanvas* FlutterPlatformViewsController::CompositeEmbeddedView(
int view_id,
const flow::EmbeddedViewParams& params,
IOSSurface& ios_surface) {
// TODO(amirh): assert that this is running on the platform thread once we support the iOS
// embedded views thread configuration.
// TODO(amirh): do nothing if the params didn't change.
EnsureOverlayInitialized(view_id);
CGFloat screenScale = [[UIScreen mainScreen] scale];
CGRect rect =
CGRectMake(params.offsetPixels.x() / screenScale, params.offsetPixels.y() / screenScale,
params.sizePoints.width(), params.sizePoints.height());

UIView* view = views_[view_id].get();
[view setFrame:rect];
composition_order_.push_back(view_id);

composition_frames_.push_back(
overlays_[view_id]->surface->AcquireFrame(params.canvasBaseLayerSize));
SkCanvas* canvas = composition_frames_.back()->SkiaCanvas();
SkCanvas* canvas = composition_frames_[view_id]->SkiaCanvas();
canvas->clear(SK_ColorTRANSPARENT);
return canvas;
}

bool FlutterPlatformViewsController::Present() {
bool did_submit = true;
for (size_t i = 0; i < composition_frames_.size(); i++) {
did_submit &= composition_frames_[i]->Submit();
for (size_t i = 0; i < composition_order_.size(); i++) {
int64_t view_id = composition_order_[i];
did_submit &= composition_frames_[view_id]->Submit();
}
composition_frames_.clear();
if (composition_order_ == active_composition_order_) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@ class FlutterPlatformViewsController {

void RegisterViewFactory(NSObject<FlutterPlatformViewFactory>* factory, NSString* factoryId);

void SetFrameSize(SkISize frame_size);

void PrerollCompositeEmbeddedView(int view_id);

std::vector<SkCanvas*> GetCurrentCanvases();

SkCanvas* CompositeEmbeddedView(int view_id,
const flow::EmbeddedViewParams& params,
IOSSurface& surface);
Expand All @@ -63,6 +69,7 @@ class FlutterPlatformViewsController {
std::map<std::string, fml::scoped_nsobject<NSObject<FlutterPlatformViewFactory>>> factories_;
std::map<int64_t, fml::scoped_nsobject<FlutterTouchInterceptingView>> views_;
std::map<int64_t, std::unique_ptr<FlutterPlatformViewLayer>> overlays_;
SkISize frame_size_;

// A vector of embedded view IDs according to their composition order.
// The last ID in this vector belond to the that is composited on top of all others.
Expand All @@ -71,7 +78,7 @@ class FlutterPlatformViewsController {
// The latest composition order that was presented in Present().
std::vector<int64_t> active_composition_order_;

std::vector<std::unique_ptr<SurfaceFrame>> composition_frames_;
std::map<int64_t, std::unique_ptr<SurfaceFrame>> composition_frames_;

void OnCreate(FlutterMethodCall* call, FlutterResult& result);
void OnDispose(FlutterMethodCall* call, FlutterResult& result);
Expand Down
9 changes: 9 additions & 0 deletions shell/platform/darwin/ios/ios_surface_gl.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,15 @@ class IOSSurfaceGL : public IOSSurface,
// |shell::GPUSurfaceGLDelegate|
flow::ExternalViewEmbedder* GetExternalViewEmbedder() override;

// |flow::ExternalViewEmbedder|
void SetFrameSize(SkISize frame_size) override;

// |flow::ExternalViewEmbedder|
void PrerollCompositeEmbeddedView(int view_id) override;

// |flow::ExternalViewEmbedder|
std::vector<SkCanvas*> GetCurrentCanvases() override;

// |flow::ExternalViewEmbedder|
SkCanvas* CompositeEmbeddedView(int view_id, const flow::EmbeddedViewParams& params) override;

Expand Down
18 changes: 18 additions & 0 deletions shell/platform/darwin/ios/ios_surface_gl.mm
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,24 @@
}
}

void IOSSurfaceGL::SetFrameSize(SkISize frame_size) {
FlutterPlatformViewsController* platform_views_controller = GetPlatformViewsController();
FML_CHECK(platform_views_controller != nullptr);
platform_views_controller->SetFrameSize(frame_size);
}

void IOSSurfaceGL::PrerollCompositeEmbeddedView(int view_id) {
FlutterPlatformViewsController* platform_views_controller = GetPlatformViewsController();
FML_CHECK(platform_views_controller != nullptr);
platform_views_controller->PrerollCompositeEmbeddedView(view_id);
}

std::vector<SkCanvas*> IOSSurfaceGL::GetCurrentCanvases() {
FlutterPlatformViewsController* platform_views_controller = GetPlatformViewsController();
FML_CHECK(platform_views_controller != nullptr);
return platform_views_controller->GetCurrentCanvases();
}

SkCanvas* IOSSurfaceGL::CompositeEmbeddedView(int view_id, const flow::EmbeddedViewParams& params) {
FlutterPlatformViewsController* platform_views_controller = GetPlatformViewsController();
FML_CHECK(platform_views_controller != nullptr);
Expand Down
9 changes: 9 additions & 0 deletions shell/platform/darwin/ios/ios_surface_software.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,15 @@ class IOSSurfaceSoftware final : public IOSSurface,
// |shell::GPUSurfaceSoftwareDelegate|
flow::ExternalViewEmbedder* GetExternalViewEmbedder() override;

// |flow::ExternalViewEmbedder|
void SetFrameSize(SkISize frame_size) override;

// |flow::ExternalViewEmbedder|
void PrerollCompositeEmbeddedView(int view_id) override;

// |flow::ExternalViewEmbedder|
std::vector<SkCanvas*> GetCurrentCanvases() override;

// |flow::ExternalViewEmbedder|
SkCanvas* CompositeEmbeddedView(int view_id, const flow::EmbeddedViewParams& params) override;

Expand Down
18 changes: 18 additions & 0 deletions shell/platform/darwin/ios/ios_surface_software.mm
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,24 @@
}
}

void IOSSurfaceSoftware::SetFrameSize(SkISize frame_size) {
FlutterPlatformViewsController* platform_views_controller = GetPlatformViewsController();
FML_CHECK(platform_views_controller != nullptr);
platform_views_controller->SetFrameSize(frame_size);
}

void IOSSurfaceSoftware::PrerollCompositeEmbeddedView(int view_id) {
FlutterPlatformViewsController* platform_views_controller = GetPlatformViewsController();
FML_CHECK(platform_views_controller != nullptr);
platform_views_controller->PrerollCompositeEmbeddedView(view_id);
}

std::vector<SkCanvas*> IOSSurfaceSoftware::GetCurrentCanvases() {
FlutterPlatformViewsController* platform_views_controller = GetPlatformViewsController();
FML_CHECK(platform_views_controller != nullptr);
return platform_views_controller->GetCurrentCanvases();
}

SkCanvas* IOSSurfaceSoftware::CompositeEmbeddedView(int view_id,
const flow::EmbeddedViewParams& params) {
FlutterPlatformViewsController* platform_views_controller = GetPlatformViewsController();
Expand Down