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 1 commit
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
ad66694
Implement unobstructed Platform Views
Feb 12, 2020
1fde093
Comments
Mar 2, 2020
9b747a3
Format gn
Mar 2, 2020
e8cfa5d
Remove log
Mar 2, 2020
ae64ac3
Add FlutterRTree unit test
Mar 2, 2020
e722620
Remove blue UIView
Mar 3, 2020
bce3c8a
Fix header
Mar 3, 2020
b1975e1
Update licenses_flutter
Mar 3, 2020
4318306
Update unit tests
Mar 3, 2020
84c3b0f
test (delete)
Mar 3, 2020
3635a70
Fix platform view scenarios tests
Mar 4, 2020
39f0bad
typo
Mar 4, 2020
62d8d8d
Update golden platform view
Mar 4, 2020
11242e9
Fix FlutterRTree bug
Mar 4, 2020
fcaa142
Clip platform view in the background canvas
Mar 4, 2020
2b27ed6
Add GetPlatformViewRect to EmbedderExternalViewEmbedder
Mar 4, 2020
b7c2bc6
Remove matrix check
Mar 4, 2020
71ba25c
Return empty skrect
Mar 4, 2020
7002929
Test
Mar 4, 2020
9f7f91c
Fix tests
Mar 5, 2020
4cb007a
Update rtree unit test
Mar 5, 2020
326f339
Minor fixes
Mar 6, 2020
6d283a9
Revert unintended change
Mar 6, 2020
781fb29
Remove stale comment
Mar 6, 2020
858849b
Clean up
Mar 6, 2020
d482d2d
Fix unittest
Mar 7, 2020
00f86a5
Add tests for unobstructed platform views
Mar 9, 2020
b35dde1
Format dart code
Mar 9, 2020
423036d
Clean up
Mar 9, 2020
ed891cb
Remove old rtree
Mar 10, 2020
207beb4
Clean up
Mar 10, 2020
f6d1269
Remove duplicated entry after rebase
Mar 11, 2020
af7b916
Remove dependency
Mar 11, 2020
4100603
Revert changes from rebase
Mar 11, 2020
0c06c48
Delete transient files
Mar 11, 2020
f705462
nits
Mar 11, 2020
71e5beb
Pass ios_context
Mar 11, 2020
d4f4386
comments
Mar 12, 2020
7f2d64e
Add todo
Mar 12, 2020
f48860f
Add FinishFrame hook to embedded_views
Mar 14, 2020
32fbc8c
empty line
Mar 14, 2020
165d9ea
Missing method
Mar 14, 2020
41b8ac4
Feedback
Mar 18, 2020
8488382
Merge remote-tracking branch 'upstream/master' into unobstructed_pv
Mar 19, 2020
32f433a
Feedback
Mar 20, 2020
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
Prev Previous commit
Next Next commit
Fix platform view scenarios tests
  • Loading branch information
