| 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,
|
|
|