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.
5 #include "ui/ozone/platform/drm/gpu/drm_gpu_display_manager.h"
7 #include "ui/display/types/gamma_ramp_rgb_entry.h"
8 #include "ui/ozone/common/display_util.h"
9 #include "ui/ozone/platform/drm/common/drm_util.h"
10 #include "ui/ozone/platform/drm/gpu/drm_device.h"
11 #include "ui/ozone/platform/drm/gpu/drm_device_manager.h"
12 #include "ui/ozone/platform/drm/gpu/drm_display.h"
13 #include "ui/ozone/platform/drm/gpu/screen_manager.h"
19 class DisplayComparator
{
21 explicit DisplayComparator(const DrmDisplay
* display
)
22 : drm_(display
->drm()),
23 crtc_(display
->crtc()),
24 connector_(display
->connector()) {}
26 DisplayComparator(const scoped_refptr
<DrmDevice
>& drm
,
29 : drm_(drm
), crtc_(crtc
), connector_(connector
) {}
31 bool operator()(const DrmDisplay
* other
) const {
32 return drm_
== other
->drm() && connector_
== other
->connector() &&
33 crtc_
== other
->crtc();
37 scoped_refptr
<DrmDevice
> drm_
;
42 bool FindMatchingMode(const std::vector
<drmModeModeInfo
> modes
,
43 const DisplayMode_Params
& mode_params
,
44 drmModeModeInfo
* mode
) {
45 for (const drmModeModeInfo
& m
: modes
) {
46 DisplayMode_Params params
= CreateDisplayModeParams(m
);
47 if (mode_params
.size
== params
.size
&&
48 mode_params
.refresh_rate
== params
.refresh_rate
&&
49 mode_params
.is_interlaced
== params
.is_interlaced
) {
60 DrmGpuDisplayManager::DrmGpuDisplayManager(ScreenManager
* screen_manager
,
61 DrmDeviceManager
* drm_device_manager
)
62 : screen_manager_(screen_manager
), drm_device_manager_(drm_device_manager
) {
65 DrmGpuDisplayManager::~DrmGpuDisplayManager() {
68 std::vector
<DisplaySnapshot_Params
> DrmGpuDisplayManager::GetDisplays() {
69 ScopedVector
<DrmDisplay
> old_displays(displays_
.Pass());
70 std::vector
<DisplaySnapshot_Params
> params_list
;
72 const DrmDeviceVector
& devices
= drm_device_manager_
->GetDrmDevices();
73 // Unique identifier used to create the display id.
75 for (const auto& drm
: devices
) {
76 ScopedVector
<HardwareDisplayControllerInfo
> display_infos
=
77 GetAvailableDisplayControllerInfos(drm
->get_fd());
78 for (auto* display_info
: display_infos
) {
79 auto it
= std::find_if(
80 old_displays
.begin(), old_displays
.end(),
81 DisplayComparator(drm
, display_info
->crtc()->crtc_id
,
82 display_info
->connector()->connector_id
));
83 if (it
!= old_displays
.end()) {
84 displays_
.push_back(*it
);
85 old_displays
.weak_erase(it
);
87 displays_
.push_back(new DrmDisplay(screen_manager_
, drm
));
90 params_list
.push_back(displays_
.back()->Update(display_info
, index
++));
94 NotifyScreenManager(displays_
.get(), old_displays
.get());
98 bool DrmGpuDisplayManager::TakeDisplayControl() {
99 const DrmDeviceVector
& devices
= drm_device_manager_
->GetDrmDevices();
101 for (const auto& drm
: devices
)
102 status
&= drm
->SetMaster();
104 // Roll-back any successful operation.
106 LOG(ERROR
) << "Failed to take control of the display";
107 RelinquishDisplayControl();
113 void DrmGpuDisplayManager::RelinquishDisplayControl() {
114 const DrmDeviceVector
& devices
= drm_device_manager_
->GetDrmDevices();
115 for (const auto& drm
: devices
)
119 bool DrmGpuDisplayManager::ConfigureDisplay(
121 const DisplayMode_Params
& mode_param
,
122 const gfx::Point
& origin
) {
123 DrmDisplay
* display
= FindDisplay(display_id
);
125 LOG(ERROR
) << "There is no display with ID " << display_id
;
129 drmModeModeInfo mode
;
130 bool mode_found
= FindMatchingMode(display
->modes(), mode_param
, &mode
);
132 // If the display doesn't have the mode natively, then lookup the mode from
133 // other displays and try using it on the current display (some displays
134 // support panel fitting and they can use different modes even if the mode
135 // isn't explicitly declared).
136 for (DrmDisplay
* other
: displays_
) {
137 mode_found
= FindMatchingMode(other
->modes(), mode_param
, &mode
);
144 LOG(ERROR
) << "Failed to find mode: size=" << mode_param
.size
.ToString()
145 << " is_interlaced=" << mode_param
.is_interlaced
146 << " refresh_rate=" << mode_param
.refresh_rate
;
150 return display
->Configure(&mode
, origin
);
153 bool DrmGpuDisplayManager::DisableDisplay(int64_t display_id
) {
154 DrmDisplay
* display
= FindDisplay(display_id
);
156 LOG(ERROR
) << "There is no display with ID " << display_id
;
160 return display
->Configure(nullptr, gfx::Point());
163 bool DrmGpuDisplayManager::GetHDCPState(int64_t display_id
, HDCPState
* state
) {
164 DrmDisplay
* display
= FindDisplay(display_id
);
166 LOG(ERROR
) << "There is no display with ID " << display_id
;
170 return display
->GetHDCPState(state
);
173 bool DrmGpuDisplayManager::SetHDCPState(int64_t display_id
, HDCPState state
) {
174 DrmDisplay
* display
= FindDisplay(display_id
);
176 LOG(ERROR
) << "There is no display with ID " << display_id
;
180 return display
->SetHDCPState(state
);
183 void DrmGpuDisplayManager::SetGammaRamp(
185 const std::vector
<GammaRampRGBEntry
>& lut
) {
186 DrmDisplay
* display
= FindDisplay(display_id
);
188 LOG(ERROR
) << "There is no display with ID " << display_id
;
192 display
->SetGammaRamp(lut
);
195 DrmDisplay
* DrmGpuDisplayManager::FindDisplay(int64_t display_id
) {
196 for (DrmDisplay
* display
: displays_
)
197 if (display
->display_id() == display_id
)
203 void DrmGpuDisplayManager::NotifyScreenManager(
204 const std::vector
<DrmDisplay
*>& new_displays
,
205 const std::vector
<DrmDisplay
*>& old_displays
) const {
206 for (size_t i
= 0; i
< old_displays
.size(); ++i
) {
207 const std::vector
<DrmDisplay
*>::const_iterator it
=
208 std::find_if(new_displays
.begin(), new_displays
.end(),
209 DisplayComparator(old_displays
[i
]));
211 if (it
== new_displays
.end()) {
212 screen_manager_
->RemoveDisplayController(old_displays
[i
]->drm(),
213 old_displays
[i
]->crtc());
217 for (size_t i
= 0; i
< new_displays
.size(); ++i
) {
218 const std::vector
<DrmDisplay
*>::const_iterator it
=
219 std::find_if(old_displays
.begin(), old_displays
.end(),
220 DisplayComparator(new_displays
[i
]));
222 if (it
== old_displays
.end()) {
223 screen_manager_
->AddDisplayController(new_displays
[i
]->drm(),
224 new_displays
[i
]->crtc(),
225 new_displays
[i
]->connector());