Chromium Code Reviews| Index: ui/ozone/platform/drm/host/drm_native_display_delegate.cc |
| diff --git a/ui/ozone/platform/drm/host/drm_native_display_delegate.cc b/ui/ozone/platform/drm/host/drm_native_display_delegate.cc |
| index 709ade8b59bb1107dbb92c2ec80363b8fdfe5e22..580d264a825fde2e9e9eb5ffa2d5c486892392b1 100644 |
| --- a/ui/ozone/platform/drm/host/drm_native_display_delegate.cc |
| +++ b/ui/ozone/platform/drm/host/drm_native_display_delegate.cc |
| @@ -27,10 +27,13 @@ namespace { |
| typedef base::Callback<void(const base::FilePath&, base::File)> |
| OnOpenDeviceReplyCallback; |
| -void OpenDeviceOnWorkerThread( |
| - const base::FilePath& path, |
| - const scoped_refptr<base::TaskRunner>& reply_runner, |
| - const OnOpenDeviceReplyCallback& callback) { |
| +const char* kDisplayActionString[] = { |
| + "ADD", |
| + "REMOVE", |
| + "CHANGE", |
| +}; |
| + |
| +base::File OpenDrmDevice(const base::FilePath& path) { |
| base::File file(path, base::File::FLAG_OPEN | base::File::FLAG_READ | |
| base::File::FLAG_WRITE); |
| @@ -40,10 +43,21 @@ void OpenDeviceOnWorkerThread( |
| CHECK(!info.is_directory); |
| CHECK(path.DirName() == base::FilePath("/dev/dri")); |
| - if (file.IsValid()) { |
| - reply_runner->PostTask( |
| - FROM_HERE, base::Bind(callback, path, base::Passed(file.Pass()))); |
| + if (!file.IsValid()) { |
| + LOG(ERROR) << "Failed to open " << path.value() << ": " |
| + << base::File::ErrorToString(file.error_details()); |
| } |
| + |
| + return file.Pass(); |
| +} |
| + |
| +void OpenDeviceOnWorkerThread( |
| + const base::FilePath& path, |
| + const scoped_refptr<base::TaskRunner>& reply_runner, |
| + const OnOpenDeviceReplyCallback& callback) { |
| + base::File file = OpenDrmDevice(path); |
| + reply_runner->PostTask(FROM_HERE, |
| + base::Bind(callback, path, base::Passed(file.Pass()))); |
| } |
| class DrmDisplaySnapshotProxy : public DisplaySnapshotProxy { |
| @@ -78,6 +92,7 @@ DrmNativeDisplayDelegate::DrmNativeDisplayDelegate( |
| has_dummy_display_(false), |
| weak_ptr_factory_(this) { |
| proxy_->RegisterHandler(this); |
| + drm_devices_.insert(primary_graphics_card_path); |
| } |
| DrmNativeDisplayDelegate::~DrmNativeDisplayDelegate() { |
| @@ -226,57 +241,93 @@ void DrmNativeDisplayDelegate::OnDeviceEvent(const DeviceEvent& event) { |
| if (event.device_type() != DeviceEvent::DISPLAY) |
| return; |
| - switch (event.action_type()) { |
| - case DeviceEvent::ADD: |
| - VLOG(1) << "Got display added event for " << event.path().value(); |
| - // The default card is a special case since it needs to be opened early on |
| - // the GPU process in order to initialize EGL. If it is opened here as |
| - // well, it will cause a race with opening it in the GPU process and the |
| - // GPU process may fail initialization. |
| - // TODO(dnicoara) Remove this when the media stack does not require super |
| - // early initialization. |
| - if (event.path() == primary_graphics_card_path_) |
| + event_queue_.push(DisplayEvent(event.action_type(), event.path())); |
| + if (event_queue_.size() == 1) |
| + ProcessEvent(); |
| +} |
| + |
| +void DrmNativeDisplayDelegate::ProcessEvent() { |
| + while (!event_queue_.empty()) { |
|
spang
2015/04/27 21:54:33
I think it would be clearer to do:
while (!event_
dnicoara
2015/04/28 14:53:04
Done.
|
| + DisplayEvent event = event_queue_.front(); |
|
spang
2015/04/27 21:54:33
Why can't you pop here?
dnicoara
2015/04/28 14:53:04
The event would act as the |task_pending_| bool.
|
| + VLOG(1) << "Got display event " << kDisplayActionString[event.action_type] |
| + << " for " << event.path.value(); |
| + switch (event.action_type) { |
| + case DeviceEvent::ADD: |
| + if (drm_devices_.find(event.path) == drm_devices_.end()) { |
| + drm_devices_.insert(event.path); |
| + base::WorkerPool::PostTask( |
| + FROM_HERE, |
| + base::Bind( |
| + &OpenDeviceOnWorkerThread, event.path, |
| + base::ThreadTaskRunnerHandle::Get(), |
| + base::Bind(&DrmNativeDisplayDelegate::OnAddGraphicsDevice, |
| + weak_ptr_factory_.GetWeakPtr())), |
| + false /* task_is_slow */); |
| + |
| + return; |
| + } |
| + break; |
| + case DeviceEvent::CHANGE: |
| + base::ThreadTaskRunnerHandle::Get()->PostTask( |
| + FROM_HERE, |
| + base::Bind(&DrmNativeDisplayDelegate::OnUpdateGraphicsDevice, |
| + weak_ptr_factory_.GetWeakPtr())); |
| return; |
| + case DeviceEvent::REMOVE: |
| + DCHECK(event.path != primary_graphics_card_path_) |
| + << "Removing primary graphics card"; |
| + auto it = drm_devices_.find(event.path); |
| + if (it != drm_devices_.end()) { |
| + drm_devices_.erase(it); |
| + base::ThreadTaskRunnerHandle::Get()->PostTask( |
| + FROM_HERE, |
| + base::Bind(&DrmNativeDisplayDelegate::OnRemoveGraphicsDevice, |
| + weak_ptr_factory_.GetWeakPtr(), event.path)); |
| + return; |
| + } |
| + break; |
| + } |
| + |
| + // The event was a no-op, so remove it and process the next one. |
| + event_queue_.pop(); |
| + } |
| +} |
| - base::WorkerPool::PostTask( |
| - FROM_HERE, |
| - base::Bind(&OpenDeviceOnWorkerThread, event.path(), |
| - base::ThreadTaskRunnerHandle::Get(), |
| - base::Bind(&DrmNativeDisplayDelegate::OnNewGraphicsDevice, |
| - weak_ptr_factory_.GetWeakPtr())), |
| - false /* task_is_slow */); |
| - return; |
| - case DeviceEvent::CHANGE: |
| - VLOG(1) << "Got display changed event for " << event.path().value(); |
| - break; |
| - case DeviceEvent::REMOVE: |
| - VLOG(1) << "Got display removed event for " << event.path().value(); |
| - // It shouldn't be possible to remove this device. |
| - DCHECK(primary_graphics_card_path_ != event.path()) |
| - << "Got event to remove primary graphics card " |
| - << event.path().value(); |
| - proxy_->Send(new OzoneGpuMsg_RemoveGraphicsDevice(event.path())); |
| - break; |
| +void DrmNativeDisplayDelegate::OnAddGraphicsDevice(const base::FilePath& path, |
| + base::File file) { |
| + if (file.IsValid()) { |
| + proxy_->Send(new OzoneGpuMsg_AddGraphicsDevice( |
| + path, base::FileDescriptor(file.Pass()))); |
| + FOR_EACH_OBSERVER(NativeDisplayObserver, observers_, |
| + OnConfigurationChanged()); |
| } |
| + event_queue_.pop(); |
| + ProcessEvent(); |
| +} |
| + |
| +void DrmNativeDisplayDelegate::OnUpdateGraphicsDevice() { |
| FOR_EACH_OBSERVER(NativeDisplayObserver, observers_, |
| OnConfigurationChanged()); |
| + event_queue_.pop(); |
| + ProcessEvent(); |
| } |
| -void DrmNativeDisplayDelegate::OnNewGraphicsDevice(const base::FilePath& path, |
| - base::File file) { |
| - DCHECK(file.IsValid()); |
| - proxy_->Send(new OzoneGpuMsg_AddGraphicsDevice( |
| - path, base::FileDescriptor(file.Pass()))); |
| - |
| +void DrmNativeDisplayDelegate::OnRemoveGraphicsDevice( |
| + const base::FilePath& path) { |
| + proxy_->Send(new OzoneGpuMsg_RemoveGraphicsDevice(path)); |
| FOR_EACH_OBSERVER(NativeDisplayObserver, observers_, |
| OnConfigurationChanged()); |
| + event_queue_.pop(); |
| + ProcessEvent(); |
| } |
| void DrmNativeDisplayDelegate::OnChannelEstablished( |
| int host_id, |
| scoped_refptr<base::SingleThreadTaskRunner> send_runner, |
| const base::Callback<void(IPC::Message*)>& send_callback) { |
| + drm_devices_.clear(); |
| + drm_devices_.insert(primary_graphics_card_path_); |
| device_manager_->ScanDevices(this); |
| FOR_EACH_OBSERVER(NativeDisplayObserver, observers_, |
| OnConfigurationChanged()); |