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/dri/native_display_delegate_dri.h"
8 #include "ui/display/types/native_display_observer.h"
9 #include "ui/events/ozone/device/device_event.h"
10 #include "ui/ozone/platform/dri/display_mode_dri.h"
11 #include "ui/ozone/platform/dri/display_snapshot_dri.h"
12 #include "ui/ozone/platform/dri/dri_util.h"
13 #include "ui/ozone/platform/dri/dri_wrapper.h"
14 #include "ui/ozone/platform/dri/screen_manager.h"
20 const char kContentProtection
[] = "Content Protection";
22 struct ContentProtectionMapping
{
27 const ContentProtectionMapping kContentProtectionStates
[] = {
28 {"Undesired", HDCP_STATE_UNDESIRED
},
29 {"Desired", HDCP_STATE_DESIRED
},
30 {"Enabled", HDCP_STATE_ENABLED
}};
32 uint32_t GetContentProtectionValue(drmModePropertyRes
* property
,
35 for (size_t i
= 0; i
< arraysize(kContentProtectionStates
); ++i
) {
36 if (kContentProtectionStates
[i
].state
== state
) {
37 name
= kContentProtectionStates
[i
].name
;
42 for (int i
= 0; i
< property
->count_enums
; ++i
)
43 if (name
== property
->enums
[i
].name
)
50 class DisplaySnapshotComparator
{
52 explicit DisplaySnapshotComparator(const DisplaySnapshotDri
* snapshot
)
53 : crtc_(snapshot
->crtc()), connector_(snapshot
->connector()) {}
55 DisplaySnapshotComparator(uint32_t crtc
, uint32_t connector
)
56 : crtc_(crtc
), connector_(connector
) {}
58 bool operator()(const DisplaySnapshotDri
* other
) const {
59 return connector_
== other
->connector() && crtc_
== other
->crtc();
69 NativeDisplayDelegateDri::NativeDisplayDelegateDri(
71 ScreenManager
* screen_manager
)
72 : dri_(dri
), screen_manager_(screen_manager
) {
73 // TODO(dnicoara): Remove when async display configuration is supported.
74 screen_manager_
->ForceInitializationOfPrimaryDisplay();
77 NativeDisplayDelegateDri::~NativeDisplayDelegateDri() {
80 DisplaySnapshot
* NativeDisplayDelegateDri::FindDisplaySnapshot(int64_t id
) {
81 for (size_t i
= 0; i
< cached_displays_
.size(); ++i
)
82 if (cached_displays_
[i
]->display_id() == id
)
83 return cached_displays_
[i
];
88 const DisplayMode
* NativeDisplayDelegateDri::FindDisplayMode(
89 const gfx::Size
& size
,
92 for (size_t i
= 0; i
< cached_modes_
.size(); ++i
)
93 if (cached_modes_
[i
]->size() == size
&&
94 cached_modes_
[i
]->is_interlaced() == is_interlaced
&&
95 cached_modes_
[i
]->refresh_rate() == refresh_rate
)
96 return cached_modes_
[i
];
101 void NativeDisplayDelegateDri::Initialize() {
104 void NativeDisplayDelegateDri::GrabServer() {
107 void NativeDisplayDelegateDri::UngrabServer() {
110 bool NativeDisplayDelegateDri::TakeDisplayControl() {
111 if (!dri_
->SetMaster()) {
112 LOG(ERROR
) << "Failed to take control of the display";
118 bool NativeDisplayDelegateDri::RelinquishDisplayControl() {
119 if (!dri_
->DropMaster()) {
120 LOG(ERROR
) << "Failed to relinquish control of the display";
126 void NativeDisplayDelegateDri::SyncWithServer() {
129 void NativeDisplayDelegateDri::SetBackgroundColor(uint32_t color_argb
) {
132 void NativeDisplayDelegateDri::ForceDPMSOn() {
133 for (size_t i
= 0; i
< cached_displays_
.size(); ++i
) {
134 DisplaySnapshotDri
* dri_output
= cached_displays_
[i
];
135 if (dri_output
->dpms_property())
136 dri_
->SetProperty(dri_output
->connector(),
137 dri_output
->dpms_property()->prop_id
, DRM_MODE_DPMS_ON
);
141 std::vector
<DisplaySnapshot
*> NativeDisplayDelegateDri::GetDisplays() {
142 ScopedVector
<DisplaySnapshotDri
> old_displays(cached_displays_
.Pass());
143 ScopedVector
<const DisplayMode
> old_modes(cached_modes_
.Pass());
145 ScopedVector
<HardwareDisplayControllerInfo
> displays
=
146 GetAvailableDisplayControllerInfos(dri_
->get_fd());
147 for (size_t i
= 0; i
< displays
.size(); ++i
) {
148 DisplaySnapshotDri
* display
= new DisplaySnapshotDri(
149 dri_
, displays
[i
]->connector(), displays
[i
]->crtc(), i
);
151 // If the display exists make sure to sync up the new snapshot with the old
152 // one to keep the user configured details.
153 auto it
= std::find_if(
154 old_displays
.begin(), old_displays
.end(),
155 DisplaySnapshotComparator(displays
[i
]->crtc()->crtc_id
,
156 displays
[i
]->connector()->connector_id
));
157 // Origin is only used within the platform code to keep track of the display
159 if (it
!= old_displays
.end())
160 display
->set_origin((*it
)->origin());
162 cached_displays_
.push_back(display
);
163 cached_modes_
.insert(cached_modes_
.end(), display
->modes().begin(),
164 display
->modes().end());
167 NotifyScreenManager(cached_displays_
.get(), old_displays
.get());
169 std::vector
<DisplaySnapshot
*> generic_displays(cached_displays_
.begin(),
170 cached_displays_
.end());
171 return generic_displays
;
174 void NativeDisplayDelegateDri::GetDisplays(
175 const GetDisplaysCallback
& callback
) {
179 void NativeDisplayDelegateDri::AddMode(const DisplaySnapshot
& output
,
180 const DisplayMode
* mode
) {
183 bool NativeDisplayDelegateDri::Configure(const DisplaySnapshot
& output
,
184 const DisplayMode
* mode
,
185 const gfx::Point
& origin
) {
186 const DisplaySnapshotDri
& dri_output
=
187 static_cast<const DisplaySnapshotDri
&>(output
);
189 VLOG(1) << "DRM configuring: crtc=" << dri_output
.crtc()
190 << " connector=" << dri_output
.connector()
191 << " origin=" << origin
.ToString()
192 << " size=" << (mode
? mode
->size().ToString() : "0x0");
195 if (!screen_manager_
->ConfigureDisplayController(
196 dri_output
.crtc(), dri_output
.connector(), origin
,
197 static_cast<const DisplayModeDri
*>(mode
)->mode_info())) {
198 VLOG(1) << "Failed to configure: crtc=" << dri_output
.crtc()
199 << " connector=" << dri_output
.connector();
203 if (!screen_manager_
->DisableDisplayController(dri_output
.crtc())) {
204 VLOG(1) << "Failed to disable crtc=" << dri_output
.crtc();
212 void NativeDisplayDelegateDri::Configure(const DisplaySnapshot
& output
,
213 const DisplayMode
* mode
,
214 const gfx::Point
& origin
,
215 const ConfigureCallback
& callback
) {
219 void NativeDisplayDelegateDri::CreateFrameBuffer(const gfx::Size
& size
) {
222 bool NativeDisplayDelegateDri::GetHDCPState(const DisplaySnapshot
& output
,
224 const DisplaySnapshotDri
& dri_output
=
225 static_cast<const DisplaySnapshotDri
&>(output
);
227 ScopedDrmConnectorPtr
connector(dri_
->GetConnector(dri_output
.connector()));
229 LOG(ERROR
) << "Failed to get connector " << dri_output
.connector();
233 ScopedDrmPropertyPtr
hdcp_property(
234 dri_
->GetProperty(connector
.get(), kContentProtection
));
235 if (!hdcp_property
) {
236 LOG(ERROR
) << "'" << kContentProtection
<< "' property doesn't exist.";
240 DCHECK_LT(static_cast<int>(hdcp_property
->prop_id
), connector
->count_props
);
241 int hdcp_state_idx
= connector
->prop_values
[hdcp_property
->prop_id
];
242 DCHECK_LT(hdcp_state_idx
, hdcp_property
->count_enums
);
244 std::string
name(hdcp_property
->enums
[hdcp_state_idx
].name
);
245 for (size_t i
= 0; i
< arraysize(kContentProtectionStates
); ++i
) {
246 if (name
== kContentProtectionStates
[i
].name
) {
247 *state
= kContentProtectionStates
[i
].state
;
248 VLOG(3) << "HDCP state: " << *state
<< " (" << name
<< ")";
253 LOG(ERROR
) << "Unknown content protection value '" << name
<< "'";
257 bool NativeDisplayDelegateDri::SetHDCPState(const DisplaySnapshot
& output
,
259 const DisplaySnapshotDri
& dri_output
=
260 static_cast<const DisplaySnapshotDri
&>(output
);
262 ScopedDrmConnectorPtr
connector(dri_
->GetConnector(dri_output
.connector()));
264 LOG(ERROR
) << "Failed to get connector " << dri_output
.connector();
268 ScopedDrmPropertyPtr
hdcp_property(
269 dri_
->GetProperty(connector
.get(), kContentProtection
));
270 if (!hdcp_property
) {
271 LOG(ERROR
) << "'" << kContentProtection
<< "' property doesn't exist.";
275 return dri_
->SetProperty(
276 dri_output
.connector(), hdcp_property
->prop_id
,
277 GetContentProtectionValue(hdcp_property
.get(), state
));
280 std::vector
<ui::ColorCalibrationProfile
>
281 NativeDisplayDelegateDri::GetAvailableColorCalibrationProfiles(
282 const ui::DisplaySnapshot
& output
) {
284 return std::vector
<ui::ColorCalibrationProfile
>();
287 bool NativeDisplayDelegateDri::SetColorCalibrationProfile(
288 const ui::DisplaySnapshot
& output
,
289 ui::ColorCalibrationProfile new_profile
) {
294 void NativeDisplayDelegateDri::AddObserver(NativeDisplayObserver
* observer
) {
295 observers_
.AddObserver(observer
);
298 void NativeDisplayDelegateDri::RemoveObserver(NativeDisplayObserver
* observer
) {
299 observers_
.RemoveObserver(observer
);
302 void NativeDisplayDelegateDri::NotifyScreenManager(
303 const std::vector
<DisplaySnapshotDri
*>& new_displays
,
304 const std::vector
<DisplaySnapshotDri
*>& old_displays
) const {
305 for (size_t i
= 0; i
< old_displays
.size(); ++i
) {
306 const std::vector
<DisplaySnapshotDri
*>::const_iterator it
=
307 std::find_if(new_displays
.begin(), new_displays
.end(),
308 DisplaySnapshotComparator(old_displays
[i
]));
310 if (it
== new_displays
.end())
311 screen_manager_
->RemoveDisplayController(old_displays
[i
]->crtc());
314 for (size_t i
= 0; i
< new_displays
.size(); ++i
) {
315 const std::vector
<DisplaySnapshotDri
*>::const_iterator it
=
316 std::find_if(old_displays
.begin(), old_displays
.end(),
317 DisplaySnapshotComparator(new_displays
[i
]));
319 if (it
== old_displays
.end())
320 screen_manager_
->AddDisplayController(dri_
, new_displays
[i
]->crtc(),
321 new_displays
[i
]->connector());