Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
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
4 changes: 4 additions & 0 deletions ci/licenses_golden/licenses_flutter
Original file line number Diff line number Diff line change
Expand Up @@ -765,6 +765,10 @@ FILE: ../../../flutter/shell/common/switches.h
FILE: ../../../flutter/shell/common/switches_unittests.cc
FILE: ../../../flutter/shell/common/thread_host.cc
FILE: ../../../flutter/shell/common/thread_host.h
FILE: ../../../flutter/shell/common/variable_refresh_rate_display.cc
FILE: ../../../flutter/shell/common/variable_refresh_rate_display.h
FILE: ../../../flutter/shell/common/variable_refresh_rate_display_unittests.cc
FILE: ../../../flutter/shell/common/variable_refresh_rate_reporter.h
FILE: ../../../flutter/shell/common/vsync_waiter.cc
FILE: ../../../flutter/shell/common/vsync_waiter.h
FILE: ../../../flutter/shell/common/vsync_waiter_fallback.cc
Expand Down
4 changes: 4 additions & 0 deletions shell/common/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,9 @@ source_set("common") {
"switches.h",
"thread_host.cc",
"thread_host.h",
"variable_refresh_rate_display.cc",
"variable_refresh_rate_display.h",
"variable_refresh_rate_reporter.h",
"vsync_waiter.cc",
"vsync_waiter.h",
"vsync_waiter_fallback.cc",
Expand Down Expand Up @@ -266,6 +269,7 @@ if (enable_unittests) {
"shell_unittests.cc",
"skp_shader_warmup_unittests.cc",
"switches_unittests.cc",
"variable_refresh_rate_display_unittests.cc",
]

deps = [
Expand Down
4 changes: 4 additions & 0 deletions shell/common/animator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,10 @@ void Animator::Render(std::unique_ptr<flutter::LayerTree> layer_tree) {
std::move(frame_timings_recorder_));
}

const VsyncWaiter& Animator::GetVsyncWaiter() const {
return *waiter_.get();
}

bool Animator::CanReuseLastLayerTree() {
return !regenerate_layer_tree_;
}
Expand Down
2 changes: 2 additions & 0 deletions shell/common/animator.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ class Animator final {

void Render(std::unique_ptr<flutter::LayerTree> layer_tree);

const VsyncWaiter& GetVsyncWaiter() const;

//--------------------------------------------------------------------------
/// @brief Schedule a secondary callback to be executed right after the
/// main `VsyncWaiter::AsyncWaitForVsync` callback (which is added
Expand Down
1 change: 1 addition & 0 deletions shell/common/display.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <optional>

#include "flutter/fml/macros.h"
#include "flutter/shell/common/variable_refresh_rate_reporter.h"

namespace flutter {

Expand Down
4 changes: 4 additions & 0 deletions shell/common/engine.cc
Original file line number Diff line number Diff line change
Expand Up @@ -600,4 +600,8 @@ void Engine::LoadDartDeferredLibraryError(intptr_t loading_unit_id,
}
}

const VsyncWaiter& Engine::GetVsyncWaiter() const {
return animator_->GetVsyncWaiter();
}

} // namespace flutter
2 changes: 2 additions & 0 deletions shell/common/engine.h
Original file line number Diff line number Diff line change
Expand Up @@ -903,6 +903,8 @@ class Engine final : public RuntimeDelegate, PointerDataDispatcher::Delegate {
return runtime_controller_.get();
}

const VsyncWaiter& GetVsyncWaiter() const;

private:
// |RuntimeDelegate|
std::string DefaultRouteName() override;
Expand Down
4 changes: 4 additions & 0 deletions shell/common/shell.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1872,4 +1872,8 @@ Shell::GetPlatformMessageHandler() const {
return platform_message_handler_;
}

const VsyncWaiter& Shell::GetVsyncWaiter() const {
return engine_->GetVsyncWaiter();
}

} // namespace flutter
2 changes: 2 additions & 0 deletions shell/common/shell.h
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,8 @@ class Shell final : public PlatformView::Delegate,
const std::shared_ptr<PlatformMessageHandler>& GetPlatformMessageHandler()
const;

const VsyncWaiter& GetVsyncWaiter() const;

