Plumb the iOS PlatformViewsController into flow. (#6603)

For flow to manipulate the embedded UIViews during the paint traversal
it needs some hook in PaintContext.
This PR introduces a ViewEmbeder interface that is implemented by the
iOS PlatformViewsController and plumbs it into PaintContext.

The ViewEmbedder interface is mainly a place holder at this point, as
this PR is focused on just the plumbing.
This commit is contained in:
Amir Hardon 2018-10-26 14:26:59 -07:00 committed by GitHub
parent 2bfb893cf3
commit df85722fa0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
27 changed files with 178 additions and 23 deletions

View File

@ -11,6 +11,7 @@ ORIGIN: ../../../flutter/flow/layers/physical_shape_layer.cc + ../../../LICENSE
TYPE: LicenseType.bsd
FILE: ../../../flutter/flow/debug_print.cc
FILE: ../../../flutter/flow/debug_print.h
FILE: ../../../flutter/flow/embedded_views.h
FILE: ../../../flutter/flow/export_node.h
FILE: ../../../flutter/flow/layers/physical_shape_layer.cc
FILE: ../../../flutter/flow/layers/physical_shape_layer.h

View File

@ -8,6 +8,7 @@ source_set("flow") {
"compositor_context.h",
"debug_print.cc",
"debug_print.h",
"embedded_views.h",
"instrumentation.cc",
"instrumentation.h",
"layers/backdrop_filter_layer.cc",

View File

@ -32,25 +32,25 @@ void CompositorContext::EndFrame(ScopedFrame& frame,
std::unique_ptr<CompositorContext::ScopedFrame> CompositorContext::AcquireFrame(
GrContext* gr_context,
SkCanvas* canvas,
ExternalViewEmbedder* view_embedder,
const SkMatrix& root_surface_transformation,
bool instrumentation_enabled) {
return std::make_unique<ScopedFrame>(*this, //
gr_context, //
canvas, //
root_surface_transformation, //
instrumentation_enabled //
);
return std::make_unique<ScopedFrame>(*this, gr_context, canvas, view_embedder,
root_surface_transformation,
instrumentation_enabled);
}
CompositorContext::ScopedFrame::ScopedFrame(
CompositorContext& context,
GrContext* gr_context,
SkCanvas* canvas,
ExternalViewEmbedder* view_embedder,
const SkMatrix& root_surface_transformation,
bool instrumentation_enabled)
: context_(context),
gr_context_(gr_context),
canvas_(canvas),
view_embedder_(view_embedder),
root_surface_transformation_(root_surface_transformation),
instrumentation_enabled_(instrumentation_enabled) {
context_.BeginFrame(*this, instrumentation_enabled_);

View File

@ -8,6 +8,7 @@
#include <memory>
#include <string>
#include "flutter/flow/embedded_views.h"
#include "flutter/flow/instrumentation.h"
#include "flutter/flow/raster_cache.h"
#include "flutter/flow/texture.h"
@ -26,6 +27,7 @@ class CompositorContext {
ScopedFrame(CompositorContext& context,
GrContext* gr_context,
SkCanvas* canvas,
ExternalViewEmbedder* view_embedder,
const SkMatrix& root_surface_transformation,
bool instrumentation_enabled);
@ -33,6 +35,8 @@ class CompositorContext {
SkCanvas* canvas() { return canvas_; }
ExternalViewEmbedder* view_embedder() { return view_embedder_; }
CompositorContext& context() const { return context_; }
const SkMatrix& root_surface_transformation() const {
@ -47,6 +51,7 @@ class CompositorContext {
CompositorContext& context_;
GrContext* gr_context_;
SkCanvas* canvas_;
ExternalViewEmbedder* view_embedder_;
const SkMatrix& root_surface_transformation_;
const bool instrumentation_enabled_;
@ -60,6 +65,7 @@ class CompositorContext {
virtual std::unique_ptr<ScopedFrame> AcquireFrame(
GrContext* gr_context,
SkCanvas* canvas,
ExternalViewEmbedder* view_embedder,
const SkMatrix& root_surface_transformation,
bool instrumentation_enabled);

34
flow/embedded_views.h Normal file
View File

@ -0,0 +1,34 @@
// Copyright 2017 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 FLUTTER_FLOW_EMBEDDED_VIEWS_H_
#define FLUTTER_FLOW_EMBEDDED_VIEWS_H_
#include "flutter/fml/memory/ref_counted.h"
namespace flow {
class EmbeddedViewParams {
public:
};
// This is only used on iOS when running in a non headless mode,
// in this case ViewEmbedded is a reference to the
// FlutterPlatformViewsController which is owned by FlutterViewController.
class ExternalViewEmbedder {
public:
ExternalViewEmbedder() = default;
// Must be called on the UI thread.
virtual void CompositeEmbeddedView(int view_id,
const EmbeddedViewParams& params) {}
virtual ~ExternalViewEmbedder() = default;
FML_DISALLOW_COPY_AND_ASSIGN(ExternalViewEmbedder);
};
} // namespace flow
#endif // FLUTTER_FLOW_EMBEDDED_VIEWS_H_

View File

@ -8,6 +8,7 @@
#include <memory>
#include <vector>
#include "flutter/flow/embedded_views.h"
#include "flutter/flow/instrumentation.h"
#include "flutter/flow/raster_cache.h"
#include "flutter/flow/texture.h"
@ -64,6 +65,7 @@ class Layer {
struct PaintContext {
SkCanvas& canvas;
ExternalViewEmbedder* view_embedder;
const Stopwatch& frame_time;
const Stopwatch& engine_time;
TextureRegistry& texture_registry;

View File

@ -68,6 +68,7 @@ void LayerTree::Paint(CompositorContext::ScopedFrame& frame,
TRACE_EVENT0("flutter", "LayerTree::Paint");
Layer::PaintContext context = {
*frame.canvas(),
frame.view_embedder(),
frame.context().frame_time(),
frame.context().engine_time(),
frame.context().texture_registry(),
@ -106,7 +107,8 @@ sk_sp<SkPicture> 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)
unused_texture_registry, // texture registry (not supported)

View File

@ -16,6 +16,13 @@ void PlatformViewLayer::Preroll(PrerollContext* context,
size_.height()));
}
void PlatformViewLayer::Paint(PaintContext& context) const {}
void PlatformViewLayer::Paint(PaintContext& context) const {
if (context.view_embedder == nullptr) {
FML_LOG(ERROR) << "Trying to embed a platform view but the PaintContext "
"does not support embedding";
return;
}
EmbeddedViewParams params;
context.view_embedder->CompositeEmbeddedView(view_id_, params);
}
} // namespace flow

View File

@ -158,6 +158,7 @@ void RasterCache::Prepare(PrerollContext* context,
[layer, context](SkCanvas* canvas) {
Layer::PaintContext paintContext = {
*canvas,
nullptr,
context->frame_time,
context->engine_time,
context->texture_registry,

View File

@ -167,7 +167,8 @@ bool Rasterizer::DrawToSurface(flow::LayerTree& layer_tree) {
auto canvas = frame->SkiaCanvas();
auto compositor_frame = compositor_context_->AcquireFrame(
surface_->GetContext(), canvas, surface_->GetRootTransformation(), true);
surface_->GetContext(), canvas, surface_->GetExternalViewEmbedder(),
surface_->GetRootTransformation(), true);
if (canvas) {
canvas->clear(SK_ColorTRANSPARENT);
@ -197,9 +198,11 @@ static sk_sp<SkData> ScreenshotLayerTreeAsPicture(
SkMatrix root_surface_transformation;
root_surface_transformation.reset();
auto frame =
compositor_context.AcquireFrame(nullptr, recorder.getRecordingCanvas(),
root_surface_transformation, false);
// TODO(amirh): figure out how to take a screenshot with embedded UIView.
// https://github.com/flutter/flutter/issues/23435
auto frame = compositor_context.AcquireFrame(
nullptr, recorder.getRecordingCanvas(), nullptr,
root_surface_transformation, false);
frame->Raster(*tree, true);
@ -249,7 +252,7 @@ static sk_sp<SkData> ScreenshotLayerTreeAsImage(
root_surface_transformation.reset();
auto frame = compositor_context.AcquireFrame(
surface_context, canvas, root_surface_transformation, false);
surface_context, canvas, nullptr, root_surface_transformation, false);
canvas->clear(SK_ColorTRANSPARENT);
frame->Raster(*tree, true);
canvas->flush();

View File

@ -64,4 +64,8 @@ Surface::Surface() = default;
Surface::~Surface() = default;
flow::ExternalViewEmbedder* Surface::GetExternalViewEmbedder() {
return nullptr;
}
} // namespace shell

View File

@ -8,6 +8,7 @@
#include <memory>
#include "flutter/flow/compositor_context.h"
#include "flutter/flow/embedded_views.h"
#include "flutter/fml/macros.h"
#include "third_party/skia/include/core/SkCanvas.h"
@ -55,6 +56,8 @@ class Surface {
virtual GrContext* GetContext() = 0;
virtual flow::ExternalViewEmbedder* GetExternalViewEmbedder();
private:
FML_DISALLOW_COPY_AND_ASSIGN(Surface);
};

View File

@ -340,4 +340,9 @@ GrContext* GPUSurfaceGL::GetContext() {
return context_.get();
}
// |shell::Surface|
flow::ExternalViewEmbedder* GPUSurfaceGL::GetExternalViewEmbedder() {
return delegate_->GetExternalViewEmbedder();
}
} // namespace shell

View File

@ -8,6 +8,7 @@
#include <functional>
#include <memory>
#include "flutter/flow/embedded_views.h"
#include "flutter/fml/macros.h"
#include "flutter/fml/memory/weak_ptr.h"
#include "flutter/shell/common/surface.h"
@ -35,6 +36,10 @@ class GPUSurfaceGLDelegate {
return matrix;
}
virtual flow::ExternalViewEmbedder* GetExternalViewEmbedder() {
return nullptr;
}
using GLProcResolver =
std::function<void* /* proc name */ (const char* /* proc address */)>;
virtual GLProcResolver GetGLProcResolver() const { return nullptr; }
@ -58,6 +63,9 @@ class GPUSurfaceGL : public Surface {
// |shell::Surface|
GrContext* GetContext() override;
// |shell::Surface|
flow::ExternalViewEmbedder* GetExternalViewEmbedder() override;
private:
GPUSurfaceGLDelegate* delegate_;
GPUSurfaceGLDelegate::GLProcResolver proc_resolver_;

View File

@ -9,6 +9,11 @@
namespace shell {
flow::ExternalViewEmbedder*
GPUSurfaceSoftwareDelegate::GetExternalViewEmbedder() {
return nullptr;
}
GPUSurfaceSoftware::GPUSurfaceSoftware(GPUSurfaceSoftwareDelegate* delegate)
: delegate_(delegate), weak_factory_(this) {}
@ -75,4 +80,9 @@ GrContext* GPUSurfaceSoftware::GetContext() {
return nullptr;
}
// |shell::Surface|
flow::ExternalViewEmbedder* GPUSurfaceSoftware::GetExternalViewEmbedder() {
return delegate_->GetExternalViewEmbedder();
}
} // namespace shell

View File

@ -5,6 +5,7 @@
#ifndef FLUTTER_SHELL_GPU_GPU_SURFACE_SOFTWARE_H_
#define FLUTTER_SHELL_GPU_GPU_SURFACE_SOFTWARE_H_
#include "flutter/flow/embedded_views.h"
#include "flutter/fml/macros.h"
#include "flutter/fml/memory/weak_ptr.h"
#include "flutter/shell/common/surface.h"
@ -17,6 +18,8 @@ class GPUSurfaceSoftwareDelegate {
virtual sk_sp<SkSurface> AcquireBackingStore(const SkISize& size) = 0;
virtual bool PresentBackingStore(sk_sp<SkSurface> backing_store) = 0;
virtual flow::ExternalViewEmbedder* GetExternalViewEmbedder();
};
class GPUSurfaceSoftware : public Surface {
@ -37,6 +40,9 @@ class GPUSurfaceSoftware : public Surface {
// |shell::Surface|
GrContext* GetContext() override;
// |shell::Surface|
flow::ExternalViewEmbedder* GetExternalViewEmbedder() override;
private:
GPUSurfaceSoftwareDelegate* delegate_;
fml::WeakPtrFactory<GPUSurfaceSoftware> weak_factory_;

View File

@ -85,4 +85,9 @@ void FlutterPlatformViewsController::RegisterViewFactory(
fml::scoped_nsobject<NSObject<FlutterPlatformViewFactory>>([factory retain]);
}
void FlutterPlatformViewsController::CompositeEmbeddedView(int view_id,
const flow::EmbeddedViewParams& params) {
// TODO(amirh): implement this.
}
} // namespace shell

View File

@ -5,6 +5,7 @@
#ifndef FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_SOURCE_FLUTTERPLATFORMVIEWS_INTERNAL_H_
#define FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_SOURCE_FLUTTERPLATFORMVIEWS_INTERNAL_H_
#include "flutter/flow/embedded_views.h"
#include "flutter/fml/platform/darwin/scoped_nsobject.h"
#include "flutter/shell/common/shell.h"
#include "flutter/shell/platform/darwin/ios/framework/Headers/FlutterBinaryMessenger.h"
@ -13,12 +14,14 @@
namespace shell {
class FlutterPlatformViewsController {
class FlutterPlatformViewsController : public flow::ExternalViewEmbedder {
public:
FlutterPlatformViewsController(NSObject<FlutterBinaryMessenger>* messenger);
void RegisterViewFactory(NSObject<FlutterPlatformViewFactory>* factory, NSString* factoryId);
void CompositeEmbeddedView(int view_id, const flow::EmbeddedViewParams& params);
private:
fml::scoped_nsobject<FlutterMethodChannel> channel_;
std::map<std::string, fml::scoped_nsobject<NSObject<FlutterPlatformViewFactory>>> factories_;

View File

@ -9,6 +9,7 @@
#include <memory>
#include "flutter/flow/embedded_views.h"
#include "flutter/fml/memory/weak_ptr.h"
#include "flutter/shell/common/shell.h"
#include "flutter/shell/platform/darwin/ios/ios_surface.h"

View File

@ -12,6 +12,7 @@
#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/framework/Source/FlutterViewController_Internal.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"
@ -54,6 +55,23 @@ id<FlutterScreenshotDelegate> _delegate;
return self;
}
- (FlutterViewController*)flutterViewController {
// Find the first view controller in the responder chain and see if it is a FlutterViewController.
for (UIResponder* responder = self.nextResponder; responder != nil;
responder = responder.nextResponder) {
if ([responder isKindOfClass:[UIViewController class]]) {
if ([responder isKindOfClass:[FlutterViewController class]]) {
return reinterpret_cast<FlutterViewController*>(responder);
} else {
// Should only happen if a non-FlutterViewController tries to somehow (via dynamic class
// resolution or reparenting) set a FlutterView as its view.
return nil;
}
}
}
return nil;
}
- (void)layoutSubviews {
if ([self.layer isKindOfClass:[CAEAGLLayer class]]) {
CAEAGLLayer* layer = reinterpret_cast<CAEAGLLayer*>(self.layer);
@ -75,13 +93,16 @@ id<FlutterScreenshotDelegate> _delegate;
}
- (std::unique_ptr<shell::IOSSurface>)createSurface {
::shell::GetExternalViewEmbedder get_view_embedder = [[^() {
return [[self flutterViewController] viewEmbedder];
} copy] autorelease];
if ([self.layer isKindOfClass:[CAEAGLLayer class]]) {
fml::scoped_nsobject<CAEAGLLayer> eagl_layer(
reinterpret_cast<CAEAGLLayer*>([self.layer retain]));
return std::make_unique<shell::IOSSurfaceGL>(std::move(eagl_layer));
return std::make_unique<shell::IOSSurfaceGL>(std::move(eagl_layer), get_view_embedder);
} else {
fml::scoped_nsobject<CALayer> layer(reinterpret_cast<CALayer*>([self.layer retain]));
return std::make_unique<shell::IOSSurfaceSoftware>(std::move(layer));
return std::make_unique<shell::IOSSurfaceSoftware>(std::move(layer), get_view_embedder);
}
}

View File

@ -124,6 +124,10 @@
return _weakFactory->GetWeakPtr();
}
- (flow::ExternalViewEmbedder*)viewEmbedder {
return _platformViewsController.get();
}
- (void)setupNotificationCenterObservers {
NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
[center addObserver:self
@ -953,4 +957,4 @@ constexpr CGFloat kStandardStatusBarHeight = 20.0;
return [_engine.get() valuePublishedByPlugin:pluginKey];
}
@end
@end

View File

@ -5,8 +5,10 @@
#ifndef FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_SOURCE_FLUTTERVIEWCONTROLLER_INTERNAL_H_
#define FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_SOURCE_FLUTTERVIEWCONTROLLER_INTERNAL_H_
#include "flutter/flow/embedded_views.h"
#include "flutter/fml/memory/weak_ptr.h"
#include "flutter/fml/platform/darwin/scoped_nsobject.h"
#include "flutter/shell/common/shell.h"
#include "flutter/shell/platform/darwin/ios/framework/Headers/FlutterViewController.h"
#include "flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h"
@ -17,6 +19,8 @@
@property(readonly) fml::scoped_nsobject<FlutterEngine> engine;
- (flow::ExternalViewEmbedder*)viewEmbedder;
@end
#endif // FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_SOURCE_FLUTTERVIEWCONTROLLER_INTERNAL_H_

View File

@ -13,6 +13,8 @@
namespace shell {
typedef flow::ExternalViewEmbedder* (^GetExternalViewEmbedder)(void);
class IOSSurface {
public:
IOSSurface();

View File

@ -17,7 +17,8 @@ namespace shell {
class IOSSurfaceGL : public IOSSurface, public GPUSurfaceGLDelegate {
public:
IOSSurfaceGL(fml::scoped_nsobject<CAEAGLLayer> layer);
IOSSurfaceGL(fml::scoped_nsobject<CAEAGLLayer> layer,
::shell::GetExternalViewEmbedder get_view_embedder);
~IOSSurfaceGL() override;
@ -39,9 +40,14 @@ class IOSSurfaceGL : public IOSSurface, public GPUSurfaceGLDelegate {
bool UseOffscreenSurface() const override;
// |shell::GPUSurfaceGLDelegate|
flow::ExternalViewEmbedder* GetExternalViewEmbedder() override;
private:
IOSGLContext context_;
fml::scoped_nsprotocol<::shell::GetExternalViewEmbedder> get_view_embedder_;
FML_DISALLOW_COPY_AND_ASSIGN(IOSSurfaceGL);
};

View File

@ -9,7 +9,9 @@
namespace shell {
IOSSurfaceGL::IOSSurfaceGL(fml::scoped_nsobject<CAEAGLLayer> layer) : context_(std::move(layer)) {}
IOSSurfaceGL::IOSSurfaceGL(fml::scoped_nsobject<CAEAGLLayer> layer,
::shell::GetExternalViewEmbedder get_view_embedder)
: context_(std::move(layer)), get_view_embedder_([get_view_embedder retain]) {}
IOSSurfaceGL::~IOSSurfaceGL() = default;
@ -56,4 +58,8 @@ bool IOSSurfaceGL::GLContextPresent() {
return IsValid() ? context_.PresentRenderBuffer() : false;
}
flow::ExternalViewEmbedder* IOSSurfaceGL::GetExternalViewEmbedder() {
return get_view_embedder_.get()();
}
} // namespace shell

View File

@ -16,7 +16,8 @@ namespace shell {
class IOSSurfaceSoftware final : public IOSSurface, public GPUSurfaceSoftwareDelegate {
public:
IOSSurfaceSoftware(fml::scoped_nsobject<CALayer> layer);
IOSSurfaceSoftware(fml::scoped_nsobject<CALayer> layer,
::shell::GetExternalViewEmbedder get_view_embedder);
~IOSSurfaceSoftware() override;
@ -38,8 +39,12 @@ class IOSSurfaceSoftware final : public IOSSurface, public GPUSurfaceSoftwareDel
// |shell::GPUSurfaceSoftwareDelegate|
bool PresentBackingStore(sk_sp<SkSurface> backing_store) override;
// |shell::GPUSurfaceSoftwareDelegate|
flow::ExternalViewEmbedder* GetExternalViewEmbedder() override;
private:
fml::scoped_nsobject<CALayer> layer_;
fml::scoped_nsprotocol<::shell::GetExternalViewEmbedder> get_view_embedder_;
sk_sp<SkSurface> sk_surface_;
FML_DISALLOW_COPY_AND_ASSIGN(IOSSurfaceSoftware);

View File

@ -15,8 +15,9 @@
namespace shell {
IOSSurfaceSoftware::IOSSurfaceSoftware(fml::scoped_nsobject<CALayer> layer)
: layer_(std::move(layer)) {
IOSSurfaceSoftware::IOSSurfaceSoftware(fml::scoped_nsobject<CALayer> layer,
::shell::GetExternalViewEmbedder get_view_embedder)
: layer_(std::move(layer)), get_view_embedder_([get_view_embedder retain]) {
UpdateStorageSizeIfNecessary();
}
@ -125,4 +126,8 @@ bool IOSSurfaceSoftware::PresentBackingStore(sk_sp<SkSurface> backing_store) {
return true;
}
flow::ExternalViewEmbedder* IOSSurfaceSoftware::GetExternalViewEmbedder() {
return get_view_embedder_.get()();
}
} // namespace shell