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

Side by Side Diff: ui/ozone/platform/drm/host/drm_native_display_delegate.cc

Issue 1064453003: [4/4][Ozone-Drm] Keep track of DRM devices in browser process (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@change-page-flip-tracking
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/host/drm_native_display_delegate.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/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 "base/threading/worker_pool.h" 12 #include "base/threading/worker_pool.h"
14 #include "ui/display/types/display_snapshot.h" 13 #include "ui/display/types/display_snapshot.h"
15 #include "ui/display/types/native_display_observer.h" 14 #include "ui/display/types/native_display_observer.h"
16 #include "ui/events/ozone/device/device_event.h" 15 #include "ui/events/ozone/device/device_event.h"
17 #include "ui/events/ozone/device/device_manager.h" 16 #include "ui/events/ozone/device/device_manager.h"
18 #include "ui/ozone/common/display_snapshot_proxy.h" 17 #include "ui/ozone/common/display_snapshot_proxy.h"
19 #include "ui/ozone/common/display_util.h" 18 #include "ui/ozone/common/display_util.h"
20 #include "ui/ozone/common/gpu/ozone_gpu_messages.h" 19 #include "ui/ozone/common/gpu/ozone_gpu_messages.h"
21 #include "ui/ozone/platform/drm/host/display_manager.h" 20 #include "ui/ozone/platform/drm/host/display_manager.h"
21 #include "ui/ozone/platform/drm/host/drm_device_handle.h"
22 #include "ui/ozone/platform/drm/host/drm_gpu_platform_support_host.h" 22 #include "ui/ozone/platform/drm/host/drm_gpu_platform_support_host.h"
23 23
24 namespace ui { 24 namespace ui {
25 25
26 namespace { 26 namespace {
27 27
28 typedef base::Callback<void(const base::FilePath&, base::File)> 28 typedef base::Callback<void(const base::FilePath&, scoped_ptr<DrmDeviceHandle>)>
29 OnOpenDeviceReplyCallback; 29 OnOpenDeviceReplyCallback;
30 30
31 const char* kDisplayActionString[] = { 31 const char* kDisplayActionString[] = {
32 "ADD", 32 "ADD",
33 "REMOVE", 33 "REMOVE",
34 "CHANGE", 34 "CHANGE",
35 }; 35 };
36 36
37 bool Authenticate(int fd) {
38 drm_magic_t magic = 0;
39 // We need to make sure the DRM device has enough privilege. Use the DRM
40 // authentication logic to figure out if the device has enough permissions.
41 return !drmGetMagic(fd, &magic) && !drmAuthMagic(fd, magic);
42 }
43
44 base::File OpenDrmDevice(const base::FilePath& path) {
45 base::File file;
46 bool print_warning = true;
47 while (true) {
48 file = base::File(path, base::File::FLAG_OPEN | base::File::FLAG_READ |
49 base::File::FLAG_WRITE);
50
51 base::File::Info info;
52 file.GetInfo(&info);
53
54 CHECK(!info.is_directory);
55 CHECK(path.DirName() == base::FilePath("/dev/dri"));
56
57 if (!file.IsValid()) {
58 LOG(ERROR) << "Failed to open " << path.value() << ": "
59 << base::File::ErrorToString(file.error_details());
60 return file.Pass();
61 }
62
63 if (Authenticate(file.GetPlatformFile()))
64 break;
65
66 LOG_IF(WARNING, print_warning) << "Failed to authenticate " << path.value();
67
68 print_warning = false;
69 usleep(100000);
70 }
71
72 VLOG(1) << "Succeeded authenticating " << path.value();
73 return file.Pass();
74 }
75
76 void OpenDeviceOnWorkerThread( 37 void OpenDeviceOnWorkerThread(
77 const base::FilePath& path, 38 const base::FilePath& path,
78 const scoped_refptr<base::TaskRunner>& reply_runner, 39 const scoped_refptr<base::TaskRunner>& reply_runner,
79 const OnOpenDeviceReplyCallback& callback) { 40 const OnOpenDeviceReplyCallback& callback) {
80 base::File file = OpenDrmDevice(path); 41 scoped_ptr<DrmDeviceHandle> handle(new DrmDeviceHandle());
81 reply_runner->PostTask(FROM_HERE, 42 handle->Initialize(path);
82 base::Bind(callback, path, base::Passed(file.Pass()))); 43 reply_runner->PostTask(
44 FROM_HERE, base::Bind(callback, path, base::Passed(handle.Pass())));
45 }
46
47 void CloseDeviceOnWorkerThread(
48 scoped_ptr<DrmDeviceHandle> handle,
49 const scoped_refptr<base::TaskRunner>& reply_runner,
50 const base::Closure& callback) {
51 handle.reset();
52 reply_runner->PostTask(FROM_HERE, callback);
83 } 53 }
84 54
85 class DrmDisplaySnapshotProxy : public DisplaySnapshotProxy { 55 class DrmDisplaySnapshotProxy : public DisplaySnapshotProxy {
86 public: 56 public:
87 DrmDisplaySnapshotProxy(const DisplaySnapshot_Params& params, 57 DrmDisplaySnapshotProxy(const DisplaySnapshot_Params& params,
88 DisplayManager* display_manager) 58 DisplayManager* display_manager)
89 : DisplaySnapshotProxy(params), display_manager_(display_manager) { 59 : DisplaySnapshotProxy(params), display_manager_(display_manager) {
90 display_manager_->RegisterDisplay(this); 60 display_manager_->RegisterDisplay(this);
91 } 61 }
92 62
(...skipping 14 matching lines...) Expand all
107 DeviceManager* device_manager, 77 DeviceManager* device_manager,
108 DisplayManager* display_manager, 78 DisplayManager* display_manager,
109 const base::FilePath& primary_graphics_card_path) 79 const base::FilePath& primary_graphics_card_path)
110 : proxy_(proxy), 80 : proxy_(proxy),
111 device_manager_(device_manager), 81 device_manager_(device_manager),
112 display_manager_(display_manager), 82 display_manager_(display_manager),
113 primary_graphics_card_path_(primary_graphics_card_path), 83 primary_graphics_card_path_(primary_graphics_card_path),
114 has_dummy_display_(false), 84 has_dummy_display_(false),
115 weak_ptr_factory_(this) { 85 weak_ptr_factory_(this) {
116 proxy_->RegisterHandler(this); 86 proxy_->RegisterHandler(this);
117 drm_devices_.insert(primary_graphics_card_path);
118 } 87 }
119 88
120 DrmNativeDisplayDelegate::~DrmNativeDisplayDelegate() { 89 DrmNativeDisplayDelegate::~DrmNativeDisplayDelegate() {
121 device_manager_->RemoveObserver(this); 90 device_manager_->RemoveObserver(this);
122 proxy_->UnregisterHandler(this); 91 proxy_->UnregisterHandler(this);
92
93 for (auto it = drm_devices_.begin(); it != drm_devices_.end(); ++it) {
dnicoara 2015/04/28 16:26:15 Added async close of the DRM handles.
94 base::WorkerPool::PostTask(FROM_HERE,
95 base::Bind(&CloseDeviceOnWorkerThread,
96 base::Passed(drm_devices_.take(it)),
97 base::ThreadTaskRunnerHandle::Get(),
98 base::Bind(&base::DoNothing)),
99 false /* task_is_slow */);
100 }
123 } 101 }
124 102
125 void DrmNativeDisplayDelegate::Initialize() { 103 void DrmNativeDisplayDelegate::Initialize() {
104 {
105 // First device needs to be treated specially. We need to open this
106 // synchronously since the GPU process will need it to initialize the
107 // graphics state.
108 base::ThreadRestrictions::ScopedAllowIO allow_io;
109 scoped_ptr<DrmDeviceHandle> handle(new DrmDeviceHandle());
110 if (!handle->Initialize(primary_graphics_card_path_)) {
111 LOG(FATAL) << "Failed to open primary graphics card";
112 return;
113 }
114 drm_devices_.add(primary_graphics_card_path_, handle.Pass());
115 }
116
126 device_manager_->AddObserver(this); 117 device_manager_->AddObserver(this);
127 device_manager_->ScanDevices(this); 118 device_manager_->ScanDevices(this);
128 119
129 if (!displays_.empty()) 120 if (!displays_.empty())
130 return; 121 return;
131 DisplaySnapshot_Params params; 122 DisplaySnapshot_Params params;
132 bool success = false; 123 bool success = false;
133 { 124 {
134 // The file generated by frecon that contains EDID for the 1st display. 125 // The file generated by frecon that contains EDID for the 1st display.
135 const base::FilePath kEDIDFile("/tmp/display_info.bin"); 126 const base::FilePath kEDIDFile("/tmp/display_info.bin");
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
269 } 260 }
270 261
271 void DrmNativeDisplayDelegate::ProcessEvent() { 262 void DrmNativeDisplayDelegate::ProcessEvent() {
272 while (!event_queue_.empty()) { 263 while (!event_queue_.empty()) {
273 DisplayEvent event = event_queue_.front(); 264 DisplayEvent event = event_queue_.front();
274 VLOG(1) << "Got display event " << kDisplayActionString[event.action_type] 265 VLOG(1) << "Got display event " << kDisplayActionString[event.action_type]
275 << " for " << event.path.value(); 266 << " for " << event.path.value();
276 switch (event.action_type) { 267 switch (event.action_type) {
277 case DeviceEvent::ADD: 268 case DeviceEvent::ADD:
278 if (drm_devices_.find(event.path) == drm_devices_.end()) { 269 if (drm_devices_.find(event.path) == drm_devices_.end()) {
279 drm_devices_.insert(event.path);
280 base::WorkerPool::PostTask( 270 base::WorkerPool::PostTask(
281 FROM_HERE, 271 FROM_HERE,
282 base::Bind( 272 base::Bind(
283 &OpenDeviceOnWorkerThread, event.path, 273 &OpenDeviceOnWorkerThread, event.path,
284 base::ThreadTaskRunnerHandle::Get(), 274 base::ThreadTaskRunnerHandle::Get(),
285 base::Bind(&DrmNativeDisplayDelegate::OnAddGraphicsDevice, 275 base::Bind(&DrmNativeDisplayDelegate::OnAddGraphicsDevice,
286 weak_ptr_factory_.GetWeakPtr())), 276 weak_ptr_factory_.GetWeakPtr())),
287 false /* task_is_slow */); 277 false /* task_is_slow */);
288 278
289 return; 279 return;
290 } 280 }
291 break; 281 break;
292 case DeviceEvent::CHANGE: 282 case DeviceEvent::CHANGE:
293 base::ThreadTaskRunnerHandle::Get()->PostTask( 283 base::ThreadTaskRunnerHandle::Get()->PostTask(
294 FROM_HERE, 284 FROM_HERE,
295 base::Bind(&DrmNativeDisplayDelegate::OnUpdateGraphicsDevice, 285 base::Bind(&DrmNativeDisplayDelegate::OnUpdateGraphicsDevice,
296 weak_ptr_factory_.GetWeakPtr())); 286 weak_ptr_factory_.GetWeakPtr()));
297 return; 287 return;
298 case DeviceEvent::REMOVE: 288 case DeviceEvent::REMOVE:
299 DCHECK(event.path != primary_graphics_card_path_) 289 DCHECK(event.path != primary_graphics_card_path_)
300 << "Removing primary graphics card"; 290 << "Removing primary graphics card";
301 auto it = drm_devices_.find(event.path); 291 auto it = drm_devices_.find(event.path);
302 if (it != drm_devices_.end()) { 292 if (it != drm_devices_.end()) {
303 drm_devices_.erase(it); 293 base::WorkerPool::PostTask(
304 base::ThreadTaskRunnerHandle::Get()->PostTask(
305 FROM_HERE, 294 FROM_HERE,
306 base::Bind(&DrmNativeDisplayDelegate::OnRemoveGraphicsDevice, 295 base::Bind(
307 weak_ptr_factory_.GetWeakPtr(), event.path)); 296 &CloseDeviceOnWorkerThread,
297 base::Passed(drm_devices_.take_and_erase(it)),
298 base::ThreadTaskRunnerHandle::Get(),
299 base::Bind(&DrmNativeDisplayDelegate::OnRemoveGraphicsDevice,
300 weak_ptr_factory_.GetWeakPtr(), event.path)),
301 false /* task_is_slow */);
308 return; 302 return;
309 } 303 }
310 break; 304 break;
311 } 305 }
312 306
313 // The event was a no-op, so remove it and process the next one. 307 // The event was a no-op, so remove it and process the next one.
314 event_queue_.pop(); 308 event_queue_.pop();
315 } 309 }
316 } 310 }
317 311
318 void DrmNativeDisplayDelegate::OnAddGraphicsDevice(const base::FilePath& path, 312 void DrmNativeDisplayDelegate::OnAddGraphicsDevice(
319 base::File file) { 313 const base::FilePath& path,
320 if (file.IsValid()) { 314 scoped_ptr<DrmDeviceHandle> handle) {
315 if (handle->IsValid()) {
316 base::ScopedFD file = handle->Duplicate();
317 drm_devices_.add(path, handle.Pass());
321 proxy_->Send(new OzoneGpuMsg_AddGraphicsDevice( 318 proxy_->Send(new OzoneGpuMsg_AddGraphicsDevice(
322 path, base::FileDescriptor(file.Pass()))); 319 path, base::FileDescriptor(file.Pass())));
323 FOR_EACH_OBSERVER(NativeDisplayObserver, observers_, 320 FOR_EACH_OBSERVER(NativeDisplayObserver, observers_,
324 OnConfigurationChanged()); 321 OnConfigurationChanged());
325 } 322 }
326 323
327 event_queue_.pop(); 324 event_queue_.pop();
328 ProcessEvent(); 325 ProcessEvent();
329 } 326 }
330 327
(...skipping 10 matching lines...) Expand all
341 FOR_EACH_OBSERVER(NativeDisplayObserver, observers_, 338 FOR_EACH_OBSERVER(NativeDisplayObserver, observers_,
342 OnConfigurationChanged()); 339 OnConfigurationChanged());
343 event_queue_.pop(); 340 event_queue_.pop();
344 ProcessEvent(); 341 ProcessEvent();
345 } 342 }
346 343
347 void DrmNativeDisplayDelegate::OnChannelEstablished( 344 void DrmNativeDisplayDelegate::OnChannelEstablished(
348 int host_id, 345 int host_id,
349 scoped_refptr<base::SingleThreadTaskRunner> send_runner, 346 scoped_refptr<base::SingleThreadTaskRunner> send_runner,
350 const base::Callback<void(IPC::Message*)>& send_callback) { 347 const base::Callback<void(IPC::Message*)>& send_callback) {
351 drm_devices_.clear(); 348 auto it = drm_devices_.find(primary_graphics_card_path_);
352 drm_devices_.insert(primary_graphics_card_path_); 349 DCHECK(it != drm_devices_.end());
353 { 350 // Send the primary device first since this is used to initialize graphics
354 // First device needs to be treated specially. We need to open this 351 // state.
355 // synchronously since the GPU process will need it to initialize the 352 proxy_->Send(new OzoneGpuMsg_AddGraphicsDevice(
356 // graphics state. 353 it->first, base::FileDescriptor(it->second->Duplicate())));
357 base::ThreadRestrictions::ScopedAllowIO allow_io; 354
358 base::File file = OpenDrmDevice(primary_graphics_card_path_); 355 for (auto pair : drm_devices_) {
359 if (!file.IsValid()) { 356 if (pair.second->IsValid()) {
360 LOG(FATAL) << "Failed to open primary graphics card"; 357 proxy_->Send(new OzoneGpuMsg_AddGraphicsDevice(
361 return; 358 pair.first, base::FileDescriptor(pair.second->Duplicate())));
362 } 359 }
363 proxy_->Send(new OzoneGpuMsg_AddGraphicsDevice(
364 primary_graphics_card_path_, base::FileDescriptor(file.Pass())));
365 } 360 }
366 361
367 device_manager_->ScanDevices(this); 362 device_manager_->ScanDevices(this);
368 FOR_EACH_OBSERVER(NativeDisplayObserver, observers_, 363 FOR_EACH_OBSERVER(NativeDisplayObserver, observers_,
369 OnConfigurationChanged()); 364 OnConfigurationChanged());
370 } 365 }
371 366
372 void DrmNativeDisplayDelegate::OnChannelDestroyed(int host_id) { 367 void DrmNativeDisplayDelegate::OnChannelDestroyed(int host_id) {
373 // If the channel got destroyed in the middle of a configuration then just 368 // If the channel got destroyed in the middle of a configuration then just
374 // respond with failure. 369 // respond with failure.
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
448 set_hdcp_state_callback_map_.erase(it); 443 set_hdcp_state_callback_map_.erase(it);
449 } 444 }
450 } 445 }
451 446
452 void DrmNativeDisplayDelegate::RunUpdateDisplaysCallback( 447 void DrmNativeDisplayDelegate::RunUpdateDisplaysCallback(
453 const GetDisplaysCallback& callback) const { 448 const GetDisplaysCallback& callback) const {
454 callback.Run(displays_.get()); 449 callback.Run(displays_.get());
455 } 450 }
456 451
457 } // namespace ui 452 } // namespace ui
OLDNEW
« no previous file with comments | « ui/ozone/platform/drm/host/drm_native_display_delegate.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698