| 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, base::File file) | 215 DrmDevice::DrmDevice(const base::FilePath& device_path, base::File file) |
| 247 : device_path_(device_path), | 216 : device_path_(device_path), |
| 248 file_(file.Pass()), | 217 file_(file.Pass()), |
| 249 page_flip_manager_(new PageFlipManager()) { | 218 page_flip_manager_(new PageFlipManager()) {} |
| 250 } | |
| 251 | 219 |
| 252 DrmDevice::~DrmDevice() { | 220 DrmDevice::~DrmDevice() {} |
| 253 if (watcher_) | |
| 254 watcher_->Shutdown(); | |
| 255 } | |
| 256 | 221 |
| 257 bool DrmDevice::Initialize(bool use_atomic) { | 222 bool DrmDevice::Initialize(bool use_atomic) { |
| 258 // Ignore devices that cannot perform modesetting. | 223 // Ignore devices that cannot perform modesetting. |
| 259 if (!CanQueryForResources(file_.GetPlatformFile())) { | 224 if (!CanQueryForResources(file_.GetPlatformFile())) { |
| 260 VLOG(2) << "Cannot query for resources for '" << device_path_.value() | 225 VLOG(2) << "Cannot query for resources for '" << device_path_.value() |
| 261 << "'"; | 226 << "'"; |
| 262 return false; | 227 return false; |
| 263 } | 228 } |
| 264 | 229 |
| 265 #if defined(USE_DRM_ATOMIC) | 230 #if defined(USE_DRM_ATOMIC) |
| 266 // Use atomic only if the build, kernel & flags all allow it. | 231 // Use atomic only if the build, kernel & flags all allow it. |
| 267 if (use_atomic && SetCapability(DRM_CLIENT_CAP_ATOMIC, 1)) | 232 if (use_atomic && SetCapability(DRM_CLIENT_CAP_ATOMIC, 1)) |
| 268 plane_manager_.reset(new HardwareDisplayPlaneManagerAtomic()); | 233 plane_manager_.reset(new HardwareDisplayPlaneManagerAtomic()); |
| 269 #endif // defined(USE_DRM_ATOMIC) | 234 #endif // defined(USE_DRM_ATOMIC) |
| 270 | 235 |
| 271 if (!plane_manager_) | 236 if (!plane_manager_) |
| 272 plane_manager_.reset(new HardwareDisplayPlaneManagerLegacy()); | 237 plane_manager_.reset(new HardwareDisplayPlaneManagerLegacy()); |
| 273 if (!plane_manager_->Initialize(this)) { | 238 if (!plane_manager_->Initialize(this)) { |
| 274 LOG(ERROR) << "Failed to initialize the plane manager for " | 239 LOG(ERROR) << "Failed to initialize the plane manager for " |
| 275 << device_path_.value(); | 240 << device_path_.value(); |
| 276 plane_manager_.reset(); | 241 plane_manager_.reset(); |
| 277 return false; | 242 return false; |
| 278 } | 243 } |
| 279 | 244 |
| 245 watcher_.reset( |
| 246 new IOWatcher(file_.GetPlatformFile(), page_flip_manager_.get())); |
| 247 |
| 280 return true; | 248 return true; |
| 281 } | 249 } |
| 282 | 250 |
| 283 void DrmDevice::InitializeTaskRunner( | |
| 284 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) { | |
| 285 DCHECK(!task_runner_); | |
| 286 task_runner_ = task_runner; | |
| 287 watcher_ = | |
| 288 new IOWatcher(file_.GetPlatformFile(), task_runner_, page_flip_manager_); | |
| 289 } | |
| 290 | |
| 291 ScopedDrmCrtcPtr DrmDevice::GetCrtc(uint32_t crtc_id) { | 251 ScopedDrmCrtcPtr DrmDevice::GetCrtc(uint32_t crtc_id) { |
| 292 DCHECK(file_.IsValid()); | 252 DCHECK(file_.IsValid()); |
| 293 return ScopedDrmCrtcPtr(drmModeGetCrtc(file_.GetPlatformFile(), crtc_id)); | 253 return ScopedDrmCrtcPtr(drmModeGetCrtc(file_.GetPlatformFile(), crtc_id)); |
| 294 } | 254 } |
| 295 | 255 |
| 296 bool DrmDevice::SetCrtc(uint32_t crtc_id, | 256 bool DrmDevice::SetCrtc(uint32_t crtc_id, |
| 297 uint32_t framebuffer, | 257 uint32_t framebuffer, |
| 298 std::vector<uint32_t> connectors, | 258 std::vector<uint32_t> connectors, |
| 299 drmModeModeInfo* mode) { | 259 drmModeModeInfo* mode) { |
| 300 DCHECK(file_.IsValid()); | 260 DCHECK(file_.IsValid()); |
| (...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 572 b.push_back(lut[i].b); | 532 b.push_back(lut[i].b); |
| 573 } | 533 } |
| 574 | 534 |
| 575 DCHECK(file_.IsValid()); | 535 DCHECK(file_.IsValid()); |
| 576 TRACE_EVENT0("drm", "DrmDevice::SetGamma"); | 536 TRACE_EVENT0("drm", "DrmDevice::SetGamma"); |
| 577 return (drmModeCrtcSetGamma(file_.GetPlatformFile(), crtc_id, r.size(), &r[0], | 537 return (drmModeCrtcSetGamma(file_.GetPlatformFile(), crtc_id, r.size(), &r[0], |
| 578 &g[0], &b[0]) == 0); | 538 &g[0], &b[0]) == 0); |
| 579 } | 539 } |
| 580 | 540 |
| 581 } // namespace ui | 541 } // namespace ui |
| OLD | NEW |