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/chromeos/native_display_delegate_dri.h"
8 #include "third_party/skia/include/core/SkCanvas.h"
9 #include "ui/display/types/native_display_observer.h"
10 #include "ui/events/ozone/device/device_event.h"
11 #include "ui/events/ozone/device/device_manager.h"
12 #include "ui/ozone/platform/dri/chromeos/display_mode_dri.h"
13 #include "ui/ozone/platform/dri/chromeos/display_snapshot_dri.h"
14 #include "ui/ozone/platform/dri/dri_console_buffer.h"
15 #include "ui/ozone/platform/dri/dri_util.h"
16 #include "ui/ozone/platform/dri/dri_wrapper.h"
17 #include "ui/ozone/platform/dri/screen_manager.h"
23 const size_t kMaxDisplayCount = 2;
25 const char kContentProtection[] = "Content Protection";
27 struct ContentProtectionMapping {
32 const ContentProtectionMapping kContentProtectionStates[] = {
33 {"Undesired", HDCP_STATE_UNDESIRED},
34 {"Desired", HDCP_STATE_DESIRED},
35 {"Enabled", HDCP_STATE_ENABLED}};
37 uint32_t GetContentProtectionValue(drmModePropertyRes* property,
40 for (size_t i = 0; i < arraysize(kContentProtectionStates); ++i) {
41 if (kContentProtectionStates[i].state == state) {
42 name = kContentProtectionStates[i].name;
47 for (int i = 0; i < property->count_enums; ++i)
48 if (name == property->enums[i].name)
55 class DisplaySnapshotComparator {
57 DisplaySnapshotComparator(const DisplaySnapshotDri* snapshot)
58 : snapshot_(snapshot) {}
60 bool operator()(const DisplaySnapshotDri* other) const {
61 if (snapshot_->connector() == other->connector() &&
62 snapshot_->crtc() == other->crtc())
69 const DisplaySnapshotDri* snapshot_;
74 NativeDisplayDelegateDri::NativeDisplayDelegateDri(
76 ScreenManager* screen_manager,
77 DeviceManager* device_manager)
79 screen_manager_(screen_manager),
80 device_manager_(device_manager) {
81 // TODO(dnicoara): Remove when async display configuration is supported.
82 screen_manager_->ForceInitializationOfPrimaryDisplay();
85 NativeDisplayDelegateDri::~NativeDisplayDelegateDri() {
87 device_manager_->RemoveObserver(this);
90 DisplaySnapshot* NativeDisplayDelegateDri::FindDisplaySnapshot(int64_t id) {
91 for (size_t i = 0; i < cached_displays_.size(); ++i)
92 if (cached_displays_[i]->display_id() == id)
93 return cached_displays_[i];
98 const DisplayMode* NativeDisplayDelegateDri::FindDisplayMode(
99 const gfx::Size& size,
101 float refresh_rate) {
102 for (size_t i = 0; i < cached_modes_.size(); ++i)
103 if (cached_modes_[i]->size() == size &&
104 cached_modes_[i]->is_interlaced() == is_interlaced &&
105 cached_modes_[i]->refresh_rate() == refresh_rate)
106 return cached_modes_[i];
111 void NativeDisplayDelegateDri::Initialize() {
113 device_manager_->AddObserver(this);
115 ScopedVector<HardwareDisplayControllerInfo> displays =
116 GetAvailableDisplayControllerInfos(dri_->get_fd());
118 // By default all displays show the same console buffer.
119 console_buffer_.reset(
120 new DriConsoleBuffer(dri_, displays[0]->crtc()->buffer_id));
121 if (!console_buffer_->Initialize()) {
122 VLOG(1) << "Failed to initialize console buffer";
123 console_buffer_.reset();
125 // Clear the console buffer such that restarting Chrome will show a
126 // predetermined background.
128 // Black was chosen since Chrome's first buffer paints start with a black
130 console_buffer_->canvas()->clear(SK_ColorBLACK);
134 void NativeDisplayDelegateDri::GrabServer() {}
136 void NativeDisplayDelegateDri::UngrabServer() {}
138 void NativeDisplayDelegateDri::SyncWithServer() {}
140 void NativeDisplayDelegateDri::SetBackgroundColor(uint32_t color_argb) {
142 console_buffer_->canvas()->clear(color_argb);
145 void NativeDisplayDelegateDri::ForceDPMSOn() {
146 for (size_t i = 0; i < cached_displays_.size(); ++i) {
147 DisplaySnapshotDri* dri_output = cached_displays_[i];
148 if (dri_output->dpms_property())
149 dri_->SetProperty(dri_output->connector(),
150 dri_output->dpms_property()->prop_id,
155 std::vector<DisplaySnapshot*> NativeDisplayDelegateDri::GetDisplays() {
156 ScopedVector<DisplaySnapshotDri> old_displays(cached_displays_.Pass());
157 cached_modes_.clear();
159 ScopedVector<HardwareDisplayControllerInfo> displays =
160 GetAvailableDisplayControllerInfos(dri_->get_fd());
162 i < displays.size() && cached_displays_.size() < kMaxDisplayCount; ++i) {
163 DisplaySnapshotDri* display = new DisplaySnapshotDri(
164 dri_, displays[i]->connector(), displays[i]->crtc(), i);
165 cached_displays_.push_back(display);
166 cached_modes_.insert(cached_modes_.end(),
167 display->modes().begin(),
168 display->modes().end());
171 NotifyScreenManager(cached_displays_.get(), old_displays.get());
173 std::vector<DisplaySnapshot*> generic_displays(cached_displays_.begin(),
174 cached_displays_.end());
175 return generic_displays;
178 void NativeDisplayDelegateDri::AddMode(const DisplaySnapshot& output,
179 const DisplayMode* mode) {}
181 bool NativeDisplayDelegateDri::Configure(const DisplaySnapshot& output,
182 const DisplayMode* mode,
183 const gfx::Point& origin) {
184 const DisplaySnapshotDri& dri_output =
185 static_cast<const DisplaySnapshotDri&>(output);
187 VLOG(1) << "DRM configuring: crtc=" << dri_output.crtc()
188 << " connector=" << dri_output.connector()
189 << " origin=" << origin.ToString()
190 << " size=" << (mode ? mode->size().ToString() : "0x0");
193 if (!screen_manager_->ConfigureDisplayController(
195 dri_output.connector(),
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::CreateFrameBuffer(const gfx::Size& size) {}
214 bool NativeDisplayDelegateDri::GetHDCPState(const DisplaySnapshot& output,
216 const DisplaySnapshotDri& dri_output =
217 static_cast<const DisplaySnapshotDri&>(output);
219 ScopedDrmConnectorPtr connector(dri_->GetConnector(dri_output.connector()));
221 LOG(ERROR) << "Failed to get connector " << dri_output.connector();
225 ScopedDrmPropertyPtr hdcp_property(
226 dri_->GetProperty(connector.get(), kContentProtection));
227 if (!hdcp_property) {
228 LOG(ERROR) << "'" << kContentProtection << "' property doesn't exist.";
232 DCHECK_LT(static_cast<int>(hdcp_property->prop_id), connector->count_props);
233 int hdcp_state_idx = connector->prop_values[hdcp_property->prop_id];
234 DCHECK_LT(hdcp_state_idx, hdcp_property->count_enums);
236 std::string name(hdcp_property->enums[hdcp_state_idx].name);
237 for (size_t i = 0; i < arraysize(kContentProtectionStates); ++i) {
238 if (name == kContentProtectionStates[i].name) {
239 *state = kContentProtectionStates[i].state;
240 VLOG(3) << "HDCP state: " << *state << " (" << name << ")";
245 LOG(ERROR) << "Unknown content protection value '" << name << "'";
249 bool NativeDisplayDelegateDri::SetHDCPState(const DisplaySnapshot& output,
251 const DisplaySnapshotDri& dri_output =
252 static_cast<const DisplaySnapshotDri&>(output);
254 ScopedDrmConnectorPtr connector(dri_->GetConnector(dri_output.connector()));
256 LOG(ERROR) << "Failed to get connector " << dri_output.connector();
260 ScopedDrmPropertyPtr hdcp_property(
261 dri_->GetProperty(connector.get(), kContentProtection));
262 if (!hdcp_property) {
263 LOG(ERROR) << "'" << kContentProtection << "' property doesn't exist.";
267 return dri_->SetProperty(
268 dri_output.connector(),
269 hdcp_property->prop_id,
270 GetContentProtectionValue(hdcp_property.get(), state));
273 std::vector<ui::ColorCalibrationProfile>
274 NativeDisplayDelegateDri::GetAvailableColorCalibrationProfiles(
275 const ui::DisplaySnapshot& output) {
277 return std::vector<ui::ColorCalibrationProfile>();
280 bool NativeDisplayDelegateDri::SetColorCalibrationProfile(
281 const ui::DisplaySnapshot& output,
282 ui::ColorCalibrationProfile new_profile) {
287 void NativeDisplayDelegateDri::AddObserver(NativeDisplayObserver* observer) {
288 observers_.AddObserver(observer);
291 void NativeDisplayDelegateDri::RemoveObserver(NativeDisplayObserver* observer) {
292 observers_.RemoveObserver(observer);
295 void NativeDisplayDelegateDri::OnDeviceEvent(const DeviceEvent& event) {
296 if (event.device_type() != DeviceEvent::DISPLAY)
299 if (event.action_type() == DeviceEvent::CHANGE) {
300 VLOG(1) << "Got display changed event";
302 NativeDisplayObserver, observers_, OnConfigurationChanged());
306 void NativeDisplayDelegateDri::NotifyScreenManager(
307 const std::vector<DisplaySnapshotDri*>& new_displays,
308 const std::vector<DisplaySnapshotDri*>& old_displays) const {
309 for (size_t i = 0; i < old_displays.size(); ++i) {
310 const std::vector<DisplaySnapshotDri*>::const_iterator it =
311 std::find_if(new_displays.begin(),
313 DisplaySnapshotComparator(old_displays[i]));
315 if (it == new_displays.end())
316 screen_manager_->RemoveDisplayController(old_displays[i]->crtc());
319 for (size_t i = 0; i < new_displays.size(); ++i) {
320 const std::vector<DisplaySnapshotDri*>::const_iterator it =
321 std::find_if(old_displays.begin(),
323 DisplaySnapshotComparator(new_displays[i]));
325 if (it == old_displays.end())
326 screen_manager_->AddDisplayController(new_displays[i]->crtc(),
327 new_displays[i]->connector());