Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(412)

Side by Side Diff: ui/ozone/platform/drm/common/drm_util.cc

Issue 1285183008: Ozone integration. (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: add missing license header Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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.
4
5 #include "ui/ozone/platform/drm/common/drm_util.h"
6
7 #include <stdint.h>
8 #include <stdlib.h>
9 #include <sys/mman.h>
10 #include <xf86drmMode.h>
11
12 #include "ui/display/types/display_constants.h"
13 #include "ui/display/util/edid_parser.h"
14
15 #if !defined(DRM_MODE_CONNECTOR_DSI)
16 #define DRM_MODE_CONNECTOR_DSI 16
17 #endif
18
19 namespace ui {
20
21 namespace {
22
23 bool IsCrtcInUse(uint32_t crtc,
24 const ScopedVector<HardwareDisplayControllerInfo>& displays) {
25 for (size_t i = 0; i < displays.size(); ++i) {
26 if (crtc == displays[i]->crtc()->crtc_id)
27 return true;
28 }
29
30 return false;
31 }
32
33 uint32_t GetCrtc(int fd,
34 drmModeConnector* connector,
35 drmModeRes* resources,
36 const ScopedVector<HardwareDisplayControllerInfo>& displays) {
37 // If the connector already has an encoder try to re-use.
38 if (connector->encoder_id) {
39 ScopedDrmEncoderPtr encoder(drmModeGetEncoder(fd, connector->encoder_id));
40 if (encoder && encoder->crtc_id && !IsCrtcInUse(encoder->crtc_id, displays))
41 return encoder->crtc_id;
42 }
43
44 // Try to find an encoder for the connector.
45 for (int i = 0; i < connector->count_encoders; ++i) {
46 ScopedDrmEncoderPtr encoder(drmModeGetEncoder(fd, connector->encoders[i]));
47 if (!encoder)
48 continue;
49
50 for (int j = 0; j < resources->count_crtcs; ++j) {
51 // Check if the encoder is compatible with this CRTC
52 if (!(encoder->possible_crtcs & (1 << j)) ||
53 IsCrtcInUse(resources->crtcs[j], displays))
54 continue;
55
56 return resources->crtcs[j];
57 }
58 }
59
60 return 0;
61 }
62
63 // Computes the refresh rate for the specific mode. If we have enough
64 // information use the mode timings to compute a more exact value otherwise
65 // fallback to using the mode's vertical refresh rate (the kernel computes this
66 // the same way, however there is a loss in precision since |vrefresh| is sent
67 // as an integer).
68 float GetRefreshRate(const drmModeModeInfo& mode) {
69 if (!mode.htotal || !mode.vtotal)
70 return mode.vrefresh;
71
72 float clock = mode.clock;
73 float htotal = mode.htotal;
74 float vtotal = mode.vtotal;
75
76 return (clock * 1000.0f) / (htotal * vtotal);
77 }
78
79 DisplayConnectionType GetDisplayType(drmModeConnector* connector) {
80 switch (connector->connector_type) {
81 case DRM_MODE_CONNECTOR_VGA:
82 return DISPLAY_CONNECTION_TYPE_VGA;
83 case DRM_MODE_CONNECTOR_DVII:
84 case DRM_MODE_CONNECTOR_DVID:
85 case DRM_MODE_CONNECTOR_DVIA:
86 return DISPLAY_CONNECTION_TYPE_DVI;
87 case DRM_MODE_CONNECTOR_LVDS:
88 case DRM_MODE_CONNECTOR_eDP:
89 case DRM_MODE_CONNECTOR_DSI:
90 return DISPLAY_CONNECTION_TYPE_INTERNAL;
91 case DRM_MODE_CONNECTOR_DisplayPort:
92 return DISPLAY_CONNECTION_TYPE_DISPLAYPORT;
93 case DRM_MODE_CONNECTOR_HDMIA:
94 case DRM_MODE_CONNECTOR_HDMIB:
95 return DISPLAY_CONNECTION_TYPE_HDMI;
96 default:
97 return DISPLAY_CONNECTION_TYPE_UNKNOWN;
98 }
99 }
100
101 int GetDrmProperty(int fd,
102 drmModeConnector* connector,
103 const std::string& name,
104 ScopedDrmPropertyPtr* property) {
105 for (int i = 0; i < connector->count_props; ++i) {
106 ScopedDrmPropertyPtr tmp(drmModeGetProperty(fd, connector->props[i]));
107 if (!tmp)
108 continue;
109
110 if (name == tmp->name) {
111 *property = tmp.Pass();
112 return i;
113 }
114 }
115
116 return -1;
117 }
118
119 std::string GetNameForEnumValue(drmModePropertyRes* property, uint32_t value) {
120 for (int i = 0; i < property->count_enums; ++i)
121 if (property->enums[i].value == value)
122 return property->enums[i].name;
123
124 return std::string();
125 }
126
127 ScopedDrmPropertyBlobPtr GetDrmPropertyBlob(int fd,
128 drmModeConnector* connector,
129 const std::string& name) {
130 ScopedDrmPropertyPtr property;
131 int index = GetDrmProperty(fd, connector, name, &property);
132 if (index < 0)
133 return nullptr;
134
135 if (property->flags & DRM_MODE_PROP_BLOB) {
136 return ScopedDrmPropertyBlobPtr(
137 drmModeGetPropertyBlob(fd, connector->prop_values[index]));
138 }
139
140 return nullptr;
141 }
142
143 bool IsAspectPreserving(int fd, drmModeConnector* connector) {
144 ScopedDrmPropertyPtr property;
145 int index = GetDrmProperty(fd, connector, "scaling mode", &property);
146 if (index < 0)
147 return false;
148
149 return (GetNameForEnumValue(property.get(), connector->prop_values[index]) ==
150 "Full aspect");
151 }
152
153 } // namespace
154
155 HardwareDisplayControllerInfo::HardwareDisplayControllerInfo(
156 ScopedDrmConnectorPtr connector,
157 ScopedDrmCrtcPtr crtc)
158 : connector_(connector.Pass()), crtc_(crtc.Pass()) {
159 }
160
161 HardwareDisplayControllerInfo::~HardwareDisplayControllerInfo() {
162 }
163
164 ScopedVector<HardwareDisplayControllerInfo> GetAvailableDisplayControllerInfos(
165 int fd) {
166 ScopedDrmResourcesPtr resources(drmModeGetResources(fd));
167 DCHECK(resources) << "Failed to get DRM resources";
168 ScopedVector<HardwareDisplayControllerInfo> displays;
169
170 for (int i = 0; i < resources->count_connectors; ++i) {
171 ScopedDrmConnectorPtr connector(
172 drmModeGetConnector(fd, resources->connectors[i]));
173
174 if (!connector || connector->connection != DRM_MODE_CONNECTED ||
175 connector->count_modes == 0)
176 continue;
177
178 uint32_t crtc_id = GetCrtc(fd, connector.get(), resources.get(), displays);
179 if (!crtc_id)
180 continue;
181
182 ScopedDrmCrtcPtr crtc(drmModeGetCrtc(fd, crtc_id));
183 displays.push_back(
184 new HardwareDisplayControllerInfo(connector.Pass(), crtc.Pass()));
185 }
186
187 return displays.Pass();
188 }
189
190 bool SameMode(const drmModeModeInfo& lhs, const drmModeModeInfo& rhs) {
191 return lhs.clock == rhs.clock && lhs.hdisplay == rhs.hdisplay &&
192 lhs.vdisplay == rhs.vdisplay && lhs.vrefresh == rhs.vrefresh &&
193 lhs.hsync_start == rhs.hsync_start && lhs.hsync_end == rhs.hsync_end &&
194 lhs.htotal == rhs.htotal && lhs.hskew == rhs.hskew &&
195 lhs.vsync_start == rhs.vsync_start && lhs.vsync_end == rhs.vsync_end &&
196 lhs.vtotal == rhs.vtotal && lhs.vscan == rhs.vscan &&
197 lhs.flags == rhs.flags && strcmp(lhs.name, rhs.name) == 0;
198 }
199
200 DisplayMode_Params CreateDisplayModeParams(const drmModeModeInfo& mode) {
201 DisplayMode_Params params;
202 params.size = gfx::Size(mode.hdisplay, mode.vdisplay);
203 params.is_interlaced = mode.flags & DRM_MODE_FLAG_INTERLACE;
204 params.refresh_rate = GetRefreshRate(mode);
205
206 return params;
207 }
208
209 DisplaySnapshot_Params CreateDisplaySnapshotParams(
210 HardwareDisplayControllerInfo* info,
211 int fd,
212 size_t display_index,
213 const gfx::Point& origin) {
214 DisplaySnapshot_Params params;
215 params.display_id = display_index;
216 params.origin = origin;
217 params.physical_size =
218 gfx::Size(info->connector()->mmWidth, info->connector()->mmHeight);
219 params.type = GetDisplayType(info->connector());
220 params.is_aspect_preserving_scaling =
221 IsAspectPreserving(fd, info->connector());
222
223 ScopedDrmPropertyBlobPtr edid_blob(
224 GetDrmPropertyBlob(fd, info->connector(), "EDID"));
225
226 if (edid_blob) {
227 std::vector<uint8_t> edid(
228 static_cast<uint8_t*>(edid_blob->data),
229 static_cast<uint8_t*>(edid_blob->data) + edid_blob->length);
230
231 if (!GetDisplayIdFromEDID(edid, display_index, &params.display_id,
232 &params.product_id))
233 params.display_id = display_index;
234
235 ParseOutputDeviceData(edid, nullptr, nullptr, &params.display_name, nullptr,
236 nullptr);
237 ParseOutputOverscanFlag(edid, &params.has_overscan);
238 } else {
239 VLOG(1) << "Failed to get EDID blob for connector "
240 << info->connector()->connector_id;
241 }
242
243 for (int i = 0; i < info->connector()->count_modes; ++i) {
244 const drmModeModeInfo& mode = info->connector()->modes[i];
245 params.modes.push_back(CreateDisplayModeParams(mode));
246
247 if (info->crtc()->mode_valid && SameMode(info->crtc()->mode, mode)) {
248 params.has_current_mode = true;
249 params.current_mode = params.modes.back();
250 }
251
252 if (mode.type & DRM_MODE_TYPE_PREFERRED) {
253 params.has_native_mode = true;
254 params.native_mode = params.modes.back();
255 }
256 }
257
258 // If no preferred mode is found then use the first one. Using the first one
259 // since it should be the best mode.
260 if (!params.has_native_mode && !params.modes.empty()) {
261 params.has_native_mode = true;
262 params.native_mode = params.modes.front();
263 }
264
265 return params;
266 }
267
268 } // namespace ui
OLDNEW
« no previous file with comments | « ui/ozone/platform/drm/common/drm_util.h ('k') | ui/ozone/platform/drm/common/inprocess_messages.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698