diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index e854c429bbde8..fe8900faa21f0 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -597,6 +597,8 @@ FILE: ../../../flutter/shell/platform/darwin/ios/framework/Headers/FlutterPlatfo FILE: ../../../flutter/shell/platform/darwin/ios/framework/Headers/FlutterPluginAppLifeCycleDelegate.h FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterCallbackCache.mm FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterCallbackCache_Internal.h +FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterOverlayView.h +FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterOverlayView.mm FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterPluginAppLifeCycleDelegate.mm FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/accessibility_text_entry.h FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/accessibility_text_entry.mm diff --git a/flow/embedded_views.h b/flow/embedded_views.h index 10740f6d0e23d..a36d941ee3476 100644 --- a/flow/embedded_views.h +++ b/flow/embedded_views.h @@ -6,6 +6,7 @@ #define FLUTTER_FLOW_EMBEDDED_VIEWS_H_ #include "flutter/fml/memory/ref_counted.h" +#include "third_party/skia/include/core/SkCanvas.h" #include "third_party/skia/include/core/SkPoint.h" #include "third_party/skia/include/core/SkSize.h" @@ -15,6 +16,7 @@ class EmbeddedViewParams { public: SkPoint offsetPixels; SkSize sizePoints; + SkISize canvasBaseLayerSize; }; // This is only used on iOS when running in a non headless mode, @@ -25,8 +27,8 @@ class ExternalViewEmbedder { ExternalViewEmbedder() = default; // Must be called on the UI thread. - virtual void CompositeEmbeddedView(int view_id, - const EmbeddedViewParams& params) {} + virtual SkCanvas* CompositeEmbeddedView(int view_id, + const EmbeddedViewParams& params) = 0; virtual ~ExternalViewEmbedder() = default; diff --git a/flow/layers/clip_path_layer.cc b/flow/layers/clip_path_layer.cc index 3c71823c48503..0726d884472b5 100644 --- a/flow/layers/clip_path_layer.cc +++ b/flow/layers/clip_path_layer.cc @@ -50,14 +50,14 @@ void ClipPathLayer::Paint(PaintContext& context) const { TRACE_EVENT0("flutter", "ClipPathLayer::Paint"); FML_DCHECK(needs_painting()); - SkAutoCanvasRestore save(&context.canvas, true); - context.canvas.clipPath(clip_path_, clip_behavior_ != Clip::hardEdge); + SkAutoCanvasRestore save(context.canvas, true); + context.canvas->clipPath(clip_path_, clip_behavior_ != Clip::hardEdge); if (clip_behavior_ == Clip::antiAliasWithSaveLayer) { - context.canvas.saveLayer(paint_bounds(), nullptr); + context.canvas->saveLayer(paint_bounds(), nullptr); } PaintChildren(context); if (clip_behavior_ == Clip::antiAliasWithSaveLayer) { - context.canvas.restore(); + context.canvas->restore(); } } diff --git a/flow/layers/clip_rect_layer.cc b/flow/layers/clip_rect_layer.cc index 733acfcebd072..aabcf5c3e5cfc 100644 --- a/flow/layers/clip_rect_layer.cc +++ b/flow/layers/clip_rect_layer.cc @@ -41,14 +41,14 @@ void ClipRectLayer::Paint(PaintContext& context) const { TRACE_EVENT0("flutter", "ClipRectLayer::Paint"); FML_DCHECK(needs_painting()); - SkAutoCanvasRestore save(&context.canvas, true); - context.canvas.clipRect(paint_bounds(), clip_behavior_ != Clip::hardEdge); + SkAutoCanvasRestore save(context.canvas, true); + context.canvas->clipRect(paint_bounds(), clip_behavior_ != Clip::hardEdge); if (clip_behavior_ == Clip::antiAliasWithSaveLayer) { - context.canvas.saveLayer(paint_bounds(), nullptr); + context.canvas->saveLayer(paint_bounds(), nullptr); } PaintChildren(context); if (clip_behavior_ == Clip::antiAliasWithSaveLayer) { - context.canvas.restore(); + context.canvas->restore(); } } diff --git a/flow/layers/clip_rrect_layer.cc b/flow/layers/clip_rrect_layer.cc index 046a0d45404ef..2434e509d0910 100644 --- a/flow/layers/clip_rrect_layer.cc +++ b/flow/layers/clip_rrect_layer.cc @@ -48,14 +48,14 @@ void ClipRRectLayer::Paint(PaintContext& context) const { TRACE_EVENT0("flutter", "ClipRRectLayer::Paint"); FML_DCHECK(needs_painting()); - SkAutoCanvasRestore save(&context.canvas, true); - context.canvas.clipRRect(clip_rrect_, clip_behavior_ != Clip::hardEdge); + SkAutoCanvasRestore save(context.canvas, true); + context.canvas->clipRRect(clip_rrect_, clip_behavior_ != Clip::hardEdge); if (clip_behavior_ == Clip::antiAliasWithSaveLayer) { - context.canvas.saveLayer(paint_bounds(), nullptr); + context.canvas->saveLayer(paint_bounds(), nullptr); } PaintChildren(context); if (clip_behavior_ == Clip::antiAliasWithSaveLayer) { - context.canvas.restore(); + context.canvas->restore(); } } diff --git a/flow/layers/layer.cc b/flow/layers/layer.cc index c1d91872127ab..e629241d6ce8d 100644 --- a/flow/layers/layer.cc +++ b/flow/layers/layer.cc @@ -26,13 +26,13 @@ Layer::AutoSaveLayer::AutoSaveLayer(const PaintContext& paint_context, const SkRect& bounds, const SkPaint* paint) : paint_context_(paint_context), bounds_(bounds) { - paint_context_.canvas.saveLayer(bounds_, paint); + paint_context_.canvas->saveLayer(bounds_, paint); } Layer::AutoSaveLayer::AutoSaveLayer(const PaintContext& paint_context, const SkCanvas::SaveLayerRec& layer_rec) : paint_context_(paint_context), bounds_(*layer_rec.fBounds) { - paint_context_.canvas.saveLayer(layer_rec); + paint_context_.canvas->saveLayer(layer_rec); } Layer::AutoSaveLayer Layer::AutoSaveLayer::Create( @@ -50,9 +50,9 @@ Layer::AutoSaveLayer Layer::AutoSaveLayer::Create( Layer::AutoSaveLayer::~AutoSaveLayer() { if (paint_context_.checkerboard_offscreen_layers) { - DrawCheckerboard(&paint_context_.canvas, bounds_); + DrawCheckerboard(paint_context_.canvas, bounds_); } - paint_context_.canvas.restore(); + paint_context_.canvas->restore(); } } // namespace flow diff --git a/flow/layers/layer.h b/flow/layers/layer.h index dbd101d6cc9b8..098ae5f789e07 100644 --- a/flow/layers/layer.h +++ b/flow/layers/layer.h @@ -64,7 +64,7 @@ class Layer { virtual void Preroll(PrerollContext* context, const SkMatrix& matrix); struct PaintContext { - SkCanvas& canvas; + SkCanvas* canvas; ExternalViewEmbedder* view_embedder; const Stopwatch& frame_time; const Stopwatch& engine_time; diff --git a/flow/layers/layer_tree.cc b/flow/layers/layer_tree.cc index 6896bb112b6a1..942f5cc9a2060 100644 --- a/flow/layers/layer_tree.cc +++ b/flow/layers/layer_tree.cc @@ -67,7 +67,7 @@ void LayerTree::Paint(CompositorContext::ScopedFrame& frame, bool ignore_raster_cache) const { TRACE_EVENT0("flutter", "LayerTree::Paint"); Layer::PaintContext context = { - *frame.canvas(), + frame.canvas(), frame.view_embedder(), frame.context().frame_time(), frame.context().engine_time(), @@ -107,7 +107,7 @@ sk_sp LayerTree::Flatten(const SkRect& bounds) { }; Layer::PaintContext paint_context = { - *canvas, // canvas + canvas, // canvas nullptr, unused_stopwatch, // frame time (dont care) unused_stopwatch, // engine time (dont care) diff --git a/flow/layers/opacity_layer.cc b/flow/layers/opacity_layer.cc index ebbced6f605a1..7d658b3726e1b 100644 --- a/flow/layers/opacity_layer.cc +++ b/flow/layers/opacity_layer.cc @@ -31,20 +31,20 @@ void OpacityLayer::Paint(PaintContext& context) const { SkPaint paint; paint.setAlpha(alpha_); - SkAutoCanvasRestore save(&context.canvas, true); - context.canvas.translate(offset_.fX, offset_.fY); + SkAutoCanvasRestore save(context.canvas, true); + context.canvas->translate(offset_.fX, offset_.fY); #ifndef SUPPORT_FRACTIONAL_TRANSLATION - context.canvas.setMatrix( - RasterCache::GetIntegralTransCTM(context.canvas.getTotalMatrix())); + context.canvas->setMatrix( + RasterCache::GetIntegralTransCTM(context.canvas->getTotalMatrix())); #endif if (layers().size() == 1 && context.raster_cache) { - const SkMatrix& ctm = context.canvas.getTotalMatrix(); + const SkMatrix& ctm = context.canvas->getTotalMatrix(); RasterCacheResult child_cache = context.raster_cache->Get(layers()[0].get(), ctm); if (child_cache.is_valid()) { - child_cache.draw(context.canvas, &paint); + child_cache.draw(*context.canvas, &paint); return; } } diff --git a/flow/layers/performance_overlay_layer.cc b/flow/layers/performance_overlay_layer.cc index 7d871af33b94f..9e014c57a08e5 100644 --- a/flow/layers/performance_overlay_layer.cc +++ b/flow/layers/performance_overlay_layer.cc @@ -73,14 +73,14 @@ 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.canvas, true); + SkAutoCanvasRestore save(context.canvas, true); - VisualizeStopWatch(context.canvas, context.frame_time, x, y, width, + VisualizeStopWatch(*context.canvas, context.frame_time, x, y, width, height - padding, options_ & kVisualizeRasterizerStatistics, options_ & kDisplayRasterizerStatistics, "GPU"); - VisualizeStopWatch(context.canvas, context.engine_time, x, y + height, width, + VisualizeStopWatch(*context.canvas, context.engine_time, x, y + height, width, height - padding, options_ & kVisualizeEngineStatistics, options_ & kDisplayEngineStatistics, "UI"); } diff --git a/flow/layers/physical_shape_layer.cc b/flow/layers/physical_shape_layer.cc index e10caaa56feed..6490413d62bc9 100644 --- a/flow/layers/physical_shape_layer.cc +++ b/flow/layers/physical_shape_layer.cc @@ -83,7 +83,7 @@ void PhysicalShapeLayer::Paint(PaintContext& context) const { FML_DCHECK(needs_painting()); if (elevation_ != 0) { - DrawShadow(&context.canvas, path_, shadow_color_, elevation_, + DrawShadow(context.canvas, path_, shadow_color_, elevation_, SkColorGetA(color_) != 0xff, device_pixel_ratio_); } @@ -91,20 +91,20 @@ void PhysicalShapeLayer::Paint(PaintContext& context) const { SkPaint paint; paint.setColor(color_); if (clip_behavior_ != Clip::antiAliasWithSaveLayer) { - context.canvas.drawPath(path_, paint); + context.canvas->drawPath(path_, paint); } - int saveCount = context.canvas.save(); + int saveCount = context.canvas->save(); switch (clip_behavior_) { case Clip::hardEdge: - context.canvas.clipPath(path_, false); + context.canvas->clipPath(path_, false); break; case Clip::antiAlias: - context.canvas.clipPath(path_, true); + context.canvas->clipPath(path_, true); break; case Clip::antiAliasWithSaveLayer: - context.canvas.clipPath(path_, true); - context.canvas.saveLayer(paint_bounds(), nullptr); + context.canvas->clipPath(path_, true); + context.canvas->saveLayer(paint_bounds(), nullptr); break; case Clip::none: break; @@ -115,12 +115,12 @@ void PhysicalShapeLayer::Paint(PaintContext& context) const { // (https://github.com/flutter/flutter/issues/18057#issue-328003931) // using saveLayer, we have to call drawPaint instead of drawPath as // anti-aliased drawPath will always have such artifacts. - context.canvas.drawPaint(paint); + context.canvas->drawPaint(paint); } PaintChildren(context); - context.canvas.restoreToCount(saveCount); + context.canvas->restoreToCount(saveCount); } void PhysicalShapeLayer::DrawShadow(SkCanvas* canvas, diff --git a/flow/layers/picture_layer.cc b/flow/layers/picture_layer.cc index 9dcef880b7313..412859b689ea9 100644 --- a/flow/layers/picture_layer.cc +++ b/flow/layers/picture_layer.cc @@ -34,22 +34,22 @@ void PictureLayer::Paint(PaintContext& context) const { FML_DCHECK(picture_.get()); FML_DCHECK(needs_painting()); - SkAutoCanvasRestore save(&context.canvas, true); - context.canvas.translate(offset_.x(), offset_.y()); + SkAutoCanvasRestore save(context.canvas, true); + context.canvas->translate(offset_.x(), offset_.y()); #ifndef SUPPORT_FRACTIONAL_TRANSLATION - context.canvas.setMatrix( - RasterCache::GetIntegralTransCTM(context.canvas.getTotalMatrix())); + context.canvas->setMatrix( + RasterCache::GetIntegralTransCTM(context.canvas->getTotalMatrix())); #endif if (context.raster_cache) { - const SkMatrix& ctm = context.canvas.getTotalMatrix(); + const SkMatrix& ctm = context.canvas->getTotalMatrix(); RasterCacheResult result = context.raster_cache->Get(*picture(), ctm); if (result.is_valid()) { - result.draw(context.canvas); + result.draw(*context.canvas); return; } } - context.canvas.drawPicture(picture()); + context.canvas->drawPicture(picture()); } } // namespace flow diff --git a/flow/layers/platform_view_layer.cc b/flow/layers/platform_view_layer.cc index 19057fbfd4b9c..efcddbcc98175 100644 --- a/flow/layers/platform_view_layer.cc +++ b/flow/layers/platform_view_layer.cc @@ -23,11 +23,16 @@ void PlatformViewLayer::Paint(PaintContext& context) const { return; } EmbeddedViewParams params; - SkMatrix transform = context.canvas.getTotalMatrix(); + SkMatrix transform = context.canvas->getTotalMatrix(); params.offsetPixels = SkPoint::Make(transform.getTranslateX(), transform.getTranslateY()); params.sizePoints = size_; + params.canvasBaseLayerSize = context.canvas->getBaseLayerSize(); - context.view_embedder->CompositeEmbeddedView(view_id_, params); + 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 diff --git a/flow/layers/shader_mask_layer.cc b/flow/layers/shader_mask_layer.cc index 6cb73bbf64855..f87cce48b89ff 100644 --- a/flow/layers/shader_mask_layer.cc +++ b/flow/layers/shader_mask_layer.cc @@ -21,8 +21,8 @@ void ShaderMaskLayer::Paint(PaintContext& context) const { SkPaint paint; paint.setBlendMode(blend_mode_); paint.setShader(shader_); - context.canvas.translate(mask_rect_.left(), mask_rect_.top()); - context.canvas.drawRect( + context.canvas->translate(mask_rect_.left(), mask_rect_.top()); + context.canvas->drawRect( SkRect::MakeWH(mask_rect_.width(), mask_rect_.height()), paint); } diff --git a/flow/layers/texture_layer.cc b/flow/layers/texture_layer.cc index 52ebdc37dbcab..cb9f63249b73e 100644 --- a/flow/layers/texture_layer.cc +++ b/flow/layers/texture_layer.cc @@ -23,7 +23,7 @@ void TextureLayer::Paint(PaintContext& context) const { if (!texture) { return; } - texture->Paint(context.canvas, paint_bounds(), freeze_); + texture->Paint(*context.canvas, paint_bounds(), freeze_); } } // namespace flow diff --git a/flow/layers/transform_layer.cc b/flow/layers/transform_layer.cc index a70cc299dd9a4..a96e0e27d7560 100644 --- a/flow/layers/transform_layer.cc +++ b/flow/layers/transform_layer.cc @@ -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.canvas, true); + context.canvas->concat(transform_); PaintChildren(context); } diff --git a/flow/raster_cache.cc b/flow/raster_cache.cc index d20c65df5b1ff..a92e1285379a7 100644 --- a/flow/raster_cache.cc +++ b/flow/raster_cache.cc @@ -157,7 +157,7 @@ void RasterCache::Prepare(PrerollContext* context, checkerboard_images_, layer->paint_bounds(), [layer, context](SkCanvas* canvas) { Layer::PaintContext paintContext = { - *canvas, + canvas, nullptr, context->frame_time, context->engine_time, diff --git a/shell/platform/darwin/ios/BUILD.gn b/shell/platform/darwin/ios/BUILD.gn index 15a14ad82bea4..80c2e31bd05f0 100644 --- a/shell/platform/darwin/ios/BUILD.gn +++ b/shell/platform/darwin/ios/BUILD.gn @@ -57,6 +57,8 @@ shared_library("create_flutter_framework_dylib") { "framework/Source/FlutterHeadlessDartRunner.mm", "framework/Source/FlutterObservatoryPublisher.h", "framework/Source/FlutterObservatoryPublisher.mm", + "framework/Source/FlutterOverlayView.h", + "framework/Source/FlutterOverlayView.mm", "framework/Source/FlutterPlatformPlugin.h", "framework/Source/FlutterPlatformPlugin.mm", "framework/Source/FlutterPlatformViews_Internal.h", diff --git a/shell/platform/darwin/ios/framework/Source/FlutterOverlayView.h b/shell/platform/darwin/ios/framework/Source/FlutterOverlayView.h new file mode 100644 index 0000000000000..527253fb73648 --- /dev/null +++ b/shell/platform/darwin/ios/framework/Source/FlutterOverlayView.h @@ -0,0 +1,28 @@ +// Copyright 2018 The Chromium 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 SHELL_PLATFORM_IOS_FRAMEWORK_SOURCE_FLUTTER_OVERLAY_VIEW_H_ +#define SHELL_PLATFORM_IOS_FRAMEWORK_SOURCE_FLUTTER_OVERLAY_VIEW_H_ + +#include + +#include + +#import "FlutterPlatformViews_Internal.h" + +#include "flutter/fml/memory/weak_ptr.h" +#include "flutter/shell/common/shell.h" +#include "flutter/shell/platform/darwin/ios/ios_surface.h" + +@interface FlutterOverlayView : UIView + +- (instancetype)initWithFrame:(CGRect)frame NS_UNAVAILABLE; +- (instancetype)initWithCoder:(NSCoder*)aDecoder NS_UNAVAILABLE; + +- (instancetype)init NS_DESIGNATED_INITIALIZER; +- (std::unique_ptr)createSurface; + +@end + +#endif // SHELL_PLATFORM_IOS_FRAMEWORK_SOURCE_FLUTTER_OVERLAY_VIEW_H_ diff --git a/shell/platform/darwin/ios/framework/Source/FlutterOverlayView.mm b/shell/platform/darwin/ios/framework/Source/FlutterOverlayView.mm new file mode 100644 index 0000000000000..9ed7c71ca9d72 --- /dev/null +++ b/shell/platform/darwin/ios/framework/Source/FlutterOverlayView.mm @@ -0,0 +1,78 @@ +// Copyright 2018 The Chromium 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/shell/platform/darwin/ios/framework/Source/FlutterOverlayView.h" + +#include "flutter/common/settings.h" +#include "flutter/common/task_runners.h" +#include "flutter/flow/layers/layer_tree.h" +#include "flutter/fml/platform/darwin/cf_utils.h" +#include "flutter/fml/synchronization/waitable_event.h" +#include "flutter/fml/trace_event.h" +#include "flutter/shell/common/platform_view.h" +#include "flutter/shell/common/rasterizer.h" +#include "flutter/shell/platform/darwin/ios/ios_surface_gl.h" +#include "flutter/shell/platform/darwin/ios/ios_surface_software.h" +#include "third_party/skia/include/utils/mac/SkCGUtils.h" + +// This is mostly a duplication of FlutterView. +// TODO(amirh): once GL support is in evaluate if we can merge this with FlutterView. +@implementation FlutterOverlayView + +- (instancetype)initWithFrame:(CGRect)frame { + @throw([NSException exceptionWithName:@"FlutterOverlayView must initWithDelegate" + reason:nil + userInfo:nil]); +} + +- (instancetype)initWithCoder:(NSCoder*)aDecoder { + @throw([NSException exceptionWithName:@"FlutterOverlayView must initWithDelegate" + reason:nil + userInfo:nil]); +} + +- (instancetype)init { + self = [super initWithFrame:CGRectZero]; + + if (self) { + self.layer.opaque = NO; + self.userInteractionEnabled = NO; + } + + return self; +} + +- (void)layoutSubviews { + if ([self.layer isKindOfClass:[CAEAGLLayer class]]) { + CAEAGLLayer* layer = reinterpret_cast(self.layer); + layer.allowsGroupOpacity = NO; + CGFloat screenScale = [UIScreen mainScreen].scale; + layer.contentsScale = screenScale; + layer.rasterizationScale = screenScale; + } + + [super layoutSubviews]; +} + ++ (Class)layerClass { +#if TARGET_IPHONE_SIMULATOR + return [CALayer class]; +#else // TARGET_IPHONE_SIMULATOR + return [CAEAGLLayer class]; +#endif // TARGET_IPHONE_SIMULATOR +} + +- (std::unique_ptr)createSurface { + if ([self.layer isKindOfClass:[CAEAGLLayer class]]) { + // TODO(amirh): create a GL surface. + return nullptr; + } else { + fml::scoped_nsobject layer(reinterpret_cast([self.layer retain])); + return std::make_unique(std::move(layer), nullptr); + } +} + +// TODO(amirh): implement drawLayer to suppoer snapshotting. + +@end diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm index 2f4cefa84d5d0..798839fab4d1c 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm @@ -2,6 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#import + +#import "FlutterOverlayView.h" +#import "flutter/shell/platform/darwin/ios/ios_surface.h" + #include #include #include @@ -10,8 +15,6 @@ #include "flutter/fml/platform/darwin/scoped_nsobject.h" #include "flutter/shell/platform/darwin/ios/framework/Headers/FlutterChannels.h" -#import - namespace shell { void FlutterPlatformViewsController::SetFlutterView(UIView* flutter_view) { @@ -45,7 +48,7 @@ long viewId = [args[@"id"] longValue]; std::string viewType([args[@"viewType"] UTF8String]); - if (views_[viewId] != nil) { + if (views_.count(viewId) != 0) { result([FlutterError errorWithCode:@"recreating_view" message:@"trying to create an already created view" details:[NSString stringWithFormat:@"view id: '%ld'", viewId]]); @@ -84,7 +87,7 @@ NSDictionary* args = [call arguments]; int64_t viewId = [args[@"id"] longLongValue]; - if (views_[viewId] == nil) { + if (views_.count(viewId) == 0) { result([FlutterError errorWithCode:@"unknown_view" message:@"trying to dispose an unknown" details:[NSString stringWithFormat:@"view id: '%lld'", viewId]]); @@ -94,6 +97,7 @@ UIView* view = views_[viewId].get(); [view removeFromSuperview]; views_.erase(viewId); + overlays_.erase(viewId); result(nil); } @@ -102,7 +106,7 @@ NSDictionary* args = [call arguments]; int64_t viewId = [args[@"id"] longLongValue]; - if (views_[viewId] == nil) { + if (views_.count(viewId) == 0) { result([FlutterError errorWithCode:@"unknown_view" message:@"trying to set gesture state for an unknown view" details:[NSString stringWithFormat:@"view id: '%lld'", viewId]]); @@ -124,25 +128,39 @@ fml::scoped_nsobject>([factory retain]); } -void FlutterPlatformViewsController::CompositeEmbeddedView(int view_id, - const flow::EmbeddedViewParams& params) { +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]; + 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(); + canvas->clear(SK_ColorTRANSPARENT); + return canvas; } -void FlutterPlatformViewsController::Present() { +bool FlutterPlatformViewsController::Present() { + bool did_submit = true; + for (size_t i = 0; i < composition_frames_.size(); i++) { + did_submit &= composition_frames_[i]->Submit(); + } + composition_frames_.clear(); if (composition_order_ == active_composition_order_) { composition_order_.clear(); - return; + return did_submit; } UIView* flutter_view = flutter_view_.get(); @@ -159,10 +177,26 @@ for (size_t i = 0; i < composition_order_.size(); i++) { int view_id = composition_order_[i]; [flutter_view addSubview:views_[view_id].get()]; + [flutter_view addSubview:overlays_[view_id]->overlay_view.get()]; active_composition_order_.push_back(view_id); } composition_order_.clear(); + return did_submit; +} + +void FlutterPlatformViewsController::EnsureOverlayInitialized(int64_t overlay_id) { + if (overlays_.count(overlay_id) != 0) { + return; + } + FlutterOverlayView* overlay_view = [[FlutterOverlayView alloc] init]; + overlay_view.frame = flutter_view_.get().bounds; + overlay_view.autoresizingMask = + (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight); + std::unique_ptr ios_surface = overlay_view.createSurface; + std::unique_ptr surface = ios_surface->CreateGPUSurface(); + overlays_[overlay_id] = std::make_unique( + overlay_view, std::move(ios_surface), std::move(surface)); } } // namespace shell diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h index 3a749a11d0d3f..92d308c244d43 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h @@ -26,6 +26,21 @@ namespace shell { +class IOSSurface; + +struct FlutterPlatformViewLayer { + FlutterPlatformViewLayer(UIView* overlay_view, + std::unique_ptr ios_surface, + std::unique_ptr surface) + : overlay_view([overlay_view retain]), + ios_surface(std::move(ios_surface)), + surface(std::move(surface)){}; + + fml::scoped_nsobject overlay_view; + std::unique_ptr ios_surface; + std::unique_ptr surface; +}; + class FlutterPlatformViewsController { public: FlutterPlatformViewsController() = default; @@ -34,9 +49,11 @@ class FlutterPlatformViewsController { void RegisterViewFactory(NSObject* factory, NSString* factoryId); - void CompositeEmbeddedView(int view_id, const flow::EmbeddedViewParams& params); + SkCanvas* CompositeEmbeddedView(int view_id, + const flow::EmbeddedViewParams& params, + IOSSurface& surface); - void Present(); + bool Present(); void OnMethodCall(FlutterMethodCall* call, FlutterResult& result); @@ -45,6 +62,7 @@ class FlutterPlatformViewsController { fml::scoped_nsobject flutter_view_; std::map>> factories_; std::map> views_; + std::map> overlays_; // 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. @@ -53,10 +71,14 @@ class FlutterPlatformViewsController { // The latest composition order that was presented in Present(). std::vector active_composition_order_; + std::vector> composition_frames_; + void OnCreate(FlutterMethodCall* call, FlutterResult& result); void OnDispose(FlutterMethodCall* call, FlutterResult& result); void OnAcceptGesture(FlutterMethodCall* call, FlutterResult& result); + void EnsureOverlayInitialized(int64_t overlay_id); + FML_DISALLOW_COPY_AND_ASSIGN(FlutterPlatformViewsController); }; diff --git a/shell/platform/darwin/ios/framework/Source/FlutterView.mm b/shell/platform/darwin/ios/framework/Source/FlutterView.mm index 3909f6367ee2e..b64fe4c2488a2 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterView.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterView.mm @@ -80,11 +80,11 @@ + (Class)layerClass { fml::scoped_nsobject eagl_layer( reinterpret_cast([self.layer retain])); return std::make_unique(std::move(eagl_layer), - *[_delegate platformViewsController]); + [_delegate platformViewsController]); } else { fml::scoped_nsobject layer(reinterpret_cast([self.layer retain])); return std::make_unique(std::move(layer), - *[_delegate platformViewsController]); + [_delegate platformViewsController]); } } diff --git a/shell/platform/darwin/ios/ios_surface.h b/shell/platform/darwin/ios/ios_surface.h index f0f835e684342..52711f1e68b6a 100644 --- a/shell/platform/darwin/ios/ios_surface.h +++ b/shell/platform/darwin/ios/ios_surface.h @@ -17,7 +17,7 @@ namespace shell { class IOSSurface { public: - IOSSurface(FlutterPlatformViewsController& platform_views_controller); + IOSSurface(FlutterPlatformViewsController* platform_views_controller); virtual ~IOSSurface(); @@ -30,10 +30,10 @@ class IOSSurface { virtual std::unique_ptr CreateGPUSurface() = 0; protected: - FlutterPlatformViewsController& GetPlatformViewsController(); + FlutterPlatformViewsController* GetPlatformViewsController(); private: - FlutterPlatformViewsController& platform_views_controller_; + FlutterPlatformViewsController* platform_views_controller_; public: FML_DISALLOW_COPY_AND_ASSIGN(IOSSurface); diff --git a/shell/platform/darwin/ios/ios_surface.mm b/shell/platform/darwin/ios/ios_surface.mm index 1a62e70e59b15..ba7bf4f93ed3f 100644 --- a/shell/platform/darwin/ios/ios_surface.mm +++ b/shell/platform/darwin/ios/ios_surface.mm @@ -11,12 +11,12 @@ namespace shell { -IOSSurface::IOSSurface(FlutterPlatformViewsController& platform_views_controller) +IOSSurface::IOSSurface(FlutterPlatformViewsController* platform_views_controller) : platform_views_controller_(platform_views_controller) {} IOSSurface::~IOSSurface() = default; -FlutterPlatformViewsController& IOSSurface::GetPlatformViewsController() { +FlutterPlatformViewsController* IOSSurface::GetPlatformViewsController() { return platform_views_controller_; } } // namespace shell diff --git a/shell/platform/darwin/ios/ios_surface_gl.h b/shell/platform/darwin/ios/ios_surface_gl.h index a2765890eb3bd..a6bcfbdf45d46 100644 --- a/shell/platform/darwin/ios/ios_surface_gl.h +++ b/shell/platform/darwin/ios/ios_surface_gl.h @@ -20,7 +20,7 @@ class IOSSurfaceGL : public IOSSurface, public flow::ExternalViewEmbedder { public: IOSSurfaceGL(fml::scoped_nsobject layer, - FlutterPlatformViewsController& platform_views_controller); + FlutterPlatformViewsController* platform_views_controller); ~IOSSurfaceGL() override; @@ -46,7 +46,7 @@ class IOSSurfaceGL : public IOSSurface, flow::ExternalViewEmbedder* GetExternalViewEmbedder() override; // |flow::ExternalViewEmbedder| - void CompositeEmbeddedView(int view_id, const flow::EmbeddedViewParams& params) override; + SkCanvas* CompositeEmbeddedView(int view_id, const flow::EmbeddedViewParams& params) override; private: IOSGLContext context_; diff --git a/shell/platform/darwin/ios/ios_surface_gl.mm b/shell/platform/darwin/ios/ios_surface_gl.mm index b65015e4d56d1..24f2a3af67c1d 100644 --- a/shell/platform/darwin/ios/ios_surface_gl.mm +++ b/shell/platform/darwin/ios/ios_surface_gl.mm @@ -10,7 +10,7 @@ namespace shell { IOSSurfaceGL::IOSSurfaceGL(fml::scoped_nsobject layer, - FlutterPlatformViewsController& platform_views_controller) + FlutterPlatformViewsController* platform_views_controller) : IOSSurface(platform_views_controller), context_(std::move(layer)) {} IOSSurfaceGL::~IOSSurfaceGL() = default; @@ -59,16 +59,21 @@ return false; } - GetPlatformViewsController().Present(); - return true; + FlutterPlatformViewsController* platform_views_controller = GetPlatformViewsController(); + if (platform_views_controller == nullptr) { + return true; + } + return platform_views_controller->Present(); } flow::ExternalViewEmbedder* IOSSurfaceGL::GetExternalViewEmbedder() { return this; } -void IOSSurfaceGL::CompositeEmbeddedView(int view_id, const flow::EmbeddedViewParams& params) { - GetPlatformViewsController().CompositeEmbeddedView(view_id, params); +SkCanvas* IOSSurfaceGL::CompositeEmbeddedView(int view_id, const flow::EmbeddedViewParams& params) { + FlutterPlatformViewsController* platform_views_controller = GetPlatformViewsController(); + FML_CHECK(platform_views_controller != nullptr); + return platform_views_controller->CompositeEmbeddedView(view_id, params, *this); } } // namespace shell diff --git a/shell/platform/darwin/ios/ios_surface_software.h b/shell/platform/darwin/ios/ios_surface_software.h index 6abfeecf0b17c..2e5da95e2b48f 100644 --- a/shell/platform/darwin/ios/ios_surface_software.h +++ b/shell/platform/darwin/ios/ios_surface_software.h @@ -20,7 +20,7 @@ class IOSSurfaceSoftware final : public IOSSurface, public flow::ExternalViewEmbedder { public: IOSSurfaceSoftware(fml::scoped_nsobject layer, - FlutterPlatformViewsController& platform_views_controller); + FlutterPlatformViewsController* platform_views_controller); ~IOSSurfaceSoftware() override; @@ -46,7 +46,7 @@ class IOSSurfaceSoftware final : public IOSSurface, flow::ExternalViewEmbedder* GetExternalViewEmbedder() override; // |flow::ExternalViewEmbedder| - void CompositeEmbeddedView(int view_id, const flow::EmbeddedViewParams& params) override; + SkCanvas* CompositeEmbeddedView(int view_id, const flow::EmbeddedViewParams& params) override; private: fml::scoped_nsobject layer_; diff --git a/shell/platform/darwin/ios/ios_surface_software.mm b/shell/platform/darwin/ios/ios_surface_software.mm index 2c561b78c397b..a35d806729b83 100644 --- a/shell/platform/darwin/ios/ios_surface_software.mm +++ b/shell/platform/darwin/ios/ios_surface_software.mm @@ -16,7 +16,7 @@ namespace shell { IOSSurfaceSoftware::IOSSurfaceSoftware(fml::scoped_nsobject layer, - FlutterPlatformViewsController& platform_views_controller) + FlutterPlatformViewsController* platform_views_controller) : IOSSurface(platform_views_controller), layer_(std::move(layer)) { UpdateStorageSizeIfNecessary(); } @@ -123,17 +123,22 @@ layer_.get().contents = reinterpret_cast(static_cast(pixmap_image)); - GetPlatformViewsController().Present(); - - return true; + FlutterPlatformViewsController* platform_views_controller = GetPlatformViewsController(); + if (platform_views_controller == nullptr) { + return true; + } + return platform_views_controller->Present(); } flow::ExternalViewEmbedder* IOSSurfaceSoftware::GetExternalViewEmbedder() { return this; } -void IOSSurfaceSoftware::CompositeEmbeddedView(int view_id, - const flow::EmbeddedViewParams& params) { - GetPlatformViewsController().CompositeEmbeddedView(view_id, params); + +SkCanvas* IOSSurfaceSoftware::CompositeEmbeddedView(int view_id, + const flow::EmbeddedViewParams& params) { + FlutterPlatformViewsController* platform_views_controller = GetPlatformViewsController(); + FML_CHECK(platform_views_controller != nullptr); + return platform_views_controller->CompositeEmbeddedView(view_id, params, *this); } } // namespace shell