Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(361)

Side by Side Diff: ui/ozone/platform/drm/gpu/drm_device.cc

Issue 1311043016: Switch DRM platform to using a separate thread (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@mv-drm-calls-on-thread2
Patch Set: Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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>
11 #include <xf86drmMode.h> 11 #include <xf86drmMode.h>
12 12
13 #include "base/logging.h" 13 #include "base/logging.h"
14 #include "base/message_loop/message_loop.h" 14 #include "base/message_loop/message_loop.h"
15 #include "base/stl_util.h"
16 #include "base/synchronization/waitable_event.h"
17 #include "base/task_runner.h" 15 #include "base/task_runner.h"
18 #include "base/thread_task_runner_handle.h" 16 #include "base/thread_task_runner_handle.h"
19 #include "base/trace_event/trace_event.h" 17 #include "base/trace_event/trace_event.h"
20 #include "third_party/skia/include/core/SkImageInfo.h" 18 #include "third_party/skia/include/core/SkImageInfo.h"
21 #include "ui/display/types/gamma_ramp_rgb_entry.h" 19 #include "ui/display/types/gamma_ramp_rgb_entry.h"
22 #include "ui/ozone/platform/drm/common/drm_util.h" 20 #include "ui/ozone/platform/drm/common/drm_util.h"
23 #include "ui/ozone/platform/drm/gpu/hardware_display_plane_manager_legacy.h" 21 #include "ui/ozone/platform/drm/gpu/hardware_display_plane_manager_legacy.h"
24 22
25 #if defined(USE_DRM_ATOMIC) 23 #if defined(USE_DRM_ATOMIC)
26 #include "ui/ozone/platform/drm/gpu/hardware_display_plane_manager_atomic.h" 24 #include "ui/ozone/platform/drm/gpu/hardware_display_plane_manager_atomic.h"
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
108 bool CanQueryForResources(int fd) { 106 bool CanQueryForResources(int fd) {
109 drm_mode_card_res resources; 107 drm_mode_card_res resources;
110 memset(&resources, 0, sizeof(resources)); 108 memset(&resources, 0, sizeof(resources));
111 // If there is no error getting DRM resources then assume this is a 109 // If there is no error getting DRM resources then assume this is a
112 // modesetting device. 110 // modesetting device.
113 return !drmIoctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &resources); 111 return !drmIoctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &resources);
114 } 112 }
115 113
116 } // namespace 114 } // namespace
117 115
118 class DrmDevice::PageFlipManager 116 class DrmDevice::PageFlipManager {
119 : public base::RefCountedThreadSafe<DrmDevice::PageFlipManager> {
120 public: 117 public:
121 PageFlipManager() : next_id_(0) {} 118 PageFlipManager() : next_id_(0) {}
119 ~PageFlipManager() {}
122 120
123 void OnPageFlip(uint32_t frame, 121 void OnPageFlip(uint32_t frame,
124 uint32_t seconds, 122 uint32_t seconds,
125 uint32_t useconds, 123 uint32_t useconds,
126 uint64_t id) { 124 uint64_t id) {
127 auto it = 125 auto it =
128 std::find_if(callbacks_.begin(), callbacks_.end(), FindCallback(id)); 126 std::find_if(callbacks_.begin(), callbacks_.end(), FindCallback(id));
129 if (it == callbacks_.end()) { 127 if (it == callbacks_.end()) {
130 LOG(WARNING) << "Could not find callback for page flip id=" << id; 128 LOG(WARNING) << "Could not find callback for page flip id=" << id;
131 return; 129 return;
(...skipping 11 matching lines...) Expand all
143 141
144 uint64_t GetNextId() { return next_id_++; } 142 uint64_t GetNextId() { return next_id_++; }
145 143
146 void RegisterCallback(uint64_t id, 144 void RegisterCallback(uint64_t id,
147 uint64_t pending_calls, 145 uint64_t pending_calls,
148 const DrmDevice::PageFlipCallback& callback) { 146 const DrmDevice::PageFlipCallback& callback) {
149 callbacks_.push_back({id, pending_calls, callback}); 147 callbacks_.push_back({id, pending_calls, callback});
150 } 148 }
151 149
152 private: 150 private:
153 friend class base::RefCountedThreadSafe<DrmDevice::PageFlipManager>;
154 ~PageFlipManager() {}
155
156 struct PageFlip { 151 struct PageFlip {
157 uint64_t id; 152 uint64_t id;
158 uint32_t pending_calls; 153 uint32_t pending_calls;
159 DrmDevice::PageFlipCallback callback; 154 DrmDevice::PageFlipCallback callback;
160 }; 155 };
161 156
162 struct FindCallback { 157 struct FindCallback {
163 FindCallback(uint64_t id) : id(id) {} 158 FindCallback(uint64_t id) : id(id) {}
164 159
165 bool operator()(const PageFlip& flip) const { return flip.id == id; } 160 bool operator()(const PageFlip& flip) const { return flip.id == id; }
166 161
167 uint64_t id; 162 uint64_t id;
168 }; 163 };
169 164
170 uint64_t next_id_; 165 uint64_t next_id_;
171 166
172 std::vector<PageFlip> callbacks_; 167 std::vector<PageFlip> callbacks_;
173 168
174 DISALLOW_COPY_AND_ASSIGN(PageFlipManager); 169 DISALLOW_COPY_AND_ASSIGN(PageFlipManager);
175 }; 170 };
176 171
177 class DrmDevice::IOWatcher 172 class DrmDevice::IOWatcher : public base::MessagePumpLibevent::Watcher {
178 : public base::RefCountedThreadSafe<DrmDevice::IOWatcher>,
179 public base::MessagePumpLibevent::Watcher {
180 public: 173 public:
181 IOWatcher(int fd, 174 IOWatcher(int fd, DrmDevice::PageFlipManager* page_flip_manager)
182 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner, 175 : page_flip_manager_(page_flip_manager), paused_(true), fd_(fd) {}
183 const scoped_refptr<DrmDevice::PageFlipManager>& page_flip_manager) 176
184 : main_task_runner_(base::ThreadTaskRunnerHandle::Get()), 177 ~IOWatcher() override {
185 io_task_runner_(io_task_runner), 178 if (!paused_)
186 page_flip_manager_(page_flip_manager), 179 Unregister();
187 paused_(true), 180 }
188 fd_(fd) {}
189 181
190 void SetPaused(bool paused) { 182 void SetPaused(bool paused) {
191 if (paused_ == paused) 183 if (paused_ == paused)
192 return; 184 return;
193 185
194 paused_ = paused; 186 paused_ = paused;
195 base::WaitableEvent done(false, false); 187 if (paused_)
196 io_task_runner_->PostTask( 188 Unregister();
197 FROM_HERE, base::Bind(&IOWatcher::SetPausedOnIO, this, &done)); 189 else
198 done.Wait(); 190 Register();
199 }
200
201 void Shutdown() {
202 if (!paused_)
203 io_task_runner_->PostTask(FROM_HERE,
204 base::Bind(&IOWatcher::UnregisterOnIO, this));
205 } 191 }
206 192
207 private: 193 private:
208 friend class base::RefCountedThreadSafe<IOWatcher>; 194 void Register() {
209
210 ~IOWatcher() override {}
211
212 void RegisterOnIO() {
213 DCHECK(base::MessageLoopForIO::IsCurrent()); 195 DCHECK(base::MessageLoopForIO::IsCurrent());
196 TRACE_EVENT0("drm", "DrmDevice::RegisterOnIO");
214 base::MessageLoopForIO::current()->WatchFileDescriptor( 197 base::MessageLoopForIO::current()->WatchFileDescriptor(
215 fd_, true, base::MessageLoopForIO::WATCH_READ, &controller_, this); 198 fd_, true, base::MessageLoopForIO::WATCH_READ, &controller_, this);
216 } 199 }
217 200
218 void UnregisterOnIO() { 201 void Unregister() {
219 DCHECK(base::MessageLoopForIO::IsCurrent()); 202 DCHECK(base::MessageLoopForIO::IsCurrent());
203 TRACE_EVENT0("drm", "DrmDevice::UnregisterOnIO");
220 controller_.StopWatchingFileDescriptor(); 204 controller_.StopWatchingFileDescriptor();
221 } 205 }
222 206
223 void SetPausedOnIO(base::WaitableEvent* done) {
224 DCHECK(base::MessageLoopForIO::IsCurrent());
225 if (paused_)
226 UnregisterOnIO();
227 else
228 RegisterOnIO();
229 done->Signal();
230 }
231
232 void OnPageFlipOnIO(uint32_t frame,
233 uint32_t seconds,
234 uint32_t useconds,
235 uint64_t id) {
236 main_task_runner_->PostTask(
237 FROM_HERE,
238 base::Bind(&DrmDevice::PageFlipManager::OnPageFlip, page_flip_manager_,
239 frame, seconds, useconds, id));
240 }
241
242 // base::MessagePumpLibevent::Watcher overrides: 207 // base::MessagePumpLibevent::Watcher overrides:
243 void OnFileCanReadWithoutBlocking(int fd) override { 208 void OnFileCanReadWithoutBlocking(int fd) override {
244 DCHECK(base::MessageLoopForIO::IsCurrent()); 209 DCHECK(base::MessageLoopForIO::IsCurrent());
245 TRACE_EVENT1("drm", "OnDrmEvent", "socket", fd); 210 TRACE_EVENT1("drm", "OnDrmEvent", "socket", fd);
246 211
247 if (!ProcessDrmEvent( 212 if (!ProcessDrmEvent(fd, base::Bind(&DrmDevice::PageFlipManager::OnPageFlip,
248 fd, base::Bind(&DrmDevice::IOWatcher::OnPageFlipOnIO, this))) 213 base::Unretained(page_flip_manager_))))
249 UnregisterOnIO(); 214 Unregister();
250 } 215 }
251 216
252 void OnFileCanWriteWithoutBlocking(int fd) override { NOTREACHED(); } 217 void OnFileCanWriteWithoutBlocking(int fd) override { NOTREACHED(); }
253 218
254 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_; 219 DrmDevice::PageFlipManager* page_flip_manager_;
255 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
256
257 scoped_refptr<DrmDevice::PageFlipManager> page_flip_manager_;
258 220
259 base::MessagePumpLibevent::FileDescriptorWatcher controller_; 221 base::MessagePumpLibevent::FileDescriptorWatcher controller_;
260 222
261 bool paused_; 223 bool paused_;
262 int fd_; 224 int fd_;
263 225
264 DISALLOW_COPY_AND_ASSIGN(IOWatcher); 226 DISALLOW_COPY_AND_ASSIGN(IOWatcher);
265 }; 227 };
266 228
267 DrmDevice::DrmDevice(const base::FilePath& device_path, base::File file) 229 DrmDevice::DrmDevice(const base::FilePath& device_path, base::File file)
268 : device_path_(device_path), 230 : device_path_(device_path),
269 file_(file.Pass()), 231 file_(file.Pass()),
270 page_flip_manager_(new PageFlipManager()) { 232 page_flip_manager_(new PageFlipManager()),
271 } 233 watcher_(
234 new IOWatcher(file_.GetPlatformFile(), page_flip_manager_.get())) {}
272 235
273 DrmDevice::~DrmDevice() { 236 DrmDevice::~DrmDevice() {}
274 if (watcher_)
275 watcher_->Shutdown();
276 }
277 237
278 bool DrmDevice::Initialize(bool use_atomic) { 238 bool DrmDevice::Initialize(bool use_atomic) {
279 // Ignore devices that cannot perform modesetting. 239 // Ignore devices that cannot perform modesetting.
280 if (!CanQueryForResources(file_.GetPlatformFile())) { 240 if (!CanQueryForResources(file_.GetPlatformFile())) {
281 VLOG(2) << "Cannot query for resources for '" << device_path_.value() 241 VLOG(2) << "Cannot query for resources for '" << device_path_.value()
282 << "'"; 242 << "'";
283 return false; 243 return false;
284 } 244 }
285 245
286 #if defined(USE_DRM_ATOMIC) 246 #if defined(USE_DRM_ATOMIC)
287 // Use atomic only if the build, kernel & flags all allow it. 247 // Use atomic only if the build, kernel & flags all allow it.
288 if (use_atomic && SetCapability(DRM_CLIENT_CAP_ATOMIC, 1)) 248 if (use_atomic && SetCapability(DRM_CLIENT_CAP_ATOMIC, 1))
289 plane_manager_.reset(new HardwareDisplayPlaneManagerAtomic()); 249 plane_manager_.reset(new HardwareDisplayPlaneManagerAtomic());
290 #endif // defined(USE_DRM_ATOMIC) 250 #endif // defined(USE_DRM_ATOMIC)
291 251
292 if (!plane_manager_) 252 if (!plane_manager_)
293 plane_manager_.reset(new HardwareDisplayPlaneManagerLegacy()); 253 plane_manager_.reset(new HardwareDisplayPlaneManagerLegacy());
294 if (!plane_manager_->Initialize(this)) { 254 if (!plane_manager_->Initialize(this)) {
295 LOG(ERROR) << "Failed to initialize the plane manager for " 255 LOG(ERROR) << "Failed to initialize the plane manager for "
296 << device_path_.value(); 256 << device_path_.value();
297 plane_manager_.reset(); 257 plane_manager_.reset();
298 return false; 258 return false;
299 } 259 }
300 260
301 return true; 261 return true;
302 } 262 }
303 263
304 void DrmDevice::InitializeTaskRunner(
305 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) {
306 DCHECK(!task_runner_);
307 task_runner_ = task_runner;
308 watcher_ =
309 new IOWatcher(file_.GetPlatformFile(), task_runner_, page_flip_manager_);
310 }
311
312 ScopedDrmCrtcPtr DrmDevice::GetCrtc(uint32_t crtc_id) { 264 ScopedDrmCrtcPtr DrmDevice::GetCrtc(uint32_t crtc_id) {
313 DCHECK(file_.IsValid()); 265 DCHECK(file_.IsValid());
314 return ScopedDrmCrtcPtr(drmModeGetCrtc(file_.GetPlatformFile(), crtc_id)); 266 return ScopedDrmCrtcPtr(drmModeGetCrtc(file_.GetPlatformFile(), crtc_id));
315 } 267 }
316 268
317 bool DrmDevice::SetCrtc(uint32_t crtc_id, 269 bool DrmDevice::SetCrtc(uint32_t crtc_id,
318 uint32_t framebuffer, 270 uint32_t framebuffer,
319 std::vector<uint32_t> connectors, 271 std::vector<uint32_t> connectors,
320 drmModeModeInfo* mode) { 272 drmModeModeInfo* mode) {
321 DCHECK(file_.IsValid()); 273 DCHECK(file_.IsValid());
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
394 if (!drmModePageFlip(file_.GetPlatformFile(), crtc_id, framebuffer, 346 if (!drmModePageFlip(file_.GetPlatformFile(), crtc_id, framebuffer,
395 DRM_MODE_PAGE_FLIP_EVENT, reinterpret_cast<void*>(id))) { 347 DRM_MODE_PAGE_FLIP_EVENT, reinterpret_cast<void*>(id))) {
396 // If successful the payload will be removed by a PageFlip event. 348 // If successful the payload will be removed by a PageFlip event.
397 page_flip_manager_->RegisterCallback(id, 1, callback); 349 page_flip_manager_->RegisterCallback(id, 1, callback);
398 350
399 // If the flip was requested synchronous or if no watcher has been installed 351 // If the flip was requested synchronous or if no watcher has been installed
400 // yet, then synchronously handle the page flip events. 352 // yet, then synchronously handle the page flip events.
401 if (is_sync || !watcher_) { 353 if (is_sync || !watcher_) {
402 TRACE_EVENT1("drm", "OnDrmEvent", "socket", file_.GetPlatformFile()); 354 TRACE_EVENT1("drm", "OnDrmEvent", "socket", file_.GetPlatformFile());
403 355
404 ProcessDrmEvent( 356 ProcessDrmEvent(file_.GetPlatformFile(),
405 file_.GetPlatformFile(), 357 base::Bind(&PageFlipManager::OnPageFlip,
406 base::Bind(&PageFlipManager::OnPageFlip, page_flip_manager_)); 358 base::Unretained(page_flip_manager_.get())));
407 } 359 }
408 360
409 return true; 361 return true;
410 } 362 }
411 363
412 return false; 364 return false;
413 } 365 }
414 366
415 bool DrmDevice::PageFlipOverlay(uint32_t crtc_id, 367 bool DrmDevice::PageFlipOverlay(uint32_t crtc_id,
416 uint32_t framebuffer, 368 uint32_t framebuffer,
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
561 page_flip_manager_->RegisterCallback(id, crtc_count, callback); 513 page_flip_manager_->RegisterCallback(id, crtc_count, callback);
562 514
563 if (watcher_) 515 if (watcher_)
564 watcher_->SetPaused(is_sync); 516 watcher_->SetPaused(is_sync);
565 517
566 // If the flip was requested synchronous or if no watcher has been installed 518 // If the flip was requested synchronous or if no watcher has been installed
567 // yet, then synchronously handle the page flip events. 519 // yet, then synchronously handle the page flip events.
568 if (is_sync || !watcher_) { 520 if (is_sync || !watcher_) {
569 TRACE_EVENT1("drm", "OnDrmEvent", "socket", file_.GetPlatformFile()); 521 TRACE_EVENT1("drm", "OnDrmEvent", "socket", file_.GetPlatformFile());
570 522
571 ProcessDrmEvent( 523 ProcessDrmEvent(file_.GetPlatformFile(),
572 file_.GetPlatformFile(), 524 base::Bind(&PageFlipManager::OnPageFlip,
573 base::Bind(&PageFlipManager::OnPageFlip, page_flip_manager_)); 525 base::Unretained(page_flip_manager_.get())));
574 } 526 }
575 return true; 527 return true;
576 } 528 }
577 #endif // defined(USE_DRM_ATOMIC) 529 #endif // defined(USE_DRM_ATOMIC)
578 return false; 530 return false;
579 } 531 }
580 532
581 bool DrmDevice::SetCapability(uint64_t capability, uint64_t value) { 533 bool DrmDevice::SetCapability(uint64_t capability, uint64_t value) {
582 DCHECK(file_.IsValid()); 534 DCHECK(file_.IsValid());
583 return !drmSetClientCap(file_.GetPlatformFile(), capability, value); 535 return !drmSetClientCap(file_.GetPlatformFile(), capability, value);
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
617 b.push_back(lut[i].b); 569 b.push_back(lut[i].b);
618 } 570 }
619 571
620 DCHECK(file_.IsValid()); 572 DCHECK(file_.IsValid());
621 TRACE_EVENT0("drm", "DrmDevice::SetGamma"); 573 TRACE_EVENT0("drm", "DrmDevice::SetGamma");
622 return (drmModeCrtcSetGamma(file_.GetPlatformFile(), crtc_id, r.size(), &r[0], 574 return (drmModeCrtcSetGamma(file_.GetPlatformFile(), crtc_id, r.size(), &r[0],
623 &g[0], &b[0]) == 0); 575 &g[0], &b[0]) == 0);
624 } 576 }
625 577
626 } // namespace ui 578 } // namespace ui
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698