| 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/gpu/drm_device.h" | 5 #include "ui/ozone/platform/drm/gpu/drm_device.h" |
| 6 | 6 |
| 7 #include <fcntl.h> | 7 #include <fcntl.h> |
| 8 #include <sys/mman.h> | 8 #include <sys/mman.h> |
| 9 #include <unistd.h> | 9 #include <unistd.h> |
| 10 #include <xf86drm.h> | 10 #include <xf86drm.h> |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 107 bool CanQueryForResources(int fd) { | 107 bool CanQueryForResources(int fd) { |
| 108 drm_mode_card_res resources; | 108 drm_mode_card_res resources; |
| 109 memset(&resources, 0, sizeof(resources)); | 109 memset(&resources, 0, sizeof(resources)); |
| 110 // If there is no error getting DRM resources then assume this is a | 110 // If there is no error getting DRM resources then assume this is a |
| 111 // modesetting device. | 111 // modesetting device. |
| 112 return !drmIoctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &resources); | 112 return !drmIoctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &resources); |
| 113 } | 113 } |
| 114 | 114 |
| 115 } // namespace | 115 } // namespace |
| 116 | 116 |
| 117 class DrmDevice::PageFlipManager | 117 class DrmDevice::PageFlipManager { |
| 118 : public base::RefCountedThreadSafe<DrmDevice::PageFlipManager> { | |
| 119 public: | 118 public: |
| 120 PageFlipManager() : next_id_(0) {} | 119 PageFlipManager() : next_id_(0) {} |
| 120 ~PageFlipManager() {} |
| 121 | 121 |
| 122 void OnPageFlip(uint32_t frame, | 122 void OnPageFlip(uint32_t frame, |
| 123 uint32_t seconds, | 123 uint32_t seconds, |
| 124 uint32_t useconds, | 124 uint32_t useconds, |
| 125 uint64_t id) { | 125 uint64_t id) { |
| 126 auto it = | 126 auto it = |
| 127 std::find_if(callbacks_.begin(), callbacks_.end(), FindCallback(id)); | 127 std::find_if(callbacks_.begin(), callbacks_.end(), FindCallback(id)); |
| 128 if (it == callbacks_.end()) { | 128 if (it == callbacks_.end()) { |
| 129 LOG(WARNING) << "Could not find callback for page flip id=" << id; | 129 LOG(WARNING) << "Could not find callback for page flip id=" << id; |
| 130 return; | 130 return; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 142 | 142 |
| 143 uint64_t GetNextId() { return next_id_++; } | 143 uint64_t GetNextId() { return next_id_++; } |
| 144 | 144 |
| 145 void RegisterCallback(uint64_t id, | 145 void RegisterCallback(uint64_t id, |
| 146 uint64_t pending_calls, | 146 uint64_t pending_calls, |
| 147 const DrmDevice::PageFlipCallback& callback) { | 147 const DrmDevice::PageFlipCallback& callback) { |
| 148 callbacks_.push_back({id, pending_calls, callback}); | 148 callbacks_.push_back({id, pending_calls, callback}); |
| 149 } | 149 } |
| 150 | 150 |
| 151 private: | 151 private: |
| 152 friend class base::RefCountedThreadSafe<DrmDevice::PageFlipManager>; | |
| 153 ~PageFlipManager() {} | |
| 154 | |
| 155 struct PageFlip { | 152 struct PageFlip { |
| 156 uint64_t id; | 153 uint64_t id; |
| 157 uint32_t pending_calls; | 154 uint32_t pending_calls; |
| 158 DrmDevice::PageFlipCallback callback; | 155 DrmDevice::PageFlipCallback callback; |
| 159 }; | 156 }; |
| 160 | 157 |
| 161 struct FindCallback { | 158 struct FindCallback { |
| 162 FindCallback(uint64_t id) : id(id) {} | 159 FindCallback(uint64_t id) : id(id) {} |
| 163 | 160 |
| 164 bool operator()(const PageFlip& flip) const { return flip.id == id; } | 161 bool operator()(const PageFlip& flip) const { return flip.id == id; } |
| 165 | 162 |
| 166 uint64_t id; | 163 uint64_t id; |
| 167 }; | 164 }; |
| 168 | 165 |
| 169 uint64_t next_id_; | 166 uint64_t next_id_; |
| 170 | 167 |
| 171 std::vector<PageFlip> callbacks_; | 168 std::vector<PageFlip> callbacks_; |
| 172 | 169 |
| 173 DISALLOW_COPY_AND_ASSIGN(PageFlipManager); | 170 DISALLOW_COPY_AND_ASSIGN(PageFlipManager); |
| 174 }; | 171 }; |
| 175 | 172 |
| 176 class DrmDevice::IOWatcher | 173 class DrmDevice::IOWatcher : public base::MessagePumpLibevent::Watcher { |
| 177 : public base::RefCountedThreadSafe<DrmDevice::IOWatcher>, | |
| 178 public base::MessagePumpLibevent::Watcher { | |
| 179 public: | 174 public: |
| 180 IOWatcher(int fd, | 175 IOWatcher(int fd, DrmDevice::PageFlipManager* page_flip_manager) |
| 181 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner, | 176 : page_flip_manager_(page_flip_manager), fd_(fd) { |
| 182 const scoped_refptr<DrmDevice::PageFlipManager>& page_flip_manager) | 177 Register(); |
| 183 : main_task_runner_(base::ThreadTaskRunnerHandle::Get()), | |
| 184 io_task_runner_(io_task_runner), | |
| 185 page_flip_manager_(page_flip_manager), | |
| 186 fd_(fd) { | |
| 187 io_task_runner_->PostTask(FROM_HERE, | |
| 188 base::Bind(&IOWatcher::RegisterOnIO, this)); | |
| 189 } | 178 } |
| 190 | 179 |
| 191 void Shutdown() { | 180 ~IOWatcher() override { Unregister(); } |
| 192 io_task_runner_->PostTask(FROM_HERE, | |
| 193 base::Bind(&IOWatcher::UnregisterOnIO, this)); | |
| 194 } | |
| 195 | 181 |
| 196 private: | 182 private: |
| 197 friend class base::RefCountedThreadSafe<IOWatcher>; | 183 void Register() { |
| 198 | |
| 199 ~IOWatcher() override {} | |
| 200 | |
| 201 void RegisterOnIO() { | |
| 202 DCHECK(base::MessageLoopForIO::IsCurrent()); | 184 DCHECK(base::MessageLoopForIO::IsCurrent()); |
| 203 base::MessageLoopForIO::current()->WatchFileDescriptor( | 185 base::MessageLoopForIO::current()->WatchFileDescriptor( |
| 204 fd_, true, base::MessageLoopForIO::WATCH_READ, &controller_, this); | 186 fd_, true, base::MessageLoopForIO::WATCH_READ, &controller_, this); |
| 205 } | 187 } |
| 206 | 188 |
| 207 void UnregisterOnIO() { | 189 void Unregister() { |
| 208 DCHECK(base::MessageLoopForIO::IsCurrent()); | 190 DCHECK(base::MessageLoopForIO::IsCurrent()); |
| 209 controller_.StopWatchingFileDescriptor(); | 191 controller_.StopWatchingFileDescriptor(); |
| 210 } | 192 } |
| 211 | 193 |
| 212 void OnPageFlipOnIO(uint32_t frame, | |
| 213 uint32_t seconds, | |
| 214 uint32_t useconds, | |
| 215 uint64_t id) { | |
| 216 main_task_runner_->PostTask( | |
| 217 FROM_HERE, | |
| 218 base::Bind(&DrmDevice::PageFlipManager::OnPageFlip, page_flip_manager_, | |
| 219 frame, seconds, useconds, id)); | |
| 220 } | |
| 221 | |
| 222 // base::MessagePumpLibevent::Watcher overrides: | 194 // base::MessagePumpLibevent::Watcher overrides: |
| 223 void OnFileCanReadWithoutBlocking(int fd) override { | 195 void OnFileCanReadWithoutBlocking(int fd) override { |
| 224 DCHECK(base::MessageLoopForIO::IsCurrent()); | 196 DCHECK(base::MessageLoopForIO::IsCurrent()); |
| 225 TRACE_EVENT1("drm", "OnDrmEvent", "socket", fd); | 197 TRACE_EVENT1("drm", "OnDrmEvent", "socket", fd); |
| 226 | 198 |
| 227 if (!ProcessDrmEvent( | 199 if (!ProcessDrmEvent(fd, base::Bind(&DrmDevice::PageFlipManager::OnPageFlip, |
| 228 fd, base::Bind(&DrmDevice::IOWatcher::OnPageFlipOnIO, this))) | 200 base::Unretained(page_flip_manager_)))) |
| 229 UnregisterOnIO(); | 201 Unregister(); |
| 230 } | 202 } |
| 231 | 203 |
| 232 void OnFileCanWriteWithoutBlocking(int fd) override { NOTREACHED(); } | 204 void OnFileCanWriteWithoutBlocking(int fd) override { NOTREACHED(); } |
| 233 | 205 |
| 234 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_; | 206 DrmDevice::PageFlipManager* page_flip_manager_; |
| 235 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_; | |
| 236 | |
| 237 scoped_refptr<DrmDevice::PageFlipManager> page_flip_manager_; | |
| 238 | 207 |
| 239 base::MessagePumpLibevent::FileDescriptorWatcher controller_; | 208 base::MessagePumpLibevent::FileDescriptorWatcher controller_; |
| 240 | 209 |
| 241 int fd_; | 210 int fd_; |
| 242 | 211 |
| 243 DISALLOW_COPY_AND_ASSIGN(IOWatcher); | 212 DISALLOW_COPY_AND_ASSIGN(IOWatcher); |
| 244 }; | 213 }; |
| 245 | 214 |
| 246 DrmDevice::DrmDevice(const base::FilePath& device_path, | 215 DrmDevice::DrmDevice(const base::FilePath& device_path, |
| 247 base::File file, | 216 base::File file, |
| 248 bool is_primary_device) | 217 bool is_primary_device) |
| 249 : device_path_(device_path), | 218 : device_path_(device_path), |
| 250 file_(file.Pass()), | 219 file_(file.Pass()), |
| 251 page_flip_manager_(new PageFlipManager()), | 220 page_flip_manager_(new PageFlipManager()), |
| 252 is_primary_device_(is_primary_device) {} | 221 is_primary_device_(is_primary_device) {} |
| 253 | 222 |
| 254 DrmDevice::~DrmDevice() { | 223 DrmDevice::~DrmDevice() {} |
| 255 if (watcher_) | |
| 256 watcher_->Shutdown(); | |
| 257 } | |
| 258 | 224 |
| 259 bool DrmDevice::Initialize(bool use_atomic) { | 225 bool DrmDevice::Initialize(bool use_atomic) { |
| 260 // Ignore devices that cannot perform modesetting. | 226 // Ignore devices that cannot perform modesetting. |
| 261 if (!CanQueryForResources(file_.GetPlatformFile())) { | 227 if (!CanQueryForResources(file_.GetPlatformFile())) { |
| 262 VLOG(2) << "Cannot query for resources for '" << device_path_.value() | 228 VLOG(2) << "Cannot query for resources for '" << device_path_.value() |
| 263 << "'"; | 229 << "'"; |
| 264 return false; | 230 return false; |
| 265 } | 231 } |
| 266 | 232 |
| 267 #if defined(USE_DRM_ATOMIC) | 233 #if defined(USE_DRM_ATOMIC) |
| 268 // Use atomic only if the build, kernel & flags all allow it. | 234 // Use atomic only if the build, kernel & flags all allow it. |
| 269 if (use_atomic && SetCapability(DRM_CLIENT_CAP_ATOMIC, 1)) | 235 if (use_atomic && SetCapability(DRM_CLIENT_CAP_ATOMIC, 1)) |
| 270 plane_manager_.reset(new HardwareDisplayPlaneManagerAtomic()); | 236 plane_manager_.reset(new HardwareDisplayPlaneManagerAtomic()); |
| 271 #endif // defined(USE_DRM_ATOMIC) | 237 #endif // defined(USE_DRM_ATOMIC) |
| 272 | 238 |
| 273 if (!plane_manager_) | 239 if (!plane_manager_) |
| 274 plane_manager_.reset(new HardwareDisplayPlaneManagerLegacy()); | 240 plane_manager_.reset(new HardwareDisplayPlaneManagerLegacy()); |
| 275 if (!plane_manager_->Initialize(this)) { | 241 if (!plane_manager_->Initialize(this)) { |
| 276 LOG(ERROR) << "Failed to initialize the plane manager for " | 242 LOG(ERROR) << "Failed to initialize the plane manager for " |
| 277 << device_path_.value(); | 243 << device_path_.value(); |
| 278 plane_manager_.reset(); | 244 plane_manager_.reset(); |
| 279 return false; | 245 return false; |
| 280 } | 246 } |
| 281 | 247 |
| 248 watcher_.reset( |
| 249 new IOWatcher(file_.GetPlatformFile(), page_flip_manager_.get())); |
| 250 |
| 282 return true; | 251 return true; |
| 283 } | 252 } |
| 284 | 253 |
| 285 void DrmDevice::InitializeTaskRunner( | |
| 286 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) { | |
| 287 DCHECK(!task_runner_); | |
| 288 task_runner_ = task_runner; | |
| 289 watcher_ = | |
| 290 new IOWatcher(file_.GetPlatformFile(), task_runner_, page_flip_manager_); | |
| 291 } | |
| 292 | |
| 293 ScopedDrmCrtcPtr DrmDevice::GetCrtc(uint32_t crtc_id) { | 254 ScopedDrmCrtcPtr DrmDevice::GetCrtc(uint32_t crtc_id) { |
| 294 DCHECK(file_.IsValid()); | 255 DCHECK(file_.IsValid()); |
| 295 return ScopedDrmCrtcPtr(drmModeGetCrtc(file_.GetPlatformFile(), crtc_id)); | 256 return ScopedDrmCrtcPtr(drmModeGetCrtc(file_.GetPlatformFile(), crtc_id)); |
| 296 } | 257 } |
| 297 | 258 |
| 298 bool DrmDevice::SetCrtc(uint32_t crtc_id, | 259 bool DrmDevice::SetCrtc(uint32_t crtc_id, |
| 299 uint32_t framebuffer, | 260 uint32_t framebuffer, |
| 300 std::vector<uint32_t> connectors, | 261 std::vector<uint32_t> connectors, |
| 301 drmModeModeInfo* mode) { | 262 drmModeModeInfo* mode) { |
| 302 DCHECK(file_.IsValid()); | 263 DCHECK(file_.IsValid()); |
| (...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 574 b.push_back(lut[i].b); | 535 b.push_back(lut[i].b); |
| 575 } | 536 } |
| 576 | 537 |
| 577 DCHECK(file_.IsValid()); | 538 DCHECK(file_.IsValid()); |
| 578 TRACE_EVENT0("drm", "DrmDevice::SetGamma"); | 539 TRACE_EVENT0("drm", "DrmDevice::SetGamma"); |
| 579 return (drmModeCrtcSetGamma(file_.GetPlatformFile(), crtc_id, r.size(), &r[0], | 540 return (drmModeCrtcSetGamma(file_.GetPlatformFile(), crtc_id, r.size(), &r[0], |
| 580 &g[0], &b[0]) == 0); | 541 &g[0], &b[0]) == 0); |
| 581 } | 542 } |
| 582 | 543 |
| 583 } // namespace ui | 544 } // namespace ui |
| OLD | NEW |