Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / ui / ozone / platform / dri / chromeos / native_display_delegate_dri.cc
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/native_display_delegate_dri.h"
6
7 #include "base/bind.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"
18
19 namespace ui {
20
21 namespace {
22
23 const size_t kMaxDisplayCount = 2;
24
25 const char kContentProtection[] = "Content Protection";
26
27 struct ContentProtectionMapping {
28   const char* name;
29   HDCPState state;
30 };
31
32 const ContentProtectionMapping kContentProtectionStates[] = {
33     {"Undesired", HDCP_STATE_UNDESIRED},
34     {"Desired", HDCP_STATE_DESIRED},
35     {"Enabled", HDCP_STATE_ENABLED}};
36
37 uint32_t GetContentProtectionValue(drmModePropertyRes* property,
38                                    HDCPState state) {
39   std::string name;
40   for (size_t i = 0; i < arraysize(kContentProtectionStates); ++i) {
41     if (kContentProtectionStates[i].state == state) {
42       name = kContentProtectionStates[i].name;
43       break;
44     }
45   }
46
47   for (int i = 0; i < property->count_enums; ++i)
48     if (name == property->enums[i].name)
49       return i;
50
51   NOTREACHED();
52   return 0;
53 }
54
55 class DisplaySnapshotComparator {
56  public:
57   DisplaySnapshotComparator(const DisplaySnapshotDri* snapshot)
58       : snapshot_(snapshot) {}
59
60   bool operator()(const DisplaySnapshotDri* other) const {
61     if (snapshot_->connector() == other->connector() &&
62         snapshot_->crtc() == other->crtc())
63       return true;
64
65     return false;
66   }
67
68  private:
69   const DisplaySnapshotDri* snapshot_;
70 };
71
72 }  // namespace
73
74 NativeDisplayDelegateDri::NativeDisplayDelegateDri(
75     DriWrapper* dri,
76     ScreenManager* screen_manager,
77     DeviceManager* device_manager)
78     : dri_(dri),
79       screen_manager_(screen_manager),
80       device_manager_(device_manager) {
81   // TODO(dnicoara): Remove when async display configuration is supported.
82   screen_manager_->ForceInitializationOfPrimaryDisplay();
83 }
84
85 NativeDisplayDelegateDri::~NativeDisplayDelegateDri() {
86   if (device_manager_)
87     device_manager_->RemoveObserver(this);
88 }
89
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];
94
95   return NULL;
96 }
97
98 const DisplayMode* NativeDisplayDelegateDri::FindDisplayMode(
99     const gfx::Size& size,
100     bool is_interlaced,
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];
107
108   return NULL;
109 }
110
111 void NativeDisplayDelegateDri::Initialize() {
112   if (device_manager_)
113     device_manager_->AddObserver(this);
114
115   ScopedVector<HardwareDisplayControllerInfo> displays =
116       GetAvailableDisplayControllerInfos(dri_->get_fd());
117
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();
124   } else {
125     // Clear the console buffer such that restarting Chrome will show a
126     // predetermined background.
127     //
128     // Black was chosen since Chrome's first buffer paints start with a black
129     // background.
130     console_buffer_->canvas()->clear(SK_ColorBLACK);
131   }
132 }
133
134 void NativeDisplayDelegateDri::GrabServer() {}
135
136 void NativeDisplayDelegateDri::UngrabServer() {}
137
138 void NativeDisplayDelegateDri::SyncWithServer() {}
139
140 void NativeDisplayDelegateDri::SetBackgroundColor(uint32_t color_argb) {
141   if (console_buffer_)
142     console_buffer_->canvas()->clear(color_argb);
143 }
144
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,
151                         DRM_MODE_DPMS_ON);
152   }
153 }
154
155 std::vector<DisplaySnapshot*> NativeDisplayDelegateDri::GetDisplays() {
156   ScopedVector<DisplaySnapshotDri> old_displays(cached_displays_.Pass());
157   cached_modes_.clear();
158
159   ScopedVector<HardwareDisplayControllerInfo> displays =
160       GetAvailableDisplayControllerInfos(dri_->get_fd());
161   for (size_t i = 0;
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());
169   }
170
171   NotifyScreenManager(cached_displays_.get(), old_displays.get());
172
173   std::vector<DisplaySnapshot*> generic_displays(cached_displays_.begin(),
174                                                  cached_displays_.end());
175   return generic_displays;
176 }
177
178 void NativeDisplayDelegateDri::AddMode(const DisplaySnapshot& output,
179                                        const DisplayMode* mode) {}
180
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);
186
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");
191
192   if (mode) {
193     if (!screen_manager_->ConfigureDisplayController(
194             dri_output.crtc(),
195             dri_output.connector(),
196             origin,
197             static_cast<const DisplayModeDri*>(mode)->mode_info())) {
198       VLOG(1) << "Failed to configure: crtc=" << dri_output.crtc()
199               << " connector=" << dri_output.connector();
200       return false;
201     }
202   } else {
203     if (!screen_manager_->DisableDisplayController(dri_output.crtc())) {
204       VLOG(1) << "Failed to disable crtc=" << dri_output.crtc();
205       return false;
206     }
207   }
208
209   return true;
210 }
211
212 void NativeDisplayDelegateDri::CreateFrameBuffer(const gfx::Size& size) {}
213
214 bool NativeDisplayDelegateDri::GetHDCPState(const DisplaySnapshot& output,
215                                             HDCPState* state) {
216   const DisplaySnapshotDri& dri_output =
217       static_cast<const DisplaySnapshotDri&>(output);
218
219   ScopedDrmConnectorPtr connector(dri_->GetConnector(dri_output.connector()));
220   if (!connector) {
221     LOG(ERROR) << "Failed to get connector " << dri_output.connector();
222     return false;
223   }
224
225   ScopedDrmPropertyPtr hdcp_property(
226       dri_->GetProperty(connector.get(), kContentProtection));
227   if (!hdcp_property) {
228     LOG(ERROR) << "'" << kContentProtection << "' property doesn't exist.";
229     return false;
230   }
231
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);
235
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 << ")";
241       return true;
242     }
243   }
244
245   LOG(ERROR) << "Unknown content protection value '" << name << "'";
246   return false;
247 }
248
249 bool NativeDisplayDelegateDri::SetHDCPState(const DisplaySnapshot& output,
250                                             HDCPState state) {
251   const DisplaySnapshotDri& dri_output =
252       static_cast<const DisplaySnapshotDri&>(output);
253
254   ScopedDrmConnectorPtr connector(dri_->GetConnector(dri_output.connector()));
255   if (!connector) {
256     LOG(ERROR) << "Failed to get connector " << dri_output.connector();
257     return false;
258   }
259
260   ScopedDrmPropertyPtr hdcp_property(
261       dri_->GetProperty(connector.get(), kContentProtection));
262   if (!hdcp_property) {
263     LOG(ERROR) << "'" << kContentProtection << "' property doesn't exist.";
264     return false;
265   }
266
267   return dri_->SetProperty(
268       dri_output.connector(),
269       hdcp_property->prop_id,
270       GetContentProtectionValue(hdcp_property.get(), state));
271 }
272
273 std::vector<ui::ColorCalibrationProfile>
274 NativeDisplayDelegateDri::GetAvailableColorCalibrationProfiles(
275     const ui::DisplaySnapshot& output) {
276   NOTIMPLEMENTED();
277   return std::vector<ui::ColorCalibrationProfile>();
278 }
279
280 bool NativeDisplayDelegateDri::SetColorCalibrationProfile(
281     const ui::DisplaySnapshot& output,
282     ui::ColorCalibrationProfile new_profile) {
283   NOTIMPLEMENTED();
284   return false;
285 }
286
287 void NativeDisplayDelegateDri::AddObserver(NativeDisplayObserver* observer) {
288   observers_.AddObserver(observer);
289 }
290
291 void NativeDisplayDelegateDri::RemoveObserver(NativeDisplayObserver* observer) {
292   observers_.RemoveObserver(observer);
293 }
294
295 void NativeDisplayDelegateDri::OnDeviceEvent(const DeviceEvent& event) {
296   if (event.device_type() != DeviceEvent::DISPLAY)
297     return;
298
299   if (event.action_type() == DeviceEvent::CHANGE) {
300     VLOG(1) << "Got display changed event";
301     FOR_EACH_OBSERVER(
302         NativeDisplayObserver, observers_, OnConfigurationChanged());
303   }
304 }
305
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(),
312                      new_displays.end(),
313                      DisplaySnapshotComparator(old_displays[i]));
314
315     if (it == new_displays.end())
316       screen_manager_->RemoveDisplayController(old_displays[i]->crtc());
317   }
318
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(),
322                      old_displays.end(),
323                      DisplaySnapshotComparator(new_displays[i]));
324
325     if (it == old_displays.end())
326       screen_manager_->AddDisplayController(new_displays[i]->crtc(),
327                                             new_displays[i]->connector());
328   }
329 }
330
331 }  // namespace ui