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 |