Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,39 @@
#include "flutter/fml/synchronization/count_down_latch.h"
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterOverlayView.h"
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterView.h"
#include "flutter/shell/platform/darwin/ios/framework/Source/overlay_layer_pool.h"
#import "flutter/shell/platform/darwin/ios/ios_surface.h"

namespace {

// The number of frames the rasterizer task runner will continue
// to run on the platform thread after no platform view is rendered.
//
// Note: this is an arbitrary number.
static const int kDefaultMergedLeaseDuration = 10;
static constexpr int kDefaultMergedLeaseDuration = 10;

static constexpr NSUInteger kFlutterClippingMaskViewPoolCapacity = 5;

struct LayerData {
SkRect rect;
int64_t view_id;
int64_t overlay_id;
std::shared_ptr<flutter::OverlayLayer> layer;
};
using LayersMap = std::unordered_map<int64_t, LayerData>;

/// Each of the following structs stores part of the platform view hierarchy according to its
/// ID.
///
/// This data must only be accessed on the platform thread.
struct PlatformViewData {
NSObject<FlutterPlatformView>* view;
FlutterTouchInterceptingView* touch_interceptor;
UIView* root_view;
};

// Converts a SkMatrix to CATransform3D.
//
// Certain fields are ignored in CATransform3D since SkMatrix is 3x3 and CATransform3D is 4x4.
CATransform3D GetCATransform3DFromSkMatrix(const SkMatrix& matrix) {
static CATransform3D GetCATransform3DFromSkMatrix(const SkMatrix& matrix) {
// Skia only supports 2D transform so we don't map z.
CATransform3D transform = CATransform3DIdentity;
transform.m11 = matrix.getScaleX();
Expand All @@ -44,13 +61,13 @@ CATransform3D GetCATransform3DFromSkMatrix(const SkMatrix& matrix) {
// Reset the anchor of `layer` to match the transform operation from flow.
//
// The position of the `layer` should be unchanged after resetting the anchor.
void ResetAnchor(CALayer* layer) {
static void ResetAnchor(CALayer* layer) {
// Flow uses (0, 0) to apply transform matrix so we need to match that in Quartz.
layer.anchorPoint = CGPointZero;
layer.position = CGPointZero;
}

CGRect GetCGRectFromSkRect(const SkRect& clipSkRect) {
static CGRect GetCGRectFromSkRect(const SkRect& clipSkRect) {
return CGRectMake(clipSkRect.fLeft, clipSkRect.fTop, clipSkRect.fRight - clipSkRect.fLeft,
clipSkRect.fBottom - clipSkRect.fTop);
}
Expand All @@ -63,9 +80,9 @@ CGRect GetCGRectFromSkRect(const SkRect& clipSkRect) {
//
// `platformview_boundingrect` is the final bounding rect of the PlatformView in the coordinate
// space where the PlatformView is displayed.
bool ClipRectContainsPlatformViewBoundingRect(const SkRect& clip_rect,
const SkRect& platformview_boundingrect,
const SkMatrix& transform_matrix) {
static bool ClipRectContainsPlatformViewBoundingRect(const SkRect& clip_rect,
const SkRect& platformview_boundingrect,
const SkMatrix& transform_matrix) {
SkRect transformed_rect = transform_matrix.mapRect(clip_rect);
return transformed_rect.contains(platformview_boundingrect);
}
Expand All @@ -78,9 +95,9 @@ bool ClipRectContainsPlatformViewBoundingRect(const SkRect& clip_rect,
//
// `platformview_boundingrect` is the final bounding rect of the PlatformView in the coordinate
// space where the PlatformView is displayed.
bool ClipRRectContainsPlatformViewBoundingRect(const SkRRect& clip_rrect,
const SkRect& platformview_boundingrect,
const SkMatrix& transform_matrix) {
static bool ClipRRectContainsPlatformViewBoundingRect(const SkRRect& clip_rrect,
const SkRect& platformview_boundingrect,
const SkMatrix& transform_matrix) {
SkVector upper_left = clip_rrect.radii(SkRRect::Corner::kUpperLeft_Corner);
SkVector upper_right = clip_rrect.radii(SkRRect::Corner::kUpperRight_Corner);
SkVector lower_right = clip_rrect.radii(SkRRect::Corner::kLowerRight_Corner);
Expand All @@ -103,27 +120,6 @@ bool ClipRRectContainsPlatformViewBoundingRect(const SkRRect& clip_rrect,
return transformed_rrect.contains(platformview_boundingrect);
}

struct LayerData {
SkRect rect;
int64_t view_id;
int64_t overlay_id;
std::shared_ptr<flutter::OverlayLayer> layer;
};

using LayersMap = std::unordered_map<int64_t, LayerData>;

/// Each of the following structs stores part of the platform view hierarchy according to its
/// ID.
///
/// This data must only be accessed on the platform thread.
struct PlatformViewData {
NSObject<FlutterPlatformView>* view;
FlutterTouchInterceptingView* touch_interceptor;
UIView* root_view;
};

} // namespace

@interface FlutterPlatformViewsController ()

// The pool of reusable view layers. The pool allows to recycle layer in each frame.
Expand Down Expand Up @@ -196,6 +192,11 @@ @interface FlutterPlatformViewsController ()
/// Only accessed from the raster thread.
@property(nonatomic, assign) BOOL hadPlatformViews;

/// Whether blurred backdrop filters can be applied.
///
/// Defaults to YES, but becomes NO if blurred backdrop filters cannot be applied.
@property(nonatomic, assign) BOOL canApplyBlurBackdrop;

/// Populate any missing overlay layers.
///
/// This requires posting a task to the platform thread and blocking on its completion.
Expand Down Expand Up @@ -264,14 +265,6 @@ - (void)removeUnusedLayers:(const std::vector<std::shared_ptr<flutter::OverlayLa
- (void)resetFrameState;
@end

namespace flutter {

// TODO(cbracken): Eliminate the use of globals.
// Becomes NO if Apple's API changes and blurred backdrop filters cannot be applied.
BOOL canApplyBlurBackdrop = YES;

} // namespace flutter

@implementation FlutterPlatformViewsController {
// TODO(cbracken): Replace with Obj-C types and use @property declarations to automatically
// synthesize the ivars.
Expand Down Expand Up @@ -301,6 +294,7 @@ - (id)init {
_maskViewPool =
[[FlutterClippingMaskViewPool alloc] initWithCapacity:kFlutterClippingMaskViewPoolCapacity];
_hadPlatformViews = NO;
_canApplyBlurBackdrop = YES;
}
return self;
}
Expand Down Expand Up @@ -630,7 +624,7 @@ - (void)applyMutators:(const flutter::MutatorsStack&)mutatorsStack
break;
case flutter::kBackdropFilter: {
// Only support DlBlurImageFilter for BackdropFilter.
if (!flutter::canApplyBlurBackdrop || !(*iter)->GetFilterMutation().GetFilter().asBlur()) {
if (!self.canApplyBlurBackdrop || !(*iter)->GetFilterMutation().GetFilter().asBlur()) {
break;
}
CGRect filterRect = GetCGRectFromSkRect((*iter)->GetFilterMutation().GetFilterRect());
Expand All @@ -656,7 +650,7 @@ - (void)applyMutators:(const flutter::MutatorsStack&)mutatorsStack
blurRadius:blurRadius
visualEffectView:visualEffectView];
if (!filter) {
flutter::canApplyBlurBackdrop = NO;
self.canApplyBlurBackdrop = NO;
} else {
[blurFilters addObject:filter];
}
Expand All @@ -666,7 +660,7 @@ - (void)applyMutators:(const flutter::MutatorsStack&)mutatorsStack
++iter;
}

if (flutter::canApplyBlurBackdrop) {
if (self.canApplyBlurBackdrop) {
[clipView applyBlurBackdropFilters:blurFilters];
}

Expand Down