Emmanuel Garcia committed Mar 10, 2020
commit 3635a706bd5318bbacd9dde86c6efe5ff06cfc92
3 changes: 3 additions & 0 deletions flow/embedded_views.h
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,9 @@ class ExternalViewEmbedder {
// Must be called on the UI thread.
virtual SkCanvas* CompositeEmbeddedView(int view_id) = 0;

// Must be called on the UI thread.
virtual SkRect GetPlatformViewRect(int view_id) = 0;

virtual bool SubmitFrame(GrContext* context);

FML_DISALLOW_COPY_AND_ASSIGN(ExternalViewEmbedder);
Expand Down
12 changes: 3 additions & 9 deletions flow/layers/image_filter_layer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,9 @@ void ImageFilterLayer::Paint(PaintContext& context) const {
FML_DCHECK(needs_painting());

#ifndef SUPPORT_FRACTIONAL_TRANSLATION
SkAutoCanvasRestore save(context.background_canvas, true);
context.background_canvas->setMatrix(RasterCache::GetIntegralTransCTM(
context.background_canvas->getTotalMatrix()));

if (context.leaf_nodes_canvas != nullptr) {
SkAutoCanvasRestore save(context.leaf_nodes_canvas, true);
context.leaf_nodes_canvas->setMatrix(RasterCache::GetIntegralTransCTM(
context.leaf_nodes_canvas->getTotalMatrix()));
}
SkAutoCanvasRestore save(context.internal_nodes_canvas, true);
context.internal_nodes_canvas->setMatrix(RasterCache::GetIntegralTransCTM(
context.internal_nodes_canvas->getTotalMatrix()));
#endif

if (context.raster_cache) {
Expand Down
2 changes: 1 addition & 1 deletion flow/layers/performance_overlay_layer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ void PerformanceOverlayLayer::Paint(PaintContext& context) const {
SkScalar y = paint_bounds().y() + padding;
SkScalar width = paint_bounds().width() - (padding * 2);
SkScalar height = paint_bounds().height() / 2;
SkAutoCanvasRestore save(context.background_canvas, true);
SkAutoCanvasRestore save(context.internal_nodes_canvas, true);

VisualizeStopWatch(
*context.background_canvas, context.raster_time, x, y, width,
Expand Down
9 changes: 2 additions & 7 deletions flow/layers/picture_layer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,8 @@ void PictureLayer::Paint(PaintContext& context) const {
FML_DCHECK(picture_.get());
FML_DCHECK(needs_painting());

SkAutoCanvasRestore save(context.background_canvas, true);
context.background_canvas->translate(offset_.x(), offset_.y());

if (context.leaf_nodes_canvas != nullptr) {
SkAutoCanvasRestore save(context.leaf_nodes_canvas, true);
context.leaf_nodes_canvas->translate(offset_.x(), offset_.y());
}
SkAutoCanvasRestore save(context.internal_nodes_canvas, true);
context.internal_nodes_canvas->translate(offset_.x(), offset_.y());

#ifndef SUPPORT_FRACTIONAL_TRANSLATION
context.background_canvas->setMatrix(RasterCache::GetIntegralTransCTM(
Expand Down
6 changes: 6 additions & 0 deletions flow/layers/platform_view_layer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,11 @@ void PlatformViewLayer::Paint(PaintContext& context) const {
}
SkCanvas* canvas = context.view_embedder->CompositeEmbeddedView(view_id_);
context.leaf_nodes_canvas = canvas;
// Don't draw on the area covered by the platform view, since these drawings
// are on an overlay on top of the platform view. This prevent to see drawings
// on the background canvas if the platform view has opacity.
context.background_canvas->clipRect(
context.view_embedder->GetPlatformViewRect(view_id_),
SkClipOp::kDifference);
}
} // namespace flutter
141 changes: 49 additions & 92 deletions shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm
Original file line number Diff line number Diff line change
Expand Up @@ -370,7 +370,7 @@
//
// The UIKit frame is set based on the logical resolution instead of physical.
// (https://developer.apple.com/library/archive/documentation/DeviceInformation/Reference/iOSDeviceCompatibility/Displays/Displays.html).
// However, flow is based on the physical resolution. For example, 1000 pixels in flow equals
// However, flow is based on the physical resol ution. For eaxmple, 1000 pixels in flow equals
// 500 points in UIKit. And until this point, we did all the calculation based on the flow
// resolution. So we need to scale down to match UIKit's logical resolution.
CGFloat screenScale = [UIScreen mainScreen].scale;
Expand Down Expand Up @@ -430,12 +430,23 @@
layer_pool_->RecycleLayers();
}

SkRect FlutterPlatformViewsController::GetPlatformViewRect(int view_id) {
UIView* platform_view = [views_[view_id].get() view];
UIScreen* screen = [UIScreen mainScreen];
CGRect platform_view_cgrect = [platform_view convertRect:platform_view.bounds
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe consider get the platform_view rect based on flutter_view_ rect instead? I'm not certain but there might be situations where the flutter_view_ is not the same size as the screen? (add to app?)

Copy link
Author

@blasten blasten Mar 12, 2020

Choose a reason for hiding this comment

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

Done. can you think of a test case to exercise that?

Copy link
Contributor

Choose a reason for hiding this comment

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

There might be a way to set a custom flutter_view_ when initializing the application? I am not able to find public API to do so in engine header tho.
Maybe try to override FlutterViewController.view with a custom UIView to see if it works.

@xster We want to run a test against a flutter_view_ with custom rect (different from window) on iOS. Is there a way to override the flutter_view_'s when initializing the engine or FlutterViewController?

toCoordinateSpace:screen.coordinateSpace];
return SkRect::MakeXYWH(platform_view_cgrect.origin.x * screen.scale, //
platform_view_cgrect.origin.y * screen.scale, //
platform_view_cgrect.size.width * screen.scale, //
platform_view_cgrect.size.height * screen.scale //
);
}

bool FlutterPlatformViewsController::SubmitFrame(GrContext* gr_context,
std::shared_ptr<IOSContext> ios_context) {
DisposeViews();

bool did_submit = true;
CGFloat screenScale = [UIScreen mainScreen].scale;

// Maps a platform view id to a vector of `FlutterPlatformViewLayer`.
LayersMap platform_view_layers;
Expand All @@ -448,66 +459,10 @@
sk_sp<SkPicture> picture =
platform_views_recorder_[platform_view_id]->finishRecordingAsPicture();

std::shared_ptr<FlutterPlatformViewLayer> layer = layer_pool_->GetLayer(gr_context, gl_context);
std::unique_ptr<SurfaceFrame> frame = layer->surface->AcquireFrame(frame_size_);

layer->overlay_view.get().frame = flutter_view_.get().bounds;

std::vector<SkRect*> rects;
bbh->getAll(&rects);

SkCanvas* overlay_canvas = frame->SkiaCanvas();
overlay_canvas->clear(SK_ColorTRANSPARENT);

auto paint = SkPaint();
paint.setColor(SkColors::kRed);
paint.setStyle(SkPaint::Style::kStroke_Style);
paint.setStrokeWidth(5);


for (SkRect* rect : rects) {
FML_DLOG(ERROR) << " rect: " << rect->x() << "x" << rect->y();
overlay_canvas->drawRect(*rect, paint);
}

frame->Submit();

platform_view_layers[platform_view_id].push_back(layer);



// std::shared_ptr<FlutterPlatformViewLayer> layer = layer_pool_->GetLayer(gr_context, gl_context);
// CGFloat screenScale = [UIScreen mainScreen].scale;
// // Set the size of the overlay UIView.
// layer->overlay_view.get().backgroundColor = [UIColor blueColor];
// layer->overlay_view.get().frame =
// CGRectMake(rect.x() / screenScale, rect.y() / screenScale, rect.width() / screenScale,
// rect.height() / screenScale);

// SkISize rect_size = SkISize::Make(rect.width(), rect.height());
// std::unique_ptr<SurfaceFrame> frame = layer->surface->AcquireFrame(rect_size);

// // If frame is null, AcquireFrame already printed out an error message.
// if (frame == nullptr) {
// return layer;
// }
// SkCanvas* overlay_canvas = frame->SkiaCanvas();
// overlay_canvas->clear(SK_ColorTRANSPARENT);
// overlay_canvas->translate(-rect.x(), -rect.y());
// overlay_canvas->drawPicture(picture);

// layer->did_submit_last_frame = frame->Submit();

continue;

for (size_t j = i + 1; j > 0; j--) {
Copy link
Contributor

Choose a reason for hiding this comment

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

nits: for (size_t j = i; j >=0; j--) and composition_order_[j] below

Copy link
Author

Choose a reason for hiding this comment

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

that causes j to go below 0, which is an issue since size_t is unsigned.

Copy link
Contributor

Choose a reason for hiding this comment

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

I might have missed something, I don't see how j can go below 0 if we do something like:

 for (size_t j = i + 1; j >= 0; j--) {
  auto current_platform_view_id = composition_order_[j];

But yeah its just a personal style preference, feel free to ignore :)

Copy link
Author

Choose a reason for hiding this comment

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

if the condition is j >= 0, the loop will stop when j < 0.

int current_platform_view_id = composition_order_[j - 1];
EmbeddedViewParams params = platform_views_params_[current_platform_view_id];
SkRect platform_view_rect = SkRect::MakeXYWH(
/*x=*/params.offsetPixels.x(),
/*y=*/params.offsetPixels.y(),
/*width=*/params.sizePoints.width() * screenScale,
/*height=*/params.sizePoints.height() * screenScale);

SkRect platform_view_rect = GetPlatformViewRect(current_platform_view_id);

std::vector<SkRect*> intersection_rects;
bbh->searchRects(platform_view_rect, &intersection_rects);
Expand All @@ -522,7 +477,7 @@
}
// Get the intersection rect between the current joined rect
// and the platform view rect.
// joined_rect.intersect(platform_view_rect);
joined_rect.intersect(platform_view_rect);
auto layer = GetLayer(gr_context, ios_context, picture, joined_rect);
did_submit &= layer->did_submit_last_frame;
platform_view_layers[current_platform_view_id].push_back(layer);
Expand All @@ -531,7 +486,7 @@
// Get the intersection rect between the current rect
// and the platform view rect.
SkRect joined_rect = *rect;
// joined_rect.intersect(platform_view_rect);
joined_rect.intersect(platform_view_rect);
auto layer = GetLayer(gr_context, ios_context, picture, joined_rect);
did_submit &= layer->did_submit_last_frame;
platform_view_layers[current_platform_view_id].push_back(layer);
Expand All @@ -544,6 +499,7 @@

composition_order_.clear();
layer_pool_->RecycleLayers();

return did_submit;
}

Expand All @@ -553,13 +509,13 @@
for (size_t i = 0; i < composition_order_.size(); i++) {
int platform_view_id = composition_order_[i];
auto layers = layer_map[platform_view_id];
// UIView* platform_view_root = root_views_[platform_view_id].get();
UIView* platform_view_root = root_views_[platform_view_id].get();

// if (platform_view_root.superview != flutter_view) {
// [flutter_view addSubview:platform_view_root];
// } else {
// platform_view_root.layer.zPosition = zIndex++;
// }
if (platform_view_root.superview != flutter_view) {
[flutter_view addSubview:platform_view_root];
} else {
platform_view_root.layer.zPosition = zIndex++;
}
for (auto layer : layers) {
if ([layer->overlay_view superview] != flutter_view) {
[flutter_view addSubview:layer->overlay_view];
Expand All @@ -571,26 +527,6 @@
}
}

void FlutterPlatformViewsController::RemoveUnusedLayers() {
auto layers = layer_pool_->GetUnusedLayers();
for (auto layer : layers) {
[layer->overlay_view removeFromSuperview];
}

std::unordered_set<int64_t> composition_order_set;

for (int64_t view_id : composition_order_) {
composition_order_set.insert(view_id);
}
// Remove unused platform views.
for (int64_t view_id : active_composition_order_) {
if (composition_order_set.find(view_id) == composition_order_set.end()) {
UIView* platform_view_root = root_views_[view_id].get();
[platform_view_root removeFromSuperview];
}
}
}

std::shared_ptr<FlutterPlatformViewLayer> FlutterPlatformViewsController::GetLayer(
GrContext* gr_context,
std::shared_ptr<IOSContext> ios_context,
Expand All @@ -599,10 +535,11 @@
std::shared_ptr<FlutterPlatformViewLayer> layer = layer_pool_->GetLayer(gr_context, ios_context);
CGFloat screenScale = [UIScreen mainScreen].scale;
// Set the size of the overlay UIView.
layer->overlay_view.get().backgroundColor = [UIColor blueColor];
layer->overlay_view.get().frame =
CGRectMake(rect.x() / screenScale, rect.y() / screenScale, rect.width() / screenScale,
rect.height() / screenScale);
layer->overlay_view.get().frame = CGRectMake(rect.x() / screenScale, //
rect.y() / screenScale, //
rect.width() / screenScale, //
rect.height() / screenScale //
);

SkISize rect_size = SkISize::Make(rect.width(), rect.height());
std::unique_ptr<SurfaceFrame> frame = layer->surface->AcquireFrame(rect_size);
Expand All @@ -620,6 +557,26 @@
return layer;
}

void FlutterPlatformViewsController::RemoveUnusedLayers() {
auto layers = layer_pool_->GetUnusedLayers();
for (auto layer : layers) {
[layer->overlay_view removeFromSuperview];
}

std::unordered_set<int64_t> composition_order_set;

for (int64_t view_id : composition_order_) {
composition_order_set.insert(view_id);
}
// Remove unused platform views.
for (int64_t view_id : active_composition_order_) {
if (composition_order_set.find(view_id) == composition_order_set.end()) {
UIView* platform_view_root = root_views_[view_id].get();
[platform_view_root removeFromSuperview];
}
}
}

void FlutterPlatformViewsController::DisposeViews() {
if (views_to_dispose_.empty()) {
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,8 @@ class FlutterPlatformViewsController {

SkCanvas* CompositeEmbeddedView(int view_id);

SkRect GetPlatformViewRect(int view_id);

// Discards all platform views instances and auxiliary resources.
void Reset();

Expand Down
28 changes: 28 additions & 0 deletions shell/platform/darwin/ios/ios_surface_gl.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,34 @@ class IOSSurfaceGL final : public IOSSurface, public GPUSurfaceGLDelegate {
// |GPUSurfaceGLDelegate|
ExternalViewEmbedder* GetExternalViewEmbedder() override;

// |ExternalViewEmbedder|
SkCanvas* GetRootCanvas() override;

// |ExternalViewEmbedder|
void CancelFrame() override;

// |ExternalViewEmbedder|
void BeginFrame(SkISize frame_size, GrContext* context, double device_pixel_ratio) override;

// |ExternalViewEmbedder|
void PrerollCompositeEmbeddedView(int view_id,
std::unique_ptr<flutter::EmbeddedViewParams> params) override;

// |ExternalViewEmbedder|
PostPrerollResult PostPrerollAction(fml::RefPtr<fml::GpuThreadMerger> gpu_thread_merger) override;

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

// |ExternalViewEmbedder|
SkCanvas* CompositeEmbeddedView(int view_id) override;

// |ExternalViewEmbedder|
SkRect GetPlatformViewRect(int view_id) override;

// |ExternalViewEmbedder|
bool SubmitFrame(GrContext* context) override;

private:
std::unique_ptr<IOSRenderTargetGL> render_target_;

Expand Down
Loading