private:
using ServiceProtocolHandler =
std::function<bool(const ServiceProtocol::Handler::ServiceProtocolMap&,
Expand Down
25 changes: 25 additions & 0 deletions shell/common/variable_refresh_rate_display.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "flutter/shell/common/variable_refresh_rate_display.h"
#include "flutter/fml/logging.h"

namespace flutter {

VariableRefreshRateDisplay::VariableRefreshRateDisplay(
DisplayId display_id,
const VariableRefreshRateReporter& refresh_rate_reporter)
: Display(display_id, refresh_rate_reporter.GetRefreshRate()),
refresh_rate_reporter_(refresh_rate_reporter) {}

VariableRefreshRateDisplay::VariableRefreshRateDisplay(
const VariableRefreshRateReporter& refresh_rate_reporter)
: Display(refresh_rate_reporter.GetRefreshRate()),
refresh_rate_reporter_(refresh_rate_reporter) {}

double VariableRefreshRateDisplay::GetRefreshRate() const {
return refresh_rate_reporter_.GetRefreshRate();
}

} // namespace flutter
37 changes: 37 additions & 0 deletions shell/common/variable_refresh_rate_display.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Copyright 2013 The Flutter 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 FLUTTER_SHELL_COMMON_VARIABLE_REFRESH_RATE_DISPLAY_H_
#define FLUTTER_SHELL_COMMON_VARIABLE_REFRESH_RATE_DISPLAY_H_

#include <optional>

#include "display.h"
#include "flutter/fml/macros.h"
#include "variable_refresh_rate_reporter.h"

namespace flutter {

/// A Display where the refresh rate can change over time.
class VariableRefreshRateDisplay : public Display {
public:
explicit VariableRefreshRateDisplay(
DisplayId display_id,
const VariableRefreshRateReporter& refresh_rate_reporter);
explicit VariableRefreshRateDisplay(
const VariableRefreshRateReporter& refresh_rate_reporter);
~VariableRefreshRateDisplay() = default;

// |Display|
double GetRefreshRate() const override;

private:
const VariableRefreshRateReporter& refresh_rate_reporter_;

FML_DISALLOW_COPY_AND_ASSIGN(VariableRefreshRateDisplay);
};

} // namespace flutter

#endif // FLUTTER_SHELL_COMMON_VARIABLE_REFRESH_RATE_DISPLAY_H_
29 changes: 29 additions & 0 deletions shell/common/variable_refresh_rate_display_unittests.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "variable_refresh_rate_display.h"
#include "vsync_waiters_test.h"

#include "gtest/gtest.h"

namespace flutter {
namespace testing {

TEST(VariableRefreshRateDisplayTest, ReportCorrectInitialRefreshRate) {
auto refresh_rate_reporter = std::make_unique<TestRefreshRateReporter>(60);
auto display =
flutter::VariableRefreshRateDisplay(*refresh_rate_reporter.get());
ASSERT_EQ(display.GetRefreshRate(), 60);
}

TEST(VariableRefreshRateDisplayTest, ReportCorrectRefreshRateWhenUpdated) {
auto refresh_rate_reporter = std::make_unique<TestRefreshRateReporter>(60);
auto display =
flutter::VariableRefreshRateDisplay(*refresh_rate_reporter.get());
refresh_rate_reporter->UpdateRefreshRate(30);
ASSERT_EQ(display.GetRefreshRate(), 30);
}

} // namespace testing
} // namespace flutter
28 changes: 28 additions & 0 deletions shell/common/variable_refresh_rate_reporter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright 2013 The Flutter 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 FLUTTER_SHELL_COMMON_VARIABLE_REFRESH_RATE_REPORTER_H_
#define FLUTTER_SHELL_COMMON_VARIABLE_REFRESH_RATE_REPORTER_H_

#include <functional>
#include <memory>
#include <mutex>
#include <unordered_map>

namespace flutter {

/// Abstract class that reprents a platform specific mechanism to report current
/// refresh rates.
class VariableRefreshRateReporter {
public:
VariableRefreshRateReporter() = default;

virtual double GetRefreshRate() const = 0;

FML_DISALLOW_COPY_AND_ASSIGN(VariableRefreshRateReporter);
};

} // namespace flutter

#endif // FLUTTER_SHELL_COMMON_VARIABLE_REFRESH_RATE_REPORTER_H_
11 changes: 11 additions & 0 deletions shell/common/vsync_waiters_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -64,5 +64,16 @@ void ConstantFiringVsyncWaiter::AwaitVSync() {
});
}

TestRefreshRateReporter::TestRefreshRateReporter(double refresh_rate)
: refresh_rate_(refresh_rate) {}

void TestRefreshRateReporter::UpdateRefreshRate(double refresh_rate) {
refresh_rate_ = refresh_rate;
}

