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

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

Issue 1056793007: [3/4][Ozone-Drm] Use numeric ID to map to callback (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@move-all-hotplug
Patch Set: Use std::vector Created 5 years, 7 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
« no previous file with comments | « ui/ozone/platform/drm/gpu/drm_device.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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>
(...skipping 11 matching lines...) Expand all
22 #include "ui/ozone/platform/drm/gpu/hardware_display_plane_manager_legacy.h" 22 #include "ui/ozone/platform/drm/gpu/hardware_display_plane_manager_legacy.h"
23 23
24 #if defined(USE_DRM_ATOMIC) 24 #if defined(USE_DRM_ATOMIC)
25 #include "ui/ozone/platform/drm/gpu/hardware_display_plane_manager_atomic.h" 25 #include "ui/ozone/platform/drm/gpu/hardware_display_plane_manager_atomic.h"
26 #endif 26 #endif
27 27
28 namespace ui { 28 namespace ui {
29 29
30 namespace { 30 namespace {
31 31
32 typedef base::Callback<void(uint32_t /* frame */,
33 uint32_t /* seconds */,
34 uint32_t /* useconds */,
35 uint64_t /* id */)> DrmEventHandler;
36
32 struct PageFlipPayload { 37 struct PageFlipPayload {
33 PageFlipPayload(const scoped_refptr<base::TaskRunner>& task_runner, 38 PageFlipPayload(const scoped_refptr<base::TaskRunner>& task_runner,
34 const DrmDevice::PageFlipCallback& callback) 39 const DrmDevice::PageFlipCallback& callback)
35 : task_runner(task_runner), callback(callback) {} 40 : task_runner(task_runner), callback(callback) {}
36 41
37 // Task runner for the thread scheduling the page flip event. This is used to 42 // Task runner for the thread scheduling the page flip event. This is used to
38 // run the callback on the same thread the callback was created on. 43 // run the callback on the same thread the callback was created on.
39 scoped_refptr<base::TaskRunner> task_runner; 44 scoped_refptr<base::TaskRunner> task_runner;
40 DrmDevice::PageFlipCallback callback; 45 DrmDevice::PageFlipCallback callback;
41 }; 46 };
(...skipping 24 matching lines...) Expand all
66 return true; 71 return true;
67 } 72 }
68 73
69 bool DrmDestroyDumbBuffer(int fd, uint32_t handle) { 74 bool DrmDestroyDumbBuffer(int fd, uint32_t handle) {
70 struct drm_mode_destroy_dumb destroy_request; 75 struct drm_mode_destroy_dumb destroy_request;
71 memset(&destroy_request, 0, sizeof(destroy_request)); 76 memset(&destroy_request, 0, sizeof(destroy_request));
72 destroy_request.handle = handle; 77 destroy_request.handle = handle;
73 return !drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_request); 78 return !drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_request);
74 } 79 }
75 80
76 void HandlePageFlipEventOnIO(int fd, 81 bool ProcessDrmEvent(int fd, const DrmEventHandler& callback) {
77 unsigned int frame, 82 char buffer[1024];
78 unsigned int seconds, 83 int len = read(fd, buffer, sizeof(buffer));
79 unsigned int useconds, 84 if (len == 0)
80 void* data) { 85 return false;
81 scoped_ptr<PageFlipPayload> payload(static_cast<PageFlipPayload*>(data));
82 payload->task_runner->PostTask(
83 FROM_HERE, base::Bind(payload->callback, frame, seconds, useconds));
84 }
85 86
86 void HandlePageFlipEventOnUI(int fd, 87 if (len < static_cast<int>(sizeof(drm_event))) {
87 unsigned int frame, 88 PLOG(ERROR) << "Failed to read DRM event";
88 unsigned int seconds, 89 return false;
89 unsigned int useconds, 90 }
90 void* data) { 91
91 scoped_ptr<PageFlipPayload> payload(static_cast<PageFlipPayload*>(data)); 92 int idx = 0;
92 payload->callback.Run(frame, seconds, useconds); 93 while (idx < len) {
94 DCHECK_LT(static_cast<int>(sizeof(drm_event)), len - idx);
95 drm_event event;
96 memcpy(&event, &buffer[idx], sizeof(event));
97 switch (event.type) {
98 case DRM_EVENT_FLIP_COMPLETE: {
99 DCHECK_LT(static_cast<int>(sizeof(drm_event_vblank)), len - idx);
100 drm_event_vblank vblank;
101 memcpy(&vblank, &buffer[idx], sizeof(vblank));
102 callback.Run(vblank.sequence, vblank.tv_sec, vblank.tv_usec,
103 vblank.user_data);
104 } break;
105 case DRM_EVENT_VBLANK:
106 break;
107 default:
108 NOTREACHED();
109 break;
110 }
111
112 idx += event.length;
113 }
114
115 return true;
93 } 116 }
94 117
95 bool CanQueryForResources(int fd) { 118 bool CanQueryForResources(int fd) {
96 drm_mode_card_res resources; 119 drm_mode_card_res resources;
97 memset(&resources, 0, sizeof(resources)); 120 memset(&resources, 0, sizeof(resources));
98 // If there is no error getting DRM resources then assume this is a 121 // If there is no error getting DRM resources then assume this is a
99 // modesetting device. 122 // modesetting device.
100 return !drmIoctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &resources); 123 return !drmIoctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &resources);
101 } 124 }
102 125
103 } // namespace 126 } // namespace
104 127
128 class DrmDevice::PageFlipManager
129 : public base::RefCountedThreadSafe<DrmDevice::PageFlipManager> {
130 public:
131 PageFlipManager() : next_id_(0) {}
132
133 void OnPageFlip(uint32_t frame,
134 uint32_t seconds,
135 uint32_t useconds,
136 uint64_t id) {
137 auto it =
138 std::find_if(callbacks_.begin(), callbacks_.end(), FindCallback(id));
139 if (it == callbacks_.end()) {
140 LOG(WARNING) << "Could not find callback for page flip id=" << id;
141 return;
142 }
143
144 DrmDevice::PageFlipCallback callback = it->callback;
145 callbacks_.erase(it);
146 callback.Run(frame, seconds, useconds);
147 }
148
149 uint64_t GetNextId() { return next_id_++; }
150
151 void RegisterCallback(uint64_t id,
152 const DrmDevice::PageFlipCallback& callback) {
153 callbacks_.push_back({id, callback});
154 }
155
156 private:
157 friend class base::RefCountedThreadSafe<DrmDevice::PageFlipManager>;
158 ~PageFlipManager() {}
159
160 struct PageFlip {
161 uint64_t id;
162 DrmDevice::PageFlipCallback callback;
163 };
164
165 struct FindCallback {
166 FindCallback(uint64_t id) : id(id) {}
167
168 bool operator()(const PageFlip& flip) const { return flip.id == id; }
169
170 uint64_t id;
171 };
172
173 uint64_t next_id_;
174
175 std::vector<PageFlip> callbacks_;
176
177 DISALLOW_COPY_AND_ASSIGN(PageFlipManager);
178 };
179
105 class DrmDevice::IOWatcher 180 class DrmDevice::IOWatcher
106 : public base::RefCountedThreadSafe<DrmDevice::IOWatcher>, 181 : public base::RefCountedThreadSafe<DrmDevice::IOWatcher>,
107 public base::MessagePumpLibevent::Watcher { 182 public base::MessagePumpLibevent::Watcher {
108 public: 183 public:
109 IOWatcher(int fd, 184 IOWatcher(int fd,
110 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner) 185 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner,
111 : io_task_runner_(io_task_runner), paused_(true), fd_(fd) {} 186 const scoped_refptr<DrmDevice::PageFlipManager>& page_flip_manager)
187 : main_task_runner_(base::ThreadTaskRunnerHandle::Get()),
188 io_task_runner_(io_task_runner),
189 page_flip_manager_(page_flip_manager),
190 paused_(true),
191 fd_(fd) {}
112 192
113 void SetPaused(bool paused) { 193 void SetPaused(bool paused) {
114 if (paused_ == paused) 194 if (paused_ == paused)
115 return; 195 return;
116 196
117 paused_ = paused; 197 paused_ = paused;
118 base::WaitableEvent done(false, false); 198 base::WaitableEvent done(false, false);
119 io_task_runner_->PostTask( 199 io_task_runner_->PostTask(
120 FROM_HERE, base::Bind(&IOWatcher::SetPausedOnIO, this, &done)); 200 FROM_HERE, base::Bind(&IOWatcher::SetPausedOnIO, this, &done));
121 done.Wait(); 201 done.Wait();
(...skipping 23 matching lines...) Expand all
145 225
146 void SetPausedOnIO(base::WaitableEvent* done) { 226 void SetPausedOnIO(base::WaitableEvent* done) {
147 DCHECK(base::MessageLoopForIO::IsCurrent()); 227 DCHECK(base::MessageLoopForIO::IsCurrent());
148 if (paused_) 228 if (paused_)
149 UnregisterOnIO(); 229 UnregisterOnIO();
150 else 230 else
151 RegisterOnIO(); 231 RegisterOnIO();
152 done->Signal(); 232 done->Signal();
153 } 233 }
154 234
235 void OnPageFlipOnIO(uint32_t frame,
236 uint32_t seconds,
237 uint32_t useconds,
238 uint64_t id) {
239 main_task_runner_->PostTask(
240 FROM_HERE,
241 base::Bind(&DrmDevice::PageFlipManager::OnPageFlip, page_flip_manager_,
242 frame, seconds, useconds, id));
243 }
244
155 // base::MessagePumpLibevent::Watcher overrides: 245 // base::MessagePumpLibevent::Watcher overrides:
156 void OnFileCanReadWithoutBlocking(int fd) override { 246 void OnFileCanReadWithoutBlocking(int fd) override {
157 DCHECK(base::MessageLoopForIO::IsCurrent()); 247 DCHECK(base::MessageLoopForIO::IsCurrent());
158 TRACE_EVENT1("drm", "OnDrmEvent", "socket", fd); 248 TRACE_EVENT1("drm", "OnDrmEvent", "socket", fd);
159 249
160 drmEventContext event; 250 if (!ProcessDrmEvent(
161 event.version = DRM_EVENT_CONTEXT_VERSION; 251 fd, base::Bind(&DrmDevice::IOWatcher::OnPageFlipOnIO, this)))
162 event.page_flip_handler = HandlePageFlipEventOnIO; 252 UnregisterOnIO();
dnicoara 2015/04/28 14:42:49 Also, since it was a trivial change, unregistered
163 event.vblank_handler = nullptr;
164
165 drmHandleEvent(fd, &event);
166 } 253 }
167 254
168 void OnFileCanWriteWithoutBlocking(int fd) override { NOTREACHED(); } 255 void OnFileCanWriteWithoutBlocking(int fd) override { NOTREACHED(); }
169 256
257 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
170 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_; 258 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
171 259
260 scoped_refptr<DrmDevice::PageFlipManager> page_flip_manager_;
261
172 base::MessagePumpLibevent::FileDescriptorWatcher controller_; 262 base::MessagePumpLibevent::FileDescriptorWatcher controller_;
173 263
174 bool paused_; 264 bool paused_;
175 int fd_; 265 int fd_;
176 266
177 DISALLOW_COPY_AND_ASSIGN(IOWatcher); 267 DISALLOW_COPY_AND_ASSIGN(IOWatcher);
178 }; 268 };
179 269
180 DrmDevice::DrmDevice(const base::FilePath& device_path) 270 DrmDevice::DrmDevice(const base::FilePath& device_path)
181 : device_path_(device_path), 271 : device_path_(device_path),
182 file_(device_path, 272 file_(device_path,
183 base::File::FLAG_OPEN | base::File::FLAG_READ | 273 base::File::FLAG_OPEN | base::File::FLAG_READ |
184 base::File::FLAG_WRITE) { 274 base::File::FLAG_WRITE),
275 page_flip_manager_(new PageFlipManager()) {
185 LOG_IF(FATAL, !file_.IsValid()) 276 LOG_IF(FATAL, !file_.IsValid())
186 << "Failed to open '" << device_path_.value() 277 << "Failed to open '" << device_path_.value()
187 << "': " << base::File::ErrorToString(file_.error_details()); 278 << "': " << base::File::ErrorToString(file_.error_details());
188 } 279 }
189 280
190 DrmDevice::DrmDevice(const base::FilePath& device_path, base::File file) 281 DrmDevice::DrmDevice(const base::FilePath& device_path, base::File file)
191 : device_path_(device_path), file_(file.Pass()) { 282 : device_path_(device_path),
283 file_(file.Pass()),
284 page_flip_manager_(new PageFlipManager()) {
192 } 285 }
193 286
194 DrmDevice::~DrmDevice() { 287 DrmDevice::~DrmDevice() {
195 if (watcher_) 288 if (watcher_)
196 watcher_->Shutdown(); 289 watcher_->Shutdown();
197 } 290 }
198 291
199 bool DrmDevice::Initialize() { 292 bool DrmDevice::Initialize() {
200 // Ignore devices that cannot perform modesetting. 293 // Ignore devices that cannot perform modesetting.
201 if (!CanQueryForResources(file_.GetPlatformFile())) { 294 if (!CanQueryForResources(file_.GetPlatformFile())) {
(...skipping 14 matching lines...) Expand all
216 return false; 309 return false;
217 } 310 }
218 311
219 return true; 312 return true;
220 } 313 }
221 314
222 void DrmDevice::InitializeTaskRunner( 315 void DrmDevice::InitializeTaskRunner(
223 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) { 316 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) {
224 DCHECK(!task_runner_); 317 DCHECK(!task_runner_);
225 task_runner_ = task_runner; 318 task_runner_ = task_runner;
226 watcher_ = new IOWatcher(file_.GetPlatformFile(), task_runner_); 319 watcher_ =
320 new IOWatcher(file_.GetPlatformFile(), task_runner_, page_flip_manager_);
227 } 321 }
228 322
229 ScopedDrmCrtcPtr DrmDevice::GetCrtc(uint32_t crtc_id) { 323 ScopedDrmCrtcPtr DrmDevice::GetCrtc(uint32_t crtc_id) {
230 DCHECK(file_.IsValid()); 324 DCHECK(file_.IsValid());
231 return ScopedDrmCrtcPtr(drmModeGetCrtc(file_.GetPlatformFile(), crtc_id)); 325 return ScopedDrmCrtcPtr(drmModeGetCrtc(file_.GetPlatformFile(), crtc_id));
232 } 326 }
233 327
234 bool DrmDevice::SetCrtc(uint32_t crtc_id, 328 bool DrmDevice::SetCrtc(uint32_t crtc_id,
235 uint32_t framebuffer, 329 uint32_t framebuffer,
236 std::vector<uint32_t> connectors, 330 std::vector<uint32_t> connectors,
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
300 const PageFlipCallback& callback) { 394 const PageFlipCallback& callback) {
301 DCHECK(file_.IsValid()); 395 DCHECK(file_.IsValid());
302 TRACE_EVENT2("drm", "DrmDevice::PageFlip", "crtc", crtc_id, "framebuffer", 396 TRACE_EVENT2("drm", "DrmDevice::PageFlip", "crtc", crtc_id, "framebuffer",
303 framebuffer); 397 framebuffer);
304 398
305 if (watcher_) 399 if (watcher_)
306 watcher_->SetPaused(is_sync); 400 watcher_->SetPaused(is_sync);
307 401
308 // NOTE: Calling drmModeSetCrtc will immediately update the state, though 402 // NOTE: Calling drmModeSetCrtc will immediately update the state, though
309 // callbacks to already scheduled page flips will be honored by the kernel. 403 // callbacks to already scheduled page flips will be honored by the kernel.
310 scoped_ptr<PageFlipPayload> payload( 404 uint64_t id = page_flip_manager_->GetNextId();
311 new PageFlipPayload(base::ThreadTaskRunnerHandle::Get(), callback));
312 if (!drmModePageFlip(file_.GetPlatformFile(), crtc_id, framebuffer, 405 if (!drmModePageFlip(file_.GetPlatformFile(), crtc_id, framebuffer,
313 DRM_MODE_PAGE_FLIP_EVENT, payload.get())) { 406 DRM_MODE_PAGE_FLIP_EVENT, reinterpret_cast<void*>(id))) {
314 // If successful the payload will be removed by a PageFlip event. 407 // If successful the payload will be removed by a PageFlip event.
315 ignore_result(payload.release()); 408 page_flip_manager_->RegisterCallback(id, callback);
316 409
317 // If the flip was requested synchronous or if no watcher has been installed 410 // If the flip was requested synchronous or if no watcher has been installed
318 // yet, then synchronously handle the page flip events. 411 // yet, then synchronously handle the page flip events.
319 if (is_sync || !watcher_) { 412 if (is_sync || !watcher_) {
320 TRACE_EVENT1("drm", "OnDrmEvent", "socket", file_.GetPlatformFile()); 413 TRACE_EVENT1("drm", "OnDrmEvent", "socket", file_.GetPlatformFile());
321 414
322 drmEventContext event; 415 ProcessDrmEvent(
323 event.version = DRM_EVENT_CONTEXT_VERSION; 416 file_.GetPlatformFile(),
324 event.page_flip_handler = HandlePageFlipEventOnUI; 417 base::Bind(&PageFlipManager::OnPageFlip, page_flip_manager_));
325 event.vblank_handler = nullptr;
326
327 drmHandleEvent(file_.GetPlatformFile(), &event);
328 } 418 }
329 419
330 return true; 420 return true;
331 } 421 }
332 422
333 return false; 423 return false;
334 } 424 }
335 425
336 bool DrmDevice::PageFlipOverlay(uint32_t crtc_id, 426 bool DrmDevice::PageFlipOverlay(uint32_t crtc_id,
337 uint32_t framebuffer, 427 uint32_t framebuffer,
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
488 DCHECK(file_.IsValid()); 578 DCHECK(file_.IsValid());
489 return (drmSetMaster(file_.GetPlatformFile()) == 0); 579 return (drmSetMaster(file_.GetPlatformFile()) == 0);
490 } 580 }
491 581
492 bool DrmDevice::DropMaster() { 582 bool DrmDevice::DropMaster() {
493 DCHECK(file_.IsValid()); 583 DCHECK(file_.IsValid());
494 return (drmDropMaster(file_.GetPlatformFile()) == 0); 584 return (drmDropMaster(file_.GetPlatformFile()) == 0);
495 } 585 }
496 586
497 } // namespace ui 587 } // namespace ui
OLDNEW
« no previous file with comments | « ui/ozone/platform/drm/gpu/drm_device.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698