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

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

Issue 2420083003: ozone: Pick CRTCs with majority of planes. (Closed)
Patch Set: Prefer already set crtc. Created 3 years, 11 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
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ui/ozone/platform/drm/common/drm_util.h" 5 #include "ui/ozone/platform/drm/common/drm_util.h"
6 6
7 #include <drm_fourcc.h> 7 #include <drm_fourcc.h>
8 #include <stdint.h> 8 #include <stdint.h>
9 #include <stdlib.h> 9 #include <stdlib.h>
10 #include <sys/mman.h> 10 #include <sys/mman.h>
11 #include <xf86drm.h> 11 #include <xf86drm.h>
12 #include <xf86drmMode.h> 12 #include <xf86drmMode.h>
13 #include <algorithm>
13 #include <utility> 14 #include <utility>
14 15
16 #include "base/containers/small_map.h"
15 #include "ui/display/util/edid_parser.h" 17 #include "ui/display/util/edid_parser.h"
16 18
17 #if !defined(DRM_FORMAT_YV12) 19 #if !defined(DRM_FORMAT_YV12)
18 // TODO(dcastagna): after libdrm has this definition, remove it. 20 // TODO(dcastagna): after libdrm has this definition, remove it.
19 #define DRM_FORMAT_YV12 fourcc_code('Y', 'V', '1', '2') 21 #define DRM_FORMAT_YV12 fourcc_code('Y', 'V', '1', '2')
20 #endif 22 #endif
21 23
22 namespace ui { 24 namespace ui {
23 25
24 namespace { 26 namespace {
25 27
26 static const size_t kDefaultCursorWidth = 64; 28 static const size_t kDefaultCursorWidth = 64;
27 static const size_t kDefaultCursorHeight = 64; 29 static const size_t kDefaultCursorHeight = 64;
28 30
29 bool IsCrtcInUse(uint32_t crtc, 31 bool IsCrtcInUse(uint32_t crtc,
30 const ScopedVector<HardwareDisplayControllerInfo>& displays) { 32 const ScopedVector<HardwareDisplayControllerInfo>& displays) {
31 for (size_t i = 0; i < displays.size(); ++i) { 33 for (size_t i = 0; i < displays.size(); ++i) {
32 if (crtc == displays[i]->crtc()->crtc_id) 34 if (crtc == displays[i]->crtc()->crtc_id)
33 return true; 35 return true;
34 } 36 }
35 37
36 return false; 38 return false;
37 } 39 }
38 40
41 // Return a CRTC compatible with |connector| and not already used in |displays|.
42 // If there are multiple compatible CRTCs, the one that supports the majority of
43 // planes will be returned.
39 uint32_t GetCrtc(int fd, 44 uint32_t GetCrtc(int fd,
40 drmModeConnector* connector, 45 drmModeConnector* connector,
41 drmModeRes* resources, 46 drmModeRes* resources,
42 const ScopedVector<HardwareDisplayControllerInfo>& displays) { 47 const ScopedVector<HardwareDisplayControllerInfo>& displays) {
43 // If the connector already has an encoder try to re-use. 48 ScopedDrmPlaneResPtr plane_resources(drmModeGetPlaneResources(fd));
44 if (connector->encoder_id) { 49 std::vector<ScopedDrmPlanePtr> planes;
45 ScopedDrmEncoderPtr encoder(drmModeGetEncoder(fd, connector->encoder_id)); 50 for (uint32_t i = 0; i < plane_resources->count_planes; i++)
46 if (encoder && encoder->crtc_id && !IsCrtcInUse(encoder->crtc_id, displays)) 51 planes.emplace_back(drmModeGetPlane(fd, plane_resources->planes[i]));
47 return encoder->crtc_id; 52
48 } 53 DCHECK_GE(32, resources->count_crtcs);
54 uint32_t best_crtc = 0;
55 int best_crtc_planes = 0;
49 56
50 // Try to find an encoder for the connector. 57 // Try to find an encoder for the connector.
51 for (int i = 0; i < connector->count_encoders; ++i) { 58 for (int i = 0; i < connector->count_encoders; ++i) {
52 ScopedDrmEncoderPtr encoder(drmModeGetEncoder(fd, connector->encoders[i])); 59 ScopedDrmEncoderPtr encoder(drmModeGetEncoder(fd, connector->encoders[i]));
53 if (!encoder) 60 if (!encoder)
54 continue; 61 continue;
55 62
56 for (int j = 0; j < resources->count_crtcs; ++j) { 63 for (int j = 0; j < resources->count_crtcs; ++j) {
57 // Check if the encoder is compatible with this CRTC 64 // Check if the encoder is compatible with this CRTC
58 if (!(encoder->possible_crtcs & (1 << j)) || 65 int crtc_bit = 1 << j;
66 if (!(encoder->possible_crtcs & crtc_bit) ||
59 IsCrtcInUse(resources->crtcs[j], displays)) 67 IsCrtcInUse(resources->crtcs[j], displays))
60 continue; 68 continue;
61 69
62 return resources->crtcs[j]; 70 int supported_planes = std::count_if(
71 planes.begin(), planes.end(), [crtc_bit](const ScopedDrmPlanePtr& p) {
72 return p->possible_crtcs & crtc_bit;
73 });
74
75 uint32_t assigned_crtc = 0;
Daniele Castagna 2017/01/10 01:11:45 Added logic to prefer an already set crtc in case
76 if (connector->encoder_id == encoder->encoder_id)
77 assigned_crtc = encoder->crtc_id;
78 if (supported_planes > best_crtc_planes ||
79 (supported_planes == best_crtc_planes &&
80 assigned_crtc == resources->crtcs[j])) {
81 best_crtc_planes = supported_planes;
82 best_crtc = resources->crtcs[j];
83 }
63 } 84 }
64 } 85 }
65 86
66 return 0; 87 return best_crtc;
67 } 88 }
68 89
69 // Computes the refresh rate for the specific mode. If we have enough 90 // Computes the refresh rate for the specific mode. If we have enough
70 // information use the mode timings to compute a more exact value otherwise 91 // information use the mode timings to compute a more exact value otherwise
71 // fallback to using the mode's vertical refresh rate (the kernel computes this 92 // fallback to using the mode's vertical refresh rate (the kernel computes this
72 // the same way, however there is a loss in precision since |vrefresh| is sent 93 // the same way, however there is a loss in precision since |vrefresh| is sent
73 // as an integer). 94 // as an integer).
74 float GetRefreshRate(const drmModeModeInfo& mode) { 95 float GetRefreshRate(const drmModeModeInfo& mode) {
75 if (!mode.htotal || !mode.vtotal) 96 if (!mode.htotal || !mode.vtotal)
76 return mode.vrefresh; 97 return mode.vrefresh;
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
199 220
200 HardwareDisplayControllerInfo::~HardwareDisplayControllerInfo() { 221 HardwareDisplayControllerInfo::~HardwareDisplayControllerInfo() {
201 } 222 }
202 223
203 ScopedVector<HardwareDisplayControllerInfo> GetAvailableDisplayControllerInfos( 224 ScopedVector<HardwareDisplayControllerInfo> GetAvailableDisplayControllerInfos(
204 int fd) { 225 int fd) {
205 ScopedDrmResourcesPtr resources(drmModeGetResources(fd)); 226 ScopedDrmResourcesPtr resources(drmModeGetResources(fd));
206 DCHECK(resources) << "Failed to get DRM resources"; 227 DCHECK(resources) << "Failed to get DRM resources";
207 ScopedVector<HardwareDisplayControllerInfo> displays; 228 ScopedVector<HardwareDisplayControllerInfo> displays;
208 229
230 std::vector<ScopedDrmConnectorPtr> available_connectors;
231 std::vector<ScopedDrmConnectorPtr::element_type*> connectors;
209 for (int i = 0; i < resources->count_connectors; ++i) { 232 for (int i = 0; i < resources->count_connectors; ++i) {
210 ScopedDrmConnectorPtr connector( 233 ScopedDrmConnectorPtr connector(
211 drmModeGetConnector(fd, resources->connectors[i])); 234 drmModeGetConnector(fd, resources->connectors[i]));
235 connectors.push_back(connector.get());
212 236
213 if (!connector || connector->connection != DRM_MODE_CONNECTED || 237 if (connector && connector->connection == DRM_MODE_CONNECTED &&
214 connector->count_modes == 0) 238 connector->count_modes != 0)
215 continue; 239 available_connectors.push_back(std::move(connector));
240 }
216 241
217 uint32_t crtc_id = GetCrtc(fd, connector.get(), resources.get(), displays); 242 base::SmallMap<std::map<ScopedDrmConnectorPtr::element_type*, int>>
243 connector_crtcs;
244 for (auto& c : available_connectors) {
245 uint32_t possible_crtcs = 0;
246 for (int i = 0; i < c->count_encoders; ++i) {
247 ScopedDrmEncoderPtr encoder(drmModeGetEncoder(fd, c->encoders[i]));
248 if (!encoder)
249 continue;
250 possible_crtcs |= encoder->possible_crtcs;
251 }
252 connector_crtcs[c.get()] = possible_crtcs;
253 }
254 // Make sure to start assigning a crtc to the connector that supports the
255 // fewest crtcs first.
256 std::stable_sort(available_connectors.begin(), available_connectors.end(),
257 [&connector_crtcs](const ScopedDrmConnectorPtr& c1,
258 const ScopedDrmConnectorPtr& c2) {
259 // When c1 supports a proper subset of the crtcs of c2, we
260 // should process c1 first (return true).
261 int c1_crtcs = connector_crtcs[c1.get()];
262 int c2_crtcs = connector_crtcs[c2.get()];
263 return (c1_crtcs & c2_crtcs) == c1_crtcs &&
264 c1_crtcs != c2_crtcs;
265 });
266
267 for (auto& c : available_connectors) {
268 uint32_t crtc_id = GetCrtc(fd, c.get(), resources.get(), displays);
218 if (!crtc_id) 269 if (!crtc_id)
219 continue; 270 continue;
220 271
221 ScopedDrmCrtcPtr crtc(drmModeGetCrtc(fd, crtc_id)); 272 ScopedDrmCrtcPtr crtc(drmModeGetCrtc(fd, crtc_id));
222 displays.push_back(new HardwareDisplayControllerInfo(std::move(connector), 273 size_t index = std::find(connectors.begin(), connectors.end(), c.get()) -
223 std::move(crtc), i)); 274 connectors.begin();
275 DCHECK_LT(index, connectors.size());
276 displays.push_back(new HardwareDisplayControllerInfo(
277 std::move(c), std::move(crtc), index));
224 } 278 }
225 279
226 return displays; 280 return displays;
227 } 281 }
228 282
229 bool SameMode(const drmModeModeInfo& lhs, const drmModeModeInfo& rhs) { 283 bool SameMode(const drmModeModeInfo& lhs, const drmModeModeInfo& rhs) {
230 return lhs.clock == rhs.clock && lhs.hdisplay == rhs.hdisplay && 284 return lhs.clock == rhs.clock && lhs.hdisplay == rhs.hdisplay &&
231 lhs.vdisplay == rhs.vdisplay && lhs.vrefresh == rhs.vrefresh && 285 lhs.vdisplay == rhs.vdisplay && lhs.vrefresh == rhs.vrefresh &&
232 lhs.hsync_start == rhs.hsync_start && lhs.hsync_end == rhs.hsync_end && 286 lhs.hsync_start == rhs.hsync_start && lhs.hsync_end == rhs.hsync_end &&
233 lhs.htotal == rhs.htotal && lhs.hskew == rhs.hskew && 287 lhs.htotal == rhs.htotal && lhs.hskew == rhs.hskew &&
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
377 case gfx::BufferFormat::BGR_565: 431 case gfx::BufferFormat::BGR_565:
378 return DRM_FORMAT_RGB565; 432 return DRM_FORMAT_RGB565;
379 case gfx::BufferFormat::UYVY_422: 433 case gfx::BufferFormat::UYVY_422:
380 return DRM_FORMAT_UYVY; 434 return DRM_FORMAT_UYVY;
381 default: 435 default:
382 NOTREACHED(); 436 NOTREACHED();
383 return 0; 437 return 0;
384 } 438 }
385 } 439 }
386 } // namespace ui 440 } // namespace ui
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698