19
19
#include "real_kms_output.h"
20
20
#include "page_flipper.h"
21
#include "kms-utils/kms_connector.h"
21
22
#include "mir/fatal.h"
22
23
#include "mir/log.h"
23
24
#include <string.h> // strcmp
25
26
namespace mg = mir::graphics;
26
27
namespace mgm = mg::mesa;
28
namespace mgk = mg::kms;
27
29
namespace geom = mir::geometry;
32
bool encoder_is_used(mgm::DRMModeResources const& resources, uint32_t encoder_id)
34
bool encoder_used{false};
36
resources.for_each_connector([&](mgm::DRMModeConnectorUPtr connector)
38
if (connector->encoder_id == encoder_id &&
39
connector->connection == DRM_MODE_CONNECTED)
41
auto encoder = resources.encoder(connector->encoder_id);
44
auto crtc = resources.crtc(encoder->crtc_id);
54
bool crtc_is_used(mgm::DRMModeResources const& resources, uint32_t crtc_id)
56
bool crtc_used{false};
58
resources.for_each_connector([&](mgm::DRMModeConnectorUPtr connector)
60
if (connector->connection == DRM_MODE_CONNECTED)
62
auto encoder = resources.encoder(connector->encoder_id);
65
if (encoder->crtc_id == crtc_id)
74
std::vector<mgm::DRMModeEncoderUPtr>
75
connector_available_encoders(mgm::DRMModeResources const& resources,
76
drmModeConnector const* connector)
78
std::vector<mgm::DRMModeEncoderUPtr> encoders;
80
for (int i = 0; i < connector->count_encoders; i++)
82
if (!encoder_is_used(resources, connector->encoders[i]))
83
encoders.push_back(resources.encoder(connector->encoders[i]));
89
bool encoder_supports_crtc_index(drmModeEncoder const* encoder, uint32_t crtc_index)
91
return (encoder->possible_crtcs & (1 << crtc_index));
94
const char *connector_type_name(uint32_t type)
96
static const int nnames = 15;
97
static const char * const names[nnames] =
98
{ // Ordered according to xf86drmMode.h
122
std::string connector_name(const drmModeConnector *conn)
124
std::string name = connector_type_name(conn->connector_type);
126
name += std::to_string(conn->connector_type_id);
132
31
mgm::RealKMSOutput::RealKMSOutput(int drm_fd, uint32_t connector_id,
133
32
std::shared_ptr<PageFlipper> const& page_flipper)
134
33
: drm_fd{drm_fd}, connector_id{connector_id}, page_flipper{page_flipper},
141
DRMModeResources resources{drm_fd};
40
kms::DRMModeResources resources{drm_fd};
143
auto encoder = resources.encoder(connector->encoder_id);
42
if (connector->encoder_id)
146
auto crtc = resources.crtc(encoder->crtc_id);
44
auto encoder = resources.encoder(connector->encoder_id);
47
saved_crtc = *resources.crtc(encoder->crtc_id);
157
57
void mgm::RealKMSOutput::reset()
159
DRMModeResources resources{drm_fd};
59
kms::DRMModeResources resources{drm_fd};
161
61
/* Update the connector to ensure we have the latest information */
162
connector = resources.connector(connector_id);
165
fatal_error("No DRM connector found");
64
connector = resources.connector(connector_id);
66
catch (std::exception const& e)
68
fatal_error(e.what());
167
71
// TODO: What if we can't locate the DPMS property?
168
72
for (int i = 0; i < connector->count_props; i++)
208
112
if (!ensure_crtc())
210
114
fatal_error("Output %s has no associated CRTC to set a framebuffer on",
211
connector_name(connector.get()).c_str());
115
mgk::connector_name(connector).c_str());
214
118
auto ret = drmModeSetCrtc(drm_fd, current_crtc->crtc_id,
228
132
void mgm::RealKMSOutput::clear_crtc()
231
* In order to actually clear the output, we need to have a crtc
232
* connected to the output/connector so that we can disconnect
233
* it. However, not being able to get a crtc is OK, since it means
234
* that the output cannot be displaying anything anyway.
141
* In order to actually clear the output, we need to have a crtc
142
* connected to the output/connector so that we can disconnect
143
* it. However, not being able to get a crtc is OK, since it means
144
* that the output cannot be displaying anything anyway.
239
149
auto result = drmModeSetCrtc(drm_fd, current_crtc->crtc_id,
240
150
0, 0, 0, nullptr, 0, nullptr);
243
153
fatal_error("Couldn't clear output %s (drmModeSetCrtc = %d)",
244
connector_name(connector.get()).c_str(), result);
154
mgk::connector_name(connector).c_str(), result);
247
157
current_crtc = nullptr;
334
244
if (connector->connection != DRM_MODE_CONNECTED)
337
DRMModeResources resources{drm_fd};
339
/* Check to see if there is a crtc already connected */
340
auto encoder = resources.encoder(connector->encoder_id);
342
current_crtc = resources.crtc(encoder->crtc_id);
344
/* If we don't have a current crtc, try to find one */
347
auto available_encoders = connector_available_encoders(resources, connector.get());
351
resources.for_each_crtc([&](DRMModeCrtcUPtr crtc)
353
if (!current_crtc && !crtc_is_used(resources, crtc->crtc_id))
355
for (auto& enc : available_encoders)
357
if (encoder_supports_crtc_index(enc.get(), crtc_index))
359
current_crtc = std::move(crtc);
247
current_crtc = mgk::find_crtc_for_connector(drm_fd, connector);
369
250
return (current_crtc != nullptr);