5#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterSurfaceManager.h"
11#include "flutter/fml/logging.h"
12#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterSurface.h"
50 [NSColor yellowColor],
52 [NSColor magentaColor],
54 [NSColor purpleColor],
55 [NSColor orangeColor],
58 return colors[layer % colors.count];
68 const std::vector<FlutterRect>& paintRegion) {
70 while (layer.sublayers.count > paintRegion.size()) {
71 [layer.sublayers.lastObject removeFromSuperlayer];
74 while (layer.sublayers.count < paintRegion.size()) {
75 CALayer* newLayer = [CALayer layer];
76 [layer addSublayer:newLayer];
79 for (
size_t i = 0; i < paintRegion.size(); i++) {
80 CALayer* subLayer = [layer.sublayers objectAtIndex:i];
81 const auto& rect = paintRegion[i];
82 subLayer.frame = CGRectMake(rect.left /
scale, rect.top /
scale,
83 (rect.right - rect.left) /
scale, (rect.bottom - rect.top) /
scale);
85 double width = surfaceSize.width;
86 double height = surfaceSize.height;
88 subLayer.contentsRect =
89 CGRectMake(rect.left /
width, rect.top /
height, (rect.right - rect.left) /
width,
90 (rect.bottom - rect.top) /
height);
92 if (borderColor != nil) {
94 subLayer.borderColor = borderColor.CGColor;
95 subLayer.borderWidth = 1.0;
104- (instancetype)initWithDevice:(
id<MTLDevice>)device
105 commandQueue:(
id<MTLCommandQueue>)commandQueue
106 layer:(CALayer*)containingLayer
107 delegate:(__weak
id<FlutterSurfaceManagerDelegate>)delegate {
108 if (
self = [super init]) {
116 _layers = [NSMutableArray array];
142 if (_enableSurfaceDebugInfo == nil) {
144 [[NSBundle mainBundle] objectForInfoDictionaryKey:@"FLTEnableSurfaceDebugInfo"];
145 if (_enableSurfaceDebugInfo == nil) {
149 return [_enableSurfaceDebugInfo boolValue];
156 [_backBufferCache returnSurfaces:_frontSurfaces];
159 [_frontSurfaces removeAllObjects];
161 [_frontSurfaces addObject:info.surface];
166 [_layers.lastObject removeFromSuperlayer];
167 [_layers removeLastObject];
170 CALayer* layer = [CALayer layer];
171 [_containingLayer addSublayer:layer];
172 [_layers addObject:layer];
178 for (
size_t i = 0; i < surfaces.count; ++i) {
185 layer.contents = (__bridge
id)
info.surface.ioSurface;
187 layer.frame = CGRectZero;
192 layer.zPosition =
info.zIndex;
196 if (_infoLayer == nil) {
198 [_containingLayer addSublayer:_infoLayer];
200 _infoLayer.foregroundColor = [NSColor yellowColor].CGColor;
201 _infoLayer.frame = CGRectMake(15, 15, 300, 100);
205 _infoLayer.string = [NSString stringWithFormat:@"Surface count: %li", _layers.count];
210 CGSize size = CGSizeZero;
212 size = CGSizeMake(std::max(size.width,
info.offset.x +
info.surface.size.width),
213 std::max(size.height,
info.offset.y +
info.surface.size.height));
219 atTime:(CFTimeInterval)presentationTime
220 notify:(dispatch_block_t)notify {
221 id<MTLCommandBuffer> commandBuffer = [_commandQueue commandBuffer];
222 [commandBuffer commit];
223 [commandBuffer waitUntilScheduled];
225 dispatch_block_t presentBlock = ^{
228 [_delegate onPresent:size
230 _lastPresentationTime = presentationTime;
231 [
self commit:surfaces];
238 if (presentationTime > 0) {
251 CFTimeInterval now = CACurrentMediaTime();
252 if (now < minPresentationTime) {
253 NSTimer* timer = [NSTimer timerWithTimeInterval:minPresentationTime - now
255 block:^(NSTimer* timer) {
258 [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
284- (instancetype)
init {
287 self->_surfaceAge = [NSMapTable weakToStrongObjectsMapTable];
293 NSNumber* age = [_surfaceAge objectForKey:surface];
294 return age != nil ? age.intValue : 0;
298 [_surfaceAge setObject:@(age) forKey:surface];
302 @
synchronized(
self) {
304 if (
_surfaces.firstObject != nil && !CGSizeEqualToSize(
_surfaces.firstObject.size, size)) {
305 [_surfaces removeAllObjects];
315 (res == nil || [
self ageForSurface:res] > [
self ageForSurface:
surface])) {
320 [_surfaces removeObject:res];
326- (void)returnSurfaces:(nonnull NSArray<
FlutterSurface*>*)returnedSurfaces {
327 @
synchronized(
self) {
329 [
self setAge:0 forSurface:surface];
332 [
self setAge:[
self ageForSurface:surface] + 1 forSurface:surface];
335 [_surfaces addObjectsFromArray:returnedSurfaces];
342 [_surfaces filterUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(FlutterSurface* surface,
343 NSDictionary* bindings) {
344 return [
self ageForSurface:surface] < kSurfaceEvictionAge;
349 [
self performSelectorOnMainThread:@selector(reschedule) withObject:nil waitUntilDone:NO];
353 @
synchronized(
self) {
359 @
synchronized(
self) {
360 [_surfaces removeAllObjects];
365 [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(onIdle) object:nil];
366 [
self performSelector:@selector(onIdle) withObject:nil afterDelay:kIdleDelay];
370 [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(onIdle) object:nil];
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
static void UpdateContentSubLayers(CALayer *layer, IOSurfaceRef surface, CGFloat scale, CGSize surfaceSize, NSColor *borderColor, const std::vector< FlutterRect > &paintRegion)
static NSColor * GetBorderColorForLayer(int layer)
static const double kIdleDelay
static const int kSurfaceEvictionAge
Type::kYUV Type::kRGBA() int(0.7 *637)
#define FML_DCHECK(condition)
NSMutableArray< FlutterSurface * > * _surfaces
NSMapTable< FlutterSurface *, NSNumber * > * _surfaceAge
static CGSize GetRequiredFrameSize(NSArray< FlutterSurfacePresentInfo * > *surfaces)
CALayer * _containingLayer
id< MTLCommandQueue > _commandQueue
NSMutableArray< FlutterSurface * > * _frontSurfaces
BOOL enableSurfaceDebugInfo()
NSArray * frontSurfaces()
__weak id< FlutterSurfaceManagerDelegate > _delegate
FlutterBackBufferCache * _backBufferCache
CFTimeInterval _lastPresentationTime
NSMutableArray< CALayer * > * _layers
FlutterBackBufferCache * backBufferCache()
NSNumber * _enableSurfaceDebugInfo