OLD | NEW |
---|---|
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/host/drm_native_display_delegate.h" | 5 #include "ui/ozone/platform/drm/host/drm_native_display_delegate.h" |
6 | 6 |
7 #include <stdio.h> | 7 #include <stdio.h> |
8 #include <xf86drm.h> | |
9 | 8 |
10 #include "base/logging.h" | 9 #include "base/logging.h" |
11 #include "base/thread_task_runner_handle.h" | 10 #include "base/thread_task_runner_handle.h" |
12 #include "base/threading/thread_restrictions.h" | 11 #include "base/threading/thread_restrictions.h" |
13 #include "ui/display/types/display_snapshot.h" | 12 #include "ui/display/types/display_snapshot.h" |
14 #include "ui/display/types/native_display_observer.h" | 13 #include "ui/display/types/native_display_observer.h" |
15 #include "ui/events/ozone/device/device_event.h" | 14 #include "ui/events/ozone/device/device_event.h" |
16 #include "ui/events/ozone/device/device_manager.h" | 15 #include "ui/events/ozone/device/device_manager.h" |
17 #include "ui/ozone/common/display_snapshot_proxy.h" | 16 #include "ui/ozone/common/display_snapshot_proxy.h" |
18 #include "ui/ozone/common/display_util.h" | 17 #include "ui/ozone/common/display_util.h" |
19 #include "ui/ozone/common/gpu/ozone_gpu_messages.h" | 18 #include "ui/ozone/common/gpu/ozone_gpu_messages.h" |
20 #include "ui/ozone/platform/drm/host/display_manager.h" | 19 #include "ui/ozone/platform/drm/host/display_manager.h" |
20 #include "ui/ozone/platform/drm/host/drm_device_handle.h" | |
21 #include "ui/ozone/platform/drm/host/drm_gpu_platform_support_host.h" | 21 #include "ui/ozone/platform/drm/host/drm_gpu_platform_support_host.h" |
22 | 22 |
23 namespace ui { | 23 namespace ui { |
24 | 24 |
25 namespace { | 25 namespace { |
26 | 26 |
27 typedef base::Callback<void(const base::FilePath&, base::File)> | 27 typedef base::Callback<void(const base::FilePath&)> OnOpenDeviceReplyCallback; |
28 OnOpenDeviceReplyCallback; | |
29 | 28 |
30 const char* kDisplayActionString[] = { | 29 const char* kDisplayActionString[] = { |
31 "ADD", | 30 "ADD", |
32 "REMOVE", | 31 "REMOVE", |
33 "CHANGE", | 32 "CHANGE", |
34 }; | 33 }; |
35 | 34 |
36 bool Authenticate(int fd) { | |
37 drm_magic_t magic = 0; | |
38 // We need to make sure the DRM device has enough privilege. Use the DRM | |
39 // authentication logic to figure out if the device has enough permissions. | |
40 return !drmGetMagic(fd, &magic) && !drmAuthMagic(fd, magic); | |
41 } | |
42 | |
43 base::File OpenDrmDevice(const base::FilePath& path) { | |
44 base::File file; | |
45 bool print_warning = true; | |
46 while (true) { | |
47 file = base::File(path, base::File::FLAG_OPEN | base::File::FLAG_READ | | |
48 base::File::FLAG_WRITE); | |
49 | |
50 base::File::Info info; | |
51 file.GetInfo(&info); | |
52 | |
53 CHECK(!info.is_directory); | |
54 CHECK(path.DirName() == base::FilePath("/dev/dri")); | |
55 | |
56 if (!file.IsValid()) { | |
57 LOG(ERROR) << "Failed to open " << path.value() << ": " | |
58 << base::File::ErrorToString(file.error_details()); | |
59 return file.Pass(); | |
60 } | |
61 | |
62 if (Authenticate(file.GetPlatformFile())) | |
63 break; | |
64 | |
65 LOG_IF(WARNING, print_warning) << "Failed to authenticate " << path.value(); | |
66 | |
67 print_warning = false; | |
68 usleep(100000); | |
69 } | |
70 | |
71 VLOG(1) << "Succeeded authenticating " << path.value(); | |
72 return file.Pass(); | |
73 } | |
74 | |
75 void OpenDeviceOnWorkerThread( | 35 void OpenDeviceOnWorkerThread( |
76 const base::FilePath& path, | 36 const base::FilePath& path, |
37 DrmDeviceHandle* handle, | |
77 const scoped_refptr<base::TaskRunner>& reply_runner, | 38 const scoped_refptr<base::TaskRunner>& reply_runner, |
78 const OnOpenDeviceReplyCallback& callback) { | 39 const OnOpenDeviceReplyCallback& callback) { |
79 base::File file = OpenDrmDevice(path); | 40 if (handle->Initialize(path)) |
80 reply_runner->PostTask(FROM_HERE, | 41 reply_runner->PostTask(FROM_HERE, base::Bind(callback, path)); |
81 base::Bind(callback, path, base::Passed(file.Pass()))); | |
82 } | 42 } |
83 | 43 |
84 void UpdateDeviceOnWorkerThread( | 44 void UpdateDeviceOnWorkerThread( |
85 const scoped_refptr<base::TaskRunner>& reply_runner, | 45 const scoped_refptr<base::TaskRunner>& reply_runner, |
86 const base::Closure& callback) { | 46 const base::Closure& callback) { |
87 // Just reply since there isn't a need for extra operations. | 47 // Just reply since there isn't a need for extra operations. |
88 reply_runner->PostTask(FROM_HERE, callback); | 48 reply_runner->PostTask(FROM_HERE, callback); |
89 } | 49 } |
90 | 50 |
51 void CloseDeviceOnWorkerThread( | |
52 scoped_ptr<DrmDeviceHandle> handle, | |
53 const scoped_refptr<base::TaskRunner>& reply_runner, | |
54 const base::Closure& callback) { | |
55 handle->Shutdown(); | |
56 reply_runner->PostTask(FROM_HERE, callback); | |
57 } | |
58 | |
91 class DrmDisplaySnapshotProxy : public DisplaySnapshotProxy { | 59 class DrmDisplaySnapshotProxy : public DisplaySnapshotProxy { |
92 public: | 60 public: |
93 DrmDisplaySnapshotProxy(const DisplaySnapshot_Params& params, | 61 DrmDisplaySnapshotProxy(const DisplaySnapshot_Params& params, |
94 DisplayManager* display_manager) | 62 DisplayManager* display_manager) |
95 : DisplaySnapshotProxy(params), display_manager_(display_manager) { | 63 : DisplaySnapshotProxy(params), display_manager_(display_manager) { |
96 display_manager_->RegisterDisplay(this); | 64 display_manager_->RegisterDisplay(this); |
97 } | 65 } |
98 | 66 |
99 ~DrmDisplaySnapshotProxy() override { | 67 ~DrmDisplaySnapshotProxy() override { |
100 display_manager_->UnregisterDisplay(this); | 68 display_manager_->UnregisterDisplay(this); |
(...skipping 12 matching lines...) Expand all Loading... | |
113 DeviceManager* device_manager, | 81 DeviceManager* device_manager, |
114 DisplayManager* display_manager, | 82 DisplayManager* display_manager, |
115 const base::FilePath& primary_graphics_card_path) | 83 const base::FilePath& primary_graphics_card_path) |
116 : proxy_(proxy), | 84 : proxy_(proxy), |
117 device_manager_(device_manager), | 85 device_manager_(device_manager), |
118 display_manager_(display_manager), | 86 display_manager_(display_manager), |
119 primary_graphics_card_path_(primary_graphics_card_path), | 87 primary_graphics_card_path_(primary_graphics_card_path), |
120 has_dummy_display_(false), | 88 has_dummy_display_(false), |
121 weak_ptr_factory_(this) { | 89 weak_ptr_factory_(this) { |
122 proxy_->RegisterHandler(this); | 90 proxy_->RegisterHandler(this); |
123 drm_devices_.insert(primary_graphics_card_path); | |
124 } | 91 } |
125 | 92 |
126 DrmNativeDisplayDelegate::~DrmNativeDisplayDelegate() { | 93 DrmNativeDisplayDelegate::~DrmNativeDisplayDelegate() { |
127 device_manager_->RemoveObserver(this); | 94 device_manager_->RemoveObserver(this); |
128 proxy_->UnregisterHandler(this); | 95 proxy_->UnregisterHandler(this); |
129 } | 96 } |
130 | 97 |
131 void DrmNativeDisplayDelegate::Initialize() { | 98 void DrmNativeDisplayDelegate::Initialize() { |
132 device_manager_->AddObserver(this); | 99 device_manager_->AddObserver(this); |
133 device_manager_->ScanDevices(this); | 100 device_manager_->ScanDevices(this); |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
262 | 229 |
263 void DrmNativeDisplayDelegate::OnDeviceEvent(const DeviceEvent& event) { | 230 void DrmNativeDisplayDelegate::OnDeviceEvent(const DeviceEvent& event) { |
264 if (event.device_type() != DeviceEvent::DISPLAY) | 231 if (event.device_type() != DeviceEvent::DISPLAY) |
265 return; | 232 return; |
266 | 233 |
267 VLOG(1) << "Got display event " << kDisplayActionString[event.action_type()] | 234 VLOG(1) << "Got display event " << kDisplayActionString[event.action_type()] |
268 << " for " << event.path().value(); | 235 << " for " << event.path().value(); |
269 switch (event.action_type()) { | 236 switch (event.action_type()) { |
270 case DeviceEvent::ADD: | 237 case DeviceEvent::ADD: |
271 if (drm_devices_.find(event.path()) == drm_devices_.end()) { | 238 if (drm_devices_.find(event.path()) == drm_devices_.end()) { |
272 drm_devices_.insert(event.path()); | 239 scoped_ptr<DrmDeviceHandle> handle(new DrmDeviceHandle()); |
273 scheduler_.PostNamedSequencedWorkerTask( | 240 scheduler_.PostNamedSequencedWorkerTask( |
274 event.path().value(), FROM_HERE, | 241 event.path().value(), FROM_HERE, |
275 base::Bind( | 242 base::Bind( |
276 &OpenDeviceOnWorkerThread, event.path(), | 243 &OpenDeviceOnWorkerThread, event.path(), handle.get(), |
277 base::ThreadTaskRunnerHandle::Get(), | 244 base::ThreadTaskRunnerHandle::Get(), |
278 base::Bind(&DrmNativeDisplayDelegate::OnAddGraphicsDevice, | 245 base::Bind(&DrmNativeDisplayDelegate::OnAddGraphicsDevice, |
279 weak_ptr_factory_.GetWeakPtr()))); | 246 weak_ptr_factory_.GetWeakPtr()))); |
247 drm_devices_.add(event.path(), handle.Pass()); | |
dnicoara
2015/04/27 16:46:55
Hmm, this will be problematic since the handle may
| |
280 } | 248 } |
281 return; | 249 return; |
282 case DeviceEvent::CHANGE: | 250 case DeviceEvent::CHANGE: |
283 scheduler_.PostNamedSequencedWorkerTask( | 251 scheduler_.PostNamedSequencedWorkerTask( |
284 event.path().value(), FROM_HERE, | 252 event.path().value(), FROM_HERE, |
285 base::Bind( | 253 base::Bind( |
286 &UpdateDeviceOnWorkerThread, base::ThreadTaskRunnerHandle::Get(), | 254 &UpdateDeviceOnWorkerThread, base::ThreadTaskRunnerHandle::Get(), |
287 base::Bind(&DrmNativeDisplayDelegate::OnUpdateGraphicsDevice, | 255 base::Bind(&DrmNativeDisplayDelegate::OnUpdateGraphicsDevice, |
288 weak_ptr_factory_.GetWeakPtr()))); | 256 weak_ptr_factory_.GetWeakPtr()))); |
289 return; | 257 return; |
290 case DeviceEvent::REMOVE: | 258 case DeviceEvent::REMOVE: |
291 DCHECK(event.path() != primary_graphics_card_path_) | 259 DCHECK(event.path() != primary_graphics_card_path_) |
292 << "Removing primary graphics card"; | 260 << "Removing primary graphics card"; |
293 auto it = drm_devices_.find(event.path()); | 261 auto it = drm_devices_.find(event.path()); |
294 if (it != drm_devices_.end()) { | 262 if (it != drm_devices_.end()) { |
295 drm_devices_.erase(it); | |
296 scheduler_.PostNamedSequencedWorkerTask( | 263 scheduler_.PostNamedSequencedWorkerTask( |
297 event.path().value(), FROM_HERE, | 264 event.path().value(), FROM_HERE, |
298 base::Bind( | 265 base::Bind( |
299 &UpdateDeviceOnWorkerThread, | 266 &CloseDeviceOnWorkerThread, |
267 base::Passed(drm_devices_.take_and_erase(it)), | |
300 base::ThreadTaskRunnerHandle::Get(), | 268 base::ThreadTaskRunnerHandle::Get(), |
301 base::Bind(&DrmNativeDisplayDelegate::OnRemoveGraphicsDevice, | 269 base::Bind(&DrmNativeDisplayDelegate::OnRemoveGraphicsDevice, |
302 weak_ptr_factory_.GetWeakPtr(), event.path()))); | 270 weak_ptr_factory_.GetWeakPtr(), event.path()))); |
303 } | 271 } |
304 return; | 272 return; |
305 } | 273 } |
306 } | 274 } |
307 | 275 |
308 void DrmNativeDisplayDelegate::OnAddGraphicsDevice(const base::FilePath& path, | 276 void DrmNativeDisplayDelegate::OnAddGraphicsDevice(const base::FilePath& path) { |
309 base::File file) { | 277 auto it = drm_devices_.find(path); |
310 if (!file.IsValid()) | 278 if (it == drm_devices_.end()) |
311 return; | 279 return; |
312 | 280 |
313 proxy_->Send(new OzoneGpuMsg_AddGraphicsDevice( | 281 proxy_->Send(new OzoneGpuMsg_AddGraphicsDevice( |
314 path, base::FileDescriptor(file.Pass()))); | 282 path, base::FileDescriptor(it->second->DuplicateFile()))); |
315 FOR_EACH_OBSERVER(NativeDisplayObserver, observers_, | 283 FOR_EACH_OBSERVER(NativeDisplayObserver, observers_, |
316 OnConfigurationChanged()); | 284 OnConfigurationChanged()); |
317 } | 285 } |
318 | 286 |
319 void DrmNativeDisplayDelegate::OnUpdateGraphicsDevice() { | 287 void DrmNativeDisplayDelegate::OnUpdateGraphicsDevice() { |
320 FOR_EACH_OBSERVER(NativeDisplayObserver, observers_, | 288 FOR_EACH_OBSERVER(NativeDisplayObserver, observers_, |
321 OnConfigurationChanged()); | 289 OnConfigurationChanged()); |
322 } | 290 } |
323 | 291 |
324 void DrmNativeDisplayDelegate::OnRemoveGraphicsDevice( | 292 void DrmNativeDisplayDelegate::OnRemoveGraphicsDevice( |
325 const base::FilePath& path) { | 293 const base::FilePath& path) { |
326 proxy_->Send(new OzoneGpuMsg_RemoveGraphicsDevice(path)); | 294 proxy_->Send(new OzoneGpuMsg_RemoveGraphicsDevice(path)); |
327 FOR_EACH_OBSERVER(NativeDisplayObserver, observers_, | 295 FOR_EACH_OBSERVER(NativeDisplayObserver, observers_, |
328 OnConfigurationChanged()); | 296 OnConfigurationChanged()); |
329 } | 297 } |
330 | 298 |
331 void DrmNativeDisplayDelegate::OnChannelEstablished( | 299 void DrmNativeDisplayDelegate::OnChannelEstablished( |
332 int host_id, | 300 int host_id, |
333 scoped_refptr<base::SingleThreadTaskRunner> send_runner, | 301 scoped_refptr<base::SingleThreadTaskRunner> send_runner, |
334 const base::Callback<void(IPC::Message*)>& send_callback) { | 302 const base::Callback<void(IPC::Message*)>& send_callback) { |
335 drm_devices_.clear(); | 303 if (drm_devices_.find(primary_graphics_card_path_) == drm_devices_.end()) { |
336 drm_devices_.insert(primary_graphics_card_path_); | |
337 { | |
338 // First device needs to be treated specially. We need to open this | 304 // First device needs to be treated specially. We need to open this |
339 // synchronously since the GPU process will need it to initialize the | 305 // synchronously since the GPU process will need it to initialize the |
340 // graphics state. | 306 // graphics state. |
341 base::ThreadRestrictions::ScopedAllowIO allow_io; | 307 base::ThreadRestrictions::ScopedAllowIO allow_io; |
342 base::File file = OpenDrmDevice(primary_graphics_card_path_); | 308 scoped_ptr<DrmDeviceHandle> handle(new DrmDeviceHandle()); |
343 if (!file.IsValid()) { | 309 if (!handle->Initialize(primary_graphics_card_path_)) { |
344 LOG(FATAL) << "Failed to open primary graphics card"; | 310 LOG(FATAL) << "Failed to open primary graphics card"; |
345 return; | 311 return; |
346 } | 312 } |
347 OnAddGraphicsDevice(primary_graphics_card_path_, file.Pass()); | 313 drm_devices_.add(primary_graphics_card_path_, handle.Pass()); |
314 OnAddGraphicsDevice(primary_graphics_card_path_); | |
348 } | 315 } |
349 | 316 |
317 for (auto pair : drm_devices_) | |
318 OnAddGraphicsDevice(pair.first); | |
319 | |
350 device_manager_->ScanDevices(this); | 320 device_manager_->ScanDevices(this); |
351 FOR_EACH_OBSERVER(NativeDisplayObserver, observers_, | 321 FOR_EACH_OBSERVER(NativeDisplayObserver, observers_, |
352 OnConfigurationChanged()); | 322 OnConfigurationChanged()); |
353 } | 323 } |
354 | 324 |
355 void DrmNativeDisplayDelegate::OnChannelDestroyed(int host_id) { | 325 void DrmNativeDisplayDelegate::OnChannelDestroyed(int host_id) { |
356 // If the channel got destroyed in the middle of a configuration then just | 326 // If the channel got destroyed in the middle of a configuration then just |
357 // respond with failure. | 327 // respond with failure. |
358 if (!get_displays_callback_.is_null()) { | 328 if (!get_displays_callback_.is_null()) { |
359 base::ThreadTaskRunnerHandle::Get()->PostTask( | 329 base::ThreadTaskRunnerHandle::Get()->PostTask( |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
408 configure_callback_map_.erase(it); | 378 configure_callback_map_.erase(it); |
409 } | 379 } |
410 } | 380 } |
411 | 381 |
412 void DrmNativeDisplayDelegate::RunUpdateDisplaysCallback( | 382 void DrmNativeDisplayDelegate::RunUpdateDisplaysCallback( |
413 const GetDisplaysCallback& callback) const { | 383 const GetDisplaysCallback& callback) const { |
414 callback.Run(displays_.get()); | 384 callback.Run(displays_.get()); |
415 } | 385 } |
416 | 386 |
417 } // namespace ui | 387 } // namespace ui |
OLD | NEW |