Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit ac874d6

Browse files
authored
[Multiwindow] Renderers receive view IDs as argument (#36593)
* Impl * Format * TODO comments * Fix compile * Better empty indication * Change invalid ID to -1 * fix doc * Change to default view * Better doc * Update doc of FlutterFrameInfo * Change to ID * Address comment * Fix comment * To assertion * Fix compile
1 parent d955a72 commit ac874d6

File tree

6 files changed

+68
-40
lines changed

6 files changed

+68
-40
lines changed

shell/platform/darwin/macos/framework/Headers/FlutterEngine.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,10 @@ FLUTTER_DARWIN_EXPORT
6363
- (BOOL)runWithEntrypoint:(nullable NSString*)entrypoint;
6464

6565
/**
66-
* The `FlutterViewController` associated with this engine, if any.
66+
* The default `FlutterViewController` associated with this engine, if any.
67+
*
68+
* The default view always has ID kFlutterDefaultViewId, and is the view
69+
* operated by the APIs that do not have a view ID specified.
6770
*/
6871
@property(nonatomic, nullable, weak) FlutterViewController* viewController;
6972

shell/platform/darwin/macos/framework/Source/FlutterEngine.mm

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -400,7 +400,6 @@ - (void)loadAOTData:(NSString*)assetsDir {
400400
- (void)setViewController:(FlutterViewController*)controller {
401401
if (_viewController != controller) {
402402
_viewController = controller;
403-
[_renderer setFlutterView:controller.flutterView];
404403

405404
if (_semanticsEnabled && _bridge) {
406405
_bridge->UpdateDefaultViewController(_viewController);
@@ -425,10 +424,14 @@ - (FlutterCompositor*)createFlutterCompositor {
425424
_macOSCompositor = std::make_unique<flutter::FlutterCompositor>(
426425
_viewProvider, _platformViewController, _renderer.device);
427426
_macOSCompositor->SetPresentCallback([weakSelf](bool has_flutter_content) {
427+
// TODO(dkwingsmt): The compositor only supports single-view for now. As
428+
// more classes are gradually converted to multi-view, it should get the
429+
// view ID from somewhere.
430+
uint64_t viewId = kFlutterDefaultViewId;
428431
if (has_flutter_content) {
429-
return [weakSelf.renderer present] == YES;
432+
return [weakSelf.renderer present:viewId] == YES;
430433
} else {
431-
[weakSelf.renderer presentWithoutContent];
434+
[weakSelf.renderer presentWithoutContent:viewId];
432435
return true;
433436
}
434437
});

shell/platform/darwin/macos/framework/Source/FlutterRenderer.h

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,30 +30,25 @@
3030
*/
3131
- (nullable instancetype)initWithFlutterEngine:(nonnull FlutterEngine*)flutterEngine;
3232

33-
/**
34-
* Sets the FlutterView to render to.
35-
*/
36-
- (void)setFlutterView:(nullable FlutterView*)view;
37-
3833
/**
3934
* Creates a FlutterRendererConfig that renders using the appropriate backend.
4035
*/
4136
- (FlutterRendererConfig)createRendererConfig;
4237

4338
/**
44-
* Called by the engine when the context's buffers should be swapped.
39+
* Called by the engine when the given view's buffers should be swapped.
4540
*/
46-
- (BOOL)present;
41+
- (BOOL)present:(uint64_t)viewId;
4742

4843
/**
4944
* Tells the renderer that there is no Flutter content available for this frame.
5045
*/
51-
- (void)presentWithoutContent;
46+
- (void)presentWithoutContent:(uint64_t)viewId;
5247

5348
/**
54-
* Creates a Metal texture for the given size.
49+
* Creates a Metal texture for the given view with the given size.
5550
*/
56-
- (FlutterMetalTexture)createTextureForSize:(CGSize)size;
51+
- (FlutterMetalTexture)createTextureForView:(uint64_t)viewId size:(CGSize)size;
5752

5853
/**
5954
* Populates the texture registry with the provided metalTexture.

shell/platform/darwin/macos/framework/Source/FlutterRenderer.mm

Lines changed: 36 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,29 @@
66

77
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterEngine_Internal.h"
88
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterExternalTexture.h"
9-
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterView.h"
9+
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterViewController_Internal.h"
10+
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterViewEngineProvider.h"
1011
#include "flutter/shell/platform/embedder/embedder.h"
1112

1213
#pragma mark - Static callbacks that require the engine.
1314

14-
static FlutterMetalTexture OnGetNextDrawable(FlutterEngine* engine,
15-
const FlutterFrameInfo* frameInfo) {
15+
static FlutterMetalTexture OnGetNextDrawableForDefaultView(FlutterEngine* engine,
16+
const FlutterFrameInfo* frameInfo) {
17+
// TODO(dkwingsmt): This callback only supports single-view, therefore it only
18+
// operates on the default view. To support multi-view, we need a new callback
19+
// that also receives a view ID, or pass the ID via FlutterFrameInfo.
20+
uint64_t viewId = kFlutterDefaultViewId;
1621
CGSize size = CGSizeMake(frameInfo->size.width, frameInfo->size.height);
17-
return [engine.renderer createTextureForSize:size];
22+
return [engine.renderer createTextureForView:viewId size:size];
1823
}
1924

20-
static bool OnPresentDrawable(FlutterEngine* engine, const FlutterMetalTexture* texture) {
21-
return [engine.renderer present];
25+
static bool OnPresentDrawableOfDefaultView(FlutterEngine* engine,
26+
const FlutterMetalTexture* texture) {
27+
// TODO(dkwingsmt): This callback only supports single-view, therefore it only
28+
// operates on the default view. To support multi-view, we need a new callback
29+
// that also receives a view ID.
30+
uint64_t viewId = kFlutterDefaultViewId;
31+
return [engine.renderer present:viewId];
2232
}
2333

2434
static bool OnAcquireExternalTexture(FlutterEngine* engine,
@@ -33,14 +43,15 @@ static bool OnAcquireExternalTexture(FlutterEngine* engine,
3343
#pragma mark - FlutterRenderer implementation
3444

3545
@implementation FlutterRenderer {
36-
FlutterView* _flutterView;
46+
FlutterViewEngineProvider* _viewProvider;
3747

3848
FlutterDarwinContextMetalSkia* _darwinMetalContext;
3949
}
4050

4151
- (instancetype)initWithFlutterEngine:(nonnull FlutterEngine*)flutterEngine {
4252
self = [super initWithDelegate:self engine:flutterEngine];
4353
if (self) {
54+
_viewProvider = [[FlutterViewEngineProvider alloc] initWithEngine:flutterEngine];
4455
_device = MTLCreateSystemDefaultDevice();
4556
if (!_device) {
4657
NSLog(@"Could not acquire Metal device.");
@@ -59,20 +70,16 @@ - (instancetype)initWithFlutterEngine:(nonnull FlutterEngine*)flutterEngine {
5970
return self;
6071
}
6172

62-
- (void)setFlutterView:(FlutterView*)view {
63-
_flutterView = view;
64-
}
65-
6673
- (FlutterRendererConfig)createRendererConfig {
6774
FlutterRendererConfig config = {
6875
.type = FlutterRendererType::kMetal,
6976
.metal.struct_size = sizeof(FlutterMetalRendererConfig),
7077
.metal.device = (__bridge FlutterMetalDeviceHandle)_device,
7178
.metal.present_command_queue = (__bridge FlutterMetalCommandQueueHandle)_commandQueue,
7279
.metal.get_next_drawable_callback =
73-
reinterpret_cast<FlutterMetalTextureCallback>(OnGetNextDrawable),
80+
reinterpret_cast<FlutterMetalTextureCallback>(OnGetNextDrawableForDefaultView),
7481
.metal.present_drawable_callback =
75-
reinterpret_cast<FlutterMetalPresentCallback>(OnPresentDrawable),
82+
reinterpret_cast<FlutterMetalPresentCallback>(OnPresentDrawableOfDefaultView),
7683
.metal.external_texture_frame_callback =
7784
reinterpret_cast<FlutterMetalTextureFrameCallback>(OnAcquireExternalTexture),
7885
};
@@ -81,9 +88,15 @@ - (FlutterRendererConfig)createRendererConfig {
8188

8289
#pragma mark - Embedder callback implementations.
8390

84-
- (FlutterMetalTexture)createTextureForSize:(CGSize)size {
91+
- (FlutterMetalTexture)createTextureForView:(uint64_t)viewId size:(CGSize)size {
92+
FlutterView* view = [_viewProvider getView:viewId];
93+
NSAssert(view != nil, @"Can't create texture on a non-existent view 0x%llx.", viewId);
94+
if (view == nil) {
95+
// FlutterMetalTexture has texture `null`, therefore is discarded.
96+
return FlutterMetalTexture{};
97+
}
8598
FlutterMetalRenderBackingStore* backingStore =
86-
(FlutterMetalRenderBackingStore*)[_flutterView backingStoreForSize:size];
99+
(FlutterMetalRenderBackingStore*)[view backingStoreForSize:size];
87100
id<MTLTexture> texture = backingStore.texture;
88101
FlutterMetalTexture embedderTexture;
89102
embedderTexture.struct_size = sizeof(FlutterMetalTexture);
@@ -92,19 +105,21 @@ - (FlutterMetalTexture)createTextureForSize:(CGSize)size {
92105
return embedderTexture;
93106
}
94107

95-
- (BOOL)present {
96-
if (!_flutterView) {
108+
- (BOOL)present:(uint64_t)viewId {
109+
FlutterView* view = [_viewProvider getView:viewId];
110+
if (view == nil) {
97111
return NO;
98112
}
99-
[_flutterView present];
113+
[view present];
100114
return YES;
101115
}
102116

103-
- (void)presentWithoutContent {
104-
if (!_flutterView) {
117+
- (void)presentWithoutContent:(uint64_t)viewId {
118+
FlutterView* view = [_viewProvider getView:viewId];
119+
if (view == nil) {
105120
return;
106121
}
107-
[_flutterView presentWithoutContent];
122+
[view presentWithoutContent];
108123
}
109124

110125
#pragma mark - FlutterTextureRegistrar methods.

shell/platform/darwin/macos/framework/Source/FlutterRendererTest.mm

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterEngine_Internal.h"
1010
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterRenderer.h"
1111
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterView.h"
12+
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterViewController_Internal.h"
1213
#include "flutter/shell/platform/embedder/embedder.h"
1314
#include "flutter/shell/platform/embedder/test_utils/proc_table_replacement.h"
1415
#include "flutter/testing/testing.h"
@@ -24,21 +25,29 @@
2425
ICUDataPath:[fixtures stringByAppendingString:@"/icudtl.dat"]];
2526
return [[FlutterEngine alloc] initWithName:@"test" project:project allowHeadlessExecution:true];
2627
}
28+
29+
void SetEngineDefaultView(FlutterEngine* engine, id flutterView) {
30+
id mockFlutterViewController = OCMClassMock([FlutterViewController class]);
31+
OCMStub([mockFlutterViewController flutterView]).andReturn(flutterView);
32+
[engine setViewController:mockFlutterViewController];
33+
}
34+
2735
} // namespace
2836

2937
TEST(FlutterRenderer, PresentDelegatesToFlutterView) {
3038
FlutterEngine* engine = CreateTestEngine();
3139
FlutterRenderer* renderer = [[FlutterRenderer alloc] initWithFlutterEngine:engine];
3240
id mockFlutterView = OCMClassMock([FlutterView class]);
41+
SetEngineDefaultView(engine, mockFlutterView);
3342
[(FlutterView*)[mockFlutterView expect] present];
34-
[renderer setFlutterView:mockFlutterView];
35-
[renderer present];
43+
[renderer present:kFlutterDefaultViewId];
3644
}
3745

3846
TEST(FlutterRenderer, TextureReturnedByFlutterView) {
3947
FlutterEngine* engine = CreateTestEngine();
4048
FlutterRenderer* renderer = [[FlutterRenderer alloc] initWithFlutterEngine:engine];
4149
id mockFlutterView = OCMClassMock([FlutterView class]);
50+
SetEngineDefaultView(engine, mockFlutterView);
4251
FlutterFrameInfo frameInfo;
4352
frameInfo.struct_size = sizeof(FlutterFrameInfo);
4453
FlutterUIntSize dimensions;
@@ -47,8 +56,7 @@
4756
frameInfo.size = dimensions;
4857
CGSize size = CGSizeMake(dimensions.width, dimensions.height);
4958
[[mockFlutterView expect] backingStoreForSize:size];
50-
[renderer setFlutterView:mockFlutterView];
51-
[renderer createTextureForSize:size];
59+
[renderer createTextureForView:kFlutterDefaultViewId size:size];
5260
}
5361

5462
} // namespace flutter::testing

shell/platform/embedder/embedder.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -448,7 +448,9 @@ typedef struct {
448448
/// This information is passed to the embedder when requesting a frame buffer
449449
/// object.
450450
///
451-
/// See: \ref FlutterOpenGLRendererConfig.fbo_with_frame_info_callback.
451+
/// See: \ref FlutterOpenGLRendererConfig.fbo_with_frame_info_callback,
452+
/// \ref FlutterMetalRendererConfig.get_next_drawable_callback,
453+
/// and \ref FlutterVulkanRendererConfig.get_next_image_callback.
452454
typedef struct {
453455
/// The size of this struct. Must be sizeof(FlutterFrameInfo).
454456
size_t struct_size;
@@ -633,6 +635,8 @@ typedef struct {
633635
int64_t texture_id;
634636
/// Handle to the MTLTexture that is owned by the embedder. Engine will render
635637
/// the frame into this texture.
638+
///
639+
/// A NULL texture is considered invalid.
636640
FlutterMetalTextureHandle texture;
637641
/// A baton that is not interpreted by the engine in any way. It will be given
638642
/// back to the embedder in the destruction callback below. Embedder resources

0 commit comments

Comments
 (0)