37
auto configure_outputs(MirConnection* connection)
38
-> std::unordered_map<uint32_t, std::shared_ptr<mgn::detail::NestedOutput>>
40
// TODO for proper mirrored mode support we will need to detect overlapping outputs and
41
// TODO only use a single surface for them. The OverlappingOutputGrouping utility class
42
// TODO used by the GBM backend for a similar purpose could help with this.
44
mgnw::MirDisplayConfigHandle display_config{connection};
46
std::unordered_map<uint32_t, std::shared_ptr<mgn::detail::NestedOutput>> result;
48
for (decltype(display_config->num_outputs) i = 0; i != display_config->num_outputs; ++i)
50
auto const egl_display_info = display_config->outputs+i;
52
if (egl_display_info->used)
54
result[egl_display_info->output_id] =
55
std::make_shared<mgn::detail::NestedOutput>(connection, egl_display_info);
62
37
EGLint const egl_attribs[] = {
63
38
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
79
mgn::detail::MirSurfaceHandle::MirSurfaceHandle(MirConnection* connection, MirDisplayOutput* const egl_display_info)
54
mgn::detail::MirSurfaceHandle::MirSurfaceHandle(MirConnection* connection, DisplayConfigurationOutput const& output)
81
auto const egl_display_mode = egl_display_info->modes + egl_display_info->current_mode;
82
auto const egl_display_format = egl_display_info->output_formats[egl_display_info->current_output_format];
56
auto const& egl_display_mode = output.modes[output.current_mode_index];
57
auto const egl_display_format = output.pixel_formats[output.current_format_index];
84
59
MirSurfaceParameters const request_params =
86
61
"Mir nested display",
87
int(egl_display_mode->horizontal_resolution),
88
int(egl_display_mode->vertical_resolution),
62
egl_display_mode.size.width.as_int(),
63
egl_display_mode.size.height.as_int(),
64
MirPixelFormat(egl_display_format),
90
65
mir_buffer_usage_hardware,
91
egl_display_info->output_id
66
static_cast<uint32_t>(output.id.as_value())
94
69
mir_surface = mir_connection_create_surface_sync(connection, &request_params);
161
136
if (!display_handles.fetch_add(-1)) eglTerminate(egl_display);
164
mgn::detail::NestedOutput::NestedOutput(MirConnection* connection, MirDisplayOutput* const egl_display_info) :
165
mir_surface(connection, egl_display_info),
139
mgn::detail::NestedOutput::NestedOutput(MirConnection* connection, DisplayConfigurationOutput const& output) :
140
mir_surface(connection, output),
166
141
egl_display{connection},
167
142
egl_config{(egl_display.initialize(), egl_display.choose_config(egl_attribs))},
168
143
egl_surface{egl_display, egl_display.egl_surface(egl_config, mir_surface)},
180
155
mgn::NestedDisplay::NestedDisplay(MirConnection* connection, std::shared_ptr<mg::DisplayReport> const& display_report) :
181
156
connection{connection},
182
157
display_report{display_report},
183
outputs{configure_outputs(connection)}
186
BOOST_THROW_EXCEPTION(std::runtime_error("Nested Mir needs at least one output for display"));
160
configure(*configuration());
189
163
mgn::NestedDisplay::~NestedDisplay() noexcept
203
177
void mgn::NestedDisplay::configure(mg::DisplayConfiguration const& configuration)
179
decltype(outputs) result;
181
// TODO for proper mirrored mode support we will need to detect overlapping outputs and
182
// TODO only use a single surface for them. The OverlappingOutputGrouping utility class
183
// TODO used by the GBM backend for a similar purpose could help with this.
184
configuration.for_each_output(
185
[&](mg::DisplayConfigurationOutput const& output)
189
result[output.id] = std::make_shared<mgn::detail::NestedOutput>(connection, output);
194
BOOST_THROW_EXCEPTION(std::runtime_error("Nested Mir needs at least one output for display"));
205
196
auto const& conf = dynamic_cast<NestedDisplayConfiguration const&>(configuration);
198
outputs.swap(result);
207
199
mir_connection_apply_display_config(connection, conf);
204
void display_config_callback_thunk(MirConnection* /*connection*/, void* callback)
206
(*static_cast<mg::DisplayConfigurationChangeHandler*>(callback))();
210
210
void mgn::NestedDisplay::register_configuration_change_handler(
211
211
EventHandlerRegister& /*handlers*/,
212
DisplayConfigurationChangeHandler const& /*conf_change_handler*/)
212
DisplayConfigurationChangeHandler const& conf_change_handler)
214
// TODO need to watch for changes via mir_connection_set_display_config_change_callback()
215
// TODO and invoke conf_change_handler() (I don't think we need handlers)
214
mir_connection_set_display_config_change_callback(
216
&display_config_callback_thunk,
217
&(my_conf_change_handler = conf_change_handler));
218
220
void mgn::NestedDisplay::register_pause_resume_handlers(