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 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
567 b.push_back(lut[i].b); | 527 b.push_back(lut[i].b); |
568 } | 528 } |
569 | 529 |
570 DCHECK(file_.IsValid()); | 530 DCHECK(file_.IsValid()); |
571 TRACE_EVENT0("drm", "DrmDevice::SetGamma"); | 531 TRACE_EVENT0("drm", "DrmDevice::SetGamma"); |
572 return (drmModeCrtcSetGamma(file_.GetPlatformFile(), crtc_id, r.size(), &r[0], | 532 return (drmModeCrtcSetGamma(file_.GetPlatformFile(), crtc_id, r.size(), &r[0], |
573 &g[0], &b[0]) == 0); | 533 &g[0], &b[0]) == 0); |
574 } | 534 } |
575 | 535 |
576 } // namespace ui | 536 } // namespace ui |
OLD | NEW |