| 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_display_host_manager.h" | 5 #include "ui/ozone/platform/drm/host/drm_display_host_manager.h" |
| 6 | 6 |
| 7 #include <fcntl.h> | 7 #include <fcntl.h> |
| 8 #include <stdio.h> | 8 #include <stdio.h> |
| 9 #include <xf86drm.h> | 9 #include <xf86drm.h> |
| 10 | 10 |
| (...skipping 30 matching lines...) Expand all Loading... |
| 41 void OpenDeviceOnWorkerThread( | 41 void OpenDeviceOnWorkerThread( |
| 42 const base::FilePath& path, | 42 const base::FilePath& path, |
| 43 const scoped_refptr<base::TaskRunner>& reply_runner, | 43 const scoped_refptr<base::TaskRunner>& reply_runner, |
| 44 const OnOpenDeviceReplyCallback& callback) { | 44 const OnOpenDeviceReplyCallback& callback) { |
| 45 scoped_ptr<DrmDeviceHandle> handle(new DrmDeviceHandle()); | 45 scoped_ptr<DrmDeviceHandle> handle(new DrmDeviceHandle()); |
| 46 handle->Initialize(path); | 46 handle->Initialize(path); |
| 47 reply_runner->PostTask( | 47 reply_runner->PostTask( |
| 48 FROM_HERE, base::Bind(callback, path, base::Passed(handle.Pass()))); | 48 FROM_HERE, base::Bind(callback, path, base::Passed(handle.Pass()))); |
| 49 } | 49 } |
| 50 | 50 |
| 51 void CloseDeviceOnWorkerThread( | |
| 52 scoped_ptr<DrmDeviceHandle> handle, | |
| 53 const scoped_refptr<base::TaskRunner>& reply_runner, | |
| 54 const base::Closure& callback) { | |
| 55 handle.reset(); | |
| 56 reply_runner->PostTask(FROM_HERE, callback); | |
| 57 } | |
| 58 | |
| 59 base::FilePath GetPrimaryDisplayCardPath() { | 51 base::FilePath GetPrimaryDisplayCardPath() { |
| 60 struct drm_mode_card_res res; | 52 struct drm_mode_card_res res; |
| 61 for (int i = 0; /* end on first card# that does not exist */; i++) { | 53 for (int i = 0; /* end on first card# that does not exist */; i++) { |
| 62 std::string card_path = base::StringPrintf(kDefaultGraphicsCardPattern, i); | 54 std::string card_path = base::StringPrintf(kDefaultGraphicsCardPattern, i); |
| 63 | 55 |
| 64 if (access(card_path.c_str(), F_OK) != 0) | 56 if (access(card_path.c_str(), F_OK) != 0) |
| 65 break; | 57 break; |
| 66 | 58 |
| 67 int fd = open(card_path.c_str(), O_RDWR | O_CLOEXEC); | 59 int fd = open(card_path.c_str(), O_RDWR | O_CLOEXEC); |
| 68 if (fd < 0) { | 60 if (fd < 0) { |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 104 delegate_(nullptr), | 96 delegate_(nullptr), |
| 105 primary_graphics_card_path_(GetPrimaryDisplayCardPath()), | 97 primary_graphics_card_path_(GetPrimaryDisplayCardPath()), |
| 106 has_dummy_display_(false), | 98 has_dummy_display_(false), |
| 107 task_pending_(false), | 99 task_pending_(false), |
| 108 weak_ptr_factory_(this) { | 100 weak_ptr_factory_(this) { |
| 109 { | 101 { |
| 110 // First device needs to be treated specially. We need to open this | 102 // First device needs to be treated specially. We need to open this |
| 111 // synchronously since the GPU process will need it to initialize the | 103 // synchronously since the GPU process will need it to initialize the |
| 112 // graphics state. | 104 // graphics state. |
| 113 base::ThreadRestrictions::ScopedAllowIO allow_io; | 105 base::ThreadRestrictions::ScopedAllowIO allow_io; |
| 114 scoped_ptr<DrmDeviceHandle> handle(new DrmDeviceHandle()); | 106 primary_drm_device_handle_.reset(new DrmDeviceHandle()); |
| 115 if (!handle->Initialize(primary_graphics_card_path_)) { | 107 if (!primary_drm_device_handle_->Initialize(primary_graphics_card_path_)) { |
| 116 LOG(FATAL) << "Failed to open primary graphics card"; | 108 LOG(FATAL) << "Failed to open primary graphics card"; |
| 117 return; | 109 return; |
| 118 } | 110 } |
| 119 drm_devices_.add(primary_graphics_card_path_, handle.Pass()); | 111 drm_devices_.insert(primary_graphics_card_path_); |
| 120 } | 112 } |
| 121 | 113 |
| 122 device_manager_->AddObserver(this); | 114 device_manager_->AddObserver(this); |
| 123 proxy_->RegisterHandler(this); | 115 proxy_->RegisterHandler(this); |
| 124 | 116 |
| 125 DrmDeviceHandle* handle = drm_devices_.get(primary_graphics_card_path_); | |
| 126 ScopedVector<HardwareDisplayControllerInfo> display_infos = | 117 ScopedVector<HardwareDisplayControllerInfo> display_infos = |
| 127 GetAvailableDisplayControllerInfos(handle->fd()); | 118 GetAvailableDisplayControllerInfos(primary_drm_device_handle_->fd()); |
| 128 has_dummy_display_ = !display_infos.empty(); | 119 has_dummy_display_ = !display_infos.empty(); |
| 129 for (size_t i = 0; i < display_infos.size(); ++i) { | 120 for (size_t i = 0; i < display_infos.size(); ++i) { |
| 130 displays_.push_back(new DisplaySnapshotProxy(CreateDisplaySnapshotParams( | 121 displays_.push_back(new DisplaySnapshotProxy(CreateDisplaySnapshotParams( |
| 131 display_infos[i], handle->fd(), i, gfx::Point()))); | 122 display_infos[i], primary_drm_device_handle_->fd(), i, gfx::Point()))); |
| 132 } | 123 } |
| 133 } | 124 } |
| 134 | 125 |
| 135 DrmDisplayHostManager::~DrmDisplayHostManager() { | 126 DrmDisplayHostManager::~DrmDisplayHostManager() { |
| 136 device_manager_->RemoveObserver(this); | 127 device_manager_->RemoveObserver(this); |
| 137 proxy_->UnregisterHandler(this); | 128 proxy_->UnregisterHandler(this); |
| 138 | |
| 139 for (auto it = drm_devices_.begin(); it != drm_devices_.end(); ++it) { | |
| 140 base::WorkerPool::PostTask(FROM_HERE, | |
| 141 base::Bind(&CloseDeviceOnWorkerThread, | |
| 142 base::Passed(drm_devices_.take(it)), | |
| 143 base::ThreadTaskRunnerHandle::Get(), | |
| 144 base::Bind(&base::DoNothing)), | |
| 145 false /* task_is_slow */); | |
| 146 } | |
| 147 } | 129 } |
| 148 | 130 |
| 149 DisplaySnapshot* DrmDisplayHostManager::GetDisplay(int64_t display_id) { | 131 DisplaySnapshot* DrmDisplayHostManager::GetDisplay(int64_t display_id) { |
| 150 auto it = std::find_if(displays_.begin(), displays_.end(), | 132 auto it = std::find_if(displays_.begin(), displays_.end(), |
| 151 FindDisplaySnapshotById(display_id)); | 133 FindDisplaySnapshotById(display_id)); |
| 152 if (it == displays_.end()) | 134 if (it == displays_.end()) |
| 153 return nullptr; | 135 return nullptr; |
| 154 | 136 |
| 155 return *it; | 137 return *it; |
| 156 } | 138 } |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 261 task_pending_ = base::ThreadTaskRunnerHandle::Get()->PostTask( | 243 task_pending_ = base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 262 FROM_HERE, | 244 FROM_HERE, |
| 263 base::Bind(&DrmDisplayHostManager::OnUpdateGraphicsDevice, | 245 base::Bind(&DrmDisplayHostManager::OnUpdateGraphicsDevice, |
| 264 weak_ptr_factory_.GetWeakPtr())); | 246 weak_ptr_factory_.GetWeakPtr())); |
| 265 break; | 247 break; |
| 266 case DeviceEvent::REMOVE: | 248 case DeviceEvent::REMOVE: |
| 267 DCHECK(event.path != primary_graphics_card_path_) | 249 DCHECK(event.path != primary_graphics_card_path_) |
| 268 << "Removing primary graphics card"; | 250 << "Removing primary graphics card"; |
| 269 auto it = drm_devices_.find(event.path); | 251 auto it = drm_devices_.find(event.path); |
| 270 if (it != drm_devices_.end()) { | 252 if (it != drm_devices_.end()) { |
| 271 task_pending_ = base::WorkerPool::PostTask( | 253 task_pending_ = base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 272 FROM_HERE, | 254 FROM_HERE, |
| 273 base::Bind( | 255 base::Bind(&DrmDisplayHostManager::OnRemoveGraphicsDevice, |
| 274 &CloseDeviceOnWorkerThread, | 256 weak_ptr_factory_.GetWeakPtr(), event.path)); |
| 275 base::Passed(drm_devices_.take_and_erase(it)), | 257 drm_devices_.erase(it); |
| 276 base::ThreadTaskRunnerHandle::Get(), | |
| 277 base::Bind(&DrmDisplayHostManager::OnRemoveGraphicsDevice, | |
| 278 weak_ptr_factory_.GetWeakPtr(), event.path)), | |
| 279 false /* task_is_slow */); | |
| 280 return; | |
| 281 } | 258 } |
| 282 break; | 259 break; |
| 283 } | 260 } |
| 284 } | 261 } |
| 285 } | 262 } |
| 286 | 263 |
| 287 void DrmDisplayHostManager::OnAddGraphicsDevice( | 264 void DrmDisplayHostManager::OnAddGraphicsDevice( |
| 288 const base::FilePath& path, | 265 const base::FilePath& path, |
| 289 scoped_ptr<DrmDeviceHandle> handle) { | 266 scoped_ptr<DrmDeviceHandle> handle) { |
| 290 if (handle->IsValid()) { | 267 if (handle->IsValid()) { |
| 291 base::ScopedFD file = handle->Duplicate(); | 268 drm_devices_.insert(path); |
| 292 drm_devices_.add(path, handle.Pass()); | |
| 293 proxy_->Send(new OzoneGpuMsg_AddGraphicsDevice( | 269 proxy_->Send(new OzoneGpuMsg_AddGraphicsDevice( |
| 294 path, base::FileDescriptor(file.Pass()))); | 270 path, base::FileDescriptor(handle->PassFD()))); |
| 295 NotifyDisplayDelegate(); | 271 NotifyDisplayDelegate(); |
| 296 } | 272 } |
| 297 | 273 |
| 298 task_pending_ = false; | 274 task_pending_ = false; |
| 299 ProcessEvent(); | 275 ProcessEvent(); |
| 300 } | 276 } |
| 301 | 277 |
| 302 void DrmDisplayHostManager::OnUpdateGraphicsDevice() { | 278 void DrmDisplayHostManager::OnUpdateGraphicsDevice() { |
| 303 NotifyDisplayDelegate(); | 279 NotifyDisplayDelegate(); |
| 304 task_pending_ = false; | 280 task_pending_ = false; |
| 305 ProcessEvent(); | 281 ProcessEvent(); |
| 306 } | 282 } |
| 307 | 283 |
| 308 void DrmDisplayHostManager::OnRemoveGraphicsDevice(const base::FilePath& path) { | 284 void DrmDisplayHostManager::OnRemoveGraphicsDevice(const base::FilePath& path) { |
| 309 proxy_->Send(new OzoneGpuMsg_RemoveGraphicsDevice(path)); | 285 proxy_->Send(new OzoneGpuMsg_RemoveGraphicsDevice(path)); |
| 310 NotifyDisplayDelegate(); | 286 NotifyDisplayDelegate(); |
| 311 task_pending_ = false; | 287 task_pending_ = false; |
| 312 ProcessEvent(); | 288 ProcessEvent(); |
| 313 } | 289 } |
| 314 | 290 |
| 315 void DrmDisplayHostManager::OnChannelEstablished( | 291 void DrmDisplayHostManager::OnChannelEstablished( |
| 316 int host_id, | 292 int host_id, |
| 317 scoped_refptr<base::SingleThreadTaskRunner> send_runner, | 293 scoped_refptr<base::SingleThreadTaskRunner> send_runner, |
| 318 const base::Callback<void(IPC::Message*)>& send_callback) { | 294 const base::Callback<void(IPC::Message*)>& send_callback) { |
| 319 auto it = drm_devices_.find(primary_graphics_card_path_); | 295 drm_devices_.clear(); |
| 320 DCHECK(it != drm_devices_.end()); | 296 drm_devices_.insert(primary_graphics_card_path_); |
| 297 scoped_ptr<DrmDeviceHandle> handle = primary_drm_device_handle_.Pass(); |
| 298 if (!handle) { |
| 299 base::ThreadRestrictions::ScopedAllowIO allow_io; |
| 300 handle.reset(new DrmDeviceHandle()); |
| 301 if (!handle->Initialize(primary_graphics_card_path_)) |
| 302 LOG(FATAL) << "Failed to open primary graphics card"; |
| 303 } |
| 304 |
| 321 // Send the primary device first since this is used to initialize graphics | 305 // Send the primary device first since this is used to initialize graphics |
| 322 // state. | 306 // state. |
| 323 proxy_->Send(new OzoneGpuMsg_AddGraphicsDevice( | 307 proxy_->Send(new OzoneGpuMsg_AddGraphicsDevice( |
| 324 it->first, base::FileDescriptor(it->second->Duplicate()))); | 308 primary_graphics_card_path_, base::FileDescriptor(handle->PassFD()))); |
| 325 | |
| 326 for (auto pair : drm_devices_) { | |
| 327 if (pair.second->IsValid() && pair.first != primary_graphics_card_path_) { | |
| 328 proxy_->Send(new OzoneGpuMsg_AddGraphicsDevice( | |
| 329 pair.first, base::FileDescriptor(pair.second->Duplicate()))); | |
| 330 } | |
| 331 } | |
| 332 | 309 |
| 333 device_manager_->ScanDevices(this); | 310 device_manager_->ScanDevices(this); |
| 334 NotifyDisplayDelegate(); | 311 NotifyDisplayDelegate(); |
| 335 } | 312 } |
| 336 | 313 |
| 337 void DrmDisplayHostManager::OnChannelDestroyed(int host_id) { | 314 void DrmDisplayHostManager::OnChannelDestroyed(int host_id) { |
| 338 // If the channel got destroyed in the middle of a configuration then just | 315 // If the channel got destroyed in the middle of a configuration then just |
| 339 // respond with failure. | 316 // respond with failure. |
| 340 if (!get_displays_callback_.is_null()) { | 317 if (!get_displays_callback_.is_null()) { |
| 341 base::ThreadTaskRunnerHandle::Get()->PostTask( | 318 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 417 const GetDisplaysCallback& callback) const { | 394 const GetDisplaysCallback& callback) const { |
| 418 callback.Run(displays_.get()); | 395 callback.Run(displays_.get()); |
| 419 } | 396 } |
| 420 | 397 |
| 421 void DrmDisplayHostManager::NotifyDisplayDelegate() const { | 398 void DrmDisplayHostManager::NotifyDisplayDelegate() const { |
| 422 if (delegate_) | 399 if (delegate_) |
| 423 delegate_->OnConfigurationChanged(); | 400 delegate_->OnConfigurationChanged(); |
| 424 } | 401 } |
| 425 | 402 |
| 426 } // namespace ui | 403 } // namespace ui |
| OLD | NEW |