double TestRefreshRateReporter::GetRefreshRate() const {
return refresh_rate_;
}

} // namespace testing
} // namespace flutter
12 changes: 12 additions & 0 deletions shell/common/vsync_waiters_test.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,18 @@ class ConstantFiringVsyncWaiter : public VsyncWaiter {
void AwaitVSync() override;
};

class TestRefreshRateReporter final : public VariableRefreshRateReporter {
public:
explicit TestRefreshRateReporter(double refresh_rate);
void UpdateRefreshRate(double refresh_rate);

// |RefreshRateReporter|
double GetRefreshRate() const override;

private:
double refresh_rate_;
};

} // namespace testing
} // namespace flutter

Expand Down
6 changes: 4 additions & 2 deletions shell/platform/darwin/ios/framework/Source/FlutterEngine.mm
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "flutter/shell/common/shell.h"
#include "flutter/shell/common/switches.h"
#include "flutter/shell/common/thread_host.h"
#include "flutter/shell/common/variable_refresh_rate_display.h"
#import "flutter/shell/platform/darwin/common/command_line.h"
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterBinaryMessengerRelay.h"
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterDartProject_Internal.h"
Expand Down Expand Up @@ -699,9 +700,10 @@ - (BOOL)createShell:(NSString*)entrypoint
}

- (void)initializeDisplays {
double refresh_rate = [DisplayLinkManager displayRefreshRate];
const flutter::VsyncWaiterIOS& vsync_waiter_ios =
static_cast<const flutter::VsyncWaiterIOS&>(_shell->GetVsyncWaiter());
std::vector<std::unique_ptr<flutter::Display>> displays;
displays.push_back(std::make_unique<flutter::Display>(refresh_rate));
displays.push_back(std::make_unique<flutter::VariableRefreshRateDisplay>(vsync_waiter_ios));
_shell->OnDisplayUpdates(flutter::DisplayUpdateType::kStartup, std::move(displays));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "flutter/fml/macros.h"
#include "flutter/fml/memory/weak_ptr.h"
#include "flutter/fml/platform/darwin/scoped_nsobject.h"
#include "flutter/shell/common/variable_refresh_rate_reporter.h"
#include "flutter/shell/common/vsync_waiter.h"

@interface DisplayLinkManager : NSObject
Expand All @@ -34,16 +35,21 @@

- (void)invalidate;

- (double)getRefreshRate;

@end

namespace flutter {

class VsyncWaiterIOS final : public VsyncWaiter {
class VsyncWaiterIOS final : public VsyncWaiter, public VariableRefreshRateReporter {
public:
explicit VsyncWaiterIOS(flutter::TaskRunners task_runners);

~VsyncWaiterIOS() override;

// |VariableRefreshRateReporter|
double GetRefreshRate() const override;

private:
fml::scoped_nsobject<VSyncClient> client_;

Expand Down
14 changes: 14 additions & 0 deletions shell/platform/darwin/ios/framework/Source/vsync_waiter_ios.mm
Original file line number Diff line number Diff line change
Expand Up @@ -39,18 +39,25 @@
[client_.get() await];
}

// |VariableRefreshRateReporter|
double VsyncWaiterIOS::GetRefreshRate() const {
return [client_.get() getRefreshRate];
}

} // namespace flutter

@implementation VSyncClient {
flutter::VsyncWaiter::Callback callback_;
fml::scoped_nsobject<CADisplayLink> display_link_;
double current_refresh_rate_;
}

- (instancetype)initWithTaskRunner:(fml::RefPtr<fml::TaskRunner>)task_runner
callback:(flutter::VsyncWaiter::Callback)callback {
self = [super init];

if (self) {
current_refresh_rate_ = [DisplayLinkManager displayRefreshRate];
callback_ = std::move(callback);
display_link_ = fml::scoped_nsobject<CADisplayLink> {
[[CADisplayLink displayLinkWithTarget:self selector:@selector(onDisplayLink:)] retain]
Expand Down Expand Up @@ -87,6 +94,9 @@ - (void)onDisplayLink:(CADisplayLink*)link {

std::unique_ptr<flutter::FrameTimingsRecorder> recorder =
std::make_unique<flutter::FrameTimingsRecorder>();

current_refresh_rate_ = round(1 / (frame_target_time - frame_start_time).ToSecondsF());

recorder->RecordVsync(frame_start_time, frame_target_time);
display_link_.get().paused = YES;

Expand All @@ -103,6 +113,10 @@ - (void)dealloc {
[super dealloc];
}

- (double)getRefreshRate {
return current_refresh_rate_;
}

@end

@implementation DisplayLinkManager
Expand Down