1 // Copyright 2014 The Chromium 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.
5 #include "ui/ozone/platform/dri/dri_util.h"
13 #include <xf86drmMode.h>
15 #include "base/strings/stringprintf.h"
16 #include "ui/ozone/platform/dri/drm_device.h"
17 #include "ui/ozone/platform/dri/screen_manager.h"
23 const char kDefaultGraphicsCardPattern
[] = "/dev/dri/card%d";
25 bool IsCrtcInUse(uint32_t crtc
,
26 const ScopedVector
<HardwareDisplayControllerInfo
>& displays
) {
27 for (size_t i
= 0; i
< displays
.size(); ++i
) {
28 if (crtc
== displays
[i
]->crtc()->crtc_id
)
35 uint32_t GetCrtc(int fd
,
36 drmModeConnector
* connector
,
37 drmModeRes
* resources
,
38 const ScopedVector
<HardwareDisplayControllerInfo
>& displays
) {
39 // If the connector already has an encoder try to re-use.
40 if (connector
->encoder_id
) {
41 ScopedDrmEncoderPtr
encoder(drmModeGetEncoder(fd
, connector
->encoder_id
));
42 if (encoder
&& encoder
->crtc_id
&& !IsCrtcInUse(encoder
->crtc_id
, displays
))
43 return encoder
->crtc_id
;
46 // Try to find an encoder for the connector.
47 for (int i
= 0; i
< connector
->count_encoders
; ++i
) {
48 ScopedDrmEncoderPtr
encoder(drmModeGetEncoder(fd
, connector
->encoders
[i
]));
52 for (int j
= 0; j
< resources
->count_crtcs
; ++j
) {
53 // Check if the encoder is compatible with this CRTC
54 if (!(encoder
->possible_crtcs
& (1 << j
)) ||
55 IsCrtcInUse(resources
->crtcs
[j
], displays
))
58 return resources
->crtcs
[j
];
67 HardwareDisplayControllerInfo::HardwareDisplayControllerInfo(
68 ScopedDrmConnectorPtr connector
,
69 ScopedDrmCrtcPtr crtc
)
70 : connector_(connector
.Pass()),
73 HardwareDisplayControllerInfo::~HardwareDisplayControllerInfo() {}
75 ScopedVector
<HardwareDisplayControllerInfo
>
76 GetAvailableDisplayControllerInfos(int fd
) {
77 ScopedDrmResourcesPtr
resources(drmModeGetResources(fd
));
78 DCHECK(resources
) << "Failed to get DRM resources";
79 ScopedVector
<HardwareDisplayControllerInfo
> displays
;
81 for (int i
= 0; i
< resources
->count_connectors
; ++i
) {
82 ScopedDrmConnectorPtr
connector(drmModeGetConnector(
83 fd
, resources
->connectors
[i
]));
85 if (!connector
|| connector
->connection
!= DRM_MODE_CONNECTED
||
86 connector
->count_modes
== 0)
89 uint32_t crtc_id
= GetCrtc(fd
, connector
.get(), resources
.get(), displays
);
93 ScopedDrmCrtcPtr
crtc(drmModeGetCrtc(fd
, crtc_id
));
94 displays
.push_back(new HardwareDisplayControllerInfo(connector
.Pass(),
98 return displays
.Pass();
101 bool SameMode(const drmModeModeInfo
& lhs
, const drmModeModeInfo
& rhs
) {
102 return lhs
.clock
== rhs
.clock
&&
103 lhs
.hdisplay
== rhs
.hdisplay
&&
104 lhs
.vdisplay
== rhs
.vdisplay
&&
105 lhs
.vrefresh
== rhs
.vrefresh
&&
106 lhs
.hsync_start
== rhs
.hsync_start
&&
107 lhs
.hsync_end
== rhs
.hsync_end
&&
108 lhs
.htotal
== rhs
.htotal
&&
109 lhs
.hskew
== rhs
.hskew
&&
110 lhs
.vsync_start
== rhs
.vsync_start
&&
111 lhs
.vsync_end
== rhs
.vsync_end
&&
112 lhs
.vtotal
== rhs
.vtotal
&&
113 lhs
.vscan
== rhs
.vscan
&&
114 lhs
.flags
== rhs
.flags
&&
115 strcmp(lhs
.name
, rhs
.name
) == 0;
118 bool MapDumbBuffer(int fd
,
122 struct drm_mode_map_dumb map_request
;
123 memset(&map_request
, 0, sizeof(map_request
));
124 map_request
.handle
= handle
;
125 if (drmIoctl(fd
, DRM_IOCTL_MODE_MAP_DUMB
, &map_request
)) {
126 VLOG(2) << "Cannot prepare dumb buffer for mapping (" << errno
<< ") "
133 PROT_READ
| PROT_WRITE
,
137 if (*pixels
== MAP_FAILED
) {
138 VLOG(2) << "Cannot mmap dumb buffer (" << errno
<< ") " << strerror(errno
);
145 void ForceInitializationOfPrimaryDisplay(const scoped_refptr
<DrmDevice
>& drm
,
146 ScreenManager
* screen_manager
) {
147 LOG(WARNING
) << "Forcing initialization of primary display.";
148 ScopedVector
<HardwareDisplayControllerInfo
> displays
=
149 GetAvailableDisplayControllerInfos(drm
->get_fd());
151 if (displays
.empty())
154 ScopedDrmPropertyPtr
dpms(drm
->GetProperty(displays
[0]->connector(), "DPMS"));
156 screen_manager
->AddDisplayController(drm
, displays
[0]->crtc()->crtc_id
,
157 displays
[0]->connector()->connector_id
);
158 if (screen_manager
->ConfigureDisplayController(
159 drm
, displays
[0]->crtc()->crtc_id
,
160 displays
[0]->connector()->connector_id
, gfx::Point(),
161 displays
[0]->connector()->modes
[0])) {
163 drm
->SetProperty(displays
[0]->connector()->connector_id
, dpms
->prop_id
,
168 base::FilePath
GetPrimaryDisplayCardPath() {
169 struct drm_mode_card_res res
;
170 for (int i
= 0; /* end on first card# that does not exist */; i
++) {
171 std::string card_path
= base::StringPrintf(kDefaultGraphicsCardPattern
, i
);
173 if (access(card_path
.c_str(), F_OK
) != 0)
176 int fd
= open(card_path
.c_str(), O_RDWR
| O_CLOEXEC
);
180 memset(&res
, 0, sizeof(struct drm_mode_card_res
));
181 int ret
= drmIoctl(fd
, DRM_IOCTL_MODE_GETRESOURCES
, &res
);
183 if (ret
== 0 && res
.count_crtcs
> 0) {
184 return base::FilePath(card_path
);
188 return base::FilePath();