display_snapshot_dri.cc revision 0529e5d033099cbfc42635f6f6183833b09dff6e
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/chromeos/display_snapshot_dri.h"
6
7#include <stdint.h>
8#include <stdlib.h>
9#include <xf86drmMode.h>
10
11#include "base/format_macros.h"
12#include "base/logging.h"
13#include "base/strings/stringprintf.h"
14#include "ui/display/util/edid_parser.h"
15#include "ui/ozone/platform/dri/chromeos/display_mode_dri.h"
16#include "ui/ozone/platform/dri/dri_wrapper.h"
17
18namespace ui {
19
20namespace {
21
22DisplayConnectionType GetDisplayType(drmModeConnector* connector) {
23  switch (connector->connector_type) {
24    case DRM_MODE_CONNECTOR_VGA:
25      return DISPLAY_CONNECTION_TYPE_VGA;
26    case DRM_MODE_CONNECTOR_DVII:
27    case DRM_MODE_CONNECTOR_DVID:
28    case DRM_MODE_CONNECTOR_DVIA:
29      return DISPLAY_CONNECTION_TYPE_DVI;
30    case DRM_MODE_CONNECTOR_LVDS:
31    case DRM_MODE_CONNECTOR_eDP:
32      return DISPLAY_CONNECTION_TYPE_INTERNAL;
33    case DRM_MODE_CONNECTOR_DisplayPort:
34      return DISPLAY_CONNECTION_TYPE_DISPLAYPORT;
35    case DRM_MODE_CONNECTOR_HDMIA:
36    case DRM_MODE_CONNECTOR_HDMIB:
37      return DISPLAY_CONNECTION_TYPE_HDMI;
38    default:
39      return DISPLAY_CONNECTION_TYPE_UNKNOWN;
40  }
41}
42
43bool SameMode(const drmModeModeInfo& lhs, const drmModeModeInfo& rhs) {
44  return lhs.clock == rhs.clock &&
45         lhs.hdisplay == rhs.vdisplay &&
46         lhs.vrefresh == rhs.vrefresh &&
47         lhs.hsync_start == rhs.hsync_start &&
48         lhs.hsync_end == rhs.hsync_end &&
49         lhs.htotal == rhs.htotal &&
50         lhs.hskew == rhs.hskew &&
51         lhs.vsync_start == rhs.vsync_start &&
52         lhs.vsync_end == rhs.vsync_end &&
53         lhs.vtotal == rhs.vtotal &&
54         lhs.vscan == rhs.vscan &&
55         lhs.flags == rhs.flags &&
56         strcmp(lhs.name, rhs.name) == 0;
57}
58
59bool IsAspectPreserving(DriWrapper* drm, drmModeConnector* connector) {
60  drmModePropertyRes* property = drm->GetProperty(connector, "scaling mode");
61  if (property) {
62    for (int j = 0; j < property->count_enums; ++j) {
63      if (property->enums[j].value ==
64              connector->prop_values[property->prop_id] &&
65          strcmp(property->enums[j].name, "Full aspect") == 0) {
66        drm->FreeProperty(property);
67        return true;
68      }
69    }
70
71    drm->FreeProperty(property);
72  }
73
74  return false;
75}
76
77}  // namespace
78
79DisplaySnapshotDri::DisplaySnapshotDri(
80    DriWrapper* drm,
81    drmModeConnector* connector,
82    drmModeCrtc* crtc,
83    uint32_t index)
84    : DisplaySnapshot(index,
85                      false,
86                      gfx::Point(crtc->x, crtc->y),
87                      gfx::Size(connector->mmWidth, connector->mmHeight),
88                      GetDisplayType(connector),
89                      IsAspectPreserving(drm, connector),
90                      false,
91                      std::string(),
92                      std::vector<const DisplayMode*>(),
93                      NULL,
94                      NULL),
95      connector_(connector->connector_id),
96      crtc_(crtc->crtc_id),
97      dpms_property_(drm->GetProperty(connector, "DPMS")) {
98  drmModePropertyBlobRes* edid_blob = drm->GetPropertyBlob(connector, "EDID");
99
100  if (edid_blob) {
101    std::vector<uint8_t> edid(
102        static_cast<uint8_t*>(edid_blob->data),
103        static_cast<uint8_t*>(edid_blob->data) + edid_blob->length);
104
105    has_proper_display_id_ = GetDisplayIdFromEDID(edid, index, &display_id_);
106    ParseOutputDeviceData(edid, NULL, &display_name_);
107    ParseOutputOverscanFlag(edid, &overscan_flag_);
108
109    drm->FreePropertyBlob(edid_blob);
110  } else {
111    VLOG(1) << "Failed to get EDID blob for connector "
112            << connector->connector_id;
113  }
114
115  for (int i = 0; i < connector->count_modes; ++i) {
116    drmModeModeInfo& mode = connector->modes[i];
117    modes_.push_back(new DisplayModeDri(mode));
118
119    if (crtc->mode_valid && SameMode(crtc->mode, mode))
120      current_mode_ = modes_.back();
121
122    if (mode.type & DRM_MODE_TYPE_PREFERRED)
123      native_mode_ = modes_.back();
124  }
125}
126
127DisplaySnapshotDri::~DisplaySnapshotDri() {
128  if (dpms_property_)
129    drmModeFreeProperty(dpms_property_);
130}
131
132std::string DisplaySnapshotDri::ToString() const {
133  return base::StringPrintf(
134      "[type=%d, connector=%" PRIu32 ", crtc=%" PRIu32 ", mode=%s, dim=%s]",
135      type_,
136      connector_,
137      crtc_,
138      current_mode_ ? current_mode_->ToString().c_str() : "NULL",
139      physical_size_.ToString().c_str());
140}
141
142}  // namespace ui
143