73
void safe_power_mode(mga::HwcConfiguration& config, MirPowerMode mode) noexcept
74
mga::DisplayName name,
75
mga::HwcConfiguration& control,
76
mg::DisplayConfigurationOutput& config,
77
MirPowerMode intended_mode)
79
if (config.power_mode != intended_mode)
81
control.power_mode(name, intended_mode);
82
config.power_mode = intended_mode;
87
mga::DisplayName name,
88
mga::HwcConfiguration& control,
89
mg::DisplayConfigurationOutput& config,
90
MirPowerMode intended_mode) noexcept
76
config.power_mode(mga::DisplayName::primary, mode);
93
power_mode(name, control, config, intended_mode);
96
void set_powermode_all_displays(
97
mga::HwcConfiguration& control,
98
mga::DisplayConfiguration& config,
99
MirPowerMode intended_mode) noexcept
101
power_mode_safe(mga::DisplayName::primary, control, config.primary(), intended_mode);
102
if (config.external().connected)
103
power_mode_safe(mga::DisplayName::external, control, config.external(), intended_mode);
79
106
std::unique_ptr<mga::ConfigurableDisplayBuffer> create_display_buffer(
107
std::shared_ptr<mga::DisplayDevice> const& display_device,
108
mga::DisplayName name,
80
109
mga::DisplayComponentFactory& display_buffer_builder,
81
mga::DisplayAttribs const& attribs,
110
mg::DisplayConfigurationOutput const& config,
82
111
std::shared_ptr<mg::GLProgramFactory> const& gl_program_factory,
83
112
mga::PbufferGLContext const& gl_context,
84
113
mga::OverlayOptimization overlay_option)
86
std::shared_ptr<mga::FramebufferBundle> fbs{display_buffer_builder.create_framebuffers(attribs)};
115
std::shared_ptr<mga::FramebufferBundle> fbs{display_buffer_builder.create_framebuffers(config)};
87
116
auto cache = std::make_shared<mga::InterpreterCache>();
88
auto interpreter = std::make_shared<mga::ServerRenderWindow>(fbs, cache);
117
auto interpreter = std::make_shared<mga::ServerRenderWindow>(fbs, config.current_format, cache);
89
118
auto native_window = std::make_shared<mga::MirNativeWindow>(interpreter);
90
119
return std::unique_ptr<mga::ConfigurableDisplayBuffer>(new mga::DisplayBuffer(
91
121
display_buffer_builder.create_layer_list(),
93
display_buffer_builder.create_display_device(),
96
126
*gl_program_factory,
105
135
std::shared_ptr<GLConfig> const& gl_config,
106
136
std::shared_ptr<DisplayReport> const& display_report,
107
137
mga::OverlayOptimization overlay_option) :
138
display_report{display_report},
108
139
display_buffer_builder{display_buffer_builder},
109
140
hwc_config{display_buffer_builder->create_hwc_configuration()},
110
hotplug_subscription{hwc_config->subscribe_to_config_changes(std::bind(&mga::Display::on_hotplug, this))},
111
primary_attribs(hwc_config->active_attribs_for(mga::DisplayName::primary)),
141
hotplug_subscription{hwc_config->subscribe_to_config_changes(
142
std::bind(&mga::Display::on_hotplug, this),
143
std::bind(&mga::Display::on_vsync, this, std::placeholders::_1))},
114
hwc_config->active_attribs_for(mga::DisplayName::external)),
115
gl_context{config.primary_config().current_format, *gl_config, *display_report},
116
display_buffer{create_display_buffer(
117
*display_buffer_builder,
122
display_change_pipe(new DisplayChangePipe)
145
hwc_config->active_config_for(mga::DisplayName::primary),
147
hwc_config->active_config_for(mga::DisplayName::external),
149
gl_context{config.primary().current_format, *gl_config, *display_report},
150
display_device(display_buffer_builder->create_display_device()),
151
display_change_pipe(new DisplayChangePipe),
152
gl_program_factory(gl_program_factory),
155
create_display_buffer(
157
mga::DisplayName::primary,
158
*display_buffer_builder,
124
164
//Some drivers (depending on kernel state) incorrectly report an error code indicating that the display is already on. Ignore the first failure.
125
safe_power_mode(*hwc_config, mir_power_mode_on);
165
set_powermode_all_displays(*hwc_config, config, mir_power_mode_on);
167
if (config.external().connected)
169
displays.add(mga::DisplayName::external,
170
create_display_buffer(
172
mga::DisplayName::external,
173
*display_buffer_builder,
177
mga::OverlayOptimization::disabled));
127
180
display_report->report_successful_setup_of_native_resources();
135
188
mga::Display::~Display() noexcept
137
if (config.primary_config().power_mode != mir_power_mode_off)
138
safe_power_mode(*hwc_config, mir_power_mode_off);
141
void mga::Display::for_each_display_buffer(std::function<void(mg::DisplayBuffer&)> const& f)
143
std::lock_guard<decltype(configuration_mutex)> lock{configuration_mutex};
145
if (config.primary_config().power_mode == mir_power_mode_on)
149
std::unique_ptr<mg::DisplayConfiguration> mga::Display::configuration() const
151
std::lock_guard<decltype(configuration_mutex)> lock{configuration_mutex};
190
set_powermode_all_displays(*hwc_config, config, mir_power_mode_off);
193
void mga::Display::update_configuration(std::lock_guard<std::mutex> const&) const
152
195
if (configuration_dirty)
197
auto external_config = hwc_config->active_config_for(mga::DisplayName::external);
198
if (external_config.connected)
199
power_mode(mga::DisplayName::external, *hwc_config, config.external(), mir_power_mode_on);
201
config.external().power_mode = mir_power_mode_off;
154
203
config = mga::DisplayConfiguration(
155
hwc_config->active_attribs_for(mga::DisplayName::primary),
156
hwc_config->active_attribs_for(mga::DisplayName::external));
204
hwc_config->active_config_for(mga::DisplayName::primary),
205
config.primary().power_mode,
206
std::move(external_config),
207
config.external().power_mode);
157
208
configuration_dirty = false;
212
void mga::Display::for_each_display_sync_group(std::function<void(mg::DisplaySyncGroup&)> const& f)
214
std::lock_guard<decltype(configuration_mutex)> lock{configuration_mutex};
215
update_configuration(lock);
216
if ((config.external().connected) && !displays.display_present(mga::DisplayName::external))
217
displays.add(mga::DisplayName::external,
218
create_display_buffer(
220
mga::DisplayName::external,
221
*display_buffer_builder,
225
mga::OverlayOptimization::disabled));
226
if ((!config.external().connected) && displays.display_present(mga::DisplayName::external))
227
displays.remove(mga::DisplayName::external);
232
std::unique_ptr<mg::DisplayConfiguration> mga::Display::configuration() const
234
std::lock_guard<decltype(configuration_mutex)> lock{configuration_mutex};
235
update_configuration(lock);
160
236
return std::unique_ptr<mg::DisplayConfiguration>(new mga::DisplayConfiguration(config));
168
244
std::lock_guard<decltype(configuration_mutex)> lock{configuration_mutex};
170
new_configuration.for_each_output([this](mg::DisplayConfigurationOutput const& output) {
171
//TODO: support configuring the external displaybuffer
172
if (config.primary_config().id == output.id)
174
if (output.current_format != config[output.id].current_format)
175
BOOST_THROW_EXCEPTION(std::logic_error("could not change display buffer format"));
177
//TODO: We don't support rotation yet, so
178
//we preserve this orientation change so the compositor can rotate everything in GL
179
config[output.id].orientation = output.orientation;
181
if (output.power_mode != config[output.id].power_mode)
183
hwc_config->power_mode(mga::DisplayName::primary, output.power_mode);
184
config[output.id].power_mode = output.power_mode;
187
display_buffer->configure(output.power_mode, output.orientation);
246
new_configuration.for_each_output([this](mg::DisplayConfigurationOutput const& output)
248
if (output.current_format != config[output.id].current_format)
249
BOOST_THROW_EXCEPTION(std::logic_error("could not change display buffer format"));
251
config[output.id].orientation = output.orientation;
252
if (config.primary().id == output.id)
254
power_mode(mga::DisplayName::primary, *hwc_config, config.primary(), output.power_mode);
255
displays.configure(mga::DisplayName::primary, output.power_mode, output.orientation);
257
else if (config.external().connected)
259
power_mode(mga::DisplayName::external, *hwc_config, config.external(), output.power_mode);
260
displays.configure(mga::DisplayName::external, output.power_mode, output.orientation);
192
//NOTE: We cannot call back to hwc from within the hotplug callback. Only arrange for an update.
265
//NOTE: We avoid calling back to hwc from within the hotplug callback. Only arrange for an update.
193
266
void mga::Display::on_hotplug()
195
268
std::lock_guard<decltype(configuration_mutex)> lock{configuration_mutex};