Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(736)

Side by Side Diff: ui/ozone/platform/drm/gpu/drm_gpu_display_manager.cc

Issue 1129923004: [1/2][Ozone-Drm] Refactor GPU display management (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@handle-display-init2
Patch Set: . Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « ui/ozone/platform/drm/gpu/drm_gpu_display_manager.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ui/ozone/platform/drm/gpu/drm_gpu_display_manager.h" 5 #include "ui/ozone/platform/drm/gpu/drm_gpu_display_manager.h"
6 6
7 #include "base/bind.h"
8 #include "base/command_line.h"
9 #include "base/file_descriptor_posix.h"
10 #include "base/files/file.h"
11 #include "base/single_thread_task_runner.h"
12 #include "ui/display/types/gamma_ramp_rgb_entry.h" 7 #include "ui/display/types/gamma_ramp_rgb_entry.h"
13 #include "ui/display/types/native_display_observer.h"
14 #include "ui/events/ozone/device/device_event.h"
15 #include "ui/ozone/common/display_util.h" 8 #include "ui/ozone/common/display_util.h"
16 #include "ui/ozone/platform/drm/common/drm_util.h" 9 #include "ui/ozone/platform/drm/common/drm_util.h"
17 #include "ui/ozone/platform/drm/gpu/drm_device.h" 10 #include "ui/ozone/platform/drm/gpu/drm_device.h"
18 #include "ui/ozone/platform/drm/gpu/drm_device_manager.h" 11 #include "ui/ozone/platform/drm/gpu/drm_device_manager.h"
19 #include "ui/ozone/platform/drm/gpu/drm_display_mode.h" 12 #include "ui/ozone/platform/drm/gpu/drm_display.h"
20 #include "ui/ozone/platform/drm/gpu/drm_display_snapshot.h"
21 #include "ui/ozone/platform/drm/gpu/screen_manager.h" 13 #include "ui/ozone/platform/drm/gpu/screen_manager.h"
22 #include "ui/ozone/public/ozone_switches.h"
23 14
24 namespace ui { 15 namespace ui {
25 16
26 namespace { 17 namespace {
27 18
28 const char kContentProtection[] = "Content Protection"; 19 class DisplayComparator {
20 public:
21 explicit DisplayComparator(const DrmDisplay* display)
22 : drm_(display->drm()),
23 crtc_(display->crtc()),
24 connector_(display->connector()) {}
29 25
30 struct ContentProtectionMapping { 26 DisplayComparator(const scoped_refptr<DrmDevice>& drm,
31 const char* name; 27 uint32_t crtc,
32 HDCPState state; 28 uint32_t connector)
33 };
34
35 const ContentProtectionMapping kContentProtectionStates[] = {
36 {"Undesired", HDCP_STATE_UNDESIRED},
37 {"Desired", HDCP_STATE_DESIRED},
38 {"Enabled", HDCP_STATE_ENABLED}};
39
40 uint32_t GetContentProtectionValue(drmModePropertyRes* property,
41 HDCPState state) {
42 std::string name;
43 for (size_t i = 0; i < arraysize(kContentProtectionStates); ++i) {
44 if (kContentProtectionStates[i].state == state) {
45 name = kContentProtectionStates[i].name;
46 break;
47 }
48 }
49
50 for (int i = 0; i < property->count_enums; ++i)
51 if (name == property->enums[i].name)
52 return i;
53
54 NOTREACHED();
55 return 0;
56 }
57
58 class DisplaySnapshotComparator {
59 public:
60 explicit DisplaySnapshotComparator(const DrmDisplaySnapshot* snapshot)
61 : drm_(snapshot->drm()),
62 crtc_(snapshot->crtc()),
63 connector_(snapshot->connector()) {}
64
65 DisplaySnapshotComparator(const scoped_refptr<DrmDevice>& drm,
66 uint32_t crtc,
67 uint32_t connector)
68 : drm_(drm), crtc_(crtc), connector_(connector) {} 29 : drm_(drm), crtc_(crtc), connector_(connector) {}
69 30
70 bool operator()(const DrmDisplaySnapshot* other) const { 31 bool operator()(const DrmDisplay* other) const {
71 return drm_ == other->drm() && connector_ == other->connector() && 32 return drm_ == other->drm() && connector_ == other->connector() &&
72 crtc_ == other->crtc(); 33 crtc_ == other->crtc();
73 } 34 }
74 35
75 private: 36 private:
76 scoped_refptr<DrmDevice> drm_; 37 scoped_refptr<DrmDevice> drm_;
77 uint32_t crtc_; 38 uint32_t crtc_;
78 uint32_t connector_; 39 uint32_t connector_;
79 }; 40 };
80 41
81 std::string GetEnumNameForProperty(drmModeConnector* connector, 42 bool FindMatchingMode(const std::vector<drmModeModeInfo> modes,
82 drmModePropertyRes* property) { 43 const DisplayMode_Params& mode_params,
83 for (int prop_idx = 0; prop_idx < connector->count_props; ++prop_idx) { 44 drmModeModeInfo* mode) {
84 if (connector->props[prop_idx] != property->prop_id) 45 for (const drmModeModeInfo& m : modes) {
85 continue; 46 DisplayMode_Params params = CreateDisplayModeParams(m);
86 47 if (mode_params.size == params.size &&
87 for (int enum_idx = 0; enum_idx < property->count_enums; ++enum_idx) { 48 mode_params.refresh_rate == params.refresh_rate &&
88 const drm_mode_property_enum& property_enum = property->enums[enum_idx]; 49 mode_params.is_interlaced == params.is_interlaced) {
89 if (property_enum.value == connector->prop_values[prop_idx]) 50 *mode = m;
90 return property_enum.name; 51 return true;
91 } 52 }
92 } 53 }
93 54
94 NOTREACHED(); 55 return false;
95 return std::string(); 56 }
57
58 std::vector<drmModeModeInfo> GetDrmModeVector(drmModeConnector* connector) {
59 std::vector<drmModeModeInfo> modes;
60 for (int i = 0; i < connector->count_modes; ++i)
61 modes.push_back(connector->modes[i]);
62
63 return modes;
96 } 64 }
97 65
98 } // namespace 66 } // namespace
99 67
100 DrmGpuDisplayManager::DrmGpuDisplayManager(ScreenManager* screen_manager, 68 DrmGpuDisplayManager::DrmGpuDisplayManager(ScreenManager* screen_manager,
101 DrmDeviceManager* drm_device_manager) 69 DrmDeviceManager* drm_device_manager)
102 : screen_manager_(screen_manager), drm_device_manager_(drm_device_manager) { 70 : screen_manager_(screen_manager), drm_device_manager_(drm_device_manager) {
103 } 71 }
104 72
105 DrmGpuDisplayManager::~DrmGpuDisplayManager() { 73 DrmGpuDisplayManager::~DrmGpuDisplayManager() {
106 } 74 }
107 75
108 std::vector<DisplaySnapshot_Params> DrmGpuDisplayManager::GetDisplays() { 76 std::vector<DisplaySnapshot_Params> DrmGpuDisplayManager::GetDisplays() {
109 RefreshDisplayList(); 77 ScopedVector<DrmDisplay> old_displays(displays_.Pass());
78 std::vector<DisplaySnapshot_Params> params_list;
110 79
111 std::vector<DisplaySnapshot_Params> displays; 80 const DrmDeviceVector& devices = drm_device_manager_->GetDrmDevices();
112 for (size_t i = 0; i < cached_displays_.size(); ++i) 81 // Unique identifier used to create the display id.
113 displays.push_back(GetDisplaySnapshotParams(*cached_displays_[i])); 82 size_t index = 0;
83 for (const auto& drm : devices) {
84 ScopedVector<HardwareDisplayControllerInfo> display_infos =
85 GetAvailableDisplayControllerInfos(drm->get_fd());
86 for (auto* display_info : display_infos) {
87 DisplaySnapshot_Params params =
88 CreateDisplaySnapshotParams(display_info, drm->get_fd(), index++);
89 params_list.push_back(params);
114 90
115 return displays; 91 displays_.push_back(
116 } 92 new DrmDisplay(screen_manager_, params.display_id, drm,
117 93 display_info->crtc()->crtc_id,
118 bool DrmGpuDisplayManager::ConfigureDisplay( 94 display_info->connector()->connector_id,
119 int64_t id, 95 GetDrmModeVector(display_info->connector())));
120 const DisplayMode_Params& mode_param,
121 const gfx::Point& origin) {
122 DrmDisplaySnapshot* display = FindDisplaySnapshot(id);
123 if (!display) {
124 LOG(ERROR) << "There is no display with ID " << id;
125 return false;
126 }
127
128 const DisplayMode* mode = NULL;
129 for (size_t i = 0; i < display->modes().size(); ++i) {
130 if (mode_param.size == display->modes()[i]->size() &&
131 mode_param.is_interlaced == display->modes()[i]->is_interlaced() &&
132 mode_param.refresh_rate == display->modes()[i]->refresh_rate()) {
133 mode = display->modes()[i];
134 break;
135 } 96 }
136 } 97 }
137 98
138 // If the display doesn't have the mode natively, then lookup the mode from 99 NotifyScreenManager(displays_.get(), old_displays.get());
139 // other displays and try using it on the current display (some displays 100 return params_list;
140 // support panel fitting and they can use different modes even if the mode
141 // isn't explicitly declared).
142 if (!mode)
143 mode = FindDisplayMode(mode_param.size, mode_param.is_interlaced,
144 mode_param.refresh_rate);
145
146 if (!mode) {
147 LOG(ERROR) << "Failed to find mode: size=" << mode_param.size.ToString()
148 << " is_interlaced=" << mode_param.is_interlaced
149 << " refresh_rate=" << mode_param.refresh_rate;
150 return false;
151 }
152
153 bool success =
154 Configure(*display, static_cast<const DrmDisplayMode*>(mode), origin);
155 if (success) {
156 display->set_origin(origin);
157 display->set_current_mode(mode);
158 }
159
160 return success;
161 }
162
163 bool DrmGpuDisplayManager::DisableDisplay(int64_t id) {
164 DrmDisplaySnapshot* display = FindDisplaySnapshot(id);
165 bool success = false;
166 if (display)
167 success = Configure(*display, NULL, gfx::Point());
168 else
169 LOG(ERROR) << "There is no display with ID " << id;
170
171 return success;
172 } 101 }
173 102
174 bool DrmGpuDisplayManager::TakeDisplayControl() { 103 bool DrmGpuDisplayManager::TakeDisplayControl() {
175 const DrmDeviceVector& devices = drm_device_manager_->GetDrmDevices(); 104 const DrmDeviceVector& devices = drm_device_manager_->GetDrmDevices();
176 for (const auto& drm : devices) { 105 for (const auto& drm : devices) {
177 if (!drm->SetMaster()) { 106 if (!drm->SetMaster()) {
178 LOG(ERROR) << "Failed to take control of the display"; 107 LOG(ERROR) << "Failed to take control of the display";
179 return false; 108 return false;
180 } 109 }
181 } 110 }
111
182 return true; 112 return true;
183 } 113 }
184 114
185 bool DrmGpuDisplayManager::RelinquishDisplayControl() { 115 bool DrmGpuDisplayManager::RelinquishDisplayControl() {
186 const DrmDeviceVector& devices = drm_device_manager_->GetDrmDevices(); 116 const DrmDeviceVector& devices = drm_device_manager_->GetDrmDevices();
187 for (const auto& drm : devices) { 117 for (const auto& drm : devices) {
188 if (!drm->DropMaster()) { 118 if (!drm->DropMaster()) {
189 LOG(ERROR) << "Failed to relinquish control of the display"; 119 LOG(ERROR) << "Failed to relinquish control of the display";
190 return false; 120 return false;
191 } 121 }
192 } 122 }
193 return true;
194 }
195
196 void DrmGpuDisplayManager::SetGammaRamp(
197 int64_t id,
198 const std::vector<GammaRampRGBEntry>& lut) {
199 DrmDisplaySnapshot* display = FindDisplaySnapshot(id);
200 if (!display) {
201 LOG(ERROR) << "There is no display with ID " << id;
202 return;
203 }
204
205 if (!display->drm()->SetGammaRamp(display->crtc(), lut)) {
206 LOG(ERROR) << "Failed to set gamma ramp for display: crtc_id = "
207 << display->crtc() << " size = " << lut.size();
208 }
209 }
210
211 DrmDisplaySnapshot* DrmGpuDisplayManager::FindDisplaySnapshot(int64_t id) {
212 for (size_t i = 0; i < cached_displays_.size(); ++i)
213 if (cached_displays_[i]->display_id() == id)
214 return cached_displays_[i];
215
216 return NULL;
217 }
218
219 const DrmDisplayMode* DrmGpuDisplayManager::FindDisplayMode(
220 const gfx::Size& size,
221 bool is_interlaced,
222 float refresh_rate) {
223 for (size_t i = 0; i < cached_modes_.size(); ++i)
224 if (cached_modes_[i]->size() == size &&
225 cached_modes_[i]->is_interlaced() == is_interlaced &&
226 cached_modes_[i]->refresh_rate() == refresh_rate)
227 return static_cast<const DrmDisplayMode*>(cached_modes_[i]);
228
229 return NULL;
230 }
231
232 void DrmGpuDisplayManager::RefreshDisplayList() {
233 ScopedVector<DrmDisplaySnapshot> old_displays(cached_displays_.Pass());
234 ScopedVector<const DisplayMode> old_modes(cached_modes_.Pass());
235
236 const DrmDeviceVector& devices = drm_device_manager_->GetDrmDevices();
237 for (const auto& drm : devices) {
238 ScopedVector<HardwareDisplayControllerInfo> displays =
239 GetAvailableDisplayControllerInfos(drm->get_fd());
240 for (size_t i = 0; i < displays.size(); ++i) {
241 DrmDisplaySnapshot* display = new DrmDisplaySnapshot(
242 drm, displays[i]->connector(), displays[i]->crtc(), i);
243
244 // If the display exists make sure to sync up the new snapshot with the
245 // old one to keep the user configured details.
246 auto it = std::find_if(
247 old_displays.begin(), old_displays.end(),
248 DisplaySnapshotComparator(drm, displays[i]->crtc()->crtc_id,
249 displays[i]->connector()->connector_id));
250 // Origin is only used within the platform code to keep track of the
251 // display location.
252 if (it != old_displays.end())
253 display->set_origin((*it)->origin());
254
255 cached_displays_.push_back(display);
256 cached_modes_.insert(cached_modes_.end(), display->modes().begin(),
257 display->modes().end());
258 }
259 }
260
261 NotifyScreenManager(cached_displays_.get(), old_displays.get());
262 }
263
264 bool DrmGpuDisplayManager::Configure(const DrmDisplaySnapshot& output,
265 const DrmDisplayMode* mode,
266 const gfx::Point& origin) {
267 VLOG(1) << "DRM configuring: device=" << output.drm()->device_path().value()
268 << " crtc=" << output.crtc() << " connector=" << output.connector()
269 << " origin=" << origin.ToString()
270 << " size=" << (mode ? mode->size().ToString() : "0x0");
271
272 if (mode) {
273 if (!screen_manager_->ConfigureDisplayController(
274 output.drm(), output.crtc(), output.connector(), origin,
275 mode->mode_info())) {
276 VLOG(1) << "Failed to configure: device="
277 << output.drm()->device_path().value()
278 << " crtc=" << output.crtc()
279 << " connector=" << output.connector();
280 return false;
281 }
282 } else {
283 if (!screen_manager_->DisableDisplayController(output.drm(),
284 output.crtc())) {
285 VLOG(1) << "Failed to disable device="
286 << output.drm()->device_path().value()
287 << " crtc=" << output.crtc();
288 return false;
289 }
290 }
291 123
292 return true; 124 return true;
293 } 125 }
294 126
295 bool DrmGpuDisplayManager::GetHDCPState(int64_t display_id, HDCPState* state) { 127 bool DrmGpuDisplayManager::ConfigureDisplay(
296 DrmDisplaySnapshot* output = FindDisplaySnapshot(display_id); 128 int64_t display_id,
297 if (!output) { 129 const DisplayMode_Params& mode_param,
130 const gfx::Point& origin) {
131 DrmDisplay* display = FindDisplay(display_id);
132 if (!display) {
298 LOG(ERROR) << "There is no display with ID " << display_id; 133 LOG(ERROR) << "There is no display with ID " << display_id;
299 return false; 134 return false;
300 } 135 }
301 136
302 ScopedDrmConnectorPtr connector( 137 drmModeModeInfo mode;
303 output->drm()->GetConnector(output->connector())); 138 bool mode_found = FindMatchingMode(display->modes(), mode_param, &mode);
304 if (!connector) { 139 if (!mode_found) {
305 PLOG(ERROR) << "Failed to get connector " << output->connector(); 140 // If the display doesn't have the mode natively, then lookup the mode from
141 // other displays and try using it on the current display (some displays
142 // support panel fitting and they can use different modes even if the mode
143 // isn't explicitly declared).
144 for (DrmDisplay* other : displays_) {
145 mode_found = FindMatchingMode(other->modes(), mode_param, &mode);
146 if (mode_found)
147 break;
148 }
149 }
150
151 if (!mode_found) {
152 LOG(ERROR) << "Failed to find mode: size=" << mode_param.size.ToString()
153 << " is_interlaced=" << mode_param.is_interlaced
154 << " refresh_rate=" << mode_param.refresh_rate;
306 return false; 155 return false;
307 } 156 }
308 157
309 ScopedDrmPropertyPtr hdcp_property( 158 return display->Configure(&mode, origin);
310 output->drm()->GetProperty(connector.get(), kContentProtection));
311 if (!hdcp_property) {
312 PLOG(ERROR) << "'" << kContentProtection << "' property doesn't exist.";
313 return false;
314 }
315
316 std::string name =
317 GetEnumNameForProperty(connector.get(), hdcp_property.get());
318 for (size_t i = 0; i < arraysize(kContentProtectionStates); ++i) {
319 if (name == kContentProtectionStates[i].name) {
320 *state = kContentProtectionStates[i].state;
321 VLOG(3) << "HDCP state: " << *state << " (" << name << ")";
322 return true;
323 }
324 }
325
326 LOG(ERROR) << "Unknown content protection value '" << name << "'";
327 return false;
328 } 159 }
329 160
330 bool DrmGpuDisplayManager::SetHDCPState(int64_t display_id, HDCPState state) { 161 bool DrmGpuDisplayManager::DisableDisplay(int64_t display_id) {
331 DrmDisplaySnapshot* output = FindDisplaySnapshot(display_id); 162 DrmDisplay* display = FindDisplay(display_id);
332 if (!output) { 163 if (!display) {
333 LOG(ERROR) << "There is no display with ID " << display_id; 164 LOG(ERROR) << "There is no display with ID " << display_id;
334 return false; 165 return false;
335 } 166 }
336 167
337 ScopedDrmConnectorPtr connector( 168 return display->Configure(nullptr, gfx::Point());
338 output->drm()->GetConnector(output->connector())); 169 }
339 if (!connector) { 170
340 PLOG(ERROR) << "Failed to get connector " << output->connector(); 171 bool DrmGpuDisplayManager::GetHDCPState(int64_t display_id, HDCPState* state) {
172 DrmDisplay* display = FindDisplay(display_id);
173 if (!display) {
174 LOG(ERROR) << "There is no display with ID " << display_id;
341 return false; 175 return false;
342 } 176 }
343 177
344 ScopedDrmPropertyPtr hdcp_property( 178 return display->GetHDCPState(state);
345 output->drm()->GetProperty(connector.get(), kContentProtection)); 179 }
346 if (!hdcp_property) { 180
347 PLOG(ERROR) << "'" << kContentProtection << "' property doesn't exist."; 181 bool DrmGpuDisplayManager::SetHDCPState(int64_t display_id, HDCPState state) {
182 DrmDisplay* display = FindDisplay(display_id);
183 if (!display) {
184 LOG(ERROR) << "There is no display with ID " << display_id;
348 return false; 185 return false;
349 } 186 }
350 187
351 return output->drm()->SetProperty( 188 return display->SetHDCPState(state);
352 output->connector(), hdcp_property->prop_id, 189 }
353 GetContentProtectionValue(hdcp_property.get(), state)); 190
191 void DrmGpuDisplayManager::SetGammaRamp(
192 int64_t display_id,
193 const std::vector<GammaRampRGBEntry>& lut) {
194 DrmDisplay* display = FindDisplay(display_id);
195 if (!display) {
196 LOG(ERROR) << "There is no display with ID " << display_id;
197 return;
198 }
199
200 display->SetGammaRamp(lut);
201 }
202
203 DrmDisplay* DrmGpuDisplayManager::FindDisplay(int64_t display_id) {
204 for (DrmDisplay* display : displays_)
205 if (display->display_id() == display_id)
206 return display;
207
208 return nullptr;
354 } 209 }
355 210
356 void DrmGpuDisplayManager::NotifyScreenManager( 211 void DrmGpuDisplayManager::NotifyScreenManager(
357 const std::vector<DrmDisplaySnapshot*>& new_displays, 212 const std::vector<DrmDisplay*>& new_displays,
358 const std::vector<DrmDisplaySnapshot*>& old_displays) const { 213 const std::vector<DrmDisplay*>& old_displays) const {
359 for (size_t i = 0; i < old_displays.size(); ++i) { 214 for (size_t i = 0; i < old_displays.size(); ++i) {
360 const std::vector<DrmDisplaySnapshot*>::const_iterator it = 215 const std::vector<DrmDisplay*>::const_iterator it =
361 std::find_if(new_displays.begin(), new_displays.end(), 216 std::find_if(new_displays.begin(), new_displays.end(),
362 DisplaySnapshotComparator(old_displays[i])); 217 DisplayComparator(old_displays[i]));
363 218
364 if (it == new_displays.end()) { 219 if (it == new_displays.end()) {
365 screen_manager_->RemoveDisplayController(old_displays[i]->drm(), 220 screen_manager_->RemoveDisplayController(old_displays[i]->drm(),
366 old_displays[i]->crtc()); 221 old_displays[i]->crtc());
367 } 222 }
368 } 223 }
369 224
370 for (size_t i = 0; i < new_displays.size(); ++i) { 225 for (size_t i = 0; i < new_displays.size(); ++i) {
371 const std::vector<DrmDisplaySnapshot*>::const_iterator it = 226 const std::vector<DrmDisplay*>::const_iterator it =
372 std::find_if(old_displays.begin(), old_displays.end(), 227 std::find_if(old_displays.begin(), old_displays.end(),
373 DisplaySnapshotComparator(new_displays[i])); 228 DisplayComparator(new_displays[i]));
374 229
375 if (it == old_displays.end()) { 230 if (it == old_displays.end()) {
376 screen_manager_->AddDisplayController(new_displays[i]->drm(), 231 screen_manager_->AddDisplayController(new_displays[i]->drm(),
377 new_displays[i]->crtc(), 232 new_displays[i]->crtc(),
378 new_displays[i]->connector()); 233 new_displays[i]->connector());
379 } 234 }
380 } 235 }
381 } 236 }
382 237
383 } // namespace ui 238 } // namespace ui
OLDNEW
« no previous file with comments | « ui/ozone/platform/drm/gpu/drm_gpu_display_manager.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698