Skip to content

Commit 67fdd7e

Browse files
authored
Embedder API Support for display settings (flutter#21355)
Embedders can now notify shell during startup about the various displays and their corresponding settings. Adds a notion of Display update type which can later include chages to displays during runtime such as addition / removal / reconfiguration of displays. We also remove the responsibility of providing the refresh rate from `vsync_waiter` to `DisplayManager`. Rewires existing platform implementations of the said API to use `Shell::OnDisplayUpdate` to notify the display manager of the startup configuration. DisplayManager is also thread-safe to account for rasterizer and UI thread accesses.
1 parent aa8d5d4 commit 67fdd7e

27 files changed

+645
-136
lines changed

ci/licenses_golden/licenses_flutter

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -599,6 +599,9 @@ FILE: ../../../flutter/shell/common/animator_unittests.cc
599599
FILE: ../../../flutter/shell/common/canvas_spy.cc
600600
FILE: ../../../flutter/shell/common/canvas_spy.h
601601
FILE: ../../../flutter/shell/common/canvas_spy_unittests.cc
602+
FILE: ../../../flutter/shell/common/display.h
603+
FILE: ../../../flutter/shell/common/display_manager.cc
604+
FILE: ../../../flutter/shell/common/display_manager.h
602605
FILE: ../../../flutter/shell/common/engine.cc
603606
FILE: ../../../flutter/shell/common/engine.h
604607
FILE: ../../../flutter/shell/common/engine_unittests.cc

shell/common/BUILD.gn

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ source_set("common") {
6464
"animator.h",
6565
"canvas_spy.cc",
6666
"canvas_spy.h",
67+
"display.h",
68+
"display_manager.cc",
69+
"display_manager.h",
6770
"engine.cc",
6871
"engine.h",
6972
"isolate_configuration.cc",

shell/common/animator.cc

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,6 @@ Animator::Animator(Delegate& delegate,
5353

5454
Animator::~Animator() = default;
5555

56-
float Animator::GetDisplayRefreshRate() const {
57-
return waiter_->GetDisplayRefreshRate();
58-
}
59-
6056
void Animator::Stop() {
6157
paused_ = true;
6258
}

shell/common/animator.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,6 @@ class Animator final {
4747

4848
~Animator();
4949

50-
float GetDisplayRefreshRate() const;
51-
5250
void RequestFrame(bool regenerate_layer_tree = true);
5351

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

shell/common/display.h

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
#ifndef FLUTTER_SHELL_COMMON_DISPLAY_H_
6+
#define FLUTTER_SHELL_COMMON_DISPLAY_H_
7+
8+
#include <optional>
9+
10+
namespace flutter {
11+
12+
/// Unique ID per display that is stable until the Flutter application restarts.
13+
/// See also: `flutter::Display`
14+
typedef uint64_t DisplayId;
15+
16+
/// To be used when the display refresh rate is unknown.
17+
static constexpr double kUnknownDisplayRefreshRate = 0;
18+
19+
/// Display refers to a graphics hardware system consisting of a framebuffer,
20+
/// typically a monitor or a screen. This class holds the various display
21+
/// settings.
22+
class Display {
23+
public:
24+
//------------------------------------------------------------------------------
25+
/// @brief Construct a new Display object in case where the display id of the
26+
/// display is known. In cases where there is more than one display, every
27+
/// display is expected to have a display id.
28+
///
29+
Display(DisplayId display_id, double refresh_rate)
30+
: display_id_(display_id), refresh_rate_(refresh_rate) {}
31+
32+
//------------------------------------------------------------------------------
33+
/// @brief Construct a new Display object when there is only a single display.
34+
/// When there are multiple displays, every display must have a display id.
35+
///
36+
explicit Display(double refresh_rate)
37+
: display_id_({}), refresh_rate_(refresh_rate) {}
38+
39+
~Display() = default;
40+
41+
// Get the display's maximum refresh rate in the unit of frame per second.
42+
// Return `kUnknownDisplayRefreshRate` if the refresh rate is unknown.
43+
double GetRefreshRate() const { return refresh_rate_; }
44+
45+
/// Returns the `DisplayId` of the display.
46+
std::optional<DisplayId> GetDisplayId() const { return display_id_; }
47+
48+
private:
49+
std::optional<DisplayId> display_id_;
50+
double refresh_rate_;
51+
};
52+
53+
} // namespace flutter
54+
55+
#endif // FLUTTER_SHELL_COMMON_DISPLAY_H_

shell/common/display_manager.cc

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
#include "flutter/shell/common/display_manager.h"
6+
7+
#include "flutter/fml/logging.h"
8+
#include "flutter/fml/macros.h"
9+
10+
namespace flutter {
11+
12+
DisplayManager::DisplayManager() = default;
13+
14+
DisplayManager::~DisplayManager() = default;
15+
16+
double DisplayManager::GetMainDisplayRefreshRate() const {
17+
std::scoped_lock lock(displays_mutex_);
18+
if (displays_.empty()) {
19+
return kUnknownDisplayRefreshRate;
20+
} else {
21+
return displays_[0].GetRefreshRate();
22+
}
23+
}
24+
25+
void DisplayManager::HandleDisplayUpdates(DisplayUpdateType update_type,
26+
std::vector<Display> displays) {
27+
std::scoped_lock lock(displays_mutex_);
28+
CheckDisplayConfiguration(displays);
29+
switch (update_type) {
30+
case DisplayUpdateType::kStartup:
31+
FML_CHECK(displays_.empty());
32+
displays_ = displays;
33+
return;
34+
default:
35+
FML_CHECK(false) << "Unknown DisplayUpdateType.";
36+
}
37+
}
38+
39+
void DisplayManager::CheckDisplayConfiguration(
40+
std::vector<Display> displays) const {
41+
FML_CHECK(!displays.empty());
42+
if (displays.size() > 1) {
43+
for (auto& display : displays) {
44+
FML_CHECK(display.GetDisplayId().has_value());
45+
}
46+
}
47+
}
48+
49+
} // namespace flutter

shell/common/display_manager.h

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
#ifndef FLUTTER_SHELL_COMMON_DISPLAY_MANAGER_H_
6+
#define FLUTTER_SHELL_COMMON_DISPLAY_MANAGER_H_
7+
8+
#include <mutex>
9+
#include <vector>
10+
11+
#include "flutter/shell/common/display.h"
12+
13+
namespace flutter {
14+
15+
/// The update type parameter that is passed to
16+
/// `DisplayManager::HandleDisplayUpdates`.
17+
enum class DisplayUpdateType {
18+
/// `flutter::Display`s that were active during start-up. A display is
19+
/// considered active if:
20+
/// 1. The frame buffer hardware is connected.
21+
/// 2. The display is drawable, e.g. it isn't being mirrored from another
22+
/// connected display or sleeping.
23+
kStartup
24+
};
25+
26+
/// Manages lifecycle of the connected displays. This class is thread-safe.
27+
class DisplayManager {
28+
public:
29+
DisplayManager();
30+
31+
~DisplayManager();
32+
33+
/// Returns the display refresh rate of the main display. In cases where there
34+
/// is only one display connected, it will return that. We do not yet support
35+
/// cases where there are multiple displays.
36+
///
37+
/// When there are no registered displays, it returns
38+
/// `kUnknownDisplayRefreshRate`.
39+
double GetMainDisplayRefreshRate() const;
40+
41+
/// Handles the display updates.
42+
void HandleDisplayUpdates(DisplayUpdateType update_type,
43+
std::vector<Display> displays);
44+
45+
private:
46+
/// Guards `displays_` vector.
47+
mutable std::mutex displays_mutex_;
48+
std::vector<Display> displays_;
49+
50+
/// Checks that the provided display configuration is valid. Currently this
51+
/// ensures that all the displays have an id in the case there are multiple
52+
/// displays. In case where there is a single display, it is valid for the
53+
/// display to not have an id.
54+
void CheckDisplayConfiguration(std::vector<Display> displays) const;
55+
};
56+
57+
} // namespace flutter
58+
59+
#endif // FLUTTER_SHELL_COMMON_DISPLAY_MANAGER_H_

shell/common/engine.cc

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -97,10 +97,6 @@ Engine::Engine(Delegate& delegate,
9797

9898
Engine::~Engine() = default;
9999

100-
float Engine::GetDisplayRefreshRate() const {
101-
return animator_->GetDisplayRefreshRate();
102-
}
103-
104100
fml::WeakPtr<Engine> Engine::GetWeakPtr() const {
105101
return weak_factory_.GetWeakPtr();
106102
}

shell/common/engine.h

Lines changed: 1 addition & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "flutter/runtime/runtime_controller.h"
2525
#include "flutter/runtime/runtime_delegate.h"
2626
#include "flutter/shell/common/animator.h"
27+
#include "flutter/shell/common/display_manager.h"
2728
#include "flutter/shell/common/platform_view.h"
2829
#include "flutter/shell/common/pointer_data_dispatcher.h"
2930
#include "flutter/shell/common/rasterizer.h"
@@ -328,30 +329,6 @@ class Engine final : public RuntimeDelegate,
328329
///
329330
~Engine() override;
330331

331-
//----------------------------------------------------------------------------
332-
/// @brief Gets the refresh rate in frames per second of the vsync waiter
333-
/// used by the animator managed by this engine. This information
334-
/// is purely advisory and is not used by any component. It is
335-
/// only used by the tooling to visualize frame performance.
336-
///
337-
/// @attention The display refresh rate is useless for frame scheduling
338-
/// because it can vary and more accurate frame specific
339-
/// information is given to the engine by the vsync waiter
340-
/// already. However, this call is used by the tooling to ask very
341-
/// high level questions about display refresh rate. For example,
342-
/// "Is the display 60 or 120Hz?". This information is quite
343-
/// unreliable (not available immediately on launch on some
344-
/// platforms), variable and advisory. It must not be used by any
345-
/// component that claims to use it to perform accurate frame
346-
/// scheduling.
347-
///
348-
/// @return The display refresh rate in frames per second. This may change
349-
/// from frame to frame, throughout the lifecycle of the
350-
/// application, and, may not be available immediately upon
351-
/// application launch.
352-
///
353-
float GetDisplayRefreshRate() const;
354-
355332
//----------------------------------------------------------------------------
356333
/// @return The pointer to this instance of the engine. The engine may
357334
/// only be accessed safely on the UI task runner.

shell/common/rasterizer.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,9 @@ class Rasterizer final : public SnapshotDelegate {
6868
///
6969
virtual void OnFrameRasterized(const FrameTiming& frame_timing) = 0;
7070

71-
/// Time limit for a smooth frame. See `Engine::GetDisplayRefreshRate`.
71+
/// Time limit for a smooth frame.
72+
///
73+
/// See: `DisplayManager::GetMainDisplayRefreshRate`.
7274
virtual fml::Milliseconds GetFrameBudget() = 0;
7375

7476
/// Target time for the latest frame. See also `Shell::OnAnimatorBeginFrame`

0 commit comments

Comments
 (0)