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

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: Added comment 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
« no previous file with comments | « ui/ozone/platform/dri/dri_wrapper.h ('k') | ui/ozone/platform/dri/gbm_surface.h » ('j') | 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/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,
29 const DriWrapper::PageFlipCallback& callback)
30 : task_runner(task_runner), callback(callback) {}
31
32 // Task runner for the thread scheduling the page flip event. This is used to
33 // run the callback on the same thread the callback was created on.
34 scoped_refptr<base::TaskRunner> task_runner;
35 DriWrapper::PageFlipCallback callback;
36 };
37
24 bool DrmCreateDumbBuffer(int fd, 38 bool DrmCreateDumbBuffer(int fd,
25 const SkImageInfo& info, 39 const SkImageInfo& info,
26 uint32_t* handle, 40 uint32_t* handle,
27 uint32_t* stride) { 41 uint32_t* stride) {
28 struct drm_mode_create_dumb request; 42 struct drm_mode_create_dumb request;
29 memset(&request, 0, sizeof(request)); 43 memset(&request, 0, sizeof(request));
30 request.width = info.width(); 44 request.width = info.width();
31 request.height = info.height(); 45 request.height = info.height();
32 request.bpp = info.bytesPerPixel() << 3; 46 request.bpp = info.bytesPerPixel() << 3;
33 request.flags = 0; 47 request.flags = 0;
(...skipping 14 matching lines...) Expand all
48 return true; 62 return true;
49 } 63 }
50 64
51 void DrmDestroyDumbBuffer(int fd, uint32_t handle) { 65 void DrmDestroyDumbBuffer(int fd, uint32_t handle) {
52 struct drm_mode_destroy_dumb destroy_request; 66 struct drm_mode_destroy_dumb destroy_request;
53 memset(&destroy_request, 0, sizeof(destroy_request)); 67 memset(&destroy_request, 0, sizeof(destroy_request));
54 destroy_request.handle = handle; 68 destroy_request.handle = handle;
55 drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_request); 69 drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_request);
56 } 70 }
57 71
72 void HandlePageFlipEventOnIO(int fd,
73 unsigned int frame,
74 unsigned int seconds,
75 unsigned int useconds,
76 void* data) {
77 scoped_ptr<PageFlipPayload> payload(static_cast<PageFlipPayload*>(data));
78 payload->task_runner->PostTask(
79 FROM_HERE, base::Bind(payload->callback, frame, seconds, useconds));
80 }
81
82 void HandlePageFlipEventOnUI(int fd,
83 unsigned int frame,
84 unsigned int seconds,
85 unsigned int useconds,
86 void* data) {
87 scoped_ptr<PageFlipPayload> payload(static_cast<PageFlipPayload*>(data));
88 payload->callback.Run(frame, seconds, useconds);
89 }
90
58 } // namespace 91 } // namespace
59 92
60 DriWrapper::DriWrapper(const char* device_path) 93 class DriWrapper::IOWatcher
61 : fd_(-1), device_path_(device_path) { 94 : public base::RefCountedThreadSafe<DriWrapper::IOWatcher>,
95 public base::MessagePumpLibevent::Watcher {
96 public:
97 IOWatcher(int fd,
98 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner)
99 : io_task_runner_(io_task_runner) {
100 io_task_runner_->PostTask(FROM_HERE,
101 base::Bind(&IOWatcher::RegisterOnIO, this, fd));
102 }
103
104 void Shutdown() {
105 io_task_runner_->PostTask(FROM_HERE,
106 base::Bind(&IOWatcher::UnregisterOnIO, this));
107 }
108
109 private:
110 friend class base::RefCountedThreadSafe<IOWatcher>;
111
112 ~IOWatcher() override {}
113
114 void RegisterOnIO(int fd) {
115 DCHECK(base::MessageLoopForIO::IsCurrent());
116 base::MessageLoopForIO::current()->WatchFileDescriptor(
117 fd, true, base::MessageLoopForIO::WATCH_READ, &controller_, this);
118 }
119
120 void UnregisterOnIO() {
121 DCHECK(base::MessageLoopForIO::IsCurrent());
122 controller_.StopWatchingFileDescriptor();
123 }
124
125 // base::MessagePumpLibevent::Watcher overrides:
126 void OnFileCanReadWithoutBlocking(int fd) override {
127 DCHECK(base::MessageLoopForIO::IsCurrent());
128 TRACE_EVENT1("dri", "OnDrmEvent", "socket", fd);
129
130 drmEventContext event;
131 event.version = DRM_EVENT_CONTEXT_VERSION;
132 event.page_flip_handler = HandlePageFlipEventOnIO;
133 event.vblank_handler = nullptr;
134
135 drmHandleEvent(fd, &event);
136 }
137
138 void OnFileCanWriteWithoutBlocking(int fd) override { NOTREACHED(); }
139
140 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
141
142 base::MessagePumpLibevent::FileDescriptorWatcher controller_;
143
144 DISALLOW_COPY_AND_ASSIGN(IOWatcher);
145 };
146
147 DriWrapper::DriWrapper(const char* device_path, bool software_mode)
148 : fd_(-1),
149 software_mode_(software_mode),
150 device_path_(device_path),
151 io_thread_("DriIOThread") {
62 plane_manager_.reset(new HardwareDisplayPlaneManagerLegacy()); 152 plane_manager_.reset(new HardwareDisplayPlaneManagerLegacy());
63 } 153 }
64 154
65 DriWrapper::~DriWrapper() { 155 DriWrapper::~DriWrapper() {
66 if (fd_ >= 0) 156 if (fd_ >= 0)
67 close(fd_); 157 close(fd_);
158
159 if (watcher_)
160 watcher_->Shutdown();
68 } 161 }
69 162
70 void DriWrapper::Initialize() { 163 void DriWrapper::Initialize() {
71 fd_ = open(device_path_, O_RDWR | O_CLOEXEC); 164 fd_ = open(device_path_, O_RDWR | O_CLOEXEC);
72 if (fd_ < 0) 165 if (fd_ < 0)
73 PLOG(FATAL) << "open: " << device_path_; 166 PLOG(FATAL) << "open: " << device_path_;
74 if (!plane_manager_->Initialize(this)) 167 if (!plane_manager_->Initialize(this))
75 LOG(ERROR) << "Failed to initialize the plane manager"; 168 LOG(ERROR) << "Failed to initialize the plane manager";
76 } 169 }
77 170
171 void DriWrapper::InitializeIOWatcher() {
172 if (!software_mode_ && !watcher_) {
173 if (!io_thread_.StartWithOptions(
174 base::Thread::Options(base::MessageLoop::TYPE_IO, 0)))
175 LOG(FATAL) << "Failed to start the IO helper thread";
176
177 watcher_ = new IOWatcher(fd_, io_thread_.task_runner());
178 }
179 }
180
78 ScopedDrmCrtcPtr DriWrapper::GetCrtc(uint32_t crtc_id) { 181 ScopedDrmCrtcPtr DriWrapper::GetCrtc(uint32_t crtc_id) {
79 DCHECK(fd_ >= 0); 182 DCHECK(fd_ >= 0);
80 return ScopedDrmCrtcPtr(drmModeGetCrtc(fd_, crtc_id)); 183 return ScopedDrmCrtcPtr(drmModeGetCrtc(fd_, crtc_id));
81 } 184 }
82 185
83 bool DriWrapper::SetCrtc(uint32_t crtc_id, 186 bool DriWrapper::SetCrtc(uint32_t crtc_id,
84 uint32_t framebuffer, 187 uint32_t framebuffer,
85 std::vector<uint32_t> connectors, 188 std::vector<uint32_t> connectors,
86 drmModeModeInfo* mode) { 189 drmModeModeInfo* mode) {
87 DCHECK(fd_ >= 0); 190 DCHECK(fd_ >= 0);
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
154 257
155 bool DriWrapper::RemoveFramebuffer(uint32_t framebuffer) { 258 bool DriWrapper::RemoveFramebuffer(uint32_t framebuffer) {
156 DCHECK(fd_ >= 0); 259 DCHECK(fd_ >= 0);
157 TRACE_EVENT1("dri", "DriWrapper::RemoveFramebuffer", 260 TRACE_EVENT1("dri", "DriWrapper::RemoveFramebuffer",
158 "framebuffer", framebuffer); 261 "framebuffer", framebuffer);
159 return !drmModeRmFB(fd_, framebuffer); 262 return !drmModeRmFB(fd_, framebuffer);
160 } 263 }
161 264
162 bool DriWrapper::PageFlip(uint32_t crtc_id, 265 bool DriWrapper::PageFlip(uint32_t crtc_id,
163 uint32_t framebuffer, 266 uint32_t framebuffer,
164 void* data) { 267 const PageFlipCallback& callback) {
165 DCHECK(fd_ >= 0); 268 DCHECK(fd_ >= 0);
166 TRACE_EVENT2("dri", "DriWrapper::PageFlip", 269 TRACE_EVENT2("dri", "DriWrapper::PageFlip",
167 "crtc", crtc_id, 270 "crtc", crtc_id,
168 "framebuffer", framebuffer); 271 "framebuffer", framebuffer);
169 return !drmModePageFlip(fd_, 272
170 crtc_id, 273 // NOTE: Calling drmModeSetCrtc will immediately update the state, though
171 framebuffer, 274 // callbacks to already scheduled page flips will be honored by the kernel.
172 DRM_MODE_PAGE_FLIP_EVENT, 275 scoped_ptr<PageFlipPayload> payload(
173 data); 276 new PageFlipPayload(base::ThreadTaskRunnerHandle::Get(), callback));
277 if (!drmModePageFlip(fd_, crtc_id, framebuffer, DRM_MODE_PAGE_FLIP_EVENT,
278 payload.get())) {
279 // If successful the payload will be removed by a PageFlip event.
280 ignore_result(payload.release());
281 if (software_mode_) {
282 TRACE_EVENT1("dri", "OnDrmEvent", "socket", fd_);
283
284 drmEventContext event;
285 event.version = DRM_EVENT_CONTEXT_VERSION;
286 event.page_flip_handler = HandlePageFlipEventOnUI;
287 event.vblank_handler = nullptr;
288
289 drmHandleEvent(fd_, &event);
290 } else {
291 InitializeIOWatcher();
292 }
293
294 return true;
295 }
296
297 return false;
174 } 298 }
175 299
176 bool DriWrapper::PageFlipOverlay(uint32_t crtc_id, 300 bool DriWrapper::PageFlipOverlay(uint32_t crtc_id,
177 uint32_t framebuffer, 301 uint32_t framebuffer,
178 const gfx::Rect& location, 302 const gfx::Rect& location,
179 const gfx::Rect& source, 303 const gfx::Rect& source,
180 int overlay_plane) { 304 int overlay_plane) {
181 DCHECK(fd_ >= 0); 305 DCHECK(fd_ >= 0);
182 TRACE_EVENT2("dri", "DriWrapper::PageFlipOverlay", 306 TRACE_EVENT2("dri", "DriWrapper::PageFlipOverlay",
183 "crtc", crtc_id, 307 "crtc", crtc_id,
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
250 DCHECK(fd_ >= 0); 374 DCHECK(fd_ >= 0);
251 TRACE_EVENT1("dri", "DriWrapper::SetCursor", "handle", handle); 375 TRACE_EVENT1("dri", "DriWrapper::SetCursor", "handle", handle);
252 return !drmModeSetCursor(fd_, crtc_id, handle, size.width(), size.height()); 376 return !drmModeSetCursor(fd_, crtc_id, handle, size.width(), size.height());
253 } 377 }
254 378
255 bool DriWrapper::MoveCursor(uint32_t crtc_id, const gfx::Point& point) { 379 bool DriWrapper::MoveCursor(uint32_t crtc_id, const gfx::Point& point) {
256 DCHECK(fd_ >= 0); 380 DCHECK(fd_ >= 0);
257 return !drmModeMoveCursor(fd_, crtc_id, point.x(), point.y()); 381 return !drmModeMoveCursor(fd_, crtc_id, point.x(), point.y());
258 } 382 }
259 383
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, 384 bool DriWrapper::CreateDumbBuffer(const SkImageInfo& info,
267 uint32_t* handle, 385 uint32_t* handle,
268 uint32_t* stride, 386 uint32_t* stride,
269 void** pixels) { 387 void** pixels) {
270 DCHECK(fd_ >= 0); 388 DCHECK(fd_ >= 0);
271 389
272 TRACE_EVENT0("dri", "DriWrapper::CreateDumbBuffer"); 390 TRACE_EVENT0("dri", "DriWrapper::CreateDumbBuffer");
273 if (!DrmCreateDumbBuffer(fd_, info, handle, stride)) 391 if (!DrmCreateDumbBuffer(fd_, info, handle, stride))
274 return false; 392 return false;
275 393
(...skipping 19 matching lines...) Expand all
295 DCHECK(fd_ >= 0); 413 DCHECK(fd_ >= 0);
296 return (drmSetMaster(fd_) == 0); 414 return (drmSetMaster(fd_) == 0);
297 } 415 }
298 416
299 bool DriWrapper::DropMaster() { 417 bool DriWrapper::DropMaster() {
300 DCHECK(fd_ >= 0); 418 DCHECK(fd_ >= 0);
301 return (drmDropMaster(fd_) == 0); 419 return (drmDropMaster(fd_) == 0);
302 } 420 }
303 421
304 } // namespace ui 422 } // namespace ui
OLDNEW
« no previous file with comments | « ui/ozone/platform/dri/dri_wrapper.h ('k') | ui/ozone/platform/dri/gbm_surface.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698