-
Notifications
You must be signed in to change notification settings - Fork 6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[ios] Lock refresh rate to 80fps when threads are merged #39172
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,8 +12,12 @@ | |
|
||
#include "flutter/common/task_runners.h" | ||
#include "flutter/fml/logging.h" | ||
#include "flutter/fml/memory/task_runner_checker.h" | ||
#include "flutter/fml/trace_event.h" | ||
|
||
// When calculating refresh rate diffrence, anything within 0.1 fps is ignored. | ||
const static double kRefreshRateDiffToIgnore = 0.1; | ||
|
||
namespace flutter { | ||
|
||
VsyncWaiterIOS::VsyncWaiterIOS(const flutter::TaskRunners& task_runners) | ||
|
@@ -26,6 +30,7 @@ | |
client_ = | ||
fml::scoped_nsobject{[[VSyncClient alloc] initWithTaskRunner:task_runners_.GetUITaskRunner() | ||
callback:callback]}; | ||
max_refresh_rate_ = [DisplayLinkManager displayRefreshRate]; | ||
} | ||
|
||
VsyncWaiterIOS::~VsyncWaiterIOS() { | ||
|
@@ -35,6 +40,19 @@ | |
} | ||
|
||
void VsyncWaiterIOS::AwaitVSync() { | ||
double new_max_refresh_rate = [DisplayLinkManager displayRefreshRate]; | ||
if (fml::TaskRunnerChecker::RunsOnTheSameThread( | ||
task_runners_.GetRasterTaskRunner()->GetTaskQueueId(), | ||
task_runners_.GetPlatformTaskRunner()->GetTaskQueueId())) { | ||
// Pressure tested on iPhone 13 pro, the oldest iPhone that supports refresh rate greater than | ||
// 60fps. A flutter app can handle fast scrolling on 80 fps with 6 PlatformViews in the scene at | ||
// the same time. | ||
new_max_refresh_rate = 80; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I originally set it to 60, but it looks like we can def hit 80 consistently. I decided to lock it at 80 so the scrolling with PlatformView is still smoother than 60fps. This might change when we re-evaluate what the default fps we want the Flutter apps to run on after we implement a new API for the APP to set refresh rates, see flutter/flutter#119268 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you add a comment for why you chose this? What hardware did you try? |
||
} | ||
if (fabs(new_max_refresh_rate - max_refresh_rate_) > kRefreshRateDiffToIgnore) { | ||
max_refresh_rate_ = new_max_refresh_rate; | ||
[client_.get() setMaxRefreshRate:max_refresh_rate_]; | ||
} | ||
[client_.get() await]; | ||
} | ||
|
||
|
@@ -43,6 +61,10 @@ | |
return [client_.get() getRefreshRate]; | ||
} | ||
|
||
fml::scoped_nsobject<VSyncClient> VsyncWaiterIOS::GetVsyncClient() const { | ||
return client_; | ||
} | ||
|
||
} // namespace flutter | ||
|
||
@implementation VSyncClient { | ||
|
@@ -64,7 +86,7 @@ - (instancetype)initWithTaskRunner:(fml::RefPtr<fml::TaskRunner>)task_runner | |
}; | ||
display_link_.get().paused = YES; | ||
|
||
[self setMaxRefreshRateIfEnabled]; | ||
[self setMaxRefreshRate:[DisplayLinkManager displayRefreshRate]]; | ||
|
||
task_runner->PostTask([client = [self retain]]() { | ||
[client->display_link_.get() addToRunLoop:[NSRunLoop currentRunLoop] | ||
|
@@ -76,15 +98,12 @@ - (instancetype)initWithTaskRunner:(fml::RefPtr<fml::TaskRunner>)task_runner | |
return self; | ||
} | ||
|
||
- (void)setMaxRefreshRateIfEnabled { | ||
NSNumber* minimumFrameRateDisabled = | ||
[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CADisableMinimumFrameDurationOnPhone"]; | ||
if (![minimumFrameRateDisabled boolValue]) { | ||
- (void)setMaxRefreshRate:(double)refreshRate { | ||
if (!DisplayLinkManager.maxRefreshRateEnabledOnIPhone) { | ||
return; | ||
} | ||
double maxFrameRate = fmax([DisplayLinkManager displayRefreshRate], 60); | ||
double maxFrameRate = fmax(refreshRate, 60); | ||
double minFrameRate = fmax(maxFrameRate / 2, 60); | ||
|
||
if (@available(iOS 15.0, *)) { | ||
display_link_.get().preferredFrameRateRange = | ||
CAFrameRateRangeMake(minFrameRate, maxFrameRate, maxFrameRate); | ||
|
@@ -170,4 +189,9 @@ - (void)onDisplayLink:(CADisplayLink*)link { | |
// no-op. | ||
} | ||
|
||
+ (BOOL)maxRefreshRateEnabledOnIPhone { | ||
return [[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CADisableMinimumFrameDurationOnPhone"] | ||
boolValue]; | ||
} | ||
|
||
@end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pro-motion iPad Pros too, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is only for iPhone, iPad always has high refresh rate on, let me add a comment about it too.