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

Side by Side Diff: ui/ozone/platform/dri/dri_wrapper.cc

Issue 821023003: [Ozone-DRI] Listen for swap events (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@async-swap
Patch Set: . Created 5 years, 11 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/dri/dri_wrapper.h" 5 #include "ui/ozone/platform/dri/dri_wrapper.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/debug/trace_event.h" 13 #include "base/debug/trace_event.h"
14 #include "base/logging.h" 14 #include "base/logging.h"
15 #include "base/message_loop/message_loop.h"
15 #include "base/stl_util.h" 16 #include "base/stl_util.h"
17 #include "base/task_runner.h"
18 #include "base/thread_task_runner_handle.h"
16 #include "third_party/skia/include/core/SkImageInfo.h" 19 #include "third_party/skia/include/core/SkImageInfo.h"
17 #include "ui/ozone/platform/dri/dri_util.h" 20 #include "ui/ozone/platform/dri/dri_util.h"
18 #include "ui/ozone/platform/dri/hardware_display_plane_manager_legacy.h" 21 #include "ui/ozone/platform/dri/hardware_display_plane_manager_legacy.h"
19 22
20 namespace ui { 23 namespace ui {
21 24
22 namespace { 25 namespace {
23 26
27 struct PageFlipPayload {
28 PageFlipPayload(const scoped_refptr<base::TaskRunner>& task_runner,
alexst (slow to review) 2015/01/09 03:55:46 You should mention which thread this task runner b
dnicoara 2015/01/09 15:08:24 Added some comments. In principle it doesn't matte
29 const DriWrapper::PageFlipCallback& callback)
30 : task_runner(task_runner), callback(callback) {}
31
32 scoped_refptr<base::TaskRunner> task_runner;
33 DriWrapper::PageFlipCallback callback;
34 };
35
24 bool DrmCreateDumbBuffer(int fd, 36 bool DrmCreateDumbBuffer(int fd,
25 const SkImageInfo& info, 37 const SkImageInfo& info,
26 uint32_t* handle, 38 uint32_t* handle,
27 uint32_t* stride) { 39 uint32_t* stride) {
28 struct drm_mode_create_dumb request; 40 struct drm_mode_create_dumb request;
29 memset(&request, 0, sizeof(request)); 41 memset(&request, 0, sizeof(request));
30 request.width = info.width(); 42 request.width = info.width();
31 request.height = info.height(); 43 request.height = info.height();
32 request.bpp = info.bytesPerPixel() << 3; 44 request.bpp = info.bytesPerPixel() << 3;
33 request.flags = 0; 45 request.flags = 0;
(...skipping 14 matching lines...) Expand all
48 return true; 60 return true;
49 } 61 }
50 62
51 void DrmDestroyDumbBuffer(int fd, uint32_t handle) { 63 void DrmDestroyDumbBuffer(int fd, uint32_t handle) {
52 struct drm_mode_destroy_dumb destroy_request; 64 struct drm_mode_destroy_dumb destroy_request;
53 memset(&destroy_request, 0, sizeof(destroy_request)); 65 memset(&destroy_request, 0, sizeof(destroy_request));
54 destroy_request.handle = handle; 66 destroy_request.handle = handle;
55 drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_request); 67 drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_request);
56 } 68 }
57 69
70 void HandlePageFlipEventOnIO(int fd,
71 unsigned int frame,
72 unsigned int seconds,
73 unsigned int useconds,
74 void* data) {
75 scoped_ptr<PageFlipPayload> payload(static_cast<PageFlipPayload*>(data));
76 payload->task_runner->PostTask(
77 FROM_HERE, base::Bind(payload->callback, frame, seconds, useconds));
78 }
79
80 void HandlePageFlipEventOnUI(int fd,
81 unsigned int frame,
82 unsigned int seconds,
83 unsigned int useconds,
84 void* data) {
85 scoped_ptr<PageFlipPayload> payload(static_cast<PageFlipPayload*>(data));
86 payload->callback.Run(frame, seconds, useconds);
87 }
88
58 } // namespace 89 } // namespace
59 90
60 DriWrapper::DriWrapper(const char* device_path) 91 class DriWrapper::IOWatcher
61 : fd_(-1), device_path_(device_path) { 92 : public base::RefCountedThreadSafe<DriWrapper::IOWatcher>,
93 public base::MessagePumpLibevent::Watcher {
94 public:
95 IOWatcher(int fd,
96 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner)
97 : io_task_runner_(io_task_runner) {
98 io_task_runner_->PostTask(FROM_HERE,
99 base::Bind(&IOWatcher::RegisterOnIO, this, fd));
100 }
101
102 private:
103 friend class base::RefCountedThreadSafe<IOWatcher>;
104
105 ~IOWatcher() override {
106 io_task_runner_->PostTask(FROM_HERE,
107 base::Bind(&IOWatcher::UnregisterOnIO, this));
alexst (slow to review) 2015/01/09 03:55:46 I am pretty sure this is not safe, we are in the d
dnicoara 2015/01/09 15:08:24 Doh! You are right, move the post in a Shutdown()
108 }
109
110 void RegisterOnIO(int fd) {
111 DCHECK(base::MessageLoopForIO::IsCurrent());
112 base::MessageLoopForIO::current()->WatchFileDescriptor(
113 fd, true, base::MessageLoopForIO::WATCH_READ, &controller_, this);
114 }
115
116 void UnregisterOnIO() {
117 DCHECK(base::MessageLoopForIO::IsCurrent());
alexst (slow to review) 2015/01/09 03:55:46 Is this checking that an IO type thread is current
dnicoara 2015/01/09 15:08:24 Yes. It would be hard to check which IO message lo
118 controller_.StopWatchingFileDescriptor();
119 }
120
121 // base::MessagePumpLibevent::Watcher overrides:
122 void OnFileCanReadWithoutBlocking(int fd) override {
123 DCHECK(base::MessageLoopForIO::IsCurrent());
124 TRACE_EVENT1("dri", "OnDrmEvent", "socket", fd);
125
126 drmEventContext event;
127 event.version = DRM_EVENT_CONTEXT_VERSION;
128 event.page_flip_handler = HandlePageFlipEventOnIO;
129 event.vblank_handler = nullptr;
130
131 drmHandleEvent(fd, &event);
132 }
133
134 void OnFileCanWriteWithoutBlocking(int fd) override { NOTREACHED(); }
135
136 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
137
138 base::MessagePumpLibevent::FileDescriptorWatcher controller_;
139
140 DISALLOW_COPY_AND_ASSIGN(IOWatcher);
141 };
142
143 DriWrapper::DriWrapper(const char* device_path, bool software_mode)
144 : fd_(-1),
145 software_mode_(software_mode),
146 device_path_(device_path),
147 io_thread_("DriIOThread") {
62 plane_manager_.reset(new HardwareDisplayPlaneManagerLegacy()); 148 plane_manager_.reset(new HardwareDisplayPlaneManagerLegacy());
63 } 149 }
64 150
65 DriWrapper::~DriWrapper() { 151 DriWrapper::~DriWrapper() {
66 if (fd_ >= 0) 152 if (fd_ >= 0)
67 close(fd_); 153 close(fd_);
68 } 154 }
69 155
70 void DriWrapper::Initialize() { 156 void DriWrapper::Initialize() {
71 fd_ = open(device_path_, O_RDWR | O_CLOEXEC); 157 fd_ = open(device_path_, O_RDWR | O_CLOEXEC);
72 if (fd_ < 0) 158 if (fd_ < 0)
73 PLOG(FATAL) << "open: " << device_path_; 159 PLOG(FATAL) << "open: " << device_path_;
74 if (!plane_manager_->Initialize(this)) 160 if (!plane_manager_->Initialize(this))
75 LOG(ERROR) << "Failed to initialize the plane manager"; 161 LOG(ERROR) << "Failed to initialize the plane manager";
76 } 162 }
77 163
164 void DriWrapper::InitializeIOWatcher() {
165 if (!software_mode_ && !watcher_) {
166 if (!io_thread_.StartWithOptions(
167 base::Thread::Options(base::MessageLoop::TYPE_IO, 0)))
168 LOG(FATAL) << "Failed to start the IO helper thread";
169
170 watcher_ = new IOWatcher(fd_, io_thread_.task_runner());
171 }
172 }
173
78 ScopedDrmCrtcPtr DriWrapper::GetCrtc(uint32_t crtc_id) { 174 ScopedDrmCrtcPtr DriWrapper::GetCrtc(uint32_t crtc_id) {
79 DCHECK(fd_ >= 0); 175 DCHECK(fd_ >= 0);
80 return ScopedDrmCrtcPtr(drmModeGetCrtc(fd_, crtc_id)); 176 return ScopedDrmCrtcPtr(drmModeGetCrtc(fd_, crtc_id));
81 } 177 }
82 178
83 bool DriWrapper::SetCrtc(uint32_t crtc_id, 179 bool DriWrapper::SetCrtc(uint32_t crtc_id,
84 uint32_t framebuffer, 180 uint32_t framebuffer,
85 std::vector<uint32_t> connectors, 181 std::vector<uint32_t> connectors,
86 drmModeModeInfo* mode) { 182 drmModeModeInfo* mode) {
87 DCHECK(fd_ >= 0); 183 DCHECK(fd_ >= 0);
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
154 250
155 bool DriWrapper::RemoveFramebuffer(uint32_t framebuffer) { 251 bool DriWrapper::RemoveFramebuffer(uint32_t framebuffer) {
156 DCHECK(fd_ >= 0); 252 DCHECK(fd_ >= 0);
157 TRACE_EVENT1("dri", "DriWrapper::RemoveFramebuffer", 253 TRACE_EVENT1("dri", "DriWrapper::RemoveFramebuffer",
158 "framebuffer", framebuffer); 254 "framebuffer", framebuffer);
159 return !drmModeRmFB(fd_, framebuffer); 255 return !drmModeRmFB(fd_, framebuffer);
160 } 256 }
161 257
162 bool DriWrapper::PageFlip(uint32_t crtc_id, 258 bool DriWrapper::PageFlip(uint32_t crtc_id,
163 uint32_t framebuffer, 259 uint32_t framebuffer,
164 void* data) { 260 const PageFlipCallback& callback) {
165 DCHECK(fd_ >= 0); 261 DCHECK(fd_ >= 0);
166 TRACE_EVENT2("dri", "DriWrapper::PageFlip", 262 TRACE_EVENT2("dri", "DriWrapper::PageFlip",
167 "crtc", crtc_id, 263 "crtc", crtc_id,
168 "framebuffer", framebuffer); 264 "framebuffer", framebuffer);
169 return !drmModePageFlip(fd_, 265
170 crtc_id, 266 // NOTE: Calling drmModeSetCrtc will immediately update the state, though
171 framebuffer, 267 // callbacks to already scheduled page flips will be honored by the kernel.
172 DRM_MODE_PAGE_FLIP_EVENT, 268 scoped_ptr<PageFlipPayload> payload(
173 data); 269 new PageFlipPayload(base::ThreadTaskRunnerHandle::Get(), callback));
270 if (!drmModePageFlip(fd_, crtc_id, framebuffer, DRM_MODE_PAGE_FLIP_EVENT,
271 payload.get())) {
272 // If successful the payload will be removed by a PageFlip event.
273 ignore_result(payload.release());
274 if (software_mode_) {
275 TRACE_EVENT1("dri", "OnDrmEvent", "socket", fd_);
276
277 drmEventContext event;
278 event.version = DRM_EVENT_CONTEXT_VERSION;
279 event.page_flip_handler = HandlePageFlipEventOnUI;
280 event.vblank_handler = nullptr;
281
282 drmHandleEvent(fd_, &event);
283 } else {
284 InitializeIOWatcher();
285 }
286
287 return true;
288 }
289
290 return false;
174 } 291 }
175 292
176 bool DriWrapper::PageFlipOverlay(uint32_t crtc_id, 293 bool DriWrapper::PageFlipOverlay(uint32_t crtc_id,
177 uint32_t framebuffer, 294 uint32_t framebuffer,
178 const gfx::Rect& location, 295 const gfx::Rect& location,
179 const gfx::Rect& source, 296 const gfx::Rect& source,
180 int overlay_plane) { 297 int overlay_plane) {
181 DCHECK(fd_ >= 0); 298 DCHECK(fd_ >= 0);
182 TRACE_EVENT2("dri", "DriWrapper::PageFlipOverlay", 299 TRACE_EVENT2("dri", "DriWrapper::PageFlipOverlay",
183 "crtc", crtc_id, 300 "crtc", crtc_id,
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
250 DCHECK(fd_ >= 0); 367 DCHECK(fd_ >= 0);
251 TRACE_EVENT1("dri", "DriWrapper::SetCursor", "handle", handle); 368 TRACE_EVENT1("dri", "DriWrapper::SetCursor", "handle", handle);
252 return !drmModeSetCursor(fd_, crtc_id, handle, size.width(), size.height()); 369 return !drmModeSetCursor(fd_, crtc_id, handle, size.width(), size.height());
253 } 370 }
254 371
255 bool DriWrapper::MoveCursor(uint32_t crtc_id, const gfx::Point& point) { 372 bool DriWrapper::MoveCursor(uint32_t crtc_id, const gfx::Point& point) {
256 DCHECK(fd_ >= 0); 373 DCHECK(fd_ >= 0);
257 return !drmModeMoveCursor(fd_, crtc_id, point.x(), point.y()); 374 return !drmModeMoveCursor(fd_, crtc_id, point.x(), point.y());
258 } 375 }
259 376
260 void DriWrapper::HandleEvent(drmEventContext& event) {
261 DCHECK(fd_ >= 0);
262 TRACE_EVENT0("dri", "DriWrapper::HandleEvent");
263 drmHandleEvent(fd_, &event);
264 }
265
266 bool DriWrapper::CreateDumbBuffer(const SkImageInfo& info, 377 bool DriWrapper::CreateDumbBuffer(const SkImageInfo& info,
267 uint32_t* handle, 378 uint32_t* handle,
268 uint32_t* stride, 379 uint32_t* stride,
269 void** pixels) { 380 void** pixels) {
270 DCHECK(fd_ >= 0); 381 DCHECK(fd_ >= 0);
271 382
272 TRACE_EVENT0("dri", "DriWrapper::CreateDumbBuffer"); 383 TRACE_EVENT0("dri", "DriWrapper::CreateDumbBuffer");
273 if (!DrmCreateDumbBuffer(fd_, info, handle, stride)) 384 if (!DrmCreateDumbBuffer(fd_, info, handle, stride))
274 return false; 385 return false;
275 386
(...skipping 19 matching lines...) Expand all
295 DCHECK(fd_ >= 0); 406 DCHECK(fd_ >= 0);
296 return (drmSetMaster(fd_) == 0); 407 return (drmSetMaster(fd_) == 0);
297 } 408 }
298 409
299 bool DriWrapper::DropMaster() { 410 bool DriWrapper::DropMaster() {
300 DCHECK(fd_ >= 0); 411 DCHECK(fd_ >= 0);
301 return (drmDropMaster(fd_) == 0); 412 return (drmDropMaster(fd_) == 0);
302 } 413 }
303 414
304 } // namespace ui 415 } // namespace ui
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698