summaryrefslogtreecommitdiffstats
path: root/chromium/ui/ozone/platform/dri/dri_util.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/ui/ozone/platform/dri/dri_util.cc')
-rw-r--r--chromium/ui/ozone/platform/dri/dri_util.cc125
1 files changed, 125 insertions, 0 deletions
diff --git a/chromium/ui/ozone/platform/dri/dri_util.cc b/chromium/ui/ozone/platform/dri/dri_util.cc
new file mode 100644
index 00000000000..b3eab02b41a
--- /dev/null
+++ b/chromium/ui/ozone/platform/dri/dri_util.cc
@@ -0,0 +1,125 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/ozone/platform/dri/dri_util.h"
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <xf86drmMode.h>
+
+namespace ui {
+
+namespace {
+
+bool IsCrtcInUse(uint32_t crtc,
+ const ScopedVector<HardwareDisplayControllerInfo>& displays) {
+ for (size_t i = 0; i < displays.size(); ++i) {
+ if (crtc == displays[i]->crtc()->crtc_id)
+ return true;
+ }
+
+ return false;
+}
+
+uint32_t GetCrtc(int fd,
+ drmModeConnector* connector,
+ drmModeRes* resources,
+ const ScopedVector<HardwareDisplayControllerInfo>& displays) {
+ // If the connector already has an encoder try to re-use.
+ if (connector->encoder_id) {
+ drmModeEncoder* encoder = drmModeGetEncoder(fd, connector->encoder_id);
+ if (encoder) {
+ if (encoder->crtc_id && !IsCrtcInUse(encoder->crtc_id, displays)) {
+ uint32_t crtc = encoder->crtc_id;
+ drmModeFreeEncoder(encoder);
+ return crtc;
+ }
+ drmModeFreeEncoder(encoder);
+ }
+ }
+
+ // Try to find an encoder for the connector.
+ for (int i = 0; i < connector->count_encoders; ++i) {
+ drmModeEncoder* encoder = drmModeGetEncoder(fd, connector->encoders[i]);
+ if (!encoder)
+ continue;
+
+ for (int j = 0; j < resources->count_crtcs; ++j) {
+ // Check if the encoder is compatible with this CRTC
+ if (!(encoder->possible_crtcs & (1 << j)) ||
+ IsCrtcInUse(resources->crtcs[j], displays)) {
+ continue;
+ }
+
+ drmModeFreeEncoder(encoder);
+ return resources->crtcs[j];
+ }
+
+ drmModeFreeEncoder(encoder);
+ }
+
+ return 0;
+}
+
+} // namespace
+
+HardwareDisplayControllerInfo::HardwareDisplayControllerInfo(
+ drmModeConnector* connector,
+ drmModeCrtc* crtc)
+ : connector_(connector),
+ crtc_(crtc) {}
+
+HardwareDisplayControllerInfo::~HardwareDisplayControllerInfo() {
+ drmModeFreeConnector(connector_);
+ drmModeFreeCrtc(crtc_);
+}
+
+ScopedVector<HardwareDisplayControllerInfo>
+GetAvailableDisplayControllerInfos(int fd, drmModeRes* resources) {
+ ScopedVector<HardwareDisplayControllerInfo> displays;
+
+ for (int i = 0; i < resources->count_connectors; ++i) {
+ drmModeConnector* connector = drmModeGetConnector(
+ fd, resources->connectors[i]);
+
+ if (!connector)
+ continue;
+
+ if (connector->connection != DRM_MODE_CONNECTED ||
+ connector->count_modes == 0) {
+ drmModeFreeConnector(connector);
+ continue;
+ }
+
+ uint32_t crtc_id = GetCrtc(fd, connector, resources, displays);
+ if (!crtc_id) {
+ drmModeFreeConnector(connector);
+ continue;
+ }
+
+ drmModeCrtc* crtc = drmModeGetCrtc(fd, crtc_id);
+ displays.push_back(new HardwareDisplayControllerInfo(connector, crtc));
+ }
+
+ return displays.Pass();
+}
+
+bool SameMode(const drmModeModeInfo& lhs, const drmModeModeInfo& rhs) {
+ return lhs.clock == rhs.clock &&
+ lhs.hdisplay == rhs.hdisplay &&
+ lhs.vdisplay == rhs.vdisplay &&
+ lhs.vrefresh == rhs.vrefresh &&
+ lhs.hsync_start == rhs.hsync_start &&
+ lhs.hsync_end == rhs.hsync_end &&
+ lhs.htotal == rhs.htotal &&
+ lhs.hskew == rhs.hskew &&
+ lhs.vsync_start == rhs.vsync_start &&
+ lhs.vsync_end == rhs.vsync_end &&
+ lhs.vtotal == rhs.vtotal &&
+ lhs.vscan == rhs.vscan &&
+ lhs.flags == rhs.flags &&
+ strcmp(lhs.name, rhs.name) == 0;
+}
+
+} // namespace ui