ozone: evdev: Sync caps lock LED state to evdev
[chromium-blink-merge.git] / ui / ozone / platform / dri / dri_util.cc
blob338c4111a0e8227600b68f0dbdf20ffe343476aa
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"
7 #include <errno.h>
8 #include <fcntl.h>
9 #include <stdint.h>
10 #include <stdlib.h>
11 #include <sys/mman.h>
12 #include <xf86drm.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"
19 namespace ui {
21 namespace {
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)
29 return true;
32 return false;
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]));
49 if (!encoder)
50 continue;
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))
56 continue;
58 return resources->crtcs[j];
62 return 0;
65 } // namespace
67 HardwareDisplayControllerInfo::HardwareDisplayControllerInfo(
68 ScopedDrmConnectorPtr connector,
69 ScopedDrmCrtcPtr crtc)
70 : connector_(connector.Pass()),
71 crtc_(crtc.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)
87 continue;
89 uint32_t crtc_id = GetCrtc(fd, connector.get(), resources.get(), displays);
90 if (!crtc_id)
91 continue;
93 ScopedDrmCrtcPtr crtc(drmModeGetCrtc(fd, crtc_id));
94 displays.push_back(new HardwareDisplayControllerInfo(connector.Pass(),
95 crtc.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,
119 uint32_t handle,
120 uint32_t size,
121 void** pixels) {
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 << ") "
127 << strerror(errno);
128 return false;
131 *pixels = mmap(0,
132 size,
133 PROT_READ | PROT_WRITE,
134 MAP_SHARED,
136 map_request.offset);
137 if (*pixels == MAP_FAILED) {
138 VLOG(2) << "Cannot mmap dumb buffer (" << errno << ") " << strerror(errno);
139 return false;
142 return true;
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())
152 return;
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])) {
162 if (dpms)
163 drm->SetProperty(displays[0]->connector()->connector_id, dpms->prop_id,
164 DRM_MODE_DPMS_ON);
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)
174 break;
176 int fd = open(card_path.c_str(), O_RDWR | O_CLOEXEC);
177 if (fd < 0)
178 continue;
180 memset(&res, 0, sizeof(struct drm_mode_card_res));
181 int ret = drmIoctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &res);
182 close(fd);
183 if (ret == 0 && res.count_crtcs > 0) {
184 return base::FilePath(card_path);
188 return base::FilePath();
191 } // namespace ui