dri_util.cc revision 010d83a9304c5a91596085d917d248abff47903a
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/dri/dri_util.h"
6
7#include <stdint.h>
8#include <stdlib.h>
9#include <xf86drmMode.h>
10
11namespace ui {
12
13namespace {
14
15bool IsCrtcInUse(uint32_t crtc,
16                 const ScopedVector<HardwareDisplayControllerInfo>& displays) {
17  for (size_t i = 0; i < displays.size(); ++i) {
18    if (crtc == displays[i]->crtc()->crtc_id)
19      return true;
20  }
21
22  return false;
23}
24
25uint32_t GetCrtc(int fd,
26                 drmModeConnector* connector,
27                 drmModeRes* resources,
28                 const ScopedVector<HardwareDisplayControllerInfo>& displays) {
29  // If the connector already has an encoder try to re-use.
30  if (connector->encoder_id) {
31    drmModeEncoder* encoder = drmModeGetEncoder(fd, connector->encoder_id);
32    if (encoder) {
33      if (encoder->crtc_id && !IsCrtcInUse(encoder->crtc_id, displays)) {
34        uint32_t crtc = encoder->crtc_id;
35        drmModeFreeEncoder(encoder);
36        return crtc;
37      }
38      drmModeFreeEncoder(encoder);
39    }
40  }
41
42  // Try to find an encoder for the connector.
43  for (int i = 0; i < connector->count_encoders; ++i) {
44    drmModeEncoder* encoder = drmModeGetEncoder(fd, connector->encoders[i]);
45    if (!encoder)
46      continue;
47
48    for (int j = 0; j < resources->count_crtcs; ++j) {
49      // Check if the encoder is compatible with this CRTC
50      if (!(encoder->possible_crtcs & (1 << j)) ||
51          IsCrtcInUse(resources->crtcs[j], displays)) {
52        continue;
53      }
54
55      drmModeFreeEncoder(encoder);
56      return resources->crtcs[j];
57    }
58
59    drmModeFreeEncoder(encoder);
60  }
61
62  return 0;
63}
64
65}  // namespace
66
67HardwareDisplayControllerInfo::HardwareDisplayControllerInfo(
68    drmModeConnector* connector,
69    drmModeCrtc* crtc)
70    : connector_(connector),
71      crtc_(crtc) {}
72
73HardwareDisplayControllerInfo::~HardwareDisplayControllerInfo() {
74  drmModeFreeConnector(connector_);
75  drmModeFreeCrtc(crtc_);
76}
77
78ScopedVector<HardwareDisplayControllerInfo>
79GetAvailableDisplayControllerInfos(int fd, drmModeRes* resources) {
80  ScopedVector<HardwareDisplayControllerInfo> displays;
81
82  for (int i = 0; i < resources->count_connectors; ++i) {
83    drmModeConnector* connector = drmModeGetConnector(
84        fd, resources->connectors[i]);
85
86    if (!connector)
87      continue;
88
89    if (connector->connection != DRM_MODE_CONNECTED ||
90        connector->count_modes == 0) {
91      drmModeFreeConnector(connector);
92      continue;
93    }
94
95    uint32_t crtc_id = GetCrtc(fd, connector, resources, displays);
96    if (!crtc_id) {
97      drmModeFreeConnector(connector);
98      continue;
99    }
100
101    drmModeCrtc* crtc = drmModeGetCrtc(fd, crtc_id);
102    displays.push_back(new HardwareDisplayControllerInfo(connector, crtc));
103  }
104
105  return displays.Pass();
106}
107
108bool SameMode(const drmModeModeInfo& lhs, const drmModeModeInfo& rhs) {
109  return lhs.clock == rhs.clock &&
110         lhs.hdisplay == rhs.hdisplay &&
111         lhs.vdisplay == rhs.vdisplay &&
112         lhs.vrefresh == rhs.vrefresh &&
113         lhs.hsync_start == rhs.hsync_start &&
114         lhs.hsync_end == rhs.hsync_end &&
115         lhs.htotal == rhs.htotal &&
116         lhs.hskew == rhs.hskew &&
117         lhs.vsync_start == rhs.vsync_start &&
118         lhs.vsync_end == rhs.vsync_end &&
119         lhs.vtotal == rhs.vtotal &&
120         lhs.vscan == rhs.vscan &&
121         lhs.flags == rhs.flags &&
122         strcmp(lhs.name, rhs.name) == 0;
123}
124
125}  // namespace ui
126