Index: ui/ozone/platform/dri/dri_wrapper.cc |
diff --git a/ui/ozone/platform/dri/dri_wrapper.cc b/ui/ozone/platform/dri/dri_wrapper.cc |
index a2b333f16e762f6d5ce2d67e762e7f9fb730ff80..bd859499f1ab59047aa5ea8fa359350cf8092921 100644 |
--- a/ui/ozone/platform/dri/dri_wrapper.cc |
+++ b/ui/ozone/platform/dri/dri_wrapper.cc |
@@ -13,6 +13,7 @@ |
#include "base/logging.h" |
#include "base/message_loop/message_loop.h" |
#include "base/stl_util.h" |
+#include "base/synchronization/waitable_event.h" |
#include "base/task_runner.h" |
#include "base/thread_task_runner_handle.h" |
#include "base/trace_event/trace_event.h" |
@@ -35,6 +36,12 @@ struct PageFlipPayload { |
DriWrapper::PageFlipCallback callback; |
}; |
+struct PageFlipSyncPayload { |
+ unsigned int frame; |
+ unsigned int seconds; |
+ unsigned int useconds; |
+}; |
+ |
bool DrmCreateDumbBuffer(int fd, |
const SkImageInfo& info, |
uint32_t* handle, |
@@ -88,6 +95,17 @@ void HandlePageFlipEventOnUI(int fd, |
payload->callback.Run(frame, seconds, useconds); |
} |
+void HandlePageFlipEventSync(int fd, |
+ unsigned int frame, |
+ unsigned int seconds, |
+ unsigned int useconds, |
+ void* data) { |
+ PageFlipSyncPayload* payload = static_cast<PageFlipSyncPayload*>(data); |
+ payload->frame = frame; |
+ payload->seconds = seconds; |
+ payload->useconds = useconds; |
+} |
+ |
bool CanQueryForResources(int fd) { |
drm_mode_card_res resources; |
memset(&resources, 0, sizeof(resources)); |
@@ -104,9 +122,20 @@ class DriWrapper::IOWatcher |
public: |
IOWatcher(int fd, |
const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner) |
- : io_task_runner_(io_task_runner) { |
+ : io_task_runner_(io_task_runner), paused_(false), fd_(fd) { |
io_task_runner_->PostTask(FROM_HERE, |
- base::Bind(&IOWatcher::RegisterOnIO, this, fd)); |
+ base::Bind(&IOWatcher::RegisterOnIO, this)); |
+ } |
+ |
+ void SetPaused(bool value) { |
+ bool paused = !!value; |
+ if (paused_ == paused) |
+ return; |
+ |
+ base::WaitableEvent done(false, false); |
+ io_task_runner_->PostTask( |
+ FROM_HERE, base::Bind(&IOWatcher::SetPausedOnIO, this, paused, &done)); |
+ paused_ = paused; |
} |
void Shutdown() { |
@@ -117,12 +146,14 @@ class DriWrapper::IOWatcher |
private: |
friend class base::RefCountedThreadSafe<IOWatcher>; |
- ~IOWatcher() override {} |
+ ~IOWatcher() override { |
+ SetPaused(true); |
+ } |
- void RegisterOnIO(int fd) { |
+ void RegisterOnIO() { |
DCHECK(base::MessageLoopForIO::IsCurrent()); |
base::MessageLoopForIO::current()->WatchFileDescriptor( |
- fd, true, base::MessageLoopForIO::WATCH_READ, &controller_, this); |
+ fd_, true, base::MessageLoopForIO::WATCH_READ, &controller_, this); |
} |
void UnregisterOnIO() { |
@@ -130,6 +161,15 @@ class DriWrapper::IOWatcher |
controller_.StopWatchingFileDescriptor(); |
} |
+ void SetPausedOnIO(bool paused, base::WaitableEvent* done) { |
+ DCHECK(base::MessageLoopForIO::IsCurrent()); |
+ if (paused) |
+ UnregisterOnIO(); |
+ else |
+ RegisterOnIO(); |
+ done->Signal(); |
+ } |
+ |
// base::MessagePumpLibevent::Watcher overrides: |
void OnFileCanReadWithoutBlocking(int fd) override { |
DCHECK(base::MessageLoopForIO::IsCurrent()); |
@@ -149,6 +189,9 @@ class DriWrapper::IOWatcher |
base::MessagePumpLibevent::FileDescriptorWatcher controller_; |
+ bool paused_; |
+ int fd_; |
+ |
DISALLOW_COPY_AND_ASSIGN(IOWatcher); |
}; |
@@ -276,6 +319,8 @@ bool DriWrapper::PageFlip(uint32_t crtc_id, |
"crtc", crtc_id, |
"framebuffer", framebuffer); |
+ watcher_->SetPaused(false); |
+ |
// NOTE: Calling drmModeSetCrtc will immediately update the state, though |
// callbacks to already scheduled page flips will be honored by the kernel. |
scoped_ptr<PageFlipPayload> payload( |
@@ -304,6 +349,34 @@ bool DriWrapper::PageFlip(uint32_t crtc_id, |
return false; |
} |
+bool DriWrapper::PageFlipSync(uint32_t crtc_id, |
+ uint32_t framebuffer, |
+ const PageFlipCallback& callback) { |
+ DCHECK(file_.IsValid()); |
+ TRACE_EVENT2("dri", "DriWrapper::PageFlip", "crtc", crtc_id, "framebuffer", |
+ framebuffer); |
+ |
+ watcher_->SetPaused(true); |
+ |
+ PageFlipSyncPayload payload; |
+ if (!drmModePageFlip(file_.GetPlatformFile(), crtc_id, framebuffer, |
+ DRM_MODE_PAGE_FLIP_EVENT, &payload)) { |
+ TRACE_EVENT1("dri", "OnDrmEvent", "socket", file_.GetPlatformFile()); |
+ |
+ drmEventContext event; |
+ event.version = DRM_EVENT_CONTEXT_VERSION; |
+ event.page_flip_handler = HandlePageFlipEventSync; |
+ event.vblank_handler = nullptr; |
+ |
+ drmHandleEvent(file_.GetPlatformFile(), &event); |
+ |
+ callback.Run(payload.frame, payload.seconds, payload.useconds); |
+ return true; |
+ } |
+ |
+ return false; |
+} |
+ |
bool DriWrapper::PageFlipOverlay(uint32_t crtc_id, |
uint32_t framebuffer, |
const gfx::Rect& location, |