Skip to content

Commit

Permalink
Add an overlay surface on top of embedded UIViews. (#6726)
Browse files Browse the repository at this point in the history
The overlay surfaces are going to be the same IOSSurface implementation
with the platform views controller set to null (so these are surfaces
that don't support embedding platform views to them).

  * Adds a FlutterOverlayView which is a UIView that's showing an
    overlay surface.
  * Creates an overlay surface for each embedded UIView (done in
    FlutterPlatformViewsController).
  * Changes CompositeEmbeddedView to return a new canvas.
  * Makes the PlatformViewLayer replace the PaintContext's canvas with
    the canvas for the overlay view.
  * Changed canvas in PaintContext to be a pointer so it can be changed.

TBD in following PRs:
  * Copy the current canvas state when replacing a canvas in PaintContext.
  * Make FlutterOverlayView work with a GL backend (currently it only
    works with software rendering)
  • Loading branch information
amirh authored Nov 2, 2018
1 parent 1360556 commit 9e1f546
Show file tree
Hide file tree
Showing 29 changed files with 272 additions and 89 deletions.
2 changes: 2 additions & 0 deletions ci/licenses_golden/licenses_flutter
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 4 additions & 2 deletions flow/embedded_views.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand All @@ -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,
Expand All @@ -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;

Expand Down
8 changes: 4 additions & 4 deletions flow/layers/clip_path_layer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
}

Expand Down
8 changes: 4 additions & 4 deletions flow/layers/clip_rect_layer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
}

Expand Down
8 changes: 4 additions & 4 deletions flow/layers/clip_rrect_layer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
}

Expand Down
8 changes: 4 additions & 4 deletions flow/layers/layer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand All @@ -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
2 changes: 1 addition & 1 deletion flow/layers/layer.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
4 changes: 2 additions & 2 deletions flow/layers/layer_tree.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down Expand Up @@ -107,7 +107,7 @@ 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)
Expand Down
12 changes: 6 additions & 6 deletions flow/layers/opacity_layer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
Expand Down
6 changes: 3 additions & 3 deletions flow/layers/performance_overlay_layer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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");
}
Expand Down
18 changes: 9 additions & 9 deletions flow/layers/physical_shape_layer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -83,28 +83,28 @@ 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_);
}

// Call drawPath without clip if possible for better performance.
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;
Expand All @@ -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,
Expand Down
14 changes: 7 additions & 7 deletions flow/layers/picture_layer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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
9 changes: 7 additions & 2 deletions flow/layers/platform_view_layer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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
4 changes: 2 additions & 2 deletions flow/layers/shader_mask_layer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down
2 changes: 1 addition & 1 deletion flow/layers/texture_layer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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
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.canvas, true);
context.canvas->concat(transform_);
PaintChildren(context);
}

Expand Down
2 changes: 1 addition & 1 deletion flow/raster_cache.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
2 changes: 2 additions & 0 deletions shell/platform/darwin/ios/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
28 changes: 28 additions & 0 deletions shell/platform/darwin/ios/framework/Source/FlutterOverlayView.h
Original file line number Diff line number Diff line change
@@ -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 <UIKit/UIKit.h>

#include <memory>

#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<shell::IOSSurface>)createSurface;

@end

#endif // SHELL_PLATFORM_IOS_FRAMEWORK_SOURCE_FLUTTER_OVERLAY_VIEW_H_
Loading

0 comments on commit 9e1f546

Please sign in to comment.